3 * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
5 * This file is part of gLabels.
7 * gLabels is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU 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.
12 * gLabels 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 General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with gLabels. If not, see <http://www.gnu.org/licenses/>.
25 #include <glib/gi18n.h>
30 #include <libglabels/libglabels.h>
32 #include "cairo-label-path.h"
37 /*===========================================*/
38 /* Private macros and constants. */
39 /*===========================================*/
41 #define OUTLINE_RGB_ARGS 0.0, 0.0, 0.0
43 #define OUTLINE_WIDTH 0.25
45 #define TICK_OFFSET 2.25
46 #define TICK_LENGTH 18.0
49 /*=========================================================================*/
51 /*=========================================================================*/
53 typedef struct _PrintInfo {
56 /* gLabels Template */
57 lglTemplate *template;
58 gboolean label_rotate_flag;
67 /*=========================================================================*/
68 /* Private function prototypes. */
69 /*=========================================================================*/
70 static PrintInfo *print_info_new (cairo_t *cr,
73 static void print_info_free (PrintInfo **pi);
75 static void print_crop_marks (PrintInfo *pi);
77 static void print_label (PrintInfo *pi,
81 glMergeRecord *record,
82 gboolean outline_flag,
83 gboolean reverse_flag);
86 static void draw_outline (PrintInfo *pi,
89 static void clip_to_outline (PrintInfo *pi,
93 /*****************************************************************************/
94 /* Print simple sheet (no merge data) command. */
95 /*****************************************************************************/
97 gl_print_simple_sheet (glLabel *label,
103 gboolean outline_flag,
104 gboolean reverse_flag,
105 gboolean crop_marks_flag)
108 const lglTemplateFrame *frame;
110 lglTemplateOrigin *origins;
112 gl_debug (DEBUG_PRINT, "START");
114 pi = print_info_new (cr, label);
116 frame = (lglTemplateFrame *)pi->template->frames->data;
117 origins = lgl_template_frame_get_origins (frame);
119 if (crop_marks_flag) {
120 print_crop_marks (pi);
123 for (i_label = first - 1; i_label < last; i_label++) {
125 print_label (pi, label,
126 origins[i_label].x, origins[i_label].y,
127 NULL, outline_flag, reverse_flag);
133 print_info_free (&pi);
135 gl_debug (DEBUG_PRINT, "END");
139 /*****************************************************************************/
140 /* Print collated merge sheet command */
141 /*****************************************************************************/
143 gl_print_collated_merge_sheet (glLabel *label,
148 gboolean outline_flag,
149 gboolean reverse_flag,
150 gboolean crop_marks_flag,
154 const GList *record_list;
156 const lglTemplateFrame *frame;
157 gint i_label, n_labels_per_page, i_copy;
158 glMergeRecord *record;
160 lglTemplateOrigin *origins;
162 gl_debug (DEBUG_PRINT, "START");
164 merge = gl_label_get_merge (label);
165 record_list = gl_merge_get_record_list (merge);
167 pi = print_info_new (cr, label);
168 frame = (lglTemplateFrame *)pi->template->frames->data;
170 n_labels_per_page = lgl_template_frame_get_n_labels (frame);
171 origins = lgl_template_frame_get_origins (frame);
173 if (crop_marks_flag) {
174 print_crop_marks (pi);
180 state->p_record = (GList *)record_list;
190 for ( p=(GList *)state->p_record; p!=NULL; p=p->next ) {
191 record = (glMergeRecord *)p->data;
193 if ( record->select_flag ) {
194 for (i_copy = state->i_copy; i_copy < n_copies; i_copy++) {
196 print_label (pi, label,
200 outline_flag, reverse_flag);
203 if (i_label == n_labels_per_page)
206 print_info_free (&pi);
208 state->i_copy = (i_copy+1) % n_copies;
209 if (state->i_copy == 0)
211 state->p_record = p->next;
225 print_info_free (&pi);
227 gl_debug (DEBUG_PRINT, "END");
231 /*****************************************************************************/
232 /* Print uncollated merge sheet command */
233 /*****************************************************************************/
235 gl_print_uncollated_merge_sheet (glLabel *label,
240 gboolean outline_flag,
241 gboolean reverse_flag,
242 gboolean crop_marks_flag,
246 const GList *record_list;
248 const lglTemplateFrame *frame;
249 gint i_label, n_labels_per_page, i_copy;
250 glMergeRecord *record;
252 lglTemplateOrigin *origins;
254 gl_debug (DEBUG_PRINT, "START");
256 merge = gl_label_get_merge (label);
257 record_list = gl_merge_get_record_list (merge);
259 pi = print_info_new (cr, label);
260 frame = (lglTemplateFrame *)pi->template->frames->data;
262 n_labels_per_page = lgl_template_frame_get_n_labels (frame);
263 origins = lgl_template_frame_get_origins (frame);
265 if (crop_marks_flag) {
266 print_crop_marks (pi);
272 state->p_record = (GList *)record_list;
281 for (i_copy = state->i_copy; i_copy < n_copies; i_copy++) {
283 for ( p=state->p_record; p!=NULL; p=p->next ) {
284 record = (glMergeRecord *)p->data;
286 if ( record->select_flag ) {
288 print_label (pi, label,
292 outline_flag, reverse_flag);
295 if (i_label == n_labels_per_page)
298 print_info_free (&pi);
300 state->p_record = p->next;
301 if (state->p_record == NULL)
303 state->p_record = (GList *)record_list;
304 state->i_copy = i_copy + 1;
308 state->i_copy = i_copy;
314 state->p_record = (GList *)record_list;
319 print_info_free (&pi);
321 gl_debug (DEBUG_PRINT, "END");
325 /*---------------------------------------------------------------------------*/
326 /* PRIVATE. new print info structure */
327 /*---------------------------------------------------------------------------*/
329 print_info_new (cairo_t *cr,
332 PrintInfo *pi = g_new0 (PrintInfo, 1);
334 gl_debug (DEBUG_PRINT, "START");
336 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
338 g_return_val_if_fail (label->template, NULL);
339 g_return_val_if_fail (label->template->paper_id, NULL);
340 g_return_val_if_fail (label->template->page_width > 0, NULL);
341 g_return_val_if_fail (label->template->page_height > 0, NULL);
345 gl_debug (DEBUG_PRINT,
346 "setting page size = \"%s\"", label->template->paper_id);
348 pi->page_width = label->template->page_width;
349 pi->page_height = label->template->page_height;
351 pi->template = label->template;
352 pi->label_rotate_flag = label->rotate_flag;
354 gl_debug (DEBUG_PRINT, "END");
360 /*---------------------------------------------------------------------------*/
361 /* PRIVATE. free print info structure */
362 /*---------------------------------------------------------------------------*/
364 print_info_free (PrintInfo **pi)
366 gl_debug (DEBUG_PRINT, "START");
372 gl_debug (DEBUG_PRINT, "END");
376 /*---------------------------------------------------------------------------*/
377 /* PRIVATE. Print crop tick marks. */
378 /*---------------------------------------------------------------------------*/
380 print_crop_marks (PrintInfo *pi)
382 const lglTemplateFrame *frame;
383 gdouble w, h, page_w, page_h;
385 lglTemplateLayout *layout;
386 gdouble xmin, ymin, xmax, ymax, dx, dy;
387 gdouble x1, y1, x2, y2, x3, y3, x4, y4;
390 gl_debug (DEBUG_PRINT, "START");
392 frame = (lglTemplateFrame *)pi->template->frames->data;
394 lgl_template_frame_get_size (frame, &w, &h);
396 page_w = pi->page_width;
397 page_h = pi->page_height;
401 cairo_set_source_rgb (pi->cr, OUTLINE_RGB_ARGS);
402 cairo_set_line_width (pi->cr, OUTLINE_WIDTH);
404 for (p=frame->all.layouts; p != NULL; p=p->next) {
406 layout = (lglTemplateLayout *)p->data;
410 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
411 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
419 for (ix=0; ix < nx; ix++) {
424 y1 = MAX((ymin - TICK_OFFSET), 0.0);
425 y2 = MAX((y1 - TICK_LENGTH), 0.0);
427 y3 = MIN((ymax + TICK_OFFSET), page_h);
428 y4 = MIN((y3 + TICK_LENGTH), page_h);
430 cairo_move_to (pi->cr, x1, y1);
431 cairo_line_to (pi->cr, x1, y2);
432 cairo_stroke (pi->cr);
434 cairo_move_to (pi->cr, x2, y1);
435 cairo_line_to (pi->cr, x2, y2);
436 cairo_stroke (pi->cr);
438 cairo_move_to (pi->cr, x1, y3);
439 cairo_line_to (pi->cr, x1, y4);
440 cairo_stroke (pi->cr);
442 cairo_move_to (pi->cr, x2, y3);
443 cairo_line_to (pi->cr, x2, y4);
444 cairo_stroke (pi->cr);
448 for (iy=0; iy < ny; iy++) {
453 x1 = MAX((xmin - TICK_OFFSET), 0.0);
454 x2 = MAX((x1 - TICK_LENGTH), 0.0);
456 x3 = MIN((xmax + TICK_OFFSET), page_w);
457 x4 = MIN((x3 + TICK_LENGTH), page_w);
459 cairo_move_to (pi->cr, x1, y1);
460 cairo_line_to (pi->cr, x2, y1);
461 cairo_stroke (pi->cr);
463 cairo_move_to (pi->cr, x1, y2);
464 cairo_line_to (pi->cr, x2, y2);
465 cairo_stroke (pi->cr);
467 cairo_move_to (pi->cr, x3, y1);
468 cairo_line_to (pi->cr, x4, y1);
469 cairo_stroke (pi->cr);
471 cairo_move_to (pi->cr, x3, y2);
472 cairo_line_to (pi->cr, x4, y2);
473 cairo_stroke (pi->cr);
479 cairo_restore (pi->cr);
481 gl_debug (DEBUG_PRINT, "END");
485 /*---------------------------------------------------------------------------*/
486 /* PRIVATE. Print i'th label. */
487 /*---------------------------------------------------------------------------*/
489 print_label (PrintInfo *pi,
493 glMergeRecord *record,
494 gboolean outline_flag,
495 gboolean reverse_flag)
497 const lglTemplateFrame *frame;
498 gdouble width, height;
500 gl_debug (DEBUG_PRINT, "START");
502 frame = (lglTemplateFrame *)pi->template->frames->data;
504 gl_label_get_size (label, &width, &height);
508 /* Transform coordinate system to be relative to upper corner */
509 /* of the current label */
510 cairo_translate (pi->cr, x, y);
514 clip_to_outline (pi, label);
518 /* Special transformations. */
519 if (label->rotate_flag) {
520 gl_debug (DEBUG_PRINT, "Rotate flag set");
521 cairo_rotate (pi->cr, M_PI/2.0);
522 cairo_translate (pi->cr, 0.0, -height);
524 if ( reverse_flag ) {
525 cairo_translate (pi->cr, width, 0.0);
526 cairo_scale (pi->cr, -1.0, 1.0);
529 gl_label_draw (label, pi->cr, FALSE, record);
531 cairo_restore (pi->cr); /* From special transformations. */
533 cairo_restore (pi->cr); /* From clip to outline. */
536 draw_outline (pi, label);
539 cairo_restore (pi->cr); /* From translation. */
541 gl_debug (DEBUG_PRINT, "END");
545 /*---------------------------------------------------------------------------*/
546 /* PRIVATE. Draw outline. */
547 /*---------------------------------------------------------------------------*/
549 draw_outline (PrintInfo *pi,
552 gl_debug (DEBUG_PRINT, "START");
556 cairo_set_source_rgb (pi->cr, OUTLINE_RGB_ARGS);
557 cairo_set_line_width (pi->cr, OUTLINE_WIDTH);
559 gl_cairo_label_path (pi->cr, label->template, FALSE, FALSE);
561 cairo_stroke (pi->cr);
563 cairo_restore (pi->cr);
565 gl_debug (DEBUG_PRINT, "END");
569 /*---------------------------------------------------------------------------*/
570 /* PRIVATE. Clip to outline. */
571 /*---------------------------------------------------------------------------*/
573 clip_to_outline (PrintInfo *pi,
576 gl_debug (DEBUG_PRINT, "START");
578 gl_cairo_label_path (pi->cr, label->template, FALSE, TRUE);
580 cairo_set_fill_rule (pi->cr, CAIRO_FILL_RULE_EVEN_ODD);
583 gl_debug (DEBUG_PRINT, "END");
591 * Local Variables: -- emacs
593 * c-basic-offset: 8 -- emacs
594 * tab-width: 8 -- emacs
595 * indent-tabs-mode: nil -- emacs