campo-sirio/pdf/pdflib/p_annots.c

1915 lines
56 KiB
C
Raw Normal View History

/*---------------------------------------------------------------------------*
| PDFlib - A library for generating PDF on the fly |
+---------------------------------------------------------------------------+
| Copyright (c) 1997-2005 Thomas Merz and PDFlib GmbH. All rights reserved. |
+---------------------------------------------------------------------------+
| |
| This software is subject to the PDFlib license. It is NOT in the |
| public domain. Extended versions and commercial licenses are |
| available, please check http://www.pdflib.com. |
| |
*---------------------------------------------------------------------------*/
/* $Id: p_annots.c,v 1.1 2006-05-04 16:36:51 brugno Exp $
*
* PDFlib routines for annnotations
*
*/
#define P_ANNOTS_C
#include "p_intern.h"
#include "p_color.h"
#include "p_font.h"
/* annotation types */
typedef enum
{
ann_text = (1<<0),
ann_link = (1<<1),
ann_freetext = (1<<2),
ann_line = (1<<3),
ann_square = (1<<4),
ann_circle = (1<<5),
ann_highlight = (1<<6),
ann_underline = (1<<7),
ann_squiggly = (1<<8),
ann_strikeout = (1<<9),
ann_stamp = (1<<10),
ann_ink = (1<<11),
ann_polygon = (1<<12),
ann_polyline = (1<<13),
ann_popup = (1<<14),
ann_fileattachment = (1<<15)
}
pdf_annottype;
static const pdc_keyconn pdf_annottype_pdfkeylist[] =
{
{"Text", ann_text},
{"Link", ann_link},
{"FreeText", ann_freetext},
{"Line", ann_line},
{"Square", ann_square},
{"Circle", ann_circle},
{"Highlight", ann_highlight},
{"Underline", ann_underline},
{"Squiggly", ann_squiggly},
{"StrikeOut", ann_strikeout},
{"Stamp", ann_stamp},
{"Polygon", ann_polygon},
{"PolyLine", ann_polyline},
{"Ink", ann_ink},
{"Popup", ann_popup},
{"FileAttachment", ann_fileattachment},
{NULL, 0}
};
static const pdc_keyconn pdf_polyline_pdfkeylist[] =
{
{"QuadPoints", ann_highlight},
{"QuadPoints", ann_underline},
{"QuadPoints", ann_squiggly},
{"QuadPoints", ann_strikeout},
{"InkList", ann_ink},
{"Vertices", ann_polygon},
{"Vertices", ann_polyline},
{NULL, 0}
};
/* flags for annotation dictionary entries */
typedef enum
{
anndict_a = (1<<0),
anndict_bs = (1<<1),
anndict_c = (1<<2),
anndict_contents = (1<<3),
anndict_f = (1<<4),
anndict_fs = (1<<5),
anndict_h = (1<<6),
anndict_ic = (1<<7),
anndict_inklist = (1<<8),
anndict_l = (1<<9),
anndict_le = (1<<10),
anndict_name = (1<<11),
anndict_nm = (1<<12),
anndict_open = (1<<13),
anndict_parent = (1<<14),
anndict_popup = (1<<15),
anndict_q = (1<<16),
anndict_quadpoints = (1<<17),
anndict_rect = (1<<18),
anndict_subtype = (1<<19),
anndict_t = (1<<20),
anndict_vertices = (1<<21)
}
pdf_anndictentries;
static const pdc_keyconn pdf_perm_entries_pdfkeylist[] =
{
{"Contents", anndict_contents},
{"Name", anndict_name},
{"NM", anndict_nm},
{"Open", anndict_open},
{NULL, 0}
};
static const pdc_keyconn pdf_forb_entries_pdfkeylist[] =
{
{"A", anndict_a},
{"BS", anndict_bs},
{"C", anndict_c},
{"F", anndict_f},
{"FS", anndict_fs},
{"H", anndict_h},
{"IC", anndict_ic},
{"InkList", anndict_inklist},
{"L", anndict_l},
{"LE", anndict_le},
{"Parent", anndict_parent},
{"Popup", anndict_popup},
{"Q", anndict_q},
{"QuadPoints", anndict_quadpoints},
{"Rect", anndict_rect},
{"Subtype", anndict_subtype},
{"T", anndict_t},
{"Vertices", anndict_vertices},
{NULL, 0}
};
/* line ending styles */
typedef enum
{
line_none,
line_square,
line_circle,
line_diamond,
line_openarrow,
line_closedarrow
}
pdf_endingstyles;
static const pdc_keyconn pdf_endingstyles_pdfkeylist[] =
{
{"None", line_none},
{"Square", line_square},
{"Circle", line_circle},
{"Diamond", line_diamond},
{"OpenArrow", line_openarrow},
{"ClosedArrow", line_closedarrow},
{NULL, 0}
};
/* text icon names */
typedef enum
{
icon_text_comment,
icon_text_help,
icon_text_key,
icon_text_insert,
icon_text_newparagraph,
icon_text_note,
icon_text_paragraph
}
pdf_text_iconnames;
static const pdc_keyconn pdf_text_iconnames_pdfkeylist[] =
{
{"Comment", icon_text_comment},
{"Help", icon_text_help},
{"Key", icon_text_key},
{"Insert", icon_text_insert},
{"NewParagraph", icon_text_newparagraph},
{"Note", icon_text_note},
{"Paragraph", icon_text_paragraph},
{NULL, 0}
};
/* stamp icon names */
typedef enum
{
icon_stamp_approved,
icon_stamp_asls,
icon_stamp_confidential,
icon_stamp_departmental,
icon_stamp_draft,
icon_stamp_experimental,
icon_stamp_expired,
icon_stamp_final,
icon_stamp_forcomment,
icon_stamp_forpublicrelease,
icon_stamp_notapproved,
icon_stamp_notforpublicrelease,
icon_stamp_sold,
icon_stamp_topsecret
}
pdf_stamp_iconnames;
static const pdc_keyconn pdf_stamp_iconnames_pdfkeylist[] =
{
{"Approved", icon_stamp_approved},
{"AsIs", icon_stamp_asls},
{"Confidential", icon_stamp_confidential},
{"Departmental", icon_stamp_departmental},
{"Draft", icon_stamp_draft},
{"Experimental", icon_stamp_experimental},
{"Expired", icon_stamp_expired},
{"Final", icon_stamp_final},
{"ForComment", icon_stamp_forcomment},
{"ForPublicRelease", icon_stamp_forpublicrelease},
{"NotApproved", icon_stamp_notapproved},
{"NotForPublicRelease", icon_stamp_notforpublicrelease},
{"Sold", icon_stamp_sold},
{"TopSecret", icon_stamp_topsecret},
{NULL, 0}
};
/* file attachment icon names */
typedef enum
{
icon_attach_graph,
icon_attach_paperclip,
icon_attach_pushpin,
icon_attach_tag
}
pdf_attach_iconnames;
static const pdc_keyconn pdf_attach_iconnames_pdfkeylist[] =
{
{"Graph", icon_attach_graph},
{"Paperclip", icon_attach_paperclip},
{"PushPin", icon_attach_pushpin},
{"Tag", icon_attach_tag},
{NULL, 0}
};
static const pdc_defopt pdf_create_annot_options[] =
{
{"annotwarning", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
0.0, 0.0, NULL},
{"usercoordinates", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
0.0, 0.0, NULL},
{"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1,
0.0, PDF_MAX_NAMESTRING, NULL},
{"custom", pdc_stringlist, PDC_OPT_NONE, 1, 64,
0.0, PDF_MAXSTRINGSIZE, NULL},
{"name", pdc_stringlist, PDC_OPT_NONE, 1, 1,
0.0, PDF_MAXSTRINGSIZE, NULL},
{"parentname", pdc_stringlist, PDC_OPT_NONE, 1, 1,
0.0, PDF_MAXSTRINGSIZE, NULL},
{"popup", pdc_stringlist, PDC_OPT_NONE, 1, 1,
0.0, PDF_MAXSTRINGSIZE, NULL},
{"title", pdc_stringlist, PDC_OPT_NONE, 1, 1,
0.0, PDF_MAXSTRINGSIZE, NULL},
{"subject", pdc_stringlist, PDC_OPT_PDC_1_5, 1, 1,
0.0, PDF_MAXSTRINGSIZE, NULL},
{"annotcolor", pdc_stringlist, PDC_OPT_NONE, 1, 5,
0.0, PDF_MAX_NAMESTRING, NULL},
{"borderstyle", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
0.0, 0.0, pdf_borderstyle_keylist},
{"dasharray", pdc_scalarlist, PDC_OPT_NONE, 1, 2,
PDC_FLOAT_PREC, PDC_FLOAT_MAX, NULL},
{"linewidth", pdc_integerlist, PDC_OPT_NONE, 1, 1,
0.0, PDC_USHRT_MAX, NULL},
{"opacity", pdc_scalarlist, PDC_OPT_PDC_1_4 | PDC_OPT_PERCENT, 1, 1,
0.0, 1.0, NULL},
{"highlight", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
0.0, 0.0, pdf_highlight_keylist},
{"display", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
0.0, 0.0, pdf_display_keylist},
{"zoom", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
0.0, 0.0, NULL},
{"rotate", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
0.0, 0.0, NULL},
{"readonly", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
0.0, 0.0, NULL},
{"locked", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1,
0.0, 0.0, NULL},
{"open", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1,
0.0, 0.0, NULL},
{"createdate", pdc_booleanlist, PDC_OPT_PDC_1_5, 1, 1,
0.0, 0.0, NULL},
{"fillcolor", pdc_stringlist, PDC_OPT_NONE, 2, 5,
0.0, PDF_MAX_NAMESTRING, NULL},
{"alignment", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
0.0, 0.0, pdf_quadding_keylist},
{"font", pdc_fonthandle, PDC_OPT_NONE, 1, 1,
0.0, 0.0, NULL},
{"fontsize", pdc_scalarlist, PDC_OPT_NONE, 1, 1,
0.0, PDC_FLOAT_MAX, NULL},
{"contents", pdc_stringlist, PDC_OPT_NONE, 1, 1,
0.0, PDF_MAXSTRINGSIZE, NULL},
{"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1,
0.0, PDF_MAXSTRINGSIZE, NULL},
{"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1,
0.0, PDF_MAXSTRINGSIZE, NULL},
{"filename", pdc_stringlist, PDC_OPT_NONE, 1, 1,
1.0, PDF_FILENAMELEN, NULL},
{"mimetype", pdc_stringlist, PDC_OPT_NONE, 1, 1,
0.0, PDF_MAX_NAMESTRING, NULL},
{"iconname", pdc_stringlist, PDC_OPT_NONE, 1, 1,
0.0, PDF_MAX_NAMESTRING, NULL},
{"endingstyles", pdc_keywordlist, PDC_OPT_NONE, 2, 2,
0.0, 0.0, pdf_endingstyles_pdfkeylist},
{"interiorcolor", pdc_stringlist, PDC_OPT_NONE, 1, 5,
0.0, PDF_MAX_NAMESTRING, NULL},
{"cloudy", pdc_scalarlist, PDC_OPT_PDC_1_5, 1, 1,
0.0, 2.0, NULL},
{"line", pdc_scalarlist, PDC_OPT_NONE, 4, 4,
PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},
{"polylinelist", pdc_stringlist, PDC_OPT_NONE, 1, PDF_MAXARRAYSIZE,
7.0, PDF_MAXSTRINGSIZE, NULL},
{"action", pdc_stringlist, PDC_OPT_NONE, 1, 1,
0.0, PDF_MAXSTRINGSIZE, NULL},
PDC_OPT_TERMINATE
};
/* Annotation member */
struct pdf_annot_s
{
pdc_id obj_id;
pdf_annot *next;
pdf_annottype atype;
int mask;
pdc_rectangle rect;
pdc_bool usercoordinates;
pdc_encoding hypertextencoding;
pdf_coloropt annotcolor;
pdf_coloropt interiorcolor;
pdf_coloropt fillcolor;
int linewidth;
pdc_scalar opacity;
pdf_borderstyle borderstyle;
pdc_scalar dasharray[2];
pdf_highlight highlight;
pdf_display display;
pdc_bool zoom;
pdc_bool rotate;
pdc_bool kreadonly;
pdc_bool locked;
pdc_bool open;
pdc_bool createdate;
int font;
pdc_scalar fontsize;
pdf_quadding alignment;
pdf_endingstyles endingstyles[2];
pdc_scalar cloudy;
pdf_dest *dest;
char *name;
char *parentname;
char *popup;
char *title;
char *subject;
char *contents;
char *filename;
char *mimetype;
const char *iconname;
pdc_scalar *line;
pdc_polyline *polylinelist;
int nplines;
char **custom;
int ncustoms;
char *action;
};
static pdf_annot *
pdf_init_annot(PDF *p, pdf_annottype atype)
{
static const char fn[] = "pdf_init_annot";
pdf_annot *ann = (pdf_annot *) pdc_malloc(p->pdc, sizeof(pdf_annot), fn);
/* Initialize with PDF default values */
ann->obj_id = PDC_BAD_ID;
ann->next = NULL;
ann->atype = atype;
ann->mask = 0;
ann->usercoordinates = p->usercoordinates;
ann->hypertextencoding = p->hypertextencoding;
ann->annotcolor.type = (int) color_none;
ann->interiorcolor.type = (int) color_none;
pdf_init_coloropt(&ann->fillcolor);
ann->linewidth = 1;
ann->opacity = 1;
ann->borderstyle = border_solid;
ann->dasharray[0] = 3;
ann->dasharray[1] = 3;
ann->highlight = high_invert;
ann->display = disp_visible;
ann->zoom = pdc_true;
ann->rotate = pdc_true;
ann->kreadonly = pdc_false;
ann->locked = pdc_false;
ann->open = pdc_false;
ann->createdate = pdc_false;
ann->font = -1;
ann->fontsize = 0;
ann->alignment = text_left;
ann->cloudy = -1;
ann->endingstyles[0] = line_none;
ann->endingstyles[1] = line_none;
ann->dest = NULL;
ann->name = NULL;
ann->parentname = NULL;
ann->popup = NULL;
ann->title = NULL;
ann->subject = NULL;
ann->contents = NULL;
ann->filename = NULL;
ann->mimetype = NULL;
ann->iconname = NULL;
ann->line = NULL;
ann->polylinelist = NULL;
ann->nplines = 0;
ann->custom = NULL;
ann->ncustoms = 0;
ann->action = NULL;
return ann;
}
static void
pdf_init_rectangle(PDF *p, pdf_annot *ann, pdc_bool usercoordinates,
pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury)
{
pdc_check_number(p->pdc, "llx", llx);
pdc_check_number(p->pdc, "lly", lly);
pdc_check_number(p->pdc, "urx", urx);
pdc_check_number(p->pdc, "ury", ury);
pdc_rect_init(&ann->rect, (pdc_scalar) llx, (pdc_scalar) lly,
(pdc_scalar) urx, (pdc_scalar) ury);
if (usercoordinates == pdc_true)
pdc_rect_transform(&p->curr_ppt->gstate[p->curr_ppt->sl].ctm,
&ann->rect, &ann->rect);
}
static pdf_annot *
pdf_add_annot(PDF *p, pdf_annottype atype)
{
pdf_annot *ann, *prev = pdf_get_annots_list(p);
ann = pdf_init_annot(p, atype);
if (prev == NULL)
pdf_set_annots_list(p, ann);
else
{
while (prev->next != NULL)
prev = prev->next;
prev->next = ann;
}
return ann;
}
static pdf_annot *
pdf_cleanup_annot(PDF *p, pdf_annot *ann)
{
pdf_annot *next = ann->next;
int i;
pdf_cleanup_destination(p, ann->dest);
ann->dest = NULL;
if (ann->name)
{
pdc_free(p->pdc, ann->name);
ann->name = NULL;
}
if (ann->parentname)
{
pdc_free(p->pdc, ann->parentname);
ann->parentname = NULL;
}
if (ann->popup)
{
pdc_free(p->pdc, ann->popup);
ann->popup = NULL;
}
if (ann->title)
{
pdc_free(p->pdc, ann->title);
ann->title = NULL;
}
if (ann->subject)
{
pdc_free(p->pdc, ann->subject);
ann->subject = NULL;
}
if (ann->contents)
{
pdc_free(p->pdc, ann->contents);
ann->contents = NULL;
}
if (ann->filename)
{
pdc_free(p->pdc, ann->filename);
ann->filename = NULL;
}
if (ann->mimetype)
{
pdc_free(p->pdc, ann->mimetype);
ann->mimetype = NULL;
}
if (ann->line)
{
pdc_free(p->pdc, ann->line);
ann->line = NULL;
}
if (ann->polylinelist)
{
for (i = 0; i < ann->nplines; i++)
pdc_free(p->pdc, ann->polylinelist[i].p);
pdc_free(p->pdc, ann->polylinelist);
ann->polylinelist = NULL;
}
if (ann->custom)
{
pdc_cleanup_optstringlist(p->pdc, ann->custom, ann->ncustoms);
ann->custom = NULL;
ann->ncustoms = 0;
}
if (ann->action)
{
pdc_free(p->pdc, ann->action);
ann->action = NULL;
}
pdc_free(p->pdc, ann);
return next;
}
static const pdc_keyconn pdf_keytype_keylist[] =
{
{"boolean", pdc_booleanlist},
{"name", pdc_keywordlist},
{"string", pdc_stringlist},
{NULL, 0}
};
static const pdc_defopt pdf_custom_list_options[] =
{
{"key", pdc_stringlist, PDC_OPT_REQUIRED, 1, 1,
1.0, PDF_MAX_NAMESTRING, NULL},
{"type", pdc_keywordlist, PDC_OPT_REQUIRED, 1, 1,
0.0, 0.0, pdf_keytype_keylist},
{"value", pdc_stringlist, PDC_OPT_REQUIRED, 1, 1,
1.0, PDF_MAXSTRINGSIZE, NULL},
PDC_OPT_TERMINATE
};
static void
pdf_parse_and_write_annot_customlist(PDF *p, pdf_annot *ann, pdc_bool output)
{
int i;
/* custom entries */
for (i = 0; i < ann->ncustoms; i++)
{
pdc_resopt *resopts = NULL;
const char *stemp;
const char *keyword;
char **strlist = NULL;
char *string;
int inum;
resopts = pdc_parse_optionlist(p->pdc, ann->custom[i],
pdf_custom_list_options, NULL, pdc_true);
keyword = "key";
pdc_get_optvalues(keyword, resopts, NULL, &strlist);
string = strlist[0];
inum = pdc_get_keycode(string, pdf_forb_entries_pdfkeylist);
if (inum != PDC_KEY_NOTFOUND)
{
stemp = pdc_errprintf(p->pdc, "%.*s", PDC_ET_MAXSTRLEN, string);
pdc_error(p->pdc, PDF_E_ANN_ILLCUSTOMKEY, stemp, 0, 0, 0);
}
inum = pdc_get_keycode(string, pdf_perm_entries_pdfkeylist);
if (inum != PDC_KEY_NOTFOUND)
ann->mask |= inum;
if (output)
pdc_printf(p->out, "/%s", string);
keyword = "type";
pdc_get_optvalues(keyword, resopts, &inum, NULL);
keyword = "value";
pdc_get_optvalues(keyword, resopts, NULL, &strlist);
string = strlist[0];
switch (inum)
{
case pdc_booleanlist:
if (pdc_stricmp(string, "true") && pdc_stricmp(string, "false"))
{
stemp = pdc_errprintf(p->pdc, "%.*s", PDC_ET_MAXSTRLEN, string);
pdc_error(p->pdc, PDC_E_OPT_ILLBOOLEAN, keyword, stemp, 0, 0);
}
if (output)
pdc_printf(p->out, " %s",
PDC_BOOLSTR(pdc_stricmp(string, "false")));
break;
case pdc_keywordlist:
if (output)
pdc_printf(p->out, "/%s", string);
break;
case pdc_stringlist:
pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
pdc_true, NULL, &string, NULL);
if (output)
pdf_put_hypertext(p, string);
break;
}
if (output)
pdc_puts(p->out, "\n");
}
}
static void
pdf_opt_alrdef(PDF *p, const char *keyword, pdf_annot *ann, int flag)
{
if (ann->mask & flag)
pdc_error(p->pdc, PDF_E_ANN_OPTALRDEF, keyword, 0, 0, 0);
}
static int
pdf_opt_effectless(PDF *p, const char *keyword, pdf_annottype curratype,
pdf_annottype intendatypes, pdc_bool verbose)
{
if ((pdf_annottype) !(intendatypes & curratype))
{
const char *type = pdc_get_keyword(curratype, pdf_annottype_pdfkeylist);
if (verbose)
pdc_warning(p->pdc, PDF_E_ANN_OPTEFFLESS_FORTYPE, keyword, type,
0, 0);
return 1;
}
return 0;
}
void
pdf__create_annotation(PDF *p,
pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury,
const char *type, const char *optlist)
{
static const char fn[] = "PDF_create_annotation";
pdc_resopt *resopts = NULL;
pdc_clientdata data;
pdf_annottype atype;
pdf_annot *ann;
pdf_dest *dest = NULL;
const char *keyword, *keyword_s = NULL;
char **strlist = NULL, **plstring = NULL;
pdc_scalar *line;
pdc_encoding enc = pdc_invalidenc;
pdc_bool verbose = pdc_true;
int errcode = 0;
int i, j, k, ns, np, nss[2];
pdf_ppt *ppt = p->curr_ppt;
pdc_check_number(p->pdc, "llx", llx);
pdc_check_number(p->pdc, "lly", lly);
pdc_check_number(p->pdc, "urx", urx);
pdc_check_number(p->pdc, "ury", ury);
if (type == NULL || *type == '\0')
pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0);
k = pdc_get_keycode_ci(type, pdf_annottype_pdfkeylist);
if (k == PDC_KEY_NOTFOUND)
pdc_error(p->pdc, PDC_E_ILLARG_STRING, "type", type, 0, 0);
atype = (pdf_annottype) k;
/* compatibility */
if (p->compatibility < PDC_1_5 &&
(atype == ann_polygon || atype == ann_polyline))
{
pdc_error(p->pdc, PDC_E_PAR_VERSION, type,
pdc_get_pdfversion(p->pdc, PDC_1_5), 0, 0);
}
/* Parsing option list */
pdf_set_clientdata(p, &data);
resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_create_annot_options,
&data, pdc_true);
keyword = "annotwarning";
pdc_get_optvalues(keyword, resopts, &verbose, NULL);
/* Initializing */
ann = pdf_add_annot(p, atype);
keyword = "usercoordinates";
pdc_get_optvalues(keyword, resopts, &ann->usercoordinates, NULL);
/* Set widget rectangle */
pdc_rect_init(&ann->rect, llx, lly, urx, ury);
if (ann->usercoordinates == pdc_true)
pdc_rect_transform(&ppt->gstate[ppt->sl].ctm, &ann->rect, &ann->rect);
ann->hypertextencoding =
pdf_get_hypertextencoding_opt(p, resopts, NULL, verbose);
keyword = "custom";
ns = pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
pdc_true, NULL, NULL, &ann->custom);
if (ns)
{
pdc_save_lastopt(resopts, PDC_OPT_SAVEALL);
ann->ncustoms = ns;
pdf_parse_and_write_annot_customlist(p, ann, pdc_false);
}
keyword = "name";
if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
{
pdf_opt_alrdef(p, keyword, ann, anndict_nm);
ann->name = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
}
keyword = "parentname";
if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
ann->parentname = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
keyword = "popup";
if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
ann->popup = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
keyword = "title";
if (pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
pdc_true, NULL, &ann->title, NULL))
pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
keyword = "subject";
if (pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
pdc_true, NULL, &ann->subject, NULL))
pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
keyword = "annotcolor";
ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
if (ns)
pdf_parse_coloropt(p, keyword, strlist, ns, (int) color_rgb,
&ann->annotcolor);
keyword = "borderstyle";
if (pdc_get_optvalues(keyword, resopts, &ns, NULL))
ann->borderstyle = (pdf_borderstyle) ns;
keyword = "dasharray";
ns = pdc_get_optvalues(keyword, resopts, ann->dasharray, NULL);
if (ns)
{
if (ns == 1)
ann->dasharray[1] = ann->dasharray[0];
if (verbose && ann->borderstyle != border_dashed)
pdc_warning(p->pdc, PDC_E_OPT_IGNORED, keyword, 0, 0, 0);
}
keyword = "linewidth";
pdc_get_optvalues(keyword, resopts, &ann->linewidth, NULL);
keyword = "opacity";
pdc_get_optvalues(keyword, resopts, &ann->opacity, NULL);
keyword = "highlight";
if (pdc_get_optvalues(keyword, resopts, &ns, NULL))
{
pdf_opt_effectless(p, keyword, atype, ann_link, verbose);
ann->highlight = (pdf_highlight) ns;
}
keyword = "display";
if (pdc_get_optvalues(keyword, resopts, &ann->display, NULL))
ann->display = (pdf_display) ns;
keyword = "zoom";
pdc_get_optvalues(keyword, resopts, &ann->zoom, NULL);
keyword = "rotate";
pdc_get_optvalues(keyword, resopts, &ann->rotate, NULL);
keyword = "readonly";
pdc_get_optvalues(keyword, resopts, &ann->kreadonly, NULL);
keyword = "locked";
pdc_get_optvalues(keyword, resopts, &ann->locked, NULL);
keyword = "open";
if (pdc_get_optvalues(keyword, resopts, &ann->open, NULL))
{
pdf_opt_alrdef(p, keyword, ann, anndict_open);
pdf_opt_effectless(p, keyword, atype,
(pdf_annottype) (ann_text | ann_popup), verbose);
}
keyword = "createdate";
pdc_get_optvalues(keyword, resopts, &ann->createdate, NULL);
keyword = "fillcolor";
ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
if (ns && !pdf_opt_effectless(p, keyword, atype, ann_freetext, verbose))
pdf_parse_coloropt(p, keyword, strlist, ns, (int) color_cmyk,
&ann->fillcolor);
keyword = "alignment";
if (pdc_get_optvalues(keyword, resopts, &ns, NULL))
ann->alignment = (pdf_quadding) ns;
keyword = "font";
if (pdc_get_optvalues(keyword, resopts, &ann->font, NULL))
pdf_opt_effectless(p, keyword, atype, ann_freetext, verbose);
keyword = "fontsize";
if (pdc_get_optvalues(keyword, resopts, &ann->fontsize, NULL))
{
pdf_opt_effectless(p, keyword, atype, ann_freetext, verbose);
if (ann->usercoordinates == pdc_true)
ann->fontsize = pdc_transform_scalar(&ppt->gstate[ppt->sl].ctm,
ann->fontsize);
}
keyword = "contents";
if (atype == ann_freetext)
{
enc = pdc_invalidenc;
if (ann->font > -1)
enc = p->fonts[ann->font].encoding;
pdf_get_opt_textlist(p, keyword, resopts, enc,
pdc_false, NULL, &ann->contents, NULL);
}
else
{
pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding,
pdc_true, NULL, &ann->contents, NULL);
}
if (ann->contents)
{
pdf_opt_alrdef(p, keyword, ann, anndict_contents);
pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
}
keyword = "destination";
if (pdc_get_optvalues(keyword, resopts, NULL, &strlist) &&
!pdf_opt_effectless(p, keyword, atype, ann_link, verbose))
{
ann->dest = pdf_parse_destination_optlist(p, strlist[0], 0,
pdf_locallink, verbose);
keyword_s = keyword;
}
else
{
keyword = "destname";
if (atype == ann_link)
dest = pdf_get_option_destname(p, resopts, ann->hypertextencoding);
else if (pdc_get_optvalues(keyword, resopts, NULL, NULL))
pdf_opt_effectless(p, keyword, atype, ann_link, verbose);
if (dest)
{
ann->dest = dest;
keyword_s = keyword;
}
}
keyword = "filename";
if (pdc_get_optvalues(keyword, resopts, NULL, NULL) &&
!pdf_opt_effectless(p, keyword, atype, ann_fileattachment, verbose))
ann->filename = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
keyword = "mimetype";
if (pdc_get_optvalues(keyword, resopts, NULL, NULL) &&
!pdf_opt_effectless(p, keyword, atype, ann_fileattachment, verbose))
ann->mimetype = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
keyword = "iconname";
if (pdc_get_optvalues(keyword, resopts, NULL, &strlist) &&
!pdf_opt_effectless(p, keyword, atype,
(pdf_annottype) (ann_text | ann_stamp | ann_fileattachment),
verbose))
{
const pdc_keyconn *kc = pdf_text_iconnames_pdfkeylist;
pdf_opt_alrdef(p, keyword, ann, anndict_name);
if (atype == ann_stamp)
kc = pdf_stamp_iconnames_pdfkeylist;
else if (atype == ann_fileattachment)
kc = pdf_attach_iconnames_pdfkeylist;
ann->iconname = pdc_get_int_keyword(strlist[0], kc);
if (ann->iconname == NULL)
pdc_error(p->pdc, PDC_E_OPT_ILLKEYWORD, keyword, strlist[0],
0, 0);
}
keyword = "endingstyles";
if (pdc_get_optvalues(keyword, resopts, nss, NULL))
{
ann->endingstyles[0] = (pdf_endingstyles) nss[0];
ann->endingstyles[1] = (pdf_endingstyles) nss[1];
pdf_opt_effectless(p, keyword, atype,
(pdf_annottype) (ann_line | ann_polyline),
verbose);
}
keyword = "interiorcolor";
ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
if (ns && !pdf_opt_effectless(p, keyword, atype,
(pdf_annottype) (ann_line | ann_polyline |
ann_square | ann_circle), verbose))
pdf_parse_coloropt(p, keyword, strlist, ns, (int) color_rgb,
&ann->interiorcolor);
keyword = "cloudy";
if (pdc_get_optvalues(keyword, resopts, &ann->cloudy, NULL))
pdf_opt_effectless(p, keyword, atype, ann_polygon, verbose);
keyword = "line";
ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
if (ns && !pdf_opt_effectless(p, keyword, atype, ann_line, verbose))
{
line = (pdc_scalar *) strlist;
if (ann->usercoordinates == pdc_true)
{
pdc_transform_point(&ppt->gstate[ppt->sl].ctm,
line[0], line[1], &line[0], &line[1]);
pdc_transform_point(&ppt->gstate[ppt->sl].ctm,
line[2], line[3], &line[2], &line[3]);
}
ann->line = (pdc_scalar *) pdc_save_lastopt(resopts, PDC_OPT_SAVEALL);
}
keyword = "polylinelist";
ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist);
if (ns)
{
if (!pdf_opt_effectless(p, keyword, atype,
(pdf_annottype) (ann_ink | ann_polygon | ann_polyline |
ann_highlight | ann_underline |
ann_squiggly | ann_strikeout), verbose))
{
ann->polylinelist = (pdc_polyline *)
pdc_calloc(p->pdc, ns * sizeof(pdc_polyline), fn);
ann->nplines = ns;
for (i = 0; i < ns; i++)
{
pdc_polyline *pl = &ann->polylinelist[i];
np = pdc_split_stringlist(p->pdc, strlist[i], "\f\n\r\t\v ",
&plstring);
if (np < 4 || np % 2 ||
(atype != ann_ink && atype != ann_polygon &&
atype != ann_polyline && np != 8))
{
errcode = PDF_E_ANN_BADNUMCOORD;
goto PDF_ANN_ERROR;
}
pl->np = np / 2;
pl->p = (pdc_vector *)
pdc_malloc(p->pdc, pl->np * sizeof(pdc_vector), fn);
for (j = 0, k = 0; j < pl->np; j++, k++)
{
if (pdc_str2double(plstring[k], &pl->p[j].x) == pdc_false)
{
errcode = PDC_E_OPT_ILLNUMBER;
goto PDF_ANN_ERROR;
}
k++;
if (pdc_str2double(plstring[k], &pl->p[j].y) == pdc_false)
{
errcode = PDC_E_OPT_ILLNUMBER;
goto PDF_ANN_ERROR;
}
if (ann->usercoordinates == pdc_true)
pdc_transform_vector(&ppt->gstate[ppt->sl].ctm,
&pl->p[j], NULL);
}
pdc_cleanup_stringlist(p->pdc, plstring);
}
}
PDF_ANN_ERROR:
if (errcode)
{
pdc_cleanup_stringlist(p->pdc, plstring);
pdc_error(p->pdc, errcode, keyword, 0, 0, 0);
}
}
keyword = "action";
if (pdc_get_optvalues(keyword, resopts, NULL, &strlist))
{
if (ann->dest)
{
pdf_cleanup_destination(p, ann->dest);
ann->dest = NULL;
if (verbose)
pdc_warning(p->pdc, PDC_E_OPT_IGNORE, keyword_s, keyword, 0, 0);
}
/* parsing of action list */
pdf_parse_and_write_actionlist(p, event_annotation, NULL,
(const char *) strlist[0]);
ann->action = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
}
/* required options */
keyword = NULL;
if (ann->contents == NULL && atype != ann_link && atype != ann_popup)
keyword = "contents";
if (ann->fontsize == 0 && atype == ann_freetext)
keyword = "fontsize";
if (ann->font == -1 && atype == ann_freetext)
keyword = "font";
if (ann->filename == NULL && atype == ann_fileattachment)
keyword = "filename";
if (ann->line == NULL && atype == ann_line)
keyword = "line";
if (ann->polylinelist == NULL &&
(atype == ann_ink || atype == ann_polygon || atype == ann_polyline))
keyword = "polylinelist";
if (keyword)
pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, keyword, 0, 0, 0);
if (atype == ann_freetext)
{
pdc_font *font_s = &p->fonts[ann->font];
const char *fontname =
pdc_errprintf(p->pdc, "%.*s", PDC_ET_MAXSTRLEN, font_s->name);
if (!strcmp(pdf_get_pdf_fontname(font_s), fontname))
pdc_error(p->pdc, PDF_E_ANN_NOSTDFONT, fontname, 0, 0, 0);
}
}
pdc_id
pdf_write_annots_root(PDF *p, pdf_annot *annotlist, pdf_widget *widgetlist)
{
pdf_annot *ann;
pdc_id result = PDC_BAD_ID;
/* Annotations array */
if (annotlist || widgetlist)
{
result = pdc_begin_obj(p->out, PDC_NEW_ID);
pdc_begin_array(p->out);
for (ann = annotlist; ann != NULL; ann = ann->next)
{
ann->obj_id = pdc_alloc_id(p->out);
pdc_objref_c(p->out, ann->obj_id);
}
(void) widgetlist;
pdc_end_array(p->out);
pdc_end_obj(p->out);
}
return result;
}
#define BUFSIZE 256
static void
pdf_write_defappstring(PDF *p, pdf_annot *ann)
{
char buf[BUFSIZE], *bufc;
pdf_coloropt *fs;
int ct;
if (ann->font == -1)
return;
bufc = buf;
/* font and fontsize */
bufc += pdc_sprintf(p->pdc, pdc_true, bufc, "/%s %f Tf",
pdf_get_pdf_fontname(&p->fonts[ann->font]),
ann->fontsize);
/* fill and stroke color */
fs = &ann->fillcolor;
ct = fs->type;
switch (ct)
{
case color_gray:
bufc += pdc_sprintf(p->pdc, pdc_true, bufc, " %f g",
fs->value[0]);
break;
case color_rgb:
bufc += pdc_sprintf(p->pdc, pdc_true, bufc, " %f %f %f rg",
fs->value[0], fs->value[1], fs->value[2]);
break;
case color_cmyk:
bufc += pdc_sprintf(p->pdc, pdc_true, bufc, " %f %f %f %f k",
fs->value[0], fs->value[1],
fs->value[2], fs->value[3]);
break;
}
pdc_puts(p->out, "/DA");
pdf_put_hypertext(p, buf);
pdc_puts(p->out, "\n");
}
void
pdf_write_page_annots(PDF *p, pdf_annot *list)
{
pdf_annot *ann, *annpar;
pdc_id act_idlist[PDF_MAX_EVENTS];
int i, j, flags;
for (ann = list; ann != NULL; ann = ann->next)
{
/* write action objects */
if (ann->action)
pdf_parse_and_write_actionlist(p, event_annotation, act_idlist,
(const char *) ann->action);
pdc_begin_obj(p->out, ann->obj_id); /* Annotation object */
pdc_begin_dict(p->out); /* Annotation dict */
pdc_puts(p->out, "/Type/Annot\n");
pdc_printf(p->out, "/Subtype/%s\n",
pdc_get_keyword(ann->atype, pdf_annottype_pdfkeylist));
/* Contents */
if (ann->contents)
{
pdc_puts(p->out, "/Contents");
if (ann->atype == ann_freetext)
pdf_put_fieldtext(p, ann->contents, ann->font);
else
pdf_put_hypertext(p, ann->contents);
pdc_puts(p->out, "\n");
}
/* Current Page */
pdc_objref(p->out, "/P", pdf_get_page_id(p, 0));
/* Rectangle */
pdc_printf(p->out, "/Rect[%f %f %f %f]\n",
ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury);
/* Name */
if (ann->name)
{
pdc_puts(p->out, "/NM");
pdf_put_hypertext(p, ann->name);
pdc_puts(p->out, "\n");
}
/* Flags */
flags = 0;
if (ann->display != disp_noprint)
{
flags = (1<<2);
flags |= ann->display;
}
if (!ann->zoom)
flags |= (1<<3);
if (!ann->rotate)
flags |= (1<<4);
if (ann->kreadonly)
flags |= (1<<6);
if (ann->locked)
flags |= (1<<7);
if (flags)
pdc_printf(p->out, "/F %d\n", flags);
/* Border style dictionary */
if (ann->linewidth != 1 || ann->borderstyle != border_solid)
{
pdc_puts(p->out, "/BS");
pdc_begin_dict(p->out); /* BS dict */
pdc_printf(p->out, "/W %d", ann->linewidth);
pdc_printf(p->out, "/S/%s",
pdc_get_keyword(ann->borderstyle, pdf_borderstyle_pdfkeylist));
if (ann->borderstyle == border_dashed)
pdc_printf(p->out, "/D[%f %f]",
ann->dasharray[0], ann->dasharray[1]);
pdc_end_dict(p->out); /* BS dict */
/* Write the Border key in old-style PDF 1.1 format
* because of a bug in PDF 1.4 and earlier
*/
pdc_printf(p->out, "/Border[0 0 %f", (double) ann->linewidth);
if (ann->borderstyle == border_dashed)
pdc_printf(p->out, "[%f %f]",
ann->dasharray[0], ann->dasharray[1]);
pdc_puts(p->out, "]\n");
}
/* Annotation color */
if (ann->annotcolor.type != (int) color_none)
{
pdc_printf(p->out, "/C[%f %f %f]\n", ann->annotcolor.value[0],
ann->annotcolor.value[1], ann->annotcolor.value[2]);
}
/* Title */
if (ann->title && *ann->title)
{
pdc_puts(p->out, "/T");
pdf_put_hypertext(p, ann->title);
pdc_puts(p->out, "\n");
}
/* Subject */
if (ann->subject && *ann->subject)
{
pdc_puts(p->out, "/Subj");
pdf_put_hypertext(p, ann->subject);
pdc_puts(p->out, "\n");
}
/* Popup */
if (ann->popup && *ann->popup)
{
for (annpar = list;
annpar != NULL && annpar != ann;
annpar = annpar->next)
{
if (!strcmp(ann->popup, annpar->name))
{
pdc_objref(p->out, "/Popup", annpar->obj_id);
break;
}
}
}
/* Icon Name */
if (ann->iconname && *ann->iconname)
pdc_printf(p->out, "/Name/%s\n", ann->iconname);
/* CreationDate */
if (ann->createdate)
{
char time_str[PDC_TIME_SBUF_SIZE];
pdc_get_timestr(time_str);
pdc_puts(p->out, "/CreationDate ");
pdf_put_hypertext(p, time_str);
pdc_puts(p->out, "\n");
}
/* Opacity */
if (ann->opacity != 1)
pdc_printf(p->out, "/CA %f\n", ann->opacity);
/* write Action entries */
if (ann->action)
pdf_write_action_entries(p, event_annotation, act_idlist);
/* custom entries */
pdf_parse_and_write_annot_customlist(p, ann, pdc_true);
switch (ann->atype)
{
/* Open */
case ann_text:
case ann_popup:
if (ann->open)
pdc_puts(p->out, "/Open true\n");
break;
/* Alignment, Default appearance string */
case ann_freetext:
if (ann->alignment != text_left)
pdc_printf(p->out, "/Q %d\n", ann->alignment);
pdf_write_defappstring(p, ann);
break;
/* Destination, Highlight */
case ann_link:
if (ann->dest)
{
pdc_puts(p->out, "/Dest");
pdf_write_destination(p, ann->dest);
}
if (ann->highlight != high_invert)
pdc_printf(p->out, "/H/%s\n",
pdc_get_keyword(ann->highlight, pdf_highlight_pdfkeylist));
break;
/* Line */
case ann_line:
pdc_printf(p->out, "/L[%f %f %f %f]\n",
ann->line[0], ann->line[1], ann->line[2], ann->line[3]);
break;
/* InkList, QuadPoints and Vertices */
case ann_highlight:
case ann_underline:
case ann_squiggly:
case ann_strikeout:
case ann_ink:
case ann_polygon:
case ann_polyline:
pdc_printf(p->out, "/%s",
pdc_get_keyword(ann->atype, pdf_polyline_pdfkeylist));
pdc_begin_array(p->out);
for (i = 0; i < ann->nplines; i++)
{
if (ann->atype == ann_ink)
pdc_begin_array(p->out);
for (j = 0; j < ann->polylinelist[i].np; j++)
pdc_printf(p->out, "%f %f ", ann->polylinelist[i].p[j].x,
ann->polylinelist[i].p[j].y);
if (ann->atype == ann_ink)
pdc_end_array_c(p->out);
}
pdc_end_array(p->out);
break;
default:
break;
}
switch (ann->atype)
{
/* Line ending styles */
case ann_line:
case ann_polyline:
if (ann->endingstyles[0] != line_none ||
ann->endingstyles[1] != line_none)
pdc_printf(p->out, "/LE[/%s /%s]\n",
pdc_get_keyword(ann->endingstyles[0],
pdf_endingstyles_pdfkeylist),
pdc_get_keyword(ann->endingstyles[1],
pdf_endingstyles_pdfkeylist));
break;
/* border effect dictionary */
case ann_polygon:
if (ann->cloudy > -1)
{
pdc_puts(p->out, "/BE");
pdc_begin_dict(p->out); /* BE dict */
pdc_puts(p->out, "/S/C");
if (ann->cloudy > 0)
pdc_printf(p->out, "/I %f", ann->cloudy);
pdc_end_dict(p->out); /* BE dict */
}
default:
break;
}
switch (ann->atype)
{
/* Interior color */
case ann_line:
case ann_polyline:
case ann_square:
case ann_circle:
if (ann->interiorcolor.type != (int) color_none)
{
pdc_printf(p->out, "/IC[%f %f %f]\n",
ann->interiorcolor.value[0],
ann->interiorcolor.value[1],
ann->interiorcolor.value[2]);
}
break;
/* Parent Annotation */
case ann_popup:
if (ann->parentname && *ann->parentname)
{
for (annpar = list;
annpar != NULL && annpar != ann;
annpar = annpar->next)
{
if (!strcmp(ann->parentname, annpar->name))
{
pdc_objref(p->out, "/Parent", annpar->obj_id);
break;
}
}
}
break;
/* File specification */
case ann_fileattachment:
{
pdc_puts(p->out, "/FS");
pdc_begin_dict(p->out); /* FS dict */
pdc_puts(p->out, "/Type/Filespec\n");
pdc_puts(p->out, "/F");
pdf_put_pdffilename(p, ann->filename);
pdc_puts(p->out, "\n");
/* alloc id for the actual embedded file stream */
ann->obj_id = pdc_alloc_id(p->out);
pdc_puts(p->out, "/EF");
pdc_begin_dict(p->out);
pdc_objref(p->out, "/F", ann->obj_id);
pdc_end_dict(p->out);
pdc_end_dict(p->out); /* FS dict */
}
break;
default:
break;
}
pdc_end_dict(p->out); /* Annotation dict */
pdc_end_obj(p->out); /* Annotation object */
}
/* Write the actual embedded files with preallocated ids */
for (ann = list; ann != NULL; ann = ann->next)
{
pdc_id length_id;
PDF_data_source src;
if (ann->atype != ann_fileattachment)
continue;
pdc_begin_obj(p->out, ann->obj_id); /* EmbeddedFile */
pdc_puts(p->out, "<</Type/EmbeddedFile\n");
if (ann->mimetype && *ann->mimetype)
{
pdc_puts(p->out, "/Subtype");
pdf_put_pdfname(p, ann->mimetype);
pdc_puts(p->out, "\n");
}
if (pdc_get_compresslevel(p->out))
pdc_puts(p->out, "/Filter/FlateDecode\n");
length_id = pdc_alloc_id(p->out);
pdc_objref(p->out, "/Length", length_id);
pdc_end_dict(p->out); /* F dict */
/* write the file in the PDF */
src.private_data = (void *) ann->filename;
src.init = pdf_data_source_file_init;
src.fill = pdf_data_source_file_fill;
src.terminate = pdf_data_source_file_terminate;
src.length = (long) 0;
src.offset = (long) 0;
pdf_copy_stream(p, &src, pdc_true); /* embedded file stream */
pdc_end_obj(p->out); /* EmbeddedFile object */
pdc_put_pdfstreamlength(p->out, length_id);
if (p->flush & pdf_flush_content)
pdc_flush_stream(p->out);
}
}
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)
{
char optlist[2048];
char *name;
int acthdl;
if (!pdc_stricmp(type, "URI"))
strcpy(optlist, "url {");
else if (!pdc_stricmp(type, "GoTo"))
strcpy(optlist, "destname {");
else if (!pdc_stricmp(type, "GoToR"))
strcpy(optlist, "destination {page 1} filename {");
name = pdf_convert_name(p, utext, len, pdc_true);
strcat(optlist, name);
pdc_free(p->pdc, name);
strcat(optlist, "}");
acthdl = pdf__create_action(p, type, optlist);
if (acthdl > -1)
{
if (p->hastobepos) acthdl++;
pdc_sprintf(p->pdc, pdc_false, optlist,
"action {activate %d} usercoordinates ", acthdl);
strcat(optlist, annopts);
pdf__create_annotation(p, llx, lly, urx, ury, "Link", optlist);
}
}
void
pdf_cleanup_page_annots(PDF *p, pdf_annot *list)
{
while (list != (pdf_annot *) NULL)
list = pdf_cleanup_annot(p, list);
pdf_set_annots_list(p, NULL);
}
/*****************************************************************************/
/** deprecated historical annotation functions **/
/*****************************************************************************/
void
pdf_init_annot_params(PDF *p)
{
/* annotation border style defaults */
p->border_style = border_solid;
p->border_width = 1;
p->border_red = 0;
p->border_green = 0;
p->border_blue = 0;
p->border_dash1 = 3;
p->border_dash2 = 3;
/* auxiliary function parameters */
p->launchlink_parameters = NULL;
p->launchlink_operation = NULL;
p->launchlink_defaultdir = NULL;
}
void
pdf_cleanup_annot_params(PDF *p)
{
if (p->launchlink_parameters)
{
pdc_free(p->pdc, p->launchlink_parameters);
p->launchlink_parameters = NULL;
}
if (p->launchlink_operation)
{
pdc_free(p->pdc, p->launchlink_operation);
p->launchlink_operation = NULL;
}
if (p->launchlink_defaultdir)
{
pdc_free(p->pdc, p->launchlink_defaultdir);
p->launchlink_defaultdir = NULL;
}
}
static void
pdf_insert_annot_params(PDF *p, pdf_annot *ann)
{
ann->borderstyle = p->border_style;
ann->linewidth = (int) p->border_width;
ann->annotcolor.type = (int) color_rgb;
ann->annotcolor.value[0] = p->border_red;
ann->annotcolor.value[1] = p->border_green;
ann->annotcolor.value[2] = p->border_blue;
ann->annotcolor.value[3] = 0;
ann->dasharray[0] = p->border_dash1;
ann->dasharray[1] = p->border_dash2;
}
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)
{
pdc_file *attfile;
pdf_annot *ann;
pdf_attach_iconnames icontype = icon_attach_pushpin;
filename = pdf_convert_filename(p, filename, len_filename, "filename",
pdc_true);
if (icon != NULL && *icon)
{
int k = pdc_get_keycode_ci(icon, pdf_attach_iconnames_pdfkeylist);
if (k == PDC_KEY_NOTFOUND)
pdc_error(p->pdc, PDC_E_ILLARG_STRING, "icon", icon, 0, 0);
icontype = (pdf_attach_iconnames) k;
}
if ((attfile = pdf_fopen(p, filename, "attachment ", 0)) == NULL)
pdc_error(p->pdc, -1, 0, 0, 0, 0);
pdf_lock_pvf(p, filename);
pdc_fclose(attfile);
/* fill up annotation struct */
ann = pdf_add_annot(p, ann_fileattachment);
pdf_init_rectangle(p, ann, p->usercoordinates, llx, lly, urx, ury);
pdf_insert_annot_params(p, ann);
ann->filename = pdc_strdup(p->pdc, filename);
ann->contents = pdf_convert_hypertext_depr(p, description, len_descr);
ann->title = pdf_convert_hypertext_depr(p, author, len_auth);
if (mimetype != NULL && mimetype)
ann->mimetype = pdc_strdup(p->pdc, mimetype);
if (icontype != icon_attach_pushpin)
ann->iconname =
pdc_get_keyword(icontype, pdf_attach_iconnames_pdfkeylist);
ann->zoom = pdc_false;
ann->rotate = pdc_false;
}
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 open)
{
pdf_annot *ann;
pdf_text_iconnames icontype = icon_text_note;
if (icon != NULL && *icon)
{
int k = pdc_get_keycode_ci(icon, pdf_text_iconnames_pdfkeylist);
if (k == PDC_KEY_NOTFOUND)
pdc_error(p->pdc, PDC_E_ILLARG_STRING, "icon", icon, 0, 0);
icontype = (pdf_text_iconnames) k;
}
/* fill up annotation struct */
ann = pdf_add_annot(p, ann_text);
pdf_init_rectangle(p, ann, p->usercoordinates, llx, lly, urx, ury);
pdf_insert_annot_params(p, ann);
ann->contents = pdf_convert_hypertext_depr(p, contents, len_cont);
ann->title = pdf_convert_hypertext_depr(p, title, len_title);
if (icontype != icon_text_note)
ann->iconname = pdc_get_keyword(icontype,pdf_text_iconnames_pdfkeylist);
ann->open = open;
ann->display = disp_noprint;
}
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)
{
char actoptlist[2048], *sopt;
pdf_annot *ann;
int acthdl;
if (filename == NULL || *filename == '\0')
pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "filename", 0, 0, 0);
/* creating a GoToR action */
actoptlist[0] = 0;
sopt = actoptlist;
sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "filename {%s} ", filename);
if (optlist == NULL) optlist = "";
sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "destination {%s page %d} ",
optlist, page);
acthdl = pdf__create_action(p, "GoToR", actoptlist);
/* fill up annotation struct */
if (acthdl > -1)
{
ann = pdf_add_annot(p, ann_link);
pdf_init_rectangle(p, ann, p->usercoordinates, llx, lly, urx, ury);
pdf_insert_annot_params(p, ann);
if (p->hastobepos) acthdl++;
pdc_sprintf(p->pdc, pdc_false, actoptlist, "activate %d", acthdl);
ann->action = pdc_strdup(p->pdc, actoptlist);
ann->display = disp_noprint;
}
}
void
pdf__add_launchlink(
PDF *p,
pdc_scalar llx,
pdc_scalar lly,
pdc_scalar urx,
pdc_scalar ury,
const char *filename)
{
char actoptlist[2048], *sopt;
pdf_annot *ann;
int acthdl;
if (filename == NULL || *filename == '\0')
pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "filename", 0, 0, 0);
/* creating a Launch action */
actoptlist[0] = 0;
sopt = actoptlist;
sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "filename {%s} ", filename);
if (p->launchlink_parameters)
{
sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "parameters {%s} ",
p->launchlink_parameters);
pdc_free(p->pdc, p->launchlink_parameters);
p->launchlink_parameters = NULL;
}
if (p->launchlink_operation)
{
sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "operation {%s} ",
p->launchlink_operation);
pdc_free(p->pdc, p->launchlink_operation);
p->launchlink_operation = NULL;
}
if (p->launchlink_defaultdir)
{
sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "defaultdir {%s} ",
p->launchlink_defaultdir);
pdc_free(p->pdc, p->launchlink_defaultdir);
p->launchlink_defaultdir = NULL;
}
acthdl = pdf__create_action(p, "Launch", actoptlist);
/* fill up annotation struct */
if (acthdl > -1)
{
ann = pdf_add_annot(p, ann_link);
pdf_init_rectangle(p, ann, p->usercoordinates, llx, lly, urx, ury);
pdf_insert_annot_params(p, ann);
if (p->hastobepos) acthdl++;
pdc_sprintf(p->pdc, pdc_false, actoptlist, "activate %d", acthdl);
ann->action = pdc_strdup(p->pdc, actoptlist);
ann->display = disp_noprint;
}
}
void
pdf__add_locallink(
PDF *p,
pdc_scalar llx,
pdc_scalar lly,
pdc_scalar urx,
pdc_scalar ury,
int page,
const char *optlist)
{
pdf_annot *ann;
/* fill up annotation struct */
ann = pdf_add_annot(p, ann_link);
pdf_init_rectangle(p, ann, p->usercoordinates, llx, lly, urx, ury);
pdf_insert_annot_params(p, ann);
ann->dest =
pdf_parse_destination_optlist(p, optlist, page, pdf_locallink, pdc_true);
ann->display = disp_noprint;
}
void
pdf__add_weblink(
PDF *p,
pdc_scalar llx,
pdc_scalar lly,
pdc_scalar urx,
pdc_scalar ury,
const char *url)
{
char actoptlist[2048];
pdf_annot *ann;
int acthdl;
if (url == NULL || *url == '\0')
pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "url", 0, 0, 0);
/* creating a URI action */
pdc_sprintf(p->pdc, pdc_false, actoptlist, "url {%s} ", url);
acthdl = pdf__create_action(p, "URI", actoptlist);
/* fill up annotation struct */
if (acthdl > -1)
{
ann = pdf_add_annot(p, ann_link);
pdf_init_rectangle(p, ann, p->usercoordinates, llx, lly, urx, ury);
pdf_insert_annot_params(p, ann);
if (p->hastobepos) acthdl++;
pdc_sprintf(p->pdc, pdc_false, actoptlist, "activate %d", acthdl);
ann->action = pdc_strdup(p->pdc, actoptlist);
ann->display = disp_noprint;
}
}
void
pdf__set_border_style(PDF *p, const char *style, pdc_scalar width)
{
int k;
p->border_style = border_solid;
if (style)
{
k = pdc_get_keycode_ci(style, pdf_borderstyle_keylist);
if (k == PDC_KEY_NOTFOUND)
pdc_error(p->pdc, PDC_E_ILLARG_STRING, "style", style, 0, 0);
p->border_style = (pdf_borderstyle) k;
}
pdc_check_number_limits(p->pdc, "width", width, 0.0, PDC_FLOAT_MAX);
p->border_width = width;
}
void
pdf__set_border_color(PDF *p, pdc_scalar red, pdc_scalar green, pdc_scalar blue)
{
pdc_check_number_limits(p->pdc, "red", red, 0.0, 1.0);
pdc_check_number_limits(p->pdc, "green", green, 0.0, 1.0);
pdc_check_number_limits(p->pdc, "blue", blue, 0.0, 1.0);
p->border_red = red;
p->border_green = green;
p->border_blue = blue;
}
void
pdf__set_border_dash(PDF *p, pdc_scalar b, pdc_scalar w)
{
pdc_check_number_limits(p->pdc, "b", b, 0.0, PDC_FLOAT_MAX);
pdc_check_number_limits(p->pdc, "w", w, 0.0, PDC_FLOAT_MAX);
p->border_dash1 = b;
p->border_dash2 = w;
}