1 /*---------------------------------------------------------------------------*
2 | PDFlib - A library for generating PDF on the fly |
3 +---------------------------------------------------------------------------+
4 | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
5 +---------------------------------------------------------------------------+
6 | |
7 | This software is subject to the PDFlib license. It is NOT in the |
8 | public domain. Extended versions and commercial licenses are |
9 | available, please check http://www.pdflib.com. |
10 | |
11 *---------------------------------------------------------------------------*/
12
13 /* $Id: p_annots.c,v 1.198.2.30 2010/04/16 12:32:27 kurt Exp $
14 *
15 * PDFlib routines for annnotations
16 *
17 */
18
19 #define P_ANNOTS_C
20
21 #include "p_intern.h"
22 #include "p_color.h"
23 #include "p_font.h"
24 #include "p_image.h"
25
26
27
28
29 /* annotation types */
30 typedef enum
31 {
32 ann_text = (1<<0),
33 ann_link = (1<<1),
34 ann_freetext = (1<<2),
35 ann_line = (1<<3),
36 ann_square = (1<<4),
37 ann_circle = (1<<5),
38 ann_highlight = (1<<6),
39 ann_underline = (1<<7),
40 ann_squiggly = (1<<8),
41 ann_strikeout = (1<<9),
42 ann_stamp = (1<<10),
43 ann_ink = (1<<11),
44 ann_polygon = (1<<12),
45 ann_polyline = (1<<13),
46 ann_popup = (1<<14),
47 ann_fileattachment = (1<<15),
48 ann_3d = (1<<16),
49 ann_movie = (1<<17)
50 }
51 pdf_annottype;
52
53 static const pdc_keyconn pdf_annottype_pdfkeylist[] =
54 {
55 {"Text", ann_text},
56 {"Link", ann_link},
57 {"FreeText", ann_freetext},
58 {"Line", ann_line},
59 {"Square", ann_square},
60 {"Circle", ann_circle},
61 {"Highlight", ann_highlight},
62 {"Underline", ann_underline},
63 {"Squiggly", ann_squiggly},
64 {"StrikeOut", ann_strikeout},
65 {"Stamp", ann_stamp},
66 {"Polygon", ann_polygon},
67 {"PolyLine", ann_polyline},
68 {"Ink", ann_ink},
69 {"Popup", ann_popup},
70 {"FileAttachment", ann_fileattachment},
71 {"3D", ann_3d},
72 {"Movie", ann_movie},
73 {NULL, 0}
74 };
75
76 static const pdc_keyconn pdf_polyline_pdfkeylist[] =
77 {
78 {"QuadPoints", ann_link},
79 {"QuadPoints", ann_highlight},
80 {"QuadPoints", ann_underline},
81 {"QuadPoints", ann_squiggly},
82 {"QuadPoints", ann_strikeout},
83 {"InkList", ann_ink},
84 {"Vertices", ann_polygon},
85 {"Vertices", ann_polyline},
86 {NULL, 0}
87 };
88
89 /* flags for annotation dictionary entries */
90 typedef enum
91 {
92 anndict_a = (1<<0),
93 anndict_bs = (1<<1),
94 anndict_c = (1<<2),
95 anndict_contents = (1<<3),
96 anndict_f = (1<<4),
97 anndict_fs = (1<<5),
98 anndict_h = (1<<6),
99 anndict_ic = (1<<7),
100 anndict_inklist = (1<<8),
101 anndict_l = (1<<9),
102 anndict_le = (1<<10),
103 anndict_movie = (1<<11),
104 anndict_name = (1<<12),
105 anndict_nm = (1<<13),
106 anndict_open = (1<<14),
107 anndict_parent = (1<<15),
108 anndict_popup = (1<<16),
109 anndict_q = (1<<17),
110 anndict_quadpoints = (1<<18),
111 anndict_rect = (1<<19),
112 anndict_subtype = (1<<20),
113 anndict_t = (1<<21),
114 anndict_vertices = (1<<22),
115 anndict_3dd = (1<<23),
116 anndict_3da = (1<<24),
117 anndict_3dv = (1<<25)
118 }
119 pdf_anndictentries;
120
121 static const pdc_keyconn pdf_perm_entries_pdfkeylist[] =
122 {
123 {"Contents", anndict_contents},
124 {"Name", anndict_name},
125 {"NM", anndict_nm},
126 {"Open", anndict_open},
127 {NULL, 0}
128 };
129
130 static const pdc_keyconn pdf_forb_entries_pdfkeylist[] =
131 {
132 {"A", anndict_a},
133 {"BS", anndict_bs},
134 {"C", anndict_c},
135 {"F", anndict_f},
136 {"FS", anndict_fs},
137 {"H", anndict_h},
138 {"IC", anndict_ic},
139 {"InkList", anndict_inklist},
140 {"L", anndict_l},
141 {"LE", anndict_le},
142 {"Movie", anndict_movie},
143 {"Parent", anndict_parent},
144 {"Popup", anndict_popup},
145 {"Q", anndict_q},
146 {"QuadPoints", anndict_quadpoints},
147 {"Rect", anndict_rect},
148 {"Subtype", anndict_subtype},
149 {"T", anndict_t},
150 {"Vertices", anndict_vertices},
151 {"3DD", anndict_3dd},
152 {"3DV", anndict_3dv},
153 {"3DA", anndict_3da},
154 {NULL, 0}
155 };
156
157 /* line ending styles */
158 typedef enum
159 {
160 line_none,
161 line_square,
162 line_circle,
163 line_diamond,
164 line_openarrow,
165 line_closedarrow
166 }
167 pdf_endingstyles;
168
169 static const pdc_keyconn pdf_endingstyles_pdfkeylist[] =
170 {
171 {"None", line_none},
172 {"Square", line_square},
173 {"Circle", line_circle},
174 {"Diamond", line_diamond},
175 {"OpenArrow", line_openarrow},
176 {"ClosedArrow", line_closedarrow},
177 {NULL, 0}
178 };
179
180 /* text icon names */
181 typedef enum
182 {
183 icon_text_comment,
184 icon_text_help,
185 icon_text_key,
186 icon_text_insert,
187 icon_text_newparagraph,
188 icon_text_note,
189 icon_text_paragraph
190 }
191 pdf_text_iconnames;
192
193 static const pdc_keyconn pdf_text_iconnames_pdfkeylist[] =
194 {
195 {"Comment", icon_text_comment},
196 {"Help", icon_text_help},
197 {"Key", icon_text_key},
198 {"Insert", icon_text_insert},
199 {"NewParagraph", icon_text_newparagraph},
200 {"Note", icon_text_note},
201 {"Paragraph", icon_text_paragraph},
202 {NULL, 0}
203 };
204
205 /* stamp icon names */
206 typedef enum
207 {
208 icon_stamp_approved,
209 icon_stamp_asls,
210 icon_stamp_confidential,
211 icon_stamp_departmental,
212 icon_stamp_draft,
213 icon_stamp_experimental,
214 icon_stamp_expired,
215 icon_stamp_final,
216 icon_stamp_forcomment,
217 icon_stamp_forpublicrelease,
218 icon_stamp_notapproved,
219 icon_stamp_notforpublicrelease,
220 icon_stamp_sold,
221 icon_stamp_topsecret
222 }
223 pdf_stamp_iconnames;
224
225 static const pdc_keyconn pdf_stamp_iconnames_pdfkeylist[] =
226 {
227 {"Approved", icon_stamp_approved},
228 {"AsIs", icon_stamp_asls},
229 {"Confidential", icon_stamp_confidential},
230 {"Departmental", icon_stamp_departmental},
231 {"Draft", icon_stamp_draft},
232 {"Experimental", icon_stamp_experimental},
233 {"Expired", icon_stamp_expired},
234 {"Final", icon_stamp_final},
235 {"ForComment", icon_stamp_forcomment},
236 {"ForPublicRelease", icon_stamp_forpublicrelease},
237 {"NotApproved", icon_stamp_notapproved},
238 {"NotForPublicRelease", icon_stamp_notforpublicrelease},
239 {"Sold", icon_stamp_sold},
240 {"TopSecret", icon_stamp_topsecret},
241 {NULL, 0}
242 };
243
244 /* file attachment icon names */
245 typedef enum
246 {
247 icon_attach_graph,
248 icon_attach_paperclip,
249 icon_attach_pushpin,
250 icon_attach_tag
251 }
252 pdf_attach_iconnames;
253
254 static const pdc_keyconn pdf_attach_iconnames_pdfkeylist[] =
255 {
256 {"Graph", icon_attach_graph},
257 {"Paperclip", icon_attach_paperclip},
258 {"PushPin", icon_attach_pushpin},
259 {"Tag", icon_attach_tag},
260 {NULL, 0}
261 };
262
263
264 static const pdc_keyconn pdf_3dview_keylist[] =
265 {
266 {NULL, 0}
267 };
268
269
270 typedef enum
271 {
272 movieposter_none = -1,
273 movieposter_auto = -2
274 }
275 pdf_movieposter_states;
276
277 static const pdc_keyconn pdf_movieposter_keylist[] =
278 {
279 {"none", movieposter_none},
280 {"auto", movieposter_auto},
281 {NULL, 0}
282 };
283
284 typedef enum
285 {
286 playmode_once,
287 playmode_open,
288 playmode_repeat,
289 playmode_palindrome
290 }
291 pdf_playmode_states;
292
293 static const pdc_keyconn pdf_playmode_pdfkeylist[] =
294 {
295 {"Once", playmode_once},
296 {"Open", playmode_open},
297 {"Repeat", playmode_repeat},
298 {"Palindrome", playmode_palindrome},
299 {NULL, 0}
300 };
301
302 #define PDF_ANN_FULLSCREEN -9999
303
304 static const pdc_keyconn pdf_windowscale_keylist[] =
305 {
306 {"fullscreen", PDF_ANN_FULLSCREEN},
307 {NULL, 0}
308 };
309
310
311 #define PDF_LAYER_FLAG PDC_OPT_UNSUPP
312
313 #define PDF_3DANNOT_FLAG PDC_OPT_UNSUPP
314 static const pdc_defopt pdf_create_annot_options[] =
315 {
316 /* deprecated */
317 {"annotwarning", pdc_booleanlist, PDC_OPT_PDFLIB_7, 1, 1,
318 0.0, 0.0, NULL},
319
320 {"usercoordinates", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
321 0.0, 0.0, NULL},
322
323 {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1,
324 0.0, PDF_MAX_NAMESTRING, NULL},
325
326 {"custom", pdc_stringlist, PDC_OPT_NONE, 1, 64,
327 0.0, PDC_INT_MAX, NULL},
328
329 {"name", pdc_stringlist, PDC_OPT_NONE, 1, 1,
330 0.0, PDC_USHRT_MAX, NULL},
331
332 {"parentname", pdc_stringlist, PDC_OPT_NONE, 1, 1,
333 0.0, PDC_USHRT_MAX, NULL},
334
335 {"popup", pdc_stringlist, PDC_OPT_NONE, 1, 1,
336 0.0, PDC_USHRT_MAX, NULL},
337
338 {"title", pdc_stringlist, PDC_OPT_NONE, 1, 1,
339 0.0, PDC_USHRT_MAX, NULL},
340
341 {"subject", pdc_stringlist, PDC_OPT_PDC_1_5, 1, 1,
342 0.0, PDC_USHRT_MAX, NULL},
343
344 {"annotcolor", pdc_stringlist, PDC_OPT_NONE, 1, 5,
345 0.0, PDF_MAX_NAMESTRING, NULL},
346
347 {"borderstyle", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
348 0.0, 0.0, pdf_borderstyle_keylist},
349
350 {"dasharray", pdc_scalarlist, PDC_OPT_NONE, 1, 2,
351 PDC_FLOAT_PREC, PDC_FLOAT_MAX, NULL},
352
353 {"linewidth", pdc_integerlist, PDC_OPT_NONE, 1, 1,
354 0.0, PDC_USHRT_MAX, NULL},
355
356 {"opacity", pdc_scalarlist, PDC_OPT_PDC_1_4 | PDC_OPT_PERCENT, 1, 1,
357 0.0, 1.0, NULL},
358
359 {"highlight", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
360 0.0, 0.0, pdf_highlight_keylist},
361
362 {"display", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
363 0.0, 0.0, pdf_display_keylist},
364
365 {"zoom", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
366 0.0, 0.0, NULL},
367
368 {"rotate", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
369 0.0, 0.0, NULL},
370
371 {"readonly", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
372 0.0, 0.0, NULL},
373
374 {"locked", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1,
375 0.0, 0.0, NULL},
376
377 {"open", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1,
378 0.0, 0.0, NULL},
379
380 {"createdate", pdc_booleanlist, PDC_OPT_PDC_1_5, 1, 1,
381 0.0, 0.0, NULL},
382
383 {"fillcolor", pdc_stringlist, PDC_OPT_NONE, 2, 5,
384 0.0, PDF_MAX_NAMESTRING, NULL},
385
386 {"alignment", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
387 0.0, 0.0, pdf_quadding_keylist},
388
389 {"font", pdc_fonthandle, PDC_OPT_NONE, 1, 1,
390 0.0, 0.0, NULL},
391
392 {"fontsize", pdc_scalarlist, PDC_OPT_SUBOPTLIST | PDC_OPT_KEYLIST1, 1, 2,
393 0.0, PDC_FLOAT_MAX, pdf_fontsize_keylist},
394
395 {"orientate", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
396 0.0, 0.0, pdf_orientate_keylist},
397
398 {"contents", pdc_stringlist, PDC_OPT_NONE, 1, 1,
399 0.0, PDC_INT_MAX, NULL},
400
401 {"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1,
402 0.0, PDC_USHRT_MAX, NULL},
403
404 {"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1,
405 0.0, PDC_USHRT_MAX, NULL},
406
407 {"filename", pdc_stringlist, PDC_OPT_NONE, 1, 1,
408 1.0, PDC_FILENAMELEN, NULL},
409
410 {"mimetype", pdc_stringlist, PDC_OPT_NONE, 1, 1,
411 0.0, PDF_MAX_NAMESTRING, NULL},
412
413 {"iconname", pdc_stringlist, PDC_OPT_NONE, 1, 1,
414 0.0, PDF_MAX_NAMESTRING, NULL},
415
416 {"endingstyles", pdc_keywordlist, PDC_OPT_NONE, 2, 2,
417 0.0, 0.0, pdf_endingstyles_pdfkeylist},
418
419 {"interiorcolor", pdc_stringlist, PDC_OPT_NONE, 1, 5,
420 0.0, PDF_MAX_NAMESTRING, NULL},
421
422 {"cloudy", pdc_scalarlist, PDC_OPT_PDC_1_5, 1, 1,
423 0.0, 2.0, NULL},
424
425 {"line", pdc_scalarlist, PDC_OPT_NONE, 4, 4,
426 PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
427
428 {"polylinelist", pdc_polylinelist, PDC_OPT_NONE, 1, PDF_MAXARRAYSIZE,
429 PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
430
431 {"action", pdc_stringlist, PDC_OPT_NONE, 1, 1,
432 0.0, PDC_USHRT_MAX, NULL},
433
434 {"usematchbox", pdc_stringlist, PDC_OPT_NONE, 1, 1,
435 0.0, PDC_USHRT_MAX, NULL},
436
437 {"layer", pdc_layerhandle, PDF_LAYER_FLAG, 1, 1,
438 0.0, 0.0, NULL},
439
440 {"3dactivate", pdc_stringlist, PDF_3DANNOT_FLAG, 1, 1,
441 0.0, PDC_USHRT_MAX, NULL},
442
443 {"3dbox", pdc_scalarlist, PDF_3DANNOT_FLAG, 4, 4,
444 PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
445
446 {"3ddata", pdc_3ddatahandle, PDF_3DANNOT_FLAG, 1, 1,
447 0.0, 0.0, NULL},
448
449 {"3dinteractive", pdc_booleanlist, PDF_3DANNOT_FLAG, 1, 1,
450 0.0, 0.0, NULL},
451
452 {"3dshared", pdc_booleanlist, PDF_3DANNOT_FLAG, 1, 1,
453 0.0, 0.0, NULL},
454
455 {"3dinitialview", pdc_3dviewhandle, PDF_3DANNOT_FLAG, 1, 1,
456 0.0, 0.0, pdf_3dview_keylist},
457
458 {"movieposter", pdc_templatehandle, PDC_OPT_NONE, 1, 1,
459 0.0, 0.0, pdf_movieposter_keylist},
460
461 {"showcontrols", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
462 0.0, 0.0, NULL},
463
464 {"playmode", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
465 0.0, 0.0, pdf_playmode_pdfkeylist},
466
467 {"windowscale", pdc_scalarlist, PDC_OPT_NONE, 1, 1,
468 PDC_FLOAT_PREC, PDC_FLOAT_MAX, pdf_windowscale_keylist},
469
470 {"windowposition", pdc_scalarlist, PDC_OPT_NONE, 1, 2,
471 0.0, 100.0, pdf_position_keylist},
472
473 {"soundvolume", pdc_scalarlist, PDC_OPT_NONE, 1, 1,
474 -1.0, 1.0, NULL},
475
476 PDC_OPT_TERMINATE
477 };
478
479 /* Annotation member */
480 typedef struct pdf_annot_s
481 {
482 pdc_bool iscopy;
483 pdc_id obj_id;
484 pdf_annottype atype;
485 int mask;
486 pdc_rectangle rect;
487 pdc_bool usercoordinates;
488 pdc_encoding hypertextencoding;
489 int hypertextcodepage;
490 pdf_coloropt annotcolor;
491 pdf_coloropt interiorcolor;
492 pdf_coloropt fillcolor;
493 int linewidth;
494 pdc_scalar opacity;
495 pdf_borderstyle borderstyle;
496 pdc_scalar dasharray[2];
497 pdf_highlight highlight;
498 pdf_display display;
499 pdc_bool zoom;
500 pdc_bool rotate;
501 pdc_bool kreadonly;
502 pdc_bool locked;
503 pdc_bool open;
504 pdc_bool createdate;
505 int font;
506 pdc_scalar fontsize;
507 int orientate;
508 pdf_quadding alignment;
509 pdf_endingstyles endingstyles[2];
510 pdc_scalar cloudy;
511 pdf_dest *dest;
512 char *name;
513 char *parentname;
514 char *popup;
515 char *title;
516 char *subject;
517 char *contents;
518 char *filename;
519 char *nativefilename;
520 char *mimetype;
521 const char *iconname;
522 pdc_off_t filesize;
523 pdc_scalar *line;
524 pdc_polyline *polylinelist;
525 int nplines;
526 char **custom;
527 int ncustoms;
528 char *action;
529
530
531
532 pdc_id movieposter;
533 pdc_bool showcontrols;
534 pdf_playmode_states playmode;
535 pdc_scalar windowscale;
536 pdc_scalar windowposition[2];
537 pdc_scalar soundvolume;
538 }
539 pdf_annot;
540
541 static void
pdf_reclaim_annot(void * item)542 pdf_reclaim_annot(void *item)
543 {
544 pdf_annot *ann = (pdf_annot *) item;
545
546 ann->iscopy = pdc_false;
547 ann->obj_id = PDC_BAD_ID;
548 ann->atype = (pdf_annottype)0;
549 ann->mask = 0;
550 ann->usercoordinates = pdc_false;
551 ann->hypertextencoding = pdc_invalidenc;
552 ann->hypertextcodepage = 0;
553 ann->annotcolor.type = (int) color_none;
554 ann->interiorcolor.type = (int) color_none;
555 ann->fillcolor.type = (int) color_none;
556 ann->linewidth = 1;
557 ann->opacity = 1;
558 ann->borderstyle = border_solid;
559 ann->dasharray[0] = 3;
560 ann->dasharray[1] = 3;
561 ann->highlight = high_invert;
562 ann->display = disp_visible;
563 ann->zoom = pdc_true;
564 ann->rotate = pdc_true;
565 ann->kreadonly = pdc_false;
566 ann->locked = pdc_false;
567 ann->open = pdc_false;
568 ann->createdate = pdc_false;
569 ann->font = -1;
570 ann->fontsize = 0;
571 ann->orientate = 0;
572 ann->alignment = quadd_left;
573 ann->cloudy = -1;
574 ann->endingstyles[0] = line_none;
575 ann->endingstyles[1] = line_none;
576 ann->dest = NULL;
577 ann->name = NULL;
578 ann->parentname = NULL;
579 ann->popup = NULL;
580 ann->title = NULL;
581 ann->subject = NULL;
582 ann->contents = NULL;
583 ann->filename = NULL;
584 ann->nativefilename = NULL;
585 ann->mimetype = NULL;
586 ann->iconname = NULL;
587 ann->filesize = 0;
588 ann->line = NULL;
589 ann->polylinelist = NULL;
590 ann->nplines = 0;
591 ann->custom = NULL;
592 ann->ncustoms = 0;
593 ann->action = NULL;
594
595
596
597
598
599 ann->movieposter = PDC_BAD_ID /* = movieposter_none */;
600 ann->showcontrols = pdc_false;
601 ann->playmode = playmode_once;
602 ann->windowscale = 0;
603 ann->windowposition[0] = 50.0;
604 ann->windowposition[1] = 50.0;
605 ann->soundvolume = 1.0;
606 }
607
608 static void
pdf_release_annot(void * context,void * item)609 pdf_release_annot(void *context, void *item)
610 {
611 PDF *p = (PDF *) context;
612 pdf_annot *ann = (pdf_annot *) item;
613
614 /* is not a copy */
615 if (!ann->iscopy)
616 {
617 pdf_cleanup_destination(p, ann->dest);
618 ann->dest = NULL;
619
620 if (ann->name)
621 {
622 pdc_free(p->pdc, ann->name);
623 ann->name = NULL;
624 }
625 if (ann->parentname)
626 {
627 pdc_free(p->pdc, ann->parentname);
628 ann->parentname = NULL;
629 }
630 if (ann->popup)
631 {
632 pdc_free(p->pdc, ann->popup);
633 ann->popup = NULL;
634 }
635 if (ann->title)
636 {
637 pdc_free(p->pdc, ann->title);
638 ann->title = NULL;
639 }
640 if (ann->subject)
641 {
642 pdc_free(p->pdc, ann->subject);
643 ann->subject = NULL;
644 }
645 if (ann->contents)
646 {
647 pdc_free(p->pdc, ann->contents);
648 ann->contents = NULL;
649 }
650 if (ann->filename)
651 {
652 pdc_free(p->pdc, ann->filename);
653 ann->filename = NULL;
654 }
655 if (ann->nativefilename)
656 {
657 pdc_free(p->pdc, ann->nativefilename);
658 ann->nativefilename = NULL;
659 }
660 if (ann->mimetype)
661 {
662 pdc_free(p->pdc, ann->mimetype);
663 ann->mimetype = NULL;
664 }
665 if (ann->line)
666 {
667 pdc_free(p->pdc, ann->line);
668 ann->line = NULL;
669 }
670 if (ann->custom)
671 {
672 pdc_cleanup_optstringlist(p->pdc, ann->custom, ann->ncustoms);
673 ann->custom = NULL;
674 ann->ncustoms = 0;
675 }
676 if (ann->action)
677 {
678 pdc_free(p->pdc, ann->action);
679 ann->action = NULL;
680 }
681 }
682
683 ann->polylinelist = (pdc_polyline *)pdc_delete_polylinelist(
684 p->pdc, ann->polylinelist, ann->nplines);
685 }
686
687 static pdc_ced pdf_annot_ced =
688 {
689 sizeof(pdf_annot), pdf_reclaim_annot, pdf_release_annot, NULL
690 };
691
692 static pdc_vtr_parms pdf_annot_parms =
693 {
694 0, 10, 10
695 };
696
697 static pdf_annot *
pdf_new_annot(PDF * p,pdf_annottype atype)698 pdf_new_annot(PDF *p, pdf_annottype atype)
699 {
700 pdc_vtr *annots = pdf_get_annots_list(p);
701 pdf_annot *ann;
702
703 if (annots == NULL)
704 {
705 annots = pdc_vtr_new(p->pdc, &pdf_annot_ced, p, &pdf_annot_parms);
706 pdf_set_annots_list(p, annots);
707 }
708
709 ann = pdc_vtr_incr(annots, pdf_annot);
710 ann->atype = atype;
711
712
713 ann->usercoordinates = p->usercoordinates;
714 ann->hypertextencoding = p->hypertextencoding;
715 ann->hypertextcodepage = p->hypertextcodepage;
716 pdf_init_coloropt(p, &ann->fillcolor);
717
718 return ann;
719 }
720
721 static void
pdf_delete_last_annot(PDF * p)722 pdf_delete_last_annot(PDF *p)
723 {
724 pdc_vtr *annots = pdf_get_annots_list(p);
725
726 if (annots != NULL)
727 {
728 if (pdc_vtr_size(annots) > 1)
729 {
730 pdc_vtr_pop(annots);
731 }
732 else
733 {
734 pdc_vtr_delete(annots);
735 pdf_set_annots_list(p, NULL);
736 }
737 }
738 }
739
740 static void
pdf_init_rectangle(PDF * p,pdf_annot * ann,pdc_scalar llx,pdc_scalar lly,pdc_scalar urx,pdc_scalar ury,pdc_vector * polyline)741 pdf_init_rectangle(PDF *p, pdf_annot *ann,
742 pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury,
743 pdc_vector *polyline)
744 {
745 static const char fn[] = "pdf_init_rectangle";
746 pdc_matrix *ctm = &p->curr_ppt->gstate[p->curr_ppt->sl].ctm;
747 int i;
748
749 pdc_check_number(p->pdc, "llx", llx);
750 pdc_check_number(p->pdc, "lly", lly);
751 pdc_check_number(p->pdc, "urx", urx);
752 pdc_check_number(p->pdc, "ury", ury);
753
754 pdc_delete_polylinelist(p->pdc, ann->polylinelist, ann->nplines);
755 ann->nplines = 1;
756 ann->polylinelist = (pdc_polyline *) pdc_malloc(p->pdc,
757 ann->nplines * sizeof(pdc_polyline), fn);
758 ann->polylinelist[0].np = 5;
759 ann->polylinelist[0].p = (pdc_vector *) pdc_malloc(p->pdc,
760 ann->polylinelist[0].np * sizeof(pdc_vector), fn);
761
762 if (polyline == NULL)
763 {
764 if (!ann->usercoordinates)
765 ctm = NULL;
766 pdc_rect_init(&ann->rect, llx, lly, urx, ury);
767 pdc_rect2polyline(ctm, &ann->rect, ann->polylinelist[0].p);
768 }
769 else
770 {
771 for (i = 0; i < 5; i++)
772 pdc_transform_vector(ctm, &polyline[i],
773 &ann->polylinelist[0].p[i]);
774 }
775
776 if (ctm != NULL)
777 pdc_polyline2rect(ann->polylinelist[0].p, 4, &ann->rect);
778 }
779
780 /* because of Acrobat muddle */
781 static void
pdf_permute_coordinates(pdf_annot * ann,pdf_annottype atype)782 pdf_permute_coordinates(pdf_annot *ann, pdf_annottype atype)
783 {
784 if (ann->nplines == 1 &&
785 (atype == ann_highlight ||
786 atype == ann_underline ||
787 atype == ann_squiggly ||
788 atype == ann_strikeout))
789 {
790 pdc_vector pl[5];
791 int i;
792
793 for (i = 0; i < ann->polylinelist[0].np; i++)
794 pl[i] = ann->polylinelist[0].p[i];
795
796 ann->polylinelist[0].p[0] = pl[3];
797 ann->polylinelist[0].p[1] = pl[2];
798 ann->polylinelist[0].p[2] = pl[0];
799 ann->polylinelist[0].p[3] = pl[1];
800 ann->polylinelist[0].p[4] = pl[3];
801 }
802 }
803
804 static const pdc_keyconn pdf_keytype_keylist[] =
805 {
806 {"boolean", pdc_booleanlist},
807 {"name", pdc_keywordlist},
808 {"string", pdc_stringlist},
809 {NULL, 0}
810 };
811
812 static const pdc_defopt pdf_custom_list_options[] =
813 {
814 {"key", pdc_stringlist, PDC_OPT_REQUIRED, 1, 1,
815 1.0, PDF_MAX_NAMESTRING, NULL},
816
817 {"type", pdc_keywordlist, PDC_OPT_REQUIRED, 1, 1,
818 0.0, 0.0, pdf_keytype_keylist},
819
820 {"value", pdc_stringlist, PDC_OPT_REQUIRED, 1, 1,
821 1.0, PDC_USHRT_MAX, NULL},
822
823 PDC_OPT_TERMINATE
824 };
825
826 static void
pdf_parse_and_write_annot_customlist(PDF * p,pdf_annot * ann,pdc_bool output)827 pdf_parse_and_write_annot_customlist(PDF *p, pdf_annot *ann, pdc_bool output)
828 {
829 int i;
830
831 /* custom entries */
832 for (i = 0; i < ann->ncustoms; i++)
833 {
834 pdc_resopt *resopts = NULL;
835 const char *stemp;
836 const char *keyword;
837 char **strlist = NULL;
838 char *string;
839 int inum;
840
841 resopts = pdc_parse_optionlist(p->pdc, ann->custom[i],
842 pdf_custom_list_options, NULL, pdc_true);
843
844 keyword = "key";
845 pdc_get_optvalues(keyword, resopts, NULL, &strlist);
846 string = strlist[0];
847
848 inum = pdc_get_keycode(string, pdf_forb_entries_pdfkeylist);
849 if (inum != PDC_KEY_NOTFOUND)
850 {
851 stemp = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, string);
852 pdc_error(p->pdc, PDF_E_ANN_ILLCUSTOMKEY, stemp, 0, 0, 0);
853 }
854 inum = pdc_get_keycode(string, pdf_perm_entries_pdfkeylist);
855 if (inum != PDC_KEY_NOTFOUND)
856 ann->mask |= inum;
857
858 if (output)
859 pdc_printf(p->out, "/%s", string);
860
861 keyword = "type";
862 pdc_get_optvalues(keyword, resopts, &inum, NULL);
863
864 keyword = "value";
865 pdc_get_optvalues(keyword, resopts, NULL, &strlist);
866 string = strlist[0];
867
868 switch (inum)
869 {
870 case pdc_booleanlist:
871 if (pdc_stricmp(string, "true") && pdc_stricmp(string, "false"))
872 {
873 stemp =
874 pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, string);
875
876 pdc_error(p->pdc, PDC_E_OPT_ILLBOOLEAN, keyword, stemp, 0, 0);
877 }
878 if (output)
879 pdc_printf(p->out, " %s",
880 PDC_BOOLSTR(pdc_stricmp(string, "false")));
881 break;
882
883 case pdc_keywordlist:
884 if (output)
885 pdc_printf(p->out, "/%s", string);
886 break;
887
888 case pdc_stringlist:
889 pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
890 ann->hypertextcodepage, pdc_true, NULL, &string, NULL);
891 if (output)
892 pdf_put_hypertext(p, string);
893 break;
894 }
895 if (output)
896 pdc_puts(p->out, "\n");
897 }
898 }
899
900
901
902 static void
pdf_opt_alrdef(PDF * p,const char * keyword,pdf_annot * ann,int flag)903 pdf_opt_alrdef(PDF *p, const char *keyword, pdf_annot *ann, int flag)
904 {
905 if (ann->mask & flag)
906 pdc_error(p->pdc, PDF_E_ANN_OPTALRDEF, keyword, 0, 0, 0);
907 }
908
909 static int
pdf_opt_effectless(PDF * p,const char * keyword,pdf_annottype curratype,pdf_annottype intendatypes)910 pdf_opt_effectless(PDF *p, const char *keyword, pdf_annottype curratype,
911 pdf_annottype intendatypes)
912 {
913 if ((pdf_annottype) !(intendatypes & curratype))
914 {
915 const char *type = pdc_get_keyword(curratype, pdf_annottype_pdfkeylist);
916 pdc_warning(p->pdc, PDF_E_ANN_OPTEFFLESS_FORTYPE, keyword, type,
917 0, 0);
918 return 1;
919 }
920 return 0;
921 }
922
923 void
pdf__create_annotation(PDF * p,pdc_scalar llx,pdc_scalar lly,pdc_scalar urx,pdc_scalar ury,const char * type,const char * optlist)924 pdf__create_annotation(PDF *p,
925 pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury,
926 const char *type, const char *optlist)
927 {
928 pdc_resopt *resopts = NULL;
929 pdc_clientdata cdata;
930 pdf_annottype atype;
931 pdf_annot *ann;
932 pdf_dest *dest = NULL;
933 const char *keyword, *keyword_s = NULL;
934 char **strlist = NULL;
935 pdc_scalar *line;
936 int i, j, k, ns, nss[2];
937 pdf_colortype maxcs = color_rgb;
938 pdf_ppt *ppt = p->curr_ppt;
939 pdc_matrix *ctm = &ppt->gstate[ppt->sl].ctm;
940
941 pdc_check_number(p->pdc, "llx", llx);
942 pdc_check_number(p->pdc, "lly", lly);
943 pdc_check_number(p->pdc, "urx", urx);
944 pdc_check_number(p->pdc, "ury", ury);
945
946 if (type == NULL || *type == '\0')
947 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0);
948
949 k = pdc_get_keycode_ci(type, pdf_annottype_pdfkeylist);
950 if (k == PDC_KEY_NOTFOUND)
951 pdc_error(p->pdc, PDC_E_ILLARG_STRING, "type", type, 0, 0);
952 atype = (pdf_annottype) k;
953
954
955 /* compatibility */
956 if (p->compatibility < PDC_1_5 &&
957 (atype == ann_polygon || atype == ann_polyline))
958 {
959 pdc_error(p->pdc, PDC_E_PAR_VERSION, type,
960 pdc_get_pdfversion(p->pdc, PDC_1_5), 0, 0);
961 }
962
963 if (p->compatibility >= PDC_1_6)
964 maxcs = color_cmyk;
965
966 /* Parsing option list */
967 pdf_set_clientdata(p, &cdata);
968 resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_create_annot_options,
969 &cdata, pdc_true);
970
971 /* Initializing */
972 ann = pdf_new_annot(p, atype);
973
974 keyword = "usercoordinates";
975 pdc_get_optvalues(keyword, resopts, &ann->usercoordinates, NULL);
976 pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
977
978 ann->hypertextencoding =
979 pdf_get_hypertextencoding_opt(p, resopts, &ann->hypertextcodepage,
980 pdc_true);
981
982 keyword = "custom";
983 ns = pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
984 ann->hypertextcodepage, pdc_true, NULL, NULL, &ann->custom);
985 if (ns)
986 {
987 pdc_save_lastopt(resopts, PDC_OPT_SAVEALL);
988 ann->ncustoms = ns;
989 pdf_parse_and_write_annot_customlist(p, ann, pdc_false);
990 }
991
992 keyword = "name";
993 ns = pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
994 ann->hypertextcodepage, pdc_true, NULL, &ann->name, NULL);
995 if (ns)
996 {
997 pdf_opt_alrdef(p, keyword, ann, anndict_nm);
998 pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
999 }
1000
1001 keyword = "parentname";
1002 if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
1003 ann->parentname = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
1004
1005 keyword = "popup";
1006 if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
1007 ann->popup = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
1008
1009 keyword = "title";
1010 if (pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
1011 ann->hypertextcodepage, pdc_true, NULL, &ann->title, NULL))
1012 pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
1013
1014 keyword = "subject";
1015 if (pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
1016 ann->hypertextcodepage, pdc_true, NULL, &ann->subject, NULL))
1017 pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
1018
1019 keyword = "annotcolor";
1020 ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
1021 if (ns)
1022 {
1023 pdf_parse_coloropt(p, keyword, strlist, ns, (int) maxcs,
1024 &ann->annotcolor);
1025 }
1026
1027 keyword = "borderstyle";
1028 if (pdc_get_optvalues(keyword, resopts, &ns, NULL))
1029 ann->borderstyle = (pdf_borderstyle) ns;
1030
1031 keyword = "dasharray";
1032 ns = pdc_get_optvalues(keyword, resopts, ann->dasharray, NULL);
1033 if (ns)
1034 {
1035 if (ns == 1)
1036 ann->dasharray[1] = ann->dasharray[0];
1037 if (ann->borderstyle != border_dashed)
1038 pdc_warning(p->pdc, PDC_E_OPT_IGNORED, keyword, 0, 0, 0);
1039 }
1040
1041 keyword = "linewidth";
1042 pdc_get_optvalues(keyword, resopts, &ann->linewidth, NULL);
1043
1044 keyword = "opacity";
1045 pdc_get_optvalues(keyword, resopts, &ann->opacity, NULL);
1046
1047
1048 keyword = "highlight";
1049 if (pdc_get_optvalues(keyword, resopts, &ns, NULL))
1050 {
1051 pdf_opt_effectless(p, keyword, atype, ann_link);
1052 ann->highlight = (pdf_highlight) ns;
1053 }
1054
1055 keyword = "display";
1056 if (pdc_get_optvalues(keyword, resopts, &ann->display, NULL))
1057 ann->display = (pdf_display) ns;
1058
1059 keyword = "zoom";
1060 pdc_get_optvalues(keyword, resopts, &ann->zoom, NULL);
1061
1062 keyword = "rotate";
1063 pdc_get_optvalues(keyword, resopts, &ann->rotate, NULL);
1064
1065 keyword = "readonly";
1066 pdc_get_optvalues(keyword, resopts, &ann->kreadonly, NULL);
1067
1068 keyword = "locked";
1069 pdc_get_optvalues(keyword, resopts, &ann->locked, NULL);
1070
1071 keyword = "open";
1072 if (pdc_get_optvalues(keyword, resopts, &ann->open, NULL))
1073 {
1074 pdf_opt_alrdef(p, keyword, ann, anndict_open);
1075 pdf_opt_effectless(p, keyword, atype,
1076 (pdf_annottype) (ann_text | ann_popup));
1077 }
1078
1079 keyword = "createdate";
1080 pdc_get_optvalues(keyword, resopts, &ann->createdate, NULL);
1081
1082 keyword = "fillcolor";
1083 ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
1084 if (ns && !pdf_opt_effectless(p, keyword, atype, ann_freetext))
1085 {
1086 pdf_parse_coloropt(p, keyword, strlist, ns, (int) color_cmyk,
1087 &ann->fillcolor);
1088 }
1089
1090 keyword = "alignment";
1091 if (pdc_get_optvalues(keyword, resopts, &ns, NULL))
1092 ann->alignment = (pdf_quadding) ns;
1093
1094 keyword = "font";
1095 if (pdc_get_optvalues(keyword, resopts, &ann->font, NULL))
1096 pdf_opt_effectless(p, keyword, atype, ann_freetext);
1097
1098 keyword = "fontsize";
1099 if (pdf_get_fontsize_option(p, ann->font, resopts, &ann->fontsize))
1100 {
1101 pdf_opt_effectless(p, keyword, atype, ann_freetext);
1102 if (ann->usercoordinates == pdc_true)
1103 ann->fontsize = pdc_transform_scalar(ctm, ann->fontsize);
1104 }
1105
1106 keyword = "orientate";
1107 if (pdc_get_optvalues(keyword, resopts, &ann->orientate, NULL))
1108 pdf_opt_effectless(p, keyword, atype,
1109 (pdf_annottype) (ann_freetext | ann_stamp));
1110
1111 keyword = "contents";
1112 if (atype == ann_freetext)
1113 {
1114 pdc_encoding enc = pdc_invalidenc;
1115 int codepage = 0;
1116
1117 if (ann->font > -1)
1118 {
1119 enc = p->fonts[ann->font].ft.enc;
1120 codepage = p->fonts[ann->font].codepage;
1121 }
1122 pdf_get_opt_textlist(p, keyword, resopts, enc, codepage,
1123 pdc_false, NULL, &ann->contents, NULL);
1124 }
1125 else
1126 {
1127 pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
1128 ann->hypertextcodepage, pdc_true, NULL, &ann->contents, NULL);
1129 }
1130 if (ann->contents)
1131 {
1132 pdf_opt_alrdef(p, keyword, ann, anndict_contents);
1133 pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
1134 }
1135
1136 keyword = "destination";
1137 if (pdc_get_optvalues(keyword, resopts, NULL, &strlist) &&
1138 !pdf_opt_effectless(p, keyword, atype, ann_link))
1139 {
1140 ann->dest = pdf_parse_destination_optlist(p, strlist[0], 0,
1141 pdf_locallink);
1142 keyword_s = keyword;
1143 }
1144 else
1145 {
1146 keyword = "destname";
1147 if (atype == ann_link)
1148 dest = pdf_get_option_destname(p, resopts, ann->hypertextencoding,
1149 ann->hypertextcodepage);
1150 else if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
1151 pdf_opt_effectless(p, keyword, atype, ann_link);
1152 if (dest)
1153 {
1154 ann->dest = dest;
1155 keyword_s = keyword;
1156 }
1157 }
1158
1159 keyword = "filename";
1160 if (pdc_get_optvalues(keyword, resopts, NULL, NULL) &&
1161 !pdf_opt_effectless(p, keyword, atype,
1162 (pdf_annottype) (ann_fileattachment | ann_movie)))
1163 {
1164 /* DON'T change order */
1165
1166 /* native filename */
1167 ann->nativefilename = pdf_get_opt_filename(p, keyword, resopts,
1168 ann->hypertextencoding, ann->hypertextcodepage);
1169
1170 pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
1171 ann->hypertextcodepage,
1172 /* bug #2344 */ atype == ann_fileattachment ? pdc_undef : pdc_true,
1173 NULL, &ann->filename, NULL);
1174 pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
1175
1176 if (atype == ann_fileattachment)
1177 ann->filesize = pdf_check_file(p, ann->filename, pdc_true);
1178 }
1179
1180 keyword = "mimetype";
1181 if (pdc_get_optvalues(keyword, resopts, NULL, NULL) &&
1182 !pdf_opt_effectless(p, keyword, atype, ann_fileattachment))
1183 ann->mimetype = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
1184
1185 keyword = "iconname";
1186 if (pdc_get_optvalues(keyword, resopts, NULL, &strlist) &&
1187 !pdf_opt_effectless(p, keyword, atype,
1188 (pdf_annottype) (ann_text | ann_stamp | ann_fileattachment)))
1189 {
1190 const pdc_keyconn *kc = pdf_text_iconnames_pdfkeylist;
1191
1192 pdf_opt_alrdef(p, keyword, ann, anndict_name);
1193
1194 if (atype == ann_stamp)
1195 kc = pdf_stamp_iconnames_pdfkeylist;
1196 else if (atype == ann_fileattachment)
1197 kc = pdf_attach_iconnames_pdfkeylist;
1198
1199 ann->iconname = pdc_get_int_keyword(strlist[0], kc);
1200 if (ann->iconname == NULL)
1201 pdc_error(p->pdc, PDC_E_OPT_ILLKEYWORD, keyword, strlist[0],
1202 0, 0);
1203 }
1204
1205 keyword = "endingstyles";
1206 if (pdc_get_optvalues(keyword, resopts, nss, NULL))
1207 {
1208 ann->endingstyles[0] = (pdf_endingstyles) nss[0];
1209 ann->endingstyles[1] = (pdf_endingstyles) nss[1];
1210 pdf_opt_effectless(p, keyword, atype,
1211 (pdf_annottype) (ann_line | ann_polyline));
1212 }
1213
1214 keyword = "interiorcolor";
1215 ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
1216 if (ns && !pdf_opt_effectless(p, keyword, atype,
1217 (pdf_annottype) (ann_line | ann_polyline |
1218 ann_square | ann_circle)))
1219 {
1220 pdf_parse_coloropt(p, keyword, strlist, ns, (int) maxcs,
1221 &ann->interiorcolor);
1222 }
1223
1224 keyword = "cloudy";
1225 if (pdc_get_optvalues(keyword, resopts, &ann->cloudy, NULL))
1226 pdf_opt_effectless(p, keyword, atype, ann_polygon);
1227
1228 keyword = "line";
1229 ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
1230 if (ns && !pdf_opt_effectless(p, keyword, atype, ann_line))
1231 {
1232 line = (pdc_scalar *) strlist;
1233 if (ann->usercoordinates == pdc_true)
1234 {
1235 pdc_transform_point(ctm, line[0], line[1], &line[0], &line[1]);
1236 pdc_transform_point(ctm, line[2], line[3], &line[2], &line[3]);
1237 }
1238 ann->line = (pdc_scalar *) pdc_save_lastopt(resopts, PDC_OPT_SAVEALL);
1239 }
1240
1241 keyword = "polylinelist";
1242 ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
1243 if (ns)
1244 {
1245 if (!pdf_opt_effectless(p, keyword, atype,
1246 (pdf_annottype) (ann_ink | ann_polygon | ann_polyline |
1247 ann_highlight | ann_underline |
1248 ann_squiggly | ann_strikeout)))
1249 {
1250 pdc_polyline *pl = (pdc_polyline *) strlist;
1251
1252 for (j = 0; j < ns; j++)
1253 {
1254 if (pl[j].np < 2 ||
1255 (atype != ann_ink && atype != ann_polygon &&
1256 atype != ann_polyline && pl[j].np != 4))
1257 {
1258 pdc_error(p->pdc, PDF_E_ANN_BADNUMCOORD, keyword, 0, 0, 0);
1259 }
1260 for (i = 0; i < pl[j].np; i++)
1261 {
1262 if (ann->usercoordinates == pdc_true)
1263 pdc_transform_vector(ctm, &pl[j].p[i], NULL);
1264 }
1265 }
1266 pdc_delete_polylinelist(p->pdc, ann->polylinelist, ann->nplines);
1267 ann->polylinelist = pl;
1268 ann->nplines = ns;
1269 pdc_save_lastopt(resopts, PDC_OPT_SAVEALL);
1270 }
1271 }
1272 else
1273 pdf_permute_coordinates(ann, atype);
1274
1275 keyword = "action";
1276 if (pdc_get_optvalues(keyword, resopts, NULL, &strlist))
1277 {
1278 /*
1279 * PDF 1.7 allows the A action dictionary only for annotation types
1280 * link, widget and screen. Widget is handled elsewhere, and screen
1281 * is not yet implemented, so only link is allowed with compatiblity
1282 * 1.7.
1283 * Must be extended that also screen annotation is accepted here
1284 * once it is implemented.
1285 */
1286 if (p->compatibility >= PDC_1_7)
1287 {
1288 if (ann->atype != ann_link)
1289 {
1290 pdc_error(p->pdc, PDF_E_ANN_ACTIONNOTALLOWED,
1291 pdc_get_keyword(ann->atype, pdf_annottype_pdfkeylist),
1292 0, 0, 0);
1293 }
1294 }
1295
1296 if (ann->dest)
1297 {
1298 pdf_cleanup_destination(p, ann->dest);
1299 ann->dest = NULL;
1300 pdc_warning(p->pdc, PDC_E_OPT_IGNORE, keyword_s, keyword, 0, 0);
1301 }
1302
1303 /* parsing of action list */
1304 pdf_parse_and_write_actionlist(p, event_annotation, NULL,
1305 (const char *) strlist[0]);
1306 ann->action = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
1307 }
1308
1309
1310
1311 keyword = "movieposter";
1312 if (pdc_get_optvalues(keyword, resopts, &ns, NULL))
1313 {
1314 pdf_opt_effectless(p, keyword, atype, ann_movie);
1315 if (ns < 0)
1316 {
1317 ann->movieposter = (pdc_id) ns;
1318 }
1319 else
1320 {
1321 #if 0
1322 int cstype = pdf_get_image_colorspace(p, ns);
1323
1324 if (cstype != (int) DeviceGray && cstype != (int) DeviceRGB)
1325 pdc_error(p->pdc, PDF_E_ANN_ILLTEMPLATE, 0, 0, 0, 0);
1326 #endif
1327 ann->movieposter = pdf_get_xobject(p, ns);
1328 }
1329 }
1330
1331 keyword = "showcontrols";
1332 if (pdc_get_optvalues(keyword, resopts, &ann->showcontrols, NULL))
1333 pdf_opt_effectless(p, keyword, atype, ann_movie);
1334
1335 keyword = "playmode";
1336 if (pdc_get_optvalues(keyword, resopts, &ns, NULL))
1337 {
1338 pdf_opt_effectless(p, keyword, atype, ann_movie);
1339 ann->playmode = (pdf_playmode_states) ns;
1340 }
1341
1342 keyword = "windowscale";
1343 if (pdc_get_optvalues(keyword, resopts, &ann->windowscale, NULL))
1344 pdf_opt_effectless(p, keyword, atype, ann_movie);
1345
1346 keyword = "windowposition";
1347 ns = pdc_get_optvalues(keyword, resopts, ann->windowposition, NULL);
1348 if (ns)
1349 {
1350 pdf_opt_effectless(p, keyword, atype, ann_movie);
1351 pdf_set_position_values(p, ann->windowposition, ns);
1352 }
1353
1354 keyword = "soundvolume";
1355 if (pdc_get_optvalues(keyword, resopts, &ann->soundvolume, NULL))
1356 pdf_opt_effectless(p, keyword, atype, ann_movie);
1357
1358 /* named annotation, to be accessible by a GoTo3DView or Movie action */
1359 if ((atype == ann_3d || atype == ann_movie) && ann->name != NULL)
1360 {
1361 char *name = (char *) pdc_strdup(p->pdc, ann->name);
1362
1363 ann->obj_id = pdc_alloc_id(p->out);
1364 pdf_insert_name(p, name, names_annots, ann->obj_id);
1365 }
1366
1367 /* work-around for Acrobat 8 (see bug #1225) */
1368 if (ann->annotcolor.type == (int) color_none &&
1369 (atype == ann_square || atype == ann_circle))
1370 {
1371 ann->annotcolor.type = (int) color_rgb;
1372 ann->annotcolor.value[0] = 1.0;
1373 ann->annotcolor.value[1] = 1.0;
1374 ann->annotcolor.value[2] = 1.0;
1375 }
1376
1377 /* required options */
1378 keyword = NULL;
1379 if (ann->contents == NULL &&
1380 atype != ann_link && atype != ann_popup && atype != ann_movie)
1381 keyword = "contents";
1382 if (ann->fontsize == 0 && atype == ann_freetext)
1383 keyword = "fontsize";
1384 if (ann->font == -1 && atype == ann_freetext)
1385 keyword = "font";
1386 if (ann->filename == NULL &&
1387 (atype == ann_fileattachment || atype == ann_movie))
1388 keyword = "filename";
1389 if (ann->line == NULL && atype == ann_line)
1390 keyword = "line";
1391 if (ann->polylinelist == NULL &&
1392 (atype == ann_ink || atype == ann_polygon || atype == ann_polyline))
1393 keyword = "polylinelist";
1394
1395 if (keyword)
1396 pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, keyword, 0, 0, 0);
1397
1398
1399 if (atype == ann_freetext)
1400 {
1401 pdf_font *font_s = &p->fonts[ann->font];
1402 const char *fontname =
1403 pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, font_s->ft.name);
1404
1405 if (!strcmp(pdf_get_pdf_fontname(font_s), fontname))
1406 pdc_error(p->pdc, PDF_E_ANN_NOSTDFONT, fontname, 0, 0, 0);
1407 }
1408
1409 /*
1410 * matchbox available
1411 */
1412 keyword = "usematchbox";
1413 if (pdc_get_optvalues(keyword, resopts, NULL, &strlist))
1414 {
1415 pdf_annot *ann_first = ann;
1416 const char *mboxname;
1417 int ir, nrect, irect;
1418
1419 mboxname = pdf_get_usematchbox(p, keyword, strlist[0], &irect, &nrect);
1420 if (mboxname != NULL)
1421 {
1422 if (irect > nrect)
1423 {
1424 pdf_delete_last_annot(p);
1425 }
1426 else
1427 {
1428 pdf_mbox *mbox;
1429 pdc_vector pl[5];
1430
1431 /* rectangle loop */
1432 for (ir = irect; ir <= nrect; ir++)
1433 {
1434 if (ir > irect)
1435 {
1436 /* create copy */
1437 ann = pdf_new_annot(p, atype);
1438 memcpy(ann, ann_first, sizeof(pdf_annot));
1439 ann->obj_id = PDC_BAD_ID;
1440 ann->iscopy = pdc_true;
1441 ann->nplines = 0;
1442 ann->polylinelist = NULL;
1443 }
1444
1445 /* rectangle #ir */
1446 mbox = pdf_get_mbox(p, NULL, mboxname, ir, NULL);
1447 pdf_get_mbox_rectangle(p, mbox, pl);
1448 pdf_init_rectangle(p, ann, 0, 0, 0, 0, pl);
1449 pdf_permute_coordinates(ann, atype);
1450 ann->usercoordinates = pdc_true;
1451 }
1452 }
1453 }
1454 }
1455
1456 }
1457
1458 pdc_id
pdf_write_annots_root(PDF * p,pdc_vtr * annots,pdf_widget * widgetlist)1459 pdf_write_annots_root(PDF *p, pdc_vtr *annots, pdf_widget *widgetlist)
1460 {
1461 pdc_id result = PDC_BAD_ID;
1462
1463 /* Annotations array */
1464 if (annots != NULL || widgetlist)
1465 {
1466 result = pdc_begin_obj(p->out, PDC_NEW_ID);
1467 pdc_begin_array(p->out);
1468
1469 if (annots != NULL)
1470 {
1471 pdf_annot *ann;
1472 int i, na = pdc_vtr_size(annots);
1473
1474 for (i = 0; i < na; i++)
1475 {
1476 ann = (pdf_annot *) &pdc_vtr_at(annots, i, pdf_annot);
1477 if (ann->obj_id == PDC_BAD_ID)
1478 ann->obj_id = pdc_alloc_id(p->out);
1479 pdc_objref_c(p->out, ann->obj_id);
1480 }
1481 }
1482
1483 (void) widgetlist;
1484
1485 pdc_end_array(p->out);
1486 pdc_end_obj(p->out);
1487 }
1488
1489 return result;
1490 }
1491
1492 static void
pdf_write_defappstring(PDF * p,pdf_annot * ann)1493 pdf_write_defappstring(PDF *p, pdf_annot *ann)
1494 {
1495 char buf[PDC_GEN_BUFSIZE], *bufc;
1496 pdf_coloropt *fs;
1497 int ct;
1498
1499 if (ann->font == -1)
1500 return;
1501
1502 bufc = buf;
1503
1504 /* font and fontsize */
1505 bufc += pdc_sprintf(p->pdc, pdc_true, bufc, "/%s %f Tf",
1506 pdf_get_pdf_fontname(&p->fonts[ann->font]),
1507 ann->fontsize);
1508
1509 /* fill and stroke color */
1510 fs = &ann->fillcolor;
1511 ct = fs->type;
1512 switch (ct)
1513 {
1514 case color_gray:
1515 bufc += pdc_sprintf(p->pdc, pdc_true, bufc, " %f g",
1516 fs->value[0]);
1517 break;
1518
1519 case color_rgb:
1520 bufc += pdc_sprintf(p->pdc, pdc_true, bufc, " %f %f %f rg",
1521 fs->value[0], fs->value[1], fs->value[2]);
1522 break;
1523
1524 case color_cmyk:
1525 bufc += pdc_sprintf(p->pdc, pdc_true, bufc, " %f %f %f %f k",
1526 fs->value[0], fs->value[1],
1527 fs->value[2], fs->value[3]);
1528 break;
1529 }
1530
1531 pdc_puts(p->out, "/DA");
1532 pdf_put_hypertext(p, buf);
1533 pdc_puts(p->out, "\n");
1534 }
1535
1536 static void
pdf_write_colorentry(PDF * p,const char * keyname,pdf_coloropt * coloropt)1537 pdf_write_colorentry(PDF *p, const char *keyname, pdf_coloropt *coloropt)
1538 {
1539 if (p->compatibility < PDC_1_6)
1540 {
1541 if (coloropt->type != (int) color_none)
1542 {
1543 pdc_printf(p->out, "%s[%f %f %f]\n",
1544 keyname,
1545 coloropt->value[0],
1546 coloropt->value[1],
1547 coloropt->value[2]);
1548 }
1549 }
1550 else
1551 {
1552 switch (coloropt->type)
1553 {
1554 case color_none:
1555 /* this doesn't work in Acrobat 8
1556 pdc_printf(p->out, "%s[0]\n",
1557 keyname);
1558 */
1559 break;
1560
1561 case color_gray:
1562 pdc_printf(p->out, "%s[%f]\n",
1563 keyname,
1564 coloropt->value[0]);
1565 break;
1566
1567 case color_rgb:
1568 pdc_printf(p->out, "%s[%f %f %f]\n",
1569 keyname,
1570 coloropt->value[0],
1571 coloropt->value[1],
1572 coloropt->value[2]);
1573 break;
1574
1575 case color_cmyk:
1576 pdc_printf(p->out, "%s[%f %f %f %f]\n",
1577 keyname,
1578 coloropt->value[0],
1579 coloropt->value[1],
1580 coloropt->value[2],
1581 coloropt->value[3]);
1582 break;
1583 }
1584 }
1585 }
1586
1587 void
pdf_write_page_annots(PDF * p,pdc_vtr * annots)1588 pdf_write_page_annots(PDF *p, pdc_vtr *annots)
1589 {
1590 pdf_annot *ann, *annpar;
1591 pdc_id act_idlist[PDF_MAX_EVENTS];
1592 int i, j, k, na, flags;
1593
1594 na = pdc_vtr_size(annots);
1595
1596 for (k = 0; k < na; k++)
1597 {
1598 ann = (pdf_annot *) &pdc_vtr_at(annots, k, pdf_annot);
1599
1600
1601 /* write action objects */
1602 if (ann->action)
1603 pdf_parse_and_write_actionlist(p, event_annotation, act_idlist,
1604 (const char *) ann->action);
1605
1606
1607 pdc_begin_obj(p->out, ann->obj_id); /* Annotation object */
1608 pdc_begin_dict(p->out); /* Annotation dict */
1609
1610 pdc_puts(p->out, "/Type/Annot\n");
1611 pdc_printf(p->out, "/Subtype/%s\n",
1612 pdc_get_keyword(ann->atype, pdf_annottype_pdfkeylist));
1613
1614
1615
1616
1617 /* Contents */
1618 if (ann->contents)
1619 {
1620 pdc_puts(p->out, "/Contents");
1621 if (ann->atype == ann_freetext)
1622 pdf_put_fieldtext(p, ann->contents, ann->font);
1623 else
1624 pdf_put_hypertext(p, ann->contents);
1625 pdc_puts(p->out, "\n");
1626 }
1627
1628 /* Current Page */
1629 pdc_objref(p->out, "/P", pdf_get_page_id(p, 0));
1630
1631 /* Rectangle */
1632 pdc_printf(p->out, "/Rect[%f %f %f %f]\n",
1633 ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury);
1634
1635 /* Name */
1636 if (ann->name)
1637 {
1638 pdc_puts(p->out, "/NM");
1639 pdf_put_hypertext(p, ann->name);
1640 pdc_puts(p->out, "\n");
1641 }
1642
1643 /* Flags */
1644 flags = 0;
1645 if (ann->display != disp_noprint)
1646 {
1647 flags = (1<<2);
1648 flags |= ann->display;
1649 }
1650 if (!ann->zoom)
1651 flags |= (1<<3);
1652 if (!ann->rotate)
1653 flags |= (1<<4);
1654 if (ann->kreadonly)
1655 flags |= (1<<6);
1656 if (ann->locked)
1657 flags |= (1<<7);
1658 if (flags)
1659 pdc_printf(p->out, "/F %d\n", flags);
1660
1661 /* Border style dictionary */
1662 if (ann->linewidth != 1 || ann->borderstyle != border_solid)
1663 {
1664 pdc_puts(p->out, "/BS");
1665 pdc_begin_dict(p->out); /* BS dict */
1666
1667 pdc_printf(p->out, "/W %d", ann->linewidth);
1668 pdc_printf(p->out, "/S/%s",
1669 pdc_get_keyword(ann->borderstyle, pdf_borderstyle_pdfkeylist));
1670 if (ann->borderstyle == border_dashed)
1671 pdc_printf(p->out, "/D[%f %f]",
1672 ann->dasharray[0], ann->dasharray[1]);
1673
1674 pdc_end_dict(p->out); /* BS dict */
1675
1676 /* Write the Border key in old-style PDF 1.1 format
1677 * because of a bug in PDF 1.4 and earlier
1678 */
1679 pdc_printf(p->out, "/Border[0 0 %f", (double) ann->linewidth);
1680
1681 if (ann->borderstyle == border_dashed)
1682 pdc_printf(p->out, "[%f %f]",
1683 ann->dasharray[0], ann->dasharray[1]);
1684 pdc_puts(p->out, "]\n");
1685 }
1686
1687 /* Annotation color */
1688 pdf_write_colorentry(p, "/C", &ann->annotcolor);
1689
1690 /* Title */
1691 if (ann->title && *ann->title)
1692 {
1693 pdc_puts(p->out, "/T");
1694 pdf_put_hypertext(p, ann->title);
1695 pdc_puts(p->out, "\n");
1696 }
1697
1698 /* Subject */
1699 if (ann->subject && *ann->subject)
1700 {
1701 pdc_puts(p->out, "/Subj");
1702 pdf_put_hypertext(p, ann->subject);
1703 pdc_puts(p->out, "\n");
1704 }
1705
1706 /* Popup */
1707 if (ann->popup && *ann->popup)
1708 {
1709 for (i = 0; i < na; i++)
1710 {
1711 annpar = (pdf_annot *) &pdc_vtr_at(annots, i, pdf_annot);
1712 if (annpar->name != NULL &&
1713 !strcmp(ann->popup, annpar->name))
1714 {
1715 pdc_objref(p->out, "/Popup", annpar->obj_id);
1716 break;
1717 }
1718 }
1719 }
1720
1721 /* Icon Name */
1722 if (ann->iconname && *ann->iconname)
1723 pdc_printf(p->out, "/Name/%s\n", ann->iconname);
1724
1725 /* CreationDate */
1726 if (ann->createdate)
1727 {
1728 char time_str[PDC_TIME_SBUF_SIZE];
1729
1730 pdc_get_timestr(time_str, pdc_false);
1731 pdc_puts(p->out, "/CreationDate ");
1732 pdf_put_hypertext(p, time_str);
1733 pdc_puts(p->out, "\n");
1734 }
1735
1736 /* Opacity */
1737 if (ann->opacity != 1)
1738 pdc_printf(p->out, "/CA %f\n", ann->opacity);
1739
1740 /* write Action entries */
1741 if (ann->action)
1742 pdf_write_action_entries(p, event_annotation, act_idlist);
1743
1744 /* custom entries */
1745 pdf_parse_and_write_annot_customlist(p, ann, pdc_true);
1746
1747 switch (ann->atype)
1748 {
1749 /* Open */
1750 case ann_text:
1751 case ann_popup:
1752 if (ann->open)
1753 pdc_puts(p->out, "/Open true\n");
1754 break;
1755
1756 /* Alignment, Default appearance string */
1757 case ann_freetext:
1758 if (ann->alignment != quadd_left)
1759 pdc_printf(p->out, "/Q %d\n", ann->alignment);
1760 pdf_write_defappstring(p, ann);
1761 break;
1762
1763 /* Line */
1764 case ann_line:
1765 pdc_printf(p->out, "/L[%f %f %f %f]\n",
1766 ann->line[0], ann->line[1], ann->line[2], ann->line[3]);
1767 break;
1768
1769 /* InkList, QuadPoints and Vertices */
1770 case ann_link:
1771 if (!ann->usercoordinates || p->compatibility < PDC_1_6)
1772 break;
1773 case ann_highlight:
1774 case ann_underline:
1775 case ann_squiggly:
1776 case ann_strikeout:
1777 ann->polylinelist[0].np = 4; /* because of Acrobat error */
1778 case ann_ink:
1779 case ann_polygon:
1780 case ann_polyline:
1781 pdc_printf(p->out, "/%s",
1782 pdc_get_keyword(ann->atype, pdf_polyline_pdfkeylist));
1783 pdc_begin_array(p->out);
1784 for (i = 0; i < ann->nplines; i++)
1785 {
1786 if (ann->atype == ann_ink)
1787 pdc_begin_array(p->out);
1788 for (j = 0; j < ann->polylinelist[i].np; j++)
1789 pdc_printf(p->out, "%f %f ", ann->polylinelist[i].p[j].x,
1790 ann->polylinelist[i].p[j].y);
1791 if (ann->atype == ann_ink)
1792 pdc_end_array_c(p->out);
1793 }
1794 pdc_end_array(p->out);
1795 break;
1796
1797 default:
1798 break;
1799 }
1800
1801 switch (ann->atype)
1802 {
1803 /* Destination, Highlight */
1804 case ann_link:
1805 if (ann->dest)
1806 {
1807 pdc_puts(p->out, "/Dest");
1808 pdf_write_destination(p, ann->dest);
1809 }
1810 if (ann->highlight != high_invert)
1811 pdc_printf(p->out, "/H/%s\n",
1812 pdc_get_keyword(ann->highlight, pdf_highlight_pdfkeylist));
1813 break;
1814
1815 /* Line ending styles */
1816 case ann_line:
1817 case ann_polyline:
1818 if (ann->endingstyles[0] != line_none ||
1819 ann->endingstyles[1] != line_none)
1820 pdc_printf(p->out, "/LE[/%s /%s]\n",
1821 pdc_get_keyword(ann->endingstyles[0],
1822 pdf_endingstyles_pdfkeylist),
1823 pdc_get_keyword(ann->endingstyles[1],
1824 pdf_endingstyles_pdfkeylist));
1825 break;
1826
1827 /* border effect dictionary */
1828 case ann_polygon:
1829 if (ann->cloudy > -1)
1830 {
1831 pdc_puts(p->out, "/BE");
1832 pdc_begin_dict(p->out); /* BE dict */
1833 pdc_puts(p->out, "/S/C");
1834 if (ann->cloudy > 0)
1835 pdc_printf(p->out, "/I %f", ann->cloudy);
1836 pdc_end_dict(p->out); /* BE dict */
1837 }
1838
1839 /* rotate */
1840 case ann_stamp:
1841 case ann_freetext:
1842 if (ann->orientate)
1843 pdc_printf(p->out, "/Rotate %d\n", ann->orientate);
1844 break;
1845
1846 default:
1847 break;
1848 }
1849
1850 switch (ann->atype)
1851 {
1852 /* Interior color */
1853 case ann_line:
1854 case ann_polyline:
1855 case ann_square:
1856 case ann_circle:
1857 pdf_write_colorentry(p, "/IC", &ann->interiorcolor);
1858 break;
1859
1860 /* Parent Annotation */
1861 case ann_popup:
1862 if (ann->parentname && *ann->parentname)
1863 {
1864 for (i = 0; i < na; i++)
1865 {
1866 annpar = (pdf_annot *) &pdc_vtr_at(annots, i, pdf_annot);
1867 if (annpar->name != NULL &&
1868 !strcmp(ann->parentname, annpar->name))
1869 {
1870 pdc_objref(p->out, "/Parent", annpar->obj_id);
1871 break;
1872 }
1873 }
1874 }
1875 break;
1876
1877 /* File specification */
1878 case ann_fileattachment:
1879 {
1880 /* see bug #1439 */
1881 const char *basename = pdc_file_strip_dirs(ann->nativefilename);
1882
1883 pdc_puts(p->out, "/FS");
1884 pdc_begin_dict(p->out); /* FS dict */
1885 pdc_puts(p->out, "/Type/Filespec\n");
1886 pdc_puts(p->out, "/F");
1887 pdf_put_pdffilename(p, basename);
1888 pdc_puts(p->out, "\n");
1889 if (p->compatibility >= PDC_1_7)
1890 {
1891 pdc_puts(p->out, "/UF");
1892 pdf_put_pdfunifilename(p, basename);
1893 pdc_puts(p->out, "\n");
1894 }
1895
1896 /* alloc id for the actual embedded file stream */
1897 ann->obj_id = pdc_alloc_id(p->out);
1898 pdc_puts(p->out, "/EF");
1899 pdc_begin_dict(p->out);
1900 pdc_objref(p->out, "/F", ann->obj_id);
1901 pdc_end_dict(p->out);
1902 pdc_end_dict(p->out); /* FS dict */
1903 }
1904 break;
1905
1906
1907 case ann_movie:
1908 {
1909 pdc_puts(p->out, "/Movie");
1910 pdc_begin_dict(p->out); /* Movie dict */
1911
1912 /* File specification */
1913 pdc_puts(p->out, "/F");
1914 pdc_begin_dict(p->out); /* F dict */
1915 pdc_puts(p->out, "/Type/Filespec\n");
1916 pdc_puts(p->out, "/F");
1917 pdf_put_pdffilename(p, ann->nativefilename);
1918 pdc_puts(p->out, "\n");
1919 if (p->compatibility >= PDC_1_7)
1920 {
1921 pdc_puts(p->out, "/UF");
1922 pdf_put_pdfunifilename(p, ann->filename);
1923 pdc_puts(p->out, "\n");
1924 }
1925 pdc_end_dict(p->out); /* F dict */
1926
1927 /* Aspect - not supported by Acrobat */
1928 /* Rotate - doesn't work */
1929
1930 /* Poster */
1931 if (ann->movieposter != movieposter_none)
1932 {
1933 if (ann->movieposter == movieposter_auto)
1934 pdc_puts(p->out, "/Poster true");
1935 else
1936 pdc_objref(p->out, "/Poster", ann->movieposter);
1937 }
1938
1939 pdc_end_dict(p->out); /* Movie dict */
1940
1941 if (ann->soundvolume != 1.0 ||
1942 ann->showcontrols ||
1943 ann->playmode != playmode_once ||
1944 ann->windowscale != 0)
1945 {
1946 pdc_puts(p->out, "/A");
1947 pdc_begin_dict(p->out); /* Activation dict */
1948
1949 /* Start, Duration, Rate, Synchronus - not supported */
1950
1951 /* Volume */
1952 if (ann->soundvolume != 1.0)
1953 pdc_printf(p->out, "/Volume %f\n", ann->soundvolume);
1954
1955 /* ShowControls */
1956 if (ann->showcontrols)
1957 pdc_puts(p->out, "/ShowControls true\n");
1958
1959 /* Mode */
1960 if (ann->playmode != playmode_once)
1961 pdc_printf(p->out, "/Mode/%s\n",
1962 pdc_get_keyword(ann->playmode,
1963 pdf_playmode_pdfkeylist));
1964
1965 /* window */
1966 if (ann->windowscale != 0)
1967 {
1968 int sx, sy;
1969
1970 if (ann->windowscale == PDF_ANN_FULLSCREEN)
1971 {
1972 /* see PDF Reference 1.7, Appendix H, 153. */
1973 sx = 999;
1974 sy = 1;
1975 }
1976 else
1977 {
1978 pdc_scalar sf, sp;
1979
1980 sp = 1;
1981 for (i = 0; ; i++)
1982 {
1983 sf = sp * ann->windowscale;
1984 if (sf == (double) (int) (sf) || i == 5)
1985 break;
1986 sp *= 10;
1987 }
1988
1989 sx = (int) sf;
1990 sy = (int) sp;
1991 }
1992
1993 /* FWScale */
1994 pdc_printf(p->out, "/FWScale[%d %d]\n", sx, sy);
1995
1996 /* FWPosition */
1997 if (ann->windowposition[0] != 50.0 ||
1998 ann->windowposition[1] != 50.0)
1999 {
2000 pdc_printf(p->out, "/FWPosition[%f %f]\n",
2001 ann->windowposition[0] / 100.0,
2002 1.0 - ann->windowposition[1] / 100.0);
2003 }
2004 }
2005
2006 pdc_end_dict(p->out); /* Activation dict */
2007 }
2008 }
2009 break;
2010
2011 default:
2012 break;
2013 }
2014
2015
2016 pdc_end_dict(p->out); /* Annotation dict */
2017 pdc_end_obj(p->out); /* Annotation object */
2018 }
2019
2020 /* Write the actual embedded files with preallocated ids */
2021 for (k = 0; k < na; k++)
2022 {
2023 ann = (pdf_annot *) &pdc_vtr_at(annots, k, pdf_annot);
2024 if (ann->atype == ann_fileattachment)
2025 pdf_embed_file(p, ann->obj_id, ann->filename, ann->mimetype,
2026 ann->filesize);
2027 }
2028 }
2029
2030 /*****************************************************************************/
2031 /** deprecated historical annotation functions **/
2032 /*****************************************************************************/
2033
2034 void
pdf_create_link(PDF * p,const char * type,pdc_scalar llx,pdc_scalar lly,pdc_scalar urx,pdc_scalar ury,const char * annopts,const char * utext,int len)2035 pdf_create_link(
2036 PDF *p,
2037 const char *type,
2038 pdc_scalar llx,
2039 pdc_scalar lly,
2040 pdc_scalar urx,
2041 pdc_scalar ury,
2042 const char *annopts,
2043 const char *utext,
2044 int len)
2045 {
2046 static const char *fn = "pdf_create_link";
2047 char *optlist;
2048 char *name;
2049 int acthdl;
2050
2051 name = pdf_convert_name(p, utext, len, PDC_CONV_WITHBOM);
2052 optlist = (char *) pdc_malloc(p->pdc, strlen(name) + 80, fn);
2053
2054 if (!pdc_stricmp(type, "URI"))
2055 strcpy(optlist, "url {");
2056 else if (!pdc_stricmp(type, "GoTo"))
2057 strcpy(optlist, "destname {");
2058 else if (!pdc_stricmp(type, "GoToR"))
2059 strcpy(optlist, "destination {page 1} filename {");
2060 strcat(optlist, name);
2061 strcat(optlist, "}");
2062
2063 acthdl = pdf__create_action(p, type, optlist);
2064 if (acthdl > -1)
2065 {
2066 if (p->pdc->hastobepos) acthdl++;
2067 pdc_sprintf(p->pdc, pdc_false, optlist,
2068 "action {activate %d} usercoordinates ", acthdl);
2069 strcat(optlist, annopts);
2070 pdf__create_annotation(p, llx, lly, urx, ury, "Link", optlist);
2071 }
2072
2073 pdc_free(p->pdc, optlist);
2074 pdc_free(p->pdc, name);
2075 }
2076
2077 void
pdf_init_annot_params(PDF * p)2078 pdf_init_annot_params(PDF *p)
2079 {
2080 /* annotation border style defaults */
2081 p->border_style = border_solid;
2082 p->border_width = 1;
2083 p->border_red = 0;
2084 p->border_green = 0;
2085 p->border_blue = 0;
2086 p->border_dash1 = 3;
2087 p->border_dash2 = 3;
2088
2089 /* auxiliary function parameters */
2090 p->launchlink_parameters = NULL;
2091 p->launchlink_operation = NULL;
2092 p->launchlink_defaultdir = NULL;
2093 }
2094
2095 void
pdf_cleanup_annot_params(PDF * p)2096 pdf_cleanup_annot_params(PDF *p)
2097 {
2098 if (p->launchlink_parameters)
2099 {
2100 pdc_free(p->pdc, p->launchlink_parameters);
2101 p->launchlink_parameters = NULL;
2102 }
2103
2104 if (p->launchlink_operation)
2105 {
2106 pdc_free(p->pdc, p->launchlink_operation);
2107 p->launchlink_operation = NULL;
2108 }
2109
2110 if (p->launchlink_defaultdir)
2111 {
2112 pdc_free(p->pdc, p->launchlink_defaultdir);
2113 p->launchlink_defaultdir = NULL;
2114 }
2115 }
2116
2117 static void
pdf_insert_annot_params(PDF * p,pdf_annot * ann)2118 pdf_insert_annot_params(PDF *p, pdf_annot *ann)
2119 {
2120 ann->borderstyle = p->border_style;
2121 ann->linewidth = (int) p->border_width;
2122 ann->annotcolor.type = (int) color_rgb;
2123 ann->annotcolor.value[0] = p->border_red;
2124 ann->annotcolor.value[1] = p->border_green;
2125 ann->annotcolor.value[2] = p->border_blue;
2126 ann->annotcolor.value[3] = 0;
2127 ann->dasharray[0] = p->border_dash1;
2128 ann->dasharray[1] = p->border_dash2;
2129 }
2130
2131 void
pdf__attach_file(PDF * p,pdc_scalar llx,pdc_scalar lly,pdc_scalar urx,pdc_scalar ury,const char * filename,int len_filename,const char * description,int len_descr,const char * author,int len_auth,const char * mimetype,const char * icon)2132 pdf__attach_file(
2133 PDF *p,
2134 pdc_scalar llx,
2135 pdc_scalar lly,
2136 pdc_scalar urx,
2137 pdc_scalar ury,
2138 const char *filename,
2139 int len_filename,
2140 const char *description,
2141 int len_descr,
2142 const char *author,
2143 int len_auth,
2144 const char *mimetype,
2145 const char *icon)
2146 {
2147 pdc_file *attfile;
2148 pdf_annot *ann;
2149 pdf_attach_iconnames icontype = icon_attach_pushpin;
2150
2151 filename = pdf_convert_filename(p, filename, len_filename, "filename",
2152 PDC_CONV_WITHBOM);
2153
2154 if (icon != NULL && *icon)
2155 {
2156 int k = pdc_get_keycode_ci(icon, pdf_attach_iconnames_pdfkeylist);
2157 if (k == PDC_KEY_NOTFOUND)
2158 pdc_error(p->pdc, PDC_E_ILLARG_STRING, "icon", icon, 0, 0);
2159 icontype = (pdf_attach_iconnames) k;
2160 }
2161
2162 attfile = pdc_fsearch_fopen(p->pdc, filename, NULL, "attachment ", 0);
2163 if (attfile == NULL)
2164 pdc_error(p->pdc, -1, 0, 0, 0, 0);
2165
2166 pdc_lock_pvf(p->pdc, filename);
2167 pdc_fclose(attfile);
2168
2169 /* fill up annotation struct */
2170 ann = pdf_new_annot(p, ann_fileattachment);
2171 ann->zoom = pdc_false;
2172 ann->rotate = pdc_false;
2173 pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
2174 pdf_insert_annot_params(p, ann);
2175 ann->filename = pdc_strdup(p->pdc, filename);
2176 ann->nativefilename = pdc_strdup(p->pdc, filename);
2177 ann->filesize = pdf_check_file(p, ann->filename, pdc_true);
2178 ann->contents = pdf_convert_hypertext_depr(p, description, len_descr);
2179 ann->title = pdf_convert_hypertext_depr(p, author, len_auth);
2180 if (mimetype != NULL && mimetype)
2181 ann->mimetype = pdc_strdup(p->pdc, mimetype);
2182 if (icontype != icon_attach_pushpin)
2183 ann->iconname =
2184 pdc_get_keyword(icontype, pdf_attach_iconnames_pdfkeylist);
2185 }
2186
2187 void
pdf__add_note(PDF * p,pdc_scalar llx,pdc_scalar lly,pdc_scalar urx,pdc_scalar ury,const char * contents,int len_cont,const char * title,int len_title,const char * icon,int kopen)2188 pdf__add_note(
2189 PDF *p,
2190 pdc_scalar llx,
2191 pdc_scalar lly,
2192 pdc_scalar urx,
2193 pdc_scalar ury,
2194 const char *contents,
2195 int len_cont,
2196 const char *title,
2197 int len_title,
2198 const char *icon,
2199 int kopen)
2200 {
2201 pdf_annot *ann;
2202 pdf_text_iconnames icontype = icon_text_note;
2203
2204 if (icon != NULL && *icon)
2205 {
2206 int k = pdc_get_keycode_ci(icon, pdf_text_iconnames_pdfkeylist);
2207 if (k == PDC_KEY_NOTFOUND)
2208 pdc_error(p->pdc, PDC_E_ILLARG_STRING, "icon", icon, 0, 0);
2209 icontype = (pdf_text_iconnames) k;
2210 }
2211
2212 /* fill up annotation struct */
2213 ann = pdf_new_annot(p, ann_text);
2214 pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
2215 pdf_insert_annot_params(p, ann);
2216 ann->contents = pdf_convert_hypertext_depr(p, contents, len_cont);
2217 ann->title = pdf_convert_hypertext_depr(p, title, len_title);
2218 if (icontype != icon_text_note)
2219 ann->iconname = pdc_get_keyword(icontype,pdf_text_iconnames_pdfkeylist);
2220 ann->open = kopen;
2221 ann->display = disp_noprint;
2222 }
2223
2224 void
pdf__add_pdflink(PDF * p,pdc_scalar llx,pdc_scalar lly,pdc_scalar urx,pdc_scalar ury,const char * filename,int page,const char * optlist)2225 pdf__add_pdflink(
2226 PDF *p,
2227 pdc_scalar llx,
2228 pdc_scalar lly,
2229 pdc_scalar urx,
2230 pdc_scalar ury,
2231 const char *filename,
2232 int page,
2233 const char *optlist)
2234 {
2235 static const char *fn = "pdf__add_pdflink";
2236 char *actoptlist, *sopt;
2237 pdf_annot *ann;
2238 int acthdl;
2239 size_t size;
2240
2241 if (filename == NULL || *filename == '\0')
2242 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "filename", 0, 0, 0);
2243
2244 if (optlist == NULL)
2245 optlist = "";
2246
2247 size = strlen(filename) + strlen(optlist) + 80;
2248 actoptlist = (char *) pdc_malloc(p->pdc, size, fn);
2249
2250 /* creating a GoToR action */
2251 actoptlist[0] = 0;
2252 sopt = actoptlist;
2253 sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "filename {%s} ", filename);
2254 sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "destination {%s page %d} ",
2255 optlist, page);
2256 acthdl = pdf__create_action(p, "GoToR", actoptlist);
2257
2258 /* fill up annotation struct */
2259 if (acthdl > -1)
2260 {
2261 ann = pdf_new_annot(p, ann_link);
2262 pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
2263 pdf_insert_annot_params(p, ann);
2264 if (p->pdc->hastobepos) acthdl++;
2265 pdc_sprintf(p->pdc, pdc_false, actoptlist, "activate %d", acthdl);
2266 ann->action = pdc_strdup(p->pdc, actoptlist);
2267 ann->display = disp_noprint;
2268 }
2269
2270 pdc_free(p->pdc, actoptlist);
2271 }
2272
2273 void
pdf__add_launchlink(PDF * p,pdc_scalar llx,pdc_scalar lly,pdc_scalar urx,pdc_scalar ury,const char * filename)2274 pdf__add_launchlink(
2275 PDF *p,
2276 pdc_scalar llx,
2277 pdc_scalar lly,
2278 pdc_scalar urx,
2279 pdc_scalar ury,
2280 const char *filename)
2281 {
2282 static const char *fn = "pdf__add_launchlink";
2283 char *actoptlist, *sopt;
2284 pdf_annot *ann;
2285 int acthdl;
2286 size_t size;
2287
2288 if (filename == NULL || *filename == '\0')
2289 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "filename", 0, 0, 0);
2290 size = strlen(filename) + 80;
2291 if (p->launchlink_parameters)
2292 size += strlen(p->launchlink_parameters);
2293 if (p->launchlink_operation)
2294 size += strlen(p->launchlink_operation);
2295 if (p->launchlink_defaultdir)
2296 size += strlen(p->launchlink_defaultdir);
2297 actoptlist = (char *) pdc_malloc(p->pdc, size, fn);
2298
2299 /* creating a Launch action */
2300 actoptlist[0] = 0;
2301 sopt = actoptlist;
2302 sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "filename {%s} ", filename);
2303 if (p->launchlink_parameters)
2304 {
2305 sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "parameters {%s} ",
2306 p->launchlink_parameters);
2307 pdc_free(p->pdc, p->launchlink_parameters);
2308 p->launchlink_parameters = NULL;
2309 }
2310 if (p->launchlink_operation)
2311 {
2312 sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "operation {%s} ",
2313 p->launchlink_operation);
2314 pdc_free(p->pdc, p->launchlink_operation);
2315 p->launchlink_operation = NULL;
2316 }
2317 if (p->launchlink_defaultdir)
2318 {
2319 sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "defaultdir {%s} ",
2320 p->launchlink_defaultdir);
2321 pdc_free(p->pdc, p->launchlink_defaultdir);
2322 p->launchlink_defaultdir = NULL;
2323 }
2324 acthdl = pdf__create_action(p, "Launch", actoptlist);
2325
2326 /* fill up annotation struct */
2327 if (acthdl > -1)
2328 {
2329 ann = pdf_new_annot(p, ann_link);
2330 pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
2331 pdf_insert_annot_params(p, ann);
2332 if (p->pdc->hastobepos) acthdl++;
2333 pdc_sprintf(p->pdc, pdc_false, actoptlist, "activate %d", acthdl);
2334 ann->action = pdc_strdup(p->pdc, actoptlist);
2335 ann->display = disp_noprint;
2336 }
2337
2338 pdc_free(p->pdc, actoptlist);
2339 }
2340
2341 void
pdf__add_locallink(PDF * p,pdc_scalar llx,pdc_scalar lly,pdc_scalar urx,pdc_scalar ury,int page,const char * optlist)2342 pdf__add_locallink(
2343 PDF *p,
2344 pdc_scalar llx,
2345 pdc_scalar lly,
2346 pdc_scalar urx,
2347 pdc_scalar ury,
2348 int page,
2349 const char *optlist)
2350 {
2351 pdf_annot *ann;
2352
2353 /* fill up annotation struct */
2354 ann = pdf_new_annot(p, ann_link);
2355 pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
2356 pdf_insert_annot_params(p, ann);
2357 ann->dest = pdf_parse_destination_optlist(p, optlist, page, pdf_locallink);
2358 ann->display = disp_noprint;
2359 }
2360
2361 void
pdf__add_weblink(PDF * p,pdc_scalar llx,pdc_scalar lly,pdc_scalar urx,pdc_scalar ury,const char * url)2362 pdf__add_weblink(
2363 PDF *p,
2364 pdc_scalar llx,
2365 pdc_scalar lly,
2366 pdc_scalar urx,
2367 pdc_scalar ury,
2368 const char *url)
2369 {
2370 static const char *fn = "pdf__add_weblink";
2371 char *actoptlist;
2372 pdf_annot *ann;
2373 int acthdl;
2374
2375 if (url == NULL || *url == '\0')
2376 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "url", 0, 0, 0);
2377 actoptlist = (char *) pdc_malloc(p->pdc, strlen(url) + 80, fn);
2378
2379 /* creating a URI action */
2380 pdc_sprintf(p->pdc, pdc_false, actoptlist, "url {%s} ", url);
2381 acthdl = pdf__create_action(p, "URI", actoptlist);
2382
2383 /* fill up annotation struct */
2384 if (acthdl > -1)
2385 {
2386 ann = pdf_new_annot(p, ann_link);
2387 pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL);
2388 pdf_insert_annot_params(p, ann);
2389 if (p->pdc->hastobepos) acthdl++;
2390 pdc_sprintf(p->pdc, pdc_false, actoptlist, "activate %d", acthdl);
2391 ann->action = pdc_strdup(p->pdc, actoptlist);
2392 ann->display = disp_noprint;
2393 }
2394
2395 pdc_free(p->pdc, actoptlist);
2396 }
2397
2398 void
pdf__set_border_style(PDF * p,const char * style,pdc_scalar width)2399 pdf__set_border_style(PDF *p, const char *style, pdc_scalar width)
2400 {
2401 int k;
2402
2403 p->border_style = border_solid;
2404 if (style)
2405 {
2406 k = pdc_get_keycode_ci(style, pdf_borderstyle_keylist);
2407 if (k == PDC_KEY_NOTFOUND)
2408 pdc_error(p->pdc, PDC_E_ILLARG_STRING, "style", style, 0, 0);
2409 p->border_style = (pdf_borderstyle) k;
2410 }
2411
2412 pdc_check_number_limits(p->pdc, "width", width, 0.0, PDC_FLOAT_MAX);
2413
2414 p->border_width = width;
2415 }
2416
2417 void
pdf__set_border_color(PDF * p,pdc_scalar red,pdc_scalar green,pdc_scalar blue)2418 pdf__set_border_color(PDF *p, pdc_scalar red, pdc_scalar green, pdc_scalar blue)
2419 {
2420 pdc_check_number_limits(p->pdc, "red", red, 0.0, 1.0);
2421 pdc_check_number_limits(p->pdc, "green", green, 0.0, 1.0);
2422 pdc_check_number_limits(p->pdc, "blue", blue, 0.0, 1.0);
2423
2424 p->border_red = red;
2425 p->border_green = green;
2426 p->border_blue = blue;
2427 }
2428
2429 void
pdf__set_border_dash(PDF * p,pdc_scalar b,pdc_scalar w)2430 pdf__set_border_dash(PDF *p, pdc_scalar b, pdc_scalar w)
2431 {
2432 pdc_check_number_limits(p->pdc, "b", b, 0.0, PDC_FLOAT_MAX);
2433 pdc_check_number_limits(p->pdc, "w", w, 0.0, PDC_FLOAT_MAX);
2434
2435 p->border_dash1 = b;
2436 p->border_dash2 = w;
2437 }
2438