]> git.sur5r.net Git - glabels/blob - libglbarcode/lgl-barcode-render-to-cairo.c
Imported Upstream version 3.0.0
[glabels] / libglbarcode / lgl-barcode-render-to-cairo.c
1 /*
2  *  lgl-barcode-render-to-cairo.c
3  *  Copyright (C) 2010  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of libglbarcode.
6  *
7  *  libglbarcode is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU Lesser General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  libglbarcode is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License
18  *  along with libglbarcode.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include "lgl-barcode-render-to-cairo.h"
24
25 #include <pango/pangocairo.h>
26 #include <math.h>
27
28
29 /*===========================================*/
30 /* Private macros and constants.             */
31 /*===========================================*/
32
33 #define FONT_SCALE (72.0/96.0)
34 #define BARCODE_FONT_FAMILY      "Sans"
35 #define BARCODE_FONT_WEIGHT      PANGO_WEIGHT_NORMAL
36
37
38 /*===========================================*/
39 /* Private types                             */
40 /*===========================================*/
41
42
43 /*===========================================*/
44 /* Private globals                           */
45 /*===========================================*/
46
47
48 /*===========================================*/
49 /* Local function prototypes                 */
50 /*===========================================*/
51
52
53 /****************************************************************************/
54 /**
55  * lgl_barcode_render_to_cairo:
56  * @bc:     An #lglBarcode structure
57  * @cr:     A #cairo_t context
58  *
59  * Render barcode to cairo context.  Context should be prepared with desired
60  * translation and appropriate scale.  Context should be translated such that
61  * the origin is at the desired location of the upper left hand corner of the
62  * barcode bounding box.  Context should be scaled such that all dimensions
63  * are in points ( 1 point = 1/72 inch ) and that positive y coordinates
64  * go down the surface.
65  */
66 void
67 lgl_barcode_render_to_cairo (const lglBarcode  *bc,
68                              cairo_t           *cr)
69 {
70         GList                  *p;
71
72         lglBarcodeShape        *shape;
73         lglBarcodeShapeLine    *line;
74         lglBarcodeShapeBox     *box;
75         lglBarcodeShapeChar    *bchar;
76         lglBarcodeShapeString  *bstring;
77         lglBarcodeShapeRing    *ring;
78         lglBarcodeShapeHexagon *hexagon;
79
80         PangoLayout            *layout;
81         PangoFontDescription   *desc;
82         gchar                  *cstring;
83         gdouble                 x_offset, y_offset;
84         gint                    iw, ih;
85         gdouble                 layout_width;
86
87
88         for (p = bc->shapes; p != NULL; p = p->next) {
89
90                 shape = (lglBarcodeShape *)p->data;
91
92                 switch (shape->type)
93                 {
94
95                 case LGL_BARCODE_SHAPE_LINE:
96                         line = (lglBarcodeShapeLine *) shape;
97
98                         cairo_move_to (cr, line->x, line->y);
99                         cairo_line_to (cr, line->x, line->y + line->length);
100                         cairo_set_line_width (cr, line->width);
101                         cairo_stroke (cr);
102
103                         break;
104
105                 case LGL_BARCODE_SHAPE_BOX:
106                         box = (lglBarcodeShapeBox *) shape;
107
108                         cairo_rectangle (cr, box->x, box->y, box->width, box->height);
109                         cairo_fill (cr);
110
111                         break;
112
113                 case LGL_BARCODE_SHAPE_CHAR:
114                         bchar = (lglBarcodeShapeChar *) shape;
115
116                         layout = pango_cairo_create_layout (cr);
117
118                         desc = pango_font_description_new ();
119                         pango_font_description_set_family (desc, BARCODE_FONT_FAMILY);
120                         pango_font_description_set_size   (desc, bchar->fsize * PANGO_SCALE * FONT_SCALE);
121                         pango_layout_set_font_description (layout, desc);
122                         pango_font_description_free       (desc);
123
124                         cstring = g_strdup_printf ("%c", bchar->c);
125                         pango_layout_set_text (layout, cstring, -1);
126                         g_free (cstring);
127
128                         y_offset = 0.2 * bchar->fsize;
129
130                         cairo_move_to (cr, bchar->x, bchar->y-y_offset);
131                         pango_cairo_show_layout (cr, layout);
132
133                         g_object_unref (layout);
134
135                         break;
136
137                 case LGL_BARCODE_SHAPE_STRING:
138                         bstring = (lglBarcodeShapeString *) shape;
139
140                         layout = pango_cairo_create_layout (cr);
141
142                         desc = pango_font_description_new ();
143                         pango_font_description_set_family (desc, BARCODE_FONT_FAMILY);
144                         pango_font_description_set_size   (desc, bstring->fsize * PANGO_SCALE * FONT_SCALE);
145                         pango_layout_set_font_description (layout, desc);
146                         pango_font_description_free       (desc);
147
148                         pango_layout_set_text (layout, bstring->string, -1);
149
150                         pango_layout_get_size (layout, &iw, &ih);
151                         layout_width = (gdouble)iw / (gdouble)PANGO_SCALE;
152
153                         x_offset = layout_width / 2.0;
154                         y_offset = 0.2 * bstring->fsize;
155
156                         cairo_move_to (cr, (bstring->x - x_offset), (bstring->y - y_offset));
157                         pango_cairo_show_layout (cr, layout);
158
159                         g_object_unref (layout);
160
161                         break;
162
163                 case LGL_BARCODE_SHAPE_RING:
164                         ring = (lglBarcodeShapeRing *) shape;
165
166                         cairo_arc (cr, ring->x, ring->y, ring->radius, 0.0, 2 * G_PI);
167                         cairo_set_line_width (cr, ring->line_width);
168                         cairo_stroke (cr);
169
170                         break;
171
172                 case LGL_BARCODE_SHAPE_HEXAGON:
173                         hexagon = (lglBarcodeShapeHexagon *) shape;
174
175                         cairo_move_to (cr, hexagon->x, hexagon->y);
176                         cairo_line_to (cr, hexagon->x + 0.433*hexagon->height, hexagon->y + 0.25*hexagon->height);
177                         cairo_line_to (cr, hexagon->x + 0.433*hexagon->height, hexagon->y + 0.75*hexagon->height);
178                         cairo_line_to (cr, hexagon->x,                         hexagon->y +      hexagon->height);
179                         cairo_line_to (cr, hexagon->x - 0.433*hexagon->height, hexagon->y + 0.75*hexagon->height);
180                         cairo_line_to (cr, hexagon->x - 0.433*hexagon->height, hexagon->y + 0.25*hexagon->height);
181                         cairo_close_path (cr);
182                         cairo_fill (cr);
183
184                         break;
185
186                 default:
187                         g_assert_not_reached ();
188                         break;
189
190                 }
191
192         }
193
194 }
195
196
197 /****************************************************************************/
198 /**
199  * lgl_barcode_render_to_cairo_path:
200  * @bc:     An #lglBarcode structure
201  * @cr:     A #cairo_t context
202  *
203  * Render barcode to cairo context, but only create a path to be filled or
204  * tested against.  Context should be prepared with desired
205  * translation and appropriate scale.  Context should be translated such that
206  * the origin is at the desired location of the upper left hand corner of the
207  * barcode bounding box.  Context should be scaled such that all dimensions
208  * are in points ( 1 point = 1/72 inch ) and that positive y coordinates
209  * go down the surface.
210  */
211 void
212 lgl_barcode_render_to_cairo_path (const lglBarcode  *bc,
213                                   cairo_t           *cr)
214 {
215         GList                  *p;
216
217         lglBarcodeShape        *shape;
218         lglBarcodeShapeLine    *line;
219         lglBarcodeShapeBox     *box;
220         lglBarcodeShapeChar    *bchar;
221         lglBarcodeShapeString  *bstring;
222         lglBarcodeShapeRing    *ring;
223         lglBarcodeShapeHexagon *hexagon;
224
225         PangoLayout            *layout;
226         PangoFontDescription   *desc;
227         gchar                  *cstring;
228         gdouble                 x_offset, y_offset;
229         gint                    iw, ih;
230         gdouble                 layout_width;
231
232
233         for (p = bc->shapes; p != NULL; p = p->next) {
234
235                 shape = (lglBarcodeShape *)p->data;
236
237                 switch (shape->type)
238                 {
239
240                 case LGL_BARCODE_SHAPE_LINE:
241                         line = (lglBarcodeShapeLine *) shape;
242
243                         cairo_rectangle (cr, line->x - line->width/2, line->y, line->width, line->length);
244
245                         break;
246
247                 case LGL_BARCODE_SHAPE_BOX:
248                         box = (lglBarcodeShapeBox *) shape;
249
250                         cairo_rectangle (cr, box->x, box->y, box->width, box->height);
251
252                         break;
253
254                 case LGL_BARCODE_SHAPE_CHAR:
255                         bchar = (lglBarcodeShapeChar *) shape;
256
257                         layout = pango_cairo_create_layout (cr);
258
259                         desc = pango_font_description_new ();
260                         pango_font_description_set_family (desc, BARCODE_FONT_FAMILY);
261                         pango_font_description_set_size   (desc, bchar->fsize * PANGO_SCALE * FONT_SCALE);
262                         pango_layout_set_font_description (layout, desc);
263                         pango_font_description_free       (desc);
264
265                         cstring = g_strdup_printf ("%c", bchar->c);
266                         pango_layout_set_text (layout, cstring, -1);
267                         g_free (cstring);
268
269                         y_offset = 0.2 * bchar->fsize;
270
271                         cairo_move_to (cr, bchar->x, bchar->y-y_offset);
272                         pango_cairo_layout_path (cr, layout);
273
274                         g_object_unref (layout);
275
276                         break;
277
278                 case LGL_BARCODE_SHAPE_STRING:
279                         bstring = (lglBarcodeShapeString *) shape;
280
281                         layout = pango_cairo_create_layout (cr);
282
283                         desc = pango_font_description_new ();
284                         pango_font_description_set_family (desc, BARCODE_FONT_FAMILY);
285                         pango_font_description_set_size   (desc, bstring->fsize * PANGO_SCALE * FONT_SCALE);
286                         pango_layout_set_font_description (layout, desc);
287                         pango_font_description_free       (desc);
288
289                         pango_layout_set_text (layout, bstring->string, -1);
290
291                         pango_layout_get_size (layout, &iw, &ih);
292                         layout_width = (gdouble)iw / (gdouble)PANGO_SCALE;
293
294                         x_offset = layout_width / 2.0;
295                         y_offset = 0.2 * bstring->fsize;
296
297                         cairo_move_to (cr, (bstring->x - x_offset), (bstring->y - y_offset));
298                         pango_cairo_layout_path (cr, layout);
299
300                         g_object_unref (layout);
301
302                         break;
303
304                 case LGL_BARCODE_SHAPE_RING:
305                         ring = (lglBarcodeShapeRing *) shape;
306
307                         cairo_new_sub_path (cr);
308                         cairo_arc (cr, ring->x, ring->y, ring->radius + ring->line_width/2, 0.0, 2 * G_PI);
309                         cairo_close_path (cr);
310                         cairo_new_sub_path (cr);
311                         cairo_arc (cr, ring->x, ring->y, ring->radius - ring->line_width/2, 0.0, 2 * G_PI);
312                         cairo_close_path (cr);
313                         break;
314
315                 case LGL_BARCODE_SHAPE_HEXAGON:
316                         hexagon = (lglBarcodeShapeHexagon *) shape;
317
318                         cairo_move_to (cr, hexagon->x, hexagon->y);
319                         cairo_line_to (cr, hexagon->x + 0.433*hexagon->height, hexagon->y + 0.25*hexagon->height);
320                         cairo_line_to (cr, hexagon->x + 0.433*hexagon->height, hexagon->y + 0.75*hexagon->height);
321                         cairo_line_to (cr, hexagon->x,                         hexagon->y +      hexagon->height);
322                         cairo_line_to (cr, hexagon->x - 0.433*hexagon->height, hexagon->y + 0.75*hexagon->height);
323                         cairo_line_to (cr, hexagon->x - 0.433*hexagon->height, hexagon->y + 0.25*hexagon->height);
324                         cairo_close_path (cr);
325                         break;
326
327                 default:
328                         g_assert_not_reached ();
329                         break;
330
331                 }
332
333         }
334
335 }
336
337
338
339 /*
340  * Local Variables:       -- emacs
341  * mode: C                -- emacs
342  * c-basic-offset: 8      -- emacs
343  * tab-width: 8           -- emacs
344  * indent-tabs-mode: nil  -- emacs
345  * End:                   -- emacs
346  */