diff options
Diffstat (limited to 'src/pdflib/pdflib')
68 files changed, 42947 insertions, 0 deletions
diff --git a/src/pdflib/pdflib/p_3d.c b/src/pdflib/pdflib/p_3d.c new file mode 100644 index 0000000..033c834 --- /dev/null +++ b/src/pdflib/pdflib/p_3d.c @@ -0,0 +1,22 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_3d.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib 3D functions routines + * + */ + +#define P_3D_C + +#include "p_intern.h" +#include "p_color.h" + diff --git a/src/pdflib/pdflib/p_actions.c b/src/pdflib/pdflib/p_actions.c new file mode 100644 index 0000000..f3c42fc --- /dev/null +++ b/src/pdflib/pdflib/p_actions.c @@ -0,0 +1,1155 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_actions.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib actions handling routines + * + */ + +#define P_ACTIONS_C + +#include "p_intern.h" +#include "p_layer.h" + +typedef enum +{ + pdf_allact = -1, + pdf_goto = (1<<0), + pdf_gotor = (1<<1), + pdf_launch = (1<<2), + pdf_uri = (1<<3), + pdf_hide = (1<<4), + pdf_named = (1<<5), + pdf_submitform = (1<<6), + pdf_resetform = (1<<7), + pdf_importdata = (1<<8), + pdf_javascript = (1<<9), + pdf_setocgstate = (1<<10), + pdf_trans = (1<<11), + pdf_goto3dview = (1<<12) +} +pdf_actiontype; + +static const pdc_keyconn pdf_action_pdfkeylist[] = +{ + {"GoTo", pdf_goto}, + {"GoToR", pdf_gotor}, + {"Launch", pdf_launch}, + {"URI", pdf_uri}, + {"Hide", pdf_hide}, + {"Named", pdf_named}, + {"SubmitForm", pdf_submitform}, + {"ResetForm", pdf_resetform}, + {"ImportData", pdf_importdata}, + {"JavaScript", pdf_javascript}, + {"SetOCGState", pdf_setocgstate}, + {"Trans", pdf_trans}, + {"GoTo3DView", pdf_goto3dview}, + {NULL, 0} +}; + + +typedef enum +{ + /* values are identical with PDF values */ + pdf_exp_fdf = (1<<1), + pdf_exp_html = (1<<2), + pdf_exp_getrequest = (1<<3), + pdf_exp_coordinates = (1<<4), + pdf_exp_xfdf = (1<<5), + pdf_exp_updates = (1<<6), + pdf_exp_annotfields = (1<<7), + pdf_exp_pdf = (1<<8), + pdf_exp_onlyuser = (1<<10), + pdf_exp_exclurl = (1<<11) +} +pdf_exportmethod; + +/* allowed combinations of exportmethod keywords */ +static pdf_exportmethod pdf_allfdf = (pdf_exportmethod) + (pdf_exp_fdf | + pdf_exp_updates | + pdf_exp_exclurl | + pdf_exp_annotfields | + pdf_exp_onlyuser); + +static pdf_exportmethod pdf_allhtml = (pdf_exportmethod) + (pdf_exp_html | + pdf_exp_getrequest | + pdf_exp_coordinates); + +static pdf_exportmethod pdf_allxfdf = pdf_exp_xfdf; + +static pdf_exportmethod pdf_allpdf = (pdf_exportmethod) + (pdf_exp_pdf | + pdf_exp_getrequest); + +static const pdc_keyconn pdf_exportmethod_keylist[] = +{ + {"fdf", pdf_exp_fdf}, + {"html", pdf_exp_html}, + {"xfdf", pdf_exp_xfdf}, + {"pdf", pdf_exp_pdf}, + {"getrequest", pdf_exp_getrequest}, + {"coordinates", pdf_exp_coordinates}, + {"updates", pdf_exp_updates}, + {"annotfields", pdf_exp_annotfields}, + {"onlyuser", pdf_exp_onlyuser}, + {"exclurl", pdf_exp_exclurl}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_filename_keylist[] = +{ + {"filename", (pdf_actiontype) (pdf_gotor | pdf_launch | pdf_importdata)}, + {"url", (pdf_actiontype) (pdf_uri | pdf_submitform)}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_operation_pdfkeylist[] = +{ + {"open", 1}, + {"print", 2}, + {NULL, 0} +}; + + +static const pdc_keyconn pdf_3dview_keylist[] = +{ + {NULL, 0} +}; + + + +#define PDF_LAYER_FLAG PDC_OPT_UNSUPP + +#define PDF_JAVASCRIPT_FLAG PDC_OPT_UNSUPP +#define PDF_3DVIEW_FLAG PDC_OPT_UNSUPP + +static const pdc_defopt pdf_create_action_options[] = +{ + /* deprecated */ + {"actionwarning", 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}, + + {"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"filename", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_FILENAMELEN, NULL}, + + {"url", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"parameters", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"operation", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, pdf_operation_pdfkeylist}, + + {"defaultdir", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"menuname", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"script", pdc_stringlist, PDF_JAVASCRIPT_FLAG, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"scriptname", pdc_stringlist, PDF_JAVASCRIPT_FLAG, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"namelist", pdc_stringlist, PDC_OPT_NONE, 1, PDF_MAXARRAYSIZE, + 0.0, PDC_USHRT_MAX, NULL}, + + {"exportmethod", pdc_keywordlist, PDC_OPT_BUILDOR, 1, 10, + 0.0, 0.0, pdf_exportmethod_keylist}, + + {"newwindow", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"ismap", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"hide", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"exclude", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"submitemptyfields", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1, + 0.0, 0.0, NULL}, + + {"canonicaldate", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"layerstate", pdc_stringlist, PDF_LAYER_FLAG | PDC_OPT_EVENNUM, 1, 100, + 1.0, 8.0, NULL}, + + {"preserveradio", pdc_booleanlist, PDF_LAYER_FLAG, 1, 1, + 0.0, 0.0, NULL}, + + {"3dview", pdc_3dviewhandle, PDF_3DVIEW_FLAG, 1, 1, + 0.0, 0.0, pdf_3dview_keylist}, + + {"target", pdc_stringlist, PDF_3DVIEW_FLAG, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"transition", pdc_keywordlist, PDC_OPT_PDC_1_5, 1, 1, + 0.0, 0.0, pdf_transition_keylist}, + + {"duration", pdc_scalarlist, PDC_OPT_PDC_1_5, 1, 1, + 0.0, PDC_FLOAT_MAX, NULL}, + + PDF_ERRORPOLICY_OPTION + + PDC_OPT_TERMINATE +}; + +typedef struct pdf_action_s +{ + pdc_id obj_id; + pdf_actiontype atype; + pdf_dest *dest; + pdc_encoding hypertextencoding; + char *filename; + char *parameters; + char *operation; + char *defaultdir; + char *menuname; + char *script; + char *scriptname; + char **namelist; + int nsnames; + pdc_bool newwindow; + pdc_bool ismap; + pdc_bool hide; + pdc_bool exclude; + pdc_bool submitemptyfields; + pdc_bool canonicaldate; + pdf_exportmethod exportmethod; + int transition; + double duration; +} +pdf_action; + +static void +pdf_reclaim_action(void *item) +{ + pdf_action *action = (pdf_action *) item; + + action->obj_id = PDC_BAD_ID; + action->atype = (pdf_actiontype) 0; + action->dest = NULL; + action->hypertextencoding = pdc_invalidenc; + action->filename = NULL; + action->parameters = NULL; + action->operation = NULL; + action->defaultdir = NULL; + action->menuname = NULL; + action->script = NULL; + action->scriptname = NULL; + action->namelist = NULL; + action->nsnames = 0; + action->newwindow = pdc_undef; + action->ismap = pdc_false; + action->hide = pdc_true; + action->exclude = pdc_false; + action->submitemptyfields = pdc_false; + action->canonicaldate = pdc_false; + action->exportmethod = pdf_exp_fdf; + action->transition = (int) trans_replace; + action->duration = 1; +} + +static void +pdf_release_action(void *context, void *item) +{ + PDF *p = (PDF *) context; + pdf_action *action = (pdf_action *) item; + + pdf_cleanup_destination(p, action->dest); + + if (action->filename) + { + pdc_free(p->pdc, action->filename); + action->filename = NULL; + } + + if (action->parameters) + { + pdc_free(p->pdc, action->parameters); + action->parameters = NULL; + } + + if (action->defaultdir) + { + pdc_free(p->pdc, action->defaultdir); + action->defaultdir = NULL; + } + + if (action->menuname) + { + pdc_free(p->pdc, action->menuname); + action->menuname = NULL; + } + + if (action->script) + { + pdc_free(p->pdc, action->script); + action->script = NULL; + } + + if (action->namelist) + { + pdc_cleanup_optstringlist(p->pdc, action->namelist, action->nsnames); + action->namelist = NULL; + } + +} + +static pdc_ced pdf_action_ced = +{ + sizeof(pdf_action), pdf_reclaim_action, pdf_release_action, NULL +}; + +static pdc_vtr_parms pdf_action_parms = +{ + 0, 10, 10 +}; + +static pdf_action * +pdf_new_action(PDF *p) +{ + pdf_action *result; + + if (p->actions == NULL) + p->actions = pdc_vtr_new(p->pdc, &pdf_action_ced, p, &pdf_action_parms); + + result = pdc_vtr_incr(p->actions, pdf_action); + result->hypertextencoding = p->hypertextencoding; + return result; +} + +void +pdf_delete_actions(PDF *p) +{ + if (p->actions != NULL) + { + pdc_vtr_delete(p->actions); + p->actions = NULL; + } +} + +int +pdf_get_max_action(PDF *p) +{ + return (p->actions == NULL) ? -1 : pdc_vtr_size(p->actions) - 1; +} + +static pdc_id pdf_write_action(PDF *p, pdf_action *action, pdc_id next_id); + + +static int +pdf_opt_effectless(PDF *p, const char *keyword, pdf_actiontype curratype, + pdf_actiontype intendatypes) +{ + if ((pdf_actiontype) !(intendatypes & curratype)) + { + const char *type = pdc_get_keyword(curratype, pdf_action_pdfkeylist); + pdc_warning(p->pdc, PDF_E_ACT_OPTIGNORE_FORTYPE, keyword,type, 0, 0); + return 1; + } + return 0; +} + +int +pdf__create_action(PDF *p, const char *type, const char *optlist) +{ + pdc_resopt *resopts = NULL; + pdc_clientdata data; + pdf_action *action; + pdf_actiontype atype; + pdf_dest *dest = NULL; + pdc_bool verbose = pdc_true; + pdc_bool hasdest = pdc_false; + pdc_encoding htenc; + int htcp; + const char *keyword; + char **strlist; + int i, k, ns; + + if (type == NULL || *type == '\0') + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0); + + k = pdc_get_keycode_ci(type, pdf_action_pdfkeylist); + if (k == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_ILLARG_STRING, "type", type, 0, 0); + atype = (pdf_actiontype) k; + + + if (atype == pdf_javascript) + pdc_error(p->pdc, PDF_E_UNSUPP_JAVASCRIPT, 0, 0, 0, 0); + + /* compatibility */ + if (p->compatibility < PDC_1_6 && atype == pdf_goto3dview) + { + pdc_error(p->pdc, PDC_E_PAR_VERSION, type, + pdc_get_pdfversion(p->pdc, PDC_1_6), 0, 0); + } + if (p->compatibility < PDC_1_5 && + (atype == pdf_setocgstate || atype == pdf_trans)) + { + pdc_error(p->pdc, PDC_E_PAR_VERSION, type, + pdc_get_pdfversion(p->pdc, PDC_1_5), 0, 0); + } + + /* new action */ + action = pdf_new_action(p); + action->atype = atype; + + /* Parsing option list */ + pdf_set_clientdata(p, &data); + resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_create_action_options, + &data, pdc_true); + + keyword = "actionwarning"; + pdc_get_optvalues(keyword, resopts, &verbose, NULL); + verbose = pdf_get_errorpolicy(p, resopts, verbose); + + htenc = pdf_get_hypertextencoding_opt(p, resopts, &htcp, pdc_true); + + keyword = "destination"; + if (pdc_get_optvalues(keyword, resopts, NULL, &strlist)) + { + if (!pdf_opt_effectless(p, keyword, atype, + (pdf_actiontype) (pdf_goto | pdf_gotor))) + { + action->dest = pdf_parse_destination_optlist(p, strlist[0], + (atype == pdf_goto) ? 0 : 1, + (atype == pdf_goto) ? pdf_locallink : pdf_remotelink); + hasdest = pdc_true; + } + } + else + { + keyword = "destname"; + if (atype == pdf_goto || atype == pdf_gotor) + dest = pdf_get_option_destname(p, resopts, htenc, htcp); + else if (pdc_get_optvalues(keyword, resopts, NULL, NULL)) + pdf_opt_effectless(p, keyword, atype, + (pdf_actiontype) (pdf_goto | pdf_gotor)); + if (dest) + { + action->dest = dest; + hasdest = pdc_true; + } + } + + /* filename or url */ + for (i = 0; ; i++) + { + keyword = pdf_filename_keylist[i].word; + if (keyword) + { + if (pdc_get_optvalues(keyword, resopts, NULL, &strlist)) + { + if (!pdf_opt_effectless(p, keyword, atype, + (pdf_actiontype) pdf_filename_keylist[i].code)) + { + action->filename = + (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + } + } + } + else + break; + } + + keyword = "parameters"; + if (pdc_get_optvalues(keyword, resopts, NULL, NULL) && + !pdf_opt_effectless(p, keyword, atype, pdf_launch)) + action->parameters = + (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + + keyword = "operation"; + if (pdc_get_optvalues(keyword, resopts, &k, NULL) && + !pdf_opt_effectless(p, keyword, atype, pdf_launch)) + action->operation = + (char *) pdc_get_keyword(k, pdf_operation_pdfkeylist); + + keyword = "defaultdir"; + if (pdc_get_optvalues(keyword, resopts, NULL, NULL) && + !pdf_opt_effectless(p, keyword, atype, pdf_launch)) + action->defaultdir = + (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + + keyword = "menuname"; + if (pdc_get_optvalues(keyword, resopts, NULL, NULL) && + !pdf_opt_effectless(p, keyword, atype, pdf_named)) + { + action->menuname = + (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + } + + keyword = "namelist"; + ns = pdc_get_optvalues(keyword, resopts, NULL, NULL); + if (ns && !pdf_opt_effectless(p, keyword, atype, + (pdf_actiontype) (pdf_hide | pdf_submitform | pdf_resetform))) + { + action->namelist = (char **) pdc_save_lastopt(resopts, PDC_OPT_SAVEALL); + action->nsnames = ns; + } + + + keyword = "exportmethod"; + if (pdc_get_optvalues(keyword, resopts, &k, NULL)) + { + action->exportmethod = (pdf_exportmethod) k; + if (!pdf_opt_effectless(p, keyword, atype, pdf_submitform)) + { + if ((action->exportmethod & pdf_exp_fdf && + (action->exportmethod | pdf_allfdf) != pdf_allfdf) || + (action->exportmethod & pdf_exp_html && + (action->exportmethod | pdf_allhtml) != pdf_allhtml) || + (action->exportmethod & pdf_exp_xfdf && + (action->exportmethod | pdf_allxfdf) != pdf_allxfdf) || + (action->exportmethod & pdf_exp_pdf && + (action->exportmethod | pdf_allpdf) != pdf_allpdf)) + { + pdc_error(p->pdc, PDC_E_OPT_ILLCOMB, keyword, 0, 0, 0); + } + if (action->exportmethod & pdf_exp_fdf) + action->exportmethod = (pdf_exportmethod) + (action->exportmethod & ~pdf_exp_fdf); + } + } + + keyword = "newwindow"; + if (pdc_get_optvalues(keyword, resopts, &action->newwindow, NULL)) + pdf_opt_effectless(p, keyword, atype, + (pdf_actiontype) (pdf_gotor | pdf_launch)); + + keyword = "ismap"; + if (pdc_get_optvalues(keyword, resopts, &action->ismap, NULL)) + pdf_opt_effectless(p, keyword, atype, pdf_uri); + + keyword = "hide"; + if (pdc_get_optvalues(keyword, resopts, &action->hide, NULL)) + pdf_opt_effectless(p, keyword, atype, pdf_hide); + + keyword = "exclude"; + if (pdc_get_optvalues(keyword, resopts, &action->exclude, NULL)) + pdf_opt_effectless(p, keyword, atype, + (pdf_actiontype) (pdf_submitform | pdf_resetform)); + + keyword = "submitemptyfields"; + if (pdc_get_optvalues(keyword, resopts, &action->submitemptyfields, NULL)) + pdf_opt_effectless(p, keyword, atype, pdf_submitform); + + keyword = "canonicaldate"; + if (pdc_get_optvalues(keyword, resopts, &action->canonicaldate, NULL)) + pdf_opt_effectless(p, keyword, atype, pdf_submitform); + + keyword = "transition"; + if (pdc_get_optvalues(keyword, resopts, &action->transition, NULL)) + pdf_opt_effectless(p, keyword, atype, pdf_trans); + + keyword = "duration"; + if (pdc_get_optvalues(keyword, resopts, &action->duration, NULL)) + pdf_opt_effectless(p, keyword, atype, pdf_trans); + + + + /* required options */ + keyword = NULL; + if (!hasdest && + (atype == pdf_goto || atype == pdf_gotor)) + keyword = "destination"; + if (!action->filename && + (atype == pdf_gotor || atype == pdf_launch || atype == pdf_importdata)) + keyword = "filename"; + if (!action->menuname && atype == pdf_named) + keyword = "menuname"; + if (!action->namelist && atype == pdf_hide) + keyword = "namelist"; + if (!action->filename && + (atype == pdf_uri || atype == pdf_submitform)) + keyword = "url"; + if (keyword) + pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, keyword, 0, 0, 0); + + + return pdf_get_max_action(p); +} + + +static pdc_id +pdf_write_action(PDF *p, pdf_action *action, pdc_id next_id) +{ + pdc_id ret_id = PDC_BAD_ID; + int i, flags = 0; + + + ret_id = pdc_begin_obj(p->out, PDC_NEW_ID); /* Action object */ + pdc_begin_dict(p->out); /* Action dict */ + + pdc_puts(p->out, "/Type/Action\n"); + pdc_printf(p->out, "/S/%s\n", + pdc_get_keyword(action->atype, pdf_action_pdfkeylist)); + + /* next action */ + if (next_id != PDC_BAD_ID) + pdc_objref(p->out, "/Next", next_id); + else + action->obj_id = ret_id; + + /* destination */ + switch (action->atype) + { + case pdf_goto: + case pdf_gotor: + + pdc_puts(p->out, "/D"); + pdf_write_destination(p, action->dest); + + default: + break; + } + + /* file specification */ + switch (action->atype) + { + case pdf_gotor: + case pdf_launch: + if (action->newwindow != pdc_undef) + pdc_printf(p->out, "/NewWindow %s\n", + PDC_BOOLSTR(action->newwindow)); + case pdf_importdata: + + if (action->parameters || action->operation || action->defaultdir) + { + /* Windows-specific launch parameters */ + pdc_puts(p->out, "/Win"); + pdc_begin_dict(p->out); /* Win dict */ + pdc_printf(p->out, "/F"); + pdf_put_hypertext(p, action->filename); + pdc_puts(p->out, "\n"); + if (action->parameters) + { + pdc_printf(p->out, "/P"); + pdf_put_hypertext(p, action->parameters); + pdc_puts(p->out, "\n"); + pdc_free(p->pdc, action->parameters); + action->parameters = NULL; + } + if (action->operation) + { + pdc_printf(p->out, "/O"); + pdf_put_hypertext(p, action->operation); + pdc_puts(p->out, "\n"); + action->operation = NULL; + } + if (action->defaultdir) + { + pdc_printf(p->out, "/D"); + pdf_put_hypertext(p, action->defaultdir); + pdc_puts(p->out, "\n"); + pdc_free(p->pdc, action->defaultdir); + action->defaultdir = NULL; + } + pdc_end_dict(p->out); /* Win dict */ + } + else + { + pdc_puts(p->out, "/F"); + pdc_begin_dict(p->out); /* F dict */ + pdc_puts(p->out, "/Type/Filespec\n"); + pdc_printf(p->out, "/F"); + pdf_put_pdffilename(p, action->filename); + pdc_puts(p->out, "\n"); + pdc_end_dict(p->out); /* F dict */ + } + + default: + break; + } + + /* URI */ + switch (action->atype) + { + case pdf_uri: + pdc_puts(p->out, "/URI"); + pdf_put_hypertext(p, action->filename); + pdc_puts(p->out, "\n"); + + /* IsMap */ + if (action->ismap == pdc_true) + pdc_puts(p->out, "/IsMap true\n"); + + default: + break; + } + + /* Named */ + switch (action->atype) + { + case pdf_named: + pdc_printf(p->out, "/N"); + pdf_put_pdfname(p, action->menuname); + pdc_puts(p->out, "\n"); + + default: + break; + } + + /* name list */ + switch (action->atype) + { + case pdf_hide: + if (action->hide == pdc_false) + pdc_puts(p->out, "/H false\n"); + case pdf_submitform: + case pdf_resetform: + + if (action->nsnames) + { + pdc_printf(p->out, "/%s", + (action->atype == pdf_hide) ? "T" : "Fields"); + pdc_begin_array(p->out); + for (i = 0; i < action->nsnames; i++) + { + pdf_put_hypertext(p, action->namelist[i]); + if (i < action->nsnames - 1) + pdc_puts(p->out, "\n"); + else + pdc_end_array(p->out); + } + } + + default: + break; + } + + /* URL */ + switch (action->atype) + { + case pdf_submitform: + pdc_puts(p->out, "/F"); + pdc_begin_dict(p->out); /* F dict */ + pdc_puts(p->out, "/FS/URL\n"); + pdc_printf(p->out, "/F"); + pdf_put_hypertext(p, action->filename); + pdc_puts(p->out, "\n"); + pdc_end_dict(p->out); /* F dict */ + + default: + break; + } + + /* Trans */ + switch (action->atype) + { + case pdf_trans: + pdc_puts(p->out, "/Trans"); + pdc_begin_dict(p->out); /* Trans dict */ + pdc_puts(p->out, "/Type/Trans\n"); + if (action->transition != trans_replace) + pdc_printf(p->out, "/S/%s", + pdc_get_keyword(action->transition, pdf_transition_pdfkeylist)); + if (action->duration > 0) + pdc_printf(p->out, "/D %f\n", action->duration); + pdc_end_dict(p->out); /* Trans dict */ + + default: + break; + } + + /* Flags */ + switch (action->atype) + { + case pdf_submitform: + flags = (int) action->exportmethod; + if (action->submitemptyfields) + flags |= (1<<1); + if (action->canonicaldate) + flags |= (1<<9); + case pdf_resetform: + + if (action->exclude) + flags |= (1<<0); + if (flags) + pdc_printf(p->out, "/Flags %d\n", flags); + + default: + break; + } + + + + pdc_end_dict(p->out); /* Action dict */ + pdc_end_obj(p->out); /* Action object */ + + return ret_id; +} + + + +/* ---- Annotations events ---- */ + +static const pdc_keyconn pdf_annotevent_keylist[] = +{ + {"activate", 0}, + {"enter", 1}, + {"exit", 2}, + {"down", 3}, + {"up", 4}, + {"focus", 5}, + {"blur", 6}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_annotevent_pdfkeylist[] = +{ + {"A", 0}, + {"E", 1}, + {"X", 2}, + {"D", 3}, + {"U", 4}, + {"Fo", 5}, + {"Bl", 6}, + {NULL, 0} +}; + +static int pdf_annotevent_beginjava = 99; + +static const pdc_defopt pdf_annotevent_options[] = +{ + {"activate", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"enter", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"exit", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"down", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"up", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"focus", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"blur", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + PDC_OPT_TERMINATE +}; + + +/* ---- Bookmark events ---- */ + +static const pdc_keyconn pdf_bookmarkevent_keylist[] = +{ + {"activate", 0}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_bookmarkevent_pdfkeylist[] = +{ + {"A", 0}, + {NULL, 0} +}; + +static int pdf_bookmarkevent_beginjava = 99; + +static const pdc_defopt pdf_bookmarkevent_options[] = +{ + {"activate", pdc_actionhandle, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + PDC_OPT_TERMINATE +}; + + +/* ---- Document events ---- */ + +static const pdc_keyconn pdf_documentevent_keylist[] = +{ + {"open", 0}, + {"didprint", 1}, + {"didsave", 2}, + {"willclose", 3}, + {"willprint", 4}, + {"willsave", 5}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_documentevent_pdfkeylist[] = +{ + {"OpenAction", 0}, + {"DP", 1}, + {"DS", 2}, + {"WC", 3}, + {"WP", 4}, + {"WS", 5}, + {NULL, 0} +}; + +static int pdf_documentevent_beginjava = 1; + +static const pdc_defopt pdf_documentevent_options[] = +{ + {"open", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"didprint", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"didsave", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"willclose", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"willprint", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"willsave", pdc_actionhandle, PDC_OPT_PDC_1_4, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + PDC_OPT_TERMINATE +}; + + +/* ---- Page events ---- */ + +static const pdc_keyconn pdf_pageevent_keylist[] = +{ + {"", 0}, + {"open", 1}, + {"close", 2}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_pageevent_pdfkeylist[] = +{ + {"", 0}, + {"O", 1}, + {"C", 2}, + {NULL, 0} +}; + +static int pdf_pageevent_beginjava = 99; + +static const pdc_defopt pdf_pageevent_options[] = +{ + {"open", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + {"close", pdc_actionhandle, PDC_OPT_NONE, 1, PDC_USHRT_MAX, + 0.0, 0.0, NULL}, + + PDC_OPT_TERMINATE +}; + + +pdc_bool +pdf_parse_and_write_actionlist(PDF *p, pdf_event_object eventobj, + pdc_id *act_idlist, const char *optlist) +{ + const pdc_defopt *defopttable = NULL; + const pdc_keyconn *keyconntable = NULL; + pdc_resopt *resopts = NULL; + pdc_clientdata data; + pdc_id ret_id = PDC_BAD_ID; + pdf_action *action = NULL; + pdc_bool calcevent = pdc_false; + const char *keyword, *type; + char **strlist; + int *actlist; + int i, code, nsact, beginjava = 0; + + switch(eventobj) + { + + case event_annotation: + defopttable = pdf_annotevent_options; + keyconntable = pdf_annotevent_keylist; + beginjava = pdf_annotevent_beginjava; + break; + + case event_bookmark: + defopttable = pdf_bookmarkevent_options; + keyconntable = pdf_bookmarkevent_keylist; + beginjava = pdf_bookmarkevent_beginjava; + break; + + case event_document: + defopttable = pdf_documentevent_options; + keyconntable = pdf_documentevent_keylist; + beginjava = pdf_documentevent_beginjava; + break; + + case event_page: + defopttable = pdf_pageevent_options; + keyconntable = pdf_pageevent_keylist; + beginjava = pdf_pageevent_beginjava; + break; + + default: + break; + } + + /* parsing option list */ + pdf_set_clientdata(p, &data); + resopts = pdc_parse_optionlist(p->pdc, optlist, defopttable, + &data, pdc_true); + + /* write actions and saving action ids */ + for (code = 0; ; code++) + { + keyword = pdc_get_keyword(code, keyconntable); + if (keyword) + { + nsact = pdc_get_optvalues(keyword, resopts, NULL, &strlist); + actlist = (int *) strlist; + + /* Not activate event */ + if (code && nsact) + { + /* additional action type check */ + for (i = 0; i < nsact; i++) + { + action = (pdf_action *) &pdc_vtr_at(p->actions, actlist[i], + pdf_action); + if (code >= beginjava && action->atype != pdf_javascript) + { + type = pdc_get_keyword(action->atype, + pdf_action_pdfkeylist); + pdc_error(p->pdc, PDF_E_ACT_BADACTTYPE, + type, keyword, 0, 0); + } + } + + /* saving calculation event */ + if (!strcmp(keyword, "calculate")) + calcevent = pdc_true; + } + + /* write action objects */ + if (act_idlist != NULL) + { + if (nsact == 1) + { + action = (pdf_action *) &pdc_vtr_at(p->actions, actlist[0], + pdf_action); + if (action->obj_id == PDC_BAD_ID) + ret_id = pdf_write_action(p, action, PDC_BAD_ID); + else + ret_id = action->obj_id; + } + else if (nsact > 1) + { + for (i = nsact-1; i >= 0; i--) + { + action = (pdf_action *) &pdc_vtr_at(p->actions, + actlist[i], pdf_action); + ret_id = pdf_write_action(p, action, ret_id); + } + } + else + ret_id = PDC_BAD_ID; + act_idlist[code] = ret_id; + } + } + else + break; + } + + return calcevent; +} + +pdc_bool +pdf_write_action_entries(PDF *p, pdf_event_object eventobj, pdc_id *act_idlist) +{ + const pdc_keyconn *keyconntable = NULL; + const char *keyword; + pdc_id act_id = PDC_BAD_ID; + pdc_bool adict = pdc_false; + pdc_bool aadict = pdc_false; + int code; + + + switch(eventobj) + { + + case event_annotation: + keyconntable = pdf_annotevent_pdfkeylist; + break; + + case event_bookmark: + keyconntable = pdf_bookmarkevent_pdfkeylist; + break; + + case event_document: + keyconntable = pdf_documentevent_pdfkeylist; + break; + + case event_page: + keyconntable = pdf_pageevent_pdfkeylist; + break; + + default: + break; + } + + for (code = 0; ; code++) + { + keyword = pdc_get_keyword(code, keyconntable); + if (keyword) + { + act_id = act_idlist[code]; + if (act_id != PDC_BAD_ID) + { + if (code && !aadict) + { + pdc_puts(p->out, "/AA"); + pdc_begin_dict(p->out); /* AA dict */ + aadict = pdc_true; + } + else if (!code) + adict = pdc_true; + pdc_printf(p->out, "/%s", keyword); + pdc_objref_c(p->out, act_id); + } + } + else + break; + } + if (aadict) + pdc_end_dict(p->out); /* AA dict */ + else if (adict) + pdc_puts(p->out, "\n"); + + return adict; +} diff --git a/src/pdflib/pdflib/p_afm.c b/src/pdflib/pdflib/p_afm.c new file mode 100644 index 0000000..8de04a5 --- /dev/null +++ b/src/pdflib/pdflib/p_afm.c @@ -0,0 +1,756 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_afm.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib AFM parsing routines + * + */ + +#include "p_intern.h" +#include "p_font.h" + +#define AFM_GLYPH_SUPPL 3 + +#define AFM_LINEBUF 4096 + +#define AFM_SEPARATORS "\f\n\r\t\v ,:;" + +/* The values of each of these enumerated items correspond to an entry in the + * table of strings defined below. Therefore, if you add a new string as + * new keyword into the keyStrings table, you must also add a corresponding + * pdf_afmkey AND it MUST be in the same position! + * + * IMPORTANT: since the sorting algorithm is a binary search, the strings of + * keywords must be placed in lexicographical order, below. [Therefore, the + * enumerated items are not necessarily in lexicographical order, depending + * on the name chosen. BUT, they must be placed in the same position as the + * corresponding key string.] The NOPE shall remain in the last position, + * since it does not correspond to any key string. + */ + +#ifndef PDFLIB_EBCDIC +typedef enum +{ + ASCENDER, + CHARBBOX, + CODE, + COMPCHAR, + CODEHEX, + CAPHEIGHT, + CHARWIDTH, + CHARACTERSET, + CHARACTERS, + COMMENT, + DESCENDER, + ENCODINGSCHEME, + ENDCHARMETRICS, + ENDCOMPOSITES, + ENDDIRECTION, + ENDFONTMETRICS, + ENDKERNDATA, + ENDKERNPAIRS, + ENDKERNPAIRS0, + ENDKERNPAIRS1, + ENDMASTERFONTMETRICS, + ENDTRACKKERN, + ESCCHAR, + FAMILYNAME, + FONTBBOX, + FONTNAME, + FULLNAME, + ISBASEFONT, + ISCIDFONT, + ISFIXEDPITCH, + ISFIXEDV, + ITALICANGLE, + KERNPAIR, + KERNPAIRHAMT, + KERNPAIRXAMT, + KERNPAIRYAMT, + LIGATURE, + MAPPINGSCHEME, + METRICSSETS, + CHARNAME, + NOTICE, + COMPCHARPIECE, + STARTCHARMETRICS, + STARTCOMPFONTMETRICS, + STARTCOMPOSITES, + STARTDIRECTION, + STARTFONTMETRICS, + STARTKERNDATA, + STARTKERNPAIRS, + STARTKERNPAIRS0, + STARTKERNPAIRS1, + STARTMASTERFONTMETRICS, + STARTTRACKKERN, + STDHW, + STDVW, + TRACKKERN, + UNDERLINEPOSITION, + UNDERLINETHICKNESS, + VVECTOR, + VERSION, + XYWIDTH, + XY0WIDTH, + X0WIDTH, + Y0WIDTH, + XY1WIDTH, + X1WIDTH, + Y1WIDTH, + XWIDTH, + YWIDTH, + WEIGHT, + XHEIGHT, + NOPE +} +pdf_afmkey; + +/* keywords for the system: + * This a table of all of the current strings that are vaild AFM keys. + * Each entry can be referenced by the appropriate pdf_afmkey value (an + * enumerated data type defined above). If you add a new keyword here, + * a corresponding pdf_afmkey MUST be added to the enumerated data type + * defined above, AND it MUST be added in the same position as the + * string is in this table. + * + * IMPORTANT: since the sorting algorithm is a binary search, the keywords + * must be placed in lexicographical order. And, NULL should remain at the + * end. + */ + +static const char *keyStrings[] = +{ + "Ascender", + "B", + "C", + "CC", + "CH", + "CapHeight", + "CharWidth", + "CharacterSet", + "Characters", + "Comment", + "Descender", + "EncodingScheme", + "EndCharMetrics", + "EndComposites", + "EndDirection", + "EndFontMetrics", + "EndKernData", + "EndKernPairs", + "EndKernPairs0", + "EndKernPairs1", + "EndMasterFontMetrics", + "EndTrackKern", + "EscChar", + "FamilyName", + "FontBBox", + "FontName", + "FullName", + "IsBaseFont", + "IsCIDFont", + "IsFixedPitch", + "IsFixedV", + "ItalicAngle", + "KP", + "KPH", + "KPX", + "KPY", + "L", + "MappingScheme", + "MetricsSets", + "N", + "Notice", + "PCC", + "StartCharMetrics", + "StartCompFontMetrics", + "StartComposites", + "StartDirection", + "StartFontMetrics", + "StartKernData", + "StartKernPairs", + "StartKernPairs0", + "StartKernPairs1", + "StartMasterFontMetrics", + "StartTrackKern", + "StdHW", + "StdVW", + "TrackKern", + "UnderlinePosition", + "UnderlineThickness", + "VVector", + "Version", + "W", + "W0", + "W0X", + "W0Y", + "W1", + "W1X", + "W1Y", + "WX", + "WY", + "Weight", + "XHeight" +}; + +#else /* !PDFLIB_EBCDIC */ +#endif /* PDFLIB_EBCDIC */ + +static pdc_bool +pdf_parse_afm( + PDF *p, + pdc_file *fp, + pdf_font *font, + const char *fontname, + const char *filename) +{ + static const char fn[] = "pdf_parse_afm"; + fnt_font_metric *ftm = &font->ft.m; + const char *afmtype = NULL; + char **wordlist, *keyword, *arg1; + char line[AFM_LINEBUF]; + int i, cmp, lo, hi, nwords, nglyphs = 0, nline = 0; + int tablen = ((sizeof keyStrings) / (sizeof (char *))); + pdc_sint32 iz; + double dz; + pdc_scalar charwidth = -1; + pdf_afmkey keynumber; + fnt_glyphwidth *glw; + pdc_bool toskip = pdc_false; + pdc_bool is_zadbfont = !strcmp(fontname, "ZapfDingbats"); + + /* all new glyph names of AGL 2.0 are missing */ + font->missingglyphs = 0xFFFFFFFF; + + /* read loop. because of Mac files we use pdc_fgetline */ + while (pdc_fgetline(line, AFM_LINEBUF, fp) != NULL) + { + /* split line */ + nline++; + nwords = pdc_split_stringlist(p->pdc, line, AFM_SEPARATORS, 0, + &wordlist); + if (!nwords) continue; + keyword = wordlist[0]; + + /* find keynumber */ + lo = 0; + hi = tablen; + keynumber = NOPE; + while (lo < hi) + { + i = (lo + hi) / 2; + cmp = strcmp(keyword, keyStrings[i]); + + if (cmp == 0) + { + keynumber = (pdf_afmkey) i; + break; + } + + if (cmp < 0) + hi = i; + else + lo = i + 1; + } + + /* unkown key */ + if (keynumber == NOPE) + { + pdc_warning(p->pdc, PDF_E_T1_AFMBADKEY, keyword, filename, 0,0); + goto PDF_PARSECONTD; + } + if (keynumber == ENDDIRECTION) + toskip = pdc_false; + + if (nwords == 1 || toskip == pdc_true) + goto PDF_PARSECONTD; + + /* key switch */ + arg1 = wordlist[1]; + switch (keynumber) + { + case STARTDIRECTION: + if (pdc_str2integer(arg1, 0, &iz) != pdc_true) + goto PDF_SYNTAXERROR; + if (iz) + toskip = pdc_true; + break; + + case STARTCOMPFONTMETRICS: + afmtype = "ACFM"; + goto PDF_SYNTAXERROR; + + case STARTMASTERFONTMETRICS: + afmtype = "AMFM"; + goto PDF_SYNTAXERROR; + + case ISCIDFONT: + afmtype = "CID font"; + if (!strcmp(arg1, "true")) + goto PDF_SYNTAXERROR; + break; + + case FONTNAME: + font->ft.name = pdc_strdup(p->pdc, arg1); + ftm->name = pdc_strdup(p->pdc, arg1); + pdc_logg_cond(p->pdc, 1, trc_font, + "\tPostScript font name: \"%s\"\n", ftm->name); + break; + + /* Recognize Multiple Master fonts by last part of name */ + case FAMILYNAME: + if (!strcmp(wordlist[nwords-1], "MM")) + ftm->type = fnt_MMType1; + else + ftm->type = fnt_Type1; + break; + + /* Default: FontSpecific */ + case ENCODINGSCHEME: + if (!pdc_stricmp(arg1, "StandardEncoding") || + !pdc_stricmp(arg1, "AdobeStandardEncoding")) + font->ft.issymbfont = pdc_false; + break; + + case STDHW: + if (pdc_str2double(arg1, &dz) != pdc_true) + goto PDF_SYNTAXERROR; + ftm->StdHW = (int) dz; + break; + + case STDVW: + if (pdc_str2double(arg1, &dz) != pdc_true) + goto PDF_SYNTAXERROR; + ftm->StdVW = (int) dz; + break; + + case WEIGHT: + font->ft.weight = fnt_check_weight(fnt_weightname2weight(arg1)); + break; + + case ISFIXEDPITCH: + if (!pdc_stricmp(arg1, "false")) + ftm->isFixedPitch = pdc_false; + else + ftm->isFixedPitch = pdc_true; + break; + + /* New AFM 4.1 keyword "CharWidth" implies fixed pitch */ + case CHARWIDTH: + if (pdc_str2double(arg1, &dz) != pdc_true) + goto PDF_SYNTAXERROR; + charwidth = dz; + ftm->isFixedPitch = pdc_true; + break; + + case ITALICANGLE: + { + if (pdc_str2double(arg1, &dz) != pdc_true) + goto PDF_SYNTAXERROR; + ftm->italicAngle = dz; + } + break; + + case UNDERLINEPOSITION: + if (pdc_str2double(arg1, &dz) != pdc_true) + goto PDF_SYNTAXERROR; + ftm->underlinePosition = (int) dz; + break; + + case UNDERLINETHICKNESS: + if (pdc_str2double(arg1, &dz) != pdc_true) + goto PDF_SYNTAXERROR; + ftm->underlineThickness = (int) dz; + break; + + case FONTBBOX: + { + if (nwords != 5) + goto PDF_SYNTAXERROR; + for (i = 1; i < nwords; i++) + { + if (pdc_str2double(wordlist[i], &dz) != pdc_true) + goto PDF_SYNTAXERROR; + if (i == 1) + ftm->llx = dz; + else if (i == 2) + ftm->lly = dz; + else if (i == 3) + ftm->urx = dz; + else if (i == 4) + ftm->ury = dz; + } + } + break; + + case CAPHEIGHT: + if (pdc_str2double(arg1, &dz) != pdc_true) + goto PDF_SYNTAXERROR; + ftm->capHeight = (int) dz; + break; + + case XHEIGHT: + if (pdc_str2double(arg1, &dz) != pdc_true) + goto PDF_SYNTAXERROR; + ftm->xHeight = (int) dz; + break; + + case DESCENDER: + if (pdc_str2double(arg1, &dz) != pdc_true) + goto PDF_SYNTAXERROR; + ftm->descender = (int) dz; + break; + + case ASCENDER: + if (pdc_str2double(arg1, &dz) != pdc_true) + goto PDF_SYNTAXERROR; + ftm->ascender = (int) dz; + break; + + /* Character widths */ + + case STARTCHARMETRICS: + if (pdc_str2integer(arg1, PDC_INT_UNSIGNED, (pdc_sint32 *) &nglyphs) + != pdc_true || nglyphs <= 0) + goto PDF_SYNTAXERROR; + ftm->glw = (fnt_glyphwidth *) pdc_calloc(p->pdc, + (size_t) nglyphs * sizeof(fnt_glyphwidth), fn); + break; + + /* Character code */ + case CODE: + case CODEHEX: + if (!nglyphs || !ftm->glw) + goto PDF_SYNTAXERROR; + if (font->ft.numglyphs >= nglyphs) + { + nglyphs++; + ftm->glw = (fnt_glyphwidth *) pdc_realloc(p->pdc, ftm->glw, + (size_t) nglyphs * sizeof(fnt_glyphwidth), fn); + } + glw = &ftm->glw[font->ft.numglyphs]; + if (keynumber == CODE) + { + if (pdc_str2integer(arg1, 0, &iz) != pdc_true) + goto PDF_SYNTAXERROR; + } + else + { + if (pdc_str2integer(arg1, PDC_INT_HEXADEC, &iz) != pdc_true) + goto PDF_SYNTAXERROR; + } + glw->code = (pdc_short) iz; + glw->unicode = 0; + glw->width = (pdc_ushort) + (font->opt.monospace ? font->opt.monospace : charwidth); + font->ft.numglyphs++; + + /* Character width and name */ + for (i = 2; i < nwords; i++) + { + if (!strcmp(wordlist[i], "WX") || + !strcmp(wordlist[i], "W0X") || + !strcmp(wordlist[i], "W")) + { + i++; + if (i == nwords) + goto PDF_SYNTAXERROR; + if (pdc_str2double(wordlist[i], &dz) != pdc_true) + goto PDF_SYNTAXERROR; + glw->width = (pdc_ushort) + (font->opt.monospace ? font->opt.monospace : dz); + } + + if (!strcmp(wordlist[i], "N")) + { + i++; + if (i == nwords) + goto PDF_SYNTAXERROR; + + /* Unicode value by means of AGL, + * internal and private table + */ + glw->unicode = is_zadbfont ? + (pdc_ushort) pdc_zadb2unicode(wordlist[i]): + pdc_insert_glyphname(p->pdc, wordlist[i]); + pdc_delete_missingglyph_bit(glw->unicode, + &font->missingglyphs); + + } + } + break; + + + default: + break; + } + + PDF_PARSECONTD: + pdc_cleanup_stringlist(p->pdc, wordlist); + wordlist = NULL; + + if (keynumber == ENDFONTMETRICS) + break; + } + + /* necessary font struct members */ + if (font->ft.name == NULL || ftm->glw == NULL) + goto PDF_SYNTAXERROR; + + pdc_fclose(fp); + + ftm->numglwidths = font->ft.numglyphs; + return pdc_true; + + PDF_SYNTAXERROR: + pdc_fclose(fp); + pdc_cleanup_stringlist(p->pdc, wordlist); + + if (afmtype) + pdc_set_errmsg(p->pdc, PDF_E_T1_UNSUPP_FORMAT, afmtype, 0, 0, 0); + else + pdc_set_errmsg(p->pdc, PDC_E_IO_ILLSYNTAX, "AFM ", filename, + pdc_errprintf(p->pdc, "%d", nline), 0); + return pdc_false; +} + +pdc_bool +pdf_process_metrics_data( + PDF *p, + pdf_font *font, + const char *fontname) +{ + static const char fn[] = "pdf_process_metrics_data"; + fnt_font_metric *ftm = &font->ft.m; + int width = 0; + pdc_ushort uv; + pdc_encoding enc = font->ft.enc; + pdc_encodingvector *ev = NULL; + int nalloc, foundglyphs = 0, i, j = 0, k; + + (void) j; + + /* Unallowed encoding */ + if (enc == pdc_cid || enc < pdc_builtin) + { + + pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0); + + return pdc_false; + } + + /* Determine the default character width (width of space character) */ + if (font->opt.monospace) + { + ftm->defwidth = font->opt.monospace; + } + else + { + width = fnt_get_glyphwidth((int) PDF_DEFAULT_CHAR, &font->ft); + if (width != FNT_MISSING_WIDTH) + ftm->defwidth = width; + else + ftm->defwidth = FNT_DEFAULT_WIDTH; + } + + /* builtin font */ + if (font->ft.issymbfont == pdc_true && enc != pdc_builtin && + !strcmp(font->encapiname, "auto")) + { + enc = pdc_builtin; + font->ft.enc = enc; + } + + /* optimizing PDF output */ + if (enc == pdc_ebcdic || + enc == pdc_ebcdic_37 || + enc == pdc_ebcdic_winansi) + font->towinansi = pdc_winansi; + + /* glyph name list for incore fonts */ + nalloc = font->ft.numglyphs + AFM_GLYPH_SUPPL; + + /* + * Generate character width according to the chosen encoding + */ + + { + font->ft.numcodes = 256; + font->ft.code2gid = (pdc_ushort *) pdc_calloc(p->pdc, + font->ft.numcodes * sizeof (pdc_ushort), fn); + + ftm->numwidths = font->ft.numcodes; + ftm->widths = (int *)pdc_calloc(p->pdc, + font->ft.numcodes * sizeof(int), fn); + + /* Given 8-bit encoding */ + if (enc >= 0) + { + ev = pdc_get_encoding_vector(p->pdc, enc); + for (k = 0; k < font->ft.numcodes; k++) + { + uv = ev->codes[k]; + ftm->widths[k] = ftm->defwidth; + if (uv) + { + uv = pdc_get_alter_glyphname(uv, font->missingglyphs, NULL); + if (uv) + { + for (i = 0; i < ftm->numglwidths; i++) + { + if (ftm->glw[i].unicode == uv) + { + j = i + 1; + ftm->widths[k] = ftm->glw[i].width; + font->ft.code2gid[k] = j; + foundglyphs++; + } + } + } + } + } + + if (ftm->ciw != NULL) + { + pdc_free(p->pdc, ftm->ciw); + ftm->ciw = NULL; + } + + pdc_logg_cond(p->pdc, 2, trc_font, + "\t\t%d glyphs could be mapped to Unicode\n", foundglyphs); + + /* No characters found */ + if (!foundglyphs) + { + if (font->ft.issymbfont == pdc_false) + { + pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0); + return pdc_false; + } + else + { + /* We enforce builtin encoding */ + pdc_warning(p->pdc, PDF_E_FONT_FORCEENC, + pdf_get_encoding_name(p, pdc_builtin, font), + 0, 0, 0); + enc = pdc_builtin; + font->ft.enc = enc; + font->towinansi = pdc_invalidenc; + } + } + else if (foundglyphs < PDF_MIN_GLYPHS) + { + pdc_warning(p->pdc, PDF_E_FONT_INAPPROPENC, + pdc_errprintf(p->pdc, "%d", foundglyphs), 0, 0, 0); + } + } + + /* built-in encoding */ + if (enc == pdc_builtin) + { + if (ftm->glw == NULL) + { + pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0); + return pdc_false; + } + + /* encoding for builtin */ + ev = pdf_create_font_encoding(p, enc, font, fontname, pdc_true); + font->symenc = font->ft.enc; + + /***************************/ + font->ft.enc = pdc_builtin; + /***************************/ + + for (i = 0; i < font->ft.numcodes; i++) + { + ftm->widths[i] = ftm->defwidth; + } + + for (i = 0; i < font->ft.numglyphs; i++) + { + pdc_short code = ftm->glw[i].code; + + if (code >= 0 && code < font->ft.numcodes) + { + j = i + 1; + ftm->widths[code] = ftm->glw[i].width; + font->ft.code2gid[code] = j; + if (ev != NULL) + { + ev->codes[code] = ftm->glw[i].unicode; + } + } + } + } + } + + + if (ftm->glw != NULL) + { + pdc_free(p->pdc, ftm->glw); + ftm->glw = NULL; + } + + return pdc_true; +} + +pdc_bool +pdf_get_metrics_afm( + PDF *p, + pdf_font *font, + const char *fontname, + pdc_encoding enc, + const char *filename, + pdc_bool requested) +{ + static const char fn[] = "pdf_get_metrics_afm"; + char fullname[PDC_FILENAMELEN]; + pdc_file *afmfile; + + /* open AFM file */ + afmfile = pdc_fsearch_fopen(p->pdc, filename, fullname, "AFM ", + PDC_FILE_TEXT); + if (afmfile == NULL) + return pdc_check_fopen_errmsg(p->pdc, requested); + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tLoading AFM metric fontfile \"%s\":\n", fullname); + + /* parse AFM file */ + if (pdf_parse_afm(p, afmfile, font, fontname, fullname) == pdc_false) + return pdc_false; + + /* members not fount */ + if (font->ft.m.type == fnt_unknownType) + font->ft.m.type = fnt_Type1; + if (font->ft.name == NULL) + { + font->ft.name = pdc_strdup(p->pdc, fontname); + font->ft.m.name = pdc_strdup(p->pdc, fontname); + } + + /* save full filename */ + font->metricfilename = pdc_strdup_ext(p->pdc, fullname, 0, fn); + + /* process metric data */ + font->ft.enc = enc; + if (pdf_process_metrics_data(p, font, fontname) == pdc_false) + return pdc_false; + + if (!pdf_make_fontflag(p, font)) + return pdc_false; + + return pdc_true; +} diff --git a/src/pdflib/pdflib/p_annots.c b/src/pdflib/pdflib/p_annots.c new file mode 100644 index 0000000..b38da91 --- /dev/null +++ b/src/pdflib/pdflib/p_annots.c @@ -0,0 +1,2078 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib routines for annnotations + * + */ + +#define P_ANNOTS_C + +#include "p_intern.h" +#include "p_color.h" +#include "p_font.h" +#include "p_image.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), + ann_3d = (1<<16) +} +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}, + {"3D", ann_3d}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_polyline_pdfkeylist[] = +{ + {"QuadPoints", ann_link}, + {"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), + anndict_3dd = (1<<22), + anndict_3da = (1<<23), + anndict_3dv = (1<<24) +} +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}, + {"3DD", anndict_3dd}, + {"3DV", anndict_3dv}, + {"3DA", anndict_3da}, + {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_keyconn pdf_3dview_keylist[] = +{ + {NULL, 0} +}; + + + +#define PDF_LAYER_FLAG PDC_OPT_UNSUPP + +#define PDF_3DANNOT_FLAG PDC_OPT_UNSUPP +static const pdc_defopt pdf_create_annot_options[] = +{ + /* deprecated */ + {"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, PDC_INT_MAX, NULL}, + + {"name", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"parentname", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"popup", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"title", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"subject", pdc_stringlist, PDC_OPT_PDC_1_5, 1, 1, + 0.0, PDC_USHRT_MAX, 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_SUBOPTLIST | PDC_OPT_KEYLIST1, 1, 2, + 0.0, PDC_FLOAT_MAX, pdf_fontsize_keylist}, + + {"orientate", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, pdf_orientate_keylist}, + + {"contents", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_INT_MAX, NULL}, + + {"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"filename", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 1.0, PDC_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_polylinelist, PDC_OPT_NONE, 1, PDF_MAXARRAYSIZE, + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, + + {"action", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"usematchbox", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"layer", pdc_layerhandle, PDF_LAYER_FLAG, 1, 1, + 0.0, 0.0, NULL}, + + {"3dactivate", pdc_stringlist, PDF_3DANNOT_FLAG, 1, 1, + 0.0, PDC_USHRT_MAX, NULL}, + + {"3dbox", pdc_scalarlist, PDF_3DANNOT_FLAG, 4, 4, + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, + + {"3ddata", pdc_3ddatahandle, PDF_3DANNOT_FLAG, 1, 1, + 0.0, 0.0, NULL}, + + {"3dinteractive", pdc_booleanlist, PDF_3DANNOT_FLAG, 1, 1, + 0.0, 0.0, NULL}, + + {"3dshared", pdc_booleanlist, PDF_3DANNOT_FLAG, 1, 1, + 0.0, 0.0, NULL}, + + {"3dinitialview", pdc_3dviewhandle, PDF_3DANNOT_FLAG, 1, 1, + 0.0, 0.0, pdf_3dview_keylist}, + + PDC_OPT_TERMINATE +}; + +/* Annotation member */ +typedef struct pdf_annot_s +{ + pdc_bool iscopy; + pdc_id obj_id; + pdf_annottype atype; + int mask; + pdc_rectangle rect; + pdc_bool usercoordinates; + pdc_encoding hypertextencoding; + int hypertextcodepage; + 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; + int orientate; + 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_off_t filesize; + pdc_scalar *line; + pdc_polyline *polylinelist; + int nplines; + char **custom; + int ncustoms; + char *action; + + +} +pdf_annot; + +static void +pdf_reclaim_annot(void *item) +{ + pdf_annot *ann = (pdf_annot *) item; + + ann->iscopy = pdc_false; + ann->obj_id = PDC_BAD_ID; + ann->atype = (pdf_annottype)0; + ann->mask = 0; + ann->usercoordinates = pdc_false; + ann->hypertextencoding = pdc_invalidenc; + ann->hypertextcodepage = 0; + ann->annotcolor.type = (int) color_none; + ann->interiorcolor.type = (int) color_none; + ann->fillcolor.type = (int) color_none; + 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->orientate = 0; + ann->alignment = quadd_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->filesize = 0; + ann->line = NULL; + ann->polylinelist = NULL; + ann->nplines = 0; + ann->custom = NULL; + ann->ncustoms = 0; + ann->action = NULL; + + + + +} + +static void +pdf_release_annot(void *context, void *item) +{ + PDF *p = (PDF *) context; + pdf_annot *ann = (pdf_annot *) item; + + /* is not a copy */ + if (!ann->iscopy) + { + 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->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; + } + } + + ann->polylinelist = (pdc_polyline *)pdc_delete_polylinelist( + p->pdc, ann->polylinelist, ann->nplines); +} + +static pdc_ced pdf_annot_ced = +{ + sizeof(pdf_annot), pdf_reclaim_annot, pdf_release_annot, NULL +}; + +static pdc_vtr_parms pdf_annot_parms = +{ + 0, 10, 10 +}; + +static pdf_annot * +pdf_new_annot(PDF *p) +{ + pdc_vtr *annots = pdf_get_annots_list(p); + pdf_annot *result; + + if (annots == NULL) + { + annots = pdc_vtr_new(p->pdc, &pdf_annot_ced, p, &pdf_annot_parms); + pdf_set_annots_list(p, annots); + } + + result = pdc_vtr_incr(annots, pdf_annot); + result->usercoordinates = p->usercoordinates; + result->hypertextencoding = p->hypertextencoding; + result->hypertextcodepage = p->hypertextcodepage; + pdf_init_coloropt(p, &result->fillcolor); + + + return result; +} + +static void +pdf_delete_last_annot(PDF *p) +{ + pdc_vtr *annots = pdf_get_annots_list(p); + + if (annots != NULL) + { + if (pdc_vtr_size(annots) > 1) + { + pdc_vtr_pop(annots); + } + else + { + pdc_vtr_delete(annots); + pdf_set_annots_list(p, NULL); + } + } +} + +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) +{ + static const char fn[] = "pdf_init_rectangle"; + pdc_matrix *ctm = &p->curr_ppt->gstate[p->curr_ppt->sl].ctm; + int i; + + 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_delete_polylinelist(p->pdc, ann->polylinelist, ann->nplines); + ann->nplines = 1; + ann->polylinelist = (pdc_polyline *) pdc_malloc(p->pdc, + ann->nplines * sizeof(pdc_polyline), fn); + ann->polylinelist[0].np = 5; + ann->polylinelist[0].p = (pdc_vector *) pdc_malloc(p->pdc, + ann->polylinelist[0].np * sizeof(pdc_vector), fn); + + if (polyline == NULL) + { + if (!ann->usercoordinates) + ctm = NULL; + pdc_rect_init(&ann->rect, llx, lly, urx, ury); + pdc_rect2polyline(ctm, &ann->rect, ann->polylinelist[0].p); + } + else + { + for (i = 0; i < 5; i++) + pdc_transform_vector(ctm, &polyline[i], + &ann->polylinelist[0].p[i]); + } + + if (ctm != NULL) + pdc_polyline2rect(ann->polylinelist[0].p, 4, &ann->rect); +} + +/* because of Acrobat muddle */ +static void +pdf_permute_coordinates(pdf_annot *ann, pdf_annottype atype) +{ + if (ann->nplines == 1 && + (atype == ann_highlight || + atype == ann_underline || + atype == ann_squiggly || + atype == ann_strikeout)) + { + pdc_vector pl[5]; + int i; + + for (i = 0; i < ann->polylinelist[0].np; i++) + pl[i] = ann->polylinelist[0].p[i]; + + ann->polylinelist[0].p[0] = pl[3]; + ann->polylinelist[0].p[1] = pl[2]; + ann->polylinelist[0].p[2] = pl[0]; + ann->polylinelist[0].p[3] = pl[1]; + ann->polylinelist[0].p[4] = pl[3]; + } +} + +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, PDC_USHRT_MAX, 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_ERR_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_ERR_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, + ann->hypertextcodepage, 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) +{ + if ((pdf_annottype) !(intendatypes & curratype)) + { + const char *type = pdc_get_keyword(curratype, pdf_annottype_pdfkeylist); + 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) +{ + pdc_resopt *resopts = NULL; + pdc_clientdata cdata; + pdf_annottype atype; + pdf_annot *ann; + pdf_dest *dest = NULL; + const char *keyword, *keyword_s = NULL; + char **strlist = NULL; + pdc_scalar *line; + int i, j, k, ns, nss[2]; + pdf_ppt *ppt = p->curr_ppt; + pdc_matrix *ctm = &ppt->gstate[ppt->sl].ctm; + + 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, &cdata); + resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_create_annot_options, + &cdata, pdc_true); + + /* Initializing */ + ann = pdf_new_annot(p); + ann->atype = atype; + + keyword = "usercoordinates"; + pdc_get_optvalues(keyword, resopts, &ann->usercoordinates, NULL); + pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL); + + ann->hypertextencoding = + pdf_get_hypertextencoding_opt(p, resopts, &ann->hypertextcodepage, + pdc_true); + + keyword = "custom"; + ns = pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding, + ann->hypertextcodepage, 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"; + ns = pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding, + ann->hypertextcodepage, pdc_true, NULL, &ann->name, NULL); + if (ns) + { + pdf_opt_alrdef(p, keyword, ann, anndict_nm); + 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, + ann->hypertextcodepage, 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, + ann->hypertextcodepage, 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 (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); + 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)); + } + + 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)) + { + 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); + + keyword = "fontsize"; + if (pdf_get_fontsize_option(p, ann->font, resopts, &ann->fontsize)) + { + pdf_opt_effectless(p, keyword, atype, ann_freetext); + if (ann->usercoordinates == pdc_true) + ann->fontsize = pdc_transform_scalar(ctm, ann->fontsize); + } + + keyword = "orientate"; + if (pdc_get_optvalues(keyword, resopts, &ann->orientate, NULL)) + pdf_opt_effectless(p, keyword, atype, + (pdf_annottype) (ann_freetext | ann_stamp)); + + keyword = "contents"; + if (atype == ann_freetext) + { + pdc_encoding enc = pdc_invalidenc; + int codepage = 0; + + if (ann->font > -1) + { + enc = p->fonts[ann->font].ft.enc; + codepage = p->fonts[ann->font].codepage; + } + pdf_get_opt_textlist(p, keyword, resopts, enc, codepage, + pdc_false, NULL, &ann->contents, NULL); + } + else + { + pdf_get_opt_textlist(p, keyword, resopts, ann->hypertextencoding, + ann->hypertextcodepage, 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)) + { + ann->dest = pdf_parse_destination_optlist(p, strlist[0], 0, + pdf_locallink); + keyword_s = keyword; + } + else + { + keyword = "destname"; + if (atype == ann_link) + dest = pdf_get_option_destname(p, resopts, ann->hypertextencoding, + ann->hypertextcodepage); + else if (pdc_get_optvalues(keyword, resopts, NULL, NULL)) + pdf_opt_effectless(p, keyword, atype, ann_link); + 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)) + { + ann->filename = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + ann->filesize = pdf_check_file(p, ann->filename, pdc_true); + } + + keyword = "mimetype"; + if (pdc_get_optvalues(keyword, resopts, NULL, NULL) && + !pdf_opt_effectless(p, keyword, atype, ann_fileattachment)) + 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))) + { + 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)); + } + + 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))) + { + 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); + + keyword = "line"; + ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist); + if (ns && !pdf_opt_effectless(p, keyword, atype, ann_line)) + { + line = (pdc_scalar *) strlist; + if (ann->usercoordinates == pdc_true) + { + pdc_transform_point(ctm, line[0], line[1], &line[0], &line[1]); + pdc_transform_point(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))) + { + pdc_polyline *pl = (pdc_polyline *) strlist; + + for (j = 0; j < ns; j++) + { + if (pl[j].np < 2 || + (atype != ann_ink && atype != ann_polygon && + atype != ann_polyline && pl[j].np != 4)) + { + pdc_error(p->pdc, PDF_E_ANN_BADNUMCOORD, keyword, 0, 0, 0); + } + for (i = 0; i < pl[j].np; i++) + { + if (ann->usercoordinates == pdc_true) + pdc_transform_vector(ctm, &pl[j].p[i], NULL); + } + } + pdc_delete_polylinelist(p->pdc, ann->polylinelist, ann->nplines); + ann->polylinelist = pl; + ann->nplines = ns; + pdc_save_lastopt(resopts, PDC_OPT_SAVEALL); + } + } + else + pdf_permute_coordinates(ann, atype); + + keyword = "action"; + if (pdc_get_optvalues(keyword, resopts, NULL, &strlist)) + { + if (ann->dest) + { + pdf_cleanup_destination(p, ann->dest); + ann->dest = NULL; + 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) + { + pdf_font *font_s = &p->fonts[ann->font]; + const char *fontname = + pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, font_s->ft.name); + + if (!strcmp(pdf_get_pdf_fontname(font_s), fontname)) + pdc_error(p->pdc, PDF_E_ANN_NOSTDFONT, fontname, 0, 0, 0); + } + + /* + * matchbox available + */ + keyword = "usematchbox"; + if (pdc_get_optvalues(keyword, resopts, NULL, &strlist)) + { + pdf_annot *ann_first = ann; + const char *mboxname; + int ir, nrect, irect; + + mboxname = pdf_get_usematchbox(p, keyword, strlist[0], &irect, &nrect); + if (mboxname != NULL) + { + if (irect > nrect) + { + pdf_delete_last_annot(p); + } + else + { + pdf_mbox *mbox; + pdc_vector pl[5]; + + /* rectangle loop */ + for (ir = irect; ir <= nrect; ir++) + { + if (ir > irect) + { + /* create copy */ + ann = pdf_new_annot(p); + ann->atype = atype; + memcpy(ann, ann_first, sizeof(pdf_annot)); + ann->obj_id = PDC_BAD_ID; + ann->iscopy = pdc_true; + ann->nplines = 0; + ann->polylinelist = NULL; + } + + /* rectangle #ir */ + mbox = pdf_get_mbox(p, NULL, mboxname, ir, NULL); + pdf_get_mbox_rectangle(p, mbox, pl); + pdf_init_rectangle(p, ann, 0, 0, 0, 0, pl); + pdf_permute_coordinates(ann, atype); + ann->usercoordinates = pdc_true; + } + } + } + } + +} + +pdc_id +pdf_write_annots_root(PDF *p, pdc_vtr *annots, pdf_widget *widgetlist) +{ + pdc_id result = PDC_BAD_ID; + + /* Annotations array */ + if (annots != NULL || widgetlist) + { + result = pdc_begin_obj(p->out, PDC_NEW_ID); + pdc_begin_array(p->out); + + if (annots != NULL) + { + pdf_annot *ann; + int i, na = pdc_vtr_size(annots); + + for (i = 0; i < na; i++) + { + ann = (pdf_annot *) &pdc_vtr_at(annots, i, pdf_annot); + if (ann->obj_id == PDC_BAD_ID) + 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, pdc_vtr *annots) +{ + pdf_annot *ann, *annpar; + pdc_id act_idlist[PDF_MAX_EVENTS]; + int i, j, k, na, flags; + + na = pdc_vtr_size(annots); + + for (k = 0; k < na; k++) + { + ann = (pdf_annot *) &pdc_vtr_at(annots, k, pdf_annot); + + + /* 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 (i = 0; i < na; i++) + { + annpar = (pdf_annot *) &pdc_vtr_at(annots, i, pdf_annot); + if (annpar->name != NULL && + !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_false); + 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 != quadd_left) + pdc_printf(p->out, "/Q %d\n", ann->alignment); + pdf_write_defappstring(p, ann); + 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_link: + if (!ann->usercoordinates || p->compatibility < PDC_1_6) + break; + case ann_highlight: + case ann_underline: + case ann_squiggly: + case ann_strikeout: + ann->polylinelist[0].np = 4; /* because of Acrobat error */ + 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) + { + /* 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 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 */ + } + + /* rotate */ + case ann_stamp: + case ann_freetext: + if (ann->orientate) + pdc_printf(p->out, "/Rotate %d", ann->orientate); + break; + + 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 (i = 0; i < na; i++) + { + annpar = (pdf_annot *) &pdc_vtr_at(annots, i, pdf_annot); + if (annpar->name != NULL && + !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 (k = 0; k < na; k++) + { + ann = (pdf_annot *) &pdc_vtr_at(annots, k, pdf_annot); + if (ann->atype == ann_fileattachment) + pdf_embed_file(p, ann->obj_id, ann->filename, ann->mimetype, + ann->filesize); + } +} + +/*****************************************************************************/ +/** deprecated historical annotation functions **/ +/*****************************************************************************/ + +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_CONV_WITHBOM); + strcat(optlist, name); + pdc_free(p->pdc, name); + + strcat(optlist, "}"); + + acthdl = pdf__create_action(p, type, optlist); + if (acthdl > -1) + { + if (p->pdc->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_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_CONV_WITHBOM); + + 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; + } + + attfile = pdc_fsearch_fopen(p->pdc, filename, NULL, "attachment ", 0); + if (attfile == NULL) + pdc_error(p->pdc, -1, 0, 0, 0, 0); + + pdc_lock_pvf(p->pdc, filename); + pdc_fclose(attfile); + + /* fill up annotation struct */ + ann = pdf_new_annot(p); + ann->atype = ann_fileattachment; + pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL); + pdf_insert_annot_params(p, ann); + ann->filename = pdc_strdup(p->pdc, filename); + ann->filesize = pdf_check_file(p, ann->filename, pdc_true); + 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 kopen) +{ + 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_new_annot(p); + ann->atype = ann_text; + pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL); + 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 = kopen; + 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_new_annot(p); + ann->atype = ann_link; + pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL); + pdf_insert_annot_params(p, ann); + if (p->pdc->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_new_annot(p); + ann->atype = ann_link; + pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL); + pdf_insert_annot_params(p, ann); + if (p->pdc->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_new_annot(p); + ann->atype = ann_link; + pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL); + pdf_insert_annot_params(p, ann); + ann->dest = pdf_parse_destination_optlist(p, optlist, page, pdf_locallink); + 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_new_annot(p); + ann->atype = ann_link; + pdf_init_rectangle(p, ann, llx, lly, urx, ury, NULL); + pdf_insert_annot_params(p, ann); + if (p->pdc->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; +} + + + diff --git a/src/pdflib/pdflib/p_block.c b/src/pdflib/pdflib/p_block.c new file mode 100644 index 0000000..24a55a8 --- /dev/null +++ b/src/pdflib/pdflib/p_block.c @@ -0,0 +1,26 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2007 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_block.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * Block processing routines (require the PDI library) + * + */ + +#define P_BLOCK_C + +#include "p_intern.h" +#include "p_color.h" +#include "p_font.h" +#include "p_image.h" +#include "p_defopt.h" + diff --git a/src/pdflib/pdflib/p_bmp.c b/src/pdflib/pdflib/p_bmp.c new file mode 100644 index 0000000..ac6a974 --- /dev/null +++ b/src/pdflib/pdflib/p_bmp.c @@ -0,0 +1,795 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_bmp.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * BMP processing for PDFlib + * + */ + +#include "p_intern.h" +#include "p_color.h" +#include "p_image.h" + +#ifndef PDF_BMP_SUPPORTED + +pdc_bool +pdf_is_BMP_file(PDF *p, pdc_file *fp) +{ + (void) p; + (void) fp; + + return pdc_false; +} + +int +pdf_process_BMP_data( + PDF *p, + int imageslot) +{ + pdf_image *image = &p->images[imageslot]; + + pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "BMP", 0, 0, 0); + + return -1; +} + +#else /* !PDF_BMP_SUPPORTED */ + +/* for documentation only */ +#if 0 + +/* BMP file header structure */ +typedef struct +{ + pdc_ushort bfType; /* Magic number for file */ + pdc_uint32 bfSize; /* Size of file */ + pdc_ushort bfReserved1; /* Reserved */ + pdc_ushort bfReserved2; /* ... */ + pdc_uint32 bfOffBits; /* Offset to bitmap data */ +} +BITMAPFILEHEADER; + +/* BMP file info structure */ +typedef struct +{ + pdc_uint32 biSize; /* Size of info header */ + pdc_sint32 biWidth; /* Width of image */ + pdc_sint32 biHeight; /* Height of image */ + pdc_ushort biPlanes; /* Number of color planes */ + pdc_ushort biBitCount; /* Number of bits per pixel */ + pdc_uint32 biCompression; /* Type of compression to use */ + pdc_uint32 biSizeImage; /* Size of image data */ + pdc_sint32 biXPelsPerMeter; /* X pixels per meter */ + pdc_sint32 biYPelsPerMeter; /* Y pixels per meter */ + pdc_uint32 biClrUsed; /* Number of colors used */ + pdc_uint32 biClrImportant; /* Number of important colors */ +} +BITMAPINFOHEADER; + +#endif + +#define PDF_GET_BYTE(pos) *pos, pos += sizeof(pdc_byte) +#define PDF_GET_SHORT(pos) pdc_get_le_short(pos), pos += sizeof(pdc_short) +#define PDF_GET_USHORT(pos) pdc_get_le_ushort(pos), pos += sizeof(pdc_ushort) +#define PDF_GET_LONG(pos) pdc_get_le_long(pos), pos += sizeof(pdc_sint32) +#define PDF_GET_ULONG(pos) pdc_get_le_ulong(pos), pos += sizeof(pdc_uint32) + +#define PDF_BMP_STRING "\102\115" /* "BM" */ + +#define PDF_BMP_RGB 0 /* No compression - straight BGR data */ +#define PDF_BMP_RLE8 1 /* 8-bit run-length compression */ +#define PDF_BMP_RLE4 2 /* 4-bit run-length compression */ +#define PDF_BMP_BITFIELDS 3 /* RGB bitmap with RGB masks */ + +#define PDF_BMP_FILE_HEADSIZE 14 /* File header size */ +#define PDF_BMP_INFO_HEAD2SIZE 12 /* Info header size BMP Version 2 */ +#define PDF_BMP_INFO_HEAD3SIZE 40 /* Info header size BMP Version 3 */ +#define PDF_BMP_INFO_HEAD4SIZE 108 /* Info header size BMP Version 4 */ + +static void +pdf_data_source_BMP_init(PDF *p, PDF_data_source *src) +{ + static const char *fn = "pdf_data_source_BMP_init"; + pdf_image *image = (pdf_image *) src->private_data; + + src->buffer_length = image->info.bmp.rowbytes_buf; + src->buffer_start = (pdc_byte *) + pdc_calloc(p->pdc, image->info.bmp.rowbytes_pad, fn); + src->bytes_available = image->info.bmp.rowbytes_pdf; + src->next_byte = src->buffer_start; +} + +static pdc_bool +pdf_data_source_BMP_fill(PDF *p, PDF_data_source *src) +{ + pdf_image *image = (pdf_image *) src->private_data; + int i, j; + + (void) p; + + if (image->info.bmp.bpp == 16) + { + if (image->info.bmp.pos < image->info.bmp.end) + { + pdc_ushort pixel, ppixel; + int ilast = image->info.bmp.rowbytes_buf - 3; + + i = 0; + for (j = 0; j < (int) image->info.bmp.rowbytes; j += 2) + { + pixel = PDF_GET_USHORT(image->info.bmp.pos); + + if (i <= ilast) + { + ppixel = (pixel & image->info.bmp.redmask); + ppixel = (ppixel >> image->info.bmp.redmove); + src->buffer_start[i] = (pdc_byte) ((ppixel * 255) / + image->info.bmp.redmax); + i++; + + ppixel = (pixel & image->info.bmp.greenmask); + ppixel = (ppixel >> image->info.bmp.greenmove); + src->buffer_start[i] = (pdc_byte) ((ppixel * 255) / + image->info.bmp.greenmax); + i++; + + ppixel = (pixel & image->info.bmp.bluemask); + ppixel = (ppixel >> image->info.bmp.bluemove); + src->buffer_start[i] = (pdc_byte) ((ppixel * 255) / + image->info.bmp.bluemax); + i++; + } + } + } + else + { + src->bytes_available = 0; + } + } + + else if (image->info.bmp.bpp == 32 || + image->info.bmp.compression == PDF_BMP_RGB) + { + size_t avail; + + /* Read 1 padded row from file */ + avail = pdc_fread(src->buffer_start, 1, image->info.bmp.rowbytes_pad, + image->fp); + if (avail > 0) + { + /* Fill up remaining bytes */ + if (avail < image->info.bmp.rowbytes_pad) + { + for (i = (int) avail; i < (int) src->buffer_length; i++) + src->buffer_start[i] = 0; + } + + if (image->colorspace == DeviceRGB) + { + /* Swap red and blue */ + if (image->info.bmp.bpp == 32) + { + pdc_uint32 pixel, ppixel; + pdc_byte *pos = src->buffer_start; + + i = 0; + for (j = 0; j < (int) image->info.bmp.rowbytes_buf; j += 4) + { + pixel = PDF_GET_ULONG(pos); + + ppixel = (pixel & image->info.bmp.redmask); + ppixel = (ppixel >> image->info.bmp.redmove); + src->buffer_start[i] = (pdc_byte) ((ppixel * 255) / + image->info.bmp.redmax); + i++; + + ppixel = (pixel & image->info.bmp.greenmask); + ppixel = (ppixel >> image->info.bmp.greenmove); + src->buffer_start[i] = (pdc_byte) ((ppixel * 255) / + image->info.bmp.greenmax); + i++; + + ppixel = (pixel & image->info.bmp.bluemask); + ppixel = (ppixel >> image->info.bmp.bluemove); + src->buffer_start[i] = (pdc_byte) ((ppixel * 255) / + image->info.bmp.bluemax); + i++; + } + } + else + { + for (j = 0; j < (int) image->info.bmp.rowbytes_buf; j += 3) + { + pdc_byte c = src->buffer_start[j]; + src->buffer_start[j] = src->buffer_start[j + 2]; + src->buffer_start[j + 2] = c; + } + } + } + } + else + { + src->bytes_available = 0; + } + } + + /* Compression methods RLE8 and RLE4 */ + else + { + int col = 0; + int fnibble = 1; + pdc_byte c, cc, ccc, cn[2], ccn; + + if (image->info.bmp.pos < image->info.bmp.end) + { + if (image->info.bmp.skiprows) + { + for (; col < (int) image->info.bmp.rowbytes; col++) + src->buffer_start[col] = 0; + image->info.bmp.skiprows--; + } + else + { + while (1) + { + c = *image->info.bmp.pos; + image->info.bmp.pos++; + if (image->info.bmp.pos >= image->info.bmp.end) + goto PDF_BMP_CORRUPT; + cc = *image->info.bmp.pos; + + if (c != 0) + { + /* Repeat c time pixel value */ + if (image->info.bmp.compression == PDF_BMP_RLE8) + { + for (i = 0; i < (int) c; i++) + { + if (col >= (int) image->info.bmp.rowbytes) + goto PDF_BMP_CORRUPT; + src->buffer_start[col] = cc; + col++; + } + } + else + { + cn[0] = (pdc_byte) ((cc & 0xF0) >> 4); + cn[1] = (pdc_byte) (cc & 0x0F); + for (i = 0; i < (int) c; i++) + { + if (col >= (int) image->info.bmp.rowbytes) + goto PDF_BMP_CORRUPT; + ccn = cn[i%2]; + if (fnibble) + { + fnibble = 0; + src->buffer_start[col] = + (pdc_byte) (ccn << 4); + } + else + { + fnibble = 1; + src->buffer_start[col] |= ccn; + col++; + } + } + } + } + else if (cc > 2) + { + /* cc different pixel values */ + if (image->info.bmp.compression == PDF_BMP_RLE8) + { + for (i = 0; i < (int) cc; i++) + { + image->info.bmp.pos++; + if (image->info.bmp.pos >= image->info.bmp.end) + goto PDF_BMP_CORRUPT; + if (col >= (int) image->info.bmp.rowbytes) + goto PDF_BMP_CORRUPT; + src->buffer_start[col] = *image->info.bmp.pos; + col++; + } + } + else + { + for (i = 0; i < (int) cc; i++) + { + if (!(i%2)) + { + image->info.bmp.pos++; + if (image->info.bmp.pos >= + image->info.bmp.end) + goto PDF_BMP_CORRUPT; + ccc = *image->info.bmp.pos; + cn[0] = (pdc_byte) ((ccc & 0xF0) >> 4); + cn[1] = (pdc_byte) (ccc & 0x0F); + } + if (col >= (int) image->info.bmp.rowbytes) + goto PDF_BMP_CORRUPT; + ccn = cn[i%2]; + if (fnibble) + { + fnibble = 0; + src->buffer_start[col] = + (pdc_byte) (ccn << 4); + } + else + { + fnibble = 1; + src->buffer_start[col] |= ccn; + col++; + } + } + if (cc % 2) cc++; + cc /= 2; + } + + /* Odd number of bytes */ + if (cc % 2) + image->info.bmp.pos++; + } + else if (cc < 2) + { + /* End of scan line or end of bitmap data*/ + for (; col < (int) image->info.bmp.rowbytes; col++) + src->buffer_start[col] = 0; + } + else if (cc == 2) + { + int cola; + + /* Run offset marker */ + if (image->info.bmp.pos >= image->info.bmp.end - 1) + goto PDF_BMP_CORRUPT; + image->info.bmp.pos++; + c = *image->info.bmp.pos; + image->info.bmp.pos++; + cc = *image->info.bmp.pos; + + /* Fill current row */ + cola = col; + for (; col < (int) image->info.bmp.rowbytes; col++) + src->buffer_start[col] = 0; + if (col - cola != (int) c) + goto PDF_BMP_CORRUPT; + + /* Number of rows to be skipped */ + image->info.bmp.skiprows = (size_t) cc; + } + + image->info.bmp.pos++; + if (col >= (int) image->info.bmp.rowbytes) + { + /* Skip end of scan line marker */ + if (image->info.bmp.pos < image->info.bmp.end - 1) + { + c = *image->info.bmp.pos; + cc = *(image->info.bmp.pos + 1); + if(cc == 0 && cc <= 1) + image->info.bmp.pos += 2; + } + break; + } + } + } + } + else + { + src->bytes_available = 0; + } + } + + return (src->bytes_available ? pdc_true : pdc_false); + + PDF_BMP_CORRUPT: + + image->corrupt = pdc_true; + src->bytes_available = 0; + return pdc_false; +} + +static void +pdf_data_source_BMP_terminate(PDF *p, PDF_data_source *src) +{ + pdf_image *image = (pdf_image *) src->private_data; + + pdc_free(p->pdc, (void *) src->buffer_start); + if (image->info.bmp.bitmap != NULL) + pdc_free(p->pdc, (void *) image->info.bmp.bitmap); +} + +pdc_bool +pdf_is_BMP_file(PDF *p, pdc_file *fp) +{ + pdc_byte buf[2]; + + pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type BMP...\n"); + + if (pdc_fread(buf, 1, 2, fp) < 2 || + strncmp((const char *) buf, PDF_BMP_STRING, 2) != 0) + { + pdc_fseek(fp, 0L, SEEK_SET); + return pdc_false; + } + return pdc_true; +} + +int +pdf_process_BMP_data( + PDF *p, + int imageslot) +{ + static const char *fn = "pdf_process_BMP_data"; + pdc_byte buf[256], *pos, *cmap, bdummy; + pdf_image *image = &p->images[imageslot]; + pdc_file *fp = image->fp; + pdc_uint32 uldummy, infosize = 0, offras = 0, planes = 0, bitmapsize = 0; + pdc_uint32 ncolors = 0, importcolors = 0, compression = PDF_BMP_RGB; + pdc_ushort usdummy, bpp = 0, bpp_pdf = 0; + pdc_sint32 width = 0, height = 0, dpi_x = 0, dpi_y = 0; + pdc_uint32 redmask = 0, greenmask = 0, bluemask = 0, ccmax; + size_t nbytes; + pdf_colorspace cs; + pdf_colormap colormap; + int i, slot, colsize = 0, errcode = 0; + + /* Error reading magic number or not a BMP file */ + if (pdf_is_BMP_file(p, image->fp) == pdc_false) + { + errcode = PDC_E_IO_BADFORMAT; + goto PDF_BMP_ERROR; + } + + /* read file header without FileType field + */ + /* Size field of info header */ + pos = &buf[2]; + nbytes = PDF_BMP_FILE_HEADSIZE - 2 + 4; + if (!PDC_OK_FREAD(fp, pos, nbytes)) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_BMP_ERROR; + } + uldummy = PDF_GET_ULONG(pos); + usdummy = PDF_GET_USHORT(pos); + usdummy = PDF_GET_USHORT(pos); + offras = PDF_GET_ULONG(pos); + infosize = PDF_GET_ULONG(pos); + + /* no support of later version than 3 */ + if (infosize != PDF_BMP_INFO_HEAD2SIZE && + infosize != PDF_BMP_INFO_HEAD3SIZE) + { + errcode = PDF_E_BMP_VERSUNSUPP; + goto PDF_BMP_ERROR; + } + + /* info header */ + pos = buf; + nbytes = infosize - 4; + if (!PDC_OK_FREAD(fp, pos, nbytes)) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_BMP_ERROR; + } + if (infosize == PDF_BMP_INFO_HEAD2SIZE) + { + width = PDF_GET_SHORT(pos); + height = PDF_GET_SHORT(pos); + planes = PDF_GET_USHORT(pos); + bpp = PDF_GET_USHORT(pos); + colsize = 3; + } + else if (infosize == PDF_BMP_INFO_HEAD3SIZE) + { + width = PDF_GET_LONG(pos); + height = PDF_GET_LONG(pos); + planes = PDF_GET_USHORT(pos); + bpp = PDF_GET_USHORT(pos); + compression = PDF_GET_ULONG(pos); + bitmapsize = PDF_GET_ULONG(pos); + dpi_x = PDF_GET_LONG(pos); + dpi_y = PDF_GET_LONG(pos); + ncolors = PDF_GET_ULONG(pos); + importcolors = PDF_GET_ULONG(pos); + colsize = 4; + } + + /* compressed BMP images by bitfields */ + if (compression == PDF_BMP_BITFIELDS) + { + pos = buf; + nbytes = 3 * sizeof(pdc_uint32); + if (!PDC_OK_FREAD(fp, pos, nbytes)) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_BMP_ERROR; + } + else + { + redmask = PDF_GET_ULONG(pos); + greenmask = PDF_GET_ULONG(pos); + bluemask = PDF_GET_ULONG(pos); + } + } + + pdc_logg_cond(p->pdc, 5, trc_image, + "\t\t\tinfosize = %d\n" + "\t\t\twidth = %d\n" + "\t\t\theight = %d\n" + "\t\t\tplanes = %d\n" + "\t\t\tbpp = %d\n" + "\t\t\tcompression = %d\n" + "\t\t\tbitmapsize = %d\n" + "\t\t\tdpi_x = %d\n" + "\t\t\tdpi_y = %d\n" + "\t\t\tncolors = %d\n" + "\t\t\timportcolors = %d\n" + "\t\t\tcolsize = %d\n" + "\t\t\tredmask = 0x%08X\n" + "\t\t\tgreenmask = 0x%08X\n" + "\t\t\tbluemask = 0x%08X\n", + infosize, width, height, planes, bpp, compression, + bitmapsize, dpi_x, dpi_y, ncolors, importcolors, + colsize, redmask, greenmask, bluemask); + + image->bpc = bpp; + image->width = width; + image->height = -height; + image->dpi_x = (pdc_scalar) (PDC_INCH2METER * dpi_x); + image->dpi_y = (pdc_scalar) (PDC_INCH2METER * dpi_y); + image->info.bmp.bpp = bpp; + bpp_pdf = bpp; + + /* color map only for bpp = 1, 4, 8 */ + if (bpp < 16) + { + if (!ncolors) + ncolors = (pdc_uint32) (1 << bpp); + if (ncolors > (offras - PDF_BMP_FILE_HEADSIZE - infosize) / colsize) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_BMP_ERROR; + } + + /* allocate and read color map */ + nbytes = colsize * ncolors; + cmap = (pdc_byte *) pdc_malloc(p->pdc, nbytes, fn); + if (!PDC_OK_FREAD(fp, cmap, nbytes)) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_BMP_ERROR; + } + + /* set color map (bgr) */ + pos = cmap; + for (i = 0; i < (int) ncolors; i++) + { + colormap[i][2] = PDF_GET_BYTE(pos); + colormap[i][1] = PDF_GET_BYTE(pos); + colormap[i][0] = PDF_GET_BYTE(pos); + if (infosize == PDF_BMP_INFO_HEAD3SIZE) + { + bdummy = PDF_GET_BYTE(pos); + } + } + pdc_free(p->pdc, cmap); + + pdc_logg_cond(p->pdc, 5, trc_image, + "\t\t\tcolor map with %d colors generated\n", + ncolors); + + image->components = 1; + + cs.type = Indexed; + cs.val.indexed.base = DeviceRGB; + cs.val.indexed.palette_size = (int) ncolors; + cs.val.indexed.colormap = &colormap; + cs.val.indexed.colormap_id = PDC_BAD_ID; + slot = pdf_add_colorspace(p, &cs, pdc_false); + + image->colorspace = slot; + + + } + else + { + image->colorspace = DeviceRGB; + image->components = 3; + image->bpc = 8; + if (bpp == 16) + { + bpp = 24; + bpp_pdf = 24; + if (compression == PDF_BMP_RGB) + { + redmask = 0x00007C00; + greenmask = 0x000003E0; + bluemask = 0x0000001F; + } + } + if (bpp == 32) + { + bpp_pdf = 24; + if (compression == PDF_BMP_RGB) + { + redmask = 0x00FF0000; + greenmask = 0x0000FF00; + bluemask = 0x000000FF; + } + } + + /* maximum and movement */ + if (image->info.bmp.bpp != 24) + { + for (i = 0; i < 32; i++) + { + ccmax = (redmask >> i); + if (ccmax & 0x00000001) + break; + } + image->info.bmp.redmask = redmask; + image->info.bmp.redmax = ccmax; + image->info.bmp.redmove = i; + + + for (i = 0; i < 32; i++) + { + ccmax = (greenmask >> i); + if (ccmax & 0x00000001) + break; + } + image->info.bmp.greenmask = greenmask; + image->info.bmp.greenmax = ccmax; + image->info.bmp.greenmove = i; + + for (i = 0; i < 32; i++) + { + ccmax = (bluemask >> i); + if (ccmax & 0x00000001) + break; + } + image->info.bmp.bluemask = bluemask; + image->info.bmp.bluemax = ccmax; + image->info.bmp.bluemove = i; + } + } + + if (image->imagemask) + { + if (image->components != 1) { + errcode = PDF_E_IMAGE_BADMASK; + goto PDF_BMP_ERROR; + } + + if (p->compatibility <= PDC_1_3) { + if (image->components != 1 || image->bpc != 1) { + errcode = PDF_E_IMAGE_MASK1BIT13; + goto PDF_BMP_ERROR; + } + } else if (image->bpc > 1) { + /* images with more than one bit will be written as /SMask, + * and don't require an /ImageMask entry. + */ + image->imagemask = pdc_false; + } + image->colorspace = DeviceGray; + } + + + + /* we invert this flag later */ + if (image->ignoremask) + image->transparent = pdc_true; + + /* number of bytes per row */ + image->info.bmp.rowbytes_pdf = (size_t) ((bpp_pdf * width + 7) / 8); + image->info.bmp.rowbytes_buf = (size_t) ((bpp * width + 7) / 8); + if (bpp == 4) + image->info.bmp.rowbytes = image->info.bmp.rowbytes_buf; + else if (image->info.bmp.bpp == 16) + image->info.bmp.rowbytes = + (size_t) (4 * ((image->info.bmp.bpp * width + 31) / 32)); + else + image->info.bmp.rowbytes = (size_t) ((bpp * width) / 8); + image->info.bmp.rowbytes_pad = (size_t) (4 * ((bpp * width + 31) / 32)); + image->info.bmp.compression = compression; + image->info.bmp.skiprows = 0; + image->info.bmp.bitmap = NULL; + + pdc_logg_cond(p->pdc, 5, trc_image, + "\t\t\tinternal variables:\n" + "\t\t\t\tbpp_pdf = %d\n" + "\t\t\t\trowbytes = %d\n" + "\t\t\t\trowbytes_buf = %d\n" + "\t\t\t\trowbytes_pdf = %d\n" + "\t\t\t\trowbytes_pad = %d\n", + bpp_pdf, image->info.bmp.rowbytes, image->info.bmp.rowbytes_buf, + image->info.bmp.rowbytes_pdf, image->info.bmp.rowbytes_pad); + + /* read whole bitmap */ + if (image->info.bmp.bpp < 24 && (image->info.bmp.bpp == 16 || + image->info.bmp.compression != PDF_BMP_RGB)) + { + if (!bitmapsize) + { + bitmapsize = (int) (pdc_file_size(fp) - pdc_ftell(fp)); + pdc_logg_cond(p->pdc, 5, trc_image, + "\t\t\tcalculated bitmapsize = %d\n", bitmapsize); + } + + image->info.bmp.bitmap = + (pdc_byte *) pdc_malloc(p->pdc, bitmapsize, fn); + if (!PDC_OK_FREAD(fp, image->info.bmp.bitmap, bitmapsize)) + { + pdc_free(p->pdc, (void *) image->info.bmp.bitmap); + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_BMP_ERROR; + } + image->info.bmp.pos = image->info.bmp.bitmap; + image->info.bmp.end = image->info.bmp.bitmap + bitmapsize; + } + + /* offset bitmap data */ + pdc_fseek(image->fp, (pdc_sint32) offras, SEEK_SET); + + /* put image data */ + image->src.init = pdf_data_source_BMP_init; + image->src.fill = pdf_data_source_BMP_fill; + image->src.terminate = pdf_data_source_BMP_terminate; + image->src.private_data = (void *) image; + + image->use_raw = pdc_false; + image->in_use = pdc_true; + + pdf_put_image(p, imageslot, pdc_true, pdc_true); + + if (image->corrupt) + errcode = PDF_E_IMAGE_CORRUPT; + else + return imageslot; + + PDF_BMP_ERROR: + { + const char *stemp = NULL; + + if (errcode) + stemp = pdf_get_image_filename(p, image); + + switch (errcode) + { + case PDF_E_IMAGE_MASK1BIT13: + case PDF_E_BMP_VERSUNSUPP: + case PDF_E_BMP_COMPUNSUPP: + case PDF_E_IMAGE_BADMASK: + pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0); + break; + + case PDC_E_IO_BADFORMAT: + pdc_set_errmsg(p->pdc, errcode, stemp, "BMP", 0, 0); + break; + + case PDF_E_IMAGE_CORRUPT: + pdc_set_errmsg(p->pdc, errcode, "BMP", stemp, 0, 0); + break; + + case 0: /* error code and message already set */ + break; + } + } + + return -1; +} + +#endif /* PDF_BMP_SUPPORTED */ + diff --git a/src/pdflib/pdflib/p_ccitt.c b/src/pdflib/pdflib/p_ccitt.c new file mode 100644 index 0000000..ce028b7 --- /dev/null +++ b/src/pdflib/pdflib/p_ccitt.c @@ -0,0 +1,186 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_ccitt.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * CCITT (Fax G3 and G4) processing for PDFlib + * + */ + +#include "p_intern.h" +#include "p_color.h" +#include "p_image.h" + +/* + * Do a bit-reversal of all bytes in the buffer. + * This is supported for some clients which provide + * CCITT-compressed data in a byte-reversed format. + */ + +static void +pdf_reverse_bit_order(unsigned char *buffer, size_t size) +{ + size_t i; + + /* table for fast byte reversal */ + static const pdc_byte reverse[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff + }; + + if (buffer != NULL) { + for (i = 0; i < size; i++) { + buffer[i] = reverse[buffer[i]]; + } + } +} + +static void +pdf_data_source_ccitt_raw_init(PDF *p, PDF_data_source *src) +{ + (void) p; + + src->bytes_available = 0; +} + +static pdc_bool +pdf_data_source_ccitt_raw_fill(PDF *p, PDF_data_source *src) +{ + pdf_image *image; + pdc_bool ismem; + + (void) p; + + if (src->bytes_available) + return pdc_false; + + image = (pdf_image *) src->private_data; + + src->buffer_start = (pdc_byte *) + pdc_freadall(image->fp, (size_t *) &src->buffer_length, &ismem); + + if (src->buffer_length == 0) + return pdc_false; + + src->bytes_available = src->buffer_length; + src->next_byte = src->buffer_start; + + if (image->info.ccitt.BitReverse) + pdf_reverse_bit_order(src->buffer_start, src->bytes_available); + + if (ismem) + src->buffer_length = 0; + + return pdc_true; +} + +static void +pdf_data_source_ccitt_raw_terminate(PDF *p, PDF_data_source *src) +{ + if (src->buffer_length) + pdc_free(p->pdc, (void *) src->buffer_start); +} + +static int +pdf_process_ccitt_raw_data(PDF *p, int imageslot) +{ + pdf_image *image = &p->images[imageslot]; + + /* check data length for raw uncompressed images */ + if (image->compression == pdf_comp_none && image->fp) + { + pdc_off_t length = pdc_file_size(image->fp); + if (length != (image->height_pixel * + ((image->width_pixel * image->components * image->bpc + 7) / 8))) + { + pdc_set_errmsg(p->pdc, PDF_E_RAW_ILLSIZE, + pdc_errprintf(p->pdc, "%lld", length), + pdf_get_image_filename(p, image), 0, 0); + return -1; + } + } + + + + + if (image->reference == pdf_ref_direct) + { + image->src.init = pdf_data_source_ccitt_raw_init; + image->src.fill = pdf_data_source_ccitt_raw_fill; + image->src.terminate = pdf_data_source_ccitt_raw_terminate; + image->src.private_data = (void *) image; + } + + image->in_use = pdc_true; /* mark slot as used */ + + if (image->doinline) + pdf_put_inline_image(p, imageslot); + else + pdf_put_image(p, imageslot, pdc_true, pdc_true); + + return imageslot; +} + +int +pdf_process_CCITT_data(PDF *p, int imageslot) +{ + pdf_image *image = &p->images[imageslot]; + + /* CCITT specific information */ + image->info.ccitt.BitReverse = image->bitreverse; + image->compression = pdf_comp_ccitt; + image->use_raw = pdc_true; + + return pdf_process_ccitt_raw_data(p, imageslot); +} + +int +pdf_process_RAW_data(PDF *p, int imageslot) +{ + pdf_image *image = &p->images[imageslot]; + + /* RAW specific information */ + image->info.ccitt.BitReverse = 0; + image->compression = pdf_comp_none; + + return pdf_process_ccitt_raw_data(p, imageslot); +} diff --git a/src/pdflib/pdflib/p_cid.c b/src/pdflib/pdflib/p_cid.c new file mode 100644 index 0000000..6d7766c --- /dev/null +++ b/src/pdflib/pdflib/p_cid.c @@ -0,0 +1,198 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_cid.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib CID font handling routines + * + */ + +#include "p_intern.h" +#include "p_font.h" + +#include "ft_cid.h" + + +/* +** Returns CMap slot and for standard CJK fonts: fontandle. +** +** pdc_invalidenc: predefined CMap not found +** pdc_cid or pdc_unicode: predefined CMap found +** +** *o_slot: +** >= 0: standard font found +** < 0: |error code| +*/ +pdc_bool +pdf_handle_cidfont(PDF *p, const char *fontname, const char *encoding, + pdc_encoding enc, pdf_font *font, int *o_slot, + pdc_encoding *newenc) +{ + const char *encapiname = encoding; + fnt_cmap_info cmapinfo; + const fnt_font_metric *fontmetric; + pdc_bool isidentity = pdc_false; + pdc_bool isstdfont = pdc_false; + pdc_bool iscjkcp = pdc_false; + int charcoll, slot; + + (void) enc; + (void) iscjkcp; + (void) encapiname; + + *o_slot = -1; + *newenc = pdc_invalidenc; + + + /* + * Look whether font is already in the cache. + * If font with same name and encoding is found, + * returns its slot number. + */ + + for (slot = 0; slot < p->fonts_number; slot++) + { + if (p->fonts[slot].ft.enc == pdc_cid && + p->fonts[slot].opt.fontstyle == font->opt.fontstyle && + p->fonts[slot].opt.embedding == font->opt.embedding && + !strcmp(p->fonts[slot].apiname, fontname) && + !strcmp(p->fonts[slot].ft.cmapname, encoding)) + { + *o_slot = slot; + *newenc = pdc_cid; + return pdc_true; + } + } + + /* Check the requested CMap */ + charcoll = fnt_get_predefined_cmap_info(encoding, &cmapinfo); + if (charcoll == (int) cc_none) + return pdc_true; + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tPredefined CMap \"%s\" found\n", encoding); + + /* Check whether this CMap is supported in the desired PDF version */ + if (cmapinfo.compatibility > p->compatibility) + { + pdc_set_errmsg(p->pdc, PDF_E_DOC_PDFVERSION, + encoding, pdc_get_pdfversion(p->pdc, p->compatibility), 0, 0); + return pdc_false; + } + + /* For Unicode capable language wrappers only UCS2/UTF16 CMaps allowed */ + if (cmapinfo.codesize == 0 && p->pdc->unicaplang) + { + pdc_set_errmsg(p->pdc, PDF_E_FONT_NEEDUCS2, 0, 0, 0, 0); + return pdc_false; + } + + /* Check whether the font name is among the known Acrobat CJK fonts */ + charcoll = fnt_get_preinstalled_cidfont(fontname, &fontmetric); + isidentity = cmapinfo.charcoll == (int) cc_identity; + if (isidentity) + cmapinfo.charcoll = abs(charcoll); + + /* known Acrobat CID font */ + if (charcoll != (int) cc_none) + { + pdc_logg_cond(p->pdc, 1, trc_font, + "\tStandard CJK font \"%s\" found\n", fontname); + + /* Selected CMap and known standard font don't match */ + if ((cmapinfo.charcoll != abs(charcoll) || + (charcoll == (int) cc_japanese && cmapinfo.codesize == -2))) + { + pdc_set_errmsg(p->pdc, PDF_E_CJK_UNSUPP_CHARCOLL, + 0, 0, 0, 0); + return pdc_false; + } + isstdfont = pdc_true; + + + /* Embedding not possible */ + if (font->opt.embedding) + { + pdc_set_errmsg(p->pdc, PDF_E_FONT_EMBEDCMAP, 0, 0, 0, 0); + return pdc_false; + } + } +#ifdef WIN32 + else if (iscjkcp && !p->pdc->ptfrun) + { + return pdc_true; + } +#endif + + + /* embedding check */ + if (!pdf_check_font_embedding(p, font, fontname)) + return pdc_false; + + /* supplement number, number of codes = (maximal) number of CIDs */ + font->supplement = fnt_get_supplement(&cmapinfo, p->compatibility); + if (isidentity) + font->supplement = -1; + font->ft.numcodes = fnt_get_maxcid(cmapinfo.charcoll, font->supplement) + 1; + + { + font->passthrough = pdc_true; + font->codesize = 0; + } + + /* CMap and default settings */ + font->ft.vertical = cmapinfo.vertical; + font->ft.cmapname = pdc_strdup(p->pdc, encoding); + if (font->outcmapname == NULL) + font->outcmapname = pdc_strdup(p->pdc, encoding); + font->ft.enc = pdc_cid; + font->iscidfont = pdc_true; + + /* Fill up the font struct */ + fnt_fill_font_metric(p->pdc, &font->ft, pdc_false, fontmetric); + + /* CID widths not available */ + font->widthsmissing = pdc_true; + + pdc_logg_cond(p->pdc, 1, trc_font, + "\n\t%s CJK font: \"%s\"\n\tPredefined CMap: \"%s\"\n" + "\tOrdering: \"%s\"\n\tSupplement: %d\n", + font->ft.isstdfont ? "Adobe Standard" : "Custom", fontname, encoding, + fnt_get_ordering_cid(font->ft.m.charcoll), font->supplement); + + *newenc = pdc_cid; + + return pdc_true; +} + +#ifdef PDF_CJKFONTWIDTHS_SUPPORTED +void +pdf_put_cidglyph_widths(PDF *p, pdf_font *font) +{ + if (font->opt.monospace) + { + if (font->opt.monospace != FNT_DEFAULT_CIDWIDTH) + pdc_printf(p->out, "/DW %d\n", font->opt.monospace); + } + else + { + const char **widths = fnt_get_cid_widths_array(p->pdc, &font->ft); + int i; + + pdc_puts(p->out, "/W"); + pdc_begin_array(p->out); + for (i = 0; i < FNT_CIDMETRIC_INCR - 1; i++) + pdc_puts(p->out, widths[i]); + pdc_end_array(p->out); + } +} +#endif /* PDF_CJKFONTWIDTHS_SUPPORTED */ diff --git a/src/pdflib/pdflib/p_color.c b/src/pdflib/pdflib/p_color.c new file mode 100644 index 0000000..d996d06 --- /dev/null +++ b/src/pdflib/pdflib/p_color.c @@ -0,0 +1,1130 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2007 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_color.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib color routines + * + */ + +#define P_COLOR_C + +#include "p_intern.h" +#include "p_color.h" + + +static const pdc_keyconn pdf_colortype_keylist[] = +{ + {"none", color_none}, + {"gray", color_gray}, + {"rgb", color_rgb}, + {"cmyk", color_cmyk}, + {"spotname", color_spotname}, + {"spot", color_spot}, + {"pattern", color_pattern}, + {"iccbasedgray", color_iccbasedgray}, + {"iccbasedrgb", color_iccbasedrgb}, + {"iccbasedcmyk", color_iccbasedcmyk}, + {"lab", color_lab}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_colorcomp_keylist[] = +{ + {"none", 0}, + {"gray", 1}, + {"rgb", 3}, + {"cmyk", 4}, + {"spotname", 2}, + {"spot", 2}, + {"pattern", 1}, + {"iccbasedgray", 1}, + {"iccbasedrgb", 3}, + {"iccbasedcmyk", 4}, + {"lab", 3}, + {NULL, 0} +}; + +/* ------------------------ color state ----------------------- */ + +struct pdf_cstate_s +{ + pdf_color fill; + pdf_color stroke; +}; + +void +pdf_init_cstate(PDF *p) +{ + static const char fn[] = "pdf_init_cstate"; + pdf_cstate *cstate; + + if (!p->curr_ppt->cstate) + { + p->curr_ppt->cstate = (pdf_cstate *) pdc_malloc(p->pdc, + PDF_MAX_SAVE_LEVEL * sizeof(pdf_cstate), fn); + } + + cstate = &p->curr_ppt->cstate[p->curr_ppt->sl]; + + cstate->fill.cs = DeviceGray; + cstate->fill.val.gray = 0.0; + + cstate->stroke.cs = DeviceGray; + cstate->stroke.val.gray = 0.0; +} + +void +pdf_save_cstate(PDF *p) +{ + pdf_ppt *ppt = p->curr_ppt; + int sl = ppt->sl; + + memcpy(&ppt->cstate[sl + 1], &ppt->cstate[sl], sizeof(pdf_cstate)); +} + +pdf_color * +pdf_get_cstate(PDF *p, pdf_drawmode mode) +{ + if (mode == pdf_fill) + return &p->curr_ppt->cstate[p->curr_ppt->sl].fill; + else + return &p->curr_ppt->cstate[p->curr_ppt->sl].stroke; +} + +void +pdf_cleanup_page_cstate(PDF *p, pdf_ppt *ppt) +{ + if (ppt->cstate != NULL) + pdc_free(p->pdc, ppt->cstate); + + ppt->cstate = NULL; +} + + + +/* Avoid wrong error messages due to rounding artifacts. + * This doesn't do any harm since we truncate to 5 decimal places anyway + * when producing PDF output. + */ +#define EPSILON ((1.0 + PDF_SMALLREAL)) + +static void pdf_check_color_values(PDF *p, pdf_colorspacetype type, + pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4); + +static int +pdf_color_components(PDF *p, int slot) +{ + static const char *fn = "pdf_color_components"; + pdf_colorspace *cs; + int components = 0; + + cs = &p->colorspaces[slot]; + + switch (cs->type) { + case DeviceGray: + case Indexed: + components = 1; + break; + + case DeviceRGB: + components = 3; + break; + + case DeviceCMYK: + components = 4; + break; + + case PatternCS: + if (cs->val.pattern.base == pdc_undef) + components = 0; /* PaintType 1: colored pattern */ + else + components = pdf_color_components(p, cs->val.pattern.base); + + default: + pdc_error(p->pdc, PDF_E_INT_BADCS, fn, + pdc_errprintf(p->pdc, "%d", slot), + pdc_errprintf(p->pdc, "%d", cs->type), 0); + } + + return components; +} /* pdf_color_components */ + +static void +pdf_write_color_values(PDF *p, pdf_color *color, pdf_drawmode drawmode) +{ + static const char *fn = "pdf_write_color_values"; + pdf_colorspace * cs = &p->colorspaces[color->cs]; + int cs_bias = p->curr_ppt->cs_bias; + int pt_bias = p->curr_ppt->pt_bias; + + switch (cs->type) + { + case DeviceGray: + { + pdc_printf(p->out, "%f", color->val.gray); + + if (drawmode == pdf_fill) + pdc_puts(p->out, " g\n"); + else if (drawmode == pdf_stroke) + pdc_puts(p->out, " G\n"); + + break; + } + + case DeviceRGB: + { + pdc_printf(p->out, "%f %f %f", + color->val.rgb.r, color->val.rgb.g, color->val.rgb.b); + + if (drawmode == pdf_fill) + pdc_puts(p->out, " rg\n"); + else if (drawmode == pdf_stroke) + pdc_puts(p->out, " RG\n"); + + break; + } + + case DeviceCMYK: + { + pdc_printf(p->out, "%f %f %f %f", + color->val.cmyk.c, color->val.cmyk.m, + color->val.cmyk.y, color->val.cmyk.k); + + if (drawmode == pdf_fill) + pdc_puts(p->out, " k\n"); + else if (drawmode == pdf_stroke) + pdc_puts(p->out, " K\n"); + + break; + } + + + case PatternCS: + { + if (drawmode == pdf_fill) + { + if (p->pattern[color->val.pattern].painttype == 1) + { + pdc_puts(p->out, "/Pattern cs"); + } + else if (p->pattern[color->val.pattern].painttype == 2) + { + pdc_printf(p->out, "/C%d cs ", cs_bias + color->cs); + pdf_write_color_values(p, + &p->curr_ppt->cstate[p->curr_ppt->sl].fill, pdf_none); + } + + pdc_printf(p->out, "/P%d scn\n", pt_bias + color->val.pattern); + } + else if (drawmode == pdf_stroke) + { + if (p->pattern[color->val.pattern].painttype == 1) + { + pdc_puts(p->out, "/Pattern CS"); + } + else if (p->pattern[color->val.pattern].painttype == 2) + { + pdc_printf(p->out, "/C%d CS ", cs_bias + color->cs); + pdf_write_color_values(p, + &p->curr_ppt->cstate[p->curr_ppt->sl].stroke, pdf_none); + } + + pdc_printf(p->out, "/P%d SCN\n", pt_bias + color->val.pattern); + } + + p->pattern[color->val.pattern].used_on_current_page = pdc_true; + break; + } + + + case Indexed: /* LATER */ + default: + pdc_error(p->pdc, PDF_E_INT_BADCS, fn, + pdc_errprintf(p->pdc, "%d", color->cs), + pdc_errprintf(p->pdc, "%d", cs->type), 0); + } +} /* pdf_write_color_values */ + +static pdc_bool +pdf_color_equal(PDF *p, pdf_color *c1, pdf_color *c2) +{ + pdf_colorspace *cs1; + + cs1 = &p->colorspaces[c1->cs]; + + if (c1->cs != c2->cs) + return pdc_false; + + switch (cs1->type) { + case DeviceGray: + return (c1->val.gray == c2->val.gray); + break; + + case DeviceRGB: + return (c1->val.rgb.r == c2->val.rgb.r && + c1->val.rgb.g == c2->val.rgb.g && + c1->val.rgb.b == c2->val.rgb.b); + break; + + case DeviceCMYK: + return (c1->val.cmyk.c == c2->val.cmyk.c && + c1->val.cmyk.m == c2->val.cmyk.m && + c1->val.cmyk.y == c2->val.cmyk.y && + c1->val.cmyk.k == c2->val.cmyk.k); + break; + + case Indexed: + return (c1->val.idx == c2->val.idx); + break; + + case PatternCS: + return (c1->val.pattern == c2->val.pattern); + break; + + + default: + break; + } + + return pdc_true; +} /* pdf_color_equal */ + +static pdc_bool +pdf_colorspace_equal(PDF *p, pdf_colorspace *cs1, pdf_colorspace *cs2) +{ + static const char *fn = "pdf_colorspace_equal"; + + if (cs1->type != cs2->type) + return pdc_false; + + switch (cs1->type) { + case DeviceGray: + case DeviceRGB: + case DeviceCMYK: + return pdc_true; + break; + + + case Indexed: + return ((cs1->val.indexed.base == cs2->val.indexed.base) && + (cs1->val.indexed.palette_size==cs2->val.indexed.palette_size)&& + (cs1->val.indexed.colormap_id != PDC_BAD_ID && + cs1->val.indexed.colormap_id == cs2->val.indexed.colormap_id)); + break; + + case PatternCS: + return (cs1->val.pattern.base == cs2->val.pattern.base); + break; + + + default: + pdc_error(p->pdc, PDF_E_INT_BADCS, fn, "(unknown)", + pdc_errprintf(p->pdc, "%d", cs1->type), 0); + } + + return pdc_false; +} /* pdf_colorspace_equal */ + +static void +pdf_grow_colorspaces(PDF *p) +{ + int i; + + p->colorspaces = (pdf_colorspace *) pdc_realloc(p->pdc, p->colorspaces, + sizeof(pdf_colorspace) * 2 * p->colorspaces_capacity, + "pdf_grow_colorspaces"); + + for (i = p->colorspaces_capacity; i < 2 * p->colorspaces_capacity; i++) { + p->colorspaces[i].used_on_current_page = pdc_false; + } + + p->colorspaces_capacity *= 2; +} + +int +pdf_add_colorspace(PDF *p, pdf_colorspace *cs, pdc_bool inuse) +{ + pdf_colorspace *cs_new; + static const char fn[] = "pdf_add_colorspace"; + int slot; + + for (slot = 0; slot < p->colorspaces_number; slot++) + { + if (pdf_colorspace_equal(p, &p->colorspaces[slot], cs)) + { + if (inuse) + p->colorspaces[slot].used_on_current_page = pdc_true; + return slot; + } + } + + slot = p->colorspaces_number; + + if (p->colorspaces_number >= p->colorspaces_capacity) + pdf_grow_colorspaces(p); + + cs_new = &p->colorspaces[slot]; + + cs_new->type = cs->type; + + /* don't allocate id for simple color spaces, since we don't write these */ + if (PDF_SIMPLE_COLORSPACE(cs)) { + cs_new->obj_id = PDC_BAD_ID; + cs_new->used_on_current_page = pdc_false; + + } else { + cs_new->obj_id = pdc_alloc_id(p->out); + cs_new->used_on_current_page = inuse; + } + + switch (cs_new->type) { + case DeviceGray: + case DeviceRGB: + case DeviceCMYK: + break; + + + case Indexed: + { + size_t palsize; /* palette size in bytes */ + + palsize = cs->val.indexed.palette_size * + pdf_color_components(p, cs->val.indexed.base); + + cs_new->val.indexed.base = cs->val.indexed.base; + cs_new->val.indexed.palette_size = cs->val.indexed.palette_size; + cs_new->val.indexed.colormap_id = pdc_alloc_id(p->out); + cs_new->val.indexed.colormap = + (pdf_colormap *) pdc_malloc(p->pdc, palsize, fn); + memcpy(cs_new->val.indexed.colormap, cs->val.indexed.colormap, palsize); + cs_new->val.indexed.colormap_done = pdc_false; + break; + + case PatternCS: + cs_new->val.pattern.base = cs->val.pattern.base; + break; + } + + + default: + pdc_error(p->pdc, PDF_E_INT_BADCS, fn, + pdc_errprintf(p->pdc, "%d", slot), + pdc_errprintf(p->pdc, "%d", cs_new->type), 0); + } + + p->colorspaces_number++; + + return slot; +} /* pdf_add_colorspace */ + + +static void +pdf_set_color_values(PDF *p, pdf_color *c, pdf_drawmode drawmode) +{ + pdf_color *current; + pdf_colorspace *cs; + + cs = &p->colorspaces[c->cs]; + + if (drawmode == pdf_stroke || drawmode == pdf_fillstroke) + { + current = &p->curr_ppt->cstate[p->curr_ppt->sl].stroke; + + if (!pdf_color_equal(p, current, c) || PDF_FORCE_OUTPUT()) + { + if (PDF_GET_STATE(p) != pdf_state_document) + pdf_write_color_values(p, c, pdf_stroke); + + *current = *c; + } + } + if (drawmode == pdf_fill || drawmode == pdf_fillstroke) + { + current = &p->curr_ppt->cstate[p->curr_ppt->sl].fill; + + if (!pdf_color_equal(p, current, c) || PDF_FORCE_OUTPUT()) + { + if (PDF_GET_STATE(p) != pdf_state_document) + pdf_write_color_values(p, c, pdf_fill); + + *current = *c; + } + } + + /* simple colorspaces don't get written */ + if (!PDF_SIMPLE_COLORSPACE(cs)) + cs->used_on_current_page = pdc_true; + +} /* pdf_set_color_values */ + +void +pdf_init_colorspaces(PDF *p) +{ + int i, slot; + pdf_colorspace cs; + + + p->colorspaces_number = 0; + p->colorspaces_capacity = COLORSPACES_CHUNKSIZE; + + p->colorspaces = (pdf_colorspace *) + pdc_malloc(p->pdc, sizeof(pdf_colorspace) * p->colorspaces_capacity, + "pdf_init_colorspaces"); + + for (i = 0; i < p->colorspaces_capacity; i++) { + p->colorspaces[i].used_on_current_page = pdc_false; + } + + /* + * Initialize a few slots with simple color spaces for easier use. + * These can be used without further ado: the slot number is identical + * to the enum value due to the ordering below. + */ + + cs.type = DeviceGray; + slot = pdf_add_colorspace(p, &cs, pdc_false); + cs.type = DeviceRGB; + slot = pdf_add_colorspace(p, &cs, pdc_false); + cs.type = DeviceCMYK; + slot = pdf_add_colorspace(p, &cs, pdc_false); + +} /* pdf_init_colorspaces */ + +void +pdf_write_page_colorspaces(PDF *p) +{ + int i, total = 0; + int bias = p->curr_ppt->cs_bias; + + for (i = 0; i < p->colorspaces_number; i++) + if (p->colorspaces[i].used_on_current_page) + total++; + + if (total > 0 || bias + ) + { + pdc_puts(p->out, "/ColorSpace"); + pdc_begin_dict(p->out); + + if (total > 0) + { + for (i = 0; i < p->colorspaces_number; i++) + { + pdf_colorspace *cs = &p->colorspaces[i]; + + if (cs->used_on_current_page) + { + cs->used_on_current_page = pdc_false; /* reset */ + + /* don't write simple color spaces as resource */ + if (!PDF_SIMPLE_COLORSPACE(cs)) + { + pdc_printf(p->out, "/C%d", bias + i); + pdc_objref(p->out, "", cs->obj_id); + } + } + } + } + + + if (!bias) + pdc_end_dict(p->out); /* color space names */ + } +} /* pdf_write_page_colorspaces */ + +void +pdf_get_page_colorspaces(PDF *p, pdf_reslist *rl) +{ + int i; + + for (i = 0; i < p->colorspaces_number; i++) + { + pdf_colorspace *cs = &p->colorspaces[i]; + + if (cs->used_on_current_page) + { + cs->used_on_current_page = pdc_false; + + if (!PDF_SIMPLE_COLORSPACE(cs)) + pdf_add_reslist(p, rl, i); + } + } +} + +void +pdf_mark_page_colorspace(PDF *p, int n) +{ + p->colorspaces[n].used_on_current_page = pdc_true; +} + +void +pdf_write_function_dict(PDF *p, pdf_color *c0, pdf_color *c1, pdc_scalar N) +{ + static const char *fn = "pdf_write_function_dict"; + + pdf_colorspace *cs; + + cs = &p->colorspaces[c1->cs]; + + pdc_begin_dict(p->out); /* function dict */ + + pdc_puts(p->out, "/FunctionType 2\n"); + pdc_puts(p->out, "/Domain[0 1]\n"); + pdc_printf(p->out, "/N %f\n", N); + + switch (cs->type) { + + case DeviceGray: + pdc_puts(p->out, "/Range[0 1]\n"); + if (c0->val.gray != 0) pdc_printf(p->out, "/C0[%f]\n", c0->val.gray); + if (c1->val.gray != 1) pdc_printf(p->out, "/C1[%f]", c1->val.gray); + break; + + case DeviceRGB: + pdc_puts(p->out, "/Range[0 1 0 1 0 1]\n"); + pdc_printf(p->out, "/C0[%f %f %f]\n", + c0->val.rgb.r, c0->val.rgb.g, c0->val.rgb.b); + pdc_printf(p->out, "/C1[%f %f %f]", + c1->val.rgb.r, c1->val.rgb.g, c1->val.rgb.b); + break; + + case DeviceCMYK: + pdc_puts(p->out, "/Range[0 1 0 1 0 1 0 1]\n"); + pdc_printf(p->out, "/C0[%f %f %f %f]\n", + c0->val.cmyk.c, c0->val.cmyk.m, c0->val.cmyk.y, c0->val.cmyk.k); + pdc_printf(p->out, "/C1[%f %f %f %f]", + c1->val.cmyk.c, c1->val.cmyk.m, c1->val.cmyk.y, c1->val.cmyk.k); + break; + + + default: + pdc_error(p->pdc, PDF_E_INT_BADCS, fn, "(unknown)", + pdc_errprintf(p->pdc, "%d", cs->type), 0); + } + + pdc_end_dict_c(p->out); /* function dict */ +} /* pdf_write_function_dict */ + +void +pdf_write_colormap(PDF *p, int slot) +{ + PDF_data_source src; + pdf_colorspace *cs, *base; + pdc_id length_id; + + cs = &p->colorspaces[slot]; + + if (cs->type != Indexed || cs->val.indexed.colormap_done == pdc_true) + return; + + base = &p->colorspaces[cs->val.indexed.base]; + + pdc_begin_obj(p->out, cs->val.indexed.colormap_id); /* colormap object */ + pdc_begin_dict(p->out); + + if (pdc_get_compresslevel(p->out)) + pdc_puts(p->out, "/Filter/FlateDecode\n"); + + /* Length of colormap object */ + length_id = pdc_alloc_id(p->out); + pdc_objref(p->out, "/Length", length_id); + pdc_end_dict(p->out); + + src.init = NULL; + src.fill = pdf_data_source_buf_fill; + src.terminate = NULL; + + src.buffer_start = (unsigned char *) cs->val.indexed.colormap; + + src.buffer_length = (size_t) (cs->val.indexed.palette_size * + pdf_color_components(p, cs->val.indexed.base)); + + src.bytes_available = 0; + src.next_byte = NULL; + + /* Write colormap data */ + pdf_copy_stream(p, &src, pdc_true); /* colormap data */ + + pdc_end_obj(p->out); /* colormap object */ + + pdc_put_pdfstreamlength(p->out, length_id); + + /* free the colormap now that it's written */ + pdc_free(p->pdc, cs->val.indexed.colormap); + cs->val.indexed.colormap = NULL; + cs->val.indexed.colormap_done = pdc_true; +} /* pdf_write_colormap */ + +void +pdf_write_colorspace(PDF *p, int slot, pdc_bool direct) +{ + static const char *fn = "pdf_write_colorspace"; + + pdf_colorspace *cs; + int base; + + if (slot < 0 || slot >= p->colorspaces_number) + pdc_error(p->pdc, PDF_E_INT_BADCS, fn, + pdc_errprintf(p->pdc, "%d", slot), + "(unknown)", 0); + + cs = &p->colorspaces[slot]; + + /* we always write simple colorspaces directly */ + if (PDF_SIMPLE_COLORSPACE(cs)) + direct = pdc_true; + + if (!direct) { + pdc_objref_c(p->out, cs->obj_id); + return; + } + + switch (cs->type) { + case DeviceGray: + pdc_printf(p->out, "/DeviceGray"); + break; + + case DeviceRGB: + pdc_printf(p->out, "/DeviceRGB"); + break; + + case DeviceCMYK: + pdc_printf(p->out, "/DeviceCMYK"); + break; + + + case Indexed: + base = cs->val.indexed.base; + + pdc_begin_array(p->out); + pdc_puts(p->out, "/Indexed"); + + pdf_write_colorspace(p, base, pdc_false); + + pdc_printf(p->out, " %d", cs->val.indexed.palette_size - 1); + pdc_objref_c(p->out, cs->val.indexed.colormap_id); + pdc_end_array_c(p->out); + break; + + case PatternCS: + pdc_begin_array(p->out); + pdc_printf(p->out, "/Pattern"); + pdf_write_colorspace(p, cs->val.pattern.base, pdc_false); + pdc_end_array(p->out); + break; + + default: + pdc_error(p->pdc, PDF_E_INT_BADCS, fn, + pdc_errprintf(p->pdc, "%d", slot), + pdc_errprintf(p->pdc, "%d", cs->type), 0); + } +} /* pdf_write_colorspace */ + +void +pdf_write_doc_colorspaces(PDF *p) +{ + int i; + + for (i = 0; i < p->colorspaces_number; i++) { + pdf_colorspace *cs = &p->colorspaces[i]; + + /* don't write simple color spaces as resource */ + if (PDF_SIMPLE_COLORSPACE(cs)) + continue; + + pdc_begin_obj(p->out, cs->obj_id); + pdf_write_colorspace(p, i, pdc_true); + pdc_puts(p->out, "\n"); + pdc_end_obj(p->out); /* color space resource */ + + pdf_write_colormap(p, i); /* write pending colormaps */ + } +} + +void +pdf_cleanup_colorspaces(PDF *p) +{ + static const char *fn = "pdf_cleanup_colorspaces"; + + int i; + + if (!p->colorspaces) + return; + + for (i = 0; i < p->colorspaces_number; i++) { + pdf_colorspace *cs = &p->colorspaces[i];; + + switch (cs->type) { + case DeviceGray: + case DeviceRGB: + case DeviceCMYK: + case PatternCS: + break; + + case Indexed: + if (cs->val.indexed.colormap) + pdc_free(p->pdc, cs->val.indexed.colormap); + break; + + + default: + pdc_error(p->pdc, PDF_E_INT_BADCS, fn, + pdc_errprintf(p->pdc, "%d", i), + pdc_errprintf(p->pdc, "%d", cs->type), 0); + } + } + + pdc_free(p->pdc, p->colorspaces); + p->colorspaces = NULL; +} + + + + + +static void +pdf_check_color_values( + PDF *p, + pdf_colorspacetype type, + pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4) +{ + switch (type) { + case DeviceGray: + pdc_check_number_limits(p->pdc, "c1", c1, 0.0, EPSILON); + break; + + case DeviceRGB: + pdc_check_number_limits(p->pdc, "c1", c1, 0.0, EPSILON); + pdc_check_number_limits(p->pdc, "c2", c2, 0.0, EPSILON); + pdc_check_number_limits(p->pdc, "c3", c3, 0.0, EPSILON); + + break; + + case DeviceCMYK: + pdc_check_number_limits(p->pdc, "c1", c1, 0.0, EPSILON); + pdc_check_number_limits(p->pdc, "c2", c2, 0.0, EPSILON); + pdc_check_number_limits(p->pdc, "c3", c3, 0.0, EPSILON); + pdc_check_number_limits(p->pdc, "c4", c4, 0.0, EPSILON); + break; + + + + case PatternCS: + pdf_check_handle(p, (int) c1, pdc_patternhandle); + if (c1 == p->pattern_number - 1 && PDF_GET_STATE(p) & pdf_state_pattern) + { + pdc_error(p->pdc, PDF_E_PATTERN_SELF, 0, 0, 0, 0); + } + break; + + case Separation: + pdf_check_handle(p, (int) c1, pdc_colorhandle); + pdc_check_number_limits(p->pdc, "c2", c2, 0.0, EPSILON); + break; + + case Indexed: + default: + break; + } +} /* pdf_check_color_values */ + +static void +pdf_setcolor_internal(PDF *p, int drawmode, int colortype, + pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4, + pdf_color *fcolor) +{ + pdf_color c; + pdf_colorspace cs; + + /* TODO: synchronize the PDF/X checks below with pdf_check_pdfx_colorspaces + */ + switch (colortype) + { + case color_gray: + cs.type = DeviceGray; + c.cs = cs.type; + c.val.gray = c1; + pdf_check_color_values(p, cs.type, c1, c2, c3, c4); + break; + + case color_rgb: + cs.type = DeviceRGB; + c.cs = cs.type; + c.val.rgb.r = c1; + c.val.rgb.g = c2; + c.val.rgb.b = c3; + pdf_check_color_values(p, cs.type, c1, c2, c3, c4); + break; + + case color_cmyk: + cs.type = DeviceCMYK; + c.cs = cs.type; + c.val.cmyk.c = c1; + c.val.cmyk.m = c2; + c.val.cmyk.y = c3; + c.val.cmyk.k = c4; + pdf_check_color_values(p, cs.type, c1, c2, c3, c4); + break; + + + case color_pattern: + cs.type = PatternCS; + if (p->pdc->hastobepos) c1 -= 1; + c.val.pattern = (int) c1; + pdf_check_color_values(p, cs.type, c1, c2, c3, c4); + + if (p->pattern[c.val.pattern].painttype == 1) + { + cs.val.pattern.base = pdc_undef; + c.cs = pdf_add_colorspace(p, &cs, pdc_false); + } + else + { + cs.val.pattern.base = p->curr_ppt->cstate[p->curr_ppt->sl].fill.cs; + c.cs = pdf_add_colorspace(p, &cs, pdc_true); + } + break; + + } + + + + if (fcolor == NULL) + pdf_set_color_values(p, &c, (pdf_drawmode) drawmode); + else + *fcolor = c; +} + +static const pdc_keyconn pdf_fstype_keylist[] = +{ + {"stroke", pdf_stroke}, + {"fill", pdf_fill}, + {"fillstroke", pdf_stroke | pdf_fill}, + {"both", pdf_stroke | pdf_fill}, + {NULL, 0} +}; + +void +pdf__setcolor( + PDF *p, + const char *fstype, + const char *colorspace, + pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4) +{ + int drawmode = (int) pdf_none; + int colortype; + + if (!fstype || !*fstype) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fstype", 0, 0, 0); + + if (!colorspace || !*colorspace) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "colorspace", 0, 0, 0); + + drawmode = pdc_get_keycode_ci(fstype, pdf_fstype_keylist); + if (drawmode == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_ILLARG_STRING, "fstype", fstype, 0, 0); + + colortype = pdc_get_keycode_ci(colorspace, pdf_colortype_keylist); + if (colortype == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_ILLARG_STRING, "colorspace", colorspace, 0, 0); + + pdf_setcolor_internal(p, drawmode, colortype, c1, c2, c3, c4, NULL); +} + +void +pdf_set_default_color(PDF *p, pdc_bool reset) +{ + + + + if (reset) + pdf__setcolor(p, "fillstroke", "gray", 0, 0, 0, 0); +} + + +void +pdf_parse_coloropt(PDF *p, const char *optname, char **optvalue, int ns, + int maxtype, pdf_coloropt *c) +{ + int errcode = 0; + const char *stemp = NULL; + + if (ns) + { + int i, j, n, iz = 0; + double dz; + + c->type = pdc_get_keycode_ci(optvalue[0], pdf_colortype_keylist); + if (c->type == PDC_KEY_NOTFOUND || c->type > maxtype) + { + stemp = pdc_errprintf(p->pdc, + "%.*s", PDC_ERR_MAXSTRLEN, optvalue[0]); + errcode = PDC_E_OPT_ILLKEYWORD; + goto PDF_COLOPT_ERROR; + } + + if (c->type == (int) color_spotname || c->type == (int) color_spot) + { + errcode = PDF_E_UNSUPP_SPOTCOLOR; + goto PDF_COLOPT_ERROR; + } + + n = 1 + pdc_get_keycode_ci(optvalue[0], pdf_colorcomp_keylist); + if (n != ns) + { + if (c->type == (int) color_spotname) + n++; + if (n != ns) + { + stemp = pdc_errprintf(p->pdc, "%d", n); + errcode = n < ns ? PDC_E_OPT_TOOMANYVALUES : + PDC_E_OPT_TOOFEWVALUES; + goto PDF_COLOPT_ERROR; + } + } + + for (i = 0; i < 4; i++) + { + j = i + 1; + if (i >= ns - 1) + { + if (!i || c->type != (int) color_gray) + c->value[i] = 0.0; + else + c->value[i] = c->value[0]; + } + else + { + if (!i && (c->type >= (int) color_spotname && + c->type <= (int) color_pattern)) + { + c->name[0] =0; + if (pdc_str2integer(optvalue[j], 0, (pdc_sint32 *) &iz) == + pdc_false) + { + { + stemp = pdc_errprintf(p->pdc, "%.*s", + PDC_ERR_MAXSTRLEN, optvalue[j]); + errcode = PDC_E_OPT_ILLNUMBER; + goto PDF_COLOPT_ERROR; + } + } + c->value[i] = iz; + } + else + { + if (pdc_str2double(optvalue[j], &dz) == pdc_false) + { + stemp = pdc_errprintf(p->pdc, "%.*s", + PDC_ERR_MAXSTRLEN, optvalue[j]); + errcode = PDC_E_OPT_ILLNUMBER; + goto PDF_COLOPT_ERROR; + } + else + c->value[i] = dz; + } + } + } + + if (c->type <= (int) color_cmyk) + { + for (i = 0; i < ns - 1; i++) + { + if (c->value[i] < 0 || c->value[i] > EPSILON) + { + stemp = pdc_errprintf(p->pdc, "%f", c->value[i]); + errcode = PDC_E_OPT_ILLNUMBER; + goto PDF_COLOPT_ERROR; + } + } + } + } + + PDF_COLOPT_ERROR: + + if (errcode) + pdc_error(p->pdc, errcode, optname, stemp, 0, 0); +} + + +void +pdf_set_coloropt(PDF *p, int drawmode, pdf_coloropt *c) +{ + if (c->type == (int) color_none) + return; + if (c->type == (int) color_spotname) + { + pdc_error(p->pdc, PDF_E_UNSUPP_SPOTCOLOR, 0, 0, 0, 0); + } + + pdf_setcolor_internal(p, drawmode, c->type, + c->value[0], c->value[1], c->value[2], c->value[3], + NULL); +} + +void +pdf_init_coloropt(PDF *p, pdf_coloropt *c) +{ + (void) p; + + { + c->name[0] = 0; + c->type = (int) color_gray; + c->value[0] = 0; + c->value[1] = 0; + c->value[2] = 0; + c->value[3] = 0; + } +} + +void +pdf_logg_coloropt(PDF *p, pdf_coloropt *c, pdc_bool newline) +{ + const char *keyword = + pdc_get_keyword((int) c->type, pdf_colortype_keylist); + + pdc_logg(p->pdc, "{%s ", keyword); + + switch (c->type) + { + case color_gray: + case color_iccbasedgray: + case color_pattern: + case color_spot: + pdc_logg(p->pdc, "%g}", c->value[0]); + break; + + case color_rgb: + case color_iccbasedrgb: + case color_lab: + pdc_logg(p->pdc, "%g %g %g}", c->value[0], c->value[1], c->value[2]); + break; + + case color_cmyk: + case color_iccbasedcmyk: + pdc_logg(p->pdc, "%g %g %g %g}", c->value[0], c->value[1], + c->value[2], c->value[3]); + break; + + case color_spotname: + pdc_logg(p->pdc, "{%s} %g}", c->name, c->value[0]); + break; + + default: + pdc_logg(p->pdc, "}"); + break; + } + + if (newline) + pdc_logg(p->pdc, "\n"); +} diff --git a/src/pdflib/pdflib/p_color.h b/src/pdflib/pdflib/p_color.h new file mode 100644 index 0000000..d8a0fa8 --- /dev/null +++ b/src/pdflib/pdflib/p_color.h @@ -0,0 +1,109 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_color.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib color definitions + * + */ + +#ifndef P_COLOR_H +#define P_COLOR_H + +/* + * These are treated specially in the global colorspace list, and are not + * written as /ColorSpace resource since we always specify them directly. + * Pattern colorspace with base == pdc_undef means PaintType == 1. + */ +#define PDF_SIMPLE_COLORSPACE(cs) \ + ((cs)->type == DeviceGray || \ + (cs)->type == DeviceRGB || \ + (cs)->type == DeviceCMYK || \ + ((cs)->type == PatternCS && cs->val.pattern.base == pdc_undef)) + + +struct pdf_pattern_s { + pdc_id obj_id; /* object id of this pattern */ + int painttype; /* colored (1) or uncolored (2) */ + pdc_bool used_on_current_page; /* this pattern used on current page */ +}; + +typedef pdc_byte pdf_colormap[256][3]; + +typedef struct { + int cs; /* slot of underlying color space */ + + union { + pdc_scalar gray; /* DeviceGray */ + int pattern; /* Pattern */ + int idx; /* Indexed */ + struct { /* DeviceRGB */ + pdc_scalar r; + pdc_scalar g; + pdc_scalar b; + } rgb; + struct { /* DeviceCMYK */ + pdc_scalar c; + pdc_scalar m; + pdc_scalar y; + pdc_scalar k; + } cmyk; + } val; +} pdf_color; + +struct pdf_colorspace_s { + pdf_colorspacetype type; /* color space type */ + + union { + struct { /* Indexed */ + int base; /* base color space */ + pdf_colormap *colormap; /* pointer to colormap */ + pdc_bool colormap_done; /* colormap already written to output */ + int palette_size; /* # of palette entries (not bytes!) */ + pdc_id colormap_id; /* object id of colormap */ + } indexed; + + struct { /* Pattern */ + int base; /* base color space for PaintType 2 */ + } pattern; + + } val; + + pdc_id obj_id; /* object id of this colorspace */ + pdc_bool used_on_current_page; /* this resource used on current page */ +}; + +/* "color" option */ +typedef struct +{ + char name[PDF_MAX_NAMESTRING + 1]; + int type; + pdc_scalar value[4]; +} +pdf_coloropt; + + +pdf_color *pdf_get_cstate(PDF *p, pdf_drawmode mode); +void pdf_get_page_colorspaces(PDF *p, pdf_reslist *rl); +void pdf_write_function_dict(PDF *p, pdf_color *c0, pdf_color *c1, + pdc_scalar N); +int pdf_add_colorspace(PDF *p, pdf_colorspace *cs, pdc_bool inuse); +void pdf_parse_coloropt(PDF *p, const char *optname, char **optvalue, int ns, + int maxtype, pdf_coloropt *c); +void pdf_set_coloropt(PDF *p, int drawmode, pdf_coloropt *c); +void pdf_init_coloropt(PDF *p, pdf_coloropt *c); +void pdf_logg_coloropt(PDF *p, pdf_coloropt *c, pdc_bool newline); + + + +#endif /* P_COLOR_H */ + diff --git a/src/pdflib/pdflib/p_defopt.h b/src/pdflib/pdflib/p_defopt.h new file mode 100644 index 0000000..6c4a862 --- /dev/null +++ b/src/pdflib/pdflib/p_defopt.h @@ -0,0 +1,494 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_defopt.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib shared option definitions and structures + * + */ + +#ifndef P_DEFOPT_H +#define P_DEFOPT_H + +#define PDF_KEEP_TEXTLEN (1L<<0) /* keep text length */ +#define PDF_KEEP_CONTROL (1L<<1) /* keep special control character */ +#define PDF_KEEP_UNICODE (1L<<2) /* keep Unicode text */ +#define PDF_FORCE_NEWALLOC (1L<<3) /* force alloc for new text */ +#define PDF_USE_TMPALLOC (1L<<4) /* use temporary memory */ + +#define PDF_RETURN_BOXEMPTY "_boxempty" +#define PDF_RETURN_BOXFULL "_boxfull" +#define PDF_RETURN_NEXTPAGE "_nextpage" +#define PDF_RETURN_STOP "_stop" + +typedef enum +{ + is_block = (1L<<0), + is_image = (1L<<1), + is_textline = (1L<<2), + is_textflow = (1L<<3), + is_inline = (1L<<4) +} +pdf_elemflags; + +struct pdf_text_options_s +{ + pdc_scalar charspacing; + pdc_scalar charspacing_pc; + pdf_coloropt fillcolor; + int font; + pdc_scalar fontsize; + pdc_scalar fontsize_pc; + int fontsize_st; + pdc_bool glyphwarning; + pdc_scalar horizscaling; + pdc_scalar italicangle; + pdc_bool fakebold; + pdc_bool kerning; + unsigned int mask; + unsigned int pcmask; + unsigned int fontset; + pdc_bool overline; + pdc_bool strikeout; + pdf_coloropt strokecolor; + pdc_scalar strokewidth; + pdc_scalar dasharray[2]; + char *text; + int textlen; + pdc_text_format textformat; + int textrendering; + pdc_scalar textrise; + pdc_scalar textrise_pc; + pdc_scalar leading; + pdc_scalar leading_pc; + pdc_bool underline; + pdc_scalar wordspacing; + pdc_scalar wordspacing_pc; + pdc_scalar underlinewidth; + pdc_scalar underlineposition; + pdc_scalar *xadvancelist; + int nglyphs; + char *link; + char *linktype; + pdc_bool charref; + pdc_bool escapesequence; + pdc_glyphcheck glyphcheck; +}; + +typedef enum +{ + xo_filename, + xo_ignoreorientation, + xo_imagewarning, + xo_dpi, + xo_page, + xo_scale +} +pdf_xobject_optflags; + +typedef struct +{ + pdc_bool adjustpage; + pdc_bool blind; + char *filename; + int flags; + pdc_bool imagewarning; + pdc_bool ignoreorientation; + unsigned int mask; + int im; + int page; + pdc_scalar dpi[2]; + pdc_scalar scale[2]; +} +pdf_xobject_options; + +typedef enum +{ + fit_boxsize, + fit_fitmethod, + fit_margin, + fit_shrinklimit, + fit_position, + fit_orientate, + fit_rotate, + fit_matchbox, + fit_alignchar, + fit_refpoint +} +pdf_fit_optflags; + + +typedef struct +{ + pdc_scalar boxsize[2]; + pdc_fitmethod fitmethod; + int flags; + pdc_scalar margin[2]; + unsigned int mask; + unsigned int pcmask; + pdc_scalar shrinklimit; + pdc_scalar position[2]; + int orientate; + pdc_scalar refpoint[2]; + pdc_scalar rotate; + pdc_bool showborder; + pdf_mbox *matchbox; + pdc_ushort alignchar; +} +pdf_fit_options; + +typedef struct pdf_fittext_s pdf_fittext; + + +/* font option definitions */ + +#define PDF_KERNING_FLAG PDC_OPT_UNSUPP +#define PDF_SUBSETTING_FLAG PDC_OPT_UNSUPP +#define PDF_AUTOCIDFONT_FLAG PDC_OPT_UNSUPP +#define PDF_EMBEDOPENTYPE_FLAG PDC_OPT_UNSUPP +#define PDF_CHARREF_FLAG PDC_OPT_UNSUPP +#define PDF_ESCAPESEQU_FLAG PDC_OPT_UNSUPP +#define PDF_GLYPHCHECK_FLAG PDC_OPT_UNSUPP +#define PDF_VERTICAL_FLAG PDC_OPT_UNSUPP +#define PDF_REPLCHAR_FLAG PDC_OPT_UNSUPP +#define PDF_KEEPNATIVE_FLAG PDC_OPT_UNSUPP +#define PDF_STAMP_FLAG PDC_OPT_UNSUPP +#define PDF_LEADER_FLAG PDC_OPT_UNSUPP + +#define PDF_METADATA_FLAG PDC_OPT_UNSUPP + +#define PDF_CLIPPATH_FLAG PDC_OPT_UNSUPP + +#define PDF_FONT_OPTIONS1 \ +\ + {"encoding", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDF_MAX_NAMESTRING, NULL}, \ +\ + {"fontname", pdc_stringlist, PDC_OPT_NONE | PDC_OPT_CONVUTF8, 1, 1, \ + 1.0, PDF_MAX_FONTNAME, NULL}, \ + + +#define PDF_FONT_OPTIONS2 \ +\ + {"autocidfont", pdc_booleanlist, PDF_AUTOCIDFONT_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"autosubsetting", pdc_booleanlist, PDF_SUBSETTING_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"embedding", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"fontstyle", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, pdf_fontstyle_pdfkeylist}, \ +\ + /* deprecated */ \ + {"fontwarning", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"monospace", pdc_integerlist, PDC_OPT_NONE, 1, 1, \ + 1.0, FNT_MAX_METRICS, NULL}, \ +\ + {"ascender", pdc_integerlist, PDC_OPT_NONE, 1, 1, \ + -FNT_MAX_METRICS, FNT_MAX_METRICS, NULL}, \ +\ + {"descender", pdc_integerlist, PDC_OPT_NONE, 1, 1, \ + -FNT_MAX_METRICS, FNT_MAX_METRICS, NULL}, \ +\ + {"capheight", pdc_integerlist, PDC_OPT_NONE, 1, 1, \ + -FNT_MAX_METRICS, FNT_MAX_METRICS, NULL}, \ +\ + {"xheight", pdc_integerlist, PDC_OPT_NONE, 1, 1, \ + -FNT_MAX_METRICS, FNT_MAX_METRICS, NULL}, \ +\ + {"linegap", pdc_integerlist, PDC_OPT_NONE, 1, 1, \ + -FNT_MAX_METRICS, FNT_MAX_METRICS, NULL}, \ +\ + {"subsetlimit", pdc_doublelist, PDF_SUBSETTING_FLAG|PDC_OPT_PERCENT, 1, 1, \ + 0.0, 100.0, NULL}, \ +\ + {"subsetminsize", pdc_doublelist, PDF_SUBSETTING_FLAG, 1, 1, \ + 0.0, PDC_FLOAT_MAX, NULL}, \ +\ + {"subsetting", pdc_booleanlist, PDF_SUBSETTING_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"unicodemap", pdc_booleanlist, PDF_AUTOCIDFONT_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"embedopentype", pdc_booleanlist, PDF_EMBEDOPENTYPE_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"keepnative", pdc_booleanlist, PDF_KEEPNATIVE_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"vertical", pdc_booleanlist, PDF_VERTICAL_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"replacementchar", pdc_unicharlist, PDF_REPLCHAR_FLAG, 1, 1, \ + 0.0, PDC_MAX_UNIVAL, NULL}, \ +\ + {"metadata", pdc_stringlist, PDF_METADATA_FLAG, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ + + +#define PDF_FONT_OPTIONS3 \ +\ + {"kerning", pdc_booleanlist, PDF_KERNING_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ + + +/* text option definitions */ + +#define PDF_TEXT_OPTIONS \ +\ + {"charspacing", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \ +\ + /* deprecated */ \ + {"glyphwarning", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"fillcolor", pdc_stringlist, PDC_OPT_NONE, 1, 5, \ + 0.0, PDF_MAX_NAMESTRING, NULL}, \ +\ + {"font", pdc_fonthandle, PDC_OPT_NONE, 1, 1, \ + 0, 0, NULL}, \ +\ + {"fontsize", pdc_scalarlist, \ + PDC_OPT_PERCENT | PDC_OPT_SUBOPTLIST | PDC_OPT_KEYLIST1, 1, 2, \ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, pdf_fontsize_keylist}, \ +\ + {"horizscaling", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \ +\ + {"italicangle", pdc_scalarlist, PDC_OPT_NONE, 1, 1, \ + -89.99, 89.99, NULL}, \ +\ + {"fakebold", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"kerning", pdc_booleanlist, PDF_KERNING_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"overline", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"strikeout", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"strokecolor", pdc_stringlist, PDC_OPT_NONE, 1, 5, \ + 0.0, PDF_MAX_NAMESTRING, NULL}, \ +\ + {"strokewidth", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \ + 0.0, PDC_FLOAT_MAX, pdf_underlinewidth_keylist}, \ +\ + {"dasharray", pdc_scalarlist, PDC_OPT_NONE, 1, 2, \ + 0.0, PDC_FLOAT_MAX, NULL}, \ +\ + {"textformat", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, pdf_textformat_keylist}, \ +\ + {"textrendering", pdc_integerlist, PDC_OPT_NONE, 1, 1, \ + 0, PDF_LAST_TRMODE, NULL}, \ +\ + {"textrise", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \ +\ + {"underline", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"wordspacing", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \ +\ + {"underlinewidth", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \ + 0.0, PDC_FLOAT_MAX, pdf_underlinewidth_keylist}, \ +\ + {"underlineposition", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, \ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, pdf_underlineposition_keylist}, \ +\ + /* deprecated */ \ + {"weblink", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + /* deprecated */ \ + {"locallink", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + /* deprecated */ \ + {"pdflink", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + {"charref", pdc_booleanlist, PDF_CHARREF_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"escapesequence", pdc_booleanlist, PDF_ESCAPESEQU_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"glyphcheck", pdc_keywordlist, PDF_GLYPHCHECK_FLAG, 1, 1, \ + 0.0, 0.0, pdf_glyphcheck_keylist}, \ +\ + + +/* xobject option definitions */ + +#define PDF_XOBJECT_OPTIONS1 \ +\ + {"adjustpage", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"blind", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ + + +#define PDF_XOBJECT_OPTIONS2 \ +\ + {"ignoreorientation", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"ignoreclippingpath", pdc_booleanlist, PDF_CLIPPATH_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + /* deprecated */ \ + {"imagewarning", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"dpi", pdc_scalarlist, PDC_OPT_NONE, 1, 2, \ + 0.0, PDC_INT_MAX, pdf_dpi_keylist}, \ + + +#define PDF_XOBJECT_OPTIONS3 \ +\ + {"scale", pdc_scalarlist, PDC_OPT_NOZERO, 1, 2, \ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \ + + +/* general fit option definitions */ + +#define PDF_FIT_OPTIONS1 \ +\ + {"boxsize", pdc_scalarlist, PDC_OPT_NONE, 2, 2, \ + 0, PDC_FLOAT_MAX, NULL}, \ +\ + {"margin", pdc_scalarlist, PDC_OPT_NONE, 1, 2, \ + 0, PDC_FLOAT_MAX, NULL}, \ +\ + {"shrinklimit", pdc_scalarlist, PDC_OPT_PERCENT | PDC_OPT_PERCRANGE, 1, 1, \ + 0.0, 100.0, NULL}, \ +\ + {"position", pdc_scalarlist, PDC_OPT_NONE, 1, 2, \ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, pdf_position_keylist}, \ +\ + {"matchbox", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ + + +#define PDF_FIT_OPTIONS2 \ +\ + {"fitmethod", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, pdf_fitmethod_keylist}, \ +\ + {"rotate", pdc_scalarlist, PDC_OPT_NONE, 1, 1, \ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \ +\ + {"orientate", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, pdf_orientate_keylist}, \ +\ + {"showborder", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ + + +#define PDF_FIT_OPTIONS6 \ +\ + {"alignchar", pdc_unicharlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDC_USHRT_MAX, pdf_charname_keylist}, \ +\ + {"stamp", pdc_keywordlist, PDF_STAMP_FLAG, 1, 1, \ + 0.0, 0.0, pdf_stampdir_keylist}, \ +\ + {"leader", pdc_stringlist, PDF_LEADER_FLAG, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ + + +#define PDF_FIT_OPTIONS3 \ +\ + {"refpoint", pdc_scalarlist, PDC_OPT_NONE, 2, 2, \ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, \ + + + +/* p_font.c */ +void pdf_get_font_options(PDF *p, pdf_font_options *fo, pdc_resopt *resopts); +int pdf_load_font_internal(PDF *p, pdf_font_options *fo); + +/* p_image.c */ +void pdf_init_xobject_options(PDF *p, pdf_xobject_options *xo); +void pdf_get_xobject_options(PDF *p, pdf_xobject_options *xo, + pdc_resopt *resopts); +pdc_resopt *pdf_parse_fitxobject_optlist(PDF *p, int im, + pdf_xobject_options *xo, pdf_fit_options *fit, const char *optlist); +void pdf_fit_xobject_internal(PDF *p, pdf_xobject_options *xo, + pdf_fit_options *fit, pdc_matrix *immatrix); + +/* p_mbox.c */ +void pdf_init_fit_options(PDF *p, pdc_bool fortflow, pdf_fit_options *fit); +void pdf_cleanup_fit_options(PDF *p, pdf_fit_options *fit); +void pdf_get_fit_options(PDF *p, pdc_bool fortflow, pdf_fit_options *fit, + pdc_resopt *resopts); +void pdf_get_mbox_boxheight(PDF *p, pdf_mbox *mbox, + pdc_scalar *boxheight); +pdc_bool pdf_get_mbox_clipping(PDF *p, pdf_mbox *mbox, + pdc_scalar width, pdc_scalar height, pdc_box *clipbox); +double pdf_get_mbox_info(PDF *p, pdf_mbox *mbox, const char *keyword); + +/* p_text.c */ +pdc_bool pdf_calculate_text_options(PDF *p, pdf_text_options *to, + pdc_bool force, pdc_scalar fontscale, pdc_scalar minfontsize, + pdc_scalar fontsizeref); +void pdf_set_text_options(PDF *p, pdf_text_options *to); +void pdf_init_text_options(PDF *p, pdf_text_options *to); +void pdf_get_text_options(PDF *p, pdf_text_options *to, pdc_resopt *resopts); +pdc_resopt *pdf_parse_fittextline_optlist(PDF *p, pdf_text_options *to, + pdf_fit_options *fit, const char *optlist); +int pdf_fit_textline_internal(PDF *p, pdf_fittext *fitres, + pdf_text_options *to, pdf_fit_options *fit, pdc_matrix *matrix); +void pdf_calculate_textline_size(PDF *p, pdf_text_options *to, + pdf_fit_options *fit, pdc_scalar *width, pdc_scalar *height); +pdc_bool pdf_is_horiz_orientated(pdf_fit_options *fit); +int pdf_calculate_leader_pos(PDF *p, pdf_alignment alignment, + pdf_text_options *to, int nchars,pdc_scalar *xstart, pdc_scalar *xstop, + pdc_scalar width, pdc_bool left); +void pdf_draw_leader_text(PDF *p, pdc_scalar xstart, pdc_scalar ybase, + pdc_scalar width, int nchars, pdc_byte *utext, int len, int charlen, + pdf_text_options *to); + +int pdf_get_approximate_uvlist(PDF *p, pdf_font *currfont, + pdc_encodingvector *ev, int usv, pdc_bool replace, pdc_ushort *uvlist, + pdc_ushort *cglist); +void pdf_get_input_textformat(pdf_font *currfont, + pdc_text_format *intextformat, int *convflags); +int pdf_check_textstring(PDF *p, const char *text, int len, int flags, + pdf_text_options *to, pdc_byte **outtext, int *outlen, int *outcharlen, + pdc_bool verbose); +pdc_scalar pdf_calculate_textsize(PDF *p, const pdc_byte *text, int len, + int charlen, pdf_text_options *to, int breakchar, pdc_scalar *height, + pdc_bool verbose); +pdc_scalar pdf_trim_textwidth(pdc_scalar width, pdf_text_options *to); +void pdf_place_text(PDF *p, pdc_byte *text, int len, int charlen, + pdf_text_options *to, pdc_scalar width, pdc_scalar height, + pdc_bool cont); + + + + +#endif /* P_DEFOPT_H */ + diff --git a/src/pdflib/pdflib/p_document.c b/src/pdflib/pdflib/p_document.c new file mode 100644 index 0000000..4c00aa3 --- /dev/null +++ b/src/pdflib/pdflib/p_document.c @@ -0,0 +1,1939 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_document.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib document related routines + * + */ + + +#undef MVS_TEST + +#define P_DOCUMENT_C + +/* For checking the beta expiration date */ +#include <time.h> + +#include "p_intern.h" +#include "p_image.h" +#include "p_layer.h" +#include "p_page.h" +#include "p_tagged.h" + + + + + +#if (defined(WIN32) || defined(OS2)) && !defined(WINCE) +#include <fcntl.h> +#include <io.h> +#endif + + +/* file attachment structure */ +typedef struct +{ + char *filename; + char *name; + char *description; + char *mimetype; + pdc_off_t filesize; +} +pdf_attachments; + +#define PDF_MAX_LANGCODE 8 + +/* Document open modes */ + +typedef enum +{ + open_auto, + open_none, + open_bookmarks, + open_thumbnails, + open_fullscreen, + open_attachments + +} +pdf_openmode; + +static const pdc_keyconn pdf_openmode_keylist[] = +{ + {"none", open_none}, + {"bookmarks", open_bookmarks}, + {"thumbnails", open_thumbnails}, + {"fullscreen", open_fullscreen}, + {"attachments", open_attachments}, + + {NULL, 0} +}; + +static const pdc_keyconn pdf_openmode_pdfkeylist[] = +{ + {"UseNone", open_auto}, + {"UseNone", open_none}, + {"UseOutlines", open_bookmarks}, + {"UseThumbs", open_thumbnails}, + {"FullScreen", open_fullscreen}, + {"UseAttachments", open_attachments}, + + {NULL, 0} +}; + + +/* Document page layout */ + +typedef enum +{ + layout_default, + layout_singlepage, + layout_onecolumn, + layout_twocolumnleft, + layout_twocolumnright, + layout_twopageleft, + layout_twopageright +} +pdf_pagelayout; + +static const pdc_keyconn pdf_pagelayout_pdfkeylist[] = +{ + {"Default", layout_default}, + {"SinglePage", layout_singlepage}, + {"OneColumn", layout_onecolumn}, + {"TwoColumnLeft", layout_twocolumnleft}, + {"TwoColumnRight", layout_twocolumnright}, + {"TwoPageLeft", layout_twopageleft}, + {"TwoPageRight", layout_twopageright}, + {NULL, 0} +}; + + +/* NonFullScreenPageMode */ + +static const pdc_keyconn pdf_nonfullscreen_keylist[] = +{ + {"none", open_none}, + {"bookmarks", open_bookmarks}, + {"thumbnails", open_thumbnails}, + + {NULL, 0} +}; + +typedef enum +{ + doc_none, + doc_l2r, + doc_r2l, + doc_appdefault, + doc_simplex, + doc_duplexflipshortedge, + doc_duplexfliplongedge +} +pdf_viewerprefence; + +/* Direction */ + +static const pdc_keyconn pdf_textdirection_pdfkeylist[] = +{ + {"L2R", doc_l2r}, + {"R2L", doc_r2l}, + {NULL, 0} +}; + +/* PrintScaling */ + +static const pdc_keyconn pdf_printscaling_pdfkeylist[] = +{ + {"None", doc_none}, + {"AppDefault", doc_appdefault}, + {NULL, 0} +}; + +/* Duplex */ + +static const pdc_keyconn pdf_duplex_pdfkeylist[] = +{ + {"None", doc_none}, + {"Simplex", doc_simplex}, + {"DuplexFlipShortEdge", doc_duplexflipshortedge}, + {"DuplexFlipLongEdge", doc_duplexfliplongedge}, + {NULL, 0} +}; + + + +static const pdc_keyconn pdf_pdfa_keylist[] = +{ + {NULL, 0} +}; + + + +static const pdc_keyconn pdf_pdfx_keylist[] = +{ + {NULL, 0} +}; + + +/* configurable flush points */ + +static const pdc_keyconn pdf_flush_keylist[] = +{ + {"none", pdc_flush_none}, + {"page", pdc_flush_page}, + {"content", pdc_flush_content}, + {"heavy", pdc_flush_heavy}, + {NULL, 0} +}; + +static const pdc_keyconn pl_pwencoding_keylist[] = +{ + {"ebcdic", pdc_ebcdic}, + {"ebcdic_37", pdc_ebcdic_37}, + {"ebcdic_winansi", pdc_ebcdic_winansi}, + {"pdfdoc", pdc_pdfdoc}, + {"winansi", pdc_winansi}, + {"macroman", pdc_macroman_apple}, + {NULL, 0} +}; + +#define PDF_MAXPW 0 +static const pdc_keyconn pdc_permissions_keylist[] = +{ + {NULL, 0} +}; + +#define PDF_PDFA_FLAG PDC_OPT_UNSUPP + +#define PDF_SECURITY_FLAG PDC_OPT_UNSUPP + +#define PDF_LINEARIZE_FLAG PDC_OPT_UNSUPP + +#define PDF_ICC_FLAG PDC_OPT_UNSUPP + +#define PDF_TAGGED_FLAG PDC_OPT_UNSUPP + +#define PDF_METADATA_FLAG PDC_OPT_UNSUPP + +#define PDF_UPDATE_FLAG PDC_OPT_UNSUPP + +#define PDF_DOCUMENT_OPTIONS1 \ +\ + {"pdfa", pdc_keywordlist, PDF_PDFA_FLAG, 1, 1, \ + 0.0, 0.0, pdf_pdfa_keylist}, \ +\ + {"pdfx", pdc_keywordlist, PDF_ICC_FLAG, 1, 1, \ + 0.0, 0.0, pdf_pdfx_keylist}, \ +\ + {"compatibility", pdc_keywordlist, PDC_OPT_IGNOREIF1, 1, 1, \ + 0.0, 0.0, pdf_compatibility_keylist}, \ +\ + {"flush", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, pdf_flush_keylist}, \ +\ + {"passwordencoding", pdc_keywordlist, PDF_SECURITY_FLAG, 1, 1, \ + 0.0, 0.0, pl_pwencoding_keylist}, \ +\ + {"attachmentpassword", pdc_stringlist, PDF_SECURITY_FLAG, 1, 1, \ + 0.0, PDF_MAXPW, NULL}, \ +\ + {"masterpassword", pdc_stringlist, PDF_SECURITY_FLAG, 1, 1, \ + 0.0, PDF_MAXPW, NULL}, \ +\ + {"userpassword", pdc_stringlist, PDF_SECURITY_FLAG, 1, 1, \ + 0.0, PDF_MAXPW, NULL}, \ +\ + {"permissions", pdc_keywordlist, \ + PDF_SECURITY_FLAG | PDC_OPT_BUILDOR | PDC_OPT_DUPORIGVAL, 1, 9,\ + 0.0, 0.0, pdc_permissions_keylist}, \ +\ + {"update", pdc_booleanlist, PDF_UPDATE_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"tagged", pdc_booleanlist, PDF_TAGGED_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"lang", pdc_stringlist, PDF_TAGGED_FLAG, 1, 1, \ + 0.0, PDF_MAX_LANGCODE, NULL}, \ +\ + {"search", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + {"groups", pdc_stringlist, PDC_OPT_NONE, 1, PDC_USHRT_MAX, \ + 0.0, PDF_MAX_NAMESTRING, NULL}, \ +\ + {"optimize", pdc_booleanlist, PDF_LINEARIZE_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"linearize", pdc_booleanlist, PDF_LINEARIZE_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"inmemory", pdc_booleanlist, PDF_LINEARIZE_FLAG, 1, 1,\ + 0.0, 0.0, NULL}, \ +\ + {"tempdirname", pdc_stringlist, PDF_LINEARIZE_FLAG, 1, 1, \ + 4.0, 400.0, NULL}, \ + + +#if defined(MVS) || defined(MVS_TEST) +#define PDF_DOCUMENT_OPTIONS10 \ +\ + {"recordsize", pdc_integerlist, PDF_LINEARIZE_FLAG, 1, 1, \ + 0.0, 32768.0, NULL}, \ +\ + {"tempfilenames", pdc_stringlist, PDF_LINEARIZE_FLAG, 2, 2, \ + 4.0, 400.0, NULL}, \ + +#endif + + +#define PDF_DOCUMENT_OPTIONS2 \ +\ + {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDF_MAX_NAMESTRING, NULL}, \ +\ + {"moddate", pdc_booleanlist, PDC_OPT_NONE, 1, 1,\ + 0.0, 0.0, NULL}, \ +\ + {"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + {"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + {"action", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + {"labels", pdc_stringlist, PDC_OPT_NONE, 1, PDC_USHRT_MAX, \ + 0.0, PDC_USHRT_MAX, NULL}, \ +\ + {"openmode", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, pdf_openmode_keylist}, \ +\ + {"pagelayout", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, pdf_pagelayout_pdfkeylist}, \ +\ + {"uri", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + {"viewerpreferences", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDC_USHRT_MAX, NULL}, \ +\ + {"autoxmp", pdc_booleanlist, PDF_METADATA_FLAG, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"metadata", pdc_stringlist, PDF_METADATA_FLAG, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + {"attachments", pdc_stringlist, PDC_OPT_NONE, 1, PDC_USHRT_MAX, \ + 0.0, PDC_INT_MAX, NULL}, \ + + +/* document struct */ + +struct pdf_document_s +{ + int compatibility; /* PDF version number * 10 */ + pdc_flush_state flush; /* output flushing points */ + + + + + + + pdc_bool moddate; /* modified date will be created */ + char lang[PDF_MAX_LANGCODE + 1]; /* default natural language */ + char *action; /* document actions */ + pdf_dest *dest; /* destination as open action */ + char *uri; /* document's base url */ + char *viewerpreferences; /* option list with viewer preferences */ + pdc_bool writevpdict; /* viewer preferences dictionary + * must be written */ + pdf_openmode openmode; /* document open mode */ + pdf_pagelayout pagelayout; /* page layout within document */ + + char *searchindexname; /* file name for search index */ + char *searchindextype; /* type for search index */ + + pdf_attachments *attachments; /* temporarily file attachments */ + int nattachs; /* number of file attachments */ + + + char *filename; /* file name of document */ + size_t (*writeproc)(PDF *p, void *data, size_t size); + /* output procedure */ + FILE *fp; /* file id - deprecated */ + int len; /* length of custom */ +}; + +static pdf_document * +pdf_init_get_document(PDF *p) +{ + static const char fn[] = "pdf_init_get_document"; + + if (p->document == NULL) + { + pdf_document *doc = (pdf_document *) + pdc_malloc(p->pdc, sizeof(pdf_document), fn); + + doc->compatibility = PDF_DEF_COMPATIBILITY; + doc->flush = pdc_flush_page; + + + + + + + doc->moddate = pdc_false; + doc->lang[0] = 0; + doc->action = NULL; + doc->dest = NULL; + doc->uri = NULL; + doc->viewerpreferences = NULL; + doc->writevpdict = pdc_false; + doc->openmode = open_auto; + doc->pagelayout = layout_default; + + doc->searchindexname = NULL; + doc->searchindextype = NULL; + + doc->attachments = NULL; + doc->nattachs = 0; + + + doc->fp = NULL; + doc->filename = NULL; + doc->writeproc = NULL; + doc->len = 0; + + p->document = doc; + } + + return p->document; +} + +static void +pdf_cleanup_document_internal(PDF *p) +{ + pdf_document *doc = (pdf_document *) p->document; + + if (doc) + { + pdf_cleanup_destination(p, doc->dest); + doc->dest = NULL; + + if (doc->action) + { + pdc_free(p->pdc, doc->action); + doc->action = NULL; + } + + if (doc->uri) + { + pdc_free(p->pdc, doc->uri); + doc->uri = NULL; + } + + if (doc->viewerpreferences) + { + pdc_free(p->pdc, doc->viewerpreferences); + doc->viewerpreferences = NULL; + } + + + + + if (doc->searchindexname) + { + pdc_free(p->pdc, doc->searchindexname); + doc->searchindexname = NULL; + } + + if (doc->searchindextype) + { + pdc_free(p->pdc, doc->searchindextype); + doc->searchindextype = NULL; + } + + if (doc->filename) + { + pdc_free(p->pdc, doc->filename); + doc->filename = NULL; + } + + pdc_free(p->pdc, doc); + p->document = NULL; + } +} + + +/* ---------------------------- PDFA / PDFX -------------------------- */ + + + +void +pdf_fix_openmode(PDF *p) +{ + pdf_document *doc = pdf_init_get_document(p); + + if (doc->openmode == open_auto) + doc->openmode = open_bookmarks; +} + + + + + +/* ------------------------- viewerpreferences ----------------------- */ + +static const pdc_defopt pdf_viewerpreferences_options[] = +{ + {"centerwindow", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0, NULL}, + + {"direction", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, pdf_textdirection_pdfkeylist}, + + {"displaydoctitle", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0, NULL}, + + {"fitwindow", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0, NULL}, + + {"hidemenubar", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0, NULL}, + + {"hidetoolbar", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0, NULL}, + + {"hidewindowui", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0, NULL}, + + {"nonfullscreenpagemode", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, pdf_nonfullscreen_keylist}, + + {"viewarea", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, pdf_usebox_keylist}, + + {"viewclip", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, pdf_usebox_keylist}, + + {"printarea", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, pdf_usebox_keylist}, + + {"printclip", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, pdf_usebox_keylist}, + + {"printscaling", pdc_keywordlist, PDC_OPT_PDC_1_6, 1, 1, + 0.0, 0.0, pdf_printscaling_pdfkeylist}, + + {"duplex", pdc_keywordlist, PDC_OPT_PDC_1_7, 1, 1, + 0.0, 0.0, pdf_duplex_pdfkeylist}, + + {"picktraybypdfsize", pdc_booleanlist, PDC_OPT_PDC_1_7, 1, 1, + 0.0, 0, NULL}, + + {"printpagerange", pdc_integerlist, PDC_OPT_PDC_1_7 | PDC_OPT_EVENNUM, + 1, PDC_USHRT_MAX, 1.0, PDC_INT_MAX, NULL}, \ + + {"numcopies", pdc_integerlist, PDC_OPT_PDC_1_7, 1, 1, \ + 1.0, 5.0, NULL}, \ + + PDC_OPT_TERMINATE +}; + +static int +pdf_parse_and_write_viewerpreferences(PDF *p, const char *optlist, + pdc_bool output) +{ + pdc_resopt *resopts = NULL; + pdc_clientdata cdata; + char **strlist; + pdc_bool writevpdict = pdc_false; + pdc_bool flag; + int i, nv, inum; + + /* parsing option list */ + pdf_set_clientdata(p, &cdata); + resopts = pdc_parse_optionlist(p->pdc, optlist, + pdf_viewerpreferences_options, &cdata, pdc_true); + + if (pdc_get_optvalues("hidetoolbar", resopts, &flag, NULL) && flag) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/HideToolbar true\n"); + } + + if (pdc_get_optvalues("hidemenubar", resopts, &flag, NULL) && flag) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/HideMenubar true\n"); + } + + if (pdc_get_optvalues("hidewindowui", resopts, &flag, NULL) && flag) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/HideWindowUI true\n"); + } + + if (pdc_get_optvalues("fitwindow", resopts, &flag, NULL) && flag) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/FitWindow true\n"); + } + + if (pdc_get_optvalues("centerwindow", resopts, &flag, NULL) && flag) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/CenterWindow true\n"); + } + + if (pdc_get_optvalues("displaydoctitle", resopts, &flag, NULL) && flag) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/DisplayDocTitle true\n"); + } + + if (pdc_get_optvalues("nonfullscreenpagemode", resopts, &inum, NULL) && + inum != (int) open_none) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/NonFullScreenPageMode/%s\n", + pdc_get_keyword(inum, pdf_openmode_pdfkeylist)); + } + + + if (pdc_get_optvalues("direction", resopts, &inum, NULL) && + inum != (int) doc_l2r) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/Direction/%s\n", + pdc_get_keyword(inum, pdf_textdirection_pdfkeylist)); + } + + if (pdc_get_optvalues("viewarea", resopts, &inum, NULL) && + inum != (int) pdc_pbox_crop) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/ViewArea%s\n", + pdc_get_keyword(inum, pdf_usebox_pdfkeylist)); + } + + if (pdc_get_optvalues("viewclip", resopts, &inum, NULL) && + inum != (int) pdc_pbox_crop) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/ViewClip%s\n", + pdc_get_keyword(inum, pdf_usebox_pdfkeylist)); + } + + if (pdc_get_optvalues("printarea", resopts, &inum, NULL) && + inum != (int) pdc_pbox_crop) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/PrintArea%s\n", + pdc_get_keyword(inum, pdf_usebox_pdfkeylist)); + } + + if (pdc_get_optvalues("printclip", resopts, &inum, NULL) && + inum != (int) pdc_pbox_crop) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/PrintClip%s\n", + pdc_get_keyword(inum, pdf_usebox_pdfkeylist)); + } + + if (pdc_get_optvalues("printscaling", resopts, &inum, NULL) && + inum != (int) doc_appdefault) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/PrintScaling/%s\n", + pdc_get_keyword(inum, pdf_printscaling_pdfkeylist)); + } + + if (pdc_get_optvalues("duplex", resopts, &inum, NULL) && + inum != (int) doc_none) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/Duplex/%s\n", + pdc_get_keyword(inum, pdf_duplex_pdfkeylist)); + } + + if (pdc_get_optvalues("picktraybypdfsize", resopts, &flag, NULL)) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/PickTrayByPDFSize %s\n", + PDC_BOOLSTR(flag)); + } + + nv = pdc_get_optvalues("printpagerange", resopts, NULL, &strlist); + if (nv) + { + writevpdict = pdc_true; + if (output) + { + int *prs = (int *) strlist; + + pdc_printf(p->out, "/PrintPageRange"); + pdc_begin_array(p->out); + for (i = 0; i < nv; i++) + pdc_printf(p->out, "%d ", prs[i]); + pdc_end_array(p->out); + } + } + + if (pdc_get_optvalues("numcopies", resopts, &inum, NULL)) + { + writevpdict = pdc_true; + if (output) pdc_printf(p->out, "/NumCopies %d\n", inum); + } + + pdc_cleanup_optionlist(p->pdc, resopts); + + return writevpdict; +} + + +/* ------------------------- search ----------------------- */ + +static const pdc_defopt pdf_search_options[] = +{ + {"filename", pdc_stringlist, PDC_OPT_REQUIRED, 1, 1, + 1.0, PDC_FILENAMELEN, NULL}, + + {"indextype", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDF_MAX_NAMESTRING, NULL}, + + PDC_OPT_TERMINATE +}; + +static void +pdf_parse_search_optlist(PDF *p, const char *optlist) +{ + pdf_document *doc = p->document; + pdc_resopt *resopts = NULL; + + /* parsing option list */ + resopts = pdc_parse_optionlist(p->pdc, optlist, + pdf_search_options, NULL, pdc_true); + + if (pdc_get_optvalues("filename", resopts, NULL, NULL)) + doc->searchindexname = + (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + + if (pdc_get_optvalues("indextype", resopts, NULL, NULL)) + doc->searchindextype = + (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + else + doc->searchindextype = pdc_strdup(p->pdc, "PDX"); + + pdc_cleanup_optionlist(p->pdc, resopts); +} + +static void +pdf_write_search_indexes(PDF *p) +{ + pdf_document *doc = p->document; + + if (doc->searchindexname != NULL) + { + pdc_puts(p->out, "/Search"); + pdc_begin_dict(p->out); /* Search */ + pdc_puts(p->out, "/Indexes"); + pdc_begin_array(p->out); + pdc_begin_dict(p->out); /* Indexes */ + pdc_puts(p->out, "/Name"); + pdc_printf(p->out, "/%s", doc->searchindextype); + pdc_puts(p->out, "/Index"); + pdc_begin_dict(p->out); /* Index */ + pdc_puts(p->out, "/Type/Filespec"); + pdc_puts(p->out, "/F"); + pdf_put_pdffilename(p, doc->searchindexname); + pdc_end_dict(p->out); /* Index */ + pdc_end_dict(p->out); /* Indexes */ + pdc_end_array(p->out); + pdc_end_dict(p->out); /* Search */ + } +} + + +/* ---------------------- file attachements -------------------- */ + +static void +pdc_cleanup_attachments_tmp(void *opaque, void *mem) +{ + if (mem) + { + PDF *p = (PDF *) opaque; + pdf_document *doc = p->document; + int i; + + if (doc != NULL) + { + for (i = 0; i < doc->nattachs; i++) + { + pdf_attachments *fat = &doc->attachments[i]; + + if (fat->filename != NULL) + pdc_free(p->pdc, fat->filename); + if (fat->name != NULL) + pdc_free(p->pdc, fat->name); + if (fat->description != NULL) + pdc_free(p->pdc, fat->description); + if (fat->mimetype != NULL) + pdc_free(p->pdc, fat->mimetype); + } + + doc->attachments = NULL; + doc->nattachs = 0; + } + } +} + +static const pdc_defopt pdf_attachments_options[] = +{ + {"filename", pdc_stringlist, PDC_OPT_REQUIRED, 1, 1, + 1.0, PDC_FILENAMELEN, NULL}, + + {"description", pdc_stringlist, PDC_OPT_PDC_1_6, 1, 1, + 0.0, PDC_INT_MAX, NULL}, + + {"name", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDF_MAX_NAMESTRING, NULL}, + + {"mimetype", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDF_MAX_NAMESTRING, NULL}, + + PDC_OPT_TERMINATE +}; + +static void +pdf_parse_attachments_optlist(PDF *p, char **optlists, int ns, + pdc_encoding htenc, int htcp) +{ + static const char fn[] = "pdf_parse_attachments_optlist"; + pdf_document *doc = p->document; + pdc_resopt *resopts = NULL; + pdc_clientdata cdata; + int i; + + doc->attachments = (pdf_attachments *) pdc_malloc_tmp(p->pdc, + ns * sizeof(pdf_attachments), fn, + p, pdc_cleanup_attachments_tmp); + doc->nattachs = ns; + + pdf_set_clientdata(p, &cdata); + + for (i = 0; i < ns; i++) + { + pdf_attachments *fat = &doc->attachments[i]; + + fat->filename = NULL; + fat->name = NULL; + fat->description = NULL; + fat->mimetype = NULL; + fat->filesize = 0; + } + + for (i = 0; i < ns; i++) + { + pdf_attachments *fat = &doc->attachments[i]; + + /* parsing option list */ + resopts = pdc_parse_optionlist(p->pdc, optlists[i], + pdf_attachments_options, &cdata, pdc_true); + + if (pdc_get_optvalues("filename", resopts, NULL, NULL)) + fat->filename = + (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + + if (pdf_get_opt_textlist(p, "description", resopts, htenc, htcp, + pdc_true, NULL, &fat->description, NULL)) + pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + + if (pdf_get_opt_textlist(p, "name", resopts, htenc, htcp, + pdc_true, NULL, &fat->name, NULL)) + pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + + if (pdc_get_optvalues("mimetype", resopts, NULL, NULL)) + fat->mimetype = + (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + + pdc_cleanup_optionlist(p->pdc, resopts); + + fat->filesize = pdf_check_file(p, fat->filename, pdc_true); + } +} + +static void +pdf_write_attachments(PDF *p) +{ + static const char fn[] = "pdf_write_attachments"; + pdf_document *doc = p->document; + pdc_id attachment_id, obj_id; + char *name; + int i; + + for (i = 0; i < doc->nattachs; i++) + { + pdf_attachments *fat = &doc->attachments[i]; + + if (fat->filesize > 0) + { + /* create file specification dictionary */ + attachment_id = pdc_begin_obj(p->out, PDC_NEW_ID); + pdc_begin_dict(p->out); /* FS dict */ + + pdc_puts(p->out, "/Type/Filespec\n"); + pdc_printf(p->out, "/F"); + pdf_put_pdffilename(p, fat->filename); + pdc_puts(p->out, "\n"); + + if (fat->description != NULL) + { + pdc_puts(p->out, "/Desc"); + pdf_put_hypertext(p, fat->description); + pdc_puts(p->out, "\n"); + } + + obj_id = pdc_alloc_id(p->out); + pdc_puts(p->out, "/EF"); + pdc_begin_dict(p->out); + pdc_objref(p->out, "/F", obj_id); + pdc_end_dict(p->out); + + pdc_end_dict(p->out); /* FS dict */ + pdc_end_obj(p->out); + + /* embed file */ + pdf_embed_file(p, obj_id, fat->filename, fat->mimetype, + fat->filesize); + + /* insert name in tree */ + if (fat->name == NULL) + name = pdc_strdup_ext(p->pdc, fat->filename, 0, fn); + else + name = pdc_strdup_ext(p->pdc, fat->name, 0, fn); + pdf_insert_name(p, name, names_embeddedfiles, attachment_id); + } + } +} + +pdc_off_t +pdf_check_file(PDF *p, const char *filename, pdc_bool verbose) +{ + pdc_off_t filesize = 0; + const char *qualifier = "attachment "; + pdc_file *fp; + + fp = pdc_fsearch_fopen(p->pdc, filename, NULL, qualifier, + PDC_FILE_BINARY); + if (fp == NULL) + { + if (verbose) + pdc_error(p->pdc, -1, 0, 0, 0, 0); + } + else + { + filesize = pdc_file_size(fp); + pdc_fclose(fp); + + if (filesize == 0) + { + pdc_set_errmsg(p->pdc, PDC_E_IO_FILE_EMPTY, qualifier, filename, + 0, 0); + if (verbose) + pdc_error(p->pdc, -1, 0, 0, 0, 0); + } + } + + return filesize; +} + +void +pdf_embed_file(PDF *p, pdc_id obj_id, const char *filename, + const char *mimetype, pdc_off_t filesize) +{ + pdc_id length_id; + PDF_data_source src; + + pdc_begin_obj(p->out, obj_id); + pdc_begin_dict(p->out); /* F dict */ + + pdc_puts(p->out, "/Type/EmbeddedFile\n"); + + if (mimetype && *mimetype) + { + pdc_puts(p->out, "/Subtype"); + pdf_put_pdfname(p, mimetype); + pdc_puts(p->out, "\n"); + } + + pdc_puts(p->out, "/Params"); + pdc_begin_dict(p->out); /* Params */ + pdc_printf(p->out, "/Size %lld", filesize); + pdc_end_dict(p->out); /* Params */ + + 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 *) 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); + + + pdc_end_obj(p->out); + + pdc_put_pdfstreamlength(p->out, length_id); + + if (p->flush & pdc_flush_content) + pdc_flush_stream(p->out); +} + + +/* ---------------------- linearize -------------------- */ + + + +/* ------------------ document options ----------------- */ + +static void +pdf_get_document_common_options(PDF *p, pdc_resopt *resopts, int fcode) +{ + pdf_document *doc = p->document; + pdc_encoding htenc; + int htcp; + char **strlist; + int i, inum, ns; + + + htenc = + pdf_get_hypertextencoding_opt(p, resopts, &htcp, pdc_true); + + if (pdc_get_optvalues("destination", resopts, NULL, &strlist)) + { + if (doc->dest) + pdc_free(p->pdc, doc->dest); + doc->dest = pdf_parse_destination_optlist(p, strlist[0], 1, + pdf_openaction); + } + else + { + pdf_dest *dest = pdf_get_option_destname(p, resopts, htenc, htcp); + if (dest) + { + if (doc->dest) + pdc_free(p->pdc, doc->dest); + doc->dest = dest; + } + } + + if (pdc_get_optvalues("action", resopts, NULL, NULL)) + { + if (doc->action) + pdc_free(p->pdc, doc->action); + doc->action = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + pdf_parse_and_write_actionlist(p, event_document, NULL, doc->action); + } + + inum = pdc_get_optvalues("labels", resopts, NULL, &strlist); + for (i = 0; i < inum; i++) + pdf_set_pagelabel(p, strlist[i], fcode); + + if (pdc_get_optvalues("openmode", resopts, &inum, NULL)) + doc->openmode = (pdf_openmode) inum; + if (doc->openmode == open_attachments && p->compatibility < PDC_1_6) + pdc_error(p->pdc, PDC_E_OPT_VERSION, "openmode=attachments", + pdc_get_pdfversion(p->pdc, p->compatibility), 0, 0); + + if (pdc_get_optvalues("pagelayout", resopts, &inum, NULL)) + doc->pagelayout = (pdf_pagelayout) inum; + if (p->compatibility < PDC_1_5) + { + if (doc->pagelayout == layout_twopageleft) + pdc_error(p->pdc, PDC_E_OPT_VERSION, "pagelayout=TwoPageLeft", + pdc_get_pdfversion(p->pdc, p->compatibility), 0, 0); + if (doc->pagelayout == layout_twopageright) + pdc_error(p->pdc, PDC_E_OPT_VERSION, "pagelayout=TwoPageRight", + pdc_get_pdfversion(p->pdc, p->compatibility), 0, 0); + } + + if (pdc_get_optvalues("uri", resopts, NULL, NULL)) + { + if (doc->uri) + pdc_free(p->pdc, doc->uri); + doc->uri = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + } + + if (pdc_get_optvalues("viewerpreferences", resopts, NULL, NULL)) + { + if (doc->viewerpreferences) + pdc_free(p->pdc, doc->viewerpreferences); + doc->viewerpreferences = + (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + doc->writevpdict |= + pdf_parse_and_write_viewerpreferences(p, doc->viewerpreferences, + pdc_false); + } + + if (pdc_get_optvalues("search", resopts, NULL, &strlist)) + pdf_parse_search_optlist(p, strlist[0]); + + + pdc_get_optvalues("moddate", resopts, &doc->moddate, NULL); + + + + ns = pdc_get_optvalues("attachments", resopts, NULL, &strlist); + if (ns) + pdf_parse_attachments_optlist(p, strlist, ns, htenc, htcp); +} + +static const pdc_defopt pdf_begin_document_options[] = +{ + PDF_DOCUMENT_OPTIONS1 +#if defined(MVS) || defined(MVS_TEST) + PDF_DOCUMENT_OPTIONS10 +#endif + PDF_DOCUMENT_OPTIONS2 + PDF_ERRORPOLICY_OPTION + PDC_OPT_TERMINATE +}; + + +/* + * The external callback interface requires a PDF* as the first argument, + * while the internal interface uses pdc_output* and doesn't know about PDF*. + * We use a wrapper to bridge the gap, and store the PDF* within the + * pdc_output structure opaquely. + */ + +static size_t +writeproc_wrapper(pdc_output *out, void *data, size_t size) +{ + size_t ret; + + PDF *p = (PDF *) pdc_get_opaque(out); + + ret = (p->writeproc)(p, data, size); + pdc_logg_cond(p->pdc, 1, trc_api, + "/* writeproc(data[%p], %d)[%d] */\n", data, size, ret); + return ret; +} + + + +/* ---------------------------- begin document -------------------------- */ + +static int +pdf_begin_document_internal(PDF *p, const char *optlist, pdc_bool callback) +{ + pdf_document *doc = p->document; + pdc_resopt *resopts = NULL; + char **groups = NULL; + int n_groups = 0; + pdc_bool verbose = p->debug[(int) 'o']; + pdc_outctl oc; + + (void) callback; + + verbose = pdf_get_errorpolicy(p, NULL, verbose); + + /* parsing option list */ + if (optlist && *optlist) + { + int inum; + + resopts = pdc_parse_optionlist(p->pdc, optlist, + pdf_begin_document_options, NULL, pdc_true); + + verbose = pdf_get_errorpolicy(p, resopts, verbose); + + pdc_get_optvalues("compatibility", resopts, &doc->compatibility, NULL); + + if (pdc_get_optvalues("flush", resopts, &inum, NULL)) + doc->flush = (pdc_flush_state) inum; + + pdc_get_optvalues("lang", resopts, doc->lang, NULL); + + + + + + + + + n_groups = pdc_get_optvalues("groups", resopts, NULL, &groups); + } + + /* copy for easy access */ + p->compatibility = doc->compatibility; + p->pdc->compatibility = doc->compatibility; + p->flush = doc->flush; + + + + + + /* + * None of these functions must call pdc_alloc_id() or generate + * any output since the output machinery is not yet initialized! + */ + + pdf_init_pages(p, (const char **) groups, n_groups); + + /* common options */ + pdf_get_document_common_options(p, resopts, PDF_FC_BEGIN_DOCUMENT); + + + /* deprecated */ + p->bookmark_dest = pdf_init_destination(p); + + pdf_init_images(p); + pdf_init_xobjects(p); + pdf_init_fonts(p); + pdf_init_outlines(p); + pdf_init_annot_params(p); + pdf_init_colorspaces(p); + pdf_init_pattern(p); + pdf_init_shadings(p); + pdf_init_extgstates(p); + + + + + + /* create document digest */ + pdc_init_digest(p->out); + + if (!p->pdc->ptfrun) + { + if (doc->fp) + pdc_update_digest(p->out, (pdc_byte *) doc->fp, doc->len); + else if (doc->writeproc) + pdc_update_digest(p->out, (pdc_byte *) &doc->writeproc, doc->len); + else if (doc->filename) + pdc_update_digest(p->out, (pdc_byte *) doc->filename, doc->len); + } + + pdf_feed_digest_info(p); + + if (!p->pdc->ptfrun) + { + pdc_update_digest(p->out, (pdc_byte *) &p, sizeof(PDF*)); + pdc_update_digest(p->out, (pdc_byte *) p, sizeof(PDF)); + } + + + pdc_finish_digest(p->out, !p->pdc->ptfrun); + + /* preparing output struct */ + pdc_init_outctl(&oc); + oc.flush = doc->flush; + + if (doc->fp) + oc.fp = doc->fp; + else if (doc->writeproc) + { + oc.writeproc = writeproc_wrapper; + p->writeproc = doc->writeproc; + } + else if (doc->filename) + oc.filename = doc->filename; + else + oc.filename = ""; + + + + if (!pdc_init_output((void *) p, p->out, doc->compatibility, &oc)) + { + if (oc.filename && *oc.filename) + { + pdc_set_fopen_errmsg(p->pdc, + pdc_get_fopen_errnum(p->pdc, PDC_E_IO_WROPEN), "PDF ", + pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, oc.filename)); + + if (verbose) + pdc_error(p->pdc, -1, 0, 0, 0, 0); + } + + pdf_cleanup_document_internal(p); + return -1; + } + + /* Write the constant /ProcSet array once at the beginning */ + p->procset_id = pdc_begin_obj(p->out, PDC_NEW_ID); + pdc_puts(p->out, "[/PDF/ImageB/ImageC/ImageI/Text]\n"); + pdc_end_obj(p->out); + + pdf_init_pages2(p); + + pdf_write_attachments(p); + + return 1; +} + +#if defined(_MSC_VER) && defined(_MANAGED) +#pragma unmanaged +#endif +int +pdf__begin_document(PDF *p, const char *filename, int len, const char *optlist) +{ + pdf_document *doc; + pdc_bool verbose = p->debug[(int) 'o']; + int retval; + + verbose = pdf_get_errorpolicy(p, NULL, verbose); + + + doc = pdf_init_get_document(p); + + /* file ID or filename */ + if (len == -1) + { + FILE *fp = (FILE *) filename; + + /* + * It is the callers responsibility to open the file in binary mode, + * but it doesn't hurt to make sure it really is. + * The Intel version of the Metrowerks compiler doesn't have setmode(). + */ +#if !defined(__MWERKS__) && (defined(WIN32) || defined(OS2)) +#if defined WINCE + _setmode(fileno(fp), _O_BINARY); +#else + setmode(fileno(fp), O_BINARY); +#endif +#endif + + doc->fp = fp; + doc->len = sizeof(FILE); + } + else if (filename && (*filename || len > 0)) + { + filename = pdf_convert_filename(p, filename, len, "filename", + PDC_CONV_WITHBOM); + doc->filename = pdc_strdup(p->pdc, filename); + doc->len = (int) strlen(doc->filename); + } + + retval = pdf_begin_document_internal(p, optlist, pdc_false); + + if (retval > -1) + PDF_SET_STATE(p, pdf_state_document); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[Begin document]\n"); + + return retval; +} +#if defined(_MSC_VER) && defined(_MANAGED) +#pragma managed +#endif + +void +pdf__begin_document_callback(PDF *p, + size_t (*i_writeproc)(PDF *p, void *data, size_t size), const char *optlist) +{ + size_t (*writeproc)(PDF *, void *, size_t) = i_writeproc; + pdf_document *doc; + + if (writeproc == NULL) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "writeproc", 0, 0, 0); + + doc = pdf_init_get_document(p); + + /* initializing and opening the document */ + doc->writeproc = writeproc; + doc->len = sizeof(writeproc); + + (void) pdf_begin_document_internal(p, optlist, pdc_true); + + PDF_SET_STATE(p, pdf_state_document); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[Begin document]\n"); +} + +/* ----------------------------- name tree ----------------------------- */ + +struct pdf_name_s +{ + pdc_id obj_id; /* id of this name object */ + char * name; /* name string */ + pdf_nametree_type type; /* name tree type */ +}; + +static void +pdf_cleanup_names(PDF *p) +{ + int i; + + if (p->names == NULL) + return; + + for (i = 0; i < p->names_number; i++) + { + pdc_free(p->pdc, p->names[i].name); + } + + pdc_free(p->pdc, p->names); + p->names_number = 0; + p->names = NULL; +} + +void +pdf_insert_name(PDF *p, const char *name, pdf_nametree_type type, pdc_id obj_id) +{ + static const char fn[] = "pdf_insert_name"; + int i; + + if (p->names == NULL || p->names_number == p->names_capacity) + { + if (p->names == NULL) + { + p->names_number = 0; + p->names_capacity = NAMES_CHUNKSIZE; + p->names = (pdf_name *) pdc_malloc(p->pdc, + sizeof(pdf_name) * p->names_capacity, fn); + } + else + { + p->names_capacity *= 2; + p->names = (pdf_name *) pdc_realloc(p->pdc, p->names, + sizeof(pdf_name) * p->names_capacity, fn); + } + for (i = p->names_number; i < p->names_capacity; i++) + { + p->names[i].obj_id = PDC_BAD_ID; + p->names[i].name = NULL; + p->names[i].type = names_undef; + } + } + + /* check identity */ + for (i = 0; i < p->names_number; i++) + { + if (p->names[i].type == type && !strcmp(p->names[i].name, name)) + { + pdc_free(p->pdc, p->names[i].name); + p->names[i].name = (char *) name; + return; + } + } + + p->names[i].obj_id = obj_id; + p->names[i].name = (char *) name; + p->names[i].type = type; + p->names_number++; +} + +pdc_id +pdf_get_id_from_nametree(PDF *p, pdf_nametree_type type, const char *name) +{ + int i; + + for (i = 0; i < p->names_number; i++) + { + if (p->names[i].type == type && !strcmp(name, p->names[i].name)) + return p->names[i].obj_id; + } + + return PDC_BAD_ID; +} + +static pdc_id +pdf_write_names(PDF *p, pdf_nametree_type type) +{ + pdc_id ret = PDC_BAD_ID; + int i, ibeg = -1, iend = 0; + + for (i = 0; i < p->names_number; i++) + { + if (p->names[i].type == type) + { + if (ibeg == -1) + ibeg = i; + iend = i; + } + } + + if (ibeg > -1) + { + ret = pdc_begin_obj(p->out, PDC_NEW_ID); /* Names object */ + + pdc_begin_dict(p->out); /* Node dict */ + + /* + * Because we have only the 1 tree - the root tree + * the /Limits entry is not allowed (see chapter 3.8.5). + * + pdc_puts(p->out, "/Limits"); + pdc_begin_array(p->out); + pdf_put_hypertext(p, p->names[ibeg].name); + pdf_put_hypertext(p, p->names[iend].name); + pdc_end_array(p->out); + */ + + pdc_puts(p->out, "/Names"); + pdc_begin_array(p->out); + + for (i = ibeg; i <= iend; i++) + { + if (p->names[i].type == type) + { + pdf_put_hypertext(p, p->names[i].name); + pdc_objref(p->out, "", p->names[i].obj_id); + } + } + + pdc_end_array(p->out); + + pdc_end_dict(p->out); /* Node dict */ + + pdc_end_obj(p->out); /* Names object */ + + } + return ret; +} + +static int +name_compare( const void* a, const void* b) +{ + pdf_name *p1 = (pdf_name *) a; + pdf_name *p2 = (pdf_name *) b; + + return strcmp(p1->name, p2->name); +} + +/* ---------------------------- write document -------------------------- */ + +static pdc_id +pdf_write_pages_and_catalog(PDF *p, pdc_id orig_root_id) +{ + pdf_document *doc = p->document; + pdc_bool openact = pdc_false; + pdc_bool forpdfa = pdc_false; + pdc_id act_idlist[PDF_MAX_EVENTS]; + pdc_id root_id = PDC_BAD_ID; + pdc_id names_dests_id = PDC_BAD_ID; + pdc_id names_javascript_id = PDC_BAD_ID; + pdc_id names_ap_id = PDC_BAD_ID; + pdc_id names_embeddedfiles_id = PDC_BAD_ID; + pdc_id outintents1_id = PDC_BAD_ID; + pdc_id outintents2_id = PDC_BAD_ID; + + pdc_id pages_id = pdf_write_pages_tree(p); + pdc_id labels_id = pdf_write_pagelabels(p); + + + + (void) orig_root_id; + + /* name tree dictionaries */ + if (p->names_number) + { + + qsort(p->names, (size_t) p->names_number, sizeof(pdf_name), + name_compare); + + + names_dests_id = pdf_write_names(p, names_dests); + names_javascript_id = pdf_write_names(p, names_javascript); + names_ap_id = pdf_write_names(p, names_ap); + names_embeddedfiles_id = pdf_write_names(p, names_embeddedfiles); + } + + + (void) forpdfa; + + + + + /* write action objects */ + if (doc->action) + pdf_parse_and_write_actionlist(p, event_document, act_idlist, + (const char *) doc->action); + + root_id = pdc_begin_obj(p->out, PDC_NEW_ID); /* Catalog */ + pdc_begin_dict(p->out); + pdc_puts(p->out, "/Type/Catalog\n"); + + pdc_objref(p->out, "/Pages", pages_id); /* Pages object */ + + + if (labels_id != PDC_BAD_ID) + { + pdc_objref(p->out, "/PageLabels", labels_id); + } + + if (p->names_number) + { + pdc_printf(p->out, "/Names"); + pdc_begin_dict(p->out); /* Names */ + + if (names_dests_id != PDC_BAD_ID) + pdc_objref(p->out, "/Dests", names_dests_id); + if (names_javascript_id != PDC_BAD_ID) + pdc_objref(p->out, "/JavaScript", names_javascript_id); + if (names_ap_id != PDC_BAD_ID) + pdc_objref(p->out, "/AP", names_ap_id); + if (names_embeddedfiles_id != PDC_BAD_ID) + pdc_objref(p->out, "/EmbeddedFiles", names_embeddedfiles_id); + + pdc_end_dict(p->out); /* Names */ + } + + if (doc->writevpdict) + { + pdc_printf(p->out, "/ViewerPreferences\n"); + pdc_begin_dict(p->out); /* ViewerPreferences */ + pdf_parse_and_write_viewerpreferences(p, + doc->viewerpreferences, pdc_true); + pdc_end_dict(p->out); /* ViewerPreferences */ + } + + if (doc->pagelayout != layout_default) + pdc_printf(p->out, "/PageLayout/%s\n", + pdc_get_keyword(doc->pagelayout, pdf_pagelayout_pdfkeylist)); + + if (doc->openmode != open_auto && doc->openmode != open_none) + pdc_printf(p->out, "/PageMode/%s\n", + pdc_get_keyword(doc->openmode, pdf_openmode_pdfkeylist)); + + pdf_write_outline_root(p); /* /Outlines */ + + if (doc->action) /* /AA */ + openact = pdf_write_action_entries(p, event_document, act_idlist); + + if (doc->dest && !openact) + { + pdc_puts(p->out, "/OpenAction"); + pdf_write_destination(p, doc->dest); + } + + if (doc->uri) + { + pdc_puts(p->out, "/URI"); + pdc_begin_dict(p->out); + pdc_printf(p->out, "/Base"); + pdf_put_hypertext(p, doc->uri); + pdc_end_dict(p->out); + } + + + if (doc->lang[0]) + { + pdc_puts(p->out, "/Lang"); + pdf_put_hypertext(p, doc->lang); + pdc_puts(p->out, "\n"); + } + + /* /StructTreeRoot /MarkInfo */ + + /* /OCProperties */ + + if (outintents1_id != PDC_BAD_ID || outintents2_id != PDC_BAD_ID) + { + pdc_puts(p->out, "/OutputIntents"); + pdc_begin_array(p->out); + if (outintents1_id != PDC_BAD_ID) + pdc_objref(p->out, "", outintents1_id); + if (outintents2_id != PDC_BAD_ID) + pdc_objref(p->out, "", outintents2_id); + pdc_end_array(p->out); + } + + /* /Search */ + pdf_write_search_indexes(p); + + /* /Metadata */ + + /* not supported: /Threads /PieceInfo /Perms /Legal */ + + pdc_end_dict(p->out); /* Catalog */ + pdc_end_obj(p->out); + + return root_id; +} + + +static void +pdf_write_document(PDF *p) +{ + if (PDF_GET_STATE(p) != pdf_state_error) + { + pdf_document *doc = p->document; + pdc_id info_id = PDC_BAD_ID; + pdc_id root_id = PDC_BAD_ID; + + if (pdf_last_page(p) == 0) + pdc_error(p->pdc, PDF_E_DOC_EMPTY, 0, 0, 0, 0); + + pdf_write_attachments(p); + + + /* Write all pending document information up to xref table + trailer */ + info_id = pdf_write_info(p, doc->moddate); + + pdf_write_doc_fonts(p); /* font objects */ + pdf_write_doc_colorspaces(p); /* color space resources */ + pdf_write_doc_extgstates(p); /* ExtGState resources */ + root_id = pdf_write_pages_and_catalog(p, root_id); + pdf_write_outlines(p); + pdc_write_xref(p->out); + + pdc_write_trailer(p->out, info_id, root_id, 0, -1, -1, -1); + } + + pdc_close_output(p->out); +} + +/* ------------------------------ end document ---------------------------- */ + +void +pdf_cleanup_document(PDF *p) +{ + if (PDF_GET_STATE(p) != pdf_state_object) + { + /* Don't call pdc_cleanup_output() here because we may still need + * the buffer contents for pdf__get_buffer() after pdf__end_document(). + */ + + pdf_delete_actions(p); + + pdf_cleanup_destination(p, p->bookmark_dest); /* deprecated */ + pdf_cleanup_pages(p); + pdf_cleanup_document_internal(p); + pdf_cleanup_info(p); + pdf_cleanup_fonts(p); + pdf_cleanup_outlines(p); + pdf_cleanup_annot_params(p); + pdf_cleanup_names(p); + pdf_cleanup_colorspaces(p); + pdf_cleanup_pattern(p); + pdf_cleanup_shadings(p); + pdf_cleanup_images(p); + pdf_cleanup_xobjects(p); + pdf_cleanup_extgstates(p); + + + + + + + + + + pdf_cleanup_stringlists(p); + + PDF_SET_STATE(p, pdf_state_object); + } +} + +static const pdc_defopt pdf_end_document_options[] = +{ + PDF_DOCUMENT_OPTIONS2 + PDC_OPT_TERMINATE +}; + +void +pdf__end_document(PDF *p, const char *optlist) +{ + pdf_document *doc; + + /* check if there are any suspended pages left. + */ + pdf_check_suspended_pages(p); + + /* get document pointer */ + doc = pdf_init_get_document(p); + + if (optlist && *optlist) + { + pdc_resopt *resopts = NULL; + pdc_clientdata cdata; + + /* parsing option list */ + pdf_set_clientdata(p, &cdata); + resopts = pdc_parse_optionlist(p->pdc, optlist, + pdf_end_document_options, &cdata, pdc_true); + + /* get options */ + pdf_get_document_common_options(p, resopts, PDF_FC_END_DOCUMENT); + + } + + pdf_write_document(p); + + + pdf_cleanup_document(p); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[End document]\n\n"); +} + +const char * +pdf__get_buffer(PDF *p, long *size) +{ + const char *ret; + pdc_off_t llsize; + + + ret = pdc_get_stream_contents(p->out, &llsize); + + if (llsize > LONG_MAX) + pdc_error(p->pdc, PDF_E_DOC_GETBUF_2GB, 0, 0, 0, 0); + + *size = (long) llsize; + return ret; +} + + + + +/*****************************************************************************/ +/** deprecated historical document functions **/ +/*****************************************************************************/ + +void +pdf_set_flush(PDF *p, const char *flush) +{ + if (p->pdc->binding != NULL && strcmp(p->pdc->binding, "C++")) + return; + + if (flush != NULL && *flush) + { + int i = pdc_get_keycode_ci(flush, pdf_flush_keylist); + if (i != PDC_KEY_NOTFOUND) + { + pdf_document *doc = pdf_init_get_document(p); + + doc->flush = (pdc_flush_state) i; + p->flush = doc->flush; + return; + } + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, flush, "flush", + 0, 0); + } +} + +void +pdf_set_uri(PDF *p, const char *uri) +{ + pdf_document *doc = pdf_init_get_document(p); + + if (doc->uri) + pdc_free(p->pdc, doc->uri); + doc->uri = pdc_strdup(p->pdc, uri); +} + + +void +pdf_set_compatibility(PDF *p, const char *compatibility) +{ + + if (compatibility != NULL && *compatibility) + { + int i = pdc_get_keycode_ci(compatibility, pdf_compatibility_keylist); + if (i != PDC_KEY_NOTFOUND) + { + pdf_document *doc = pdf_init_get_document(p); + + p->compatibility = i; + doc->compatibility = i; + p->pdc->compatibility = i; + return; + } + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, compatibility, "compatibility", + 0, 0); + } +} + +void +pdf_set_openaction(PDF *p, const char *openaction) +{ + pdf_document *doc = pdf_init_get_document(p); + + if (openaction != NULL && *openaction) + { + pdf_cleanup_destination(p, doc->dest); + doc->dest = pdf_parse_destination_optlist(p, openaction, 1, + pdf_openaction); + } +} + +void +pdf_set_openmode(PDF *p, const char *openmode) +{ + int i; + + if (openmode == NULL || !*openmode) + openmode = "none"; + + i = pdc_get_keycode_ci(openmode, pdf_openmode_keylist); + if (i != PDC_KEY_NOTFOUND) + { + pdf_document *doc = pdf_init_get_document(p); + + doc->openmode = (pdf_openmode) i; + } + else + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, openmode, "openmode", 0, 0); +} + +void +pdf_set_viewerpreference(PDF *p, const char *viewerpreference) +{ + static const char fn[] = "pdf_set_viewerpreference"; + pdf_document *doc = pdf_init_get_document(p); + char *optlist; + size_t nb1 = 0, nb2 = 0; + + if (doc->viewerpreferences) + nb1 = strlen(doc->viewerpreferences) * sizeof(char *); + nb2 = strlen(viewerpreference) * sizeof(char *); + + optlist = (char *) pdc_malloc(p->pdc, nb1 + nb2 + 2, fn); + optlist[0] = 0; + if (doc->viewerpreferences) + { + strcat(optlist, doc->viewerpreferences); + strcat(optlist, " "); + } + strcat(optlist, viewerpreference); + + if (doc->viewerpreferences) + pdc_free(p->pdc, doc->viewerpreferences); + doc->viewerpreferences = optlist; + doc->writevpdict |= + pdf_parse_and_write_viewerpreferences(p, optlist, pdc_false); +} + + + + diff --git a/src/pdflib/pdflib/p_draw.c b/src/pdflib/pdflib/p_draw.c new file mode 100644 index 0000000..dc9271e --- /dev/null +++ b/src/pdflib/pdflib/p_draw.c @@ -0,0 +1,410 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_draw.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib drawing routines + * + */ + +#include "p_intern.h" +#include "p_layer.h" +#include "p_tagged.h" + +/* Path segment operators */ + +static void +pdf_begin_path(PDF *p) +{ + if (PDF_GET_STATE(p) == pdf_state_path) + return; + + + + + pdf_end_text(p); + PDF_PUSH_STATE(p, "pdf_begin_path", pdf_state_path); +} + +static void +pdf_end_path(PDF *p) +{ + pdf_ppt *ppt = p->curr_ppt; + + PDF_POP_STATE(p, "pdf_end_path"); + + ppt->gstate[ppt->sl].x = 0; + ppt->gstate[ppt->sl].y = 0; +} + +/* ----------------- Basic functions for API functions --------------*/ + +void +pdf__moveto(PDF *p, pdc_scalar x, pdc_scalar y) +{ + pdf_ppt *ppt = p->curr_ppt; + + pdc_check_number(p->pdc, "x", x); + pdc_check_number(p->pdc, "y", y); + + ppt->gstate[ppt->sl].startx = ppt->gstate[ppt->sl].x = x; + ppt->gstate[ppt->sl].starty = ppt->gstate[ppt->sl].y = y; + + pdf_begin_path(p); + pdc_printf(p->out, "%f %f m\n", x, y); +} + +void +pdf__rmoveto(PDF *p, pdc_scalar x, pdc_scalar y) +{ + pdf_ppt *ppt = p->curr_ppt; + + pdc_scalar x_0 = ppt->gstate[ppt->sl].x; + pdc_scalar y_0 = ppt->gstate[ppt->sl].y; + + pdc_check_number(p->pdc, "x", x); + pdc_check_number(p->pdc, "y", y); + + pdf__moveto(p, x_0 + x, y_0 + y); +} + +void +pdf__lineto(PDF *p, pdc_scalar x, pdc_scalar y) +{ + pdf_ppt *ppt = p->curr_ppt; + + pdc_check_number(p->pdc, "x", x); + pdc_check_number(p->pdc, "y", y); + + pdc_printf(p->out, "%f %f l\n", x, y); + + ppt->gstate[ppt->sl].x = x; + ppt->gstate[ppt->sl].y = y; +} + +void +pdf__rlineto(PDF *p, pdc_scalar x, pdc_scalar y) +{ + pdf_ppt *ppt = p->curr_ppt; + + pdc_scalar x_0 = ppt->gstate[ppt->sl].x; + pdc_scalar y_0 = ppt->gstate[ppt->sl].y; + + pdc_check_number(p->pdc, "x", x); + pdc_check_number(p->pdc, "y", y); + + pdf__lineto(p, x_0 + x, y_0 + y); +} + +void +pdf__curveto(PDF *p, + pdc_scalar x_1, pdc_scalar y_1, + pdc_scalar x_2, pdc_scalar y_2, + pdc_scalar x_3, pdc_scalar y_3) +{ + pdf_ppt *ppt = p->curr_ppt; + + pdc_check_number(p->pdc, "x_1", x_1); + pdc_check_number(p->pdc, "y_1", y_1); + pdc_check_number(p->pdc, "x_2", x_2); + pdc_check_number(p->pdc, "y_2", y_2); + pdc_check_number(p->pdc, "x_3", x_3); + pdc_check_number(p->pdc, "y_3", y_3); + + /* second c.p. coincides with final point */ + if (fabs(x_2 - x_3) < PDC_FLOAT_PREC && + fabs(y_2 - y_3) < PDC_FLOAT_PREC) + pdc_printf(p->out, "%f %f %f %f y\n", x_1, y_1, x_3, y_3); + + /* general case with four distinct points */ + else + pdc_printf(p->out, "%f %f %f %f %f %f c\n", + x_1, y_1, x_2, y_2, x_3, y_3); + + ppt->gstate[ppt->sl].x = x_3; + ppt->gstate[ppt->sl].y = y_3; +} + +void +pdf__rcurveto(PDF *p, + pdc_scalar x_1, pdc_scalar y_1, + pdc_scalar x_2, pdc_scalar y_2, + pdc_scalar x_3, pdc_scalar y_3) +{ + pdf_ppt *ppt = p->curr_ppt; + + pdc_scalar x_0 = ppt->gstate[ppt->sl].x; + pdc_scalar y_0 = ppt->gstate[ppt->sl].y; + + pdc_check_number(p->pdc, "x_1", x_1); + pdc_check_number(p->pdc, "y_1", y_1); + pdc_check_number(p->pdc, "x_2", x_2); + pdc_check_number(p->pdc, "y_2", y_2); + pdc_check_number(p->pdc, "x_3", x_3); + pdc_check_number(p->pdc, "y_3", y_3); + + pdf__curveto(p, x_0 + x_1, y_0 + y_1, + x_0 + x_2, y_0 + y_2, + x_0 + x_3, y_0 + y_3); +} + +void +pdf_rrcurveto(PDF *p, + pdc_scalar x_1, pdc_scalar y_1, + pdc_scalar x_2, pdc_scalar y_2, + pdc_scalar x_3, pdc_scalar y_3) +{ + pdf__rcurveto(p, x_1, y_1, + x_1 + x_2, y_1 + y_2, + x_1 + x_2 + x_3, y_1 + y_2 + y_3); +} + +void +pdf_hvcurveto(PDF *p, pdc_scalar x_1, pdc_scalar x_2, + pdc_scalar y_2, pdc_scalar y_3) +{ + pdf_rrcurveto(p, x_1, 0, x_2, y_2, 0, y_3); +} + +void +pdf_vhcurveto(PDF *p, pdc_scalar y_1, pdc_scalar x_2, + pdc_scalar y_2, pdc_scalar x_3) +{ + pdf_rrcurveto(p, 0, y_1, x_2, y_2, x_3, 0); +} + +void +pdf__rect(PDF *p, pdc_scalar x, pdc_scalar y, + pdc_scalar width, pdc_scalar height) +{ + pdf_ppt *ppt = p->curr_ppt; + + pdc_check_number(p->pdc, "x", x); + pdc_check_number(p->pdc, "y", y); + pdc_check_number(p->pdc, "width", width); + pdc_check_number(p->pdc, "height", height); + + ppt->gstate[ppt->sl].startx = ppt->gstate[ppt->sl].x = x; + ppt->gstate[ppt->sl].starty = ppt->gstate[ppt->sl].y = y; + + pdf_begin_path(p); + pdc_printf(p->out, "%f %f %f %f re\n", x, y, width, p->ydirection * height); +} + +/* 4/3 * (1-cos 45°)/sin 45° = 4/3 * sqrt(2) - 1 */ +#define ARC_MAGIC (0.552284749) + +static void +pdf_short_arc(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r, + pdc_scalar alpha, pdc_scalar beta) +{ + pdc_scalar bcp; + pdc_scalar cos_alpha, cos_beta, sin_alpha, sin_beta; + + alpha = alpha * PDC_DEG2RAD; + beta = beta * PDC_DEG2RAD; + + /* This formula yields ARC_MAGIC for alpha == 0, beta == 90 degrees */ + bcp = (4.0/3 * (1 - cos((beta - alpha)/2)) / sin((beta - alpha)/2)); + + sin_alpha = sin(alpha); + sin_beta = sin(beta); + cos_alpha = cos(alpha); + cos_beta = cos(beta); + + pdf__curveto(p, + x + r * (cos_alpha - bcp * sin_alpha), /* p1 */ + y + r * (sin_alpha + bcp * cos_alpha), + x + r * (cos_beta + bcp * sin_beta), /* p2 */ + y + r * (sin_beta - bcp * cos_beta), + x + r * cos_beta, /* p3 */ + y + r * sin_beta); +} + +static void +pdf_orient_arc(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r, + pdc_scalar alpha, pdc_scalar beta, pdc_scalar orient) +{ + pdf_ppt *ppt = p->curr_ppt; + pdc_scalar rad_a = alpha * PDC_DEG2RAD; + pdc_scalar startx = (x + r * cos(rad_a)); + pdc_scalar starty = (y + r * sin(rad_a)); + + if (PDF_GET_STATE(p) != pdf_state_path) + { + pdf__moveto(p, startx, starty); /* this enters pdf_state_path */ + } + else if ((ppt->gstate[ppt->sl].x != startx + || ppt->gstate[ppt->sl].y != starty)) + { + pdf__lineto(p, startx, starty); + } + + if (orient > 0) + { + while (beta < alpha) + beta += 360; + + if (alpha == beta) + return; + + while (beta - alpha > 90) + { + pdf_short_arc(p, x, y, r, alpha, alpha + 90); + alpha += 90; + } + } + else + { + while (alpha < beta) + alpha += 360; + + if (alpha == beta) + return; + + while (alpha - beta > 90) + { + pdf_short_arc(p, x, y, r, alpha, alpha - 90); + alpha -= 90; + } + } + + if (alpha != beta) + pdf_short_arc(p, x, y, r, alpha, beta); +} + +void +pdf__arc(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r, + pdc_scalar alpha, pdc_scalar beta) +{ + pdc_check_number(p->pdc, "x", x); + pdc_check_number(p->pdc, "y", y); + pdc_check_number_limits(p->pdc, "r", r, PDC_FLOAT_PREC, PDC_FLOAT_MAX); + pdc_check_number(p->pdc, "alpha", alpha); + pdc_check_number(p->pdc, "beta", beta); + + pdf_orient_arc(p, x, y, r, + p->ydirection * alpha, p->ydirection * beta, p->ydirection); +} + +void +pdf__arcn(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r, + pdc_scalar alpha, pdc_scalar beta) +{ + pdc_check_number(p->pdc, "x", x); + pdc_check_number(p->pdc, "y", y); + pdc_check_number_limits(p->pdc, "r", r, PDC_FLOAT_PREC, PDC_FLOAT_MAX); + pdc_check_number(p->pdc, "alpha", alpha); + pdc_check_number(p->pdc, "beta", beta); + + pdf_orient_arc(p, x, y, r, + p->ydirection * alpha, p->ydirection * beta, -p->ydirection); +} + +void +pdf__circle(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r) +{ + pdc_check_number(p->pdc, "x", x); + pdc_check_number(p->pdc, "y", y); + pdc_check_number_limits(p->pdc, "r", r, PDC_FLOAT_PREC, PDC_FLOAT_MAX); + + /* + * pdf_begin_path() not required since we descend to other + * path segment functions. + */ + + /* draw four Bezier curves to approximate a circle */ + pdf__moveto(p, x + r, y); + pdf__curveto(p, x + r, y + r*ARC_MAGIC, x + r*ARC_MAGIC, y + r, x, y + r); + pdf__curveto(p, x - r*ARC_MAGIC, y + r, x - r, y + r*ARC_MAGIC, x - r, y); + pdf__curveto(p, x - r, y - r*ARC_MAGIC, x - r*ARC_MAGIC, y - r, x, y - r); + pdf__curveto(p, x + r*ARC_MAGIC, y - r, x + r, y - r*ARC_MAGIC, x + r, y); + + pdf__closepath(p); +} + +void +pdf__closepath(PDF *p) +{ + pdf_ppt *ppt = p->curr_ppt; + + pdc_puts(p->out, "h\n"); + + ppt->gstate[ppt->sl].x = ppt->gstate[ppt->sl].startx; + ppt->gstate[ppt->sl].y = ppt->gstate[ppt->sl].starty; +} + +void +pdf__endpath(PDF *p) +{ + pdc_puts(p->out, "n\n"); + pdf_end_path(p); +} + +void +pdf__stroke(PDF *p) +{ + pdc_puts(p->out, "S\n"); + pdf_end_path(p); +} + +void +pdf__closepath_stroke(PDF *p) +{ + pdc_puts(p->out, "s\n"); + pdf_end_path(p); +} + +void +pdf__fill(PDF *p) +{ + if (p->curr_ppt->fillrule == pdf_fill_winding) + pdc_puts(p->out, "f\n"); + else if (p->curr_ppt->fillrule == pdf_fill_evenodd) + pdc_puts(p->out, "f*\n"); + + pdf_end_path(p); +} + +void +pdf__fill_stroke(PDF *p) +{ + if (p->curr_ppt->fillrule == pdf_fill_winding) + pdc_puts(p->out, "B\n"); + else if (p->curr_ppt->fillrule == pdf_fill_evenodd) + pdc_puts(p->out, "B*\n"); + + pdf_end_path(p); +} + +void +pdf__closepath_fill_stroke(PDF *p) +{ + if (p->curr_ppt->fillrule == pdf_fill_winding) + pdc_puts(p->out, "b\n"); + else if (p->curr_ppt->fillrule == pdf_fill_evenodd) + pdc_puts(p->out, "b*\n"); + + pdf_end_path(p); +} + +void +pdf__clip(PDF *p) +{ + if (p->curr_ppt->fillrule == pdf_fill_winding) + pdc_puts(p->out, "W n\n"); + else if (p->curr_ppt->fillrule == pdf_fill_evenodd) + pdc_puts(p->out, "W* n\n"); + + pdf_end_path(p); +} + diff --git a/src/pdflib/pdflib/p_encoding.c b/src/pdflib/pdflib/p_encoding.c new file mode 100644 index 0000000..af24792 --- /dev/null +++ b/src/pdflib/pdflib/p_encoding.c @@ -0,0 +1,187 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_encoding.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib encoding handling routines + * + */ + +#include "p_intern.h" +#include "p_font.h" + +void +pdf__encoding_set_char(PDF *p, const char *encoding, int slot, + const char *glyphname, int uv) +{ + int enc; + pdc_encodingvector *ev; + char given; + + if (!encoding || !*encoding) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "encoding", 0, 0, 0); + + if (slot < 0 || slot > 255) + pdc_error(p->pdc, PDC_E_ILLARG_INT, + "slot", pdc_errprintf(p->pdc, "%d", slot), 0, 0); + + if (uv < 0 || uv >= PDC_NUM_BMPVAL) + pdc_error(p->pdc, PDC_E_ILLARG_INT, + "uv", pdc_errprintf(p->pdc, "%d", uv), 0, 0); + + if (!glyphname || !*glyphname) + { + if (uv == 0) + pdc_error(p->pdc, PDF_E_ENC_GLYPHORCODE, 0, 0, 0, 0); + } + + for (enc = (int) pdc_invalidenc + 1; enc < (int) pdc_firstvarenc; enc++) + { + if (!strcmp(encoding, pdc_get_fixed_encoding_name((pdc_encoding) enc))) + pdc_error(p->pdc, PDF_E_ENC_CANTCHANGE, encoding, 0, 0, 0); + } + + if (uv == 0) + { + given = 1; + uv = (int) pdc_insert_glyphname(p->pdc, glyphname); + } + else if (!glyphname || !*glyphname) + { + given = 0; + glyphname = pdc_insert_unicode(p->pdc, (pdc_ushort) uv); + } + else + { + const char *reg_glyphname; + pdc_ushort reg_uv; + int retval; + + given = 1; + reg_glyphname = pdc_unicode2glyphname(p->pdc, (pdc_ushort) uv); + if (reg_glyphname) + { + if (strcmp(reg_glyphname, glyphname) && + p->debug[(int) 'F'] == pdc_true) + { + pdc_warning(p->pdc, PDF_E_ENC_BADGLYPH, + glyphname, + pdc_errprintf(p->pdc, "%04X", uv), + reg_glyphname, 0); + } + + /* We take the registered name */ + } + else + { + retval = pdc_glyphname2unicode(p->pdc, glyphname); + if (retval > -1) + { + reg_uv = (pdc_ushort) retval; + if (reg_uv && reg_uv != (pdc_ushort) uv && + p->debug[(int) 'F'] == pdc_true) + { + pdc_error(p->pdc, PDF_E_ENC_BADUNICODE, + pdc_errprintf(p->pdc, "%04X", uv), glyphname, + pdc_errprintf(p->pdc, "%04X", reg_uv), 0); + } + } + + /* We register the new glyph name and unicode value */ + pdc_register_glyphname(p->pdc, glyphname, (pdc_ushort) uv, + pdc_false); + } + } + + /* search for a registered encoding */ + enc = pdc_find_encoding(p->pdc, encoding); + + /* not found */ + if (enc == pdc_invalidenc) + { + ev = pdc_new_encoding(p->pdc, encoding); + ev->flags |= PDC_ENC_USER; + ev->flags |= PDC_ENC_SETNAMES; + ev->flags |= PDC_ENC_ALLOCCHARS; + + enc = pdc_insert_encoding_vector(p->pdc, ev); + } + + /* encoding vector */ + ev = pdc_get_encoding_vector(p->pdc, (pdc_encoding)enc); + if (!(ev->flags & PDC_ENC_USER)) + { + pdc_error(p->pdc, PDF_E_ENC_CANTCHANGE, encoding, 0, 0, 0); + } + else if (ev->flags & PDC_ENC_USED) + { + pdc_error(p->pdc, PDF_E_ENC_INUSE, encoding, 0, 0, 0); + } + + /* Free character name */ + if (ev->chars[slot] != NULL) + pdc_free(p->pdc, ev->chars[slot]); + + /* Saving */ + ev->codes[slot] = (pdc_ushort) uv; + if (glyphname != NULL) + ev->chars[slot] = pdc_strdup(p->pdc, glyphname); + ev->given[slot] = given; + + pdc_encoding_logg_protocol(p->pdc, ev); +} + +pdc_encoding +pdf_get_hypertextencoding_param(PDF *p, int *codepage) +{ + if (p->hypertextencoding == pdc_invalidenc) + { + p->hypertextencoding = pdf_get_hypertextencoding(p, "auto", + &p->hypertextcodepage, pdc_true); + + if (p->hypertextencoding == pdc_invalidenc) + pdc_error(p->pdc, -1, 0, 0, 0, 0); + } + + if (codepage) + *codepage = p->hypertextcodepage; + + return p->hypertextencoding; +} + +pdc_encoding +pdf_get_hypertextencoding(PDF *p, const char *encoding, int *codepage, + pdc_bool verbose) +{ + pdc_encoding enc = pdc_invalidenc; + + *codepage = 0; + + if (!*encoding) + { + enc = pdc_unicode; + } + else + { + { + enc = pdc_get_encoding(p->pdc, encoding, codepage, verbose); + if (enc < 0 && enc != pdc_invalidenc && enc != pdc_unicode) + { + pdc_set_errmsg(p->pdc, PDF_E_ENC_BADHYPTEXTENC, encoding, + 0, 0, 0); + enc = pdc_invalidenc; + } + } + } + + return enc; +} diff --git a/src/pdflib/pdflib/p_fields.c b/src/pdflib/pdflib/p_fields.c new file mode 100644 index 0000000..4900b3b --- /dev/null +++ b/src/pdflib/pdflib/p_fields.c @@ -0,0 +1,30 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_fields.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib form fields handling routines + * + */ + +#define P_FIELDS_C + +#include "p_intern.h" +#include "p_color.h" +#include "p_font.h" +#include "p_image.h" + + + + + + diff --git a/src/pdflib/pdflib/p_filter.c b/src/pdflib/pdflib/p_filter.c new file mode 100644 index 0000000..d5a11a6 --- /dev/null +++ b/src/pdflib/pdflib/p_filter.c @@ -0,0 +1,120 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_filter.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * Compressed and uncompressed stream output + * + */ + +#include "p_intern.h" + +/* methods for constructing a data source from a file */ + +#define FILE_BUFSIZE 1024 + +void +pdf_data_source_file_init(PDF *p, PDF_data_source *src) +{ + pdc_file *fp; + + src->buffer_length = FILE_BUFSIZE; + src->buffer_start = (pdc_byte *) + pdc_malloc(p->pdc, src->buffer_length, "pdf_data_source_file_init"); + + fp = pdc_fsearch_fopen(p->pdc, (const char *) src->private_data, NULL, + "embedded ", PDC_FILE_BINARY); + + if (fp == NULL) + pdc_error(p->pdc, -1, 0, 0, 0, 0); + + if (src->offset) + pdc_fseek(fp, src->offset, SEEK_SET); + + src->private_data = (void *) fp; + src->total = (long) 0; +} + +pdc_bool +pdf_data_source_file_fill(PDF *p, PDF_data_source *src) +{ + size_t bytes_needed; + (void) p; /* avoid compiler warning "unreferenced parameter" */ + + if (src->length != (long) 0 && src->total + FILE_BUFSIZE > src->length) + bytes_needed = (size_t) (src->length - src->total); + else + bytes_needed = FILE_BUFSIZE; + + src->next_byte = src->buffer_start; + src->bytes_available = pdc_fread(src->buffer_start, 1, + bytes_needed, (pdc_file *) (src->private_data)); + + src->total += (long) src->bytes_available; + + if (src->bytes_available == 0) + return pdc_false; + else + return pdc_true; +} + +void +pdf_data_source_file_terminate(PDF *p, PDF_data_source *src) +{ + pdc_free(p->pdc, (void *) src->buffer_start); + pdc_fclose((pdc_file *) src->private_data); + + if (src->length != (long) 0 && src->total != src->length) + pdc_error(p->pdc, PDC_E_IO_READ, "?", 0, 0, 0); +} + +/* methods for constructing a data source from a memory buffer */ + +int +pdf_data_source_buf_fill(PDF *p, PDF_data_source *src) +{ + (void) p; /* avoid compiler warning "unreferenced parameter" */ + + if (src->next_byte == NULL) { + src->next_byte = src->buffer_start; + src->bytes_available = src->buffer_length; + return pdc_true; + } + + return pdc_false; +} + +/* copy the complete contents of src to a stream */ +void +pdf_copy_stream(PDF *p, PDF_data_source *src, pdc_bool compress) +{ + int oldcompresslevel = pdc_get_compresslevel(p->out); + + if (!compress) + pdc_set_compresslevel(p->out, 0); + + if (src->init) + src->init(p, src); + + pdc_begin_pdfstream(p->out); + + while (src->fill(p, src)) + pdc_write(p->out, src->next_byte, src->bytes_available); + + pdc_end_pdfstream(p->out); + + if (src->terminate) + src->terminate(p, src); + + if (!compress) + pdc_set_compresslevel(p->out, oldcompresslevel); +} diff --git a/src/pdflib/pdflib/p_font.c b/src/pdflib/pdflib/p_font.c new file mode 100644 index 0000000..5dfce77 --- /dev/null +++ b/src/pdflib/pdflib/p_font.c @@ -0,0 +1,2513 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_font.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib font handling routines + * + */ + +#define P_FONT_C + +#include "p_intern.h" +#include "p_color.h" +#include "p_defopt.h" +#include "p_font.h" +#include "p_tagged.h" + +#include "ft_truetype.h" + + +#define PDF_TTC_SEPARATOR ':' + +static const pdc_keyconn pdf_fonttype_pdfkeylist[] = +{ + {"Type1", fnt_Type1}, + {"MMType1", fnt_MMType1}, + {"TrueType", fnt_TrueType}, + {"Type0", fnt_CIDFontType2}, + {"Type1", fnt_Type1C}, + {"Type0", fnt_CIDFontType0}, + {"Type3", fnt_Type3}, + {NULL, 0} +}; + +typedef enum +{ + font_afm = 1, + font_pfm = 2, + font_ttot = 3, + font_pfab = 4 +} +pdf_fontfile_type; + +static const pdc_keyconn pdf_extension_names[] = +{ + {".tte", font_ttot}, + {".ttf", font_ttot}, + {".otf", font_ttot}, + {".afm", font_afm}, + {".pfm", font_pfm}, + {".ttc", font_ttot}, + {".TTE", font_ttot}, + {".TTF", font_ttot}, + {".OTF", font_ttot}, + {".AFM", font_afm}, + {".PFM", font_pfm}, + {".TTC", font_ttot}, + {".pfa", font_pfab}, + {".pfb", font_pfab}, + {".PFA", font_pfab}, + {".PFB", font_pfab}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_fontoption_keylist[] = +{ + {"fontname", fo_fontname}, + {"encoding", fo_encoding}, + {"fontstyle", fo_fontstyle}, + {"monospace", fo_monospace}, + {NULL, 0} +}; + + +void +pdf_init_font(PDF *p, pdf_font *font, pdf_font_options *fo) +{ + (void) p; + + /* font metric */ + fnt_init_font(&font->ft); + + /* font options */ + font->opt = *fo; + font->verbose = fo->fontwarning; + + font->apiname = NULL; + font->filename = NULL; + font->metricfilename = NULL; + + font->used_in_formfield = pdc_false; + font->used_in_current_doc = pdc_false; + font->used_on_current_page = pdc_false; + font->obj_id = PDC_BAD_ID; + + font->cff_offset = 0; + font->cff_length = 0; + + font->t3font = NULL; + font->hasoriginal = pdc_false; + + font->encapiname = NULL; + font->outcmapname = NULL; + font->codepage = 0; + font->towinansi = pdc_invalidenc; + font->hasnomac = pdc_false; + font->passthrough = pdc_false; + font->unibyte = pdc_false; + font->asciispace = pdc_false; + font->issemantic = pdc_false; + font->widthsmissing = pdc_false; + font->missingglyphs = 0; + font->metricflags = 0; + font->supplement = 0; + font->symenc = pdc_invalidenc; + font->replacementchar = -1; + font->replacementcode = -1; + + font->codesize = 1; + font->lastcode = -1; + font->gid0code = -1; + font->usedgids = NULL; + font->expectglyphs = pdc_false; + font->iscidfont = pdc_false; + +} + +void +pdf_cleanup_font(PDF *p, pdf_font *font) +{ + if (font->ft.imgname) + pdc_unlock_pvf(p->pdc, font->ft.imgname); + + /* font metric */ + fnt_cleanup_font(p->pdc, &font->ft); + + if (font->apiname != NULL) + { + pdc_free(p->pdc, font->apiname); + font->apiname = NULL; + } + + if (font->metricfilename != NULL) + { + pdc_free(p->pdc, font->metricfilename); + font->metricfilename = NULL; + } + + if (font->encapiname != NULL) + { + pdc_free(p->pdc, font->encapiname); + font->encapiname = NULL; + } + + if (font->outcmapname != NULL) + { + pdc_free(p->pdc, font->outcmapname); + font->outcmapname = NULL; + } + + + if (font->usedgids != NULL) + { + pdc_free(p->pdc, font->usedgids); + font->usedgids = NULL; + } + + /* Type3 font */ + if (font->t3font != NULL && font->hasoriginal) + { + pdf_cleanup_t3font(p, font->t3font); + pdc_free(p->pdc, font->t3font); + font->t3font = NULL; + } + +} + +void +pdf_init_fonts(PDF *p) +{ + p->fonts = NULL; + p->fonts_number = 0; + p->fonts_capacity = 0; + p->t3slot = -1; + + + pdc_init_encoding_info_ids(p->pdc); +} + +void +pdf_cleanup_fonts(PDF *p) +{ + int slot; + + if (p->fonts != NULL) + { + for (slot = 0; slot < p->fonts_number; slot++) + pdf_cleanup_font(p, &p->fonts[slot]); + + pdc_free(p->pdc, p->fonts); + p->fonts = NULL; + } + +} + +int +pdf_insert_font(PDF *p, pdf_font *font) +{ + static const char fn[] = "pdf_insert_font"; + int slot = p->fonts_number; + + /* insert font */ + if (p->fonts_number == p->fonts_capacity) + { + if (p->fonts_capacity == 0) + { + p->fonts_capacity = FONTS_CHUNKSIZE; + p->fonts = (pdf_font *) pdc_calloc(p->pdc, + sizeof(pdf_font) * p->fonts_capacity, fn); + } + else + { + p->fonts_capacity *= 2; + p->fonts = (pdf_font *) pdc_realloc(p->pdc, p->fonts, + sizeof(pdf_font) * p->fonts_capacity, fn); + } + } + p->fonts[slot] = *font; + + p->fonts_number++; + + return slot; +} + + +const char * +pdf_get_pdf_fontname(pdf_font *font) +{ + const char *fontname; + + fontname = fnt_get_abb_std_fontname(font->ft.name); + if (fontname == NULL) + fontname = fnt_get_abb_cjk_fontname(font->ft.name); + if (fontname == NULL) + fontname = font->ft.name; + + return (const char *) fontname; +} + +const char * +pdf_get_encoding_name(PDF *p, pdc_encoding enc, pdf_font *font) +{ + const char *apiname = pdc_get_fixed_encoding_name(enc); + if (!apiname[0] && enc >= 0) + { + pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc); + apiname = (const char *) ev->apiname; + } + else if (enc == pdc_cid && font != NULL && font->outcmapname != NULL) + apiname = (const char *) font->outcmapname; + return apiname; +} + +char * +pdf_get_encoding_adaptname(PDF *p, pdc_encoding enc, pdf_font *font, + const char *fontname) +{ + static const char *fn = "pdf_get_encoding_adaptname"; + char *encname = (char *) pdf_get_encoding_name(p, enc, font); + char *adaptname = NULL; + size_t len; + + len = strlen(encname) + 1 + strlen(fontname) + 1; + adaptname = (char *) pdc_malloc_tmp(p->pdc, len, fn, 0, 0); + strcpy(adaptname, encname); + strcat(adaptname, PDC_ENC_MODSEPAR); + strcat(adaptname, fontname); + + return adaptname; +} + +pdc_encodingvector * +pdf_create_font_encoding(PDF *p, pdc_encoding enc, pdf_font *font, + const char *fontname, pdc_bool kreg) +{ + pdc_encodingvector *ev = NULL; + char *adaptname = NULL; + + adaptname = pdf_get_encoding_adaptname(p, enc, font, fontname); + + /* search for a registered encoding */ + enc = pdc_find_encoding(p->pdc, adaptname); + if (enc != pdc_invalidenc) + { + font->ft.enc = enc; + } + else + { + /* create a font encoding */ + ev = pdc_new_encoding(p->pdc, adaptname); + ev->flags |= PDC_ENC_FONT; + ev->flags |= PDC_ENC_SETNAMES; + + if (kreg) + { + enc = pdc_insert_encoding_vector(p->pdc, ev); + font->ft.enc = enc; + } + } + + pdc_free_tmp(p->pdc, adaptname); + + return ev; +} + +const char * +pdf_get_font_char_option(PDF *p, pdf_font_optflags fflags) +{ + pdf_text_options *to = p->curr_ppt->currto; + pdf_font *currfont; + + if (p->fonts_number == 0 || to->font == -1) + pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, + pdc_get_keyword(fflags, pdf_fontoption_keylist), 0, 0, 0); + currfont = &p->fonts[to->font]; + + switch (fflags) + { + case fo_fontname: + return (const char *) currfont->ft.name; + + case fo_encoding: + return pdf_get_encoding_name(p, currfont->ft.enc, currfont); + + case fo_fontstyle: + return pdc_get_keyword(currfont->opt.fontstyle, + pdf_fontstyle_pdfkeylist); + + default: + return NULL; + } +} + +double +pdf_get_font_float_option(PDF *p, pdf_font_optflags fflags) +{ + pdf_text_options *to = p->curr_ppt->currto; + pdf_font *currfont; + + if (p->fonts_number == 0 || to->font == -1) + pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, + pdc_get_keyword(fflags, pdf_fontoption_keylist), 0, 0, 0); + currfont = &p->fonts[to->font]; + + switch (fflags) + { + case fo_monospace: + return (double) currfont->opt.monospace; + + default: + return 0; + } +} + +static const pdc_keyconn pdf_courier_keylist[] = +{ + {"Courier", fnt_Normal}, + {"Courier-Bold", fnt_Bold}, + {"Courier-Oblique", fnt_Italic}, + {"Courier-BoldOblique", fnt_BoldItalic}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_helvetica_keylist[] = +{ + {"Helvetica", fnt_Normal}, + {"Helvetica-Bold", fnt_Bold}, + {"Helvetica-Oblique", fnt_Italic}, + {"Helvetica-BoldOblique", fnt_BoldItalic}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_times_keylist[] = +{ + {"Times-Roman", fnt_Normal}, + {"Times-Bold", fnt_Bold}, + {"Times-Italic", fnt_Italic}, + {"Times-BoldItalic", fnt_BoldItalic}, + {NULL, 0} +}; + +static const char * +pdf_get_fontname_core(pdf_font *font, const char *fontname, pdc_bool checktimes) +{ + const char *fname = NULL; + + /* font style for core fonts */ + if (font->opt.fontstyle != fnt_Normal) + { + if (!strcmp(fontname, "Courier")) + fname = pdc_get_keyword(font->opt.fontstyle, pdf_courier_keylist); + else if (!strcmp(fontname, "Helvetica")) + fname = pdc_get_keyword(font->opt.fontstyle, pdf_helvetica_keylist); + else if (!strcmp(fontname, "Times-Roman")) + fname = pdc_get_keyword(font->opt.fontstyle, pdf_times_keylist); + } + + if (checktimes) + { + if (!strcmp(fontname, "Times")) + fname = pdc_get_keyword(font->opt.fontstyle, pdf_times_keylist); + } + + return fname; +} + +static pdc_bool +pdf_get_metrics_core(PDF *p, pdf_font *font, const char *fontname, + pdc_encoding enc, pdc_bool checktimes) +{ + const char *fname = NULL; + const fnt_font_metric *ftm; + + fname = pdf_get_fontname_core(font, fontname, checktimes); + if (fname != NULL) + { + fontname = fname; + font->opt.fontstyle = fnt_Normal; + } + + ftm = fnt_get_core_metric(fontname); + if (ftm != NULL) + { + pdc_logg_cond(p->pdc, 1, trc_font, + "\tLoading metrics data for core font \"%s\":\n", fontname); + + /* Fill up the font struct */ + fnt_fill_font_metric(p->pdc, &font->ft, + pdc_false, + ftm); + font->ft.enc = enc; + + /* all new glyph names of AGL 2.0 are missing */ + font->missingglyphs = 0xFFFFFFFF; + + /* Process metrics data */ + if (pdf_process_metrics_data(p, font, fontname)) + { + if (pdf_make_fontflag(p, font)) + { + if (!font->opt.monospace) + return pdc_true; + else + pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace", + 0, 0, 0); + } + } + + return pdc_false; + } + + return pdc_undef; +} + +void +pdf_font_set_missvalues(PDF *p, pdf_font *font) +{ + pdf_font_options *fo = &font->opt; + fnt_font_metric *ftm = &font->ft.m; + + (void) p; + + if (ftm->descender > 0) + ftm->descender = -(ftm->descender); + + if (fo->mask & (1L << fo_ascender)) + { + font->metricflags |= font_ascender; + ftm->ascender = fo->ascender; + } + else if (ftm->ascender <= 0) + { + font->metricflags |= font_ascender; + ftm->ascender = 720; + } + + if (fo->mask & (1L << fo_descender)) + { + font->metricflags |= font_descender; + ftm->descender = fo->descender; + } + else if (ftm->descender == FNT_MISSING_FONTVAL) + { + font->metricflags |= font_descender; + ftm->descender = (int) PDC_ROUND(-0.25 * ftm->ascender); + } + + if (fo->mask & (1L << fo_capheight)) + { + font->metricflags |= font_capheight; + ftm->capHeight = fo->capheight; + } + else if (ftm->capHeight <= 0) + { + font->metricflags |= font_capheight; + ftm->capHeight = (int) PDC_ROUND(0.93 * ftm->ascender); + } + + if (fo->mask & (1L << fo_xheight)) + { + font->metricflags |= font_xheight; + ftm->xHeight = fo->xheight; + } + else if (ftm->xHeight <= 0) + { + font->metricflags |= font_xheight; + ftm->xHeight = (int) PDC_ROUND(0.66 * ftm->ascender); + } + + if (fo->mask & (1L << fo_linegap)) + { + font->metricflags |= font_linegap; + font->ft.linegap = fo->linegap; + } + else if (font->ft.linegap == FNT_MISSING_FONTVAL) + { + font->metricflags |= font_linegap; + font->ft.linegap = (int) PDC_ROUND(0.23 * ftm->ascender); + } + + if (ftm->llx == FNT_MISSING_FONTVAL) + ftm->llx = -50; + if (ftm->lly == FNT_MISSING_FONTVAL) + ftm->lly = ftm->descender; + if (ftm->urx == FNT_MISSING_FONTVAL) + ftm->urx = 1000; + if (ftm->ury == FNT_MISSING_FONTVAL) + ftm->ury = ftm->ascender; + + /* try to fix broken entries */ + if (ftm->lly > ftm->ury) + ftm->ury = ftm->lly + ftm->ascender; + if (ftm->llx > ftm->urx) + ftm->urx = ftm->llx + 1000; +} + +pdc_bool +pdf_font_get_is_faked(pdf_font *font, pdf_font_values flag) +{ + return (font->metricflags & flag) ? pdc_true : pdc_false; +} + +double +pdf_font_get_metric_value(int value) +{ + return (double) value / 1000.0; +} + + +/* --------------------------- font processing ---------------------------- */ + +pdc_bool +pdf_make_fontflag(PDF *p, pdf_font *font) +{ + int errcode = 0; + + if (font->ft.m.type != fnt_Type3) + { + if (font->ft.m.isFixedPitch) + font->ft.m.flags |= FNT_FIXEDWIDTH; + + if (font->ft.issymbfont == pdc_false || + font->ft.enc == pdc_winansi || + font->ft.enc == pdc_macroman || + font->ft.enc == pdc_ebcdic || + font->ft.enc == pdc_ebcdic_37 || + font->ft.enc == pdc_ebcdic_winansi) + font->ft.m.flags |= FNT_ADOBESTANDARD; + else + font->ft.m.flags |= FNT_SYMBOL; + + if (font->ft.m.italicAngle < 0 || + font->opt.fontstyle == fnt_Italic || + font->opt.fontstyle == fnt_BoldItalic) + font->ft.m.flags |= FNT_ITALIC; + if (font->ft.m.italicAngle == 0 && + font->ft.m.flags & FNT_ITALIC) + font->ft.m.italicAngle = FNT_DEF_ITALICANGLE; + + /* heuristic to identify (small) caps fonts */ + if (font->ft.name && + (strstr(font->ft.name, "Caps") || + !strcmp(font->ft.name + strlen(font->ft.name) - 2, "SC"))) + font->ft.m.flags |= FNT_SMALLCAPS; + + if (font->opt.fontstyle == fnt_Bold || + font->opt.fontstyle == fnt_BoldItalic) + font->ft.weight = FNT_FW_BOLD; + + if (strstr(font->ft.name, "Bold") || + font->ft.weight >= FNT_FW_BOLD) + font->ft.m.flags |= FNT_FORCEBOLD; + + /* determine values for FontWeight to StemV */ + if (font->ft.m.StdVW == 0) + font->ft.m.StdVW = fnt_weight2stemv(font->ft.weight); + else if (font->ft.weight == 0) + font->ft.weight = fnt_stemv2weight(font->ft.m.StdVW); + } + + fnt_font_logg_protocol(p->pdc, &font->ft); + + switch(font->ft.m.type) + { + case fnt_Type1: + case fnt_MMType1: + case fnt_Type3: + if (font->opt.fontstyle == fnt_Bold || + font->opt.fontstyle == fnt_BoldItalic) + { + font->metricflags |= font_bold; + } + + if (font->opt.fontstyle == fnt_Italic || + font->opt.fontstyle == fnt_BoldItalic) + { + font->metricflags |= font_italic; + } + + break; + + default: + if (font->opt.embedding) + { + if (font->opt.fontstyle == fnt_Bold || + font->opt.fontstyle == fnt_BoldItalic) + { + font->metricflags |= font_bold; + } + + if (font->opt.fontstyle == fnt_Italic || + font->opt.fontstyle == fnt_BoldItalic) + { + font->metricflags |= font_italic; + } + } + break; + } + + + return errcode ? pdc_false : pdc_true; +} + +int +pdf_get_code_or_glyphid(PDF *p, pdf_font *font, pdc_encodingvector *ev, + pdc_ushort uv) +{ + if (ev != NULL) + { + int code = pdc_get_encoding_bytecode(p->pdc, ev, uv); + + if (code >= 0) + { + if (fnt_get_glyphid(code, &font->ft) <= 0) + code = 0; + } + return code; + } + + return fnt_get_glyphid((int) uv, &font->ft); +} + +void +pdf_set_replchar(PDF *p, pdf_font *font) +{ + pdc_encoding enc = font->ft.enc; + + switch (enc) + { + case pdc_glyphid: + case pdc_cid: + return; + + case pdc_builtin: + font->replacementcode = 0; + return; + + case pdc_unicode: + default: + { + pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc); + pdc_ushort uv = 0; + int cg = 0; + uv = PDC_UNICODE_NBSP; + cg = pdf_get_code_or_glyphid(p, font, ev, uv); + if (cg <= 0) + { + uv = PDC_UNICODE_SPACE; + cg = pdf_get_code_or_glyphid(p, font, ev, uv); + if (cg <= 0) + { + uv = 0; + cg = 0; + } + } + + font->replacementchar = (int) uv; + font->replacementcode = cg; + } + return; + } +} + +void +pdf_font_issemantic(PDF *p, pdf_font *font) +{ + pdc_encoding enc = font->ft.enc; + pdc_ushort spacechar = 0; + + /* Flag: encoding with ASCII space for wordspacing */ + if (enc >= 0) + { + pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc); + int i; + + ev->flags |= PDC_ENC_USED; + i = pdc_get_encoding_bytecode(p->pdc, ev, PDC_UNICODE_SPACE); + if (i > -1) + { + spacechar = (pdc_ushort) i; + if (spacechar == PDC_UNICODE_SPACE) + font->asciispace = pdc_true; + } + } + + /* Flag: encoding is Unicode interpretable */ + if ((enc >= 0) || + (enc == pdc_cid && font->codesize == 2) || + (enc == pdc_unicode)) + font->issemantic = pdc_true; + + /* determine code of space character */ + switch(enc) + { + case pdc_cid: + if (font->codesize == 2) + font->ft.spacechar = PDC_UNICODE_SPACE; + break; + + case pdc_unicode: + font->ft.spacechar = PDC_UNICODE_SPACE; + break; + + case pdc_glyphid: + font->ft.spacechar = + (pdc_ushort) MAX(fnt_get_glyphid(PDC_UNICODE_SPACE, &font->ft), 0); + break; + + default: + font->ft.spacechar = spacechar; + break; + } +} + +/* definitions of font options */ +static const pdc_defopt pdf_load_font_options[] = +{ + PDF_FONT_OPTIONS2 + PDF_FONT_OPTIONS3 + PDF_ERRORPOLICY_OPTION + PDC_OPT_TERMINATE +}; + +void +pdf_init_font_options(PDF *p, pdf_font_options *fo) +{ + static const char fn[] = "pdf_init_font_options"; + + if (fo == NULL) + { + p->currfo = (pdf_font_options *) pdc_malloc(p->pdc, + sizeof(pdf_font_options), fn); + + + fo = p->currfo; + } + else + { + } + + + fo->embedding = pdc_false; /* default true if CID custom font */ + fo->encoding = NULL; + fo->flags = 0; + fo->fontname = NULL; + fo->fontstyle = fnt_Normal; + fo->fontwarning = p->debug[(int) 'F']; + fo->fontwarning = pdf_get_errorpolicy(p, NULL, fo->fontwarning); + fo->mask = 0; + fo->monospace = 0; + fo->ascender = 0; + fo->descender = 0; + fo->capheight = 0; + fo->xheight = 0; + fo->linegap = 0; + fo->auxiliary = pdc_false; + +} + +void +pdf_cleanup_font_curroptions(PDF *p) +{ + if (p->currfo) + { + pdc_free(p->pdc, p->currfo); + p->currfo = NULL; + } +} + +void +pdf_cleanup_font_options(PDF *p, pdf_font_options *fo) +{ + if (fo->fontname != NULL) + { + pdc_free(p->pdc, fo->fontname); + fo->fontname = NULL; + } + + if (fo->encoding != NULL) + { + pdc_free(p->pdc, fo->encoding); + fo->encoding = NULL; + } +} + +void +pdf_parse_font_options(PDF *p, const char *optlist) +{ + pdc_resopt *resopts = pdc_parse_optionlist(p->pdc, optlist, + pdf_load_font_options, NULL, pdc_true); + + pdf_get_font_options(p, p->currfo, resopts); + pdc_cleanup_optionlist(p->pdc, resopts); +} + +void +pdf_get_font_options(PDF *p, pdf_font_options *fo, pdc_resopt *resopts) +{ + int inum; + + (void) p; + + if (fo->flags & is_block || + fo->flags & is_textline || + fo->flags & is_textflow) + { + if (pdc_get_optvalues("fontname", resopts, NULL, NULL)) + { + fo->fontname = (char *)pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + fo->mask |= (1L << fo_fontname); + } + + if (pdc_get_optvalues("encoding", resopts, NULL, NULL)) + { + fo->encoding = (char *)pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + fo->mask |= (1L << fo_encoding); + } + } + + if (pdc_get_optvalues("fontwarning", resopts, &fo->fontwarning, NULL)) + fo->mask |= (1L << fo_fontwarning); + fo->fontwarning = pdf_get_errorpolicy(p, resopts, fo->fontwarning); + + if (pdc_get_optvalues("embedding", resopts, &fo->embedding, NULL)) + fo->mask |= (1L << fo_embedding); + + + if (pdc_get_optvalues("fontstyle", resopts, &inum, NULL)) + { + fo->fontstyle = (fnt_fontstyle) inum; + fo->mask |= (1L << fo_fontstyle); + } + + if (pdc_get_optvalues("monospace", resopts, &fo->monospace, NULL)) + fo->mask |= (1L << fo_monospace); + + if (pdc_get_optvalues("ascender", resopts, &fo->ascender, NULL)) + fo->mask |= (1L << fo_ascender); + + if (pdc_get_optvalues("descender", resopts, &fo->descender, NULL)) + fo->mask |= (1L << fo_descender); + + if (pdc_get_optvalues("capheight", resopts, &fo->capheight, NULL)) + fo->mask |= (1L << fo_capheight); + + if (pdc_get_optvalues("xheight", resopts, &fo->xheight, NULL)) + fo->mask |= (1L << fo_xheight); + + if (pdc_get_optvalues("linegap", resopts, &fo->linegap, NULL)) + fo->mask |= (1L << fo_linegap); + +} + +int +pdf__load_font(PDF *p, const char *fontname, int inlen, + const char *encoding, const char *optlist) +{ + int slot; + pdf_font_options fo; + + if (encoding == NULL || *encoding == '\0') + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "encoding", 0, 0, 0); + + if (fontname == NULL) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0); + + /* initialize */ + pdf_init_font_options(p, &fo); + + /* Converting fontname */ + fo.fontname = (char *) pdf_convert_name(p, fontname, inlen, + PDC_CONV_WITHBOM); + if (fo.fontname == NULL || *fo.fontname == '\0') + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0); + + /* encoding */ + fo.encoding = (char *) pdc_strdup(p->pdc, encoding); + + /* parsing option list */ + if (optlist && strlen(optlist)) + { + pdc_resopt *resopts; + pdc_clientdata data; + + pdf_set_clientdata(p, &data); + resopts = pdc_parse_optionlist(p->pdc, optlist, + pdf_load_font_options, &data, pdc_true); + if (!resopts) + { + pdf_cleanup_font_options(p, &fo); + return -1; + } + + pdf_get_font_options(p, &fo, resopts); + pdc_cleanup_optionlist(p->pdc, resopts); + } + + slot = pdf_load_font_internal(p, &fo); + return slot; +} + +static void +pdf_check_font_identical(PDF *p, pdf_font *font, int *slot) +{ + pdf_font *oldfont = &p->fonts[*slot]; + const char *optname = NULL; + + if (!oldfont->opt.embedding && font->opt.embedding) + { + optname = "embedding"; + if (p->errorpolicy == errpol_legacy) + { + pdc_warning(p->pdc, PDF_E_FONT_NOTFULFILL, optname, optname, + 0, 0); + } + else + { + pdc_set_errmsg(p->pdc, PDF_E_FONT_NOTFULFILL, optname, optname, + 0, 0); + *slot = -1; + } + } + +} + +pdc_bool +pdf_check_font_embedding(PDF *p, pdf_font *font, const char *fontname) +{ + (void) p; + (void) font; + (void) fontname; + + + + return pdc_true; +} + +int +pdf_load_font_internal(PDF *p, pdf_font_options *fo) +{ + pdc_bool logg2 = pdc_logg_is_enabled(p->pdc, 2, trc_font); + const char *fontname; + const char *encoding; + const char *encoding_aux; + pdc_encoding enc = pdc_invalidenc; + pdf_font tmpfont, *font; + const char *filename = NULL; + const char *extension = NULL; + const char *outfilename = NULL; + char *fontname_p = NULL; + char testfilename[PDF_MAX_FONTNAME + 5]; + char *sf, *mmparam, mastername[PDF_MAX_FONTNAME + 1]; + char ittc; + size_t len; + pdc_bool retval = pdc_false; + int slot = -1, i; + + /* host or UTF-8 encoded font name without BOM */ + fontname_p = pdc_utf8_to_hostbytes(p->pdc, pdc_false, fo->fontname); + if (fontname_p == NULL) + { + fontname = pdc_utf8strprint(p->pdc, fo->fontname); + } + else + { + fontname = pdc_utf8strprint(p->pdc, fontname_p); + pdc_free(p->pdc, fontname_p); + } + fontname_p = NULL; + + /* font encoding */ + encoding = fo->encoding; + encoding_aux = encoding; + + /* initialize font struct */ + font = &tmpfont; + pdf_init_font(p, font, fo); + + /* error message prefix */ + pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX, fontname, encoding, 0, 0); + + + + + /* API font name */ + font->apiname = pdc_strdup(p->pdc, fontname); + + /* UTF-8 font name with BOM */ + font->ft.utf8name = pdc_strdup(p->pdc, fo->fontname); + + pdc_logg_cond(p->pdc, 1, trc_font, "\tFont UTF-8 name: \"%s\"\n", + font->ft.utf8name); + + /* specified encoding name */ + font->encapiname = pdc_strdup(p->pdc, encoding); + + /* search for a registered encoding */ + enc = pdc_find_encoding(p->pdc, encoding); + if (enc == pdc_invalidenc || enc == pdc_unicode) + { + /* search for a predefined CMap and registered fonts */ + if (!pdf_handle_cidfont(p, fontname, encoding, enc, font, &slot, &enc)) + goto PDF_PREMATURE_EXIT; + + if (enc == pdc_invalidenc) + { + /* search for a new encoding */ + enc = pdc_insert_encoding(p->pdc, encoding, &font->codepage, + font->verbose); + if (enc == pdc_invalidenc) + goto PDF_PREMATURE_EXIT; + } + else if (enc == pdc_cid) + { + if (slot == -1) + goto PDF_NEWFONT_EXIT; + else + goto PDF_PREMATURE_EXIT; + } + else if (enc == pdc_glyphid) + { + encoding_aux = "glyphid"; + } + else if (enc == pdc_unicode) + { + encoding_aux = "unicode"; + } + } + + if (pdc_strcmp(font->encapiname, encoding)) + { + pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX2, + fontname, font->encapiname, encoding, 0); + } + encoding = encoding_aux; + + encoding = pdc_get_user_encoding(p->pdc, enc); + pdc_logg_cond(p->pdc, 1, trc_encoding, "\tFont encoding: \"%s\"\n", + encoding); + + if (enc == pdc_unicode || enc == pdc_glyphid) + { + pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0); + goto PDF_PREMATURE_EXIT; + } + + /* + * Look whether font is already in the cache. + * Look first for the auxiliary font (obj_id == -1). + * If a font with same encoding and same relevant options is found, + * return its handle. + * If a Type 3 font with the same name but different encoding + * is found, make a copy in a new slot and attach the requested encoding. + */ + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tFont will be searched in the PDFlib font cache\n"); + for (slot = 0; slot < p->fonts_number; slot++) + { + if (p->fonts[slot].obj_id == PDC_BAD_ID && + p->fonts[slot].ft.m.type != fnt_Type3) + { + if (font->opt.auxiliary) + goto PDF_PREMATURE_EXIT; + } + else if (!font->opt.auxiliary && + !pdc_strcmp(p->fonts[slot].apiname, fontname) && + p->fonts[slot].opt.fontstyle == font->opt.fontstyle) + { + if (p->fonts[slot].ft.m.type == fnt_Type3) + { + if (logg2) + pdc_logg(p->pdc, "\t\tType3 font [%d] found\n", slot); + + if (enc < pdc_winansi && enc != pdc_unicode) + { + pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0); + + slot = -1; + goto PDF_PREMATURE_EXIT; + } + + if (p->fonts[slot].ft.enc != enc) + { + if (!pdf_handle_t3font(p, fontname, enc, font, &slot)) + { + slot = -1; + goto PDF_PREMATURE_EXIT; + } + if (slot > -1) + font = &p->fonts[slot]; + goto PDF_NEWFONT_EXIT; + } + + goto PDF_PREMATURE_EXIT; + } + else if (p->fonts[slot].opt.monospace == font->opt.monospace + ) + { + if (p->fonts[slot].ft.enc == enc && + p->fonts[slot].codepage == font->codepage) + { + if (logg2) + pdc_logg(p->pdc, + "\t\tfont [%d] with same encoding found\n", + slot); + + pdf_check_font_identical(p, font, &slot); + goto PDF_PREMATURE_EXIT; + } + else + { + char *adaptname; + int kc; + + /* Comparing apiname of encoding */ + if (!pdc_stricmp(font->encapiname, + p->fonts[slot].encapiname) && + !pdc_stricmp(font->ft.cmapname, + p->fonts[slot].ft.cmapname)) + { + if (logg2) + pdc_logg(p->pdc, + "\t\tfont [%d] with same encoding " + "apiname '%s' found\n", slot, encoding); + + pdf_check_font_identical(p, font, &slot); + goto PDF_PREMATURE_EXIT; + } + + /* Name of adapted to font encoding */ + adaptname = + pdf_get_encoding_adaptname(p, enc, font, fontname); + kc = strcmp(adaptname, pdf_get_encoding_name(p, + p->fonts[slot].ft.enc, &p->fonts[slot])); + if (!kc) + { + if (logg2) + pdc_logg(p->pdc, + "\t\tfont [%d] with same internal " + "encoding name '%s' found\n", + slot, adaptname); + pdc_free_tmp(p->pdc, adaptname); + + pdf_check_font_identical(p, font, &slot); + goto PDF_PREMATURE_EXIT; + } + pdc_free_tmp(p->pdc, adaptname); + } + } + } + else if (!font->opt.auxiliary && + p->fonts[slot].ft.m.type == fnt_Type1 && + p->fonts[slot].ft.isstdfont && p->fonts[slot].ft.enc == enc) + { + /* different core font specifications */ + const char *fname = pdf_get_fontname_core(font, fontname, pdc_true); + + if ((fname != NULL && !strcmp(fname, p->fonts[slot].ft.name) && + p->fonts[slot].opt.fontstyle == fnt_Normal) || + (!strcmp(fontname, p->fonts[slot].ft.name) && + p->fonts[slot].opt.fontstyle == font->opt.fontstyle)) + { + if (logg2) + pdc_logg(p->pdc, + "\t\tfont [%d] with same font style '%s' found\n", + slot, pdc_get_keyword(font->opt.fontstyle, + pdf_fontstyle_pdfkeylist)); + + pdf_check_font_identical(p, font, &slot); + goto PDF_PREMATURE_EXIT; + } + } + } + + slot = -1; + pdc_logg_cond(p->pdc, 1, trc_font, + "\tFont not found in the PDFlib font cache\n"); + + /* embedding check */ + if (!pdf_check_font_embedding(p, font, fontname)) + { + goto PDF_PREMATURE_EXIT; + } + + /* Multiple Master handling: + * - strip MM parameters to build the master name + * - the master name is used to find the metrics + * - the instance name (client-supplied font name) is used in all places + * - although the master name is used for finding the metrics, the + * instance name is stored in the font struct. + */ + + len = strlen(fontname); + if (len > PDF_MAX_FONTNAME) + { + pdc_set_errmsg(p->pdc, FNT_E_FONT_NAMETOOLONG, + pdc_errprintf(p->pdc, "%d", PDF_MAX_FONTNAME), 0, 0, 0); + goto PDF_PREMATURE_EXIT; + } + strcpy(mastername, fontname); + + /* A Multiple Master font was requested */ + if ((mmparam = strstr(mastername, "MM_")) != NULL) + { + if (font->opt.embedding) + { + pdc_set_errmsg(p->pdc, PDF_E_FONT_EMBEDMM, 0, 0, 0, 0); + goto PDF_PREMATURE_EXIT; + } + mmparam[2] = '\0'; /* strip the parameter from the master name */ + } + + /* Font for vertical writing mode */ + fontname_p = mastername; + if (mastername[0] == '@') + { + font->ft.vertical = pdc_true; + fontname_p = &mastername[1]; + } + + /* protocol */ + pdc_logg_cond(p->pdc, 1, trc_font, + "\tPDFlib font name: \"%s\"\n", fontname_p); + + /* Font file search hierarchy + * - Check "FontOutline" resource entry and check TrueType font + * - Check "FontAFM" resource entry + * - Check "FontPFM" resource entry + * - Check "HostFont" resource entry + * - Check available in-core metrics + * - Check host font + */ + retval = pdc_false; + while (1) + { +#ifdef PDF_TRUETYPE_SUPPORTED + /* Check specified TrueType file */ + filename = pdc_find_resource(p->pdc, "FontOutline", fontname_p); + if (!filename) + { + /* check for TTC font names with index */ + ittc = PDF_TTC_SEPARATOR; + sf = strrchr(fontname_p, ittc); + + if (sf != NULL) + { + *sf = 0; + filename = pdc_find_resource(p->pdc, "FontOutline", fontname_p); + *sf = ittc; + } + } + if (filename) + { + outfilename = filename; + retval = fnt_check_tt_font(p->pdc, filename, fontname_p, &font->ft, + pdc_false); + if (retval == pdc_true) + { + retval = pdf_get_metrics_tt(p, font, fontname_p, enc, filename); + break; + } + else if (retval == pdc_undef && + pdc_get_errnum(p->pdc) == PDC_E_IO_RDOPEN_NF) + { + /* file must be exist */ + retval = pdc_false; + } + if (retval == pdc_false) + break; + } +#endif /* PDF_TRUETYPE_SUPPORTED */ + + /* Check specified AFM file */ + filename = pdc_find_resource(p->pdc, "FontAFM", fontname_p); + if (filename) + { + retval = pdf_get_metrics_afm(p, font, fontname_p, enc, filename, + pdc_true); + break; + } + + /* Check specified PFM file */ + filename = pdc_find_resource(p->pdc, "FontPFM", fontname_p); + if (filename) + { + retval = pdf_get_metrics_pfm(p, font, fontname_p, enc, filename, + pdc_true); + break; + } + + + + /* Check available in-core metrics */ + retval = pdf_get_metrics_core(p, font, fontname_p, enc, pdc_false); + if (retval != pdc_undef) + break; + retval = pdc_false; + + + /* Check available in-core metrics */ + retval = pdf_get_metrics_core(p, font, fontname_p, enc, pdc_true); + if (retval != pdc_undef) + break; + retval = pdc_false; + + /* Searching for a metric file */ + pdc_logg_cond(p->pdc, 1, trc_font, + "\tSearching for font metrics data file:\n"); + + filename = testfilename; + for (i = 0; i < 100; i++) + { + extension = pdf_extension_names[i].word; + if (!extension) + break; + + strcpy(testfilename, fontname_p); + sf = strrchr(testfilename, PDF_TTC_SEPARATOR); + if (sf != NULL) + *sf = 0; + strcat(testfilename, extension); + + switch (pdf_extension_names[i].code) + { +#ifdef PDF_TRUETYPE_SUPPORTED + case font_ttot: + retval = fnt_check_tt_font(p->pdc, filename, fontname_p, + &font->ft, pdc_false); + if (retval == pdc_true) + retval = pdf_get_metrics_tt(p, font, fontname_p, enc, + filename); + break; +#endif /* PDF_TRUETYPE_SUPPORTED */ + + case font_afm: + retval = pdf_get_metrics_afm(p, font, fontname_p, enc, + filename, pdc_false); + break; + + case font_pfm: + retval = pdf_get_metrics_pfm(p, font, fontname_p, enc, + filename, pdc_false); + break; + + default: + break; + } + + /* file found or error */ + if (retval != pdc_undef) + { + if (retval == pdc_true) + if (pdf_extension_names[i].code == font_ttot) + outfilename = filename; + break; + } + } + + if (retval == pdc_undef) + { + retval = pdc_false; + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tMetric data file for font \"%s\" not available\n", + fontname_p); + pdc_set_errmsg(p->pdc, PDF_E_FONT_NOMETRICS, 0, 0, 0, 0); + } + + break; + } + + /* metrics data search finished */ + + if (retval == pdc_false) + { + goto PDF_PREMATURE_EXIT; + } + + /* store instance name instead of master name in the font structure */ + if (mmparam) + { + pdc_free(p->pdc, font->ft.name); + font->ft.name = pdc_strdup(p->pdc, fontname); + pdc_free(p->pdc, font->ft.m.name); + font->ft.m.name = pdc_strdup(p->pdc, fontname); + } + + /* If embedding was requested, check font file (or raise an exception) */ + if (font->opt.embedding) + { + if (font->ft.img == NULL) + { + retval = pdc_undef; + + if (outfilename) + { + /* Font outline file specified */ + if (font->ft.m.type == fnt_Type1 || + font->ft.m.type == fnt_MMType1) + { + retval = pdf_t1open_fontfile(p, font, outfilename, NULL, + pdc_true); + } + else + { + retval = fnt_check_tt_font(p->pdc, outfilename, NULL, + &font->ft, pdc_true); + } + } + else + { + /* Searching font outline file */ + pdc_logg_cond(p->pdc, 1, trc_font, + "\tSearching for font outline data file:\n"); + + outfilename = testfilename; + for (i = 0; i < 100; i++) + { + extension = pdf_extension_names[i].word; + if (!extension) + break; + + strcpy(testfilename, fontname_p); + strcat(testfilename, extension); + + if (font->ft.m.type == fnt_Type1 || + font->ft.m.type == fnt_MMType1) + { + if (pdf_extension_names[i].code == font_pfab) + { + retval = pdf_t1open_fontfile(p, font, outfilename, + NULL, pdc_false); + } + } + else if (pdf_extension_names[i].code == font_ttot) + { + retval = fnt_check_tt_font(p->pdc, outfilename, + NULL, &font->ft, pdc_false); + } + + /* file found or error */ + if (retval != pdc_undef) + break; + } + + if (retval == pdc_undef) + { + retval = pdc_false; + pdc_set_errmsg(p->pdc, PDF_E_FONT_NOOUTLINE, 0, 0, 0, 0); + } + } + + if (retval == pdc_false) + { + pdc_logg_cond(p->pdc, 1, trc_font, + "\tOutline data file for font \"%s\" not found\n", + fontname_p); + } + else + { + if (!font->ft.img) + font->filename = font->ft.filename; + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tFont outline data file \"%s\" available\n", + font->filename ? + font->filename : font->ft.imgname); + } + } + } + else if (font->ft.img) + { + if (!font->ft.imgname) + pdc_free(p->pdc, font->ft.img); + else + { + pdc_unlock_pvf(p->pdc, font->ft.imgname); + pdc_free(p->pdc, font->ft.imgname); + font->ft.imgname = NULL; + } + font->ft.img = NULL; + font->ft.filelen = 0; + } + + if (retval && font->opt.monospace && font->opt.embedding) + { + pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace", 0, 0, 0); + retval = pdc_false; + } + + if (retval == pdc_false) + { + goto PDF_PREMATURE_EXIT; + } + + PDF_NEWFONT_EXIT: + + pdf_cleanup_font_options(p, fo); + + encoding = pdc_get_user_encoding(p->pdc, font->ft.enc); + if (pdc_strcmp(font->encapiname, encoding)) + pdc_logg_cond(p->pdc, 1, trc_encoding, + "\tDetermined font encoding: \"%s\"\n", encoding); + + /* set missing font metrics values */ + pdf_font_set_missvalues(p, font); + + /* font is semantic (Unicode compatible) */ + pdf_font_issemantic(p, font); + + /* set replacement character and code */ + pdf_set_replchar(p, font); + + /* font object ID */ + if (!font->opt.auxiliary) + font->obj_id = pdc_alloc_id(p->out); + + /* Now everything is fine, insert font */ + if (slot == -1) + slot = pdf_insert_font(p, font); + + + pdc_pop_errmsg(p->pdc); + + return slot; + + + PDF_PREMATURE_EXIT: + + pdf_cleanup_font_options(p, fo); + pdf_cleanup_font(p, font); + + if (slot == -1) + { + if (font->verbose) + pdc_error(p->pdc, -1, 0, 0, 0, 0); + } + + pdc_pop_errmsg(p->pdc); + + return slot; +} + + +/* --------------------------- font writing ---------------------------- */ + +static char * +pdf_code2fontglyphname(pdf_font *font, pdc_encodingvector *ev, int code) +{ + char *glyphname; + + glyphname = ev->chars[code]; + pdc_get_alter_glyphname(ev->codes[code], font->missingglyphs, + &glyphname); + + return glyphname ? glyphname : (char *) pdc_get_notdef_glyphname(); +} + +void +pdf_transform_fontwidths(PDF *p, pdf_font *font, pdc_encodingvector *evto, + pdc_encodingvector *evfrom) +{ + int widths[256]; + pdc_ushort code2gid[256]; + int i, j; + + for (i = 0; i < 256; i++) + { + widths[i] = font->ft.m.defwidth; + code2gid[i] = 0; + } + + for (i = 0; i < 256; i++) + { + j = (int) pdc_transform_bytecode(p->pdc, evto, evfrom, (pdc_byte)i); + widths[j] = font->ft.m.widths[i]; + if (font->ft.code2gid != NULL) + code2gid[j] = font->ft.code2gid[i]; + } + + widths[0] = font->ft.m.defwidth; + memcpy(font->ft.m.widths, widths, 256 * sizeof(int)); + if (font->ft.code2gid != NULL) + memcpy(font->ft.code2gid, code2gid, 256 * sizeof(pdc_ushort)); +} + + + +static void +pdf_write_fontdescriptor( + PDF *p, + pdf_font *font, + int missingwidth, + pdc_id fontdescriptor_id, + pdc_id cidset_id, + pdc_id fontfile_id, + int nusedgids) +{ + (void) cidset_id; + (void) nusedgids; + + /* + * Font descriptor object + */ + pdc_begin_obj(p->out, fontdescriptor_id); /* font descriptor obj */ + pdc_begin_dict(p->out); /* font descriptor dict */ + + pdc_puts(p->out, "/Type/FontDescriptor\n"); + pdc_printf(p->out, "/Flags %ld\n", font->ft.m.flags); + + + pdc_printf(p->out, "/Ascent %d\n", font->ft.m.ascender); + pdc_printf(p->out, "/CapHeight %d\n", font->ft.m.capHeight); + pdc_printf(p->out, "/Descent %d\n", font->ft.m.descender); + pdc_printf(p->out, "/FontBBox[%d %d %d %d]\n", + (int) font->ft.m.llx, (int) font->ft.m.lly, + (int) font->ft.m.urx, (int) font->ft.m.ury); + + pdc_printf(p->out, "/FontName"); + pdf_put_pdfname(p, font->ft.m.name); + pdc_puts(p->out, "\n"); + + pdc_printf(p->out, "/ItalicAngle %d\n", (int) (font->ft.m.italicAngle)); + pdc_printf(p->out, "/StemV %d\n", font->ft.m.StdVW); + + if (font->ft.m.StdHW > 0) + pdc_printf(p->out, "/StemH %d\n", font->ft.m.StdHW); + + if (font->ft.m.xHeight > 0) + pdc_printf(p->out, "/XHeight %d\n", font->ft.m.xHeight); + + if (missingwidth > 0) + pdc_printf(p->out, "/MissingWidth %d\n", missingwidth); + + if (fontfile_id != PDC_BAD_ID) + { + switch(font->ft.m.type) + { + case fnt_Type1: + case fnt_MMType1: + pdc_objref(p->out, "/FontFile", fontfile_id); + break; + +#ifdef PDF_TRUETYPE_SUPPORTED + case fnt_TrueType: + case fnt_CIDFontType2: + pdc_objref(p->out, "/FontFile2", fontfile_id); + break; + + case fnt_Type1C: + case fnt_CIDFontType0: + pdc_objref(p->out, "/FontFile3", fontfile_id); + break; +#endif /* PDF_TRUETYPE_SUPPORTED */ + + default: + break; + } + } + + + pdc_end_dict(p->out); /* font descriptor dict */ + pdc_end_obj(p->out); /* font descriptor obj */ +} + +static void +pdf_put_font(PDF *p, pdf_font *font) +{ + const char *fontname = font->ft.name; + fnt_fonttype fonttype = font->ft.m.type; + pdc_id fontdescriptor_id = PDC_BAD_ID; + pdc_id fontfile_id = PDC_BAD_ID; + pdc_id encoding_id = PDC_BAD_ID; + pdc_id cidset_id = PDC_BAD_ID; + pdc_id length_id = PDC_BAD_ID; + pdc_id descendant_id = PDC_BAD_ID; + pdc_encoding enc = font->ft.enc; + const char *encoding; + pdc_encoding_info *encinfo = NULL; + pdc_bool comp_font = pdc_false; + pdc_bool acro_fontstyle = pdc_false; + pdc_scalar a = 1.0; + PDF_data_source src; + int nusedgids = 0; + + /* save font struct members */ + pdc_encodingvector *ev = NULL; + pdc_encoding font_encoding = font->ft.enc; + int font_numcodes = font->ft.numcodes; + int font_codesize = font->codesize; + + int missingwidth = 0; + int i; + + encoding = pdc_get_user_encoding(p->pdc, enc); + if (!pdc_strcmp(font->encapiname, encoding)) + { + pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX, + font->apiname, font->encapiname, 0, 0); + } + else + { + pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX2, + font->apiname, font->encapiname, encoding, 0); + } + + + /* ID for embedded font */ + if (font->opt.embedding) + { + switch(fonttype) + { + case fnt_Type1: + case fnt_MMType1: + case fnt_TrueType: + case fnt_CIDFontType2: + case fnt_Type1C: + case fnt_CIDFontType0: + fontfile_id = pdc_alloc_id(p->out); + break; + + default: + break; + } + } + + /* + * Font dictionary + */ + pdc_begin_obj(p->out, font->obj_id); /* font obj */ + pdc_begin_dict(p->out); /* font dict */ + pdc_puts(p->out, "/Type/Font\n"); + + /* /Subtype */ + pdc_printf(p->out, "/Subtype/%s\n", + pdc_get_keyword(fonttype, pdf_fonttype_pdfkeylist)); + comp_font = fonttype == fnt_CIDFontType0 || fonttype == fnt_CIDFontType2; + + /* Acrobat font style */ + acro_fontstyle = font->opt.fontstyle != fnt_Normal && + !(font->metricflags & (font_bold | font_italic)); + + /* /Name */ + if (fonttype == fnt_Type3 || font->used_in_formfield) + { + /* + * The name is optional, but if we include it it will show up + * in Acrobat's font info box. However, if the same font name + * is used with different encodings Acrobat 4 will not be + * able to distinguish both. For this reason we add the + * encoding name to make the font name unique. + */ + + const char *name = fontname; + + if (font->used_in_formfield) + name = pdf_get_pdf_fontname(font); + + pdc_puts(p->out, "/Name"); + pdf_put_pdfname(p, name); + pdc_puts(p->out, "\n"); + } + + /* /BaseFont */ + switch (fonttype) + { + case fnt_Type1: + case fnt_MMType1: + case fnt_TrueType: + case fnt_Type1C: + case fnt_CIDFontType2: + case fnt_CIDFontType0: + { + pdc_puts(p->out, "/BaseFont"); + pdf_put_pdfname(p, fontname); + if (font->outcmapname) + pdc_printf(p->out, "-%s", font->outcmapname); + if (acro_fontstyle && !comp_font) + pdc_printf(p->out, ",%s", pdc_get_keyword(font->opt.fontstyle, + pdf_fontstyle_pdfkeylist)); + pdc_puts(p->out, "\n"); + } + break; + + /* /FontBBox, /FontMatrix, /CharProcs /Resources */ + case fnt_Type3: + if (font->t3font->charprocs_id == PDC_BAD_ID) + pdc_error(p->pdc, PDF_E_T3_OUTLINESMISSING, fontname, 0, 0, 0); + + pdc_printf(p->out, "/FontBBox[%f %f %f %f]\n", + font->ft.bbox.llx, font->ft.bbox.lly, + font->ft.bbox.urx, font->ft.bbox.ury); + + pdc_printf(p->out, "/FontMatrix[%f %f %f %f %f %f]\n", + font->ft.matrix.a, font->ft.matrix.b, + font->ft.matrix.c, font->ft.matrix.d, + font->ft.matrix.e, font->ft.matrix.f); + pdc_objref(p->out, "/CharProcs", font->t3font->charprocs_id); + pdc_objref(p->out, "/Resources", font->t3font->res_id); + + /* We must apply a correctional factor since Type 3 fonts not + * necessarily use 1000 units per em. We apply the correction + * here, and store the 1000-based width values in the font in + * order to speed up PDF_stringwidth(). + */ + a = 1000 * font->ft.matrix.a; + break; + + default: + break; + } + + /* changing 8-bit font encoding to builtin */ + if (enc >= 0 && font->symenc != pdc_invalidenc) + { + ev = NULL; + enc = pdc_builtin; + font->ft.enc = enc; + } + + /* changing 8-bit font encoding to winansi */ + if (font->towinansi != pdc_invalidenc) + { + pdc_encodingvector *evfrom; + + ev = pdc_get_encoding_vector(p->pdc, font->towinansi); + evfrom = pdc_get_encoding_vector(p->pdc, enc); + pdf_transform_fontwidths(p, font, ev, evfrom); + + enc = font->towinansi; + font->ft.enc = enc; + } + + /* /FontDescriptor, /FirstChar, /LastChar, /Widths */ + switch (fonttype) + { + case fnt_Type1: + /* disabled, because of PDF 1.7 reference + if (font->ft.isstdfont == pdc_true) break; + */ + case fnt_MMType1: + case fnt_TrueType: + case fnt_Type1C: + case fnt_Type3: + { + int firstchar = 0; + int lastchar = 255; + int defwidth = 0; + + if (fonttype != fnt_Type3 + ) + { + fontdescriptor_id = pdc_alloc_id(p->out); + pdc_objref(p->out, "/FontDescriptor", fontdescriptor_id); + } + + + /* determine missing width. + * Only for embedded fonts because of a bug in Acrobat, + * which arises if the font is not installed at host. + */ + if (font->opt.embedding) + { + if (fonttype != fnt_Type3) + defwidth = font->ft.m.widths[0]; + + { + for (i = 1; i < 255; i++) + { + if (font->ft.m.widths[i] != defwidth) + break; + } + if (i > 1) + firstchar = i; + for (i = 255; i > 0; i--) + { + if (i == firstchar || font->ft.m.widths[i] != defwidth) + break; + } + lastchar = i; + } + + if (firstchar > 0 || lastchar < 255) + missingwidth = (int) (defwidth / a + 0.5); + } + + pdc_printf(p->out, "/FirstChar %d\n", firstchar); + pdc_printf(p->out, "/LastChar %d\n", lastchar); + + pdc_puts(p->out, "/Widths"); + pdc_begin_array(p->out); + for (i = firstchar; i <= lastchar; i++) + { + pdc_printf(p->out, "%d", + (int) (font->ft.m.widths[i] / a + .5)); + if (i < 255) + pdc_printf(p->out, "%s", ((i + 1) % 16) ? " " : "\n"); + } + pdc_end_array(p->out); + } + break; + + default: + break; + } + + /* /Encoding */ + switch (fonttype) + { + case fnt_Type1: + case fnt_MMType1: + case fnt_TrueType: + case fnt_Type1C: + if (!font->used_in_formfield) + { + if (enc == pdc_winansi) + { + pdc_printf(p->out, "/Encoding/WinAnsiEncoding\n"); + break; + } + if (enc == pdc_macroman && font->hasnomac == pdc_false) + { + pdc_printf(p->out, "/Encoding/MacRomanEncoding\n"); + break; + } + } + case fnt_Type3: + if (enc >= 0) + { + encinfo = pdc_get_encoding_info(p->pdc, enc); + if (encinfo->id == PDC_BAD_ID) + encinfo->id = pdc_alloc_id(p->out); + encoding_id = encinfo->id; + } + + if (encoding_id != PDC_BAD_ID) + pdc_objref(p->out, "/Encoding", encoding_id); + + if (encinfo != NULL) + { + if (!encinfo->stored) + encinfo->stored = pdc_true; + else + encoding_id = PDC_BAD_ID; + } + + break; + + case fnt_CIDFontType2: + case fnt_CIDFontType0: + if (font->outcmapname) + { + pdc_printf(p->out, "/Encoding/%s\n", font->outcmapname); + } + break; + + default: + break; + } + + /* /ToUnicode . Only reasonable if nusedgids != 1 + * (== 1: only notdef character in a font subset) + */ + + + /* /DescendantFonts */ + if (comp_font == pdc_true) + { + descendant_id = pdc_alloc_id(p->out); + pdc_puts(p->out, "/DescendantFonts"); + pdc_begin_array(p->out); + pdc_objref(p->out, "", descendant_id); + pdc_end_array(p->out); + } + + pdc_end_dict(p->out); /* font dict */ + pdc_end_obj(p->out); /* font obj */ + + /* + * Encoding dictionary + */ + if (encoding_id != PDC_BAD_ID) + { + char *glyphname; + + pdc_begin_obj(p->out, encoding_id); /* encoding obj */ + pdc_begin_dict(p->out); /* encoding dict */ + + pdc_puts(p->out, "/Type/Encoding\n"); + + { + pdc_encodingvector *evb = NULL; + + pdc_set_encoding_glyphnames(p->pdc, enc); + ev = pdc_get_encoding_vector(p->pdc, enc); + + /* See Implementation Note 46. The restrictions described there + * are also valid for Acrobat versions up to now. + */ + if (fonttype != fnt_Type3 && !font->used_in_formfield) + { + if (!strncmp(ev->apiname, PDC_ENC_MODWINANSI, + strlen(PDC_ENC_MODWINANSI)) || + !strncmp(ev->apiname, PDC_ENC_ISO8859, + strlen(PDC_ENC_ISO8859)) || + !strncmp(ev->apiname, PDC_ENC_CP125, + strlen(PDC_ENC_CP125))) + { + pdc_puts(p->out, "/BaseEncoding/WinAnsiEncoding\n"); + evb = pdc_get_encoding_vector(p->pdc, pdc_winansi); + } + else if (!strncmp(ev->apiname, PDC_ENC_MODMACROMAN, + strlen(PDC_ENC_MODMACROMAN))) + { + pdc_puts(p->out, "/BaseEncoding/MacRomanEncoding\n"); + evb = pdc_get_encoding_vector(p->pdc, pdc_macroman); + } + else + { + /* /BaseEncoding/StandardEncoding */ + evb = pdc_get_encoding_vector(p->pdc, pdc_stdenc); + } + } + + if (evb != NULL) + { + int iv = -1; + for (i = 0; i < font->ft.numcodes; i++) + { + glyphname = pdf_code2fontglyphname(font, ev, i); + + /* enforce first three names because of bug in Acrobat 6 */ + if (i < 3 || + (glyphname && !evb->chars[i]) || + (!glyphname && evb->chars[i]) || + (glyphname && evb->chars[i] && + strcmp(glyphname, evb->chars[i]))) + { + if (iv == -1) + pdc_puts(p->out, "/Differences[0"); + if (i > iv + 1) + pdc_printf(p->out, "%d", i); + pdf_put_pdfname(p, glyphname); + pdc_puts(p->out, "\n"); + iv = i; + } + } + if (iv > -1) + pdc_end_array(p->out); + } + else + { + pdc_puts(p->out, "/Differences[0"); + for (i = 0; i < font->ft.numcodes; i++) + { + glyphname = pdf_code2fontglyphname(font, ev, i); + pdf_put_pdfname(p, glyphname); + pdc_puts(p->out, "\n"); + } + pdc_end_array(p->out); + } + } + + pdc_end_dict(p->out); /* encoding dict */ + pdc_end_obj(p->out); /* encoding obj */ + + if (p->flush & pdc_flush_content) + pdc_flush_stream(p->out); + } + + + /* + * CID fonts dictionary + */ + if (descendant_id != PDC_BAD_ID) + { + pdc_begin_obj(p->out, descendant_id); /* CID font obj */ + pdc_begin_dict(p->out); /* CID font dict */ + pdc_puts(p->out, "/Type/Font\n"); + + /* /Subtype */ + if (fonttype == fnt_CIDFontType0) + pdc_puts(p->out, "/Subtype/CIDFontType0\n"); + if (fonttype == fnt_CIDFontType2) + pdc_puts(p->out, "/Subtype/CIDFontType2\n"); + + /* /BaseFont */ + pdc_puts(p->out, "/BaseFont"); + pdf_put_pdfname(p, fontname); + if (acro_fontstyle) + pdc_printf(p->out, ",%s", + pdc_get_keyword(font->opt.fontstyle, pdf_fontstyle_pdfkeylist)); + pdc_puts(p->out, "\n"); + + /* /CIDSystemInfo */ + pdc_puts(p->out, "/CIDSystemInfo<</Registry"); + pdf_put_hypertext(p, "Adobe"); + pdc_puts(p->out, "/Ordering"); + pdf_put_hypertext(p, fnt_get_ordering_cid(font->ft.m.charcoll)); + pdc_printf(p->out, "/Supplement %d>>\n", MAX(font->supplement, 0)); + + /* /FontDescriptor */ + fontdescriptor_id = pdc_alloc_id(p->out); + pdc_objref(p->out, "/FontDescriptor", fontdescriptor_id); + + + + /* /DW /W */ +#ifdef PDF_CJKFONTWIDTHS_SUPPORTED + if (font->ft.isstdfont) + pdf_put_cidglyph_widths(p, font); +#endif /* PDF_CJKFONTWIDTHS_SUPPORTED */ + + + pdc_end_dict(p->out); /* CID font dict */ + pdc_end_obj(p->out); /* CID font obj */ + + } + + + /* + * FontDescriptor dictionary + */ + if (fontdescriptor_id != PDC_BAD_ID) + pdf_write_fontdescriptor(p, font, missingwidth, fontdescriptor_id, + cidset_id, fontfile_id, nusedgids); + + + + /* + * Font embedding + */ + if (fontfile_id != PDC_BAD_ID) + { + pdc_id length1_id = PDC_BAD_ID; + pdc_id length2_id = PDC_BAD_ID; + pdc_id length3_id = PDC_BAD_ID; + pdc_bool compress = pdc_false; + + /* Prepare embedding */ + switch(fonttype) + { + case fnt_Type1: + case fnt_MMType1: + { + pdf_make_t1src(p, font, &src); + length1_id = pdc_alloc_id(p->out); + length2_id = pdc_alloc_id(p->out); + length3_id = pdc_alloc_id(p->out); + } + break; + +#ifdef PDF_TRUETYPE_SUPPORTED + case fnt_TrueType: + case fnt_CIDFontType2: + { + length1_id = pdc_alloc_id(p->out); + } + case fnt_Type1C: + case fnt_CIDFontType0: + case fnt_OpenType: + { + src.private_data = (void *) font->filename; + if (font->filename) + { + /* Read the font from file */ + src.init = pdf_data_source_file_init; + src.fill = pdf_data_source_file_fill; + src.terminate = pdf_data_source_file_terminate; + switch(fonttype) + { + case fnt_TrueType: + case fnt_CIDFontType2: + case fnt_OpenType: + src.offset = (long) 0; + src.length = (long) 0; + break; + + case fnt_Type1C: + case fnt_CIDFontType0: + src.offset = font->cff_offset; + src.length = (long) font->cff_length; + break; + + default: + break; + } + } + else + { + /* Read the font from memory */ + src.init = NULL; + src.fill = pdf_data_source_buf_fill; + src.terminate = NULL; + switch(fonttype) + { + case fnt_TrueType: + case fnt_CIDFontType2: + case fnt_OpenType: + src.buffer_start = font->ft.img; + src.buffer_length = font->ft.filelen; + break; + + case fnt_Type1C: + case fnt_CIDFontType0: + src.buffer_start = font->ft.img + font->cff_offset; + src.buffer_length = font->cff_length; + break; + + default: + break; + } + src.bytes_available = 0; + src.next_byte = NULL; + } + } + break; +#endif /* PDF_TRUETYPE_SUPPORTED */ + + default: + break; + } + + /* Embedded font stream dictionary */ + pdc_begin_obj(p->out, fontfile_id); /* Embedded font stream obj */ + pdc_begin_dict(p->out); /* Embedded font stream dict */ + + /* /Length, /Filter */ + length_id = pdc_alloc_id(p->out); + pdc_objref(p->out, "/Length", length_id); + switch(fonttype) + { + case fnt_Type1: + case fnt_MMType1: + break; + +#ifdef PDF_TRUETYPE_SUPPORTED + case fnt_TrueType: + case fnt_CIDFontType2: + case fnt_Type1C: + case fnt_CIDFontType0: + case fnt_OpenType: + if (font->ft.filelen != 0L) + { + compress = pdc_true; + if (pdc_get_compresslevel(p->out)) + pdc_puts(p->out, "/Filter/FlateDecode\n"); + } + break; +#endif /* PDF_TRUETYPE_SUPPORTED */ + + default: + break; + } + + /* /Length1, /Length2, Length3 */ + if (length1_id != PDC_BAD_ID) + pdc_objref(p->out, "/Length1", length1_id); + if (length2_id != PDC_BAD_ID) + pdc_objref(p->out, "/Length2", length2_id); + if (length3_id != PDC_BAD_ID) + pdc_objref(p->out, "/Length3", length3_id); + +#ifdef PDF_TRUETYPE_SUPPORTED + /* /Subtype */ + if(fonttype == fnt_Type1C) + pdc_puts(p->out, "/Subtype/Type1C\n"); + if (fonttype == fnt_CIDFontType0) + pdc_puts(p->out, "/Subtype/CIDFontType0C\n"); + if (fonttype == fnt_OpenType) + pdc_puts(p->out, "/Subtype/OpenType\n"); +#endif /* PDF_TRUETYPE_SUPPORTED */ + + + pdc_end_dict(p->out); /* Embedded font stream dict */ + + /* Stream */ + pdf_copy_stream(p, &src, compress); + + pdc_end_obj(p->out); /* Embedded font stream obj */ + + pdc_put_pdfstreamlength(p->out, length_id); + + /* Length objects */ + switch(fonttype) + { + case fnt_Type1: + case fnt_MMType1: + pdf_put_length_objs(p, &src, length1_id, length2_id, length3_id); + break; + +#ifdef PDF_TRUETYPE_SUPPORTED + case fnt_TrueType: + case fnt_CIDFontType2: + if (compress) + { + pdc_begin_obj(p->out, length1_id); /* Length1 obj */ + pdc_printf(p->out, "%ld\n", (long) font->ft.filelen); + pdc_end_obj(p->out); /* Length1 obj */ + } + else + { + /* same as /Length */ + pdc_put_pdfstreamlength(p->out, length1_id); + } + break; +#endif /* PDF_TRUETYPE_SUPPORTED */ + + default: + break; + } + } + + if (p->flush & pdc_flush_content) + pdc_flush_stream(p->out); + + /* restore font struct members */ + font->ft.enc = font_encoding; + font->ft.numcodes = font_numcodes; + font->codesize = font_codesize; + + pdc_pop_errmsg(p->pdc); +} + +void +pdf_write_doc_fonts(PDF *p) +{ + int slot; + pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_font); + + /* output pending font objects */ + for (slot = 0; slot < p->fonts_number; slot++) + { + pdf_font *font = &p->fonts[slot]; + + switch(p->fonts[slot].ft.m.type) + { + case fnt_Type1: + case fnt_MMType1: +#ifdef PDF_TRUETYPE_SUPPORTED + case fnt_TrueType: + case fnt_CIDFontType2: + case fnt_Type1C: +#endif /* PDF_TRUETYPE_SUPPORTED */ + case fnt_CIDFontType0: + case fnt_Type3: + if (font->obj_id != PDC_BAD_ID) + { + if (logg1) + { + pdc_logg(p->pdc, + "\tProcessing font %d: \"%s\" " + "with encoding \"%s\" and PDF object id %ld", + slot, font->ft.name, + pdf_get_encoding_name(p, font->ft.enc, font), + font->obj_id); + } + + if (font->ft.enc == pdc_invalidenc || + font->used_in_current_doc == pdc_false) + { + if (logg1) + pdc_logg(p->pdc, " - but not used\n", font->obj_id); + + /* + * This font has been defined, but never used in the + * document. Ignore it. However, the font's object id + * has already been allocated, so we mark the object + * as free in order to avoid a complaint of the object + * machinery. + */ + pdc_mark_free(p->out, font->obj_id); + } + else + { + if (logg1) + pdc_logg(p->pdc, "\n"); + + pdf_put_font(p, font); + } + } + break; + + default: + break; + } + } +} + +void +pdf_write_page_fonts(PDF *p) +{ + int i, total = 0; + int bias = p->curr_ppt->fn_bias; + + /* This doesn't really belong here, but all modules which write + * font resources also need this, so we include it here. + * Note that keeping track of ProcSets is considered obsolete + * starting with PDF 1.4, so we always include the full set which + * is written as a constant object at the beginning of the file. + */ + + pdc_objref(p->out, "/ProcSet", p->procset_id); + + for (i = 0; i < p->fonts_number; i++) + if (p->fonts[i].used_on_current_page == pdc_true) + total++; + + if (total > 0 || bias) + { + pdc_puts(p->out, "/Font"); + pdc_begin_dict(p->out); /* font resource dict */ + } + + if (total > 0) + { + for (i = 0; i < p->fonts_number; i++) + { + if (p->fonts[i].used_on_current_page == pdc_true) { + p->fonts[i].used_on_current_page = pdc_false; /* reset */ + pdc_printf(p->out, "/F%d", bias + i); + pdc_objref(p->out, "", p->fonts[i].obj_id); + } + } + + if (!bias) + pdc_end_dict(p->out); /* font resource dict */ + } +} + +void +pdf_get_page_fonts(PDF *p, pdf_reslist *rl) +{ + int i; + + for (i = 0; i < p->fonts_number; i++) + { + if (p->fonts[i].used_on_current_page) + { + p->fonts[i].used_on_current_page = pdc_false; /* reset */ + pdf_add_reslist(p, rl, i); + } + } +} + +void +pdf_mark_page_font(PDF *p, int ft) +{ + p->fonts[ft].used_on_current_page = pdc_true; +} + + + diff --git a/src/pdflib/pdflib/p_font.h b/src/pdflib/pdflib/p_font.h new file mode 100644 index 0000000..3dc4d91 --- /dev/null +++ b/src/pdflib/pdflib/p_font.h @@ -0,0 +1,225 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_font.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * Header file for the PDFlib font subsystem + * + */ + +#ifndef P_FONT_H +#define P_FONT_H + +#define PDF_DEFAULT_CHAR PDC_UNICODE_SPACE + +/* internal maximal length of fontnames */ +#define PDF_MAX_FONTNAME 128 + +/* last text rendering mode number */ +#define PDF_LAST_TRMODE 7 + +/* minimal number of glyphs for appropriate encoding */ +#define PDF_MIN_GLYPHS 5 + +typedef enum +{ + font_ascender = (1<<0), + font_descender = (1<<1), + font_capheight = (1<<2), + font_xheight = (1<<3), + font_linegap = (1<<4), + + font_italic = (1<<8), + font_bold = (1<<9) +} +pdf_font_values; + +typedef struct pdf_t3glyph_s pdf_t3glyph; + +/* font options */ +struct pdf_font_options_s +{ + pdc_bool embedding; + char *encoding; + int flags; + char *fontname; + fnt_fontstyle fontstyle; + pdc_bool fontwarning; + int mask; + int monospace; + int ascender; + int descender; + int capheight; + int xheight; + int linegap; + pdc_bool auxiliary; +}; + +/* Type3 font structures */ +struct pdf_t3glyph_s +{ + char *name; + pdc_id charproc_id; + pdc_scalar wx; + pdc_scalar llx; + pdc_scalar lly; + pdc_scalar urx; + pdc_scalar ury; + pdc_scalar width; + int pass; /* 0, 1, 2 */ +}; + +struct pdf_t3font_s +{ + pdf_t3glyph *glyphs; /* dynamically growing glyph table */ + int capacity; /* current number of slots */ + int next_glyph; /* next available slot */ + int curr_glyph; /* slot of current glyph */ + + pdc_id charprocs_id; /* id of /CharProcs dict */ + pdc_id res_id; /* id of /Resources dict */ + pdc_bool colorized; /* glyphs colorized */ + int pass; /* 0, 1, 2 */ + +}; + +/* pdflib font structure */ +struct pdf_font_s +{ + /* pdcore font structure */ + fnt_font ft; + + /* font options */ + pdf_font_options opt; /* pdflib font options */ + pdc_bool verbose; /* put out warning/error messages */ + + /* special font names */ + char *apiname; /* font name specified in API call */ + const char *filename; /* name of font file, copy of ft.filename */ + char *metricfilename; /* name of metric font file */ + + /* font control */ + pdc_bool used_in_formfield; /* this font is in use in form field */ + pdc_bool used_in_current_doc; /* this font is in use in current doc. */ + pdc_bool used_on_current_page; /* this font is in use on current page */ + pdc_id obj_id; /* object id of this font */ + + /* CFF table */ + long cff_offset; /* start of CFF table in font */ + size_t cff_length; /* length of CFF table in font */ + + /* Type3 font */ + pdf_t3font *t3font; /* Type3 font data */ + pdc_bool hasoriginal; /* has the original Type3 font data */ + + /* pdflib encoding and CMap properties */ + char *encapiname; /* encoding name specified in API call */ + char *outcmapname; /* output CMap namel */ + int codepage; /* OEM multi byte code-page number */ + pdc_encoding towinansi; /* convert to 'towinansi' enc. for output */ + pdc_bool hasnomac; /* TT font has no macroman cmap */ + pdc_bool passthrough; /* text will be passed through as is */ + pdc_bool unibyte; /* take Unicode encoding as byte encoding */ + pdc_bool asciispace; /* encoding has space at x20 */ + pdc_bool issemantic; /* encoding is Unicode interpretable */ + pdc_bool widthsmissing; /* GID widths not available */ + pdc_ulong missingglyphs; /* bit mask for missing new AGL glyphs */ + int metricflags; /* flags for faked font values */ + int supplement; /* supplement number of CMap + * = -1: Identity-H/V */ + pdc_encoding symenc; /* font encoding for symbol fonts */ + int replacementchar; /* replacement character */ + int replacementcode; /* replacement code or glyph id resp. */ + + /* encoding and glyph control */ + int codesize; /* code size */ + /* = 0: unknown, no Unicode CMap */ + /* = 1: 1 byte encoding */ + /* = 2: 2 byte encoding */ + int lastcode; /* AFM: last byte code for generating runtime */ + /* byte encoding. = -1: ignore */ + int gid0code; /* code für gid 0 (because of Type3 fonts) */ + pdc_byte *usedgids; /* used Glyph IDs for font subsetting */ + pdc_bool expectglyphs; /* TT: glyph id text strings are expected */ + pdc_bool iscidfont; /* is CID font */ + +}; + +/* p_truetype.c */ +pdc_bool pdf_get_metrics_tt(PDF *p, pdf_font *font, + const char *fontname, pdc_encoding enc, + const char *filename); +int pdf_check_tt_hostfont(PDF *p, const char *hostname); + +/* p_afm.c */ +pdc_bool pdf_process_metrics_data(PDF *p, pdf_font *font, + const char *fontname); +pdc_bool pdf_get_metrics_afm(PDF *p, pdf_font *font, + const char *fontname, pdc_encoding enc, + const char *filename, pdc_bool requested); + +/* p_pfm.c */ +pdc_bool pdf_check_pfm_encoding(PDF *p, pdf_font *font, + pdc_encoding enc); +pdc_bool pdf_get_metrics_pfm(PDF *p, pdf_font *font, + const char *fontname, pdc_encoding enc, + const char *filename, pdc_bool requested); + +/* p_cid.c */ +pdc_bool pdf_handle_cidfont(PDF *p, const char *fontname, + const char *encoding, pdc_encoding enc, pdf_font *font, int *o_slot, + pdc_encoding *newenc); +void pdf_put_cidglyph_widths(PDF *p, pdf_font *font); + +/* p_font.c */ +void pdf_get_page_fonts(PDF *p, pdf_reslist *rl); +void pdf_parse_font_options(PDF *p, const char *optlist); +double pdf_get_font_float_option(PDF *p, pdf_font_optflags fflags); +pdc_bool pdf_check_font_embedding(PDF *p, pdf_font *font, const char *fontname); +pdc_bool pdf_make_fontflag(PDF *p, pdf_font *font); +int pdf_get_code_or_glyphid(PDF *p, pdf_font *font, pdc_encodingvector *ev, + pdc_ushort uv); +void pdf_set_replchar(PDF *p, pdf_font *font); +void pdf_font_issemantic(PDF *p, pdf_font *font); +void pdf_font_set_missvalues(PDF *p, pdf_font *font); +pdc_bool pdf_font_get_is_faked(pdf_font *font, pdf_font_values flag); +double pdf_font_get_metric_value(int value); +const char *pdf_get_encoding_name(PDF *p, pdc_encoding enc, pdf_font *font); +const char *pdf_get_font_char_option(PDF *p, pdf_font_optflags fflags); +const char *pdf_get_pdf_fontname(pdf_font *font); +char *pdf_get_encoding_adaptname(PDF *p, pdc_encoding enc, pdf_font *font, + const char *fontname); +pdc_encodingvector *pdf_create_font_encoding(PDF *p, pdc_encoding enc, + pdf_font *font, const char *fontname, pdc_bool kreg); +void pdf_transform_fontwidths(PDF *p, pdf_font *font, + pdc_encodingvector *evto, pdc_encodingvector *evfrom); + +/* p_type1.c */ +pdc_bool pdf_t1open_fontfile(PDF *p, pdf_font *font, const char *fontname, + PDF_data_source *t1src, pdc_bool requested); +pdc_bool pdf_make_t1src(PDF *p, pdf_font *font, PDF_data_source *t1src); +void pdf_put_length_objs(PDF *p, PDF_data_source *t1src, + pdc_id length1_id, pdc_id length2_id, pdc_id length3_id); + +/* p_type3.c */ +void pdf_cleanup_t3font(PDF *p, pdf_t3font *t3font); +void pdf_init_type3(PDF *p); +pdc_bool pdf_handle_t3font(PDF *p, const char *fontname, pdc_encoding enc, + pdf_font *font, int *slot); +pdc_bool pdf_isvalid_font(PDF *p, int slot); + +/* p_subsett.c */ +int pdf_prepare_ttfont(PDF *p, pdf_font *font); + + +#endif /* P_FONT_H */ + diff --git a/src/pdflib/pdflib/p_generr.h b/src/pdflib/pdflib/p_generr.h new file mode 100644 index 0000000..166e0f7 --- /dev/null +++ b/src/pdflib/pdflib/p_generr.h @@ -0,0 +1,705 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_generr.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib error messages + * + */ + +#define P_GENERR_H + +#if pdf_genNames +#define gen(n, num, nam, msg) PDF_E_##nam = num, +#elif pdf_genInfo +#define gen(n, num, nam, msg) { n, num, msg, (const char *) 0 }, + +#else +#error invalid inclusion of generator file +#endif + + +/* -------------------------------------------------------------------- */ +/* Configuration (20xx) */ +/* -------------------------------------------------------------------- */ + +gen(0, 2000, UNSUPP_CRYPT, "Encryption not supported in PDFlib Lite") + +gen(0, 2002, UNSUPP_KERNING, "Kerning not supported in PDFlib Lite") + +gen(0, 2003, UNSUPP_FONTINFO, "Font info not supported in PDFlib Lite") + +gen(0, 2004, UNSUPP_SUBSET, "Subsetting not supported in PDFlib Lite") + +gen(0, 2006, UNSUPP_PDFX, "PDF/X not supported in PDFlib Lite") + +gen(1, 2008, UNSUPP_IMAGE, "$1 images not supported in this configuration") + +gen(0, 2010, UNSUPP_ICC, "ICC profiles not supported in PDFlib Lite") + +gen(0, 2012, UNSUPP_UNICODE, + "Unicode and glyph id addressing not supported in PDFlib Lite") + +gen(0, 2014, UNSUPP_SPOTCOLOR, "Spot colors not supported in PDFlib Lite") + +gen(0, 2016, UNSUPP_PDI, "PDF import (PDI) not supported in PDFlib Lite") + +gen(0, 2017, UNSUPP_PDI_CONFIG, + "PDF import (PDI) not supported in this configuration") + +gen(0, 2018, UNSUPP_BLOCK, + "Personalization with blocks not supported in PDFlib Lite") + +gen(0, 2019, UNSUPP_BLOCK_CONFIG, + "Personalization with blocks not supported in this configuration") + +gen(0, 2020, UNSUPP_FORMFIELDS, "Form fields not supported in PDFlib Lite") + +gen(0, 2021, UNSUPP_JAVASCRIPT, "JavaScript not supported in PDFlib Lite") + +gen(0, 2022, UNSUPP_MC, "Marked content not supported in PDFlib Lite") + +gen(0, 2024, UNSUPP_TAGGED, "Tagged PDF not supported in PDFlib Lite") + +gen(0, 2026, UNSUPP_LAYER, + "Optional content (layers) not supported in PDFlib Lite") + +gen(0, 2028, UNSUPP_TEXTFLOWS, "Textflow not supported in PDFlib Lite") + +gen(0, 2029, UNSUPP_GLYPHCHECK, + "Glyph check not supported in PDFlib Lite") + +gen(0, 2030, UNSUPP_CHARREF, + "Character references not supported in PDFlib Lite") + +gen(0, 2031, UNSUPP_ESCAPESEQU, + "Escape sequences not supported in PDFlib Lite") + +gen(0, 2032, UNSUPP_JPEG2000, + "JPEG2000 images not supported in PDFlib Lite") + +gen(0, 2033, UNSUPP_TABLES, "Tables not supported in PDFlib Lite") + +gen(0, 2034, UNSUPP_3DANNOT, "3D annotations not supported in PDFlib Lite") + +gen(0, 2035, UNSUPP_HONORLANG, + "LANG environment variable not supported in PDFlib Lite") + +gen(0, 2098, BETA_EXPIRED, + "PDFlib 6 beta expired -- get latest version at www.pdflib.com") + + +/* -------------------------------------------------------------------- */ +/* Document, page, scoping and resource (21xx) */ +/* -------------------------------------------------------------------- */ + +gen(1, 2100, DOC_SCOPE, "Function must not be called in '$1' scope") + +gen(1, 2102, DOC_FUNCUNSUPP, "Function not supported for '$1'") + +gen(2, 2104, DOC_PDFVERSION, "$1 not supported in PDF $2") + +gen(0, 2106, DOC_EMPTY, "Generated document doesn't contain any pages") + +gen(0, 2110, PAGE_SIZE_ACRO, "Page size incompatible with Acrobat") + +gen(2, 2112, PAGE_BADBOX, "Illegal $1 [$2]") + +gen(0, 2114, PAGE_ILLCHGSIZE, + "Page size cannot be changed in top-down coordinate system") + +gen(2, 2120, RES_BADRES, "Bad resource specification '$1' for category '$2'") + +gen(2, 2122, DOC_SCOPE_GET, "Can't get parameter '$1' in '$2' scope") + +gen(2, 2124, DOC_SCOPE_SET, "Can't set parameter '$1' in '$2' scope") + +gen(1, 2126, PAGE_NOSUSPEND, "Page number $1 has not been suspended") + +gen(2, 2128, PAGE_NOSUSPEND2, + "Page number $1 in group '$2' has not been suspended") + +gen(1, 2130, PAGE_ILLNUMBER, "Illegal page number $1") + +gen(1, 2132, PAGE_NOTEXIST, "Page number $1 does not exist") + +gen(2, 2134, PAGE_NOTEXIST2, "Page number $1 in group '$2' does not exist") + +gen(0, 2136, PAGE_NEEDGROUP, "No page group specified") + +gen(0, 2138, PAGE_NEEDGROUP2, + "No page group specified (use PDF_begin_page_ext)") + +gen(1, 2140, DOC_UNKNOWNGROUP, "Unknown page group '$1'") + +gen(1, 2142, DOC_GROUPMISSING, + "Page group '$1' is missing in list of option 'grouporder'") + +gen(0, 2144, DOC_OPTGROUPORDER, + "Option 'grouporder' is illegal (no page groups are specified)") + +gen(1, 2146, DOC_DUPLGROUP, + "Duplicate definition of group '$1' in option 'grouporder'") + +gen(1, 2148, DOC_ILL_LABELOPT, + "Label option '$1' is illegal for this function") + +gen(1, 2150, DOC_NEED_LABELOPT, + "Option 'labels' requires suboption '$1' if used with this function") + +gen(1, 2152, PAGE_TRANS_COMPAT, + "Page transition '$1' requires PDF version 1.5 or higher") + +gen(1, 2154, PAGE_ILLROTATE, "Option 'rotate' has illegal value $1") + +gen(0, 2156, PAGE_SUSPEND_TAGGED, + "This function must not be used in Tagged PDF mode") + +gen(0, 2158, PAGE_SEP_NOSPOT, + "Option 'separationinfo' requires 'spotname' or 'spotcolor'") + +gen(0, 2160, PAGE_SEP_ILLPAGES, + "Option 'separationinfo' must not use 'pages' if not first page in group") + +gen(0, 2162, PAGE_SEP_NOPAGES, "Option 'separationinfo' requires 'pages'") + +gen(0, 2164, PAGE_SEP_NOINFO, "Option 'separationinfo' missing") + +gen(0, 2166, DOC_SEP_INCOMPLETE, "Incomplete separation group") + +gen(0, 2168, PAGE_TOPDOWN_NODIMS, + "Must specify page dimensions with option 'topdown'") + +gen(0, 2170, PAGE_NODIMS, "No dimensions specified for this page") + +gen(0, 2172, DOC_GETBUF_2GB, + "Can't process buffers larger than 2GB on this platform") + +gen(1, 2174, PAGE_SUSPENDED, "Page number $1 is still suspended") + +gen(0, 2176, DOC_GETBUF_LIN, + "Don't fetch buffer contents before PDF_end_document() when linearizing") + +gen(1, 2178, PAGE_ILLREF, + "A link annotation refers to non-existing page '$1'") + + +/* -------------------------------------------------------------------- */ +/* Graphics and Text (22xx) */ +/* -------------------------------------------------------------------- */ + +gen(0, 2200, GSTATE_UNMATCHEDSAVE, "Unmatched save level") + +gen(0, 2202, GSTATE_RESTORE, "Invalid restore (no matching save level)") + +gen(1, 2204, GSTATE_SAVELEVEL, "Too many save levels (max. $1)") + +gen(0, 2210, PATTERN_SELF, "Can't use a pattern within its own definition") + +gen(0, 2212, SHADING13, "Smooth shadings are not supported in PDF 1.3") + +gen(1, 2220, TEMPLATE_SELF, + "Can't place template handle $1 within its own definition") + +/* UNUSED +gen(1, 2230, TEXT_UNICODENOTSHOW, + "Can't show character with Unicode value U+$1") + +gen(1, 2232, TEXT_GLYPHIDNOTSHOW, "Can't show character with glyph id $1") + +gen(1, 2233, TEXT_BUILTINNOTSHOW, + "Can't show 16-bit character $1 for builtin encoding") +*/ + +gen(1, 2234, TEXT_TOOLONG, "Text too long (max. $1)") + +gen(2, 2235, TEXT_SIZENOMATCH, + "Size ($1) of glyphwidths list doesn't match size ($2 characters) of text") + +gen(0, 2236, TEXT_TOOMANYCODES, "Too many different unicode values (> 256)") + +gen(0, 2237, TEXT_NOFONTSIZESET, "Font size not specified for text") + +gen(0, 2238, TEXT_NOFONT, "No font set for text") + +gen(0, 2239, TEXT_ITALUNSUPP, + "Parameter 'italicangle' not supported for vertical writing mode") + +gen(1, 2240, TEXT_NOFONT_PAR, "No font set for parameter '$1'") + + + + + + +/* -------------------------------------------------------------------- */ +/* Color (23xx) */ +/* -------------------------------------------------------------------- */ + +gen(0, 2300, COLOR_SPOT, +"Spot color can not be based on a Pattern, Indexed, or Separation color space") + +gen(2, 2302, COLOR_BADSPOT, "Color name '$1' not found in $2 table") + +gen(1, 2304, COLOR_SPOTBW, + "Alternate color for custom spot color '$1' is black or white") + +gen(1, 2306, COLOR_UNLIC_SPOTCOLOR, "$1 spot colors not licensed") + +gen(0, 2308, COLOR_UNSUPP_SPOTNAME, "Unicode spot color names not supported") + +gen(2, 2309, COLOR_REDEFINE_SPOTNAME, + "Option '$1': spot color '$2' has already an alternative color") + + + +/* -------------------------------------------------------------------- */ +/* Image (24xx) */ +/* -------------------------------------------------------------------- */ + +gen(2, 2400, IMAGE_CORRUPT, "Corrupt $1 image file '$2'") + +gen(3, 2402, IMAGE_NOPAGE, "Requested page $1 in $2 image '$3' not found") + +gen(2, 2404, IMAGE_BADDEPTH, + "Bad number of bits per pixel ($1) in image file '$2'") + +gen(1, 2406, IMAGE_BADMASK, + "Image '$1' not suitable as mask (more than one color component)") + +gen(2, 2407, IMAGE_NOMATCH, + "Image '$1' not suitable as mask for image '$2' (different orientation)") + +gen(1, 2408, IMAGE_MASK1BIT13, + "Image '$1' with more than 1 bit not supported as mask in PDF 1.3") + +gen(1, 2410, IMAGE_COLORMAP, "Couldn't read colormap in image '$1'") + +gen(2, 2412, IMAGE_BADCOMP, + "Bad number of color components ($1) in image '$2'") + +gen(1, 2414, IMAGE_COLORIZE, + "Can't colorize image '$1' with more than 1 component") + +gen(1, 2416, IMAGE_ICC, "Couldn't handle embedded ICC profile in image '$1'") + +gen(1, 2418, IMAGE_ICC2, + "ICC profile for image file '$1' doesn't match image data") + +gen(0, 2420, IMAGE_THUMB, "More than one thumbnail for this page") + +gen(1, 2422, IMAGE_THUMB_MULTISTRIP, + "Can't use multi-strip image $1 as thumbnail") + +gen(1, 2424, IMAGE_THUMB_CS, + "Unsupported color space in thumbnail image handle $1") + +gen(2, 2426, IMAGE_THUMB_SIZE, "Thumbnail image $1 larger than $2 pixels") + +gen(2, 2428, IMAGE_OPTUNSUPP, + "Option '$1' for image type '$2' not supported") + +gen(2, 2430, IMAGE_OPTUNREAS, + "Option '$1' for image type '$2' doesn't have any effect") + +gen(2, 2432, IMAGE_OPTBADMASK, "Option '$1' has bad image mask $2") + +gen(1, 2434, IMAGE_UNKNOWN, "Unknown image type in file '$1'") + +gen(0, 2436, IMAGE_NOADJUST, + "Option 'adjustpage' must not be used in top-down system") + +gen(1, 2437, IMAGE_OPI_ILLRECT, "Option '$1' has bad rectangle") + +gen(2, 2438, IMAGE_OPI_ILLMAPSIZE, "Option '$1': Number of values must be $2") + +gen(1, 2439, IMAGE_OPI_ILLPARALL, "Option '$1' has bad parallelogram") + +gen(2, 2440, RAW_ILLSIZE, + "Size ($1 bytes) of raw image file '$2' doesn't match specified options") + +gen(2, 2442, IMAGE_TYPUNSUPP, "Image type '$1' is not supported in PDF $2") + +gen(1, 2444, BMP_VERSUNSUPP, + "Version of BMP image file '$1' not supported") + +gen(1, 2446, BMP_COMPUNSUPP, + "Compression in BMP image file '$1' not supported") + +gen(2, 2450, JPEG_COMPRESSION, + "JPEG compression scheme $1 in file '$2' not supported in PDF") + +/* UNUSED +gen(1, 2452, JPEG_MULTISCAN, + "JPEG file '$1' contains multiple scans, which is not supported in PDF") +*/ + +gen(2, 2454, JPEG_TRANSCODE, + "Problems during JPEG transcoding in file '$1' ($2)") + +/* UNUSED +gen(1, 2460, GIF_LZWOVERFLOW, "LZW code size overflow in GIF file '$1'") + +gen(1, 2462, GIF_LZWSIZE, + "Color palette in GIF file '$1' with fewer than 128 colors not supported") + +gen(1, 2464, GIF_INTERLACED, "Interlaced GIF image '$1' not supported") + +gen(2, 2470, TIFF_UNSUPP_CS, + "Couldn't open TIFF image '$1' (unsupported color space; photometric $2)") + +gen(2, 2472, TIFF_UNSUPP_PREDICT, + "Couldn't open TIFF image '$1' (unsupported predictor tag $2)") + +gen(1, 2474, TIFF_UNSUPP_LZW, "Couldn't open LZW-compressed TIFF image '$1')") + +gen(1, 2476, TIFF_UNSUPP_LZW_PLANES, + "Couldn't open TIFF image '$1' (separate planes with LZW compression)") + +gen(1, 2478, TIFF_UNSUPP_LZW_ALPHA, + "Couldn't open TIFF image '$1' (alpha channel with LZW compression)") + +gen(2, 2480, TIFF_UNSUPP_JPEG, + "Couldn't open TIFF image '$1' (JPEG compression scheme $2)") + +gen(1, 2482, TIFF_UNSUPP_JPEG_TILED, + "Couldn't open TIFF image '$1' (tiled image with JPEG compression)") +*/ + +gen(2, 2483, TIFF_UNSUPP_COLORSPACE, + "Color space (photometric) $1 in TIFF image '$2' not supported") + +gen(1, 2484, TIFF_UNSUPP_JPEG_SEPARATE, + "Couldn't open TIFF image '$1' (JPEG with separate image planes)") + +gen(2, 2486, TIFF_UNSUPP_SEP_NONCMYK, + "Couldn't open TIFF image '$1' (unsupported inkset tag $2)") + +gen(1, 2488, TIFF_MASK_MULTISTRIP, "Can't mask multistrip TIFF image '$1'") + +gen(2, 2489, TIFF_CLIPPPATH_NOTFOUND, + "Couldn't find clipping path '$1' in TIFF image '$2'") + +gen(1, 2490, TIFF_16BITCMYK_UNSUPP, + "Compressed 16-bit CMYK TIFF image '$1' not supported") + +gen(1, 2491, TIFF_16BIT_UNSUPP, + "More than 16 bits per component in TIFF image '$1' not supported") + +gen(1, 2492, TIFF_CMYK_MASK, "Couldn't open TIFF image '$1' (CMYK with mask)") + +gen(2, 2493, TIFF_UNSUPP_COMPRESSION, + "Compression scheme $1 in TIFF image '$2' not supported") + +gen(1, 2494, JPX_FORMATUNSUPP, + "JPEG2000 flavor in image file '$1' not supported") + +gen(1, 2496, JPX_RAWDATAUNSUPP, + "Raw JPEG2000 code stream in image file '$1' not supported") + +gen(1, 2498, JPX_COMPOUNDUNSUPP, + "Compound JPEG2000 (JPM) image file '$1' not supported") + + +/* -------------------------------------------------------------------- */ +/* Font (25xx) */ +/* -------------------------------------------------------------------- */ + +gen(2, 2500, FONT_CORRUPT, "Corrupt $1 font file '$2'") + +gen(2, 2501, FONT_PREFIX, "Font '$1' with encoding '$2': ") + +gen(0, 2502, FONT_BADENC, "Font doesn't support encoding") + +gen(3, 2503, FONT_PREFIX2, "Font '$1' with encoding '$2' (changed to '$3'): ") + +gen(1, 2504, FONT_FORCEENC, + "Font doesn't support encoding (encoding '$1' will be used)") + +gen(0, 2505, FONT_NEEDUCS2, + "Encoding not supported (use Unicode-compatible CMap)") + +/* UNUSED +gen(0, 2506, FONT_FORCEEMBED, + "Font will be embedded (encoding requires CID font") +*/ + +gen(1, 2507, FONT_INAPPROPENC, + "Encoding not appropriate for the font (only $1 glyphs found)") + +/* UNUSED +gen(1, 2508, FONT_BADTEXTFORM, + "Current text format not allowed for builtin encoding") +*/ + +gen(0, 2509, FONT_FORCECVTUNI, + "Native text code (keepnative) for this font configuration will be ignored") + +gen(0, 2514, FONT_EMBEDMM, "Multiple Master font cannot be embedded") + +gen(0, 2516, FONT_NOMETRICS, "Metrics data not found") + +gen(0, 2518, FONT_NOOUTLINE, "File with outline data not found") + +/* Unused +gen(0, 2520, FONT_NOGLYPHID, "Font doesn't contain any glyph IDs") +*/ + +gen(0, 2522, FONT_FORCEEMBED2, "Metadata requires embedding") + +gen(0, 2530, CJK_UNSUPP_REGISTRY, + "Font not supported (contains non-Adobe registry in CMap)") + +gen(0, 2531, CJK_UNSUPP_CHARCOLL, + "CJK font doesn't support encoding (use a compatible predefined CMap)") + +gen(0, 2532, FONT_EMBEDCMAP, + "Standard CJK font with predefined CMap cannot be embedded") + +gen(0, 2533, FONT_ONLY_CMAP, + "Font doesn't support encoding (use predefined CMap or 'unicode' encoding)") + +/* Unused +gen(0, 2534, FONT_EMBEDSTYLE, + "Option 'fontstyle' not allowed for embedded fonts") +*/ + +gen(0, 2535, FONT_UNSUPP_CMAP, + "Font doesn't support predefined CMap") + +gen(2, 2536, FONT_UNSUPPOPTION, + "Option '$1' not supported for font type '$2'") + +gen(0, 2538, FONT_IGNOREVERTICAL, + "Option 'vertical' ignored because of predefined CMap or font name resp.") + +gen(1, 2540, T3_BADBBOX, + "Bounding box values must be 0 for colorized font") + +gen(1, 2541, T3_FONT_PREFIX, "Type3 font '$1': ") + +gen(1, 2542, T3_GLYPH, "Glyph '$1' already defined") + +gen(0, 2544, T3_FONTEXISTS, "Already exists") + +gen(0, 2545, T3_FONTSUBSET, "Font with subsetting can only be loaded once") + +gen(1, 2546, T3_GLYPHMISSING, "Outlines of glyph '$1' not defined") + +gen(1, 2547, T3_OUTLINESMISSING, "Outlines of Type3 font '$1' missing") + +gen(1, 2548, T3_UNKOWNGLYPH, "Glyph '$1' unknown") + +gen(1, 2549, T3_MISSNOTDEF, "Glyph for character '.notdef' is missing") + +gen(1, 2550, T1_BADCHARSET, + "PDFlib doesn't support encoding (dfCharSet $1 in PFM file unknown)") + +gen(1, 2551, T1_UNSUPP_FORMAT, "'$1' metrics file type not supported") + +gen(2, 2554, T1_AFMBADKEY, "Unknown key '$1' in AFM file '$2'") + +gen(1, 2558, T1_NOFONT, "'$1' is not a PostScript Type1 font file") + +gen(2, 2560, FONT_CODENOTFOUND1, + "Glyph with character code $1 not found in font '$2'") + +gen(2, 2561, FONT_CODENOTFOUNDREP1, + "Glyph with character code $1 not found in font '$2' (will be replaced)") + +gen(2, 2562, FONT_UNICODENOTFOUND, + "Glyph with Unicode value U+$1 not found in font '$2'") + +gen(2, 2563, FONT_UNICODENOTFOUNDREP, + "Glyph with Unicode value U+$1 not found in font '$2' (will be replaced)") + +gen(2, 2564, FONT_GLYPHIDNOTFOUND, + "Glyph with id $1 not found in font '$2'") + +gen(3, 2566, FONT_CODENOTFOUND2, + "Glyph with code $1 and Unicode value U+$2 not found in font '$3'") + +gen(3, 2567, FONT_CODENOTFOUNDREP2, + "Glyph with code $1 and Unicode value U+$2 not found in font '$3' " + "(will be replaced)") + +gen(2, 2569, FONT_NOTFULFILL, + "Option '$1' cannot be fulfilled (same font already loaded with no$1)") + +/* -------------------------------------------------------------------- */ +/* Encoding (26xx) */ +/* -------------------------------------------------------------------- */ + +/* MOVED to pc_generr.h, #1552 +gen(1, 2600, ENC_NOTFOUND, "Couldn't find encoding '$1'") +*/ + +gen(1, 2602, ENC_UNSUPP, "Code page '$1' not supported") + +gen(1, 2606, ENC_CANTQUERY, "Can't query encoding '$1'") + +gen(1, 2608, ENC_CANTCHANGE, "Can't change encoding '$1'") + +gen(1, 2610, ENC_INUSE, + "Encoding '$1' can't be changed since it has already been used") + +/* MOVED to pc_generr.h, #1550 +gen(2, 2612, ENC_TOOLONG, "Encoding name '$1' too long (max. $2)") + + MOVED to pc_generr.h, #1551 +gen(2, 2614, ENC_BADLINE, "Syntax error in encoding file '$1' (line '$2')") +*/ + +gen(0, 2616, ENC_GLYPHORCODE, "Glyph name or Unicode value required") + +gen(3, 2618, ENC_BADGLYPH, + "Glyph name '$1' for Unicode value U+$2 differs from AGL name '$3'") + +gen(3, 2620, ENC_BADUNICODE, + "Unicode value U+$1 for glyph name '$2' differs from AGL value U+$3") + +gen(2, 2622, ENC_BADFONT, + "Current font $1 wasn't specified with encoding '$2'") + +gen(1, 2640, ENC_BADHYPTEXTENC, "Bad hypertext encoding '$1'") + +gen(1, 2650, ENC_UNSUPPENCFORMAT, + "Parameter or option '$1' not supported in Unicode-capable languages") + +/* Unused +gen(2, 2670, CMAP_ILLCODESEQU, "Illegal code sequence in '$1' for CMap '$2'") +*/ + + + +/* -------------------------------------------------------------------- */ +/* Hypertext, form fields, actions, annotations (28xx) */ +/* -------------------------------------------------------------------- */ + +gen(2, 2802, HYP_OPTIGNORE_FORTYPE, + "Option '$1' for destination type '$2' doesn't have any effect") + +gen(1, 2804, HYP_OPTIGNORE_FORELEM, + "Option '$1' for hypertext function will be ignored") + +gen(2, 2820, FF_OPTEFFLESS_FORTYPE, + "Option '$1' for field type '$2' doesn't have any effect") + +gen(1, 2822, FF_GROUPMISSING, + "Required field group missing for radio button field '$1'") + +gen(1, 2824, FF_FONTMISSING, "Font not specified for field '$1'") + +gen(2, 2826, FF_OPTIONMISSING, + "Option '$1' not specified for field '$2'") + +gen(1, 2828, FF_CIDFONT, + "Specified font '$1' not allowed for fields (encoding not supported)") + +gen(1, 2830, FF_NOEMBEDFONT, + "Specified font '$1' not allowed for fields (must be embedded)") + +gen(1, 2832, FF_SUBSETTFONT, + "Specified font '$1' not allowed for fields (must not be subset)") + +gen(1, 2834, FF_CAPTMISSING, "No caption or icon specified for field '$1'") + +gen(0, 2836, FF_DIFFSTRLISTS, + "Options 'itemnamelist' and 'itemtextlist' contain " + "different numbers of strings") + +gen(2, 2838, FF_INVALINDEX, "Option '$1' has invalid list index '$2'") + +gen(2, 2840, FF_NOTFOUND, + "Illegal field pathname '$1' (name '$2' not found)") + +gen(2, 2842, FF_NAMEEXISTS, + "Illegal field pathname '$1' (name '$2' already exists)") + +gen(2, 2844, FF_NOTGROUP, + "Illegal field pathname '$1' ('$2' is not a field group)") + +gen(3, 2846, FF_TYPENOTMATCH, + "Type '$1' of field '$2' doesn't match type '$3' of group") + +gen(0, 2848, FF_ITEMNAMEORNOT, +"Either all or none of the buttons/checkboxes in a group can have item names") + +gen(2, 2850, FF_OPTEFFONLY, + "Option '$1' for field type '$2' only has an effect for highlight=push") + +gen(2, 2852, FF_ILLUNINAME, + "Illegal field name '$1' (Unicode names are not supported in PDF $2") + +gen(0, 2854, FF_DEMOLIMIT, + "No more than 10 fields can be created with the evaluation version") + +gen(0, 2856, FF_RICHTEXT, + "fontsize 0 not supported for fields with rich text") + +gen(2, 2860, ACT_OPTIGNORE_FORTYPE, + "Option '$1' for action type '$2' doesn't have any effect") + +gen(2, 2862, ACT_BADACTTYPE, "Action type '$1' for event '$2' not allowed") + + +gen(2, 2880, ANN_OPTEFFLESS_FORTYPE, + "Option '$1' for annotation type '$2' doesn't have any effect") + +gen(1, 2882, ANN_NOSTDFONT, + "Font '$1' not allowed for annotations (not a core or standard CJK font)") + +gen(1, 2884, ANN_BADNUMCOORD, "Option '$1' has bad number of coordinates") + +gen(1, 2886, ANN_OPTALRDEF, + "Option '$1' already defined in option 'custom'") + +gen(1, 2888, ANN_ILLCUSTOMKEY, + "Option 'custom' uses illegal key '$1' (already defined in PDF)") + + +/* -------------------------------------------------------------------- */ +/* Internal (29xx) */ +/* -------------------------------------------------------------------- */ + +gen(1, 2900, INT_BADSCOPE, "Bad scope '$1'") + +gen(1, 2902, INT_BADANNOT, "Bad annotation type '$1'") + +gen(3, 2904, INT_BADCS, +"Unknown color space (function $1, index $2, type $3)") + +gen(1, 2906, INT_BADALTERNATE, "Bad alternate color space $1") + +gen(1, 2908, INT_BADPROFILE, "Unknown number of profile components ($1)") + +gen(1, 2910, INT_SSTACK_OVER, "State stack overflow in function '$1'") + +gen(1, 2912, INT_SSTACK_UNDER, "State stack underflow in function '$1'") + +gen(3, 2914, INT_WRAPPER, "Error in PDFlib $1 wrapper function $2 ($3)") + +gen(0, 2990, OT_UNSUPP_SID2CID, + "Accented characters not supported; contact support@pdflib.com") + + + + + + + +#undef gen +#undef pdf_genNames +#undef pdf_genInfo + + + diff --git a/src/pdflib/pdflib/p_gif.c b/src/pdflib/pdflib/p_gif.c new file mode 100644 index 0000000..59d80f5 --- /dev/null +++ b/src/pdflib/pdflib/p_gif.c @@ -0,0 +1,744 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_gif.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * GIF processing for PDFlib + * + */ + +/* + * This module contains modified parts of the giftopnm.c progam in the + * netpbm package. It contained the following copyright notice: + */ + +/* +-------------------------------------------------------------------+ */ +/* | Copyright 1990 - 1994, David Koblas. (koblas@netcom.com) | */ +/* | Permission to use, copy, modify, and distribute this software | */ +/* | and its documentation for any purpose and without fee is hereby | */ +/* | granted, provided that the above copyright notice appear in all | */ +/* | copies and that both that copyright notice and this permission | */ +/* | notice appear in supporting documentation. This software is | */ +/* | provided "as is" without express or implied warranty. | */ +/* +-------------------------------------------------------------------+ */ + +#include "p_intern.h" +#include "p_color.h" +#include "p_image.h" + +#ifndef PDF_GIF_SUPPORTED + +pdc_bool +pdf_is_GIF_file(PDF *p, pdc_file *fp) +{ + (void) p; + (void) fp; + + return pdc_false; +} + +int +pdf_process_GIF_data( + PDF *p, + int imageslot) +{ + pdf_image *image = &p->images[imageslot]; + + pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "GIF", 0, 0, 0); + + return -1; +} + +/* CDPDF - added missing function */ +void +pdf_cleanup_gif(PDF *p, pdf_image *image) +{ + (void) p; + (void) image; +} + +#else + +#define LOCALCOLORMAP 0x80 +#define BitSet(byteval, bitval) (((byteval) & (bitval)) == (bitval)) + +static int ReadColorMap(pdc_core *pdc, pdc_file *fp, + int number, pdf_colormap *buffer); +static int DoExtension(PDF *p, pdf_image *image, int label); +static int GetDataBlock(PDF *p, pdf_image *image, unsigned char *buf); +static void ReadImage(PDF *p, pdf_image *image, PDF_data_source *src); + +static void +pdf_data_source_GIF_init(PDF *p, PDF_data_source *src) +{ + pdf_image *image; + + image = (pdf_image *) src->private_data; + + src->buffer_length = (size_t) (image->width * image->height * 1); + src->buffer_start = (pdc_byte *) pdc_malloc(p->pdc, src->buffer_length, + "pdf_data_source_GIF_init"); + src->bytes_available= 0; + src->next_byte = NULL; +} + +static pdc_bool +pdf_data_source_GIF_fill(PDF *p, PDF_data_source *src) +{ + pdf_image *image; + + if (src->next_byte != NULL) /* all finished in one turn */ + return pdc_false; + + image = (pdf_image *) src->private_data; + + src->next_byte = src->buffer_start; + src->bytes_available = src->buffer_length; + + PDC_TRY(p->pdc) + { + ReadImage(p, image, src); + } + PDC_CATCH(p->pdc) + { + image->corrupt = pdc_true; + } + + pdf_cleanup_gif(p, image); + + return !image->corrupt; +} + +static void +pdf_data_source_GIF_terminate(PDF *p, PDF_data_source *src) +{ + pdc_free(p->pdc, (void *) src->buffer_start); +} + +#define PDF_STRING_GIF "\107\111\106" +#define PDF_STRING_87a "\070\067\141" +#define PDF_STRING_89a "\070\071\141" + +pdc_bool +pdf_is_GIF_file(PDF *p, pdc_file *fp) +{ + unsigned char buf[3]; + + pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type GIF...\n"); + + if (!PDC_OK_FREAD(fp, buf, 3) || + strncmp((const char *) buf, PDF_STRING_GIF, 3) != 0) + { + pdc_fseek(fp, 0L, SEEK_SET); + return pdc_false; + } + return pdc_true; +} + +int +pdf_process_GIF_data( + PDF *p, + int imageslot) +{ + unsigned char buf[16]; + char c; + int imageCount = 0; + char version[4]; + int errcode = 0; + pdf_image *image; + pdf_colorspace cs; + pdf_colormap colormap; + int slot; + + image = &p->images[imageslot]; + + image->info.gif.stack = NULL; + image->info.gif.table = NULL; + + /* we invert this flag later */ + if (image->ignoremask) + image->transparent = pdc_true; + + if (image->page == pdc_undef) + image->page = 1; + + /* Error reading magic number or not a GIF file */ + if (pdf_is_GIF_file(p, image->fp) == pdc_false) { + errcode = PDC_E_IO_BADFORMAT; + goto PDF_GIF_ERROR; + } + + /* Version number */ + if (! PDC_OK_FREAD(image->fp, buf, 3)) { + errcode = PDC_E_IO_BADFORMAT; + goto PDF_GIF_ERROR; + } + strncpy(version, (const char *) buf, 3); + version[3] = '\0'; + if ((strcmp(version, PDF_STRING_87a) != 0) && + (strcmp(version, PDF_STRING_89a) != 0)) { + errcode = PDC_E_IO_BADFORMAT; + goto PDF_GIF_ERROR; + } + + /* Failed to read screen descriptor */ + if (! PDC_OK_FREAD(image->fp, buf, 7)) { + errcode = PDC_E_IO_BADFORMAT; + goto PDF_GIF_ERROR; + } + + cs.type = Indexed; + /* size of the global color table */ + cs.val.indexed.palette_size = 2 << (buf[4] & 0x07); + cs.val.indexed.base = DeviceRGB; + cs.val.indexed.colormap = &colormap; + cs.val.indexed.colormap_id = PDC_BAD_ID; + + if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ + if (ReadColorMap(p->pdc, image->fp, + cs.val.indexed.palette_size, &colormap)) { + errcode = PDF_E_IMAGE_COLORMAP; + goto PDF_GIF_ERROR; + } + } + + /* translate the aspect ratio to PDFlib notation */ + if (buf[6] != 0) { + image->dpi_x = (pdc_scalar) (-(buf[6] + 15.0) / 64.0); + image->dpi_y = -1.0; + } + + for (/* */ ; /* */ ; /* */) { + /* EOF / read error in image data */ + if (!PDC_OK_FREAD(image->fp, &c, 1)) { + errcode = PDC_E_IO_READ; + goto PDF_GIF_ERROR; + } + +#define PDF_SEMICOLON ((char) 0x3b) /* ASCII ';' */ + + if (c == PDF_SEMICOLON) { /* GIF terminator */ + /* Not enough images found in file */ + if (imageCount < image->page) { + if (!imageCount) + errcode = PDF_E_IMAGE_CORRUPT; + else + errcode = PDF_E_IMAGE_NOPAGE; + goto PDF_GIF_ERROR; + } + break; + } + +#define PDF_EXCLAM ((char) 0x21) /* ASCII '!' */ + + if (c == PDF_EXCLAM) { /* Extension */ + if (!PDC_OK_FREAD(image->fp, &c, 1)) { + /* EOF / read error on extension function code */ + errcode = PDC_E_IO_READ; + goto PDF_GIF_ERROR; + } + DoExtension(p, image, (int) c); + continue; + } + +#define PDF_COMMA ((char) 0x2c) /* ASCII ',' */ + + if (c != PDF_COMMA) { /* Not a valid start character */ + /* Bogus character, ignoring */ + continue; + } + + ++imageCount; + + if (! PDC_OK_FREAD(image->fp, buf, 9)) { + /* Couldn't read left/top/width/height */ + errcode = PDC_E_IO_READ; + goto PDF_GIF_ERROR; + } + + image->components = 1; + image->bpc = 8; + image->width = (pdc_scalar) pdc_get_le_ushort(&buf[4]); + image->height = (pdc_scalar) pdc_get_le_ushort(&buf[6]); + +#define INTERLACE 0x40 + image->info.gif.interlace= BitSet(buf[8], INTERLACE); + + if (image->imagemask) + { + if (p->compatibility <= PDC_1_3) { + errcode = PDF_E_IMAGE_MASK1BIT13; + goto PDF_GIF_ERROR; + } else { + /* images with more than one bit will be written as /SMask, + * and don't require an /ImageMask entry. + */ + image->imagemask = pdc_false; + } + image->colorspace = DeviceGray; + } + + if (BitSet(buf[8], LOCALCOLORMAP)) { + /* The local color map may have a different size */ + cs.val.indexed.palette_size = 2 << (buf[8] & 0x07); + + if (ReadColorMap(p->pdc, image->fp, + cs.val.indexed.palette_size, &colormap)) + { + errcode = PDF_E_IMAGE_COLORMAP; + goto PDF_GIF_ERROR; + } + } + + if (imageCount == image->page) + break; + } + + image->src.init = pdf_data_source_GIF_init; + image->src.fill = pdf_data_source_GIF_fill; + image->src.terminate = pdf_data_source_GIF_terminate; + image->src.private_data = (void *) image; + + image->compression = pdf_comp_none; + image->use_raw = pdc_false; + + image->in_use = pdc_true; /* mark slot as used */ + + slot = pdf_add_colorspace(p, &cs, pdc_false); + image->colorspace = slot; + + + + + pdf_put_image(p, imageslot, pdc_true, pdc_true); + + if (!image->corrupt) + return imageslot; + + PDF_GIF_ERROR: + { + const char *stemp = NULL; + + if (errcode) + stemp = pdf_get_image_filename(p, image); + + switch (errcode) + { + case PDC_E_IO_READ: + case PDF_E_IMAGE_COLORMAP: + case PDF_E_IMAGE_MASK1BIT13: + pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0); + break; + + case PDC_E_IO_BADFORMAT: + pdc_set_errmsg(p->pdc, errcode, stemp, "GIF", 0, 0); + break; + + case PDF_E_IMAGE_CORRUPT: + pdc_set_errmsg(p->pdc, errcode, "GIF", stemp, 0, 0); + break; + + case PDF_E_IMAGE_NOPAGE: + pdc_set_errmsg(p->pdc, errcode, + pdc_errprintf(p->pdc, "%d", image->page), "GIF", stemp, 0); + break; + + case 0: /* error code and message already set */ + break; + } + } + + return -1; +} /* pdf_open_GIF_data */ + +static int +ReadColorMap(pdc_core *pdc, pdc_file *fp, int number, pdf_colormap *buffer) +{ + int i; + unsigned char rgb[3]; + + (void) pdc; + + for (i = 0; i < number; ++i) { + if (! PDC_OK_FREAD(fp, rgb, sizeof(rgb))) { + return pdc_true; /* yk: true == error */ + } + + (*buffer)[i][0] = rgb[0] ; + (*buffer)[i][1] = rgb[1] ; + (*buffer)[i][2] = rgb[2] ; + } + return pdc_false; /* yk: false == ok. */ +} /* ReadColorMap */ + +static int +DoExtension(PDF *p, pdf_image *image, int label) +{ + pdc_byte buf[256]; + + switch ((unsigned char) label) { + case 0x01: /* Plain Text Extension */ + break; + + case 0xff: /* Application Extension */ + break; + + case 0xfe: /* Comment Extension */ + while (GetDataBlock(p, image, (unsigned char*) buf) != 0) { + /* */ + } + return pdc_false; + + case 0xf9: /* Graphic Control Extension */ + (void) GetDataBlock(p, image, (unsigned char*) buf); + + if ((buf[0] & 0x1) != 0) { + image->transparent = !image->transparent; + image->transval[0] = buf[3]; + } + + while (GetDataBlock(p, image, (unsigned char*) buf) != 0) { + /* */ ; + } + return pdc_false; + + default: + break; + } + + while (GetDataBlock(p, image, (unsigned char*) buf) != 0) { + /* */ ; + } + + return pdc_false; +} /* DoExtension */ + +/* + * A bunch of formely static variables which are now kept in the + * image structure in order to keep the GIF reader thread-safe. + */ + +/* for GetDataBlock() */ +#define ZeroDataBlock (image->info.gif.ZeroDataBlock) + +/* for initLWZ() */ +#define curbit (image->info.gif.curbit) +#define lastbit (image->info.gif.lastbit) +#define get_done (image->info.gif.get_done) +#define last_byte (image->info.gif.last_byte) +#define return_clear (image->info.gif.return_clear) + +#define sp (image->info.gif.sp) +#define code_size (image->info.gif.code_size) +#define set_code_size (image->info.gif.set_code_size) +#define max_code (image->info.gif.max_code) +#define max_code_size (image->info.gif.max_code_size) +#define clear_code (image->info.gif.clear_code) +#define end_code (image->info.gif.end_code) + +/* for nextCode() */ +#define buf (image->info.gif.buf) + +/* for nextLWZ() */ +#define stack (image->info.gif.stack) +#define table (image->info.gif.table) +#define firstcode (image->info.gif.firstcode) +#define oldcode (image->info.gif.oldcode) + +static int +GetDataBlock(PDF *p, pdf_image *image, unsigned char *lbuf) +{ + unsigned char count; + pdc_file *fp = image->fp; + + if (!PDC_OK_FREAD(fp, &count, 1)) + return -1; /* Error in getting DataBlock size */ + + ZeroDataBlock = (count == 0); + + if ((count != (unsigned char) 0) && (!PDC_OK_FREAD(fp, lbuf, count))) + { + /* Error in reading DataBlock */ + pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF", + pdf_get_image_filename(p, image), 0, 0); + } + + return count; +} /* GetDataBlock */ + +static void +initLWZ(PDF *p, pdf_image *image, int input_code_size) +{ +#define GIF_TABLE_SIZE (sizeof(int [2][GIF_TABLE_ELEMENTS])) +#define GIF_STACK_SIZE (sizeof(int [GIF_TABLE_ELEMENTS*2])) + + table = (int(*)[GIF_TABLE_ELEMENTS]) + pdc_malloc(p->pdc, GIF_TABLE_SIZE, "initLWZ"); + stack = (int *) pdc_malloc(p->pdc, GIF_STACK_SIZE, "initLWZ"); + + set_code_size = input_code_size; + code_size = set_code_size + 1; + clear_code = 1 << set_code_size ; + end_code = clear_code + 1; + max_code_size = 2 * clear_code; + max_code = clear_code + 2; + + curbit = lastbit = 0; + last_byte = 2; + get_done = pdc_false; + + return_clear = pdc_true; + + sp = stack; +} + +/* + * We clean up after decompressing the image; in rare cases (exception + * caused by damaged compressed data) this may also be called when + * cleaning up the full image struct. + */ +void +pdf_cleanup_gif(PDF *p, pdf_image *image) +{ + if (table) + { + pdc_free(p->pdc, table); + table = NULL; + } + if (stack) + { + pdc_free(p->pdc, stack); + stack = NULL; + } +} + +static int +nextCode(PDF *p, pdf_image *image, int codesize) +{ + static const int maskTbl[16] = { + 0x0000, 0x0001, 0x0003, 0x0007, + 0x000f, 0x001f, 0x003f, 0x007f, + 0x00ff, 0x01ff, 0x03ff, 0x07ff, + 0x0fff, 0x1fff, 0x3fff, 0x7fff, + }; + int i, j, ret, end; + + if (return_clear) { + return_clear = pdc_false; + return clear_code; + } + + end = curbit + codesize; + + if (end >= lastbit) { + int count; + + if (get_done) { + if (curbit >= lastbit) + { + /* + ERROR("ran off the end of my bits" ); + */ + pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF", + pdf_get_image_filename(p, image), 0, 0); + } + return -1; + } + + if (last_byte >= 2) + { + buf[0] = buf[last_byte-2]; + buf[1] = buf[last_byte-1]; + } + + if ((count = GetDataBlock(p, image, &buf[2])) == 0) + get_done = pdc_true; + + last_byte = 2 + count; + curbit = (curbit - lastbit) + 16; + lastbit = (2+count)*8 ; + + end = curbit + codesize; + } + + j = end / 8; + i = curbit / 8; + + if (i == j) + ret = buf[i]; + else if (i + 1 == j) + ret = buf[i] | (buf[i+1] << 8); + else + ret = buf[i] | (buf[i+1] << 8) | (buf[i+2] << 16); + + ret = (ret >> (curbit % 8)) & maskTbl[codesize]; + + curbit += codesize; + + return ret; +} + +#define readLWZ(p, image) ((sp > stack) ? *--sp : nextLWZ(p, image)) + +static int +nextLWZ(PDF *p, pdf_image *image) +{ + int code, incode; + int i; + + while ((code = nextCode(p, image, code_size)) >= 0) { + if (code == clear_code) { + for (i = 0; i < clear_code; ++i) { + table[0][i] = 0; + table[1][i] = i; + } + for (; i < (1<<MAX_LWZ_BITS); ++i) + table[0][i] = table[1][i] = 0; + code_size = set_code_size+1; + max_code_size = 2*clear_code; + max_code = clear_code+2; + sp = stack; + do { + firstcode = oldcode = nextCode(p, image, code_size); + } while (firstcode == clear_code); + + return firstcode; + } + if (code == end_code) { + int count; + unsigned char lbuf[260]; + + if (ZeroDataBlock) + return -2; + + while ((count = GetDataBlock(p, image, lbuf)) > 0) + ; + + /* count != 0: INFO_MSG(("missing EOD in data stream")); */ + + return -2; + } + + incode = code; + + if (code >= max_code) { + *sp++ = firstcode; + code = oldcode; + } + + while (code >= clear_code) { + *sp++ = table[1][code]; + if (code == table[0][code]) + { + /* ERROR("circular table entry BIG ERROR"); */ + pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF", + pdf_get_image_filename(p, image), 0, 0); + } + code = table[0][code]; + } + + *sp++ = firstcode = table[1][code]; + + if ((code = max_code) <(1<<MAX_LWZ_BITS)) { + table[0][code] = oldcode; + table[1][code] = firstcode; + ++max_code; + if ((max_code >= max_code_size) && + (max_code_size < (1<<MAX_LWZ_BITS))) { + max_code_size *= 2; + ++code_size; + } + } + + oldcode = incode; + + if (sp > stack) + return *--sp; + } + return code; +} + +static void +ReadImage(PDF *p, pdf_image *image, PDF_data_source *src) +{ + unsigned char c; + int v; + unsigned int xpos = 0, ypos = 0; + pdc_byte *dp; + unsigned int h = (unsigned int) image->height; + unsigned int w = (unsigned int) image->width; + + /* + * Initialize the Compression routines + */ + ZeroDataBlock = pdc_false; + + if (!PDC_OK_FREAD(image->fp, &c, 1)) + { + pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF", + pdf_get_image_filename(p, image), 0, 0); + } + + initLWZ(p, image, c); + + if (image->info.gif.interlace) { + int i; + int pass = 0, step = 8; + + for (i = 0; i < (int) h; i++) { + dp = &src->buffer_start[w * ypos]; + for (xpos = 0; xpos < w; xpos++) { + if ((v = readLWZ(p, image)) < 0) + goto fini; + + *dp++ = v; + } + if ((ypos += step) >= h) { + do { + if (pass++ > 0) + step /= 2; + ypos = step / 2; + } while (ypos > h); + } + } + } else { + dp = src->buffer_start; + for (ypos = 0; ypos < h; ypos++) { + for (xpos = 0; xpos < w; xpos++) { + if ((v = readLWZ(p, image)) < 0) + goto fini; + + *dp++ = v; + } + } + } + +fini: + if (readLWZ(p, image) >= 0) + /* Too much input data in GIF file '%s', ignoring extra. */ + ; +} + +#undef fresh +#undef code_size +#undef set_code_size +#undef max_code +#undef max_code_size +#undef firstcode +#undef oldcode +#undef clear_code +#undef end_code +#undef sp +#undef table +#undef stack + +#endif /* PDF_GIF_SUPPORTED */ diff --git a/src/pdflib/pdflib/p_gstate.c b/src/pdflib/pdflib/p_gstate.c new file mode 100644 index 0000000..2b62542 --- /dev/null +++ b/src/pdflib/pdflib/p_gstate.c @@ -0,0 +1,451 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_gstate.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib routines dealing with the graphics states + * + */ + +#include "p_intern.h" + +/* ---------------------- matrix functions ----------------------------- */ + +void +pdf_concat_raw(PDF *p, pdc_matrix *m) +{ + if (pdc_is_identity_matrix(m)) + return; + + pdf_end_text(p); + + pdc_printf(p->out, "%f %f %f %f %f %f cm\n", + m->a, m->b, m->c, m->d, m->e, m->f); + + pdc_multiply_matrix(m, &p->curr_ppt->gstate[p->curr_ppt->sl].ctm); +} + +void +pdf_set_topdownsystem(PDF *p, pdc_scalar height) +{ + if (p->ydirection < 0) + { + pdc_matrix m, sm; + + pdc_translation_matrix(0, height, &m); + pdc_scale_matrix(1, -1, &sm); + pdc_multiply_matrix(&sm, &m); + pdf_concat_raw(p, &m); + } +} + +/* -------------------- Special graphics state ---------------------------- */ + +void +pdf_init_gstate(PDF *p) +{ + pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl]; + + pdc_identity_matrix(&gs->ctm); + + gs->x = 0; + gs->y = 0; + + p->curr_ppt->fillrule = pdf_fill_winding; + + gs->lwidth = 1; + gs->lcap = 0; + gs->ljoin = 0; + gs->miter = 10; + gs->flatness = -1; /* -1 means "has not been set" */ + gs->dashed = pdc_false; +} + +void +pdf__save(PDF *p) +{ + pdf_ppt * ppt = p->curr_ppt; + int sl = ppt->sl; + + if (sl == PDF_MAX_SAVE_LEVEL - 1) + pdc_error(p->pdc, PDF_E_GSTATE_SAVELEVEL, + pdc_errprintf(p->pdc, "%d", PDF_MAX_SAVE_LEVEL - 1), 0, 0, 0); + + pdf_end_text(p); + pdc_puts(p->out, "q\n"); + + /* propagate states to next level */ + memcpy(&ppt->gstate[sl + 1], &ppt->gstate[sl], sizeof(pdf_gstate)); + pdf_save_cstate(p); + pdf_save_tstate(p); + ++ppt->sl; +} + +void +pdf__restore(PDF *p) +{ + if (p->curr_ppt->sl == 0) + pdc_error(p->pdc, PDF_E_GSTATE_RESTORE, 0, 0, 0, 0); + + pdf_end_text(p); + + pdc_puts(p->out, "Q\n"); + + p->curr_ppt->sl--; + + pdf_restore_currto(p); +} + +void +pdf__translate(PDF *p, pdc_scalar tx, pdc_scalar ty) +{ + pdc_matrix m; + + pdc_check_number(p->pdc, "tx", tx); + pdc_check_number(p->pdc, "ty", ty); + + if (tx == 0 && ty == 0) + return; + + pdc_translation_matrix(tx, ty, &m); + + pdf_concat_raw(p, &m); +} + +void +pdf__scale(PDF *p, pdc_scalar sx, pdc_scalar sy) +{ + pdc_matrix m; + + pdc_check_number_zero(p->pdc, "sx", sx); + pdc_check_number_zero(p->pdc, "sy", sy); + + if (sx == 1 && sy == 1) + return; + + pdc_scale_matrix(sx, sy, &m); + + pdf_concat_raw(p, &m); +} + +void +pdf__rotate(PDF *p, pdc_scalar phi) +{ + pdc_matrix m; + + pdc_check_number(p->pdc, "phi", phi); + + if (phi == 0) + return; + + pdc_rotation_matrix(p->ydirection * phi, &m); + + pdf_concat_raw(p, &m); +} + +void +pdf__skew(PDF *p, pdc_scalar alpha, pdc_scalar beta) +{ + pdc_matrix m; + + pdc_check_number(p->pdc, "alpha", alpha); + pdc_check_number(p->pdc, "beta", beta); + + if (alpha == 0 && beta == 0) + return; + + if (alpha > 360 || alpha < -360 || + alpha == -90 || alpha == -270 || + alpha == 90 || alpha == 270) + { + pdc_error(p->pdc, PDC_E_ILLARG_FLOAT, + "alpha", pdc_errprintf(p->pdc, "%f", alpha), 0, 0); + } + + if (beta > 360 || beta < -360 || + beta == -90 || beta == -270 || + beta == 90 || beta == 270) + { + pdc_error(p->pdc, PDC_E_ILLARG_FLOAT, + "beta", pdc_errprintf(p->pdc, "%f", beta), 0, 0); + } + + pdc_skew_matrix(p->ydirection * alpha, p->ydirection * beta, &m); + + pdf_concat_raw(p, &m); +} + +void +pdf__concat(PDF *p, pdc_scalar a, pdc_scalar b, pdc_scalar c, pdc_scalar d, + pdc_scalar e, pdc_scalar f) +{ + pdc_matrix m; + pdc_scalar det = a * d - b * c; + + pdc_check_number(p->pdc, "a", a); + pdc_check_number(p->pdc, "b", b); + pdc_check_number(p->pdc, "c", c); + pdc_check_number(p->pdc, "d", d); + pdc_check_number(p->pdc, "e", e); + pdc_check_number(p->pdc, "f", f); + + if (fabs(det) < PDF_SMALLREAL) + pdc_error(p->pdc, PDC_E_ILLARG_MATRIX, + pdc_errprintf(p->pdc, "%f %f %f %f %f %f", a, b, c, d, e, f), + 0, 0, 0); + + m.a = a; + m.b = b; + m.c = c; + m.d = d; + m.e = e; + m.f = f; + + pdf_concat_raw(p, &m); +} + +void +pdf_setmatrix_e(PDF *p, pdc_matrix *n) +{ + pdc_matrix m; + pdc_scalar det = n->a * n->d - n->b * n->c; + + if (fabs(det) < PDF_SMALLREAL) + pdc_error(p->pdc, PDC_E_ILLARG_MATRIX, + pdc_errprintf(p->pdc, "%f %f %f %f %f %f", + n->a, n->b, n->c, n->d, n->e, n->f), + 0, 0, 0); + + pdc_invert_matrix(p->pdc, &m, &p->curr_ppt->gstate[p->curr_ppt->sl].ctm); + pdc_multiply_matrix(n, &m); + pdf_concat_raw(p, &m); +} + + +void +pdf__setmatrix(PDF *p, pdc_scalar a, pdc_scalar b, pdc_scalar c, pdc_scalar d, + pdc_scalar e, pdc_scalar f) +{ + pdc_matrix n; + + pdc_check_number(p->pdc, "a", a); + pdc_check_number(p->pdc, "b", b); + pdc_check_number(p->pdc, "c", c); + pdc_check_number(p->pdc, "d", d); + pdc_check_number(p->pdc, "e", e); + pdc_check_number(p->pdc, "f", f); + + n.a = a; + n.b = b; + n.c = c; + n.d = d; + n.e = e; + n.f = f; + pdf_setmatrix_e(p, &n); +} + +/* -------------------- General graphics state ---------------------------- */ + +/* definitions of dash options */ +static const pdc_defopt pdf_dashoptions[] = +{ + {"dasharray", pdc_scalarlist, PDC_OPT_NONE, 2, PDF_MAX_DASHLENGTH, + PDC_FLOAT_PREC, PDC_FLOAT_MAX, NULL}, + + {"dashphase", pdc_scalarlist, PDC_OPT_NONE, 1, 1, 0.0, PDC_FLOAT_MAX, NULL}, + + PDC_OPT_TERMINATE +}; + +void +pdf_setdashpattern_internal(PDF *p, pdc_scalar *darray, int length, + pdc_scalar phase) +{ + pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl]; + + /* length == 0 or 1 means solid line */ + if (length < 2) + { + if (gs->dashed || PDF_FORCE_OUTPUT()) + { + pdc_puts(p->out, "[] 0 d\n"); + gs->dashed = pdc_false; + } + } + else + { + int i; + + pdc_begin_array(p->out); + for (i = 0; i < length; i++) + { + pdc_printf(p->out, "%f ", darray[i]); + } + pdc_end_array_c(p->out); + pdc_printf(p->out, "%f d\n", phase); + gs->dashed = pdc_true; + } +} + +void +pdf__setdash(PDF *p, pdc_scalar b, pdc_scalar w) +{ + pdc_scalar darray[2]; + int length = 2; + + 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); + + /* both zero means solid line */ + if (b == 0.0 && w == 0.0) + { + length = 0; + } + else + { + darray[0] = b; + darray[1] = w; + } + pdf_setdashpattern_internal(p, darray, length, 0); +} + +void +pdf__setdashpattern(PDF *p, const char *optlist) +{ + pdc_resopt *results; + char **strlist; + pdc_scalar *darray = NULL, phase = 0; + int length; + + /* parsing optlist */ + results = pdc_parse_optionlist(p->pdc, optlist, pdf_dashoptions, NULL, + pdc_true); + + length = pdc_get_optvalues("dasharray", results, NULL, &strlist); + darray = (pdc_scalar *) strlist; + + pdc_get_optvalues("dashphase", results, &phase, NULL); + + pdf_setdashpattern_internal(p, darray, length, phase); + + pdc_cleanup_optionlist(p->pdc, results); +} + +void +pdf__setflat(PDF *p, pdc_scalar flat) +{ + pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl]; + + pdc_check_number_limits(p->pdc, "flat", flat, 0.0, 100.0); + + if (flat != gs->flatness || PDF_FORCE_OUTPUT()) + { + gs->flatness = flat; + pdc_printf(p->out, "%f i\n", flat); + } +} + +void +pdf__setlinejoin(PDF *p, int join) +{ + pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl]; + const int LAST_JOIN = 2; + + if (join < 0 || join > LAST_JOIN) + pdc_error(p->pdc, PDC_E_ILLARG_INT, + "join", pdc_errprintf(p->pdc, "%d", join), 0, 0); + + if (join != gs->ljoin || PDF_FORCE_OUTPUT()) + { + gs->ljoin = join; + pdc_printf(p->out, "%d j\n", join); + } +} + +void +pdf__setlinecap(PDF *p, int cap) +{ + pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl]; + const int LAST_CAP = 2; + + if (cap < 0 || cap > LAST_CAP) + pdc_error(p->pdc, PDC_E_ILLARG_INT, + "cap", pdc_errprintf(p->pdc, "%d", cap), 0, 0); + + if (cap != gs->lcap || PDF_FORCE_OUTPUT()) + { + gs->lcap = cap; + pdc_printf(p->out, "%d J\n", cap); + } +} + +void +pdf__setmiterlimit(PDF *p, pdc_scalar miter) +{ + pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl]; + + pdc_check_number_limits(p->pdc, "miter", miter, 1.0, PDC_FLOAT_MAX); + + if (miter != gs->miter || PDF_FORCE_OUTPUT()) + { + gs->miter = miter; + pdc_printf(p->out, "%f M\n", miter); + } +} + +void +pdf__setlinewidth(PDF *p, pdc_scalar width) +{ + pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl]; + + pdc_check_number_limits(p->pdc, "width", width, + PDC_FLOAT_PREC, PDC_FLOAT_MAX); + + if (width != gs->lwidth || PDF_FORCE_OUTPUT()) + { + gs->lwidth = width; + pdc_printf(p->out, "%f w\n", width); + } +} + +/* reset all gstate parameters except CTM +*/ +void +pdf_reset_gstate(PDF *p) +{ + pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl]; + + pdf_set_default_color(p, pdc_true); + pdf__setlinewidth(p, 1); + pdf__setlinecap(p, 0); + pdf__setlinejoin(p, 0); + pdf__setmiterlimit(p, 10); + pdf__setdash(p, 0, 0); + + if (gs->flatness != -1) + pdf__setflat(p, 1); +} + +void +pdf__initgraphics(PDF *p) +{ + pdc_matrix inv_ctm; + + pdf_reset_gstate(p); + + pdc_invert_matrix(p->pdc, &inv_ctm, + &p->curr_ppt->gstate[p->curr_ppt->sl].ctm); + pdf_concat_raw(p, &inv_ctm); + + /* This also resets the CTM which guards against rounding artifacts. */ + pdf_init_gstate(p); +} diff --git a/src/pdflib/pdflib/p_hkscmyk.h b/src/pdflib/pdflib/p_hkscmyk.h new file mode 100644 index 0000000..924ad64 --- /dev/null +++ b/src/pdflib/pdflib/p_hkscmyk.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_hkscmyk.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib HKS spot CMYK color table + * + * HKS is a registered trademark of + * HKS (Hostmann-Steinberg, K+E, Schmincke)-Warenzeichenverband e.V. + * Germany + * + */ + +#ifndef P_HKSCMYK_H +#define P_HKSCMYK_H + + +#endif /* P_HKSCMYK_H */ + diff --git a/src/pdflib/pdflib/p_hkslab.h b/src/pdflib/pdflib/p_hkslab.h new file mode 100644 index 0000000..68f13bb --- /dev/null +++ b/src/pdflib/pdflib/p_hkslab.h @@ -0,0 +1,26 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_hkslab.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib HKS spot Lab color table + * + * HKS is a registered trademark of + * HKS (Hostmann-Steinberg, K+E, Schmincke)-Warenzeichenverband e.V. Germany + * + */ + +#ifndef P_HKSLAB_H +#define P_HKSLAB_H + + +#endif /* P_HKSTAB_H */ diff --git a/src/pdflib/pdflib/p_hyper.c b/src/pdflib/pdflib/p_hyper.c new file mode 100644 index 0000000..644e311 --- /dev/null +++ b/src/pdflib/pdflib/p_hyper.c @@ -0,0 +1,1449 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_hyper.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib routines for hypertext stuff: + * named destination, bookmarks, document info + * + */ + +#define P_HYPER_C + +#include "p_intern.h" +#include "p_color.h" + + + + +/* -------------------------- named destinations -------------------------- */ + +typedef enum +{ + fixed, + fitwindow, + fitwidth, + fitheight, + fitrect, + fitvisible, + fitvisiblewidth, + fitvisibleheight, + nameddest, + filedest +} +pdf_desttype; + +static const pdc_keyconn pdf_type_keylist[] = +{ + {"fixed", fixed}, + {"fitwindow", fitwindow}, + {"fitwidth", fitwidth}, + {"fitheight", fitheight}, + {"fitrect", fitrect}, + {"fitvisible", fitvisible}, + {"fitvisiblewidth", fitvisiblewidth}, + {"fitvisibleheight",fitvisibleheight}, + {"nameddest", nameddest}, + {"file", filedest}, + {NULL, 0} +}; + +/* Destination structure */ +struct pdf_dest_s +{ + pdf_desttype type; + char *filename; /* name of a file to be launched - deprecated */ + int remote_page; /* remote target page number */ + int pgnum; + pdc_id page; /* local target page object id */ + char *name; /* destination name, only for type=nameddest */ + int len; /* length of the name string */ + pdc_scalar zoom; /* magnification */ + pdc_scalar left; + pdc_scalar right; + pdc_scalar bottom; + pdc_scalar top; + pdc_scalar color[3]; /* rgb color of bookmark text - deprecated */ + fnt_fontstyle fontstyle; /* font style of bookmark text - deprecated */ +}; + +static const pdc_defopt pdf_destination_options[] = +{ + {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDF_MAX_NAMESTRING, NULL}, + + {"hypertextformat", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, pdf_textformat_keylist}, + + {"fitbbox", pdc_booleanlist, PDC_OPT_NONE, + 1, 1, 0.0, 0.0, NULL}, + + {"fitheight", pdc_booleanlist, PDC_OPT_NONE, + 1, 1, 0.0, 0.0, NULL}, + + {"fitpage", pdc_booleanlist, PDC_OPT_NONE, + 1, 1, 0.0, 0.0, NULL}, + + {"fitwidth", pdc_booleanlist, PDC_OPT_NONE, + 1, 1, 0.0, 0.0, NULL}, + + {"retain", pdc_booleanlist, PDC_OPT_NONE, + 1, 1, 0.0, 0.0, NULL}, + + {"type", pdc_keywordlist, PDC_OPT_NONE, + 1, 1, 0.0, 0.0, pdf_type_keylist}, + + {"name", pdc_stringlist, PDC_OPT_NONE, + 1, 1, 1.0, PDC_INT_MAX, NULL}, + + {"page", pdc_integerlist, PDC_OPT_NONE, + 1, 1, 0, PDC_INT_MAX, NULL}, + + {"group", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 1.0, PDF_MAX_NAMESTRING, NULL}, + + /* Acrobat 5 supports a maximum zoom of 1600%, but we allow some more */ + {"zoom", pdc_scalarlist, PDC_OPT_PERCENT, + 1, 1, 0.0, 10000, NULL}, + + {"left", pdc_scalarlist, PDC_OPT_NONE, + 1, 1, 0.0, PDF_ACRO_MAXPAGE, NULL}, + + {"right", pdc_scalarlist, PDC_OPT_NONE, + 1, 1, 0.0, PDF_ACRO_MAXPAGE, NULL}, + + {"bottom", pdc_scalarlist, PDC_OPT_REQUIRIF1, + 1, 1, 0.0, PDF_ACRO_MAXPAGE, NULL}, + + {"top", pdc_scalarlist, PDC_OPT_NONE, + 1, 1, 0.0, PDF_ACRO_MAXPAGE, NULL}, + + {"color", pdc_scalarlist, PDC_OPT_NONE, + 1, 3, 0.0, 1.0, NULL}, + + {"fontstyle", pdc_keywordlist, PDC_OPT_NONE, + 1, 1, 0.0, 0.0, pdf_fontstyle_pdfkeylist}, + + {"filename", pdc_stringlist, PDC_OPT_NONE, + 1, 1, 0.0, PDC_FILENAMELEN, NULL}, + + PDC_OPT_TERMINATE +}; + +pdf_dest * +pdf_init_destination(PDF *p) +{ + static const char fn[] = "pdf_init_destination"; + pdf_dest *dest = (pdf_dest *) pdc_malloc(p->pdc, sizeof(pdf_dest), fn); + + dest->type = fitwindow; + dest->remote_page = 0; + dest->pgnum = 0; + dest->page = PDC_BAD_ID; + dest->left = -1; + dest->right = -1; + dest->bottom = -1; + dest->top = -1; + dest->zoom = -1; + dest->name = NULL; + dest->color[0] = 0.0; + dest->color[1] = 0.0; + dest->color[2] = 0.0; + dest->fontstyle = fnt_Normal; + dest->filename = NULL; + + return dest; +} + +void +pdf_cleanup_destination(PDF *p, pdf_dest *dest) +{ + if (dest) + { + if (dest->name) + { + pdc_free(p->pdc, dest->name); + dest->name = NULL; + } + if (dest->filename) + { + pdc_free(p->pdc, dest->filename); + dest->filename = NULL; + } + + pdc_free(p->pdc, dest); + } +} + +pdf_dest * +pdf_parse_destination_optlist( + PDF *p, + const char *optlist, + int page, + pdf_destuse destuse) +{ + int minpage; + pdc_resopt *resopts; + pdc_encoding hypertextencoding; + int hypertextcodepage; + const char *keyword; + const char *type_name; + char **strlist = NULL; + int inum; + pdc_bool boolval; + + /* Defaults */ + pdf_dest *dest = pdf_init_destination(p); + + /* parse option list */ + resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_destination_options, + NULL, pdc_true); + + if (pdc_get_optvalues("fitbbox", resopts, &boolval, NULL) && + boolval == pdc_true) + dest->type = fitvisible; + + if (pdc_get_optvalues("fitheight", resopts, &boolval, NULL) && + boolval == pdc_true) + dest->type = fitheight; + + if (pdc_get_optvalues("fitpage", resopts, &boolval, NULL) && + boolval == pdc_true) + dest->type = fitwindow; + + if (pdc_get_optvalues("fitwidth", resopts, &boolval, NULL) && + boolval == pdc_true) + dest->type = fitwidth; + + if (pdc_get_optvalues("retain", resopts, &boolval, NULL) && + boolval == pdc_true) + dest->type = fixed; + + if (pdc_get_optvalues("type", resopts, &inum, NULL)) + dest->type = (pdf_desttype) inum; + type_name = pdc_get_keyword(dest->type, pdf_type_keylist); + + hypertextencoding = + pdf_get_hypertextencoding_opt(p, resopts, &hypertextcodepage, pdc_true); + + keyword = "name"; + if (pdf_get_opt_textlist(p, keyword, resopts, hypertextencoding, + hypertextcodepage, pdc_true, NULL, &dest->name, NULL)) + { + if (dest->type != nameddest) + { + dest->name = NULL; + pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, + type_name, 0, 0); + } + else + pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + } + + keyword = "page"; + if (pdc_get_optvalues(keyword, resopts, &page, NULL) && + dest->type == filedest) + pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name, + 0, 0); + + keyword = "group"; + if (pdc_get_optvalues(keyword, resopts, NULL, &strlist)) + { + page = pdf_xlat_pageno(p, page, strlist[0]); + } + + keyword = "zoom"; + if (pdc_get_optvalues(keyword, resopts, &dest->zoom, NULL) && + dest->type != fixed) + pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name, + 0, 0); + + keyword = "left"; + if (pdc_get_optvalues(keyword, resopts, &dest->left, NULL) && + (dest->type == fitwindow || dest->type == fitwidth || + dest->type == fitvisible || dest->type == fitvisiblewidth || + dest->type == nameddest || dest->type == filedest)) + pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name, + 0, 0); + + keyword = "right"; + if (pdc_get_optvalues(keyword, resopts, &dest->right, NULL) && + dest->type != fitrect) + pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name, + 0, 0); + + keyword = "bottom"; + if (pdc_get_optvalues(keyword, resopts, &dest->bottom, NULL) && + dest->type != fitrect) + pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name, + 0, 0); + + keyword = "top"; + if (pdc_get_optvalues(keyword, resopts, &dest->top, NULL) && + (dest->type == fitwindow || dest->type == fitheight || + dest->type == fitvisible || dest->type == fitvisibleheight || + dest->type == nameddest || dest->type == filedest)) + pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, type_name, + 0, 0); + + keyword = "color"; + if (pdc_get_optvalues(keyword, resopts, &dest->color, NULL) && + destuse != pdf_bookmark) + pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORELEM, keyword, 0, 0, 0); + + keyword = "fontstyle"; + if (pdc_get_optvalues(keyword, resopts, &inum, NULL)) + { + dest->fontstyle = (fnt_fontstyle) inum; + if (destuse != pdf_bookmark) + pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORELEM, keyword, 0, 0, 0); + } + + keyword = "filename"; + if (pdc_get_optvalues(keyword, resopts, NULL, NULL)) + { + if (dest->type != filedest) + { + pdc_warning(p->pdc, PDF_E_HYP_OPTIGNORE_FORTYPE, keyword, + type_name, 0, 0); + } + else + dest->filename = + (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + } + + pdc_cleanup_optionlist(p->pdc, resopts); + + switch (dest->type) + { + case fitwidth: + /* Trick: we don't know the height of a future page yet, + * so we use a "large" value for top which will do for + * most pages. If it doesn't work, not much harm is done. + */ + if (dest->top == -1) + dest->top = 10000; + break; + + case fitrect: + case fitheight: + case fitvisiblewidth: + case fitvisibleheight: + if (dest->left == -1) + dest->left = 0; + if (dest->bottom == -1) + dest->bottom = 0; + if (dest->right == -1) + dest->right = 1000; + if (dest->top == -1) + dest->top = 1000; + break; + + case nameddest: + if (destuse == pdf_nameddest) + { + pdf_cleanup_destination(p, dest); + pdc_error(p->pdc, PDC_E_OPT_ILLKEYWORD, "type", type_name, 0, 0); + } + if (dest->name == NULL) + { + pdf_cleanup_destination(p, dest); + pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, "name", 0, 0, 0); + } + break; + + case filedest: + if (destuse != pdf_bookmark) + { + pdf_cleanup_destination(p, dest); + pdc_error(p->pdc, PDC_E_OPT_ILLKEYWORD, "type", type_name, 0, 0); + } + if (dest->filename == NULL) + { + pdf_cleanup_destination(p, dest); + pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, "filename", 0, 0, 0); + } + break; + + default: + break; + } + + /* check for minpage */ + minpage = (destuse == pdf_bookmark) ? 0 : 1; + switch (destuse) + { + case pdf_nameddest: + case pdf_locallink: + if (page == 0) + { + page = pdf_current_page(p); + } + + case pdf_openaction: + case pdf_bookmark: + case pdf_remotelink: + if (page < minpage) + { + const char *stemp = pdc_errprintf(p->pdc, "%d", page); + pdf_cleanup_destination(p, dest); + pdc_error(p->pdc, PDC_E_ILLARG_HANDLE, "page", stemp, 0, 0); + } + break; + } + + dest->pgnum = page; + + if (destuse != pdf_remotelink && destuse != pdf_openaction && page != 0) + { + dest->page = pdf_get_page_id(p, page); + } + + /* remote page number */ + if (destuse == pdf_remotelink) + dest->remote_page = page; + + return dest; +} + +#if defined(_MSC_VER) && defined(_MANAGED) +#pragma unmanaged +#endif +pdf_dest * +pdf_get_option_destname(PDF *p, pdc_resopt *resopts, + pdc_encoding hypertextencoding, + int hypertextcodepage) +{ + pdc_text_format hypertextformat = pdc_bytes; + pdf_dest *dest = NULL; + char **strlist; + int outlen; + + if (pdc_get_optvalues("destname", resopts, NULL, &strlist)) + { + dest = pdf_init_destination(p); + dest->type = nameddest; + + if (pdc_is_lastopt_utf8(resopts)) + hypertextformat = PDC_UTF8; + dest->name = pdf_convert_hypertext(p, strlist[0], 0, hypertextformat, + hypertextencoding, hypertextcodepage, + &outlen, PDC_UTF8_FLAG, pdc_true); + } + return dest; +} +#if defined(_MSC_VER) && defined(_MANAGED) +#pragma managed +#endif + + +void +pdf_write_destination(PDF *p, pdf_dest *dest) +{ + if (dest->type == nameddest) + { + pdf_put_hypertext(p, dest->name); + pdc_puts(p->out, "\n"); + return; + } + + pdc_begin_array(p->out); + + if (dest->remote_page) + { + pdc_printf(p->out, "%d", dest->remote_page - 1); /* zero-based */ + } + else + { + if (dest->page == PDC_BAD_ID) + dest->page = pdf_get_page_id(p, dest->pgnum); + + pdc_objref_c(p->out, dest->page); + } + + switch (dest->type) { + + case fixed: + pdc_puts(p->out, "/XYZ "); + + if (dest->left != -1) + pdc_printf(p->out, "%f ", dest->left); + else + pdc_puts(p->out, "null "); + + if (dest->top != -1) + pdc_printf(p->out, "%f ", dest->top); + else + pdc_puts(p->out, "null "); + + if (dest->zoom != -1) + pdc_printf(p->out, "%f", dest->zoom); + else + pdc_puts(p->out, "null"); + + break; + + case fitwindow: + pdc_puts(p->out, "/Fit"); + break; + + case fitwidth: + pdc_printf(p->out, "/FitH %f", dest->top); + break; + + case fitheight: + pdc_printf(p->out, "/FitV %f", dest->left); + break; + + case fitrect: + pdc_printf(p->out, "/FitR %f %f %f %f", + dest->left, dest->bottom, dest->right, dest->top); + break; + + case fitvisible: + pdc_puts(p->out, "/FitB"); + break; + + case fitvisiblewidth: + pdc_printf(p->out, "/FitBH %f", dest->top); + break; + + case fitvisibleheight: + pdc_printf(p->out, "/FitBV %f", dest->left); + break; + + default: + break; + } + + pdc_end_array(p->out); +} + +void +pdf__add_nameddest( + PDF *p, + const char *name, + int len, + const char *optlist) +{ + pdc_resopt *resopts = NULL; + pdc_text_format hypertextformat = p->hypertextformat; + pdc_encoding hypertextencoding; + int hypertextcodepage; + pdc_id obj_id = PDC_BAD_ID; + char *name2 = NULL; + pdf_dest *dest; + int inum; + + if (!name) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "name", 0, 0, 0); + + resopts = pdc_parse_optionlist(p->pdc, optlist, + pdf_destination_options, NULL, pdc_true); + + hypertextencoding = + pdf_get_hypertextencoding_opt(p, resopts, &hypertextcodepage, pdc_true); + + if (pdc_get_optvalues("hypertextformat", resopts, &inum, NULL)) + { + hypertextformat = (pdc_text_format) inum; + pdf_check_hypertextformat(p, hypertextformat); + } + + pdc_cleanup_optionlist(p->pdc, resopts); + + /* create hypertext string */ + name2 = pdf_convert_hypertext(p, name, len, hypertextformat, + hypertextencoding, hypertextcodepage, &len, + pdc_true, pdc_true); + if (name2 == NULL || len == 0) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "name", 0, 0, 0); + + /* parsing option list */ + dest = pdf_parse_destination_optlist(p, optlist, 0, pdf_nameddest); + + /* interrupt the content stream if we are on a page */ + if (PDF_GET_STATE(p) == pdf_state_page) + pdf_end_contents_section(p); + + obj_id = pdc_begin_obj(p->out, PDC_NEW_ID); /* Dest object */ + pdc_begin_dict(p->out); /* Destination dict */ + + pdc_puts(p->out, "/D"); + pdf_write_destination(p, dest); + + pdc_end_dict(p->out); /* Destination dict */ + pdc_end_obj(p->out); /* Dest object */ + + /* continue the contents stream */ + if (PDF_GET_STATE(p) == pdf_state_page) + pdf_begin_contents_section(p); + + pdf_cleanup_destination(p, dest); + + /* insert name in tree */ + pdf_insert_name(p, name2, names_dests, obj_id); +} + + +/* -------------------------- bookmarks -------------------------- */ + +static const pdc_defopt pdf_create_bookmark_options[] = +{ + {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDF_MAX_NAMESTRING, NULL}, + + {"hypertextformat", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, pdf_textformat_keylist}, + + {"textcolor", pdc_stringlist, PDC_OPT_NONE, 2, 5, + 0.0, PDF_MAX_NAMESTRING, NULL}, + + {"fontstyle", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, pdf_fontstyle_pdfkeylist}, + + {"parent", pdc_bookmarkhandle, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"index", pdc_integerlist, PDC_OPT_NONE, 1, 1, + -1, PDC_INT_MAX, NULL}, + + {"open", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"destination", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_INT_MAX, NULL}, + + {"destname", pdc_stringlist, PDC_OPT_IGNOREIF1, 1, 1, + 0.0, PDC_INT_MAX, NULL}, + + {"action", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_INT_MAX, NULL}, + + PDC_OPT_TERMINATE +}; + +struct pdf_outline_s { + pdc_id obj_id; /* id of this outline object */ + char *text; /* bookmark text */ + int count; /* number of open sub-entries */ + pdc_bool open; /* whether or not to display children */ + pdc_scalar textcolor[3]; /* rgb color of bookmark text */ + fnt_fontstyle fontstyle; /* font style of bookmark text */ + char *action; /* action optlist */ + pdf_dest *dest; /* outline destination */ + + /* these members control automatic ordering of bookmarks. + */ + pdc_bool in_order; /* this book mark is "in order" */ + pdc_id page_id; /* id of page where this bookmark */ + /* was defined */ + + /* the members below are indices into the p->outlines[] array. + */ + int prev; /* previous entry at this level */ + int next; /* next entry at this level */ + int parent; /* ancestor's index */ + int first; /* first sub-entry */ + int last; /* last sub-entry */ +}; + +static void +pdf_init_outline(PDF *p, pdf_outline *outline) +{ + (void) p; + + outline->obj_id = PDC_BAD_ID; + outline->text = NULL; + outline->count = 0; + outline->open = pdc_false; + outline->textcolor[0] = 0.0; + outline->textcolor[1] = 0.0; + outline->textcolor[2] = 0.0; + outline->fontstyle = fnt_Normal; + outline->action = NULL; + outline->dest = NULL; + outline->in_order = pdc_false; + outline->page_id = PDC_BAD_ID; + outline->prev = 0; + outline->next = 0; + outline->parent = 0; + outline->first = 0; + outline->last = 0; +} + +/* We can't work with pointers in the outline objects because + * the complete outline block may be reallocated. Therefore we use + * this simple mechanism for achieving indirection. + */ +#define COUNT(jndex) (p->outlines[jndex].count) +#define OPEN(jndex) (p->outlines[jndex].open) +#define IN_ORDER(jndex) (p->outlines[jndex].in_order) +#define PAGE_ID(jndex) (p->outlines[jndex].page_id) +#define LAST(jndex) (p->outlines[jndex].last) +#define PARENT(jndex) (p->outlines[jndex].parent) +#define FIRST(jndex) (p->outlines[jndex].first) +#define OBJ_ID(jndex) (p->outlines[jndex].obj_id) +#define PREV(jndex) (p->outlines[jndex].prev) +#define NEXT(jndex) (p->outlines[jndex].next) + +static int +search_forward(PDF *p, int start_page, int start_index) +{ + int idx; + + for (idx = start_index; idx != 0; idx = NEXT(idx)) + { + if (IN_ORDER(idx)) + return pdf_search_page_fwd(p, start_page, PAGE_ID(idx)); + } + + return PDC_INT_MAX; +} + +static int +search_backward(PDF *p, int start_page, int start_index) +{ + int idx; + + for (idx = start_index; idx != 0; idx = PREV(idx)) + { + if (IN_ORDER(idx)) + { + int pg = pdf_search_page_bwd(p, start_page, PAGE_ID(idx)); + + return (pg == -1) ? PDC_INT_MAX : pg; + } + } + + return -1; +} + +static int +pdf_insert_bookmark( + PDF *p, + const char *hypertext, + pdf_outline *outline, + int jndex) +{ + static const char fn[] = "pdf_insert_bookmark"; + pdf_outline *root, *self; + int parent; + int self_idx; + int pageno = pdf_current_page(p); + + /* allocation */ + if (p->outline_count == 0) + { + p->outline_capacity = OUTLINE_CHUNKSIZE; + p->outlines = (pdf_outline *) pdc_calloc(p->pdc, + sizeof(pdf_outline) * p->outline_capacity, fn); + + /* populate the root outline object */ + root = &p->outlines[0]; + pdf_init_outline(p, root); + root->obj_id = pdc_alloc_id(p->out); + root->open = pdc_true; + + /* set the open mode show bookmarks if we have at least one, + * and the client didn't already set his own open mode. + */ + pdf_fix_openmode(p); + } + else if (p->outline_count + 1 >= p->outline_capacity) + { + p->outline_capacity *= 2; + p->outlines = (pdf_outline *) pdc_realloc(p->pdc, p->outlines, + sizeof(pdf_outline) * p->outline_capacity, fn); + } + + /* copy */ + self_idx = ++p->outline_count; + self = &p->outlines[self_idx]; + memcpy(self, outline, sizeof(pdf_outline)); + + self->obj_id = pdc_alloc_id(p->out); + self->text = (char *) hypertext; + self->page_id = pdf_get_page_id(p, 0); + parent = self->parent; + + /* default destination */ + if (self->action == NULL && self->dest == NULL) + self->dest = pdf_init_destination(p); + + /* no destination */ + if (self->dest != NULL && + self->dest->name != NULL && !strlen(self->dest->name)) + { + pdf_cleanup_destination(p, self->dest); + self->dest = NULL; + } + + /* current page */ + if (self->dest) + { + /* this ugly code is for compatibility with the + ** obsolete "bookmarkdest" parameter. + */ + if (self->dest->pgnum == 0) + self->dest->pgnum = pdf_current_page(p); + + if (self->dest->pgnum == 0) + { + self->dest->pgnum = 1; + } + else if (self->dest->page == PDC_BAD_ID) + { + self->dest->page = pdf_get_page_id(p, self->dest->pgnum); + } + } + + /* special case: empty list. + */ + if (FIRST(parent) == 0) + { + if (jndex > 0) + pdc_error(p->pdc, PDC_E_OPT_ILLINTEGER, "index", + pdc_errprintf(p->pdc, "%d", jndex), 0, 0); + + FIRST(parent) = LAST(parent) = self_idx; + self->in_order = pdc_true; + } + else switch (jndex) + { + case -2: /* insert "in order" */ + { + /* the "natural" case: append to the end if appropriate. + */ + if (pageno >= search_backward(p, -1, LAST(parent))) + { + self->prev = LAST(parent); + NEXT(LAST(parent)) = self_idx; + LAST(parent) = self_idx; + } + else + { + int idx; + int curr_pg = 1; + int next_pg; + + for (idx = FIRST(parent); idx != 0; idx = NEXT(idx)) + { + if (!IN_ORDER(idx)) + continue; + + next_pg = pdf_search_page_fwd(p, curr_pg, PAGE_ID(idx)); + + /* TODO: understand why this can happen. + */ + if (next_pg < 1) + { + idx = 0; + break; + } + + if (next_pg > pageno) + { + self->next = idx; + self->prev = PREV(idx); + PREV(idx) = self_idx; + + if (self->prev == 0) + FIRST(parent) = self_idx; + else + NEXT(self->prev) = self_idx; + + break; + } + + curr_pg = next_pg; + } + + /* if there are no "in order" bookmarks yet, + ** we simply append this one to the end. + */ + if (idx == 0) + { + self->prev = LAST(parent); + NEXT(LAST(parent)) = self_idx; + LAST(parent) = self_idx; + } + } + + self->in_order = pdc_true; + break; + } + + case -1: /* append to the end */ + { + self->prev = LAST(parent); + NEXT(LAST(parent)) = self_idx; + LAST(parent) = self_idx; + + self->in_order = + (pageno >= search_backward(p, pageno, self->prev)); + break; + } + + case 0: /* insert at the beginning */ + { + self->next = FIRST(parent); + PREV(FIRST(parent)) = self_idx; + FIRST(parent) = self_idx; + + self->in_order = + (pageno <= search_forward(p, pageno, self->next)); + break; + } + + default: /* insert before [1..LAST] */ + { + int i; + int target = FIRST(parent); + + for (i = 0; i < jndex; ++i) + { + if (target == LAST(parent)) + pdc_error(p->pdc, PDC_E_OPT_ILLINTEGER, "index", + pdc_errprintf(p->pdc, "%d", jndex), 0, 0); + + target = NEXT(target); + } + + self->next = target; + self->prev = PREV(target); + NEXT(self->prev) = PREV(self->next) = self_idx; + + self->in_order = + ((pageno >= search_backward(p, pageno, self->prev)) && + (pageno <= search_forward(p, pageno, self->next))); + break; + } + } /* else switch */ + + /* increase the number of open sub-entries for all relevant ancestors */ + do { + COUNT(parent)++; + } while (OPEN(parent) && (parent = PARENT(parent)) != 0); + + return (self_idx); /* caller may use this as handle */ +} + +int +pdf__create_bookmark(PDF *p, const char *text, int len, const char *optlist) +{ + pdc_resopt *resopts = NULL; + pdc_clientdata data; + pdf_outline self; + pdf_dest *dest = NULL; + pdc_text_format hypertextformat; + pdc_encoding hypertextencoding; + pdf_coloropt textcolor; + char *hypertext = NULL; + const char *keyword = NULL; + char **strlist = NULL; + int hypertextcodepage; + int ns, inum, outlen, retval = 0; + int jndex = -2; + + /* Initialize */ + pdf_init_outline(p, &self); + hypertextformat = p->hypertextformat; + hypertextencoding = p->hypertextencoding; + hypertextcodepage = p->hypertextcodepage; + + /* Parsing option list */ + if (optlist && strlen(optlist)) + { + pdf_set_clientdata(p, &data); + resopts = pdc_parse_optionlist(p->pdc, optlist, + pdf_create_bookmark_options, &data, pdc_true); + + hypertextencoding = + pdf_get_hypertextencoding_opt(p, resopts, &hypertextcodepage, + pdc_true); + + if (pdc_get_optvalues("hypertextformat", resopts, &inum, NULL)) + { + hypertextformat = (pdc_text_format) inum; + pdf_check_hypertextformat(p, hypertextformat); + } + + ns = pdc_get_optvalues("textcolor", resopts, NULL, &strlist); + if (ns) + { + pdf_parse_coloropt(p, "textcolor", strlist, ns, (int) color_rgb, + &textcolor); + self.textcolor[0] = textcolor.value[0]; + self.textcolor[1] = textcolor.value[1]; + self.textcolor[2] = textcolor.value[2]; + } + + if (pdc_get_optvalues("fontstyle", resopts, &inum, NULL)) + self.fontstyle = (fnt_fontstyle) inum; + + pdc_get_optvalues("parent", resopts, &self.parent, NULL); + + pdc_get_optvalues("index", resopts, &jndex, NULL); + + pdc_get_optvalues("open", resopts, &self.open, NULL); + + if (pdc_get_optvalues("destination", resopts, NULL, &strlist)) + { + self.dest = pdf_parse_destination_optlist(p, strlist[0], 0, + pdf_bookmark); + keyword = "destination"; + } + else + { + dest = pdf_get_option_destname(p, resopts, hypertextencoding, + hypertextcodepage); + if (dest) + { + self.dest = dest; + keyword = "destname"; + } + } + + if (pdc_get_optvalues("action", resopts, NULL, &strlist)) + { + if (self.dest) + { + pdf_cleanup_destination(p, self.dest); + self.dest = NULL; + pdc_warning(p->pdc, PDC_E_OPT_IGNORE, keyword, "action", 0, 0); + } + + /* parsing of action list */ + pdf_parse_and_write_actionlist(p, event_bookmark, NULL, + (const char *) strlist[0]); + self.action = + (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + } + + pdc_cleanup_optionlist(p->pdc, resopts); + } + + /* create hypertext string */ + hypertext = pdf_convert_hypertext(p, text, len, hypertextformat, + hypertextencoding, hypertextcodepage, + &outlen, PDC_UTF8_FLAG, pdc_true); + if (hypertext) + retval = pdf_insert_bookmark(p, hypertext, &self, jndex); + + return retval; +} + +static void +pdf_write_outline_dict(PDF *p, int entry) +{ + pdf_outline *outline = &p->outlines[entry]; + pdc_id act_idlist[PDF_MAX_EVENTS]; + + /* write action objects */ + if (outline->action) + pdf_parse_and_write_actionlist(p, event_bookmark, act_idlist, + (const char *) outline->action); + + pdc_begin_obj(p->out, OBJ_ID(entry)); /* outline object */ + pdc_begin_dict(p->out); + + pdc_objref(p->out, "/Parent", OBJ_ID(PARENT(entry))); + + /* outline destination */ + if (outline->dest) + { + pdc_puts(p->out, "/Dest"); + pdf_write_destination(p, outline->dest); + } + + /* write Action entries */ + else if (outline->action) + pdf_write_action_entries(p, event_bookmark, act_idlist); + + pdc_puts(p->out, "/Title"); /* outline text */ + pdf_put_hypertext(p, outline->text); + pdc_puts(p->out, "\n"); + + if (PREV(entry)) + pdc_objref(p->out, "/Prev", OBJ_ID(PREV(entry))); + if (NEXT(entry)) + pdc_objref(p->out, "/Next", OBJ_ID(NEXT(entry))); + + if (FIRST(entry)) { + pdc_objref(p->out, "/First", OBJ_ID(FIRST(entry))); + pdc_objref(p->out, "/Last", OBJ_ID(LAST(entry))); + } + if (COUNT(entry)) { + if (OPEN(entry)) + pdc_printf(p->out, "/Count %d\n", COUNT(entry)); /* open */ + else + pdc_printf(p->out, "/Count %d\n", -COUNT(entry));/* closed */ + } + + /* Color */ + if (outline->textcolor[0] != 0.0 || + outline->textcolor[1] != 0.0 || + outline->textcolor[2] != 0.0) + pdc_printf(p->out, "/C[%f %f %f]\n", outline->textcolor[0], + outline->textcolor[1], + outline->textcolor[2]); + + /* FontStyle */ + if (outline->fontstyle != fnt_Normal) + { + int fontstyle = 0; + if (outline->fontstyle == fnt_Bold) + fontstyle = 2; + if (outline->fontstyle == fnt_Italic) + fontstyle = 1; + if (outline->fontstyle == fnt_BoldItalic) + fontstyle = 3; + pdc_printf(p->out, "/F %d\n", fontstyle); + } + + pdc_end_dict(p->out); + pdc_end_obj(p->out); /* outline object */ +} + +void +pdf_write_outlines(PDF *p) +{ + int i; + + if (p->outline_count == 0) /* no outlines: return */ + return; + + pdc_begin_obj(p->out, p->outlines[0].obj_id); /* root outline object */ + pdc_begin_dict(p->out); + + if (p->outlines[0].count != 0) + pdc_printf(p->out, "/Count %d\n", COUNT(0)); + pdc_objref(p->out, "/First", OBJ_ID(FIRST(0))); + pdc_objref(p->out, "/Last", OBJ_ID(LAST(0))); + + pdc_end_dict(p->out); + pdc_end_obj(p->out); /* root outline object */ + +#define PDF_FLUSH_AFTER_MANY_OUTLINES 1000 /* ca. 50-100 KB */ + for (i = 1; i <= p->outline_count; i++) { + /* reduce memory usage for many outline entries */ + if (i % PDF_FLUSH_AFTER_MANY_OUTLINES == 0) + pdc_flush_stream(p->out); + + pdf_write_outline_dict(p, i); + } +} + +void +pdf_write_outline_root(PDF *p) +{ + if (p->outline_count != 0) + pdc_objref(p->out, "/Outlines", p->outlines[0].obj_id); +} + +void +pdf_init_outlines(PDF *p) +{ + p->outline_count = 0; +} + +/* Free outline entries */ +void +pdf_cleanup_outlines(PDF *p) +{ + int i; + + if (!p->outlines || p->outline_count == 0) + return; + + /* outlines[0] is the outline root object */ + for (i = 0; i <= p->outline_count; i++) + { + if (p->outlines[i].text) + { + pdc_free(p->pdc, p->outlines[i].text); + p->outlines[i].text = NULL; + } + if (p->outlines[i].action) + { + pdc_free(p->pdc, p->outlines[i].action); + p->outlines[i].action = NULL; + } + pdf_cleanup_destination(p, p->outlines[i].dest); + p->outlines[i].dest = NULL; + } + + pdc_free(p->pdc, (void*) p->outlines); + + p->outlines = NULL; +} + + +/*****************************************************************************/ +/** deprecated historical bookmark function **/ +/*****************************************************************************/ + +int +pdf__add_bookmark(PDF *p, const char *text, int len, int parent, int open) +{ + pdf_outline self; + pdf_dest *dest = (pdf_dest *) p->bookmark_dest; + char *hypertext = NULL; + int acthdl; + int retval = 0; + + pdf_init_outline(p, &self); + + if (parent != 0) + pdf_check_handle(p, parent, pdc_bookmarkhandle); + self.parent = parent; + self.open = open; + + /* creating a Launch action - defined via bookmarkdest */ + if (dest->filename) + { + char actoptlist[2048]; + + sprintf(actoptlist, "filename {%s} ", dest->filename); + acthdl = pdf__create_action(p, "Launch", actoptlist); + if (acthdl != -1) + { + if (p->pdc->hastobepos) acthdl++; + sprintf(actoptlist, "activate %d", acthdl); + self.action = pdc_strdup(p->pdc, actoptlist); + } + } + else + { + self.dest = pdf_init_destination(p); + *self.dest = *dest; + if (dest->name) + self.dest->name = pdc_strdup(p->pdc, dest->name); + } + + memcpy(self.textcolor, dest->color, 3 * sizeof(pdc_scalar)); + self.fontstyle = dest->fontstyle; + + hypertext = pdf_convert_hypertext_depr(p, text, len); + if (hypertext) + retval = pdf_insert_bookmark(p, hypertext, &self, -1); + + return retval; +} + +/* -------------------------- document info ------------------------------- */ + +struct pdf_info_s +{ + char *key; /* ASCII string */ + char *value; /* Unicode string */ + pdf_info *next; /* next info entry */ +}; + +void +pdf_cleanup_info(PDF *p) +{ + pdf_info *info, *last; + + if (p->userinfo) + { + for (info = p->userinfo; info != NULL; /* */) + { + last = info; + info = info->next; + + pdc_free(p->pdc, last->key); + pdc_free(p->pdc, last->value); + pdc_free(p->pdc, last); + } + + p->userinfo = NULL; + } +} + +static pdf_info * +pdf_have_infokey(PDF *p, const char *key) +{ + pdf_info *info; + + for (info = p->userinfo; info != NULL; info = info->next) + { + if (strlen(info->key) == strlen(key) && !strcmp(info->key, key)) + return info; + } + + return NULL; +} + +void +pdf_feed_digest_info(PDF *p) +{ + pdf_info *info; + + if (p->userinfo) + { + for (info = p->userinfo; info != NULL; info = info->next) + { + pdc_update_digest(p->out, + (unsigned char *) info->key, strlen(info->key)); + } + } +} + +#define PDF_TRAPPED_TRUE "True" +#define PDF_TRAPPED_FALSE "False" +#define PDF_TRAPPED_UNKNOWN "Unknown" + +/* Set Info dictionary entries */ +void +pdf__set_info(PDF *p, const char *key, const char *value, int len) +{ + static const char fn[] = "pdf__set_info"; + char *key_buf, *val_buf; + pdf_info *oldentry, *newentry; + + if (key == NULL || !*key) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "key", 0, 0, 0); + + if (!strcmp(key, "Producer") || + !strcmp(key, "CreationDate") || + !strcmp(key, "ModDate")) + pdc_error(p->pdc, PDC_E_ILLARG_STRING, "key", key, 0, 0); + + /* converting key */ + key_buf = pdf_convert_name(p, key, 0, 0); + + /* convert text string */ + val_buf = pdf_convert_hypertext_depr(p, value, len); + if (!val_buf) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "value", 0, 0, 0); + + /* special handling required for "Trapped" */ + if (!strcmp(key_buf, "Trapped")) + { + if (strcmp(val_buf, PDF_TRAPPED_TRUE) && + strcmp(val_buf, PDF_TRAPPED_FALSE) && + strcmp(val_buf, PDF_TRAPPED_UNKNOWN)) + { + pdc_free(p->pdc, val_buf); + pdc_free(p->pdc, key_buf); + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); + } + } + + oldentry = pdf_have_infokey(p, key_buf); + if (oldentry != NULL) + { + pdc_free(p->pdc, key_buf); + pdc_free(p->pdc, oldentry->value); + oldentry->value = val_buf; + } + else + { + newentry = (pdf_info *) + pdc_malloc(p->pdc, sizeof(pdf_info), fn); + newentry->key = key_buf; + newentry->value = val_buf; + newentry->next = p->userinfo; + + /* ordering doesn't matter so we insert at the beginning */ + p->userinfo = newentry; + } +} + + +pdc_id +pdf_write_info(PDF *p, pdc_bool moddate) +{ + char time_str[PDC_TIME_SBUF_SIZE]; + char producer[PDF_MAX_PARAMSTRING]; + pdf_info *info; + pdc_id info_id; + + + + const char *product = "PDFlib Lite"; + + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, + "[Full product name: \"%s\"]\n", product); + + info_id = pdc_begin_obj(p->out, PDC_NEW_ID); /* Info object */ + + pdc_begin_dict(p->out); + + /* + * Although it would be syntactically correct, we must not remove + * the space characters after the dictionary keys since this + * would break the PDF properties feature in Windows Explorer. + */ + + if (p->userinfo) + { + for (info = p->userinfo; info != NULL; info = info->next) + { + pdf_put_pdfname(p, info->key); + pdc_puts(p->out, " "); + + if (strcmp(info->key, "Trapped")) + pdf_put_hypertext(p, info->value); + else + pdf_put_pdfname(p, info->value); + + pdc_puts(p->out, "\n"); + } + } + + + pdc_get_timestr(time_str, pdc_false); + + /* creation date and time */ + pdc_puts(p->out, "/CreationDate "); + pdf_put_hypertext(p, time_str); + pdc_puts(p->out, "\n"); + + /* modification date and time */ + if (moddate) + { + pdc_puts(p->out, "/ModDate "); + pdf_put_hypertext(p, time_str); + pdc_puts(p->out, "\n"); + } + + /* + * If you change the /Producer entry your license to use + * PDFlib will be void! + */ + + if (p->pdc->binding) + sprintf(producer, "%s %s (%s/%s)", product, + PDFLIB_VERSIONSTRING, p->pdc->binding, PDF_PLATFORM); + else + sprintf(producer, "%s %s (%s)", product, + PDFLIB_VERSIONSTRING, PDF_PLATFORM); + + pdc_puts(p->out, "/Producer "); + pdf_put_hypertext(p, producer); + pdc_puts(p->out, "\n"); + + pdc_end_dict(p->out); + pdc_end_obj(p->out); /* Info object */ + + + + + return info_id; +} + + diff --git a/src/pdflib/pdflib/p_icc.c b/src/pdflib/pdflib/p_icc.c new file mode 100644 index 0000000..072ea55 --- /dev/null +++ b/src/pdflib/pdflib/p_icc.c @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_icc.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib ICC handling routines + * + * This software is based in part on the work of Graeme W. Gill + * + */ + +#define P_ICC_C + +#include "p_intern.h" +#include "p_color.h" + +#if defined(WIN32) +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + + + diff --git a/src/pdflib/pdflib/p_icc.h b/src/pdflib/pdflib/p_icc.h new file mode 100644 index 0000000..73fedfa --- /dev/null +++ b/src/pdflib/pdflib/p_icc.h @@ -0,0 +1,24 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_icc.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib ICC typedefs, structures, and enums + * + */ + +#ifndef P_ICC_H +#define P_ICC_H + + +#endif /* P_ICC_H */ + diff --git a/src/pdflib/pdflib/p_icc9809.h b/src/pdflib/pdflib/p_icc9809.h new file mode 100644 index 0000000..3ceb0f7 --- /dev/null +++ b/src/pdflib/pdflib/p_icc9809.h @@ -0,0 +1,38 @@ +/* $Id: p_icc9809.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * Header file of ICC (name see note above) for ICClib and PDFlib + * + */ + +/* + * Note: Modified for use by icclib V2.00: + * + * Changed guard bands from ICC_H to ICC9809_H + * + * Replace tag last values 0xFFFFFFFFL with define icMaxTagVal, + * and define this to be -1, for better compiler compatibility. + * + * Add section to use machine specific INR & ORD to define + * the sizes of ic Numbers, if ORD is defined. + * + * Adding colorspaces 'MCH5-8' for Hexachrome and others. (Colorsync ?) + * Added the Positive/Negative and Color/BlackAndWhite Attribute bits + * + * I believe icMeasurementFlare as an enumeration is bogus in + * this file. It is meant to be a u16.16 number. + * + * Add Chromaticity Tag and Type from ICC.1A:1999-04, + * but there is no formal "icc.h" from the ICC that indicates + * what the names should be. + * + * Added Colorsync 2.5 specific VideoCardGamma defines. + * + * Graeme Gill. + */ + +/* Header file guard bands */ +#ifndef P_ICC9809_H +#define P_ICC9809_H + + +#endif /* P_ICC9809_H */ diff --git a/src/pdflib/pdflib/p_icclib.c b/src/pdflib/pdflib/p_icclib.c new file mode 100644 index 0000000..02275da --- /dev/null +++ b/src/pdflib/pdflib/p_icclib.c @@ -0,0 +1,62 @@ +/* $Id: p_icclib.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * ICClib routines for PDFlib, slightly modified from the original ICClib. + * (see below). + * + * $Log: p_icclib.c,v $ + * Revision 1.1 2008/10/17 06:11:49 scuri + * First commit - moving from LuaForge to SourceForge + * + * Revision 1.3 2007/11/06 15:48:55 scuri + * PDF Lite library updated to version "7.0.2". + * + * Revision 1.18.8.3 2007/05/23 21:15:00 york + * fixed #1230: "Performance problems in mulithreaded env with tolower/toupper". + * + * Revision 1.18.8.2 2007/05/23 19:37:21 york + * implemented pdc_isXXX() character classification macros. + * started to replace isXXX() with pdc_isXXX() in all modules. + * + * Revision 1.18.8.1 2007/03/28 12:47:10 kurt + * bug #1180 (Function prefixes missing for zlib assembler and ICC code) fixed + * names of all external functions of ICClib have the prefix "pdf_" now + * + * Revision 1.18 2004/08/05 09:11:27 rjs + * merged 6.0.x to pdflib-x + * + * Revision 1.17.2.1 2004/07/30 16:14:30 kurt + * icc_read: all free statements in the error case removed + * (because of program crash in icc_delete) + * icc_delete: more security checks + * new public function: icc_get_errmsg + * + */ + +/* + * International Color Consortium Format Library (icclib) + * For ICC profile version 3.4 + * + * Author: Graeme W. Gill + * Date: 2002/04/22 + * Version: 2.02 + * + * Copyright 1997 - 2002 Graeme W. Gill + * See Licence.txt file for conditions of use. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <math.h> +#ifdef __sun +#include <unistd.h> +#endif +#if defined(__IBMC__) && defined(_M_IX86) +#include <float.h> +#endif + +/* PDFlib */ +#include "pc_util.h" +#include "pc_core.h" +#include "pc_ctype.h" diff --git a/src/pdflib/pdflib/p_icclib.h b/src/pdflib/pdflib/p_icclib.h new file mode 100644 index 0000000..b300419 --- /dev/null +++ b/src/pdflib/pdflib/p_icclib.h @@ -0,0 +1,38 @@ +/* $Id: p_icclib.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * ICClib Header file icc.h for PDFlib + * + * $Log: p_icclib.h,v $ + * Revision 1.1 2008/10/17 06:11:49 scuri + * First commit - moving from LuaForge to SourceForge + * + * Revision 1.3 2007/11/06 15:48:55 scuri + * PDF Lite library updated to version "7.0.2". + * + * Revision 1.12.8.1 2007/03/28 12:47:10 kurt + * bug #1180 (Function prefixes missing for zlib assembler and ICC code) fixed + * names of all external functions of ICClib have the prefix "pdf_" now + * + * Revision 1.12 2004/08/05 09:11:27 rjs + * merged 6.0.x to pdflib-x + * + * Revision 1.11.2.1 2004/07/30 16:14:31 kurt + * icc_read: all free statements in the error case removed + * (because of program crash in icc_delete) + * icc_delete: more security checks + * new public function: icc_get_errmsg + * + * Revision 1.11 2004/06/14 10:53:19 kurt + * FEATURE defines reduced and renamed + * + * Revision 1.10 2003/03/03 12:46:43 tm + * Changed the licensing comment. + * + */ + +#ifndef P_ICCLIB_H +#define P_ICCLIB_H + + +#endif /* P_ICCLIB_H */ + diff --git a/src/pdflib/pdflib/p_image.c b/src/pdflib/pdflib/p_image.c new file mode 100644 index 0000000..fe95b1c --- /dev/null +++ b/src/pdflib/pdflib/p_image.c @@ -0,0 +1,2253 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2007 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_image.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib image routines + * + */ + +#define P_IMAGE_C + +#include "p_intern.h" +#include "p_color.h" +#include "p_defopt.h" +#include "p_font.h" +#include "p_image.h" +#include "p_layer.h" +#include "p_tagged.h" + +static void +pdf_init_image_struct(PDF *p, pdf_image *image) +{ + (void) p; + + /********** option variables *************/ + image->verbose = p->debug[(int) 'i']; + image->verbose = pdf_get_errorpolicy(p, NULL, image->verbose); + image->bitreverse = pdc_false; + image->bpc = pdc_undef; + image->components = pdc_undef; + image->height_pixel = pdc_undef; + image->ignoremask = pdc_false; + image->ignoreorient = pdc_false; + image->doinline = pdc_false; + image->interpolate = pdc_false; + image->invert = pdc_false; + image->jpegoptimize = pdc_true; + image->passthrough = pdc_undef; + image->K = 0; + image->imagemask = pdc_false; + image->mask = pdc_undef; + image->ri = AutoIntent; + image->page = 1; + image->reference = pdf_ref_direct; + image->width_pixel = pdc_undef; + image->topdown_save = pdc_false; + image->iconname = (char *) NULL; + /*****************************************/ + + image->orientation = 1; + image->transparent = pdc_false; + image->compression = pdf_comp_none; + image->predictor = pred_default; + image->in_use = pdc_false; + image->corrupt = pdc_false; + image->fp = (pdc_file *) NULL; + image->filename = (char *) NULL; + image->params = (char *) NULL; + image->dpi_x = 0; + image->dpi_y = 0; + image->strips = 1; + image->rowsperstrip = 1; + image->colorspace = pdc_undef; + image->dochandle = pdc_undef; /* this means "not a PDI page" */ + image->use_raw = pdc_false; + image->pixelmode = pdc_undef; + image->type = pdf_img_auto; + image->transval[0] = 0; + image->transval[1] = 0; + image->transval[2] = 0; + image->transval[3] = 0; + + + /********* image-type specific stuff *****/ + /* This is ugly, but we must do it here since both the TIFF and JPEG + * modules are affected. + */ + image->info.jpeg.jpegifoffset = 0L; +} + +void +pdf_init_images(PDF *p) +{ + int im; + + p->images_capacity = IMAGES_CHUNKSIZE; + + p->images = (pdf_image *) + pdc_malloc(p->pdc, + sizeof(pdf_image) * p->images_capacity, "pdf_init_images"); + + for (im = 0; im < p->images_capacity; im++) + pdf_init_image_struct(p, &(p->images[im])); +} + +void +pdf_grow_images(PDF *p) +{ + int im; + + p->images = (pdf_image *) pdc_realloc(p->pdc, p->images, + sizeof(pdf_image) * 2 * p->images_capacity, "pdf_grow_images"); + + for (im = p->images_capacity; im < 2 * p->images_capacity; im++) + pdf_init_image_struct(p, &(p->images[im])); + + p->images_capacity *= 2; +} + +void +pdf_cleanup_image(PDF *p, int im) +{ + pdf_image *image = &p->images[im]; + + /* clean up parameter string if necessary */ + if (image->params) + { + pdc_free(p->pdc, image->params); + image->params = NULL; + } + + if (image->filename) + { + pdc_free(p->pdc, image->filename); + image->filename = NULL; + } + + if (image->fp) + { + pdc_fclose(image->fp); + image->fp = NULL; + } + + if (image->iconname) + { + pdc_free(p->pdc, image->iconname); + image->iconname = NULL; + } + + + + /* type-specific cleanups */ + if (image->type == pdf_img_gif) + pdf_cleanup_gif(p, image); + + if (image->type == pdf_img_jpeg) + pdf_cleanup_jpeg(p, image); + + /* free the image slot and prepare for next use */ + pdf_init_image_struct(p, image); +} + +void +pdf_cleanup_images(PDF *p) +{ + int im; + + if (!p->images) + return; + + /* Free images which the caller left open */ + + /* When we think of inter-document survival of images, + ** we MUST NOT FORGET that the current TIFF algorithm + ** depends on contiguous image slots for the image strips! + */ + for (im = 0; im < p->images_capacity; im++) + { + if (p->images[im].in_use) /* found used slot */ + pdf_cleanup_image(p, im); /* free image descriptor */ + } + + pdc_free(p->pdc, p->images); + p->images = NULL; +} + +void +pdf_init_xobjects(PDF *p) +{ + int idx; + + p->xobjects_number = 0; + + if (p->xobjects == (pdf_xobject *) 0) + { + p->xobjects_capacity = XOBJECTS_CHUNKSIZE; + + p->xobjects = (pdf_xobject *) + pdc_malloc(p->pdc, sizeof(pdf_xobject) * p->xobjects_capacity, + "pdf_init_xobjects"); + } + + for (idx = 0; idx < p->xobjects_capacity; idx++) + p->xobjects[idx].flags = 0; +} + +int +pdf_new_xobject(PDF *p, pdf_xobj_type type, pdc_id obj_id) +{ + static const char fn[] = "pdf_new_xobject"; + int i, slot = p->xobjects_number++; + + if (slot == p->xobjects_capacity) + { + p->xobjects = (pdf_xobject *) pdc_realloc(p->pdc, p->xobjects, + sizeof(pdf_xobject) * 2 * p->xobjects_capacity, fn); + + for (i = p->xobjects_capacity; i < 2 * p->xobjects_capacity; i++) + p->xobjects[i].flags = 0; + + p->xobjects_capacity *= 2; + } + + if (obj_id == PDC_NEW_ID) + obj_id = pdc_begin_obj(p->out, PDC_NEW_ID); + + p->xobjects[slot].obj_id = obj_id; + p->xobjects[slot].type = type; + p->xobjects[slot].flags = xobj_flag_used; + + return slot; +} + +pdc_id +pdf_get_xobject(PDF *p, int im) +{ + if (im >= 0 && im < p->images_capacity) + { + pdf_image *img = &p->images[im]; + + if (img->in_use) + return p->xobjects[img->no].obj_id; + } + return PDC_BAD_ID; +} + +void +pdf_write_xobjects(PDF *p) +{ + if (p->xobjects_number > 0) + { + pdc_bool hit = pdc_false; + int i; + + for (i = 0; i < p->xobjects_number; ++i) + { + if (p->xobjects[i].flags & xobj_flag_write) + { + if (!hit) + { + pdc_puts(p->out, "/XObject"); + pdc_begin_dict(p->out); + hit = pdc_true; + } + + pdc_printf(p->out, "/I%d", i); + pdc_objref(p->out, "", p->xobjects[i].obj_id); + p->xobjects[i].flags &= ~xobj_flag_write; + } + } + + if (hit) + pdc_end_dict(p->out); + } +} + +void +pdf_get_page_xobjects(PDF *p, pdf_reslist *rl) +{ + int i; + + for (i = 0; i < p->xobjects_number; i++) { + if (p->xobjects[i].flags & xobj_flag_write) { + p->xobjects[i].flags &= ~xobj_flag_write; + pdf_add_reslist(p, rl, i); + } + } +} + +void +pdf_mark_page_xobject(PDF *p, int n) +{ + p->xobjects[n].flags |= xobj_flag_write; +} + +void +pdf_cleanup_xobjects(PDF *p) +{ + if (p->xobjects) { + pdc_free(p->pdc, p->xobjects); + p->xobjects = NULL; + } +} + + +/* ---------------------------- put image ----------------------------------- */ + +void +pdf_put_inline_image(PDF *p, int im) +{ + static const char *fn = "pdf_put_inline_image"; + pdf_image *image; + pdc_matrix m; + PDF_data_source *src; + int i; + + image = &p->images[im]; + + /* Image object */ + + image->no = -1; + + pdf__save(p); + + pdc_scale_matrix(image->width, image->height, &m); + + pdf_concat_raw(p, &m); + + pdc_puts(p->out, "BI"); + + pdc_printf(p->out, "/W %d", (int) image->width); + pdc_printf(p->out, "/H %d", (int) image->height); + + /* Acrobat 7 and 8 require /BPC even for image masks */ + pdc_printf(p->out, "/BPC %d", image->bpc); + + if (image->imagemask == pdc_true) { + pdc_puts(p->out, "/IM true"); + + } else if (image->colorspace != pdc_undef) { + + switch (p->colorspaces[image->colorspace].type) { + case DeviceGray: + pdc_printf(p->out, "/CS/G"); + break; + + case DeviceRGB: + pdc_printf(p->out, "/CS/RGB"); + break; + + case DeviceCMYK: + pdc_printf(p->out, "/CS/CMYK"); + break; + + default: + pdc_error(p->pdc, PDF_E_INT_BADCS, fn, + pdc_errprintf(p->pdc, "%d", image->colorspace), + pdc_errprintf(p->pdc, "%d", + (int) p->colorspaces[image->colorspace].type), + 0); + break; + } + } + + if (image->compression != pdf_comp_none) { + pdc_printf(p->out, "/F/%s", + pdc_get_keyword(image->compression, pdf_shortfilter_pdfkeylist)); + } + + /* prepare precompressed (raw) image data */ + if (image->use_raw && + (image->params || + image->predictor != pred_default || + image->compression == pdf_comp_ccitt)) { + + pdc_printf(p->out, "/DP[<<"); + + /* write EarlyChange */ + if (image->params) + pdc_puts(p->out, image->params); + + if (image->compression == pdf_comp_ccitt) { + if (image->K != 0) + pdc_printf(p->out, "/K %d", image->K); + } + + if (image->compression == pdf_comp_flate || + image->compression == pdf_comp_lzw) { + if (image->predictor != pred_default) { + pdc_printf(p->out, "/Predictor %d", (int) image->predictor); + pdc_printf(p->out, "/Columns %d", (int) image->width); + if (image->bpc != 8) + pdc_printf(p->out, "/BitsPerComponent %d", image->bpc); + + if (image->components != 1) /* 1 is default */ + pdc_printf(p->out, "/Colors %d", image->components); + } + } + + if (image->compression == pdf_comp_ccitt) { + if ((int) image->width != 1728) /* CCITT default width */ + pdc_printf(p->out, "/Columns %d", (int) image->width); + + /* /Rows is not required */ + } + pdc_puts(p->out, ">>]"); /* DecodeParms dict and array */ + } + + if (image->ri != AutoIntent) { + pdc_printf(p->out, "/Intent/%s", + pdc_get_keyword(image->ri, pdf_renderingintent_pdfkeylist)); + } + + if (image->interpolate) { + pdc_puts(p->out, "/I true"); + } + + if (image->invert) { + pdc_puts(p->out, "/D[1 0"); + for (i = 1; i < image->components; i++) + pdc_puts(p->out, " 1 0"); + pdc_puts(p->out, "]ID\n"); + + } else { + pdc_puts(p->out, " ID\n"); + } + + /* Write the actual image data to the content stream */ + + src = &image->src; + + /* We can't use pdf_copy_stream() here because it automatically + * generates a stream object, which is not correct for inline + * image data. + */ + if (src->init) + src->init(p, src); + + while (src->fill(p, src)) + pdc_write(p->out, src->next_byte, src->bytes_available); + + if (src->terminate) + src->terminate(p, src); + + /* Acrobat requires whitespace between image data and "EI" */ + pdc_puts(p->out, "\nEI\n"); + + pdf__restore(p); + + /* Do the equivalent of PDF_close_image() since the image handle + * cannot be re-used anyway. + */ + pdf_cleanup_image(p, im); +} + +void +pdf_put_image(PDF *p, int im, pdc_bool firststrip, pdc_bool checkcontentstream) +{ + static const char *fn = "pdf_put_image"; + pdc_bool logg3 = pdc_logg_is_enabled(p->pdc, 3, trc_image); + pdc_id length_id; + pdf_image *image; + int i; + pdf_compression compression; + + image = &p->images[im]; + + if (logg3) + pdc_logg(p->pdc, "\t\t\tput image %d to PDF file ...\n", im); + + /* Images may also be written to the output before the first page */ + if (checkcontentstream && PDF_GET_STATE(p) == pdf_state_page) + pdf_end_contents_section(p); + + + + pdc_logg_cond(p->pdc, 2, trc_image, + "\tpdf_put_image:\n" + "\t\t\tim = %d\n" + "\t\t\timage->colorspace = %d\n", + im, + image->colorspace); + + if (image->colorspace != pdc_undef) + pdc_logg_cond(p->pdc, 2, trc_image, + "\t\t\tcolor space type = %d\n", + (int) p->colorspaces[image->colorspace].type); + + /* Image object */ + + image->no = pdf_new_xobject(p, image_xobject, PDC_NEW_ID); + + pdc_begin_dict(p->out); /* XObject */ + + pdc_puts(p->out, "/Subtype/Image\n"); + + pdc_printf(p->out, "/Width %d\n", (int) image->width); + pdc_printf(p->out, "/Height %d\n", (int) fabs(image->height)); + + /* + * Transparency handling + */ + + /* Masking by color: single transparent color value */ + if (image->transparent && image->colorspace != pdc_undef) { + pdf_colorspace *cs = &p->colorspaces[image->colorspace]; + + switch (cs->type) { + case Indexed: + case DeviceGray: + pdc_printf(p->out,"/Mask[%d %d]\n", + (int) image->transval[0], (int) image->transval[0]); + break; + + + case DeviceRGB: + pdc_printf(p->out,"/Mask[%d %d %d %d %d %d]\n", + (int) image->transval[0], (int) image->transval[0], + (int) image->transval[1], (int) image->transval[1], + (int) image->transval[2], (int) image->transval[2]); + break; + + case DeviceCMYK: + pdc_printf(p->out,"/Mask[%d %d %d %d %d %d %d %d]\n", + (int) image->transval[0], (int) image->transval[0], + (int) image->transval[1], (int) image->transval[1], + (int) image->transval[2], (int) image->transval[2], + (int) image->transval[3], (int) image->transval[3]); + break; + + default: + pdc_error(p->pdc, PDF_E_INT_BADCS, fn, + pdc_errprintf(p->pdc, "%d", image->colorspace), + pdc_errprintf(p->pdc, "%d", + (int) p->colorspaces[image->colorspace].type), + 0); + } + + /* Masking by position: separate bitmap mask */ + } else if (image->mask != pdc_undef && p->images[image->mask].bpc > 1) { + pdc_objref(p->out, "/SMask", + p->xobjects[p->images[image->mask].no].obj_id); + + } else if (image->mask != pdc_undef) { + pdc_objref(p->out, "/Mask", + p->xobjects[p->images[image->mask].no].obj_id); + } + + /* + * /BitsPerComponent is optional for image masks according to the + * PDF reference, but some viewers require it nevertheless. + * We must therefore always write it. + */ + if (image->type != pdf_img_jpeg2000) + pdc_printf(p->out, "/BitsPerComponent %d\n", image->bpc); + + if (image->imagemask) { + pdc_puts(p->out, "/ImageMask true\n"); + if (image->type == pdf_img_jpeg2000) + pdc_puts(p->out, "/SMaskInData 1\n"); + + } else if (image->colorspace != pdc_undef) { + + switch (p->colorspaces[image->colorspace].type) { + case DeviceGray: + break; + + case DeviceRGB: + break; + + case DeviceCMYK: + break; + + case Indexed: + break; + + + + default: + pdc_error(p->pdc, PDF_E_INT_BADCS, fn, + pdc_errprintf(p->pdc, "%d", image->colorspace), + pdc_errprintf(p->pdc, "%d", + (int) p->colorspaces[image->colorspace].type), + 0); + } + + pdc_puts(p->out, "/ColorSpace"); + pdf_write_colorspace(p, image->colorspace, pdc_false); + pdc_puts(p->out, "\n"); + } + + if (image->invert) { + pdc_puts(p->out, "/Decode[1 0"); + for (i = 1; i < image->components; i++) + pdc_puts(p->out, " 1 0"); + pdc_end_array(p->out); + } + + if (image->ri != AutoIntent) { + pdc_printf(p->out, "/Intent/%s\n", + pdc_get_keyword(image->ri, pdf_renderingintent_pdfkeylist)); + } + + if (image->interpolate) { + pdc_puts(p->out, "/Interpolate true\n"); + } + + /* special case: referenced image data instead of direct data */ + if (image->reference != pdf_ref_direct) { + + if (image->compression != pdf_comp_none) { + pdc_printf(p->out, "/FFilter[/%s]\n", + pdc_get_keyword(image->compression, pdf_filter_pdfkeylist)); + } + + if (image->compression == pdf_comp_ccitt) { + pdc_puts(p->out, "/FDecodeParms[<<"); + + if ((int) image->width != 1728) /* CCITT default width */ + pdc_printf(p->out, "/Columns %d", (int) image->width); + + /* + pdc_printf(p->out, "/Rows %d", (int) fabs(image->height)); + */ + + if (image->K != 0) + pdc_printf(p->out, "/K %d", image->K); + + pdc_puts(p->out, ">>]\n"); + + } + + if (image->reference == pdf_ref_file) { + + /* LATER: make image file name platform-neutral: + * Change : to / on the Mac + * Change \ to / on Windows + */ + pdc_puts(p->out, "/F"); + pdc_put_pdfstring(p->out, image->filename, 0); + pdc_puts(p->out, "/Length 0"); + + } else if (image->reference == pdf_ref_url) { + + pdc_puts(p->out, "/F<</FS/URL/F"); + pdc_put_pdfstring(p->out, image->filename, 0); + pdc_puts(p->out, ">>/Length 0"); + } + + pdc_end_dict(p->out); /* XObject */ + + /* We must avoid pdc_begin/end_pdfstream() here in order to + * generate a really empty stream. + */ + pdc_puts(p->out, "stream\n"); /* dummy image stream */ + pdc_puts(p->out, "endstream\n"); + + pdc_end_obj(p->out); /* XObject */ + + if (PDF_GET_STATE(p) == pdf_state_page) + pdf_begin_contents_section(p); + + return; + } + + compression = image->compression; + + /* + * Now the (more common) handling of actual image + * data to be included in the PDF output. + */ + + /* force compression if not a recognized precompressed image format */ + if ((!image->use_raw || compression == pdf_comp_none) && + pdc_get_compresslevel(p->out)) + compression = pdf_comp_flate; + + if (compression != pdf_comp_none) + pdc_printf(p->out, "/Filter/%s\n", + pdc_get_keyword(compression, pdf_filter_pdfkeylist)); + + /* prepare precompressed (raw) image data; avoid empty DecodeParms */ + if (image->use_raw && + (image->params || + image->predictor != pred_default || + compression == pdf_comp_ccitt)) { + + pdc_printf(p->out, "/DecodeParms<<"); + + /* write EarlyChange */ + if (image->params) + pdc_puts(p->out, image->params); + + if (compression == pdf_comp_ccitt) { + if (image->K != 0) + pdc_printf(p->out, "/K %d", image->K); + } + + if (compression == pdf_comp_flate || compression == pdf_comp_lzw) { + if (image->predictor != pred_default) { + pdc_printf(p->out, "/Predictor %d", (int) image->predictor); + pdc_printf(p->out, "/Columns %d", (int) image->width); + if (image->bpc != 8) + pdc_printf(p->out, "/BitsPerComponent %d", image->bpc); + + if (image->components != 1) /* 1 is default */ + pdc_printf(p->out, "/Colors %d", image->components); + } + } + + if (compression == pdf_comp_ccitt) { + if ((int) image->width != 1728) /* CCITT default width */ + pdc_printf(p->out, "/Columns %d", (int) image->width); + + /* /Rows is not required */ + } + + pdc_puts(p->out, ">>\n"); /* DecodeParms dict */ + } + + + + + /* Write the actual image data */ + length_id = pdc_alloc_id(p->out); + + pdc_objref(p->out, "/Length", length_id); + pdc_end_dict(p->out); /* XObject */ + + /* image data */ + + /* + * We must check "image->compression" here since this describes the + * actual status of the input data, as opposed to "compression" + * which describes the desired status of the output data. + */ + + pdf_copy_stream(p, &image->src, + !image->use_raw || image->compression == pdf_comp_none); + + pdc_end_obj(p->out); /* XObject */ + + pdc_put_pdfstreamlength(p->out, length_id); + + if (p->flush & pdc_flush_content) + pdc_flush_stream(p->out); + + /* + * Write colormap information for indexed color spaces + */ + if (firststrip && image->colorspace != pdc_undef && + p->colorspaces[image->colorspace].type == Indexed) { + pdf_write_colormap(p, image->colorspace); + } + + if (checkcontentstream && PDF_GET_STATE(p) == pdf_state_page) + pdf_begin_contents_section(p); + + if (p->flush & pdc_flush_content) + pdc_flush_stream(p->out); +} + + +/* ---------------------------- fit image ----------------------------------- */ + +void +pdf__fit_image(PDF *p, int im, pdc_scalar x, pdc_scalar y, const char *optlist) +{ + pdf_image *image; + int legal_states; + + pdf_check_handle(p, im, pdc_imagehandle); + + image = &p->images[im]; + + if (PDF_GET_STATE(p) == pdf_state_glyph && !pdf_get_t3colorized(p) && + image->imagemask == pdc_false) + legal_states = pdf_state_page | pdf_state_pattern | pdf_state_template; + else + legal_states = pdf_state_content; + PDF_CHECK_STATE(p, legal_states); + + if (PDF_GET_STATE(p) == pdf_state_template && im == p->templ) + pdc_error(p->pdc, PDF_E_TEMPLATE_SELF, + pdc_errprintf(p->pdc, "%d", im), 0, 0, 0); + + pdc_check_number(p->pdc, "x", x); + pdc_check_number(p->pdc, "y", y); + + pdf_place_xobject(p, im, x, y, optlist); +} + +void +pdf_init_xobject_options(PDF *p, pdf_xobject_options *xo) +{ + xo->adjustpage = pdc_false; + xo->blind = pdc_false; + xo->filename = NULL; + xo->flags = 0; + xo->imagewarning = p->debug[(int) 'i']; + xo->ignoreorientation = pdc_false; + xo->im = -1; + xo->mask = 0; + xo->dpi[0] = 0; + xo->dpi[1] = 0; + xo->page = 1; + xo->scale[0] = 1; + xo->scale[1] = 1; +} + +void +pdf_get_xobject_options(PDF *p, pdf_xobject_options *xo, pdc_resopt *resopts) +{ + int inum; + + (void) p; + + if (!(xo->flags & is_block)) + { + pdc_get_optvalues("adjustpage", resopts, &xo->adjustpage, NULL); + + pdc_get_optvalues("blind", resopts, &xo->blind, NULL); + } + + if (xo->flags & is_image) + { + if (pdc_get_optvalues("ignoreorientation", resopts, + &xo->ignoreorientation, NULL)) + xo->mask |= (1L << xo_ignoreorientation); + + + inum = pdc_get_optvalues("dpi", resopts, xo->dpi, NULL); + if (inum) + { + if (inum == 1) + xo->dpi[1] = xo->dpi[0]; + xo->mask |= (1L << xo_dpi); + } + } + + if (xo->flags & is_block) + { + if (pdc_get_optvalues("imagewarning", resopts, &xo->imagewarning, NULL)) + xo->mask |= (1L << xo_imagewarning); + } + + inum = pdc_get_optvalues("scale", resopts, xo->scale, NULL); + if (inum) + { + if (inum == 1) + xo->scale[1] = xo->scale[0]; + xo->mask |= (1L << xo_scale); + } +} + +/* definitions of fit xobject options */ +static const pdc_defopt pdf_fit_xobject_options[] = +{ + PDF_XOBJECT_OPTIONS1 + PDF_XOBJECT_OPTIONS2 + PDF_XOBJECT_OPTIONS3 + PDF_FIT_OPTIONS1 + PDF_FIT_OPTIONS2 + PDC_OPT_TERMINATE +}; + +pdc_resopt * +pdf_parse_fitxobject_optlist(PDF *p, int im, pdf_xobject_options *xo, + pdf_fit_options *fit, const char *optlist) +{ + pdc_resopt *resopts = NULL; + pdf_image *image = &p->images[im]; + + /* initialize */ + pdf_init_xobject_options(p, xo); + xo->im = im; + if (p->xobjects[image->no].type == image_xobject) + { + xo->flags |= is_image; + xo->dpi[0] = dpi_internal; + xo->dpi[1] = dpi_internal; + xo->ignoreorientation = image->ignoreorient; + } + pdf_init_fit_options(p, pdc_false, fit); + fit->flags |= is_image; + + /* parsing option list */ + if (optlist && strlen(optlist)) + { + pdc_clientdata data; + + pdf_set_clientdata(p, &data); + resopts = pdc_parse_optionlist(p->pdc, optlist, + pdf_fit_xobject_options, &data, pdc_true); + + pdf_get_xobject_options(p, xo, resopts); + pdf_get_fit_options(p, pdc_false, fit, resopts); + } + + return resopts; +} + +void +pdf_place_xobject(PDF *p, int im, pdc_scalar x, pdc_scalar y, + const char *optlist) +{ + pdf_xobject_options xo; + pdf_fit_options fit; + + /* initialize */ + pdf_parse_fitxobject_optlist(p, im, &xo, &fit, optlist); + fit.refpoint[0] = x; + fit.refpoint[1] = y; + + /* put out xobject */ + if (!xo.blind) + { + pdf_end_text(p); + pdf_begin_contents_section(p); + + + + pdf__save(p); + } + + pdf_fit_xobject_internal(p, &xo, &fit, NULL); + + if (!xo.blind) + pdf__restore(p); +} + +void +pdf_fit_xobject_internal(PDF *p, pdf_xobject_options *xo, pdf_fit_options *fit, + pdc_matrix *immatrix) +{ + pdc_bool logg3 = pdc_logg_is_enabled(p->pdc, 3, trc_image); + pdf_image *image = &p->images[xo->im]; + pdf_xobject_options xo_save; + pdc_rectangle matchrect; + pdf_fit_options fit_save; + pdc_matrix m, mm, sm, ctm_save; + pdc_vector tmpscale, elemscale, fitscale, purescale; + pdc_vector elemsize, mirror, shift, relpos; + pdc_vector polyline[5]; + pdc_box fitbox, clipbox, elembox; + pdc_scalar x, y, ss; + pdc_scalar rowsize = 1, lastratio = 1; + pdc_scalar dpi_x, dpi_y, tx = 0, ty = 0, boxwidth, boxheight; + pdc_bool hasfitbox, kclip = pdc_false, kcliptiff = pdc_false; + int indangle, indmirror; + int is, ip, islast; + int imageno; + + /* initialize */ + tmpscale.x = 1; + tmpscale.y = 1; + if (image->mask != pdc_undef) + { + ctm_save = p->curr_ppt->gstate[p->curr_ppt->sl].ctm; + xo_save = *xo; + fit_save = *fit; + } + else + { + pdc_identity_matrix(&ctm_save); + } + + /* box size */ + boxwidth = fit->boxsize[0]; + boxheight = fit->boxsize[1]; + hasfitbox = boxwidth > PDC_FLOAT_PREC && boxheight > PDC_FLOAT_PREC; + + /* element size */ + elemsize.x = fabs(image->width); + elemsize.y = fabs(image->height); + + if (logg3) + pdc_logg(p->pdc, + "\t\t\tfitbox size: width=%g, height=%g\n" + "\t\t\telement size: width=%g, height=%g\n", + boxwidth, boxheight, elemsize.x, elemsize.y); + + /* clipping */ + if (!kclip) + { + kclip = pdf_get_mbox_clipping(p, fit->matchbox, elemsize.x, elemsize.y, + &clipbox); + } + + if (logg3 && kclip) + pdc_logg(p->pdc, + "\t\t\tclip box: llx=%g, lly=%g, urx=%g, ury=%g\n", + clipbox.ll.x, clipbox.ll.y, clipbox.ur.x, clipbox.ur.y); + + /* TIFF image orientation */ + if (image->orientation != 1 && !xo->ignoreorientation) + { + /* Tag Orientation = 1, 2, 3, 4, 5, 6, 7, 8 */ + const int addangle[8] = {0, 0, 180, 180, 90, 270, 270, 90}; + const int rowmirror[8] = {1, -1, 1, -1, -1, 1, -1, 1}; + + if (logg3) + pdc_logg(p->pdc, "\t\t\torientation tag: %d\n", image->orientation); + + is = image->orientation - 1; + + fit->orientate += addangle[is]; + if (fit->orientate >= 360) + fit->orientate -= 360; + tmpscale.x = rowmirror[is]; + + if (kclip) + { + switch (addangle[is]) + { + default: + elembox = clipbox; + break; + + case 90: + elembox.ll.x = clipbox.ll.y; + elembox.ll.y = elemsize.x - clipbox.ur.x; + elembox.ur.x = clipbox.ur.y; + elembox.ur.y = elemsize.x - clipbox.ll.x; + break; + + case 180: + elembox.ll.x = elemsize.x - clipbox.ur.x; + elembox.ll.y = elemsize.y - clipbox.ur.y; + elembox.ur.x = elemsize.x - clipbox.ll.x; + elembox.ur.y = elemsize.y - clipbox.ll.y; + break; + + case 270: + elembox.ll.x = elemsize.y - clipbox.ur.y; + elembox.ll.y = clipbox.ll.x; + elembox.ur.x = elemsize.y - clipbox.ll.y; + elembox.ur.y = clipbox.ur.x; + break; + } + clipbox = elembox; + + if (tmpscale.x == -1) + { + clipbox.ll.x = elemsize.x - elembox.ur.x; + clipbox.ur.x = elemsize.x - elembox.ll.x; + } + } + } + + /* Compensate inverted direction handling in TIFFReadRGBAImageOriented() */ + if (!image->use_raw && image->pixelmode == pdc_true) + { + tmpscale.y = -1; + elembox = clipbox; + clipbox.ll.y = elemsize.y - elembox.ur.y; + clipbox.ur.y = elemsize.y - elembox.ll.y; + } + + if (logg3 && kclip) + pdc_logg(p->pdc, + "\t\t\tclip box: llx=%g, lly=%g, urx=%g, ury=%g " + "(corrected)\n", + clipbox.ll.x, clipbox.ll.y, clipbox.ur.x, clipbox.ur.y); + + /* image scale */ + elemscale.x = tmpscale.x * xo->scale[0]; + elemscale.y = tmpscale.y * xo->scale[1]; + + if (logg3) + pdc_logg(p->pdc, + "\t\t\telement scaling: sx=%g, sy=%g " + "(user, correction mirroring)\n", + elemscale.x, elemscale.y); + + /* element size */ + elemsize.x = fabs(clipbox.ur.x - clipbox.ll.x); + elemsize.y = fabs(clipbox.ur.y - clipbox.ll.y); + + /* calculation of image scale and size */ + if (xo->flags & is_image) + { + tmpscale.x = 1.0; + tmpscale.y = 1.0; + if (xo->dpi[0] == dpi_internal) + { + dpi_x = image->dpi_x; + dpi_y = image->dpi_y; + if (dpi_x > 0 && dpi_y > 0) + { + tmpscale.x = 72.0 / dpi_x; + tmpscale.y = 72.0 / dpi_y; + } + else if (dpi_x < 0 && dpi_y < 0) + { + tmpscale.y = dpi_y / dpi_x; + } + } + else if (xo->dpi[0] > 0) + { + tmpscale.x = 72.0 / xo->dpi[0]; + tmpscale.y = 72.0 / xo->dpi[1]; + } + + elemscale.x *= tmpscale.x; + elemscale.y *= tmpscale.y; + rowsize = elemscale.y * image->rowsperstrip; + + if (logg3) + pdc_logg(p->pdc, + "\t\t\telement scaling: sx=%g, sy=%g " + "(relating to 72dpi)\n", + tmpscale.x, tmpscale.y); + } + + /* pure scaling without mirroring */ + purescale.x = fabs(elemscale.x); + purescale.y = fabs(elemscale.y); + + /* element size */ + elemsize.x *= purescale.x; + elemsize.y *= purescale.y; + + if (logg3) + pdc_logg(p->pdc, + "\t\t\telement size: width=%g, height=%g (scaled)\n", + elemsize.x, elemsize.y); + + if (xo->flags & is_image) + { + elemscale.x *= image->width; + elemscale.y *= image->height; + lastratio = (elemscale.y / rowsize) - (image->strips - 1); + } + + /* mirroring */ + indmirror = 0; + if (elemscale.x < 0 && elemscale.y < 0) + indmirror = 2; + else if (elemscale.x < 0) + indmirror = 1; + else if (elemscale.y < 0) + indmirror = 3; + + /* orientation */ + indangle = fit->orientate / 90; + if (indangle % 2) + { + ss = elemsize.x; + elemsize.x = elemsize.y; + elemsize.y = ss; + } + + /* box for fitting */ + fitbox.ll.x = 0; + fitbox.ll.y = 0; + fitbox.ur.x = boxwidth; + fitbox.ur.y = boxheight; + + /* relative position */ + relpos.x = fit->position[0] / 100.0; + relpos.y = fit->position[1] / 100.0; + + /* calculate image box */ + if (fit->fitmethod == pdc_tauto) + fit->fitmethod = pdc_meet; + pdc_place_element(fit->fitmethod, 1.0, &fitbox, &relpos, + &elemsize, &relpos, &elembox, &fitscale); + + if (logg3) + pdc_logg(p->pdc, + "\t\t\telement scaling: sx=%g, sy=%g " + "(relating to fitbox)\n", + fitscale.x, fitscale.y); + + /* reference point */ + x = fit->refpoint[0]; + y = fit->refpoint[1]; + + + /* adjust page size */ + if (!xo->blind && xo->adjustpage && PDF_GET_STATE(p) == pdf_state_page) + { + pdc_scalar urx, ury, width, height, theight; + + urx = 2 * x + elembox.ur.x; + ury = 2 * y + elembox.ur.y; + pdc_transform_point(&p->curr_ppt->gstate[p->curr_ppt->sl].ctm, + urx, ury, &width, &theight); + height = (p->ydirection > 0) ? theight + : pdf_get_pageheight(p) - p->ydirection * theight; + + if (height < p->ydirection * theight / 2.0) + pdc_error(p->pdc, PDF_E_IMAGE_NOADJUST, 0, 0, 0, 0); + + width = fabs(width); + height = fabs(height); + + if ((width < PDF_ACRO_MINPAGE || width > PDF_ACRO_MAXPAGE || + height < PDF_ACRO_MINPAGE || height > PDF_ACRO_MAXPAGE)) + pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO, 0, 0, 0, 0); + + pdf_set_pagebox(p, pdf_mediabox, 0, 0, width, height); + pdf_set_pagebox(p, pdf_artbox, 0, 0, 0, 0); + pdf_set_pagebox(p, pdf_bleedbox, 0, 0, 0, 0); + pdf_set_pagebox(p, pdf_cropbox, 0, 0, 0, 0); + pdf_set_pagebox(p, pdf_trimbox, 0, 0, 0, 0); + } + + /* reference point */ + pdc_translation_matrix(x, y, &m); + + /* optional rotation */ + if (fabs(fit->rotate) > PDC_FLOAT_PREC) + { + pdc_rotation_matrix(p->ydirection * fit->rotate, &mm); + pdc_multiply_matrix(&mm, &m); + } + + /* output after translation and rotation */ + if (!xo->blind) + { + /* new CTM */ + if (fit->showborder || + fit->fitmethod == pdc_clip || fit->fitmethod == pdc_slice) + { + pdf_concat_raw(p, &m); + pdc_identity_matrix(&m); + } + + /* show border */ + if (fit->showborder) + { + pdf__rect(p, 0, 0, boxwidth, boxheight); + pdf__stroke(p); + } + + /* clipping */ + if (fit->fitmethod == pdc_clip || fit->fitmethod == pdc_slice) + { + pdc_scalar cw = boxwidth; + pdc_scalar ch = boxheight; + + if (cw < PDC_FLOAT_PREC) + cw = PDF_ACRO_MAXPAGE; + if (ch < PDC_FLOAT_PREC) + ch = PDF_ACRO_MAXPAGE; + pdf__rect(p, 0, 0, cw, ch); + pdf__clip(p); + } + } + + /* translation of element box */ + elembox.ll.y *= p->ydirection; + elembox.ur.y *= p->ydirection; + pdc_box2polyline(NULL, &elembox, polyline); + ip = indangle + indmirror; + if (ip >= 4) ip -= 4; + tx = polyline[ip].x; + ty = polyline[ip].y; + pdc_translation_matrix(tx, ty, &mm); + pdc_multiply_matrix(&mm, &m); + boxwidth = elembox.ur.x - elembox.ll.x; + boxheight = elembox.ur.y - elembox.ll.y; + + /* orientation of image */ + if (fit->orientate != 0) + { + pdc_rotation_matrix(p->ydirection * fit->orientate, &mm); + pdc_multiply_matrix(&mm, &m); + if (indangle % 2) + { + ss = fitscale.x; + fitscale.x = fitscale.y; + fitscale.y = ss; + + ss = boxwidth; + boxwidth = p->ydirection * boxheight; + boxheight = p->ydirection * ss; + } + } + + /* mirroring of image */ + mirror.x = elemscale.x * fitscale.x; + elemscale.x = fabs(mirror.x); + mirror.x /= elemscale.x; + if (image->strips == 1) + mirror.y = p->ydirection * elemscale.y * fitscale.y; + else + mirror.y = p->ydirection * rowsize * fitscale.y; + elemscale.y = fabs(mirror.y); + mirror.y /= elemscale.y; + pdc_scale_matrix(mirror.x, mirror.y, &mm); + pdc_multiply_matrix(&mm, &m); + + if (logg3) + pdc_logg(p->pdc, + "\t\t\tcumulative mirroring: mx=%g, my=%g\n", + mirror.x, mirror.y); + + /* matchbox or clip path */ + if (!xo->blind && (fit->matchbox || kclip || kcliptiff)) + { + pdf_concat_raw(p, &m); + pdc_identity_matrix(&m); + + if (fit->matchbox) + { + matchrect.llx = 0; + matchrect.lly = 0; + matchrect.urx = boxwidth; + matchrect.ury = p->ydirection * boxheight; + pdf_set_mbox_rectangle(p, fit->matchbox, &matchrect, 0); + pdf_draw_mbox_rectangle(p, fit->matchbox, mbox_area | mbox_border); + + pdf_add_page_mbox(p, fit->matchbox); + } + + /* displacement of image because of clipping */ + shift = clipbox.ll; + purescale.x *= fitscale.x; + purescale.y *= fitscale.y; + if (kclip) + { + shift.x *= -purescale.x; + shift.y *= -purescale.y; + } + + if (kclip) + { + /* user clipping path */ + pdf__rect(p, 0, 0, boxwidth, boxheight); + pdf__clip(p); + } + + if (kclip) + { + pdc_translation_matrix(shift.x, shift.y, &mm); + pdc_multiply_matrix(&mm, &m); + } + } + + /* scaling of image */ + pdc_scale_matrix(elemscale.x, elemscale.y, &mm); + pdc_multiply_matrix(&mm, &m); + + /* ctm */ + if (xo->blind) + { + if (immatrix == NULL) + mm = p->curr_ppt->gstate[p->curr_ppt->sl].ctm; + else + mm = *immatrix; + pdc_multiply_matrix(&m, &mm); + } + else + { + pdf_concat_raw(p, &m); + mm = p->curr_ppt->gstate[p->curr_ppt->sl].ctm; + } + + pdc_logg_cond(p->pdc, 5, trc_image, + "\t\t\tCTM components of image %s\"%s\":\n" + "\t\t\ta = %f\n" + "\t\t\tb = %f\n" + "\t\t\tc = %f\n" + "\t\t\td = %f\n" + "\t\t\te = %f\n" + "\t\t\tf = %f\n", + image->imagemask ? "mask " : "", + image->filename, mm.a, mm.b, mm.c, mm.d, mm.e, mm.f); + + if (!xo->blind) + pdf_cleanup_fit_options(p, fit); + + /* check image orientation */ + if (immatrix != NULL) + { + *immatrix = mm; + return; + } + if (image->mask != pdc_undef) + { + sm = ctm_save; + xo_save.im = image->mask; + xo_save.blind = pdc_true; + pdf_fit_xobject_internal(p, &xo_save, &fit_save, &sm); + + if ((sm.a * mm.a < 0) || (sm.b * mm.b < 0) || + (sm.c * mm.c < 0) || (sm.d * mm.d < 0)) + { + pdc_error(p->pdc, PDF_E_IMAGE_NOMATCH, + p->images[image->mask].filename, image->filename, 0, 0); + } + } + + if (!(xo->flags & is_image) && !xo->blind) + { + pdf_reset_gstate(p); + pdf_reset_tstate(p); + } + + + if (!xo->blind) + { + /* last strip first */ + if (image->strips > 1 && lastratio != 1.0) + { + pdc_scale_matrix(1, lastratio, &m); + pdf_concat_raw(p, &m); + } + + /* put out image strips separately if available */ + islast = image->strips - 1; + imageno = image->no + islast; + for (is = islast; is >= 0; is--) + { + pdc_printf(p->out, "/I%d Do\n", imageno); + p->xobjects[imageno].flags |= xobj_flag_write; + if (image->strips > 1 && is > 0) + { + pdc_translation_matrix(0, 1, &m); + if (is == islast && lastratio != 1.0) + { + pdc_scale_matrix(1, (1.0 / lastratio), &sm); + pdc_multiply_matrix(&sm, &m); + } + pdf_concat_raw(p, &m); + imageno--; + } + } + if (image->mask != pdc_undef) + p->xobjects[p->images[image->mask].no].flags |= xobj_flag_write; + } +} + + +/* ---------------------------- info image --------------------------------- */ + +void +pdf_get_image_size(PDF *p, int im, pdc_scalar *width, pdc_scalar *height) +{ + pdf_image *image; + + pdf_check_handle(p, im, pdc_imagehandle); + image = &p->images[im]; + + if (image->orientation < 5 || image->ignoreorient) + { + if (width) + *width = image->width; + if (height) + *height = fabs(image->height); + } + else + { + if (width) + *width = fabs(image->height); + if (height) + *height = image->width; + } +} + +void +pdf_get_image_resolution(PDF *p, int im, pdc_scalar *dpi_x, pdc_scalar *dpi_y) +{ + pdf_image *image; + + pdf_check_handle(p, im, pdc_imagehandle); + image = &p->images[im]; + + if (image->orientation < 5 || image->ignoreorient) + { + if (dpi_x) + *dpi_x = image->dpi_x; + if (dpi_y) + *dpi_y = image->dpi_y; + } + else + { + if (dpi_x) + *dpi_x = image->dpi_y; + if (dpi_y) + *dpi_y = image->dpi_x; + } +} + + +const char * +pdf_get_image_filename(PDF *p, pdf_image *image) +{ + return pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, image->filename); +} + + +/* ---------------------------- load image --------------------------------- */ + +static const pdc_keyconn pdf_extension_names[] = +{ + {".bmp", pdf_img_bmp}, + {".ccitt", pdf_img_ccitt}, + {".g3", pdf_img_ccitt}, + {".g4", pdf_img_ccitt}, + {".fax", pdf_img_ccitt}, + {".gif", pdf_img_gif}, + {".jpg", pdf_img_jpeg}, + {".jpeg", pdf_img_jpeg}, + {".jpx", pdf_img_jpeg2000}, + {".jp2", pdf_img_jpeg2000}, + {".jpf", pdf_img_jpeg2000}, + {".jpm", pdf_img_jpeg2000}, + {".j2k", pdf_img_jpeg2000}, + {".png", pdf_img_png}, + {".raw", pdf_img_raw}, + {".tif", pdf_img_tiff}, + {".tiff", pdf_img_tiff}, + {NULL, 0} +}; + +/* allowed values for options 'bpc' */ +static const pdc_keyconn pdf_bpcvalues[] = +{ + {"1", 1}, {"2", 2}, {"4", 4}, {"8", 8}, {"16", 16}, {NULL, 0} +}; + +/* allowed values for options 'components' */ +static const pdc_keyconn pdf_compvalues[] = +{ + {"1", 1}, {"3", 3}, {"4", 4}, {NULL, 0} +}; + +#define PDF_OPIOPT_FLAG PDC_OPT_UNSUPP +#define PDF_ICCOPT_FLAG PDC_OPT_UNSUPP +#define PDF_CLIPPATH_FLAG PDC_OPT_UNSUPP + +#define PDF_METADATA_FLAG PDC_OPT_UNSUPP + +#define PDF_LAYER_FLAG PDC_OPT_UNSUPP + +/* definitions of open image options */ +static const pdc_defopt pdf_open_image_options[] = +{ + {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDF_MAX_NAMESTRING, NULL}, + + {"bitreverse", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + {"bpc", pdc_integerlist, PDC_OPT_INTLIST, 1, 1, 1.0, 16.0, pdf_bpcvalues}, + + {"components", pdc_integerlist, PDC_OPT_INTLIST, 1, 1, 1.0, 4.0, + pdf_compvalues}, + + {"height", pdc_integerlist, 0, 1, 1, 1.0, PDC_INT_MAX, NULL}, + + {"width", pdc_integerlist, 0, 1, 1, 1.0, PDC_INT_MAX, NULL}, + + {"honoriccprofile", pdc_booleanlist, PDF_ICCOPT_FLAG, 1, 1, 0.0, 0.0, NULL}, + + /* ordering of the next three options is significant */ + + {"iccprofile", pdc_iccprofilehandle, PDF_ICCOPT_FLAG, 1, 1, 1.0, 0.0, NULL}, + + {"colorize", pdc_colorhandle, PDC_OPT_IGNOREIF1, 1, 1, 0.0, 0.0, NULL}, + + {"mask", pdc_booleanlist, PDC_OPT_IGNOREIF2, 1, 1, 0.0, 0.0, NULL}, + + {"honorclippingpath", pdc_booleanlist, PDF_CLIPPATH_FLAG, 1, 1, + 0.0, 0.0, NULL}, + + {"clippingpathname", pdc_stringlist, PDF_CLIPPATH_FLAG, 1, 1, + 1.0, PDC_INT_MAX, NULL}, + + {"ignoremask", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + {"ignoreorientation", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + /* deprecated */ + {"imagewarning", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + {"inline", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + {"interpolate", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + {"invert", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + {"jpegoptimize", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + {"passthrough", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + {"K", pdc_integerlist, 0, 1, 1, -1.0, 1.0, NULL}, + + {"masked", pdc_imagehandle, 0, 1, 1, 0.0, 0.0, NULL}, + + {"page", pdc_integerlist, 0, 1, 1, 1.0, PDC_INT_MAX, NULL}, + + {"renderingintent", pdc_keywordlist, 0, 1, 1, 0.0, 0.0, + pdf_renderingintent_pdfkeylist}, + + {"reftype", pdc_keywordlist, 0, 1, 1, 0.0, 0.0, pdf_reftype_keys}, + + {"template", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + {"iconname", pdc_stringlist, 0, 1, 1, + 1.0, PDF_MAX_NAMESTRING, NULL}, + + {"OPI-1.3", pdc_stringlist, PDF_OPIOPT_FLAG, 1, 1, + 0.0, PDC_INT_MAX, NULL}, + + {"OPI-2.0", pdc_stringlist, PDF_OPIOPT_FLAG | PDC_OPT_IGNOREIF1, 1, 1, + 0.0, PDC_INT_MAX, NULL}, + + {"metadata", pdc_stringlist, PDF_METADATA_FLAG, 1, 1, + 0.0, PDC_INT_MAX, NULL}, + + {"layer", pdc_layerhandle, PDF_LAYER_FLAG, 1, 1, + 0.0, 0.0, NULL}, + + PDF_ERRORPOLICY_OPTION + + PDC_OPT_TERMINATE +}; + +int +pdf__load_image( + PDF *p, + const char *type, + const char *filename, + const char *optlist) +{ + const char *keyword = NULL, *stemp1 = NULL, *stemp2 = NULL, *stemp3 = NULL; + char qualname[32], uptype[16], testfilename[PDC_FILENAMELEN + 1]; + pdc_clientdata data; + pdc_resopt *resopts; + pdc_encoding htenc; + int htcp; + pdf_image_type imgtype; + pdc_file *fp = NULL; + int colorize = pdc_undef; + pdf_image *image; + pdc_bool indjpeg = pdc_false; + pdc_bool templ = pdc_false; + pdc_bool verbose = p->debug[(int) 'i']; + int legal_states = 0; + int i, k, inum, imageslot, retval = -1, errcode = 0; + + if (type == NULL || *type == '\0') + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0); + + /* parsing image type */ + k = pdc_get_keycode_ci(type, pdf_image_keylist); + if (k == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_ILLARG_STRING, "type", type, 0, 0); + imgtype = (pdf_image_type) k; + type = pdc_get_keyword(imgtype, pdf_image_keylist); + + verbose = pdf_get_errorpolicy(p, NULL, verbose); + + /* filename must be already converted to UTF-8 */ + pdc_logg_cond(p->pdc, 1, trc_image, "\tImage file: \"%s\"\n", filename); + + /* search for image file */ + fp = pdc_fsearch_fopen(p->pdc, filename, NULL, "image ", PDC_FILE_BINARY); + + /* automatic check */ + if (imgtype == pdf_img_auto) + { + pdf_tiff_info tiff_info; + + /* search for files with other extensions */ + if (fp == NULL) + { + pdc_logg_cond(p->pdc, 1, trc_image, + "\tImage file not found; searching for files " + "with alternative extensions\n"); + + for (i = 0; i < 2; i++) + { + for (k = 0; k < 100; k++) + { + const char *extension = pdf_extension_names[k].word; + if (extension) + { + strcpy(testfilename, filename); + strcpy(uptype, extension); + if (i) + pdc_strtoupper(uptype); + strcat(testfilename, uptype); + + fp = pdc_fsearch_fopen(p->pdc, testfilename, NULL, + "image ", PDC_FILE_BINARY); + if (fp != NULL) + break; + } + else + { + break; + } + } + if (fp != NULL) + break; + } + + if (fp != NULL) + { + filename = (const char *) testfilename; + pdc_logg_cond(p->pdc, 1, trc_image, + "\tImage file \"%s\" found\n", filename); + } + else + { + fp = pdc_fsearch_fopen(p->pdc, filename, NULL, "image ", + PDC_FILE_BINARY); + } + } + + /* automatic type check */ + if (fp != NULL) + { + if (pdf_is_BMP_file(p, fp)) + imgtype = pdf_img_bmp; + else if (pdf_is_GIF_file(p, fp)) + imgtype = pdf_img_gif; + else if (pdf_is_PNG_file(p, fp)) + imgtype = pdf_img_png; + else if (pdf_is_TIFF_file(p, fp, &tiff_info, pdc_true)) + imgtype = pdf_img_tiff; + else if (pdf_is_JPEG_file(p, fp)) + imgtype = pdf_img_jpeg; + else if (pdf_is_JPX_file(p, fp)) + imgtype = pdf_img_jpeg2000; + else + { + pdc_fclose(fp); + + pdc_set_errmsg(p->pdc, PDF_E_IMAGE_UNKNOWN, filename, 0, 0, 0); + + if (verbose) + PDC_RETHROW(p->pdc); + + return -1; + } + type = pdc_get_keyword(imgtype, pdf_image_keylist); + } + } + + if (fp == NULL) + { + if (verbose) + PDC_RETHROW(p->pdc); + + return -1; + } + pdc_fclose(fp); + + strcpy(uptype, type); + pdc_strtoupper(uptype); + pdc_logg_cond(p->pdc, 1, trc_image, + "\tImage type \"%s\" detected\n", uptype); + + if (imgtype == pdf_img_jpeg2000) + { + pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_JPEG2000, 0, 0, 0, 0); + + if (verbose) + PDC_RETHROW(p->pdc); + + return -1; + } + + /* find free slot */ + for (imageslot = 0; imageslot < p->images_capacity; imageslot++) + if (!p->images[imageslot].in_use) + break; + + if (imageslot == p->images_capacity) + pdf_grow_images(p); + image = &p->images[imageslot]; + + /* copy filename */ + image->filename = pdc_strdup(p->pdc, filename); + + /* inherit global flags */ + image->verbose = verbose; + image->ri = p->rendintent; + + /* parsing optlist */ + if (optlist && strlen(optlist)) + { + pdf_set_clientdata(p, &data); + resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_open_image_options, + &data, pdc_true); + /* save and check options */ + keyword = "imagewarning"; + pdc_get_optvalues(keyword, resopts, &image->verbose, NULL); + image->verbose = pdf_get_errorpolicy(p, resopts, image->verbose); + verbose = image->verbose; + + keyword = "reftype"; + if (pdc_get_optvalues(keyword, resopts, &inum, NULL)) + { + image->reference = (pdf_ref_type) inum; + if (image->reference != pdf_ref_direct && + imgtype != pdf_img_ccitt && + imgtype != pdf_img_jpeg && + imgtype != pdf_img_raw) + { + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNSUPP, keyword, uptype, + 0, 0); + image->reference = pdf_ref_direct; + } + } + indjpeg = (imgtype == pdf_img_jpeg && + image->reference != pdf_ref_direct) ? pdc_true : pdc_false; + + keyword = "bpc"; + if (pdc_get_optvalues(keyword, resopts, &image->bpc, NULL)) + { + if (imgtype != pdf_img_raw && !indjpeg) + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype, + 0, 0); + if (image->bpc == 16) + { + if (p->compatibility < PDC_1_5) + { + errcode = PDC_E_OPT_VERSION; + stemp1 = "bpc=16"; + stemp2 = pdc_get_pdfversion(p->pdc, p->compatibility); + goto PDF_IMAGE_ERROR; + } + } + } + + keyword = "components"; + if (pdc_get_optvalues(keyword, resopts, &image->components, NULL)) + { + if (imgtype != pdf_img_raw && !indjpeg) + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype, + 0, 0); + } + + keyword = "height"; + if (pdc_get_optvalues(keyword, resopts, &image->height_pixel, NULL)) + { + if (imgtype != pdf_img_ccitt && + imgtype != pdf_img_raw && !indjpeg) + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype, + 0, 0); + } + + keyword = "width"; + if (pdc_get_optvalues(keyword, resopts, &image->width_pixel, NULL)) + { + if (imgtype != pdf_img_raw && + imgtype != pdf_img_ccitt && !indjpeg) + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype, + 0, 0); + } + + keyword = "bitreverse"; + if (pdc_get_optvalues(keyword, resopts, &image->bitreverse, NULL)) + { + if (image->bitreverse && + (imgtype != pdf_img_ccitt || image->reference != pdf_ref_direct)) + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype, + 0, 0); + } + + keyword = "colorize"; + if (pdc_get_optvalues(keyword, resopts, &colorize, NULL)) + { + if (imgtype == pdf_img_jpeg2000) + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype, + 0, 0); + } + + + keyword = "ignoremask"; + if (pdc_get_optvalues(keyword, resopts, &image->ignoremask, NULL)) + { + if (imgtype == pdf_img_bmp || + imgtype == pdf_img_ccitt || + imgtype == pdf_img_raw) + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNSUPP, keyword, uptype, + 0, 0); + } + + keyword = "ignoreorientation"; + if (pdc_get_optvalues(keyword, resopts, &image->ignoreorient, NULL)) + { + if (imgtype == pdf_img_tiff) + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNSUPP, keyword, uptype, + 0, 0); + } + + keyword = "inline"; + if (pdc_get_optvalues(keyword, resopts, + &image->doinline, NULL) && image->doinline) + { + if (imgtype != pdf_img_ccitt && + imgtype != pdf_img_jpeg && + imgtype != pdf_img_raw) + { + pdc_warning(p->pdc, + PDF_E_IMAGE_OPTUNSUPP, keyword, uptype, 0, 0); + image->doinline = pdc_false; + } + else if (image->reference != pdf_ref_direct) + { + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype, + 0, 0); + image->doinline = pdc_false; + } + } + + keyword = "interpolate"; + pdc_get_optvalues(keyword, resopts, &image->interpolate, NULL); + + + keyword = "invert"; + if (pdc_get_optvalues(keyword, resopts, &image->invert, NULL)) + { + if (imgtype == pdf_img_jpeg2000) + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype, + 0, 0); + } + + keyword = "jpegoptimize"; + pdc_get_optvalues(keyword, resopts, &image->jpegoptimize, NULL); + + keyword = "passthrough"; + pdc_get_optvalues(keyword, resopts, &image->passthrough, NULL); + + keyword = "K"; + if (pdc_get_optvalues(keyword, resopts, &image->K, NULL)) + { + if (imgtype != pdf_img_ccitt) + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNREAS, keyword, uptype, + 0, 0); + } + + keyword = "mask"; + pdc_get_optvalues(keyword, resopts, &image->imagemask, NULL); + + + keyword = "masked"; + if (pdc_get_optvalues(keyword, resopts, &image->mask, NULL)) + { + + + if (!p->images[image->mask].in_use || + p->images[image->mask].strips != 1 || + (p->compatibility <= PDC_1_3 && + (p->images[image->mask].imagemask != pdc_true || + p->images[image->mask].bpc != 1))) + { + errcode = PDF_E_IMAGE_OPTBADMASK; + stemp1 = keyword; + stemp2 = pdc_errprintf(p->pdc, "%d", image->mask); + goto PDF_IMAGE_ERROR; + } + + if (p->colorspaces[p->images[image->mask].colorspace].type != + DeviceGray) + { + errcode = PDF_E_IMAGE_BADMASK; + stemp1 = pdc_errprintf(p->pdc, "%s", + p->images[image->mask].filename); + goto PDF_IMAGE_ERROR; + } + } + + keyword = "renderingintent"; + if (pdc_get_optvalues(keyword, resopts, &inum, NULL)) + image->ri = (pdf_renderingintent) inum; + + keyword = "page"; + if (pdc_get_optvalues(keyword, resopts, &image->page, NULL)) + { + if (imgtype != pdf_img_tiff) + { + if (image->page == 1) + { + pdc_warning(p->pdc, PDF_E_IMAGE_OPTUNSUPP, keyword, + uptype, 0, 0); + } + else + { + errcode = PDF_E_IMAGE_NOPAGE; + stemp1 = pdc_errprintf(p->pdc, "%d", image->page); + stemp2 = uptype; + stemp3 = pdc_errprintf(p->pdc, "%s", image->filename); + goto PDF_IMAGE_ERROR; + } + } + } + + keyword = "template"; + if (pdc_get_optvalues(keyword, resopts, &templ, NULL)) + { + if (templ && image->doinline) + { + pdc_warning(p->pdc, PDC_E_OPT_IGNORE, keyword, "inline", + 0, 0); + templ = pdc_false; + } + } + + htenc = + pdf_get_hypertextencoding_opt(p, resopts, &htcp, pdc_true); + keyword = "iconname"; + if (pdf_get_opt_textlist(p, keyword, resopts, htenc, htcp, pdc_true, + NULL, &image->iconname, NULL)) + { + if (image->doinline) + { + image->iconname = NULL; + pdc_warning(p->pdc, PDC_E_OPT_IGNORE, keyword, "inline", + 0, 0); + } + else + { + pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + templ = pdc_true; + } + } + + + + } + + /* precise scope diagnosis */ + if (image->doinline) + legal_states = pdf_state_content; + else if (templ) + legal_states = pdf_state_document; + else + legal_states = pdf_state_document | pdf_state_page | pdf_state_font; + PDF_CHECK_STATE(p, legal_states); + + /* required options */ + if (imgtype == pdf_img_raw || imgtype == pdf_img_ccitt || indjpeg) + { + keyword = ""; + if (image->height_pixel == pdc_undef) + keyword = "height"; + else if (image->width_pixel == pdc_undef) + keyword = "width"; + else + { + image->width = image->width_pixel; + image->height = image->height_pixel; + } + + if (imgtype == pdf_img_ccitt) + { + image->components = 1; + image->bpc = 1; + } + if (image->bpc == pdc_undef) + keyword = "bpc"; + else if (image->components == pdc_undef) + keyword = "components"; + + if (*keyword) + { + errcode = PDC_E_OPT_NOTFOUND; + stemp1 = keyword; + goto PDF_IMAGE_ERROR; + } + } + + + + /* set colorspace */ + if (colorize != pdc_undef) + { + image->colorspace = colorize; + } + else if (image->imagemask == pdc_true) + { + image->colorspace = (int) DeviceGray; + } + else + { + switch(image->components) + { + case 1: + image->colorspace = DeviceGray; + break; + + case 3: + image->colorspace = DeviceRGB; + break; + + case 4: + image->colorspace = DeviceCMYK; + break; + + default: + break; + } + } + + /* try to open image file */ + if (image->reference == pdf_ref_direct) + { + strcpy(qualname, uptype); + strcat(qualname, " "); + image->fp = pdc_fsearch_fopen(p->pdc, image->filename, NULL, qualname, + PDC_FILE_BINARY); + if (image->fp == NULL) + goto PDF_IMAGE_ERROR; + } + + + /* set image type */ + image->type = imgtype; + + /* call working function */ + switch (imgtype) + { + case pdf_img_bmp: + retval = pdf_process_BMP_data(p, imageslot); + break; + + case pdf_img_ccitt: + retval = pdf_process_CCITT_data(p, imageslot); + break; + + case pdf_img_gif: + retval = pdf_process_GIF_data(p, imageslot); + break; + + case pdf_img_jpeg: + if (image->passthrough == pdc_undef) + image->passthrough = pdc_false; + retval = pdf_process_JPEG_data(p, imageslot); + break; + + case pdf_img_jpeg2000: + retval = pdf_process_JPX_data(p, imageslot); + break; + + case pdf_img_png: + retval = pdf_process_PNG_data(p, imageslot); + break; + + default: + case pdf_img_raw: + retval = pdf_process_RAW_data(p, imageslot); + break; + + case pdf_img_tiff: + if (image->passthrough == pdc_undef) + image->passthrough = pdc_true; + retval = pdf_process_TIFF_data(p, imageslot); + break; + } + + /* cleanup */ + if (retval == -1) + { + pdf_cleanup_image(p, imageslot); + + if (verbose) + PDC_RETHROW(p->pdc); + } + else + { + if (image->fp) + pdc_fclose(image->fp); + image->fp = NULL; + + /* logging protocol */ + if (pdc_logg_is_enabled(p->pdc, 1, trc_image)) + { + pdc_scalar width, height, dpi_x, dpi_y; + + pdf_get_image_size(p, imageslot, &width, &height); + pdf_get_image_resolution(p, imageslot, &dpi_x, &dpi_y); + + pdc_logg(p->pdc, "\tImage width: %g pixel\n" + "\tImage height: %g pixel\n" + "\tImage x resolution: %g dpi\n" + "\tImage y resolution: %g dpi\n", + width, height, dpi_x, dpi_y); + + if (imgtype == pdf_img_tiff) + pdc_logg(p->pdc, "\tOrientation tag: %d\n", + image->orientation); + + } + + if (templ) + { + retval = pdf_embed_image(p, imageslot); + pdf_cleanup_image(p, imageslot); + } + } + + return retval; + + PDF_IMAGE_ERROR: + + pdf_cleanup_image(p, imageslot); + + if (errcode) + pdc_set_errmsg(p->pdc, errcode, stemp1, stemp2, stemp3, 0); + if (verbose) + PDC_RETHROW(p->pdc); + + return retval; +} + +void +pdf__close_image(PDF *p, int image) +{ + pdf_check_handle(p, image, pdc_imagehandle); + pdf_cleanup_image(p, image); +} + + +#define MAX_THUMBNAIL_SIZE 106 + +void +pdf__add_thumbnail(PDF *p, int im) +{ + pdf_image *image; + + pdf_check_handle(p, im, pdc_imagehandle); + + if (pdf_get_thumb_id(p) != PDC_BAD_ID) + pdc_error(p->pdc, PDF_E_IMAGE_THUMB, 0, 0, 0, 0); + + image = &p->images[im]; + + if (image->strips > 1) + pdc_error(p->pdc, PDF_E_IMAGE_THUMB_MULTISTRIP, + pdc_errprintf(p->pdc, "%d", im), 0, 0, 0); + + if (image->width > MAX_THUMBNAIL_SIZE || image->height > MAX_THUMBNAIL_SIZE) + pdc_error(p->pdc, PDF_E_IMAGE_THUMB_SIZE, + pdc_errprintf(p->pdc, "%d", im), + pdc_errprintf(p->pdc, "%d", MAX_THUMBNAIL_SIZE), 0, 0); + + if (image->colorspace != (int) DeviceGray && + image->colorspace != (int) DeviceRGB && + image->colorspace != (int) Indexed) + pdc_error(p->pdc, PDF_E_IMAGE_THUMB_CS, + pdc_errprintf(p->pdc, "%d", im), 0, 0, 0); + + /* Add the image to the thumbnail key of the current page. */ + pdf_set_thumb_id(p, p->xobjects[image->no].obj_id); +} diff --git a/src/pdflib/pdflib/p_image.h b/src/pdflib/pdflib/p_image.h new file mode 100644 index 0000000..2f67649 --- /dev/null +++ b/src/pdflib/pdflib/p_image.h @@ -0,0 +1,358 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_image.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * Header file for the PDFlib image subsystem + * + */ + +#ifndef P_IMAGE_H +#define P_IMAGE_H + +#ifdef HAVE_LIBTIFF +#include "tiffio.h" +#endif + +#ifdef HAVE_LIBPNG +#include "png.h" +#endif + +/* image type */ +typedef enum +{ + pdf_img_auto, + pdf_img_bmp, + pdf_img_ccitt, + pdf_img_gif, + pdf_img_jpeg, + pdf_img_jpeg2000, + pdf_img_png, + pdf_img_raw, + pdf_img_tiff +} +pdf_image_type; + +/* compression type */ +typedef enum +{ + pdf_comp_none, + pdf_comp_lzw, + pdf_comp_runlength, + pdf_comp_ccitt, + pdf_comp_dct, + pdf_comp_flate, + pdf_comp_jbig2, + pdf_comp_jpx +} +pdf_compression; + +/* image reference */ +typedef enum +{ + pdf_ref_direct, + pdf_ref_file, + pdf_ref_url +} +pdf_ref_type; + +typedef enum +{ + pred_default = 1, + pred_tiff = 2, + pred_png = 15 +} +pdf_predictor; + +#ifdef P_IMAGE_C + +const pdc_keyconn pdf_image_keylist[] = +{ + {"auto", pdf_img_auto}, + {"bmp", pdf_img_bmp}, + {"ccitt", pdf_img_ccitt}, + {"gif", pdf_img_gif}, + {"jpeg", pdf_img_jpeg}, + {"jpeg2000", pdf_img_jpeg2000}, + {"png", pdf_img_png}, + {"raw", pdf_img_raw}, + {"tiff", pdf_img_tiff}, + {NULL, 0} +}; + +const pdc_keyconn pdf_filter_pdfkeylist[] = +{ + {"", pdf_comp_none}, + {"LZWDecode", pdf_comp_lzw}, + {"RunLengthDecode", pdf_comp_runlength}, + {"CCITTFaxDecode", pdf_comp_ccitt}, + {"DCTDecode", pdf_comp_dct}, + {"FlateDecode", pdf_comp_flate}, + {"JBIG2Decode", pdf_comp_jbig2}, + {"JPXDecode", pdf_comp_jpx}, + {NULL, 0} +}; + +const pdc_keyconn pdf_shortfilter_pdfkeylist[] = +{ + {"", pdf_comp_none}, + {"LZW", pdf_comp_lzw}, + {"RL", pdf_comp_runlength}, + {"CCF", pdf_comp_ccitt}, + {"DCT", pdf_comp_dct}, + {"Fl", pdf_comp_flate}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_reftype_keys[] = +{ + {"direct", pdf_ref_direct}, + {"fileref", pdf_ref_file}, + {"url", pdf_ref_url}, + {NULL, 0} +}; + +#endif /* P_IMAGE_C */ + +/* BMP specific image information */ +typedef struct pdf_bmp_info_t { + pdc_uint32 compression; /* BMP compression */ + pdc_uint32 redmask; /* red mask */ + pdc_ushort redmax; /* red maximal value */ + pdc_ushort redmove; /* red mask's movement */ + pdc_uint32 greenmask; /* green mask */ + pdc_ushort greenmax; /* green maximal value */ + pdc_ushort greenmove; /* green mask's movement */ + pdc_uint32 bluemask; /* blue mask */ + pdc_ushort bluemax; /* blue maximal value */ + pdc_ushort bluemove; /* blue mask's movement */ + pdc_ushort bpp; /* bits per pixel */ + size_t rowbytes; /* length of row data */ + size_t rowbytes_pad; /* padded length of row data */ + size_t rowbytes_buf; /* buffer for row data */ + size_t rowbytes_pdf; /* length of row data for PDF */ + size_t skiprows; /* number of rows to be skipped */ + pdc_byte *bitmap; /* bitmap buffer */ + pdc_byte *end; /* first byte above bitmap buffer */ + pdc_byte *pos; /* current position in bitmap buffer */ +} pdf_bmp_info; + +typedef struct pdf_jpeg_segment_s pdf_jpeg_segment; + +/* JPEG specific image information */ +#define JPEG_MAX_COMPS 4 /* max number components */ +typedef struct pdf_jpeg_info_t { + const char *virtfile; /* temporary virtual file name */ + pdf_jpeg_segment *seglist; /* list of segments to be copy */ + int capacity; /* currently allocated size */ + int number; /* next available segment number */ + pdc_uint32 jpegifoffset; /* offset to JPEG data for TIFF OJPEG */ /* CDPDF - replaced toff_t by pdc_uint32 */ + pdc_byte id[JPEG_MAX_COMPS]; /* component ids */ + pdc_byte hsamp[JPEG_MAX_COMPS]; /* horizontal sampling factor */ + pdc_byte vsamp[JPEG_MAX_COMPS]; /* vertical sampling factor */ + pdc_byte table[JPEG_MAX_COMPS]; /* quant table */ +} pdf_jpeg_info; + +/* GIF specific image information */ +typedef struct pdf_gif_info_t { + int useGlobalColormap; + int interlace; + + /* LZW decompression state */ + int ZeroDataBlock; + int curbit; + int lastbit; + int get_done; + int last_byte; + int return_clear; + int *sp; + int code_size, set_code_size; + int max_code, max_code_size; + int clear_code, end_code; + pdc_byte buf[280]; + int firstcode; + int oldcode; + + /* These are dynamically malloc'ed to avoid wasting 64KB for each image */ +#define MAX_LWZ_BITS 12 +#define GIF_TABLE_ELEMENTS (1<< MAX_LWZ_BITS) + int (*table)[GIF_TABLE_ELEMENTS]; + int *stack; +} pdf_gif_info; + + +/* PNG specific image information */ +typedef struct pdf_png_info_t { + size_t nbytes; /* number of bytes left */ + /* in current IDAT chunk */ +#ifdef HAVE_LIBPNG + png_structp png_ptr; + png_infop info_ptr; + png_uint_32 rowbytes; + pdc_byte *raster; + int cur_line; +#endif /* HAVE_LIBPNG */ +} pdf_png_info; + + +/* TIFF specific image information */ +typedef struct pdf_tiff_info_t { +#ifdef HAVE_LIBTIFF + TIFF *tif; /* pointer to TIFF data structure */ + uint32 *raster; /* frame buffer */ +#endif /* HAVE_LIBTIFF */ + + int cur_line; /* current image row or strip */ +} pdf_tiff_info; + +/* CCITT specific image information */ +typedef struct pdf_ccitt_info_t { + int BitReverse; /* reverse all bits prior to use */ +} pdf_ccitt_info; + +/* The image descriptor */ +struct pdf_image_s { + pdc_file *fp; /* image file pointer */ + char *filename; /* image file name or url */ + /* width and height in pixels, or in points for PDF pages and templates */ + pdc_scalar width; /* image width */ + pdc_scalar height; /* image height */ + int orientation; /* image orientation according TIFF */ + pdf_compression compression; /* image compression type */ + int colorspace; /* image color space */ + + /*************************** option variables *****************************/ + pdc_bool verbose; /* put out warning/error messages */ + pdc_bool bitreverse; /* bitwise reversal of all bytes */ + int bpc; /* bits per color component */ + int components; /* number of color components */ + int height_pixel; /* image height in pixel */ + int width_pixel; /* image width in pixel */ + pdc_bool ignoremask; /* ignore any transparency information*/ + pdc_bool ignoreorient; /* ignore orientation TIFF tag */ + pdc_bool doinline; /* inline image */ + pdc_bool interpolate; /* interpolate image */ + pdc_bool invert; /* reverse black and white */ + pdc_bool jpegoptimize; /* skip application segments of JPEG */ + pdc_bool passthrough; /* pass through mode for TIFF, JPEG */ + int K; /* encoding type of CCITT */ + pdc_bool imagemask; /* create a mask from a 1-bit image */ + int mask; /* image number of image mask */ + pdf_renderingintent ri; /* rendering intent of image */ + int page; /* page number of TIFF image */ + pdf_ref_type reference; /* kind of image data reference */ + pdc_bool topdown_save; /* saved topdown flag */ + char *iconname; /* icon name for template images */ + /**************************************************************************/ + + pdc_bool transparent; /* image is transparent */ + pdc_byte transval[4]; /* transparent color values */ + pdf_predictor predictor; /* predictor for lzw and flate */ + + pdc_scalar dpi_x; /* horiz. resolution in dots per inch */ + pdc_scalar dpi_y; /* vert. resolution in dots per inch */ + /* dpi is 0 if unknown */ + + pdc_bool in_use; /* image slot currently in use */ + pdc_bool corrupt; /* image is corrupt */ + + char *params; /* for TIFF */ + int strips; /* number of strips in image */ + int rowsperstrip; /* number of rows per strip */ + int pagehandle; /* PDI page handle */ + int dochandle; /* PDI document handle */ + pdc_pagebox usebox; + pdc_bool use_raw; /* use raw (compressed) image data */ + /* Only relevant for use_raw = false */ + pdc_bool pixelmode; /* Use TIFFReadRGBAImageOriented() ? */ + + pdf_image_type type; /* image type, used for cleanup */ + /* image format specific information */ + union { + pdf_bmp_info bmp; + pdf_jpeg_info jpeg; + pdf_gif_info gif; + pdf_png_info png; + pdf_tiff_info tiff; + pdf_ccitt_info ccitt; + } info; + + int no; /* PDF image number */ + PDF_data_source src; +}; + +/* xobject types */ +typedef enum { + image_xobject = 1 << 0, + form_xobject = 1 << 1, + pdi_xobject = 1 << 2 +} pdf_xobj_type; + +typedef enum { + xobj_flag_used = 1 << 0, /* in use */ + xobj_flag_write = 1 << 1 /* write at end of page */ +} pdf_xobj_flags; + +/* A PDF xobject */ +struct pdf_xobject_s { + pdc_id obj_id; /* object id of this xobject */ + int flags; /* bit mask of pdf_xobj_flags */ + pdf_xobj_type type; /* type of this xobject */ +}; + +/* p_bmp.c */ +int pdf_process_BMP_data(PDF *p, int imageslot); +pdc_bool pdf_is_BMP_file(PDF *p, pdc_file *fp); + +/* p_ccitt.c */ +int pdf_process_CCITT_data(PDF *p, int imageslot); +int pdf_process_RAW_data(PDF *p, int imageslot); + +/* p_gif.c */ +int pdf_process_GIF_data(PDF *p, int imageslot); +pdc_bool pdf_is_GIF_file(PDF *p, pdc_file *fp); +void pdf_cleanup_gif(PDF *p, pdf_image *image); + +/* p_jpeg.c */ +int pdf_process_JPEG_data(PDF *p, int imageslot); +pdc_bool pdf_is_JPEG_file(PDF *p, pdc_file *fp); +void pdf_cleanup_jpeg(PDF *p, pdf_image *image); + +/* p_jpx.c */ +int pdf_process_JPX_data(PDF *p, int imageslot); +pdc_bool pdf_is_JPX_file(PDF *p, pdc_file *fp); +void pdf_cleanup_jpx(PDF *p, pdf_image *image); + +/* p_png.c */ +int pdf_process_PNG_data(PDF *p, int imageslot); +pdc_bool pdf_is_PNG_file(PDF *p, pdc_file *fp); + +/* p_tiff.c */ +int pdf_process_TIFF_data(PDF *p, int imageslot); +pdc_bool pdf_is_TIFF_file(PDF *p, pdc_file *fp, pdf_tiff_info *tiff, + pdc_bool check); + +/* p_image.c */ +pdc_id pdf_get_xobject(PDF *p, int im); +void pdf_init_xobjects(PDF *p); +void pdf_write_xobjects(PDF *p); +void pdf_place_xobject(PDF *p, int im, pdc_scalar x, pdc_scalar y, + const char *optlist); +int pdf_new_xobject(PDF *p, pdf_xobj_type type, pdc_id obj_id); +void pdf_get_page_xobjects(PDF *p, pdf_reslist *rl); +void pdf_mark_page_xobject(PDF *p, int n); +void pdf_cleanup_xobjects(PDF *p); +const char *pdf_get_image_filename(PDF *p, pdf_image *image); + + +#endif /* P_IMAGE_H */ + diff --git a/src/pdflib/pdflib/p_intern.h b/src/pdflib/pdflib/p_intern.h new file mode 100644 index 0000000..80f92d9 --- /dev/null +++ b/src/pdflib/pdflib/p_intern.h @@ -0,0 +1,1027 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_intern.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib internal definitions + * + */ + +#ifndef P_INTERN_H +#define P_INTERN_H + +#include "pdflib.h" + +#include "ft_font.h" +#include "pc_file.h" +#include "pc_contain.h" + +#include "p_keyconn.h" + + + + +/* ------------------------ PDFlib feature configuration ------------------- */ + +/* changing the following is not recommended, and not supported */ + +/* BMP image support */ +/* #define PDF_BMP_SUPPORTED CDPDF: leave this to the IM library */ + +/* GIF image support */ +/* #define PDF_GIF_SUPPORTED CDPDF: leave this to the IM library */ + +/* JPEG image support */ +/* #define PDF_JPEG_SUPPORTED CDPDF: leave this to the IM library */ + +/* JPEG2000 image support */ +/* #define PDF_JPX_SUPPORTED CDPDF: leave this to the IM library */ + +/* PNG image support, requires HAVE_LIBZ */ +/* #define HAVE_LIBPNG CDPDF: leave this to the IM library */ + +/* TIFF image support */ +/* #define HAVE_LIBTIFF CDPDF: leave this to the IM library */ + + +/* -------------------------------- macros ------------------------------- */ + +/* + * Allocation chunk sizes. These don't affect the generated documents + * in any way. In order to save initial memory, however, you can lower + * the values. Increasing the values will bring some performance gain + * for large documents, but will waste memory for small ones. + */ +#define PAGES_CHUNKSIZE 512 /* pages */ +#define PNODES_CHUNKSIZE 64 /* page tree nodes */ +#define CONTENTS_CHUNKSIZE 64 /* page content streams */ +#define FONTS_CHUNKSIZE 16 /* document fonts */ +#define XOBJECTS_CHUNKSIZE 128 /* document xobjects */ +#define IMAGES_CHUNKSIZE 128 /* document images */ +#define OUTLINE_CHUNKSIZE 256 /* document outlines */ +#define NAMES_CHUNKSIZE 256 /* names */ +#define PDI_CHUNKSIZE 16 /* PDI instances */ +#define COLORSPACES_CHUNKSIZE 16 /* color spaces */ +#define PATTERN_CHUNKSIZE 4 /* pattern */ +#define SHADINGS_CHUNKSIZE 4 /* shadings */ +#define EXTGSTATE_CHUNKSIZE 4 /* external graphic states */ +#define T3GLYPHS_CHUNKSIZE 256 /* type 3 font glyph table */ +#define ICCPROFILE_CHUNKSIZE 4 /* ICC profiles */ +#define STRINGLISTS_CHUNKSIZE 128 /* document stringlists */ +#define ITEMS_CHUNKSIZE 256 /* PDFlib items */ +#define ITEMS_KIDS_CHUNKSIZE 64 /* PDFlib item's kids */ +#define ITEMS_MC_CHUNKSIZE 16 /* PDFlib item mc sequences */ +#define LAYER_DEP_CHUNKSIZE 16 /* PDFlib layer dependencies */ +#define RESLIST_CHUNKSIZE 16 /* per page resource list */ + +/* Acrobat 4 allows only 12 levels, but Acrobat 5 increases the limit to 28 */ +#define PDF_MAX_SAVE_LEVEL 28 /* max number of save levels */ + +#define PDF_MAX_PARAMSTRING 256 /* image parameter string */ +#define PDF_MAX_NAMESTRING 127 /* maximum name length */ +#define PDF_MAX_EVENTS 16 /* maximum number of events */ +#define PDF_MAX_DASHLENGTH 8 /* maximum number of dashes */ + +/* default PDF compatibility */ +#define PDF_DEF_COMPATIBILITY PDC_1_6 + + +/* ------------------------ typedefs and enums --------------------------- */ + +/* PDFlib error numbers. +*/ +#ifndef P_GENERR_H +enum +{ +#define pdf_genNames 1 +#include "p_generr.h" + + PDF_E_dummy +}; +#endif + +#define pdf_state_content \ + (pdf_state) (pdf_state_page | pdf_state_pattern | \ + pdf_state_template | pdf_state_glyph) + +#define pdf_state_all \ + (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page | \ + pdf_state_pattern | pdf_state_template | pdf_state_path | \ + pdf_state_font | pdf_state_glyph) + +#define PDF_STATE_STACK_SIZE 4 + +/* function-like macros. +** must behave well wherever function calls are syntactically legal. +*/ +#define PDF_GET_STATE(p) \ + ((p)->state_stack[(p)->state_sp]) + +#define PDF_SET_STATE(p, s) \ + ((p)->state_stack[(p)->state_sp] = (s)) + +/* statement-like macros. +** must behave well wherever statements are syntactically legal. +*/ +#define PDF_CHECK_STATE(p, s) \ + if ((((p)->state_stack[(p)->state_sp] & (s)) != 0)) { \ + } else pdc_error((p)->pdc, \ + PDF_E_DOC_SCOPE, pdf_current_scope(p), 0, 0, 0) + +#define PDF_PUSH_STATE(p, fn, s) \ + if ((p)->state_sp == PDF_STATE_STACK_SIZE - 1) \ + pdc_error((p)->pdc, PDF_E_INT_SSTACK_OVER, fn, 0, 0, 0); \ + else \ + (p)->state_stack[++(p)->state_sp] = (s) + +#define PDF_POP_STATE(p, fn) \ + if ((p)->state_sp == 0) \ + pdc_error((p)->pdc, PDF_E_INT_SSTACK_UNDER, fn, 0, 0, 0); \ + else \ + --(p)->state_sp + + +/* -------------------------- structs ------------------------------ */ + +#ifndef PDI_DEFINED +#define PDI_DEFINED +typedef struct PDI_s PDI; /* The opaque PDI type */ +typedef struct pdi_pcos_s pdi_pcos; +typedef struct pdi_props_s pdi_props; +#endif + +typedef struct +{ + pdc_bool info_mode; + PDI * pi; + pdc_byte * data; + pdi_pcos * pcc; +} pdf_pdi; + +/* Opaque types which are detailed in the respective modules + in alphabetical order */ +typedef struct pdf_category_s pdf_category; +typedef struct pdf_colorspace_s pdf_colorspace; +typedef struct pdf_cstate_s pdf_cstate; +typedef struct pdf_dest_s pdf_dest; +typedef struct pdf_document_s pdf_document; +typedef struct pdf_extgstateresource_s pdf_extgstateresource; +typedef struct pdf_font_options_s pdf_font_options; +typedef struct pdf_font_s pdf_font; +typedef struct pdf_formfields_s pdf_formfields; +typedef struct pdf_iccprofile_s pdf_iccprofile; +typedef struct pdf_image_s pdf_image; +typedef struct pdf_info_s pdf_info; +typedef struct pdf_layers_s pdf_layers; +typedef struct pdf_linearopts_s pdf_linearopts; +typedef struct pdf_mbox_s pdf_mbox; +typedef struct pdf_name_s pdf_name; +typedef struct pdf_outline_s pdf_outline; +typedef struct pdf_pages_s pdf_pages; +typedef struct pdf_pattern_s pdf_pattern; +typedef struct pdf_reslist_s pdf_reslist; +typedef struct pdf_shading_s pdf_shading; +typedef struct pdf_t3font_s pdf_t3font; +typedef struct pdf_tags_s pdf_tags; +typedef struct pdf_text_options_s pdf_text_options; +typedef struct pdf_tstate_s pdf_tstate; +typedef struct pdf_widget_s pdf_widget; +typedef struct pdf_xobject_s pdf_xobject; + + +/* -------------------- special graphics state -------------------- */ +typedef struct { + pdc_matrix ctm; /* current transformation matrix */ + pdc_scalar x; /* current x coordinate */ + pdc_scalar y; /* current y coordinate */ + + pdc_scalar startx; /* starting x point of the subpath */ + pdc_scalar starty; /* starting y point of the subpath */ + + pdc_scalar lwidth; /* line width */ + int lcap; /* line cap style */ + int ljoin; /* line join style */ + pdc_scalar miter; /* miter limit */ + pdc_scalar flatness; /* path flatness */ + pdc_bool dashed; /* line dashing in effect */ +} pdf_gstate; + +/* ---------------------- page/pattern/template ----------------------- */ +typedef struct +{ + /* graphics, text, and color state. + */ + int sl; /* current save level */ + pdf_gstate gstate[PDF_MAX_SAVE_LEVEL]; /* graphics state */ + pdf_tstate *tstate; /* text state */ + pdf_cstate *cstate; /* color state */ + + pdf_text_options *currto; /* current text options */ + pdf_fillrule fillrule; /* nonzero or evenodd fill rule */ + + pdc_vtr * mboxes; /* matchbox chain */ + + /* in update mode, the resource numbers generally don't start + ** with 0, but with a bias value derived from the original + ** page's resources. + */ + int cs_bias; /* colorspaces */ + int eg_bias; /* extended gstates */ + int fn_bias; /* fonts */ + int pt_bias; /* patterns */ + int sh_bias; /* shadings */ + int xo_bias; /* xobjects */ +} pdf_ppt; + +/* Force graphics or color operator output, avoiding the optimization + * which checks whether the new value might be the same as the old. + * This is especially required for Type 3 glyph descriptions which + * inherit the surrounding page description's gstate parameters, + * and therefore even must write default values. + */ +#define PDF_FORCE_OUTPUT() (PDF_GET_STATE(p) == pdf_state_glyph) + +/* + * ************************************************************************* + * The core PDF context descriptor + * ************************************************************************* + */ + +struct PDF_s { + /* -------------------------- general stuff ------------------------ */ + unsigned long magic; /* poor man's integrity check */ + void (*freeproc)(PDF *p, void *mem); + pdc_core *pdc; /* core context */ + int compatibility; /* PDF version number * 10 */ + pdf_errpol errorpolicy; /* error policy */ + + + + + pdf_state state_stack[PDF_STATE_STACK_SIZE]; + int state_sp; /* state stack pointer */ + + /* ------------------- PDF Catalog dictionary --------------------- */ + pdf_document *document; /* document struct */ + + + /* ------------------- PDF Info dictionary entries ----------------- */ + pdf_info *userinfo; /* list of user-defined entries */ + + /* -------------- I/O, error handling and memory management ------------- */ + size_t (*writeproc)(PDF *p, void *data, size_t size); + void (*errorhandler)(PDF *p, int level, const char* msg); + void *opaque; /* user-specific, opaque data */ + + /* ------------------------- PDF import ---------------------------- */ + pdf_pdi *pdi; /* PDI context array */ + int pdi_capacity; /* currently allocated size */ + pdc_pagebox pdi_usebox; + pdc_bool pdi_strict; /* strict PDF parser mode */ + pdc_bstr * pdi_parmbuf; /* string buffer for pdi parms */ + + /* ------------ stuff for hypertext functions ---------- */ + pdc_encoding hypertextencoding; /* encoding of hypertexts */ + pdc_text_format hypertextformat; /* format of hypertexts */ + int hypertextcodepage; /* OEM multi byte code-page number */ + pdc_bool usercoordinates; /* interprete rectangle coordinates */ + /* of hypertext funcs. in user space */ + pdc_bool usehyptxtenc; /* use hypertextencoding */ + /* for name strings */ + + + /* ------------------- PDF output bookkeeping ------------------- */ + pdc_id procset_id; /* id of constant ProcSet array */ + pdc_output *out; /* output manager */ + pdc_id length_id; /* id of current stream's length*/ + pdc_flush_state flush; /* flush state */ + + /* ------------------- page bookkeeping ------------------- */ + pdf_pages *doc_pages; /* document wide page management */ + + /* ------------------- document resources ------------------- */ + pdf_font *fonts; /* all fonts in document */ + int fonts_capacity; /* currently allocated size */ + int fonts_number; /* next available font number */ + int t3slot; /* slot of temporary type 3 font */ + fnt_cmap_stack *cmst; /* CMap stack handle */ + + + + pdf_xobject *xobjects; /* all xobjects in document */ + int xobjects_capacity; /* currently allocated size */ + int xobjects_number; /* next available xobject slot */ + + pdf_colorspace *colorspaces; /* all color space resources */ + int colorspaces_capacity; /* currently allocated size */ + int colorspaces_number; /* next available color space number */ + + + pdf_pattern *pattern; /* all pattern resources */ + int pattern_capacity; /* currently allocated size */ + int pattern_number; /* next available pattern number */ + + pdf_shading *shadings; /* all shading resources */ + int shadings_capacity; /* currently allocated size */ + int shadings_number; /* next available shading number */ + + pdf_extgstateresource *extgstates; /* all ext. graphic state resources */ + int extgstates_capacity; /* currently allocated size */ + int extgstates_number; /* next available extgstate number */ + + pdf_image *images; /* all images in document */ + int images_capacity; /* currently allocated size */ + + pdc_vtr *actions; /* all actions in document */ + + + /* ------------------ utilities ------------------- */ + char ***stringlists; /* string lists */ + int stringlists_capacity; /* currently allocated size */ + int stringlists_number; /* next available string list number */ + int *stringlistsizes; /* sizes of string lists */ + int utilstrlist_index; /* index of utility string list */ + int utilstring_number; /* next available utility string */ + + /* ------------------- document outline tree ------------------- */ + pdf_outline *outlines; /* dynamic array of outlines */ + int outline_capacity; /* currently allocated size */ + int outline_count; /* total number of outlines */ + + /* ------------------- name tree ------------------- */ + pdf_name *names; /* page ids */ + int names_capacity; + int names_number; /* next available names number */ + + /* -------------- page/pattern/template specific stuff -------------- */ + pdf_ppt * curr_ppt; /* current ppt descriptor */ + pdc_id res_id; /* id of this pattern/templ res dict */ + + pdc_scalar ydirection; /* direction of y axis of default */ + /* system rel. to viewport (1 or -1) */ + + pdf_renderingintent rendintent; /* RenderingIntent */ + + pdc_bool preserveoldpantonenames;/* preserve old PANTONE names */ + pdc_bool spotcolorlookup; /* use internal look-up table for + * color values */ + + /* ------------------------ template stuff ----------------------- */ + int templ; /* current template if in templ. state*/ + + /* --------------- other font and text stuff ---------------- */ + + pdf_font_options *currfo; /* current font settings */ + + pdc_glyphcheck glyphcheck; /* check for unavailable glyphs */ + pdc_text_format textformat; /* text storage format */ + pdc_bool in_text; /* currently in BT/ET section */ + + /* ------------------------ miscellaneous ------------------------ */ + char debug[256]; /* debug flags */ + + + + /* ------- deprecated stuff because of deprecated parameter ---------- */ + pdf_borderstyle border_style; + pdc_scalar border_width; + pdc_scalar border_red; + pdc_scalar border_green; + pdc_scalar border_blue; + pdc_scalar border_dash1; + pdc_scalar border_dash2; + pdf_dest *bookmark_dest; + char *launchlink_parameters; + char *launchlink_operation; + char *launchlink_defaultdir; + +}; + +/* Data source for images, compression, ASCII encoding, fonts, etc. */ +typedef struct PDF_data_source_s PDF_data_source; +struct PDF_data_source_s { + pdc_byte *next_byte; + size_t bytes_available; + void (*init)(PDF *, PDF_data_source *src); + int (*fill)(PDF *, PDF_data_source *src); + void (*terminate)(PDF *, PDF_data_source *src); + + pdc_byte *buffer_start; + size_t buffer_length; + void *private_data; + long offset; /* start of data to read */ + long length; /* length of data to read */ + long total; /* total bytes read so far */ +}; + +/* ------ Private functions for library-internal use only --------- */ + + +/* + (((((OpenVMS porting note))))) + + Symbols are restricted to <= 31 bytes on OpenVMS systems.... + Please truncate new function names to fit this silly restriction! + + (((((OpenVMS porting note))))) +*/ + + + + + +/********************** + * + * p_actions.c + * + **********************/ + +int pdf__create_action(PDF *p, const char *type, const char *optlist); + +void pdf_delete_actions(PDF *p); +int pdf_get_max_action(PDF *p); +pdc_bool pdf_parse_and_write_actionlist(PDF *p, pdf_event_object eventobj, + pdc_id *act_idlist, const char *optlist); +pdc_bool pdf_write_action_entries(PDF *p, pdf_event_object eventobj, + pdc_id *act_idlist); + + +/********************** + * + * p_annots.c + * + **********************/ + +void pdf__add_launchlink(PDF *p, pdc_scalar llx, pdc_scalar lly, + pdc_scalar urx, pdc_scalar ury, const char *filename); +void pdf__add_locallink(PDF *p, pdc_scalar llx, pdc_scalar lly, + pdc_scalar urx, pdc_scalar ury, int page, const char *optlist); +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); +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); +void pdf__add_weblink(PDF *p, pdc_scalar llx, pdc_scalar lly, + pdc_scalar urx, pdc_scalar ury, const char *url); +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); +void pdf__create_annotation(PDF *p, pdc_scalar llx, pdc_scalar lly, + pdc_scalar urx, pdc_scalar ury, const char *type, const char *optlist); +void pdf__set_border_color(PDF *p, pdc_scalar red, pdc_scalar green, + pdc_scalar blue); +void pdf__set_border_dash(PDF *p, pdc_scalar b, pdc_scalar w); +void pdf__set_border_style(PDF *p, const char *style, pdc_scalar width); + +void pdf_init_annot_params(PDF *p); +void pdf_cleanup_annot_params(PDF *p); +pdc_id pdf_write_annots_root(PDF *p, pdc_vtr *annots, pdf_widget *widgetlist); +void pdf_write_page_annots(PDF *p, pdc_vtr *annots); + +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); + + + +/********************** + * + * p_color.c + * + **********************/ + + +void pdf__setcolor(PDF *p, const char *fstype, const char *colorspace, + pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4); + +void pdf_init_cstate(PDF *p); +void pdf_save_cstate(PDF *p); +void pdf_cleanup_page_cstate(PDF *p, pdf_ppt *ppt); +void pdf_init_colorspaces(PDF *p); +void pdf_set_default_color(PDF *p, pdc_bool reset); +void pdf_write_page_colorspaces(PDF *p); +void pdf_mark_page_colorspace(PDF *p, int n); +void pdf_write_doc_colorspaces(PDF *p); +void pdf_write_colorspace(PDF *p, int slot, pdc_bool direct); +void pdf_cleanup_colorspaces(PDF *p); +void pdf_write_colormap(PDF *p, int slot); + + +/********************** + * + * p_document.c + * + **********************/ + +int pdf__begin_document(PDF *p, const char *filename, int len, + const char *optlist); + +void pdf__begin_document_callback(PDF *p, writeproc_t writeproc, + const char *optlist); + +void pdf__end_document(PDF *p, const char *optlist); + +void pdf_cleanup_document(PDF *p); +void pdf_fix_openmode(PDF *p); +void pdf_insert_name(PDF *p, const char *name, pdf_nametree_type type, + pdc_id obj_id); +pdc_id pdf_get_id_from_nametree(PDF *p, pdf_nametree_type type, + const char *name); +char *pdf_parse_and_write_metadata(PDF *p, const char *optlist, pdc_bool output, + int *outlen); +pdc_off_t pdf_check_file(PDF *p, const char *filename, pdc_bool verbose); +void pdf_embed_file(PDF *p, pdc_id obj_id, const char *filename, + const char *mimetype, pdc_off_t filesize); + +/* deprecated functions: */ +void pdf_set_flush(PDF *p, const char *flush); +void pdf_set_uri(PDF *p, const char *uri); +void pdf_set_compatibility(PDF *p, const char *compatibility); +void pdf_set_openmode(PDF *p, const char *openmode); +void pdf_set_openaction(PDF *p, const char *openaction); +void pdf_set_viewerpreference(PDF *p, const char *viewerpreference); +const char *pdf__get_buffer(PDF *p, long *size); + + + + +/********************** + * + * p_draw.c + * + **********************/ + + +void pdf__arc(PDF *p, pdc_scalar x, pdc_scalar y, + pdc_scalar r, pdc_scalar alpha, pdc_scalar beta); +void pdf__arcn(PDF *p, pdc_scalar x, pdc_scalar y, + pdc_scalar r, pdc_scalar alpha, pdc_scalar beta); +void pdf__circle(PDF *p, pdc_scalar x, pdc_scalar y, pdc_scalar r); +void pdf__clip(PDF *p); +void pdf__closepath(PDF *p); +void pdf__closepath_fill_stroke(PDF *p); +void pdf__closepath_stroke(PDF *p); +void pdf__curveto(PDF *p, pdc_scalar x_1, pdc_scalar y_1, + pdc_scalar x_2, pdc_scalar y_2, pdc_scalar x_3, pdc_scalar y_3); +void pdf__endpath(PDF *p); +void pdf__fill(PDF *p); +void pdf__fill_stroke(PDF *p); +void pdf__lineto(PDF *p, pdc_scalar x, pdc_scalar y); +void pdf__rlineto(PDF *p, pdc_scalar x, pdc_scalar y); +void pdf__moveto(PDF *p, pdc_scalar x, pdc_scalar y); +void pdf__rcurveto(PDF *p, pdc_scalar x_1, pdc_scalar y_1, + pdc_scalar x_2, pdc_scalar y_2, pdc_scalar x_3, pdc_scalar y_3); +void pdf__rect(PDF *p, pdc_scalar x, pdc_scalar y, + pdc_scalar width, pdc_scalar height); +void pdf__rmoveto(PDF *p, pdc_scalar x, pdc_scalar y); +void pdf__stroke(PDF *p); + +void pdf_rrcurveto(PDF *p, pdc_scalar x_1, pdc_scalar y_1, + pdc_scalar x_2, pdc_scalar y_2, pdc_scalar x_3, pdc_scalar y_3); +void pdf_hvcurveto(PDF *p, pdc_scalar x_1, pdc_scalar x_2, + pdc_scalar y_2, pdc_scalar y_3); +void pdf_vhcurveto(PDF *p, pdc_scalar y_1, pdc_scalar x_2, + pdc_scalar y_2, pdc_scalar x_3); + + +/********************** + * + * p_encoding.c + * + **********************/ + +void pdf__encoding_set_char(PDF *p, const char *encoding, int slot, + const char *glyphname, int uv); + +pdc_encoding pdf_get_hypertextencoding_param(PDF *p, int *codepage); +pdc_encoding pdf_get_hypertextencoding(PDF *p, const char *encoding, + int *codepage, pdc_bool verbose); + + + + +/********************** + * + * p_filter.c + * + **********************/ + +int pdf_data_source_buf_fill(PDF *p, PDF_data_source *src); +void pdf_data_source_file_init(PDF *p, PDF_data_source *src); +int pdf_data_source_file_fill(PDF *p, PDF_data_source *src); +void pdf_data_source_file_terminate(PDF *p, PDF_data_source *src); +void pdf_copy_stream(PDF *p, PDF_data_source *src, pdc_bool compress); + + +/********************** + * + * p_font.c + * + **********************/ + +double pdf__info_font(PDF *p, int ifont, const char *keyword, + const char *optlist); +int pdf__load_font(PDF *p, const char *fontname, int len, + const char *encoding, const char *optlist); + +void pdf_init_font_options(PDF *p, pdf_font_options *fo); +void pdf_cleanup_font_curroptions(PDF *p); +void pdf_cleanup_font_options(PDF *p, pdf_font_options *fo); +void pdf_init_font(PDF *p, pdf_font *font, pdf_font_options *fo); +void pdf_cleanup_font(PDF *p, pdf_font *font); +void pdf_init_fonts(PDF *p); +void pdf_cleanup_fonts(PDF *p); +int pdf_insert_font(PDF *p, pdf_font *font); +void pdf_write_doc_fonts(PDF *p); +void pdf_write_page_fonts(PDF *p); +void pdf_get_page_fonts(PDF *p, pdf_reslist *rl); +void pdf_mark_page_font(PDF *p, int ft); + + +/********************** + * + * p_gstate.c + * + **********************/ + +void pdf__concat(PDF *p, pdc_scalar a, pdc_scalar b, pdc_scalar c, pdc_scalar d, + pdc_scalar e, pdc_scalar f); +void pdf__initgraphics(PDF *p); +void pdf__restore(PDF *p); +void pdf__rotate(PDF *p, pdc_scalar phi); +void pdf__save(PDF *p); +void pdf__scale(PDF *p, pdc_scalar sx, pdc_scalar sy); +void pdf__setdash(PDF *p, pdc_scalar b, pdc_scalar w); +void pdf__setdashpattern(PDF *p, const char *optlist); +void pdf__setflat(PDF *p, pdc_scalar flatness); +void pdf__setlinecap(PDF *p, int linecap); +void pdf__setlinejoin(PDF *p, int linejoin); +void pdf__setlinewidth(PDF *p, pdc_scalar width); +void pdf__setmatrix(PDF *p, pdc_scalar a, pdc_scalar b, pdc_scalar c, + pdc_scalar d, pdc_scalar e, pdc_scalar f); +void pdf__setmiterlimit(PDF *p, pdc_scalar miter); +void pdf__skew(PDF *p, pdc_scalar alpha, pdc_scalar beta); +void pdf__translate(PDF *p, pdc_scalar tx, pdc_scalar ty); + +void pdf_setmatrix_e(PDF *p, pdc_matrix *n); +void pdf_init_gstate(PDF *p); +void pdf_concat_raw(PDF *p, pdc_matrix *m); +void pdf_reset_gstate(PDF *p); +void pdf_set_topdownsystem(PDF *p, pdc_scalar height); +void pdf_setdashpattern_internal(PDF *p, pdc_scalar *darray, int length, + pdc_scalar phase); + + +/********************** + * + * p_hyper.c + * + **********************/ + +int pdf__add_bookmark(PDF *p, const char *text, int len, int parent, int open); +void pdf__add_nameddest(PDF *p, const char *name, int len, const char *optlist); +int pdf__create_bookmark(PDF *p, const char *text, int len, + const char *optlist); +void pdf__set_info(PDF *p, const char *key, const char *value, int len); + +pdf_dest *pdf_init_destination(PDF *p); +pdf_dest *pdf_parse_destination_optlist(PDF *p, const char *optlist, + int page, pdf_destuse destuse); +void pdf_cleanup_destination(PDF *p, pdf_dest *dest); +void pdf_write_destination(PDF *p, pdf_dest *dest); +pdf_dest *pdf_get_option_destname(PDF *p, pdc_resopt *resopts, + pdc_encoding hypertextencoding, int hypertextcodepage); +void pdf_init_outlines(PDF *p); +void pdf_write_outlines(PDF *p); +void pdf_write_outline_root(PDF *p); +void pdf_cleanup_outlines(PDF *p); +void pdf_feed_digest_info(PDF *p); +pdc_id pdf_write_info(PDF *p, pdc_bool moddate); +void pdf_cleanup_info(PDF *p); + + + + +/********************** + * + * p_image.c + * + **********************/ + +void pdf__add_thumbnail(PDF *p, int image); +void pdf__close_image(PDF *p, int image); +void pdf__fit_image(PDF *p, int image, pdc_scalar x, pdc_scalar y, + const char *optlist); +int pdf__load_image(PDF *p, const char *imagetype, const char *filename, + const char *optlist); + +void pdf_grow_images(PDF *p); +void pdf_put_image(PDF *p, int im, pdc_bool firststrip, + pdc_bool checkcontentstream); +void pdf_put_inline_image(PDF *p, int im); +void pdf_init_images(PDF *p); +void pdf_cleanup_images(PDF *p); +void pdf_cleanup_image(PDF *p, int im); +void pdf_get_image_size(PDF *p, int im, pdc_scalar *width, pdc_scalar *height); +void pdf_get_image_resolution(PDF *p, int im, pdc_scalar *dpi_x, + pdc_scalar *dpi_y); + + + + + + +/********************** + * + * p_mbox.c + * + **********************/ + +double pdf__info_matchbox(PDF *p, const char *boxname, int len, int num, + const char *keyword); + +pdc_vtr *pdf_new_mboxes(PDF *p, pdf_mbox *mbox, pdc_vtr *mboxes); +pdf_mbox *pdf_parse_mbox_optlist(PDF *p, const char *optlist); +pdf_mbox *pdf_get_mbox(PDF *p, pdc_vtr *mboxes, const char *name, int number, + int *o_count); +void pdf_delete_mbox(PDF *p, pdf_mbox *mbox); +void pdf_add_page_mbox(PDF *p, pdf_mbox *mbox); + +pdc_bool pdf_get_mbox_drawborder(PDF *p, pdf_mbox *mbox, int keycode); +void pdf_set_mbox_rectangle(PDF *p, pdf_mbox *mbox, pdc_rectangle *rect, + int flags); +void pdf_get_mbox_rectangle(PDF *p, pdf_mbox *mbox, pdc_vector *polyline); +void pdf_draw_mbox_rectangle(PDF *p, pdf_mbox *mbox, pdc_bool saverestore); +const char *pdf_get_usematchbox(PDF *p, const char *option, const char *optval, + int *istart, int *istop); + +void pdf_set_position_values(PDF *p, pdc_scalar *i_position, int nv); + + +/********************** + * + * p_object.c + * + **********************/ + +void pdf__delete(PDF *p); + +PDF *pdf__new(errorproc_t errorhandler, allocproc_t allocproc, + reallocproc_t reallocproc, freeproc_t freeproc, void *opaque); + +const char *pdf_current_scope(PDF *p); + + +/********************** + * + * p_page.c + * + **********************/ + +void pdf__begin_page(PDF *p, pdc_scalar width, pdc_scalar height); +void pdf__begin_page_ext(PDF *p, pdc_scalar width, pdc_scalar height, + const char *optlist); +void pdf__end_page_ext(PDF *p, const char *optlist); +void pdf__resume_page(PDF *p, const char *optlist); +void pdf__suspend_page(PDF *p, const char *optlist); +void pdf_pg_resume(PDF *p, int pageno); +void pdf_pg_suspend(PDF *p); + +void pdf_init_pages(PDF *p, const char **groups, int n_groups); +void pdf_init_pages2(PDF *p); +void pdf_check_suspended_pages(PDF *p); +void pdf_cleanup_pages(PDF *p); +pdc_id pdf_get_page_id(PDF *p, int n); +int pdf_current_page(PDF *p); +int pdf_current_page_id(PDF *p); +int pdf_last_page(PDF *p); +int pdf_search_page_fwd(PDF *p, int start_page, pdc_id id); +int pdf_search_page_bwd(PDF *p, int start_page, pdc_id id); +int pdf_xlat_pageno(PDF *p, int pageno, const char *groupname); + +double pdf_get_pageheight(PDF *p); +const pdc_rectangle *pdf_get_pagebox(PDF *p, pdf_pagebox box); +void pdf_set_pagebox_llx(PDF *p, pdf_pagebox box, pdc_scalar llx); +void pdf_set_pagebox_lly(PDF *p, pdf_pagebox box, pdc_scalar lly); +void pdf_set_pagebox_urx(PDF *p, pdf_pagebox box, pdc_scalar urx); +void pdf_set_pagebox_ury(PDF *p, pdf_pagebox box, pdc_scalar ury); +void pdf_set_pagebox(PDF *p, pdf_pagebox box, pdc_scalar llx, pdc_scalar lly, + pdc_scalar urx, pdc_scalar ury); + +pdc_vtr *pdf_get_annots_list(PDF *p); +void pdf_set_annots_list(PDF *p, pdc_vtr *annots); +pdc_id pdf_get_thumb_id(PDF *p); +void pdf_set_thumb_id(PDF *p, pdc_id id); + +void pdf_begin_contents_section(PDF *p); +void pdf_end_contents_section(PDF *p); +void pdf_add_reslist(PDF *p, pdf_reslist *rl, int num); +pdc_id pdf_write_pagelabels(PDF *p); + + + +/********************** + * + * p_parameter.c + * + **********************/ + +const char *pdf__get_parameter(PDF *p, const char *key, double modifier); +double pdf__get_value(PDF *p, const char *key, double modifier); +void pdf__set_parameter(PDF *p, const char *key, const char *value); +void pdf__set_value(PDF *p, const char *key, double value); + + +/********************** + * + * p_pattern.c + * + **********************/ + +int pdf__begin_pattern(PDF *p, + pdc_scalar width, pdc_scalar height, pdc_scalar xstep, pdc_scalar ystep, + int painttype); + +void pdf__end_pattern(PDF *p); + +void pdf_init_pattern(PDF *p); +void pdf_write_page_pattern(PDF *p); +void pdf_get_page_patterns(PDF *p, pdf_reslist *rl); +void pdf_mark_page_pattern(PDF *p, int n); +void pdf_cleanup_pattern(PDF *p); +void pdf_grow_pattern(PDF *p); + + + + +/********************** + * + * p_shading.c + * + **********************/ + +int pdf__shading(PDF *p, const char *shtype, pdc_scalar x_0, pdc_scalar y_0, + pdc_scalar x_1, pdc_scalar y_1, pdc_scalar c_1, pdc_scalar c_2, + pdc_scalar c_3, pdc_scalar c_4, const char *optlist); +int pdf__shading_pattern(PDF *p, int shading, const char *optlist); +void pdf__shfill(PDF *p, int shading); + +void pdf_init_shadings(PDF *p); +void pdf_write_page_shadings(PDF *p); +void pdf_get_page_shadings(PDF *p, pdf_reslist *rl); +void pdf_mark_page_shading(PDF *p, int n); +void pdf_cleanup_shadings(PDF *p); +int pdf_get_shading_painttype(PDF *p); + + + + + + +/********************** + * + * p_template.c + * + **********************/ + +int pdf__begin_template(PDF *p, pdc_scalar width, pdc_scalar height, + const char *optlist); +void pdf__end_template(PDF *p); +int pdf_embed_image(PDF *p, int im); + + +/********************** + * + * p_text.c + * + **********************/ + +void pdf__fit_textline(PDF *p, const char *text, int len, + pdc_scalar x, pdc_scalar y, const char *optlist); +double pdf__info_textline(PDF *p, const char *text, int len, + const char *keyword, const char *optlist); +void pdf__setfont(PDF *p, int font, pdc_scalar fontsize); +void pdf__set_text_pos(PDF *p, pdc_scalar x, pdc_scalar y); +void pdf__show_text(PDF *p, const char *text, int len, pdc_bool cont); +void pdf__xshow(PDF *p, const char *text, int len, + const pdc_scalar *xadvancelist); +int pdf__show_boxed(PDF *p, const char *text, int len, + pdc_scalar left, pdc_scalar top, pdc_scalar width, pdc_scalar height, + const char *hmode, const char *feature); +pdc_scalar pdf__stringwidth(PDF *p, const char *text, int len, + int font, pdc_scalar size); + +void pdf_init_tstate(PDF *p); +void pdf_cleanup_page_tstate(PDF *p, pdf_ppt *ppt); +void pdf_save_tstate(PDF *p); +void pdf_restore_currto(PDF *p); +void pdf_set_tstate(PDF *p, pdc_scalar value, pdf_text_optflags flag); +double pdf_get_tstate(PDF *p, pdf_text_optflags tflag); +void pdf_end_text(PDF *p); +void pdf_reset_tstate(PDF *p); +int pdf_get_font(PDF *p); +void pdf_put_fieldtext(PDF *p, const char *text, int font); +int pdf_get_fontsize_option(PDF *p, int font, pdc_resopt *resopts, + pdc_scalar *fontsize); + + + + + +/********************** + * + * p_type3.c + * + **********************/ + +void pdf__begin_font(PDF *p, const char *fontname, int len, + pdc_scalar a, pdc_scalar b, pdc_scalar c, pdc_scalar d, + pdc_scalar e, pdc_scalar f, const char *optlist); +void pdf__begin_glyph(PDF *p, const char *glyphname, pdc_scalar wx, + pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury); +void pdf__end_font(PDF *p); +void pdf__end_glyph(PDF *p); + +int pdf_get_t3colorized(PDF *p); + + +/********************** + * + * p_util.c + * + **********************/ + +const char *pdf__utf32_to_utf16(PDF *p, const char *utf32string, int len, + const char *ordering, int *outlen); +const char *pdf__utf16_to_utf8(PDF *p, const char *utf16string, int len, + int *outlen); +const char *pdf__utf8_to_utf16(PDF *p, const char *utf8string, + const char *ordering, int *outlen); + +void pdf_check_textformat(PDF *p, pdc_text_format textformat); +void pdf_check_hypertextformat(PDF *p, pdc_text_format hypertextformat); +void pdf_check_hypertextencoding(PDF *p, pdc_encoding hypertextencoding); +void pdf_put_pdfname(PDF *p, const char *name); +pdc_encoding pdf_get_hypertextencoding_opt(PDF *p, pdc_resopt *resopts, + int *codepage, pdc_bool verbose); +char *pdf_convert_hypertext_depr(PDF *p, const char *text, int len); +char *pdf_convert_hypertext(PDF *p, const char *text, int len, + pdc_text_format hypertextformat, pdc_encoding hypertextencoding, + int codepage, int *outlen, pdc_bool oututf8, pdc_bool verbose); +void pdf_put_hypertext(PDF *p, const char *text); +char *pdf_convert_name(PDF *p, const char *name, int len, int flags); +const char *pdf_convert_filename(PDF *p, const char *filename, int len, + const char *paramname, int flags); +void pdf_add_resource(PDF *p, const char *category, const char *resname); +void pdf_put_pdffilename(PDF *p, const char *text); +void pdf_check_handle(PDF *p, int value, pdc_opttype type); +void pdf_set_clientdata(PDF *p, pdc_clientdata *clientdata); +void pdf_init_stringlists(PDF *p); +int pdf_insert_stringlist(PDF *p, char **stringlist, int ns); +void pdf_cleanup_stringlists(PDF *p); +int pdf_insert_utilstring(PDF *p, const char *utilstring, pdc_bool kdup); +const char *pdf_get_utilstring(PDF *p, int i); +int pdf_get_opt_textlist(PDF *p, const char *keyword, pdc_resopt *resopts, + pdc_encoding enc, int codepage, pdc_bool ishypertext, + const char *fieldname, char **text, char ***textlist); +char *pdf_get_opt_utf8name(PDF *p, const char *keyword, pdc_resopt *resopts); +pdc_bool pdf_get_errorpolicy(PDF *p, pdc_resopt *resopts, pdc_bool verbose); + + +/********************** + * + * p_xgstate.c + * + **********************/ + +int pdf__create_gstate(PDF *p, const char *optlist); +void pdf__set_gstate(PDF *p, int gstate); + +void pdf_init_extgstates(PDF *p); +void pdf_write_page_extgstates(PDF *p); +void pdf_get_page_extgstates(PDF *p, pdf_reslist *rl); +void pdf_mark_page_extgstate(PDF *p, int n); +void pdf_write_doc_extgstates(PDF *p); +void pdf_cleanup_extgstates(PDF *p); +pdc_id pdf_get_gstate_id(PDF *p, int gstate); + + + + +#endif /* P_INTERN_H */ + + + + + diff --git a/src/pdflib/pdflib/p_jpeg.c b/src/pdflib/pdflib/p_jpeg.c new file mode 100644 index 0000000..467f282 --- /dev/null +++ b/src/pdflib/pdflib/p_jpeg.c @@ -0,0 +1,1560 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_jpeg.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * JPEG processing for PDFlib + * + */ + +#include "p_intern.h" +#include "p_color.h" +#include "p_image.h" + +#ifndef PDF_JPEG_SUPPORTED + +pdc_bool +pdf_is_JPEG_file(PDF *p, pdc_file *fp) +{ + (void) p; + (void) fp; + + return pdc_false; +} + +int +pdf_process_JPEG_data( + PDF *p, + int imageslot) +{ + pdf_image *image = &p->images[imageslot]; + + pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "JPEG", 0, 0, 0); + + return -1; +} + +/* CDPDF - added missing function */ +void +pdf_cleanup_jpeg(PDF *p, pdf_image *image) +{ + (void) p; + (void) image; +} + +#else + +#include "jinclude.h" +#include "jpeglib.h" + +/* + * The following enum is stolen from the IJG JPEG library + * Comments added by tm. + * This table contains far too many names since PDFlib + * is rather simple-minded about markers. + */ + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, /* baseline DCT */ + M_SOF1 = 0xc1, /* extended sequential DCT */ + M_SOF2 = 0xc2, /* progressive DCT */ + M_SOF3 = 0xc3, /* lossless (sequential) */ + + M_SOF5 = 0xc5, /* differential sequential DCT */ + M_SOF6 = 0xc6, /* differential progressive DCT */ + M_SOF7 = 0xc7, /* differential lossless */ + + M_JPG = 0xc8, /* JPEG extensions */ + M_SOF9 = 0xc9, /* extended sequential DCT */ + M_SOF10 = 0xca, /* progressive DCT */ + M_SOF11 = 0xcb, /* lossless (sequential) */ + + M_SOF13 = 0xcd, /* differential sequential DCT */ + M_SOF14 = 0xce, /* differential progressive DCT */ + M_SOF15 = 0xcf, /* differential lossless */ + + M_DHT = 0xc4, /* define Huffman tables */ + + M_DAC = 0xcc, /* define arithmetic conditioning table */ + + M_RST0 = 0xd0, /* restart */ + M_RST1 = 0xd1, /* restart */ + M_RST2 = 0xd2, /* restart */ + M_RST3 = 0xd3, /* restart */ + M_RST4 = 0xd4, /* restart */ + M_RST5 = 0xd5, /* restart */ + M_RST6 = 0xd6, /* restart */ + M_RST7 = 0xd7, /* restart */ + + M_SOI = 0xd8, /* start of image */ + M_EOI = 0xd9, /* end of image */ + M_SOS = 0xda, /* start of scan */ + M_DQT = 0xdb, /* define quantization tables */ + M_DNL = 0xdc, /* define number of lines */ + M_DRI = 0xdd, /* define restart interval */ + M_DHP = 0xde, /* define hierarchical progression */ + M_EXP = 0xdf, /* expand reference image(s) */ + + M_APP0 = 0xe0, /* application marker, used for JFIF */ + M_APP1 = 0xe1, /* application marker, used for Exif */ + M_APP2 = 0xe2, /* application marker, used for FlashPix* + * and ICC Profiles */ + M_APP3 = 0xe3, /* application marker */ + M_APP4 = 0xe4, /* application marker */ + M_APP5 = 0xe5, /* application marker */ + M_APP6 = 0xe6, /* application marker */ + M_APP7 = 0xe7, /* application marker */ + M_APP8 = 0xe8, /* application marker, used for SPIFF */ + M_APP9 = 0xe9, /* application marker */ + M_APP10 = 0xea, /* application marker */ + M_APP11 = 0xeb, /* application marker */ + M_APP12 = 0xec, /* application marker */ + M_APP13 = 0xed, /* application marker, used by Photoshop*/ + M_APP14 = 0xee, /* application marker, used by Adobe */ + M_APP15 = 0xef, /* application marker */ + + M_JPG0 = 0xf0, /* reserved for JPEG extensions */ + M_JPG13 = 0xfd, /* reserved for JPEG extensions */ + M_COM = 0xfe, /* comment */ + + M_TEM = 0x01 /* temporary use */ + +} JPEG_MARKER; + +#define JPEG_SEGLIST_CHUNKSIZE 64 +#define JPEG_MARKER_LEN 2 +#define JPEG_LENGTH_LEN 2 +#define JPEG_BUFSIZE 0xFFFF + +struct pdf_jpeg_segment_s +{ + long pos; /* position of segment */ + size_t length; /* length of segement in byte */ +}; + +static void +pdf_register_JPEG_segment(PDF *p, pdf_image *image, long pos, size_t length) +{ + static const char fn[] = "pdf_register_JPEG_segment"; + pdf_jpeg_info *jpeg = &image->info.jpeg; + size_t len; + + pdc_logg_cond(p->pdc, 5, trc_image, + "\t\tKeep segment, position = 0x%lX, length = 0x%lX(%ld)\n", + pos, length, length); + + while(length > 0) + { + len = length; + if (len > JPEG_BUFSIZE) + len = JPEG_BUFSIZE; + + if (jpeg->number >= jpeg->capacity) + { + if (jpeg->capacity == 0) + { + jpeg->capacity = JPEG_SEGLIST_CHUNKSIZE; + jpeg->seglist = (pdf_jpeg_segment *) pdc_malloc(p->pdc, + jpeg->capacity * sizeof(pdf_jpeg_segment), fn); + } + else + { + jpeg->capacity += JPEG_SEGLIST_CHUNKSIZE; + jpeg->seglist = (pdf_jpeg_segment *) pdc_realloc(p->pdc, + jpeg->seglist, jpeg->capacity* sizeof(pdf_jpeg_segment), fn); + } + } + jpeg->seglist[jpeg->number].pos = pos; + jpeg->seglist[jpeg->number].length = len; + jpeg->number++; + + length -= len; + pos += len; + } +} + +static void +pdf_data_source_JPEG_init(PDF *p, PDF_data_source *src) +{ + static const char fn[] = "pdf_data_source_JPEG_init"; + pdf_image *image; + pdf_jpeg_info *jpeg; + + image = (pdf_image *) src->private_data; + jpeg = &image->info.jpeg; + + jpeg->capacity = jpeg->number; + jpeg->number = 0; + + src->buffer_start = (pdc_byte *) pdc_malloc(p->pdc, JPEG_BUFSIZE, fn); + src->buffer_length = JPEG_BUFSIZE; +} + +static pdc_bool +pdf_data_source_JPEG_fill(PDF *p, PDF_data_source *src) +{ + pdf_image *image; + pdf_jpeg_info *jpeg; + size_t length; + long pos; + + (void) p; + + image = (pdf_image *) src->private_data; + jpeg = &image->info.jpeg; + + if (jpeg->number < jpeg->capacity) + { + pos = jpeg->seglist[jpeg->number].pos; + length = jpeg->seglist[jpeg->number].length; + jpeg->number++; + + pdc_fseek(image->fp, pos, SEEK_SET); + src->next_byte = src->buffer_start; + src->bytes_available = + pdc_fread(src->buffer_start, 1, length, image->fp); + } + else + { + src->bytes_available = 0; + } + + if (src->bytes_available == 0) + return pdc_false; + else + return pdc_true; +} + +static void +pdf_data_source_JPEG_terminate(PDF *p, PDF_data_source *src) +{ + pdc_free(p->pdc, (void *) src->buffer_start); +} + +/********************************************************************** + * + * Decompression data source routines for the case of + * reading JPEG data from a PDFlib virtual file in + * JPEG library - analogous to ../libs/jpeg/jdatasrc.c + * + **********************************************************************/ + +typedef struct +{ + struct jpeg_source_mgr pub; /* public fields */ + pdc_file *infile; + PDF *p; /* required for logging only */ + pdf_image *image; /* required for access to the filename */ +} +pdf_source_mgr; + +typedef pdf_source_mgr * pdf_src_ptr; + +static void +pdf_init_JPEG_source (j_decompress_ptr cinfo) +{ + (void) cinfo; +} + +static boolean +pdf_fill_JPEG_input_buffer (j_decompress_ptr cinfo) +{ + pdf_src_ptr src = (pdf_src_ptr) cinfo->src; + JOCTET *buffer; + size_t nbytes; + + buffer = (JOCTET *) pdc_freadall(src->infile, &nbytes, NULL); + + src->pub.next_input_byte = buffer; + src->pub.bytes_in_buffer = nbytes; + + return TRUE; +} + +static void +pdf_skip_JPEG_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + pdf_src_ptr src = (pdf_src_ptr) cinfo->src; + + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; +} + +static void +pdf_term_JPEG_source (j_decompress_ptr cinfo) +{ + (void) cinfo; +} + +static void +pdf_jpeg_pdcread_src(j_decompress_ptr cinfo, + PDF *p, pdc_file *infile, pdf_image *image) +{ + pdf_src_ptr src; + + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(pdf_source_mgr)); + + src = (pdf_src_ptr) cinfo->src; + src->pub.init_source = pdf_init_JPEG_source; + src->pub.fill_input_buffer = pdf_fill_JPEG_input_buffer; + src->pub.skip_input_data = pdf_skip_JPEG_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; + src->pub.term_source = pdf_term_JPEG_source; + src->infile = infile; + src->p = p; + src->image = image; + src->pub.bytes_in_buffer = 0; + src->pub.next_input_byte = NULL; +} + +/********************************************************************** + * + * Compression data destination routines for the case of + * emitting JPEG data to a open PDFlib PDF file in + * JPEG library - analogous to ../libs/jpeg/jdatadst.c + * + **********************************************************************/ + +typedef struct +{ + struct jpeg_destination_mgr pub; + PDF *p; + pdf_image *image; /* required for access to the filename */ + JOCTET *buffer; +} +pdf_destination_mgr; + +typedef pdf_destination_mgr * pdf_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 + +static void +pdf_init_JPEG_destination (j_compress_ptr cinfo) +{ + pdf_dest_ptr dest = (pdf_dest_ptr) cinfo->dest; + + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + +static boolean +pdf_empty_JPEG_output_buffer (j_compress_ptr cinfo) +{ + pdf_dest_ptr dest = (pdf_dest_ptr) cinfo->dest; + + pdc_write(dest->p->out, dest->buffer, OUTPUT_BUF_SIZE); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return TRUE; +} + +static void +pdf_term_JPEG_destination (j_compress_ptr cinfo) +{ + pdf_dest_ptr dest = (pdf_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + if (datacount) + pdc_write(dest->p->out, dest->buffer, datacount); +} + +static void +pdf_jpeg_pdcwrite_dest(j_compress_ptr cinfo, PDF *p, pdf_image *image) +{ + pdf_dest_ptr dest; + + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(pdf_destination_mgr)); + + dest = (pdf_dest_ptr) cinfo->dest; + dest->pub.init_destination = pdf_init_JPEG_destination; + dest->pub.empty_output_buffer = pdf_empty_JPEG_output_buffer; + dest->pub.term_destination = pdf_term_JPEG_destination; + dest->p = p; + dest->image = image; +} + +/**********************************************************************/ + +#define PDF_JMSG_LENGTH_MAX 200 + +/* + * Private replacements for libjpeg's error message function. + * They serve two purposes: + * - avoid libjpeg writing to stderr + * - write the message to the log file if logging is enabled + * One function is required for each source and destination. + */ + +static void +pdf_output_message_src(j_common_ptr cinfo) +{ + char buffer[PDF_JMSG_LENGTH_MAX]; + + /* we use this method only for decompression objects */ + j_decompress_ptr cinfo2 = (j_decompress_ptr) cinfo; + pdf_source_mgr *src = (pdf_source_mgr *) cinfo2->src; + + if (!pdc_logg_is_enabled(src->p->pdc, 5, trc_image)) + return; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + + pdc_logg(src->p->pdc, "\tlibjpeg src: %s\n", buffer); +} + +static void +pdf_output_message_dst(j_common_ptr cinfo) +{ + char buffer[PDF_JMSG_LENGTH_MAX]; + + /* we use this method only for compression objects */ + j_compress_ptr cinfo2 = (j_compress_ptr) cinfo; + pdf_destination_mgr *dst = (pdf_destination_mgr *) cinfo2->dest; + + if (!pdc_logg_is_enabled(dst->p->pdc, 5, trc_image)) + return; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + + pdc_logg(dst->p->pdc, "\tlibjpeg dst: %s\n", buffer); +} + +/* + * Private replacements for libjpeg's error_exit function. + * They serve three purposes: + * - avoid libjpeg exiting + * - write a message to the log file if logging is enabled + * - return control from libjpeg by raising an exception + * One function is required for each source and destination. + */ + +static void +pdf_error_exit_src(j_common_ptr cinfo) +{ + PDF *p; + pdf_image *image; + char buffer[PDF_JMSG_LENGTH_MAX]; + + /* we use this method only for decompression objects */ + j_decompress_ptr cinfo2 = (j_decompress_ptr) cinfo; + pdf_source_mgr *src = (pdf_source_mgr *) cinfo2->src; + + p = src->p; + image = src->image; + + (*cinfo->err->output_message) (cinfo); + (*cinfo->err->format_message) (cinfo, buffer); + + if (pdc_logg_is_enabled(p->pdc, 5, trc_image)) + pdc_logg(p->pdc, "\tlibjpeg (src) called error_exit routine\n"); + + /* clean up libjpeg */ + jpeg_destroy(cinfo); + + pdc_error(p->pdc, PDF_E_JPEG_TRANSCODE, + pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, image->filename), + buffer, 0, 0); +} + +static void +pdf_error_exit_dst(j_common_ptr cinfo) +{ + PDF *p; + pdf_image *image; + char buffer[PDF_JMSG_LENGTH_MAX]; + + /* we use this method only for compression objects */ + j_compress_ptr cinfo2 = (j_compress_ptr) cinfo; + pdf_destination_mgr *dst = (pdf_destination_mgr *) cinfo2->dest; + + p = dst->p; + image = dst->image; + + (*cinfo->err->output_message) (cinfo); + (*cinfo->err->format_message) (cinfo, buffer); + + if (pdc_logg_is_enabled(p->pdc, 5, trc_image)) + pdc_logg(p->pdc, "\tlibjpeg (dst) called error_exit routine\n"); + + /* clean up libjpeg */ + jpeg_destroy(cinfo); + + pdc_error(p->pdc, PDF_E_JPEG_TRANSCODE, + pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, image->filename), + buffer, 0, 0); +} + +static pdc_bool +pdf_data_source_JPEG_fill_transcode(PDF *p, PDF_data_source *src) +{ + pdf_image *image = (pdf_image *) src->private_data; + pdc_bool logg5 = pdc_logg_is_enabled(p->pdc, 5, trc_image); + + struct jpeg_decompress_struct srcinfo; + struct jpeg_compress_struct dstinfo; + jvirt_barray_ptr * src_coef_arrays; + struct jpeg_error_mgr jsrcerr, jdsterr; + + /* ---------- Setup for decompression ---------- */ + /* Initialize the JPEG decompression object with default error handling. */ + srcinfo.err = jpeg_std_error(&jsrcerr); + + /* Hook up our own message handler for logging */ + srcinfo.err->output_message = pdf_output_message_src; + + /* Hook up our own fatal error handler */ + srcinfo.err->error_exit = pdf_error_exit_src; + + /* Extended libjpeg tracing if PDFlib logging is enabled */ + if (logg5) + srcinfo.err->trace_level = 5; + + jpeg_create_decompress(&srcinfo); + + /* Specify data source for decompression analogous to jpeg_stdio_src */ + pdf_jpeg_pdcread_src(&srcinfo, p, image->fp, image); + + /* ---------- Setup for compression ---------- */ + /* Initialize the JPEG compression object with default error handling. */ + dstinfo.err = jpeg_std_error(&jdsterr); + + /* Hook up our own message handler for logging */ + dstinfo.err->output_message = pdf_output_message_dst; + + /* Hook up our own fatal error handler */ + dstinfo.err->error_exit = pdf_error_exit_dst; + + /* Extended libjpeg tracing if PDFlib logging is enabled */ + if (logg5) + dstinfo.err->trace_level = 5; + + jpeg_create_compress(&dstinfo); + + PDC_TRY(p->pdc) + { + /* ---------- start transcoding ---------- */ + + /* Read file header */ + if (jpeg_read_header(&srcinfo, TRUE) != JPEG_HEADER_OK) + { + if (logg5) + pdc_logg(p->pdc, "\tlibjpeg couldn't read header\n"); + + pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "JPEG", + pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, + image->filename), 0, 0); + } + + /* Read source file as DCT coefficients */ + src_coef_arrays = jpeg_read_coefficients(&srcinfo); + if (src_coef_arrays == NULL) + { + if (logg5) + pdc_logg(p->pdc, "\tlibjpeg couldn't read coefficients\n"); + + pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "JPEG", + pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, + image->filename), 0, 0); + } + + /* Initialize destination compression parameters from source values */ + jpeg_copy_critical_parameters(&srcinfo, &dstinfo); + + /* Specify data destination for compression analogous to + * jpeg_stdio_dest + */ + pdf_jpeg_pdcwrite_dest(&dstinfo, p, image); + + /* Start compressor (note no image data is actually written here) */ + jpeg_write_coefficients(&dstinfo, src_coef_arrays); + + /* Finish compression */ + /* DON'T change the order! */ + jpeg_finish_compress(&dstinfo); + (void) jpeg_finish_decompress(&srcinfo); + } + PDC_CATCH(p->pdc) + { + image->corrupt = pdc_true; + } + + /* Release memory */ + jpeg_destroy_compress(&dstinfo); + jpeg_destroy_decompress(&srcinfo); + + /* All done. Check for errors */ + if (jsrcerr.num_warnings != 0 && logg5) + { + /* + * We don't really care about problems in the input since + * they will be fixed by transcoding. Log them, but don't throw an + * exception. + */ + pdc_logg(p->pdc, + "\tlibjpeg total: %d corrupt data warning(s)\n", + jsrcerr.num_warnings); + } + + if (jdsterr.num_warnings != 0) + { + char buffer[PDF_JMSG_LENGTH_MAX]; + + /* + * Errors in the output are rare, but fatal. Log them, + * and unconditionally throw an exception. + */ + if (logg5) + { + pdc_logg(p->pdc, "\tlibjpeg: %d warning(s) for output\n", + jdsterr.num_warnings); + } + + (dstinfo.err->format_message) ((j_common_ptr) &dstinfo, buffer); + pdc_set_errmsg(p->pdc, PDF_E_JPEG_TRANSCODE, + pdf_get_image_filename(p, image), buffer, 0, 0); + + image->corrupt = pdc_true; + } + + return pdc_false; +} + +static pdc_ushort +get_ushort(pdc_file *fp) +{ + pdc_byte c[2]; + + c[0] = (pdc_byte) pdc_fgetc(fp); + c[1] = (pdc_byte) pdc_fgetc(fp); + + return pdc_get_be_ushort(c); +} + +#define CHECK_LENGTH 1024L + +pdc_bool +pdf_is_JPEG_file(PDF *p, pdc_file *fp) +{ + long pos = 0L; + int c; + long start = (long) pdc_ftell(fp); + long check_length = start + CHECK_LENGTH; + + pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type JPEG...\n"); + +#if !defined(MVS) || !defined(I370) + /* Tommy's special trick for Macintosh JPEGs: simply skip some */ + /* hundred bytes at the beginning of the file! */ + do + { + do /* skip if not FF */ + { + c = pdc_fgetc(fp); + pos++; + + } + while (!pdc_feof(fp) && c != 0xFF && pos < check_length); + + if (pdc_feof(fp) || pos >= check_length) + { + pdc_fseek(fp, start, SEEK_SET); + return pdc_false; + } + + do /* skip repeated FFs */ + { + c = pdc_fgetc(fp); + pos++; + } + while (c == 0xFF && pos < check_length); + + /* remember start position */ + pos = (pdc_off_t1) pdc_ftell(fp); + if (pos < 0L || pos >= check_length) + { + pdc_fseek(fp, start, SEEK_SET); + return pdc_false; + } + + pos -= JPEG_MARKER_LEN; /* subtract marker length */ + + if (c == M_SOI) + { + pdc_fseek(fp, pos, SEEK_SET); + break; + } + } + while (!pdc_feof(fp)); +#endif /* !MVS || !I370 */ + +#define BOGUS_LENGTH 768 + /* If we are that far from the start we consider the image as damaged if: + * - OJPEG-TIFF: it does not start at the alleged data offset + * - any other flavor: it has too much garbage at the beginning + */ + if (pdc_feof(fp) || pos > (start ? start : BOGUS_LENGTH)) + { + pdc_fseek(fp, start, SEEK_SET); + return pdc_false; + } + + return pdc_true; +} + +/* This function should be moved to p_color.c once it gets used by other + * image modules as well. + */ + +static void +pdf_log_colorspace(PDF *p, int slot) +{ + pdf_colorspace *cs; + + if (slot < 0 || slot >= p->colorspaces_number) + { + pdc_logg(p->pdc, " Bad color space slot %d", slot); + } + + cs = &p->colorspaces[slot]; + + switch (cs->type) { + case DeviceGray: + pdc_logg(p->pdc, "/DeviceGray"); + break; + + case DeviceRGB: + pdc_logg(p->pdc, "/DeviceRGB"); + break; + + case DeviceCMYK: + pdc_logg(p->pdc, "/DeviceCMYK"); + break; + + + case Indexed: + pdc_logg(p->pdc, "/Indexed"); + break; + + case PatternCS: + pdc_logg(p->pdc, "/Pattern"); + break; + + default: + pdc_logg(p->pdc, "%d (unknown)", cs->type); + } +} + +/* open JPEG image and analyze marker */ +int +pdf_process_JPEG_data( + PDF *p, + int imageslot) +{ + int c, unit; + unsigned long length, len = 0, slen; +#define APP_MAX 255 + pdc_byte appstring[APP_MAX]; + const char *filename = NULL; + pdc_bool ismem = pdc_false; + void *filebase = NULL; + size_t filelen; + pdf_image *image; + int transform = 0; + pdc_bool marker_found = pdc_false; + pdc_bool markers_done = pdc_false; + pdc_bool need_transcode = pdc_false; + pdc_bool logg5 = pdc_logg_is_enabled(p->pdc, 5, trc_image); + long pos = 0, endpos = 0; + long adobe_pos = 0, adobe_len = 0; + int errint = 0; + int errcode = 0; + + image = &p->images[imageslot]; + image->compression = pdf_comp_dct; + image->use_raw = pdc_true; + image->info.jpeg.virtfile = NULL; + image->info.jpeg.seglist = NULL; + image->info.jpeg.capacity = 0; + image->info.jpeg.number = 0; + + need_transcode = !image->passthrough; + + if (logg5) + { + pdc_logg(p->pdc, "\tjpegoptimize = %s\n", + image->jpegoptimize ? "true" : "false"); + if (need_transcode) + pdc_logg(p->pdc, "\ttranscoding...\n"); + else + pdc_logg(p->pdc, "\ttranscoding disabled by passthrough option\n"); + } + + /* jpeg file not available */ + if (image->reference != pdf_ref_direct) + { + + + image->in_use = pdc_true; /* mark slot as used */ + pdf_put_image(p, imageslot, pdc_true, pdc_true); + return imageslot; + } + + if (!pdc_file_isvirtual(image->fp)) + { + /* read whole file */ + filebase = (void *) pdc_freadall(image->fp, &filelen, &ismem); + if (filebase == NULL) + { + errcode = PDC_E_IO_READ; + goto PDF_JPEG_ERROR; + } + pdc_fclose(image->fp); + + /* temporary memory */ + pdc_insert_mem_tmp(p->pdc, filebase, 0, 0); + + /* create virtual image file */ + filename = "__jpeg__image__data__"; + pdc__create_pvf(p->pdc, filename, filebase, filelen, ""); + image->info.jpeg.virtfile = filename; + + if (logg5) + { + pdc_logg(p->pdc, "\tVirtual file created, " + "length = 0x%lX(%ld)\n", filelen, filelen); + } + + /* open virtual file */ + image->fp = pdc_fsearch_fopen(p->pdc, filename, NULL, "", + PDC_FILE_BINARY); + } + + if (image->info.jpeg.jpegifoffset) + { + /* Just to be sure: if we were handed a OJPEG-compressed TIFF with + * an offset we let libjpeg transcode. + */ + need_transcode = pdc_true; + + if (logg5) + { + pdc_logg(p->pdc, + "\ttranscoding because of OJPEG-compressed TIFF\n"); + pdc_logg(p->pdc, + "\tseeking to base offset 0x%lX(%ld) (TIFF with OJPEG)\n", + image->info.jpeg.jpegifoffset, image->info.jpeg.jpegifoffset); + } + pdc_fseek(image->fp, image->info.jpeg.jpegifoffset, SEEK_SET); + } + + if (pdf_is_JPEG_file(p, image->fp) == pdc_false) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_JPEG_ERROR; + } + + /* JPEG marker loop */ + while (1) + { + /* look for next JPEG Marker */ + if (!markers_done) + { + do /* repeat if FF/00 */ + { + do /* skip to FF */ + { + if (pdc_feof(image->fp)) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_JPEG_ERROR; + } + c = pdc_fgetc(image->fp); + } + while (c != 0xFF); + + do /* skip repeated FFs */ + { + if (pdc_feof(image->fp)) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_JPEG_ERROR; + } + c = pdc_fgetc(image->fp); + } + while (c == 0xFF); + } + while (c == 0); + + /* start of new segment */ + pos = (pdc_off_t1) pdc_ftell(image->fp) - JPEG_MARKER_LEN; + + /* skip garbage at the start of image data */ + if (!marker_found && pos > 0) + { + if (logg5 && pos > (long) image->info.jpeg.jpegifoffset) + { + pdc_logg(p->pdc, "\t0x%lX(%ld) bytes garbage " + "at start of image\n", pos, pos); + } + + /* we must create a new virtual file */ + if (image->info.jpeg.virtfile == 0) + { + /* read whole file */ + filebase = (void *) pdc_freadall(image->fp, + &filelen, &ismem); + if (filebase == NULL) + { + errcode = PDC_E_IO_READ; + goto PDF_JPEG_ERROR; + } + + /* temporary memory */ + pdc_insert_mem_tmp(p->pdc, filebase, 0, 0); + + filename = "__jpeg__image__data__"; + } + else + { + /* delete virtual file */ + pdc__delete_pvf(p->pdc, image->info.jpeg.virtfile); + } + + /* [re]create virtual file */ + filelen -= pos; + memmove(filebase, (char *) filebase + pos, filelen); + pdc__create_pvf(p->pdc, filename, filebase, filelen, ""); + image->info.jpeg.virtfile = filename; + + if (logg5) + { + pdc_logg(p->pdc, "\tVirtual file created, " + "length = 0x%lX(%ld)\n", + filelen, filelen); + } + /* [re]open virtual file */ + pdc_fclose(image->fp); + image->fp = pdc_fsearch_fopen(p->pdc, filename, NULL, "", + PDC_FILE_BINARY); + + /* restart with the cleaned file */ + continue; + } + length = 0; + marker_found = pdc_true; + } + else + { + /* enforcing end of image */ + pos = (pdc_off_t1) pdc_ftell(image->fp); + pdc_fseek(image->fp, 0L, SEEK_END); + endpos = (pdc_off_t1) pdc_ftell(image->fp) - JPEG_MARKER_LEN; + length = endpos - pos; + c = M_EOI; + } + + /* analyzing JPEG Marker */ + switch (c) + { + /* markers which are not supported in PDF 1.3 and above */ + case M_SOF3: + case M_SOF5: + case M_SOF6: + case M_SOF7: + case M_SOF9: + case M_SOF11: + case M_SOF13: + case M_SOF14: + case M_SOF15: + { + if (logg5) + { + pdc_logg(p->pdc, "\tMarker 0x%X(SOF%d) found - " + "not supported\n", c, c - M_SOF0); + } + errint = c; + errcode = PDF_E_JPEG_COMPRESSION; + } + goto PDF_JPEG_ERROR; + + /* markers without any parameters */ + case M_SOI: + case M_TEM: + case M_EOI: + case M_RST0: + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + { + if (logg5) + { + pdc_logg(p->pdc, "\tMarker 0x%X", c); + if (c == M_EOI) + pdc_logg(p->pdc, "(EOI)"); + pdc_logg(p->pdc, " found - no contents\n"); + } + pdf_register_JPEG_segment(p, image, pos, + (size_t) (length + JPEG_MARKER_LEN)); + } + break; + + /* skip segment if jpegoptimize = true, otherwise keep */ + case M_APP0: + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP14: + case M_APP15: + case M_COM: + { + if (logg5) + { + pdc_logg(p->pdc, "\tMarker 0x%X", c); + if (c == M_COM) + pdc_logg(p->pdc, "(COM) found\n"); + else + pdc_logg(p->pdc, "(APP%d) found\n", c - M_APP0); + } + + length = get_ushort(image->fp); + if (!image->jpegoptimize) + pdf_register_JPEG_segment(p, image, pos, + (size_t) (length + JPEG_MARKER_LEN)); + else if (logg5) + pdc_logg(p->pdc, "\t\tSkip segment, position=0x%lX, " + "length=0x%lX(%ld)\n", + pos, length, length); + + /* We may have to register the Adobe marker later */ + if (c == M_APP14) + { + adobe_pos = pos; + adobe_len = length; + } + + length -= JPEG_LENGTH_LEN; + } + break; + + /* keep segment unconditionally */ + case M_SOF0: + case M_SOF1: + case M_SOF2: + case M_SOF10: + case M_SOS: + default: + { + if (logg5) + { + pdc_logg(p->pdc, "\tMarker 0x%X", c); + if (c == M_SOS) + pdc_logg(p->pdc, "(SOS) found\n"); + else if (c <= M_SOF15) + pdc_logg(p->pdc, "(SOF%d) found\n", c - M_SOF0); + else + pdc_logg(p->pdc, " found\n"); + } + + length = get_ushort(image->fp); + pdf_register_JPEG_segment(p, image, pos, + (size_t) (length + JPEG_MARKER_LEN)); + length -= JPEG_LENGTH_LEN; + } + break; + } + + /* end of image */ + if (c == M_EOI) + { + if (logg5) + { + pdc_logg(p->pdc, "\tEnd of image\n"); + } + break; + } + + /* processing JPEG Marker */ + switch (c) + { + /* check for frame header markers */ + case M_SOF0: + case M_SOF1: + case M_SOF2: + case M_SOF10: + { + int comp; + + image->bpc = pdc_fgetc(image->fp); + image->height = (pdc_scalar) get_ushort(image->fp); + image->width = (pdc_scalar) get_ushort(image->fp); + image->components = pdc_fgetc(image->fp); + length -= 6; + + for (comp=0; comp<image->components; comp++) + { + pdc_byte b; + + /* We don't support more than 4 components */ + if (comp==JPEG_MAX_COMPS) break; + + image->info.jpeg.id[comp] = pdc_fgetc(image->fp); + b = pdc_fgetc(image->fp); + image->info.jpeg.hsamp[comp] = (b >> 4) & 0x0F; + image->info.jpeg.vsamp[comp] = b & 0x0F; + image->info.jpeg.table[comp] = pdc_fgetc(image->fp); + length -= 3; + } + + /* + * No need to read more markers since multiscan detection + * not required for single-component images. + */ + if (image->components == 1) + markers_done = pdc_true; + + if (logg5) + { + pdc_logg(p->pdc, "\t\tbpc = %d\n", image->bpc); + pdc_logg(p->pdc, "\t\theight = %g\n", image->height); + pdc_logg(p->pdc, "\t\twidth = %g\n", image->width); + pdc_logg(p->pdc, "\t\tcomponents = %d\n", + image->components); + + for (comp=0; comp<image->components; comp++) + { + if (comp==JPEG_MAX_COMPS) + { + pdc_logg(p->pdc, "\t\tMore components found\n"); + break; + } + + if (pdc_logg_isprint((int) image->info.jpeg.id[comp])) + { + pdc_logg(p->pdc, + "\t\tcomponent 0x%x (name='%c'): " + "%dhx%dv table=%d\n", + image->info.jpeg.id[comp], + image->info.jpeg.id[comp], + image->info.jpeg.hsamp[comp], + image->info.jpeg.vsamp[comp], + image->info.jpeg.table[comp]); + } + else + { + pdc_logg(p->pdc, + "\t\tcomponent 0x%x: %dhx%dv table=%d\n", + image->info.jpeg.id[comp], + image->info.jpeg.hsamp[comp], + image->info.jpeg.vsamp[comp], + image->info.jpeg.table[comp]); + } + } + } + } + break; + + /* check for JFIF marker with resolution */ + case M_APP0: + { + len = MIN(APP_MAX, length); + if (!PDC_OK_FREAD(image->fp, appstring, len)) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_JPEG_ERROR; + } + length -= len; + + /* Check for JFIF application marker and read density values + * per JFIF spec version 1.02. + */ + +#define PDF_STRING_JFIF "\x4A\x46\x49\x46" + + slen = strlen(PDF_STRING_JFIF); + if (len > slen && + !strncmp(PDF_STRING_JFIF, (char *) appstring, slen)) + { + /* resolution unit and resolution */ + unit = appstring[7]; + image->dpi_x = (pdc_scalar) + pdc_get_be_ushort(&appstring[8]); + image->dpi_y = (pdc_scalar) + pdc_get_be_ushort(&appstring[10]); + +#define JFIF_ASPECT_RATIO 0 /* JFIF unit byte: aspect ratio only */ +#define JFIF_DOTS_PER_INCH 1 /* JFIF unit byte: dots per inch */ +#define JFIF_DOTS_PER_CM 2 /* JFIF unit byte: dots per cm */ + + switch (unit) + { + case JFIF_DOTS_PER_INCH: + break; + + case JFIF_DOTS_PER_CM: + image->dpi_x *= 100 * PDC_INCH2METER; + image->dpi_y *= 100 * PDC_INCH2METER; + break; + + case JFIF_ASPECT_RATIO: + image->dpi_x *= -1; + image->dpi_y *= -1; + break; + + /* unknown ==> ignore */ + default: + break; + } + + if (logg5) + { + pdc_logg(p->pdc, "\t\tJFIF marker found\n"); + pdc_logg(p->pdc, "\t\tJFIF density unit: %d", unit); + + switch (unit) + { + case JFIF_DOTS_PER_INCH: + pdc_logg(p->pdc, " (inch)\n"); + break; + + case JFIF_DOTS_PER_CM: + pdc_logg(p->pdc, " (cm)\n"); + break; + + case JFIF_ASPECT_RATIO: + pdc_logg(p->pdc, " (aspect ratio)\n"); + break; + + default: + pdc_logg(p->pdc, " (unknown; ignored)\n"); + break; + } + pdc_logg(p->pdc, "\t\tJFIF x resolution = %g\n", + image->dpi_x); + pdc_logg(p->pdc, "\t\tJFIF y resolution = %g\n", + image->dpi_y); + } + } + } + break; + + + /* check for Adobe marker */ + case M_APP14: + { + len = MIN(APP_MAX, length); + if (!PDC_OK_FREAD(image->fp, appstring, len)) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_JPEG_ERROR; + } + length -= len; + + /* + * Check for Adobe application marker. It is known + * (per Adobe's TN5116) + * to contain the string "Adobe" at the start + * of the APP14 marker. + */ + +#define PDF_STRING_Adobe "\x41\x64\x6F\x62\x65" + + slen = strlen(PDF_STRING_Adobe); + if (len > slen && + !strncmp(PDF_STRING_Adobe, (char *) appstring, slen)) + { + if (logg5) + { + pdc_byte *val = appstring+slen; + + pdc_logg(p->pdc, "\t\tAdobe marker found\n"); + + if (len >= 12) + { + pdc_logg(p->pdc, "\t\tversion = 0x%02X 0x%02X\n", + (unsigned char) val[0], (unsigned char) val[1]); + pdc_logg(p->pdc, "\t\tflags0 = 0x%02X 0x%02X\n", + (unsigned char) val[2], (unsigned char) val[3]); + pdc_logg(p->pdc, "\t\tflags1 = 0x%02X 0x%02X\n", + (unsigned char) val[4], (unsigned char) val[5]); + pdc_logg(p->pdc, "\t\tcolor transform = 0x%02X\n", + val[6]); + } + } + if (len >= 12) + transform = appstring[slen+6]; + + /* Keep Adobe marker for transform == 2 (YCCK) */ + if (transform == 2) + { + if (logg5) + pdc_logg(p->pdc, + "\t\tYCCK color space: Keep Adobe marker\n"); + + pdf_register_JPEG_segment(p, image, + adobe_pos, (size_t) (adobe_len + JPEG_MARKER_LEN)); + } + } + } + break; + + /* check for start of scan marker */ + case M_SOS: + { + pdc_byte comps = pdc_fgetc(image->fp); + length -= 1; + + if (logg5) + { + pdc_logg(p->pdc, "\t\tNumber of components in scan = " + "%d\n", comps); + } + + /* + * If the scan doesn't contain all components it must be + * a multiscan image, which doesn't work in Acrobat. + */ + + if (comps < image->components) + { + need_transcode = pdc_true; + if (logg5) + { + pdc_logg(p->pdc, + "\ttranscoding because of multiscan\n"); + } + } + + markers_done = pdc_true; + } + break; + + default: + break; + } + + /* jump to the next marker */ + if (length > 0) + { + if (pdc_fseek(image->fp, (long) length, SEEK_CUR) == -1) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_JPEG_ERROR; + } + } + } + + /* do some sanity checks with the parameters */ + if (image->height <= 0 || image->width <= 0 || image->components <= 0) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_JPEG_ERROR; + } + + if (image->bpc != 8) + { + errint = image->bpc; + errcode = PDF_E_IMAGE_BADDEPTH; + goto PDF_JPEG_ERROR; + } + + { + switch (image->components) { + case 1: + /* spot color may have been applied */ + if (image->colorspace == pdc_undef) + image->colorspace = DeviceGray; + break; + + case 3: + image->colorspace = DeviceRGB; + break; + + case 4: + image->colorspace = DeviceCMYK; + break; + + default: + errint = image->components; + errcode = PDF_E_IMAGE_BADCOMP; + goto PDF_JPEG_ERROR; + } + } + + + + if (image->imagemask) + { + if (image->components != 1) + { + errcode = PDF_E_IMAGE_BADMASK; + goto PDF_JPEG_ERROR; + } + + if (p->compatibility <= PDC_1_3) + { + errcode = PDF_E_IMAGE_MASK1BIT13; + goto PDF_JPEG_ERROR; + } + else + { + /* images with more than one bit will be written as /SMask, + * and don't require an /ImageMask entry. + */ + image->imagemask = pdc_false; + } + } + + if (logg5) + { + pdc_logg(p->pdc, "\tColorspace="); + pdf_log_colorspace(p, image->colorspace); + pdc_logg(p->pdc, "\n"); + } + + /* special handling for CMYK JPEG files */ + if (image->components == 4) + { + /* CMYK JPEGs use inverse polarity */ + image->invert = !image->invert; + if (logg5) + pdc_logg(p->pdc, + "\tinverting image because of 4 components\n"); + + /* Adobe and other CMYK JPEGs always require transcoding */ + need_transcode = pdc_true; + if (logg5) + pdc_logg(p->pdc, + "\ttranscoding image because of 4 components\n"); + + } + + image->in_use = pdc_true; /* mark slot as used */ + + if (need_transcode) + { + if (logg5) + { + pdc_logg(p->pdc, "\tcalling libjpeg for transcoding\n"); + } + image->src.init = NULL; + image->src.fill = pdf_data_source_JPEG_fill_transcode; + image->src.terminate = NULL; + } + else + { + image->src.init = pdf_data_source_JPEG_init; + image->src.fill = pdf_data_source_JPEG_fill; + image->src.terminate = pdf_data_source_JPEG_terminate; + } + + image->src.private_data = (void *) image; + + if (image->doinline) + pdf_put_inline_image(p, imageslot); + else + pdf_put_image(p, imageslot, pdc_true, pdc_true); + + if (!image->corrupt) + { + pdf_cleanup_jpeg(p, image); + + return imageslot; + } + + PDF_JPEG_ERROR: + { + const char *stemp = NULL; + + if (errcode) + stemp = pdf_get_image_filename(p, image); + + + switch (errcode) + { + case PDC_E_IO_READ: + case PDF_E_IMAGE_ICC: + case PDF_E_IMAGE_ICC2: + case PDF_E_IMAGE_COLORIZE: + case PDF_E_IMAGE_BADMASK: + case PDF_E_IMAGE_MASK1BIT13: + pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0); + break; + + case PDC_E_IO_BADFORMAT: + pdc_set_errmsg(p->pdc, errcode, stemp, "JPEG", 0, 0); + break; + + case PDF_E_IMAGE_CORRUPT: + pdc_set_errmsg(p->pdc, errcode, "JPEG", stemp, 0, 0); + break; + + case PDF_E_JPEG_COMPRESSION: + case PDF_E_IMAGE_BADDEPTH: + case PDF_E_IMAGE_BADCOMP: + pdc_set_errmsg(p->pdc, errcode, + pdc_errprintf(p->pdc, "%d", errint), stemp, 0, 0); + break; + + case 0: /* error code and message already set */ + break; + } + } + + pdf_cleanup_jpeg(p, image); + + return -1; +} + +void +pdf_cleanup_jpeg(PDF *p, pdf_image *image) +{ + if (image->info.jpeg.virtfile != NULL) + { + (void) pdc__delete_pvf(p->pdc, image->info.jpeg.virtfile); + image->info.jpeg.virtfile = NULL; + } + + if (image->info.jpeg.seglist != NULL) + { + pdc_free(p->pdc, image->info.jpeg.seglist); + image->info.jpeg.seglist = NULL; + } +} + + +#endif /* PDF_JPEG_SUPPORTED */ diff --git a/src/pdflib/pdflib/p_jpx.c b/src/pdflib/pdflib/p_jpx.c new file mode 100644 index 0000000..73e364c --- /dev/null +++ b/src/pdflib/pdflib/p_jpx.c @@ -0,0 +1,73 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_jpx.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * JPEG2000 processing for PDFlib + * + */ + +#include "p_intern.h" +#include "p_color.h" +#include "p_image.h" + +#ifndef PDF_JPX_SUPPORTED + +pdc_bool +pdf_is_JPX_file(PDF *p, pdc_file *fp) +{ + (void) p; + (void) fp; + + return pdc_false; +} + +int +pdf_process_JPX_data( + PDF *p, + int imageslot) +{ + (void) imageslot; + + pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "JPEG2000", 0, 0, 0); + + return -1; +} + +#else + + +pdc_bool +pdf_is_JPX_file(PDF *p, pdc_file *fp) +{ + (void) p; + (void) fp; + + return pdc_false; +} + +int +pdf_process_JPX_data( + PDF *p, + int imageslot) +{ + (void) imageslot; + + pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "JPEG2000", 0, 0, 0); + + return -1; +} + + + +#endif /* PDF_JPX_SUPPORTED */ + diff --git a/src/pdflib/pdflib/p_kerning.c b/src/pdflib/pdflib/p_kerning.c new file mode 100644 index 0000000..bc711ba --- /dev/null +++ b/src/pdflib/pdflib/p_kerning.c @@ -0,0 +1,21 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_kerning.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib kerning routines + * + */ + +#include "p_intern.h" +#include "p_font.h" + diff --git a/src/pdflib/pdflib/p_keyconn.h b/src/pdflib/pdflib/p_keyconn.h new file mode 100644 index 0000000..a56d783 --- /dev/null +++ b/src/pdflib/pdflib/p_keyconn.h @@ -0,0 +1,827 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_keyconn.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib shared keys connection lists + * + */ + +#ifndef P_KEYCONN_H +#define P_KEYCONN_H + +/* + * ------------- enumerations for pdc_keyconn tables ------------------ + */ + +typedef enum +{ + pdf_state_object = (1<<0), /* outside any document */ + pdf_state_document = (1<<1), /* document */ + pdf_state_page = (1<<2), /* page description in a document */ + pdf_state_pattern = (1<<3), /* pattern in a document */ + pdf_state_template = (1<<4), /* template in a document */ + pdf_state_path = (1<<5), /* path in a page description */ + pdf_state_font = (1<<6), /* font definition */ + pdf_state_glyph = (1<<7), /* glyph description in a Type3 font */ + pdf_state_glyphmetric = (1<<8), /* glyph metric in a Type3 font */ + pdf_state_glyphignore = (1<<9), /* glyph will be ignored without error */ + pdf_state_error = (1<<10) /* in error cleanup */ +} +pdf_state; + +typedef enum +{ + errpol_legacy = -1, + errpol_return = 0, + errpol_exception = 1 +} +pdf_errpol; + +typedef enum +{ + names_undef = 0, + names_3dannots, /* internal for named 3D annotations */ + names_dests, + names_javascript, + names_ap, + names_embeddedfiles +} +pdf_nametree_type; + +typedef enum +{ + event_formfield, + event_annotation, + event_bookmark, + event_page, + event_document +} +pdf_event_object; + +typedef enum +{ + pdf_openaction, + pdf_bookmark, + pdf_remotelink, + pdf_locallink, + pdf_nameddest +} +pdf_destuse; + +typedef enum +{ + pdf_3dview_first = -1, + pdf_3dview_last = -2, + pdf_3dview_next = -3, + pdf_3dview_previous = -4, + pdf_3dview_default = -5 +} +pdf_3dviewoptions; + +typedef enum +{ + pdf_none = 0, + pdf_fill, + pdf_stroke, + pdf_fillstroke +} +pdf_drawmode; + +typedef enum +{ + pdf_fill_winding, + pdf_fill_evenodd +} +pdf_fillrule; + +typedef enum +{ + NoColor = -1, + DeviceGray = 0, + DeviceRGB, + DeviceCMYK, + CalGray, + CalRGB, + Lab, + ICCBased, + Indexed, + PatternCS, + Separation, + DeviceN +} +pdf_colorspacetype; + +typedef enum +{ + color_undefgray = -1, + color_none = 0, + color_gray, + color_rgb, + color_cmyk, + color_spotname, + color_spot, + color_pattern, + color_iccbasedgray, + color_iccbasedrgb, + color_iccbasedcmyk, + color_lab, + + color_max /* for pdf_parse_coloropt */ +} +pdf_colortype; + +typedef enum +{ + AutoIntent = 0, + AbsoluteColorimetric, + RelativeColorimetric, + Saturation, + Perceptual +} +pdf_renderingintent; + +/* only up to 32 values permitted! */ +typedef enum +{ + fo_autocidfont, + fo_autosubsetting, + fo_embedding, + fo_encoding, + fo_fontname, + fo_fontstyle, + fo_fontwarning, + fo_kerning, + fo_monospace, + fo_subsetlimit, + fo_subsetminsize, + fo_subsetting, + fo_unicodemap, + fo_embedopentype, + fo_vertical, + fo_keepnative, + fo_replacementchar, + fo_ascender, + fo_descender, + fo_capheight, + fo_xheight, + fo_linegap +} +pdf_font_optflags; + +/* only up to 32 values permitted! */ +typedef enum +{ + to_charspacing, + to_fillcolor, + to_font, + to_fontsize, + to_fontsize_st, + to_deffont, + to_glyphwarning, + to_horizscaling, + to_italicangle, + to_fakebold, + to_kerning, + to_overline, + to_strikeout, + to_strokecolor, + to_strokewidth, + to_dasharray, + to_text, + to_textformat, + to_textrendering, + to_textrise, + to_leading, + to_underline, + to_wordspacing, + to_underlinewidth, + to_underlineposition, + to_charref, + to_escapesequence, + to_glyphcheck, + + to_textx, + to_texty +} +pdf_text_optflags; + +typedef enum +{ + border_solid, + border_dashed, + border_beveled, + border_inset, + border_underline +} +pdf_borderstyle; + +typedef enum +{ + label_none, + label_123, + label_IVX, + label_ivx, + label_ABC, + label_abc +} +pdf_labelstyle; + +typedef enum { + BM_None = 0, + BM_Normal = (1<<0), + BM_Multiply = (1<<1), + BM_Screen = (1<<2), + BM_Overlay = (1<<3), + BM_Darken = (1<<4), + BM_Lighten = (1<<5), + BM_ColorDodge = (1<<6), + BM_ColorBurn = (1<<7), + BM_HardLight = (1<<8), + BM_SoftLight = (1<<9), + BM_Difference = (1<<10), + BM_Exclusion = (1<<11), + BM_Hue = (1<<12), + BM_Saturation = (1<<13), + BM_Color = (1<<14), + BM_Luminosity = (1<<15) +} +pdf_blendmode; + +/* these values are used directly as indices into +** a page's boxes[] array. +*/ +typedef enum +{ + pdf_artbox, + pdf_bleedbox, + pdf_cropbox, + pdf_mediabox, + pdf_trimbox +} pdf_pagebox; + +typedef enum +{ + tabs_none, + tabs_fitbox, + tabs_validarea +} +pdf_showtabs; + +typedef enum +{ + text_noalign, + text_left, + text_center, + text_right, + text_justify, + text_lastauto, + text_fulljustify, + text_decimal, + text_top, + text_bottom, + text_grid +} +pdf_alignment; + +typedef enum +{ + text_nofit, + text_clip, + text_shrink, + text_split, + text_spread, + text_auto +} +pdf_adjustmethod; + +typedef enum +{ + text_relative, + text_typewriter, + text_ruler +} +pdf_hortabmethod; + +typedef enum +{ + text_none = -90000, + text_textrise = -70000, + text_xheight = -60000, + text_descender = -50000, + text_capheight = -40000, + text_ascender = -30000, + text_fontsize = -20000, + text_leading = -10000 +} +pdf_charmetric; + +typedef enum +{ + mbox_none = 0, + mbox_openleft = (1<<0), + mbox_openright = (1<<1), + mbox_openbottom = (1<<2), + mbox_opentop = (1<<3), + mbox_border = (1<<4), + mbox_area = (1<<5), + mbox_saverestore = (1<<6), + mbox_statleft = (1<<7), + mbox_statright = (1<<8), + mbox_statbottom = (1<<9), + mbox_stattop = (1<<10) +} +pdf_mbox_flags; + +typedef enum +{ + quadd_left = 0, + quadd_center = 1, + quadd_right = 2 +} +pdf_quadding; + +typedef enum +{ + disp_visible = (1<<2), + disp_hidden = (1<<1), + disp_noview = (1<<5), + disp_noprint = 0 +} +pdf_display; + +typedef enum +{ + high_none, + high_invert, + high_outline, + high_push +} +pdf_highlight; + +typedef enum +{ + pos_left = 1000, + pos_bottom = 2000, + pos_center = 50, + pos_right = 1100, + pos_top = 2100 +} +pdf_position; + +typedef enum +{ + dpi_none = -999999, + dpi_internal = 0 +} +pdf_dpi_states; + +typedef enum +{ + trans_none, + trans_split, + trans_blinds, + trans_box, + trans_wipe, + trans_dissolve, + trans_glitter, + trans_replace, + + TRANS_1_5, + trans_fly = TRANS_1_5, + trans_push, + trans_cover, + trans_uncover, + trans_fade +} +pdf_transition; + + +/* + * -------- pdc_keyconn tables shared by more than one c file ---------- + */ + +#if defined(P_MBOX_C) + +static const pdc_keyconn pdf_mbox_keylist[] = +{ + {"all", -1}, + {NULL, 0} +}; + +#endif /* P_MBOX_C */ + + +#if defined(P_DOCUMENT_C) || defined(P_PARAMS_C) + +static const pdc_keyconn pdf_compatibility_keylist[] = +{ + {"1.3", PDC_1_3}, + {"1.4", PDC_1_4}, + {"1.5", PDC_1_5}, + {"1.6", PDC_1_6}, + {"1.7", PDC_1_7}, + {NULL, 0} +}; + +#endif /* P_DOCUMENT_C || P_PARAMS_C */ + + +#if defined(P_ACTIONS_C) || defined(P_PAGE_C) + +static const pdc_keyconn pdf_transition_keylist[] = +{ + {"none", trans_none}, + {"split", trans_split}, + {"blinds", trans_blinds}, + {"box", trans_box}, + {"wipe", trans_wipe}, + {"dissolve", trans_dissolve}, + {"glitter", trans_glitter}, + {"replace", trans_replace}, + {"fly", trans_fly}, + {"push", trans_push}, + {"cover", trans_cover}, + {"uncover", trans_uncover}, + {"fade", trans_fade}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_transition_pdfkeylist[] = +{ + {"R", trans_none}, + {"Split", trans_split}, + {"Blinds", trans_blinds}, + {"Box", trans_box}, + {"Wipe", trans_wipe}, + {"Dissolve", trans_dissolve}, + {"Glitter", trans_glitter}, + {"R", trans_replace}, + {"Fly", trans_fly}, + {"Push", trans_push}, + {"Cover", trans_cover}, + {"Uncover", trans_uncover}, + {"Fade", trans_fade}, + {NULL, 0} +}; + +#endif /* P_ACTIONS_C || P_PAGE_C */ + + +#if defined(P_IMAGE_C) || defined(P_PARAMS_C) || defined(P_XGSTATE_C) + +static const pdc_keyconn pdf_renderingintent_pdfkeylist[] = +{ + {"Auto", AutoIntent}, + {"AbsoluteColorimetric", AbsoluteColorimetric}, + {"RelativeColorimetric", RelativeColorimetric}, + {"Saturation", Saturation}, + {"Perceptual", Perceptual}, + {NULL, 0} +}; + +#endif /* P_IMAGE_C || P_PARAMS_C || P_XGSTATE_C */ + + +#if defined(P_MBOX_C) || defined(P_XGSTATE_C) + +static const pdc_keyconn pdf_linecap_keylist[] = +{ + {"butt", 0}, + {"round", 1}, + {"projecting", 2}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_linejoin_keylist[] = +{ + {"miter", 0}, + {"round", 1}, + {"bevel", 2}, + {NULL, 0} +}; + +#endif /* P_MBOX_C || P_XGSTATE_C */ + + +#if defined(P_DOCUMENT_C) || defined(P_PARAMS_C) || defined(P_PDI_C) + +static const pdc_keyconn pdf_usebox_keylist[] = +{ + {"art", pdc_pbox_art}, + {"bleed", pdc_pbox_bleed}, + {"crop", pdc_pbox_crop}, + {"media", pdc_pbox_media}, + {"trim", pdc_pbox_trim}, + {NULL, 0} +}; + +#endif /* P_DOCUMENT_C || P_PARAMS_C || P_PDI_C */ + +#if defined(P_DOCUMENT_C) || defined(P_PDI_C) + +static const pdc_keyconn pdf_usebox_pdfkeylist[] = +{ + {"/ArtBox", pdc_pbox_art }, + {"/BleedBox", pdc_pbox_bleed }, + {"/CropBox", pdc_pbox_crop }, + {"/MediaBox", pdc_pbox_media }, + {"/TrimBox", pdc_pbox_trim }, + {NULL, 0} +}; + +#endif /* P_DOCUMENT_C || P_PDI_C */ + + +#if defined(P_BLOCK_C) || defined(P_IMAGE_C) + +static const pdc_keyconn pdf_dpi_keylist[] = +{ + {"none", dpi_none}, + {"internal", dpi_internal}, + {NULL, 0} +}; + +#endif /* P_BLOCK_C || P_IMAGE_C */ + +#if defined(P_BLOCK_C) || defined(P_TEXT_C) + +static const pdc_keyconn pdf_stampdir_keylist[] = +{ + {NULL, 0} +}; + +#endif /* P_BLOCK_C || P_TEXT_C */ + + + + +#if defined(P_MBOX_C) || defined(P_TEXTFLOW_C) +static const pdc_keyconn pdf_boxheight_keylist[] = +{ + {"none", text_none}, + {"baseline", text_none}, + {"textrise", text_textrise}, + {"xheight", text_xheight}, + {"descender", text_descender}, + {"capheight", text_capheight}, + {"ascender", text_ascender}, + {"fontsize", text_fontsize}, + {"leading", text_leading}, + {NULL, 0} +}; + +#endif /* P_MBOX_C || P_TEXTFLOW_C */ + + +#if defined(P_BLOCK_C) || defined(P_TEXT_C) || defined(P_TEXTFLOW_C) + +static const pdc_keyconn pdf_charname_keylist[] = +{ + {"none", 0}, + {NULL, 0} +}; + +#define PDF_UNDERLINEWIDTH_AUTO 0 +static const pdc_keyconn pdf_underlinewidth_keylist[] = +{ + {"auto", PDF_UNDERLINEWIDTH_AUTO}, + {NULL, 0} +}; + +#define PDF_UNDERLINEPOSITION_AUTO 1000000 +static const pdc_keyconn pdf_underlineposition_keylist[] = +{ + {"auto", PDF_UNDERLINEPOSITION_AUTO}, + {NULL, 0} +}; + +#endif /* P_BLOCK_C || P_TEXT_C || P_TEXTFLOW_C */ + + +#if defined(P_BLOCK_C)|| defined(P_PARAMS_C) || \ + defined(P_TEXT_C) || defined(P_TEXTFLOW_C) + +static const pdc_keyconn pdf_glyphcheck_keylist[] = +{ + {"none", text_nocheck}, + {"error", text_error}, + {"replace", text_replace}, + {NULL, 0} +}; + +#endif /* P_BLOCK_C || P_PARAMS_C || P_TEXT_C || P_TEXTFLOW_C */ + + +#if defined(P_BLOCK_C) || defined(P_FIELDS_C) || \ + defined(P_IMAGE_C) || defined(P_TEXT_C) + +static const pdc_keyconn pdf_position_keylist[] = +{ + {"left", pos_left}, + {"bottom", pos_bottom}, + {"center", pos_center}, + {"right", pos_right}, + {"top", pos_top}, + {NULL, 0} +}; + +#endif /* P_BLOCK_C || P_FIELDS_C || P_IMAGE_C || P_TEXT_C */ + + +#if defined(P_BLOCK_C) || defined(P_FIELDS_C) || \ + defined(P_IMAGE_C) || defined(P_TABLE_C) || \ + defined(P_TEXT_C) || defined(P_TEXTFLOW_C) + +static const pdc_keyconn pdf_fitmethod_keylist[] = +{ + {"nofit", pdc_nofit}, + {"clip", pdc_clip}, + {"auto", pdc_tauto}, +#if !defined (P_TEXTFLOW_C) + {"slice", pdc_slice}, + {"meet", pdc_meet}, + {"entire", pdc_entire}, +#endif + {NULL, 0} +}; + +#endif /* P_BLOCK_C || P_FIELDS_C || P_IMAGE_C || P_TABLE_C || + P_TEXT_C || P_TEXTFLOW_C */ + + +#if defined(P_ANNOTS_C) || defined(P_BLOCK_C) || defined(P_FIELDS_C) || \ + defined(P_IMAGE_C) || defined(P_TEXT_C) || defined(P_TEXTFLOW_C) + +static const pdc_keyconn pdf_orientate_keylist[] = +{ + {"north", 0}, + {"west", 90}, + {"south", 180}, + {"east", 270}, + {NULL, 0} +}; + +#endif /* P_ANNOTS_C || P_BLOCK_C || P_FIELDS_C || + P_IMAGE_C || P_TEXT_C || P_TEXTFLOW_C */ + + +#if defined(P_ANNOTS_C) || defined(P_BLOCK_C) || defined(P_FIELDS_C) || \ + defined(P_MBOX_C) || defined(P_TEXT_C) || defined(P_TEXTFLOW_C) + +static const pdc_keyconn pdf_fontsize_keylist[] = +{ + {"auto", 0}, + {"xheight", text_xheight}, + {"capheight", text_capheight}, + {"ascender", text_ascender}, + {"bodyheight", text_fontsize}, + {NULL, 0} +}; + +#endif /* P_ANNOTS_C P_BLOCK_C || P_FIELDS_C || + P_MBOX_C || P_TEXT_C || P_TEXTFLOW_C */ + + +#if defined(P_BLOCK_C) || defined(P_FONT_C) || defined(P_HYPER_C) || \ + defined(P_MBOX_C) || defined(P_TEXT_C) || defined(P_TEXTFLOW_C) + +static const pdc_keyconn pdf_fontstyle_pdfkeylist[] = +{ + {"Normal", fnt_Normal}, + {"Bold", fnt_Bold}, + {"Italic", fnt_Italic}, + {"BoldItalic", fnt_BoldItalic}, + {NULL, 0} +}; + +#endif /* P_BLOCK_C || P_FONT_C || P_HYPER_C || + P_MBOX_C || P_TEXT_C || P_TEXTFLOW_C */ + + +#if defined(P_ANNOTS_C) || defined(P_FIELDS_C) + +static const pdc_keyconn pdf_quadding_keylist[] = +{ + {"left", quadd_left}, + {"center", quadd_center}, + {"right", quadd_right}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_display_keylist[] = +{ + {"visible", disp_visible}, + {"hidden", disp_hidden}, + {"noview", disp_noview}, + {"noprint", disp_noprint}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_highlight_keylist[] = +{ + {"none", high_none}, + {"invert", high_invert}, + {"outline", high_outline}, + {"push", high_push}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_highlight_pdfkeylist[] = +{ + {"N", high_none}, + {"I", high_invert}, + {"O", high_outline}, + {"P", high_push}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_borderstyle_keylist[] = +{ + {"solid", border_solid}, + {"dashed", border_dashed}, + {"beveled", border_beveled}, + {"inset", border_inset}, + {"underline", border_underline}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_borderstyle_pdfkeylist[] = +{ + {"S", border_solid}, + {"D", border_dashed}, + {"B", border_beveled}, + {"I", border_inset}, + {"U", border_underline}, + {NULL, 0} +}; + +#endif /* P_ANNOTS_C || P_FIELDS_C */ + + +#if defined(P_3D_C) || defined(P_BLOCK_C) || defined(P_FIELDS_C) || \ + defined(P_HYPER_C) || defined(P_LAYER_C) || defined(P_PARAMS_C) || \ + defined(P_TEXT_C) || defined(P_TEXTFLOW_C) || defined(P_UTIL_C) || \ + defined(P_XMP_C) + +/* original in pc_unicode.h */ +static const pdc_keyconn pdf_textformat_keylist[] = +{ + {"auto", pdc_auto}, + {"auto2", pdc_auto2}, + {"bytes", pdc_bytes}, + {"bytes2", pdc_bytes2}, + {"utf8", pdc_utf8}, + {"utf16", pdc_utf16}, + {"utf16be", pdc_utf16be}, + {"utf16le", pdc_utf16le}, + {NULL, 0} +}; + +#endif /* P_3D_C || P_BLOCK_C || P_FIELDS_C || P_HYPER_C || + P_LAYER_C || P_PARAMS_C || P_TEXT_C || P_TEXTFLOW_C || + P_UTIL_C || P_XMP_C */ + + +#if defined(P_DOCUMENT_C) || \ + defined(P_3D_C) || \ + defined(P_ACTIONS_C) || \ + defined(P_BLOCK_C) || \ + defined(P_FIELDS_C) || \ + defined(P_FONT_C) || \ + defined(P_ICC_C) || \ + defined(P_IMAGE_C) || \ + defined(P_PARAMS_C) || \ + defined(P_PDI_C) || \ + defined(P_TABLE_C) || \ + defined(P_TEMPLATE_C) || \ + defined(P_TEXT_C) || \ + defined(P_TEXTFLOW_C) + +static const pdc_keyconn pdf_errpol_keylist[] = +{ + {"legacy", errpol_legacy}, + {"return", errpol_return}, + {"exception", errpol_exception}, + {NULL, 0} +}; + +#define PDF_ERRORPOLICY_OPTION \ +\ + {"errorpolicy", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \ + 0, 0, pdf_errpol_keylist}, \ + +#endif + + +#endif /* P_KEYCONN_H */ + diff --git a/src/pdflib/pdflib/p_layer.c b/src/pdflib/pdflib/p_layer.c new file mode 100644 index 0000000..1600a5b --- /dev/null +++ b/src/pdflib/pdflib/p_layer.c @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_layer.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib optional content routines + * + */ + +#define P_LAYER_C + +#include "p_intern.h" +#include "p_layer.h" +#include "p_tagged.h" + + + + + + + + + + + + + + diff --git a/src/pdflib/pdflib/p_layer.h b/src/pdflib/pdflib/p_layer.h new file mode 100644 index 0000000..74d51eb --- /dev/null +++ b/src/pdflib/pdflib/p_layer.h @@ -0,0 +1,24 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_layer.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib marked content header + * + */ + +#ifndef P_LAYER_H +#define P_LAYER_H + + +#endif /* P_LAYER_H */ + diff --git a/src/pdflib/pdflib/p_mbox.c b/src/pdflib/pdflib/p_mbox.c new file mode 100644 index 0000000..db6ffff --- /dev/null +++ b/src/pdflib/pdflib/p_mbox.c @@ -0,0 +1,943 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_mbox.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib matchbox related routines + * + */ + +#define P_MBOX_C + +#include "p_intern.h" +#include "p_color.h" +#include "p_font.h" +#include "p_defopt.h" + +static const pdc_defopt pdf_create_mbox_options[] = +{ + {"name", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_INT_MAX, NULL}, + + {"boxheight", pdc_scalarlist, PDC_OPT_NONE, 2, 2, + 0.0, PDC_FLOAT_MAX, pdf_boxheight_keylist}, + + {"clipping", pdc_scalarlist, PDC_OPT_PERCENT, 4, 4, + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, + + + {"innerbox", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"openrect", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"fillcolor", pdc_stringlist, PDC_OPT_NONE, 1, 5, + 0.0, PDF_MAX_NAMESTRING, NULL}, + + {"strokecolor", pdc_stringlist, PDC_OPT_NONE, 1, 5, + 0.0, PDF_MAX_NAMESTRING, NULL}, + + {"borderwidth", pdc_scalarlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_FLOAT_MAX, NULL}, + + {"dasharray", pdc_scalarlist, PDC_OPT_NONE, 0, PDF_MAX_DASHLENGTH, + PDC_FLOAT_PREC, PDC_FLOAT_MAX, NULL}, + + {"dashphase", pdc_scalarlist, PDC_OPT_NONE, 1, 1, + 0.0, PDC_FLOAT_MAX, NULL}, + + {"linecap", pdc_integerlist, PDC_OPT_NONE, 1, 1, + 0.0, 2.0, pdf_linecap_keylist}, + + {"linejoin", pdc_integerlist, PDC_OPT_NONE, 1, 1, + 0.0, 2.0, pdf_linejoin_keylist}, + + {"drawleft", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"drawbottom", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"drawright", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"drawtop", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"margin", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, + + {"offsetleft", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, + + {"offsetbottom", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, + + {"offsetright", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, + + {"offsettop", pdc_scalarlist, PDC_OPT_PERCENT, 1, 1, + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, + + PDC_OPT_TERMINATE +}; + +struct pdf_mbox_s +{ + char *name; + pdc_rectangle rect; + pdc_matrix ctm; + pdc_scalar boxheight[2]; + pdc_scalar clipping[4]; + pdc_bool percentclipping[4]; + pdc_bool innerbox; + pdc_bool openrect; + pdf_coloropt fillcolor; + pdf_coloropt strokecolor; + pdc_scalar borderwidth; + int linecap; + int linejoin; + pdc_scalar dasharray[PDF_MAX_DASHLENGTH]; + int dashlength; + pdc_scalar dashphase; + pdc_bool drawleft; + pdc_bool drawbottom; + pdc_bool drawright; + pdc_bool drawtop; + pdc_scalar offsetleft; + pdc_bool percentleft; + pdc_scalar offsetbottom; + pdc_bool percentbottom; + pdc_scalar offsetright; + pdc_bool percentright; + pdc_scalar offsettop; + pdc_bool percenttop; +}; + +static void +pdf_reclaim_mbox(void *item) +{ + pdf_mbox *mbox = (pdf_mbox *) item; + + mbox->name = NULL; + pdc_rect_init(&mbox->rect, 0, 0, 0, 0); + pdc_identity_matrix(&mbox->ctm); + mbox->boxheight[0] = (pdc_scalar) text_capheight; + mbox->boxheight[1] = (pdc_scalar) text_none; + mbox->clipping[0] = 0; + mbox->clipping[1] = 0; + mbox->clipping[2] = 1; + mbox->clipping[3] = 1; + mbox->percentclipping[0] = pdc_true; + mbox->percentclipping[1] = pdc_true; + mbox->percentclipping[2] = pdc_true; + mbox->percentclipping[3] = pdc_true; + mbox->innerbox = pdc_false; + mbox->openrect = pdc_false; + mbox->fillcolor.type = (int) color_none; + mbox->strokecolor.type = (int) color_none; + mbox->borderwidth = 0.0; + mbox->linecap = 0; + mbox->linejoin = 0; + mbox->dasharray[0] = 0.0; + mbox->dasharray[1] = 0.0; + mbox->dashlength = 0; + mbox->dashphase = 0; + mbox->drawleft = pdc_true; + mbox->drawbottom = pdc_true; + mbox->drawright = pdc_true; + mbox->drawtop = pdc_true; + mbox->offsetleft = 0.0; + mbox->percentleft = pdc_false; + mbox->offsetbottom = 0.0; + mbox->percentbottom = pdc_false; + mbox->offsetright = 0.0; + mbox->percentright = pdc_false; + mbox->offsettop = 0.0; + mbox->percenttop = pdc_false; +} + +static void +pdf_release_mbox(void *context, void *item) +{ + PDF *p = (PDF *) context; + pdf_mbox *mbox = (pdf_mbox *) item; + + if (mbox->name != NULL) + { + pdc_free(p->pdc, mbox->name); + mbox->name = NULL; + } +} + +static pdc_ced pdf_mbox_ced = +{ + sizeof(pdf_mbox), pdf_reclaim_mbox, pdf_release_mbox, NULL +}; + +static pdc_vtr_parms pdf_mbox_parms = +{ + 0, 10, 10 +}; + +pdc_vtr * +pdf_new_mboxes(PDF *p, pdf_mbox *mbox, pdc_vtr *mboxes) +{ + static const char fn[] = "pdf_new_mboxes"; + char *name = mbox->name; + + if (mboxes == NULL) + mboxes = pdc_vtr_new(p->pdc, &pdf_mbox_ced, p, &pdf_mbox_parms); + + if (mbox->name != NULL) + mbox->name = pdc_strdup_ext(p->pdc, mbox->name, 0, fn); + pdc_vtr_push(mboxes, *mbox, pdf_mbox); + + mbox->name = name; + + return mboxes; +} + +void +pdf_add_page_mbox(PDF *p, pdf_mbox *mbox) +{ + /* save current trafo matrix */ + mbox->ctm = p->curr_ppt->gstate[p->curr_ppt->sl].ctm; + + if (mbox->name && strlen(mbox->name)) + { + pdc_vtr *mboxes_new; + pdc_vtr *mboxes = p->curr_ppt->mboxes; + + mboxes_new = pdf_new_mboxes(p, mbox, mboxes); + if (mboxes_new != mboxes) + p->curr_ppt->mboxes = mboxes_new; + + } +} + +void +pdf_delete_mbox(PDF *p, pdf_mbox *mbox) +{ + if (mbox != NULL) + { + pdf_release_mbox(p, mbox); + pdc_free(p->pdc, mbox); + } +} + +pdf_mbox * +pdf_get_mbox(PDF *p, pdc_vtr *mboxes, const char *name, int number, + int *o_count) +{ + pdf_mbox *o_mbox = NULL; + int count = 0; + + if (mboxes == NULL) + mboxes = p->curr_ppt->mboxes; + + if (mboxes != NULL) + { + if (name == NULL && number <= 0) + { + count = pdc_vtr_size(mboxes); + } + else + { + int i, n = pdc_vtr_size(mboxes); + + for (i = 0; i < n; i++) + { + pdf_mbox *mbox = (pdf_mbox *) &pdc_vtr_at(mboxes, i, pdf_mbox); + + if (name == NULL || !pdc_strcmp(name, mbox->name)) + { + count++; + if (o_count == NULL && count == number) + { + o_mbox = mbox; + break; + } + } + } + } + } + + if (o_count != NULL) + *o_count = count; + + return o_mbox; +} + +pdf_mbox * +pdf_parse_mbox_optlist(PDF *p, const char *optlist) +{ + static const char fn[] = "pdf_parse_mbox_optlist"; + pdc_resopt *resopts = NULL; + pdf_mbox *mbox; + char **strlist = NULL; + pdc_scalar margin; + int i, ns; + + resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_create_mbox_options, + NULL, pdc_true); + + mbox = (pdf_mbox *) pdc_malloc(p->pdc, sizeof(pdf_mbox), fn); + pdf_reclaim_mbox(mbox); + + if (pdc_get_optvalues("name", resopts, NULL, NULL)) + mbox->name = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + + pdc_get_optvalues("boxheight", resopts, mbox->boxheight, NULL); + if (pdc_get_optvalues("clipping", resopts, mbox->clipping, NULL)) + { + for (i = 0; i < 4; i++) + mbox->percentclipping[i] = pdc_is_lastopt_percent(resopts, i) ? + pdc_true : pdc_false; + } + + + pdc_get_optvalues("innerbox", resopts, &mbox->innerbox, NULL); + pdc_get_optvalues("openrect", resopts, &mbox->openrect, NULL); + + ns = pdc_get_optvalues("fillcolor", resopts, NULL, &strlist); + if (ns) + pdf_parse_coloropt(p, "fillcolor", strlist, ns, (int) color_max, + &mbox->fillcolor); + + pdf_init_coloropt(p, &mbox->strokecolor); + ns = pdc_get_optvalues("strokecolor", resopts, NULL, &strlist); + if (ns) + pdf_parse_coloropt(p, "strokecolor", strlist, ns, (int) color_max, + &mbox->strokecolor); + + pdc_get_optvalues("borderwidth", resopts, &mbox->borderwidth, NULL); + mbox->dashlength = + pdc_get_optvalues("dasharray", resopts, mbox->dasharray, NULL); + pdc_get_optvalues("dashphase", resopts, &mbox->dashphase, NULL); + pdc_get_optvalues("linecap", resopts, &mbox->linecap, NULL); + pdc_get_optvalues("linejoin", resopts, &mbox->linejoin, NULL); + + pdc_get_optvalues("drawleft", resopts, &mbox->drawleft, NULL); + pdc_get_optvalues("drawbottom", resopts, &mbox->drawbottom, NULL); + pdc_get_optvalues("drawright", resopts, &mbox->drawright, NULL); + pdc_get_optvalues("drawtop", resopts, &mbox->drawtop, NULL); + + if (pdc_get_optvalues("margin", resopts, &margin, NULL)) + { + mbox->offsetleft = margin; + mbox->percentleft = pdc_is_lastopt_percent(resopts, 0); + + mbox->offsetbottom = margin; + mbox->percentbottom = pdc_is_lastopt_percent(resopts, 0); + + mbox->offsetright = -margin; + mbox->percentright = pdc_is_lastopt_percent(resopts, 0); + + mbox->offsettop = -margin; + mbox->percenttop = pdc_is_lastopt_percent(resopts, 0); + } + + if (pdc_get_optvalues("offsetleft", resopts, &mbox->offsetleft, NULL)) + { + mbox->percentleft = pdc_is_lastopt_percent(resopts, 0); + } + if (pdc_get_optvalues("offsetbottom", resopts, &mbox->offsetbottom, NULL)) + { + mbox->percentbottom = pdc_is_lastopt_percent(resopts, 0); + } + if (pdc_get_optvalues("offsetright", resopts, &mbox->offsetright, NULL)) + { + mbox->percentright = pdc_is_lastopt_percent(resopts, 0); + } + if (pdc_get_optvalues("offsettop", resopts, &mbox->offsettop, NULL)) + { + mbox->percenttop = pdc_is_lastopt_percent(resopts, 0); + } + + pdc_cleanup_optionlist(p->pdc, resopts); + + return mbox; +} + +void +pdf_get_mbox_boxheight(PDF *p, pdf_mbox *mbox, pdc_scalar *boxheight) +{ + (void) p; + + if (mbox == NULL) + { + boxheight[0] = (pdc_scalar) text_capheight; + boxheight[1] = (pdc_scalar) text_none; + } + else + { + boxheight[0] = mbox->boxheight[0]; + boxheight[1] = mbox->boxheight[1]; + } +} + +pdc_bool +pdf_get_mbox_clipping(PDF *p, pdf_mbox *mbox, + pdc_scalar width, pdc_scalar height, + pdc_box *clipbox) +{ + (void) p; + + if (mbox == NULL) + { + clipbox->ll.x = 0; + clipbox->ll.y = 0; + clipbox->ur.x = width; + clipbox->ur.y = height; + } + else + { + if (mbox->percentclipping[0]) + clipbox->ll.x = mbox->clipping[0] * width; + else + clipbox->ll.x = mbox->clipping[0]; + + if (mbox->percentclipping[1]) + clipbox->ll.y = mbox->clipping[1] * height; + else + clipbox->ll.y = mbox->clipping[1]; + + if (mbox->percentclipping[2]) + clipbox->ur.x = mbox->clipping[2] * width; + else + clipbox->ur.x = mbox->clipping[2]; + + if (mbox->percentclipping[3]) + clipbox->ur.y = mbox->clipping[3] * height; + else + clipbox->ur.y = mbox->clipping[3]; + } + + return (clipbox->ll.x != 0 || clipbox->ll.y != 0 || + clipbox->ur.x != width || clipbox->ur.y != height) ? + pdc_true : pdc_false; +} + +void +pdf_set_mbox_rectangle(PDF *p, pdf_mbox *mbox, pdc_rectangle *rect, int flags) +{ + pdc_scalar width, height; + + (void) p; + + mbox->rect = *rect; + + width = mbox->rect.urx - mbox->rect.llx; + height = mbox->rect.ury - mbox->rect.lly; + + if (!(flags & mbox_statleft)) + { + if (mbox->percentleft) + mbox->rect.llx += mbox->offsetleft * width; + else + mbox->rect.llx += mbox->offsetleft; + } + + if (!(flags & mbox_statbottom)) + { + if (mbox->percentbottom) + mbox->rect.lly += mbox->offsetbottom * height; + else + mbox->rect.lly += mbox->offsetbottom; + } + + if (!(flags & mbox_statright)) + { + if (mbox->percentright) + mbox->rect.urx += mbox->offsetright * width; + else + mbox->rect.urx += mbox->offsetright; + } + + if (!(flags & mbox_stattop)) + { + if (mbox->percenttop) + mbox->rect.ury += mbox->offsettop * height; + else + mbox->rect.ury += mbox->offsettop; + } +} + +double +pdf_get_mbox_info(PDF *p, pdf_mbox *mbox, const char *keyword) +{ + (void) p; + + + if (!strcmp(keyword, "openrect")) + return (double) mbox->openrect; + + if (!strcmp(keyword, "innerbox")) + return (double) mbox->innerbox; + + return 0; +} + +pdc_bool +pdf_get_mbox_drawborder(PDF *p, pdf_mbox *mbox, int keycode) +{ + pdc_bool drawborder = mbox->borderwidth > 0 && + mbox->strokecolor.type != (int) color_none; + + (void) p; + + switch (keycode) + { + case mbox_openleft: + return drawborder && mbox->drawleft; + + case mbox_openright: + return drawborder && mbox->drawright; + + case mbox_openbottom: + return drawborder && mbox->drawbottom; + + case mbox_opentop: + return drawborder && mbox->drawtop; + } + + return pdc_false; +} + +void +pdf_get_mbox_rectangle(PDF *p, pdf_mbox *mbox, pdc_vector *polyline) +{ + pdc_matrix ctminv; + + pdc_invert_matrix(p->pdc, &ctminv, + &p->curr_ppt->gstate[p->curr_ppt->sl].ctm); + pdc_multiply_matrix(&mbox->ctm, &ctminv); + pdc_rect2polyline(&ctminv, &mbox->rect, polyline); +} + +void +pdf_draw_mbox_rectangle(PDF *p, pdf_mbox *mbox, int flags) +{ + pdc_bool drawleft, drawright, drawbottom, drawtop; + pdc_bool saverestore = (flags & mbox_saverestore) && + ((flags & mbox_area && + mbox->fillcolor.type != (int) color_none) || + (flags & mbox_border && + mbox->strokecolor.type != (int) color_none && mbox->borderwidth > 0)); + + if (saverestore) + pdf__save(p); + + if (flags & mbox_area && mbox->fillcolor.type != (int) color_none && + mbox->rect.llx != mbox->rect.urx && + mbox->rect.lly != mbox->rect.ury) + { + pdf_set_coloropt(p, pdf_fill, &mbox->fillcolor); + pdf__moveto(p, mbox->rect.llx, mbox->rect.lly); + pdf__lineto(p, mbox->rect.urx, mbox->rect.lly); + pdf__lineto(p, mbox->rect.urx, mbox->rect.ury); + pdf__lineto(p, mbox->rect.llx, mbox->rect.ury); + pdf__lineto(p, mbox->rect.llx, mbox->rect.lly); + pdf__fill(p); + } + + if (flags & mbox_border && + mbox->strokecolor.type != (int) color_none && mbox->borderwidth > 0) + { + pdf_set_coloropt(p, pdf_stroke, &mbox->strokecolor); + pdf__setlinewidth(p, mbox->borderwidth); + pdf_setdashpattern_internal(p, mbox->dasharray, mbox->dashlength, + mbox->dashphase); + pdf__setlinecap(p, mbox->linecap); + pdf__setlinejoin(p, mbox->linejoin); + + drawbottom = mbox->drawbottom && + (!(flags & mbox_openbottom) || !mbox->openrect); + if (drawbottom) + { + pdf__moveto(p, mbox->rect.llx, mbox->rect.lly); + pdf__lineto(p, mbox->rect.urx, mbox->rect.lly); + } + + drawright = mbox->drawright && + (!(flags & mbox_openright) || !mbox->openrect); + if (drawright) + { + if (!drawbottom) + pdf__moveto(p, mbox->rect.urx, mbox->rect.lly); + pdf__lineto(p, mbox->rect.urx, mbox->rect.ury); + } + + drawtop = mbox->drawtop && + (!(flags & mbox_opentop) || !mbox->openrect); + if (drawtop) + { + if (!drawright) + pdf__moveto(p, mbox->rect.urx, mbox->rect.ury); + pdf__lineto(p, mbox->rect.llx, mbox->rect.ury); + } + + drawleft = mbox->drawleft && + (!(flags & mbox_openleft) || !mbox->openrect); + if (drawleft) + { + if (!drawtop) + pdf__moveto(p, mbox->rect.llx, mbox->rect.ury); + if (drawbottom && drawright && drawtop) + pdf__closepath(p); + else + pdf__lineto(p, mbox->rect.llx, mbox->rect.lly); + } + + pdf__stroke(p); + } + + if (saverestore) + pdf__restore(p); +} + +const char * +pdf_get_usematchbox(PDF *p, const char *option, const char *optval, + int *istart, int *istop) +{ + const char *boxname = NULL, *stemp = NULL; + char **strlist = NULL; + int errcode = 0; + int k, ir, ns, irect = 1, nrect = 0; + + ns = pdc_split_stringlist(p->pdc, optval, NULL, PDC_SPLIT_ISOPTLIST, + &strlist); + if (ns) + { + boxname = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, strlist[0]); + + /* number of rectangles */ + pdf_get_mbox(p, NULL, boxname, 0, &nrect); + + if (ns == 2) + { + stemp = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, + strlist[1]); + + /* rectangle number or all rectangles */ + if (!pdc_str2integer(stemp, 0, &ir)) + { + k = pdc_get_keycode_ci(stemp, pdf_mbox_keylist); + if (k == PDC_KEY_NOTFOUND) + { + errcode = PDC_E_OPT_ILLKEYWORD; + goto PDF_USEMATCHBOX_ERROR; + } + } + else if (ir <= 0) + { + errcode = PDC_E_OPT_ILLINTEGER; + goto PDF_USEMATCHBOX_ERROR; + } + else + { + irect = ir; + nrect = MIN(irect, nrect); + } + } + else + { + irect = 1; + } + } + + PDF_USEMATCHBOX_ERROR: + + pdc_cleanup_stringlist(p->pdc, strlist); + + if (errcode) + pdc_error(p->pdc, errcode, option, stemp, 0, 0); + + *istart = irect; + *istop = nrect; + + return boxname; +} + +static const pdc_keyconn pdf_info_keylist[] = +{ + {"count", 0}, + {"exists", 1}, + {"width", 2}, + {"height", 3}, + {"x1", 4}, + {"y1", 5}, + {"x2", 6}, + {"y2", 7}, + {"x3", 8}, + {"y3", 9}, + {"x4", 10}, + {"y4", 11}, + {NULL, 0} +}; + +double +pdf__info_matchbox(PDF *p, const char *boxname, int len, int num, + const char *keyword) +{ + pdf_mbox *mbox; + char *cname; + double mbinfo = 0; + int infokey, count; + + if (boxname == NULL) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "boxname", 0, 0, 0); + + if (keyword == NULL || *keyword == '0') + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "keyword", 0, 0, 0); + + /* Converting boxname */ + cname = pdf_convert_name(p, boxname, len, 0); + if (cname == NULL || *cname == '\0') + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "boxname", 0, 0, 0); + boxname = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, cname); + pdc_free(p->pdc, cname); + + infokey = pdc_get_keycode_ci(keyword, pdf_info_keylist); + if (infokey == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_ILLARG_STRING, "keyword", keyword, 0, 0); + + /* count */ + if (!infokey) + { + pdf_get_mbox(p, NULL, boxname, num, &count); + mbinfo = (double) count; + } + else + { + if (num < 1) + pdc_error(p->pdc, PDC_E_ILLARG_INT, "num", + pdc_errprintf(p->pdc, "%d", num), 0, 0); + + mbox = pdf_get_mbox(p, NULL, boxname, num, NULL); + if (mbox != NULL) + { + pdc_vector polyline[5]; + + if (infokey > 1) + pdf_get_mbox_rectangle(p, mbox, polyline); + + switch (infokey) + { + case 1: + mbinfo = 1; + break; + + case 2: + mbinfo = pdc_get_vector_length(&polyline[0], &polyline[1]); + break; + + case 3: + mbinfo = pdc_get_vector_length(&polyline[0], &polyline[3]); + break; + + case 4: + mbinfo = polyline[0].x; + break; + + case 5: + mbinfo = polyline[0].y; + break; + + case 6: + mbinfo = polyline[1].x; + break; + + case 7: + mbinfo = polyline[1].y; + break; + + case 8: + mbinfo = polyline[2].x; + break; + + case 9: + mbinfo = polyline[2].y; + break; + + case 10: + mbinfo = polyline[3].x; + break; + + case 11: + mbinfo = polyline[3].y; + break; + } + } + } + + return mbinfo; +} + + +/* -------------------------- fit functions --------------------------- */ + +void +pdf_init_fit_options(PDF *p, pdc_bool fortflow, pdf_fit_options *fit) +{ + (void) p; + (void) fortflow; + + fit->boxsize[0] = 0; + fit->boxsize[1] = 0; + fit->flags = 0; + fit->fitmethod = pdc_nofit; + fit->margin[0] = 0; + fit->margin[1] = 0; + fit->mask = 0; + fit->pcmask = 0; + fit->shrinklimit = 0.75; + fit->position[0] = 0; + fit->position[1] = 0; + fit->orientate = 0; + fit->rotate = 0; + fit->refpoint[0] = 0; + fit->refpoint[1] = 0; + fit->showborder = pdc_false; + fit->matchbox = NULL; + fit->alignchar = 0; +} + +void +pdf_cleanup_fit_options(PDF *p, pdf_fit_options *fit) +{ + pdf_delete_mbox(p, fit->matchbox); + fit->matchbox = NULL; + + +} + +void +pdf_set_position_values(PDF *p, pdc_scalar *i_position, int nv) +{ + pdc_scalar position[2]; + int i, ipos; + + (void) p; + + position[0] = 0; + position[1] = 0; + + for (i = 0; i < nv; i++) + { + ipos = (int) i_position[i]; + switch(ipos) + { + case pos_left: + case pos_right: + position[0] = i_position[i] - pos_left; + break; + + case pos_bottom: + case pos_top: + position[1] = i_position[i] - pos_bottom; + break; + + default: + position[i] = i_position[i]; + break; + } + } + + if (nv == 1) + position[1] = position[0]; + + i_position[0] = position[0]; + i_position[1] = position[1]; +} + + +void +pdf_get_fit_options(PDF *p, pdc_bool fortflow, pdf_fit_options *fit, + pdc_resopt *resopts) +{ + char **strlist = NULL; + int inum; + + (void) fortflow; + + if (pdc_get_optvalues("fitmethod", resopts, &inum, NULL)) + { + fit->fitmethod = (pdc_fitmethod) inum; + fit->mask |= (1L << fit_fitmethod); + } + + if (pdc_get_optvalues("rotate", resopts, &fit->rotate, NULL)) + fit->mask |= (1L << fit_rotate); + + if (pdc_get_optvalues("orientate", resopts, &fit->orientate, NULL)) + fit->mask |= (1L << fit_orientate); + + pdc_get_optvalues("showborder", resopts, &fit->showborder, NULL); + + if (fit->flags & is_textline) + { + inum = pdc_get_optvalues("margin", resopts, fit->margin, NULL); + if (inum) + { + if (inum == 1) + fit->margin[1] = fit->margin[0]; + fit->mask |= (1L << fit_margin); + } + + if (pdc_get_optvalues("alignchar", resopts, &inum, NULL)) + { + fit->alignchar = (pdc_ushort) inum; + fit->mask |= (1L << fit_alignchar); + } + + } + + if (fit->flags & is_block) + { + if (pdc_get_optvalues("refpoint", resopts, fit->refpoint, NULL)) + fit->mask |= (1L << fit_refpoint); + } + + + if (fit->flags & is_block || !(fit->flags & is_textflow)) + { + if (pdc_get_optvalues("boxsize", resopts, fit->boxsize, NULL)) + fit->mask |= (1L << fit_boxsize); + + if (pdc_get_optvalues("shrinklimit", resopts, &fit->shrinklimit, NULL)) + fit->mask |= (1L << fit_shrinklimit); + + inum = pdc_get_optvalues("position", resopts, fit->position, NULL); + if (inum) + { + pdf_set_position_values(p, fit->position, inum); + fit->mask |= (1L << fit_position); + } + + if (pdc_get_optvalues("matchbox", resopts, NULL, &strlist)) + { + fit->matchbox = pdf_parse_mbox_optlist(p, strlist[0]); + fit->mask |= (1L << fit_matchbox); + } + } +} + +pdc_bool +pdf_is_horiz_orientated(pdf_fit_options *fit) +{ + return (fit->orientate == 0 || fit->orientate == 180) ? + pdc_true : pdc_false; +} + diff --git a/src/pdflib/pdflib/p_object.c b/src/pdflib/pdflib/p_object.c new file mode 100644 index 0000000..8ff285c --- /dev/null +++ b/src/pdflib/pdflib/p_object.c @@ -0,0 +1,257 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_object.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib PDF object functions + * + */ + +#define P_OBJECT_C + +#include "p_intern.h" +#include "p_image.h" + + + +static const pdc_keyconn pdf_scope_keylist[] = +{ + {"object", pdf_state_object}, + {"document", pdf_state_document}, + {"page", pdf_state_page}, + {"pattern", pdf_state_pattern}, + {"template", pdf_state_template}, + {"path", pdf_state_path}, + {"font", pdf_state_font}, + {"glyph", pdf_state_glyph}, + {"glyphmetric", pdf_state_glyphmetric}, + {"glyphignore", pdf_state_glyphignore}, + {"error", pdf_state_error}, + {NULL, 0} +}; + +static pdc_error_info pdf_errors[] = +{ +#define pdf_genInfo 1 +#include "p_generr.h" +}; + +#define N_PDF_ERRORS (sizeof pdf_errors / sizeof (pdc_error_info)) + +const char * +pdf_current_scope(PDF *p) +{ + const char *scopename = + pdc_get_keyword(PDF_GET_STATE(p), pdf_scope_keylist); + + if (!scopename) + pdc_error(p->pdc, PDF_E_INT_BADSCOPE, + pdc_errprintf(p->pdc, " (0x%08X)", PDF_GET_STATE(p)), 0, 0, 0); + + return (char *) scopename; /* be happy, compiler! */ +} + +/* p may be NULL on the first call - we don't use it anyway */ +static void * +default_malloc(PDF *p, size_t size, const char *caller) +{ + void *ret = malloc(size); + + (void) p; + (void) caller; + + return ret; +} + +static void * +default_realloc(PDF *p, void *mem, size_t size, const char *caller) +{ + void *ret = realloc(mem, size); + + (void) p; + (void) caller; + + return ret; +} + +static void +default_free(PDF *p, void *mem) +{ + (void) p; + + free(mem); +} + +PDF * +pdf__new( + void (*errorhandler)(PDF *p, int type, const char *msg), + void* (*allocproc)(PDF *p, size_t size, const char *caller), + void* (*reallocproc)(PDF *p, void *mem, size_t size, const char *caller), + void (*freeproc)(PDF *p, void *mem), + void *opaque) +{ + PDF * p; + pdc_core * pdc; + + /* If allocproc is NULL, all entries are supplied internally by PDFlib */ + if (allocproc == NULL) { + allocproc = default_malloc; + reallocproc = default_realloc; + freeproc = default_free; + } + + p = (PDF *) (*allocproc) (NULL, sizeof(PDF), "PDF_new"); + + if (p == NULL) + return NULL; + + /* + * Guard against crashes when PDF_delete is called without any + * PDF_open_*() in between. + */ + memset((void *)p, 0, (size_t) sizeof(PDF)); + + /* these two are required by PDF_get_opaque() */ + p->magic = PDC_MAGIC; + p->opaque = opaque; + + pdc = pdc_new_core( + (pdc_error_fp) errorhandler, + (pdc_alloc_fp) allocproc, + (pdc_realloc_fp) reallocproc, + (pdc_free_fp) freeproc, p, + PDFLIB_PRODUCTNAME, + PDFLIB_VERSIONSTRING); + + if (pdc == NULL) + { + (*freeproc)(p, p); + return NULL; + } + + pdc_register_errtab(pdc, PDC_ET_PDFLIB, pdf_errors, N_PDF_ERRORS); + fnt_register_errtab(pdc); + + PDC_TRY(pdc) + { + p->freeproc = freeproc; + p->pdc = pdc; + p->compatibility = PDF_DEF_COMPATIBILITY; + p->errorpolicy = errpol_legacy; + + p->userinfo = NULL; + p->document = NULL; + + p->errorhandler = errorhandler; + + p->flush = pdc_flush_page; + + p->hypertextencoding= pdc_invalidenc; + p->hypertextformat = pdc_auto; + p->hypertextcodepage= 0; + p->usercoordinates = pdc_false; + p->usehyptxtenc = pdc_false; + + p->currfo = NULL; + p->curr_ppt = NULL; + + p->glyphcheck = text_nocheck; + p->textformat = pdc_auto; + p->in_text = pdc_false; + + + p->rendintent = AutoIntent; + p->preserveoldpantonenames = pdc_false; + p->spotcolorlookup = pdc_true; + p->ydirection = 1; + p->names = NULL; + p->names_capacity = 0; + p->xobjects = NULL; + p->state_sp = 0; + p->doc_pages = NULL; + + p->actions = NULL; + + + + + + PDF_SET_STATE(p, pdf_state_object); + + /* all debug flags are cleared by default + * because of the above memset... */ + + /* ...but warning messages for non-fatal errors should be set, + * as well as font warnings -- the client must explicitly disable these. + */ + p->debug[(int) 'e'] = pdc_true; + p->debug[(int) 'F'] = pdc_true; + p->debug[(int) 'I'] = pdc_true; + + pdf_init_stringlists(p); + pdf_init_font_options(p, NULL); + + p->out = pdc_boot_output(p->pdc); + + + } + PDC_CATCH(pdc) + { + pdc_delete_core(pdc); + return (PDF *) 0; + } + return p; +} /* pdf__new */ + + +/* + * PDF_delete must be called for cleanup in case of error, + * or when the client is done producing PDF. + * It should never be called more than once for a given PDF, although + * we try to guard against duplicated calls. + * + * Note: all pdf_cleanup_*() functions may safely be called multiple times. + */ + +void +pdf__delete(PDF *p) +{ + /* + * Close the output stream, because it could be open + */ + pdc_close_output(p->out); + + /* + * Clean up page-related stuff if necessary. Do not raise + * an error here since we may be called from the error handler. + */ + pdf_cleanup_document(p); + pdf_cleanup_stringlists(p); + pdf_cleanup_font_curroptions(p); + pdc_cleanup_output(p->out, pdc_false); + + + + + if (p->out) + pdc_free(p->pdc, p->out); + + /* we never reach this point if (p->pdc == NULL). + */ + pdc_delete_core(p->pdc); + + /* free the PDF structure and try to protect against duplicated calls */ + + p->magic = 0L; /* we don't reach this with the wrong magic */ + (*p->freeproc)(p, (void *) p); +} + diff --git a/src/pdflib/pdflib/p_opi.c b/src/pdflib/pdflib/p_opi.c new file mode 100644 index 0000000..94cb435 --- /dev/null +++ b/src/pdflib/pdflib/p_opi.c @@ -0,0 +1,21 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_opi.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib OPI routines + * + */ + +#include "p_intern.h" +#include "p_image.h" + diff --git a/src/pdflib/pdflib/p_page.c b/src/pdflib/pdflib/p_page.c new file mode 100644 index 0000000..c03aaf3 --- /dev/null +++ b/src/pdflib/pdflib/p_page.c @@ -0,0 +1,2261 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_page.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib page related routines + * + */ + +#define P_PAGE_C + +#include "p_intern.h" +#include "p_color.h" +#include "p_font.h" +#include "p_image.h" +#include "p_layer.h" +#include "p_page.h" +#include "p_tagged.h" + + + +#define PDF_N_PAGE_BOXES 5 + +static const pdc_keyconn pdf_labelstyle_pdfkeylist[] = +{ + {"none", label_none}, + {"D", label_123}, + {"R", label_IVX}, + {"r", label_ivx}, + {"A", label_ABC}, + {"a", label_abc}, + {NULL, 0} +}; + +typedef enum +{ + tabo_none, + tabo_row, + tabo_column, + tabo_structure +} +pdf_taborder; + +static const pdc_keyconn pdf_taborder_keylist[] = +{ + {"none", tabo_none}, + {"row", tabo_row}, + {"column", tabo_column}, + {"structure", tabo_structure}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_taborder_pdfkeylist[] = +{ + {"R", tabo_row}, + {"C", tabo_column}, + {"S", tabo_structure}, + {NULL, 0} +}; + +static const pdc_keyconn pdf_colorspace_pdfkeylist[] = +{ + {"DeviceGray", color_gray}, + {"DeviceRGB", color_rgb}, + {"DeviceCMYK", color_cmyk}, + {NULL, 0} +}; + +typedef struct +{ + pdf_colortype colorspace; /* color space */ + pdc_bool isolated; /* isolated flag I */ + pdc_bool knockout; /* knockout flag K */ +} pg_transgroup; + +typedef struct +{ + pdf_labelstyle style; /* page label style */ + char * prefix; /* page label prefix */ + int start; /* page label numbering start */ + /* 0 means "no label" */ +} pg_label; + +typedef struct +{ + char * name; /* group name */ + int n_pages; /* # of pages in this group */ + int capacity; /* # of pages reserved */ + int start; /* 1-based physical page number */ + pg_label label; +} pg_group; + +/* per page resource list +*/ +struct pdf_reslist_s +{ + int * list; /* resource numbers */ + int capacity; + int length; +}; + +/* current, or suspended page. +*/ +typedef struct +{ + pdf_ppt ppt; + + /* list of content stream IDs. + */ + pdc_id * contents_ids; + int contents_ids_capacity; + int next_content; + + pdc_vtr * annots; /* annotation chain */ + + /* local values of global parameters. + */ + pdc_scalar ydir; /* p->ydirection */ + + /* resource lists. + */ + pdf_reslist rl_colorspaces; + pdf_reslist rl_extgstates; + pdf_reslist rl_fonts; + pdf_reslist rl_layers; + pdf_reslist rl_patterns; + pdf_reslist rl_shadings; + pdf_reslist rl_xobjects; +} pdf_page; + + +/* PDF page object. +*/ +typedef struct +{ + pg_label label; + pdc_id id; /* object id for this page */ + pdf_page * pg; /* NULL if this page is not suspended */ + + /* object ids (PDC_BAD_ID if not present). + */ + pdc_id annots_id; /* id of page's /Annots entry */ + pdc_id contents_id; /* id of page's /Contents entry */ + pdc_id res_id; /* id of page's /Resources entry */ + pdc_id thumb_id; /* id of page's /Thumb entry */ + + int rotate; /* page's /Rotate entry */ + int transition; /* page transition type, or -1 */ + int taborder; /* page taborder type */ + double duration; /* page display duration, or -1 */ + pdc_scalar userunit; /* page user unit */ + char * action; /* "action" option string */ + + pg_transgroup tgroup; /* transparency group definition */ + + + pdc_id * act_idlist; /* action object ids */ + pdc_rectangle * boxes[PDF_N_PAGE_BOXES]; /* MediaBox etc. */ +} page_obj; + + +struct pdf_pages_s +{ + pdf_page *curr_pg; + pdc_bool have_labels; + pdc_bool have_groups; + pdc_bool in_csect; /* currently in contents section */ + int last_suspended; /* 1-based page number or -1 */ + pdf_ppt default_ppt; /* pseudo-ppt (for document scope) */ + + /* as long as we support the old global parameters in addition to + ** the new options, we have to save their values on entry to + ** begin/resume_page(), and restore them during end/suspend_page(). + */ + pdc_scalar old_ydir; /* p->ydirection */ + + /* deprecated parameters. + */ + int transition; /* page transition type */ + double duration; /* page display duration */ + + /* page descriptors in physical page order. + */ + page_obj * pages; /* page ids and suspended page descr */ + int pages_capacity; + int current_page; /* current page number (1-based) */ + int last_page; /* last page number allocated yet */ + int max_page; /* highest page number pre-allocated yet */ + + /* page groups. + */ + pg_group * groups; + int groups_capacity; + int n_groups; + + pdc_id *pnodes; /* page tree node ids */ + int pnodes_capacity; /* current # of entries in pnodes */ + int current_pnode; /* current node number (0-based) */ + int current_pnode_kids; /* current # of kids in current node */ +}; + + +static const pdc_rectangle pdf_null_rect = +{ + 0, 0, 0, 0 +}; + + +/*********************** initialization & cleanup ***********************/ + +static void +pdf_init_ppt(PDF *p, pdc_bool new_ppt) +{ + pdf_ppt *ppt = p->curr_ppt; + + if (new_ppt) + { + ppt->cstate = 0; + ppt->tstate = 0; + + ppt->mboxes = (pdc_vtr *) 0; + + ppt->cs_bias = 0; + ppt->eg_bias = 0; + ppt->fn_bias = 0; + ppt->pt_bias = 0; + ppt->sh_bias = 0; + ppt->xo_bias = 0; + } + + ppt->sl = 0; + + pdf_init_tstate(p); + pdf_init_gstate(p); + pdf_init_cstate(p); +} /* pdf_init_ppt */ + +static void +pdf_reset_ppt(pdf_ppt *ppt) +{ + if (ppt->mboxes) + { + pdc_vtr_delete(ppt->mboxes); + ppt->mboxes = (pdc_vtr *) 0; + } +} + +static void +pdf_delete_page(PDF *p, pdf_page *pg) +{ + if (pg != 0) + { + pdf_cleanup_page_cstate(p, &pg->ppt); + pdf_cleanup_page_tstate(p, &pg->ppt); + pdf_reset_ppt(&pg->ppt); + + if (pg->contents_ids) + pdc_free(p->pdc, pg->contents_ids); + + if (pg->annots) + { + pdc_vtr_delete(pg->annots); + pg->annots = (pdc_vtr *) 0; + } + + if (pg->rl_colorspaces.list) + pdc_free(p->pdc, pg->rl_colorspaces.list); + if (pg->rl_extgstates.list) + pdc_free(p->pdc, pg->rl_extgstates.list); + if (pg->rl_fonts.list) + pdc_free(p->pdc, pg->rl_fonts.list); + if (pg->rl_layers.list) + pdc_free(p->pdc, pg->rl_layers.list); + if (pg->rl_patterns.list) + pdc_free(p->pdc, pg->rl_patterns.list); + if (pg->rl_shadings.list) + pdc_free(p->pdc, pg->rl_shadings.list); + if (pg->rl_xobjects.list) + pdc_free(p->pdc, pg->rl_xobjects.list); + + pdc_free(p->pdc, pg); + } +} /* pdf_delete_page */ + + +static void +pdf_init_page_obj(page_obj *po) +{ + int i; + + po->id = PDC_BAD_ID; + po->pg = (pdf_page *) 0; + po->label.start = 0; + po->label.prefix = (char *) 0; + + po->tgroup.colorspace = color_none; + po->tgroup.isolated = pdc_false; + po->tgroup.knockout = pdc_false; + + po->annots_id = PDC_BAD_ID; + po->contents_id = PDC_BAD_ID; + po->res_id = PDC_BAD_ID; + po->thumb_id = PDC_BAD_ID; + po->transition = -1; + po->duration = -1; + po->taborder = (int) tabo_none; + po->userunit = 1.0; + po->action = (char *) 0; + + po->rotate = 0; + + po->act_idlist = (pdc_id *) 0; + for (i = 0; i < PDF_N_PAGE_BOXES; ++i) + po->boxes[i] = (pdc_rectangle *) 0; +} /* pdf_init_page_obj */ + + +static void +pdf_grow_pages(PDF *p) +{ + static const char fn[] = "pdf_grow_pages"; + + pdf_pages *dp = p->doc_pages; + int i; + + dp->pages = (page_obj *) pdc_realloc(p->pdc, dp->pages, + 2 * sizeof (page_obj) * dp->pages_capacity, fn); + + for (i = dp->pages_capacity; i < dp->pages_capacity * 2; i++) + pdf_init_page_obj(&dp->pages[i]); + + dp->pages_capacity *= 2; +} /* pdf_grow_pages */ + + +void +pdf_init_pages(PDF *p, const char **groups, int n_groups) +{ + static const char fn[] = "pdf_init_pages"; + + int i, k; + pdf_pages * dp = (pdf_pages *) pdc_malloc(p->pdc, sizeof (pdf_pages), fn); + + p->doc_pages = dp; + + dp->have_labels = pdc_false; + dp->have_groups = (n_groups != 0); + dp->n_groups = 0; + dp->last_suspended = 0; + dp->in_csect = pdc_false; + dp->transition = (int) trans_none; + dp->duration = 0; + + dp->pages = (page_obj *) 0; + dp->pnodes = (pdc_id *) 0; + + dp->pages_capacity = PAGES_CHUNKSIZE; + dp->pages = (page_obj *) + pdc_malloc(p->pdc, sizeof (page_obj) * dp->pages_capacity, fn); + + /* mark ids to allow for pre-allocation of page ids */ + for (i = 0; i < dp->pages_capacity; i++) + pdf_init_page_obj(&dp->pages[i]); + + dp->current_page = 0; + dp->last_page = 0; + dp->max_page = 0; + dp->curr_pg = (pdf_page *) 0; + + dp->pnodes_capacity = PNODES_CHUNKSIZE; + dp->pnodes = (pdc_id *) + pdc_malloc(p->pdc, sizeof (pdc_id) * dp->pnodes_capacity, fn); + + dp->current_pnode = 0; + dp->current_pnode_kids = 0; + + /* clients may set char/word spacing and horizontal scaling outside pages + ** for PDF_stringwidth() calculations, and they may set a color for use + ** in PDF_makespotcolor(). that's what default_ppt is good for. + */ + p->curr_ppt = &dp->default_ppt; + pdf_init_ppt(p, pdc_true); + + for (i = 0; i < n_groups - 1; ++i) + for (k = i + 1; k < n_groups; ++k) + if (strcmp(groups[i], groups[k]) == 0) + { + pdc_error(p->pdc, PDF_E_DOC_DUPLGROUP, groups[i], 0, 0, 0); + } + + dp->n_groups = n_groups; + dp->groups = (pg_group *) (n_groups ? + pdc_malloc(p->pdc, sizeof (pg_group) * n_groups, fn) : 0); + + for (i = 0; i < n_groups; ++i) + { + dp->groups[i].name = pdc_strdup(p->pdc, groups[i]); + dp->groups[i].n_pages = 0; + dp->groups[i].capacity = 0; + dp->groups[i].start = 1; + dp->groups[i].label.prefix = (char *) 0; + dp->groups[i].label.start = 0; + } +} /* pdf_init_pages */ + + +void pdf_check_suspended_pages(PDF *p) +{ + int i; + pdf_pages * dp = p->doc_pages; + + for (i = 0; i <= dp->last_page; ++i) + { + if (dp->pages[i].pg != (pdf_page *) 0) + { + pdc_error(p->pdc, PDF_E_PAGE_SUSPENDED, + pdc_errprintf(p->pdc, "%d", i), 0, 0, 0); + } + } +} /* pdf_check_suspended_pages */ + + +void +pdf_cleanup_pages(PDF *p) +{ + if (p->doc_pages != (pdf_pages *) 0) + { + int i; + pdf_pages * dp = p->doc_pages; + + if (dp->groups) + { + for (i = 0; i < dp->n_groups; ++i) + { + if (dp->groups[i].name) + pdc_free(p->pdc, dp->groups[i].name); + + if (dp->groups[i].label.prefix) + pdc_free(p->pdc, dp->groups[i].label.prefix); + } + + pdc_free(p->pdc, dp->groups); + } + + if (dp->curr_pg) + pdf_delete_page(p, dp->curr_pg); + + if (dp->pages) + { + for (i = 0; i <= dp->last_page; ++i) + { + int k; + page_obj *po = &dp->pages[i]; + + if (po->label.prefix) + pdc_free(p->pdc, po->label.prefix); + + if (po->action) + pdc_free(p->pdc, po->action); + + + if (po->pg != (pdf_page *) 0) + pdf_delete_page(p, po->pg); + + if (po->act_idlist != (pdc_id *) 0) + pdc_free(p->pdc, po->act_idlist); + + for (k = 0; k < PDF_N_PAGE_BOXES; ++k) + { + if (po->boxes[k] != (pdc_rectangle *) 0) + pdc_free(p->pdc, po->boxes[k]); + } + } + + pdc_free(p->pdc, dp->pages); + } + + if (dp->pnodes) + { + pdc_free(p->pdc, dp->pnodes); + } + + if (p->curr_ppt != 0) + { + pdf_cleanup_page_cstate(p, &dp->default_ppt); + pdf_cleanup_page_tstate(p, &dp->default_ppt); + } + + pdc_free(p->pdc, p->doc_pages); + p->doc_pages = (pdf_pages *) 0; + } +} /* pdf_cleanup_pages */ + + +/******************** page group & labels management ********************/ + +static pg_group * +find_group(pdf_pages *dp, const char *name) +{ + int i; + + for (i = 0; i < dp->n_groups; ++i) + if (strcmp(dp->groups[i].name, name) == 0) + return &dp->groups[i]; + + return (pg_group *) 0; +} /* find_group */ + + +static void +grow_group(PDF *p, pg_group *group, int pageno, int n) +{ + pdf_pages * dp = p->doc_pages; + int i; + + while (dp->max_page + n >= dp->pages_capacity) + pdf_grow_pages(p); + + if (dp->max_page >= pageno) + { + memmove(&dp->pages[pageno + n], &dp->pages[pageno], + (dp->max_page - pageno + 1) * sizeof (page_obj)); + + for (i = pageno; i < pageno + n; ++i) + pdf_init_page_obj(&dp->pages[i]); + } + + dp->max_page += n; + + if (dp->last_page >= pageno) + dp->last_page += n; + + if (dp->current_page >= pageno) + dp->current_page += n; + + group->capacity += n; + + for (i = group - dp->groups + 1; i < dp->n_groups; ++i) + dp->groups[i].start += n; +} + + +/* translate the group-relative pageno to an absolute page number. +** as a side effect, the group gets enlarged as needed if pageno +** exceeds the current number of pages in the group. +*/ +int +pdf_xlat_pageno(PDF *p, int pageno, const char *groupname) +{ + pdf_pages * dp = p->doc_pages; + pg_group * group = (pg_group *) 0; + + if (groupname && *groupname) + { + if ((group = find_group(dp, groupname)) == (pg_group *) 0) + pdc_error(p->pdc, PDF_E_DOC_UNKNOWNGROUP, groupname, 0, 0, 0); + } + + if (group) + { + if (pageno < 1) + pdc_error(p->pdc, PDF_E_PAGE_NOTEXIST2, + pdc_errprintf(p->pdc, "%d", pageno), group->name, 0, 0); + + if (pageno > group->capacity) + grow_group(p, group, group->start + group->capacity, + pageno - group->capacity); + + pageno = group->start + pageno - 1; + } + else + { + if (dp->have_groups && pageno != 0) + pdc_error(p->pdc, PDF_E_PAGE_NEEDGROUP, 0, 0, 0, 0); + } + + return pageno; +} + + +/* TODO (york): get rid of this function. +*/ +void +pdf_init_pages2(PDF *p) +{ + pdf_pages * dp = p->doc_pages; + + dp->pnodes[0] = pdc_alloc_id(p->out); +} /* pdf_init_pages2 */ + + +static const pdc_defopt pdf_pagelabel_options[] = +{ + {"pagenumber", pdc_integerlist, PDC_OPT_NONE, 1, 1, + 1.0, PDC_INT_MAX, NULL}, + + {"group", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 1.0, PDF_MAX_NAMESTRING, NULL}, + + {"style", pdc_keywordlist, PDC_OPT_CASESENS, 1, 1, + 0.0, 0.0, pdf_labelstyle_pdfkeylist}, + + {"hypertextencoding", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDF_MAX_NAMESTRING, NULL}, + + {"prefix", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 0.0, PDF_MAX_NAMESTRING, NULL}, + + {"start", pdc_integerlist, PDC_OPT_NONE, 1, 1, + 1.0, PDC_INT_MAX, NULL}, + + PDC_OPT_TERMINATE +}; + +void +pdf_set_pagelabel(PDF *p, const char *optlist, int pageno) +{ + pdf_pages * dp = p->doc_pages; + pg_label * lp; + pdc_resopt *resopts = NULL; + char ** strlist; + int inum; + + int page = 0; + char * groupname = NULL; + pdf_labelstyle style = label_none; + pdc_encoding htenc; + int htcp; + char * prefix = NULL; + int start = 1; + + resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_pagelabel_options, + NULL, pdc_true); + + switch (pageno) + { + case PDF_FC_BEGIN_DOCUMENT: + if (pdc_get_optvalues("group", resopts, NULL, &strlist)) + groupname = strlist[0]; + else + pdc_error(p->pdc, PDF_E_DOC_NEED_LABELOPT, "group", 0, 0, 0); + + if (pdc_get_optvalues("pagenumber", resopts, &page, NULL)) + pdc_error(p->pdc, PDF_E_DOC_ILL_LABELOPT, + "pagenumber", 0, 0, 0); + break; + + case PDF_FC_END_DOCUMENT: + if (pdc_get_optvalues("group", resopts, NULL, &strlist)) + pdc_error(p->pdc, PDF_E_DOC_ILL_LABELOPT, "group", 0, 0, 0); + + if (!pdc_get_optvalues("pagenumber", resopts, &page, NULL)) + pdc_error(p->pdc, PDF_E_DOC_NEED_LABELOPT, + "pagenumber", 0, 0, 0); + + break; + + default: + if (pdc_get_optvalues("group", resopts, NULL, &strlist)) + pdc_error(p->pdc, PDF_E_DOC_ILL_LABELOPT, "group", 0, 0, 0); + + if (pdc_get_optvalues("pagenumber", resopts, &page, NULL)) + pdc_error(p->pdc, PDF_E_DOC_ILL_LABELOPT, + "pagenumber", 0, 0, 0); + + page = pageno; + break; + } + + if (pdc_get_optvalues("style", resopts, &inum, NULL)) + style = (pdf_labelstyle) inum; + + htenc = pdf_get_hypertextencoding_opt(p, resopts, &htcp, pdc_true); + + pdf_get_opt_textlist(p, "prefix", resopts, htenc, htcp, + pdc_true, NULL, &prefix, NULL); + pdc_get_optvalues("start", resopts, &start, NULL); + + dp->have_labels = pdc_true; + + if (groupname) + { + pg_group *group; + + if ((group = find_group(dp, groupname)) == (pg_group *) 0) + pdc_error(p->pdc, PDF_E_DOC_UNKNOWNGROUP, groupname, 0, 0, 0); + + lp = &group->label; + } + else + { + if (dp->last_page < page) + pdc_error(p->pdc, PDF_E_PAGE_NOTEXIST, + pdc_errprintf(p->pdc, "%d", page), 0, 0, 0); + + lp = &dp->pages[page].label; + } + + lp->style = style; + lp->start = start; + + if (prefix) + { + if (lp->prefix) + pdc_free(p->pdc, lp->prefix); + + lp->prefix = pdc_strdup(p->pdc, prefix); + } +} /* pdf_set_pagelabel */ + + +static void +write_label(PDF *p, pg_label *label, int pageno) +{ + pdc_printf(p->out, "%d", pageno); + pdc_begin_dict(p->out); + + if (label->style != label_none) + { + pdc_printf(p->out, "/S/%s", + pdc_get_keyword(label->style, pdf_labelstyle_pdfkeylist)); + } + + if (label->prefix) + { + pdc_printf(p->out, "/P"); + pdf_put_hypertext(p, label->prefix); + } + + if (label->start != 1) + pdc_printf(p->out, "/St %d", label->start); + + pdc_end_dict(p->out); +} /* write_label */ + + +pdc_id +pdf_write_pagelabels(PDF *p) +{ + pdf_pages * dp = p->doc_pages; + pdc_id result; + int i, k; + + if (!dp->have_labels || dp->last_page == 0) + return PDC_BAD_ID; + + result = pdc_begin_obj(p->out, PDC_NEW_ID); + pdc_begin_dict(p->out); + + pdc_printf(p->out, "/Nums"); + pdc_begin_array(p->out); + + /* generate default label if page 1 doesn't have one: + */ + if (dp->pages[1].label.start == 0 && + (dp->n_groups == 0 || dp->groups[0].label.start == 0)) + { + pdc_puts(p->out, "0"); + pdc_begin_dict(p->out); + pdc_puts(p->out, "/S/D"); /* 1-based decimal w/o prefix */ + pdc_end_dict(p->out); + } + + if (dp->n_groups == 0) + { + for (i = 1; i <= dp->last_page; ++i) + if (dp->pages[i].label.start != 0) + write_label(p, &dp->pages[i].label, i - 1); + } + else + { + for (i = 0; i < dp->n_groups; ++i) + { + pg_group *gp = &dp->groups[i]; + + if (gp->label.start != 0 && gp->n_pages != 0) + { + /* if present, the page label beats the group label. + */ + if (dp->pages[gp->start].label.start == 0) + write_label(p, &gp->label, gp->start - 1); + } + + for (k = gp->start; k < gp->start + gp->n_pages; ++k) + if (dp->pages[k].label.start != 0) + write_label(p, &dp->pages[k].label, k - 1); + } + } + + pdc_end_array_c(p->out); + pdc_end_dict(p->out); + pdc_end_obj(p->out); + + return result; +} /* pdf_write_pagelabels */ + +static const pdc_defopt pdf_transgroup_options[] = +{ + {"CS", pdc_keywordlist, PDC_OPT_NONE, 1, 1, + 1.0, PDC_INT_MAX, pdf_colorspace_pdfkeylist}, + + {"I", pdc_booleanlist, PDC_OPT_NONE, 1, 1, + 0.0, 0.0, NULL}, + + {"K", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ + + PDC_OPT_TERMINATE +}; + +static void +pdf_set_transgroup(PDF *p, const char *optlist, int pageno) +{ + pdf_pages * dp = p->doc_pages; + page_obj * po = &dp->pages[pageno]; + pdc_resopt *resopts = NULL; + int inum; + + resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_transgroup_options, + NULL, pdc_true); + + if (pdc_get_optvalues("CS", resopts, &inum, NULL)) + po->tgroup.colorspace = (pdf_colortype) inum; + + pdc_get_optvalues("I", resopts, &po->tgroup.isolated, NULL); + pdc_get_optvalues("K", resopts, &po->tgroup.knockout, NULL); +} + +static void +write_transgroup(PDF *p, int pageno) +{ + pdf_pages * dp = p->doc_pages; + page_obj *po = &dp->pages[pageno]; + + pdc_puts(p->out, "/Group"); + pdc_begin_dict(p->out); + pdc_printf(p->out, "/S/Transparency/CS/%s", + pdc_get_keyword(po->tgroup.colorspace, + pdf_colorspace_pdfkeylist)); + + if (po->tgroup.isolated) + pdc_printf(p->out, "/I true"); + + if (po->tgroup.knockout) + pdc_printf(p->out, "/K true"); + + pdc_end_dict(p->out); +} + + +/************************** utility functions ***************************/ + +/* get the id of an existing or future page. +** pageno == 0 means current page. note that pdf_get_page_id(0) returns +** PDC_BAD_ID if no page has been opened yet, whereas pdf_current_page_id() +** returns a pre-allocated id for page 1 in this case. +*/ +pdc_id +pdf_get_page_id(PDF *p, int pageno) +{ + pdf_pages *dp = p->doc_pages; + + if (pageno == 0) + { + return dp->pages[dp->current_page].id; + } + else + { + while (pageno >= dp->pages_capacity) + pdf_grow_pages(p); + + /* preallocate page object id for a later page + */ + if (dp->pages[pageno].id == PDC_BAD_ID) + dp->pages[pageno].id = pdc_alloc_id(p->out); + + return dp->pages[pageno].id; + } +} /* pdf_get_page_id */ + +int +pdf_current_page(PDF *p) +{ + pdf_pages *dp = p->doc_pages; + + return dp ? dp->current_page : 0; +} /* pdf_current_page */ + +/* get the id of the current page. if there are no pages in the +** document yet, an id will be pre-allocated for page 1. +*/ +int +pdf_current_page_id(PDF *p) +{ + pdf_pages *dp = p->doc_pages; + + if (dp->current_page != 0) + return dp->pages[dp->current_page].id; + else + return pdf_get_page_id(p, 1); +} /* pdf_current_page_id */ + +int +pdf_last_page(PDF *p) +{ + return p->doc_pages->last_page; +} /* pdf_last_page */ + +int +pdf_search_page_fwd(PDF *p, int start_page, pdc_id id) +{ + pdf_pages * dp = p->doc_pages; + int i; + + for (i = start_page; i <= dp->last_page; ++i) + { + if (dp->pages[i].id == id) + return i; + } + + return -1; +} /* pdf_search_page_fwd */ + +int +pdf_search_page_bwd(PDF *p, int start_page, pdc_id id) +{ + pdf_pages * dp = p->doc_pages; + int i; + + if (start_page == -1) + start_page = dp->last_page; + + for (i = start_page; i > 0; --i) + { + if (dp->pages[i].id == id) + return i; + } + + return -1; +} /* pdf_search_page_bwd */ + + +double +pdf_get_pageheight(PDF *p) +{ + pdf_pages * dp = p->doc_pages; + page_obj * po = &dp->pages[dp->current_page]; + + return po->boxes[pdf_mediabox]->ury - po->boxes[pdf_mediabox]->lly; +} /* pdf_get_pageheight */ + +void +pdf_set_pagebox( + PDF * p, + pdf_pagebox box, + pdc_scalar llx, + pdc_scalar lly, + pdc_scalar urx, + pdc_scalar ury) +{ + static const char fn[] = "pdf_set_pagebox"; + + pdf_pages * dp = p->doc_pages; + page_obj * po = &dp->pages[dp->current_page]; + + if (po->boxes[box] == (pdc_rectangle *) 0) + { + po->boxes[box] = (pdc_rectangle *) + pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn); + } + + pdc_rect_init(po->boxes[box], llx, lly, urx, ury); +} /* pdf_set_pagebox */ + +void +pdf_set_pagebox_llx(PDF *p, pdf_pagebox box, pdc_scalar llx) +{ + static const char fn[] = "pdf_set_pagebox_llx"; + + pdf_pages * dp = p->doc_pages; + page_obj * po = &dp->pages[dp->current_page]; + + if (po->boxes[box] == (pdc_rectangle *) 0) + { + po->boxes[box] = (pdc_rectangle *) + pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn); + + pdc_rect_init(po->boxes[box], 0, 0, 0, 0); + } + + po->boxes[box]->llx = llx; +} /* pdf_set_pagebox_llx */ + +void +pdf_set_pagebox_lly(PDF *p, pdf_pagebox box, pdc_scalar lly) +{ + static const char fn[] = "pdf_set_pagebox_lly"; + + pdf_pages * dp = p->doc_pages; + page_obj * po = &dp->pages[dp->current_page]; + + if (po->boxes[box] == (pdc_rectangle *) 0) + { + po->boxes[box] = (pdc_rectangle *) + pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn); + + pdc_rect_init(po->boxes[box], 0, 0, 0, 0); + } + + po->boxes[box]->lly = lly; +} /* pdf_set_pagebox_lly */ + +void +pdf_set_pagebox_urx(PDF *p, pdf_pagebox box, pdc_scalar urx) +{ + static const char fn[] = "pdf_set_pagebox_urx"; + + pdf_pages * dp = p->doc_pages; + page_obj * po = &dp->pages[dp->current_page]; + + if (po->boxes[box] == (pdc_rectangle *) 0) + { + po->boxes[box] = (pdc_rectangle *) + pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn); + + pdc_rect_init(po->boxes[box], 0, 0, 0, 0); + } + + po->boxes[box]->urx = urx; +} /* pdf_set_pagebox_urx */ + +void +pdf_set_pagebox_ury(PDF *p, pdf_pagebox box, pdc_scalar ury) +{ + static const char fn[] = "pdf_set_pagebox_ury"; + + pdf_pages * dp = p->doc_pages; + page_obj * po = &dp->pages[dp->current_page]; + + if (po->boxes[box] == (pdc_rectangle *) 0) + { + po->boxes[box] = (pdc_rectangle *) + pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn); + + pdc_rect_init(po->boxes[box], 0, 0, 0, 0); + } + + po->boxes[box]->ury = ury; +} /* pdf_set_pagebox_ury */ + +const pdc_rectangle * +pdf_get_pagebox(PDF *p, pdf_pagebox box) +{ + pdf_pages * dp = p->doc_pages; + page_obj * po = &dp->pages[dp->current_page]; + + if (po->boxes[box]) + return po->boxes[box]; + else + return &pdf_null_rect; +} /* pdf_get_pagebox */ + +pdc_vtr * +pdf_get_annots_list(PDF *p) +{ + pdf_pages * dp = p->doc_pages; + + return dp->curr_pg->annots; +} /* pdf_get_annots_list */ + +void +pdf_set_annots_list(PDF *p, pdc_vtr *annots) +{ + pdf_pages * dp = p->doc_pages; + + if (dp->curr_pg) + dp->curr_pg->annots = annots; +} /* pdf_set_annots_list */ + + +pdc_id +pdf_get_thumb_id(PDF *p) +{ + pdf_pages * dp = p->doc_pages; + page_obj * po = &dp->pages[dp->current_page]; + + return po->thumb_id; +} /* pdf_get_thumb_id */ + +void +pdf_set_thumb_id(PDF *p, pdc_id id) +{ + pdf_pages * dp = p->doc_pages; + page_obj * po = &dp->pages[dp->current_page]; + + po->thumb_id = id; +} /* pdf_set_thumb_id */ + + +/************************* contents sections ***************************/ + +void +pdf_begin_contents_section(PDF *p) +{ + pdf_page *pg = p->doc_pages->curr_pg; + + if (PDF_GET_STATE(p) != pdf_state_page || p->doc_pages->in_csect) + return; + + p->doc_pages->in_csect = pdc_true; + + if (pg->next_content >= pg->contents_ids_capacity) { + pg->contents_ids_capacity *= 2; + pg->contents_ids = (pdc_id *) pdc_realloc(p->pdc, pg->contents_ids, + sizeof(pdc_id) * pg->contents_ids_capacity, + "pdf_begin_contents_section"); + } + + pg->contents_ids[pg->next_content] = pdc_begin_obj(p->out, PDC_NEW_ID); + pdc_begin_dict(p->out); + p->length_id = pdc_alloc_id(p->out); + pdc_objref(p->out, "/Length", p->length_id); + + if (pdc_get_compresslevel(p->out)) + pdc_puts(p->out, "/Filter/FlateDecode\n"); + + pdc_end_dict(p->out); + + pdc_begin_pdfstream(p->out); + + pg->next_content++; +} /* pdf_begin_contents_section */ + + +void +pdf_end_contents_section(PDF *p) +{ + if (!p->doc_pages->in_csect) + return; + + p->doc_pages->in_csect = pdc_false; + + pdf_end_text(p); + pdc_end_pdfstream(p->out); + pdc_end_obj(p->out); + + pdc_put_pdfstreamlength(p->out, p->length_id); +} /* pdf_end_contents_section */ + + +/************************* page tree generation *************************/ + +static void +pdf_write_pnode(PDF *p, + pdc_id node_id, + pdc_id parent_id, + page_obj *kids, + int n_kids, + int n_pages) +{ + pdc_begin_obj(p->out, node_id); + pdc_begin_dict(p->out); + pdc_puts(p->out, "/Type/Pages\n"); + pdc_printf(p->out, "/Count %d\n", n_pages); + + if (parent_id != PDC_BAD_ID) + pdc_objref(p->out, "/Parent", parent_id); + + pdc_puts(p->out, "/Kids"); + pdc_begin_array(p->out); + + do + { + pdc_objref_c(p->out, kids->id); + ++kids; + } while (--n_kids > 0); + + pdc_end_array_c(p->out); + pdc_end_dict(p->out); + pdc_end_obj(p->out); +} /* pdf_write_pnode */ + +#define N_KIDS 10 + +static pdc_id +pdf_get_pnode_id(PDF *p) +{ + static const char fn[] = "pdf_get_pnode_id"; + + pdf_pages *dp = p->doc_pages; + + if (dp->current_pnode_kids == N_KIDS) + { + if (++dp->current_pnode == dp->pnodes_capacity) + { + dp->pnodes_capacity *= 2; + dp->pnodes = (pdc_id *) pdc_realloc(p->pdc, dp->pnodes, + sizeof (pdc_id) * dp->pnodes_capacity, fn); + } + + dp->pnodes[dp->current_pnode] = pdc_alloc_id(p->out); + dp->current_pnode_kids = 1; + } + else + ++dp->current_pnode_kids; + + return dp->pnodes[dp->current_pnode]; +} /* pdf_get_pnode_id */ + +static pdc_id +write_pages_tree(PDF *p, + pdc_id parent_id, + pdc_id *pnodes, + page_obj *pages, + int n_pages) +{ + if (n_pages <= N_KIDS) + { + /* this is a near-to-leaf node. use the pre-allocated id + ** from dp->pnodes. + */ + pdf_write_pnode(p, *pnodes, parent_id, pages, n_pages, n_pages); + return *pnodes; + } + else + { + pdc_id node_id = pdc_alloc_id(p->out); + page_obj kids[N_KIDS]; + int n_kids, rest; + int tpow = N_KIDS; + int i; + + /* tpow < n_pages <= tpow*N_KIDS + */ + while (tpow * N_KIDS < n_pages) + tpow *= N_KIDS; + + n_kids = n_pages / tpow; + rest = n_pages % tpow; + + for (i = 0; i < n_kids; ++i, pnodes += tpow / N_KIDS, pages += tpow) + { + kids[i].id = write_pages_tree(p, node_id, pnodes, pages, tpow); + } + + if (rest) + { + kids[i].id = write_pages_tree(p, node_id, pnodes, pages, rest); + ++n_kids; + } + + pdf_write_pnode(p, node_id, parent_id, kids, n_kids, n_pages); + return node_id; + } +} /* write_pages_tree */ + +static void +pdf_write_box(PDF *p, pdc_rectangle *box, const char *name) +{ + if (!box || pdc_rect_isnull(box)) + return; + + if (box->urx <= box->llx || box->ury <= box->lly) + { + pdc_error(p->pdc, PDF_E_PAGE_BADBOX, name, + pdc_errprintf(p->pdc, "%f %f %f %f", + box->llx, box->lly, box->urx, box->ury), 0, 0); + } + + pdc_printf(p->out, "/%s[%f %f %f %f]\n", + name, box->llx, box->lly, box->urx, box->ury); +} /* pdf_write_box */ + +pdc_id +pdf_write_pages_tree(PDF *p) +{ + int i; + pdf_pages * dp = p->doc_pages; + + for (i = dp->last_page + 1; i < dp->pages_capacity; ++i) + { + if (dp->pages[i].id != PDC_BAD_ID) + { + pdc_error(p->pdc, PDF_E_PAGE_ILLREF, + pdc_errprintf(p->pdc, "%d", i), 0, 0, 0); + } + } + + for (i = 1; i <= dp->last_page; ++i) + { + page_obj *po = &dp->pages[i]; + + pdc_begin_obj(p->out, po->id); + pdc_begin_dict(p->out); + pdc_puts(p->out, "/Type/Page\n"); + pdc_objref(p->out, "/Parent", pdf_get_pnode_id(p)); + + if (po->annots_id != PDC_BAD_ID) + pdc_objref(p->out, "/Annots", po->annots_id); + + if (po->contents_id != PDC_BAD_ID) + pdc_objref(p->out, "/Contents", po->contents_id); + + if (po->res_id != PDC_BAD_ID) + pdc_objref(p->out, "/Resources", po->res_id); + + if (po->thumb_id != PDC_BAD_ID) + pdc_objref(p->out, "/Thumb", po->thumb_id); + + if (po->duration > 0) + pdc_printf(p->out, "/Dur %f\n", po->duration); + + if (po->taborder != (int) tabo_none) + pdc_printf(p->out, "/Tabs/%s\n", + pdc_get_keyword(po->taborder, pdf_taborder_pdfkeylist)); + + if (po->userunit > 1.0) + pdc_printf(p->out, "/UserUnit %f\n", po->userunit); + + if (po->rotate > 0) + pdc_printf(p->out, "/Rotate %d\n", po->rotate); + + if (po->action) + pdf_write_action_entries(p, event_page, po->act_idlist); + + + + + if (po->transition != trans_none) + { + pdc_puts(p->out, "/Trans"); + pdc_begin_dict(p->out); + pdc_printf(p->out, "/S/%s", + pdc_get_keyword(po->transition, pdf_transition_pdfkeylist)); + + pdc_end_dict(p->out); + } + + if (po->tgroup.colorspace != color_none) + write_transgroup(p, i); + + pdf_write_box(p, po->boxes[pdf_artbox], "ArtBox"); + pdf_write_box(p, po->boxes[pdf_bleedbox], "BleedBox"); + pdf_write_box(p, po->boxes[pdf_cropbox], "CropBox"); + pdf_write_box(p, po->boxes[pdf_mediabox], "MediaBox"); + pdf_write_box(p, po->boxes[pdf_trimbox], "TrimBox"); + + pdc_end_dict(p->out); + pdc_end_obj(p->out); + } + + return write_pages_tree(p, PDC_BAD_ID, dp->pnodes, dp->pages + 1, + dp->last_page); +} /* pdf_write_pages_tree */ + + +/**************************** resource lists ****************************/ + +static void +pdf_init_reslist(pdf_reslist *rl) +{ + rl->length = 0; + rl->capacity = 0; + rl->list = (int *) 0; +} /* pdf_init_reslist */ + +void +pdf_add_reslist(PDF *p, pdf_reslist *rl, int num) +{ + static const char fn[] = "pdf_add_reslist"; + + if (rl->length == rl->capacity) + { + if (rl->capacity == 0) + { + rl->capacity = RESLIST_CHUNKSIZE; + rl->list = (int *) + pdc_malloc(p->pdc, rl->capacity * sizeof (pdf_reslist), fn); + } + else + { + rl->capacity *= 2; + rl->list = (int *) pdc_realloc(p->pdc, + rl->list, rl->capacity * sizeof (pdf_reslist), fn); + } + } + + rl->list[rl->length++] = num; +} /* pdf_add_reslist */ + + +/****************************** begin_page ******************************/ + +/* begin_page_ext() only: +*/ +#define PDF_ICC_FLAG PDC_OPT_UNSUPP +#define PDF_SPOT_FLAG PDC_OPT_UNSUPP + +#define PDF_METADATA_FLAG PDC_OPT_UNSUPP + +static const pdc_defopt pdf_sepinfo_options[] = +{ + {"pages", pdc_integerlist, PDC_OPT_NONE, 1, 1, + 1.0, PDC_INT_MAX, NULL}, + + {"spotname", pdc_stringlist, PDC_OPT_NONE, 1, 1, + 1.0, PDF_MAX_NAMESTRING, NULL}, + + {"spotcolor", pdc_colorhandle, PDC_OPT_NONE, 1, 1, + 1.0, PDC_INT_MAX, NULL}, + + PDC_OPT_TERMINATE +}; + +#define PDF_PAGE_OPTIONS1 \ +\ + {"topdown", pdc_booleanlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, NULL}, \ +\ + {"defaultgray", pdc_iccprofilehandle, PDF_ICC_FLAG, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + {"defaultrgb", pdc_iccprofilehandle, PDF_ICC_FLAG, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + {"defaultcmyk", pdc_iccprofilehandle, PDF_ICC_FLAG, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + {"separationinfo", pdc_stringlist, PDF_SPOT_FLAG, 1, 1, \ + 0.0, PDC_USHRT_MAX, NULL}, \ + +/* begin_page_ext() and resume_page(): +*/ +#define PDF_PAGE_OPTIONS2 \ +\ + {"group", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 1.0, PDF_MAX_NAMESTRING, NULL}, \ +\ + {"pagenumber", pdc_integerlist, PDC_OPT_NONE, 1, 1, \ + 1.0, PDC_INT_MAX, NULL}, \ + +/* begin_page_ext() and end_page_ext(): +*/ +static const pdc_keyconn pdf_pagedim_keylist[] = +{ + { "a0.width", (int) a0_width }, + { "a0.height", (int) a0_height }, + { "a1.width", (int) a1_width }, + { "a1.height", (int) a1_height }, + { "a2.width", (int) a2_width }, + { "a2.height", (int) a2_height }, + { "a3.width", (int) a3_width }, + { "a3.height", (int) a3_height }, + { "a4.width", (int) a4_width }, + { "a4.height", (int) a4_height }, + { "a5.width", (int) a5_width }, + { "a5.height", (int) a5_height }, + { "a6.width", (int) a6_width }, + { "a6.height", (int) a6_height }, + { "b5.width", (int) b5_width }, + { "b5.height", (int) b5_height }, + { "letter.width", (int) letter_width }, + { "letter.height", (int) letter_height }, + { "legal.width", (int) legal_width }, + { "legal.height", (int) legal_height }, + { "ledger.width", (int) ledger_width }, + { "ledger.height", (int) ledger_height }, + { "11x17.width", (int) p11x17_width }, + { "11x17.height", (int) p11x17_height }, + { NULL, 0 } +}; + +typedef enum +{ + pdf_unit_mm = -1000, + pdf_unit_cm = -100, + pdf_unit_m = -1 +} +pdf_page_unit; + +static const pdc_keyconn pdf_userunit_keylist[] = +{ + { "mm", pdf_unit_mm }, + { "cm", pdf_unit_cm }, + { "m", pdf_unit_m }, + + { NULL, 0 } +}; + + +#define PDF_PAGE_OPTIONS3 \ +\ + {"action", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 1.0, PDF_MAX_NAMESTRING, NULL}, \ +\ + {"artbox", pdc_scalarlist, PDC_OPT_NONE, 4, 4,\ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},\ +\ + {"bleedbox", pdc_scalarlist, PDC_OPT_NONE, 4, 4,\ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},\ +\ + {"cropbox", pdc_scalarlist, PDC_OPT_NONE, 4, 4,\ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},\ +\ + {"duration", pdc_scalarlist, PDC_OPT_NONE, 1, 1,\ + 0.0, PDC_FLOAT_MAX, NULL},\ +\ + {"height", pdc_scalarlist, PDC_OPT_NONE, 1, 1,\ + 0.0, PDC_FLOAT_MAX, pdf_pagedim_keylist},\ +\ + {"label", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 0.0, PDC_USHRT_MAX, NULL}, \ +\ + {"mediabox", pdc_scalarlist, PDC_OPT_NONE, 4, 4,\ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},\ +\ + {"metadata", pdc_stringlist, PDF_METADATA_FLAG, 1, 1, \ + 0.0, PDC_INT_MAX, NULL}, \ +\ + {"rotate", pdc_integerlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 270, NULL}, \ +\ + {"transition", pdc_keywordlist, PDC_OPT_NONE, 1, 1, \ + 0.0, 0.0, pdf_transition_keylist}, \ +\ + {"transparencygroup", pdc_stringlist, PDC_OPT_NONE, 1, 1, \ + 1.0, PDF_MAX_NAMESTRING, NULL}, \ +\ + {"taborder", pdc_keywordlist, PDC_OPT_PDC_1_5, 1, 1, \ + 0.0, 0.0, pdf_taborder_keylist}, \ +\ + {"trimbox", pdc_scalarlist, PDC_OPT_NONE, 4, 4,\ + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL},\ +\ + {"userunit", pdc_scalarlist, PDC_OPT_PDC_1_6, 1, 1,\ + 1.0, 75000, pdf_userunit_keylist},\ +\ + {"width", pdc_scalarlist, PDC_OPT_NONE, 1, 1,\ + 0.0, PDC_FLOAT_MAX, pdf_pagedim_keylist},\ + +/* common helper function for pdf__begin_page_ext() and pdf__resume_page(). +** returns the target group (if any) and the target page number. the +** page number is relative to the group (if available). page number -1 +** means "no page number". +*/ +static pg_group * +get_page_options2(PDF *p, pdc_resopt *resopts, int *pageno) +{ + pdf_pages * dp = p->doc_pages; + pg_group * group = (pg_group *) 0; + char ** strlist; + + *pageno = -1; + + if (pdc_get_optvalues("pagenumber", resopts, pageno, NULL)) + { + if (*pageno <= 0) + pdc_error(p->pdc, PDF_E_PAGE_ILLNUMBER, + pdc_errprintf(p->pdc, "%d", *pageno), 0, 0, 0); + } + + if (pdc_get_optvalues("group", resopts, NULL, &strlist)) + { + if ((group = find_group(dp, strlist[0])) == (pg_group *) 0) + pdc_error(p->pdc, PDF_E_DOC_UNKNOWNGROUP, strlist[0], 0, 0, 0); + } + + if (group) + { + if (*pageno > group->n_pages) + pdc_error(p->pdc, PDF_E_PAGE_NOTEXIST2, + pdc_errprintf(p->pdc, "%d", *pageno), group->name, 0, 0); + } + else + { + if (dp->have_groups) + pdc_error(p->pdc, PDF_E_PAGE_NEEDGROUP, 0, 0, 0, 0); + + if (*pageno > dp->last_page) + pdc_error(p->pdc, PDF_E_PAGE_NOTEXIST, + pdc_errprintf(p->pdc, "%d", *pageno), 0, 0, 0); + } + + return group; +} /* get_page_options2 */ + +static pdc_rectangle * +pdf_new_box(PDF *p, const pdc_rectangle *box) +{ + static const char fn[] = "pdf_new_box"; + + pdc_rectangle *result = (pdc_rectangle *) + pdc_malloc(p->pdc, sizeof (pdc_rectangle), fn); + + if (box) + *result = *box; + else + pdc_rect_init(result, 0, 0, 0, 0); + return result; +} /* pdf_new_box */ + +/* common helper function for pdf__begin_page_ext() and pdf__end_page_ext(). +*/ +static void +get_page_options3(PDF *p, pdc_resopt *resopts, pdc_bool end_page) +{ + pdf_pages * dp = p->doc_pages; + int pageno = dp->current_page; + page_obj * po = &dp->pages[pageno]; + pdc_scalar width; + pdc_scalar height; + pdc_bool has_width; + pdc_bool has_height; + pdc_bool has_mediabox; + pdc_rectangle box; + char **slist; + + if (pdc_get_optvalues("action", resopts, NULL, NULL)) + { + po->action = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + pdf_parse_and_write_actionlist(p, event_page, NULL, + (char *) po->action); + } + + if (pdc_get_optvalues("artbox", resopts, &box, NULL)) + po->boxes[pdf_artbox] = pdf_new_box(p, &box); + if (pdc_get_optvalues("bleedbox", resopts, &box, NULL)) + po->boxes[pdf_bleedbox] = pdf_new_box(p, &box); + if (pdc_get_optvalues("cropbox", resopts, &box, NULL)) + po->boxes[pdf_cropbox] = pdf_new_box(p, &box); + if (pdc_get_optvalues("trimbox", resopts, &box, NULL)) + po->boxes[pdf_trimbox] = pdf_new_box(p, &box); + + pdc_get_optvalues("taborder", resopts, &po->taborder, NULL); + pdc_get_optvalues("duration", resopts, &po->duration, NULL); + pdc_get_optvalues("userunit", resopts, &po->userunit, NULL); + if (po->userunit < 1.0) + po->userunit = 72.0 / (PDC_INCH2METER * fabs(po->userunit)); + + if (pdc_get_optvalues("label", resopts, NULL, NULL)) + { + char *pagelabel = pdf_get_opt_utf8name(p, "label", resopts); + pdf_set_pagelabel(p, pagelabel, pageno); + pdc_free(p->pdc, pagelabel); + } + + if (pdc_get_optvalues("transparencygroup", resopts, NULL, &slist)) + pdf_set_transgroup(p, slist[0], pageno); + + /* the "width" and "height" options must be processed BEFORE the + ** "mediabox" option, since the latter dominates over the formers. + */ + has_width = pdc_get_optvalues("width", resopts, &width, NULL); + has_height = pdc_get_optvalues("height", resopts, &height, NULL); + + if (has_width) + po->boxes[pdf_mediabox]->urx = po->boxes[pdf_mediabox]->llx + width; + + if (has_height) + po->boxes[pdf_mediabox]->ury = po->boxes[pdf_mediabox]->lly + height; + + has_mediabox = + pdc_get_optvalues("mediabox", resopts, po->boxes[pdf_mediabox], NULL); + + width = po->boxes[pdf_mediabox]->urx - po->boxes[pdf_mediabox]->llx; + height = po->boxes[pdf_mediabox]->ury - po->boxes[pdf_mediabox]->lly; + + if (p->ydirection == -1) + { + if (end_page) + { + if (has_mediabox || has_width || has_height) + pdc_error(p->pdc, PDF_E_PAGE_ILLCHGSIZE, 0, 0, 0, 0); + } + else + { + if (width == 0 || height == 0) + pdc_error(p->pdc, PDF_E_PAGE_TOPDOWN_NODIMS, 0, 0, 0, 0); + + if ((height < PDF_ACRO_MINPAGE || width < PDF_ACRO_MINPAGE || + height > PDF_ACRO_MAXPAGE || width > PDF_ACRO_MAXPAGE)) + pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO, 0, 0, 0, 0); + } + } + + + pdc_get_optvalues("rotate", resopts, &po->rotate, NULL); + switch (po->rotate) + { + case 0: case 90: case 180: case 270: + break; + + default: + pdc_error(p->pdc, PDF_E_PAGE_ILLROTATE, + pdc_errprintf(p->pdc, "%d", po->rotate), 0, 0, 0); + } + + pdc_get_optvalues("transition", resopts, &po->transition, NULL); + if (po->transition >= (int) TRANS_1_5 && p->compatibility < PDC_1_5) + pdc_error(p->pdc, PDF_E_PAGE_TRANS_COMPAT, + pdc_get_keyword(po->transition, pdf_transition_keylist), 0, 0, 0); +} /* get_page_options3 */ + + + +static const pdc_defopt pdf_begin_page_ext_options[] = +{ + PDF_PAGE_OPTIONS1 + PDF_PAGE_OPTIONS2 + PDF_PAGE_OPTIONS3 + + PDC_OPT_TERMINATE +}; + + +void +pdf__begin_page_ext( + PDF * p, + pdc_scalar width, + pdc_scalar height, + const char *optlist) +{ + static const char fn[] = "pdf__begin_page_ext"; + + pdf_pages * dp = p->doc_pages; + pdf_page * pg; + page_obj * po; + + + pdc_resopt *resopts = NULL; + pg_group * group = (pg_group *) 0; + int pageno = -1; + + pdc_check_number_limits(p->pdc, "width", width, 0.0, PDC_FLOAT_MAX); + pdc_check_number_limits(p->pdc, "height", height, 0.0, PDC_FLOAT_MAX); + + if (optlist && *optlist) + { + pdc_clientdata cdata; + + pdf_set_clientdata(p, &cdata); + resopts = pdc_parse_optionlist(p->pdc, + optlist, pdf_begin_page_ext_options, &cdata, pdc_true); + + group = get_page_options2(p, resopts, &pageno); + } + + if (group) + { + if (pageno == -1) + pageno = group->start + group->n_pages; + else + pageno = group->start + pageno - 1; + + if (++group->n_pages > group->capacity) + { + grow_group(p, group, pageno, 1); + } + else if (pageno < group->start + group->n_pages - 1) + { + memmove(&dp->pages[pageno + 1], &dp->pages[pageno], + (group->start + group->n_pages - pageno) * sizeof (page_obj)); + + pdf_init_page_obj(&dp->pages[pageno]); + } + + if (dp->last_page < group->start + group->n_pages - 1) + dp->last_page = group->start + group->n_pages - 1; + } + else + { + if (dp->last_page + 1 >= dp->pages_capacity) + pdf_grow_pages(p); + + ++dp->last_page; + + if (dp->last_page > dp->max_page) + ++dp->max_page; + + if (pageno == -1) + pageno = dp->last_page; + + if (pageno != dp->last_page) + { + memmove(&dp->pages[pageno + 1], &dp->pages[pageno], + (dp->max_page - pageno) * sizeof (page_obj)); + + pdf_init_page_obj(&dp->pages[pageno]); + } + } + + po = &dp->pages[pageno]; + dp->current_page = pageno; + + /* no id has been preallocated */ + if (po->id == PDC_BAD_ID) + po->id = pdc_alloc_id(p->out); + + pg = dp->curr_pg = (pdf_page *) pdc_malloc(p->pdc, sizeof (pdf_page), fn); + p->curr_ppt = &pg->ppt; + + pg->contents_ids = (pdc_id *) 0; + pg->annots = (pdc_vtr *) 0; + + /* save and take over global parameters. + */ + pg->ydir = dp->old_ydir = p->ydirection; + + pg->rl_colorspaces.list = (int *) 0; + pg->rl_extgstates.list = (int *) 0; + pg->rl_fonts.list = (int *) 0; + pg->rl_layers.list = (int *) 0; + pg->rl_patterns.list = (int *) 0; + pg->rl_shadings.list = (int *) 0; + pg->rl_xobjects.list = (int *) 0; + + pg->contents_ids_capacity = CONTENTS_CHUNKSIZE; + pg->contents_ids = (pdc_id *) pdc_malloc(p->pdc, + sizeof(pdc_id) * pg->contents_ids_capacity, fn); + + /* might be overwritten by options */ + po->boxes[pdf_mediabox] = pdf_new_box(p, 0); + pdc_rect_init(po->boxes[pdf_mediabox], 0, 0, width, height); + + if (resopts) + { + pdc_bool topdown = pdc_false; + + if (pdc_get_optvalues("topdown", resopts, &topdown, NULL)) + p->ydirection = pg->ydir = topdown ? -1 : 1; + + + get_page_options3(p, resopts, pdc_false); + } + + /* initialize the current ppt descriptor. p->ydirection + ** must be set before pdf_init_ppt()! + */ + pdf_init_ppt(p, pdc_true); + + pg->next_content = 0; + + pdf_init_reslist(&pg->rl_colorspaces); + pdf_init_reslist(&pg->rl_extgstates); + pdf_init_reslist(&pg->rl_fonts); + pdf_init_reslist(&pg->rl_layers); + pdf_init_reslist(&pg->rl_patterns); + pdf_init_reslist(&pg->rl_shadings); + pdf_init_reslist(&pg->rl_xobjects); + + PDF_SET_STATE(p, pdf_state_page); + + pdf_begin_contents_section(p); + + /* top-down y coordinates */ + pdf_set_topdownsystem(p, pdf_get_pageheight(p)); + + /* set color differing from PDF default */ + pdf_set_default_color(p, pdc_false); + + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[Begin page #%d]\n", + dp->current_page); + +} /* pdf__begin_page_ext */ + + +void +pdf__begin_page( + PDF * p, + pdc_scalar width, + pdc_scalar height) +{ + if (p->doc_pages->have_groups) + pdc_error(p->pdc, PDF_E_PAGE_NEEDGROUP2, 0, 0, 0, 0); + + pdf__begin_page_ext(p, width, height, 0); +} /* pdf__begin_page */ + + +/*************************** suspend & resume ***************************/ + +void +pdf_pg_suspend(PDF *p) +{ + pdf_pages *dp = p->doc_pages; + + if (PDF_GET_STATE(p) != pdf_state_page) + { + dp->last_suspended = -1; + } + else + { + pdf_page *pg = dp->curr_pg; + + pdf_end_contents_section(p); + + /* restore global parms. + */ + p->ydirection = dp->old_ydir; + + pdf_get_page_colorspaces(p, &pg->rl_colorspaces); + pdf_get_page_extgstates(p, &pg->rl_extgstates); + pdf_get_page_fonts(p, &pg->rl_fonts); + pdf_get_page_patterns(p, &pg->rl_patterns); + pdf_get_page_shadings(p, &pg->rl_shadings); + pdf_get_page_xobjects(p, &pg->rl_xobjects); + + dp->pages[dp->current_page].pg = pg; + dp->curr_pg = (pdf_page *) 0; + dp->last_suspended = dp->current_page; + + /* restore the default ppt for out-of-page usage. + */ + p->curr_ppt = &dp->default_ppt; + } + + pdf_init_ppt(p, pdc_false); +} /* pdf_pg_suspend */ + + +static const pdc_defopt pdf_suspend_page_options[] = +{ + PDC_OPT_TERMINATE +}; + +void +pdf__suspend_page(PDF *p, const char *optlist) +{ + if (optlist && *optlist) + { + pdc_resopt *resopts = pdc_parse_optionlist(p->pdc, + optlist, pdf_suspend_page_options, NULL, pdc_true); + + (void) resopts; + } + + pdf_pg_suspend(p); + PDF_SET_STATE(p, pdf_state_document); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[Suspend page #%d]\n", + p->doc_pages->current_page); +} /* pdf__suspend_page */ + + +void +pdf_pg_resume(PDF *p, int pageno) +{ + pdf_pages *dp = p->doc_pages; + + pdf_reset_ppt(p->curr_ppt); + + if (pageno == -1) + { + pageno = dp->last_suspended; + dp->last_suspended = -1; + } + + if (pageno == -1) + { + PDF_SET_STATE(p, pdf_state_document); + } + else + { + pdf_page *pg; + int i; + + /* prevent error cleanup from killing the same page twice. + */ + pg = dp->curr_pg = dp->pages[pageno].pg; + dp->pages[pageno].pg = (pdf_page *) 0; + + dp->current_page = pageno; + p->curr_ppt = &pg->ppt; + + PDF_SET_STATE(p, pdf_state_page); + + /* save global parameters and replace them + ** with the page specific ones. + */ + dp->old_ydir = p->ydirection; + + p->ydirection = pg->ydir; + + pdf_begin_contents_section(p); + + /* mark global resources as "used on current page". + */ + for (i = 0; i < pg->rl_colorspaces.length; ++i) + pdf_mark_page_colorspace(p, pg->rl_colorspaces.list[i]); + + for (i = 0; i < pg->rl_extgstates.length; ++i) + pdf_mark_page_extgstate(p, pg->rl_extgstates.list[i]); + + for (i = 0; i < pg->rl_fonts.length; ++i) + pdf_mark_page_font(p, pg->rl_fonts.list[i]); + + + for (i = 0; i < pg->rl_patterns.length; ++i) + pdf_mark_page_pattern(p, pg->rl_patterns.list[i]); + + for (i = 0; i < pg->rl_shadings.length; ++i) + pdf_mark_page_shading(p, pg->rl_shadings.list[i]); + + for (i = 0; i < pg->rl_xobjects.length; ++i) + pdf_mark_page_xobject(p, pg->rl_xobjects.list[i]); + } +} /* pdf_pg_resume */ + + +static const pdc_defopt pdf_resume_page_options[] = +{ + PDF_PAGE_OPTIONS2 + + PDC_OPT_TERMINATE +}; + +void +pdf__resume_page(PDF *p, const char *optlist) +{ + pdf_pages * dp = p->doc_pages; + pg_group * group = (pg_group *) 0; + int pageno = -1; /* logical page number */ + int physno; /* physical page number */ + + if (optlist && *optlist) + { + pdc_resopt *resopts = pdc_parse_optionlist(p->pdc, + optlist, pdf_resume_page_options, NULL, pdc_true); + + group = get_page_options2(p, resopts, &pageno); + } + + if (group) + { + if (pageno == -1) + pageno = group->n_pages; + + physno = group->start + pageno - 1; + } + else + { + if (pageno == -1) + pageno = dp->last_page; + + physno = pageno; + } + + if (dp->pages[physno].pg == (pdf_page *) 0) + { + if (group) + { + pdc_error(p->pdc, PDF_E_PAGE_NOSUSPEND2, + pdc_errprintf(p->pdc, "%d", pageno), group->name, 0, 0); + } + else + { + pdc_error(p->pdc, PDF_E_PAGE_NOSUSPEND, + pdc_errprintf(p->pdc, "%d", pageno), 0, 0, 0); + } + } + + pdf_pg_resume(p, physno); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[Resume page #%d]\n", physno); + +} /* pdf__resume_page */ + + +/******************************* end_page *******************************/ + + +static const pdc_defopt pdf_end_page_ext_options[] = +{ + PDF_PAGE_OPTIONS3 + + PDC_OPT_TERMINATE +}; + +void +pdf__end_page_ext(PDF *p, const char *optlist) +{ + static const char fn[] = "pdf__end_page_ext"; + + pdf_pages * dp = p->doc_pages; + page_obj * po = &dp->pages[dp->current_page]; + + pdc_scalar width; + pdc_scalar height; + pdf_page * pg; + pdf_ppt * ppt = p->curr_ppt; + int i; + + + if (optlist && *optlist) + { + pdc_resopt *resopts = pdc_parse_optionlist(p->pdc, + optlist, pdf_end_page_ext_options, NULL, pdc_true); + + get_page_options3(p, resopts, pdc_true); + } + + width = po->boxes[pdf_mediabox]->urx - po->boxes[pdf_mediabox]->llx; + height = po->boxes[pdf_mediabox]->ury - po->boxes[pdf_mediabox]->lly; + + if (width == 0 || height == 0) + pdc_error(p->pdc, PDF_E_PAGE_NODIMS, 0, 0, 0, 0); + + if ((height < PDF_ACRO_MINPAGE || width < PDF_ACRO_MINPAGE || + height > PDF_ACRO_MAXPAGE || width > PDF_ACRO_MAXPAGE)) + pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO, 0, 0, 0, 0); + + + + + /* check whether PDF_save() and PDF_restore() calls are balanced */ + if (ppt->sl > 0) + pdc_error(p->pdc, PDF_E_GSTATE_UNMATCHEDSAVE, 0, 0, 0, 0); + + /* TODO (york): avoid memory leak in error case. */ + pg = dp->curr_pg; + + + pdf_end_contents_section(p); + + + /* if no "duration" or "transition" options have been specified + ** for this page, fall back on the (deprecated) global parameters. + */ + if (po->duration == -1) + po->duration = dp->duration; + + if (po->transition == -1) + po->transition = dp->transition; + + if (pg->next_content > 0) + { + if (pg->next_content == 1) + { + po->contents_id = pg->contents_ids[0]; + } + else + { + po->contents_id = pdc_begin_obj(p->out, PDC_NEW_ID); + pdc_begin_array(p->out); + + for (i = 0; i < pg->next_content; ++i) + { + pdc_objref_c(p->out, pg->contents_ids[i]); + } + + pdc_end_array(p->out); + pdc_end_obj(p->out); + } + } + + if (po->action) + { + po->act_idlist = (pdc_id *) + pdc_malloc(p->pdc, PDF_MAX_EVENTS * sizeof (pdc_id), fn); + + pdf_parse_and_write_actionlist(p, event_page, po->act_idlist, + po->action); + } + + po->annots_id = pdf_write_annots_root(p, pg->annots, NULL); + + /* resources dictionary + */ + po->res_id = pdc_begin_obj(p->out, PDC_NEW_ID); + + pdc_begin_dict(p->out); + + pdf_write_page_fonts(p); /* Font resources */ + + pdf_write_page_colorspaces(p); /* ColorSpace resources */ + + pdf_write_page_pattern(p); /* Pattern resources */ + + pdf_write_page_shadings(p); /* Shading resources */ + + pdf_write_xobjects(p); /* XObject resources */ + + pdf_write_page_extgstates(p); /* ExtGState resources */ + + + pdc_end_dict(p->out); + pdc_end_obj(p->out); + + if (pg->annots != (pdc_vtr *) 0) + pdf_write_page_annots(p, pg->annots); /* Annotation dicts */ + + + /* restore global parms. + */ + p->ydirection = dp->old_ydir; + + /* restore the default ppt for out-of-page usage. + */ + p->curr_ppt = &dp->default_ppt; + pdf_init_ppt(p, pdc_false); + PDF_SET_STATE(p, pdf_state_document); + pdf_delete_page(p, pg); + dp->curr_pg = (pdf_page *) 0; + + if (p->flush & (pdc_flush_page | pdc_flush_content)) + pdc_flush_stream(p->out); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[End page #%d]\n", + dp->current_page); + +} /* pdf__end_page_ext */ + + +/*****************************************************************************/ +/** deprecated historical page functions **/ +/*****************************************************************************/ + +/* set page display duration for current and future pages */ + +void +pdf_set_duration(PDF *p, double t) +{ + p->doc_pages->duration = t; +} + +/* set transition mode for current and future pages */ + +void +pdf_set_transition(PDF *p, const char *transition) +{ + int i; + + if (transition == NULL || !*transition) + transition = "none"; + + i = pdc_get_keycode_ci(transition, pdf_transition_keylist); + + if (i == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, transition, "transition", 0, 0); + + if (i >= (int) TRANS_1_5 && p->compatibility < PDC_1_5) + pdc_error(p->pdc, PDF_E_PAGE_TRANS_COMPAT, + pdc_get_keyword(i, pdf_transition_keylist), 0, 0, 0); + + p->doc_pages->transition = i; +} + diff --git a/src/pdflib/pdflib/p_page.h b/src/pdflib/pdflib/p_page.h new file mode 100644 index 0000000..3f496e4 --- /dev/null +++ b/src/pdflib/pdflib/p_page.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_page.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * Header file for the PDFlib page system + * + */ + +#ifndef P_PAGE_H +#define P_PAGE_H + +/* the "pageno" parameter for function pdf_set_pagelabel() can take +** negative values, indicating the calling function. +*/ +#define PDF_FC_BEGIN_DOCUMENT -1 +#define PDF_FC_END_DOCUMENT -2 +void pdf_set_pagelabel(PDF *p, const char *optlist, int pageno); + +pdc_id pdf_write_pages_tree(PDF *p); + +void pdf_set_transition(PDF *p, const char *type); +void pdf_set_duration(PDF *p, double t); + +#endif /* P_PAGE_H */ diff --git a/src/pdflib/pdflib/p_pantlab.h b/src/pdflib/pdflib/p_pantlab.h new file mode 100644 index 0000000..79c35cc --- /dev/null +++ b/src/pdflib/pdflib/p_pantlab.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_pantlab.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib PANTONE spot LAB color table derived from + * PANTONE MATCHING SYSTEM + * + * PANTONE and PANTONE MATCHING SYSTEM is a registered trademark of + * Pantone,Inc. + * + */ + +#ifndef P_PANTLAB_H +#define P_PANTLAB_H + + +#endif /* P_PANTAB_H */ + diff --git a/src/pdflib/pdflib/p_params.c b/src/pdflib/pdflib/p_params.c new file mode 100644 index 0000000..e55a8b1 --- /dev/null +++ b/src/pdflib/pdflib/p_params.c @@ -0,0 +1,1306 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_params.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib parameter handling + * + */ + +#define P_PARAMS_C + +#include "p_intern.h" +#include "p_color.h" +#include "p_font.h" +#include "p_image.h" +#include "p_page.h" +#include "p_tagged.h" + +static const pdc_keyconn pdf_fillrule_keylist[] = +{ + {"winding", pdf_fill_winding }, + {"evenodd", pdf_fill_evenodd }, + {NULL, 0} +}; + +/* + * PDF_get_parameter() and PDF_set_parameter() deal with strings, + * PDF_get_value() and PDF_set_value() deal with numerical values. + */ + +typedef struct +{ + char * name; /* parameter name */ + pdc_bool mod_zero; /* PDF_get_() modifier argument must be 0 */ + pdc_bool check_scope; /* check following scope for PDF_get_...() */ + int scope; /* bit mask of legal states */ + +} +pdf_parm_descr; + +static pdf_parm_descr parms[] = +{ +#define pdf_gen_parm_descr 1 +#include "p_params.h" +#undef pdf_gen_parm_descr + + { "", 0, 0, 0 } +}; + +enum +{ +#define pdf_gen_parm_enum 1 +#include "p_params.h" +#undef pdf_gen_parm_enum + + PDF_PARAMETER_LIMIT +}; + +static int +pdf_get_index(PDF *p, const char *key, pdc_bool setpar) +{ + int i; + + if (key == NULL || !*key) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "key", 0, 0, 0); + + for (i = 0; i < PDF_PARAMETER_LIMIT; ++i) + { + if (pdc_stricmp(key, parms[i].name) == 0) + { + if ((setpar || parms[i].check_scope) && + (p->state_stack[p->state_sp] & parms[i].scope) == 0) + pdc_error(p->pdc, PDF_E_DOC_SCOPE_SET, key, + pdf_current_scope(p), 0, 0); + return i; + } + } + + if (i == PDF_PARAMETER_LIMIT) + pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0); + + return -1; +} + +static pdc_bool +pdf_bool_value(PDF *p, const char *key, const char *value) +{ + if (!pdc_stricmp(value, "true")) + return pdc_true; + + if (!pdc_stricmp(value, "false")) + return pdc_false; + + pdc_error(p->pdc, PDC_E_ILLARG_BOOL, key, value, 0, 0); + + return pdc_false; /* compilers love it */ +} + +void +pdf__set_parameter(PDF *p, const char *key, const char *value) +{ + pdc_pagebox usebox = pdc_pbox_none; + pdc_text_format textformat = pdc_auto; + char optlist[512]; + pdf_ppt *ppt; + int i, k; + + i = pdf_get_index(p, key, pdc_true); + + if (value == NULL) value = ""; + + ppt = p->curr_ppt; + + switch (i) + { + case PDF_PARAMETER_PDIUSEBOX: + case PDF_PARAMETER_VIEWAREA: + case PDF_PARAMETER_VIEWCLIP: + case PDF_PARAMETER_PRINTAREA: + case PDF_PARAMETER_PRINTCLIP: + k = pdc_get_keycode_ci(value, pdf_usebox_keylist); + if (k == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); + usebox = (pdc_pagebox) k; + strcpy(optlist, key); + strcat(optlist, " "); + strcat(optlist, value); + break; + + case PDF_PARAMETER_TEXTFORMAT: + case PDF_PARAMETER_HYPERTEXTFORMAT: + k = pdc_get_keycode_ci(value, pdf_textformat_keylist); + if (k == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); + textformat = (pdc_text_format) k; + break; + } + + switch (i) + { + case PDF_PARAMETER_SEARCHPATH: + case PDF_PARAMETER_FONTAFM: + case PDF_PARAMETER_FONTPFM: + case PDF_PARAMETER_FONTOUTLINE: + case PDF_PARAMETER_HOSTFONT: + case PDF_PARAMETER_ENCODING: + case PDF_PARAMETER_ICCPROFILE: + case PDF_PARAMETER_STANDARDOUTPUTINTENT: + { + pdf_add_resource(p, key, value); + break; + } + + case PDF_PARAMETER_DEBUG: + { + const unsigned char *c; + + for (c = (const unsigned char *) value; *c; c++) + p->debug[(int) *c] = 1; + break; + } + + case PDF_PARAMETER_NODEBUG: + { + const unsigned char *c; + + for (c = (const unsigned char *) value; *c; c++) + p->debug[(int) *c] = 0; + break; + } + + case PDF_PARAMETER_BINDING: + if (!p->pdc->binding) + p->pdc->binding = pdc_strdup(p->pdc, value); + break; + + case PDF_PARAMETER_OBJORIENT: + p->pdc->objorient = pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_HASTOBEPOS: + p->pdc->hastobepos = pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_PTFRUN: + p->pdc->ptfrun = pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_SMOKERUN: + p->pdc->smokerun = pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_UNICAPLANG: + p->pdc->unicaplang = pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_ERRORPOLICY: + k = pdc_get_keycode_ci(value, pdf_errpol_keylist); + if (k == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); + p->errorpolicy = (pdf_errpol) k; + break; + + case PDF_PARAMETER_UNDERLINE: + pdf_set_tstate(p, (double) pdf_bool_value(p, key, value), + to_underline); + break; + + case PDF_PARAMETER_OVERLINE: + pdf_set_tstate(p, (double) pdf_bool_value(p, key, value), + to_overline); + break; + + case PDF_PARAMETER_STRIKEOUT: + pdf_set_tstate(p, (double) pdf_bool_value(p, key, value), + to_strikeout); + break; + + case PDF_PARAMETER_KERNING: + pdc_warning(p->pdc, PDF_E_UNSUPP_KERNING, 0, 0, 0, 0); + break; + + case PDF_PARAMETER_FAKEBOLD: + pdf_set_tstate(p, (double) pdf_bool_value(p, key, value), + to_fakebold); + break; + + + case PDF_PARAMETER_RESOURCEFILE: + pdc_set_resourcefile(p->pdc, value); + break; + + case PDF_PARAMETER_RENDERINGINTENT: + k = pdc_get_keycode_ci(value, pdf_renderingintent_pdfkeylist); + if (k == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); + p->rendintent = (pdf_renderingintent) k; + break; + + case PDF_PARAMETER_PRESERVEOLDPANTONENAMES: + p->preserveoldpantonenames = pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_SPOTCOLORLOOKUP: + p->spotcolorlookup = pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_PDISTRICT: + p->pdi_strict = pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_TOPDOWN: + if (pdf_bool_value(p, key, value)) + p->ydirection = -1.0; + else + p->ydirection = 1.0; + break; + + case PDF_PARAMETER_USERCOORDINATES: + p->usercoordinates = pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_USEHYPERTEXTENCODING: + p->usehyptxtenc = pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_TEXTFORMAT: + pdf_check_textformat(p, textformat); + p->textformat = textformat; + if (p->curr_ppt) + pdf_set_tstate(p, (double) textformat, to_textformat); + break; + + case PDF_PARAMETER_HYPERTEXTFORMAT: + pdf_check_hypertextformat(p, textformat); + p->hypertextformat = textformat; + break; + + case PDF_PARAMETER_HYPERTEXTENCODING: + { + p->hypertextencoding = + pdf_get_hypertextencoding(p, value, &p->hypertextcodepage, + pdc_true); + pdf_check_hypertextencoding(p, p->hypertextencoding); + break; + } + + case PDF_PARAMETER_CHARREF: + pdc_warning(p->pdc, PDF_E_UNSUPP_CHARREF, 0, 0, 0, 0); + break; + + case PDF_PARAMETER_ESCAPESEQUENCE: + pdc_warning(p->pdc, PDF_E_UNSUPP_ESCAPESEQU, 0, 0, 0, 0); + break; + + case PDF_PARAMETER_HONORLANG: + pdc_warning(p->pdc, PDF_E_UNSUPP_HONORLANG, 0, 0, 0, 0); + break; + + case PDF_PARAMETER_GLYPHCHECK: + pdc_warning(p->pdc, PDF_E_UNSUPP_GLYPHCHECK, 0, 0, 0, 0); + break; + + case PDF_PARAMETER_FILLRULE: + k = pdc_get_keycode_ci(value, pdf_fillrule_keylist); + if (k == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); + ppt->fillrule = (pdf_fillrule) k; + break; + + case PDF_PARAMETER_LOGGING: + pdc_set_logg_options(p->pdc, value); + break; + + case PDF_PARAMETER_LOGMSG: + pdc_logg_cond(p->pdc, 1, trc_user, value); + break; + + case PDF_PARAMETER_TRACEMSG: + /* do nothing -- client-supplied string will show up + * in the log file + */ + break; + + case PDF_PARAMETER_NODEMOSTAMP: + break; + + case PDF_PARAMETER_SERIAL: + case PDF_PARAMETER_LICENCE: + case PDF_PARAMETER_LICENSE: + break; + + case PDF_PARAMETER_LICENCEFILE: + case PDF_PARAMETER_LICENSEFILE: + break; + + case PDF_PARAMETER_AUTOSPACE: + pdc_warning(p->pdc, PDF_E_UNSUPP_TAGGED, 0, 0, 0, 0); + break; + +/*****************************************************************************/ +/** deprecated historical parameters **/ +/*****************************************************************************/ + + case PDF_PARAMETER_OPENWARNING: + p->debug[(int) 'o'] = (char) pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_FONTWARNING: + p->debug[(int) 'F'] = (char) pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_ICCWARNING: + p->debug[(int) 'I'] = (char) pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_IMAGEWARNING: + p->debug[(int) 'i'] = (char) pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_PDIWARNING: + p->debug[(int) 'p'] = (char) pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_HONORICCPROFILE: + p->debug[(int) 'e'] = (char) pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_GLYPHWARNING: + p->debug[(int) 'g'] = (char) pdf_bool_value(p, key, value); + if (p->curr_ppt) + pdf_set_tstate(p, (double) pdf_bool_value(p, key, value), + to_glyphwarning); + break; + + case PDF_PARAMETER_TRACE: + { + pdc_bool bv = pdf_bool_value(p, key, value); + if (bv) + pdc_set_logg_options(p->pdc, ""); + else + pdc_set_logg_options(p->pdc, "disable"); + break; + } + + case PDF_PARAMETER_TRACEFILE: + strcpy(optlist, "filename "); + strcat(optlist, value); + pdc_set_logg_options(p->pdc, optlist); + break; + + case PDF_PARAMETER_WARNING: + break; + + case PDF_PARAMETER_MASTERPASSWORD: + pdc_warning(p->pdc, PDF_E_UNSUPP_CRYPT, 0, 0, 0, 0); + break; + + case PDF_PARAMETER_USERPASSWORD: + pdc_warning(p->pdc, PDF_E_UNSUPP_CRYPT, 0, 0, 0, 0); + break; + + case PDF_PARAMETER_PERMISSIONS: + pdc_warning(p->pdc, PDF_E_UNSUPP_CRYPT, 0, 0, 0, 0); + break; + + case PDF_PARAMETER_COMPATIBILITY: + pdf_set_compatibility(p, value); + break; + + case PDF_PARAMETER_FLUSH: + pdf_set_flush(p, value); + break; + + case PDF_PARAMETER_PDFX: + pdc_warning(p->pdc, PDF_E_UNSUPP_PDFX, 0, 0, 0, 0); + break; + + case PDF_PARAMETER_HIDETOOLBAR: + case PDF_PARAMETER_HIDEMENUBAR: + case PDF_PARAMETER_HIDEWINDOWUI: + case PDF_PARAMETER_FITWINDOW: + case PDF_PARAMETER_CENTERWINDOW: + case PDF_PARAMETER_DISPLAYDOCTITLE: + if (pdf_bool_value(p, key, value)) + pdf_set_viewerpreference(p, key); + break; + + case PDF_PARAMETER_NONFULLSCREENPAGEMODE: + if (!pdc_stricmp(value, "useoutlines")) + pdf_set_viewerpreference(p, "nonfullscreenpagemode bookmarks"); + else if (!pdc_stricmp(value, "usethumbs")) + pdf_set_viewerpreference(p, "nonfullscreenpagemode thumbnails"); + else if (!pdc_stricmp(value, "usenone")) + pdf_set_viewerpreference(p, "nonfullscreenpagemode none"); + else + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); + break; + + case PDF_PARAMETER_DIRECTION: + if (!pdc_stricmp(value, "r2l")) + pdf_set_viewerpreference(p, "direction r2l"); + else if (!pdc_stricmp(value, "l2r")) + pdf_set_viewerpreference(p, "direction l2r"); + else + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); + break; + + case PDF_PARAMETER_VIEWAREA: + case PDF_PARAMETER_VIEWCLIP: + case PDF_PARAMETER_PRINTAREA: + case PDF_PARAMETER_PRINTCLIP: + pdf_set_viewerpreference(p, optlist); + break; + + case PDF_PARAMETER_OPENACTION: + pdf_set_openaction(p, value); + break; + + case PDF_PARAMETER_OPENMODE: + pdf_set_openmode(p, value); + break; + + case PDF_PARAMETER_BOOKMARKDEST: + pdf_cleanup_destination(p, p->bookmark_dest); + p->bookmark_dest = + pdf_parse_destination_optlist(p, value, 0, pdf_bookmark); + break; + + case PDF_PARAMETER_INHERITGSTATE: + (void) pdf_bool_value(p, key, value); + break; + + case PDF_PARAMETER_TRANSITION: + pdf_set_transition(p, value); + break; + + case PDF_PARAMETER_BASE: + pdf_set_uri(p, value); + break; + + case PDF_PARAMETER_LAUNCHLINK_PARAMETERS: + if (p->launchlink_parameters) { + pdc_free(p->pdc, p->launchlink_parameters); + p->launchlink_parameters = NULL; + } + p->launchlink_parameters = pdc_strdup(p->pdc, value); + break; + + case PDF_PARAMETER_LAUNCHLINK_OPERATION: + if (p->launchlink_operation) { + pdc_free(p->pdc, p->launchlink_operation); + p->launchlink_operation = NULL; + } + p->launchlink_operation = pdc_strdup(p->pdc, value); + break; + + case PDF_PARAMETER_LAUNCHLINK_DEFAULTDIR: + if (p->launchlink_defaultdir) { + pdc_free(p->pdc, p->launchlink_defaultdir); + p->launchlink_defaultdir = NULL; + } + p->launchlink_defaultdir = pdc_strdup(p->pdc, value); + break; + + case PDF_PARAMETER_PDIUSEBOX: + p->pdi_usebox = usebox; + break; + + case PDF_PARAMETER_AUTOSUBSETTING: + case PDF_PARAMETER_AUTOCIDFONT: + case PDF_PARAMETER_UNICODEMAP: + pdc_warning(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0); + break; + + default: + pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0); + break; + } /* switch */ +} /* pdf__set_parameter */ + +static double +pdf_value(PDF *p, const char *key, double value, int minver) +{ + if (p->compatibility < minver) + pdc_error(p->pdc, PDC_E_PAR_VERSION, + key, pdc_get_pdfversion(p->pdc, minver), 0, 0); + + return value; +} + +static double +pdf_pos_value(PDF *p, const char *key, double value, int minver) +{ + if (p->compatibility < minver) + pdc_error(p->pdc, PDC_E_PAR_VERSION, + key, pdc_get_pdfversion(p->pdc, minver), 0, 0); + + if (value <= 0) + pdc_error(p->pdc, PDC_E_PAR_ILLVALUE, + pdc_errprintf(p->pdc, "%f", value), key, 0, 0); + + return value; +} + +void +pdf__set_value(PDF *p, const char *key, double value) +{ + int i; + int ivalue = (int) value; + pdf_ppt *ppt; + + i = pdf_get_index(p, key, pdc_true); + + ppt = p->curr_ppt; + + pdc_check_number(p->pdc, "value", value); + + switch (i) + { + case PDF_PARAMETER_COMPRESS: + if (ivalue < 0 || ivalue > 9) + pdc_error(p->pdc, PDC_E_PAR_ILLVALUE, + pdc_errprintf(p->pdc, "%f", value), key, 0, 0); + + if (pdc_get_compresslevel(p->out) != ivalue) + { + /* + * We must restart the compression engine and start a new + * contents section if we're in the middle of a page. + */ + if (PDF_GET_STATE(p) == pdf_state_page) { + pdf_end_contents_section(p); + pdc_set_compresslevel(p->out, ivalue); + pdf_begin_contents_section(p); + } else + pdc_set_compresslevel(p->out, ivalue); + } + + break; + + case PDF_PARAMETER_FLOATDIGITS: + if (3 <= ivalue && ivalue <= 6) + { + p->pdc->floatdigits = ivalue; + } + else + pdc_error(p->pdc, PDC_E_PAR_ILLVALUE, + pdc_errprintf(p->pdc, "%d", ivalue), key, 0, 0); + break; + + /* TODO (york): take /CropBox into account? + */ + case PDF_PARAMETER_PAGEWIDTH: + { + const pdc_rectangle *box = pdf_get_pagebox(p, pdf_mediabox); + + if (p->ydirection == -1) + pdc_error(p->pdc, PDF_E_PAGE_ILLCHGSIZE, 0, 0, 0, 0); + + if (value < PDF_ACRO_MINPAGE || value > PDF_ACRO_MAXPAGE) + pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO, 0, 0, 0, 0); + + pdf_set_pagebox_urx(p, pdf_mediabox, + box->llx + pdf_pos_value(p, key, value, PDC_1_3)); + break; + } + + /* TODO (york): take /CropBox into account? + */ + case PDF_PARAMETER_PAGEHEIGHT: + { + const pdc_rectangle *box = pdf_get_pagebox(p, pdf_mediabox); + + if (p->ydirection == -1) + pdc_error(p->pdc, PDF_E_PAGE_ILLCHGSIZE, 0, 0, 0, 0); + + if (value < PDF_ACRO_MINPAGE || value > PDF_ACRO_MAXPAGE) + pdc_warning(p->pdc, PDF_E_PAGE_SIZE_ACRO, 0, 0, 0, 0); + + pdf_set_pagebox_ury(p, pdf_mediabox, + box->lly + pdf_pos_value(p, key, value, PDC_1_3)); + break; + } + + case PDF_PARAMETER_CROPBOX_LLX: + pdf_set_pagebox_llx(p, pdf_cropbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_CROPBOX_LLY: + pdf_set_pagebox_lly(p, pdf_cropbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_CROPBOX_URX: + pdf_set_pagebox_urx(p, pdf_cropbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_CROPBOX_URY: + pdf_set_pagebox_ury(p, pdf_cropbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_BLEEDBOX_LLX: + pdf_set_pagebox_llx(p, pdf_bleedbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_BLEEDBOX_LLY: + pdf_set_pagebox_lly(p, pdf_bleedbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_BLEEDBOX_URX: + pdf_set_pagebox_urx(p, pdf_bleedbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_BLEEDBOX_URY: + pdf_set_pagebox_ury(p, pdf_bleedbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_TRIMBOX_LLX: + pdf_set_pagebox_llx(p, pdf_trimbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_TRIMBOX_LLY: + pdf_set_pagebox_lly(p, pdf_trimbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_TRIMBOX_URX: + pdf_set_pagebox_urx(p, pdf_trimbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_TRIMBOX_URY: + pdf_set_pagebox_ury(p, pdf_trimbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_ARTBOX_LLX: + pdf_set_pagebox_llx(p, pdf_artbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_ARTBOX_LLY: + pdf_set_pagebox_lly(p, pdf_artbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_ARTBOX_URX: + pdf_set_pagebox_urx(p, pdf_artbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_ARTBOX_URY: + pdf_set_pagebox_ury(p, pdf_artbox, + pdf_value(p, key, value, PDC_1_3)); + break; + + case PDF_PARAMETER_LEADING: + pdf_set_tstate(p, value, to_leading); + break; + + case PDF_PARAMETER_TEXTRISE: + pdf_set_tstate(p, value, to_textrise); + break; + + case PDF_PARAMETER_HORIZSCALING: + pdf_set_tstate(p, value /100, to_horizscaling); + break; + + case PDF_PARAMETER_ITALICANGLE: + pdf_set_tstate(p, value, to_italicangle); + break; + + case PDF_PARAMETER_TEXTRENDERING: + pdf_set_tstate(p, value, to_textrendering); + break; + + case PDF_PARAMETER_CHARSPACING: + pdf_set_tstate(p, value, to_charspacing); + break; + + case PDF_PARAMETER_WORDSPACING: + pdf_set_tstate(p, value, to_wordspacing); + break; + + case PDF_PARAMETER_UNDERLINEWIDTH: + pdf_set_tstate(p, value, to_underlinewidth); + break; + + case PDF_PARAMETER_UNDERLINEPOSITION: + pdf_set_tstate(p, value, to_underlineposition); + break; + + case PDF_PARAMETER_DEFAULTGRAY: + break; + + case PDF_PARAMETER_DEFAULTRGB: + break; + + case PDF_PARAMETER_DEFAULTCMYK: + break; + + case PDF_PARAMETER_SETCOLOR_ICCPROFILEGRAY: + break; + + case PDF_PARAMETER_SETCOLOR_ICCPROFILERGB: + break; + + case PDF_PARAMETER_SETCOLOR_ICCPROFILECMYK: + break; + +/*****************************************************************************/ +/** deprecated historical parameters **/ +/*****************************************************************************/ + + case PDF_PARAMETER_SUBSETLIMIT: + case PDF_PARAMETER_SUBSETMINSIZE: + { + pdc_warning(p->pdc, PDF_E_UNSUPP_SUBSET, 0, 0, 0, 0); + break; + } + + case PDF_PARAMETER_DURATION: + pdf_set_duration(p, value); + break; + + default: + pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0); + break; + } /* switch */ +} /* pdf__set_value */ + +double +pdf__get_value(PDF *p, const char *key, double mod) +{ + int i = -1; + int imod = (int) mod; + double result = 0; + const pdc_rectangle *box = NULL; + pdf_ppt *ppt; + + i = pdf_get_index(p, key, pdc_false); + + if (parms[i].mod_zero && mod != 0) + pdc_error(p->pdc, PDC_E_PAR_ILLVALUE, + pdc_errprintf(p->pdc, "%f", mod), key, 0, 0); + + ppt = p->curr_ppt; + + switch (i) + { + case PDF_PARAMETER_IMAGEWIDTH: + case PDF_PARAMETER_IMAGEHEIGHT: + case PDF_PARAMETER_RESX: + case PDF_PARAMETER_RESY: + case PDF_PARAMETER_ORIENTATION: + if (p->pdc->hastobepos) imod -= 1; + pdf_check_handle(p, imod, pdc_imagehandle); + break; + + case PDF_PARAMETER_FONTMAXCODE: + case PDF_PARAMETER_CAPHEIGHT: + case PDF_PARAMETER_ASCENDER: + case PDF_PARAMETER_DESCENDER: + case PDF_PARAMETER_XHEIGHT: + if (p->pdc->hastobepos) imod -= 1; + pdf_check_handle(p, imod, pdc_fonthandle); + break; + } + + switch (i) + { + case PDF_PARAMETER_COMPRESS: + result = (double) pdc_get_compresslevel(p->out); + break; + + case PDF_PARAMETER_FLOATDIGITS: + result = (double) p->pdc->floatdigits; + break; + + /* TODO (york): take /CropBox into account? + */ + case PDF_PARAMETER_PAGEWIDTH: + box = pdf_get_pagebox(p, pdf_mediabox); + result = box->urx - box->llx; + break; + + /* TODO (york): take /CropBox into account? + */ + case PDF_PARAMETER_PAGEHEIGHT: + box = pdf_get_pagebox(p, pdf_mediabox); + result = box->ury - box->lly; + break; + + case PDF_PARAMETER_CROPBOX_LLX: + box = pdf_get_pagebox(p, pdf_cropbox); + result = box->llx; + break; + + case PDF_PARAMETER_CROPBOX_LLY: + box = pdf_get_pagebox(p, pdf_cropbox); + result = box->lly; + break; + + case PDF_PARAMETER_CROPBOX_URX: + box = pdf_get_pagebox(p, pdf_cropbox); + result = box->urx; + break; + + case PDF_PARAMETER_CROPBOX_URY: + box = pdf_get_pagebox(p, pdf_cropbox); + result = box->ury; + break; + + case PDF_PARAMETER_BLEEDBOX_LLX: + box = pdf_get_pagebox(p, pdf_bleedbox); + result = box->llx; + break; + + case PDF_PARAMETER_BLEEDBOX_LLY: + box = pdf_get_pagebox(p, pdf_bleedbox); + result = box->lly; + break; + + case PDF_PARAMETER_BLEEDBOX_URX: + box = pdf_get_pagebox(p, pdf_bleedbox); + result = box->urx; + break; + + case PDF_PARAMETER_BLEEDBOX_URY: + box = pdf_get_pagebox(p, pdf_bleedbox); + result = box->ury; + break; + + case PDF_PARAMETER_TRIMBOX_LLX: + box = pdf_get_pagebox(p, pdf_trimbox); + result = box->llx; + break; + + case PDF_PARAMETER_TRIMBOX_LLY: + box = pdf_get_pagebox(p, pdf_trimbox); + result = box->lly; + break; + + case PDF_PARAMETER_TRIMBOX_URX: + box = pdf_get_pagebox(p, pdf_trimbox); + result = box->urx; + break; + + case PDF_PARAMETER_TRIMBOX_URY: + box = pdf_get_pagebox(p, pdf_trimbox); + result = box->ury; + break; + + case PDF_PARAMETER_ARTBOX_LLX: + box = pdf_get_pagebox(p, pdf_artbox); + result = box->llx; + break; + + case PDF_PARAMETER_ARTBOX_LLY: + box = pdf_get_pagebox(p, pdf_artbox); + result = box->lly; + break; + + case PDF_PARAMETER_ARTBOX_URX: + box = pdf_get_pagebox(p, pdf_artbox); + result = box->urx; + break; + + case PDF_PARAMETER_ARTBOX_URY: + box = pdf_get_pagebox(p, pdf_artbox); + result = box->ury; + break; + + case PDF_PARAMETER_IMAGEWIDTH: + pdf_get_image_size(p, imod, (double *) &result, NULL); + break; + + case PDF_PARAMETER_IMAGEHEIGHT: + pdf_get_image_size(p, imod, NULL, (double *) &result); + break; + + case PDF_PARAMETER_RESX: + pdf_get_image_resolution(p, imod, (double *) &result, NULL); + break; + + case PDF_PARAMETER_RESY: + pdf_get_image_resolution(p, imod, NULL, (double *) &result); + break; + + case PDF_PARAMETER_ORIENTATION: + result = (double) (p->images[imod].orientation); + break; + + + case PDF_PARAMETER_CURRENTX: + result = (double) (ppt->gstate[ppt->sl].x); + break; + + case PDF_PARAMETER_CURRENTY: + result = (double) (ppt->gstate[ppt->sl].y); + break; + + case PDF_PARAMETER_CTM_A: + result = (double) (ppt->gstate[ppt->sl].ctm.a); + break; + + case PDF_PARAMETER_CTM_B: + result = (double) (ppt->gstate[ppt->sl].ctm.b); + break; + + case PDF_PARAMETER_CTM_C: + result = (double) (ppt->gstate[ppt->sl].ctm.c); + break; + + case PDF_PARAMETER_CTM_D: + result = (double) (ppt->gstate[ppt->sl].ctm.d); + break; + + case PDF_PARAMETER_CTM_E: + result = (double) (ppt->gstate[ppt->sl].ctm.e); + break; + + case PDF_PARAMETER_CTM_F: + result = (double) (ppt->gstate[ppt->sl].ctm.f); + break; + + case PDF_PARAMETER_TEXTX: + result = pdf_get_tstate(p, to_textx); + break; + + case PDF_PARAMETER_TEXTY: + result = pdf_get_tstate(p, to_texty); + break; + + case PDF_PARAMETER_UNDERLINEWIDTH: + result = pdf_get_tstate(p, to_underlinewidth); + break; + + case PDF_PARAMETER_UNDERLINEPOSITION: + result = pdf_get_tstate(p, to_underlineposition); + break; + + case PDF_PARAMETER_WORDSPACING: + result = pdf_get_tstate(p, to_wordspacing); + break; + + case PDF_PARAMETER_CHARSPACING: + result = pdf_get_tstate(p, to_charspacing); + break; + + case PDF_PARAMETER_HORIZSCALING: + result = 100 * pdf_get_tstate(p, to_horizscaling); + break; + + case PDF_PARAMETER_ITALICANGLE: + result = pdf_get_tstate(p, to_italicangle); + break; + + case PDF_PARAMETER_TEXTRISE: + result = pdf_get_tstate(p, to_textrise); + break; + + case PDF_PARAMETER_LEADING: + result = pdf_get_tstate(p, to_leading); + break; + + case PDF_PARAMETER_TEXTRENDERING: + result = pdf_get_tstate(p, to_textrendering); + break; + + case PDF_PARAMETER_FONTSIZE: + result = pdf_get_tstate(p, to_fontsize); + break; + + case PDF_PARAMETER_FONT: + result = pdf_get_tstate(p, to_font); + if (p->pdc->hastobepos) result += 1; + break; + + case PDF_PARAMETER_MONOSPACE: + result = pdf_get_font_float_option(p, fo_monospace); + break; + + case PDF_PARAMETER_FONTMAXCODE: + result = (double) (p->fonts[imod].ft.numcodes - 1); + break; + + case PDF_PARAMETER_ASCENDER: + result = pdf_font_get_metric_value(p->fonts[imod].ft.m.ascender); + break; + + case PDF_PARAMETER_DESCENDER: + result = pdf_font_get_metric_value(p->fonts[imod].ft.m.descender); + break; + + case PDF_PARAMETER_CAPHEIGHT: + result = pdf_font_get_metric_value(p->fonts[imod].ft.m.capHeight); + break; + + case PDF_PARAMETER_XHEIGHT: + result = pdf_font_get_metric_value(p->fonts[imod].ft.m.xHeight); + break; + + + default: + pdc_error(p->pdc, PDC_E_PAR_UNSUPPKEY, key, 0, 0, 0); + break; + } /* switch */ + + return result; +} /* pdf__get_value */ + +const char * +pdf__get_parameter(PDF *p, const char *key, double mod) +{ + int i = -1; + int imod = (int) mod; + const char *result = ""; + pdf_ppt *ppt; + + i = pdf_get_index(p, key, pdc_false); + + if (parms[i].mod_zero && mod != 0) + pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, + pdc_errprintf(p->pdc, "%f", mod), key, 0, 0); + + ppt = p->curr_ppt; + + switch (i) + { + case PDF_PARAMETER_CAPHEIGHTFAKED: + case PDF_PARAMETER_ASCENDERFAKED: + case PDF_PARAMETER_DESCENDERFAKED: + case PDF_PARAMETER_XHEIGHTFAKED: + if (p->pdc->hastobepos) imod -= 1; + pdf_check_handle(p, imod, pdc_fonthandle); + break; + } + + switch (i) + { + case PDF_PARAMETER_BINDING: + result = p->pdc->binding; + break; + + case PDF_PARAMETER_OBJORIENT: + result = PDC_BOOLSTR(p->pdc->objorient); + break; + + case PDF_PARAMETER_HASTOBEPOS: + result = PDC_BOOLSTR(p->pdc->hastobepos); + break; + + case PDF_PARAMETER_PTFRUN: + result = PDC_BOOLSTR(p->pdc->ptfrun); + break; + + case PDF_PARAMETER_SMOKERUN: + result = PDC_BOOLSTR(p->pdc->smokerun); + break; + + case PDF_PARAMETER_UNICAPLANG: + result = PDC_BOOLSTR(p->pdc->unicaplang); + break; + + + case PDF_PARAMETER_CONFIGURATION: + result = "lite"; + break; + + case PDF_PARAMETER_ERRORPOLICY: + result = pdc_get_keyword(p->errorpolicy, pdf_errpol_keylist); + break; + + case PDF_PARAMETER_PDIUSEBOX: + result = pdc_get_keyword(p->pdi_usebox, pdf_usebox_keylist); + break; + + case PDF_PARAMETER_SEARCHPATH: + case PDF_PARAMETER_FONTAFM: + case PDF_PARAMETER_FONTPFM: + case PDF_PARAMETER_FONTOUTLINE: + case PDF_PARAMETER_HOSTFONT: + case PDF_PARAMETER_ENCODING: + case PDF_PARAMETER_ICCPROFILE: + case PDF_PARAMETER_STANDARDOUTPUTINTENT: + result = pdc_find_resource_nr(p->pdc, key, imod); + break; + + case PDF_PARAMETER_FONTNAME: + result = pdf_get_font_char_option(p, fo_fontname); + break; + + case PDF_PARAMETER_FONTENCODING: + result = pdf_get_font_char_option(p, fo_encoding); + break; + + case PDF_PARAMETER_FONTSTYLE: + result = pdf_get_font_char_option(p, fo_fontstyle); + break; + + case PDF_PARAMETER_ASCENDERFAKED: + result = PDC_BOOLSTR(pdf_font_get_is_faked(&p->fonts[imod], + font_ascender)); + break; + + case PDF_PARAMETER_DESCENDERFAKED: + result = PDC_BOOLSTR(pdf_font_get_is_faked(&p->fonts[imod], + font_descender)); + break; + + case PDF_PARAMETER_CAPHEIGHTFAKED: + result = PDC_BOOLSTR(pdf_font_get_is_faked(&p->fonts[imod], + font_capheight)); + break; + + case PDF_PARAMETER_XHEIGHTFAKED: + result = PDC_BOOLSTR(pdf_font_get_is_faked(&p->fonts[imod], + font_xheight)); + break; + + + case PDF_PARAMETER_UNDERLINE: + result = PDC_BOOLSTR((int) pdf_get_tstate(p, to_underline)); + break; + + case PDF_PARAMETER_OVERLINE: + result = PDC_BOOLSTR((int) pdf_get_tstate(p, to_overline)); + break; + + case PDF_PARAMETER_STRIKEOUT: + result = PDC_BOOLSTR((int) pdf_get_tstate(p, to_strikeout)); + break; + + /* deprecated */ + case PDF_PARAMETER_INHERITGSTATE: + result = PDC_BOOLSTR(pdc_false); + break; + + case PDF_PARAMETER_SCOPE: + result = pdf_current_scope(p); + break; + + case PDF_PARAMETER_TEXTFORMAT: + result = pdc_get_keyword(p->textformat, pdf_textformat_keylist); + break; + + case PDF_PARAMETER_HYPERTEXTFORMAT: + result = pdc_get_keyword(p->hypertextformat,pdf_textformat_keylist); + break; + + case PDF_PARAMETER_HYPERTEXTENCODING: + result = pdf_get_encoding_name(p, p->hypertextencoding, NULL); + break; + + case PDF_PARAMETER_RESOURCEFILE: + result = pdc_get_resourcefile(p->pdc); + break; + + /* deprecated */ + case PDF_PARAMETER_WARNING: + result = PDC_BOOLSTR(0); + break; + + case PDF_PARAMETER_OPENWARNING: + result = PDC_BOOLSTR((int) p->debug[(int) 'o']); + break; + + case PDF_PARAMETER_FONTWARNING: + result = PDC_BOOLSTR((int) p->debug[(int) 'F']); + break; + + case PDF_PARAMETER_ICCWARNING: + result = PDC_BOOLSTR((int) p->debug[(int) 'I']); + break; + + case PDF_PARAMETER_IMAGEWARNING: + result = PDC_BOOLSTR((int) p->debug[(int) 'i']); + break; + + case PDF_PARAMETER_PDIWARNING: + result = PDC_BOOLSTR((int) p->debug[(int) 'p']); + break; + + case PDF_PARAMETER_HONORICCPROFILE: + result = PDC_BOOLSTR((int) p->debug[(int) 'e']); + break; + + case PDF_PARAMETER_GLYPHWARNING: + result = PDC_BOOLSTR((int) p->debug[(int) 'g']); + break; + + case PDF_PARAMETER_RENDERINGINTENT: + result = pdc_get_keyword(p->rendintent, + pdf_renderingintent_pdfkeylist); + break; + + case PDF_PARAMETER_PRESERVEOLDPANTONENAMES: + result = PDC_BOOLSTR(p->preserveoldpantonenames); + break; + + case PDF_PARAMETER_SPOTCOLORLOOKUP: + result = PDC_BOOLSTR(p->spotcolorlookup); + break; + + case PDF_PARAMETER_PDISTRICT: + result = PDC_BOOLSTR(p->pdi_strict); + break; + + case PDF_PARAMETER_TOPDOWN: + result = PDC_BOOLSTR((p->ydirection == -1.0)); + break; + + case PDF_PARAMETER_USERCOORDINATES: + result = PDC_BOOLSTR(p->usercoordinates); + break; + + case PDF_PARAMETER_USEHYPERTEXTENCODING: + result = PDC_BOOLSTR(p->usehyptxtenc); + break; + + + + case PDF_PARAMETER_FILLRULE: + result = pdc_get_keyword(ppt->fillrule, pdf_fillrule_keylist); + break; + + + + case PDF_PARAMETER_COMPATIBILITY: + result = pdc_get_keyword(p->compatibility, + pdf_compatibility_keylist); + break; + + case PDF_PARAMETER_STRING: + pdf_check_handle(p, imod, pdc_stringhandle); + result = pdf_get_utilstring(p, imod); + break; + + default: + pdc_error(p->pdc, PDC_E_PAR_UNSUPPKEY, key, 0, 0, 0); + break; + } /* switch */ + + return result ? result : ""; +} /* pdf__get_parameter */ + + diff --git a/src/pdflib/pdflib/p_params.h b/src/pdflib/pdflib/p_params.h new file mode 100644 index 0000000..12bbf6d --- /dev/null +++ b/src/pdflib/pdflib/p_params.h @@ -0,0 +1,373 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_params.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib parameter table + * + */ + +#if pdf_gen_parm_enum +#define pdf_gen1(code, name, zero, check, scope) PDF_PARAMETER_##code, +#elif pdf_gen_parm_descr +#define pdf_gen1(code, name, zero, check, scope) \ + { name, zero, check, scope }, +#else +#error invalid inclusion of generator file +#endif + +/* + * Deprecated and unsupported parameters: + * dep7 Deprecated since PDFlib 7 + * dep6 Deprecated since PDFlib 6 + * dep5 Deprecated since PDFlib 5 + * unsupp Unsupported (internal use, dysfunctional, or other) + */ + +/* + List of unsupported control characters for the "debug" parameter: + 2 disable the search for the Windows color directory via mscms.dll + e extract embedded ICC profiles from image files + F throw an exception in PDF_load_font (dep7); + g throw an exception in PDF_fit_textline and PDF_show (dep7) + h disable host font processing + i throw an exception in PDF_load_image (dep7) + I throw an exception in PDF_load_iccprofile (dep7); + o throw an exception in PDF_begin_document (dep7) + p throw an exception in PDF_open_pdi (dep7) + + On by default: e F I +*/ + + +/* + * ---------------------------------------------------------------------- + * Setup + * ---------------------------------------------------------------------- + */ + +pdf_gen1(OPENWARNING, "openwarning", 1, 1, pdf_state_all) /* dep6 */ +pdf_gen1(COMPRESS, "compress", 1, 1, + pdf_state_page | pdf_state_document) +pdf_gen1(FLUSH, "flush", 1, 1, pdf_state_all) /* dep6 */ +pdf_gen1(RESOURCEFILE, "resourcefile", 1, 1, pdf_state_all) +pdf_gen1(COMPATIBILITY, "compatibility",1, 0, pdf_state_object) /* dep6 */ +pdf_gen1(PDFX, "pdfx", 1, 0, pdf_state_object) /* dep6 */ +pdf_gen1(SEARCHPATH, "SearchPath", 0, 1, pdf_state_all) +pdf_gen1(ASCIIFILE, "asciifile", 1, 1, pdf_state_all) +pdf_gen1(WARNING, "warning", 1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(ERRORPOLICY, "errorpolicy", 1, 1, pdf_state_all) +pdf_gen1(NODEMOSTAMP, "nodemostamp", 1, 0, pdf_state_object) +pdf_gen1(LICENSE, "license", 1, 0, pdf_state_object) +pdf_gen1(LICENCE, "licence", 1, 0, pdf_state_object) /* unsupp */ +pdf_gen1(LICENSEFILE, "licensefile", 1, 0, pdf_state_object) +pdf_gen1(LICENCEFILE, "licencefile", 1, 0, pdf_state_object) /* unsupp */ +pdf_gen1(TRACE, "trace", 1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(TRACEFILE, "tracefile", 1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(TRACEMSG, "tracemsg", 1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(LOGGING, "logging", 1, 1, pdf_state_all) +pdf_gen1(LOGMSG, "logmsg", 1, 1, pdf_state_all) +pdf_gen1(CHARREF, "charref", 1, 1, pdf_state_all) +pdf_gen1(ESCAPESEQUENCE,"escapesequence",1,1, pdf_state_all) +pdf_gen1(HONORLANG, "honorlang", 1, 1, pdf_state_all) /* unsupp */ +pdf_gen1(STRING, "string", 0, 1, pdf_state_all) +pdf_gen1(SCOPE, "scope", 1, 1, pdf_state_all) + +pdf_gen1(SERIAL, "serial", 1, 0, pdf_state_object) /* unsupp */ +pdf_gen1(FLOATDIGITS, "floatdigits", 1, 1, pdf_state_all) /* unsupp */ +pdf_gen1(BINDING, "binding", 1, 1, pdf_state_all) /* unsupp */ +pdf_gen1(OBJORIENT, "objorient", 1, 1, pdf_state_all) /* unsupp */ +pdf_gen1(HASTOBEPOS, "hastobepos", 1, 1, pdf_state_all) /* unsupp */ +pdf_gen1(UNICAPLANG, "unicaplang", 1, 1, pdf_state_all) /* unsupp */ +pdf_gen1(DEBUG, "debug", 1, 1, pdf_state_all) /* unsupp */ +pdf_gen1(NODEBUG, "nodebug", 1, 1, pdf_state_all) /* unsupp */ +pdf_gen1(PTFRUN, "ptfrun", 1, 1, pdf_state_all) /* unsupp */ +pdf_gen1(SMOKERUN, "smokerun", 1, 1, pdf_state_all) /* unsupp */ +pdf_gen1(CONFIGURATION, "configuration",1, 1, pdf_state_all) /* unsupp */ + + +/* + * ---------------------------------------------------------------------- + * Versioning (cf. pdflib.c) + * ---------------------------------------------------------------------- + */ + +pdf_gen1(MAJOR, "major", 1, 1, pdf_state_all) +pdf_gen1(MINOR, "minor", 1, 1, pdf_state_all) +pdf_gen1(REVISION, "revision", 1, 1, pdf_state_all) +pdf_gen1(VERSION, "version", 1, 1, pdf_state_all) + + +/* + * ---------------------------------------------------------------------- + * Page + * ---------------------------------------------------------------------- + */ + +/* all of the following group are dep6 */ + +pdf_gen1(PAGEWIDTH, "pagewidth", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(PAGEHEIGHT, "pageheight", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(CROPBOX_LLX, "CropBox/llx", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(CROPBOX_LLY, "CropBox/lly", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(CROPBOX_URX, "CropBox/urx", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(CROPBOX_URY, "CropBox/ury", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(BLEEDBOX_LLX, "BleedBox/llx", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(BLEEDBOX_LLY, "BleedBox/lly", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(BLEEDBOX_URX, "BleedBox/urx", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(BLEEDBOX_URY, "BleedBox/ury", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(TRIMBOX_LLX, "TrimBox/llx", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(TRIMBOX_LLY, "TrimBox/lly", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(TRIMBOX_URX, "TrimBox/urx", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(TRIMBOX_URY, "TrimBox/ury", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(ARTBOX_LLX, "ArtBox/llx", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(ARTBOX_LLY, "ArtBox/lly", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(ARTBOX_URX, "ArtBox/urx", 1, 1, pdf_state_page | pdf_state_path) +pdf_gen1(ARTBOX_URY, "ArtBox/ury", 1, 1, pdf_state_page | pdf_state_path) + + +/* + * ---------------------------------------------------------------------- + * Font + * ---------------------------------------------------------------------- + */ + +pdf_gen1(FONTAFM, "FontAFM", 0, 1, pdf_state_all) +pdf_gen1(FONTPFM, "FontPFM", 0, 1, pdf_state_all) +pdf_gen1(FONTOUTLINE, "FontOutline", 0, 1, pdf_state_all) +pdf_gen1(HOSTFONT, "HostFont", 0, 1, pdf_state_all) +pdf_gen1(ENCODING, "Encoding", 0, 1, pdf_state_all) +pdf_gen1(FONTWARNING, "fontwarning", 1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(FONT, "font", 1, 1, pdf_state_content) +pdf_gen1(FONTSIZE, "fontsize", 1, 1, pdf_state_content) + +pdf_gen1(SUBSETLIMIT, "subsetlimit", 1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(SUBSETMINSIZE, "subsetminsize",1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(AUTOSUBSETTING,"autosubsetting",1,1, pdf_state_all) /* dep7 */ +pdf_gen1(AUTOCIDFONT, "autocidfont", 1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(UNICODEMAP, "unicodemap", 1, 1, pdf_state_all) /* dep7 */ + +pdf_gen1(FONTNAME, "fontname", 1, 1, pdf_state_content) /* dep7 */ +pdf_gen1(FONTSTYLE, "fontstyle", 1, 1, pdf_state_content) /* dep7 */ +pdf_gen1(FONTENCODING, "fontencoding", 1, 1, pdf_state_content) /* dep7 */ +pdf_gen1(MONOSPACE, "monospace", 1, 1, pdf_state_content) /* dep7 */ +pdf_gen1(FONTMAXCODE, "fontmaxcode", 0, 1, pdf_state_all) /* dep7 */ +pdf_gen1(ASCENDER, "ascender", 0, 1, pdf_state_all) /* dep7 */ +pdf_gen1(DESCENDER, "descender", 0, 1, pdf_state_all) /* dep7 */ +pdf_gen1(CAPHEIGHT, "capheight", 0, 1, pdf_state_all) /* dep7 */ +pdf_gen1(XHEIGHT, "xheight", 0, 1, pdf_state_all) /* dep7 */ +pdf_gen1(ASCENDERFAKED, "ascenderfaked",0, 1, pdf_state_all) /* dep7 */ +pdf_gen1(DESCENDERFAKED,"descenderfaked",0,1, pdf_state_all) /* dep7 */ +pdf_gen1(CAPHEIGHTFAKED,"capheightfaked",0,1, pdf_state_all) /* dep7 */ +pdf_gen1(XHEIGHTFAKED, "xheightfaked", 0,1, pdf_state_all) /* dep7 */ + + +/* + * ---------------------------------------------------------------------- + * Text + * ---------------------------------------------------------------------- + */ + +pdf_gen1(TEXTX, "textx", 1, 1, pdf_state_content) +pdf_gen1(TEXTY, "texty", 1, 1, pdf_state_content) +pdf_gen1(LEADING, "leading", 1, 1, pdf_state_content) +pdf_gen1(TEXTRISE, "textrise", 1, 1, pdf_state_content) +pdf_gen1(HORIZSCALING, "horizscaling", 1, 1, + pdf_state_content | pdf_state_document) +pdf_gen1(TEXTRENDERING, "textrendering",1, 1, pdf_state_content) +pdf_gen1(CHARSPACING, "charspacing", 1, 1, + pdf_state_content | pdf_state_document) +pdf_gen1(WORDSPACING, "wordspacing", 1, 1, + pdf_state_content | pdf_state_document) +pdf_gen1(ITALICANGLE, "italicangle", 1, 1, + pdf_state_content | pdf_state_document) +pdf_gen1(FAKEBOLD, "fakebold", 1, 1, + pdf_state_content | pdf_state_document) +pdf_gen1(UNDERLINEWIDTH,"underlinewidth", 1, 1, + pdf_state_content | pdf_state_document) +pdf_gen1(UNDERLINEPOSITION,"underlineposition", 1, 1, + pdf_state_content | pdf_state_document) +pdf_gen1(UNDERLINE, "underline", 1, 1, pdf_state_content) +pdf_gen1(OVERLINE, "overline", 1, 1, pdf_state_content) +pdf_gen1(STRIKEOUT, "strikeout", 1, 1, pdf_state_content) +pdf_gen1(KERNING, "kerning", 1, 1, pdf_state_all) +pdf_gen1(TEXTFORMAT, "textformat", 1, 1, pdf_state_all) +pdf_gen1(GLYPHWARNING, "glyphwarning", 1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(GLYPHCHECK, "glyphcheck", 1, 1, pdf_state_all) + + +/* + * ---------------------------------------------------------------------- + * Graphics + * ---------------------------------------------------------------------- + */ + +pdf_gen1(CURRENTX, "currentx", 1, 1, + pdf_state_content | pdf_state_path) +pdf_gen1(CURRENTY, "currenty", 1, 1, + pdf_state_content | pdf_state_path) +pdf_gen1(FILLRULE, "fillrule", 1, 1, pdf_state_content) +pdf_gen1(TOPDOWN, "topdown", 1, 0, pdf_state_document) +pdf_gen1(CTM_A, "ctm_a", 1, 1, pdf_state_content) +pdf_gen1(CTM_B, "ctm_b", 1, 1, pdf_state_content) +pdf_gen1(CTM_C, "ctm_c", 1, 1, pdf_state_content) +pdf_gen1(CTM_D, "ctm_d", 1, 1, pdf_state_content) +pdf_gen1(CTM_E, "ctm_e", 1, 1, pdf_state_content) +pdf_gen1(CTM_F, "ctm_f", 1, 1, pdf_state_content) + + +/* + * ---------------------------------------------------------------------- + * Color + * ---------------------------------------------------------------------- + */ + +pdf_gen1(SETCOLOR_ICCPROFILEGRAY, "setcolor:iccprofilegray", 1, 1, + pdf_state_document | pdf_state_content) +pdf_gen1(SETCOLOR_ICCPROFILERGB, "setcolor:iccprofilergb", 1, 1, + pdf_state_document | pdf_state_content) +pdf_gen1(SETCOLOR_ICCPROFILECMYK, "setcolor:iccprofilecmyk", 1, 1, + pdf_state_document | pdf_state_content) +pdf_gen1(IMAGE_ICCPROFILE,"image:iccprofile", 0, 1, + pdf_state_path | pdf_state_content | pdf_state_document) +pdf_gen1(ICCWARNING, "iccwarning", 1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(HONORICCPROFILE, "honoriccprofile", 1, 1, pdf_state_all) +pdf_gen1(ICCCOMPONENTS, "icccomponents", 0, 1, pdf_state_all) +pdf_gen1(ICCPROFILE, "ICCProfile", 0, 1, pdf_state_all) +pdf_gen1(STANDARDOUTPUTINTENT, "StandardOutputIntent", 0, 1, pdf_state_all) +pdf_gen1(RENDERINGINTENT, "renderingintent", 1, 1, pdf_state_all) + +/* 3 x dep6 */ +pdf_gen1(DEFAULTRGB, "defaultrgb", 1, 1, + pdf_state_content | pdf_state_path) +pdf_gen1(DEFAULTGRAY, "defaultgray", 1, 1, + pdf_state_content | pdf_state_path) +pdf_gen1(DEFAULTCMYK, "defaultcmyk", 1, 1, + pdf_state_content | pdf_state_path) + +pdf_gen1(PRESERVEOLDPANTONENAMES, "preserveoldpantonenames", 1, 1, + pdf_state_all) +pdf_gen1(SPOTCOLORLOOKUP, "spotcolorlookup", 1, 1, + pdf_state_all) + +/* + * ---------------------------------------------------------------------- + * Image + * ---------------------------------------------------------------------- + */ + +pdf_gen1(IMAGEWARNING, "imagewarning", 1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(IMAGEWIDTH, "imagewidth", 0, 1, + pdf_state_path | pdf_state_content | pdf_state_document) +pdf_gen1(IMAGEHEIGHT, "imageheight", 0, 1, + pdf_state_path | pdf_state_content | pdf_state_document) +pdf_gen1(RESX, "resx", 0, 1, + pdf_state_path | pdf_state_content | pdf_state_document) +pdf_gen1(RESY, "resy", 0, 1, + pdf_state_path | pdf_state_content | pdf_state_document) +pdf_gen1(ORIENTATION, "orientation", 0, 1, + pdf_state_path | pdf_state_content | pdf_state_document) + +pdf_gen1(INHERITGSTATE, "inheritgstate",1, 1, pdf_state_all) /* dep6 */ + + +/* + * ---------------------------------------------------------------------- + * PDI + * ---------------------------------------------------------------------- + */ + +pdf_gen1(PDI, "pdi", 1, 1, pdf_state_all) +pdf_gen1(PDIWARNING, "pdiwarning", 1, 1, pdf_state_all) /* dep7 */ +pdf_gen1(PDIUSEBOX, "pdiusebox", 1, 1, pdf_state_all) /* dep6 */ +pdf_gen1(PDISTRICT, "pdistrict", 1, 1, pdf_state_all) /* unsupp */ + + +/* + * ---------------------------------------------------------------------- + * Hypertext + * ---------------------------------------------------------------------- + */ + +pdf_gen1(HYPERTEXTFORMAT, "hypertextformat", 1, 1, pdf_state_all) +pdf_gen1(HYPERTEXTENCODING, "hypertextencoding", 1, 1, pdf_state_all) +pdf_gen1(USERCOORDINATES, "usercoordinates", 1, 1, pdf_state_all) +pdf_gen1(USEHYPERTEXTENCODING, "usehypertextencoding", 1, 1, pdf_state_all) + /* unsupp */ + +pdf_gen1(HIDETOOLBAR, "hidetoolbar", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(HIDEMENUBAR, "hidemenubar", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(HIDEWINDOWUI, "hidewindowui", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(FITWINDOW, "fitwindow", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(CENTERWINDOW, "centerwindow", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(DISPLAYDOCTITLE, "displaydoctitle", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(NONFULLSCREENPAGEMODE, "nonfullscreenpagemode", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(DIRECTION, "direction", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ + +pdf_gen1(VIEWAREA, "viewarea", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(VIEWCLIP, "viewclip", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(PRINTAREA, "printarea", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(PRINTCLIP, "printclip", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ + +pdf_gen1(OPENACTION, "openaction", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(OPENMODE, "openmode", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(BOOKMARKDEST, "bookmarkdest", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ +pdf_gen1(TRANSITION, "transition", 1, 1, pdf_state_all) /* dep6 */ +pdf_gen1(DURATION, "duration", 1, 1, pdf_state_all) /* dep6 */ +pdf_gen1(BASE, "base", 1, 1, + pdf_state_content | pdf_state_document) /* dep6 */ + +pdf_gen1(LAUNCHLINK_PARAMETERS, "launchlink:parameters", 1, 1, + pdf_state_all) /* dep6 */ +pdf_gen1(LAUNCHLINK_OPERATION, "launchlink:operation", 1, 1, + pdf_state_all) /* dep6 */ +pdf_gen1(LAUNCHLINK_DEFAULTDIR, "launchlink:defaultdir", 1, 1, + pdf_state_all) /* dep6 */ + + +/* + * ---------------------------------------------------------------------- + * Security (all dep6) + * ---------------------------------------------------------------------- + */ + +pdf_gen1(USERPASSWORD, "userpassword", 1, 1, pdf_state_object) /* dep6 */ +pdf_gen1(MASTERPASSWORD,"masterpassword",1,1, pdf_state_object) /* dep6 */ +pdf_gen1(PERMISSIONS, "permissions", 1, 1, pdf_state_object) /* dep6 */ + + +/* + * ---------------------------------------------------------------------- + * Tagged PDF + * ---------------------------------------------------------------------- + */ + +pdf_gen1(AUTOSPACE, "autospace", 1, 1, pdf_state_all) + + +#undef pdf_gen1 +#undef pdf_gen2 diff --git a/src/pdflib/pdflib/p_pattern.c b/src/pdflib/pdflib/p_pattern.c new file mode 100644 index 0000000..73306f7 --- /dev/null +++ b/src/pdflib/pdflib/p_pattern.c @@ -0,0 +1,231 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_pattern.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib pattern routines + * + */ + +#include "p_intern.h" +#include "p_color.h" +#include "p_image.h" + +void +pdf_init_pattern(PDF *p) +{ + static const char fn[] = "pdf_init_pattern"; + int i; + + p->pattern_number = 0; + p->pattern_capacity = PATTERN_CHUNKSIZE; + + p->pattern = (pdf_pattern *) pdc_malloc(p->pdc, + sizeof(pdf_pattern) * p->pattern_capacity, fn); + + for (i = 0; i < p->pattern_capacity; i++) { + p->pattern[i].used_on_current_page = pdc_false; + p->pattern[i].obj_id = PDC_BAD_ID; + } +} + +void +pdf_grow_pattern(PDF *p) +{ + static const char fn[] = "pdf_grow_pattern"; + int i; + + p->pattern = (pdf_pattern *) pdc_realloc(p->pdc, p->pattern, + sizeof(pdf_pattern) * 2 * p->pattern_capacity, fn); + + for (i = p->pattern_capacity; i < 2 * p->pattern_capacity; i++) { + p->pattern[i].used_on_current_page = pdc_false; + p->pattern[i].obj_id = PDC_BAD_ID; + } + + p->pattern_capacity *= 2; +} + +void +pdf_write_page_pattern(PDF *p) +{ + int i, total = 0; + int bias = p->curr_ppt->pt_bias; + + for (i = 0; i < p->pattern_number; i++) + if (p->pattern[i].used_on_current_page) + total++; + + if (total > 0 || bias) + { + pdc_puts(p->out, "/Pattern"); + pdc_begin_dict(p->out); + } + + if (total > 0) + { + for (i = 0; i < p->pattern_number; i++) + { + if (p->pattern[i].used_on_current_page) + { + p->pattern[i].used_on_current_page = pdc_false; /* reset */ + pdc_printf(p->out, "/P%d", bias + i); + pdc_objref(p->out, "", p->pattern[i].obj_id); + } + } + + if (!bias) + pdc_end_dict(p->out); + } +} + +void +pdf_get_page_patterns(PDF *p, pdf_reslist *rl) +{ + int i; + + for (i = 0; i < p->pattern_number; i++) { + if (p->pattern[i].used_on_current_page) { + p->pattern[i].used_on_current_page = pdc_false; /* reset */ + pdf_add_reslist(p, rl, i); + } + } +} + +void +pdf_mark_page_pattern(PDF *p, int n) +{ + p->pattern[n].used_on_current_page = pdc_true; +} + +void +pdf_cleanup_pattern(PDF *p) +{ + if (p->pattern) { + pdc_free(p->pdc, p->pattern); + p->pattern = NULL; + } +} + +/* Start a new pattern definition. */ +int +pdf__begin_pattern( + PDF *p, + pdc_scalar width, + pdc_scalar height, + pdc_scalar xstep, + pdc_scalar ystep, + int painttype) +{ + int slot = -1; + + pdc_check_number_limits(p->pdc, "width", width, + PDC_FLOAT_PREC, PDC_FLOAT_MAX); + pdc_check_number_limits(p->pdc, "height", height, + PDC_FLOAT_PREC, PDC_FLOAT_MAX); + + pdc_check_number_zero(p->pdc, "xstep", xstep); + pdc_check_number_zero(p->pdc, "ystep", ystep); + + if (painttype != 1 && painttype != 2) + pdc_error(p->pdc, PDC_E_ILLARG_INT, + "painttype", pdc_errprintf(p->pdc, "%d", painttype), 0, 0); + + if (p->pattern_number == p->pattern_capacity) + pdf_grow_pattern(p); + + pdf_pg_suspend(p); + PDF_SET_STATE(p, pdf_state_pattern); + + p->pattern[p->pattern_number].obj_id = pdc_begin_obj(p->out, PDC_NEW_ID); + p->pattern[p->pattern_number].painttype = painttype; + + pdc_begin_dict(p->out); /* pattern dict*/ + + p->res_id = pdc_alloc_id(p->out); + + pdc_puts(p->out, "/PatternType 1\n"); /* tiling pattern */ + + /* colored or uncolored pattern */ + pdc_printf(p->out, "/PaintType %d\n", painttype); + pdc_puts(p->out, "/TilingType 1\n"); /* constant spacing */ + + pdc_printf(p->out, "/BBox[0 0 %f %f]\n", width, height); + + pdc_printf(p->out, "/XStep %f\n", xstep); + pdc_printf(p->out, "/YStep %f\n", ystep); + + pdc_objref(p->out, "/Resources", p->res_id); + + p->length_id = pdc_alloc_id(p->out); + pdc_objref(p->out, "/Length", p->length_id); + + if (pdc_get_compresslevel(p->out)) + pdc_puts(p->out, "/Filter/FlateDecode\n"); + + pdc_end_dict(p->out); /* pattern dict*/ + pdc_begin_pdfstream(p->out); + + slot = p->pattern_number; + p->pattern_number++; + + /* top-down y-coordinates */ + pdf_set_topdownsystem(p, height); + + /* set color differing from PDF default */ + pdf_set_default_color(p, pdc_false); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[Begin pattern %d]\n", slot); + + return slot; +} + +/* Finish the pattern definition. */ +void +pdf__end_pattern(PDF *p) +{ + /* check whether pdf__save() and pdf__restore() calls are balanced */ + if (p->curr_ppt->sl > 0) + pdc_error(p->pdc, PDF_E_GSTATE_UNMATCHEDSAVE, 0, 0, 0, 0); + + pdf_end_text(p); + pdc_end_pdfstream(p->out); + pdc_end_obj(p->out); /* pattern */ + + pdc_put_pdfstreamlength(p->out, p->length_id); + + pdc_begin_obj(p->out, p->res_id); /* Resource object */ + pdc_begin_dict(p->out); /* Resource dict */ + + pdf_write_page_fonts(p); /* Font resources */ + + pdf_write_page_colorspaces(p); /* Color space resources */ + + pdf_write_page_pattern(p); /* Pattern resources */ + + pdf_write_xobjects(p); /* XObject resources */ + + pdf_write_page_extgstates(p); /* ExtGState resources */ + + pdc_end_dict(p->out); /* resource dict */ + pdc_end_obj(p->out); /* resource object */ + + pdf_pg_resume(p, -1); + + if (p->flush & pdc_flush_content) + pdc_flush_stream(p->out); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[End pattern %d]\n", + p->pattern_number -1); +} diff --git a/src/pdflib/pdflib/p_pdi.c b/src/pdflib/pdflib/p_pdi.c new file mode 100644 index 0000000..a138987 --- /dev/null +++ b/src/pdflib/pdflib/p_pdi.c @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_pdi.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDF import routines (require the PDI library) + * + */ + +#define P_PDI_C + +#include "p_intern.h" + + + + + + + diff --git a/src/pdflib/pdflib/p_pfm.c b/src/pdflib/pdflib/p_pfm.c new file mode 100644 index 0000000..cab291b --- /dev/null +++ b/src/pdflib/pdflib/p_pfm.c @@ -0,0 +1,406 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_pfm.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib routines for fast reading of PFM font metrics files + * + */ + +#include "p_intern.h" +#include "p_font.h" + +/* read data types from the PFM */ +#define PFM_BYTE(offset) pfm[offset] +#define PFM_WORD(offset) PDC_GET_WORD(&pfm[offset]) +#define PFM_SHORT(offset) PDC_GET_SHORT(&pfm[offset]) +#define PFM_DWORD(offset) PDC_GET_DWORD3(&pfm[offset]) + +/* Offsets in the buffer containing the various PFM structures */ +#define header_base 0 +#define header_dfVersion (PFM_WORD(header_base + 0)) +#define header_dfSize (PFM_DWORD(header_base + 2)) +#define header_dfAscent (PFM_WORD(header_base + 74)) +#define header_dfItalic (PFM_BYTE(header_base + 80)) +#define header_dfWeight (PFM_WORD(header_base + 83)) +#define header_dfCharSet (PFM_BYTE(header_base + 85)) +#define header_dfPitchAndFamily (PFM_BYTE(header_base + 90)) +#define header_dfMaxWidth (PFM_WORD(header_base + 93)) +#define header_dfFirstChar (PFM_BYTE(header_base + 95)) +#define header_dfLastChar (PFM_BYTE(header_base + 96)) +#define header_dfDefaultChar (PFM_BYTE(header_base + 97)) + +#define ext_base 117 +#define ext_dfExtentTable (PFM_DWORD(ext_base + 6)) +#define ext_dfKernPairs (PFM_DWORD(ext_base + 14)) +#define ext_dfKernTrack (PFM_DWORD(ext_base + 18)) +#define ext_dfDriverInfo (PFM_DWORD(ext_base + 22)) + +#define etm_base 147 +#define etmCapHeight (PFM_SHORT(etm_base + 14)) +#define etmXHeight (PFM_SHORT(etm_base + 16)) +#define etmLowerCaseAscent (PFM_SHORT(etm_base + 18)) +#define etmLowerCaseDescent (PFM_SHORT(etm_base + 20)) +#define etmSlant (PFM_SHORT(etm_base + 22)) +#define etmUnderlineOffset (PFM_SHORT(etm_base + 32)) +#define etmUnderlineWidth (PFM_SHORT(etm_base + 34)) + +#define dfDevice 199 + +/* Windows font descriptor flags */ +#define PDF_FIXED_PITCH 0x01 /* Fixed width font; rarely used flag */ + +#define PDF_DONTCARE 0x00 /* Don't care or don't know. */ +#define PDF_ROMAN 0x10 /* Variable stroke width, serifed */ +#define PDF_SWISS 0x20 /* Variable stroke width, sans-serifed */ +#define PDF_MODERN 0x30 /* fixed pitch */ +#define PDF_SCRIPT 0x40 /* Cursive, etc. */ +#define PDF_DECORATIVE 0x50 /* Old English, etc. */ + +/* Windows character set flags */ +#define PFM_ANSI_CHARSET 0 +#define PFM_SYMBOL_CHARSET 2 +#define PFM_GREEK_CHARSET 161 +#define PFM_TURKISH_CHARSET 162 +#define PFM_VIETNAMESE_CHARSET 163 +#define PFM_HEBREW_CHARSET 177 +#define PFM_ARABIC_CHARSET 178 +#define PFM_BALTIC_CHARSET 186 +#define PFM_RUSSIAN_CHARSET 204 +#define PFM_THAI_CHARSET 222 +#define PFM_EASTEUROPE_CHARSET 238 + +static const pdc_keyconn pdf_charset_keylist[] = +{ + {"winansi", PFM_ANSI_CHARSET }, + {"", PFM_SYMBOL_CHARSET }, + {"cp1253", PFM_GREEK_CHARSET }, + {"cp1254", PFM_TURKISH_CHARSET }, + {"cp1258", PFM_VIETNAMESE_CHARSET}, + {"cp1255", PFM_HEBREW_CHARSET }, + {"cp1256", PFM_ARABIC_CHARSET }, + {"cp1257", PFM_BALTIC_CHARSET }, + {"cp1251", PFM_RUSSIAN_CHARSET }, + {"cp874", PFM_THAI_CHARSET }, + {"cp1250", PFM_EASTEUROPE_CHARSET}, + {NULL, 0}, +}; + +#define PDF_STRING_PostScript \ + ((const char*) "\120\157\163\164\123\143\162\151\160\164") + +/* + * Kerning pairs + */ +typedef struct kern_ +{ + pdc_byte first; /* First character */ + pdc_byte second; /* Second character */ + pdc_byte kern[2]; /* Kern distance */ +} +KERN; + +pdc_bool +pdf_check_pfm_encoding(PDF *p, pdf_font *font, pdc_encoding enc) +{ + const char *encname = + pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, + pdf_get_encoding_name(p, enc, font)); + const char *newencname = NULL; + pdc_encoding newenc = pdc_invalidenc; + pdc_bool issymbfont = pdc_undef; + + pdc_logg_cond(p->pdc, 2, trc_font, + "\tFont internal charset (dfCharSet): %d\n", font->ft.enc); + + /* Font encoding */ + newencname = pdc_get_keyword(font->ft.enc, pdf_charset_keylist); + if (newencname == NULL) + { + pdc_set_errmsg(p->pdc, PDF_E_T1_BADCHARSET, + pdc_errprintf(p->pdc, "%d", font->ft.enc), 0, 0, 0); + return pdc_false; + } + + if (strlen(newencname)) + { + int codepage = 0; + + pdc_logg_cond(p->pdc, 2, trc_font, + "\tFont internal encoding \"%s\" found\n", newencname); + + newenc = pdc_find_encoding(p->pdc, newencname); + if (newenc == pdc_invalidenc) + newenc = pdc_insert_encoding(p->pdc, newencname, &codepage, + pdc_true); + + font->ft.issymbfont = pdc_false; + } + else + { + pdc_logg_cond(p->pdc, 2, trc_font, "\tSymbol font\n"); + + font->ft.issymbfont = pdc_true; + newenc = pdc_builtin; + + /* auto */ + if (!strcmp(font->encapiname, "auto")) + { + issymbfont = pdc_true; + enc = pdc_builtin; + } + } + + /* builtin */ + if (enc == pdc_builtin) + issymbfont = pdc_true; + + /* unicode */ + if (enc == pdc_unicode) + { + font->unibyte = pdc_true; + issymbfont = pdc_false; + enc = newenc; + } + + /* encoding is subset of 8-bit encoding */ + if (enc >= pdc_winansi && newenc >= pdc_winansi) + { + if (pdc_is_encoding_subset(p->pdc, pdc_get_encoding_vector(p->pdc, enc), + pdc_get_encoding_vector(p->pdc, newenc))) + { + if (enc != pdc_winansi && newenc == pdc_winansi && + strcmp(encname, "iso8859-1")) + font->towinansi = pdc_invalidenc; + + issymbfont = pdc_false; + enc = newenc; + } + } + + /* illegal encoding */ + if (issymbfont == pdc_undef || font->ft.issymbfont == pdc_undef) + { + pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0); + return pdc_false; + } + + font->ft.enc = enc; + if (issymbfont && !font->ft.issymbfont) + { + pdc_warning(p->pdc, PDF_E_FONT_FORCEENC, + pdf_get_encoding_name(p, newenc, NULL), + 0, 0, 0); + font->ft.enc = newenc; + } + if (!issymbfont && font->ft.issymbfont) + { + pdc_warning(p->pdc, PDF_E_FONT_FORCEENC, + pdf_get_encoding_name(p, pdc_builtin, NULL), + 0, 0, 0); + font->ft.enc = pdc_builtin; + font->towinansi = pdc_invalidenc; + } + + if (font->towinansi != pdc_invalidenc) + pdf_transform_fontwidths(p, font, + pdc_get_encoding_vector(p->pdc, font->ft.enc), + pdc_get_encoding_vector(p->pdc, font->towinansi)); + + return pdc_true; +} + + +/* + * Currently we do not populate the following fields correctly: + * - serif flag + */ + +static pdc_bool +pdf_parse_pfm(PDF *p, pdc_file *fp, pdf_font *font) +{ + static const char fn[] = "pdf_parse_pfm"; + fnt_font_metric *ftm = &font->ft.m; + size_t length; + pdc_byte *pfm; + pdc_bool ismem; + int i, dfFirstChar, dfLastChar, default_width; + unsigned long dfExtentTable; + + /* read whole file and close it */ + pfm = (pdc_byte *) pdc_freadall(fp, &length, &ismem); + pdc_fclose(fp); + + /* check whether this is really a valid PostScript PFM file */ + if (pfm == NULL || + (header_dfVersion != 0x100 && header_dfVersion != 0x200) || + dfDevice > length || + strncmp((const char *) pfm + dfDevice, PDF_STRING_PostScript, 10) || + ext_dfDriverInfo > length) + { + if (!ismem) + pdc_free(p->pdc, pfm); + return pdc_false; + } + + /* fetch relevant data from the PFM */ + ftm->type = fnt_Type1; + + font->ft.name = pdc_strdup(p->pdc, (const char *)pfm + ext_dfDriverInfo); + ftm->name = pdc_strdup(p->pdc, font->ft.name); + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tPostScript font name: \"%s\"\n", ftm->name); + + switch (header_dfPitchAndFamily & 0xF0) + { + case PDF_ROMAN: + ftm->flags |= FNT_SERIF; + break; + case PDF_MODERN: + /* Has to be ignored, contrary to MS's specs */ + break; + case PDF_SCRIPT: + ftm->flags |= FNT_SCRIPT; + break; + case PDF_DECORATIVE: + /* the dfCharSet flag lies in this case... */ + header_dfCharSet = PFM_SYMBOL_CHARSET; + break; + case PDF_SWISS: + case PDF_DONTCARE: + default: + break; + } + + /* temporarily */ + font->ft.enc = (pdc_encoding) header_dfCharSet; + + dfFirstChar = header_dfFirstChar; + dfLastChar = header_dfLastChar; + dfExtentTable = ext_dfExtentTable; + + /* + * Some rare PFMs do not contain any ExtentTable if the fixed pitch flag + * is set. Use the dfMaxWidth entry for all glyphs in this case. + * If the user forced the font to be monospaced we use this value instead. + */ + if ((!(header_dfPitchAndFamily & PDF_FIXED_PITCH) && dfExtentTable == 0) || + font->opt.monospace) + { + ftm->isFixedPitch = pdc_true; + default_width = font->opt.monospace ? font->opt.monospace : + (int) header_dfMaxWidth; + } + else + { + /* default values -- don't take the width of the default character */ + default_width = FNT_DEFAULT_WIDTH; + } + + font->ft.numcodes = 256; + ftm->numwidths = font->ft.numcodes; + ftm->widths = (int *) pdc_calloc(p->pdc, ftm->numwidths * sizeof(int), fn); + for (i = 0; i < font->ft.numcodes; i++) + ftm->widths[i] = default_width; + + if (!ftm->isFixedPitch) + { + if (ext_dfExtentTable == 0 || + ext_dfExtentTable + 2 * (header_dfLastChar-header_dfFirstChar) + 1 > + length) + { + if (!ismem) + pdc_free(p->pdc, pfm); + return pdc_false; + } + + for (i = dfFirstChar; i <= dfLastChar; i++) + ftm->widths[i] = + (int) PFM_WORD(dfExtentTable + 2 * (i - dfFirstChar)); + /* + * Check whether the font is actually opt.monospaced + * (the fixed pitch flag is not necessarily set) + */ + default_width = ftm->widths[dfFirstChar]; + + for (i = dfFirstChar+1; i <= dfLastChar; i++) + if (default_width != ftm->widths[i]) + break; + + if (i == dfLastChar + 1) + ftm->isFixedPitch = pdc_true; + } + + font->ft.weight = fnt_check_weight(header_dfWeight); + ftm->defwidth = default_width; + ftm->italicAngle = (header_dfItalic ? etmSlant/(10.0) : 0.0); + ftm->capHeight = etmCapHeight; + ftm->xHeight = etmXHeight; + ftm->descender = -etmLowerCaseDescent; + ftm->ascender = (int) header_dfAscent; + + ftm->underlinePosition = -etmUnderlineOffset; + ftm->underlineThickness = etmUnderlineWidth; + + ftm->urx = header_dfMaxWidth; + + + if (!ismem) + pdc_free(p->pdc, pfm); + + return pdc_true; +} + +pdc_bool +pdf_get_metrics_pfm( + PDF *p, + pdf_font *font, + const char *fontname, + pdc_encoding enc, + const char *filename, + pdc_bool requested) +{ + static const char fn[] = "pdf_get_metrics_pfm"; + char fullname[PDC_FILENAMELEN]; + pdc_file *pfmfile; + + (void) fontname; + + /* open PFM file */ + pfmfile = pdc_fsearch_fopen(p->pdc, filename, fullname, "PFM ", + PDC_FILE_BINARY); + if (pfmfile == NULL) + return pdc_check_fopen_errmsg(p->pdc, requested); + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tLoading PFM metric fontfile \"%s\":\n", fullname); + + /* Read PFM metrics */ + if (!pdf_parse_pfm(p, pfmfile, font)) + { + pdc_set_errmsg(p->pdc, PDF_E_FONT_CORRUPT, "PFM", fullname, 0, 0); + return pdc_false; + } + + /* save full filename */ + font->metricfilename = pdc_strdup_ext(p->pdc, fullname, 0, fn); + + /* Check encoding */ + if (!pdf_check_pfm_encoding(p, font, enc)) + return pdc_false; + + if (!pdf_make_fontflag(p, font)) + return pdc_false; + + return pdc_true; +} diff --git a/src/pdflib/pdflib/p_photoshp.c b/src/pdflib/pdflib/p_photoshp.c new file mode 100644 index 0000000..354f547 --- /dev/null +++ b/src/pdflib/pdflib/p_photoshp.c @@ -0,0 +1,23 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_photoshp.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib Photoshop image resource data routines + * + */ + +#define P_PHOTOSHP_C + +#include "p_intern.h" +#include "p_image.h" + diff --git a/src/pdflib/pdflib/p_png.c b/src/pdflib/pdflib/p_png.c new file mode 100644 index 0000000..42359a3 --- /dev/null +++ b/src/pdflib/pdflib/p_png.c @@ -0,0 +1,855 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_png.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PNG processing for PDFlib + * + */ + +#include "p_intern.h" +#include "p_color.h" +#include "p_image.h" + +#if defined(__ia64__) && defined (__linux__) +#define PDF_ALIGN16 +#endif + +/* SPNG - Simple PNG +** +** The items below, prefixed with spng_, or SPNG_, establish a replacement +** for LIBPNG that works very fast, but processes simple PNG images only: +** - bit_depth <= 8 (no 16-bit) +** - interlace_type 0 (no interlacing) +** - color_type 0, 2, or 3 (no alpha-channel); color type 3 requires +** libpng for palette processing +*/ +#define SPNG_SIGNATURE "\211\120\116\107\015\012\032\012" + +#define SPNG_CHUNK_IHDR 0x49484452 +#define SPNG_CHUNK_PLTE 0x504C5445 +#define SPNG_CHUNK_tRNS 0x74524E53 +#define SPNG_CHUNK_IDAT 0x49444154 +#define SPNG_CHUNK_IEND 0x49454E44 + +/* spng_init() return codes +*/ +#define SPNG_ERR_OK 0 /* no error */ +#define SPNG_ERR_NOPNG 1 /* bad PNG signature */ +#define SPNG_ERR_FMT 2 /* bad PNG file format */ + +typedef struct +{ + /* from IHDR: + */ + int width; + int height; + pdc_byte bit_depth; + pdc_byte color_type; + pdc_byte compr_type; + pdc_byte filter_type; + pdc_byte interlace_type; +} spng_info; + +static int +spng_getint(pdc_file *fp) +{ + unsigned char buf[4]; + + if (!PDC_OK_FREAD(fp, buf, 4)) + return -1; + + return (int) pdc_get_be_long(buf); +} /* spng_getint */ + +static int +spng_init(PDF *p, pdf_image *image, spng_info *spi) +{ + pdc_file *fp = image->fp; + char buf[8]; + + (void) p; + + /* check signature + */ + if (!PDC_OK_FREAD(fp, buf, 8) || + strncmp(buf, SPNG_SIGNATURE, 8) != 0) + return SPNG_ERR_NOPNG; + + /* read IHDR + */ + if (spng_getint(fp) != 13 || + spng_getint(fp) != SPNG_CHUNK_IHDR) + return SPNG_ERR_FMT; + + spi->width = spng_getint(fp); + spi->height = spng_getint(fp); + + if (!PDC_OK_FREAD(fp, buf, 5)) + return SPNG_ERR_FMT; + + spi->bit_depth = (pdc_byte) buf[0]; + spi->color_type = (pdc_byte) buf[1]; + spi->compr_type = (pdc_byte) buf[2]; + spi->filter_type = (pdc_byte) buf[3]; + spi->interlace_type = (pdc_byte) buf[4]; + + (void) spng_getint(fp); /* CRC */ + + /* decide whether this image is "simple". + */ +#ifdef HAVE_LIBPNG + if (spi->bit_depth > 8 || spi->color_type > 3 || spi->interlace_type != 0) +#else + if (spi->bit_depth > 8 || spi->color_type > 2 || spi->interlace_type != 0) +#endif /* !HAVE_LIBPNG */ + { + image->use_raw = pdc_false; + return SPNG_ERR_OK; + } + else + image->use_raw = pdc_true; + + /* read (or skip) all chunks up to the first IDAT. + */ + for (/* */ ; /* */ ; /* */) + { + int len = spng_getint(fp); + int type = spng_getint(fp); + + switch (type) + { + case SPNG_CHUNK_IDAT: /* prepare data xfer */ + image->info.png.nbytes = (size_t) len; + return SPNG_ERR_OK; + + case -1: + return SPNG_ERR_FMT; + + /* if we decide to live without LIBPNG, + ** we should handle these cases, too. + */ + case SPNG_CHUNK_tRNS: /* transparency chunk */ + case SPNG_CHUNK_PLTE: /* read in palette */ + + default: + pdc_fseek(fp, len + 4, SEEK_CUR); + /* skip data & CRC */ + break; + } /* switch */ + } + + return SPNG_ERR_OK; +} /* spng_init */ + +#define PDF_PNG_BUFFERSIZE 8192 + +static void +pdf_data_source_PNG_init(PDF *p, PDF_data_source *src) +{ + static const char fn[] = "pdf_data_source_PNG_init"; + pdf_image *image = (pdf_image *) src->private_data; + +#ifdef HAVE_LIBPNG + if (image->use_raw) + { +#endif + src->buffer_length = PDF_PNG_BUFFERSIZE; + src->buffer_start = (pdc_byte *) + pdc_malloc(p->pdc, src->buffer_length, fn); + src->bytes_available = 0; + src->next_byte = src->buffer_start; + +#ifdef HAVE_LIBPNG + } + else + { + image->info.png.cur_line = 0; + src->buffer_length = image->info.png.rowbytes; + } +#endif +} + +#undef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +static void +spng_error(PDF *p, PDF_data_source *src) +{ + pdf_image *image = (pdf_image *) src->private_data; + + pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "PNG", + pdf_get_image_filename(p, image), 0, 0); +} /* spng_error */ + +static pdc_bool +pdf_data_source_PNG_fill(PDF *p, PDF_data_source *src) +{ + pdf_image *image = (pdf_image *) src->private_data; + + PDC_TRY(p->pdc) + { +#ifdef HAVE_LIBPNG + if (image->use_raw) + { +#endif + pdc_file * fp = image->fp; + size_t buf_avail = src->buffer_length; + pdc_byte *scan = src->buffer_start; + + src->bytes_available = 0; + + if (image->info.png.nbytes == 0) + { + PDC_EXIT_TRY(p->pdc); + return pdc_false; + } + + do + { + size_t nbytes = min(image->info.png.nbytes, buf_avail); + + if (!PDC_OK_FREAD(fp, scan, nbytes)) + spng_error(p, src); + + src->bytes_available += nbytes; + scan += nbytes; + buf_avail -= nbytes; + + if ((image->info.png.nbytes -= nbytes) == 0) + { + /* proceed to next IDAT chunk + */ + (void) spng_getint(fp); /* CRC */ + image->info.png.nbytes = + (size_t) spng_getint(fp); /* length */ + + if (spng_getint(fp) != SPNG_CHUNK_IDAT) + { + image->info.png.nbytes = 0; + PDC_EXIT_TRY(p->pdc); + return pdc_true; + } + } + } + while (buf_avail); + +#ifdef HAVE_LIBPNG + } + else + { + if (image->info.png.cur_line == image->height) + { + PDC_EXIT_TRY(p->pdc); + return pdc_false; + } + + src->next_byte = image->info.png.raster + + image->info.png.cur_line * image->info.png.rowbytes; + + src->bytes_available = src->buffer_length; + + image->info.png.cur_line++; + } +#endif /* HAVE_LIBPNG */ + } + PDC_CATCH(p->pdc) + { + image->corrupt = pdc_true; + } + + return !image->corrupt; +} + +static void +pdf_data_source_PNG_terminate(PDF *p, PDF_data_source *src) +{ + pdf_image *image = (pdf_image *) src->private_data; + +#ifdef HAVE_LIBPNG + if (image->use_raw) + { +#endif + pdc_free(p->pdc, (void *) src->buffer_start); + +#ifdef HAVE_LIBPNG + } +#endif +} + +#ifdef HAVE_LIBPNG +/* + * We suppress libpng's warning message by supplying + * our own error and warning handlers +*/ +static void +pdf_libpng_warning_handler(png_structp png_ptr, png_const_charp message) +{ + (void) png_ptr; /* avoid compiler warning "unreferenced parameter" */ + (void) message; /* avoid compiler warning "unreferenced parameter" */ + + /* do nothing */ + return; +} + +/* + * use the libpng portability aid in an attempt to overcome version differences + */ +#ifndef png_jmpbuf +#define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif + +static void +pdf_libpng_error_handler(png_structp png_ptr, png_const_charp message) +{ +#ifdef PDF_ALIGN16 + jmp_buf jbuf; +#endif + + (void) message; /* avoid compiler warning "unreferenced parameter" */ + +#ifdef PDF_ALIGN16 + memcpy(jbuf, png_jmpbuf(png_ptr), sizeof (jmp_buf)); + longjmp(jbuf, 1); +#else + longjmp(png_jmpbuf(png_ptr), 1); +#endif +} + +static void * +pdf_libpng_malloc(png_structp png_ptr, size_t size) +{ + PDF *p = (PDF *)png_ptr->mem_ptr; + + return pdc_malloc(p->pdc, size, "libpng"); +} + +static void +pdf_libpng_free(png_structp png_ptr, void *mem) +{ + PDF *p = (PDF *)png_ptr->mem_ptr; + + pdc_free(p->pdc, mem); +} + +pdc_bool +pdf_is_PNG_file(PDF *p, pdc_file *fp) +{ + pdc_byte sig[8]; + + pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type PNG...\n"); + + if (!PDC_OK_FREAD(fp, sig, 8) || !png_check_sig(sig, 8)) { + pdc_fseek(fp, 0L, SEEK_SET); + return pdc_false; + } + return pdc_true; +} + +static void /* CDPDF - moved to inside the HAVE_LIBPNG definition */ +pdf_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + pdc_file *fp = (pdc_file *) png_ptr->io_ptr; + char *filename = (char *) pdc_file_name(fp); + + if (!PDC_OK_FREAD(fp, data, length)) + { + pdc_core *pdc = pdc_file_getpdc(fp); + + pdc_error(pdc, PDF_E_IMAGE_CORRUPT, "PNG", filename, 0, 0); + } +} + +int +pdf_process_PNG_data( + PDF *p, + int imageslot) +{ + static const char *fn = "pdf_process_PNG_data"; + pdc_file *save_fp; + spng_info s_info; +#ifdef PDF_ALIGN16 + jmp_buf jbuf; +#endif + + png_uint_32 width, height, ui; + png_bytep *row_pointers = NULL, trans; + png_color_8p sig_bit; + png_color_16p trans_values; + int bit_depth, color_type, i, num_trans; + pdc_scalar dpi_x, dpi_y; + pdf_image *image; + volatile int errcode = 0; + pdf_colorspace cs; + pdf_colormap * volatile colormap = NULL; + volatile int slot; + + image = &p->images[imageslot]; + + /* + * We can install our own memory handlers in libpng since + * our PNG library is specially extended to support this. + * A custom version of libpng without support for + * png_create_read_struct_2() is no longer supported. + */ + + image->info.png.png_ptr = + png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, + (png_error_ptr)pdf_libpng_error_handler, (png_error_ptr)pdf_libpng_warning_handler, /* CDPDF - added type cast */ + p, (png_malloc_ptr) pdf_libpng_malloc, + (png_free_ptr) pdf_libpng_free); + + if (!image->info.png.png_ptr) + { + pdc_error(p->pdc, PDC_E_MEM_OUT, fn, 0, 0, 0); + } + + image->info.png.info_ptr = png_create_info_struct(image->info.png.png_ptr); + + if (image->info.png.info_ptr == NULL) + { + png_destroy_read_struct(&image->info.png.png_ptr, + (png_infopp) NULL, (png_infopp) NULL); + pdc_error(p->pdc, PDC_E_MEM_OUT, fn, 0, 0, 0); + } + + /* due to alignment bug on itanium machines: + ** use well aligned local jbuf instead of sometimes + ** bad aligned (allocated) jmp_buf. + */ +#ifdef PDF_ALIGN16 + if (setjmp(jbuf)) +#else + if (setjmp(png_jmpbuf(image->info.png.png_ptr))) +#endif + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_PNG_ERROR; + } +#ifdef PDF_ALIGN16 + memcpy(png_jmpbuf(image->info.png.png_ptr), jbuf, sizeof (jmp_buf)); +#endif + + if (pdf_is_PNG_file(p, image->fp) == pdc_false) + { + errcode = PDC_E_IO_BADFORMAT; + goto PDF_PNG_ERROR; + } + + /* from file or from memory */ + png_set_read_fn(image->info.png.png_ptr, image->fp, (png_rw_ptr)pdf_png_read_data); /* CDPDF - added type cast */ + + png_set_sig_bytes(image->info.png.png_ptr, 8); + png_read_info(image->info.png.png_ptr, image->info.png.info_ptr); + png_get_IHDR(image->info.png.png_ptr, image->info.png.info_ptr, + &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + + image->width = (pdc_scalar) width; + image->height = (pdc_scalar) height; + + /* reduce 16-bit images to 8 bit since PDF < 1.5 stops at 8 bit */ + if (p->compatibility < PDC_1_5 && bit_depth == 16) + { + png_set_strip_16(image->info.png.png_ptr); + bit_depth = 8; + } + + image->bpc = bit_depth; + + /* + * We currently don't support a real alpha channel but only binary + * tranparency ("poor man's alpha"). For palette images we do our best and + * treat alpha values of up to 50% as transparent, and values above 50% + * as opaque. Gray and RGB images with an associated alpha channel will + * be pre-multiplied by libpng (against white background). + */ +#define ALPHA_THRESHOLD 128 + + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY_ALPHA: + /* LATER: construct mask from alpha channel */ + /* + png_set_IHDR(image->info.png.png_ptr, image->info.png.info_ptr, + width, height, bit_depth, PNG_COLOR_MASK_ALPHA, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + */ + /* + * We strip the alpha channel, and let libpng pre-multiply + * the opacity values to the image data. + */ + png_set_strip_alpha(image->info.png.png_ptr); + /* fall through */ + + case PNG_COLOR_TYPE_GRAY: + if (png_get_sBIT(image->info.png.png_ptr, + image->info.png.info_ptr, &sig_bit)) + { + png_set_shift(image->info.png.png_ptr, sig_bit); + } + + image->colorspace = DeviceGray; + + image->components = 1; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + /* LATER: construct mask from alpha channel */ + /* + * We strip the alpha channel, and let libpng pre-multiply + * the opacity values to the image data. + */ + png_set_strip_alpha(image->info.png.png_ptr); + /* fall through */ + + case PNG_COLOR_TYPE_RGB: + if (image->colorspace == pdc_undef) + image->colorspace = DeviceRGB; + image->components = 3; + + break; + + case PNG_COLOR_TYPE_PALETTE: + { + png_colorp pcm; + + png_get_PLTE(image->info.png.png_ptr, image->info.png.info_ptr, + &pcm, &cs.val.indexed.palette_size); + + colormap = + (pdf_colormap *) pdc_malloc(p->pdc, sizeof(pdf_colormap), fn); + + /* This seems redundant, but the png_colorp structure may not + * be packed on some platforms. + */ + for (i = 0; i < cs.val.indexed.palette_size; i++) + { + (*colormap)[i][0] = (pdc_byte) pcm[i].red; + (*colormap)[i][1] = (pdc_byte) pcm[i].green; + (*colormap)[i][2] = (pdc_byte) pcm[i].blue; + } + + image->components = 1; + + /* This case should arguably be prohibited. However, we allow + * it and take the palette indices 0 and 1 as the mask, + * disregarding any color values in the palette. + */ + if (image->imagemask) { + image->colorspace = DeviceGray; + break; + } + + cs.type = Indexed; + cs.val.indexed.base = DeviceRGB; + cs.val.indexed.colormap = colormap; + cs.val.indexed.colormap_id = PDC_BAD_ID; + slot = pdf_add_colorspace(p, &cs, pdc_false); + + image->colorspace = slot; + + } + break; + } + if (colormap) + pdc_free(p->pdc, colormap); + + if (image->imagemask) + { + if (image->components != 1) + { + errcode = PDF_E_IMAGE_BADMASK; + goto PDF_PNG_ERROR; + } + + if (p->compatibility <= PDC_1_3) { + if (image->components != 1 || image->bpc != 1) + { + errcode = PDF_E_IMAGE_MASK1BIT13; + goto PDF_PNG_ERROR; + } + } + else if (image->bpc > 1) + { + /* images with more than one bit will be written as /SMask, + * and don't require an /ImageMask entry. + */ + image->imagemask = pdc_false; + } + image->colorspace = DeviceGray; + } + + /* we invert this flag later */ + if (image->ignoremask) + image->transparent = pdc_true; + + /* let libpng expand interlaced images */ + (void) png_set_interlace_handling(image->info.png.png_ptr); + + /* read the physical dimensions chunk to find the resolution values */ + dpi_x = (pdc_scalar) png_get_x_pixels_per_meter(image->info.png.png_ptr, + image->info.png.info_ptr); + dpi_y = (pdc_scalar) png_get_y_pixels_per_meter(image->info.png.png_ptr, + image->info.png.info_ptr); + + if (dpi_x != 0 && dpi_y != 0) + { /* absolute values */ + image->dpi_x = dpi_x * PDC_INCH2METER; + image->dpi_y = dpi_y * PDC_INCH2METER; + + } + else + { /* aspect ratio */ + image->dpi_y = -png_get_pixel_aspect_ratio(image->info.png.png_ptr, + image->info.png.info_ptr); + + if (image->dpi_y == 0) /* unknown */ + image->dpi_x = 0; + else + image->dpi_x = -1.0; + } + + /* read the transparency chunk */ + if (png_get_valid(image->info.png.png_ptr, image->info.png.info_ptr, + PNG_INFO_tRNS)) + { + png_get_tRNS(image->info.png.png_ptr, image->info.png.info_ptr, + &trans, &num_trans, &trans_values); + if (num_trans > 0) + { + if (color_type == PNG_COLOR_TYPE_GRAY) + { + image->transparent = !image->transparent; + /* LATER: scale down 16-bit transparency values ? */ + image->transval[0] = (pdc_byte) trans_values[0].gray; + + } + else if (color_type == PNG_COLOR_TYPE_RGB) + { + image->transparent = !image->transparent; + /* LATER: scale down 16-bit transparency values ? */ + image->transval[0] = (pdc_byte) trans_values[0].red; + image->transval[1] = (pdc_byte) trans_values[0].green; + image->transval[2] = (pdc_byte) trans_values[0].blue; + + } + else if (color_type == PNG_COLOR_TYPE_PALETTE) + { + /* we use the first transparent entry in the tRNS palette */ + for (i = 0; i < num_trans; i++) + { + if ((pdc_byte) trans[i] < ALPHA_THRESHOLD) + { + image->transparent = !image->transparent; + image->transval[0] = (pdc_byte) i; + break; + } + } + } + } + } + + + + + png_read_update_info(image->info.png.png_ptr, image->info.png.info_ptr); + + image->info.png.rowbytes = + png_get_rowbytes(image->info.png.png_ptr, image->info.png.info_ptr); + + image->info.png.raster = (pdc_byte *) + pdc_calloc(p->pdc,image->info.png.rowbytes * height, fn); + + row_pointers = (png_bytep *) + pdc_malloc(p->pdc, height * sizeof(png_bytep), fn); + + for (ui = 0; ui < height; ui++) + { + row_pointers[ui] = + image->info.png.raster + ui * image->info.png.rowbytes; + } + + /* try the simple way: + */ + save_fp = image->fp; + + image->src.init = pdf_data_source_PNG_init; + image->src.fill = pdf_data_source_PNG_fill; + image->src.terminate = pdf_data_source_PNG_terminate; + image->src.private_data = (void *) image; + + + image->fp = pdc_fsearch_fopen(p->pdc, image->filename, NULL, NULL, + PDC_FILE_BINARY); + if (image->fp != NULL && + spng_init(p, image, &s_info) == SPNG_ERR_OK && image->use_raw) + { + pdc_fclose(save_fp); + image->predictor = pred_png; + image->compression = pdf_comp_flate; + } + else + { + if (image->fp != (pdc_file *) 0) + pdc_fclose(image->fp); + + image->fp = save_fp; + + /* Provide a suitable background for images with alpha channel */ + if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_color_16p image_background; + + if (png_get_bKGD(image->info.png.png_ptr, image->info.png.info_ptr, + &image_background)) + { + png_set_background(image->info.png.png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + } + else + { + png_color_16 my_white; + + if (bit_depth == 8) + { + my_white.red = 0xFF; + my_white.green = 0xFF; + my_white.blue = 0xFF; + my_white.gray = 0xFF; + } + else + { + my_white.red = 0xFFFF; + my_white.green = 0xFFFF; + my_white.blue = 0xFFFF; + my_white.gray = 0xFFFF; + } + + png_set_background(image->info.png.png_ptr, &my_white, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + } + } + + /* fetch the actual image data */ + png_read_image(image->info.png.png_ptr, row_pointers); + } + + image->in_use = pdc_true; /* mark slot as used */ + + pdf_put_image(p, imageslot, pdc_true, pdc_true); + + pdc_free(p->pdc, image->info.png.raster); + if (row_pointers != NULL) + pdc_free(p->pdc, row_pointers); + + png_destroy_read_struct(&image->info.png.png_ptr, + &image->info.png.info_ptr, NULL); + + if (!image->corrupt) + return imageslot; + + PDF_PNG_ERROR: + { + const char *stemp = NULL; + + if (errcode) + { + png_destroy_read_struct(&image->info.png.png_ptr, + &image->info.png.info_ptr, NULL); + stemp = pdf_get_image_filename(p, image); + } + + switch (errcode) + { + case PDF_E_IMAGE_ICC: + case PDF_E_IMAGE_ICC2: + case PDF_E_IMAGE_MASK1BIT13: + case PDF_E_IMAGE_BADMASK: + pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0); + break; + + case PDC_E_IO_BADFORMAT: + pdc_set_errmsg(p->pdc, errcode, stemp, "PNG", 0, 0); + break; + + case PDF_E_IMAGE_CORRUPT: + pdc_set_errmsg(p->pdc, errcode, "PNG", stemp, 0, 0); + break; + + case 0: /* error code and message already set */ + break; + } + } + + return -1; +} + +#else /* !HAVE_LIBPNG */ + +pdc_bool +pdf_is_PNG_file(PDF *p, pdc_file *fp) +{ + return pdc_false; +} + +/* simple built-in PNG reader without libpng */ + +int +pdf_process_PNG_data( + PDF *p, + int imageslot) +{ + static const char fn[] = "pdf_process_PNG_data"; + spng_info s_info; + pdf_image *image; + + image = &p->images[imageslot]; + + image->src.init = pdf_data_source_PNG_init; + image->src.fill = pdf_data_source_PNG_fill; + image->src.terminate = pdf_data_source_PNG_terminate; + image->src.private_data = (void *) image; + + if (spng_init(p, image, &s_info) == SPNG_ERR_OK && image->use_raw) + { + image->predictor = pred_png; + image->compression = pdf_comp_flate; /* CDPDF - fixed function name */ + + image->width = (pdc_scalar) s_info.width; + image->height = (pdc_scalar) s_info.height; + image->bpc = s_info.bit_depth; + + image->components = 3; + + /* other types are rejected in spng_init() */ + image->colorspace = + (s_info.color_type == 0 ? DeviceGray : DeviceRGB); + + + + } + else + { + pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "PNG", 0, 0, 0); + return -1; + } + + image->in_use = pdc_true; /* mark slot as used */ + + pdf_put_image(p, imageslot, pdc_true, pdc_true); + + return image->corrupt ? -1 : imageslot; +} + +#endif /* !HAVE_LIBPNG */ diff --git a/src/pdflib/pdflib/p_shading.c b/src/pdflib/pdflib/p_shading.c new file mode 100644 index 0000000..e027ce6 --- /dev/null +++ b/src/pdflib/pdflib/p_shading.c @@ -0,0 +1,381 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_shading.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib routines for smooth shading + * + */ + +#include "p_intern.h" +#include "p_color.h" + +typedef enum +{ + shnone = 0, + axial = 2, + radial = 3 +} pdf_shadingtype_e; + +struct pdf_shading_s { + pdc_id obj_id; /* object id of this shading */ + pdc_bool used_on_current_page; /* this shading used on current page */ +}; + +void +pdf_init_shadings(PDF *p) +{ + int i; + + p->shadings_number = 0; + p->shadings_capacity = SHADINGS_CHUNKSIZE; + + p->shadings = (pdf_shading *) pdc_malloc(p->pdc, + sizeof(pdf_shading) * p->shadings_capacity, "pdf_init_shadings"); + + for (i = 0; i < p->shadings_capacity; i++) { + p->shadings[i].used_on_current_page = pdc_false; + p->shadings[i].obj_id = PDC_BAD_ID; + } +} + +static void +pdf_grow_shadings(PDF *p) +{ + int i; + + p->shadings = (pdf_shading *) pdc_realloc(p->pdc, p->shadings, + sizeof(pdf_shading) * 2 * p->shadings_capacity, "pdf_grow_shadings"); + + for (i = p->shadings_capacity; i < 2 * p->shadings_capacity; i++) { + p->shadings[i].used_on_current_page = pdc_false; + p->shadings[i].obj_id = PDC_BAD_ID; + } + + p->shadings_capacity *= 2; +} + +void +pdf_write_page_shadings(PDF *p) +{ + int i, total = 0; + int bias = p->curr_ppt->sh_bias; + + for (i = 0; i < p->shadings_number; i++) + if (p->shadings[i].used_on_current_page) + total++; + + if (total > 0 || bias) + { + pdc_puts(p->out, "/Shading"); + pdc_begin_dict(p->out); + } + + if (total > 0) + { + for (i = 0; i < p->shadings_number; i++) + { + if (p->shadings[i].used_on_current_page) + { + p->shadings[i].used_on_current_page = pdc_false; /* reset */ + pdc_printf(p->out, "/Sh%d", bias + i); + pdc_objref(p->out, "", p->shadings[i].obj_id); + } + } + + if (!bias) + pdc_end_dict(p->out); + } +} + +void +pdf_get_page_shadings(PDF *p, pdf_reslist *rl) +{ + int i; + + for (i = 0; i < p->shadings_number; i++) { + if (p->shadings[i].used_on_current_page) { + p->shadings[i].used_on_current_page = pdc_false; /* reset */ + pdf_add_reslist(p, rl, i); + } + } +} + +void +pdf_mark_page_shading(PDF *p, int n) +{ + p->shadings[n].used_on_current_page = pdc_true; +} + +void +pdf_cleanup_shadings(PDF *p) +{ + if (p->shadings) { + pdc_free(p->pdc, p->shadings); + p->shadings = NULL; + } +} + +int +pdf_get_shading_painttype(PDF *p) +{ + return p->pattern[p->pattern_number - 1].painttype; +} + + +static const pdc_defopt pdf_shading_pattern_options[] = +{ + {"gstate", pdc_gstatehandle, 0, 1, 1, 0, 0, NULL}, + PDC_OPT_TERMINATE +}; + +int +pdf__shading_pattern(PDF *p, int shading, const char *optlist) +{ + pdc_resopt *results; + pdc_clientdata data; + int gstate = -1; + int retval = -1; + + if (p->compatibility == PDC_1_3) + pdc_error(p->pdc, PDF_E_SHADING13, 0, 0, 0, 0); + + pdf_check_handle(p, shading, pdc_shadinghandle); + + if (optlist && strlen(optlist)) { + pdf_set_clientdata(p, &data); + results = pdc_parse_optionlist(p->pdc, + optlist, pdf_shading_pattern_options, &data, pdc_true); + + (void) pdc_get_optvalues("gstate", results, &gstate, NULL); + + pdc_cleanup_optionlist(p->pdc, results); + } + + if (p->pattern_number == p->pattern_capacity) + pdf_grow_pattern(p); + + if (PDF_GET_STATE(p) == pdf_state_page) + pdf_end_contents_section(p); + + /* Pattern object */ + p->pattern[p->pattern_number].obj_id = pdc_begin_obj(p->out, PDC_NEW_ID); + + /* Shadings don't have a painttype, but this signals to the + * code which writes the pattern usage that no color values + * will be required when setting the pattern color space. + */ + p->pattern[p->pattern_number].painttype = 1; + + pdc_begin_dict(p->out); /* Pattern dict*/ + + pdc_puts(p->out, "/PatternType 2\n"); /* shading pattern */ + + pdc_objref(p->out, "/Shading", p->shadings[shading].obj_id); + + p->shadings[shading].used_on_current_page = pdc_true; + + if (gstate != -1) + pdc_objref(p->out, "/ExtGState", pdf_get_gstate_id(p, gstate)); + + pdc_end_dict(p->out); /* Pattern dict*/ + pdc_end_obj(p->out); /* Pattern object */ + + if (PDF_GET_STATE(p) == pdf_state_page) + pdf_begin_contents_section(p); + + retval = p->pattern_number; + p->pattern_number++; + return retval; +} + +void +pdf__shfill(PDF *p, int shading) +{ + int bias = p->curr_ppt->sh_bias; + + if (p->compatibility == PDC_1_3) + pdc_error(p->pdc, PDF_E_SHADING13, 0, 0, 0, 0); + + pdf_check_handle(p, shading, pdc_shadinghandle); + + pdf_end_text(p); + pdc_printf(p->out, "/Sh%d sh\n", bias + shading); + + p->shadings[shading].used_on_current_page = pdc_true; +} + +static const pdc_defopt pdf_shading_options[] = +{ + {"N", pdc_scalarlist, PDC_OPT_NOZERO, 1, 1, 0, PDC_FLOAT_MAX, NULL}, + {"r0", pdc_scalarlist, PDC_OPT_NONE, 1, 1, 0, PDC_FLOAT_MAX, NULL}, + {"r1", pdc_scalarlist, PDC_OPT_NONE, 1, 1, 0, PDC_FLOAT_MAX, NULL}, + {"extend0", pdc_booleanlist, PDC_OPT_NONE, 0, 1, 0, 1, NULL}, + {"extend1", pdc_booleanlist, PDC_OPT_NONE, 0, 1, 0, 0, NULL}, + {"antialias", pdc_booleanlist, PDC_OPT_NONE, 0, 1, 0, 0, NULL}, + PDC_OPT_TERMINATE +}; + +int +pdf__shading( + PDF *p, + const char *type, + pdc_scalar x_0, pdc_scalar y_0, + pdc_scalar x_1, pdc_scalar y_1, + pdc_scalar c_1, pdc_scalar c_2, pdc_scalar c_3, pdc_scalar c_4, + const char *optlist) +{ + pdf_shadingtype_e shtype = shnone; + pdf_color *color0, color1; + pdf_colorspace *cs; + pdc_resopt *results; + pdc_scalar N = 1.0; + pdc_scalar r_0, r_1; + pdc_bool extend0 = pdc_false, extend1 = pdc_false, antialias = pdc_false; + int retval = -1; + + if (p->compatibility == PDC_1_3) + pdc_error(p->pdc, PDF_E_SHADING13, 0, 0, 0, 0); + + if (!pdc_stricmp(type, "axial")) { + shtype = axial; + + } else if (!pdc_stricmp(type, "radial")) { + shtype = radial; + + } else + pdc_error(p->pdc, PDC_E_ILLARG_STRING, "type", type, 0, 0); + + pdc_check_number(p->pdc, "x_0", x_0); + pdc_check_number(p->pdc, "y_0", y_0); + pdc_check_number(p->pdc, "x_1", x_1); + pdc_check_number(p->pdc, "y_1", y_1); + pdc_check_number(p->pdc, "c_1", c_1); + pdc_check_number(p->pdc, "c_2", c_2); + pdc_check_number(p->pdc, "c_3", c_3); + pdc_check_number(p->pdc, "c_4", c_4); + + color0 = pdf_get_cstate(p, pdf_fill); + + color1.cs = color0->cs; + + cs = &p->colorspaces[color0->cs]; + + switch (cs->type) { + case DeviceGray: + color1.val.gray = c_1; + break; + + case DeviceRGB: + color1.val.rgb.r = c_1; + color1.val.rgb.g = c_2; + color1.val.rgb.b = c_3; + break; + + case DeviceCMYK: + color1.val.cmyk.c = c_1; + color1.val.cmyk.m = c_2; + color1.val.cmyk.y = c_3; + color1.val.cmyk.k = c_4; + break; + + + + default: + pdc_error(p->pdc, PDF_E_INT_BADCS, + pdc_errprintf(p->pdc, "%d", color0->cs), 0, 0, 0); + } + + results = pdc_parse_optionlist(p->pdc, + optlist, pdf_shading_options, NULL, pdc_true); + + (void) pdc_get_optvalues("N", results, &N, NULL); + + (void) pdc_get_optvalues("antialias", results, &antialias,NULL); + + if (shtype == radial) { + if (pdc_get_optvalues("r0", results, &r_0, NULL) != 1) + pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, "r0", 0, 0, 0); + + if (pdc_get_optvalues("r1", results, &r_1, NULL) != 1) + pdc_error(p->pdc, PDC_E_OPT_NOTFOUND, "r1", 0, 0, 0); + } + + if (shtype == axial) { + if (pdc_get_optvalues("r0", results, &r_0, NULL) == 1) + pdc_warning(p->pdc, PDC_E_OPT_IGNORED, "r0", 0, 0, 0); + + if (pdc_get_optvalues("r1", results, &r_1, NULL) == 1) + pdc_warning(p->pdc, PDC_E_OPT_IGNORED, "r1", 0, 0, 0); + } + + if (shtype == radial || shtype == axial) { + pdc_get_optvalues("extend0", results, &extend0, NULL); + pdc_get_optvalues("extend1", results, &extend1, NULL); + } + + pdc_cleanup_optionlist(p->pdc, results); + + if (p->shadings_number == p->shadings_capacity) + pdf_grow_shadings(p); + + if (PDF_GET_STATE(p) == pdf_state_page) + pdf_end_contents_section(p); + + /* Shading object */ + p->shadings[p->shadings_number].obj_id = pdc_begin_obj(p->out, PDC_NEW_ID); + + pdc_begin_dict(p->out); /* Shading dict*/ + + pdc_printf(p->out, "/ShadingType %d\n", (int) shtype); + + pdc_printf(p->out, "/ColorSpace"); + pdf_write_colorspace(p, color1.cs, pdc_false); + pdc_puts(p->out, "\n"); + + if (antialias) + pdc_printf(p->out, "/AntiAlias true\n"); + + switch (shtype) { + case axial: /* Type 2 */ + pdc_printf(p->out, "/Coords[%f %f %f %f]\n", x_0, y_0, x_1, y_1); + if (extend0 || extend1) + pdc_printf(p->out, "/Extend[%s %s]\n", + extend0 ? "true" : "false", extend1 ? "true" : "false"); + pdc_puts(p->out, "/Function"); + pdf_write_function_dict(p, color0, &color1, N); + break; + + case radial: /* Type 3 */ + pdc_printf(p->out, "/Coords[%f %f %f %f %f %f]\n", + x_0, y_0, r_0, x_1, y_1, r_1); + if (extend0 || extend1) + pdc_printf(p->out, "/Extend[%s %s]\n", + extend0 ? "true" : "false", extend1 ? "true" : "false"); + pdc_puts(p->out, "/Function"); + pdf_write_function_dict(p, color0, &color1, N); + break; + + default: + break; + } + + pdc_end_dict(p->out); /* Shading dict */ + pdc_end_obj(p->out); /* Shading object */ + + if (PDF_GET_STATE(p) == pdf_state_page) + pdf_begin_contents_section(p); + + retval = p->shadings_number; + p->shadings_number++; + return retval; +} diff --git a/src/pdflib/pdflib/p_subsett.c b/src/pdflib/pdflib/p_subsett.c new file mode 100644 index 0000000..47eece6 --- /dev/null +++ b/src/pdflib/pdflib/p_subsett.c @@ -0,0 +1,26 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_subsett.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib subsetting routines + * + */ + +#include <time.h> + +#include "p_intern.h" +#include "p_font.h" + +#include "ft_truetype.h" +#include "pc_md5.h" + diff --git a/src/pdflib/pdflib/p_table.c b/src/pdflib/pdflib/p_table.c new file mode 100644 index 0000000..dc45525 --- /dev/null +++ b/src/pdflib/pdflib/p_table.c @@ -0,0 +1,26 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_table.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib table function + * + */ + +#define P_TABLE_C + +#include "p_intern.h" +#include "p_color.h" +#include "p_defopt.h" +#include "p_font.h" +#include "p_tagged.h" + diff --git a/src/pdflib/pdflib/p_tagged.c b/src/pdflib/pdflib/p_tagged.c new file mode 100644 index 0000000..339b848 --- /dev/null +++ b/src/pdflib/pdflib/p_tagged.c @@ -0,0 +1,53 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_tagged.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib marked content routines + * + */ + +#define P_TAGGED_C + +#include "p_intern.h" +#include "p_layer.h" +#include "p_tagged.h" + + + + +#undef PDF_FEATURE_TAGGED + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/pdflib/pdflib/p_tagged.h b/src/pdflib/pdflib/p_tagged.h new file mode 100644 index 0000000..8dab696 --- /dev/null +++ b/src/pdflib/pdflib/p_tagged.h @@ -0,0 +1,25 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_tagged.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib marked content header + * + */ + +#ifndef P_TAGGED_H +#define P_TAGGED_H + + + +#endif /* P_TAGGED_H */ + diff --git a/src/pdflib/pdflib/p_template.c b/src/pdflib/pdflib/p_template.c new file mode 100644 index 0000000..b6a4f6d --- /dev/null +++ b/src/pdflib/pdflib/p_template.c @@ -0,0 +1,246 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_template.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib template routines + * + */ + +#define P_TEMPLATE_C + +#include "p_intern.h" +#include "p_image.h" + + +int +pdf_embed_image(PDF *p, int im) +{ + pdf_image *image = &p->images[im]; + char optlist[2048], *ol; + pdc_scalar width, height; + int templ; + + width = image->width; + height = fabs(image->height); + + /* create option list */ + optlist[0] = 0; + ol = optlist; + + + if (image->iconname) + sprintf(ol, "iconname {%s}", image->iconname); + + /* create template */ + templ = pdf__begin_template(p, width, height, optlist); + + /* fit image */ + sprintf(optlist, "boxsize {%g %g} fitmethod meet", width, height); + pdf__fit_image(p, im, 0, 0, optlist); + + /* end template */ + pdf__end_template(p); + + return templ; +} + +#define PDF_OPIOPT_FLAG PDC_OPT_UNSUPP + +#define PDF_METADATA_FLAG PDC_OPT_UNSUPP + +#define PDF_LAYER_FLAG PDC_OPT_UNSUPP + +/* definitions of begin template options */ +static const pdc_defopt pdf_begin_template_options[] = +{ + {"topdown", pdc_booleanlist, PDC_OPT_NONE, 1, 1, 0.0, 0.0, NULL}, + + {"OPI-1.3", pdc_stringlist, PDF_OPIOPT_FLAG, 1, 1, 0.0, 32000.0, NULL}, + + {"OPI-2.0", pdc_stringlist, PDF_OPIOPT_FLAG | PDC_OPT_IGNOREIF1, + 1, 1, 0.0, 32000.0, NULL}, + + {"iconname", pdc_stringlist, 0, 1, 1, 1.0, PDF_MAX_NAMESTRING, NULL}, + + {"metadata", pdc_stringlist, PDF_METADATA_FLAG, 1, 1, + 0.0, PDC_INT_MAX, NULL}, + + {"layer", pdc_layerhandle, PDF_LAYER_FLAG, 1, 1, + 0.0, 0.0, NULL}, + + PDF_ERRORPOLICY_OPTION + + PDC_OPT_TERMINATE +}; + +/* Start a new template definition. */ +int +pdf__begin_template(PDF *p, pdc_scalar width, pdc_scalar height, + const char *optlist) +{ + pdf_image *image; + pdc_resopt *resopts; + const char *keyword; + pdc_clientdata cdata; + pdc_bool topdown; + char *iconname = NULL; + pdc_bool verbose = pdc_true; + int im = -1; + + pdc_check_number_limits(p->pdc, "width", width, + PDC_FLOAT_PREC, PDC_FLOAT_MAX); + pdc_check_number_limits(p->pdc, "height", height, + PDC_FLOAT_PREC, PDC_FLOAT_MAX); + + for (im = 0; im < p->images_capacity; im++) + if (!p->images[im].in_use) /* found free slot */ + break; + + if (im == p->images_capacity) + pdf_grow_images(p); + + image = &p->images[im]; + image->verbose = pdf_get_errorpolicy(p, NULL, image->verbose); + image->topdown_save = (p->ydirection == -1) ? pdc_true : pdc_false; + topdown = image->topdown_save; + image->in_use = pdc_true; /* mark slot as used */ + + /* parsing optlist */ + pdf_set_clientdata(p, &cdata); + resopts = pdc_parse_optionlist(p->pdc, optlist, pdf_begin_template_options, + &cdata, pdc_true); + + /* save and check options */ + if (optlist && *optlist) + { + image->verbose = pdf_get_errorpolicy(p, resopts, image->verbose); + + keyword = "topdown"; + pdc_get_optvalues(keyword, resopts, &topdown, NULL); + + keyword = "iconname"; + if (pdc_get_optvalues(keyword, resopts, NULL, NULL)) + iconname = (char *) pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM); + + + + + pdc_cleanup_optionlist(p->pdc, resopts); + } + + verbose = image->verbose; + + + + + + p->ydirection = topdown ? -1 : 1; + pdf_pg_suspend(p); + PDF_SET_STATE(p, pdf_state_template); + + /* form xobject */ + image->no = pdf_new_xobject(p, form_xobject, PDC_NEW_ID); + image->width = width; + image->height = height; + + p->templ = im; /* remember the current template id */ + + pdc_begin_dict(p->out); /* form xobject dict*/ + pdc_puts(p->out, "/Type/XObject\n"); + pdc_puts(p->out, "/Subtype/Form\n"); + + /* contrary to the PDF reference /FormType and /Matrix are required! */ + pdc_printf(p->out, "/FormType 1\n"); + pdc_printf(p->out, "/Matrix[1 0 0 1 0 0]\n"); + + p->res_id = pdc_alloc_id(p->out); + pdc_objref(p->out, "/Resources", p->res_id); + + pdc_printf(p->out, "/BBox[0 0 %f %f]\n", width, height); + + + + + p->length_id = pdc_alloc_id(p->out); + pdc_objref(p->out, "/Length", p->length_id); + + if (pdc_get_compresslevel(p->out)) + pdc_puts(p->out, "/Filter/FlateDecode\n"); + + pdc_end_dict(p->out); /* form xobject dict*/ + + pdc_begin_pdfstream(p->out); + + /* top-down y-coordinates */ + pdf_set_topdownsystem(p, height); + + /* set color differing from PDF default */ + pdf_set_default_color(p, pdc_false); + + /* insert icon name */ + if (iconname) + { + pdc_id obj_id = pdf_get_xobject(p, im); + pdf_insert_name(p, iconname, names_ap, obj_id); + } + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[Begin template %d]\n", p->templ); + + return im; +} + +/* Finish the template definition. */ +void +pdf__end_template(PDF *p) +{ + pdf_image *image = &p->images[p->templ]; + + /* check whether pdf__save() and pdf__restore() calls are balanced */ + if (p->curr_ppt->sl > 0) + pdc_error(p->pdc, PDF_E_GSTATE_UNMATCHEDSAVE, 0, 0, 0, 0); + + pdf_end_text(p); + pdc_end_pdfstream(p->out); + pdc_end_obj(p->out); /* form xobject */ + + pdc_put_pdfstreamlength(p->out, p->length_id); + + pdc_begin_obj(p->out, p->res_id); /* Resource object */ + pdc_begin_dict(p->out); /* Resource dict */ + + pdf_write_page_fonts(p); /* Font resources */ + + pdf_write_page_colorspaces(p); /* Color space resources */ + + pdf_write_page_pattern(p); /* Pattern resources */ + + pdf_write_xobjects(p); /* XObject resources */ + + pdf_write_page_extgstates(p); /* ExtGState resources */ + + pdc_end_dict(p->out); /* resource dict */ + pdc_end_obj(p->out); /* resource object */ + + pdf_pg_resume(p, -1); + + if (p->flush & pdc_flush_content) + pdc_flush_stream(p->out); + + p->ydirection = image->topdown_save ? -1 : 1; + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[End template %d]\n", p->templ); +} + + diff --git a/src/pdflib/pdflib/p_text.c b/src/pdflib/pdflib/p_text.c new file mode 100644 index 0000000..105df11 --- /dev/null +++ b/src/pdflib/pdflib/p_text.c @@ -0,0 +1,3715 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_text.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib text routines + * + */ + +#define P_TEXT_C + +#include "p_intern.h" +#include "p_color.h" +#include "p_defopt.h" +#include "p_font.h" +#include "p_layer.h" +#include "p_tagged.h" + + +/* --------------------- Text state and options functions ------------------- */ + +struct pdf_tstate_s +{ + pdc_bool glyphinit; /* glyph description initialized */ + pdc_bool hsinit; /* horizontal scaling initialized */ + int mask; /* bit mask for text options */ + int font; /* slot number of the current font */ + int trm; /* text rendering mode */ + pdc_scalar fs; /* font size */ + pdc_scalar ld; /* leading */ + pdc_scalar cs; /* character spacing */ + pdc_scalar ws; /* word spacing */ + pdc_scalar hs; /* horizontal scaling */ + pdc_scalar ia; /* italic angle */ + pdc_bool fb; /* fake bold */ + pdc_scalar rise; /* text rise */ + pdc_scalar ulw; /* underline width */ + pdc_scalar ulp; /* underline position */ + + pdc_bool newpos; /* new text position */ + pdc_scalar currtx; /* x coordinate of current text position */ + pdc_scalar currty; /* y coordinate of current text position */ + pdc_scalar prevtx; /* x coordinate of previous text position */ + pdc_scalar prevty; /* y coordinate of previous text position */ + pdc_scalar linetx; /* x coordinate of text line start position */ + pdc_scalar refptx; /* x and y coordinate of reference position */ + pdc_scalar refpty; /* for moving to next text line start position*/ +}; + +/* Initialize the text state at the beginning of each page */ +void +pdf_init_tstate(PDF *p) +{ + static const char fn[] = "pdf_init_tstate"; + + /* text state */ + pdf_ppt *ppt = p->curr_ppt; + pdf_tstate *ts; + + if (!p->curr_ppt->tstate) + { + p->curr_ppt->tstate = (pdf_tstate *) pdc_malloc(p->pdc, + PDF_MAX_SAVE_LEVEL * sizeof(pdf_tstate), fn); + ppt->currto = (pdf_text_options *) pdc_malloc(p->pdc, + sizeof(pdf_text_options), fn); + } + + ts = &ppt->tstate[ppt->sl]; + + ts->glyphinit = pdc_undef; + ts->hsinit = (p->ydirection == -1) ? pdc_false : pdc_true; + + ts->mask = 0; + ts->font = -1; + ts->trm = 0; + ts->fs = PDC_FLOAT_MIN; + ts->ld = 0; + ts->cs = 0; + ts->ws = 0; + ts->hs = 1; + ts->ia = 0; + ts->fb = pdc_false; + ts->rise = 0; + ts->ulw = PDF_UNDERLINEWIDTH_AUTO; + ts->ulp = PDF_UNDERLINEPOSITION_AUTO; + + ts->newpos = pdc_false; + ts->currtx = 0; + ts->currty = 0; + ts->prevtx = 0; + ts->prevty = 0; + ts->linetx = 0; + ts->refptx = 0; + ts->refpty = 0; + + /* current text options */ + pdf_init_text_options(p, ppt->currto); +} + +void +pdf_cleanup_page_tstate(PDF *p, pdf_ppt *ppt) +{ + if (ppt->tstate != NULL) + { + pdc_free(p->pdc, ppt->tstate); + pdc_free(p->pdc, ppt->currto); + ppt->tstate = NULL; + ppt->currto = NULL; + } +} + +void +pdf_save_tstate(PDF *p) +{ + pdf_ppt *ppt = p->curr_ppt; + int sl = ppt->sl; + + memcpy(&ppt->tstate[sl + 1], &ppt->tstate[sl], sizeof(pdf_tstate)); +} + +void +pdf_restore_currto(PDF *p) +{ + pdf_ppt *ppt = p->curr_ppt; + pdf_text_options *currto = ppt->currto; + pdf_tstate *ts = &ppt->tstate[ppt->sl]; + + currto->mask = ts->mask; + currto->font = ts->font; + currto->textrendering = ts->trm; + currto->fontsize = ts->fs; + currto->leading = ts->ld; + currto->charspacing = ts->cs; + currto->wordspacing = ts->ws; + currto->horizscaling = ts->hs; + currto->italicangle = ts->ia; + currto->fakebold = ts->fb; + currto->textrise = ts->rise; + currto->underlinewidth = ts->ulw; + currto->underlineposition = ts->ulp; +} + +void +pdf_set_tstate(PDF *p, pdc_scalar value, pdf_text_optflags tflag) +{ + pdf_ppt *ppt = p->curr_ppt; + pdf_tstate *ts = &ppt->tstate[ppt->sl]; + pdf_text_options *currto = ppt->currto; + int ivalue = (int) value; + pdc_scalar prevvalue; + + /* text state parameter values can never be percentages */ + + switch (tflag) + { + case to_font: + pdf_check_handle(p, ivalue, pdc_fonthandle); + prevvalue = ts->font; + ts->font = currto->font = ivalue; + if (prevvalue != -1 && + (p->fonts[(int) prevvalue].metricflags & font_italic) != + (p->fonts[currto->font].metricflags & font_italic)) + currto->mask |= (1 << to_italicangle); + break; + + case to_textrendering: + if (ivalue < 0 || ivalue > PDF_LAST_TRMODE) + pdc_error(p->pdc, PDC_E_ILLARG_INT, + "textrendering", pdc_errprintf(p->pdc, "%d", ivalue), + 0, 0); + prevvalue = ts->trm; + ts->trm = currto->textrendering = ivalue; + break; + + case to_fontsize: + pdc_check_number_zero(p->pdc, "fontsize", value); + prevvalue = ts->ld; + ts->ld = currto->leading = value; + if (!PDC_FLOAT_ISNULL(value - prevvalue)) + currto->mask |= (1 << to_leading); + prevvalue = ts->fs; + ts->fs = currto->fontsize = value; + break; + + case to_leading: + prevvalue = ts->ld; + ts->ld = currto->leading = value; + break; + + case to_charspacing: + prevvalue = ts->cs; + ts->cs = currto->charspacing = value; + break; + + case to_wordspacing: + prevvalue = ts->ws; + ts->ws = currto->wordspacing = value; + break; + + case to_underlinewidth: + prevvalue = ts->ulw; + ts->ulw = currto->underlinewidth = value; + break; + + case to_underlineposition: + prevvalue = ts->ulp; + ts->ulp = currto->underlineposition = value; + break; + + case to_horizscaling: + pdc_check_number_zero(p->pdc, "horizscaling", value); + prevvalue = ts->hs; + ts->hs = currto->horizscaling = value; + break; + + case to_italicangle: + pdc_check_number_limits(p->pdc, "italicangle", value, + -90 + PDC_FLOAT_PREC, 90 + PDC_FLOAT_MAX); + prevvalue = ts->ia; + ts->ia = currto->italicangle = value; + break; + + case to_fakebold: + prevvalue = ts->fb; + ts->fb = currto->fakebold = (pdc_bool) ivalue; + return; + + case to_textrise: + prevvalue = ts->rise; + ts->rise = currto->textrise = value; + break; + + + case to_overline: + currto->overline = (pdc_bool) ivalue; + return; + + case to_strikeout: + currto->strikeout = (pdc_bool) ivalue; + return; + + case to_underline: + currto->underline = (pdc_bool) ivalue; + return; + + case to_textformat: + currto->textformat = (pdc_text_format) ivalue; + return; + + case to_charref: + currto->charref = (pdc_bool) ivalue; + return; + + case to_escapesequence: + currto->escapesequence = (pdc_bool) ivalue; + return; + + case to_glyphcheck: + currto->glyphcheck = (pdc_glyphcheck) ivalue; + return; + + case to_glyphwarning: + currto->glyphwarning = (pdc_bool) ivalue; + return; + + default: + return; + } + + if (!PDC_FLOAT_ISNULL(value - prevvalue)) + currto->mask |= (1 << tflag); + ts->mask = currto->mask; +} + +void +pdf__setfont(PDF *p, int font, pdc_scalar fontsize) +{ + pdf_set_tstate(p, (pdc_scalar) font, to_font); + pdf_set_tstate(p, fontsize, to_fontsize); +} + +void +pdf__set_text_pos(PDF *p, pdc_scalar x, pdc_scalar y) +{ + pdf_ppt *ppt = p->curr_ppt; + pdf_tstate *ts = &ppt->tstate[ppt->sl]; + + pdc_check_number(p->pdc, "x", x); + pdc_check_number(p->pdc, "y", y); + + ts->newpos = pdc_true; + ts->currtx = x; + ts->currty = y; + ts->prevtx = ts->refptx; + ts->prevty = ts->refpty; + ts->linetx = x; +} + +double +pdf_get_tstate(PDF *p, pdf_text_optflags tflag) +{ + pdf_ppt *ppt = p->curr_ppt; + pdf_text_options *currto = ppt->currto; + + switch (tflag) + { + case to_font: + return (double) currto->font; + + case to_textrendering: + return (double) currto->textrendering; + + case to_fontsize: + return (double) currto->fontsize; + + case to_leading: + return (double) currto->leading; + + case to_charspacing: + return (double) currto->charspacing; + + case to_wordspacing: + return (double) currto->wordspacing; + + case to_horizscaling: + return (double) currto->horizscaling; + + case to_italicangle: + return (double) currto->italicangle; + + case to_fakebold: + return (double) currto->fakebold; + + case to_textrise: + return (double) currto->textrise; + + case to_underlinewidth: + return (double) currto->underlinewidth; + + case to_underlineposition: + return (double) currto->underlineposition; + + + case to_overline: + return (double) currto->overline; + + case to_strikeout: + return (double) currto->strikeout; + + case to_underline: + return (double) currto->underline; + + case to_textx: + return (double) ppt->tstate[ppt->sl].currtx; + + case to_texty: + return (double) ppt->tstate[ppt->sl].currty; + + default: + break; + } + + return 0; +} + +int +pdf_get_font(PDF *p) +{ + if (p->curr_ppt) + return (int) pdf_get_tstate(p, to_font); + return -1; +} + +void +pdf_init_text_options(PDF *p, pdf_text_options *to) +{ + to->mask = 0; + to->pcmask = 0; + to->font = -1; + to->fontsize = PDC_FLOAT_MIN; + to->fontsize_pc = 0; + to->fontsize_st = (int) text_fontsize; + to->fontset = 0; + to->leading = 0; + to->leading_pc = 0; + to->textrendering = 0; + to->charspacing = 0; + to->charspacing_pc = 0; + to->horizscaling = 1; + to->italicangle = 0; + to->fakebold = pdc_false; + to->textrise = 0; + to->textrise_pc = 0; + to->wordspacing = 0; + to->wordspacing_pc = 0; + to->underlinewidth = PDF_UNDERLINEWIDTH_AUTO; + to->underlineposition = PDF_UNDERLINEPOSITION_AUTO; + to->overline = pdc_false; + to->strikeout = pdc_false; + to->underline = pdc_false; + to->text = NULL; + to->textlen = 0; + to->textformat = p->textformat; + to->charref = p->pdc->charref; + to->escapesequence = p->pdc->escapesequ; + to->glyphcheck = p->glyphcheck; + to->glyphwarning = p->debug[(int) 'g']; + to->glyphwarning = pdf_get_errorpolicy(p, NULL, to->glyphwarning); + pdf_init_coloropt(p, &to->fillcolor); + pdf_init_coloropt(p, &to->strokecolor); + to->strokewidth = PDF_UNDERLINEWIDTH_AUTO; + to->dasharray[0] = 0; + to->dasharray[1] = 0; + to->xadvancelist = NULL; + to->nglyphs = 0; + to->link = NULL; +} + +static pdf_text_optflags pdf_toptflags[] = +{ + to_font, to_fontsize, to_textrendering, to_charspacing, + to_horizscaling, to_italicangle, to_wordspacing, to_textrise +}; + +void +pdf_set_text_options(PDF *p, pdf_text_options *to) +{ + pdf_ppt *ppt = p->curr_ppt; + pdf_text_options *currto = p->curr_ppt->currto; + pdf_tstate *ts = &ppt->tstate[ppt->sl]; + pdf_text_optflags tflag; + int i, n; + + /* we synchronize both text state and text options */ + + n = sizeof(pdf_toptflags) / sizeof(pdf_text_optflags); + for (i = 0; i < n; i++) + { + tflag = pdf_toptflags[i]; + if (to->mask & (1 << tflag)) + { + switch (tflag) + { + case to_font: + if (!(currto->mask & (1 << tflag)) && + to->font == currto->font) + break; + ts->font = currto->font = to->font; + continue; + + case to_fontsize: + if (!(currto->mask & (1 << tflag)) && + PDC_FLOAT_ISNULL(to->fontsize - currto->fontsize)) + break; + ts->fs = currto->fontsize = to->fontsize; + continue; + + case to_textrendering: + if (!(currto->mask & (1 << tflag)) && + to->textrendering == currto->textrendering) + break; + ts->trm = currto->textrendering = to->textrendering; + continue; + + /* to->leading is never used */ + + case to_charspacing: + if (!(currto->mask & (1 << tflag)) && + PDC_FLOAT_ISNULL(to->charspacing - currto->charspacing)) + break; + ts->cs = currto->charspacing = to->charspacing; + continue; + + case to_horizscaling: + if (!(currto->mask & (1 << tflag)) && + PDC_FLOAT_ISNULL(to->horizscaling - currto->horizscaling)) + break; + ts->hs = currto->horizscaling = to->horizscaling; + continue; + + case to_italicangle: + if (!(currto->mask & (1 << tflag)) && + PDC_FLOAT_ISNULL(to->italicangle - currto->italicangle)) + break; + ts->ia = currto->italicangle = to->italicangle; + continue; + + case to_fakebold: + ts->fb = currto->fakebold = to->fakebold; + continue; + + case to_wordspacing: + if (!(currto->mask & (1 << tflag)) && + PDC_FLOAT_ISNULL(to->wordspacing - currto->wordspacing)) + break; + ts->ws = currto->wordspacing = to->wordspacing; + continue; + + case to_textrise: + if (!(currto->mask & (1 << tflag)) && + PDC_FLOAT_ISNULL(to->textrise - currto->textrise)) + break; + ts->rise = currto->textrise = to->textrise; + continue; + + case to_underlinewidth: + if (!(currto->mask & (1 << tflag)) && + PDC_FLOAT_ISNULL(to->underlinewidth - + currto->underlinewidth)) + break; + ts->ulw = currto->underlinewidth = to->underlinewidth; + continue; + + case to_underlineposition: + if (!(currto->mask & (1 << tflag)) && + PDC_FLOAT_ISNULL(to->underlineposition - + currto->underlineposition)) + break; + ts->ulp = currto->underlineposition = to->underlineposition; + continue; + + default: + continue; + } + + to->mask &= ~(1 << tflag); + } + } + + ts->mask = currto->mask = to->mask; +} + +int +pdf_get_fontsize_option(PDF *p, int font, pdc_resopt *resopts, + pdc_scalar *fontsize) +{ + pdc_scalar fs[2], fm ; + int ns; + + /* *fontsize is initialized from outside */ + + fs[0] = 0; /* see "auto" */ + fs[1] = 0; + ns = pdc_get_optvalues("fontsize", resopts, (pdc_scalar *) fs, NULL); + if (ns == 1) + { + *fontsize = fs[0]; + } + else if (ns == 2) + { + int kind = (int) fs[0]; + + pdf_check_handle(p, font, pdc_fonthandle); + + switch(kind) + { + case text_xheight: + fm = (pdc_scalar) p->fonts[font].ft.m.xHeight; + break; + + case text_capheight: + fm = (pdc_scalar) p->fonts[font].ft.m.capHeight; + break; + + case text_ascender: + fm = (pdc_scalar) p->fonts[font].ft.m.ascender; + break; + + default: + fm = 1000.0; + break; + } + + *fontsize = fs[1] * 1000.0 / fm; + } + + return ns; +} + +pdc_bool +pdf_calculate_text_options(PDF *p, pdf_text_options *to, pdc_bool force, + pdc_scalar fontscale, pdc_scalar minfontsize, + pdc_scalar fontsizeref) +{ + pdc_bool kminfs = pdc_false; + + if (to->mask & (1 << to_fontsize) || force) + { + pdc_scalar fontsize; + + if (fontsizeref == 0) + fontsizeref = to->fontsize; + + if (to->pcmask & (1 << to_fontsize)) + fontsize = to->fontsize_pc * fontsizeref; + else + fontsize = fontscale * to->fontsize; + + if (to->fontsize_st != (int) text_fontsize) + { + pdf_font *currfont = &p->fonts[to->font]; + pdc_scalar fm; + + switch(to->fontsize_st) + { + case text_xheight: + fm = (pdc_scalar) currfont->ft.m.xHeight; + break; + + case text_capheight: + fm = (pdc_scalar) currfont->ft.m.capHeight; + break; + + case text_ascender: + fm = (pdc_scalar) currfont->ft.m.ascender; + break; + + default: + fm = 1000.0; + break; + } + + fontsize *= 1000.0 / fm; + } + + if (fontscale < 1.0 && fabs(fontsize) < minfontsize) + { + if (fontsize > 0) + fontsize = minfontsize; + else + fontsize = -minfontsize; + kminfs = pdc_true; + } + to->fontsize = fontsize; + + /* we reset relative fontsize specifications */ + if (to->mask & (1L << to_fontsize)) + { + to->pcmask &= ~(1 << to_fontsize); + to->fontsize_st = (int) text_fontsize; + } + } + + if ((to->mask & (1 << to_charspacing) || force) && + (to->pcmask & (1 << to_charspacing))) + { + to->charspacing = to->charspacing_pc * to->fontsize; + } + + if ((to->mask & (1 << to_wordspacing) || force) && + (to->pcmask & (1 << to_wordspacing))) + { + to->wordspacing = to->wordspacing_pc * to->fontsize; + } + + if ((to->mask & (1 << to_textrise) || force) && + (to->pcmask & (1 << to_textrise))) + { + to->textrise = to->textrise_pc * to->fontsize; + } + + /* maybe used in a future version */ + if ((to->mask & (1 << to_leading) || force) && + (to->pcmask & (1 << to_leading))) + { + to->leading = to->leading_pc * to->fontsize; + } + + return kminfs; +} + +void +pdf_get_text_options(PDF *p, pdf_text_options *to, pdc_resopt *resopts) +{ + char **strlist; + int i, inum; + pdc_scalar fs[2]; + + if (pdc_get_optvalues("glyphwarning", resopts, &to->glyphwarning, NULL)) + to->mask |= (1L << to_glyphwarning); + to->glyphwarning = pdf_get_errorpolicy(p, resopts, to->glyphwarning); + + if (pdc_get_optvalues("font", resopts, &to->font, NULL)) + { + pdf_check_handle(p, to->font, pdc_fonthandle); + to->mask |= (1L << to_font); + to->fontset |= (1L << to_font); + } + + fs[0] = 0; /* see "auto" */ + fs[1] = 0; + inum = pdc_get_optvalues("fontsize", resopts, (pdc_scalar *) fs, NULL); + if (inum) + { + i = inum - 1; + to->fontsize = fs[i]; + if (inum == 2) + to->fontsize_st = (int) fs[0]; + else + to->fontsize_st = (int) text_fontsize; + to->mask |= (1L << to_fontsize); + to->mask |= (1L << to_fontsize_st); + + if (pdc_is_lastopt_percent(resopts, i)) + { + to->pcmask |= (1 << to_fontsize); + to->fontsize_pc = to->fontsize; + } + else + to->pcmask &= ~(1 << to_fontsize); + + to->fontset |= (1L << to_fontsize); + } + + if (pdc_get_optvalues("charref", resopts, &to->charref, NULL)) + to->mask |= (1L << to_charref); + + if (pdc_get_optvalues("escapesequence", resopts, &to->escapesequence, NULL)) + to->mask |= (1L << to_escapesequence); + + if (pdc_get_optvalues("glyphcheck", resopts, &inum, NULL)) + { + to->glyphcheck = (pdc_glyphcheck) inum; + to->mask |= (1L << to_glyphcheck); + } + + if (pdc_get_optvalues("charspacing", resopts, &to->charspacing, NULL)) + { + if (pdc_is_lastopt_percent(resopts, 0)) + { + to->pcmask |= (1 << to_charspacing); + to->charspacing_pc = to->charspacing; + } + else + to->pcmask &= ~(1 << to_charspacing); + to->mask |= (1L << to_charspacing); + } + + if (pdc_get_optvalues("horizscaling", resopts, &to->horizscaling, NULL)) + { + if (!pdc_is_lastopt_percent(resopts, 0)) + to->horizscaling /= 100.0; + to->mask |= (1L << to_horizscaling); + } + + if (pdc_get_optvalues("italicangle", resopts, &to->italicangle, NULL)) + to->mask |= (1L << to_italicangle); + + if (pdc_get_optvalues("fakebold", resopts, &to->fakebold, NULL)) + to->mask |= (1L << to_fakebold); + + + if (pdc_get_optvalues("overline", resopts, &to->overline, NULL)) + to->mask |= (1L << to_overline); + + if (pdc_get_optvalues("strikeout", resopts, &to->strikeout, NULL)) + to->mask |= (1L << to_strikeout); + + if (pdc_get_optvalues("textformat", resopts, &inum, NULL)) + { + to->textformat = (pdc_text_format) inum; + to->mask |= (1L << to_textformat); + pdf_check_textformat(p, to->textformat); + } + + if (pdc_get_optvalues("textrendering", resopts, &to->textrendering, NULL)) + to->mask |= (1L << to_textrendering); + + if (pdc_get_optvalues("textrise", resopts, &to->textrise, NULL)) + { + if (pdc_is_lastopt_percent(resopts, 0)) + { + to->pcmask |= (1 << to_textrise); + to->textrise_pc = to->textrise; + } + else + to->pcmask &= ~(1 << to_textrise); + to->mask |= (1L << to_textrise); + } + + if (pdc_get_optvalues("underline", resopts, &to->underline, NULL)) + to->mask |= (1L << to_underline); + + if (pdc_get_optvalues("wordspacing", resopts, &to->wordspacing, NULL)) + { + if (pdc_is_lastopt_percent(resopts, 0)) + { + to->pcmask |= (1 << to_wordspacing); + to->wordspacing_pc = to->wordspacing; + } + else + to->pcmask &= ~(1 << to_wordspacing); + to->mask |= (1L << to_wordspacing); + } + + if (pdc_get_optvalues("underlinewidth", resopts, &to->underlinewidth, NULL)) + { + if (pdc_is_lastopt_percent(resopts, 0)) + { + to->pcmask |= (1 << to_underlinewidth); + } + else + to->pcmask &= ~(1 << to_underlinewidth); + to->mask |= (1L << to_underlinewidth); + } + + if (pdc_get_optvalues("underlineposition", resopts, + &to->underlineposition, NULL)) + { + if (pdc_is_lastopt_percent(resopts, 0)) + { + to->pcmask |= (1 << to_underlineposition); + } + else + to->pcmask &= ~(1 << to_underlineposition); + to->mask |= (1L << to_underlineposition); + } + + inum = pdc_get_optvalues("fillcolor", resopts, NULL, &strlist); + if (inum) + { + pdf_parse_coloropt(p, "fillcolor", strlist, inum, (int) color_max, + &to->fillcolor); + to->mask |= (1L << to_fillcolor); + } + + inum = pdc_get_optvalues("strokecolor", resopts, NULL, &strlist); + if (inum) + { + pdf_parse_coloropt(p, "strokecolor", strlist, inum, (int) color_max, + &to->strokecolor); + to->mask |= (1L << to_strokecolor); + } + + if (pdc_get_optvalues("strokewidth", resopts, &to->strokewidth, NULL)) + { + if (pdc_is_lastopt_percent(resopts, 0)) + { + to->pcmask |= (1 << to_strokewidth); + } + else + to->pcmask &= ~(1 << to_strokewidth); + to->mask |= (1L << to_strokewidth); + } + + inum = pdc_get_optvalues("dasharray", resopts, to->dasharray, NULL); + if (inum) + { + if (inum == 1) + to->dasharray[1] = to->dasharray[0]; + to->mask |= (1L << to_dasharray); + } + + inum = pdc_get_optvalues("xadvancelist", resopts, NULL, &strlist); + if (inum) + { + to->xadvancelist = (pdc_scalar *) strlist; + to->nglyphs = inum; + } + + /* + * deprecated + */ + if (pdc_get_optvalues("weblink", resopts, NULL, &strlist)) + { + to->link = strlist[0]; + to->linktype = "URI"; + } + else if (pdc_get_optvalues("locallink", resopts, NULL, &strlist)) + { + to->link = strlist[0]; + to->linktype = "GoTo"; + } + else if (pdc_get_optvalues("pdflink", resopts, NULL, &strlist)) + { + to->link = strlist[0]; + to->linktype = "GoToR"; + } +} + +/* ------------------------ Text object functions -------------------------- */ + +static void +pdf_begin_text(PDF *p) +{ + pdf_ppt *ppt = p->curr_ppt; + pdf_tstate *ts = &ppt->tstate[ppt->sl]; + pdf_text_options *currto = ppt->currto; + pdf_font *currfont = NULL; + + if (currto->font > -1) + currfont = &p->fonts[currto->font]; + + /* end text object if italicangle changed */ + if (currto->mask & (1L << to_italicangle)) + pdf_end_text(p); + + /* begin text object */ + if (!p->in_text) + { + p->in_text = pdc_true; + pdc_puts(p->out, "BT\n"); + } + + if (PDF_FORCE_OUTPUT() && ts->glyphinit == pdc_undef) + ts->glyphinit = pdc_false; + + if (currfont && + ((currto->mask & (1L << to_font)) || + (currto->mask & (1L << to_fontsize)) || !ts->glyphinit)) + { + pdc_printf(p->out, "/F%d %f Tf\n", + ppt->fn_bias + currto->font, p->ydirection * currto->fontsize); + + currfont->used_in_current_doc = pdc_true; + currfont->used_on_current_page = pdc_true; + } + + if (currto->mask & (1L << to_textrendering) || !ts->glyphinit) + pdc_printf(p->out, "%d Tr\n", currto->textrendering); + + if (currto->mask & (1L << to_leading) || !ts->glyphinit) + pdc_printf(p->out, "%f TL\n", p->ydirection * currto->leading); + + if (currto->mask & (1L << to_charspacing) || !ts->glyphinit) + pdc_printf(p->out, "%f Tc\n", p->ydirection * currto->charspacing); + + if (!ts->hsinit || currto->mask & (1L << to_horizscaling) || !ts->glyphinit) + pdc_printf(p->out, "%f Tz\n", + 100 * p->ydirection * currto->horizscaling); + + if (currto->mask & (1L << to_textrise) || !ts->glyphinit) + pdc_printf(p->out, "%f Ts\n", p->ydirection * currto->textrise); + + /* initialize */ + if (!ts->glyphinit) + ts->glyphinit = pdc_true; + ts->hsinit = pdc_true; + ts->mask = currto->mask = 0; +} + +void +pdf_end_text(PDF *p) +{ + pdf_ppt *ppt = p->curr_ppt; + pdf_tstate *ts = &ppt->tstate[ppt->sl]; + + if (p->in_text) + { + p->in_text = pdc_false; + pdc_puts(p->out, "ET\n"); + + ts->newpos = pdc_false; + ts->prevtx = 0; + ts->prevty = 0; + ts->refptx = 0; + ts->refpty = 0; + } +} + +void +pdf_reset_tstate(PDF *p) +{ + pdf_ppt *ppt = p->curr_ppt; + pdf_tstate *ts = &ppt->tstate[ppt->sl]; + + pdf_set_tstate(p, 0, to_textrendering); + pdf_set_tstate(p, 0, to_leading); + pdf_set_tstate(p, 0, to_charspacing); + pdf_set_tstate(p, 0, to_wordspacing); + pdf_set_tstate(p, 1, to_horizscaling); + pdf_set_tstate(p, 0, to_italicangle); + pdf_set_tstate(p, 0, to_fakebold); + pdf_set_tstate(p, 0, to_textrise); + pdf_set_tstate(p, PDF_UNDERLINEWIDTH_AUTO, to_underlinewidth); + pdf_set_tstate(p, PDF_UNDERLINEPOSITION_AUTO, to_underlineposition); + + ts->hsinit = (p->ydirection == -1) ? pdc_false : pdc_true; + if (ts->mask || !ts->hsinit) + { + pdc_scalar ydirection = p->ydirection; + p->ydirection = 1; + pdf_begin_text(p); + pdf_end_text(p); + p->ydirection = ydirection; + } +} + + +/* ------------------- Text string checking function ---------------------- */ + +typedef struct pdf_ligat_s pdf_ligat; + +struct pdf_ligat_s +{ + pdf_ligat *next; + int icp; /* text position */ + int nb; /* number of parts */ + pdc_byte culist[2 * PDC_MAX_UVLIST]; + /* ligature parts */ +}; + +static pdf_ligat * +pdf_register_ligat(PDF *p, pdf_ligat *ligatlist, int icp, int nv, + pdc_ushort *culist, int charlen) +{ + static const char fn[] = "pdf_hook_ligat"; + int i; + + pdf_ligat *ligat = + (pdf_ligat *) pdc_malloc_tmp(p->pdc, sizeof(pdf_ligat), fn, NULL, NULL); + + if (ligatlist == NULL) + { + ligatlist = ligat; + } + else + { + pdf_ligat *next = ligatlist; + + while (next->next != NULL) + next = next->next; + next->next = ligat; + } + + ligat->next = NULL; + ligat->icp = charlen * icp; + nv--; + ligat->nb = charlen * nv; + + if (charlen == 1) + { + for (i = 0; i < nv; i++) + ligat->culist[i] = (pdc_byte) culist[i+1]; + } + else + { + memcpy(ligat->culist, &culist[1], (size_t) ligat->nb); + } + return ligatlist; +} + +static void +pdf_cleanup_ligat(PDF *p, pdf_ligat *list) +{ + pdf_ligat *next; + + while (list != NULL) + { + next = list->next; + pdc_free_tmp(p->pdc, list); + list = next; + } +} + + +#define PDF_MAX_GLYPHCHECKS 8 + +int +pdf_get_approximate_uvlist(PDF *p, pdf_font *currfont, pdc_encodingvector *ev, + int usv, pdc_bool replace, + pdc_ushort *uvlist, pdc_ushort *cglist) +{ + int cg = 0, nv = 1; + + (void) p; + (void) ev; + (void) usv; + + + if (cg <= 0) + { + if (replace) + { + cglist[0] = (pdc_ushort) currfont->replacementcode; + uvlist[0] = (pdc_ushort) currfont->replacementchar; + } + else + { + cglist[0] = 0; + uvlist[0] = 0; + } + nv = 1; + } + + return nv; +} + +static void +pdf_logg_glyph_replacement(PDF *p, int ic, int code, + pdc_encoding enc, int charlen, + pdc_ushort *uvlist, pdc_ushort *cglist, int nv) +{ + const char *glyphname; + int i; + + pdc_logg(p->pdc, "\t\tat text position %d: ", ic); + + if (charlen == 1) + pdc_logg(p->pdc, "code x%02X ", code); + else + pdc_logg(p->pdc, "U+%04X ", code); + + pdc_logg(p->pdc, "was replaced by: "); + if (nv > 1) + pdc_logg(p->pdc, "\n"); + + for (i = 0; i < nv; i++) + { + if (nv > 1) + pdc_logg(p->pdc, "\t\t\t"); + + if (charlen == 1) + pdc_logg(p->pdc, "code x%02X ", cglist[i]); + else + pdc_logg(p->pdc, "U+%04X ", uvlist[i]); + + if (enc >= 0) + { + if (charlen == 1) + pdc_logg(p->pdc, "U+%04X ", uvlist[i]); + else + pdc_logg(p->pdc, "code x%02X ", cglist[i]); + } + + glyphname = pdc_unicode2glyphname(p->pdc, uvlist[i]); + if (glyphname && strlen(glyphname)) + pdc_logg(p->pdc, "\"%s\"", glyphname); + + pdc_logg(p->pdc, "\n"); + } +} + +void +pdf_get_input_textformat(pdf_font *currfont, + pdc_text_format *intextformat, int *convflags) +{ + /* input text format */ + if (currfont->unibyte) + { + /* encoding=unicode, but 8-bit encoding ev is available */ + *convflags |= PDC_CONV_FORCEUTF16; + } + else if (currfont->codesize <= 1) + { + /* we must force bytes[2] source input format + * for 8-bit encodings because of "pass through mode". + */ + if (*intextformat == pdc_auto) + *intextformat = pdc_bytes; + else if (*intextformat == pdc_auto2) + *intextformat = pdc_bytes2; + } +} + +/* Converts and checks input text string. + * + * The function returns a pointer to an allocated temporary memory + * (pdc_malloc_tmp, pdc_free_tmp) containing the converted string + * if flag PDF_USE_TMPALLOC is set. + * + * If return value is -1 an error was occurred, otherwise >= 0. + * glyphcheck = none: the number of unmapped glyphs will be returned. + * + */ + +int +pdf_check_textstring(PDF *p, const char *text, int len, int flags, + pdf_text_options *to, pdc_byte **outtext_p, int *outlen, + int *outcharlen, pdc_bool verbose) +{ + static const char fn[] = "pdf_check_textstring"; + + pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_text); + pdc_bool logg2 = pdc_false; + pdf_font *currfont = &p->fonts[to->font]; + pdc_encoding enc = currfont->ft.enc; + pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc); + pdc_encodingvector *inev = NULL; + pdc_encodingvector *outev = NULL; + + pdc_text_format intextformat = to->textformat; + pdc_text_format outtextformat = pdc_utf16; + + int charlen = 1, newcharlen = 1; + int convflags = PDC_CONV_NOBOM; + int unmapgids = 0; + + pdf_ligat *ligat, *ligatlist = NULL; + pdc_byte *intext = (pdc_byte *) text, *outtext = NULL; + int newlen = -1, maxlen, replchar; + + if (logg1) + { + logg2 = pdc_logg_is_enabled(p->pdc, 2, trc_text); + + if (logg2) + pdc_logg_hexdump(p->pdc, "input text", "\t\t", (char *) text, len); + else + pdc_logg(p->pdc, + "\tText will be checked and converted: \"%T\"\n", text, len); + + if (logg2) + { + pdc_logg(p->pdc, + "\t\tfont: \"%s\"\n" + "\t\tencoding: \"%s\"\n" + "\t\ttextformat: %s\n" + "\t\tcharref: %s\n" + "\t\tescapesequence: %s\n" + "\t\tglyphwarning: %s\n" + "\t\tglyphcheck: %s\n", + currfont->ft.name, + pdf_get_encoding_name(p, enc, currfont), + pdc_get_keyword(intextformat, pdf_textformat_keylist), + PDC_BOOLSTR(to->charref), + PDC_BOOLSTR(to->escapesequence), + PDC_BOOLSTR(to->glyphwarning), + pdc_get_keyword(to->glyphcheck, pdf_glyphcheck_keylist)); + + convflags |= PDC_CONV_LOGGING; + } + } + + /* text is passed through for CID fonts with non Unicode CMap */ + if (currfont->passthrough) + { + if (logg2) + pdc_logg(p->pdc, "\t\ttext is passed through as is\n"); + + outtext = (pdc_byte *) ((flags & PDF_USE_TMPALLOC) ? + pdc_malloc_tmp(p->pdc, (size_t) len + 2, fn, NULL, NULL) : + pdc_malloc(p->pdc, (size_t) len + 2, fn)); + memcpy(outtext, text, (size_t) len); + outtext[len] = 0; + outtext[len + 1] = 0; + *outlen = len; + + outtextformat = pdc_bytes; + } + else + { + + if (flags & PDF_FORCE_NEWALLOC) + convflags |= PDC_CONV_NEWALLOC; + + if (flags & PDF_USE_TMPALLOC) + convflags |= PDC_CONV_TMPALLOC; + + if (to->glyphcheck == (int) text_replace) + { + replchar = currfont->replacementchar; + } + else + { + replchar = (int) to->glyphcheck; + if (to->glyphcheck == text_error) + { + convflags |= PDC_CONV_ENCERROR; + if (flags & PDF_KEEP_CONTROL) + convflags |= PDC_CONV_KEEPLBCHAR; + } + } + + if (flags & PDF_KEEP_UNICODE || to->glyphcheck != text_nocheck) + inev = ev; + + + /* "Pass through mode" for 8-bit text. + * The encoding vector must be specified, because + * the text could emerge as a Unicode text due to a BOM. + */ + if ((enc >= 0 && inev == NULL) || + (enc == pdc_builtin && !(flags & PDF_KEEP_UNICODE))) + { + inev = ev; + outev = ev; + outtextformat = pdc_bytes; + } + + /* input text format */ + pdf_get_input_textformat(currfont, &intextformat, &convflags); + + /* convert to 8-bit or UTF-16 text string */ + if (pdc_convert_textstring(p->pdc, intextformat, currfont->codepage, + inev, + NULL, 0, + replchar, intext, len, + &outtextformat, outev, &outtext, outlen, + convflags, pdc_false)) + { + if (newlen > -1) + pdc_free_tmp(p->pdc, intext); + goto PDF_CHECK_TEXT_ERROR; + } + } + + if (newlen > -1) + pdc_free_tmp(p->pdc, intext); + + /* check text string */ + if (outtext != NULL && *outlen) + { + pdc_ushort *usouttext = (pdc_ushort *) outtext; + pdc_ushort uvlist[PDC_MAX_UVLIST]; + pdc_ushort cglist[PDC_MAX_UVLIST]; + pdc_bool kcheck = pdc_true; + int i = 0, nv = 1, icp = 0, usvp; + int code, gid, usv, ic; + + (void) i; + + /* storage length of a character */ + if (outtextformat == pdc_utf16) + { + charlen = 2; + newcharlen = 2; + } + + /* maximal text string length - found out emprirically! */ + maxlen = (currfont->codesize == 1) ? PDF_MAXARRAYSIZE : PDF_MAXDICTSIZE; + if (!(flags & PDF_KEEP_TEXTLEN) && *outlen > maxlen) + { + pdc_set_errmsg(p->pdc, PDF_E_TEXT_TOOLONG, + pdc_errprintf(p->pdc, "%d", maxlen), 0, 0, 0); + goto PDF_CHECK_TEXT_ERROR; + } + + len = *outlen / charlen; + switch (enc) + { + + + /* + * builtin + */ + case pdc_builtin: + if (charlen == 1 || !(flags & PDF_KEEP_UNICODE)) + newcharlen = 1; + for (ic = 0; ic < len; ic++) + { + if (charlen == 1) + code = (int) outtext[ic]; + else + code = (int) usouttext[ic]; + + if (code) + { + gid = fnt_get_glyphid(code, &currfont->ft); + + /* glyph id for code value not available */ + if (gid <= 0) + { + unmapgids++; + if (to->glyphcheck == text_error) + { + pdc_set_errmsg(p->pdc, PDF_E_FONT_CODENOTFOUND1, + pdc_errprintf(p->pdc, "x%02X", code), + currfont->ft.name, 0, 0); + goto PDF_CHECK_TEXT_ERROR; + } + else if (to->glyphcheck == text_replace) + { + pdc_warning(p->pdc, PDF_E_FONT_CODENOTFOUNDREP1, + pdc_errprintf(p->pdc, "x%02X", code), + currfont->ft.name, 0, 0); + code = currfont->replacementcode; + } + } + } + + if (newcharlen == 1) + outtext[icp] = (pdc_byte) code; + else + usouttext[icp] = (pdc_ushort) code; + icp++; + } + + break; + + + /* + * cid + */ + case pdc_cid: + /* + * pass through. check and temporary conversion in + * pdf_calculate_textsize(), because we want to keep native code. + */ + break; + + + /* + * encoding vector + */ + default: + if (charlen == 1 || !(flags & PDF_KEEP_UNICODE)) + newcharlen = 1; + for (ic = 0; ic < len; ic++) + { + if (charlen == 1) + { + code = (int) outtext[ic]; + usv = ev->codes[code]; + kcheck = code > 0; + } + else + { + usv = (int) usouttext[ic]; + code = pdc_get_encoding_bytecode(p->pdc, ev, + (pdc_ushort) usv); + if (code < 0) + code = 0; + kcheck = usv > 0; + } + + if ((flags & PDF_KEEP_CONTROL) && + pdc_is_linebreaking_relchar((pdc_ushort) usv)) + { + kcheck = pdc_false; + } + + /* glyph check */ + if (kcheck) + { + /* encoding vector hasn't defined [Uni]code */ + if (usv <= 0 || code <= 0) + { + unmapgids++; + if (to->glyphcheck == text_error) + { + if (usv <= 0) + { + pdc_set_errmsg(p->pdc, PDC_E_ENC_NOTDEF_CODE, + pdc_errprintf(p->pdc, "x%02X", code), + ev->apiname, 0, 0); + goto PDF_CHECK_TEXT_ERROR; + } + else if (code <= 0) + { + pdc_set_errmsg(p->pdc, PDC_E_ENC_NOTDEF_UNICODE, + pdc_errprintf(p->pdc, "%04X", usv), + ev->apiname, 0, 0); + goto PDF_CHECK_TEXT_ERROR; + } + } + else if (to->glyphcheck == text_replace) + { + usvp = (usv <= 0) ? code : usv; + nv = pdf_get_approximate_uvlist(p, currfont, ev, + usv, pdc_true, + uvlist, cglist); + usv = (int) uvlist[0]; + code = (int) cglist[0]; + + if (logg2) + { + pdf_logg_glyph_replacement(p, ic, usvp, + enc, charlen, uvlist, cglist, nv); + } + } + } + else + { + gid = fnt_get_glyphid(code, &currfont->ft); + + /* glyph id for code not available */ + if (gid <= 0 && currfont->gid0code != code) + { + unmapgids++; + if (to->glyphcheck == text_error) + { + pdc_set_errmsg(p->pdc, PDF_E_FONT_CODENOTFOUND2, + pdc_errprintf(p->pdc, "x%02X", code), + pdc_errprintf(p->pdc, "%04X", usv), + currfont->ft.name, 0); + goto PDF_CHECK_TEXT_ERROR; + } + else if (to->glyphcheck == text_replace) + { + pdc_warning(p->pdc, PDF_E_FONT_CODENOTFOUNDREP2, + pdc_errprintf(p->pdc, "x%02X", code), + pdc_errprintf(p->pdc, "%04X", usv), + currfont->ft.name, 0); + + usvp = (usv <= 0) ? code : usv; + nv = pdf_get_approximate_uvlist(p, currfont, ev, + usv, pdc_true, + uvlist, cglist); + usv = (int) uvlist[0]; + code = (int) cglist[0]; + + if (logg2) + { + pdf_logg_glyph_replacement(p, ic, usvp, + enc, charlen, uvlist, cglist, nv); + } + } + } + } + } + + if (newcharlen == 1) + { + outtext[icp] = (pdc_byte) code; + } + else + { + usouttext[icp] = (pdc_ushort) usv; + } + if (nv > 1) + { + if (newcharlen == 1) + ligatlist = pdf_register_ligat(p, ligatlist, icp, nv, + cglist, newcharlen); + else + ligatlist = pdf_register_ligat(p, ligatlist, + icp, nv, uvlist, newcharlen); + nv = 1; + } + icp++; + } + + break; + } + + if (icp) + { + /* calculate complete text length */ + len = newcharlen * icp; + if (ligatlist != NULL) + { + ligat = ligatlist; + while (ligat != NULL) + { + len += ligat->nb; + ligat = ligat->next; + } + } + + if (len != *outlen) + { + *outlen = len; + if (flags & PDF_USE_TMPALLOC) + outtext = (pdc_byte *) pdc_realloc_tmp(p->pdc, outtext, + (size_t) (*outlen + newcharlen), fn); + else + outtext = (pdc_byte *) pdc_realloc(p->pdc, outtext, + (size_t) (*outlen + newcharlen), fn); + outtext[*outlen] = 0; + if (newcharlen == 2) + outtext[*outlen + 1] = 0; + } + + /* insert ligature parts */ + if (ligatlist != NULL) + { + int nbrest, nbgap, nbmove = 0; + + len = newcharlen * icp; + ligat = ligatlist; + while (ligat != NULL) + { + nbgap = ligat->nb; + icp = ligat->icp + nbmove; + nbrest = len - icp; + icp += newcharlen; + ic = icp + nbgap; + + memmove(&outtext[ic], &outtext[icp], (size_t) nbrest); + memcpy(&outtext[icp], ligat->culist, (size_t) nbgap); + + nbmove += nbgap; + len += nbgap; + + ligat = ligat->next; + } + + pdf_cleanup_ligat(p, ligatlist); + } + } + } + + *outtext_p = outtext; + *outcharlen = newcharlen; + + if (logg1) + { + if (logg2) + pdc_logg_hexdump(p->pdc, "converted text", "\t\t", + (char *) outtext, *outlen); + else + pdc_logg(p->pdc, + "\tChecked and converted text of length %d: \"%T\"\n", + *outlen, outtext, *outlen); + } + return unmapgids; + + PDF_CHECK_TEXT_ERROR: + + if (outtext != NULL) + { + if (flags & PDF_USE_TMPALLOC) + pdc_free_tmp(p->pdc, outtext); + else + pdc_free(p->pdc, outtext); + } + + pdf_cleanup_ligat(p, ligatlist); + + if (verbose) + pdc_error(p->pdc, -1, 0, 0, 0, 0); + + *outtext_p = NULL; + *outlen = 0; + + return -1; +} + + +/* ------------------------ Text width functions ------------------------ */ + +/* Calculates the geometrical width and height of input text string + * depending on + * + * to->font, to->fontsize, to->kerning, + * to->charspacing, to->horizscaling, to->wordspacing, + * to->xadvancelist + * + * In the case of vertical writing mode the width is the maximum + * of all glyph widths and height the height of the text string. + * + */ + +pdc_scalar +pdf_calculate_textsize(PDF *p, const pdc_byte *text, int len, int charlen, + pdf_text_options *to, int breakchar, pdc_scalar *height, + pdc_bool verbose) +{ + pdf_font *currfont = &p->fonts[to->font]; + pdc_encoding enc = currfont->ft.enc; + pdc_byte *tmpstring = (pdc_byte *) text; + pdc_ushort *ustext = (pdc_ushort *) text; + pdc_scalar glwidth = 0, width = 0; + pdc_scalar font2user = to->fontsize / 1000.0; + pdc_bool kbreak = pdc_false; + int usv, ic, icc, numglyphs = 0, numspaces = 0; + + /* We cannot handle empty strings or fonts without widths info */ + if (!len || currfont->widthsmissing) + { + if (height) + *height = 0.0; + return width; + } + + if (enc != pdc_cid) + len /= charlen; + + for (ic = 0; ic < len; ) + { + icc = ic; + + { + if (charlen == 1) + { + usv = (int) text[ic]; + } + else if (enc == pdc_unicode) + { + usv = pdc_char16_to_char32(p->pdc, ustext, &ic, len, verbose); + } + else + { + usv = (int) ustext[ic]; + } + + /* count spaces */ + if (usv == (int) currfont->ft.spacechar) + numspaces++; + + /* break character */ + if (breakchar > 0) + kbreak = (usv == breakchar); + + ic++; + } + + /* start by adding in the width of the character */ + if (currfont->opt.monospace) + { + glwidth = (pdc_scalar) currfont->opt.monospace; + } + else + { + glwidth = (pdc_scalar) fnt_get_glyphwidth(usv, &currfont->ft); + if (glwidth == FNT_MISSING_WIDTH) + glwidth = currfont->ft.m.defwidth; + } + + /* count glyphs */ + numglyphs++; + + /* horizontal or vertical writing mode */ + if (!currfont->ft.vertical) + { + width += glwidth; + + + /* supplied glyph widths */ + if (icc < to->nglyphs) + { + pdc_scalar shift = to->xadvancelist[icc] / font2user - glwidth; + width += shift; + if (p->pdc->ptfrun) + shift = PDC_ROUND(1e10 * shift) / 1e10; + shift = PDC_ROUND(1e1 * shift) / 1e1; + to->xadvancelist[icc] = shift; + } + } + else + { + /* maximum of width */ + if (glwidth > width) + width = glwidth; + } + + /* length of text part ranging to decimal character */ + if (kbreak) + break; + } + + if (breakchar > 0 && !kbreak) + return 0; + + /* charspacing and wordspacing */ + if (!currfont->ft.vertical) + { + if (to->charspacing) + width += numglyphs * to->charspacing / font2user; + if (to->wordspacing) + width += numspaces * to->wordspacing / font2user; + if (height) + *height = 0.0; + } + else + { + /* height for positive y direction. + * Acrobat calculates with negative direction (see pdf_place_text). + */ + *height = numglyphs * (to->fontsize + -to->charspacing) + + numspaces * (-to->wordspacing); + } + + /* take horizontal scaling factor and font scaling factor into account */ + width *= font2user * to->horizscaling; + + if (tmpstring != text) + pdc_free_tmp(p->pdc, tmpstring); + + return width; + +} + +pdc_scalar +pdf_trim_textwidth(pdc_scalar width, pdf_text_options *to) +{ + if (!PDC_FLOAT_ISNULL(width)) + width -= to->horizscaling * to->charspacing; + + return width; +} + + +pdc_scalar +pdf__stringwidth(PDF *p, const char *text, int len, int font, + pdc_scalar fontsize) +{ + pdc_byte *utext; + int charlen; + pdc_scalar width = 0, height = 0; + pdf_text_options to = *p->curr_ppt->currto; + + if (text && len == 0) + len = (int) strlen(text); + if (text == NULL || len <= 0) + return width; + + pdf_check_handle(p, font, pdc_fonthandle); + + pdc_check_number_zero(p->pdc, "fontsize", fontsize); + + /* convert text string */ + to.font = font; + to.fontsize = fontsize; + pdf_check_textstring(p, text, len, PDF_KEEP_TEXTLEN | PDF_USE_TMPALLOC, + &to, &utext, &len, &charlen, pdc_true); + if (utext && len) + width = pdf_calculate_textsize(p, utext, len, charlen, + &to, -1, &height, pdc_true); + + return width; +} + + +/* ------------------------ Text output functions ------------------------ */ + +static void +pdf_convert_text_towinansi(PDF *p, const pdc_byte *fromtext, int len, + pdc_byte *totext, pdf_font *currfont) +{ + pdc_encodingvector *evfrom = + pdc_get_encoding_vector(p->pdc, currfont->ft.enc); + pdc_encodingvector *evto = + pdc_get_encoding_vector(p->pdc, currfont->towinansi); + int i; + + for (i = 0; i < len; i++) + totext[i] = pdc_transform_bytecode(p->pdc, evto, evfrom, fromtext[i]); +} + +void +pdf_put_fieldtext(PDF *p, const char *text, int font) +{ + if (pdc_is_utf8_bytecode(text)) + { + pdf_put_hypertext(p, text); + } + else + { + static const char fn[] = "pdf_put_fieldtext"; + pdf_font *currfont = &p->fonts[font]; + char *tmpstring = (char *) text; + int len = (int) pdc_strlen(text); + + if (len && currfont->towinansi != pdc_invalidenc && + !pdc_is_utf16be_unicode(text)) + { + /* Convert 8-bit code string to winansi */ + tmpstring = (char *) pdc_malloc_tmp(p->pdc, + (size_t) len, fn, NULL, NULL); + pdf_convert_text_towinansi(p, (pdc_byte *) text, len, + (pdc_byte *) tmpstring, currfont); + } + + pdc_put_pdfstring(p->out, tmpstring, len); + if (tmpstring != text) + pdc_free_tmp(p->pdc, tmpstring); + } +} + +static void +pdf_put_textstring(PDF *p, const pdc_byte *text, int len, int charlen, + pdf_font *currfont) +{ + static const char fn[] = "pdf_put_textstring"; + pdc_byte *tmpstring = (pdc_byte *) text; + + (void) charlen; + + if (len) + { + + /* Convert 8-bit code string to winansi */ + if (currfont->towinansi != pdc_invalidenc) + { + tmpstring = (pdc_byte *) pdc_malloc_tmp(p->pdc, + (size_t) len, fn, NULL, NULL); + pdf_convert_text_towinansi(p, text, len, tmpstring, currfont); + } + + } + + pdc_put_pdfstring(p->out, (char *) tmpstring, len); + if (tmpstring != text) + pdc_free_tmp(p->pdc, tmpstring); +} + +static void +pdf_put_textstring_shift(PDF *p, pdc_byte *text, int len, int charlen, + pdf_text_options *to, pdc_scalar spaceshift) +{ + pdf_font *currfont = &p->fonts[to->font]; + pdc_ushort *ustext = (pdc_ushort *) text; + pdc_byte *currtext; + pdc_scalar shift; + pdc_bool isutf16; + int currlen, nchars; + int leftchar = 0, rightchar; + int ic, icp, incr = charlen; + + currlen = 0; + currtext = text; + nchars = len/charlen; + isutf16 = charlen == 2 && + currfont->codesize == 2 && + currfont->ft.enc == pdc_unicode; + for (ic = 0; ic < nchars; ic++) + { + if (charlen == 1) + { + rightchar = (int) text[ic]; + } + else if(!isutf16) + { + rightchar = (int) ustext[ic]; + } + else + { + icp = ic; + rightchar = + pdc_char16_to_char32(p->pdc, ustext, &ic, nchars, pdc_true); + incr = (1 + ic - icp) * charlen; + } + + if (ic) + { + /* PDF wants the inverse shift amount + * (positive numbers move left, negative move right!) */ + + if (spaceshift != 0 && leftchar == (int) currfont->ft.spacechar) + shift = -spaceshift; + else + shift = 0; + + + if (ic <= to->nglyphs) + shift -= to->xadvancelist[ic-1]; + + if (shift) + { + pdf_put_textstring(p, currtext, currlen, charlen, currfont); + pdc_printf(p->out, "%f", shift); + currtext = &text[charlen * ic]; + currlen = 0; + } + } + leftchar = rightchar; + currlen += incr; + } + + pdf_put_textstring(p, currtext, currlen, charlen, currfont); + + if (to->nglyphs && to->nglyphs >= nchars) + pdc_printf(p->out, "%f", -to->xadvancelist[nchars - 1]); + +} + + +/* --------------------- General text placing function --------------------- */ + + +#define PDF_RENDERMODE_FILLCLIP 4 +#define PDF_ITALICANGLE_DEFAULT -12 + +static void +pdf_place_singletext(PDF *p, pdc_byte *text, int len, int charlen, + pdf_text_options *to, pdc_scalar tx, pdc_scalar ty, + pdc_scalar width, pdc_scalar height, pdc_scalar leading, + pdc_bool cont) +{ + pdf_tstate *ts = &p->curr_ppt->tstate[p->curr_ppt->sl]; + pdf_font *currfont = &p->fonts[to->font]; + pdc_scalar dx, dy, spaceshift = 0; + pdc_scalar font2user = to->fontsize / 1000.0; + pdc_scalar linewidth = 0; + pdc_scalar deflinewidth = 0; + pdc_bool hasdeco = to->underline || to->overline || to->strikeout; + pdc_bool takeTJ = pdc_false; + + /* default linewidth for underlinewidth and strokewidth */ + if (hasdeco || (to->mask & (1 << to_strokewidth))) + { + if (currfont->ft.m.underlineThickness == 0) + currfont->ft.m.underlineThickness = 50; + deflinewidth = fabs(to->horizscaling * font2user * + currfont->ft.m.underlineThickness); + } + + /* fill and stroke color */ + if (to->mask & (1 << to_fillcolor)) + pdf_set_coloropt(p, (int) pdf_fill, &to->fillcolor); + if (to->mask & (1 << to_strokecolor)) + pdf_set_coloropt(p, (int) pdf_stroke, &to->strokecolor); + + + /* stroke width and dasharray for stroked text */ + if (to->mask & (1 << to_strokewidth)) + { + if (to->strokewidth == PDF_UNDERLINEWIDTH_AUTO) + { + linewidth = deflinewidth; + } + else + { + linewidth = to->strokewidth; + if ((to->pcmask & (1 << to_strokewidth))) + linewidth *= fabs(to->fontsize); + } + pdf__setlinewidth(p, linewidth); + } + if (to->mask & (1 << to_dasharray)) + pdf__setdash(p, to->dasharray[0], to->dasharray[1]); + + /* text decoration */ + if (width && hasdeco) + { + pdc_scalar scale = fabs(to->horizscaling); + pdc_scalar delta, fs, trise, lineheight; + pdc_scalar txe = 0, tye = 0; + pdc_scalar lineposition = 0; + + fs = p->ydirection * font2user; + trise = p->ydirection * to->textrise; + lineheight = fs * currfont->ft.m.ascender; + delta = scale * (fs * currfont->ft.m.underlinePosition + trise); + + pdf__save(p); + + if (to->underlinewidth == PDF_UNDERLINEWIDTH_AUTO) + { + linewidth = deflinewidth; + } + else + { + linewidth = to->underlinewidth; + if ((to->pcmask & (1 << to_underlinewidth))) + linewidth *= fabs(to->fontsize); + } + + if (to->underlineposition == PDF_UNDERLINEPOSITION_AUTO) + { + lineposition = delta; + } + else + { + lineposition = p->ydirection * to->underlineposition; + if ((to->pcmask & (1 << to_underlineposition))) + lineposition *= to->fontsize; + } + + if (!currfont->ft.vertical) + { + txe = tx + width; + } + else + { + txe = tx - width / 2.0; + tye = ty - p->ydirection * height; + lineposition *= p->ydirection; + delta = fabs(delta); + } + + pdf__setlinecap(p, 0); + if (!(to->mask & (1 << to_dasharray))) + pdf__setdash(p, 0, 0); + + if (to->underline) + { + pdf__setlinewidth(p, linewidth); + if (!currfont->ft.vertical) + { + pdf__moveto(p, tx, ty + lineposition); + pdf__lineto(p, txe, ty + lineposition); + } + else + { + pdf__moveto(p, txe + lineposition, ty); + pdf__lineto(p, txe + lineposition, tye); + } + pdf__stroke(p); + } + + if (to->strikeout) + { + pdf__setlinewidth(p, deflinewidth); + if (!currfont->ft.vertical) + { + pdf__moveto(p, tx, ty + lineheight/2 + delta); + pdf__lineto(p, txe, ty + lineheight/2 + delta); + } + else + { + pdf__moveto(p, tx, ty); + pdf__lineto(p, tx, tye); + } + pdf__stroke(p); + } + + if (to->overline) + { + pdf__setlinewidth(p, deflinewidth); + if (!currfont->ft.vertical) + { + delta = scale * (fs * currfont->ft.m.underlinePosition - trise); + pdf__moveto(p, tx, ty + lineheight - delta); + pdf__lineto(p, txe, ty + lineheight - delta); + } + else + { + pdf__moveto(p, txe + width + delta, ty); + pdf__lineto(p, txe + width + delta, tye); + } + pdf__stroke(p); + } + + pdf__restore(p); + } + + + + /* wordspacing */ + if (!PDC_FLOAT_ISNULL(to->wordspacing)) + { + spaceshift = to->wordspacing / font2user; + if (p->pdc->ptfrun) + spaceshift = PDC_ROUND(1e10 * spaceshift) / 1e10; + spaceshift = PDC_ROUND(1e1 * spaceshift) / 1e1; + takeTJ = PDC_FLOAT_ISNULL(spaceshift) ? pdc_false : pdc_true; + } + + + /* supplied glyph widths */ + if (!takeTJ) + takeTJ = to->nglyphs; + + /* begin text object */ + pdf_begin_text(p); + + /* italic angle - realized by Tm operator */ + if (!PDC_FLOAT_ISNULL(to->italicangle) || + currfont->metricflags & font_italic) + { + if (!currfont->ft.vertical) + { + pdc_scalar italicangle = -p->ydirection * to->italicangle; + + if (currfont->metricflags & font_italic && italicangle == 0) + italicangle = -p->ydirection * PDF_ITALICANGLE_DEFAULT; + + if (ts->hs < 0) + italicangle = -italicangle; + + pdc_printf(p->out, "1 0 %f 1 %f %f Tm\n", + tan(italicangle * PDC_DEG2RAD), tx, ty); + + cont = pdc_false; + ts->newpos = pdc_false; + ts->refptx = tx; + ts->refpty = ty; + } + else + { + pdc_error(p->pdc, PDF_E_TEXT_ITALUNSUPP, 0, 0, 0, 0); + } + } + else + { + /* components of text displacement vector */ + if (!cont) + { + dx = tx - ts->prevtx; + dy = ty - ts->prevty; + } + else + { + dx = tx - ts->refptx; + dy = ty - ts->refpty + leading; + } + + /* condition for text displacement operator Td */ + if (!PDC_FLOAT_ISNULL(dx) || !PDC_FLOAT_ISNULL(dy) || + ts->newpos || (cont && takeTJ)) + { + if (cont) + { + dy -= leading; + cont = pdc_false; + } + pdc_printf(p->out, "%f %f Td\n", dx, dy); + + /* new reference position for next line */ + ts->newpos = pdc_false; + ts->refptx = tx; + ts->refpty = ty; + } + else + { + ts->refpty -= leading; + } + } + + /* show text */ + if (!takeTJ) + { + pdf_put_textstring(p, text, len, charlen, currfont); + if (!cont) + pdc_puts(p->out, "Tj\n"); + else + pdc_puts(p->out, "'\n"); + } + else + { + pdc_puts(p->out, "["); + pdf_put_textstring_shift(p, text, len, charlen, to, spaceshift); + pdc_puts(p->out, "]TJ\n"); + } + + /* new text position */ + if (!currfont->ft.vertical) + { + ts->currtx = tx + width; + ts->currty = ty; + } + else + { + ts->currtx = tx; + ts->currty = ty - p->ydirection * height; + } + ts->prevtx = ts->currtx; + ts->prevty = ts->currty; + + if (to->textrendering >= PDF_RENDERMODE_FILLCLIP) + pdf_end_text(p); +} + +#define PDF_FAKEBOLD_OFFSET 0.03 /* 3% of font size */ + +void +pdf_place_text(PDF *p, pdc_byte *text, int len, int charlen, + pdf_text_options *to, pdc_scalar width, pdc_scalar height, + pdc_bool cont) +{ + pdf_tstate *ts = &p->curr_ppt->tstate[p->curr_ppt->sl]; + pdf_font *currfont = &p->fonts[to->font]; + pdc_scalar tx, ty, leading = 0; + + /* text position */ + if (!cont) + { + tx = ts->currtx; + ty = ts->currty; + } + else + { + leading = p->ydirection * to->leading; + tx = ts->linetx; + ty = ts->currty - leading; + } + + pdf_place_singletext(p, text, len, charlen, to, tx, ty, + width, height, leading, cont); + + /* text bolding */ + if (to->fakebold || currfont->metricflags & font_bold) + { + static const pdc_scalar fx[] = {0, 0.70711, 1}; + static const pdc_scalar fy[] = {1, 0.70711, 0}; + pdc_scalar offset, currtx, currty, linetx; + int it, nt = 3; + + offset = PDF_FAKEBOLD_OFFSET * to->fontsize; + + linetx = ts->linetx; + currtx = ts->currtx; + currty = ts->currty; + for (it = 0; it < nt; it++) + { + pdf__set_text_pos(p, tx + fx[it] * offset, + ty + p->ydirection * fy[it] * offset); + pdf_place_singletext(p, text, len, charlen, to, + ts->currtx, ts->currty, + width, height, leading, pdc_false); + } + pdf__set_text_pos(p, currtx, currty); + ts->linetx = linetx; + } +} + +/* --------------------- Simple text showing functions --------------------- */ + +void +pdf__show_text( + PDF *p, + const char *text, + int len, + pdc_bool cont) +{ + static const char *fn = "pdf__show_text"; + pdf_text_options *currto = p->curr_ppt->currto; + pdc_byte *utext = NULL; + int charlen = 1; + pdc_scalar width = 0, height = 0; + + if (text && len == 0) + len = (int) strlen(text); + if (text == NULL || len <= 0) + { + if (cont) + len = 0; + else + return; + } + + /* no font set */ + if (currto->font == -1) + pdc_error(p->pdc, PDF_E_TEXT_NOFONT, 0, 0, 0, 0); + + if (len) + { + /* convert text string */ + pdf_check_textstring(p, text, len, PDF_USE_TMPALLOC, + currto, &utext, &len, &charlen, pdc_true); + if (utext == NULL || (!cont && !len)) + return; + + /* width and height of text string */ + width = pdf_calculate_textsize(p, utext, len, charlen, + currto, -1, &height, pdc_true); + } + else + { + utext = (pdc_byte *) pdc_calloc_tmp(p->pdc, 2, fn, NULL, NULL); + } + + + /* place text */ + pdf_place_text(p, utext, len, charlen, currto, width, height, cont); +} + + +/* ---------- Text showing function with explicit glyph widths ---------- */ + +void +pdf__xshow(PDF *p, const char *text, int len, const pdc_scalar *xadvancelist) +{ + static const char *fn = "pdf__xshow"; + pdf_text_options *currto = p->curr_ppt->currto; + pdc_byte *utext = NULL; + int charlen = 1; + size_t nbytes = 0; + pdc_scalar width, height; + + if (text && len == 0) + len = (int) strlen(text); + if (text == NULL || !len) + return; + + /* no font set */ + if (currto->font == -1) + pdc_error(p->pdc, PDF_E_TEXT_NOFONT, 0, 0, 0, 0); + + /* convert text string */ + pdf_check_textstring(p, text, len, PDF_USE_TMPALLOC, + currto, &utext, &len, &charlen, pdc_true); + if (utext == NULL || !len) + return; + + /* allocating glyph widths arrays */ + nbytes = (size_t) (len / charlen) * sizeof(pdc_scalar); + currto->xadvancelist = (pdc_scalar *) pdc_malloc_tmp(p->pdc, + nbytes, fn, NULL, NULL); + memcpy(currto->xadvancelist, xadvancelist, nbytes); + currto->nglyphs = len / charlen; + + /* length of text */ + width = pdf_calculate_textsize(p, utext, len, charlen, + currto, -1, &height, pdc_true); + + + /* place text */ + pdf_place_text(p, utext, len, charlen, currto, width, height, pdc_false); + + currto->xadvancelist = NULL; + currto->nglyphs = 0; +} + + +/* --------------------------- Leader functions ---------------------------- */ + + + +/* ----------------------- Text fitting function ------------------------ */ + +struct pdf_fittext_s +{ + pdc_vector start; /* text start position */ + pdc_vector end; /* text end position */ + pdc_vector writingdir; /* unit vector of text writing direction */ + pdc_vector perpendiculardir;/* unit vector perpendicular to writing dir. */ + pdc_vector scale; /* x/y scaling */ + pdc_scalar angle; /* rotation angle of writingdir in degree */ + pdc_scalar width; /* textline width */ + pdc_scalar height; /* textline height */ + pdc_scalar mwidth; /* textline width with margins */ + pdc_scalar mheight; /* textline height with margins */ + pdc_scalar ascender; /* textline ascender */ + pdc_scalar capheight; /* textline capheight */ + pdc_scalar xheight; /* textline xheight */ + pdc_scalar descender; /* textline descender */ +}; + + +/* definitions of fit text options */ +static const pdc_defopt pdf_fit_textline_options[] = +{ + PDF_TEXT_OPTIONS + + {"xadvancelist", pdc_scalarlist, PDC_OPT_NOZERO, 0, PDC_USHRT_MAX, + PDC_FLOAT_MIN, PDC_FLOAT_MAX, NULL}, + + PDF_FIT_OPTIONS1 + PDF_FIT_OPTIONS2 + PDF_FIT_OPTIONS6 + + PDF_FONT_OPTIONS1 + PDF_FONT_OPTIONS2 + + PDF_ERRORPOLICY_OPTION + PDC_OPT_TERMINATE +}; + +pdc_resopt * +pdf_parse_fittextline_optlist(PDF *p, pdf_text_options *to, + pdf_fit_options *fit, const char *optlist) +{ + pdc_resopt *resopts = NULL; + pdf_font_options fo; + + /* *to must be initialized */ + + /* initialize fit options */ + pdf_init_fit_options(p, pdc_false, fit); + fit->flags |= is_textline; + + /* initialize font options */ + pdf_init_font_options(p, &fo); + fo.flags |= is_textline; + + /* parsing option list */ + if (optlist && strlen(optlist)) + { + pdc_clientdata data; + + pdf_set_clientdata(p, &data); + resopts = pdc_parse_optionlist(p->pdc, optlist, + pdf_fit_textline_options, &data, pdc_true); + + pdf_get_font_options(p, &fo, resopts); + pdf_get_text_options(p, to, resopts); + pdf_get_fit_options(p, pdc_false, fit, resopts); + } + + /* font options specified */ + if (fo.mask & (1 << fo_fontname) && fo.mask & (1 << fo_encoding)) + { + to->font = pdf_load_font_internal(p, &fo); + to->mask |= (1L << to_font); + to->fontset |= (1L << to_font); + } + else + { + pdf_cleanup_font_options(p, &fo); + } + + return resopts; +} + +static pdc_bool +pdf_parse_textline_options(PDF *p, const char *text, int len, + pdf_text_options *to, pdf_fit_options *fit, + const char *optlist) +{ + pdf_ppt *ppt = p->curr_ppt; + + if (text && len == 0) + len = (int) strlen(text); + if (text == NULL || len <= 0) + return pdc_false; + + /* initialize text options */ + *to = *ppt->currto; + to->text = (char *) text; + to->textlen = len; + + /* parsing option list */ + pdf_parse_fittextline_optlist(p, to, fit, optlist); + + /* no font set */ + if (to->font == -1) + pdc_error(p->pdc, PDF_E_TEXT_NOFONT, 0, 0, 0, 0); + + /* no font size set */ + if (to->fontsize == PDC_FLOAT_MIN) + { + pdc_error(p->pdc, PDF_E_TEXT_NOFONTSIZESET, 0, 0, 0, 0); + } + + return pdc_true; +} + +int +pdf_fit_textline_internal(PDF *p, pdf_fittext *fitres, + pdf_text_options *to, pdf_fit_options *fit, + pdc_matrix *matrix) +{ + pdc_bool logg5 = pdc_logg_is_enabled(p->pdc, 5, trc_text); + pdf_ppt *ppt = p->curr_ppt; + pdf_font *currfont = &p->fonts[to->font]; + pdc_byte *utext = (pdc_byte *) ""; + int len, charlen; + pdc_bool blind = (fitres != NULL) ? pdc_true : pdc_false; + pdc_bool vertical = currfont->ft.vertical; + + pdc_matrix ctm = ppt->gstate[ppt->sl].ctm; + pdc_matrix m, mm; + pdc_vector elemsize, elemscale, elemmargin, textrelpos, fitrelpos; + pdc_vector polyline[5]; + pdc_scalar textyextent[2]; + pdc_box fitbox, elembox; + pdc_scalar ss, width, height, boxwidth, boxheight, fontsizeref; + pdc_scalar ascender, capheight, xheight, descender; + pdc_scalar x, y, tx = 0, ty = 0, basey = 0; + pdc_bool hasfitbox = pdc_false; + pdc_scalar font2user; + int indangle = fit->orientate / 90; + int unmapgids = 0, i; + + (void) ppt; + + /* box size */ + boxwidth = fit->boxsize[0]; + boxheight = fit->boxsize[1]; + + /* reference for font size as percentage */ + if (indangle % 2) + fontsizeref = boxwidth; + else + fontsizeref = boxheight; + + /* calculate and set text options */ + pdf_calculate_text_options(p, to, pdc_false, 1.0, PDC_FLOAT_PREC, + fontsizeref); + if (!blind) + pdf_set_text_options(p, to); + + /* convert text string */ + unmapgids = pdf_check_textstring(p, to->text, to->textlen, PDF_USE_TMPALLOC, + to, &utext, &len, &charlen, pdc_true); + if (utext == NULL || !len) + return -1; + + if (to->nglyphs && len/charlen != to->nglyphs) + pdc_warning(p->pdc, PDF_E_TEXT_SIZENOMATCH, + pdc_errprintf(p->pdc, "%d", to->nglyphs), + pdc_errprintf(p->pdc, "%d", len/charlen), 0, 0); + + /* width and height of text */ + width = pdf_calculate_textsize(p, utext, len, charlen, + to, -1, &height, pdc_true); + width = pdf_trim_textwidth(width, to); + if (PDC_FLOAT_ISNULL(width)) + return -1; + + /* font specifics */ + font2user = to->fontsize / 1000.0; + ascender = font2user * currfont->ft.m.ascender; + capheight = font2user * currfont->ft.m.capHeight; + xheight = font2user * currfont->ft.m.xHeight; + descender = font2user * currfont->ft.m.descender; + + /* margin lower left corner */ + elemmargin.x = fit->margin[0]; + elemmargin.y = fit->margin[1]; + + /* new box size */ + boxwidth -= 2 * elemmargin.x; + if (boxwidth < 0) + boxwidth = 0; + boxheight -= 2 * elemmargin.y; + if (boxheight < 0) + boxheight = 0; + hasfitbox = boxwidth > PDC_FLOAT_PREC && boxheight > PDC_FLOAT_PREC; + + /* kind of text box */ + pdf_get_mbox_boxheight(p, fit->matchbox, textyextent); + + /* text x size */ + elemsize.x = width; + + /* TODO: for vertical text */ + /* text y size */ + if (!vertical) + { + height = 0; + for (i = 0; i < 2; i++) + { + basey = 0; + if (textyextent[i] <= 0) + { + switch ((int) textyextent[i]) + { + case text_none: + break; + + case text_ascender: + basey = ascender; + break; + + case text_capheight: + basey = capheight; + break; + + case text_xheight: + basey = xheight; + break; + + case text_descender: + basey = -descender; + break; + + case text_textrise: + basey = to->textrise; + break; + + case text_fontsize: + basey = to->fontsize; + break; + + case text_leading: + basey = to->leading; + break; + } + } + else + { + basey = textyextent[i]; + } + height += basey; + } + } + elemsize.y = height; + + /* orientation */ + if (indangle % 2) + { + ss = elemsize.x; + elemsize.x = elemsize.y; + elemsize.y = ss; + } + + /* box for fitting */ + fitbox.ll.x = 0; + fitbox.ll.y = 0; + fitbox.ur.x = boxwidth; + fitbox.ur.y = boxheight; + + /* relativ position in fit and text box */ + fitrelpos.x = fit->position[0] / 100.0; + fitrelpos.y = fit->position[1] / 100.0; + textrelpos = fitrelpos; + + /* decimal character and position */ + if (fit->alignchar) + { + pdc_encoding enc = currfont->ft.enc; + pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc); + pdc_scalar decwidth, decheight, pos1, pos2; + int poschar = (int) fit->alignchar; + + switch(enc) + { + case pdc_cid: + if (currfont->codesize != 2) + poschar = -1; + break; + + case pdc_glyphid: + poschar = fnt_get_glyphid(poschar, &currfont->ft); + break; + + case pdc_builtin: + poschar = -1; + break; + + default: + if (ev != NULL && charlen == 1) + { + poschar = pdc_get_encoding_bytecode(p->pdc, ev, + (pdc_ushort) poschar); + } + break; + } + + /* width and height of text part ranging to decimal character */ + decwidth = pdf_calculate_textsize(p, utext, len, charlen, + to, poschar, &decheight, pdc_true); + + /* position found */ + if (decwidth > 0) + { + /* relative position of position character */ + pos1 = decwidth / width; + pos2 = 1 - pos1; + i = vertical ? ((indangle + 3) % 4) : indangle; + switch (i) + { + case 0: + textrelpos.x = pos1; + break; + + case 1: + textrelpos.y = pos1; + break; + + case 2: + textrelpos.x = pos2; + break; + + case 3: + textrelpos.y = pos2; + break; + } + } + } + + /* calculate image box */ + pdc_place_element(fit->fitmethod, fit->shrinklimit, &fitbox, &fitrelpos, + &elemsize, &textrelpos, &elembox, &elemscale); + + if (logg5) + pdc_logg(p->pdc, + "\t\tFitting input parameter:\n" + "\t\t\tfitmethod = %s\n" + "\t\t\tshrinklimit = %f\n" + "\t\t\trefpoint = %f, %f\n" + "\t\t\tboxsize = %f, %f\n" + "\t\t\tfitrelpos = %f, %f\n" + "\t\t\telemsize = %f, %f\n" + "\t\t\ttextrelpos = %f, %f\n" + "\t\tFitting output parameter:\n" + "\t\t\telembox = %f, %f, %f, %f\n" + "\t\t\telemscale = %f, %f\n", + pdc_get_keyword(fit->fitmethod, pdf_fitmethod_keylist), + fit->shrinklimit, fit->refpoint[0], fit->refpoint[1], + fitbox.ur.x, fitbox.ur.y, fitrelpos.x, fitrelpos.y, + elemsize.x, elemsize.y, textrelpos.x, textrelpos.y, + elembox.ll.x, elembox.ll.y, elembox.ur.x, elembox.ur.y, + elemscale.x, elemscale.y); + + /* reference point */ + pdc_translation_matrix(fit->refpoint[0], fit->refpoint[1], &mm); + if (matrix == NULL) + { + if (blind) + { + m = ctm; + pdc_multiply_matrix(&mm, &m); + } + else + m = mm; + } + else + { + m = *matrix; + pdc_multiply_matrix(&mm, &m); + } + + /* optional rotation */ + if (fabs(fit->rotate) > PDC_FLOAT_PREC) + { + pdc_rotation_matrix(p->ydirection * fit->rotate, &mm); + pdc_multiply_matrix(&mm, &m); + } + + /* output after translation and rotation */ + if (!blind) + { + /* new CTM */ + if (fit->showborder || + fit->fitmethod == pdc_clip || fit->fitmethod == pdc_slice) + { + pdf_concat_raw(p, &m); + pdc_identity_matrix(&m); + } + + /* show border */ + if (fit->showborder) + { + pdf__rect(p, elemmargin.x, p->ydirection * elemmargin.y, + boxwidth, boxheight); + pdf__rect(p, 0, 0, fit->boxsize[0], fit->boxsize[1]); + pdf__stroke(p); + } + + /* clipping */ + if ( + (fit->fitmethod == pdc_clip || fit->fitmethod == pdc_slice)) + { + pdc_scalar cw = fit->boxsize[0]; + pdc_scalar ch = fit->boxsize[1]; + + if (cw < PDC_FLOAT_PREC) + cw = PDF_ACRO_MAXPAGE; + if (ch < PDC_FLOAT_PREC) + ch = PDF_ACRO_MAXPAGE; + pdf__rect(p, 0, 0, cw, ch); + pdf__clip(p); + } + } + + /* reference point for elembox */ + if (elemmargin.x > PDC_FLOAT_PREC || elemmargin.y > PDC_FLOAT_PREC) + { + tx = elemmargin.x; + if (boxwidth < PDC_FLOAT_PREC) + tx *= 1.0 - 2 * fitrelpos.x; + ty = elemmargin.y; + if (boxheight < PDC_FLOAT_PREC) + ty *= 1.0 - 2 * fitrelpos.y; + + pdc_translation_matrix(tx, p->ydirection * ty, &mm); + pdc_multiply_matrix(&mm, &m); + } + + + /* translation of element box */ + elembox.ll.y *= p->ydirection; + elembox.ur.y *= p->ydirection; + pdc_box2polyline(NULL, &elembox, polyline); + tx = polyline[indangle].x; + ty = polyline[indangle].y; + pdc_translation_matrix(tx, ty, &mm); + pdc_multiply_matrix(&mm, &m); + boxwidth = elembox.ur.x - elembox.ll.x; + boxheight = elembox.ur.y - elembox.ll.y; + + /* orientation of text */ + if (fit->orientate != 0) + { + pdc_rotation_matrix(p->ydirection * fit->orientate, &mm); + pdc_multiply_matrix(&mm, &m); + if (indangle % 2) + { + ss = elemscale.x; + elemscale.x = elemscale.y; + elemscale.y = ss; + + ss = boxwidth; + boxwidth = p->ydirection * boxheight; + boxheight = p->ydirection * ss; + + ss = elemmargin.x; + elemmargin.x = p->ydirection * elemmargin.y; + elemmargin.y = p->ydirection * ss; + } + } + + /* matchbox */ + if (!blind && fit->matchbox) + { + pdc_rectangle matchrect; + + pdf_concat_raw(p, &m); + pdc_identity_matrix(&m); + + matchrect.llx = 0; + matchrect.lly = 0; + matchrect.urx = boxwidth; + matchrect.ury = boxheight; + + pdf_set_mbox_rectangle(p, fit->matchbox, &matchrect, 0); + pdf_draw_mbox_rectangle(p, fit->matchbox, + mbox_saverestore | mbox_area | mbox_border); + + pdf_add_page_mbox(p, fit->matchbox); + } + + /* scaling */ + if (elemscale.x != 1 || elemscale.y != 1) + { + pdc_scale_matrix(elemscale.x, elemscale.y, &mm); + pdc_multiply_matrix(&mm, &m); + } + + /* relative text position */ + if (!vertical) + { + x = 0; + y = p->ydirection * basey; + } + else + { + x = width / 2.0; + y = p->ydirection * height; + } + + if (logg5) + pdc_logg(p->pdc, + "\t\tReference point:\n" + "\t\t\tx = %f\n" + "\t\t\ty = %f\n" + "\t\tEmbedding matrix components of textline fitting:\n" + "\t\t\ta = %f\n" + "\t\t\tb = %f\n" + "\t\t\tc = %f\n" + "\t\t\td = %f\n" + "\t\t\te = %f\n" + "\t\t\tf = %f\n", + x, y, m.a, m.b, m.c, m.d, m.e, m.f); + + /* + * blind mode: pdf__info_textline + */ + if (blind) + { + pdc_scalar mwidth = 2 * fabs(elemmargin.x); + pdc_scalar mheight = 2 * fabs(elemmargin.y); + pdc_scalar vlen; + + /* start position */ + pdc_transform_point(&m, x, y, &tx, &ty); + fitres->start.x = tx; + fitres->start.y = ty; + + /* end position */ + if (!vertical) + { + tx = x + width; + ty = y; + } + else + { + tx = x; + ty = y - p->ydirection * height; + } + pdc_transform_point(&m, tx, ty, &tx, &ty); + fitres->end.x = tx; + fitres->end.y = ty; + + /* relative vector from start to end */ + tx = fitres->end.x - fitres->start.x; + ty = fitres->end.y - fitres->start.y; + vlen = sqrt(tx * tx + ty * ty); + if (!vertical) + { + /* width and x scaling */ + fitres->width = vlen; + fitres->mwidth = vlen + mwidth; + fitres->scale.x = fitres->width / width; + + /* unit vector of base line */ + fitres->writingdir.x = tx / vlen; + fitres->writingdir.y = ty / vlen; + + /* relative vector of fontsize */ + tx = x; + ty = y + p->ydirection * height; + pdc_transform_point(&m, tx, ty, &tx, &ty); + tx -= fitres->start.x; + ty -= fitres->start.y; + vlen = sqrt(tx * tx + ty * ty); + + /* height and y scaling */ + fitres->height = vlen; + fitres->mheight = vlen + mheight; + fitres->scale.y = fitres->height / height; + } + else + { + /* height and y scaling */ + fitres->height = vlen; + fitres->mheight = vlen + mheight; + fitres->scale.y = fitres->height / height; + + /* unit vector of perpendiculardir line */ + fitres->writingdir.x = tx / vlen; + fitres->writingdir.y = ty / vlen; + + /* relative vector of width */ + tx = x + width; + ty = y; + pdc_transform_point(&m, tx, ty, &tx, &ty); + tx -= fitres->start.x; + ty -= fitres->start.y; + vlen = sqrt(tx * tx + ty * ty); + + /* width ans x scaling */ + fitres->width = vlen; + fitres->mwidth = vlen + mwidth; + fitres->scale.x = fitres->width / width; + } + + /* unit vector of perpendiculardir line */ + fitres->perpendiculardir.x = tx / vlen; + fitres->perpendiculardir.y = ty / vlen; + + /* rotation angle of base line */ + fitres->angle = atan2(fitres->writingdir.y, fitres->writingdir.x) / + PDC_DEG2RAD; + + /* font specifics */ + fitres->ascender = pdc_transform_scalar(&m, ascender); + fitres->capheight = pdc_transform_scalar(&m, capheight); + fitres->xheight = pdc_transform_scalar(&m, xheight); + fitres->descender = pdc_transform_scalar(&m, descender); + } + else + { + /* CTM */ + pdf_concat_raw(p, &m); + + /* set text position */ + pdf__set_text_pos(p, x, y); + + + /* place text */ + pdf_place_text(p, utext, len, charlen, to, width, height, pdc_false); + + + /* create a link - deprecated - */ + if (to->link) + { + pdf_check_textstring(p, to->text, to->textlen, + PDF_USE_TMPALLOC | PDF_KEEP_UNICODE, + to, &utext, &len, &charlen, pdc_true); + pdf_create_link(p, to->linktype, x, y + p->ydirection * descender, + x + width, y + p->ydirection * to->fontsize, + to->link, (char *) utext, len); + pdc_free_tmp(p->pdc, utext); + } + } + + return unmapgids; +} + +void +pdf_calculate_textline_size(PDF *p, pdf_text_options *to, pdf_fit_options *fit, + pdc_scalar *width, pdc_scalar *height) +{ + pdf_ppt *ppt = p->curr_ppt; + pdf_fittext fitres; + pdc_matrix ctminv; + + /* calculate textline size for table cells */ + fitres.width = 0.0; + fitres.height = 0.0; + pdf_fit_textline_internal(p, &fitres, to, fit, NULL); + + pdc_invert_matrix(p->pdc, &ctminv, &ppt->gstate[ppt->sl].ctm); + if (width) + *width = pdc_transform_scalar(&ctminv, fitres.mwidth); + if (height) + *height = pdc_transform_scalar(&ctminv, fitres.mheight); +} + +void +pdf__fit_textline(PDF *p, const char *text, int len, pdc_scalar x, pdc_scalar y, + const char *optlist) +{ + pdf_ppt *ppt = p->curr_ppt; + pdf_tstate *ts; + pdf_text_options to; + pdf_fit_options fit; + pdc_matrix ctminv; + pdc_scalar currtx, currty; + + pdc_check_number(p->pdc, "x", x); + pdc_check_number(p->pdc, "y", y); + + /* parse options */ + if (!pdf_parse_textline_options(p, text, len, &to, &fit, optlist)) + return; + + fit.refpoint[0] = x; + fit.refpoint[1] = y; + + pdf__save(p); + + /* output text line */ + pdf_fit_textline_internal(p, NULL, &to, &fit, NULL); + pdf_cleanup_fit_options(p, &fit); + + ts = &ppt->tstate[ppt->sl]; + pdc_transform_point(&ppt->gstate[ppt->sl].ctm, + ts->currtx, ts->currty, &currtx, &currty); + + pdf__restore(p); + + /* calculate current text position*/ + pdc_invert_matrix(p->pdc, &ctminv, &ppt->gstate[ppt->sl].ctm); + pdc_transform_point(&ctminv, currtx, currty, &currtx, &currty); + pdf__set_text_pos(p, currtx, currty); +} + +static const pdc_keyconn pdf_info_keylist[] = +{ + {"startx", 1}, + {"starty", 2}, + {"endx", 3}, + {"endy", 4}, + {"writingdirx", 5}, + {"writingdiry", 6}, + {"perpendiculardirx", 7}, + {"perpendiculardiry", 8}, + {"scalex", 9}, + {"scaley", 10}, + {"width", 11}, + {"height", 12}, + {"ascender", 13}, + {"capheight", 14}, + {"xheight", 15}, + {"descender", 16}, + {"unmappedglyphs", 17}, + {"angle", 18}, + {NULL, 0} +}; + +double +pdf__info_textline(PDF *p, const char *text, int len, const char *keyword, + const char *optlist) +{ + pdf_ppt *ppt = p->curr_ppt; + pdf_text_options to; + pdf_fit_options fit; + pdf_fittext fitres; + double tinfo = 0; + int retval, infokey; + + if (!keyword || !*keyword) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "keyword", 0, 0, 0); + + infokey = pdc_get_keycode_ci(keyword, pdf_info_keylist); + if (infokey == PDC_KEY_NOTFOUND) + pdc_error(p->pdc, PDC_E_ILLARG_STRING, "keyword", keyword, 0, 0); + + /* parse options */ + retval = pdf_parse_textline_options(p, text, len, &to, &fit, optlist); + + if (retval) + { + /* calculate textline */ + retval = pdf_fit_textline_internal(p, &fitres, &to, &fit, NULL); + pdf_cleanup_fit_options(p, &fit); + + if (retval > -1) + { + pdf_font *currfont = &p->fonts[to.font]; + pdc_matrix ctminv; + + pdc_invert_matrix(p->pdc, &ctminv, &ppt->gstate[ppt->sl].ctm); + + switch(infokey) + { + case 1: + case 2: + pdc_transform_vector(&ctminv, &fitres.start, NULL); + break; + + case 3: + case 4: + pdc_transform_vector(&ctminv, &fitres.end, NULL); + break; + + case 5: + case 6: + pdc_transform_rvector(&ctminv, &fitres.writingdir, NULL); + break; + + case 7: + case 8: + pdc_transform_rvector(&ctminv, &fitres.perpendiculardir, NULL); + break; + } + + pdc_logg_cond(p->pdc, 1, trc_text, + "\tInfo textline%s:\n" + "\tstartx = %f\n" + "\tstarty = %f\n" + "\tendx = %f\n" + "\tendy = %f\n" + "\twritingdirx = %f\n" + "\twritingdiry = %f\n" + "\tperpendiculardirx = %f\n" + "\tperpendiculardiry = %f\n" + "\tscalex = %f\n" + "\tscaley = %f\n" + "\twidth = %f\n" + "\theight = %f\n" + "\tascender = %f\n" + "\tcapheight = %f\n" + "\txheight = %f\n" + "\tdescender = %f\n", + currfont->ft.vertical ? " (vertical writing mode)" : "", + fitres.start.x, fitres.start.y, + fitres.end.x, fitres.end.y, + fitres.writingdir.x, fitres.writingdir.y, + fitres.perpendiculardir.x, fitres.perpendiculardir.y, + fitres.scale.x, fitres.scale.y, + fitres.width, fitres.height, + fitres.ascender, fitres.capheight, + fitres.xheight,fitres.descender); + + switch(infokey) + { + case 1: + tinfo = (double) fitres.start.x; + break; + + case 2: + tinfo = (double) fitres.start.y; + break; + + case 3: + tinfo = (double) fitres.end.x; + break; + + case 4: + tinfo = (double) fitres.end.y; + break; + + case 5: + tinfo = (double) fitres.writingdir.x; + break; + + case 6: + tinfo = (double) fitres.writingdir.y; + break; + + case 7: + tinfo = (double) fitres.perpendiculardir.x; + break; + + case 8: + tinfo = (double) fitres.perpendiculardir.y; + break; + + case 9: + tinfo = (double) fitres.scale.x; + break; + + case 10: + tinfo = (double) fitres.scale.y; + break; + + case 11: + tinfo = (double) fitres.width; + break; + + case 12: + tinfo = (double) fitres.height; + break; + + case 13: + tinfo = (double) fitres.ascender; + break; + + case 14: + tinfo = (double) fitres.capheight; + break; + + case 15: + tinfo = (double) fitres.xheight; + break; + + case 16: + tinfo = (double) fitres.descender; + break; + + case 17: + tinfo = (double) retval; + break; + + case 18: + tinfo = (double) fitres.angle; + break; + } + } + } + + return tinfo; +} + + + +/*****************************************************************************/ +/** deprecated historical text formatting function **/ +/*****************************************************************************/ + +/* this helper function returns the width of the null-terminated string +** 'text' for the current font and size EXCLUDING the last character's +** additional charspacing. +*/ +static pdc_scalar +pdf_swidth(PDF *p, const char *text) +{ + pdf_text_options *currto = p->curr_ppt->currto; + + pdc_scalar width = pdf_calculate_textsize(p, + (pdc_byte *) text, (int)strlen(text), 1, + currto, -1, NULL, pdc_true); + return (width - currto->horizscaling * currto->charspacing); +} + +static void +pdf_show_aligned(PDF *p, const char *text, pdc_scalar x, pdc_scalar y, + pdc_scalar wordspacing, pdf_alignment mode) +{ + if (!text) + return; + + switch (mode) { + default: + case text_left: + case text_justify: + case text_fulljustify: + /* nothing extra here... */ + break; + + case text_right: + x -= pdf_swidth(p, text); + break; + + case text_center: + x -= pdf_swidth(p, text) / 2; + break; + } + + pdf__set_text_pos(p, x, y); + pdf_set_tstate(p, wordspacing, to_wordspacing); + pdf__show_text(p, text, (int) strlen(text), pdc_false); +} + +int +pdf__show_boxed( + PDF *p, + const char *text, int len, + pdc_scalar left, + pdc_scalar bottom, + pdc_scalar width, + pdc_scalar height, + const char *hmode, + const char *feature) +{ + pdc_scalar old_wordspacing, wordspacing, textwidth, curx, cury; + pdc_bool prematureexit; /* return because box is too small */ + int curTextPos; /* character currently processed */ + int lastdone; /* last input character processed */ + int toconv = len; + pdf_text_options *currto = p->curr_ppt->currto; + pdf_font *currfont; + pdc_byte *utext = NULL; + pdc_text_format old_textformat; + pdf_alignment mode = text_left; + pdc_bool blind = pdc_false; + + /* text length */ + if (text == NULL) + return 0; + if (!len) + len = (int) strlen(text); + if (!len) + return 0; + + pdc_check_number(p->pdc, "left", left); + pdc_check_number(p->pdc, "bottom", bottom); + pdc_check_number(p->pdc, "width", width); + pdc_check_number(p->pdc, "height", height); + + if (hmode == NULL || *hmode == '\0') + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "hmode", 0, 0, 0); + + if (!strcmp(hmode, "left")) + mode = text_left; + else if (!strcmp(hmode, "right")) + mode = text_right; + else if (!strcmp(hmode, "center")) + mode = text_center; + else if (!strcmp(hmode, "justify")) + mode = text_justify; + else if (!strcmp(hmode, "fulljustify")) + mode = text_fulljustify; + else + pdc_error(p->pdc, PDC_E_ILLARG_STRING, "hmode", hmode, 0, 0); + + if (feature != NULL && *feature != '\0') + { + if (!strcmp(feature, "blind")) + blind = pdc_true; + else + pdc_error(p->pdc, PDC_E_ILLARG_STRING, "feature", feature, 0, 0); + } + + /* no font set */ + if (currto->font == -1) + pdc_error(p->pdc, PDF_E_TEXT_NOFONT, 0, 0, 0, 0); + currfont = &p->fonts[currto->font]; + + if (width == 0 && height != 0) + pdc_error(p->pdc, PDC_E_ILLARG_FLOAT, + "width", pdc_errprintf(p->pdc, "%f", width), 0, 0); + + if (width != 0 && height == 0) + pdc_error(p->pdc, PDC_E_ILLARG_FLOAT, + "height", pdc_errprintf(p->pdc, "%f", height), 0, 0); + + if (currfont->ft.vertical) + { + pdc_error(p->pdc, PDF_E_DOC_FUNCUNSUPP, "vertical writing mode", + 0, 0, 0); + } + + /* we cannot handle several encodings */ + if (currfont->ft.enc == pdc_unicode) + { + pdc_error(p->pdc, PDF_E_DOC_FUNCUNSUPP, "Unicode", 0, 0, 0); + } + + if (currfont->ft.enc == pdc_glyphid) + { + pdc_error(p->pdc, PDF_E_DOC_FUNCUNSUPP, "glyphid", 0, 0, 0); + } + + if (currfont->ft.enc == pdc_cid) + { + pdc_error(p->pdc, PDF_E_DOC_FUNCUNSUPP, "CID", 0, 0, 0); + } + + if (currfont->ft.enc == pdc_ebcdic || + currfont->ft.enc == pdc_ebcdic_37 || + currfont->ft.enc == pdc_ebcdic_winansi) + { + pdc_error(p->pdc, PDF_E_DOC_FUNCUNSUPP, "EBCDIC", 0, 0, 0); + } + + /* old wordspacing */ + old_textformat = currto->textformat; + + /* convert text string */ + if (toconv) + { + int charlen; + + /* convert text string */ + pdf_check_textstring(p, text, len, + PDF_KEEP_CONTROL | PDF_KEEP_TEXTLEN | PDF_USE_TMPALLOC, + currto, &utext, &len, &charlen, pdc_true); + if (utext == NULL || !len) + return 0; + + utext[len] = 0; + text = (const char *) utext; + currto->textformat = pdc_bytes; + } + + /* old wordspacing */ + old_wordspacing = currto->wordspacing; + + /* special case for a single aligned line */ + if (width == 0 && height == 0) + { + if (!blind) + pdf_show_aligned(p, text, left, bottom, old_wordspacing, mode); + + if (toconv) + currto->textformat = old_textformat; + return 0; + } + + curx = left; + cury = bottom + p->ydirection * height; + prematureexit = pdc_false; + curTextPos = 0; + lastdone = 0; + + /* switch curx for right and center justification */ + if (mode == text_right) + curx += width; + else if (mode == text_center) + curx += (width / 2); + +#define MAX_CHARS_IN_LINE 2048 + + /* loop until all characters processed, or box full */ + + while ((curTextPos < len) && !prematureexit) + { + /* buffer for constructing the line */ + char linebuf[MAX_CHARS_IN_LINE]; + int curCharsInLine = 0; /* # of chars in constructed line */ + int lastWordBreak = 0; /* the last seen space char */ + int wordBreakCount = 0; /* # of blanks in this line */ + + /* loop over the input string */ + while (curTextPos < len) + { + if (curCharsInLine >= MAX_CHARS_IN_LINE) + pdc_error(p->pdc, PDC_E_ILLARG_TOOLONG, "(text line)", + pdc_errprintf(p->pdc, "%d", MAX_CHARS_IN_LINE-1), 0, 0); + + /* abandon DOS line-ends */ + if (text[curTextPos] == PDF_RETURN && + text[curTextPos+1] == PDF_NEWLINE) + curTextPos++; + + /* if it's a forced line break draw the line */ + if (text[curTextPos] == PDF_NEWLINE || + text[curTextPos] == PDF_RETURN) + { + cury -= p->ydirection * currto->leading; + + if (p->ydirection * (cury - bottom) < 0) { + prematureexit = pdc_true; /* box full */ + break; + } + + linebuf[curCharsInLine] = 0; /* terminate the line */ + + /* check whether the line is too long */ + wordspacing = 0; + pdf_set_tstate(p, wordspacing, to_wordspacing); + textwidth = pdf_swidth(p, linebuf); + + /* the forced break occurs too late for this line */ + if (textwidth > width) + { + if (wordBreakCount == 0) { /* no blank found */ + prematureexit = pdc_true; + break; + } + linebuf[lastWordBreak] = 0; /* terminate at last blank */ + if (curTextPos > 0 && text[curTextPos-1] == PDF_RETURN) + --curTextPos; + curTextPos -= (curCharsInLine - lastWordBreak); + + if (!blind) + { + textwidth = pdf_swidth(p, linebuf); + if (wordBreakCount != 1 && + (mode == text_justify || + mode == text_fulljustify)) + { + wordspacing = (width - textwidth) / + ((wordBreakCount - 1) * currto->horizscaling); + } + pdf_show_aligned(p, linebuf, curx, cury, wordspacing, + mode); + } + } + else if (!blind) + { + if (mode == text_fulljustify && wordBreakCount > 0) + { + wordspacing = (width - textwidth) / + (wordBreakCount * currto->horizscaling); + } + pdf_show_aligned(p, linebuf, curx, cury, wordspacing, mode); + } + + lastdone = curTextPos; + curCharsInLine = lastWordBreak = wordBreakCount = 0; + curTextPos++; + + } + else if (text[curTextPos] == PDF_SPACE) + { + linebuf[curCharsInLine] = 0; /* terminate the line */ + + /* line too long ==> break at last blank */ + wordspacing = 0; + pdf_set_tstate(p, wordspacing, to_wordspacing); + if (pdf_swidth(p, linebuf) > width) + { + cury -= p->ydirection * currto->leading; + + if (p->ydirection * (cury - bottom) < 0) + { + prematureexit = pdc_true; /* box full */ + break; + } + + linebuf[lastWordBreak] = 0; /* terminate at last blank */ + curTextPos -= (curCharsInLine - lastWordBreak - 1); + + if (lastWordBreak == 0) + curTextPos--; + + /* LATER: * force break if wordBreakCount == 1, + * i.e., no blank + */ + if (wordBreakCount == 0) + { + prematureexit = pdc_true; + break; + } + + /* adjust word spacing for full justify */ + if (wordBreakCount != 1 && (mode == text_justify || + mode == text_fulljustify)) + { + textwidth = pdf_swidth(p, linebuf); + wordspacing = (width - textwidth) / + ((wordBreakCount - 1) * currto->horizscaling); + } + + lastdone = curTextPos; + if (!blind) + { + pdf_show_aligned(p, linebuf, curx, cury, wordspacing, + mode); + } + curCharsInLine = lastWordBreak = wordBreakCount = 0; + } + else + { + /* blank found, and line still fits */ + wordBreakCount++; + lastWordBreak = curCharsInLine; + linebuf[curCharsInLine++] = text[curTextPos++]; + } + } + else + { + /* regular character ==> store in buffer */ + linebuf[curCharsInLine++] = text[curTextPos++]; + } + } + + if (prematureexit) { + break; /* box full */ + } + + /* if there is anything left in the buffer, draw it */ + if (curTextPos >= len && curCharsInLine != 0) + { + cury -= p->ydirection * currto->leading; + + if (p->ydirection * (cury - bottom) < 0) + { + prematureexit = pdc_true; /* box full */ + break; + } + + linebuf[curCharsInLine] = 0; /* terminate the line */ + + /* check if the last line is too long */ + wordspacing = 0; + pdf_set_tstate(p, wordspacing, to_wordspacing); + textwidth = pdf_swidth(p, linebuf); + + if (textwidth > width) + { + if (wordBreakCount == 0) + { + prematureexit = pdc_true; + break; + } + + linebuf[lastWordBreak] = 0; /* terminate at last blank */ + curTextPos -= (curCharsInLine - lastWordBreak - 1); + + /* recalculate the width */ + textwidth = pdf_swidth(p, linebuf); + + /* adjust word spacing for full justify */ + if (wordBreakCount != 1 && (mode == text_justify || + mode == text_fulljustify)) + { + wordspacing = (width - textwidth) / + ((wordBreakCount - 1) * currto->horizscaling); + } + } + else if (!blind) + { + if (mode == text_fulljustify && wordBreakCount) + { + wordspacing = (width - textwidth) / + (wordBreakCount * currto->horizscaling); + } + } + + lastdone = curTextPos; + if (!blind) + { + pdf_show_aligned(p, linebuf, curx, cury, wordspacing, mode); + } + curCharsInLine = lastWordBreak = wordBreakCount = 0; + } + } + + pdf_set_tstate(p, old_wordspacing, to_wordspacing); + + /* return number of remaining characters */ + + while (text[lastdone] == PDF_SPACE) + ++lastdone; + + if ((text[lastdone] == PDF_RETURN || + text[lastdone] == PDF_NEWLINE) && text[lastdone+1] == 0) + ++lastdone; + + if (toconv) + currto->textformat = old_textformat; + + return (int) (len - lastdone); +} diff --git a/src/pdflib/pdflib/p_textflow.c b/src/pdflib/pdflib/p_textflow.c new file mode 100644 index 0000000..006facb --- /dev/null +++ b/src/pdflib/pdflib/p_textflow.c @@ -0,0 +1,27 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_textflow.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib textflow function + * + */ + +#define P_TEXTFLOW_C + +#include "p_intern.h" +#include "p_color.h" +#include "p_font.h" +#include "p_defopt.h" +#include "p_tagged.h" + + diff --git a/src/pdflib/pdflib/p_tiff.c b/src/pdflib/pdflib/p_tiff.c new file mode 100644 index 0000000..5ed382f --- /dev/null +++ b/src/pdflib/pdflib/p_tiff.c @@ -0,0 +1,1169 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_tiff.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * TIFF processing for PDFlib + * + */ + +#include "p_intern.h" +#include "p_color.h" +#include "p_image.h" + +#ifndef HAVE_LIBTIFF + +pdc_bool /* CDPDF fixed last parameter declaration */ +pdf_is_TIFF_file(PDF *p, pdc_file *fp, pdf_tiff_info *tiff, pdc_bool check) +{ + (void) p; + (void) fp; + (void) tiff; + (void) check; + + return pdc_false; +} + +int +pdf_process_TIFF_data( + PDF *p, + int imageslot) +{ + pdf_image *image = &p->images[imageslot]; + + pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "TIFF", 0, 0, 0); + + return -1; +} + +#else + +#include "tiffiop.h" +static tsize_t +pdf_libtiff_read(void* fd, tdata_t buf, tsize_t size) +{ + pdc_file *fp = (pdc_file *) fd; + + return ((tsize_t) pdc_fread(buf, 1, (size_t) size, fp)); +} + +static toff_t +pdf_libtiff_seek(void* fd, toff_t off, int whence) +{ + pdc_file *fp = (pdc_file *) fd; + + return ((toff_t) pdc_fseek(fp, (long) off, whence)); +} + +static int +pdf_libtiff_close(void* fd) +{ + (void) fd; + + /* pdc_fclose(fp); this happens in caller function */ + + return 0; +} + +static toff_t +pdf_libtiff_size(void* fd) +{ + pdc_file *fp = (pdc_file *) fd; + + return (toff_t) pdc_file_size(fp); +} + +static void * +pdf_libtiff_malloc(TIFF *t, tsize_t size) +{ + PDF *p = (PDF*) t->pdflib_opaque; + return pdc_calloc(p->pdc, (size_t)size, "libtiff"); +} + +static void * +pdf_libtiff_realloc(TIFF *t, tdata_t mem, tsize_t size) +{ + PDF *p = (PDF*) t->pdflib_opaque; + return(pdc_realloc(p->pdc, (void*)mem, (size_t)size, "libtiff")); +} + +static void +pdf_libtiff_free(TIFF *t, tdata_t mem) +{ + PDF *p = (PDF*) t->pdflib_opaque; + pdc_free(p->pdc, (void*)mem); +} + +#define PDF_TIFF_LENGTH_MAX 512 +static void +pdf_libtiff_error(TIFF *t, const char* module, const char* fmt, va_list ap) +{ + PDF *p = (PDF*) t->pdflib_opaque; + + if (pdc_logg_is_enabled(p->pdc, 5, trc_image)) + { + char buffer[PDF_TIFF_LENGTH_MAX]; + + /* Create the message */ + pdc_vsnprintf(buffer, PDF_TIFF_LENGTH_MAX, fmt, ap); + pdc_logg(p->pdc, "\tlibtiff(%s): %s\n", module, buffer); + } +} + +static void +pdf_data_source_TIFF_init(PDF *p, PDF_data_source *src) +{ + static const char *fn = "pdf_data_source_TIFF_init"; + pdf_image *image; + + image = (pdf_image *) src->private_data; + + if (image->strips == 1) + image->info.tiff.cur_line = 0; + + if (image->use_raw) + { + /* malloc is done in the fill function */ + src->buffer_length = (size_t) 0; + src->buffer_start = (pdc_byte *) NULL; + } + else + { + if (image->bpc == 1) + src->buffer_length = + (size_t) (image->components * ((int) image->width+7)/8); + else + src->buffer_length = + (size_t) (image->components * image->width); + + src->buffer_start = (pdc_byte *) + pdc_malloc(p->pdc, src->buffer_length, fn); + } +} + +/* Convert the a and b samples of Lab data from signed to unsigned. */ + +static void +pdf_signed_to_unsigned(pdc_byte *buf, size_t count) +{ + size_t i; + + for(i=0; i < count; i+=3) + { + buf[i+1] ^= 0x80; + buf[i+2] ^= 0x80; + } +} + +#define MYTIFF image->info.tiff.tif + +static pdc_bool +pdf_data_source_TIFF_fill(PDF *p, PDF_data_source *src) +{ + static const char *fn = "pdf_data_source_TIFF_fill"; + pdf_image *image; + int col; + pdc_byte *dest; + uint16 fillorder; + uint32 *s, *bc; + + image = (pdf_image *) src->private_data; + + PDC_TRY(p->pdc) + { + if (image->use_raw) + { + if (image->info.tiff.cur_line == image->strips) + { + PDC_EXIT_TRY(p->pdc); + return pdc_false; + } + + TIFFGetField(MYTIFF, TIFFTAG_STRIPBYTECOUNTS, &bc); + + if (bc[image->info.tiff.cur_line] > src->buffer_length) + { + src->buffer_length = bc[image->info.tiff.cur_line]; + src->buffer_start = (pdc_byte *) + pdc_realloc(p->pdc, src->buffer_start, + src->buffer_length, fn); + } + + if (TIFFReadRawStrip(MYTIFF, (tstrip_t) image->info.tiff.cur_line, + (tdata_t) src->buffer_start, + (tsize_t) bc[image->info.tiff.cur_line]) == -1) + { + pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "TIFF", + pdf_get_image_filename(p, image), 0, 0); + } + + src->next_byte = src->buffer_start; + src->bytes_available = bc[image->info.tiff.cur_line]; + + /* special handling for uncompressed 16-bit images */ + if (MYTIFF->tif_header.tiff_magic == TIFF_LITTLEENDIAN && + image->compression == pdf_comp_none && image->bpc == 16) + { + TIFFSwabArrayOfShort((uint16 *) src->buffer_start, + (unsigned long) src->bytes_available/2); + } + + if (TIFFGetField(MYTIFF, TIFFTAG_FILLORDER, &fillorder) + && (fillorder == FILLORDER_LSB2MSB)) + { + TIFFReverseBits((unsigned char *) src->buffer_start, + (unsigned long) src->bytes_available); + } + + /* The a and b values of (uncompressed) Lab must be adjusted */ + if (p->colorspaces[image->colorspace].type == Lab) + { + pdf_signed_to_unsigned(src->buffer_start, src->bytes_available); + } + + if (image->strips > 1) + { + /* only a single strip of a multi-strip image */ + image->info.tiff.cur_line = image->strips; + } + else + image->info.tiff.cur_line++; + } + else + { + if (image->info.tiff.cur_line++ == image->height) + { + PDC_EXIT_TRY(p->pdc); + return pdc_false; + } + + src->next_byte = src->buffer_start; + src->bytes_available = src->buffer_length; + + dest = src->buffer_start; + s = image->info.tiff.raster + + ((int)image->height - image->info.tiff.cur_line) * + (int) image->width; + + switch (image->components) + { + case 1: + if (image->bpc == 1) + { + unsigned char mask; + + memset((void*) dest, 0, src->buffer_length); + + for (mask=0x80, col = 0; col < image->width; col++) + { + if (TIFFGetR(*s++) != 0) + *dest |= mask; + + if ((mask>>=1) == 0) + { + mask = 0x80; + ++dest; + } + } + } + else /* bpc == 8 */ + { + for (col = 0; col < image->width; col++, s++) + { + *dest++ = (pdc_byte) TIFFGetR(*s); + } + } + break; + + case 3: + for (col = 0; col < image->width; col++, s++) + { + *dest++ = (pdc_byte) TIFFGetR(*s); + *dest++ = (pdc_byte) TIFFGetG(*s); + *dest++ = (pdc_byte) TIFFGetB(*s); + } + break; + + case 4: + for (col = 0; col < image->width; col++, s++) + { + unsigned char* t = (unsigned char*)&(*s); + *dest++ = (pdc_byte) t[0]; + *dest++ = (pdc_byte) t[1]; + *dest++ = (pdc_byte) t[2]; + *dest++ = (pdc_byte) t[3]; + } + break; + + default: + pdc_error(p->pdc, PDF_E_IMAGE_BADCOMP, + pdc_errprintf(p->pdc, "%d", image->components), + pdf_get_image_filename(p, image), 0, 0); + } + } + } + PDC_CATCH(p->pdc) + { + image->corrupt = pdc_true; + } + + return !image->corrupt; +} + +static void +pdf_data_source_TIFF_terminate(PDF *p, PDF_data_source *src) +{ + pdc_free(p->pdc, (void *) src->buffer_start); +} + +static int +pdf_check_colormap(int n, uint16* r, uint16* g, uint16* b) +{ + while (n-- > 0) + if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) + return(16); + return(8); +} + +pdc_bool +pdf_is_TIFF_file(PDF *p, pdc_file *fp, pdf_tiff_info *tiff_info, pdc_bool check) +{ + const char *filename; + + pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type TIFF...\n"); + + filename = pdc_file_name(fp); + tiff_info->tif = TIFFClientOpen(filename, "rc", + (void *)fp, + pdf_libtiff_read, NULL, + pdf_libtiff_seek, pdf_libtiff_close, pdf_libtiff_size, + NULL, NULL, (void *)p, + pdf_libtiff_malloc, pdf_libtiff_realloc, pdf_libtiff_free, + pdf_libtiff_error, pdf_libtiff_error); + if (tiff_info->tif == NULL) + { + pdc_fseek(fp, 0L, SEEK_SET); + return pdc_false; + } + if (check) + TIFFClose(tiff_info->tif); + return pdc_true; +} + +int +pdf_process_TIFF_data( + PDF *p, + int imageslot) +{ + static const char *fn = "pdf_process_TIFF_data"; + uint32 w, h; + uint16 unit, bpc, compression, photometric, extra, *sinfo; + uint16 orientation, planarconfig; + uint16 *rmap, *gmap, *bmap; + tsample_t components; + pdf_image *image; + float res_x, res_y; /* sic! */ + pdf_colorspace cs; + int slot; + int errint = 0; + int errcode = 0; + pdc_bool isopen = pdc_false; + int strips; + + image = &p->images[imageslot]; + + image->info.tiff.raster = (uint32 *) NULL; + + if (!pdf_is_TIFF_file(p, image->fp, &image->info.tiff, pdc_false)) + { + errcode = PDF_E_IMAGE_CORRUPT; + goto PDF_TIFF_ERROR; + } + + MYTIFF->tif_fd = (FILE*) image->fp; + isopen = pdc_true; + + if (image->page != 1) + { + if (TIFFSetDirectory(MYTIFF, (tdir_t) (image->page - 1)) != 1 ) + { + errint = image->page; + errcode = PDF_E_IMAGE_NOPAGE; + goto PDF_TIFF_ERROR; + } + } + + TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_ORIENTATION, &orientation); + image->orientation = orientation; + + TIFFGetField(MYTIFF, TIFFTAG_COMPRESSION, &compression); + + TIFFGetField(MYTIFF, TIFFTAG_IMAGEWIDTH, &w); + image->width = (pdc_scalar) w; + + TIFFGetField(MYTIFF, TIFFTAG_IMAGELENGTH, &h); + image->height = (pdc_scalar) h; + + TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_BITSPERSAMPLE, &bpc); + image->bpc = bpc; + + TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_SAMPLESPERPIXEL, &components); + image->components = components; + + TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_EXTRASAMPLES, &extra, &sinfo); + + TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_PLANARCONFIG, &planarconfig); + + photometric = 255; /* dummy value */ + TIFFGetField(MYTIFF, TIFFTAG_PHOTOMETRIC, &photometric); + + /* fetch the resolution values if found in the file */ + if (TIFFGetField(MYTIFF, TIFFTAG_XRESOLUTION, &res_x) && + TIFFGetField(MYTIFF, TIFFTAG_YRESOLUTION, &res_y) && + TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_RESOLUTIONUNIT, &unit) && + res_x > 0 && res_y > 0) { + + if (unit == RESUNIT_INCH) { + image->dpi_x = res_x; + image->dpi_y = res_y; + + } else if (unit == RESUNIT_CENTIMETER) { + image->dpi_x = res_x * 2.54; + image->dpi_y = res_y * 2.54; + + } else if (unit == RESUNIT_NONE) { + image->dpi_x = -res_x; + image->dpi_y = -res_y; + } + +#define PDF_REALLY_BIG_DPI 10000 + + /* Guard against obviously wrong values */ + if (unit != RESUNIT_NONE && + (image->dpi_x <= 1 || + image->dpi_y <= 1 || + image->dpi_x > PDF_REALLY_BIG_DPI || + image->dpi_y > PDF_REALLY_BIG_DPI)) + + image->dpi_x = image->dpi_y = 0; /* unknown */ + } + + + + /* ------------------------------------------------------------ + * Reject unsupported flavors. + * ---------------------------------------------------------- */ + + /* Catch some rare properties related to compression, photometric, + * and bpc which are definitely not supported (neither in pass-through + * mode nor libtiff) in order to provide a better error message than + * the generic "Error reading data". + */ + + /* Unsupported compression types */ + switch ((int) compression) + { + case /* 34661 */ COMPRESSION_JBIG: + case /* 34712 */ COMPRESSION_JP2000: + case 9 /* JBIG T85 */: + case 10 /* TIFF-FX JBIG (T.82) MRC (T.43) */: + case 34715 /* TFX */: + errint = (int) compression; + errcode = PDF_E_TIFF_UNSUPP_COMPRESSION; + goto PDF_TIFF_ERROR; + break; + + default: + break; + } + + /* Unsupported photometric values */ + switch ((int) photometric) + { + case PHOTOMETRIC_ICCLAB /* 9 */: + case PHOTOMETRIC_ITULAB /* 10 */: + errint = (int) photometric; + errcode = PDF_E_TIFF_UNSUPP_COLORSPACE; + goto PDF_TIFF_ERROR; + break; + + default: + break; + } + + /* 32-bit images are not supported */ + if (image->bpc > 16) + { + errcode = PDF_E_TIFF_16BIT_UNSUPP; + goto PDF_TIFF_ERROR; + } + + /* We don't support 16-bit CMYK unless it's uncompressed */ + if (image->bpc == 16 && components == 4 && compression != COMPRESSION_NONE) + { + errcode = PDF_E_TIFF_16BITCMYK_UNSUPP; + goto PDF_TIFF_ERROR; + } + + + /* ------------------------------------------------------------ + * We assume pass-through mode in the beginning, and disable it + * for image types where it doesn't work. + * ---------------------------------------------------------- */ + + image->use_raw = image->passthrough; + + /* Pass-through is not implemented for tiled images */ + if (TIFFIsTiled(MYTIFF)) + image->use_raw = pdc_false; + + + + /* Can't handle these colorspaces in raw mode (except with OJPEG) */ + if (compression != COMPRESSION_OJPEG && + (photometric == PHOTOMETRIC_YCBCR || + photometric == PHOTOMETRIC_CIELAB || + photometric == PHOTOMETRIC_MASK)) + { + image->use_raw = pdc_false; + } + + /* Can't pass through extra bits or use multiple data sources in raw mode + * (except with OJPEG). + */ + if (extra != 0 || + (compression != COMPRESSION_OJPEG && + planarconfig == PLANARCONFIG_SEPARATE && components > 1)) + { + image->components -= extra; /* ignore the extra channels */ + image->use_raw = pdc_false; + } + + /* PDF doesn't support other values of the color depth */ + if (bpc != 1 && bpc != 2 && bpc != 4 && bpc != 8 && bpc != 16) + image->use_raw = pdc_false; + + /* Disable pass-through for a large number of strips to avoid + * file size bloat (due to many small Image XObjects) and + * ugly display in Acrobat (because of banding artifacts). + * The threshold for the number of strips has been determined empirically + * as a good compromise between file size and performance. + * + * We must still maintain pass-through mode for those cases where it + * is functionally more advanced, and benefit from its better performance + * for small numbers of strips. + * + * Also, we maintain pass-through mode for very large images since + * pass-through mode - especially with pixel mode (RGBA retrieval) - + * may run out of memory. + */ + +/* ca. 10K x 10K pixels (nopassthrough requires up to 4 times as many bytes!) */ +#define PDF_TIFF_THRESHOLD 0x6000000 + + strips = (int) TIFFNumberOfStrips(MYTIFF); + + if (strips > 25 && + compression != COMPRESSION_OJPEG && compression != COMPRESSION_JPEG && + photometric != PHOTOMETRIC_PALETTE && + image->width * image->width < PDF_TIFF_THRESHOLD) + { + image->use_raw = pdc_false; + } + + if (image->bpc == 16) + { + /* PDF < 1.5 doesn't support 16-bit images, so we cannot pass through */ + if (p->compatibility < PDC_1_5) + { + image->use_raw = pdc_false; + } + + /* + * PDF requires big-endian 16-bit data. We therefore use passthrough + * mode only for big-endian input or uncompressed data. + * + * It's not nice to pull the endianness directly from the TIFF + * structure, but there doesn't seem to be a public interface for it. + */ + if (MYTIFF->tif_header.tiff_magic == TIFF_LITTLEENDIAN && + (compression == COMPRESSION_DEFLATE || + compression == COMPRESSION_ADOBE_DEFLATE)) + { + image->use_raw = pdc_false; + } + + /* We don't support 16-bit CMYK unless in passthrough mode. + * Compressed images have already been rejected earlier. + */ + if (components == 4 && image->use_raw == pdc_false) + { + errcode = PDF_E_TIFF_16BITCMYK_UNSUPP; + goto PDF_TIFF_ERROR; + } + } + + /* + * Disable pass-through for unknown compression schemes, + * and collect the necessary parameters for well-known schemes. + */ + + if (image->use_raw == pdc_true) + { + uint32 group3opts; + uint16 predictor; + toff_t jpegifoffset, jpegifbytecount; + + switch ((int) compression) + { + case COMPRESSION_CCITTRLE: + case COMPRESSION_CCITTRLEW: + image->params = (char *) pdc_malloc(p->pdc, PDF_MAX_PARAMSTRING, + fn); + + strcpy(image->params, "/EndOfBlock false"); + strcat(image->params, "/EncodedByteAlign true"); + + if (photometric == PHOTOMETRIC_MINISBLACK) + strcat(image->params, "/BlackIs1 true"); + + image->compression = pdf_comp_ccitt; + break; + + case COMPRESSION_CCITTFAX3: + image->params = (char*) pdc_malloc(p->pdc, PDF_MAX_PARAMSTRING, + fn); + + strcpy(image->params, "/EndOfBlock false"); + + /* The following contains disabled code segments. + * Apparently, and contrary to my reading of the specs, + * the following can not be deduced from the respective + * TIFF entry or option: + * - /EncodedByteAlign can not reliably be deduced from + * GROUP3OPT_FILLBITS; + * + * From practical experience, the respective lines are + * disabled, but I don't have any clear explanation for this. + * A few TIFF images still don't work with this setting, + * unfortunately. + */ + + /* SEE ABOVE! + strcat(image->params, "/DamagedRowsBeforeError 1"); + */ + + if (TIFFGetField(MYTIFF, TIFFTAG_GROUP3OPTIONS, &group3opts)) + { + /* /K = 0 (= G3,1D) is default */ + if (group3opts & GROUP3OPT_2DENCODING) + strcat(image->params, "/K 1"); + + /* SEE ABOVE! + if (group3opts & GROUP3OPT_FILLBITS) + strcat(image->params, "/EncodedByteAlign true"); + */ + } + + if (photometric == PHOTOMETRIC_MINISBLACK) + strcat(image->params, "/BlackIs1 true"); + + image->compression = pdf_comp_ccitt; + break; + + case COMPRESSION_CCITTFAX4: + image->params = (char*) pdc_malloc(p->pdc, PDF_MAX_PARAMSTRING, + fn); + + strcpy(image->params, "/K -1"); + /* Required for bug #511 */ + strcat(image->params, "/EndOfBlock false"); + + if (photometric == PHOTOMETRIC_MINISBLACK) + strcat(image->params, "/BlackIs1 true"); + + image->compression = pdf_comp_ccitt; + break; + + case COMPRESSION_OJPEG: + /* + * Check whether a full-blown JPEG can be found inside the TIFF + * + * Heuristic: + * If we find a positive JPEGIFOFFSET there should be valid + * JFIF data; however, sometimes there isn't and we must not + *call the JPEG module. Strangely enough, various creators which + * do not emit valid JFIF do emit the JPEGIFBYTECOUNT tag. + * Therefore we use the absence of JPEGIFBYTECOUNT as a hint + * that JFIF processing might work. + * + * Known trouble-makers which include JPEGIFBYTECOUNT: + * "Oi/GFS, writer v00.06.02" + */ + if (TIFFGetField(MYTIFF, TIFFTAG_JPEGIFOFFSET, &jpegifoffset) && + jpegifoffset != 0 && + !TIFFGetField(MYTIFF, TIFFTAG_JPEGIFBYTECOUNT, + &jpegifbytecount)) + { + /* stop TIFF processing */ + TIFFClose(MYTIFF); + + /* store data offset for the JPEG module (after TIFFClose() + * the image->info union is no longer used by the TIFF + * module) + */ + image->info.jpeg.jpegifoffset = jpegifoffset; + + /* ...and process the data at the offset as JPEG */ + pdc_logg_cond(p->pdc, 1, trc_image, + "\tTIFF with OJPEG: switching to JPEG processing...\n"); + return pdf_process_JPEG_data(p, imageslot); + } + else + { + /* We must repeat the check here since we omitted the OJPEG + * case when we applied the test for the first time. + */ + if (extra != 0 || + (planarconfig == PLANARCONFIG_SEPARATE && components > 1)) + { + /* ignore the extra channels */ + image->components -= extra; + } + image->use_raw = pdc_false; + } + break; + + case COMPRESSION_NONE: + if (photometric == PHOTOMETRIC_MINISWHITE) + image->invert = !image->invert; + + image->compression = pdf_comp_none; + break; + + case COMPRESSION_LZW: + if (TIFFGetField(MYTIFF, TIFFTAG_PREDICTOR, &predictor)) { + if (predictor != pred_default && predictor != pred_tiff) { + image->use_raw = pdc_false; + break; + } else + image->predictor = (pdf_predictor) predictor; + } + + if (photometric == PHOTOMETRIC_MINISWHITE) + image->invert = !image->invert; + + image->compression = pdf_comp_lzw; + break; + + case COMPRESSION_PACKBITS: + if (photometric == PHOTOMETRIC_MINISWHITE) + image->invert = !image->invert; + + image->compression = pdf_comp_runlength; + break; + + case COMPRESSION_DEFLATE: + case COMPRESSION_ADOBE_DEFLATE: + if (TIFFGetField(MYTIFF, TIFFTAG_PREDICTOR, &predictor)) { + if (predictor != pred_default && predictor != pred_tiff) { + image->use_raw = pdc_false; + break; + } else + image->predictor = (pdf_predictor) predictor; + } + + if (photometric == PHOTOMETRIC_MINISWHITE) + image->invert = !image->invert; + + image->compression = pdf_comp_flate; + break; + + default: + image->use_raw = pdc_false; + } + } + + if (image->use_raw) + { + /* pass-through mode: directly copy chunks of strip data */ + image->strips = strips; + + pdc_logg_cond(p->pdc, 1, trc_image, "\tpassthrough mode...\n"); + } + else + { + /* libtiff cannot handle JPEG-compressed TIFFs with separate image + * planes + */ + if (planarconfig == PLANARCONFIG_SEPARATE && + (compression == COMPRESSION_OJPEG || compression==COMPRESSION_JPEG)) + { + errcode = PDF_E_TIFF_UNSUPP_JPEG_SEPARATE; + goto PDF_TIFF_ERROR; + } + + /* Fallback: use TIFFlib to retrieve pixel data */ + + /* We have special handling for preserving bpc=1 if components=1, + * and therefore don't change bpc in this case. + */ + if (!(image->components == 1 && image->bpc == 1)) + { + /* Retrieve pixel data with libtiff, which converts to 8 bits. */ + image->bpc = 8; + } + + image->strips = 1; + image->compression = pdf_comp_none; + + /* Palette images are automatically converted to RGB by TIFFlib. + * Since there are actually 1-bit images (photometric=min-is-white) + * with a palette out there (which are invalid TIFF, and are not + * converted to RGB by TIFFlib) we must also check photometric. + */ + if (image->components == 1 && photometric == PHOTOMETRIC_PALETTE && + TIFFGetField(MYTIFF, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) + { + image->components = 3; + } + pdc_logg_cond(p->pdc, 1, trc_image, "\tno passthrough mode...\n"); + } + + if (image->imagemask) + { + if (image->components != 1) + { + errcode = PDF_E_IMAGE_BADMASK; + goto PDF_TIFF_ERROR; + } + + if (p->compatibility == PDC_1_3) + { + if (image->components != 1 || image->bpc != 1) + { + errcode = PDF_E_IMAGE_MASK1BIT13; + goto PDF_TIFF_ERROR; + } + } + else if (image->bpc > 1) + { + /* images with more than one bit will be written as /SMask, + * and don't require an /ImageMask entry. + */ + image->imagemask = pdc_false; + } + } + + if (image->mask != pdc_undef) + { + if (image->strips != 1) + { + errcode = PDF_E_TIFF_MASK_MULTISTRIP; + goto PDF_TIFF_ERROR; + } + } + + if (image->colorspace == pdc_undef) + { + uint16 inkset; + + switch (image->components) + { + case 1: + image->colorspace = DeviceGray; + break; + + case 3: + image->colorspace = DeviceRGB; + break; + + case 4: + if (photometric == PHOTOMETRIC_SEPARATED) + { + /* Can't handle CMYK with mask */ + if (extra != 0) + { + errint = image->components; + errcode = PDF_E_TIFF_CMYK_MASK; + goto PDF_TIFF_ERROR; + } + + TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_INKSET, &inkset); + if (inkset != INKSET_CMYK) + { + errint = inkset; + errcode = PDF_E_TIFF_UNSUPP_SEP_NONCMYK; + goto PDF_TIFF_ERROR; + } + image->colorspace = DeviceCMYK; + } + else + { + /* if it's not separated it must be RGB with alpha */ + image->components = 3; + image->colorspace = DeviceRGB; + image->compression = pdf_comp_none; + } + break; + + default: + errint = image->components; + errcode = PDF_E_IMAGE_BADCOMP; + goto PDF_TIFF_ERROR; + } + } + + + image->src.private_data = (void *) image; + image->src.init = pdf_data_source_TIFF_init; + image->src.fill = pdf_data_source_TIFF_fill; + image->src.terminate = pdf_data_source_TIFF_terminate; + + if (image->use_raw) { + uint32 row, rowsperstrip; + int strip; + + /* must handle colormap ourselves */ + if (photometric == PHOTOMETRIC_PALETTE) + { + int i; + pdf_colormap colormap; + + if (!TIFFGetField(MYTIFF, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) + { + errcode = PDF_E_IMAGE_COLORMAP; + goto PDF_TIFF_ERROR; + } + + cs.type = Indexed; + cs.val.indexed.palette_size = 1 << bpc; + cs.val.indexed.colormap = &colormap; + cs.val.indexed.colormap_id = PDC_BAD_ID; + + cs.val.indexed.base = DeviceRGB; + +#define CVT(x) (uint16) (((x) * 255) / ((1L<<16)-1)) + /* TODO: properly deal with 16-bit palette entries in PDF 1.5 */ + if (pdf_check_colormap(cs.val.indexed.palette_size, + rmap, gmap, bmap) == 16) + { + /* convert colormap to 8 bit values */ + for (i = 0; i < cs.val.indexed.palette_size; i++) + { + rmap[i] = CVT(rmap[i]); + gmap[i] = CVT(gmap[i]); + bmap[i] = CVT(bmap[i]); + } + } +#undef CVT + + for (i = 0; i < cs.val.indexed.palette_size; i++) + { + colormap[i][0] = (pdc_byte) rmap[i]; + colormap[i][1] = (pdc_byte) gmap[i]; + colormap[i][2] = (pdc_byte) bmap[i]; + } + + image->components = 1; + + slot = pdf_add_colorspace(p, &cs, pdc_false); + image->colorspace = slot; + + + } + + + + if (image->strips > image->height) + image->strips = (int) image->height; + + if (TIFFGetFieldDefaulted(MYTIFF, + TIFFTAG_ROWSPERSTRIP, &rowsperstrip) == 1 && (int)rowsperstrip!= -1) + image->rowsperstrip = (int) rowsperstrip; + else + image->rowsperstrip = (int) image->height; + + /* + * The first strip must be handled separately because it carries the + * colormap for indexed images. Other strips reuse this colormap. + */ + image->info.tiff.cur_line = 0; + image->height = (pdc_scalar) + (image->rowsperstrip > (int) h ? (int) h : image->rowsperstrip); + + /* + * Images may also be written to the output before the first page + * We do this ourselves (instead of in pdf_put_image() to avoid + * many empty contents sections for multi-strip images. + */ + if (PDF_GET_STATE(p) == pdf_state_page) + pdf_end_contents_section(p); + + pdf_put_image(p, imageslot, pdc_true, pdc_false); + + for (row = (uint32) image->rowsperstrip, strip = 1; + row < h; row += (uint32) image->rowsperstrip, strip++) { + + image->height = (pdc_scalar) (row+image->rowsperstrip > h ? + (int) (h - row) : image->rowsperstrip); + + /* + * tell pdf_data_source_TIFF_fill() to read only data of the + * current strip + */ + image->info.tiff.cur_line = strip; + pdf_put_image(p, imageslot, pdc_false, pdc_false); + } + + image->height = (pdc_scalar) h; + image->no -= (image->strips - 1); /* number of first strip */ + + /* Special handling for multi-strip images (see comment above) */ + if (PDF_GET_STATE(p) == pdf_state_page) + pdf_begin_contents_section(p); + + } else { /* !use_raw */ + size_t npixels; + + + + /* + * Retrieve full scan lines from TIFFlib for these color spaces, + * and Gray, RGB, or CMYK pixel data otherwise. + */ + if (p->colorspaces[image->colorspace].type == DeviceCMYK || + (p->colorspaces[image->colorspace].type == ICCBased && + image->components == 4)) + { + pdc_logg_cond(p->pdc, 1, trc_image, + "\tRetrieving full scan lines in native color space...\n"); + image->pixelmode = pdc_false; + } + else + { + pdc_logg_cond(p->pdc, 1, trc_image, + "\tRetrieving converted pixel data (pixel mode)...\n"); + image->pixelmode = pdc_true; + } + + if (image->pixelmode) + { + npixels = (size_t) (w * h); + + image->info.tiff.raster = (uint32 *) pdc_malloc(p->pdc, + (size_t) (npixels * sizeof (uint32)), fn); + + if (!TIFFReadRGBAImageOriented(MYTIFF, + w, h, image->info.tiff.raster, orientation, 1)) + { + errcode = PDC_E_IO_READ; + goto PDF_TIFF_ERROR; + } + } + else + { + int linecounter = 0; + + npixels = (size_t) (TIFFScanlineSize(MYTIFF) * h); + image->info.tiff.raster = (uint32 *) + pdc_malloc(p->pdc, (size_t) npixels, fn); + + while (linecounter < image->height) + { + if (TIFFReadScanline(MYTIFF, + (tdata_t) (image->info.tiff.raster + + ((int)image->height - linecounter - 1) * (int)image->width), + (uint32) linecounter, (tsample_t) 0) == -1) + { + errcode = PDC_E_IO_READ; + goto PDF_TIFF_ERROR; + } + linecounter++; + } + } + + pdf_put_image(p, imageslot, pdc_true, pdc_true); + + if (image->info.tiff.raster != NULL) + pdc_free(p->pdc, (void *) image->info.tiff.raster); + } + + image->in_use = pdc_true; /* mark slot as used */ + + if (!image->corrupt) + { + TIFFClose(MYTIFF); + return imageslot; + } + + PDF_TIFF_ERROR: + { + const char *stemp = NULL; + + if (errcode) + stemp = pdf_get_image_filename(p, image); + + if (image->info.tiff.raster != NULL) + pdc_free(p->pdc, (void *) image->info.tiff.raster); + + if (isopen) + TIFFClose(MYTIFF); + + switch (errcode) + { + case PDC_E_IO_READ: + case PDF_E_IMAGE_ICC: + case PDF_E_IMAGE_ICC2: + case PDF_E_IMAGE_MASK1BIT13: + case PDF_E_IMAGE_COLORIZE: + case PDF_E_TIFF_MASK_MULTISTRIP: + case PDF_E_IMAGE_COLORMAP: + case PDF_E_IMAGE_BADMASK: + case PDF_E_TIFF_CMYK_MASK: + case PDF_E_TIFF_UNSUPP_JPEG_SEPARATE: + case PDF_E_TIFF_16BITCMYK_UNSUPP: + case PDF_E_TIFF_16BIT_UNSUPP: + pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0); + break; + + case PDF_E_IMAGE_CORRUPT: + pdc_set_errmsg(p->pdc, errcode, "TIFF", stemp, 0, 0); + break; + + case PDF_E_TIFF_UNSUPP_COLORSPACE: + case PDF_E_TIFF_UNSUPP_COMPRESSION: + case PDF_E_IMAGE_BADCOMP: + pdc_set_errmsg(p->pdc, errcode, + pdc_errprintf(p->pdc, "%d", errint), stemp, 0, 0); + break; + + case PDF_E_IMAGE_NOPAGE: + pdc_set_errmsg(p->pdc, errcode, + pdc_errprintf(p->pdc, "%d", errint), "TIFF", stemp, 0); + break; + + case PDF_E_TIFF_UNSUPP_SEP_NONCMYK: + pdc_set_errmsg(p->pdc, errcode, + stemp, pdc_errprintf(p->pdc, "%d", errint), 0, 0); + break; + + case 0: /* error code and message already set */ + break; + } + } + + return -1; +} + +#undef MYTIFF +#endif /* HAVE_LIBTIFF */ diff --git a/src/pdflib/pdflib/p_truetype.c b/src/pdflib/pdflib/p_truetype.c new file mode 100644 index 0000000..80f2f10 --- /dev/null +++ b/src/pdflib/pdflib/p_truetype.c @@ -0,0 +1,301 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_truetype.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib TrueType handling routines + * + */ + +#include "p_intern.h" +#include "p_font.h" + +#include "ft_truetype.h" + +#ifdef PDF_TRUETYPE_SUPPORTED + + +pdc_bool +pdf_get_metrics_tt(PDF *p, pdf_font *font, const char *fontname, + pdc_encoding enc, const char *filename) +{ + pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_font); + pdc_bool logg2 = pdc_logg_is_enabled(p->pdc, 2, trc_font); + int filesize = 0; + double kbfilesize = 0; + int foundglyphs, flags = 0; + tt_file *ttf; + pdc_bool retval; + pdc_encoding enc_req; + pdc_encodingvector *ev = NULL; + pdc_bool isotf; + int errcode = 0; + + (void) logg2; + + /* + * Initialisation + */ + ttf = fnt_new_tt(p->pdc, &font->ft); + ttf->filename = filename; + ttf->fontname = fontname; + ttf->verbose = font->verbose; + ttf->incore = pdc_true; + ttf->monospace = font->opt.monospace; + filesize = font->ft.filelen; + kbfilesize = filesize / 1024.0; + + /* + * Read font file + */ + retval = fnt_read_tt(ttf); + if (retval == pdc_false) + goto PDF_TRUETYPE_ERROR2; + + /* + * Font type + */ + if (ttf->tab_CFF_) + { + isotf = pdc_true; + font->ft.m.type = fnt_Type1C; + font->cff_offset = (long) ttf->tab_CFF_->offset; + font->cff_length = ttf->tab_CFF_->length; + } + else + { + isotf = pdc_false; + font->ft.m.type = fnt_TrueType; + TT_IOCHECK(ttf, tt_tag2idx(ttf, fnt_str_glyf) != -1); + TT_IOCHECK(ttf, tt_tag2idx(ttf, fnt_str_loca) != -1); + } + + /* Number of Glyphs */ + if (ttf->numGlyphs <= 1) + { + errcode = FNT_E_TT_NOGLYFDESC; + goto PDF_TRUETYPE_ERROR1; + } + + + /* + * Encoding + */ + if (isotf) + { + /* OpenType font with CFF table */ + if (ttf->charcoll != cc_none) + { + /* CID font */ + if (font->ft.m.charcoll != cc_none) + { + if (!ttf->regisadobe) + { + errcode = PDF_E_CJK_UNSUPP_REGISTRY; + goto PDF_TRUETYPE_ERROR1; + } + + if (font->ft.m.charcoll != ttf->charcoll) + { + errcode = PDF_E_CJK_UNSUPP_CHARCOLL; + goto PDF_TRUETYPE_ERROR1; + } + + + if (font->outcmapname != NULL) + enc = pdc_cid; + + if (logg1) + pdc_logg(p->pdc, "\tCID font ordering: \"%s\"\n", + fnt_get_ordering_cid(ttf->charcoll)); + } + else if (enc == pdc_unicode || enc == pdc_glyphid) + { + font->ft.m.charcoll = ttf->charcoll; + font->supplement = ttf->supplement; + } + else + { + errcode = PDF_E_FONT_ONLY_CMAP; + goto PDF_TRUETYPE_ERROR1; + } + } + else if (font->ft.m.charcoll != cc_none) + { + /* SID font */ + errcode = PDF_E_FONT_UNSUPP_CMAP; + goto PDF_TRUETYPE_ERROR1; + } + } + else + { + if (font->ft.m.charcoll != cc_none) + { + int i; + pdc_bool iscjk = pdc_false; + + for (i = 0; i < PDC_NUMCHARCOLL; i++) + { + if (ttf->tab_OS_2->charcolls[i]) + iscjk = pdc_true; + + if (ttf->tab_OS_2->charcolls[i] == font->ft.m.charcoll) + break; + } + if (i == PDC_NUMCHARCOLL) + { + if (iscjk) + { + /* CJK font */ + errcode = PDF_E_CJK_UNSUPP_CHARCOLL; + goto PDF_TRUETYPE_ERROR1; + } + else + { + /* no CJK font */ + errcode = PDF_E_FONT_UNSUPP_CMAP; + goto PDF_TRUETYPE_ERROR1; + } + } + else + { + if (font->outcmapname != NULL) + { + ttf->charcoll = font->ft.m.charcoll; + enc = pdc_cid; + } + } + } + } + + /* encoding vector */ + enc_req = fnt_get_tt_encoding_key(ttf, enc); + if (enc_req == pdc_invalidenc) + { + errcode = FNT_E_TT_BADCMAP; + goto PDF_TRUETYPE_ERROR1; + } + else if (enc_req != enc) + { + if (strcmp(font->encapiname, "auto")) + { + pdc_warning(p->pdc, PDF_E_FONT_FORCEENC, + pdf_get_encoding_name(p, enc_req, NULL), + 0, 0, 0); + } + enc = enc_req; + } + if (enc >= 0) + ev = pdc_get_encoding_vector(p->pdc, enc); + font->ft.enc = enc; + font->ft.issymbfont = ttf->issymbol; + font->hasnomac = !ttf->tab_cmap || !ttf->tab_cmap->mac; + + + /* builtin encoding */ + if (enc == pdc_builtin) + { + if (font->ft.issymbfont == pdc_false) + { + errcode = PDF_E_FONT_BADENC; + goto PDF_TRUETYPE_ERROR1; + } + else + { + /* encoding vector for builtin */ + ev = pdf_create_font_encoding(p, enc, font, fontname, pdc_true); + font->symenc = font->ft.enc; + } + } + + { + /* optimizing PDF output */ + if (enc == pdc_ebcdic || + enc == pdc_ebcdic_37 || + enc == pdc_ebcdic_winansi) + font->towinansi = pdc_winansi; + + } + + /* /FontName in FontDescriptor */ + font->ft.m.name = pdc_strdup(p->pdc, ttf->tab_name->englishname4); + + /* /BaseFont name */ + font->ft.name = pdc_strdup(p->pdc, ttf->tab_name->englishname6); + + +#define PDF_RESTRICTED_TT_EMBEDDING 0x02 + /* check embedding flags */ + if ((font->opt.embedding) && ttf->tab_OS_2 && + ttf->tab_OS_2->fsType == PDF_RESTRICTED_TT_EMBEDDING) + { + errcode = FNT_E_TT_EMBED; + goto PDF_TRUETYPE_ERROR1; + } + + + if (logg1) + { + pdc_logg(p->pdc, + "\tFull font name: \"%s\"\n" + "\tPostScript font name: \"%s\"\n" + "\tFont embedding: %s\n", + font->ft.name, font->ft.m.name, + PDC_BOOLSTR(font->opt.embedding)); + + if (ttf->tab_name->producer != NULL) + pdc_logg(p->pdc, "\tFont producer: \"%s\"\n", + ttf->tab_name->producer); + + pdc_logg(p->pdc, "\tNumber of Glyphs: %d\n", ttf->numGlyphs); + } + + /* Save font values */ + fnt_set_tt_fontvalues(ttf); + + /* Flags for creating font arrays */ + flags = TT_FONT_code2gid | TT_FONT_m_widths; + + + /* Create font mapping and width arrays */ + foundglyphs = fnt_set_tt_fontarrays(ttf, flags); + + /***********************************/ + if (font->symenc != pdc_invalidenc) + font->ft.enc = pdc_builtin; + /***********************************/ + + if (!foundglyphs) + { + errcode = PDF_E_FONT_BADENC; + goto PDF_TRUETYPE_ERROR1; + } + + + fnt_delete_tt(ttf); + + if (!pdf_make_fontflag(p, font)) + return pdc_false; + + return pdc_true; + + PDF_TRUETYPE_ERROR1: + pdc_set_errmsg(p->pdc, errcode, 0, 0, 0, 0); + + PDF_TRUETYPE_ERROR2: + fnt_delete_tt(ttf); + + return pdc_false; +} + + +#endif /* PDF_TRUETYPE_SUPPORTED */ diff --git a/src/pdflib/pdflib/p_type1.c b/src/pdflib/pdflib/p_type1.c new file mode 100644 index 0000000..8483710 --- /dev/null +++ b/src/pdflib/pdflib/p_type1.c @@ -0,0 +1,427 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_type1.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib Type1 font handling routines + * + */ + +#include "pc_ctype.h" + +#include "p_intern.h" +#include "p_font.h" + + +/* Type 1 font portions: ASCII, encrypted, zeros */ +typedef enum { t1_ascii, t1_encrypted, t1_zeros } pdf_t1portion; + +typedef struct { + pdf_t1portion portion; + size_t length[4]; + pdc_file *fontfile; + pdc_byte *img; /* in-core Type1 font file image */ + pdc_byte *end; /* first byte above image buf */ + pdc_byte *pos; /* current "file" position */ +} t1_private_data; + +#define PFA_TESTBYTE 4 + +#define PDF_CURRENTFILE "currentfile eexec" + + +/* ---------------------------- General platforms --------------------------- */ + +#define LINEBUFLEN 256 + +/* + * PFA files are assumed to be encoded in host format. Therefore + * we must use literal strings and characters for interpreting the + * font file. + */ + +static int +PFA_data_fill(PDF *p, PDF_data_source *src) +{ + static const char *fn = "PFA_data_fill"; +#ifndef PDFLIB_EBCDIC + static const char HexToBin['F' - '0' + 1] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, + 0, 10, 11, 12, 13, 14, 15 + }; +#else +#endif + char *s, *c; + int i; + int len; + t1_private_data *t1_private; + pdf_t1portion t1portion; + + t1_private = (t1_private_data *) src->private_data; + + if (src->buffer_start == NULL) + { + src->buffer_start = (pdc_byte *) pdc_malloc(p->pdc, LINEBUFLEN + 1, fn); + src->buffer_length = LINEBUFLEN; + } + + s = pdc_fgetline((char *) src->buffer_start, LINEBUFLEN, + t1_private->fontfile); + if (s == NULL) + return pdc_false; + + /* set unix line end */ + len = (int) strlen(s); + s[len] = '\n'; + len++; + s[len] = 0; + + /* check for line of zeros: set t1_zero flag if found */ + if (*s == '0') + { + for (i = 0; s[i] == '0'; i++) + { + /* */ ; + } + if (s[i] == '\n') + t1_private->portion = t1_zeros; + } + + /* check whether font data portion follows: set t1_encrypted flag later */ + t1portion = t1_private->portion; + if (t1_private->portion != t1_encrypted && + !strncmp((const char *)s, PDF_CURRENTFILE, strlen(PDF_CURRENTFILE))) + t1portion = t1_encrypted; + + src->next_byte = src->buffer_start; + + switch (t1_private->portion) + { + case t1_ascii: + { + t1_private->length[1] += (size_t) len; + src->bytes_available = (size_t) len; + } + break; + + case t1_encrypted: + { + src->bytes_available = 0; + + /* Convert to upper case for safe binary conversion */ + for (c = s; *c != '\n'; c++) + { + *c = (char) pdc_toupper(*c); + } + + /* convert ASCII to binary in-place */ + for (i = 0; s[i] != '\n'; i += 2) + { + if ((!pdc_isxdigit(s[i]) && !pdc_isspace(s[i])) || + (!pdc_isxdigit(s[i+1]) && !pdc_isspace(s[i+1]))) + { + pdc_fclose(t1_private->fontfile); + pdc_error(p->pdc, PDF_E_FONT_CORRUPT, "PFA", "?", 0, 0); + } +#ifndef PDFLIB_EBCDIC + s[i/2] = (char) (16*HexToBin[s[i]-'0'] + HexToBin[s[i+1]-'0']); +#else +#endif + src->bytes_available++; + } + t1_private->length[2] += src->bytes_available; + } + break; + + case t1_zeros: + { + t1_private->length[3] += (size_t) len; + src->bytes_available = (size_t) len; + } + break; + } + + t1_private->portion = t1portion; + + return pdc_true; +} + +#define PFB_MARKER 0x80 +#define PFB_ASCII 1 +#define PFB_BINARY 2 +#define PFB_EOF 3 + +static int +pdf_t1getc(t1_private_data *t1) +{ + int val; + + if (t1->fontfile) + { + return pdc_fgetc(t1->fontfile); + } + val = (int) *t1->pos; + t1->pos++; + + return val; +} + +static pdc_bool +pdf_read_pfb_segment(PDF *p, PDF_data_source *src, t1_private_data *t1, int i) +{ + static const char *fn = "pdf_read_pfb_segment"; + size_t length, len; + + length = (size_t) (pdf_t1getc(t1) & 0xff); + length |= (size_t) (pdf_t1getc(t1) & 0xff) << 8; + length |= (size_t) (pdf_t1getc(t1) & 0xff) << 16; + length |= (size_t) (pdf_t1getc(t1) & 0xff) << 24; + + if (src->buffer_start) + pdc_free(p->pdc, (void *) src->buffer_start); + src->buffer_start = (pdc_byte *) pdc_malloc(p->pdc, length, fn); + + if (t1->fontfile) { + len = pdc_fread(src->buffer_start, 1, length, t1->fontfile); + } else { + len = length; + if (t1->pos + len > t1->end) + len = (unsigned int)(t1->end - t1->pos); + memcpy(src->buffer_start, t1->pos, len); + t1->pos += len; + } + + t1->length[i] = len; + src->next_byte = src->buffer_start; + src->bytes_available = len; + + return (len != length) ? pdc_true : pdc_false;; +} + +static int +PFB_data_fill(PDF *p, PDF_data_source *src) +{ + t1_private_data *t1; + unsigned char c, type; + pdc_bool err = pdc_false; + + t1 = (t1_private_data *) src->private_data; + + c = (unsigned char) pdf_t1getc(t1); + type = (unsigned char) pdf_t1getc(t1); + + if (t1->length[1] == (size_t) 0) { + if (c != PFB_MARKER || type != PFB_ASCII) { + err = pdc_true; + } else { + err = pdf_read_pfb_segment(p, src, t1, 1); + } + + } else if (t1->length[2] == (size_t) 0) { + if (c != PFB_MARKER || type != PFB_BINARY) { + err = pdc_true; + } else { + err = pdf_read_pfb_segment(p, src, t1, 2); + } + + } else if (t1->length[3] == 0) { + if (c != PFB_MARKER || type != PFB_ASCII) { + err = pdc_true; + } else { + err = pdf_read_pfb_segment(p, src, t1, 3); + } + } else if (c != PFB_MARKER || type != PFB_EOF) { + err = pdc_true; + } else { + return pdc_false; + } + + if (err) { + if (t1->fontfile) + pdc_fclose(t1->fontfile); + pdc_error(p->pdc, PDF_E_FONT_CORRUPT, "PFB", "?", 0, 0); + } + + return pdc_true; +} + +static void +t1data_terminate(PDF *p, PDF_data_source *src) +{ + pdc_free(p->pdc, (void *) src->buffer_start); +} + +static void +t1data_init(PDF *p, PDF_data_source *src) +{ + t1_private_data *t1_private; + + (void) p; + + t1_private = (t1_private_data *) src->private_data; + + t1_private->portion = t1_ascii; + t1_private->length[1] = (size_t) 0; + t1_private->length[2] = (size_t) 0; + t1_private->length[3] = (size_t) 0; + + src->buffer_start = NULL; +} + + +pdc_bool +pdf_t1open_fontfile(PDF *p, pdf_font *font, const char *filename, + PDF_data_source *t1src, pdc_bool requested) +{ + static const char *fn = "pdf_t1open_fontfile"; + t1_private_data *t1_private = NULL; + pdc_file *fp = NULL; + const char *stemp = NULL; + unsigned char magic[PFA_TESTBYTE]; + char fullname[PDC_FILENAMELEN]; + int fflags = PDC_FILE_BINARY; + int ispfb = pdc_true; + + if (filename) + { + + fp = pdc_fsearch_fopen(p->pdc, filename, fullname, "PostScript Type1 ", + fflags); + if (fp == NULL) + { + if (t1src) + pdc_error(p->pdc, -1, 0, 0, 0, 0); + return pdc_check_fopen_errmsg(p->pdc, requested); + } + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tLoading PostScript Type1 fontfile \"%s\":\n", fullname); + + } + + if (fp) + { + pdc_fread(magic, 1, PFA_TESTBYTE, fp); + stemp = filename; + } + else if (font->ft.img) + { + strncpy((char *) magic, (const char *)font->ft.img, PFA_TESTBYTE); + stemp = font->ft.name; + } + + /* try to identify PFA files */ + if (magic[0] != PFB_MARKER) + { + char startsequ[PFA_TESTBYTE + 1]; + + strcpy(startsequ, FNT_PFA_STARTSEQU); + + if (strncmp((const char *) magic, startsequ, PFA_TESTBYTE)) + { + if (fp) + pdc_fclose(fp); + pdc_set_errmsg(p->pdc, PDF_E_T1_NOFONT, stemp, 0, 0, 0); + if (t1src) + pdc_error(p->pdc, -1, 0, 0, 0, 0); + return pdc_false; + } + ispfb = pdc_false; + } + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tPostScript Type1 font of format \"%s\" detected\n", + ispfb ? "PFB" : "PFA"); + + if (t1src) + { + t1src->private_data = (unsigned char *) + pdc_malloc(p->pdc, sizeof(t1_private_data), fn); + t1_private = (t1_private_data *) t1src->private_data; + + if (filename) + { + pdc_fclose(fp); + if (ispfb) + { + t1_private->fontfile = + pdc_fsearch_fopen(p->pdc, fullname, NULL, "PFB ", fflags); + } + else + { + t1_private->fontfile = + pdc_fsearch_fopen(p->pdc, fullname, NULL, "PFA ", + PDC_FILE_TEXT); + } + + if (t1_private->fontfile == NULL) + pdc_error(p->pdc, -1, 0, 0, 0, 0); + } + else if (font->ft.img) + { + t1_private->fontfile = NULL; + t1_private->img = font->ft.img; + t1_private->pos = font->ft.img; + t1_private->end = font->ft.img + font->ft.filelen; + } + + t1src->init = t1data_init; + t1src->fill = ispfb ? PFB_data_fill : PFA_data_fill; + t1src->terminate = t1data_terminate; + } + else if (fp != NULL) + { + if (pdc_file_isvirtual(fp) == pdc_true) + { + if (ispfb) + font->ft.img = + (pdc_byte *) pdc_freadall(fp, &font->ft.filelen, NULL); + font->ft.imgname = pdc_strdup(p->pdc, fullname); + pdc_lock_pvf(p->pdc, font->ft.imgname); + } + font->ft.filename = pdc_strdup(p->pdc, fullname); + pdc_fclose(fp); + } + + return pdc_true; +} + +pdc_bool +pdf_make_t1src (PDF *p, pdf_font *font, PDF_data_source *t1src) +{ + return pdf_t1open_fontfile(p, font, font->filename, t1src, pdc_true); +} + +void +pdf_put_length_objs(PDF *p, PDF_data_source *t1src, + pdc_id length1_id, pdc_id length2_id, pdc_id length3_id) +{ + pdc_begin_obj(p->out, length1_id); /* Length1 object */ + pdc_printf(p->out, "%ld\n", + (long) ((t1_private_data *) t1src->private_data)->length[1]); + pdc_end_obj(p->out); + + pdc_begin_obj(p->out, length2_id); /* Length2 object */ + pdc_printf(p->out, "%ld\n", + (long) ((t1_private_data *) t1src->private_data)->length[2]); + pdc_end_obj(p->out); + + pdc_begin_obj(p->out, length3_id); /* Length3 object */ + pdc_printf(p->out, "%ld\n", + (long) ((t1_private_data *) t1src->private_data)->length[3]); + pdc_end_obj(p->out); + + if (((t1_private_data *) t1src->private_data)->fontfile) + pdc_fclose(((t1_private_data *) t1src->private_data)->fontfile); + + pdc_free(p->pdc, (void *) t1src->private_data); +} diff --git a/src/pdflib/pdflib/p_type3.c b/src/pdflib/pdflib/p_type3.c new file mode 100644 index 0000000..411bd0d --- /dev/null +++ b/src/pdflib/pdflib/p_type3.c @@ -0,0 +1,740 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_type3.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * Routines for Type 3 (user-defined) fonts + * + */ + +#include "p_intern.h" +#include "p_font.h" +#include "p_image.h" + +int +pdf_get_t3colorized(PDF *p) +{ + return p->fonts[p->t3slot].t3font->colorized; +} + +static void +pdf_init_t3font(PDF *p, pdf_t3font *t3font, int glyph_capacity) +{ + static char fn[] = "pdf_init_t3font"; + int i; + + /* statement order is critical for cleanup! + */ + t3font->curr_glyph = 0; + t3font->next_glyph = 0; + t3font->capacity = glyph_capacity; + t3font->glyphs = (pdf_t3glyph *) + pdc_malloc(p->pdc, t3font->capacity * sizeof (pdf_t3glyph), fn); + + for (i = 0; i < t3font->capacity; i++) + t3font->glyphs[i].name = NULL; + + t3font->charprocs_id = PDC_BAD_ID; + t3font->pass = 0; + +} + +void +pdf_cleanup_t3font(PDF *p, pdf_t3font *t3font) +{ + int i; + + for (i = 0; i < t3font->next_glyph; i++) + { + if (t3font->glyphs[i].name) + { + pdc_free(p->pdc, t3font->glyphs[i].name); + t3font->glyphs[i].name = NULL; + } + } + + pdc_free(p->pdc, t3font->glyphs); + t3font->glyphs = NULL; +} + +static void +pdf_type3_protocol(PDF *p, pdf_font *font, pdc_encodingvector *ev) +{ + /* logging protocol */ + if (pdc_logg_is_enabled(p->pdc, 2, trc_font)) + { + char *glyphname; + pdc_ushort uv = 0; + int gid, code, width = 0; + + for (gid = 0; gid < font->t3font->next_glyph; gid++) + { + glyphname = NULL; + + pdc_logg(p->pdc, "\t\tGlyph%4d: ", gid); + + if (ev != NULL) + { + code = font->ft.gid2code[gid]; + uv = ev->codes[code]; + if (glyphname == NULL) + glyphname = ev->chars[code]; + width = fnt_get_glyphwidth(code, &font->ft); + + pdc_logg(p->pdc, "code=%3d ", code); + } + + if (width == FNT_MISSING_WIDTH) + width = 0; + + pdc_logg(p->pdc, "U+%04X width=%4d \"%s\"\n", + uv, width, glyphname); + } + } +} + +/* + * We found a Type 3 font in the cache, but its encoding doesn't match. + * Make a copy of the font in a new slot, and attach the new encoding. + */ + +pdc_bool +pdf_handle_t3font(PDF *p, const char *fontname, pdc_encoding enc, + pdf_font *font, int *slot) +{ + static const char fn[] = "pdf_handle_t3font"; + const char *encname; + char *fname; + size_t namlen; + pdf_font *deffont = &p->fonts[*slot]; + pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc); + fnt_font_metric *ftm = &font->ft.m; + size_t nalloc; + int code, gid; + pdc_bool newinst = pdc_false; + + /* font name incl. encoding name */ + encname = pdc_get_user_encoding(p->pdc, enc); + namlen = strlen(fontname) + strlen(encname) + 2; + fname = (char *) pdc_malloc(p->pdc, namlen, fn); + pdc_sprintf(p->pdc, pdc_false, fname, "%s.%s", fontname, encname); + + /* we have to copy the available font. + * otherwise the original font will be changed + */ + newinst = deffont->ft.enc != pdc_invalidenc; + + pdc_logg_cond(p->pdc, 1, trc_font, + "\n\tType3 font \"%s\" with %d glyphs found\n", + fontname, deffont->t3font->next_glyph); + + if (newinst) + { + pdc_logg_cond(p->pdc, 1, trc_font, + "\tInstance with specified encoding will be created\n"); + + } + + /* copy data from available font (see pdf__begin_font()) */ + font->ft.m.type = fnt_Type3; + font->ft.matrix = deffont->ft.matrix; + font->t3font = deffont->t3font; + font->ft.numglyphs = deffont->t3font->next_glyph; + nalloc = (size_t) font->ft.numglyphs; + + ftm->name = fname; + font->ft.name = pdc_strdup(p->pdc, fname); + font->ft.enc = enc; + font->ft.issymbfont = pdc_false; + font->opt.embedding = pdc_true; + + if (enc >= pdc_winansi) + { + font->codesize = 1; + font->ft.numcodes = 256; + font->lastcode = -1; + + ftm->widths = (int *) pdc_calloc(p->pdc, + (size_t) font->ft.numcodes * sizeof(int), fn); + ftm->numwidths = font->ft.numcodes; + } + + font->ft.code2gid = (pdc_ushort *) pdc_calloc(p->pdc, + (size_t) font->ft.numcodes * sizeof(pdc_ushort), fn); + + font->ft.gid2code = (pdc_ushort *) pdc_calloc(p->pdc, + nalloc * sizeof (pdc_ushort), fn); + + /* fill up font arrays */ + for (gid = 0; gid < font->ft.numglyphs; gid++) + { + const char *str = NULL, *glyphname = font->t3font->glyphs[gid].name; + + if (enc >= pdc_winansi) + { + /* search for code */ + for (code = 0; code < font->ft.numcodes; code++) + { + if (ev->chars[code] != NULL) + str = ev->chars[code]; + else if (ev->codes[code]) + str = pdc_unicode2glyphname(p->pdc, ev->codes[code]); + + if (str != NULL && !pdc_strcmp(glyphname, str)) + break; + } + + /* code found */ + if (code < font->ft.numcodes) + { + font->ft.code2gid[code] = gid; + font->ft.gid2code[gid] = code; + + if (!gid) + font->gid0code = code; + + if (font->opt.monospace) + ftm->widths[code] = font->opt.monospace; + else + ftm->widths[code] = + (int) (font->t3font->glyphs[gid].width + 0.5); + } + } + } + + + pdf_type3_protocol(p, font, ev); + + /* font flags */ + if (!pdf_make_fontflag(p, font)) + return pdc_false; + + if (newinst) + { + *slot = -1; + } + else + { + if (deffont->apiname != NULL) + pdc_free(p->pdc, deffont->apiname); + *deffont = *font; + deffont->hasoriginal = pdc_true; + } + + return pdc_true; +} + +pdc_bool +pdf_isvalid_font(PDF *p, int slot) +{ + if (slot > -1 && slot < p->fonts_number) + { + pdf_font *font = &p->fonts[slot]; + if (!font->opt.auxiliary && + (font->t3font == NULL || font->t3font->pass != 2)) + return pdc_true; + } + + return pdc_false; +} + +#define PDF_FAMILYNAME_FLAG PDC_OPT_UNSUPP +#define PDF_STRETCH_FLAG PDC_OPT_UNSUPP +#define PDF_WEIGHT_FLAG PDC_OPT_UNSUPP + +/* + * internal font stretch values + */ +#define PDF_FS_ULTRACONDENSED 1 +#define PDF_FS_EXTRACONDENSED 2 +#define PDF_FS_CONDENSED 3 +#define PDF_FS_SEMICONDENSED 4 +#define PDF_FS_NORMAL 5 +#define PDF_FS_SEMIEXPANDED 6 +#define PDF_FS_EXPANDED 7 +#define PDF_FS_EXTRAEXPANDED 8 +#define PDF_FS_ULTRAEXPANDED 9 + +static const pdc_keyconn pdf_fontstretch_keylist[] = +{ + {"UltraCondensed", PDF_FS_ULTRACONDENSED}, + {"ExtraCondensed", PDF_FS_EXTRACONDENSED}, + {"Condensed", PDF_FS_CONDENSED}, + {"SemiCondensed", PDF_FS_SEMICONDENSED}, + {"Normal", PDF_FS_NORMAL}, + {"SemiExpanded", PDF_FS_SEMIEXPANDED}, + {"Expanded", PDF_FS_EXPANDED}, + {"ExtraExpanded", PDF_FS_EXTRAEXPANDED}, + {"UltraExpanded", PDF_FS_ULTRAEXPANDED}, + {NULL, 0} +}; + +/* conf. with fnt_fontweight_keylist[] in ft_font.c */ +static const pdc_keyconn pdf_fontweight_keylist[] = +{ + {"thin", FNT_FW_THIN}, + {"extralight", FNT_FW_EXTRALIGHT}, + {"light", FNT_FW_LIGHT}, + {"normal", FNT_FW_NORMAL}, + {"medium", FNT_FW_MEDIUM}, + {"semibold", FNT_FW_SEMIBOLD}, + {"bold", FNT_FW_BOLD}, + {"extrabold", FNT_FW_EXTRABOLD}, + {"black", FNT_FW_BLACK}, + {NULL, 0} +}; + +/* definitions of begin font options */ +static const pdc_defopt pdf_begin_font_options[] = +{ + {"colorized", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + {"widthsonly", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, + + {"familyname", pdc_stringlist, PDF_FAMILYNAME_FLAG, 1, 1, + 1.0, PDF_MAX_FONTNAME, NULL}, + + {"stretch", pdc_keywordlist, PDF_STRETCH_FLAG, 1, 1, + 0.0, 0.0, pdf_fontstretch_keylist}, + + {"weight", pdc_keywordlist, PDF_WEIGHT_FLAG, 1, 1, + 0.0, 0.0, pdf_fontweight_keylist}, + + PDC_OPT_TERMINATE +}; + +void +pdf__begin_font( + PDF *p, + const char *fontname, int len, + pdc_scalar a, pdc_scalar b, pdc_scalar c, pdc_scalar d, + pdc_scalar e, pdc_scalar f, + const char *optlist) +{ + static const char fn[] = "pdf__begin_font"; + char *fname; + pdc_resopt *results; + pdf_font tmpfont, *font; + pdf_font_options fo; + pdc_scalar det; + pdc_clientdata cdata; + int colorized = pdc_false; + int metricsonly = pdc_false; + int slot; + + if (fontname == NULL) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0); + + /* Converting fontname */ + fname = pdf_convert_name(p, fontname, len, PDC_CONV_WITHBOM); + if (fname == NULL || *fname == '\0') + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0); + fontname = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, fname); + pdc_free(p->pdc, fname); + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tBegin of Type3 font \"%s\"\n", fontname); + + /* error message prefix */ + pdc_push_errmsg(p->pdc, PDF_E_T3_FONT_PREFIX, fontname, 0, 0, 0); + + /* look for an already existing font */ + for (slot = 0; slot < p->fonts_number; slot++) + { + if (!pdc_strcmp(p->fonts[slot].apiname, fontname)) + { + if (p->fonts[slot].t3font->pass == 1) + { + pdc_logg_cond(p->pdc, 1, trc_font, + "\tType3 font [%d] with metric definition found\n", slot); + + PDF_CHECK_STATE(p, pdf_state_document); + + p->fonts[slot].t3font->pass = 2; + p->t3slot = slot; + + pdc_pop_errmsg(p->pdc); + + pdf_pg_suspend(p); + PDF_SET_STATE(p, pdf_state_font); + return; + } + + pdc_error(p->pdc, PDF_E_T3_FONTEXISTS, 0, 0, 0, 0); + } + } + + pdc_check_number(p->pdc, "a", a); + pdc_check_number(p->pdc, "b", b); + pdc_check_number(p->pdc, "c", c); + pdc_check_number(p->pdc, "d", d); + pdc_check_number(p->pdc, "e", e); + pdc_check_number(p->pdc, "f", f); + + det = a*d - b*c; + + if (det == 0) + pdc_error(p->pdc, PDC_E_ILLARG_MATRIX, + pdc_errprintf(p->pdc, "%f %f %f %f %f %f", a, b, c, d, e, f), + 0, 0, 0); + + /* parsing optlist */ + pdf_set_clientdata(p, &cdata); + results = pdc_parse_optionlist(p->pdc, optlist, pdf_begin_font_options, + &cdata, pdc_true); + + pdc_get_optvalues("colorized", results, &colorized, NULL); + pdc_get_optvalues("widthsonly", results, &metricsonly, NULL); + + + pdc_cleanup_optionlist(p->pdc, results); + + /* initialize font struct */ + font = &tmpfont; + pdf_init_font_options(p, &fo); + pdf_init_font(p, font, &fo); + + /* + * We store the new font in a font slot marked with "invalidenc" encoding. + * When the font is used for the first time we modify the encoding. + * Later uses will make a copy if the encoding is different. + */ + + /* API font name */ + font->apiname = pdc_strdup(p->pdc, fontname); + + font->ft.m.type = fnt_Type3; + font->hasoriginal = pdc_true; + + font->ft.matrix.a = a; + font->ft.matrix.b = b; + font->ft.matrix.c = c; + font->ft.matrix.d = d; + font->ft.matrix.e = e; + font->ft.matrix.f = f; + + font->t3font = (pdf_t3font*) pdc_malloc(p->pdc, sizeof(pdf_t3font), fn); + pdf_init_t3font(p, font->t3font, T3GLYPHS_CHUNKSIZE); + + font->t3font->colorized = colorized; + + + /* the resource id is needed until the font dict is written */ + font->t3font->res_id = pdc_alloc_id(p->out); + + /* Now everything is fine, insert Type3 font with invalid encoding */ + slot = pdf_insert_font(p, font); + + /* + * We must store a pointer to the current font because its glyph + * definitions may use other fonts and we would be unable to find + * "our" current font again. This pointer lives throughout the + * font definition, and will be reset in PDF_end_font() below. + */ + p->t3slot = slot; + + if (metricsonly) + { + font->t3font->pass = 1; + pdc_logg_cond(p->pdc, 2, trc_font, + "\t\tonly for metric definition\n"); + } + else + { + pdf_pg_suspend(p); + } + + pdc_pop_errmsg(p->pdc); + + PDF_SET_STATE(p, pdf_state_font); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[Begin font %d]\n", p->t3slot); +} + +void +pdf__end_font(PDF *p) +{ + int ig; + pdf_font *font; + pdf_t3font *t3font; + + PDF_SET_STATE(p, pdf_state_document); + + font = &p->fonts[p->t3slot]; + t3font = font->t3font; + + /* error message prefix */ + pdc_push_errmsg(p->pdc, PDF_E_T3_FONT_PREFIX, font->apiname, 0, 0, 0); + + if (t3font->pass == 0) + { + pdf_t3glyph glyph0 = t3font->glyphs[0]; + + /* search for .notdef glyph */ + if (pdc_strcmp(glyph0.name, (char *) pdc_get_notdef_glyphname())) + { + for (ig = 0; ig < t3font->next_glyph; ig++) + { + if (!pdc_strcmp(t3font->glyphs[ig].name, + (char *) pdc_get_notdef_glyphname())) + break; + } + + if (ig < t3font->next_glyph) + { + pdc_logg_cond(p->pdc, 2, trc_font, + "\tGlyph id %d: \"%s\" will be exchanged " + "with glyph id 0: \"%s\"\n", + ig, t3font->glyphs[ig].name, glyph0.name); + + t3font->glyphs[0] = t3font->glyphs[ig]; + t3font->glyphs[ig] = glyph0; + } + else + { + pdc_warning(p->pdc, PDF_E_T3_MISSNOTDEF, 0, 0, 0, 0); + } + } + } + + if (t3font->pass != 1) + { + t3font->charprocs_id = pdc_alloc_id(p->out); + pdc_begin_obj(p->out, t3font->charprocs_id); /* CharProcs dict */ + pdc_begin_dict(p->out); + + for (ig = 0; ig < t3font->next_glyph; ig++) + { + pdf_t3glyph *glyph = &t3font->glyphs[ig]; + + if (glyph->charproc_id != PDC_BAD_ID) + { + pdf_put_pdfname(p, glyph->name); + pdc_objref(p->out, "", glyph->charproc_id); + } + } + + pdc_end_dict(p->out); + pdc_end_obj(p->out); /* CharProcs dict */ + + pdc_begin_obj(p->out, t3font->res_id); + pdc_begin_dict(p->out); /* Resource dict */ + + pdf_write_page_fonts(p); /* Font resources */ + + pdf_write_page_colorspaces(p); /* Color space resources */ + + pdf_write_page_pattern(p); /* Pattern resources */ + + pdf_write_xobjects(p); /* XObject resources */ + + pdc_end_dict(p->out); /* Resource dict */ + pdc_end_obj(p->out); /* Resource object */ + + pdf_pg_resume(p, -1); + + if (p->flush & pdc_flush_content) + pdc_flush_stream(p->out); + + /* see pdf__begin_glyph */ + pdf_init_tstate(p); + pdf_init_gstate(p); + pdf_init_cstate(p); + } + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tEnd of Type3 font \"%s\"\n", font->apiname); + + pdc_pop_errmsg(p->pdc); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[End font %d]\n", p->t3slot); + + p->t3slot = -1; +} + +void +pdf__begin_glyph( + PDF *p, + const char *glyphname, + pdc_scalar wx, + pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury) +{ + static const char fn[] = "pdf__begin_glyph"; + pdf_font *font; + pdf_t3font *t3font; + pdf_t3glyph *glyph = NULL; + int ig; + + if (glyphname == NULL || *glyphname == '\0') + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "glyphname", 0, 0, 0); + + font = &p->fonts[p->t3slot]; + t3font = font->t3font; + + /* error message prefix */ + pdc_push_errmsg(p->pdc, PDF_E_T3_FONT_PREFIX, font->apiname, 0, 0, 0); + + for (ig = 0; ig < t3font->next_glyph; ig++) + { + glyph = &t3font->glyphs[ig]; + if (!pdc_strcmp(glyph->name, glyphname)) + { + if (t3font->pass == glyph->pass) + pdc_error(p->pdc, PDF_E_T3_GLYPH, glyphname, 0, 0, 0); + else + break; + } + } + + /* new glyph */ + if (ig == t3font->next_glyph) + { + if (t3font->pass == 2) + pdc_error(p->pdc, PDF_E_T3_UNKOWNGLYPH, glyphname, 0, 0, 0); + + pdc_check_number(p->pdc, "wx", wx); + 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 (t3font->colorized == pdc_true && + (llx != 0 || lly != 0 || + urx != 0 || ury != 0)) + pdc_error(p->pdc, PDF_E_T3_BADBBOX, 0, 0, 0, 0); + + if (ig == t3font->capacity) + { + t3font->capacity *= 2; + t3font->glyphs = (pdf_t3glyph *) pdc_realloc(p->pdc, t3font->glyphs, + t3font->capacity * sizeof (pdf_t3glyph), fn); + } + + glyph = &t3font->glyphs[ig]; + glyph->charproc_id = PDC_BAD_ID; + glyph->name = pdc_strdup(p->pdc, glyphname); + glyph->wx = wx; + glyph->llx = llx; + glyph->lly = lly; + glyph->urx = urx; + glyph->ury = ury; + + /* see comment in p_font.c for explanation */ + glyph->width = 1000 * wx * font->ft.matrix.a; + + /* if the strdup above fails, cleanup won't touch this slot. */ + t3font->next_glyph++; + } + glyph->pass = t3font->pass; + t3font->curr_glyph = ig; + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tBegin of Type3 font glyph \"%s\"\n", glyphname); + + if (t3font->pass != 1) + { + if (t3font->pass == 2) + pdc_logg_cond(p->pdc, 2, trc_font, + "\t\tglyph [%d] was used in text\n", ig); + + glyph->charproc_id = pdc_begin_obj(p->out, PDC_NEW_ID); + pdc_begin_dict(p->out); + + p->length_id = pdc_alloc_id(p->out); + pdc_objref(p->out, "/Length", p->length_id); + + if (pdc_get_compresslevel(p->out)) + pdc_puts(p->out, "/Filter/FlateDecode\n"); + + pdc_end_dict(p->out); + + pdc_begin_pdfstream(p->out); + + if (t3font->colorized == pdc_true) + pdc_printf(p->out, "%f 0 d0\n", glyph->wx); + else + { + pdc_printf(p->out, "%f 0 %f %f %f %f d1\n", + glyph->wx, glyph->llx, glyph->lly, glyph->urx, glyph->ury); + + /* adjust the font's bounding box */ + if (glyph->llx < font->ft.bbox.llx) + font->ft.bbox.llx = glyph->llx; + if (glyph->lly < font->ft.bbox.lly) + font->ft.bbox.lly = glyph->lly; + if (glyph->urx > font->ft.bbox.urx) + font->ft.bbox.urx = glyph->urx; + if (glyph->ury > font->ft.bbox.ury) + font->ft.bbox.ury = glyph->ury; + } + + /* we must initialize the text, graphics and color state + * otherwise the user get unpredictable appearance of a + * glyph because of optimizing outputting graphics properties. + * Following statements were inserted due to bug #719 + */ + pdf_init_tstate(p); + pdf_init_gstate(p); + pdf_init_cstate(p); + + PDF_SET_STATE(p, pdf_state_glyph); + } + else + { + PDF_SET_STATE(p, pdf_state_glyphmetric); + } + + pdc_pop_errmsg(p->pdc); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[Begin glyph %d]\n", ig); +} + +void +pdf__end_glyph(PDF *p) +{ + pdf_t3font *t3font = p->fonts[p->t3slot].t3font; + pdf_t3glyph *glyph = &t3font->glyphs[t3font->curr_glyph]; + int ig = t3font->curr_glyph; + + if (t3font->pass != 1 && glyph->charproc_id != PDC_BAD_ID) + { + /* check whether pdf__save() and pdf__restore() calls are balanced */ + if (p->curr_ppt->sl > 0) + pdc_error(p->pdc, PDF_E_GSTATE_UNMATCHEDSAVE, 0, 0, 0, 0); + + pdf_end_text(p); + pdc_end_pdfstream(p->out); /* glyph description stream */ + pdc_end_obj(p->out); /* glyph description */ + + pdc_put_pdfstreamlength(p->out, p->length_id); + } + + PDF_SET_STATE(p, pdf_state_font); + + pdc_logg_cond(p->pdc, 1, trc_font, + "\tEnd of Type3 font glyph \"%s\"\n", + t3font->glyphs[ig].name); + + if (!p->pdc->smokerun) + pdc_logg_cond(p->pdc, 1, trc_api, "[End glyph %d]\n", ig); +} + + +void +pdf_init_type3(PDF *p) +{ + p->t3slot = -1; +} + diff --git a/src/pdflib/pdflib/p_util.c b/src/pdflib/pdflib/p_util.c new file mode 100644 index 0000000..2728236 --- /dev/null +++ b/src/pdflib/pdflib/p_util.c @@ -0,0 +1,733 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_util.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib utility functions + * + */ + +#define P_UTIL_C + +#include "p_intern.h" +#include "p_font.h" +#include "p_image.h" +#include "p_layer.h" + + +/* ------------------------- [hyper]textformat -----------------------------*/ + +void +pdf_check_textformat(PDF *p, pdc_text_format textformat) +{ + if (!p->pdc->ptfrun && p->pdc->unicaplang && textformat != pdc_auto2) + pdc_error(p->pdc, PDF_E_ENC_UNSUPPENCFORMAT, "textformat", 0, 0, 0); + + pdc_logg_cond(p->pdc, 1, trc_encoding, "\tTextformat: \"%s\"\n", + pdc_get_keyword(textformat, pdf_textformat_keylist)); +} + +void +pdf_check_hypertextformat(PDF *p, pdc_text_format hypertextformat) +{ + if (!p->pdc->ptfrun && p->pdc->unicaplang && hypertextformat != pdc_auto2) + pdc_error(p->pdc, PDF_E_ENC_UNSUPPENCFORMAT, "hypertextformat", + 0, 0, 0); + + pdc_logg_cond(p->pdc, 1, trc_encoding, "\tHypertextformat: \"%s\"\n", + pdc_get_keyword(hypertextformat, pdf_textformat_keylist)); +} + + +/* ------------------------- hypertextencoding -----------------------------*/ + +void +pdf_check_hypertextencoding(PDF *p, pdc_encoding hypertextencoding) +{ + if (!p->pdc->ptfrun && p->pdc->unicaplang && + hypertextencoding != pdc_unicode) + pdc_error(p->pdc, PDF_E_ENC_UNSUPPENCFORMAT, "hypertextencoding", + 0, 0, 0); + + pdc_logg_cond(p->pdc, 1, trc_encoding, "\tHypertextencoding: \"%s\"\n", + pdc_get_user_encoding(p->pdc, hypertextencoding)); +} + + +/* ----------------------- string utility functions -----------------------*/ + +static void +pdf_set_convertflags(PDF *p, int *convflags) +{ + (void) p; + (void) convflags; + +} + +const char * +pdf__utf16_to_utf8(PDF *p, const char *utf16string, int len, int *size) +{ + char *utf8string; + int convflags = PDC_CONV_WITHBOM | PDC_CONV_EBCDIC | PDC_CONV_TRY7BYTES; + + pdf_set_convertflags(p, &convflags); + utf8string = pdc_utf16_to_utf8(p->pdc, utf16string, len, convflags, size); + + pdf_insert_utilstring(p, utf8string, pdc_false); + + return utf8string; +} + +const char * +pdf__utf32_to_utf16(PDF *p, const char *utf32string, int len, + const char *ordering, int *outlen) +{ + char *utf16string = pdc_utf32_to_utf16(p->pdc, utf32string, len, + ordering, 0, outlen); + + pdf_insert_utilstring(p, utf16string, pdc_false); + + return utf16string; +} + +const char * +pdf__utf8_to_utf16(PDF *p, const char *utf8string, const char *ordering, + int *outlen) +{ + char *utf16string; + int convflags = PDC_CONV_EBCDIC; + + pdf_set_convertflags(p, &convflags); + utf16string = pdc_utf8_to_utf16(p->pdc, utf8string, ordering, + convflags, outlen); + + pdf_insert_utilstring(p, utf16string, pdc_false); + + return utf16string; +} + +void +pdf_init_stringlists(PDF *p) +{ + p->stringlists_number = 0; + p->stringlists_capacity = 0; + p->stringlists = NULL; + p->stringlistsizes = NULL; + p->utilstrlist_index = -1; + p->utilstring_number = 0; +} + +int +pdf_insert_stringlist(PDF *p, char **stringlist, int ns) +{ + static const char fn[] = "pdf_insert_stringlist"; + int i; + + if (p->stringlists_number == p->stringlists_capacity) + { + int j = p->stringlists_capacity; + + if (!p->stringlists_capacity) + { + p->stringlists_capacity = STRINGLISTS_CHUNKSIZE; + + p->stringlists = (char ***) pdc_malloc(p->pdc, + sizeof(char **) * p->stringlists_capacity, fn); + + p->stringlistsizes = (int *) pdc_malloc(p->pdc, + sizeof(int) * p->stringlists_capacity, fn); + } + else + { + p->stringlists_capacity *= 2; + p->stringlists = (char ***) pdc_realloc(p->pdc, p->stringlists, + sizeof(char **) * p->stringlists_capacity, fn); + + p->stringlistsizes = (int *) pdc_realloc(p->pdc, p->stringlistsizes, + sizeof(int) * p->stringlists_capacity, fn); + } + for (i = j; i < p->stringlists_capacity; i++) + { + p->stringlists[i] = NULL; + p->stringlistsizes[i] = 0; + } + } + + i = p->stringlists_number; + p->stringlists[i] = stringlist; + p->stringlistsizes[i] = ns; + p->stringlists_number++; + + return i; +} + +void +pdf_cleanup_stringlists(PDF *p) +{ + int i; + + if (p->stringlists) + { + for (i = 0; i < p->stringlists_number; i++) + { + if (p->stringlists[i]) + pdc_cleanup_optstringlist(p->pdc, + p->stringlists[i], p->stringlistsizes[i]); + } + pdc_free(p->pdc, p->stringlists); + pdc_free(p->pdc, p->stringlistsizes); + } + + pdf_init_stringlists(p); +} + +#define PDF_MAX_UTILSTRLISTS 10 + +int +pdf_insert_utilstring(PDF *p, const char *utilstring, pdc_bool kdup) +{ + static const char fn[] = "pdf_insert_utilstring"; + char **utilstrlist; + int i = 0; + + if (p->utilstrlist_index == -1) + { + utilstrlist = (char **) pdc_calloc(p->pdc, + PDF_MAX_UTILSTRLISTS * sizeof (char *), fn); + p->utilstrlist_index = + pdf_insert_stringlist(p, utilstrlist, PDF_MAX_UTILSTRLISTS); + } + utilstrlist = p->stringlists[p->utilstrlist_index]; + + if (p->utilstring_number >= PDF_MAX_UTILSTRLISTS) + p->utilstring_number = 0; + i = p->utilstring_number; + if (utilstrlist[i] != NULL) + pdc_free(p->pdc, utilstrlist[i]); + if (kdup) + utilstrlist[i] = pdc_strdup_ext(p->pdc, utilstring, 0, fn); + else + utilstrlist[i] = (char *) utilstring; + p->utilstring_number++; + + return i; +} + +const char * +pdf_get_utilstring(PDF *p, int i) +{ + if (p->utilstrlist_index > -1 && i > -1 && i < p->utilstring_number) + { + char **utilstrlist = p->stringlists[p->utilstrlist_index]; + return utilstrlist[i]; + } + + return NULL; +} + +/* ------------------------ name treatment -------------------------------*/ + +void +pdf_put_pdfname(PDF *p, const char *name) +{ + char *ascname = (char *) name; + int len = (int) strlen(ascname); + + + pdc_put_pdfname(p->out, ascname, len); + +} + + +/* ---------------------- hyper text treatment -------------------------------*/ + +pdc_encoding +pdf_get_hypertextencoding_opt(PDF *p, pdc_resopt *resopts, int *codepage, + pdc_bool verbose) +{ + char **strlist; + pdc_encoding htenc; + + if (pdc_get_optvalues("hypertextencoding", resopts, NULL, &strlist)) + { + int cp; + + htenc = pdf_get_hypertextencoding(p, strlist[0], &cp, verbose); + pdf_check_hypertextencoding(p, htenc); + + if (codepage) + *codepage = cp; + } + else + { + htenc = pdf_get_hypertextencoding_param(p, codepage); + } + + return htenc; +} + +/* hypertext conversion for deprecated functions */ +char * +pdf_convert_hypertext_depr(PDF *p, const char *text, int len) +{ + int outlen; + + pdf_get_hypertextencoding_param(p, NULL); + + return pdf_convert_hypertext(p, text, len, p->hypertextformat, + p->hypertextencoding, p->hypertextcodepage, &outlen, + PDC_UTF8_FLAG, pdc_true); +} + +/* + * Conversion to PDFDoc/EBCDIC or UTF-16/[EBCDIC-]UTF-8 + */ +char * +pdf_convert_hypertext(PDF *p, const char *text, int len, + pdc_text_format hypertextformat, pdc_encoding hypertextencoding, + int codepage, int *outlen, pdc_bool oututf8, pdc_bool verbose) +{ + pdc_encodingvector *inev = NULL, *outev = NULL; + pdc_byte *intext = (pdc_byte *) text, *outtext = NULL; + pdc_text_format textformat = pdc_utf16be; + int convflags = PDC_CONV_WITHBOM | PDC_CONV_TRYBYTES; + + *outlen = 0; + + if (text == NULL) + return NULL; + + if (len == 0) + len = (int) strlen(text); + + /* incoming encoding */ + if (hypertextencoding >= 0) + { + inev = pdc_get_encoding_vector(p->pdc, hypertextencoding); + } + + /* PDFDocEncoding */ + outev = pdc_get_encoding_vector(p->pdc, pdc_pdfdoc); + + /* conversion to UTF-16-BE or PDFDocEncoding / EBCDIC */ + pdf_set_convertflags(p, &convflags); + pdc_convert_string(p->pdc, hypertextformat, codepage, inev, + intext, len, + &textformat, outev, &outtext, outlen, + convflags, verbose); + + + /* conversion to UTF-8 if Unicode */ + if (oututf8 && textformat == pdc_utf16be) + { + pdc_text_format outtextformat = PDC_UTF8; + pdc_byte *newtext = NULL; + + pdc_convert_string(p->pdc, textformat, 0, NULL, outtext, *outlen, + &outtextformat, NULL, &newtext, outlen, + PDC_CONV_WITHBOM, verbose); + pdc_free(p->pdc, outtext); + outtext = newtext; + } + + return (char *) outtext; +} + + +/* + * Conversion from [EBCDIC-]UTF-8 to UTF-16 and from EBCDIC to PDFDoc + */ +static void +pdf_put_hypertext_ext(PDF *p, const char *text, pdc_bool isfilename) +{ + pdc_byte *newtext = NULL; + pdc_encodingvector *outev = pdc_get_encoding_vector(p->pdc, pdc_pdfdoc); + int len = (int) pdc_strlen(text); + int convflags = PDC_CONV_WITHBOM | PDC_CONV_TRYBYTES; + + if (pdc_is_utf8_bytecode(text)) + { + pdc_text_format textformat = PDC_UTF8; + pdc_text_format outtextformat = pdc_utf16be; + + pdf_set_convertflags(p, &convflags); + pdc_convert_string(p->pdc, textformat, 0, NULL, (pdc_byte *) text, len, + &outtextformat, outev, &newtext, &len, + convflags, pdc_true); + text = (const char *) newtext; + } + + if (isfilename) + { + if (pdc_is_utf16be_unicode(text)) + pdc_error(p->pdc, PDC_E_IO_UNSUPP_UNINAME, 0, 0, 0, 0); + pdc_put_pdffilename(p->out, text, len); + } + else + { + pdc_put_pdfstring(p->out, text, len); + } + + if (newtext != NULL) + pdc_free(p->pdc, newtext); +} + +void +pdf_put_hypertext(PDF *p, const char *text) +{ + pdf_put_hypertext_ext(p, text, pdc_false); +} + +void +pdf_put_pdffilename(PDF *p, const char *text) +{ + pdf_put_hypertext_ext(p, text, pdc_true); +} + + +/* ------------------------ name strings -------------------------------*/ + +static void +pdf_prepare_name_string(PDF *p, const char *name, int len, + char **newname, int *newlen, + pdc_encoding *htenc, int *htcp) +{ + *newname = (char *) name; + *newlen = len; + *htenc = pdc_invalidenc; + *htcp = 0; + + if (p->usehyptxtenc && !len && !pdc_is_utf8_bytecode(name)) + { + *htenc = pdf_get_hypertextencoding_param(p, htcp); + + } +} + +char * +pdf_convert_name(PDF *p, const char *name, int len, int flags) +{ + char *resname; + char *newname; + int newlen; + pdc_encoding htenc; + int htcp; + + pdf_prepare_name_string(p, name, len, &newname, &newlen, &htenc, &htcp); + + flags |= PDC_CONV_EBCDIC; + resname = pdc_convert_name_ext(p->pdc, newname, newlen, htenc, htcp, flags); + if (newname != name) + pdc_free(p->pdc, newname); + + return resname; +} + +const char * +pdf_convert_filename(PDF *p, const char *filename, int len, + const char *paramname, int flags) +{ + const char *resfilename; + char *newfilename; + int newlen; + pdc_encoding htenc; + int htcp; + + pdf_prepare_name_string(p, filename, len, &newfilename, &newlen, + &htenc, &htcp); + + flags |= PDC_CONV_EBCDIC; + resfilename = pdc_convert_filename_ext(p->pdc, newfilename, len, + paramname, htenc, htcp, flags); + if (newfilename != filename) + pdc_free(p->pdc, newfilename); + + return resfilename; +} + +void +pdf_add_resource(PDF *p, const char *category, const char *resname) +{ + char *newresname; + int newlen; + pdc_encoding htenc; + int htcp; + + pdf_prepare_name_string(p, resname, 0, &newresname, &newlen, + &htenc, &htcp); + if (newlen) + { + char *tmpresname = pdc_utf16_to_utf8(p->pdc, newresname, newlen, + PDC_CONV_EBCDIC | PDC_CONV_WITHBOM, + &newlen); + pdc_free(p->pdc, newresname); + newresname = tmpresname; + newlen = 0; + } + + pdc_add_resource_ext(p->pdc, category, newresname, NULL, htenc, htcp); + + if (newresname != resname) + pdc_free(p->pdc, newresname); +} + +/* ------------------------ option text list -------------------------------*/ + +int +pdf_get_opt_textlist(PDF *p, const char *keyword, pdc_resopt *resopts, + pdc_encoding enc, int codepage, pdc_bool ishypertext, + const char *fieldname, char **text, char ***textlist) +{ + pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_optlist); + int ns; + char **strlist; + + ns = pdc_get_optvalues(keyword, resopts, NULL, &strlist); + if (ns) + { + pdc_byte *string = NULL; + pdc_encodingvector *inev = NULL, *outev = NULL; + pdc_text_format intextformat = pdc_bytes, outtextformat = pdc_utf16be; + int convflags = PDC_CONV_WITHBOM | PDC_CONV_TRYBYTES; + pdc_bool isutf8; + int i, outlen; + + /* whole option list or string list is in UTF-8 */ + isutf8 = pdc_is_lastopt_utf8(resopts); + + /* Encoding */ + if (ishypertext) + { + /* Initialize */ + if (!isutf8) + { + if (enc < 0 && enc != pdc_unicode && enc != pdc_cid) + enc = pdf_get_hypertextencoding(p, "auto", &codepage, + pdc_true); + if (enc >= 0) + inev = pdc_get_encoding_vector(p->pdc, enc); + } + + /* PDFDocEncoding */ + outev = pdc_get_encoding_vector(p->pdc, pdc_pdfdoc); + } + else + { + if (enc == pdc_invalidenc) + { + if (fieldname) + { + pdc_cleanup_optionlist(p->pdc, resopts); + pdc_error(p->pdc, PDF_E_FF_FONTMISSING, fieldname, 0, 0, 0); + } + return 0; + } + else if (enc >= 0) + { + outev = pdc_get_encoding_vector(p->pdc, enc); + } + } + + if (logg1) + { + if (isutf8) + { + pdc_logg(p->pdc, "\tOption \"%s\" is "PDC_UTF8_STRG" encoded\n", + keyword); + } + else + { + pdc_logg(p->pdc, "\tOption \"%s\" is %s encoded\n", + keyword, pdc_get_user_encoding(p->pdc, enc)); + } + } + + for (i = 0; i < ns; i++) + { + string = (pdc_byte *) strlist[i]; + + { + if (ishypertext || isutf8) + { + intextformat = isutf8 ? PDC_UTF8 : pdc_bytes; + + if (pdc_logg_is_enabled(p->pdc, 2, trc_optlist)) + convflags |= PDC_CONV_LOGGING; + pdf_set_convertflags(p, &convflags); + pdc_convert_string(p->pdc, intextformat, codepage, inev, + string, (int) strlen((char *) string), + &outtextformat, outev, &string, &outlen, + convflags, pdc_true); + pdc_free(p->pdc, strlist[i]); + strlist[i] = (char *) string; + } + } + } + + if (text) + *text = strlist[0]; + else + *textlist = strlist; + + if (fieldname) + { + strlist = (char **) pdc_save_lastopt(resopts, PDC_OPT_SAVEALL); + pdf_insert_stringlist(p, strlist, ns); + } + } + + return ns; +} + +char * +pdf_get_opt_utf8name(PDF *p, const char *keyword, pdc_resopt *resopts) +{ + char **strlist = NULL; + char *utf8name = NULL; + + if (pdc_get_opt_utf8strings(p->pdc, keyword, resopts, PDC_OPT_SAVE1ELEM, + &strlist)) + { + utf8name = strlist[0]; + } + + return utf8name; +} + + +/* -------------------------- errorpolicy -------------------------------*/ + +pdc_bool +pdf_get_errorpolicy(PDF *p, pdc_resopt *resopts, pdc_bool verbose) +{ + int errpol = (int) p->errorpolicy; + + if (resopts != NULL) + pdc_get_optvalues("errorpolicy", resopts, &errpol, NULL); + + if (errpol != (int) errpol_legacy) + verbose = errpol; + + return verbose; +} + + +/* -------------------------- handle check -------------------------------*/ + +void +pdf_check_handle(PDF *p, int handle, pdc_opttype type) +{ + int minval = 0, maxval = 0; + pdc_bool empty = pdc_false; + + switch (type) + { + + case pdc_actionhandle: + maxval = pdf_get_max_action(p); + break; + + case pdc_bookmarkhandle: + maxval = p->outline_count; + break; + + case pdc_colorhandle: + maxval = p->colorspaces_number - 1; + break; + + + case pdc_fonthandle: + maxval = p->fonts_number - 1; + empty = !pdf_isvalid_font(p, handle); + break; + + case pdc_gstatehandle: + maxval = p->extgstates_number - 1; + break; + + + case pdc_imagehandle: + maxval = p->images_capacity - 1; + if (handle >= minval && handle <= maxval && + (!p->images[handle].in_use || + p->xobjects[p->images[handle].no].type == pdi_xobject)) + empty = pdc_true; + break; + + + case pdc_pagehandle: + maxval = p->images_capacity - 1; + if (handle >= minval && handle <= maxval && + (!p->images[handle].in_use || + p->xobjects[p->images[handle].no].type != pdi_xobject)) + empty = pdc_true; + break; + + case pdc_patternhandle: + maxval = p->pattern_number - 1; + break; + + case pdc_shadinghandle: + maxval = p->shadings_number - 1; + break; + + + case pdc_templatehandle: + maxval = p->images_capacity - 1; + if (handle >= minval && handle <= maxval && + (!p->images[handle].in_use || + p->xobjects[p->images[handle].no].type != form_xobject)) + empty = pdc_true; + break; + + + case pdc_stringhandle: + if (p->utilstrlist_index == -1) + empty = pdc_true; + maxval = p->utilstring_number - 1; + break; + + default: + break; + } + + if (handle < minval || handle > maxval || empty) + { + const char *stemp1 = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN, + pdc_get_handletype(type)); + const char *stemp2 = pdc_errprintf(p->pdc, "%d", + (p->pdc->hastobepos && type != pdc_stringhandle) ? + handle + 1 : handle); + pdc_error(p->pdc, PDC_E_ILLARG_HANDLE, stemp1, stemp2, 0, 0); + } +} + +void +pdf_set_clientdata(PDF *p, pdc_clientdata *cdata) +{ + memset(cdata, 0, sizeof(pdc_clientdata)); + + cdata->maxaction = pdf_get_max_action(p); + cdata->maxbookmark = p->outline_count; + cdata->maxcolor = p->colorspaces_number - 1; + cdata->maxdocument = p->pdi_capacity - 1; + cdata->maxfont = p->fonts_number - 1; + cdata->maxgstate = p->extgstates_number - 1; + cdata->maximage = p->images_capacity - 1; + cdata->maxpage = p->images_capacity - 1; + cdata->maxpattern = p->pattern_number - 1; + cdata->maxshading = p->shadings_number - 1; + cdata->maxtemplate = p->images_capacity - 1; + cdata->maxstring = p->utilstring_number - 1; + + cdata->compatibility = p->compatibility; +} diff --git a/src/pdflib/pdflib/p_xgstate.c b/src/pdflib/pdflib/p_xgstate.c new file mode 100644 index 0000000..0e62df9 --- /dev/null +++ b/src/pdflib/pdflib/p_xgstate.c @@ -0,0 +1,514 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_xgstate.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * Extended graphics state handling + * + */ + +#define P_XGSTATE_C + +#include "p_intern.h" +#include "p_font.h" + +static const pdc_keyconn pdf_blendmode_pdfkeylist[] = +{ + {"Normal", BM_Normal}, + {"Multiply", BM_Multiply}, + {"Screen", BM_Screen}, + {"Overlay", BM_Overlay}, + {"Darken", BM_Darken}, + {"Lighten", BM_Lighten}, + {"ColorDodge", BM_ColorDodge}, + {"ColorBurn", BM_ColorBurn}, + {"HardLight", BM_HardLight}, + {"SoftLight", BM_SoftLight}, + {"Difference", BM_Difference}, + {"Exclusion", BM_Exclusion}, + {"Hue", BM_Hue}, + {"Saturation", BM_Saturation}, + {"Color", BM_Color}, + {"Luminosity", BM_Luminosity}, + {NULL, 0} +}; + +/* external graphic state */ +struct pdf_extgstateresource_s +{ + pdc_id obj_id; /* object id of this resource */ + pdc_bool used_on_current_page; /* this resource used on current page */ + + pdc_id font_obj; /* font to use */ + pdc_scalar font_size; /* at what size */ + + pdc_scalar line_width; + int line_cap; + int line_join; + pdc_scalar miter_limit; + pdc_scalar* dash_array; + int dash_count; + pdc_scalar dash_phase; + + pdf_renderingintent ri; + pdc_bool stroke_adjust; + pdc_bool overprint_stroke; + pdc_bool overprint_fill; + int overprint_mode; + + /* + The following entries which take functions are not implemented + since PDFlib has no concept of a function at this time. + + BG - black generation + BG2 - black generation + UCR - undercolor-removal + UCR2 - undercolor-removal + TR - transfer + TR2 - transfer + HT - halftone + */ + + pdc_scalar flatness; + pdc_scalar smoothness; + + /* PDF 1.4 additions */ + pdf_blendmode blendmode; /* blend mode */ + pdc_scalar opacity_fill; /* fill opacity level */ + pdc_scalar opacity_stroke; /* stroke opacity level */ + pdc_bool alpha_is_shape; + pdc_bool text_knockout; +}; + +pdc_id +pdf_get_gstate_id(PDF *p, int gstate) +{ + /* TODO: is this required for ExtGStates used in Shadings? */ + p->extgstates[gstate].used_on_current_page = pdc_true; + + return (p->extgstates[gstate].obj_id); +} + +/* Definitions of Explicit Graphics State options */ +static const pdc_defopt pdf_create_gstate_options[] = +{ + {"alphaisshape", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1, 0.0, 0.0, NULL}, + + {"blendmode", pdc_keywordlist, PDC_OPT_BUILDOR | PDC_OPT_PDC_1_4, 1, 20, + 0.0, 0.0, pdf_blendmode_pdfkeylist}, + +/* These features do not work in Acrobat (5.0.1) + {"dasharray", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 8, + PDF_SMALLREAL, PDC_FLOAT_MAX, NULL}, + + {"dashphase", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1, + 0.0, PDC_FLOAT_MAX, NULL}, + + {"fontsize", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1, + PDF_SMALLREAL, PDC_FLOAT_MAX, NULL}, + + {"font", pdc_fonthandle, PDC_OPT_PDC_1_3 | PDC_OPT_REQUIRIF1, 1, 1, + 0, 0, NULL}, +*/ + + {"flatness", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1, + PDF_SMALLREAL, PDC_FLOAT_MAX, NULL}, + + {"linecap", pdc_integerlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 2.0, + pdf_linecap_keylist}, + + {"linejoin", pdc_integerlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 2.0, + pdf_linejoin_keylist}, + + {"linewidth", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1, + PDF_SMALLREAL, PDC_FLOAT_MAX, NULL}, + + {"miterlimit", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1, 1.0, PDC_FLOAT_MAX, + NULL}, + + {"opacityfill", pdc_scalarlist, PDC_OPT_PDC_1_4 | PDC_OPT_PERCENT, + 1, 1, 0.0, 1.0, NULL}, + + {"opacitystroke", pdc_scalarlist, PDC_OPT_PDC_1_4 | PDC_OPT_PERCENT, + 1, 1, 0.0, 1.0, NULL}, + + {"overprintfill", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0, NULL}, + + {"overprintmode", pdc_integerlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 1.0, NULL}, + + {"overprintstroke", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0, NULL}, + + {"renderingintent", pdc_keywordlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0, + pdf_renderingintent_pdfkeylist}, + + {"smoothness", pdc_scalarlist, PDC_OPT_PDC_1_3 | PDC_OPT_PERCENT, + 1, 1, 0.0, 1.0, NULL}, + + {"strokeadjust", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0, NULL}, + + {"textknockout", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1, 0.0, 0.0, NULL}, + + PDC_OPT_TERMINATE +}; + +static void +pdf_init_extgstateresource(pdf_extgstateresource *egsr) +{ + egsr->used_on_current_page = pdc_false; + + /* we need to tell which parms have been set and which haven't, + ** so we initialize to invalid values. even boolean parms are + ** declared as integers, so we can set them to -1 here. + */ + egsr->font_obj = PDC_NEW_ID; + egsr->font_size = pdc_undef; + + egsr->line_width = pdc_undef; + egsr->line_cap = pdc_undef; + egsr->line_join = pdc_undef; + egsr->miter_limit = pdc_undef; + + egsr->dash_array = NULL; + egsr->dash_count = 0; + egsr->dash_phase = 0.0; + + egsr->ri = AutoIntent; + egsr->stroke_adjust = pdc_undef; + egsr->overprint_stroke = pdc_undef; + egsr->overprint_fill = pdc_undef; + egsr->overprint_mode = pdc_undef; + egsr->flatness = pdc_undef; + egsr->smoothness = pdc_undef; + + egsr->blendmode = BM_None; + egsr->opacity_stroke = pdc_undef; + egsr->opacity_fill = pdc_undef; + egsr->alpha_is_shape = pdc_undef; + egsr->text_knockout = pdc_undef; +} + +static void +pdf_grow_extgstates(PDF *p) +{ + int i; + + p->extgstates = (pdf_extgstateresource *) pdc_realloc(p->pdc, p->extgstates, + sizeof(pdf_extgstateresource) * 2 * p->extgstates_capacity, + "pdf_grow_extgstates"); + + for (i = p->extgstates_capacity; i < 2 * p->extgstates_capacity; i++) { + pdf_init_extgstateresource( &p->extgstates[i] ); + } + + p->extgstates_capacity *= 2; +} + +void +pdf_init_extgstates(PDF *p) +{ + static const char fn[] = "pdf_init_extgstates"; + int i; + + p->extgstates_number = 0; + p->extgstates_capacity = EXTGSTATE_CHUNKSIZE; + + p->extgstates = (pdf_extgstateresource *) + pdc_malloc(p->pdc, + sizeof(pdf_extgstateresource) * p->extgstates_capacity, fn); + + for (i = 0; i < p->extgstates_capacity; i++) { + pdf_init_extgstateresource( &p->extgstates[i] ); + } +} + +void +pdf_write_page_extgstates(PDF *p) +{ + int i, total = 0; + int bias = p->curr_ppt->eg_bias; + + for (i = 0; i < p->extgstates_number; i++) + if (p->extgstates[i].used_on_current_page) + total++; + + if (total > 0 || bias) + { + pdc_puts(p->out, "/ExtGState"); + pdc_begin_dict(p->out); + } + + if (total > 0) + { + for (i = 0; i < p->extgstates_number; i++) + { + if (p->extgstates[i].used_on_current_page) + { + p->extgstates[i].used_on_current_page = pdc_false; /* reset */ + pdc_printf(p->out, "/GS%d", bias + i); + pdc_objref(p->out, "", p->extgstates[i].obj_id); + } + } + + if (!bias) + pdc_end_dict(p->out); + } +} + +void +pdf_get_page_extgstates(PDF *p, pdf_reslist *rl) +{ + int i; + + for (i = 0; i < p->extgstates_number; i++) { + if (p->extgstates[i].used_on_current_page) { + p->extgstates[i].used_on_current_page = pdc_false; /* reset */ + pdf_add_reslist(p, rl, i); + } + } +} + +void +pdf_mark_page_extgstate(PDF *p, int n) +{ + p->extgstates[n].used_on_current_page = pdc_true; +} + +void +pdf_write_doc_extgstates(PDF *p) +{ + int i, j; + + pdf_extgstateresource *gs; + + for (i = 0; i < p->extgstates_number; i++) + { + gs = &p->extgstates[i]; + + pdc_begin_obj(p->out, gs->obj_id); /* ExtGState resource */ + pdc_begin_dict(p->out); + + pdc_puts(p->out, "/Type/ExtGState\n"); + + if (gs->font_obj != PDC_NEW_ID) + { + pdc_puts(p->out, "/Font"); + pdc_begin_array(p->out); + pdc_objref(p->out, "", gs->font_obj); + pdc_printf(p->out, "%f", gs->font_size); + pdc_end_array(p->out); + } + + if (gs->line_width != pdc_undef) + pdc_printf(p->out, "/LW %f\n", gs->line_width); + + if (gs->line_cap != pdc_undef) + pdc_printf(p->out, "/LC %d\n", gs->line_cap); + + if (gs->line_join != pdc_undef) + pdc_printf(p->out, "/LJ %d\n", gs->line_join); + + if (gs->miter_limit != pdc_undef) + pdc_printf(p->out, "/ML %f\n", gs->miter_limit); + + if (gs->dash_count > 0) + { + pdc_printf(p->out, "/D"); + pdc_begin_array(p->out); + pdc_begin_array(p->out); + + for (j = 0; j < gs->dash_count; ++j) + pdc_printf(p->out, "%f ", gs->dash_array[j]); + + pdc_end_array_c(p->out); + pdc_printf(p->out, "%f", gs->dash_phase); + pdc_end_array(p->out); + /* but see page 157 of PDF Reference: integer */ + } + + if (gs->ri != AutoIntent) + pdc_printf(p->out, "/RI/%s\n", + pdc_get_keyword((long) gs->ri, pdf_renderingintent_pdfkeylist)); + + if (gs->stroke_adjust != pdc_undef) + pdc_printf(p->out, "/SA %s\n", PDC_BOOLSTR(gs->stroke_adjust)); + + if (gs->overprint_stroke != pdc_undef) + pdc_printf(p->out, "/OP %s\n", PDC_BOOLSTR(gs->overprint_stroke)); + + if (gs->overprint_fill != pdc_undef) + pdc_printf(p->out, "/op %s\n", PDC_BOOLSTR(gs->overprint_fill)); + else if (gs->overprint_stroke == pdc_true) + pdc_puts(p->out, "/op false\n"); + + if (gs->overprint_mode != pdc_undef) + pdc_printf(p->out, "/OPM %d\n", gs->overprint_mode); + + if (gs->flatness != pdc_undef) + pdc_printf(p->out, "/FL %f\n", gs->flatness); + + if (gs->smoothness != pdc_undef) + pdc_printf(p->out, "/SM %f\n", gs->smoothness); + + if (gs->opacity_fill != pdc_undef) + pdc_printf(p->out, "/ca %f\n", gs->opacity_fill); + + if (gs->blendmode != BM_None) { + const char *modename; + int modecount=0; + + for (j = 0; ; j++) { + if (!pdf_blendmode_pdfkeylist[j].word) + break; + if (gs->blendmode & pdf_blendmode_pdfkeylist[j].code) + modecount++; + } + + pdc_printf(p->out, "/BM"); + + /* + * ACROBUG: Acrobat 7 doesn't like Blend mode arrays with a + * singly entry under some circumstances (many entries? images + * involved?) so we avoid the array if we have only one entry. + */ + if (modecount > 1) + pdc_begin_array(p->out); + + for (j = 0; ; j++) { + modename = pdf_blendmode_pdfkeylist[j].word; + if (!modename) break; + if (gs->blendmode & pdf_blendmode_pdfkeylist[j].code) + pdc_printf(p->out, "/%s", modename); + } + + if (modecount > 1) + pdc_end_array(p->out); + } + + if (gs->opacity_stroke != pdc_undef) + pdc_printf(p->out, "/CA %f\n", gs->opacity_stroke); + + if (gs->alpha_is_shape != pdc_undef) + pdc_printf(p->out, "/AIS %s\n", PDC_BOOLSTR(gs->alpha_is_shape)); + + if (gs->text_knockout != pdc_undef) + pdc_printf(p->out, "/TK %s\n", PDC_BOOLSTR(gs->text_knockout)); + + pdc_end_dict(p->out); + pdc_end_obj(p->out); /* ExtGState resource */ + } +} + +void +pdf_cleanup_extgstates(PDF *p) +{ + int i; + + if (!p->extgstates) + return; + + for (i = 0; i < p->extgstates_number; i++) { + if (p->extgstates[i].dash_array) + pdc_free(p->pdc, p->extgstates[i].dash_array); + } + + pdc_free(p->pdc, p->extgstates); + p->extgstates = NULL; +} + +int +pdf__create_gstate(PDF *p, const char *optlist) +{ + pdf_extgstateresource *gs; + int slot = -1; + int font = pdc_undef; + int inum; + pdc_clientdata data; + pdc_resopt *results; + + if (optlist == NULL || !*optlist) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "optlist", 0, 0, 0); + + slot = p->extgstates_number; + if (slot == p->extgstates_capacity) + pdf_grow_extgstates(p); + + p->extgstates_number++; + gs = &p->extgstates[slot]; + gs->obj_id = pdc_alloc_id(p->out); + + /* parsing optlist */ + pdf_set_clientdata(p, &data); + results = pdc_parse_optionlist(p->pdc, optlist, pdf_create_gstate_options, + &data, pdc_true); + + pdc_get_optvalues("alphaisshape", results, &gs->alpha_is_shape, NULL); + + if (pdc_get_optvalues("blendmode", results, &inum, NULL)) + gs->blendmode = (pdf_blendmode) inum; + + gs->dash_count = pdc_get_optvalues("dasharray", results, NULL, NULL); + gs->dash_array = (pdc_scalar *) pdc_save_lastopt(results, PDC_OPT_SAVEALL); + + pdc_get_optvalues("dashphase", results, &gs->dash_phase, NULL); + + pdc_get_optvalues("flatness", results, &gs->flatness, NULL); + + pdc_get_optvalues("font", results, &font, NULL); + if (font != pdc_undef) + gs->font_obj = p->fonts[font].obj_id; + + pdc_get_optvalues("fontsize", results, &gs->font_size, NULL); + + pdc_get_optvalues("linecap", results, &gs->line_cap, NULL); + + pdc_get_optvalues("linejoin", results, &gs->line_join, NULL); + + pdc_get_optvalues("linewidth", results, &gs->line_width, NULL); + + pdc_get_optvalues("miterlimit", results, &gs->miter_limit, NULL); + + pdc_get_optvalues("opacityfill", results, &gs->opacity_fill, NULL); + + pdc_get_optvalues("opacitystroke", results, &gs->opacity_stroke, NULL); + + pdc_get_optvalues("overprintfill", results, &gs->overprint_fill, NULL); + + pdc_get_optvalues("overprintmode", results, &gs->overprint_mode, NULL); + + pdc_get_optvalues("overprintstroke", results, &gs->overprint_stroke, NULL); + + if (pdc_get_optvalues("renderingintent", results, &inum, NULL)) + gs->ri = (pdf_renderingintent) inum; + + pdc_get_optvalues("smoothness", results, &gs->smoothness, NULL); + + pdc_get_optvalues("strokeadjust", results, &gs->stroke_adjust, NULL); + + pdc_get_optvalues("textknockout", results, &gs->text_knockout, NULL); + + pdc_cleanup_optionlist(p->pdc, results); + + + + return slot; +} + +void +pdf__set_gstate(PDF *p, int gstate) +{ + int bias = p->curr_ppt->eg_bias; + + pdf_check_handle(p, gstate, pdc_gstatehandle); + + pdc_printf(p->out, "/GS%d gs\n", bias + gstate); + p->extgstates[gstate].used_on_current_page = pdc_true; +} diff --git a/src/pdflib/pdflib/p_xmp.c b/src/pdflib/pdflib/p_xmp.c new file mode 100644 index 0000000..eec4002 --- /dev/null +++ b/src/pdflib/pdflib/p_xmp.c @@ -0,0 +1,25 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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_xmp.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib Metadata (XMP) related routines + * + */ + +#define P_XMP_C + +#include "p_intern.h" + + + + diff --git a/src/pdflib/pdflib/pdflib.c b/src/pdflib/pdflib/pdflib.c new file mode 100644 index 0000000..7ecd1f3 --- /dev/null +++ b/src/pdflib/pdflib/pdflib.c @@ -0,0 +1,4052 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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: pdflib.c,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * PDFlib API functions + * + */ + +#define PDFLIB_C + +#include "p_intern.h" + + +#if (defined(WIN32) || defined(__CYGWIN)) +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <winbase.h> +#undef WIN32_LEAN_AND_MEAN +#endif /* WIN32 || __CYGWIN */ + +#if _MSC_VER >= 1310 /* VS .NET 2003 and later */ +/* pdflib.h declares some functions as deprecated, but we don't want to see + * these warnings here */ +#pragma warning(disable: 4995) +#endif + +static const PDFlib_api PDFlib = { + /* version numbers for checking the DLL against client code */ + sizeof(PDFlib_api), /* size of this structure */ + + PDFLIB_MAJORVERSION, /* PDFlib major version number */ + PDFLIB_MINORVERSION, /* PDFlib minor version number */ + PDFLIB_REVISION, /* PDFlib revision number */ + + 0, /* reserved */ + + PDF_activate_item, + PDF_add_bookmark, + PDF_add_bookmark2, + PDF_add_launchlink, + PDF_add_locallink, + PDF_add_nameddest, + PDF_add_note, + PDF_add_note2, + PDF_add_pdflink, + PDF_add_table_cell, + PDF_add_textflow, + PDF_add_thumbnail, + PDF_add_weblink, + PDF_arc, + PDF_arcn, + PDF_attach_file, + PDF_attach_file2, + PDF_begin_document, + PDF_begin_document_callback, + PDF_begin_font, + PDF_begin_glyph, + PDF_begin_item, + PDF_begin_layer, + PDF_begin_mc, + PDF_begin_page, + PDF_begin_page_ext, + PDF_begin_pattern, + PDF_begin_template, + PDF_begin_template_ext, + PDF_boot, + PDF_check_context, + PDF_circle, + PDF_clip, + PDF_close, + PDF_close_image, + PDF_close_pdi, + PDF_close_pdi_document, + PDF_close_pdi_page, + PDF_closepath, + PDF_closepath_fill_stroke, + PDF_closepath_stroke, + PDF_concat, + PDF_continue_text, + PDF_continue_text2, + PDF_create_3dview, + PDF_create_action, + PDF_create_annotation, + PDF_create_bookmark, + PDF_create_field, + PDF_create_fieldgroup, + PDF_create_gstate, + PDF_create_pvf, + PDF_create_textflow, + PDF_curveto, + PDF_define_layer, + PDF_delete, + PDF_delete_pvf, + PDF_delete_table, + PDF_delete_textflow, + PDF_encoding_set_char, + PDF_end_document, + PDF_end_font, + PDF_end_glyph, + PDF_end_item, + PDF_end_layer, + PDF_end_mc, + PDF_end_page, + PDF_end_page_ext, + PDF_end_pattern, + PDF_end_template, + PDF_endpath, + PDF_fill, + PDF_fill_imageblock, + PDF_fill_pdfblock, + PDF_fill_stroke, + PDF_fill_textblock, + PDF_findfont, + PDF_fit_image, + PDF_fit_pdi_page, + PDF_fit_table, + PDF_fit_textflow, + PDF_fit_textline, + PDF_get_api, + PDF_get_apiname, + PDF_get_buffer, + PDF_get_errmsg, + PDF_get_errnum, + PDF_get_majorversion, + PDF_get_minorversion, + PDF_get_opaque, + PDF_get_parameter, + PDF_get_pdi_parameter, + PDF_get_pdi_value, + PDF_get_value, + PDF_info_font, + PDF_info_matchbox, + PDF_info_table, + PDF_info_textflow, + PDF_info_textline, + PDF_initgraphics, + PDF_lineto, + PDF_load_3ddata, + PDF_load_font, + PDF_load_iccprofile, + PDF_load_image, + PDF_makespotcolor, + PDF_mc_point, + PDF_moveto, + PDF_new, + PDF_new2, + PDF_open_CCITT, + PDF_open_file, + PDF_open_image, + PDF_open_image_file, + PDF_open_mem, + PDF_open_pdi, + PDF_open_pdi_callback, + PDF_open_pdi_document, + PDF_open_pdi_page, + PDF_pcos_get_number, + PDF_pcos_get_string, + PDF_pcos_get_stream, + PDF_place_image, + PDF_place_pdi_page, + PDF_process_pdi, + PDF_rect, + PDF_restore, + PDF_resume_page, + PDF_rotate, + PDF_save, + PDF_scale, + PDF_set_border_color, + PDF_set_border_dash, + PDF_set_border_style, + PDF_set_gstate, + PDF_set_info, + PDF_set_info2, + PDF_set_layer_dependency, + PDF_set_parameter, + PDF_set_text_pos, + PDF_set_value, + PDF_setcolor, + PDF_setdash, + PDF_setdashpattern, + PDF_setflat, + PDF_setfont, + PDF_setgray, + PDF_setgray_fill, + PDF_setgray_stroke, + PDF_setlinecap, + PDF_setlinejoin, + PDF_setlinewidth, + PDF_setmatrix, + PDF_setmiterlimit, + PDF_setpolydash, + PDF_setrgbcolor, + PDF_setrgbcolor_fill, + PDF_setrgbcolor_stroke, + PDF_shading, + PDF_shading_pattern, + PDF_shfill, + PDF_show, + PDF_show2, + PDF_show_boxed, + PDF_show_boxed2, + PDF_show_xy, + PDF_show_xy2, + PDF_shutdown, + PDF_skew, + PDF_stringwidth, + PDF_stringwidth2, + PDF_stroke, + PDF_suspend_page, + PDF_translate, + PDF_utf16_to_utf8, + PDF_utf32_to_utf16, + PDF_utf8_to_utf16, + PDF_xshow, + pdf_catch, + pdf_exit_try, + pdf_jbuf, + pdf_rethrow +}; + +static pdc_bool +pdf__check_context(PDF *p) +{ + if (p == NULL || p->magic != PDC_MAGIC) + { + fprintf(stderr, "*** PDFlib context pointer %p is invalid ***\n", p); + return pdc_false; + } + + return pdc_true; +} + +static pdc_bool +pdf_enter_api(PDF *p, const char *funame, pdf_state s, const char *fmt, ...) +{ + /* check whether the client completely screwed up */ + if (pdf__check_context(p)) + { + pdc_bool retval; + va_list args; + + va_start(args, fmt); + retval = pdc_enter_api_logg(p->pdc, funame, pdc_true, fmt, args); + va_end(args); + + if (retval) + { + /* check whether we are in a valid scope */ + if ((p->state_stack[p->state_sp] & s) != 0) + { + return pdc_true; + } + + /* check glyphignore scope */ + if ((p->state_stack[p->state_sp] & pdf_state_glyphignore) == 0) + { + /* pdc_error() will NOT throw an exception + ** (and simply return instead) if the core + ** is already in error state. + */ + pdc_error(p->pdc, PDF_E_DOC_SCOPE, pdf_current_scope(p), + 0, 0, 0); + } + } + + pdc_logg_exit_api(p->pdc, pdc_true, "\n"); + } + + /* invalid PDFlib context or + ** core is in the error state or + ** glyphignore scope + */ + return pdc_false; +} + +static pdc_bool +pdf_enter_api_simple(PDF *p, const char *funame, const char *fmt, ...) +{ + /* check whether the client completely screwed up */ + if (pdf__check_context(p)) + { + pdc_bool retval; + va_list args; + + va_start(args, fmt); + retval = pdc_enter_api_logg(p->pdc, funame, pdc_false, fmt, args); + va_end(args); + + return retval; + } + + return pdc_false; +} + +static int +pdf_exit_boolean_api(PDF *p, int retval) +{ + /* check whether the client completely screwed up */ + if (pdf__check_context(p)) + { + if (p->pdc->hastobepos && retval == -1) + retval += 1; + pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval); + } + + return retval; +} + +static int +pdf_exit_handle_api(PDF *p, int retval) +{ + /* check whether the client completely screwed up */ + if (pdf__check_context(p)) + { + if (p->pdc->hastobepos) + retval += 1; + pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval); + } + + return retval; +} + + +/*************************** + * + * external API functions + * + ***************************/ + +PDFLIB_API void PDFLIB_CALL +PDF_boot(void) +{ + /* nothing yet */ +} + +PDFLIB_API void PDFLIB_CALL +PDF_shutdown(void) +{ + /* nothing yet */ +} + +PDFLIB_API const PDFlib_api * PDFLIB_CALL +PDF_get_api(void) +{ + return &PDFlib; +} + +PDFLIB_API int PDFLIB_CALL +PDF_get_majorversion(void) +{ + return PDFLIB_MAJORVERSION; +} + +PDFLIB_API int PDFLIB_CALL +PDF_get_minorversion(void) +{ + return PDFLIB_MINORVERSION; +} + + +#if (defined(WIN32) || defined(__CYGWIN)) && defined(PDFLIB_EXPORTS) + +/* + * DLL entry function as required by Visual C++. + * It is currently not necessary on Windows, but will eventually + * be used to boot thread-global resources for PDFlib + * (mainly font-related stuff). + */ +BOOL WINAPI +DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved); + +BOOL WINAPI +DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + (void) hModule; + (void) lpReserved; + + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + PDF_boot(); + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + PDF_shutdown(); + break; + } + + return TRUE; +} +#endif /* WIN32 && PDFLIB_EXPORT */ + + +/************************* + * + * general API functions + * + *************************/ + +PDFLIB_API int PDFLIB_CALL +PDF_check_context(PDF *p) +{ + return pdf__check_context(p); +} + +PDFLIB_API int PDFLIB_CALL +PDF_get_errnum(PDF *p) +{ + static const char fn[] = "PDF_get_errnum"; + int retval = -1; + + if (pdf_enter_api_simple(p, fn, "(p_%p)\n", (void *) p)) + { + retval = pdc_get_errnum(p->pdc); + pdc_logg_exit_api(p->pdc, pdc_false, "[%d]\n", retval); + } + + return retval; +} + +PDFLIB_API const char * PDFLIB_CALL +PDF_get_errmsg(PDF *p) +{ + static const char fn[] = "PDF_get_errmsg"; + const char *retval = ""; + + if (pdf_enter_api_simple(p, fn, "(p_%p)\n", (void *) p)) + { + retval = pdc_get_errmsg(p->pdc); + pdc_logg_exit_api(p->pdc, pdc_false, "[\"%T\"]\n", retval, 0); + } + + return retval; +} + +PDFLIB_API const char * PDFLIB_CALL +PDF_get_apiname(PDF *p) +{ + static const char fn[] = "PDF_get_apiname"; + const char *retval = ""; + + if (pdf_enter_api_simple(p, fn, "(p_%p)\n", (void *) p)) + { + retval = pdc_get_apiname(p->pdc); + pdc_logg_exit_api(p->pdc, pdc_false, "[\"%T\"]\n", retval, 0); + } + + return retval; +} + +PDFLIB_API void * PDFLIB_CALL +PDF_get_opaque(PDF *p) +{ + static const char fn[] = "PDF_get_opaque"; + void *retval = NULL; + + if (pdf__check_context(p)) + { + pdc_logg_cond(p->pdc, 1, trc_api, "/* "); + pdf_enter_api_simple(p, fn, "(p_%p) */\n", (void *) p); + retval = p->opaque; + pdc_logg_exit_api(p->pdc, pdc_false, "/* [%p] */\n", retval); + } + + return retval; +} + +PDFLIB_API pdf_jmpbuf * PDFLIB_CALL +pdf_jbuf(PDF *p) +{ + if (pdf__check_context(p)) + return (pdf_jmpbuf *) pdc_jbuf(p->pdc); + + return ((pdf_jmpbuf *) NULL); +} + +PDFLIB_API void PDFLIB_CALL +pdf_exit_try(PDF *p) +{ + if (pdf__check_context(p)) + pdc_exit_try(p->pdc); +} + +PDFLIB_API int PDFLIB_CALL +pdf_catch(PDF *p) +{ + if (pdf__check_context(p)) + return pdc_catch_extern(p->pdc); + + return pdc_false; +} + +PDFLIB_API void PDFLIB_CALL +pdf_rethrow(PDF *p) +{ + static const char fn[] = "pdf_rethrow"; + + if (pdf_enter_api_simple(p, fn, "(p_%p)\n", (void *) p)) + pdc_rethrow(p->pdc); +} + +PDFLIB_API void PDFLIB_CALL +pdf_throw(PDF *p, const char *parm1, const char *parm2, const char *parm3) +{ + if (pdf__check_context(p)) + { + pdc_enter_api(p->pdc, "pdf_throw"); + pdc_error(p->pdc, PDF_E_INT_WRAPPER, parm1, parm2, parm3, NULL); + } +} + + +/********************** + * + * p_3d.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_create_3dview( + PDF *p, + const char *username, + int len, + const char *optlist) +{ + static const char fn[] = "PDF_create_3dview"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_page | pdf_state_document), + "(p_%p, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, username, len, len, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_3DANNOT, 0, 0, 0, 0); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API int PDFLIB_CALL +PDF_load_3ddata( + PDF *p, + const char *filename, + int len, + const char *optlist) +{ + static const char fn[] = "PDF_load_3ddata"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_page | pdf_state_document), + "(p_%p, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, filename, len, len, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_3DANNOT, 0, 0, 0, 0); + } + + return pdf_exit_handle_api(p, retval); +} + + +/********************** + * + * p_actions.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_create_action( + PDF *p, + const char *type, + const char *optlist) +{ + static const char fn[] = "PDF_create_action"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_page | pdf_state_document), + "(p_%p, \"%s\", \"%T\")\n", + (void *) p, type, optlist, 0)) + { + retval = pdf__create_action(p, type, optlist); + } + + return pdf_exit_handle_api(p, retval); +} + + +/********************** + * + * p_annots.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_attach_file( + PDF *p, + double llx, + double lly, + double urx, + double ury, + const char *filename, + const char *description, + const char *author, + const char *mimetype, + const char *icon) +{ + static const char fn[] = "PDF_attach_file"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %f, %f, %f, %f, \"%T\", \"%T\", \"%T\", \"%s\", \"%s\")\n", + (void *) p, llx, lly, urx, ury, filename, 0, description, 0, + author, 0, mimetype, icon)) + { + int len_descr = description ? (int) pdc_strlen(description) : 0; + int len_auth = author ? (int) pdc_strlen(author) : 0; + + pdf__attach_file(p, llx, lly, urx, ury, filename, 0, + description, len_descr, author, len_auth, mimetype, icon); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_attach_file2( + PDF *p, + double llx, + double lly, + double urx, + double 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) +{ + static const char fn[] = "PDF_attach_file2"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %f, %f, %f, %f, \"%T\", /*c*/%d, \"%T\", /*c*/%d, " + "\"%T\", /*c*/%d, \"%s\", \"%s\")\n", + (void *) p, llx, lly, urx, ury, + filename, len_filename, len_filename, + description, len_descr, len_descr, + author, len_auth, len_auth, + mimetype, icon)) + { + pdf__attach_file(p, llx, lly, urx, ury, filename, len_filename, + description, len_descr, author, len_auth, mimetype, icon); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_add_note( + PDF *p, + double llx, + double lly, + double urx, + double ury, + const char *contents, + const char *title, + const char *icon, + int open) +{ + static const char fn[] = "PDF_add_note"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %f, %f, %f, %f, \"%T\", \"%T\", \"%s\", %d)\n", + (void *) p, llx, lly, urx, ury, contents, 0, title, 0, + icon, open)) + { + int len_cont = contents ? (int) pdc_strlen(contents) : 0; + int len_title = title ? (int) pdc_strlen(title) : 0; + + pdf__add_note(p, llx, lly, urx, ury, contents, len_cont, + title, len_title, icon, open); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_add_note2( + PDF *p, + double llx, + double lly, + double urx, + double ury, + const char *contents, int len_cont, + const char *title, int len_title, + const char *icon, + int open) +{ + static const char fn[] = "PDF_add_note2"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %f, %f, %f, %f, \"%T\", /*c*/%d, \"%T\", " + "/*c*/%d, \"%s\", %d)\n", + (void *) p, llx, lly, urx, ury, contents, len_cont, len_cont, + title, len_title, len_title, icon, open)) + { + pdf__add_note(p, llx, lly, urx, ury, contents, len_cont, + title, len_title, icon, open); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_add_pdflink( + PDF *p, + double llx, + double lly, + double urx, + double ury, + const char *filename, + int page, + const char *optlist) +{ + static const char fn[] = "PDF_add_pdflink"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %f, %f, %f, %f, \"%s\", %d, \"%T\")\n", + (void *) p, llx, lly, urx, ury, filename, page, + optlist, 0)) + { + pdf__add_pdflink(p, llx, lly, urx, ury, filename, page, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_add_launchlink( + PDF *p, + double llx, + double lly, + double urx, + double ury, + const char *filename) +{ + static const char fn[] = "PDF_add_launchlink"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %f, %f, %f, %f, \"%s\")\n", + (void *)p, llx, lly, urx, ury, filename)) + { + pdf__add_launchlink(p, llx, lly, urx, ury, filename); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_add_locallink( + PDF *p, + double llx, + double lly, + double urx, + double ury, + int page, + const char *optlist) +{ + static const char fn[] = "PDF_add_locallink"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %f, %f, %f, %f, %d, \"%T\")\n", + (void *) p, llx, lly, urx, ury, page, optlist, 0)) + { + pdf__add_locallink(p, llx, lly, urx, ury, page, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_add_weblink( + PDF *p, + double llx, + double lly, + double urx, + double ury, + const char *url) +{ + static const char fn[] = "PDF_add_weblink"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %f, %f, %f, %f, \"%s\")\n", + (void *) p, llx, lly, urx, ury, url)) + { + pdf__add_weblink(p, llx, lly, urx, ury, url); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_create_annotation( + PDF *p, + double llx, + double lly, + double urx, + double ury, + const char *type, + const char *optlist) +{ + static const char fn[] = "PDF_create_annotation"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %f, %f, %f, %f, \"%s\", \"%T\")\n", + (void *) p, llx, lly, urx, ury, type, optlist, 0)) + { + pdf__create_annotation(p, llx, lly, urx, ury, type, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_set_border_color( + PDF *p, + double red, + double green, + double blue) +{ + static const char fn[] = "PDF_set_border_color"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, %f, %f, %f)\n", (void *) p, red, green, blue)) + { + pdf__set_border_color(p, red, green, blue); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_set_border_dash( + PDF *p, + double b, + double w) +{ + static const char fn[] = "PDF_set_border_dash"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, %f, %f)\n", (void *) p, b, w)) + { + pdf__set_border_dash(p, b, w); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_set_border_style( + PDF *p, + const char *style, + double width) +{ + static const char fn[] = "PDF_set_border_style"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, \"%s\", %f)\n", (void *) p, style, width)) + { + pdf__set_border_style(p, style, width); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_block.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_fill_imageblock( + PDF *p, + int page, + const char *blockname, + int image, + const char *optlist) +{ + static const char fn[] = "PDF_fill_imageblock"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) pdf_state_content, + "(p_%p, %d, \"%T\", %d, \"%T\")\n", + (void *) p, page, blockname, 0, image, optlist, 0)) + { + pdc_set_unsupp_error(p->pdc, + PDF_E_UNSUPP_BLOCK_CONFIG, PDF_E_UNSUPP_BLOCK, pdc_false); + } + + return pdf_exit_boolean_api(p, retval); +} + +PDFLIB_API int PDFLIB_CALL +PDF_fill_pdfblock( + PDF *p, + int page, + const char *blockname, + int contents, + const char *optlist) +{ + static const char fn[] = "PDF_fill_pdfblock"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) pdf_state_content, + "(p_%p, %d, \"%T\", %d, \"%T\")\n", + (void *) p, page, blockname, 0, contents, optlist, 0)) + { + pdc_set_unsupp_error(p->pdc, + PDF_E_UNSUPP_BLOCK_CONFIG, PDF_E_UNSUPP_BLOCK, pdc_false); + } + + return pdf_exit_boolean_api(p, retval); +} + +PDFLIB_API int PDFLIB_CALL +PDF_fill_textblock( + PDF *p, + int page, + const char *blockname, + const char *text, int len, + const char *optlist) +{ + static const char fn[] = "PDF_fill_textblock"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) pdf_state_content, + "(p_%p, %d, \"%T\", \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, page, blockname, 0, text, len, len, optlist, 0)) + { + pdc_set_unsupp_error(p->pdc, + PDF_E_UNSUPP_BLOCK_CONFIG, PDF_E_UNSUPP_BLOCK, pdc_false); + } + + return pdf_exit_boolean_api(p, retval); +} + + +/********************** + * + * p_color.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_makespotcolor(PDF *p, const char *spotname, int len) +{ + static const char fn[] = "PDF_makespotcolor"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_content | pdf_state_document), + "(p_%p, \"%T\", /*c*/%d)\n", + (void *) p, spotname, len, len)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_SPOTCOLOR, 0, 0, 0, 0); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API void PDFLIB_CALL +PDF_setcolor( + PDF *p, + const char *fstype, + const char *colorspace, + double c1, double c2, double c3, double c4) +{ + static const char fn[] = "PDF_setcolor"; + int legal_states; + + if (PDF_GET_STATE(p) == pdf_state_glyph && !pdf_get_t3colorized(p)) + legal_states = pdf_state_page | pdf_state_pattern | pdf_state_template; + else + legal_states = pdf_state_content | pdf_state_document; + + if (pdf_enter_api(p, fn, (pdf_state) legal_states, + "(p_%p, \"%s\", \"%s\", %f, %f, %f, %f)\n", + (void *) p, fstype, colorspace, c1, c2, c3, c4)) + { + pdf__setcolor(p, fstype, colorspace, c1, c2, c3, c4); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setgray(PDF *p, double g) +{ + static const char fn[] = "PDF_setgray"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n", + (void *) p, g)) + { + pdf__setcolor(p, "fillstroke", "gray", g, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setgray_fill(PDF *p, double gray) +{ + static const char fn[] = "PDF_setgray_fill"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n", + (void *) p, gray)) + { + pdf__setcolor(p, "fill", "gray", gray, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setgray_stroke(PDF *p, double gray) +{ + static const char fn[] = "PDF_setgray_stroke"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n", + (void *) p, gray)) + { + pdf__setcolor(p, "stroke", "gray", gray, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setrgbcolor(PDF *p, double r, double g, double b) +{ + static const char fn[] = "PDF_setrgbcolor"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f, %f)\n", + (void *) p, r, g, b)) + { + pdf__setcolor(p, "fillstroke", "rgb", r, g, b, 0); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setrgbcolor_fill(PDF *p, double r, double g, double b) +{ + static const char fn[] = "PDF_setrgbcolor_fill"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f, %f)\n", + (void *) p, r, g, b)) + { + pdf__setcolor(p, "fill", "rgb", r, g, b, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setrgbcolor_stroke(PDF *p, double r, double g, double b) +{ + static const char fn[] = "PDF_setrgbcolor_stroke"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f, %f)\n", + (void *) p, r, g, b)) + { + pdf__setcolor(p, "stroke", "rgb", r, g, b, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_document.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_begin_document( + PDF *p, + const char *filename, int len, + const char *optlist) +{ + static const char fn[] = "\nPDF_begin_document"; + int retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_object, + "(p_%p, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, filename, len, len, optlist, 0)) + { + if (filename && *filename && len < 0) + pdc_error(p->pdc, PDC_E_ILLARG_INT, + "len", pdc_errprintf(p->pdc, "%d", len), 0, 0); + retval = pdf__begin_document(p, filename, len, optlist); + } + + return pdf_exit_boolean_api(p, retval); +} + +PDFLIB_API void PDFLIB_CALL +PDF_begin_document_callback( + PDF *p, + size_t (*i_writeproc)(PDF *p, void *data, size_t size), + const char *optlist) +{ + static const char fn[] = "\nPDF_begin_document_callback"; + size_t (*writeproc)(PDF *, void *, size_t) = i_writeproc; + + if (pdf_enter_api(p, fn, pdf_state_object, + "(p_%p, wp_%p), \"%T\"", (void *) p, (void *) writeproc, optlist, 0)) + { + pdf__begin_document_callback(p, writeproc, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_close(PDF *p) +{ + static const char fn[] = "\nPDF_close"; + + if (pdf_enter_api(p, fn, pdf_state_document, + "(p_%p)\n", (void *) p)) + { + pdf__end_document(p, ""); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_end_document(PDF *p, const char *optlist) +{ + static const char fn[] = "\nPDF_end_document"; + + if (pdf_enter_api(p, fn, pdf_state_document, + "(p_%p, \"%T\")\n", (void *) p, optlist, 0)) + { + pdf__end_document(p, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API const char * PDFLIB_CALL +PDF_get_buffer(PDF *p, long *size) +{ + static const char fn[] = "PDF_get_buffer"; + const char *retval = NULL; + + if (!size) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "size", 0, 0, 0); + + *size = (long) 0; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_object | pdf_state_document), + "(p_%p, &size_%p)\n", (void *) p, (void *) size)) + { + retval = pdf__get_buffer(p, size); + + pdc_logg_exit_api(p->pdc, pdc_false, "[%p, size=%ld]\n", + (void *) (retval), *size); + } + + return retval; +} + +PDFLIB_API int PDFLIB_CALL +PDF_open_file(PDF *p, const char *filename) +{ + static const char fn[] = "\nPDF_open_file"; + int retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_object, "(p_%p, \"%s\")\n", + (void *) p, filename)) + { + retval = pdf__begin_document(p, filename, 0, ""); + } + + return pdf_exit_boolean_api(p, retval); +} + +PDFLIB_API void PDFLIB_CALL +PDF_open_mem( + PDF *p, + size_t (*i_writeproc)(PDF *p, void *data, size_t size)) +{ + static const char fn[] = "\nPDF_open_mem"; + size_t (*writeproc)(PDF *, void *, size_t) = i_writeproc; + + if (pdf_enter_api(p, fn, pdf_state_object, + "(p_%p, wp_%p)\n", (void *) p, (void *) writeproc)) + { + pdf__begin_document_callback(p, writeproc, ""); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_draw.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_arc(PDF *p, double x, double y, double r, double alpha, double beta) +{ + static const char fn[] = "PDF_arc"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_content | pdf_state_path), + "(p_%p, %f, %f, %f, %f, %f)\n", (void *) p, x, y, r, alpha, beta)) + { + pdf__arc(p, x, y, r, alpha, beta); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_arcn(PDF *p, double x, double y, double r, double alpha, double beta) +{ + static const char fn[] = "PDF_arcn"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_content | pdf_state_path), + "(p_%p, %f, %f, %f, %f, %f)\n", (void *) p, x, y, r, alpha, beta)) + { + pdf__arcn(p, x, y, r, alpha, beta); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_circle(PDF *p, double x, double y, double r) +{ + static const char fn[] = "PDF_circle"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_content | pdf_state_path), + "(p_%p, %f, %f, %f)\n", (void *) p, x, y, r)) + { + pdf__circle(p, x, y, r); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_clip(PDF *p) +{ + static const char fn[] = "PDF_clip"; + + if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p)) + { + pdf__clip(p); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_closepath(PDF *p) +{ + static const char fn[] = "PDF_closepath"; + + if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p)) + { + pdf__closepath(p); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_closepath_fill_stroke(PDF *p) +{ + static const char fn[] = "PDF_closepath_fill_stroke"; + + if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p)) + { + pdf__closepath_fill_stroke(p); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_closepath_stroke(PDF *p) +{ + static const char fn[] = "PDF_closepath_stroke"; + + if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p)) + { + pdf__closepath_stroke(p); + } + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); +} + +PDFLIB_API void PDFLIB_CALL +PDF_curveto(PDF *p, + double x_1, double y_1, double x_2, double y_2, double x_3, double y_3) +{ + static const char fn[] = "PDF_curveto"; + + if (pdf_enter_api(p, fn, pdf_state_path, + "(p_%p, %f, %f, %f, %f, %f, %f)\n", + (void *) p, x_1, y_1, x_2, y_2, x_3, y_3)) + { + pdf__curveto(p, x_1, y_1, x_2, y_2, x_3, y_3); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_endpath(PDF *p) +{ + static const char fn[] = "PDF_endpath"; + + if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p)) + { + pdf__endpath(p); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_fill(PDF *p) +{ + static const char fn[] = "PDF_fill"; + + if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p)) + { + pdf__fill(p); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_fill_stroke(PDF *p) +{ + static const char fn[] = "PDF_fill_stroke"; + + if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p)) + { + pdf__fill_stroke(p); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_lineto(PDF *p, double x, double y) +{ + static const char fn[] = "PDF_lineto"; + + if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p, %f, %f)\n", + (void *) p, x, y)) + { + pdf__lineto(p, x, y); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_moveto(PDF *p, double x, double y) +{ + static const char fn[] = "PDF_moveto"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_content | pdf_state_path), + "(p_%p, %f, %f)\n", (void *) p, x, y)) + { + pdf__moveto(p, x, y); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_rcurveto(PDF *p, + double x_1, double y_1, double x_2, double y_2, double x_3, double y_3) +{ + static const char fn[] = "PDF_rcurveto"; + + if (pdf_enter_api(p, fn, pdf_state_path, + "(p_%p, %f, %f, %f, %f, %f, %f)\n", + (void *) p, x_1, y_1, x_2, y_2, x_3, y_3)) + { + pdf__rcurveto(p, x_1, y_1, x_2, y_2, x_3, y_3); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_rect(PDF *p, double x, double y, double width, double height) +{ + static const char fn[] = "PDF_rect"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_content | pdf_state_path), + "(p_%p, %f, %f, %f, %f)\n", (void *) p, x, y, width, height)) + { + pdf__rect(p, x, y, width, height); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_rlineto(PDF *p, double x, double y) +{ + static const char fn[] = "PDF_rlineto"; + + if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p, %f, %f)\n", + (void *) p, x, y)) + { + pdf__rlineto(p, x, y); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_rmoveto(PDF *p, double x, double y) +{ + static const char fn[] = "PDF_rmoveto"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_content | pdf_state_path), + "(p_%p, %f, %f)\n", (void *) p, x, y)) + { + pdf__rmoveto(p, x, y); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_stroke(PDF *p) +{ + static const char fn[] = "PDF_stroke"; + + if (pdf_enter_api(p, fn, pdf_state_path, "(p_%p)\n", (void *) p)) + { + pdf__stroke(p); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + + +/********************** + * + * p_encoding.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_encoding_set_char( + PDF *p, + const char *encoding, + int slot, + const char *glyphname, + int uv) +{ + static const char fn[] = "PDF_encoding_set_char"; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, \"%s\", %d, \"%s\", %d/*0x%04X*/)\n", + (void *) p, encoding, slot, glyphname, uv, uv)) + { + pdf__encoding_set_char(p, encoding, slot, glyphname, uv); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_fields.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_create_field( + PDF *p, + double llx, double lly, double urx, double ury, + const char *name, int len, + const char *type, + const char *optlist) +{ + static const char fn[] = "PDF_create_field"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %f, %f, %f, %f, \"%T\", /*c*/%d, \"%s\", \"%T\")\n", + (void *) p, llx, lly, urx, ury, name, len, len, + type, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_FORMFIELDS, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +PDFLIB_API void PDFLIB_CALL +PDF_create_fieldgroup( + PDF *p, + const char *name, int len, + const char *optlist) +{ + static const char fn[] = "PDF_create_fieldgroup"; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, name, len, len, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_FORMFIELDS, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_font.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_findfont( + PDF *p, + const char *fontname, + const char *encoding, + int embed) +{ + static const char fn[] = "PDF_findfont"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_content | + pdf_state_path | pdf_state_font), + "(p_%p, \"%s\", \"%s\", %d)\n", + (void *) p, fontname, encoding, embed)) + { + if (embed < 0 || embed > 1) + pdc_error(p->pdc, PDC_E_ILLARG_INT, + "embed", pdc_errprintf(p->pdc, "%d", embed), 0, 0); + + retval = pdf__load_font(p, fontname, 0, encoding, + (embed > 0) ? "embedding" : ""); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API double PDFLIB_CALL +PDF_info_font(PDF *p, int font, const char *keyword, const char *optlist) +{ + static const char fn[] = "PDF_info_font"; + double retval = 0; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d, \"%s\", \"%s\")\n", + (void *) p, font, keyword, optlist)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_FONTINFO, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval); + } + + return retval; +} + +PDFLIB_API int PDFLIB_CALL +PDF_load_font( + PDF *p, + const char *fontname, int len, + const char *encoding, + const char *optlist) +{ + static const char fn[] = "PDF_load_font"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_content | + pdf_state_path | pdf_state_font), + "(p_%p, \"%T\", /*c*/%d, \"%s\", \"%T\")\n", + (void *) p, fontname, len, len, encoding, optlist, 0)) + { + retval = pdf__load_font(p, fontname, len, encoding, optlist); + } + + return pdf_exit_handle_api(p, retval); +} + + +/********************** + * + * p_gstate.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_concat(PDF *p, double a, double b, double c, double d, double e, double f) +{ + static const char fn[] = "PDF_concat"; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, %f, %f, %f, %f, %f, %f)\n", (void *) p, a, b, c, d, e, f)) + { + pdf__concat(p, a, b, c, d, e, f); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_initgraphics(PDF *p) +{ + static const char fn[] = "PDF_initgraphics"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p)\n", (void *) p)) + { + pdf__initgraphics(p); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_restore(PDF *p) +{ + static const char fn[] = "PDF_restore"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p)\n", (void *) p)) + { + pdf__restore(p); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_rotate(PDF *p, double phi) +{ + static const char fn[] = "PDF_rotate"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n", + (void *) p, phi)) + { + pdf__rotate(p, phi); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_save(PDF *p) +{ + static const char fn[] = "PDF_save"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p)\n", (void *) p)) + { + pdf__save(p); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_scale(PDF *p, double sx, double sy) +{ + static const char fn[] = "PDF_scale"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f)\n", + (void *) p, sx, sy)) + { + pdf__scale(p, sx, sy); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setdash(PDF *p, double b, double w) +{ + static const char fn[] = "PDF_setdash"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f)\n", + (void *) p, b, w)) + { + pdf__setdash(p, b, w); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setdashpattern(PDF *p, const char *optlist) +{ + static const char fn[] = "PDF_setdashpattern"; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, \"%T\")\n", (void *) p, optlist, 0)) + { + pdf__setdashpattern(p, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setflat(PDF *p, double flat) +{ + static const char fn[] = "PDF_setflat"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n", + (void *) p, flat)) + { + pdf__setflat(p, flat); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setlinecap(PDF *p, int cap) +{ + static const char fn[] = "PDF_setlinecap"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %d)\n", + (void *) p, cap)) + { + pdf__setlinecap(p, cap); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setlinejoin(PDF *p, int join) +{ + static const char fn[] = "PDF_setlinejoin"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %d)\n", + (void *) p, join)) + { + pdf__setlinejoin(p, join); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setlinewidth(PDF *p, double width) +{ + static const char fn[] = "PDF_setlinewidth"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n", + (void *) p, width)) + { + pdf__setlinewidth(p, width); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setmatrix(PDF *p, double a, double b, double c, double d, + double e, double f) +{ + static const char fn[] = "PDF_setmatrix"; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, %f, %f, %f, %f, %f, %f)\n", (void *) p, a, b, c, d, e, f)) + { + pdf__setmatrix(p, a, b, c, d, e, f); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setmiterlimit(PDF *p, double miter) +{ + static const char fn[] = "PDF_setmiterlimit"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f)\n", + (void *) p, miter)) + { + pdf__setmiterlimit(p, miter); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_setpolydash(PDF *p, float *darray, int length) +{ + static const char fn[] = "PDF_setpolydash"; + int i; + + if (!darray) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "darray", 0, 0, 0); + + for (i = 0; i < length; i++) + pdc_logg_cond(p->pdc, 1, trc_api, + "/* *(darray+%d) = %f; */\n", i, darray[i]); + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, darray_%p, /*c*/%d)\n", (void *) p, (void *) darray, length)) + { + char optlist[1024], *sopt; + + sopt = optlist; + sopt += pdc_sprintf(p->pdc, pdc_false, optlist, "dasharray {"); + for (i = 0; i < length; i++) + { + pdc_check_number_limits(p->pdc, "darray", darray[i], + 0.0, PDC_FLOAT_MAX); + sopt += pdc_sprintf(p->pdc, pdc_false, sopt, "%f ", darray[i]); + } + pdc_sprintf(p->pdc, pdc_false, sopt, "}"); + + pdf__setdashpattern(p, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_skew(PDF *p, double alpha, double beta) +{ + static const char fn[] = "PDF_skew"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f)\n", + (void *) p, alpha, beta)) + { + pdf__skew(p, alpha, beta); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_translate(PDF *p, double tx, double ty) +{ + static const char fn[] = "PDF_translate"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f)\n", + (void *) p, tx, ty)) + { + pdf__translate(p, tx, ty); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + + +/********************** + * + * p_hyper.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_add_bookmark( + PDF *p, + const char *text, + int parent, + int open) +{ + static const char fn[] = "PDF_add_bookmark"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_page | pdf_state_document), + "(p_%p, \"%T\", %d, %d)\n", (void *) p, text, 0, parent, open)) + { + int len = text ? (int) pdc_strlen(text) : 0; + retval = pdf__add_bookmark(p, text, len, parent, open); + pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval); + } + + return retval; +} + +PDFLIB_API int PDFLIB_CALL +PDF_add_bookmark2( + PDF *p, + const char *text, int len, + int parent, + int open) +{ + static const char fn[] = "PDF_add_bookmark2"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_page | pdf_state_document), + "(p_%p, \"%T\", /*c*/%d, %d, %d)\n", + (void *) p, text, len, len, parent, open)) + { + retval = pdf__add_bookmark(p, text, len, parent, open); + pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval); + } + + return retval; +} + +PDFLIB_API void PDFLIB_CALL +PDF_add_nameddest( + PDF *p, + const char *name, int len, + const char *optlist) +{ + static const char fn[] = "PDF_add_nameddest"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_page | pdf_state_document), + "(p_%p, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, name, len, len, optlist, 0)) + { + pdf__add_nameddest(p, name, len, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API int PDFLIB_CALL +PDF_create_bookmark( + PDF *p, + const char *text, int len, + const char *optlist) +{ + static const char fn[] = "PDF_create_bookmark"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_page | pdf_state_document), + "(p_%p, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, text, len, len, optlist, 0)) + { + retval = pdf__create_bookmark(p, text, len, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval); + } + return retval; +} + +PDFLIB_API void PDFLIB_CALL +PDF_set_info(PDF *p, const char *key, const char *value) +{ + static const char fn[] = "PDF_set_info"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page), + "(p_%p, \"%T\", \"%T\")\n", + (void *) p, key, 0, value, 0)) + { + int len = value ? (int) pdc_strlen(value) : 0; + pdf__set_info(p, key, value, len); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_set_info2(PDF *p, const char *key, const char *value, int len) +{ + static const char fn[] = "PDF_set_info2"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page), + "(p_%p, \"%T\", \"%T\", /*c*/%d)\n", + (void *) p, key, 0, value, len, len)) + { + pdf__set_info(p, key, value, len); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_icc.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_load_iccprofile( + PDF *p, + const char *profilename, int len, + const char *optlist) +{ + static const char fn[] = "PDF_load_iccprofile"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_content), + "(p_%p, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, profilename, len, len, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_ICC, 0, 0, 0, 0); + } + + return pdf_exit_handle_api(p, retval); +} + + +/********************** + * + * p_image.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_add_thumbnail(PDF *p, int image) +{ + static const char fn[] = "PDF_add_thumbnail"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %d)\n", (void *) p, image)) + { + if (p->pdc->hastobepos) image -= 1; + pdf__add_thumbnail(p, image); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_close_image(PDF *p, int image) +{ + static const char fn[] = "PDF_close_image"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page | pdf_state_font), + "(p_%p, %d)\n", (void *) p, image)) + { + if (p->pdc->hastobepos) image -= 1; + pdf__close_image(p, image); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_fit_image( + PDF *p, + int image, + double x, + double y, + const char *optlist) +{ + static const char fn[] = "PDF_fit_image"; + + /* scope check dependent on image type in kernel function */ + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d, %f, %f, \"%T\")\n", (void *) p, image, x, y, optlist, 0)) + { + if (p->pdc->hastobepos) image -= 1; + pdf__fit_image(p, image, x, y, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API int PDFLIB_CALL +PDF_load_image( + PDF *p, + const char *type, + const char *filename, + int len, + const char *optlist) +{ + static const char fn[] = "PDF_load_image"; + int retval = -1; + + /* scope check dependent on image type in kernel function */ + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page | + pdf_state_font | pdf_state_content), + "(p_%p, \"%s\", \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, type, filename, len, len, optlist, 0)) + { + filename = pdf_convert_filename(p, filename, len, + "filename", PDC_CONV_WITHBOM); + retval = pdf__load_image(p, type, filename, optlist); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API int PDFLIB_CALL +PDF_open_CCITT( + PDF *p, + const char *filename, + int width, + int height, + int BitReverse, int K, int BlackIs1) +{ + static const char fn[] = "PDF_open_CCITT"; + int retval = -1; + + /* scope check dependent on image type in kernel function */ + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page | + pdf_state_font | pdf_state_content), + "(p_%p, \"%s\", %d, %d, %d, %d, %d)\n", + (void *) p, filename, width, height, + BitReverse, K, BlackIs1)) + { + char optlist[128]; + + pdc_sprintf(p->pdc, pdc_false, optlist, + "width %d height %d bitreverse %s K %d invert %s", + width, height, PDC_BOOLSTR(BitReverse), K, PDC_BOOLSTR(BlackIs1)); + filename = pdf_convert_filename(p, filename, 0, + "filename", PDC_CONV_WITHBOM); + retval = pdf__load_image(p, "CCITT", filename, optlist); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API int PDFLIB_CALL +PDF_open_image( + PDF *p, + const char *type, + const char *source, + const char *data, + long length, + int width, + int height, + int components, + int bpc, + const char *params) +{ + static const char fn[] = "PDF_open_image"; + int retval = -1; + + /* scope check dependent on image type in kernel function */ + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page | + pdf_state_font | pdf_state_content), + "(p_%p, \"%s\", \"%s\", idata_%p, %ld, %d, %d, %d, %d, \"%s\")\n", + (void *) p, type, source, (void *) data, length, + width, height, components, bpc, params)) + { + const char *filename = data; + char optlist[512]; + pdc_bool memory = pdc_false; + + if (type == NULL || *type == '\0') + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "type", 0, 0, 0); + + if (source == NULL || *source == '\0') + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "source", 0, 0, 0); + + if (!strcmp(type, "raw") && data == NULL) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "data", 0, 0, 0); + + /* create optlist */ + optlist[0] = 0; + if (!strcmp(type, "raw") || !strcmp(type, "ccitt")) + pdc_sprintf(p->pdc, pdc_false, optlist, + "width %d height %d components %d bpc %d ", + width, height, components, bpc); + + if (length < 0L) + { + strcat(optlist, "bitreverse true "); + length = -length; + } + + strcat(optlist, "reftype "); + if (!strcmp(source, "fileref")) + strcat(optlist, "fileref "); + else if (!strcmp(source, "memory")) + { + memory = pdc_true; + strcat(optlist, "direct "); + } + else if (!strcmp(source, "url")) + strcat(optlist, "url "); + + if (params != NULL && *params != '\0') + { + char **items; + int i, nitems; + + /* separator characters because of compatibility */ + nitems = pdc_split_stringlist(p->pdc, params, "\t :", 0, &items); + for (i = 0; i < nitems; i++) + { + if (!strcmp(items[i], "invert")) + strcat(optlist, "invert true "); + else if (!strcmp(items[i], "ignoremask")) + strcat(optlist, "ignoremask true "); + else if (!strcmp(items[i], "inline")) + strcat(optlist, "inline true "); + else if (!strcmp(items[i], "interpolate")) + strcat(optlist, "interpolate true "); + else if (!strcmp(items[i], "mask")) + strcat(optlist, "mask true "); + else if (!strcmp(items[i], "/K")) + strcat(optlist, "K "); + else if (!strcmp(items[i], "/BlackIs1")) + strcat(optlist, "invert "); + else + strcat(optlist, items[i]); + } + pdc_cleanup_stringlist(p->pdc, items); + } + + /* create virtual file */ + if (memory) + { + filename = "__raw__image__data__"; + pdc__create_pvf(p->pdc, filename, data, (size_t) length, ""); + } + + filename = pdf_convert_filename(p, filename, 0, + "filename", PDC_CONV_WITHBOM); + retval = pdf__load_image(p, type, filename, (const char *) optlist); + + if (memory) + (void) pdc__delete_pvf(p->pdc, filename); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API int PDFLIB_CALL +PDF_open_image_file( + PDF *p, + const char *type, + const char *filename, + const char *stringparam, + int intparam) +{ + static const char fn[] = "PDF_open_image_file"; + int retval = -1; + + /* scope check dependent on image type in kernel function */ + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page | + pdf_state_font | pdf_state_content), + "(p_%p, \"%s\", \"%s\", \"%s\", %d)\n", + (void *) p, type, filename, stringparam, intparam)) + { + char optlist[128]; + + optlist[0] = 0; + if (stringparam != NULL && *stringparam != '\0') + { + if (!strcmp(stringparam, "invert")) + strcpy(optlist, "invert true "); + else if (!strcmp(stringparam, "inline")) + strcpy(optlist, "inline true "); + else if (!strcmp(stringparam, "ignoremask")) + strcpy(optlist, "ignoremask true "); + else if (!strcmp(stringparam, "mask")) + strcpy(optlist, "mask true "); + else if (!strcmp(stringparam, "masked")) + pdc_sprintf(p->pdc, pdc_false, optlist, "masked %d ", + intparam); + else if (!strcmp(stringparam, "colorize")) + pdc_sprintf(p->pdc, pdc_false, optlist, "colorize %d ", + intparam); + else if (!strcmp(stringparam, "page")) + pdc_sprintf(p->pdc, pdc_false, optlist, "page %d ", + intparam); + else if (!strcmp(stringparam, "iccprofile")) + pdc_sprintf(p->pdc, pdc_false, optlist, "iccprofile %d ", + intparam); + } + filename = pdf_convert_filename(p, filename, 0, + "filename", PDC_CONV_WITHBOM); + retval = pdf__load_image(p, type, filename, optlist); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API void PDFLIB_CALL +PDF_place_image( + PDF *p, + int image, + double x, + double y, + double scale) +{ + static const char fn[] = "PDF_place_image"; + + /* scope check dependent on image type in kernel function */ + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d, %f, %f, %f)\n", (void *) p, image, x, y, scale)) + { + char optlist[128]; + + pdc_sprintf(p->pdc, pdc_false, optlist, "dpi none scale %f", scale); + if (p->pdc->hastobepos) image -= 1; + pdf__fit_image(p, image, x, y, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_kerning.c + * + **********************/ + +PDFLIB_API double PDFLIB_CALL +PDF_get_kern_amount( + PDF *p, + int font, + int firstchar, + int secondchar) +{ + static const char fn[] = "PDF_get_kern_amount"; + double retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_content | pdf_state_path), + "(p_%p, %d, %d, %d)\n", (void *) p, font, firstchar, secondchar)) + { + if (p->pdc->hastobepos) font -= 1; + pdc_error(p->pdc, PDF_E_UNSUPP_KERNING, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval); + } + + return retval; +} + + +/********************** + * + * p_layer.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_begin_layer(PDF *p, int layer) +{ + static const char fn[] = "PDF_begin_layer"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p, %d)\n", (void *) p, layer)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_LAYER, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API int PDFLIB_CALL +PDF_define_layer( + PDF *p, + const char *name, int len, + const char *optlist) +{ + static const char fn[] = "PDF_define_layer"; + int retval = -1; + + if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, name, len, len, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_LAYER, 0, 0, 0, 0); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API void PDFLIB_CALL +PDF_end_layer(PDF *p) +{ + static const char fn[] = "PDF_end_layer"; + + if (pdf_enter_api(p, fn, pdf_state_page, + "(p_%p)\n", (void *) p)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_LAYER, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_set_layer_dependency( + PDF *p, + const char *type, + const char *optlist) +{ + static const char fn[] = "PDF_set_layer_dependency"; + + if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, \"%s\", \"%T\")\n", (void *) p, type, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_LAYER, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_mbox.c + * + **********************/ + + PDFLIB_API double PDFLIB_CALL + PDF_info_matchbox(PDF *p, const char *boxname, int len, int num, + const char *keyword) + { + static const char fn[] = "PDF_info_matchbox"; + double retval = 0; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_content | pdf_state_path | pdf_state_font), + "(p_%p, \"%T\", /*c*/%d, %d, \"%s\")\n", + (void *) p, boxname, len, len, num, keyword)) + { + retval = pdf__info_matchbox(p, boxname, len, num, keyword); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval); + } + + return retval; +} + + +/********************** + * + * p_object.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_delete(PDF *p) +{ + static const char fn[] = "PDF_delete"; + + if (pdf_enter_api_simple(p, fn, "(p_%p)\n", (void *) p)) + { + pdf__delete(p); + } +} + +PDFLIB_API PDF * PDFLIB_CALL +PDF_new(void) +{ + return pdf__new(NULL, NULL, NULL, NULL, NULL); +} + +PDFLIB_API PDF * PDFLIB_CALL +PDF_new2( + void (*errorhandler)(PDF *p, int type, const char *msg), + void* (*allocproc)(PDF *p, size_t size, const char *caller), + void* (*reallocproc)(PDF *p, void *mem, size_t size, const char *caller), + void (*freeproc)(PDF *p, void *mem), + void *opaque) +{ + return pdf__new(errorhandler, allocproc, reallocproc, freeproc, opaque); +} + + +/********************** + * + * p_page.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_begin_page(PDF *p, double width, double height) +{ + static const char fn[] = "\nPDF_begin_page"; + + if (pdf_enter_api(p, fn, pdf_state_document, "(p_%p, %f, %f)\n", + (void *) p, width, height)) + { + pdf__begin_page(p, width, height); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_begin_page_ext(PDF *p, double width, double height, const char *optlist) +{ + static const char fn[] = "\nPDF_begin_page_ext"; + + if (pdf_enter_api(p, fn, pdf_state_document, "(p_%p, %f, %f, \"%T\")\n", + (void *) p, width, height, optlist, 0)) + { + pdf__begin_page_ext(p, width, height, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_end_page(PDF *p) +{ + static const char fn[] = "PDF_end_page"; + + if (pdf_enter_api(p, fn, pdf_state_page, "(p_%p)\n", (void *) p)) + { + pdf__end_page_ext(p, ""); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_end_page_ext(PDF *p, const char *optlist) +{ + static const char fn[] = "PDF_end_page_ext"; + + if (pdf_enter_api(p, fn, pdf_state_page, "(p_%p, \"%T\")\n", + (void *) p, optlist, 0)) + { + pdf__end_page_ext(p, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_resume_page(PDF *p, const char *optlist) +{ + static const char fn[] = "\nPDF_resume_page"; + + if (pdf_enter_api(p, fn, pdf_state_document, "(p_%p, \"%T\")\n", + (void *) p, optlist, 0)) + { + pdf__resume_page(p, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_suspend_page(PDF *p, const char *optlist) +{ + static const char fn[] = "PDF_suspend_page"; + + if (pdf_enter_api(p, fn, pdf_state_page, "(p_%p, \"%T\")\n", + (void *) p, optlist, 0)) + { + pdf__suspend_page(p, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_parameter.c + * + **********************/ + +PDFLIB_API const char * PDFLIB_CALL +PDF_get_parameter(PDF *p, const char *key, double modifier) +{ + static const char fn[] = "PDF_get_parameter"; + const char *retval = ""; + + if (!pdc_stricmp(key, "version")) + { + retval = PDFLIB_VERSIONSTRING; + } + else if (!pdc_stricmp(key, "pdi")) + { + retval = "false"; + } + else if (pdf_enter_api(p, fn, (pdf_state) pdf_state_all, + "(p_%p, \"%s\", %f)\n", (void *) p, key, modifier)) + { + retval = pdf__get_parameter(p, key, modifier); + + pdc_logg_exit_api(p->pdc, pdc_true, "[\"%T\"]\n", retval, 0); + } + + return retval; +} + +PDFLIB_API double PDFLIB_CALL +PDF_get_value(PDF *p, const char *key, double modifier) +{ + static const char fn[] = "PDF_get_value"; + double retval = -1; + + if (!pdc_stricmp(key, "major")) + { + retval = PDFLIB_MAJORVERSION; + } + else if (!pdc_stricmp(key, "minor")) + { + retval = PDFLIB_MINORVERSION; + } + else if (!pdc_stricmp(key, "revision")) + { + retval = PDFLIB_REVISION; + } + else if (pdf_enter_api(p, fn, (pdf_state) pdf_state_all, + "(p_%p, \"%s\", %f)\n", (void *) p, key, modifier)) + { + retval = pdf__get_value(p, key, modifier); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval); + } + + return retval; +} + +PDFLIB_API void PDFLIB_CALL +PDF_set_parameter(PDF *p, const char *key, const char *value) +{ + static const char fn[] = "PDF_set_parameter"; + + if (pdf_enter_api(p, fn, (pdf_state) pdf_state_all, + "(p_%p, \"%s\", \"%T\")\n", + (void *) p, key, value, 0)) + { + pdf__set_parameter(p, key, value); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_set_value(PDF *p, const char *key, double value) +{ + static const char fn[] = "PDF_set_value"; + + if (pdf_enter_api(p, fn, (pdf_state) pdf_state_all, + "(p_%p, \"%s\", %f)\n", (void *) p, key, value)) + { + pdf__set_value(p, key, value); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + + +/********************** + * + * p_pattern.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_begin_pattern( + PDF *p, + double width, + double height, + double xstep, + double ystep, + int painttype) +{ + static const char fn[] = "\nPDF_begin_pattern"; + int retval = -1; + + if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, %f, %f, %f, %f, %d)\n", + (void *) p, width, height, xstep, ystep, painttype)) + { + retval = pdf__begin_pattern(p, width, height, xstep, ystep, painttype); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API void PDFLIB_CALL +PDF_end_pattern(PDF *p) +{ + static const char fn[] = "PDF_end_pattern"; + + if (pdf_enter_api(p, fn, pdf_state_pattern, "(p_%p)\n", (void *) p)) + { + pdf__end_pattern(p); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_pdi.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_close_pdi(PDF *p, int doc) +{ + static const char fn[] = "PDF_close_pdi"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page), + "(p_%p, %d)\n", (void *) p, doc)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_close_pdi_document(PDF *p, int doc) +{ + static const char fn[] = "PDF_close_pdi_document"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page), + "(p_%p, %d)\n", (void *) p, doc)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_close_pdi_page(PDF *p, int page) +{ + static const char fn[] = "PDF_close_pdi_page"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, %d)\n", (void *) p, page)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_fit_pdi_page(PDF *p, int page, double x, double y, const char *optlist) +{ + static const char fn[] = "PDF_fit_pdi_page"; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, %d, %f, %f, \"%T\")\n", (void *) p, page, x, y, optlist, 0)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API const char *PDFLIB_CALL +PDF_get_pdi_parameter( + PDF *p, + const char *key, + int doc, + int page, + int reserved, + int *len) +{ + static const char fn[] = "PDF_get_pdi_parameter"; + const char *retval = ""; + + if (len) + *len = 0; + + if (pdf_enter_api(p, fn, pdf_state_all, + len ? "(p_%p, \"%s\", %d, %d, %d, /*c*/&len_%p)" : + "(p_%p, \"%s\", %d, %d, %d, /*c*/NULL)\n", + (void *) p, key, doc, page, reserved, len)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, "[\"%T\"]\n", retval, 0); + } + + return retval; +} + +PDFLIB_API double PDFLIB_CALL +PDF_get_pdi_value( + PDF *p, + const char *key, + int doc, + int page, + int reserved) +{ + static const char fn[] = "PDF_get_pdi_value"; + double retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, \"%s\", %d, %d, %d)\n", + (void *) p, key, doc, page, reserved)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval); + } + + return retval; +} + +PDFLIB_API int PDFLIB_CALL +PDF_open_pdi( + PDF *p, + const char *filename, + const char *optlist, + int len) +{ + static const char fn[] = "PDF_open_pdi"; + int retval = -1; + + /* state "object" doesn't make sense until PDFlib can handle this, + ** but is allowed here for version compatibility + */ + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page), + "(p_%p, \"%T\", \"%T\", %d)\n", + (void *) p, filename, len, optlist, 0, len)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API int PDFLIB_CALL +PDF_open_pdi_document( + PDF *p, + const char *filename, + int len, + const char *optlist) +{ + static const char fn[] = "PDF_open_pdi_document"; + int retval = -1; + + /* state "object" doesn't make sense until PDFlib can handle this, + ** but is allowed here for version compatibility + */ + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page), + "(p_%p, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, filename, len, len, optlist, 0)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API int PDFLIB_CALL +PDF_open_pdi_callback( + PDF *p, + void *opaque, + size_t filesize, + size_t (*readproc)(void *opaque, void *buffer, size_t size), + int (*seekproc)(void *opaque, long offset), + const char *optlist) +{ + static const char fn[] = "PDF_open_pdi_callback"; + int retval = -1; + + /* state "object" doesn't make sense until PDFlib can handle this, + ** but is allowed here for version compatibility + */ + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_object | pdf_state_document | pdf_state_page), + "(p_%p, opaque_%p, %ld, readproc_%p, seekproc_%p \"%T\")\n", + (void *)p, opaque, filesize, readproc, seekproc, optlist, 0)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + } + + return pdf_exit_handle_api(p, retval); +} + + +PDFLIB_API int PDFLIB_CALL +PDF_open_pdi_page(PDF *p, int doc, int pagenumber, const char* optlist) +{ + static const char fn[] = "PDF_open_pdi_page"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, %d, %d, \"%T\")\n", (void *) p, doc, pagenumber, optlist, 0)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + } + + return pdf_exit_handle_api(p, retval); +} + +/* pCOS "context free parameters" +*/ +typedef enum +{ + cfp_none, cfp_major, cfp_minor, cfp_revision, cfp_version +} pcos_cfp; + +static pcos_cfp +get_pcos_cfp(const char *fmt, va_list args) +{ + const char *cfp = fmt; + + if (strcmp(fmt, "%s") == 0) + cfp = va_arg(args, char *); + + if (strcmp(cfp, "major") == 0) + return cfp_major; + + if (strcmp(cfp, "minor") == 0) + return cfp_minor; + + if (strcmp(cfp, "revision") == 0) + return cfp_revision; + + if (strcmp(cfp, "version") == 0) + return cfp_version; + + return cfp_none; +} /* get_pcos_cfp */ + + +PDFLIB_API double PDFLIB_CALL +PDF_pcos_get_number(PDF *p, int doc, const char *path, ...) +{ + static const char fn[] = "PDF_pcos_get_number"; + + double result = 0; + pcos_cfp cfp; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d, \"%s\")\n", (void *) p, doc, path)) + { + va_list args; + + if (!path) + path = ""; + + va_start(args, path); + cfp = get_pcos_cfp(path, args); + va_end(args); + + switch (cfp) + { + case cfp_major: + result = PDFLIB_MAJORVERSION; + break; + + case cfp_minor: + result = PDFLIB_MINORVERSION; + break; + + case cfp_revision: + result = PDFLIB_REVISION; + break; + + default: + { + pdc_set_unsupp_error(p->pdc, + PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, pdc_false); + break; + } + } /* switch */ + + pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", result); + } + return result; +} + +PDFLIB_API const char * PDFLIB_CALL +PDF_pcos_get_string(PDF *p, int doc, const char *path, ...) +{ + static const char fn[] = "PDF_pcos_get_string"; + + const char *result = ""; + pcos_cfp cfp; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d, \"%s\")\n", (void *) p, doc, path)) + { + va_list args; + + if (!path) + path = ""; + + va_start(args, path); + cfp = get_pcos_cfp(path, args); + va_end(args); + + switch (cfp) + { + case cfp_version: + result = PDFLIB_VERSIONSTRING; + break; + + default: + { + pdc_set_unsupp_error(p->pdc, + PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, pdc_false); + break; + } + } /* switch */ + + pdc_logg_exit_api(p->pdc, pdc_true, "[\"%T\"]\n", result, 0); + } + return result; +} + +PDFLIB_API const unsigned char * PDFLIB_CALL +PDF_pcos_get_stream( + PDF *p, int doc, int *len, const char *optlist, const char *path, ...) +{ + static const char fn[] = "PDF_pcos_get_stream"; + + const unsigned char *result = (const unsigned char *) ""; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d, \"%s\", \"%s\")\n", (void *) p, doc, optlist, path)) + { + int length = 0; + + *len = 0; + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, "[\"%T\", len=%d]\n", + result, length, length); + } + + return result; +} + +PDFLIB_API void PDFLIB_CALL +PDF_place_pdi_page(PDF *p, int page, double x, double y, double sx, double sy) +{ + static const char fn[] = "PDF_place_pdi_page"; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, %d, %f, %f, %f, %f)\n", (void *) p, page, x, y, sx, sy)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API int PDFLIB_CALL +PDF_process_pdi(PDF *p, int doc, int page, const char *optlist) +{ + static const char fn[] = "PDF_process_pdi"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document), + "(p_%p, %d, %d, \"%T\")\n", (void *) p, doc, page, optlist, 0)) + { + pdc_set_unsupp_error(p->pdc, PDF_E_UNSUPP_PDI_CONFIG, PDF_E_UNSUPP_PDI, + pdc_false); + } + + return pdf_exit_boolean_api(p, retval); +} + + +/********************** + * + * p_resource.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_create_pvf( + PDF *p, const char *filename, int len, + const void *data, size_t size, + const char *optlist) +{ + static const char fn[] = "PDF_create_pvf"; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, \"%T\", /*c*/%d, data_%p, /*c*/%d, \"%T\")\n", + (void *) p, filename, len, len, data, size, optlist, 0)) + { + filename = pdf_convert_filename(p, filename, len, "filename", 0); + pdc__create_pvf(p->pdc, filename, data, size, optlist); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API int PDFLIB_CALL +PDF_delete_pvf(PDF *p, const char *filename, int len) +{ + static const char fn[] = "PDF_delete_pvf"; + int retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, \"%T\", /*c*/%d)\n", + (void *) p, filename, len, len)) + { + filename = pdf_convert_filename(p, filename, len, "filename", 0); + retval = pdc__delete_pvf(p->pdc, filename); + } + + return pdf_exit_boolean_api(p, retval); +} + + +/********************** + * + * p_shading.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_shading( + PDF *p, + const char *type, + double x_0, double y_0, + double x_1, double y_1, + double c_1, double c_2, double c_3, double c_4, + const char *optlist) +{ + static const char fn[] = "PDF_shading"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page | pdf_state_font), + "(p_%p, \"%s\", %f, %f, %f, %f, %f, %f, %f, %f, \"%T\")\n", + (void *) p, type, x_0, y_0, x_1, y_1, c_1, c_2, c_3, c_4, + optlist, 0)) + { + retval = pdf__shading(p, type, x_0, y_0, x_1, y_1, + c_1, c_2, c_3, c_4, optlist); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API int PDFLIB_CALL +PDF_shading_pattern(PDF *p, int shading, const char *optlist) +{ + static const char fn[] = "PDF_shading_pattern"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_page | pdf_state_font), + "(p_%p, %d, \"%T\")\n", (void *) p, shading, optlist, 0)) + { + if (p->pdc->hastobepos) shading -= 1; + retval = pdf__shading_pattern(p, shading, optlist); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API void PDFLIB_CALL +PDF_shfill(PDF *p, int shading) +{ + static const char fn[] = "PDF_shfill"; + int legal_states; + + if (PDF_GET_STATE(p) == pdf_state_glyph && !pdf_get_t3colorized(p)) + legal_states = pdf_state_page | pdf_state_pattern | pdf_state_template; + + else if (PDF_GET_STATE(p) == pdf_state_pattern && + pdf_get_shading_painttype(p) == 2) + legal_states = pdf_state_page | pdf_state_glyph | pdf_state_template; + + else + legal_states = pdf_state_content; + + if (pdf_enter_api(p, fn, (pdf_state) legal_states, + "(p_%p, %d)\n", (void *) p, shading)) + { + if (p->pdc->hastobepos) shading -= 1; + pdf__shfill(p, shading); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_table.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_add_table_cell(PDF *p, int table, int column, int row, const char *text, + int len, const char *optlist) +{ + static const char fn[] = "PDF_add_table_cell"; + int retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d, %d, %d, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, table, column, row, text, len, len, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TABLES, 0, 0, 0, 0); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API void PDFLIB_CALL +PDF_delete_table(PDF *p, int table, const char *optlist) +{ + static const char fn[] = "PDF_delete_table"; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d, \"%T\")\n", (void *) p, table, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TABLES, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API const char * PDFLIB_CALL +PDF_fit_table(PDF *p, int table, double llx, double lly, + double urx, double ury, const char *optlist) +{ + static const char fn[] = "PDF_fit_table"; + const char *retval = ""; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, %d, %f, %f, %f, %f, \"%T\")\n", + (void *) p, table, llx, lly, urx, ury, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TABLES, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, "[\"%s\"]\n", retval); + } + + return retval; +} + +PDFLIB_API double PDFLIB_CALL +PDF_info_table(PDF *p, int table, const char *keyword) +{ + static const char fn[] = "PDF_info_table"; + double retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d, \"%s\")\n", (void *) p, table, keyword)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TABLES, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval); + } + + return retval; +} + + +/********************** + * + * p_tagged.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_begin_mc(PDF *p, const char *tag, const char *optlist) +{ + static const char fn[] = "PDF_begin_mc"; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, \"%s\", \"%T\")\n", (void *) p, tag, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_MC, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_end_mc(PDF *p) +{ + static const char fn[] = "PDF_end_mc"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p", (void *) p)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_MC, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_mc_point(PDF *p, const char *tag, const char *optlist) +{ + static const char fn[] = "PDF_mc_point"; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, \"%s\", \"%T\")\n", (void *) p, tag, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_MC, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_activate_item(PDF *p, int id) +{ + static const char fn[] = "PDF_activate_item"; + + if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, %d)\n", (void *) p, id)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TAGGED, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API int PDFLIB_CALL +PDF_begin_item( + PDF *p, + const char *tag, + const char *optlist) +{ + static const char fn[] = "PDF_begin_item"; + int retval = -1; + + /* further check in kernel function */ + if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, \"%s\", \"%T\")\n", (void *) p, tag, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TAGGED, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval); + } + return retval; +} + +PDFLIB_API void PDFLIB_CALL +PDF_end_item(PDF *p, int id) +{ + static const char fn[] = "PDF_end_item"; + + /* further check in kernel function */ + if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, %d)\n", (void *) p, id)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TAGGED, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_template.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_begin_template(PDF *p, double width, double height) +{ + static const char fn[] = "\nPDF_begin_template"; + int retval = -1; + + if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, %f, %f)\n", (void *) p, width, height)) + { + retval = pdf__begin_template(p, width, height, ""); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API int PDFLIB_CALL +PDF_begin_template_ext(PDF *p, double width, double height, const char *optlist) +{ + static const char fn[] = "\nPDF_begin_template_ext"; + int retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_document, "(p_%p, %f, %f, \"%T\")\n", + (void *) p, width, height, optlist, 0)) + { + retval = pdf__begin_template(p, width, height, optlist); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API void PDFLIB_CALL +PDF_end_template(PDF *p) +{ + static const char fn[] = "PDF_end_template"; + + if (pdf_enter_api(p, fn, pdf_state_template, "(p_%p)\n", (void *) p)) + { + pdf__end_template(p); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + + +/********************** + * + * p_text.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_continue_text(PDF *p, const char *text) +{ + static const char fn[] = "PDF_continue_text"; + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, \"%T\")\n", + (void *) p, text, 0)) + { + int len = text ? (int) strlen(text) : 0; + pdf__show_text(p, text, len, pdc_true); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_continue_text2(PDF *p, const char *text, int len) +{ + static const char fn[] = "PDF_continue_text2"; + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, \"%T\", /*c*/%d)\n", (void *) p, text, len, len)) + { + pdf__show_text(p, text, len, pdc_true); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_fit_textline(PDF *p, const char *text, int len, double x, double y, + const char *optlist) +{ + static const char fn[] = "PDF_fit_textline"; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, \"%T\", /*c*/%d, %f, %f, \"%T\")\n", + (void *) p, text, len, len, x, y, optlist, 0)) + { + pdf__fit_textline(p, text, len, x, y, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API double PDFLIB_CALL +PDF_info_textline(PDF *p, const char *text, int len, const char *keyword, + const char *optlist) +{ + static const char fn[] = "PDF_info_textline"; + double retval = 0; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_content | + pdf_state_path | pdf_state_font), + "(p_%p, \"%T\", /*c*/%d, \"%s\", \"%T\")\n", + (void *) p, text, len, len, keyword, optlist, 0)) + { + retval = pdf__info_textline(p, text, len, keyword, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval); + } + + return retval; +} + +PDFLIB_API void PDFLIB_CALL +PDF_setfont(PDF *p, int font, double fontsize) +{ + static const char fn[] = "PDF_setfont"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %d, %f)\n", + (void *) p, font, fontsize)) + { + if (p->pdc->hastobepos) font -= 1; + pdf__setfont(p, font, fontsize); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_set_text_pos(PDF *p, double x, double y) +{ + static const char fn[] = "PDF_set_text_pos"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %f, %f)\n", + (void *) p, x, y)) + { + pdf__set_text_pos(p, x, y); + + pdc_logg_exit_api(p->pdc, pdc_false, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_show(PDF *p, const char *text) +{ + static const char fn[] = "PDF_show"; + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, \"%T\")\n", + (void *) p, text, 0)) + { + int len = text ? (int) strlen(text) : 0; + + pdf__show_text(p, text, len, pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_show2(PDF *p, const char *text, int len) +{ + static const char fn[] = "PDF_show2"; + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, \"%T\", /*c*/%d)\n", (void *) p, text, len, len)) + { + pdf__show_text(p, text, len, pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API int PDFLIB_CALL +PDF_show_boxed( + PDF *p, + const char *text, + double left, + double bottom, + double width, + double height, + const char *hmode, + const char *feature) +{ + static const char fn[] = "PDF_show_boxed"; + int retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, \"%T\", %f, %f, %f, %f, \"%s\", \"%s\")\n", + (void *) p, text, 0, left, bottom, width, height, hmode, feature)) + { + retval = pdf__show_boxed(p, text, 0, left, bottom, width, height, + hmode, feature); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval); + } + + return retval; +} + +PDFLIB_API int PDFLIB_CALL +PDF_show_boxed2( + PDF *p, + const char *text, + int len, + double left, + double bottom, + double width, + double height, + const char *hmode, + const char *feature) +{ + static const char fn[] = "PDF_show_boxed2"; + int retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, \"%T\", /*c*/%d, %f, %f, %f, %f, \"%s\", \"%s\")\n", + (void *) p, text, len, len, left, bottom, width, height, + hmode, feature)) + { + retval = pdf__show_boxed(p, text, len, left, bottom, width, height, + hmode, feature); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%d]\n", retval); + } + + return retval; +} + +PDFLIB_API void PDFLIB_CALL +PDF_show_xy(PDF *p, const char *text, double x, double y) +{ + static const char fn[] = "PDF_show_xy"; + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, \"%T\", %f, %f)\n", + (void *) p, text, 0, x, y)) + { + int len = text ? (int) strlen(text) : 0; + pdf__set_text_pos(p, x, y); + pdf__show_text(p, text, len, pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_show_xy2(PDF *p, const char *text, int len, double x, double y) +{ + static const char fn[] = "PDF_show_xy2"; + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, \"%T\", /*c*/%d, %f, %f)\n", + (void *) p, text, len, len, x, y)) + { + pdf__set_text_pos(p, x, y); + pdf__show_text(p, text, len, pdc_false); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API double PDFLIB_CALL +PDF_stringwidth(PDF *p, const char *text, int font, double fontsize) +{ + static const char fn[] = "PDF_stringwidth"; + double retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_content | + pdf_state_path | pdf_state_font), + "(p_%p, \"%T\", %d, %f)\n", + (void *) p, text, 0, font, fontsize)) + { + int len = text ? (int) strlen(text) : 0; + if (p->pdc->hastobepos) font -= 1; + retval = pdf__stringwidth(p, text, len, font, fontsize); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval); + } + + return retval; +} + +PDFLIB_API double PDFLIB_CALL +PDF_stringwidth2(PDF *p, const char *text, int len, int font, double fontsize) +{ + static const char fn[] = "PDF_stringwidth2"; + double retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_content | + pdf_state_path | pdf_state_font), + "(p_%p, \"%T\", /*c*/%d, %d, %f)\n", + (void *) p, text, len, len, font, fontsize)) + { + if (p->pdc->hastobepos) font -= 1; + retval = pdf__stringwidth(p, text, len, font, fontsize); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval); + } + + return retval; +} + +PDFLIB_API void PDFLIB_CALL +PDF_xshow(PDF *p, const char *text, int len, const double *xadvancelist) +{ + static const char fn[] = "PDF_xshow"; + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, \"%T\", %d, %p)\n", (void *) p, text, len, len, xadvancelist)) + { + pdf__xshow(p, text, len, xadvancelist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_textflow.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_add_textflow(PDF *p, int textflow, const char *text, int len, + const char *optlist) +{ + static const char fn[] = "PDF_add_textflow"; + int retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, textflow, text, len, len, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TEXTFLOWS, 0, 0, 0, 0); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API int PDFLIB_CALL +PDF_create_textflow(PDF *p, const char *text, int len, const char *optlist) +{ + static const char fn[] = "PDF_create_textflow"; + int retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, \"%T\", /*c*/%d, \"%T\")\n", + (void *) p, text, len, len, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TEXTFLOWS, 0, 0, 0, 0); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API void PDFLIB_CALL +PDF_delete_textflow(PDF *p, int textflow) +{ + static const char fn[] = "PDF_delete_textflow"; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d)\n", (void *) p, textflow)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TEXTFLOWS, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API const char * PDFLIB_CALL +PDF_fit_textflow( + PDF *p, + int textflow, + double llx, + double lly, + double urx, + double ury, + const char *optlist) +{ + static const char fn[] = "PDF_fit_textflow"; + const char *retval = ""; + + if (pdf_enter_api(p, fn, pdf_state_content, + "(p_%p, %d, %f, %f, %f, %f, \"%T\")\n", + (void *) p, textflow, llx, lly, urx, ury, optlist, 0)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TEXTFLOWS, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, "[\"%s\"]\n", retval); + } + + return retval; +} + +PDFLIB_API double PDFLIB_CALL +PDF_info_textflow(PDF *p, int textflow, const char *keyword) +{ + static const char fn[] = "PDF_info_textflow"; + double retval = -1; + + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, %d, \"%s\")\n", (void *) p, textflow, keyword)) + { + pdc_error(p->pdc, PDF_E_UNSUPP_TEXTFLOWS, 0, 0, 0, 0); + + pdc_logg_exit_api(p->pdc, pdc_true, "[%f]\n", retval); + } + + return retval; +} + + +/********************** + * + * p_type3.c + * + **********************/ + +PDFLIB_API void PDFLIB_CALL +PDF_begin_font( + PDF *p, + const char *fontname, int len, + double a, double b, double c, double d, double e, double f, + const char *optlist) +{ + static const char fn[] = "\nPDF_begin_font"; + + if (pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_page), + "(p_%p, \"%T\", /*c*/%d, %f, %f, %f, %f, %f, %f, \"%T\")\n", + (void *) p, fontname, len, len, a, b, c, d, e, f, optlist, 0)) + { + pdf__begin_font(p, fontname, len, a, b, c, d, e, f, optlist); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_begin_glyph( + PDF *p, + const char *glyphname, + double wx, double llx, double lly, double urx, double ury) +{ + static const char fn[] = "\nPDF_begin_glyph"; + + if (pdf_enter_api(p, fn, pdf_state_font, + "(p_%p, \"%s\", %f, %f, %f, %f, %f)\n", + (void *) p, glyphname, wx, llx, lly, urx, ury)) + { + pdf__begin_glyph(p, glyphname, wx, llx, lly, urx, ury); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + +PDFLIB_API void PDFLIB_CALL +PDF_end_font(PDF *p) +{ + static const char fn[] = "\nPDF_end_font"; + + if (pdf_enter_api(p, fn, pdf_state_font, "(p_%p)\n", (void *) p)) + { + pdf__end_font(p); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +PDFLIB_API void PDFLIB_CALL +PDF_end_glyph(PDF *p) +{ + static const char fn[] = "PDF_end_glyph"; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_glyph | pdf_state_glyphmetric | + pdf_state_glyphignore), + "(p_%p)\n", (void *) p)) + { + pdf__end_glyph(p); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} + + +/********************** + * + * p_util.c + * + **********************/ + +PDFLIB_API const char * PDFLIB_CALL +PDF_utf16_to_utf8(PDF *p, const char *utf16string, int len, int *size) +{ + static const char fn[] = "PDF_utf16_to_utf8"; + const char *retval = ""; + + if (pdf__check_context(p)) + { + if (p->pdc->unicaplang) + { + retval = pdf__utf16_to_utf8(p, utf16string, len, size); + } + else + { + pdc_logg_cond(p->pdc, 1, trc_api, "/* "); + if (pdf_enter_api(p, fn, pdf_state_all, + size ? "(p_%p, \"%T\", %d, &size_%p)" : + "(p_%p, \"%s\", %d, NULL) */\n", + (void *) p, utf16string, len, len, (void *) size)) + { + retval = pdf__utf16_to_utf8(p, utf16string, len, size); + } + + pdc_logg_exit_api(p->pdc, pdc_false, "/* [\"%T\", size=%d] */\n", + retval, 0, size ? *size : 0); + } + } + + return retval; +} + +PDFLIB_API const char * PDFLIB_CALL +PDF_utf32_to_utf16(PDF *p, const char *utf32string, int len, + const char *ordering, int *size) +{ + static const char fn[] = "PDF_utf32_to_utf16"; + const char *retval = ""; + + if (pdf__check_context(p)) + { + if (p->pdc->unicaplang) + { + retval = pdf__utf32_to_utf16(p, utf32string, len, ordering, size); + } + else + { + if (size == NULL) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "size", 0, 0, 0); + + pdc_logg_cond(p->pdc, 1, trc_api, "/* "); + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, \"%T\", %d, \"%s\", &size_%p) */\n", + (void *) p, utf32string, len, len, ordering, (void *) size)) + { + retval = pdf__utf32_to_utf16(p, utf32string, + len, ordering, size); + } + + pdc_logg_exit_api(p->pdc, pdc_false, "/* [\"%T\", size=%d] */\n", + retval, *size, *size); + } + } + + return retval; +} + +PDFLIB_API const char * PDFLIB_CALL +PDF_utf8_to_utf16(PDF *p, const char *utf8string, const char *format, + int *size) +{ + static const char fn[] = "PDF_utf8_to_utf16"; + const char *retval = ""; + + if (pdf__check_context(p)) + { + if (p->pdc->unicaplang) + { + retval = pdf__utf8_to_utf16(p, utf8string, format, size); + } + else + { + if (size == NULL) + pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "size", 0, 0, 0); + + pdc_logg_cond(p->pdc, 1, trc_api, "/* "); + if (pdf_enter_api(p, fn, pdf_state_all, + "(p_%p, \"%T\", \"%s\", &size_%p) */\n", + (void *) p, utf8string, 0, format, (void *) size)) + { + retval = pdf__utf8_to_utf16(p, utf8string, format, size); + } + + pdc_logg_exit_api(p->pdc, pdc_false, "/* [\"%T\", size=%d] */\n", + retval, *size, *size); + } + } + + return retval; +} + + +/********************** + * + * p_xgstate.c + * + **********************/ + +PDFLIB_API int PDFLIB_CALL +PDF_create_gstate(PDF *p, const char *optlist) +{ + static const char fn[] = "PDF_create_gstate"; + int retval = -1; + + if (pdf_enter_api(p, fn, + (pdf_state) (pdf_state_document | pdf_state_content), + "(p_%p, \"%T\")\n", (void *) p, optlist, 0)) + { + retval = pdf__create_gstate(p, optlist); + } + + return pdf_exit_handle_api(p, retval); +} + +PDFLIB_API void PDFLIB_CALL +PDF_set_gstate(PDF *p, int gstate) +{ + static const char fn[] = "PDF_set_gstate"; + + if (pdf_enter_api(p, fn, pdf_state_content, "(p_%p, %d)\n", + (void *) p, gstate)) + { + if (p->pdc->hastobepos) gstate -= 1; + pdf__set_gstate(p, gstate); + + pdc_logg_exit_api(p->pdc, pdc_true, NULL); + } +} diff --git a/src/pdflib/pdflib/pdflib.h b/src/pdflib/pdflib/pdflib.h new file mode 100644 index 0000000..23468dd --- /dev/null +++ b/src/pdflib/pdflib/pdflib.h @@ -0,0 +1,1572 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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: pdflib.h,v 1.1 2008/10/17 06:11:49 scuri Exp $ + * + * Public function declarations for PDFlib Lite, PDFlib, PDFlib+PDI, and PPS; + * see PDFlib API reference for details. + * + */ + +#ifndef PDFLIB_H +#define PDFLIB_H + +/* Make our declarations C++ compatible */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <setjmp.h> + +#define PDFLIB_PRODUCTNAME "PDFlib" + +/* + * The version defines below can be used to check the version of the + * include file against the library. + */ + +#define PDFLIB_MAJORVERSION 7 /* major version number */ +#define PDFLIB_MINORVERSION 0 /* minor version number */ +#define PDFLIB_REVISION 2 /* revision number */ +#define PDFLIB_VERSIONSTRING "7.0.2" /* The whole bunch */ + + +/* + * ---------------------------------------------------------------------- + * Setup, mostly Windows calling conventions and DLL stuff + * ---------------------------------------------------------------------- + */ + +#if defined(WIN32) && !defined(PDFLIB_CALL) + #define PDFLIB_CALL __cdecl +#endif + +#if defined(WIN32) + + #ifdef PDFLIB_EXPORTS + #define PDFLIB_API __declspec(dllexport) /* prepare a DLL (internal use) */ + + #elif defined(PDFLIB_DLL) + + #define PDFLIB_API __declspec(dllimport) /* PDFlib clients: import DLL */ + #endif /* PDFLIB_DLL */ + +#endif /* WIN32 */ + +#if !defined(WIN32) && \ + ((defined __IBMC__ || defined __IBMCPP__) && defined __DLL__ && defined OS2) + #define PDFLIB_CALL _Export + #define PDFLIB_API +#endif /* IBM VisualAge C++ DLL */ + +#ifndef PDFLIB_CALL + #define PDFLIB_CALL /* */ /* default: no special calling conventions */ +#endif + +#ifndef PDFLIB_API + #define PDFLIB_API /* */ /* default: generate or use static library */ +#endif + +/* Define the basic PDF type. This is used opaquely at the API level. */ +#if !defined(PDF) || defined(ACTIVEX) + typedef struct PDF_s PDF; +#endif /* !PDF */ + +/* Export the API functions when creating a shared library on the Mac with CW */ +#if defined(__MWERKS__) && defined(PDFLIB_EXPORTS) +#pragma export on +#endif + +/* The API structure with function pointers. */ +typedef struct PDFlib_api_s PDFlib_api; + + +/* + * ---------------------------------------------------------------------- + * Function prototypes for all supported API functions + * ---------------------------------------------------------------------- + */ + +/* Activate a previously created structure element or other content item. */ +PDFLIB_API void PDFLIB_CALL +PDF_activate_item(PDF *p, int id); + +/* Deprecated, use PDF_create_bookmark(). */ +PDFLIB_API int PDFLIB_CALL +PDF_add_bookmark(PDF *p, const char *text, int parent, int open); + +/* Deprecated, use PDF_create_bookmark(). */ +PDFLIB_API int PDFLIB_CALL +PDF_add_bookmark2(PDF *p, const char *text, int len, int parent, int open); + +/* Deprecated, use PDF_create_action() and PDF_create_annotation(). */ +PDFLIB_API void PDFLIB_CALL +PDF_add_launchlink(PDF *p, double llx, double lly, double urx, double ury, + const char *filename); + +/* Deprecated, use PDF_create_action() and PDF_create_annotation(). */ +PDFLIB_API void PDFLIB_CALL +PDF_add_locallink(PDF *p, double llx, double lly, double urx, double ury, + int page, const char *optlist); + +/* Create a named destination on an arbitrary page in the current document. */ +PDFLIB_API void PDFLIB_CALL +PDF_add_nameddest(PDF *p, const char *name, int len, const char *optlist); + +/* Deprecated, use PDF_create_annotation(). */ +PDFLIB_API void PDFLIB_CALL +PDF_add_note(PDF *p, double llx, double lly, double urx, double ury, + const char *contents, const char *title, const char *icon, int open); + +/* Deprecated, use PDF_create_annotation(). */ +PDFLIB_API void PDFLIB_CALL +PDF_add_note2(PDF *p, double llx, double lly, double urx, double ury, + const char *contents, int len_cont, const char *title, int len_title, + const char *icon, int open); + +/* Deprecated, use PDF_create_action() and PDF_create_annotation(). */ +PDFLIB_API void PDFLIB_CALL +PDF_add_pdflink(PDF *p, double llx, double lly, double urx, double ury, + const char *filename, int page, const char *optlist); + +/* Add a cell to a new or existing table. + Returns: A table handle which can be used in subsequent table-related calls. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_add_table_cell(PDF *p, int table, int column, int row, const char *text, + int len, const char *optlist); + +/* Create a Textflow object, or add text and explicit options to an existing + Textflow. + Returns: A Textflow handle, or -1 (in PHP: 0) on error. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_add_textflow(PDF *p, int textflow, const char *text, int len, + const char *optlist); + +/* Add an existing image as thumbnail for the current page. */ +PDFLIB_API void PDFLIB_CALL +PDF_add_thumbnail(PDF *p, int image); + +/* Deprecated, use PDF_create_action() and PDF_create_annotation(). */ +PDFLIB_API void PDFLIB_CALL +PDF_add_weblink(PDF *p, double llx, double lly, double urx, double ury, + const char *url); + +/* Draw a counterclockwise circular arc segment. */ +PDFLIB_API void PDFLIB_CALL +PDF_arc(PDF *p, double x, double y, double r, double alpha, double beta); + +/* Draw a clockwise circular arc segment. */ +PDFLIB_API void PDFLIB_CALL +PDF_arcn(PDF *p, double x, double y, double r, double alpha, double beta); + +/* Deprecated, use PDF_create_annotation(). */ +PDFLIB_API void PDFLIB_CALL +PDF_attach_file(PDF *p, double llx, double lly, double urx, double ury, + const char *filename, const char *description, const char *author, + const char *mimetype, const char *icon); + +/* Deprecated, use PDF_create_annotation(). */ +PDFLIB_API void PDFLIB_CALL +PDF_attach_file2(PDF *p, double llx, double lly, double urx, double 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); + +/* Create a new PDF file subject to various options. + Returns: -1 (in PHP: 0) on error, and 1 otherwise. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_begin_document(PDF *p, const char *filename, int len, const char *optlist); + +/* Create a new PDF document subject to various options. */ +typedef size_t (*writeproc_t)(PDF *p1, void *data, size_t size); +PDFLIB_API void PDFLIB_CALL +PDF_begin_document_callback(PDF *p, writeproc_t writeproc, const char *optlist); + +/* Start a Type 3 font definition. */ +PDFLIB_API void PDFLIB_CALL +PDF_begin_font(PDF *p, const char *fontname, int len, + double a, double b, double c, double d, double e, double f, + const char *optlist); + +/* Start a glyph definition for a Type 3 font. */ +PDFLIB_API void PDFLIB_CALL +PDF_begin_glyph(PDF *p, const char *glyphname, double wx, + double llx, double lly, double urx, double ury); + +/* Open a structure element or other content item with attributes supplied + as options. + Returns: An item handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_begin_item(PDF *p, const char *tag, const char *optlist); + +/* Start a layer for subsequent output on the page (requires PDF 1.5). */ +PDFLIB_API void PDFLIB_CALL +PDF_begin_layer(PDF *p, int layer); + +/* Begin a marked content sequence with or without properties (unsupported). */ +PDFLIB_API void PDFLIB_CALL +PDF_begin_mc(PDF *p, const char *tag, const char *optlist); + +/* Deprecated, use PDF_begin_page_ext(). */ +PDFLIB_API void PDFLIB_CALL +PDF_begin_page(PDF *p, double width, double height); + +/* Add a new page to the document, and specify various options. */ +PDFLIB_API void PDFLIB_CALL +PDF_begin_page_ext(PDF *p, double width, double height, const char *optlist); + +/* Start a pattern definition. + Returns: A pattern handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_begin_pattern(PDF *p, + double width, double height, double xstep, double ystep, int painttype); + +/* Deprecated, use PDF_begin_template_ext(). */ +PDFLIB_API int PDFLIB_CALL +PDF_begin_template(PDF *p, double width, double height); + +/* Start a template definition. + Returns: A template handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_begin_template_ext(PDF *p, double width, double height, + const char *optlist); + +/* Deprecated, and not required. */ +PDFLIB_API void PDFLIB_CALL +PDF_boot(void); + +/* Check the validity of a PDFlib context (unsupported). */ +PDFLIB_API int PDFLIB_CALL +PDF_check_context(PDF *p); + +/* Draw a circle. */ +PDFLIB_API void PDFLIB_CALL +PDF_circle(PDF *p, double x, double y, double r); + +/* Use the current path as clipping path, and terminate the path. */ +PDFLIB_API void PDFLIB_CALL +PDF_clip(PDF *p); + +/* Deprecated, use PDF_end_document(). */ +PDFLIB_API void PDFLIB_CALL +PDF_close(PDF *p); + +/* Close an image. */ +PDFLIB_API void PDFLIB_CALL +PDF_close_image(PDF *p, int image); + +/* Deprecated, use PDF_close_pdi_document(). */ +PDFLIB_API void PDFLIB_CALL +PDF_close_pdi(PDF *p, int doc); + +/* Close all open PDI page handles, and close the input PDF document. */ +PDFLIB_API void PDFLIB_CALL +PDF_close_pdi_document(PDF *p, int doc); + +/* Close the page handle and free all page-related resources. */ +PDFLIB_API void PDFLIB_CALL +PDF_close_pdi_page(PDF *p, int page); + +/* Close the current path. */ +PDFLIB_API void PDFLIB_CALL +PDF_closepath(PDF *p); + +/* Close the path, fill, and stroke it. */ +PDFLIB_API void PDFLIB_CALL +PDF_closepath_fill_stroke(PDF *p); + +/* Close the path, and stroke it. */ +PDFLIB_API void PDFLIB_CALL +PDF_closepath_stroke(PDF *p); + +/* Apply a transformation matrix to the current coordinate system. */ +PDFLIB_API void PDFLIB_CALL +PDF_concat(PDF *p, double a, double b, double c, double d, double e, double f); + +/* Print text at the next line. */ +PDFLIB_API void PDFLIB_CALL +PDF_continue_text(PDF *p, const char *text); + +/* Same as PDF_continue_text(), but with explicit string length. */ +PDFLIB_API void PDFLIB_CALL +PDF_continue_text2(PDF *p, const char *text, int len); + +/* Create a 3D view (requires PDF 1.6). + Returns: A 3D view handle, or -1 (in PHP: 0) on error. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_create_3dview(PDF *p, const char *username, int len, const char *optlist); + +/* Create an action which can be applied to various objects and events. + Returns: An action handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_create_action(PDF *p, const char *type, const char *optlist); + +/* Create a rectangular annotation on the current page. */ +PDFLIB_API void PDFLIB_CALL +PDF_create_annotation(PDF *p, double llx, double lly, double urx, double ury, + const char *type, const char *optlist); + +/* Create a bookmark subject to various options. + Returns: A handle for the generated bookmark. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_create_bookmark(PDF *p, const char *text, int len, const char *optlist); + +/* Create a form field on the current page subject to various options. */ +PDFLIB_API void PDFLIB_CALL +PDF_create_field(PDF *p, double llx, double lly, double urx, double ury, + const char *name, int len, const char *type, const char *optlist); + +/* Create a form field group subject to various options. */ +PDFLIB_API void PDFLIB_CALL +PDF_create_fieldgroup(PDF *p, const char *name, int len, const char *optlist); + +/* Create a graphics state object subject to various options. + Returns: A graphics state handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_create_gstate(PDF *p, const char *optlist); + +/* Create a named virtual read-only file from data provided in memory. */ +PDFLIB_API void PDFLIB_CALL +PDF_create_pvf(PDF *p, const char *filename, int len, + const void *data, size_t size, const char *optlist); + +/* Create a Textflow object from text contents, inline options, and explicit + options. + Returns: A Textflow handle, or -1 (in PHP: 0) on error. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_create_textflow(PDF *p, const char *text, int len, const char *optlist); + +/* Draw a Bezier curve from the current point, using 3 more control points. */ +PDFLIB_API void PDFLIB_CALL +PDF_curveto(PDF *p, + double x_1, double y_1, double x_2, double y_2, double x_3, double y_3); + +/* Create a new layer definition (requires PDF 1.5). + Returns: A layer handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_define_layer(PDF *p, const char *name, int len, const char *optlist); + +/* Delete a PDFlib object and free all internal resources. */ +PDFLIB_API void PDFLIB_CALL +PDF_delete(PDF *p); + +/* Delete a named virtual file and free its data structures (but not the + contents). + Returns: -1 (in PHP: 0) if the virtual file exists but is locked, and + 1 otherwise. + */ +PDFLIB_API int PDFLIB_CALL +PDF_delete_pvf(PDF *p, const char *filename, int len); + +/* Delete a table and all associated data structures. */ +PDFLIB_API void PDFLIB_CALL +PDF_delete_table(PDF *p, int table, const char *optlist); + +/* Delete a Textflow and all associated data structures. */ +PDFLIB_API void PDFLIB_CALL +PDF_delete_textflow(PDF *p, int textflow); + +/* Add a glyph name and/or Unicode value to a custom encoding. */ +PDFLIB_API void PDFLIB_CALL +PDF_encoding_set_char(PDF *p, const char *encoding, int slot, + const char *glyphname, int uv); + +/* Close the generated PDF document and apply various options. */ +PDFLIB_API void PDFLIB_CALL +PDF_end_document(PDF *p, const char *optlist); + +/* Terminate a Type 3 font definition. */ +PDFLIB_API void PDFLIB_CALL +PDF_end_font(PDF *p); + +/* Terminate a glyph definition for a Type 3 font. */ +PDFLIB_API void PDFLIB_CALL +PDF_end_glyph(PDF *p); + +/* Close a structure element or other content item. */ +PDFLIB_API void PDFLIB_CALL +PDF_end_item(PDF *p, int id); + +/* Deactivate all active layers (requires PDF 1.5). */ +PDFLIB_API void PDFLIB_CALL +PDF_end_layer(PDF *p); + +/* End the least recently opened marked content sequence (unsupported). */ +PDFLIB_API void PDFLIB_CALL +PDF_end_mc(PDF *p); + +/* Deprecated, use PDF_end_page_ext(). */ +PDFLIB_API void PDFLIB_CALL +PDF_end_page(PDF *p); + +/* Finish a page, and apply various options. */ +PDFLIB_API void PDFLIB_CALL +PDF_end_page_ext(PDF *p, const char *optlist); + +/* Finish a pattern definition. */ +PDFLIB_API void PDFLIB_CALL +PDF_end_pattern(PDF *p); + +/* Finish a template definition. */ +PDFLIB_API void PDFLIB_CALL +PDF_end_template(PDF *p); + +/* End the current path without filling or stroking it. */ +PDFLIB_API void PDFLIB_CALL +PDF_endpath(PDF *p); + +/* Fill the interior of the path with the current fill color. */ +PDFLIB_API void PDFLIB_CALL +PDF_fill(PDF *p); + +/* Fill an image block with variable data according to its properties. + Returns: -1 (in PHP: 0) on error, and 1 otherwise. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_fill_imageblock(PDF *p, int page, const char *blockname, + int image, const char *optlist); + +/* Fill a PDF block with variable data according to its properties. + Returns: -1 (in PHP: 0) on error, and 1 otherwise. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_fill_pdfblock(PDF *p, int page, const char *blockname, + int contents, const char *optlist); + +/* Fill and stroke the path with the current fill and stroke color. */ +PDFLIB_API void PDFLIB_CALL +PDF_fill_stroke(PDF *p); + +/* Fill a text block with variable data according to its properties. + Returns: -1 (in PHP: 0) on error, and 1 otherwise. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_fill_textblock(PDF *p, int page, const char *blockname, + const char *text, int len, const char *optlist); + +/* Deprecated, use PDF_load_font(). */ +PDFLIB_API int PDFLIB_CALL +PDF_findfont(PDF *p, const char *fontname, const char *encoding, int embed); + +/* Place an image or template on the page, subject to various options. */ +PDFLIB_API void PDFLIB_CALL +PDF_fit_image(PDF *p, int image, double x, double y, const char *optlist); + +/* Place an imported PDF page on the page subject to various options. */ +PDFLIB_API void PDFLIB_CALL +PDF_fit_pdi_page(PDF *p, int page, double x, double y, const char *optlist); + +/* Fully or partially place a table on the page. + Returns: A string which specifies the reason for returning. +*/ +PDFLIB_API const char * PDFLIB_CALL +PDF_fit_table(PDF *p, int table, double llx, double lly, + double urx, double ury, const char *optlist); + +/* Format the next portion of a Textflow into a rectangular area. + Returns: A string which specifies the reason for returning. +*/ +PDFLIB_API const char * PDFLIB_CALL +PDF_fit_textflow(PDF *p, int textflow, double llx, double lly, + double urx, double ury, const char *optlist); + +/* Place a single line of text at position (x, y) subject to various options. */ +PDFLIB_API void PDFLIB_CALL +PDF_fit_textline(PDF *p, const char *text, int len, double x, double y, + const char *optlist); + +/* + * Retrieve a structure with PDFlib API function pointers (mainly for DLLs). + * Although this function is published here, it is not supposed to be used + * directly by clients. Use PDF_new_dl() (in pdflibdl.c). + */ +PDFLIB_API const PDFlib_api * PDFLIB_CALL +PDF_get_api(void); + +/* Get the name of the API function which threw the last exception or failed. + Returns: Name of an API function. +*/ +PDFLIB_API const char * PDFLIB_CALL +PDF_get_apiname(PDF *p); + +/* Get the contents of the PDF output buffer. + Returns: A buffer full of binary PDF data for consumption by the client. +*/ +PDFLIB_API const char * PDFLIB_CALL +PDF_get_buffer(PDF *p, long *size); + +/* Get the text of the last thrown exception or the reason of a failed + function call. + Returns: Text containing the description of the most recent error condition. +*/ +PDFLIB_API const char * PDFLIB_CALL +PDF_get_errmsg(PDF *p); + +/* Get the number of the last thrown exception or the reason of a failed + function call. + Returns: The error code of the most recent error condition. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_get_errnum(PDF *p); + +/* Request the amount of kerning between two characters (unsupported). */ +PDFLIB_API double PDFLIB_CALL +PDF_get_kern_amount(PDF *p, int font, int firstchar, int secondchar); + +/* Deprecated, use PDF_get_value(). */ +PDFLIB_API int PDFLIB_CALL +PDF_get_majorversion(void); + +/* Deprecated, use PDF_get_value(). */ +PDFLIB_API int PDFLIB_CALL +PDF_get_minorversion(void); + +/* Fetch the opaque application pointer stored in PDFlib. + Returns: The opaque application pointer stored in PDFlib. +*/ +PDFLIB_API void * PDFLIB_CALL +PDF_get_opaque(PDF *p); + +/* Get the contents of some PDFlib parameter with string type. + Returns: The string value of the parameter as a hypertext string. +*/ +PDFLIB_API const char * PDFLIB_CALL +PDF_get_parameter(PDF *p, const char *key, double modifier); + +/* Deprecated, use PDF_pcos_get_string(). */ +PDFLIB_API const char *PDFLIB_CALL +PDF_get_pdi_parameter(PDF *p, const char *key, int doc, int page, + int reserved, int *len); + +/* Deprecated, use PDF_pcos_get_number. */ +PDFLIB_API double PDFLIB_CALL +PDF_get_pdi_value(PDF *p, const char *key, int doc, int page, int reserved); + +/* Get the value of some PDFlib parameter with numerical type. + Returns: The numerical value of the parameter. +*/ +PDFLIB_API double PDFLIB_CALL +PDF_get_value(PDF *p, const char *key, double modifier); + +/* Query detailed information about a loaded font. + Returns: The value of some font property as requested by keyword. +*/ +PDFLIB_API double PDFLIB_CALL +PDF_info_font(PDF *p, int font, const char *keyword, const char *optlist); + +/* Query information about a matchbox on the current page. + Returns: The value of some matchbox parameter as requested by keyword. +*/ +PDFLIB_API double PDFLIB_CALL +PDF_info_matchbox(PDF *p, const char *boxname, int len, int num, + const char *keyword); + +/* Retrieve table information related to the most recently placed table + instance. + Returns: The value of some table parameter as requested by keyword. +*/ +PDFLIB_API double PDFLIB_CALL +PDF_info_table(PDF *p, int table, const char *keyword); + +/* Query the current state of a Textflow. + Returns: The value of some Textflow parameter as requested by keyword. +*/ +PDFLIB_API double PDFLIB_CALL +PDF_info_textflow(PDF *p, int textflow, const char *keyword); + +/* Perform textline formatting and query the resulting metrics. + Returns: The value of some text metric value as requested by keyword. +*/ +PDFLIB_API double PDFLIB_CALL +PDF_info_textline(PDF *p, const char *text, int len, const char *keyword, + const char *optlist); + +/* Reset all color and graphics state parameters to their defaults. */ +PDFLIB_API void PDFLIB_CALL +PDF_initgraphics(PDF *p); + +/* Draw a line from the current point to another point. */ +PDFLIB_API void PDFLIB_CALL +PDF_lineto(PDF *p, double x, double y); + +/* Load a 3D model from a disk-based or virtual file (requires PDF 1.6). + Returns: A 3D handle, or -1 (in PHP: 0) on error. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_load_3ddata(PDF *p, const char *filename, int len, const char *optlist); + +/* Search for a font and prepare it for later use. + Returns: A font handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_load_font(PDF *p, const char *fontname, int len, + const char *encoding, const char *optlist); + +/* Search for an ICC profile and prepare it for later use. + Returns: A profile handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_load_iccprofile(PDF *p, const char *profilename, int len, + const char *optlist); + +/* Open a disk-based or virtual image file subject to various options. + Returns: An image handle, or -1 (in PHP: 0) on error. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_load_image(PDF *p, const char *imagetype, const char *filename, + int len, const char *optlist); + +/* Find a built-in spot color name, or make a named spot color from the + current fill color. + Returns: A color handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_makespotcolor(PDF *p, const char *spotname, int reserved); + +/* Add a marked content point with or without properties (unsupported). */ +PDFLIB_API void PDFLIB_CALL +PDF_mc_point(PDF *p, const char *tag, const char *optlist); + +/* Set the current point. */ +PDFLIB_API void PDFLIB_CALL +PDF_moveto(PDF *p, double x, double y); + +/* Create a new PDFlib object. + Returns: A handle to a PDFlib object. +*/ +PDFLIB_API PDF * PDFLIB_CALL +PDF_new(void); + +/* Create a new PDFlib object with client-supplied error handling and memory + allocation routines. + Returns: A handle to a PDFlib object. +*/ +typedef void (*errorproc_t)(PDF *p1, int errortype, const char *msg); +typedef void* (*allocproc_t)(PDF *p2, size_t size, const char *caller); +typedef void* (*reallocproc_t)(PDF *p3, + void *mem, size_t size, const char *caller); +typedef void (*freeproc_t)(PDF *p4, void *mem); + +PDFLIB_API PDF * PDFLIB_CALL +PDF_new2(errorproc_t errorhandler, allocproc_t allocproc, + reallocproc_t reallocproc, freeproc_t freeproc, void *opaque); + +/* Deprecated, use PDF_load_image(). */ +PDFLIB_API int PDFLIB_CALL +PDF_open_CCITT(PDF *p, const char *filename, int width, int height, + int BitReverse, int K, int BlackIs1); + +/* Deprecated, use PDF_begin_document(). */ +PDFLIB_API int PDFLIB_CALL +PDF_open_file(PDF *p, const char *filename); + +/* Deprecated, use PDF_load_image() with virtual files. */ +PDFLIB_API int PDFLIB_CALL +PDF_open_image(PDF *p, const char *imagetype, const char *source, + const char *data, long length, int width, int height, int components, + int bpc, const char *params); + +/* Deprecated, use PDF_load_image(). */ +PDFLIB_API int PDFLIB_CALL +PDF_open_image_file(PDF *p, const char *imagetype, const char *filename, + const char *stringparam, int intparam); + +/* Deprecated, use PDF_begin_document_callback(). */ +PDFLIB_API void PDFLIB_CALL +PDF_open_mem(PDF *p, writeproc_t writeproc); + +/* Deprecated, use PDF_open_pdi_document(). */ +PDFLIB_API int PDFLIB_CALL +PDF_open_pdi(PDF *p, const char *filename, const char *optlist, int len); + +/* Open a disk-based or virtual PDF document and prepare it for later use. + Returns: A PDI document handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_open_pdi_document(PDF *p, const char *filename, int len, + const char *optlist); + +/* Open a PDF document from a custom data source and prepare it for + later use. + Returns: A PDI document handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_open_pdi_callback(PDF *p, void *opaque, size_t filesize, + size_t (*readproc)(void *opaque, void *buffer, size_t size), + int (*seekproc)(void *opaque, long offset), + const char *optlist); + +/* Prepare a page for later use with PDF_fit_pdi_page(). + Returns: A page handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_open_pdi_page(PDF *p, int doc, int pagenumber, const char *optlist); + +/* Get the value of a pCOS path with type number or boolean. + Returns: The numerical value of the object identified by the pCOS path. +*/ +PDFLIB_API double PDFLIB_CALL +PDF_pcos_get_number(PDF *p, int doc, const char *path, ...); + +/* Get the value of a pCOS path with type name, string or boolean. + Returns: A string with the value of the object identified by the pCOS path. +*/ +PDFLIB_API const char * PDFLIB_CALL +PDF_pcos_get_string(PDF *p, int doc, const char *path, ...); + +/* Get the contents of a pCOS path with type stream, fstream, or string. + Returns: The unencrypted data contained in the stream or string. +*/ +PDFLIB_API const unsigned char * PDFLIB_CALL +PDF_pcos_get_stream(PDF *p, int doc, int *length, const char *optlist, + const char *path, ...); + +/* Deprecated, use PDF_fit_image(). */ +PDFLIB_API void PDFLIB_CALL +PDF_place_image(PDF *p, int image, double x, double y, double scale); + +/* Deprecated, use PDF_fit_pdi_page(). */ +PDFLIB_API void PDFLIB_CALL +PDF_place_pdi_page(PDF *p, int page, double x, double y, double sx, double sy); + +/* Process certain elements of an imported PDF document. + Returns: -1 (in PHP: 0) on error, and 1 otherwise. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_process_pdi(PDF *p, int doc, int page, const char *optlist); + +/* Draw a Bezier curve using relative coordinates (unsupported). */ +PDFLIB_API void PDFLIB_CALL +PDF_rcurveto(PDF *p, + double x_1, double y_1, double x_2, double y_2, double x_3, double y_3); + +/* Draw a rectangle. */ +PDFLIB_API void PDFLIB_CALL +PDF_rect(PDF *p, double x, double y, double width, double height); + +/* Restore the most recently saved graphics state from the stack. */ +PDFLIB_API void PDFLIB_CALL +PDF_restore(PDF *p); + +/* Resume a page to add more content to it. */ +PDFLIB_API void PDFLIB_CALL +PDF_resume_page(PDF *p, const char *optlist); + +/* Draw a line from the current point to (cp + (x, y)) (unsupported). */ +PDFLIB_API void PDFLIB_CALL +PDF_rlineto(PDF *p, double x, double y); + +/* Set the new current point relative the old current point (unsupported). */ +PDFLIB_API void PDFLIB_CALL +PDF_rmoveto(PDF *p, double x, double y); + +/* Rotate the coordinate system. */ +PDFLIB_API void PDFLIB_CALL +PDF_rotate(PDF *p, double phi); + +/* Save the current graphics state to a stack. */ +PDFLIB_API void PDFLIB_CALL +PDF_save(PDF *p); + +/* Scale the coordinate system. */ +PDFLIB_API void PDFLIB_CALL +PDF_scale(PDF *p, double sx, double sy); + +/* Deprecated, use PDF_create_annotation(). */ +PDFLIB_API void PDFLIB_CALL +PDF_set_border_color(PDF *p, double red, double green, double blue); + +/* Deprecated, use PDF_create_annotation(). */ +PDFLIB_API void PDFLIB_CALL +PDF_set_border_dash(PDF *p, double b, double w); + +/* Deprecated, use PDF_create_annotation(). */ +PDFLIB_API void PDFLIB_CALL +PDF_set_border_style(PDF *p, const char *style, double width); + +/* Activate a graphics state object. */ +PDFLIB_API void PDFLIB_CALL +PDF_set_gstate(PDF *p, int gstate); + +/* Fill document information field key with value. */ +PDFLIB_API void PDFLIB_CALL +PDF_set_info(PDF *p, const char *key, const char *value); + +/* Like PDF_set_info(), but with explicit string length. */ +PDFLIB_API void PDFLIB_CALL +PDF_set_info2(PDF *p, const char *key, const char *value, int len); + +/* Define hierarchical, group, and lock conditions among layers (requires + PDF 1.5). +*/ +PDFLIB_API void PDFLIB_CALL +PDF_set_layer_dependency(PDF *p, const char *type, const char *optlist); + +/* Set some PDFlib parameter with string type. */ +PDFLIB_API void PDFLIB_CALL +PDF_set_parameter(PDF *p, const char *key, const char *value); + +/* Set the position for text output on the page. */ +PDFLIB_API void PDFLIB_CALL +PDF_set_text_pos(PDF *p, double x, double y); + +/* Set the value of some PDFlib parameter with numerical type. */ +PDFLIB_API void PDFLIB_CALL +PDF_set_value(PDF *p, const char *key, double value); + +/* Set the current color space and color. */ +PDFLIB_API void PDFLIB_CALL +PDF_setcolor(PDF *p, const char *fstype, const char *colorspace, + double c1, double c2, double c3, double c4); + +/* Set the current dash pattern. */ +PDFLIB_API void PDFLIB_CALL +PDF_setdash(PDF *p, double b, double w); + +/* Set a dash pattern defined by an option list. */ +PDFLIB_API void PDFLIB_CALL +PDF_setdashpattern(PDF *p, const char *optlist); + +/* Set the flatness parameter. */ +PDFLIB_API void PDFLIB_CALL +PDF_setflat(PDF *p, double flatness); + +/* Set the current font in the specified size. */ +PDFLIB_API void PDFLIB_CALL +PDF_setfont(PDF *p, int font, double fontsize); + +/* Deprecated, use PDF_setcolor(). */ +PDFLIB_API void PDFLIB_CALL +PDF_setgray(PDF *p, double gray); + +/* Deprecated, use PDF_setcolor(). */ +PDFLIB_API void PDFLIB_CALL +PDF_setgray_fill(PDF *p, double gray); + +/* Deprecated, use PDF_setcolor(). */ +PDFLIB_API void PDFLIB_CALL +PDF_setgray_stroke(PDF *p, double gray); + +/* Set the linecap parameter. */ +PDFLIB_API void PDFLIB_CALL +PDF_setlinecap(PDF *p, int linecap); + +/* Set the linejoin parameter. */ +PDFLIB_API void PDFLIB_CALL +PDF_setlinejoin(PDF *p, int linejoin); + +/* Set the current linewidth. */ +PDFLIB_API void PDFLIB_CALL +PDF_setlinewidth(PDF *p, double width); + +/* Explicitly set the current transformation matrix. */ +PDFLIB_API void PDFLIB_CALL +PDF_setmatrix(PDF *p, double a, double b, double c, double d, + double e, double f); + +/* Set the miter limit. */ +PDFLIB_API void PDFLIB_CALL +PDF_setmiterlimit(PDF *p, double miter); + +/* Deprecated, use PDF_setdashpattern(). */ +PDFLIB_API void PDFLIB_CALL +PDF_setpolydash(PDF *p, float *dasharray, int length); + +/* Deprecated, use PDF_setcolor(). */ +PDFLIB_API void PDFLIB_CALL +PDF_setrgbcolor(PDF *p, double red, double green, double blue); + +/* Deprecated, use PDF_setcolor(). */ +PDFLIB_API void PDFLIB_CALL +PDF_setrgbcolor_fill(PDF *p, double red, double green, double blue); + +/* Deprecated, use PDF_setcolor(). */ +PDFLIB_API void PDFLIB_CALL +PDF_setrgbcolor_stroke(PDF *p, double red, double green, double blue); + +/* Define a blend from the current fill color to another color (requires + PDF 1.4). + Returns: A shading handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_shading(PDF *p, const char *shtype, double x_0, double y_0, double x_1, + double y_1, double c_1, double c_2, double c_3, double c_4, + const char *optlist); + +/* Define a shading pattern using a shading object (requires PDF 1.4). + Returns: A pattern handle. +*/ +PDFLIB_API int PDFLIB_CALL +PDF_shading_pattern(PDF *p, int shading, const char *optlist); + +/* Fill an area with a shading, based on a shading object (requires PDF 1.4) */ +PDFLIB_API void PDFLIB_CALL +PDF_shfill(PDF *p, int shading); + +/* Print text in the current font and size at the current position. */ +PDFLIB_API void PDFLIB_CALL +PDF_show(PDF *p, const char *text); + +/* Same as PDF_show() but with explicit string length. */ +PDFLIB_API void PDFLIB_CALL +PDF_show2(PDF *p, const char *text, int len); + +/* Deprecated, use PDF_fit_textline() or PDF_fit_textflow(). */ +PDFLIB_API int PDFLIB_CALL +PDF_show_boxed(PDF *p, const char *text, double left, double top, + double width, double height, const char *hmode, const char *feature); + +/* Deprecated, use PDF_fit_textline() or PDF_fit_textflow(). */ +PDFLIB_API int PDFLIB_CALL +PDF_show_boxed2(PDF *p, const char *text, int len, double left, double top, + double width, double height, const char *hmode, const char *feature); + +/* Print text in the current font. */ +PDFLIB_API void PDFLIB_CALL +PDF_show_xy(PDF *p, const char *text, double x, double y); + +/* Same as PDF_show_xy(), but with explicit string length. */ +PDFLIB_API void PDFLIB_CALL +PDF_show_xy2(PDF *p, const char *text, int len, double x, double y); + +/* Deprecated, and not required. */ +PDFLIB_API void PDFLIB_CALL +PDF_shutdown(void); + +/* Skew the coordinate system. */ +PDFLIB_API void PDFLIB_CALL +PDF_skew(PDF *p, double alpha, double beta); + +/* Calculate the width of text in an arbitrary font. + Returns: The width of text. +*/ +PDFLIB_API double PDFLIB_CALL +PDF_stringwidth(PDF *p, const char *text, int font, double fontsize); + +/* Same as PDF_stringwidth(), but with explicit string length. */ +PDFLIB_API double PDFLIB_CALL +PDF_stringwidth2(PDF *p, const char *text, int len, int font, double fontsize); + +/* Stroke the path with the current color and line width, and clear it. */ +PDFLIB_API void PDFLIB_CALL +PDF_stroke(PDF *p); + +/* Suspend the current page so that it can later be resumed. */ +PDFLIB_API void PDFLIB_CALL +PDF_suspend_page(PDF *p, const char *optlist); + +/* Translate the origin of the coordinate system. */ +PDFLIB_API void PDFLIB_CALL +PDF_translate(PDF *p, double tx, double ty); + +/* Convert a string from UTF-16 format to UTF-8. + Returns: The converted UTF-8 string, starting with the UTF-8 BOM. +*/ +PDFLIB_API const char * PDFLIB_CALL +PDF_utf16_to_utf8(PDF *p, const char *utf16string, int len, int *size); + +/* Convert a string from UTF-32 format to UTF-16. + Returns: The converted UTF-16 string. +*/ +PDFLIB_API const char * PDFLIB_CALL +PDF_utf32_to_utf16(PDF *p, const char *utf32string, int len, + const char *ordering, int *size); + +/* Convert a string from UTF-8 format to UTF-16. + Returns: The converted UTF-16 string. +*/ +PDFLIB_API const char * PDFLIB_CALL +PDF_utf8_to_utf16(PDF *p, const char *utf8string, const char *ordering, + int *size); + +/* Print text in the current font and size, using individual horizontal + positions (unsupported). +*/ +PDFLIB_API void PDFLIB_CALL +PDF_xshow(PDF *p, const char *text, int len, const double *xadvancelist); + + +/* + * ---------------------------------------------------------------------- + * PDFlib API structure with function pointers to all API functions + * ---------------------------------------------------------------------- + */ + +/* Auxiliary structure for try/catch */ +typedef struct +{ + jmp_buf jbuf; +} pdf_jmpbuf; + + +/* The API structure with pointers to all PDFlib API functions */ +struct PDFlib_api_s { + /* version numbers for checking the DLL against client code */ + size_t sizeof_PDFlib_api; /* size of this structure */ + + int major; /* PDFlib major version number */ + int minor; /* PDFlib minor version number */ + int revision; /* PDFlib revision number */ + + int reserved; /* reserved */ + + void (PDFLIB_CALL * PDF_activate_item)(PDF *p, int id); + int (PDFLIB_CALL * PDF_add_bookmark)(PDF *p, const char *text, + int parent, int open); + int (PDFLIB_CALL * PDF_add_bookmark2)(PDF *p, const char *text, int len, + int parent, int open); + void (PDFLIB_CALL * PDF_add_launchlink)(PDF *p, + double llx, double lly, double urx, + double ury, const char *filename); + void (PDFLIB_CALL * PDF_add_locallink)(PDF *p, + double llx, double lly, double urx, + double ury, int page, const char *optlist); + void (PDFLIB_CALL * PDF_add_nameddest)(PDF *p, const char *name, + int len, const char *optlist); + void (PDFLIB_CALL * PDF_add_note)(PDF *p, double llx, double lly, + double urx, double ury, const char *contents, const char *title, + const char *icon, int open); + void (PDFLIB_CALL * PDF_add_note2)(PDF *p, double llx, double lly, + double urx, double ury, const char *contents, int len_cont, + const char *title, int len_title, const char *icon, int open); + void (PDFLIB_CALL * PDF_add_pdflink)(PDF *p, + double llx, double lly, double urx, double ury, + const char *filename, int page, const char *optlist); + int (PDFLIB_CALL * PDF_add_table_cell)(PDF *p, int table, int column, + int row, const char *text, int len, const char *optlist); + int (PDFLIB_CALL * PDF_add_textflow)(PDF *p, int textflow, const char *text, + int len, const char *optlist); + void (PDFLIB_CALL * PDF_add_thumbnail)(PDF *p, int image); + void (PDFLIB_CALL * PDF_add_weblink)(PDF *p, double llx, + double lly, double urx, double ury, const char *url); + void (PDFLIB_CALL * PDF_arc)(PDF *p, double x, double y, + double r, double alpha, double beta); + void (PDFLIB_CALL * PDF_arcn)(PDF *p, double x, double y, + double r, double alpha, double beta); + void (PDFLIB_CALL * PDF_attach_file)(PDF *p, double llx, double lly, + double urx, double ury, const char *filename, + const char *description, + const char *author, const char *mimetype, const char *icon); + void (PDFLIB_CALL * PDF_attach_file2)(PDF *p, double llx, double lly, + double urx, double 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); + int (PDFLIB_CALL * PDF_begin_document)(PDF *p, const char *filename, + int len, const char *optlist); + void (PDFLIB_CALL * PDF_begin_document_callback)(PDF *p, + writeproc_t writeproc, const char *optlist); + void (PDFLIB_CALL * PDF_begin_font)(PDF *p, const char *fontname, + int len, double a, double b, double c, double d, double e, + double f, const char *optlist); + void (PDFLIB_CALL * PDF_begin_glyph)(PDF *p, const char *glyphname, + double wx, double llx, double lly, double urx, double ury); + int (PDFLIB_CALL * PDF_begin_item)(PDF *p, const char *tag, + const char *optlist); + void (PDFLIB_CALL * PDF_begin_layer)(PDF *p, int layer); + void (PDFLIB_CALL * PDF_begin_mc)(PDF *p, + const char *tag, const char *optlist); + void (PDFLIB_CALL * PDF_begin_page)(PDF *p, double width, double height); + void (PDFLIB_CALL * PDF_begin_page_ext)(PDF *p, double width, + double height, const char *optlist); + int (PDFLIB_CALL * PDF_begin_pattern)(PDF *p, double width, double height, + double xstep, double ystep, int painttype); + int (PDFLIB_CALL * PDF_begin_template)(PDF *p, + double width, double height); + int (PDFLIB_CALL * PDF_begin_template_ext)(PDF *p, + double width, double height, const char *optlist); + void (PDFLIB_CALL * PDF_boot)(void); + int (PDFLIB_CALL * PDF_check_context)(PDF *p); + void (PDFLIB_CALL * PDF_circle)(PDF *p, double x, double y, double r); + void (PDFLIB_CALL * PDF_clip)(PDF *p); + void (PDFLIB_CALL * PDF_close)(PDF *p); + void (PDFLIB_CALL * PDF_close_image)(PDF *p, int image); + void (PDFLIB_CALL * PDF_close_pdi)(PDF *p, int doc); + void (PDFLIB_CALL * PDF_close_pdi_document)(PDF *p, int doc); + void (PDFLIB_CALL * PDF_close_pdi_page)(PDF *p, int page); + void (PDFLIB_CALL * PDF_closepath)(PDF *p); + void (PDFLIB_CALL * PDF_closepath_fill_stroke)(PDF *p); + void (PDFLIB_CALL * PDF_closepath_stroke)(PDF *p); + void (PDFLIB_CALL * PDF_concat)(PDF *p, double a, double b, + double c, double d, double e, double f); + void (PDFLIB_CALL * PDF_continue_text)(PDF *p, const char *text); + void (PDFLIB_CALL * PDF_continue_text2)(PDF *p, const char *text, int len); + int (PDFLIB_CALL * PDF_create_3dview)(PDF *p, const char *username, + int len, const char *optlist); + int (PDFLIB_CALL * PDF_create_action)(PDF *p, const char *type, + const char *optlist); + void (PDFLIB_CALL * PDF_create_annotation)(PDF *p, + double llx, double lly, double urx, double ury, + const char *type, const char *optlist); + int (PDFLIB_CALL * PDF_create_bookmark)(PDF *p, const char *text, int len, + const char *optlist); + void (PDFLIB_CALL * PDF_create_field)(PDF *p, double llx, double lly, + double urx, double ury, const char *name, int len, + const char *type, const char *optlist); + void (PDFLIB_CALL * PDF_create_fieldgroup)(PDF *p, const char *name, + int len, const char *optlist); + int (PDFLIB_CALL * PDF_create_gstate)(PDF *p, const char *optlist); + void (PDFLIB_CALL * PDF_create_pvf)(PDF *p, const char *filename, + int len, const void *data, size_t size, const char *optlist); + int (PDFLIB_CALL * PDF_create_textflow)(PDF *p, const char *text, int len, + const char *optlist); + void (PDFLIB_CALL * PDF_curveto)(PDF *p, double x_1, double y_1, + double x_2, double y_2, double x_3, double y_3); + int (PDFLIB_CALL * PDF_define_layer)(PDF *p, const char *name, int len, + const char *optlist); + void (PDFLIB_CALL * PDF_delete)(PDF *); + int (PDFLIB_CALL * PDF_delete_pvf)(PDF *p, const char *filename, int len); + void (PDFLIB_CALL * PDF_delete_table)(PDF *p, int table, + const char *optlist); + void (PDFLIB_CALL * PDF_delete_textflow)(PDF *p, int textflow); + void (PDFLIB_CALL * PDF_encoding_set_char)(PDF *p, const char *encoding, + int slot, const char *glyphname, int uv); + void (PDFLIB_CALL * PDF_end_document)(PDF *p, const char *optlist); + void (PDFLIB_CALL * PDF_end_font)(PDF *p); + void (PDFLIB_CALL * PDF_end_glyph)(PDF *p); + void (PDFLIB_CALL * PDF_end_item)(PDF *p, int id); + void (PDFLIB_CALL * PDF_end_layer)(PDF *p); + void (PDFLIB_CALL * PDF_end_mc)(PDF *p); + void (PDFLIB_CALL * PDF_end_page)(PDF *p); + void (PDFLIB_CALL * PDF_end_page_ext)(PDF *p, const char *optlist); + void (PDFLIB_CALL * PDF_end_pattern)(PDF *p); + void (PDFLIB_CALL * PDF_end_template)(PDF *p); + void (PDFLIB_CALL * PDF_endpath)(PDF *p); + void (PDFLIB_CALL * PDF_fill)(PDF *p); + int (PDFLIB_CALL * PDF_fill_imageblock)(PDF *p, int page, + const char *blockname, int image, const char *optlist); + int (PDFLIB_CALL * PDF_fill_pdfblock)(PDF *p, int page, + const char *blockname, int contents, const char *optlist); + void (PDFLIB_CALL * PDF_fill_stroke)(PDF *p); + int (PDFLIB_CALL * PDF_fill_textblock)(PDF *p, int page, + const char *blockname, const char *text, int len, + const char *optlist); + int (PDFLIB_CALL * PDF_findfont)(PDF *p, const char *fontname, + const char *encoding, int embed); + void (PDFLIB_CALL * PDF_fit_image)(PDF *p, int image, double x, double y, + const char *optlist); + void (PDFLIB_CALL * PDF_fit_pdi_page)(PDF *p, int page, double x, + double y, const char *optlist); + const char * (PDFLIB_CALL * PDF_fit_table)(PDF *p, int table, + double llx, double lly, double urx, double ury, + const char *optlist); + const char * (PDFLIB_CALL * PDF_fit_textflow)(PDF *p, int textflow, + double llx, double lly, double urx, double ury, + const char *optlist); + void (PDFLIB_CALL * PDF_fit_textline)(PDF *p, const char *text, + int len, double x, double y, const char *optlist); + const PDFlib_api * (PDFLIB_CALL * PDF_get_api)(void); + const char * (PDFLIB_CALL * PDF_get_apiname)(PDF *p); + const char * (PDFLIB_CALL * PDF_get_buffer)(PDF *p, long *size); + const char * (PDFLIB_CALL * PDF_get_errmsg)(PDF *p); + int (PDFLIB_CALL * PDF_get_errnum)(PDF *p); + int (PDFLIB_CALL * PDF_get_minorversion)(void); + int (PDFLIB_CALL * PDF_get_majorversion)(void); + void * (PDFLIB_CALL * PDF_get_opaque)(PDF *p); + const char * (PDFLIB_CALL * PDF_get_parameter)(PDF *p, + const char *key, double modifier); + const char * (PDFLIB_CALL * PDF_get_pdi_parameter)(PDF *p, + const char *key, int doc, int page, int reserved, int *len); + double (PDFLIB_CALL * PDF_get_pdi_value)(PDF *p, const char *key, + int doc, int page, int reserved); + double (PDFLIB_CALL * PDF_get_value)(PDF *p, const char *key, + double modifier); + double (PDFLIB_CALL * PDF_info_font)(PDF *p, int font, const char *keyword, + const char *optlist); + double (PDFLIB_CALL * PDF_info_matchbox)(PDF *p, const char *boxname, + int len, int num, const char *keyword); + double (PDFLIB_CALL * PDF_info_table)(PDF *p, int table, + const char *keyword); + double (PDFLIB_CALL * PDF_info_textflow)(PDF *p, int textflow, + const char *keyword); + double (PDFLIB_CALL * PDF_info_textline)(PDF *p, const char *text, int len, + const char *keyword, const char *optlist); + void (PDFLIB_CALL * PDF_initgraphics)(PDF *p); + void (PDFLIB_CALL * PDF_lineto)(PDF *p, double x, double y); + int (PDFLIB_CALL * PDF_load_3ddata)(PDF *p, const char *filename, int len, + const char *optlist); + int (PDFLIB_CALL * PDF_load_font)(PDF *p, const char *fontname, + int len, const char *encoding, const char *optlist); + int (PDFLIB_CALL * PDF_load_iccprofile)(PDF *p, const char *profilename, + int len, const char *optlist); + int (PDFLIB_CALL * PDF_load_image)(PDF *p, const char *imagetype, + const char *filename, int len, const char *optlist); + int (PDFLIB_CALL * PDF_makespotcolor)(PDF *p, const char *spotname, + int len); + void (PDFLIB_CALL * PDF_mc_point)(PDF *p, + const char *tag, const char *optlist); + void (PDFLIB_CALL * PDF_moveto)(PDF *p, double x, double y); + PDF* (PDFLIB_CALL * PDF_new)(void); + PDF* (PDFLIB_CALL * PDF_new2)(errorproc_t errorhandler, + allocproc_t allocproc, reallocproc_t reallocproc, + freeproc_t freeproc, void *opaque); + int (PDFLIB_CALL * PDF_open_CCITT)(PDF *p, const char *filename, + int width, int height, int BitReverse, int K, int BlackIs1); + int (PDFLIB_CALL * PDF_open_file)(PDF *p, const char *filename); + int (PDFLIB_CALL * PDF_open_image)(PDF *p, const char *imagetype, + const char *source, const char *data, long length, int width, + int height, int components, int bpc, const char *params); + int (PDFLIB_CALL * PDF_open_image_file)(PDF *p, const char *imagetype, + const char *filename, const char *stringparam, int intparam); + void (PDFLIB_CALL * PDF_open_mem)(PDF *p, writeproc_t writeproc); + int (PDFLIB_CALL * PDF_open_pdi)(PDF *p, const char *filename, + const char *optlist, int len); + int (PDFLIB_CALL * PDF_open_pdi_callback)(PDF *p, void *opaque, + size_t filesize, size_t (*readproc)(void *opaque, void *buffer, + size_t size), int (*seekproc)(void *opaque, long offset), + const char *optlist); + int (PDFLIB_CALL * PDF_open_pdi_document)(PDF *p, const char *filename, + int len, const char *optlist); + int (PDFLIB_CALL * PDF_open_pdi_page)(PDF *p, + int doc, int pagenumber, const char *optlist); + double (PDFLIB_CALL * PDF_pcos_get_number)(PDF *p, + int doc, const char *path, ...); + const char * (PDFLIB_CALL * PDF_pcos_get_string)(PDF *p, + int doc, const char *path, ...); + const unsigned char * (PDFLIB_CALL * PDF_pcos_get_stream)(PDF *p, + int doc, int *length, const char *optlist, + const char *path, ...); + void (PDFLIB_CALL * PDF_place_image)(PDF *p, int image, + double x, double y, double scale); + void (PDFLIB_CALL * PDF_place_pdi_page)(PDF *p, int page, + double x, double y, double sx, double sy); + int (PDFLIB_CALL * PDF_process_pdi)(PDF *p, int doc, int page, + const char *optlist); + void (PDFLIB_CALL * PDF_rect)(PDF *p, double x, double y, + double width, double height); + void (PDFLIB_CALL * PDF_restore)(PDF *p); + void (PDFLIB_CALL * PDF_resume_page)(PDF *p, const char *optlist); + void (PDFLIB_CALL * PDF_rotate)(PDF *p, double phi); + void (PDFLIB_CALL * PDF_save)(PDF *p); + void (PDFLIB_CALL * PDF_scale)(PDF *p, double sx, double sy); + void (PDFLIB_CALL * PDF_set_border_color)(PDF *p, + double red, double green, double blue); + void (PDFLIB_CALL * PDF_set_border_dash)(PDF *p, double b, double w); + void (PDFLIB_CALL * PDF_set_border_style)(PDF *p, + const char *style, double width); + void (PDFLIB_CALL * PDF_set_gstate)(PDF *p, int gstate); + void (PDFLIB_CALL * PDF_set_info)(PDF *p, const char *key, + const char *value); + void (PDFLIB_CALL * PDF_set_info2)(PDF *p, const char *key, + const char *value, int len); + void (PDFLIB_CALL * PDF_set_layer_dependency)(PDF *p, const char *type, + const char *optlist); + void (PDFLIB_CALL * PDF_set_parameter)(PDF *p, const char *key, + const char *value); + void (PDFLIB_CALL * PDF_set_text_pos)(PDF *p, double x, double y); + void (PDFLIB_CALL * PDF_set_value)(PDF *p, const char *key, double value); + void (PDFLIB_CALL * PDF_setcolor)(PDF *p, const char *fstype, + const char *colorspace, double c1, double c2, + double c3, double c4); + void (PDFLIB_CALL * PDF_setdash)(PDF *p, double b, double w); + void (PDFLIB_CALL * PDF_setdashpattern)(PDF *p, const char *optlist); + void (PDFLIB_CALL * PDF_setflat)(PDF *p, double flatness); + void (PDFLIB_CALL * PDF_setfont)(PDF *p, int font, double fontsize); + void (PDFLIB_CALL * PDF_setgray)(PDF *p, double gray); + void (PDFLIB_CALL * PDF_setgray_fill)(PDF *p, double gray); + void (PDFLIB_CALL * PDF_setgray_stroke)(PDF *p, double gray); + void (PDFLIB_CALL * PDF_setlinecap)(PDF *p, int linecap); + void (PDFLIB_CALL * PDF_setlinejoin)(PDF *p, int linejoin); + void (PDFLIB_CALL * PDF_setlinewidth)(PDF *p, double width); + void (PDFLIB_CALL * PDF_setmatrix)(PDF *p, double a, double b, + double c, double d, double e, double f); + void (PDFLIB_CALL * PDF_setmiterlimit)(PDF *p, double miter); + void (PDFLIB_CALL * PDF_setpolydash)(PDF *p, float *dasharray, int length); + void (PDFLIB_CALL * PDF_setrgbcolor)(PDF *p, double red, double green, + double blue); + void (PDFLIB_CALL * PDF_setrgbcolor_fill)(PDF *p, + double red, double green, double blue); + void (PDFLIB_CALL * PDF_setrgbcolor_stroke)(PDF *p, + double red, double green, double blue); + int (PDFLIB_CALL * PDF_shading)(PDF *p, const char *shtype, double x_0, + double y_0, double x_1, double y_1, double c_1, double c_2, + double c_3, double c_4, const char *optlist); + int (PDFLIB_CALL * PDF_shading_pattern)(PDF *p, int shading, + const char *optlist); + void (PDFLIB_CALL * PDF_shfill)(PDF *p, int shading); + void (PDFLIB_CALL * PDF_show)(PDF *p, const char *text); + void (PDFLIB_CALL * PDF_show2)(PDF *p, const char *text, int len); + int (PDFLIB_CALL * PDF_show_boxed)(PDF *p, const char *text, + double left, double top, double width, double height, + const char *hmode, const char *feature); + int (PDFLIB_CALL * PDF_show_boxed2)(PDF *p, const char *text, int len, + double left, double top, double width, double height, + const char *hmode, const char *feature); + void (PDFLIB_CALL * PDF_show_xy)(PDF *p, const char *text, double x, + double y); + void (PDFLIB_CALL * PDF_show_xy2)(PDF *p, const char *text, + int len, double x, double y); + void (PDFLIB_CALL * PDF_shutdown)(void); + void (PDFLIB_CALL * PDF_skew)(PDF *p, double alpha, double beta); + double (PDFLIB_CALL * PDF_stringwidth)(PDF *p, const char *text, + int font, double fontsize); + double (PDFLIB_CALL * PDF_stringwidth2)(PDF *p, const char *text, + int len, int font, double fontsize); + void (PDFLIB_CALL * PDF_stroke)(PDF *p); + void (PDFLIB_CALL * PDF_suspend_page)(PDF *p, const char *optlist); + void (PDFLIB_CALL * PDF_translate)(PDF *p, double tx, double ty); + const char * (PDFLIB_CALL * PDF_utf16_to_utf8)(PDF *p, + const char *utf16string, int len, int *size); + const char * (PDFLIB_CALL * PDF_utf32_to_utf16)(PDF *p, + const char *utf32string, int len, const char *ordering, + int *size); + const char * (PDFLIB_CALL * PDF_utf8_to_utf16)(PDF *p, + const char *utf8string, const char *format, int *size); + void (PDFLIB_CALL * PDF_xshow)(PDF *p, const char *text, int len, + const double *xadvancelist); + + int (PDFLIB_CALL * pdf_catch)(PDF *p); + void (PDFLIB_CALL * pdf_exit_try)(PDF *p); + pdf_jmpbuf * (PDFLIB_CALL * pdf_jbuf)(PDF *p); + void (PDFLIB_CALL * pdf_rethrow)(PDF *p); +}; + + +/* + * ---------------------------------------------------------------------- + * pCOS-specific enums and defines + * ---------------------------------------------------------------------- + */ + +/* + * PDFlib GmbH products implement the following pCOS interface numbers: + * + * pCOS interface Products + * 1 TET 2.0, 2.1 + * 2 pCOS 1.x + * 3 PDFlib 7.0.x + */ + +#ifndef PCOS_INTERFACE +#define PCOS_INTERFACE 3 + +/* document access levels. +*/ +typedef enum +{ + pcos_mode_minimum = 0, /* encrypted doc (opened w/o password) */ + pcos_mode_restricted = 1, /* encrypted doc (opened w/ user password) */ + pcos_mode_full = 2 /* unencrypted doc or opened w/ master password */ +} pcos_mode; + + +/* object types. +*/ +typedef enum +{ + pcos_ot_null = 0, + pcos_ot_boolean = 1, + pcos_ot_number = 2, + pcos_ot_name = 3, + pcos_ot_string = 4, + pcos_ot_array = 5, + pcos_ot_dict = 6, + pcos_ot_stream = 7, + pcos_ot_fstream = 8 +} pcos_object_type; + +#endif /* PCOS_INTERFACE */ + + +/* + * ---------------------------------------------------------------------- + * Exception handling with try/catch implementation + * ---------------------------------------------------------------------- + */ + +/* Set up an exception handling frame; must always be paired with PDF_CATCH().*/ + +#define PDF_TRY(p) if (p) { if (setjmp(pdf_jbuf(p)->jbuf) == 0) + +/* Inform the exception machinery that a PDF_TRY() will be left without + entering the corresponding PDF_CATCH( ) clause. */ +#define PDF_EXIT_TRY(p) pdf_exit_try(p) + +/* Catch an exception; must always be paired with PDF_TRY(). */ +#define PDF_CATCH(p) } if (pdf_catch(p)) + +/* Re-throw an exception to another handler. */ +#define PDF_RETHROW(p) pdf_rethrow(p) + + +/* + * ---------------------------------------------------------------------- + * End of supported public declarations + * ---------------------------------------------------------------------- + */ + +/* + * ------------------------------------------------------------------------ + * Deprecated: macros for page size formats + * ------------------------------------------------------------------------ + */ + +/* + * The page sizes are only available to the C and C++ bindings. + * These are deprecated; corresponding options are supported in + * PDF_begin_page_ext(). + */ + +#define a0_width 2380.0 +#define a0_height 3368.0 +#define a1_width 1684.0 +#define a1_height 2380.0 +#define a2_width 1190.0 +#define a2_height 1684.0 +#define a3_width 842.0 +#define a3_height 1190.0 +#define a4_width 595.0 +#define a4_height 842.0 +#define a5_width 421.0 +#define a5_height 595.0 +#define a6_width 297.0 +#define a6_height 421.0 +#define b5_width 501.0 +#define b5_height 709.0 +#define letter_width 612.0 +#define letter_height 792.0 +#define legal_width 612.0 +#define legal_height 1008.0 +#define ledger_width 1224.0 +#define ledger_height 792.0 +#define p11x17_width 792.0 +#define p11x17_height 1224.0 + + +/* + * ---------------------------------------------------------------------- + * Deprecated: Error classes + * ---------------------------------------------------------------------- + */ + +/* + * Error classes are deprecated; use PDF_TRY/PDF_CATCH instead. + * Note that old-style error handlers are still supported, but + * they will always receive PDF_UnknownError. + */ + +#define PDF_MemoryError 1 +#define PDF_IOError 2 +#define PDF_RuntimeError 3 +#define PDF_IndexError 4 +#define PDF_TypeError 5 +#define PDF_DivisionByZero 6 +#define PDF_OverflowError 7 +#define PDF_SyntaxError 8 +#define PDF_ValueError 9 +#define PDF_SystemError 10 +#define PDF_NonfatalError 11 +#define PDF_UnknownError 12 + + +/* + * ---------------------------------------------------------------------- + * Deprecated functions (should no longer be used) + * ---------------------------------------------------------------------- + */ + +#if _MSC_VER >= 1310 /* VS .NET 2003 and later */ +#pragma deprecated(PDF_add_bookmark) +#pragma deprecated(PDF_add_bookmark2) +#pragma deprecated(PDF_add_launchlink) +#pragma deprecated(PDF_add_locallink) +#pragma deprecated(PDF_add_note) +#pragma deprecated(PDF_add_note2) +#pragma deprecated(PDF_add_pdflink) +#pragma deprecated(PDF_add_weblink) +#pragma deprecated(PDF_attach_file) +#pragma deprecated(PDF_attach_file2) +#pragma deprecated(PDF_begin_page) +#pragma deprecated(PDF_begin_template) +#pragma deprecated(PDF_boot) +#pragma deprecated(PDF_close) +#pragma deprecated(PDF_end_page) +#pragma deprecated(PDF_findfont) +#pragma deprecated(PDF_get_majorversion) +#pragma deprecated(PDF_get_minorversion) +#pragma deprecated(PDF_get_pdi_value) +#pragma deprecated(PDF_get_pdi_parameter) +#pragma deprecated(PDF_open_CCITT) +#pragma deprecated(PDF_open_file) +#pragma deprecated(PDF_open_image) +#pragma deprecated(PDF_open_image_file) +#pragma deprecated(PDF_open_mem) +#pragma deprecated(PDF_place_image) +#pragma deprecated(PDF_place_pdi_page) +#pragma deprecated(PDF_set_border_color) +#pragma deprecated(PDF_set_border_dash) +#pragma deprecated(PDF_set_border_style) +#pragma deprecated(PDF_setgray) +#pragma deprecated(PDF_setgray_fill) +#pragma deprecated(PDF_setgray_stroke) +#pragma deprecated(PDF_setpolydash) +#pragma deprecated(PDF_setrgbcolor) +#pragma deprecated(PDF_setrgbcolor_fill) +#pragma deprecated(PDF_setrgbcolor_stroke) +#pragma deprecated(PDF_show_boxed) +#pragma deprecated(PDF_show_boxed2) +#pragma deprecated(PDF_shutdown) +#endif + +/* + * ---------------------------------------------------------------------- + * Private stuff, do not use explicitly but only via the macros above! + * ---------------------------------------------------------------------- + */ + +PDFLIB_API pdf_jmpbuf * PDFLIB_CALL +pdf_jbuf(PDF *p); + +PDFLIB_API void PDFLIB_CALL +pdf_exit_try(PDF *p); + +PDFLIB_API int PDFLIB_CALL +pdf_catch(PDF *p); + +PDFLIB_API void PDFLIB_CALL +pdf_rethrow(PDF *p); + +PDFLIB_API void PDFLIB_CALL +pdf_throw(PDF *p, const char *binding, const char *apiname, const char *errmsg); + + +/* + * ---------------------------------------------------------------------- + * End of useful stuff + * ---------------------------------------------------------------------- + */ + +#if defined(__MWERKS__) && defined(PDFLIB_EXPORTS) +#pragma export off +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* PDFLIB_H */ + +/* + * vim600: sw=4 fdm=marker + */ |