1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * print.c: Print module
8 * Copyright (C) 2001-2007 Jim Evins <evins@snaught.com>.
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.
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.
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
28 #include <glib/gi18n.h>
34 #include <libglabels/template.h>
35 #include "cairo-label-path.h"
39 /*===========================================*/
40 /* Private macros and constants. */
41 /*===========================================*/
43 #define TICK_OFFSET 2.25
44 #define TICK_LENGTH 18.0
46 /*=========================================================================*/
48 /*=========================================================================*/
50 typedef struct _PrintInfo {
53 /* gLabels Template */
55 gboolean label_rotate_flag;
64 /*=========================================================================*/
65 /* Private function prototypes. */
66 /*=========================================================================*/
67 static PrintInfo *print_info_new (cairo_t *cr,
70 static void print_info_free (PrintInfo **pi);
72 static void print_crop_marks (PrintInfo *pi);
74 static void print_label (PrintInfo *pi,
78 glMergeRecord *record,
79 gboolean outline_flag,
80 gboolean reverse_flag);
83 static void draw_outline (PrintInfo *pi,
86 static void clip_to_outline (PrintInfo *pi,
91 /*****************************************************************************/
92 /* Print simple sheet (no merge data) command. */
93 /*****************************************************************************/
95 gl_print_simple_sheet (glLabel *label,
101 gboolean outline_flag,
102 gboolean reverse_flag,
103 gboolean crop_marks_flag)
106 const glTemplateLabelType *label_type;
108 glTemplateOrigin *origins;
110 gl_debug (DEBUG_PRINT, "START");
112 pi = print_info_new (cr, label);
114 label_type = gl_template_get_first_label_type (pi->template);
115 origins = gl_template_get_origins (label_type);
117 if (crop_marks_flag) {
118 print_crop_marks (pi);
121 for (i_label = first - 1; i_label < last; i_label++) {
123 print_label (pi, label,
124 origins[i_label].x, origins[i_label].y,
125 NULL, outline_flag, reverse_flag);
131 print_info_free (&pi);
133 gl_debug (DEBUG_PRINT, "END");
136 /*****************************************************************************/
137 /* Print collated merge sheet command */
138 /*****************************************************************************/
140 gl_print_collated_merge_sheet (glLabel *label,
145 gboolean outline_flag,
146 gboolean reverse_flag,
147 gboolean crop_marks_flag,
151 const GList *record_list;
153 const glTemplateLabelType *label_type;
154 gint i_label, n_labels_per_page, i_copy;
155 glMergeRecord *record;
157 glTemplateOrigin *origins;
159 gl_debug (DEBUG_PRINT, "START");
161 merge = gl_label_get_merge (label);
162 record_list = gl_merge_get_record_list (merge);
164 pi = print_info_new (cr, label);
165 label_type = gl_template_get_first_label_type (pi->template);
167 n_labels_per_page = gl_template_get_n_labels (label_type);
168 origins = gl_template_get_origins (label_type);
170 if (crop_marks_flag) {
171 print_crop_marks (pi);
177 state->p_record = (GList *)record_list;
187 for ( p=(GList *)state->p_record; p!=NULL; p=p->next ) {
188 record = (glMergeRecord *)p->data;
190 if ( record->select_flag ) {
191 for (i_copy = state->i_copy; i_copy < n_copies; i_copy++) {
193 print_label (pi, label,
197 outline_flag, reverse_flag);
200 if (i_label == n_labels_per_page)
203 print_info_free (&pi);
205 state->i_copy = (i_copy+1) % n_copies;
206 if (state->i_copy == 0)
208 state->p_record = p->next;
222 print_info_free (&pi);
224 gl_debug (DEBUG_PRINT, "END");
227 /*****************************************************************************/
228 /* Print uncollated merge sheet command */
229 /*****************************************************************************/
231 gl_print_uncollated_merge_sheet (glLabel *label,
236 gboolean outline_flag,
237 gboolean reverse_flag,
238 gboolean crop_marks_flag,
242 const GList *record_list;
244 const glTemplateLabelType *label_type;
245 gint i_label, n_labels_per_page, i_copy;
246 glMergeRecord *record;
248 glTemplateOrigin *origins;
250 gl_debug (DEBUG_PRINT, "START");
252 merge = gl_label_get_merge (label);
253 record_list = gl_merge_get_record_list (merge);
255 pi = print_info_new (cr, label);
256 label_type = gl_template_get_first_label_type (pi->template);
258 n_labels_per_page = gl_template_get_n_labels (label_type);
259 origins = gl_template_get_origins (label_type);
261 if (crop_marks_flag) {
262 print_crop_marks (pi);
268 state->p_record = (GList *)record_list;
277 for (i_copy = state->i_copy; i_copy < n_copies; i_copy++) {
279 for ( p=state->p_record; p!=NULL; p=p->next ) {
280 record = (glMergeRecord *)p->data;
282 if ( record->select_flag ) {
284 print_label (pi, label,
288 outline_flag, reverse_flag);
291 if (i_label == n_labels_per_page)
294 print_info_free (&pi);
296 state->p_record = p->next;
297 if (state->p_record == NULL)
299 state->p_record = (GList *)record_list;
300 state->i_copy = i_copy + 1;
304 state->i_copy = i_copy;
310 state->p_record = (GList *)record_list;
315 print_info_free (&pi);
317 gl_debug (DEBUG_PRINT, "END");
320 /*---------------------------------------------------------------------------*/
321 /* PRIVATE. new print info structure */
322 /*---------------------------------------------------------------------------*/
324 print_info_new (cairo_t *cr,
327 PrintInfo *pi = g_new0 (PrintInfo, 1);
329 gl_debug (DEBUG_PRINT, "START");
331 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
333 g_return_val_if_fail (label->template, NULL);
334 g_return_val_if_fail (label->template->page_size, NULL);
335 g_return_val_if_fail (label->template->page_width > 0, NULL);
336 g_return_val_if_fail (label->template->page_height > 0, NULL);
340 gl_debug (DEBUG_PRINT,
341 "setting page size = \"%s\"", label->template->page_size);
343 pi->page_width = label->template->page_width;
344 pi->page_height = label->template->page_height;
346 pi->template = label->template;
347 pi->label_rotate_flag = label->rotate_flag;
349 gl_debug (DEBUG_PRINT, "END");
354 /*---------------------------------------------------------------------------*/
355 /* PRIVATE. free print info structure */
356 /*---------------------------------------------------------------------------*/
358 print_info_free (PrintInfo **pi)
360 gl_debug (DEBUG_PRINT, "START");
366 gl_debug (DEBUG_PRINT, "END");
369 /*---------------------------------------------------------------------------*/
370 /* PRIVATE. Print crop tick marks. */
371 /*---------------------------------------------------------------------------*/
373 print_crop_marks (PrintInfo *pi)
375 const glTemplateLabelType *label_type;
376 gdouble w, h, page_w, page_h;
378 glTemplateLayout *layout;
379 gdouble xmin, ymin, xmax, ymax, dx, dy;
380 gdouble x1, y1, x2, y2, x3, y3, x4, y4;
383 gl_debug (DEBUG_PRINT, "START");
385 label_type = gl_template_get_first_label_type (pi->template);
387 gl_template_get_label_size (label_type, &w, &h);
389 page_w = pi->page_width;
390 page_h = pi->page_height;
394 cairo_set_source_rgba (pi->cr, 0.0, 0.0, 0.0, 1.0);
395 cairo_set_line_width (pi->cr, 0.25);
397 for (p=label_type->layouts; p != NULL; p=p->next) {
399 layout = (glTemplateLayout *)p->data;
403 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
404 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
412 for (ix=0; ix < nx; ix++) {
417 y1 = MAX((ymin - TICK_OFFSET), 0.0);
418 y2 = MAX((y1 - TICK_LENGTH), 0.0);
420 y3 = MIN((ymax + TICK_OFFSET), page_h);
421 y4 = MIN((y3 + TICK_LENGTH), page_h);
423 cairo_move_to (pi->cr, x1, y1);
424 cairo_line_to (pi->cr, x1, y2);
425 cairo_stroke (pi->cr);
427 cairo_move_to (pi->cr, x2, y1);
428 cairo_line_to (pi->cr, x2, y2);
429 cairo_stroke (pi->cr);
431 cairo_move_to (pi->cr, x1, y3);
432 cairo_line_to (pi->cr, x1, y4);
433 cairo_stroke (pi->cr);
435 cairo_move_to (pi->cr, x2, y3);
436 cairo_line_to (pi->cr, x2, y4);
437 cairo_stroke (pi->cr);
441 for (iy=0; iy < ny; iy++) {
446 x1 = MAX((xmin - TICK_OFFSET), 0.0);
447 x2 = MAX((x1 - TICK_LENGTH), 0.0);
449 x3 = MIN((xmax + TICK_OFFSET), page_w);
450 x4 = MIN((x3 + TICK_LENGTH), page_w);
452 cairo_move_to (pi->cr, x1, y1);
453 cairo_line_to (pi->cr, x2, y1);
454 cairo_stroke (pi->cr);
456 cairo_move_to (pi->cr, x1, y2);
457 cairo_line_to (pi->cr, x2, y2);
458 cairo_stroke (pi->cr);
460 cairo_move_to (pi->cr, x3, y1);
461 cairo_line_to (pi->cr, x4, y1);
462 cairo_stroke (pi->cr);
464 cairo_move_to (pi->cr, x3, y2);
465 cairo_line_to (pi->cr, x4, y2);
466 cairo_stroke (pi->cr);
472 cairo_restore (pi->cr);
474 gl_debug (DEBUG_PRINT, "END");
477 /*---------------------------------------------------------------------------*/
478 /* PRIVATE. Print i'th label. */
479 /*---------------------------------------------------------------------------*/
481 print_label (PrintInfo *pi,
485 glMergeRecord *record,
486 gboolean outline_flag,
487 gboolean reverse_flag)
489 const glTemplateLabelType *label_type;
490 gdouble width, height;
492 gl_debug (DEBUG_PRINT, "START");
494 label_type = gl_template_get_first_label_type (pi->template);
496 gl_label_get_size (label, &width, &height);
500 /* Transform coordinate system to be relative to upper corner */
501 /* of the current label */
502 cairo_translate (pi->cr, x, y);
503 if (label->rotate_flag) {
504 gl_debug (DEBUG_PRINT, "Rotate flag set");
505 cairo_rotate (pi->cr, -M_PI/2.0);
506 cairo_translate (pi->cr, -width, 0.0);
508 if ( reverse_flag ) {
509 cairo_translate (pi->cr, width, 0.0);
510 cairo_scale (pi->cr, -1.0, 1.0);
513 clip_to_outline (pi, label);
514 gl_label_draw (label, pi->cr, FALSE, record);
516 draw_outline (pi, label);
519 cairo_restore (pi->cr);
521 gl_debug (DEBUG_PRINT, "END");
524 /*---------------------------------------------------------------------------*/
525 /* PRIVATE. Draw outline. */
526 /*---------------------------------------------------------------------------*/
528 draw_outline (PrintInfo *pi,
531 gl_debug (DEBUG_PRINT, "START");
535 cairo_set_source_rgba (pi->cr, 0.0, 0.0, 0.0, 1.0);
536 cairo_set_line_width (pi->cr, 0.25);
538 gl_cairo_label_path (pi->cr, label->template, FALSE, FALSE);
540 cairo_stroke (pi->cr);
542 cairo_restore (pi->cr);
544 gl_debug (DEBUG_PRINT, "END");
547 /*---------------------------------------------------------------------------*/
548 /* PRIVATE. Clip to outline. */
549 /*---------------------------------------------------------------------------*/
551 clip_to_outline (PrintInfo *pi,
554 gl_debug (DEBUG_PRINT, "START");
556 gl_cairo_label_path (pi->cr, label->template, FALSE, TRUE);
558 cairo_set_fill_rule (pi->cr, CAIRO_FILL_RULE_EVEN_ODD);
561 gl_debug (DEBUG_PRINT, "END");