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 OUTLINE_RGB_ARGS 0.0, 0.0, 0.0
45 #define OUTLINE_WIDTH 0.25
47 #define TICK_OFFSET 2.25
48 #define TICK_LENGTH 18.0
50 /*=========================================================================*/
52 /*=========================================================================*/
54 typedef struct _PrintInfo {
57 /* gLabels Template */
58 lglTemplate *template;
59 gboolean label_rotate_flag;
68 /*=========================================================================*/
69 /* Private function prototypes. */
70 /*=========================================================================*/
71 static PrintInfo *print_info_new (cairo_t *cr,
74 static void print_info_free (PrintInfo **pi);
76 static void print_crop_marks (PrintInfo *pi);
78 static void print_label (PrintInfo *pi,
82 glMergeRecord *record,
83 gboolean outline_flag,
84 gboolean reverse_flag);
87 static void draw_outline (PrintInfo *pi,
90 static void clip_to_outline (PrintInfo *pi,
95 /*****************************************************************************/
96 /* Print simple sheet (no merge data) command. */
97 /*****************************************************************************/
99 gl_print_simple_sheet (glLabel *label,
105 gboolean outline_flag,
106 gboolean reverse_flag,
107 gboolean crop_marks_flag)
110 const lglTemplateFrame *frame;
112 lglTemplateOrigin *origins;
114 gl_debug (DEBUG_PRINT, "START");
116 pi = print_info_new (cr, label);
118 frame = (lglTemplateFrame *)pi->template->frames->data;
119 origins = lgl_template_frame_get_origins (frame);
121 if (crop_marks_flag) {
122 print_crop_marks (pi);
125 for (i_label = first - 1; i_label < last; i_label++) {
127 print_label (pi, label,
128 origins[i_label].x, origins[i_label].y,
129 NULL, outline_flag, reverse_flag);
135 print_info_free (&pi);
137 gl_debug (DEBUG_PRINT, "END");
140 /*****************************************************************************/
141 /* Print collated merge sheet command */
142 /*****************************************************************************/
144 gl_print_collated_merge_sheet (glLabel *label,
149 gboolean outline_flag,
150 gboolean reverse_flag,
151 gboolean crop_marks_flag,
155 const GList *record_list;
157 const lglTemplateFrame *frame;
158 gint i_label, n_labels_per_page, i_copy;
159 glMergeRecord *record;
161 lglTemplateOrigin *origins;
163 gl_debug (DEBUG_PRINT, "START");
165 merge = gl_label_get_merge (label);
166 record_list = gl_merge_get_record_list (merge);
168 pi = print_info_new (cr, label);
169 frame = (lglTemplateFrame *)pi->template->frames->data;
171 n_labels_per_page = lgl_template_frame_get_n_labels (frame);
172 origins = lgl_template_frame_get_origins (frame);
174 if (crop_marks_flag) {
175 print_crop_marks (pi);
181 state->p_record = (GList *)record_list;
191 for ( p=(GList *)state->p_record; p!=NULL; p=p->next ) {
192 record = (glMergeRecord *)p->data;
194 if ( record->select_flag ) {
195 for (i_copy = state->i_copy; i_copy < n_copies; i_copy++) {
197 print_label (pi, label,
201 outline_flag, reverse_flag);
204 if (i_label == n_labels_per_page)
207 print_info_free (&pi);
209 state->i_copy = (i_copy+1) % n_copies;
210 if (state->i_copy == 0)
212 state->p_record = p->next;
226 print_info_free (&pi);
228 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");
324 /*---------------------------------------------------------------------------*/
325 /* PRIVATE. new print info structure */
326 /*---------------------------------------------------------------------------*/
328 print_info_new (cairo_t *cr,
331 PrintInfo *pi = g_new0 (PrintInfo, 1);
333 gl_debug (DEBUG_PRINT, "START");
335 g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
337 g_return_val_if_fail (label->template, NULL);
338 g_return_val_if_fail (label->template->paper_id, NULL);
339 g_return_val_if_fail (label->template->page_width > 0, NULL);
340 g_return_val_if_fail (label->template->page_height > 0, NULL);
344 gl_debug (DEBUG_PRINT,
345 "setting page size = \"%s\"", label->template->paper_id);
347 pi->page_width = label->template->page_width;
348 pi->page_height = label->template->page_height;
350 pi->template = label->template;
351 pi->label_rotate_flag = label->rotate_flag;
353 gl_debug (DEBUG_PRINT, "END");
358 /*---------------------------------------------------------------------------*/
359 /* PRIVATE. free print info structure */
360 /*---------------------------------------------------------------------------*/
362 print_info_free (PrintInfo **pi)
364 gl_debug (DEBUG_PRINT, "START");
370 gl_debug (DEBUG_PRINT, "END");
373 /*---------------------------------------------------------------------------*/
374 /* PRIVATE. Print crop tick marks. */
375 /*---------------------------------------------------------------------------*/
377 print_crop_marks (PrintInfo *pi)
379 const lglTemplateFrame *frame;
380 gdouble w, h, page_w, page_h;
382 lglTemplateLayout *layout;
383 gdouble xmin, ymin, xmax, ymax, dx, dy;
384 gdouble x1, y1, x2, y2, x3, y3, x4, y4;
387 gl_debug (DEBUG_PRINT, "START");
389 frame = (lglTemplateFrame *)pi->template->frames->data;
391 lgl_template_frame_get_size (frame, &w, &h);
393 page_w = pi->page_width;
394 page_h = pi->page_height;
398 cairo_set_source_rgb (pi->cr, OUTLINE_RGB_ARGS);
399 cairo_set_line_width (pi->cr, OUTLINE_WIDTH);
401 for (p=frame->all.layouts; p != NULL; p=p->next) {
403 layout = (lglTemplateLayout *)p->data;
407 xmax = layout->x0 + layout->dx*(layout->nx - 1) + w;
408 ymax = layout->y0 + layout->dy*(layout->ny - 1) + h;
416 for (ix=0; ix < nx; ix++) {
421 y1 = MAX((ymin - TICK_OFFSET), 0.0);
422 y2 = MAX((y1 - TICK_LENGTH), 0.0);
424 y3 = MIN((ymax + TICK_OFFSET), page_h);
425 y4 = MIN((y3 + TICK_LENGTH), page_h);
427 cairo_move_to (pi->cr, x1, y1);
428 cairo_line_to (pi->cr, x1, y2);
429 cairo_stroke (pi->cr);
431 cairo_move_to (pi->cr, x2, y1);
432 cairo_line_to (pi->cr, x2, y2);
433 cairo_stroke (pi->cr);
435 cairo_move_to (pi->cr, x1, y3);
436 cairo_line_to (pi->cr, x1, y4);
437 cairo_stroke (pi->cr);
439 cairo_move_to (pi->cr, x2, y3);
440 cairo_line_to (pi->cr, x2, y4);
441 cairo_stroke (pi->cr);
445 for (iy=0; iy < ny; iy++) {
450 x1 = MAX((xmin - TICK_OFFSET), 0.0);
451 x2 = MAX((x1 - TICK_LENGTH), 0.0);
453 x3 = MIN((xmax + TICK_OFFSET), page_w);
454 x4 = MIN((x3 + TICK_LENGTH), page_w);
456 cairo_move_to (pi->cr, x1, y1);
457 cairo_line_to (pi->cr, x2, y1);
458 cairo_stroke (pi->cr);
460 cairo_move_to (pi->cr, x1, y2);
461 cairo_line_to (pi->cr, x2, y2);
462 cairo_stroke (pi->cr);
464 cairo_move_to (pi->cr, x3, y1);
465 cairo_line_to (pi->cr, x4, y1);
466 cairo_stroke (pi->cr);
468 cairo_move_to (pi->cr, x3, y2);
469 cairo_line_to (pi->cr, x4, y2);
470 cairo_stroke (pi->cr);
476 cairo_restore (pi->cr);
478 gl_debug (DEBUG_PRINT, "END");
481 /*---------------------------------------------------------------------------*/
482 /* PRIVATE. Print i'th label. */
483 /*---------------------------------------------------------------------------*/
485 print_label (PrintInfo *pi,
489 glMergeRecord *record,
490 gboolean outline_flag,
491 gboolean reverse_flag)
493 const lglTemplateFrame *frame;
494 gdouble width, height;
496 gl_debug (DEBUG_PRINT, "START");
498 frame = (lglTemplateFrame *)pi->template->frames->data;
500 gl_label_get_size (label, &width, &height);
504 /* Transform coordinate system to be relative to upper corner */
505 /* of the current label */
506 cairo_translate (pi->cr, x, y);
508 clip_to_outline (pi, label);
512 /* Special transformations. */
513 if (label->rotate_flag) {
514 gl_debug (DEBUG_PRINT, "Rotate flag set");
515 cairo_rotate (pi->cr, -M_PI/2.0);
516 cairo_translate (pi->cr, -width, 0.0);
518 if ( reverse_flag ) {
519 cairo_translate (pi->cr, width, 0.0);
520 cairo_scale (pi->cr, -1.0, 1.0);
523 gl_label_draw (label, pi->cr, FALSE, record);
525 cairo_restore (pi->cr); /* From special transformations. */
528 draw_outline (pi, label);
531 cairo_restore (pi->cr); /* From translation. */
533 gl_debug (DEBUG_PRINT, "END");
536 /*---------------------------------------------------------------------------*/
537 /* PRIVATE. Draw outline. */
538 /*---------------------------------------------------------------------------*/
540 draw_outline (PrintInfo *pi,
543 gl_debug (DEBUG_PRINT, "START");
547 cairo_set_source_rgb (pi->cr, OUTLINE_RGB_ARGS);
548 cairo_set_line_width (pi->cr, OUTLINE_WIDTH);
550 gl_cairo_label_path (pi->cr, label->template, FALSE, FALSE);
552 cairo_stroke (pi->cr);
554 cairo_restore (pi->cr);
556 gl_debug (DEBUG_PRINT, "END");
559 /*---------------------------------------------------------------------------*/
560 /* PRIVATE. Clip to outline. */
561 /*---------------------------------------------------------------------------*/
563 clip_to_outline (PrintInfo *pi,
566 gl_debug (DEBUG_PRINT, "START");
568 gl_cairo_label_path (pi->cr, label->template, FALSE, TRUE);
570 cairo_set_fill_rule (pi->cr, CAIRO_FILL_RULE_EVEN_ODD);
573 gl_debug (DEBUG_PRINT, "END");