1 #include <cups/cups.h>
2 #include <cups/ppd.h>
3 #include <string>
4 #include <stdio.h>
5 #include <map>
6 #include <cairo/cairo.h>
7 #include <exception>
8 #include <math.h>
9 #include "CairoUtils.h"
10
11 using namespace std;
12
13
14
15 class Error: public exception
16 {
17 public:
Error(const string & Message)18 Error(const string& Message): exception(), Message_(Message) {}
~Error()19 virtual ~Error() throw() {}
what() const20 virtual const char* what() const throw() { return Message_.c_str(); }
21 private:
22 string Message_;
23 };
24
25 map <string, string> gPaperNames;
26 typedef pair<string, string> str_pair;
27
28 static int
GetPrinterResolution(ppd_group_t * group,int num_groups)29 GetPrinterResolution(ppd_group_t* group, int num_groups)
30 {
31 for (int i = 0; i < num_groups; ++i)
32 {
33 ppd_group_t g = group[i];
34 for (int j = 0; j < g.num_options; ++j)
35 {
36 ppd_option_t o = g.options[j];
37
38 if (!strcmp(o.keyword, "Resolution"))
39 {
40 ppd_choice_t c = o.choices[0];
41
42 return atoi(c.choice);
43 }
44 }
45 }
46
47 return 0;
48 }
49
50 static void
FindPapersOptions(ppd_option_t & o)51 FindPapersOptions(ppd_option_t& o)
52 {
53 if (!strcmp(o.keyword, "PageSize"))
54 {
55 for (int i = 0; i < o.num_choices; ++i)
56 {
57 ppd_choice_t& c = o.choices[i];
58
59 gPaperNames.insert(str_pair(c.choice, c.text));
60 }
61 }
62 }
63
64 static void
FindPapersGroup(ppd_group_t & g)65 FindPapersGroup(ppd_group_t& g)
66 {
67 for (int i = 0; i < g.num_options; ++i)
68 FindPapersOptions(g.options[i]);
69 }
70
71 static void
FindPapers(ppd_group_t * group,int num_groups)72 FindPapers(ppd_group_t* group, int num_groups)
73 {
74 for (int i = 0; i < num_groups; ++i)
75 FindPapersGroup(group[i]);
76 }
77
78
79 void
CreateBoundsImage(int Width,int Height,const string & Text,string & FileName,bool Landscape)80 CreateBoundsImage(int Width, int Height, const string& Text, string& FileName, bool Landscape)
81 {
82 FileName = "test.png";
83
84 CairoSurfacePtr Surface(cairo_image_surface_create(CAIRO_FORMAT_RGB24, Width, Height));
85 if (!*Surface)
86 throw Error("Unable to create cairo surface");
87
88
89 CairoPtr c(cairo_create(Surface));
90 if (!*c)
91 throw Error("Unable to create cairo_t");
92
93 //setup Cairo
94 cairo_set_antialias(c, CAIRO_ANTIALIAS_NONE);
95
96
97 // clear image
98 cairo_set_source_rgb(c, 1, 1, 1);
99 cairo_paint(c);
100
101 // draw rect
102 cairo_set_source_rgb(c, 0, 0, 0);
103 cairo_set_line_width(c, 3);
104 cairo_rectangle(c, 3, 3, Width - 6, Height - 6);
105 cairo_move_to(c, 3, 3);
106 cairo_line_to(c, Width - 3, Height - 3);
107 cairo_move_to(c, 3, Height - 3);
108 cairo_line_to(c, Width - 3, 3);
109 cairo_stroke(c);
110
111
112 // draw text
113 cairo_select_font_face(c, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
114 cairo_set_source_rgb(c, 0, 0, 0);
115 cairo_set_line_width(c, 1);
116
117 cairo_text_extents_t te;
118 for(int FontSize = 100; ;FontSize -= 10)
119 {
120 cairo_set_font_size(c, FontSize);
121
122 cairo_text_extents(c, Text.c_str(), &te);
123
124 if (Width > te.width)
125 break;
126 }
127
128 //cairo_move_to(c, 10, 10);
129 //cairo_show_text(c, "Hello");
130 cairo_move_to(c, (Width - te.width) / 2, (Height + te.height) / 2);
131 cairo_text_path(c, Text.c_str());
132
133 cairo_stroke(c);
134
135 // rotate if in Landscape to output always in portrait mode
136 if (Landscape)
137 {
138 int w = Height;
139 int h = Width;
140 CairoSurfacePtr Surface2(cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h));
141 if (!*Surface2)
142 throw Error("Unable to create cairo surface");
143
144
145 CairoPtr c2(cairo_create(Surface2));
146 if (!*c2)
147 throw Error("Unable to create cairo_t");
148
149 cairo_translate(c2, w * 0.5, h * 0.5);
150 cairo_rotate(c2, M_PI / 2.0);
151 cairo_translate(c2, -h * 0.5, -w * 0.5);
152 cairo_set_source_surface(c2, Surface, 0, 0);
153 cairo_set_operator(c2, CAIRO_OPERATOR_SOURCE);
154 cairo_paint(c2);
155
156 if (cairo_surface_write_to_png(Surface2, FileName.c_str()) != CAIRO_STATUS_SUCCESS)
157 throw Error("Unable to write to PNG file");
158 }
159 else
160 // save to file
161 if (cairo_surface_write_to_png(Surface, FileName.c_str()) != CAIRO_STATUS_SUCCESS)
162 throw Error("Unable to write to PNG file");
163 }
164
main(int argc,char ** argv)165 int main(int argc, char** argv)
166 {
167 try
168 {
169 if (argc < 2)
170 throw Error("Usage: paperlist <PrinterName> [LabelType]");
171
172
173 const char* ppdFileName = cupsGetPPD(argv[1]);
174 if (!ppdFileName)
175 throw Error(string("Unknown printer '") + argv[1] + "'");
176
177 ppd_file_t* ppd = ppdOpenFile(ppdFileName);
178 if (!ppd)
179 throw Error(string("Unable to open ppd file '") + ppdFileName + "'");
180
181 FindPapers(ppd->groups, ppd->num_groups);
182 int Resolution = GetPrinterResolution(ppd->groups, ppd->num_groups);
183
184
185 for (int i = 0; i < ppd->num_sizes; ++i)
186 {
187 int ch;
188 ppd_size_t size = ppd->sizes[i];
189 if (argc>=3)
190 //printf("%s\n", gPaperNames[size.name].substr(0,5).c_str());
191 if (argv[2]!=gPaperNames[size.name].substr(0,5))
192 continue;
193
194 printf("Please Insert '%s' paper. Press 'c' to continue, 's' to skip: ", gPaperNames[size.name].c_str());
195 while((ch = getchar()) == '\n') {}
196 //printf("\n");
197
198 if (ch == 's')
199 continue;
200 if (ch == 'a')
201 break;
202
203
204 int Width = int((size.right - size.left) * Resolution / 72);
205 int Height = int((size.top - size.bottom) * Resolution / 72);
206 bool Landscape = false;
207
208 string FileName;
209 if (Height > Width)
210 {
211 Landscape = true;
212 int t = Width;
213 Width = Height;
214 Height = t;
215 }
216 CreateBoundsImage(Width, Height, gPaperNames[size.name], FileName, Landscape);
217
218 int num_options = 0;
219 cups_option_t* options = NULL;
220
221 num_options = cupsAddOption("PageSize", size.name, num_options, &options);
222 num_options = cupsAddOption("scaling", "100", num_options, &options);
223 if (Landscape)
224 num_options = cupsAddOption("landscape", "no", num_options, &options);
225 //num_options = cupsAddOption("orientation-requested", "4", num_options, &options);
226
227
228
229 cupsPrintFile(argv[1], FileName.c_str(), "Test print with Cairo", num_options, options);
230
231 cupsFreeOptions(num_options, options);
232 }
233
234
235 ppdClose(ppd);
236
237 return 0;
238 }
239 catch(std::exception& e)
240 {
241 fprintf(stderr, e.what());
242 fprintf(stderr, "\n");
243 return 1;
244 }
245 }
246