Reset parser in grace_set_project().
[grace.git] / src / pdfdrv.c
blobaa4512d8353db461af62747419efc9c7aabf6ce9
1 /*
2 * Grace - GRaphing, Advanced Computation and Exploration of data
3 *
4 * Home page: http://plasma-gate.weizmann.ac.il/Grace/
5 *
6 * Copyright (c) 1996-2004 Grace Development Team
7 *
8 * Maintained by Evgeny Stambulchik
9 *
11 * All Rights Reserved
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 * Grace PDF driver
32 #include <config.h>
34 #ifdef HAVE_LIBPDF
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <stdarg.h>
42 #include <pdflib.h>
44 #define CANVAS_BACKEND_API
45 #include "grace/canvas.h"
47 #include "utils.h"
48 #include "devlist.h"
49 #include "pdfdrv.h"
51 #include "protos.h"
53 #ifndef NONE_GUI
54 # include "motifinc.h"
55 #endif
57 typedef struct {
58 PDF *phandle;
60 unsigned long page_scale;
61 float pixel_size;
62 float page_scalef;
64 int *font_ids;
65 int *pattern_ids;
67 int color;
68 int pattern;
69 double linew;
70 int lines;
71 int linecap;
72 int linejoin;
74 PDFCompatibility compat;
75 PDFColorSpace colorspace;
76 int compression;
77 int fpprec;
79 int kerning_supported;
81 #ifndef NONE_GUI
82 Widget frame;
83 OptionStructure *compat_item;
84 SpinStructure *compression_item;
85 SpinStructure *fpprec_item;
86 OptionStructure *colorspace_item;
87 #endif
88 } PDF_data;
90 static void pdf_error_handler(PDF *p, int type, const char* msg);
92 static PDF_data *init_pdf_data(void)
94 PDF_data *data;
96 /* we need to perform the allocations */
97 data = xmalloc(sizeof(PDF_data));
98 if (data == NULL) {
99 return NULL;
102 memset(data, 0, sizeof(PDF_data));
104 data->compat = PDF_1_4;
105 data->colorspace = DEFAULT_COLORSPACE;
106 data->compression = 4;
107 data->fpprec = 4;
109 return data;
112 static void pdf_data_free(void *data)
114 PDF_data *pdfdata = (PDF_data *) data;
116 if (pdfdata) {
117 xfree(pdfdata->font_ids);
118 xfree(pdfdata->pattern_ids);
119 xfree(pdfdata);
123 int register_pdf_drv(Canvas *canvas)
125 Device_entry *d;
126 PDF_data *data;
128 PDF_boot();
130 data = init_pdf_data();
131 if (!data) {
132 return -1;
135 d = device_new("PDF", DEVICE_FILE, TRUE, data, pdf_data_free);
136 if (!d) {
137 xfree(data);
138 return -1;
141 device_set_fext(d, "pdf");
143 device_set_dpi(d, 300.0);
145 device_set_procs(d,
146 pdf_initgraphics,
147 pdf_leavegraphics,
148 pdf_op_parser,
149 pdf_gui_setup,
150 NULL,
151 pdf_drawpixel,
152 pdf_drawpolyline,
153 pdf_fillpolygon,
154 pdf_drawarc,
155 pdf_fillarc,
156 pdf_putpixmap,
157 pdf_puttext);
159 return register_device(canvas, d);
162 static char *pdf_builtin_fonts[] =
164 "Times-Roman",
165 "Times-Italic",
166 "Times-Bold",
167 "Times-BoldItalic",
168 "Helvetica",
169 "Helvetica-Oblique",
170 "Helvetica-Bold",
171 "Helvetica-BoldOblique",
172 "Courier",
173 "Courier-Oblique",
174 "Courier-Bold",
175 "Courier-BoldOblique",
176 "Symbol",
177 "ZapfDingbats"
180 static int number_of_pdf_builtin_fonts = sizeof(pdf_builtin_fonts)/sizeof(char *);
182 static int pdf_builtin_font(const char *fname)
184 int i;
185 for (i = 0; i < number_of_pdf_builtin_fonts; i++) {
186 if (strcmp(pdf_builtin_fonts[i], fname) == 0) {
187 return TRUE;
190 return FALSE;
193 static size_t pdf_writeproc(PDF *p, void *data, size_t size)
195 FILE *fp = PDF_get_opaque(p);
196 return fwrite(data, 1, size, fp);
199 int pdf_initgraphics(const Canvas *canvas, void *data, const CanvasStats *cstats)
201 PDF_data *pdfdata = (PDF_data *) data;
202 unsigned int i;
203 Page_geometry *pg;
204 char *s;
206 pg = get_page_geometry(canvas);
208 pdfdata->page_scale = MIN2(pg->height, pg->width);
209 pdfdata->pixel_size = 1.0/pdfdata->page_scale;
210 pdfdata->page_scalef = (float) pdfdata->page_scale*72.0/pg->dpi;
212 /* undefine all graphics state parameters */
213 pdfdata->color = -1;
214 pdfdata->pattern = -1;
215 pdfdata->linew = -1.0;
216 pdfdata->lines = -1;
217 pdfdata->linecap = -1;
218 pdfdata->linejoin = -1;
220 pdfdata->phandle = PDF_new2(pdf_error_handler,
221 NULL, NULL, NULL, canvas_get_prstream(canvas));
222 if (pdfdata->phandle == NULL) {
223 return RETURN_FAILURE;
226 PDF_set_parameter(pdfdata->phandle, "fontwarning", "false");
228 /* check PDFlib capabilities */
229 if (!strcmp(PDF_get_parameter(pdfdata->phandle, "pdi", 0), "true")) {
230 pdfdata->kerning_supported = TRUE;
231 } else {
232 pdfdata->kerning_supported = FALSE;
235 switch (pdfdata->compat) {
236 case PDF_1_3:
237 s = "1.3";
238 break;
239 case PDF_1_4:
240 s = "1.4";
241 break;
242 case PDF_1_5:
243 s = "1.5";
244 break;
245 default:
246 s = "1.3";
247 break;
249 PDF_set_parameter(pdfdata->phandle, "compatibility", s);
251 PDF_begin_document_callback(pdfdata->phandle, pdf_writeproc, "");
253 PDF_set_value(pdfdata->phandle, "compress", (float) pdfdata->compression);
254 PDF_set_value(pdfdata->phandle, "floatdigits", (float) pdfdata->fpprec);
256 PDF_set_info(pdfdata->phandle, "Creator", bi_version_string());
257 PDF_set_info(pdfdata->phandle, "Author", canvas_get_username(canvas));
258 PDF_set_info(pdfdata->phandle, "Title", canvas_get_docname(canvas));
260 pdfdata->font_ids = xmalloc(number_of_fonts(canvas)*SIZEOF_INT);
261 for (i = 0; i < number_of_fonts(canvas); i++) {
262 pdfdata->font_ids[i] = -1;
264 for (i = 0; i < cstats->nfonts; i++) {
265 int font;
266 char buf[GR_MAXPATHLEN];
267 char *fontname, *encscheme;
268 char *pdflibenc;
269 char *embedstr;
271 font = cstats->fonts[i].font;
273 fontname = get_fontalias(canvas, font);
275 if (pdf_builtin_font(fontname)) {
276 embedstr = "embedding=false";
277 } else {
278 sprintf(buf, "%s==%s",
279 fontname, get_afmfilename(canvas, font, TRUE));
280 PDF_set_parameter(pdfdata->phandle, "FontAFM", buf);
281 sprintf(buf, "%s==%s",
282 fontname, get_fontfilename(canvas, font, TRUE));
283 PDF_set_parameter(pdfdata->phandle, "FontOutline", buf);
285 embedstr = "embedding=false";
288 encscheme = get_encodingscheme(canvas, font);
289 if (strcmp(encscheme, "FontSpecific") == 0) {
290 pdflibenc = "builtin";
291 } else {
292 pdflibenc = "winansi";
295 pdfdata->font_ids[font] =
296 PDF_load_font(pdfdata->phandle, fontname, 0,
297 pdflibenc, embedstr);
299 if (pdfdata->font_ids[font] < 0) {
300 errmsg(PDF_get_errmsg(pdfdata->phandle));
304 pdfdata->pattern_ids = xmalloc(number_of_patterns(canvas)*SIZEOF_INT);
305 for (i = 0; i < cstats->npatterns; i++) {
306 int patno = cstats->patterns[i];
307 Pattern *pat = canvas_get_pattern(canvas, patno);
308 /* Unfortunately, there is no way to open a _masked_ image from memory */
309 #if 0
310 int im;
311 pdfdata->pattern_ids[i] = PDF_begin_pattern(pdfdata->phandle,
312 pat->width, pat->height, pat->width, pat->height, 2);
313 im = PDF_open_image(pdfdata->phandle, "raw", "memory",
314 (const char *) pat_bits[i], pat->width*pat->height/8,
315 pat->width, pat->height, 1, 1, "");
316 PDF_place_image(pdfdata->phandle, im, 0.0, 0.0, 1.0);
317 PDF_close_image(pdfdata->phandle, im);
318 PDF_end_pattern(pdfdata->phandle);
319 #else
320 int j, k, l;
321 pdfdata->pattern_ids[patno] = PDF_begin_pattern(pdfdata->phandle,
322 pat->width, pat->height, pat->width, pat->height, 2);
323 for (j = 0; j < 256; j++) {
324 k = j%16;
325 l = 15 - j/16;
326 if ((pat->bits[j/8] >> (j%8)) & 0x01) {
327 /* the bit is set */
328 PDF_rect(pdfdata->phandle, (float) k, (float) l, 1.0, 1.0);
329 PDF_fill(pdfdata->phandle);
332 PDF_end_pattern(pdfdata->phandle);
333 #endif
336 PDF_begin_page_ext(pdfdata->phandle,
337 pg->width*72.0/pg->dpi, pg->height*72.0/pg->dpi, "");
339 s = canvas_get_description(canvas);
341 if (!is_empty_string(s)) {
342 PDF_set_border_style(pdfdata->phandle, "dashed", 3.0);
343 PDF_set_border_dash(pdfdata->phandle, 5.0, 1.0);
344 PDF_set_border_color(pdfdata->phandle, 1.0, 0.0, 0.0);
346 PDF_add_note(pdfdata->phandle,
347 20.0, 50.0, 320.0, 100.0, s, "Project description", "note", 0);
350 PDF_scale(pdfdata->phandle, pdfdata->page_scalef, pdfdata->page_scalef);
352 return RETURN_SUCCESS;
355 void pdf_setpen(const Canvas *canvas, const Pen *pen, PDF_data *pdfdata)
357 if (pen->color != pdfdata->color || pen->pattern != pdfdata->pattern) {
358 float c1, c2, c3, c4;
359 char *cstype;
360 switch (pdfdata->colorspace) {
361 case COLORSPACE_GRAYSCALE:
363 cstype = "gray";
365 c1 = (float) get_colorintensity(canvas, pen->color);
366 c2 = c3 = c4 = 0.0;
368 break;
369 case COLORSPACE_CMYK:
371 fCMYK fcmyk;
373 cstype = "cmyk";
375 get_fcmyk(canvas, pen->color, &fcmyk);
376 c1 = (float) fcmyk.cyan;
377 c2 = (float) fcmyk.magenta;
378 c3 = (float) fcmyk.yellow;
379 c4 = (float) fcmyk.black;
381 break;
382 case COLORSPACE_RGB:
383 default:
385 fRGB frgb;
387 cstype = "rgb";
389 get_frgb(canvas, pen->color, &frgb);
390 c1 = (float) frgb.red;
391 c2 = (float) frgb.green;
392 c3 = (float) frgb.blue;
393 c4 = 0.0;
395 break;
398 PDF_setcolor(pdfdata->phandle, "both", cstype, c1, c2, c3, c4);
399 if (pen->pattern > 1 && pdfdata->pattern_ids[pen->pattern] >= 0) {
400 PDF_setcolor(pdfdata->phandle, "both", "pattern",
401 (float) pdfdata->pattern_ids[pen->pattern], 0.0, 0.0, 0.0);
403 pdfdata->color = pen->color;
404 pdfdata->pattern = pen->pattern;
408 void pdf_setdrawbrush(const Canvas *canvas, PDF_data *pdfdata)
410 unsigned int i;
411 float lw;
412 int ls;
413 float *darray;
414 Pen pen;
416 getpen(canvas, &pen);
417 pdf_setpen(canvas, &pen, pdfdata);
419 ls = getlinestyle(canvas);
420 lw = MAX2(getlinewidth(canvas), pdfdata->pixel_size);
422 if (ls != pdfdata->lines || lw != pdfdata->linew) {
423 PDF_setlinewidth(pdfdata->phandle, lw);
425 if (ls == 0 || ls == 1) {
426 PDF_setdash(pdfdata->phandle, 0, 0);
427 } else {
428 LineStyle *linestyle = canvas_get_linestyle(canvas, ls);
429 darray = xmalloc(linestyle->length*SIZEOF_FLOAT);
430 for (i = 0; i < linestyle->length; i++) {
431 darray[i] = lw*linestyle->array[i];
433 PDF_setpolydash(pdfdata->phandle, darray, linestyle->length);
434 xfree(darray);
436 pdfdata->linew = lw;
437 pdfdata->lines = ls;
441 void pdf_setlineprops(const Canvas *canvas, PDF_data *pdfdata)
443 int lc, lj;
445 lc = getlinecap(canvas);
446 lj = getlinejoin(canvas);
448 if (lc != pdfdata->linecap) {
449 switch (lc) {
450 case LINECAP_BUTT:
451 PDF_setlinecap(pdfdata->phandle, 0);
452 break;
453 case LINECAP_ROUND:
454 PDF_setlinecap(pdfdata->phandle, 1);
455 break;
456 case LINECAP_PROJ:
457 PDF_setlinecap(pdfdata->phandle, 2);
458 break;
460 pdfdata->linecap = lc;
463 if (lj != pdfdata->linejoin) {
464 switch (lj) {
465 case LINEJOIN_MITER:
466 PDF_setlinejoin(pdfdata->phandle, 0);
467 break;
468 case LINEJOIN_ROUND:
469 PDF_setlinejoin(pdfdata->phandle, 1);
470 break;
471 case LINEJOIN_BEVEL:
472 PDF_setlinejoin(pdfdata->phandle, 2);
473 break;
475 pdfdata->linejoin = lj;
479 void pdf_drawpixel(const Canvas *canvas, void *data, const VPoint *vp)
481 PDF_data *pdfdata = (PDF_data *) data;
482 Pen pen;
484 getpen(canvas, &pen);
485 pdf_setpen(canvas, &pen, pdfdata);
487 if (pdfdata->linew != pdfdata->pixel_size) {
488 PDF_setlinewidth(pdfdata->phandle, pdfdata->pixel_size);
489 pdfdata->linew = pdfdata->pixel_size;
491 if (pdfdata->linecap != LINECAP_ROUND) {
492 PDF_setlinecap(pdfdata->phandle, 1);
493 pdfdata->linecap = LINECAP_ROUND;
495 if (pdfdata->lines != 1) {
496 PDF_setdash(pdfdata->phandle, 0, 0);
497 pdfdata->lines = 1;
500 PDF_moveto(pdfdata->phandle, (float) vp->x, (float) vp->y);
501 PDF_lineto(pdfdata->phandle, (float) vp->x, (float) vp->y);
502 PDF_stroke(pdfdata->phandle);
505 void pdf_poly_path(const VPoint *vps, int n, PDF_data *pdfdata)
507 int i;
509 PDF_moveto(pdfdata->phandle, (float) vps[0].x, (float) vps[0].y);
510 for (i = 1; i < n; i++) {
511 PDF_lineto(pdfdata->phandle, (float) vps[i].x, (float) vps[i].y);
515 void pdf_drawpolyline(const Canvas *canvas, void *data,
516 const VPoint *vps, int n, int mode)
518 PDF_data *pdfdata = (PDF_data *) data;
519 if (getlinestyle(canvas) == 0) {
520 return;
523 pdf_setdrawbrush(canvas, pdfdata);
524 pdf_setlineprops(canvas, pdfdata);
526 pdf_poly_path(vps, n, pdfdata);
528 if (mode == POLYLINE_CLOSED) {
529 PDF_closepath_stroke(pdfdata->phandle);
530 } else {
531 PDF_stroke(pdfdata->phandle);
535 void pdf_fillpolygon(const Canvas *canvas, void *data,
536 const VPoint *vps, int nc)
538 PDF_data *pdfdata = (PDF_data *) data;
539 Pen pen;
541 getpen(canvas, &pen);
543 if (pen.pattern == 0) {
544 return;
547 if (getfillrule(canvas) == FILLRULE_WINDING) {
548 PDF_set_parameter(pdfdata->phandle, "fillrule", "winding");
549 } else {
550 PDF_set_parameter(pdfdata->phandle, "fillrule", "evenodd");
553 if (pen.pattern > 1) {
554 Pen solid_pen;
555 solid_pen.color = getbgcolor(canvas);
556 solid_pen.pattern = 1;
558 pdf_setpen(canvas, &solid_pen, pdfdata);
559 pdf_poly_path(vps, nc, pdfdata);
560 PDF_fill(pdfdata->phandle);
563 getpen(canvas, &pen);
564 pdf_setpen(canvas, &pen, pdfdata);
565 pdf_poly_path(vps, nc, pdfdata);
566 PDF_fill(pdfdata->phandle);
569 void pdf_arc_path(const VPoint *vp1, const VPoint *vp2,
570 double a1, double a2, int mode, PDF_data *pdfdata)
572 VPoint vpc;
573 double rx, ry;
575 vpc.x = (vp1->x + vp2->x)/2;
576 vpc.y = (vp1->y + vp2->y)/2;
577 rx = fabs(vp2->x - vp1->x)/2;
578 ry = fabs(vp2->y - vp1->y)/2;
580 if (rx == 0.0 || ry == 0.0) {
581 return;
584 PDF_scale(pdfdata->phandle, 1.0, ry/rx);
585 PDF_moveto(pdfdata->phandle, (float) vpc.x + rx*cos(a1*M_PI/180.0),
586 (float) rx/ry*vpc.y + rx*sin(a1*M_PI/180.0));
587 if (a2 < 0) {
588 PDF_arcn(pdfdata->phandle, (float) vpc.x, (float) rx/ry*vpc.y, rx,
589 (float) a1, (float) (a1 + a2));
590 } else {
591 PDF_arc(pdfdata->phandle, (float) vpc.x, (float) rx/ry*vpc.y, rx,
592 (float) a1, (float) (a1 + a2));
595 if (mode == ARCFILL_PIESLICE) {
596 PDF_lineto(pdfdata->phandle, (float) vpc.x, (float) rx/ry*vpc.y);
600 void pdf_drawarc(const Canvas *canvas, void *data,
601 const VPoint *vp1, const VPoint *vp2, double a1, double a2)
603 PDF_data *pdfdata = (PDF_data *) data;
605 if (getlinestyle(canvas) == 0) {
606 return;
609 pdf_setdrawbrush(canvas, pdfdata);
610 PDF_save(pdfdata->phandle);
611 pdf_arc_path(vp1, vp2, a1, a2, ARCFILL_CHORD, pdfdata);
612 PDF_stroke(pdfdata->phandle);
613 PDF_restore(pdfdata->phandle);
616 void pdf_fillarc(const Canvas *canvas, void *data,
617 const VPoint *vp1, const VPoint *vp2, double a1, double a2, int mode)
619 PDF_data *pdfdata = (PDF_data *) data;
620 Pen pen;
622 getpen(canvas, &pen);
624 if (pen.pattern == 0) {
625 return;
628 if (pen.pattern > 1) {
629 Pen solid_pen;
630 solid_pen.color = getbgcolor(canvas);
631 solid_pen.pattern = 1;
633 pdf_setpen(canvas, &solid_pen, pdfdata);
634 PDF_save(pdfdata->phandle);
635 pdf_arc_path(vp1, vp2, a1, a2, mode, pdfdata);
636 PDF_fill(pdfdata->phandle);
637 PDF_restore(pdfdata->phandle);
640 pdf_setpen(canvas, &pen, pdfdata);
641 PDF_save(pdfdata->phandle);
642 pdf_arc_path(vp1, vp2, a1, a2, mode, pdfdata);
643 PDF_fill(pdfdata->phandle);
644 PDF_restore(pdfdata->phandle);
647 /* TODO: transparent pixmaps */
648 void pdf_putpixmap(const Canvas *canvas, void *data,
649 const VPoint *vp, const CPixmap *pm)
651 PDF_data *pdfdata = (PDF_data *) data;
652 char *buf, *bp;
653 int image;
654 int cindex;
655 RGB fg, bg;
656 int i, k, j;
657 long paddedW;
659 int components = 3;
661 buf = xmalloc(pm->width*pm->height*components);
662 if (buf == NULL) {
663 errmsg("xmalloc failed in pdf_putpixmap()");
664 return;
667 bp = buf;
668 if (pm->bpp == 1) {
669 paddedW = PADBITS(pm->width, pm->pad);
670 get_rgb(canvas, getcolor(canvas), &fg);
671 get_rgb(canvas, getbgcolor(canvas), &bg);
672 for (k = 0; k < pm->height; k++) {
673 for (j = 0; j < paddedW/pm->pad; j++) {
674 for (i = 0; i < pm->pad && j*pm->pad + i < pm->width; i++) {
675 if (bin_dump(&(pm->bits)[k*paddedW/pm->pad + j], i, pm->pad)) {
676 *bp++ = (char) fg.red;
677 *bp++ = (char) fg.green;
678 *bp++ = (char) fg.blue;
679 } else {
680 *bp++ = (char) bg.red;
681 *bp++ = (char) bg.green;
682 *bp++ = (char) bg.blue;
687 } else {
688 for (k = 0; k < pm->height; k++) {
689 for (j = 0; j < pm->width; j++) {
690 cindex = (pm->bits)[k*pm->width + j];
691 get_rgb(canvas, cindex, &fg);
692 *bp++ = (char) fg.red;
693 *bp++ = (char) fg.green;
694 *bp++ = (char) fg.blue;
699 image = PDF_open_image(pdfdata->phandle, "raw", "memory",
700 buf, pm->width*pm->height*components,
701 pm->width, pm->height, components, GRACE_BPP, "");
702 if (image == -1) {
703 errmsg("Not enough memory for image!");
704 xfree(buf);
705 return;
708 PDF_place_image(pdfdata->phandle,
709 image, vp->x, vp->y - pm->height*pdfdata->pixel_size, pdfdata->pixel_size);
710 PDF_close_image(pdfdata->phandle, image);
712 xfree(buf);
715 void pdf_puttext(const Canvas *canvas, void *data,
716 const VPoint *vp, const char *s, int len, int font, const TextMatrix *tm,
717 int underline, int overline, int kerning)
719 PDF_data *pdfdata = (PDF_data *) data;
720 Pen pen;
722 if (pdfdata->font_ids[font] < 0) {
723 return;
726 getpen(canvas, &pen);
727 pdf_setpen(canvas, &pen, pdfdata);
729 PDF_save(pdfdata->phandle);
731 PDF_setfont(pdfdata->phandle, pdfdata->font_ids[font], 1.0);
733 PDF_set_parameter(pdfdata->phandle, "underline", true_or_false(underline));
734 PDF_set_parameter(pdfdata->phandle, "overline", true_or_false(overline));
735 if (pdfdata->kerning_supported) {
736 PDF_set_parameter(pdfdata->phandle,
737 "kerning", kerning ? "true":"false");
739 PDF_concat(pdfdata->phandle, (float) tm->cxx, (float) tm->cyx,
740 (float) tm->cxy, (float) tm->cyy,
741 vp->x, vp->y);
743 PDF_show2(pdfdata->phandle, s, len);
745 PDF_restore(pdfdata->phandle);
748 void pdf_leavegraphics(const Canvas *canvas, void *data,
749 const CanvasStats *cstats)
751 PDF_data *pdfdata = (PDF_data *) data;
752 view v;
753 v = cstats->bbox;
755 PDF_set_value(pdfdata->phandle, "CropBox/llx", pdfdata->page_scalef*v.xv1);
756 PDF_set_value(pdfdata->phandle, "CropBox/lly", pdfdata->page_scalef*v.yv1);
757 PDF_set_value(pdfdata->phandle, "CropBox/urx", pdfdata->page_scalef*v.xv2);
758 PDF_set_value(pdfdata->phandle, "CropBox/ury", pdfdata->page_scalef*v.yv2);
760 PDF_end_page_ext(pdfdata->phandle, "");
761 PDF_end_document(pdfdata->phandle, "");
762 PDF_delete(pdfdata->phandle);
763 xfree(pdfdata->font_ids);
764 XCFREE(pdfdata->pattern_ids);
767 static void pdf_error_handler(PDF *p, int type, const char *msg)
769 char *buf, *s;
771 switch (type) {
772 case PDF_NonfatalError:
773 /* continue on a non-fatal error */
774 s = "PDFlib warning: ";
775 break;
776 default:
777 s = "PDFlib error: ";
778 /* give up in all other cases */
779 break;
781 buf = xmalloc(strlen(msg) + strlen(s) + 1);
782 if (buf) {
783 sprintf(buf, "%s%s", s, msg);
784 errmsg(buf);
785 xfree(buf);
789 int pdf_op_parser(const Canvas *canvas, void *data, const char *opstring)
791 PDF_data *pdfdata = (PDF_data *) data;
793 if (!strcmp(opstring, "compatibility:PDF-1.3")) {
794 pdfdata->compat = PDF_1_3;
795 return RETURN_SUCCESS;
796 } else
797 if (!strcmp(opstring, "compatibility:PDF-1.4")) {
798 pdfdata->compat = PDF_1_4;
799 return RETURN_SUCCESS;
800 } else
801 if (!strcmp(opstring, "compatibility:PDF-1.5")) {
802 pdfdata->compat = PDF_1_5;
803 return RETURN_SUCCESS;
804 } else
805 if (!strncmp(opstring, "compression:", 12)) {
806 char *bufp;
807 bufp = strchr(opstring, ':');
808 bufp++;
809 if (!is_empty_string(bufp)) {
810 pdfdata->compression = atoi(bufp);
811 return RETURN_SUCCESS;
812 } else {
813 return RETURN_FAILURE;
815 } else
816 if (!strncmp(opstring, "fpprecision:", 12)) {
817 char *bufp;
818 bufp = strchr(opstring, ':');
819 bufp++;
820 if (!is_empty_string(bufp)) {
821 pdfdata->fpprec = atoi(bufp);
822 return RETURN_SUCCESS;
823 } else {
824 return RETURN_FAILURE;
826 } else
827 if (!strcmp(opstring, "colorspace:grayscale")) {
828 pdfdata->colorspace = COLORSPACE_GRAYSCALE;
829 return RETURN_SUCCESS;
830 } else
831 if (!strcmp(opstring, "colorspace:rgb")) {
832 pdfdata->colorspace = COLORSPACE_RGB;
833 return RETURN_SUCCESS;
834 } else
835 if (!strcmp(opstring, "colorspace:cmyk")) {
836 pdfdata->colorspace = COLORSPACE_CMYK;
837 return RETURN_SUCCESS;
838 } else {
839 return RETURN_FAILURE;
843 #ifndef NONE_GUI
845 static void update_pdf_setup_frame(PDF_data *pdfdata);
846 static int set_pdf_setup_proc(void *data);
848 void pdf_gui_setup(const Canvas *canvas, void *data)
850 PDF_data *pdfdata = (PDF_data *) data;
852 set_wait_cursor();
854 if (pdfdata->frame == NULL) {
855 Widget fr, rc;
856 OptionItem compat_op_items[3] = {
857 {PDF_1_3, "PDF-1.3"},
858 {PDF_1_4, "PDF-1.4"},
859 {PDF_1_5, "PDF-1.5"}
861 OptionItem colorspace_op_items[3] = {
862 {COLORSPACE_GRAYSCALE, "Grayscale"},
863 {COLORSPACE_RGB, "RGB" },
864 {COLORSPACE_CMYK, "CMYK" }
867 pdfdata->frame = CreateDialogForm(app_shell, "PDF options");
869 fr = CreateFrame(pdfdata->frame, "PDF options");
870 rc = CreateVContainer(fr);
871 pdfdata->compat_item =
872 CreateOptionChoice(rc, "Compatibility:", 1, 3, compat_op_items);
873 pdfdata->colorspace_item =
874 CreateOptionChoice(rc, "Colorspace:", 1, 3, colorspace_op_items);
875 pdfdata->compression_item = CreateSpinChoice(rc,
876 "Compression:", 1, SPIN_TYPE_INT, 0.0, 9.0, 1.0);
877 pdfdata->fpprec_item = CreateSpinChoice(rc,
878 "FP precision:", 1, SPIN_TYPE_INT, 4.0, 6.0, 1.0);
880 CreateAACDialog(pdfdata->frame, fr, set_pdf_setup_proc, pdfdata);
882 update_pdf_setup_frame(pdfdata);
883 RaiseWindow(GetParent(pdfdata->frame));
884 unset_wait_cursor();
887 static void update_pdf_setup_frame(PDF_data *pdfdata)
889 if (pdfdata->frame) {
890 SetOptionChoice(pdfdata->compat_item, pdfdata->compat);
891 SetOptionChoice(pdfdata->colorspace_item, pdfdata->colorspace);
892 SetSpinChoice(pdfdata->compression_item, (double) pdfdata->compression);
893 SetSpinChoice(pdfdata->fpprec_item, (double) pdfdata->fpprec);
897 static int set_pdf_setup_proc(void *data)
899 PDF_data *pdfdata = (PDF_data *) data;
901 pdfdata->compat = GetOptionChoice(pdfdata->compat_item);
902 pdfdata->colorspace = GetOptionChoice(pdfdata->colorspace_item);
903 pdfdata->compression = (int) GetSpinChoice(pdfdata->compression_item);
904 pdfdata->fpprec = (int) GetSpinChoice(pdfdata->fpprec_item);
906 return RETURN_SUCCESS;
909 #endif
911 #else /* No PDFlib */
912 void _pdfdrv_c_dummy_func(void) {}
913 #endif