]> git.sur5r.net Git - glabels/blob - glabels2/src/mini-preview-pixbuf.c
2006-09-12 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / mini-preview-pixbuf.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (GLABELS) Label and Business Card Creation program for GNOME
5  *
6  *  mini-preview-pixbuf.c:  mini preview pixbuf module
7  *
8  *  Copyright (C) 2006  Jim Evins <evins@snaught.com>.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  */
24
25 #include <config.h>
26
27 #include "mini-preview-pixbuf.h"
28
29 #include <cairo.h>
30 #include <math.h>
31
32 #include "debug.h"
33
34 /*===========================================*/
35 /* Private types                             */
36 /*===========================================*/
37
38
39 /*===========================================*/
40 /* Private globals                           */
41 /*===========================================*/
42
43
44 /*===========================================*/
45 /* Local function prototypes                 */
46 /*===========================================*/
47
48 static void draw_paper                (cairo_t           *cr,
49                                        const glTemplate  *template,
50                                        gdouble            scale);
51
52 static void draw_label_outlines       (cairo_t           *cr,
53                                        const glTemplate  *template,
54                                        gdouble            scale);
55
56 static void draw_label_outline        (cairo_t           *cr,
57                                        const glTemplate  *template,
58                                        gdouble            x0,
59                                        gdouble            y0);
60
61 static void draw_rect_label_outline   (cairo_t           *cr,
62                                        const glTemplate  *template,
63                                        gdouble            x0,
64                                        gdouble            y0);
65
66 static void draw_round_label_outline  (cairo_t           *cr,
67                                        const glTemplate  *template,
68                                        gdouble            x0,
69                                        gdouble            y0);
70
71 static void draw_cd_label_outline     (cairo_t           *cr,
72                                        const glTemplate  *template,
73                                        gdouble            x0,
74                                        gdouble            y0);
75
76
77
78 \f
79 /****************************************************************************/
80 /* Create new pixbuf with mini preview of template                          */
81 /****************************************************************************/
82 GdkPixbuf *
83 gl_mini_preview_pixbuf_new (glTemplate *template,
84                             gint        width,
85                             gint        height)
86 {
87         cairo_surface_t   *surface;
88         cairo_t           *cr;
89         GdkPixbuf         *pixbuf;
90         gdouble            scale;
91         gdouble            w, h;
92         gdouble            offset_x, offset_y;
93
94         gl_debug (DEBUG_MINI_PREVIEW, "START");
95
96         /* Create pixbuf and cairo context. */
97         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
98         surface = cairo_image_surface_create_for_data (gdk_pixbuf_get_pixels (pixbuf),
99                                                        CAIRO_FORMAT_RGB24,
100                                                        gdk_pixbuf_get_width (pixbuf),
101                                                        gdk_pixbuf_get_height (pixbuf),
102                                                        gdk_pixbuf_get_rowstride (pixbuf));
103
104         cr = cairo_create (surface);
105         cairo_surface_destroy (surface);
106
107         /* Clear pixbuf */
108         cairo_save (cr);
109         cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
110         cairo_paint (cr);
111         cairo_restore (cr);
112
113         cairo_set_antialias (cr, CAIRO_ANTIALIAS_DEFAULT);
114
115         /* Set scale and offset */
116         w = width - 1;
117         h = height - 1;
118         if ( (w/template->page_width) > (h/template->page_height) ) {
119                 scale = h / template->page_height;
120         } else {
121                 scale = w / template->page_width;
122         }
123         offset_x = (width/scale - template->page_width) / 2.0;
124         offset_y = (height/scale - template->page_height) / 2.0;
125         cairo_identity_matrix (cr);
126         cairo_scale (cr, scale, scale);
127         cairo_translate (cr, offset_x, offset_y);
128
129         /* Draw paper and label outlines */
130         draw_paper (cr, template, scale);
131         draw_label_outlines (cr, template, scale);
132
133         /* Cleanup */
134         cairo_destroy (cr);
135
136         gl_debug (DEBUG_MINI_PREVIEW, "END");
137
138         return pixbuf;
139 }
140
141 /*--------------------------------------------------------------------------*/
142 /* PRIVATE.  Draw paper and paper outline.                                  */
143 /*--------------------------------------------------------------------------*/
144 static void
145 draw_paper (cairo_t           *cr,
146             const glTemplate  *template,
147             gdouble            scale)
148 {
149         gl_debug (DEBUG_MINI_PREVIEW, "START");
150
151         cairo_save (cr);
152         cairo_rectangle (cr, 0.0, 0.0, template->page_width, template->page_height);
153         cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
154         cairo_fill_preserve (cr);
155         cairo_set_line_width (cr, 1/scale);
156         cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
157         cairo_stroke (cr);
158         cairo_restore (cr);
159
160         gl_debug (DEBUG_MINI_PREVIEW, "END");
161 }
162
163 /*--------------------------------------------------------------------------*/
164 /* PRIVATE.  Draw label outlines.                                           */
165 /*--------------------------------------------------------------------------*/
166 static void
167 draw_label_outlines (cairo_t           *cr,
168                      const glTemplate  *template,
169                      gdouble            scale)
170 {
171         const glTemplateLabelType *label_type;
172         gint                       i, n_labels;
173         glTemplateOrigin          *origins;
174
175         gl_debug (DEBUG_MINI_PREVIEW, "START");
176
177         cairo_save (cr);
178
179         cairo_set_line_width (cr, 1.0/scale);
180         cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
181
182         label_type = gl_template_get_first_label_type (template);
183
184         n_labels = gl_template_get_n_labels (label_type);
185         origins  = gl_template_get_origins (label_type);
186
187         for ( i=0; i < n_labels; i++ ) {
188
189                 draw_label_outline(cr, template, origins[i].x, origins[i].y);
190
191         }
192
193         g_free (origins);
194
195         cairo_restore (cr);
196
197         gl_debug (DEBUG_MINI_PREVIEW, "END");
198 }
199
200 /*--------------------------------------------------------------------------*/
201 /* PRIVATE.  Draw label outline.                                            */
202 /*--------------------------------------------------------------------------*/
203 static void
204 draw_label_outline (cairo_t           *cr,
205                     const glTemplate  *template,
206                     gdouble            x0,
207                     gdouble            y0)
208 {
209         const glTemplateLabelType *label_type;
210
211         gl_debug (DEBUG_MINI_PREVIEW, "START");
212
213         cairo_save (cr);
214
215         label_type = gl_template_get_first_label_type (template);
216
217         switch (label_type->shape) {
218
219         case GL_TEMPLATE_SHAPE_RECT:
220                 draw_rect_label_outline (cr, template, x0, y0);
221                 break;
222
223         case GL_TEMPLATE_SHAPE_ROUND:
224                 draw_round_label_outline (cr, template, x0, y0);
225                 break;
226
227         case GL_TEMPLATE_SHAPE_CD:
228                 draw_cd_label_outline (cr, template, x0, y0);
229                 break;
230
231         default:
232                 g_message ("Unknown label style");
233                 break;
234         }
235
236         cairo_restore (cr);
237
238         gl_debug (DEBUG_MINI_PREVIEW, "END");
239 }
240
241 /*--------------------------------------------------------------------------*/
242 /* PRIVATE.  Draw rectangular label outline.                                */
243 /*--------------------------------------------------------------------------*/
244 static void
245 draw_rect_label_outline (cairo_t           *cr,
246                          const glTemplate  *template,
247                          gdouble            x0,
248                          gdouble            y0)
249 {
250         const glTemplateLabelType *label_type;
251         gdouble                    w, h;
252
253         gl_debug (DEBUG_MINI_PREVIEW, "START");
254
255         cairo_save (cr);
256
257         label_type = gl_template_get_first_label_type (template);
258         gl_template_get_label_size (label_type, &w, &h);
259
260         cairo_rectangle (cr, x0, y0, w, h);
261         cairo_stroke (cr);
262
263         cairo_restore (cr);
264
265         gl_debug (DEBUG_MINI_PREVIEW, "END");
266 }
267
268 /*--------------------------------------------------------------------------*/
269 /* PRIVATE.  Draw round label outline.                                      */
270 /*--------------------------------------------------------------------------*/
271 static void
272 draw_round_label_outline (cairo_t           *cr,
273                           const glTemplate  *template,
274                           gdouble            x0,
275                           gdouble            y0)
276 {
277         const glTemplateLabelType *label_type;
278         gdouble                    w, h;
279
280         gl_debug (DEBUG_MINI_PREVIEW, "START");
281
282         cairo_save (cr);
283
284         label_type = gl_template_get_first_label_type (template);
285         gl_template_get_label_size (label_type, &w, &h);
286
287         cairo_arc (cr, x0+w/2, y0+h/2, w/2, 0.0, 2*M_PI);
288         cairo_stroke (cr);
289
290         cairo_restore (cr);
291
292         gl_debug (DEBUG_MINI_PREVIEW, "END");
293 }
294
295 /*--------------------------------------------------------------------------*/
296 /* PRIVATE.  Draw cd label outline.                                         */
297 /*--------------------------------------------------------------------------*/
298 static void
299 draw_cd_label_outline (cairo_t           *cr,
300                        const glTemplate  *template,
301                        gdouble            x0,
302                        gdouble            y0)
303 {
304         const glTemplateLabelType *label_type;
305         gdouble                    w, h;
306         gdouble                    xc, yc;
307         gdouble                    r1, r2;
308
309         gl_debug (DEBUG_MINI_PREVIEW, "START");
310
311         cairo_save (cr);
312
313         label_type = gl_template_get_first_label_type (template);
314         gl_template_get_label_size (label_type, &w, &h);
315
316         xc = x0 + w/2.0;
317         yc = y0 + h/2.0;
318
319         r1 = label_type->size.cd.r1;
320         r2 = label_type->size.cd.r2;
321
322         if ( w == h )
323         {
324                 /* Simple CD */
325                 cairo_arc (cr, xc, yc, r1, 0.0, 2*M_PI);
326                 cairo_stroke (cr);
327         }
328         else
329         {
330                 /* Credit Card CD (One or both dimensions trucated) */
331                 gdouble theta1, theta2;
332
333                 theta1 = acos (w / (2.0*r1));
334                 theta2 = asin (h / (2.0*r1));
335
336                 cairo_new_path (cr);
337                 cairo_arc (cr, xc, yc, r1, theta1, theta2);
338                 cairo_arc (cr, xc, yc, r1, M_PI-theta2, M_PI-theta1);
339                 cairo_arc (cr, xc, yc, r1, M_PI+theta1, M_PI+theta2);
340                 cairo_arc (cr, xc, yc, r1, 2*M_PI-theta2, 2*M_PI-theta1);
341                 cairo_close_path (cr);
342                 cairo_stroke (cr);
343         }
344
345         /* Hole */
346         cairo_arc (cr, xc, yc, r2, 0.0, 2*M_PI);
347         cairo_stroke (cr);
348         
349         cairo_restore (cr);
350
351         gl_debug (DEBUG_MINI_PREVIEW, "END");
352 }
353
354
355