]> git.sur5r.net Git - glabels/blob - src/wdgt-mini-preview.c
Imported Upstream version 2.2.8
[glabels] / src / wdgt-mini-preview.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  *  wdgt_mini_preview.c:  mini preview widget module
7  *
8  *  Copyright (C) 2001-2007  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 "wdgt-mini-preview.h"
28
29 #include <math.h>
30
31 #include "libglabels/db.h"
32 #include "cairo-label-path.h"
33 #include "marshal.h"
34 #include "color.h"
35
36 #include "debug.h"
37
38 /*===========================================*/
39 /* Private macros and constants.             */
40 /*===========================================*/
41
42 #define PAPER_RGB_ARGS          1.0,   1.0,   1.0
43 #define PAPER_OUTLINE_RGB_ARGS  0.0,   0.0,   0.0
44 #define LABEL_OUTLINE_RGB_ARGS  0.5,   0.5,   0.5
45
46 #define SHADOW_X_OFFSET 5
47 #define SHADOW_Y_OFFSET 5
48
49 /*===========================================*/
50 /* Private types                             */
51 /*===========================================*/
52
53 enum {
54         CLICKED,
55         PRESSED,
56         LAST_SIGNAL
57 };
58
59 typedef struct {
60         gdouble x;
61         gdouble y;
62 } LabelCenter;
63
64 struct _glWdgtMiniPreviewPrivate {
65
66         gint            height;
67         gint            width;
68
69         lglTemplate    *template;
70         gdouble         scale;
71         gdouble         offset_x;
72         gdouble         offset_y;
73         gint            labels_per_sheet;
74         LabelCenter    *centers;
75
76         gint            highlight_first;
77         gint            highlight_last;
78
79         gboolean        dragging;
80         gint            first_i;
81         gint            last_i;
82         gint            prev_i;
83 };
84
85 /*===========================================*/
86 /* Private globals                           */
87 /*===========================================*/
88
89 static gint wdgt_mini_preview_signals[LAST_SIGNAL] = { 0 };
90
91 /*===========================================*/
92 /* Local function prototypes                 */
93 /*===========================================*/
94
95 static void gl_wdgt_mini_preview_finalize      (GObject                *object);
96
97 static void gl_wdgt_mini_preview_construct     (glWdgtMiniPreview      *preview,
98                                                 gint                    height,
99                                                 gint                    width);
100
101 static gboolean expose_event_cb                (GtkWidget              *widget,
102                                                 GdkEventExpose         *event);
103 static void style_set_cb                       (GtkWidget              *widget,
104                                                 GtkStyle               *previous_style);
105 static gboolean button_press_event_cb          (GtkWidget              *widget,
106                                                 GdkEventButton         *event);
107 static gboolean motion_notify_event_cb         (GtkWidget              *widget,
108                                                 GdkEventMotion         *event);
109 static gboolean button_release_event_cb        (GtkWidget              *widget,
110                                                 GdkEventButton         *event);
111
112
113 static void redraw                             (GtkWidget              *widget);
114 static void draw                               (glWdgtMiniPreview      *preview,
115                                                 cairo_t                *cr);
116
117 static void draw_shadow                        (glWdgtMiniPreview      *preview,
118                                                 cairo_t                *cr,
119                                                 gdouble                      x,
120                                                 gdouble                 y,
121                                                 gdouble                 width,
122                                                 gdouble                 height);
123 static void draw_paper                         (glWdgtMiniPreview      *preview,
124                                                 cairo_t                *cr,
125                                                 gdouble                 width,
126                                                 gdouble                 height,
127                                                 gdouble                 line_width);
128 static void draw_labels                        (glWdgtMiniPreview      *preview,
129                                                 cairo_t                *cr,
130                                                 lglTemplate            *template,
131                                                 gdouble                 line_width);
132
133 static gint find_closest_label                 (glWdgtMiniPreview      *preview,
134                                                 gdouble                 x,
135                                                 gdouble                 y);
136
137
138 \f
139 /****************************************************************************/
140 /* Boilerplate Object stuff.                                                */
141 /****************************************************************************/
142 G_DEFINE_TYPE (glWdgtMiniPreview, gl_wdgt_mini_preview, GTK_TYPE_DRAWING_AREA);
143
144
145 static void
146 gl_wdgt_mini_preview_class_init (glWdgtMiniPreviewClass *class)
147 {
148         GObjectClass   *object_class = G_OBJECT_CLASS (class);
149         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
150
151         gl_debug (DEBUG_MINI_PREVIEW, "START");
152
153         gl_wdgt_mini_preview_parent_class = gtk_type_class (gtk_hbox_get_type ());
154
155         object_class->finalize = gl_wdgt_mini_preview_finalize;
156
157         widget_class->expose_event         = expose_event_cb;
158         widget_class->style_set            = style_set_cb;
159         widget_class->button_press_event   = button_press_event_cb;
160         widget_class->motion_notify_event  = motion_notify_event_cb;
161         widget_class->button_release_event = button_release_event_cb;
162
163         wdgt_mini_preview_signals[CLICKED] =
164             g_signal_new ("clicked",
165                           G_OBJECT_CLASS_TYPE(object_class),
166                           G_SIGNAL_RUN_LAST,
167                           G_STRUCT_OFFSET (glWdgtMiniPreviewClass, clicked),
168                           NULL, NULL,
169                           gl_marshal_VOID__INT,
170                           G_TYPE_NONE, 1, G_TYPE_INT);
171
172         wdgt_mini_preview_signals[PRESSED] =
173             g_signal_new ("pressed",
174                           G_OBJECT_CLASS_TYPE(object_class),
175                           G_SIGNAL_RUN_LAST,
176                           G_STRUCT_OFFSET (glWdgtMiniPreviewClass, pressed),
177                           NULL, NULL,
178                           gl_marshal_VOID__INT_INT,
179                           G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
180
181         gl_debug (DEBUG_MINI_PREVIEW, "END");
182 }
183
184 static void
185 gl_wdgt_mini_preview_init (glWdgtMiniPreview *preview)
186 {
187         gl_debug (DEBUG_MINI_PREVIEW, "START");
188
189         preview->priv = g_new0 (glWdgtMiniPreviewPrivate, 1);
190
191         gtk_widget_add_events (GTK_WIDGET (preview),
192                                GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
193                                GDK_POINTER_MOTION_MASK);
194
195         gl_debug (DEBUG_MINI_PREVIEW, "END");
196 }
197
198 static void
199 gl_wdgt_mini_preview_finalize (GObject *object)
200 {
201         glWdgtMiniPreview *preview = GL_WDGT_MINI_PREVIEW (object);
202
203         gl_debug (DEBUG_MINI_PREVIEW, "START");
204
205         g_return_if_fail (object != NULL);
206         g_return_if_fail (GL_IS_WDGT_MINI_PREVIEW (object));
207
208         lgl_template_free (preview->priv->template);
209         g_free (preview->priv->centers);
210         g_free (preview->priv);
211
212         G_OBJECT_CLASS (gl_wdgt_mini_preview_parent_class)->finalize (object);
213
214         gl_debug (DEBUG_MINI_PREVIEW, "END");
215 }
216
217 GtkWidget *
218 gl_wdgt_mini_preview_new (gint height,
219                           gint width)
220 {
221         glWdgtMiniPreview *preview;
222
223         gl_debug (DEBUG_MINI_PREVIEW, "START");
224
225         preview = g_object_new (gl_wdgt_mini_preview_get_type (), NULL);
226
227         gl_wdgt_mini_preview_construct (preview, height, width);
228
229         gl_debug (DEBUG_MINI_PREVIEW, "END");
230
231         return GTK_WIDGET (preview);
232 }
233
234 /*--------------------------------------------------------------------------*/
235 /* Construct composite widget.                                              */
236 /*--------------------------------------------------------------------------*/
237 static void
238 gl_wdgt_mini_preview_construct (glWdgtMiniPreview *preview,
239                                 gint               height,
240                                 gint               width)
241 {
242         gl_debug (DEBUG_MINI_PREVIEW, "START");
243
244         preview->priv->height = height;
245         preview->priv->width  = width;
246
247         gtk_widget_set_size_request (GTK_WIDGET (preview), width, height);
248
249         gl_debug (DEBUG_MINI_PREVIEW, "END");
250 }
251
252 /****************************************************************************/
253 /* Set label for mini-preview to determine geometry.                        */
254 /****************************************************************************/
255 void gl_wdgt_mini_preview_set_label_by_name (glWdgtMiniPreview *preview,
256                                              const gchar       *name)
257 {
258         lglTemplate *template;
259
260         gl_debug (DEBUG_MINI_PREVIEW, "START");
261
262         /* Fetch template */
263         template = lgl_db_lookup_template_from_name (name);
264
265         gl_wdgt_mini_preview_set_template (preview, template);
266
267         lgl_template_free (template);
268
269         gl_debug (DEBUG_MINI_PREVIEW, "END");
270 }
271
272 /****************************************************************************/
273 /* Set label for mini-preview to determine geometry.                        */
274 /****************************************************************************/
275 void gl_wdgt_mini_preview_set_template (glWdgtMiniPreview *preview,
276                                         const lglTemplate *template)
277 {
278         const lglTemplateFrame    *frame;
279         lglTemplateOrigin         *origins;
280         gdouble                    w, h;
281         gint                       i;
282
283         gl_debug (DEBUG_MINI_PREVIEW, "START");
284
285         frame = (lglTemplateFrame *)template->frames->data;
286
287         /*
288          * Set template
289          */
290         lgl_template_free (preview->priv->template);
291         preview->priv->template = lgl_template_dup (template);
292
293         /*
294          * Set scale and offsets
295          */
296         w = preview->priv->width - 4 - 2*SHADOW_X_OFFSET;
297         h = preview->priv->height - 4 - 2*SHADOW_Y_OFFSET;
298         if ( (w/template->page_width) > (h/template->page_height) ) {
299                 preview->priv->scale = h / template->page_height;
300         } else {
301                 preview->priv->scale = w / template->page_width;
302         }
303         preview->priv->offset_x = (preview->priv->width/preview->priv->scale - template->page_width) / 2.0;
304         preview->priv->offset_y = (preview->priv->height/preview->priv->scale - template->page_height) / 2.0;
305
306         /*
307          * Set labels per sheet
308          */
309         preview->priv->labels_per_sheet = lgl_template_frame_get_n_labels (frame);
310
311         /*
312          * Initialize centers
313          */
314         g_free (preview->priv->centers);
315         preview->priv->centers = g_new0 (LabelCenter, preview->priv->labels_per_sheet);
316         origins = lgl_template_frame_get_origins (frame);
317         lgl_template_frame_get_size (frame, &w, &h);
318         for ( i=0; i<preview->priv->labels_per_sheet; i++ )
319         {
320                 preview->priv->centers[i].x = origins[i].x + w/2.0;
321                 preview->priv->centers[i].y = origins[i].y + h/2.0;
322         }
323         g_free (origins);
324
325         /*
326          * Redraw modified preview
327          */
328         redraw( GTK_WIDGET (preview));
329
330         gl_debug (DEBUG_MINI_PREVIEW, "END");
331 }
332
333 /****************************************************************************/
334 /* Highlight given label outlines.                                          */
335 /****************************************************************************/
336 void
337 gl_wdgt_mini_preview_highlight_range (glWdgtMiniPreview *preview,
338                                       gint               first_label,
339                                       gint               last_label)
340 {
341         gl_debug (DEBUG_MINI_PREVIEW, "START");
342
343         preview->priv->highlight_first = first_label;
344         preview->priv->highlight_last =  last_label;
345
346         redraw( GTK_WIDGET (preview));
347
348         gl_debug (DEBUG_MINI_PREVIEW, "END");
349 }
350
351
352 /*--------------------------------------------------------------------------*/
353 /* Expose event handler.                                                    */
354 /*--------------------------------------------------------------------------*/
355 static gboolean
356 expose_event_cb (GtkWidget       *widget,
357                  GdkEventExpose  *event)
358 {
359         cairo_t *cr;
360
361         gl_debug (DEBUG_MINI_PREVIEW, "START");
362
363         cr = gdk_cairo_create (widget->window);
364
365         cairo_rectangle (cr,
366                         event->area.x, event->area.y,
367                         event->area.width, event->area.height);
368         cairo_clip (cr);
369         
370         draw (GL_WDGT_MINI_PREVIEW (widget), cr);
371
372         cairo_destroy (cr);
373
374         gl_debug (DEBUG_MINI_PREVIEW, "END");
375         return FALSE;
376 }
377
378 /*--------------------------------------------------------------------------*/
379 /* Button press event handler                                               */
380 /*--------------------------------------------------------------------------*/
381 static gboolean
382 button_press_event_cb (GtkWidget      *widget,
383                        GdkEventButton *event)
384 {
385         glWdgtMiniPreview *preview = GL_WDGT_MINI_PREVIEW (widget);
386         cairo_t           *cr;
387         gdouble            x, y;
388         gint               i;
389
390         gl_debug (DEBUG_MINI_PREVIEW, "START");
391
392         if ( event->button == 1 )
393         {
394                 cr = gdk_cairo_create (widget->window);
395
396                 /* Set transformation. */
397                 cairo_identity_matrix (cr);
398                 cairo_scale (cr, preview->priv->scale, preview->priv->scale);
399                 cairo_translate (cr, preview->priv->offset_x, preview->priv->offset_y);
400
401                 x = event->x;
402                 y = event->y;
403                 cairo_device_to_user (cr, &x, &y);
404
405                 i = find_closest_label (preview, x, y);
406
407                 g_signal_emit (G_OBJECT(preview),
408                                wdgt_mini_preview_signals[CLICKED],
409                                0, i);
410
411                 preview->priv->first_i = i;
412                 preview->priv->last_i  = i;
413                 g_signal_emit (G_OBJECT(preview),
414                                wdgt_mini_preview_signals[PRESSED],
415                                0, preview->priv->first_i, preview->priv->last_i);
416
417                 preview->priv->dragging = TRUE;
418                 preview->priv->prev_i   = i;
419
420                 cairo_destroy (cr);
421         }
422
423         gl_debug (DEBUG_MINI_PREVIEW, "END");
424         return FALSE;
425 }
426
427 /*--------------------------------------------------------------------------*/
428 /* Motion notify event handler                                              */
429 /*--------------------------------------------------------------------------*/
430 static gboolean
431 motion_notify_event_cb (GtkWidget      *widget,
432                         GdkEventMotion *event)
433 {
434         glWdgtMiniPreview *preview = GL_WDGT_MINI_PREVIEW (widget);
435         cairo_t           *cr;
436         gdouble            x, y;
437         gint               i;
438
439         gl_debug (DEBUG_MINI_PREVIEW, "START");
440
441         if (preview->priv->dragging)
442         {
443                 cr = gdk_cairo_create (widget->window);
444
445                 /* Set transformation. */
446                 cairo_identity_matrix (cr);
447                 cairo_scale (cr, preview->priv->scale, preview->priv->scale);
448                 cairo_translate (cr, preview->priv->offset_x, preview->priv->offset_y);
449
450                 x = event->x;
451                 y = event->y;
452                 cairo_device_to_user (cr, &x, &y);
453
454                 i = find_closest_label (preview, x, y);
455
456                 if ( i != preview->priv->prev_i )
457                 {
458                         preview->priv->last_i = i;
459
460                         g_signal_emit (G_OBJECT(preview),
461                                        wdgt_mini_preview_signals[PRESSED],
462                                        0,
463                                        MIN (preview->priv->first_i, preview->priv->last_i),
464                                        MAX (preview->priv->first_i, preview->priv->last_i));
465
466                         preview->priv->prev_i = i;
467                 }
468                 cairo_destroy (cr);
469         }
470
471         gl_debug (DEBUG_MINI_PREVIEW, "END");
472         return FALSE;
473 }
474
475 /*--------------------------------------------------------------------------*/
476 /* Button release event handler                                             */
477 /*--------------------------------------------------------------------------*/
478 static gboolean
479 button_release_event_cb (GtkWidget      *widget,
480                          GdkEventButton *event)
481 {
482         glWdgtMiniPreview *preview = GL_WDGT_MINI_PREVIEW (widget);
483         
484         gl_debug (DEBUG_MINI_PREVIEW, "START");
485
486         if ( event->button == 1 )
487         {
488                 preview->priv->dragging = FALSE;
489
490         }
491
492         gl_debug (DEBUG_MINI_PREVIEW, "END");
493         return FALSE;
494 }
495
496 /*--------------------------------------------------------------------------*/
497 /* Style set handler (updates colors when style/theme changes).             */
498 /*--------------------------------------------------------------------------*/
499 static void
500 style_set_cb (GtkWidget        *widget,
501               GtkStyle         *previous_style)
502 {
503         gl_debug (DEBUG_MINI_PREVIEW, "START");
504
505         redraw( widget );
506
507         gl_debug (DEBUG_MINI_PREVIEW, "END");
508 }
509
510 /*--------------------------------------------------------------------------*/
511 /* Redraw.                                                                  */
512 /*--------------------------------------------------------------------------*/
513 static void
514 redraw (GtkWidget *widget)
515 {
516         GdkRegion *region;
517         
518         gl_debug (DEBUG_MINI_PREVIEW, "START");
519
520         if (widget->window)
521         {
522
523                 region = gdk_drawable_get_clip_region (widget->window);
524
525                 gdk_window_invalidate_region (widget->window, region, TRUE);
526                 gdk_window_process_updates (widget->window, TRUE);
527
528                 gdk_region_destroy (region);
529         }
530
531         gl_debug (DEBUG_MINI_PREVIEW, "END");
532 }
533
534 /*--------------------------------------------------------------------------*/
535 /* Find index+1 of label closest to given coordinates.                      */
536 /*--------------------------------------------------------------------------*/
537 static gint
538 find_closest_label (glWdgtMiniPreview      *preview,
539                     gdouble                 x,
540                     gdouble                 y)
541 {
542         gint    i;
543         gint    min_i;
544         gdouble dx, dy, d2, min_d2;
545
546         dx = x - preview->priv->centers[0].x;
547         dy = y - preview->priv->centers[0].y;
548         min_d2 = dx*dx + dy*dy;
549         min_i = 0;
550
551         for ( i=1; i<preview->priv->labels_per_sheet; i++ )
552         {
553                 dx = x - preview->priv->centers[i].x;
554                 dy = y - preview->priv->centers[i].y;
555                 d2 = dx*dx + dy*dy;
556
557                 if ( d2 < min_d2 )
558                 {
559                         min_d2 = d2;
560                         min_i  = i;
561                 }
562         }
563
564         return min_i + 1;
565 }
566
567 /*--------------------------------------------------------------------------*/
568 /* Draw mini preview.                                                       */
569 /*--------------------------------------------------------------------------*/
570 static void
571 draw (glWdgtMiniPreview  *preview,
572       cairo_t            *cr)
573 {
574         lglTemplate *template = preview->priv->template;
575         gdouble      shadow_x, shadow_y;
576
577         gl_debug (DEBUG_MINI_PREVIEW, "START");
578
579         if (template)
580         {
581
582                 /* Set transformation. */
583                 cairo_identity_matrix (cr);
584                 cairo_scale (cr, preview->priv->scale, preview->priv->scale);
585                 cairo_translate (cr, preview->priv->offset_x, preview->priv->offset_y);
586
587
588                 /* update shadow */
589                 shadow_x = SHADOW_X_OFFSET/preview->priv->scale;
590                 shadow_y = SHADOW_Y_OFFSET/preview->priv->scale;
591
592                 draw_shadow (preview, cr,
593                              shadow_x, shadow_y,
594                              template->page_width, template->page_height);
595
596                 draw_paper (preview, cr,
597                             template->page_width, template->page_height,
598                             1.0/preview->priv->scale);
599
600                 draw_labels (preview, cr, template, 1.0/preview->priv->scale);
601                              
602         }
603
604         gl_debug (DEBUG_MINI_PREVIEW, "END");
605
606 }
607
608
609 /*--------------------------------------------------------------------------*/
610 /* Draw page shadow                                                         */
611 /*--------------------------------------------------------------------------*/
612 static void
613 draw_shadow (glWdgtMiniPreview      *preview,
614              cairo_t                *cr,
615              gdouble                 x,
616              gdouble                 y,
617              gdouble                 width,
618              gdouble                 height)
619 {
620         GtkStyle *style;
621         guint     shadow_color;
622
623         gl_debug (DEBUG_MINI_PREVIEW, "START");
624
625         cairo_save (cr);
626
627         cairo_rectangle (cr, x, y, width, height);
628
629         style = gtk_widget_get_style (GTK_WIDGET(preview));
630         shadow_color = gl_color_from_gdk_color (&style->bg[GTK_STATE_ACTIVE]);
631         cairo_set_source_rgb (cr, GL_COLOR_RGB_ARGS (shadow_color));
632
633         cairo_fill (cr);
634
635         cairo_restore (cr);
636
637         gl_debug (DEBUG_MINI_PREVIEW, "END");
638 }
639
640 /*--------------------------------------------------------------------------*/
641 /* Draw page                                                                */
642 /*--------------------------------------------------------------------------*/
643 static void
644 draw_paper (glWdgtMiniPreview      *preview,
645             cairo_t                *cr,
646             gdouble                 width,
647             gdouble                 height,
648             gdouble                 line_width)
649 {
650         cairo_save (cr);
651
652         gl_debug (DEBUG_MINI_PREVIEW, "START");
653
654         cairo_rectangle (cr, 0.0, 0.0, width, height);
655
656         cairo_set_source_rgb (cr, PAPER_RGB_ARGS);
657         cairo_fill_preserve (cr);
658
659         cairo_set_source_rgb (cr, PAPER_OUTLINE_RGB_ARGS);
660         cairo_set_line_width (cr, line_width);
661         cairo_stroke (cr);
662
663         cairo_restore (cr);
664
665         gl_debug (DEBUG_MINI_PREVIEW, "END");
666 }
667
668 /*--------------------------------------------------------------------------*/
669 /* Draw labels                                                              */
670 /*--------------------------------------------------------------------------*/
671 static void
672 draw_labels (glWdgtMiniPreview *preview,
673              cairo_t           *cr,
674              lglTemplate       *template,
675              gdouble            line_width)
676 {
677         const lglTemplateFrame    *frame;
678         gint                       i, n_labels;
679         lglTemplateOrigin         *origins;
680         GtkStyle                  *style;
681         guint                      highlight_color;
682
683         gl_debug (DEBUG_MINI_PREVIEW, "START");
684
685         frame = (lglTemplateFrame *)template->frames->data;
686
687         n_labels = lgl_template_frame_get_n_labels (frame);
688         origins  = lgl_template_frame_get_origins (frame);
689
690         style = gtk_widget_get_style (GTK_WIDGET(preview));
691         highlight_color = gl_color_from_gdk_color (&style->base[GTK_STATE_SELECTED]);
692
693         for ( i=0; i < n_labels; i++ ) {
694
695                 cairo_save (cr);
696
697                 cairo_translate (cr, origins[i].x, origins[i].y);
698                 gl_cairo_label_path (cr, template, FALSE, FALSE);
699
700                 if ( ((i+1) >= preview->priv->highlight_first) &&
701                      ((i+1) <= preview->priv->highlight_last) )
702                 {
703                         cairo_set_source_rgb (cr, GL_COLOR_RGB_ARGS (highlight_color));
704                 }
705                 else
706                 {
707                         cairo_set_source_rgb (cr, PAPER_RGB_ARGS);
708                 }
709                 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
710                 cairo_fill_preserve (cr);
711
712                 cairo_set_line_width (cr, line_width);
713                 cairo_set_source_rgb (cr, LABEL_OUTLINE_RGB_ARGS);
714                 cairo_stroke (cr);
715
716                 cairo_restore (cr);
717
718         }
719
720         g_free (origins);
721
722         gl_debug (DEBUG_MINI_PREVIEW, "END");
723 }
724