int pdf__add_bookmark(PDF *p, const char *text, int len, int parent, int open) { static const char *fn = "pdf__add_bookmark"; pdf_outline self; pdf_dest *dest = (pdf_dest *) p->bookmark_dest; char *hypertext = NULL; int acthdl; int retval = 0; len = pdc_check_text_length(p->pdc, &text, len, PDF_MAXSTRINGSIZE); if (!len) pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "text", 0, 0, 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; actoptlist = (char *) pdc_malloc(p->pdc, strlen(dest->filename) + 80, fn); pdc_sprintf(p->pdc, pdc_false, actoptlist, "filename {%s} ", dest->filename); acthdl = pdf__create_action(p, "Launch", actoptlist); if (acthdl != -1) { if (p->pdc->hastobepos) acthdl++; pdc_sprintf(p->pdc, pdc_false, actoptlist, "activate %d", acthdl); self.action = pdc_strdup(p->pdc, actoptlist); } pdc_free(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; }
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; }
void pdf__create_pvf(PDF *p, const char *filename, int reserved, const void *data, size_t size, const char *optlist) { static const char fn[] = "pdf__create_pvf"; pdc_bool iscopy = pdc_false; pdf_virtfile *vfile, *lastvfile = NULL; pdc_resopt *results; (void) reserved; /* Parse optlist */ results = pdc_parse_optionlist(p->pdc, optlist, pdf_create_pvf_options, NULL, pdc_true); pdc_get_optvalues(p->pdc, "copy", results, &iscopy, NULL); pdc_cleanup_optionlist(p->pdc, results); /* Find virtual file in file system */ vfile = pdf_find_pvf(p, filename, &lastvfile); /* Name already exists */ if (vfile != NULL) pdc_error(p->pdc, PDC_E_PVF_NAMEEXISTS, filename, 0, 0, 0); /* New virtual file */ vfile = (pdf_virtfile *) pdc_calloc(p->pdc, sizeof(pdf_virtfile), fn); if (lastvfile) lastvfile->next = vfile; else p->filesystem = vfile; /* Fill up file struct */ vfile->name = pdc_strdup(p->pdc, filename); if (iscopy == pdc_true) { vfile->data = (const void *) pdc_malloc(p->pdc, size, fn); memcpy((void *) vfile->data, data, size); } else { vfile->data = data; } vfile->size = size; vfile->iscopy = iscopy; vfile->lockcount = 0; vfile->next = NULL; }
/* returns font handle, ** or -1 if no font found, ** or -2 in case of an error. */ int pdf_handle_cidfont(PDF *p, const char *fontname, const char *encoding) { pdc_font *font = &p->fonts[p->fonts_number]; int slot, cmap, metric; /* * Look whether font is already in the cache. * If font with same name and encoding is found, * return its descriptor. */ for (slot = 0; slot < p->fonts_number; slot++) { if (p->fonts[slot].encoding == pdc_cid && p->fonts[slot].style == font->style && !strcmp(p->fonts[slot].name, fontname) && !strcmp(p->fonts[slot].cmapname, encoding)) return slot; } /* Check the requested CMap */ for (cmap = 0; cmap < NUMBER_OF_CMAPS; cmap++) if (!strcmp(cmaps[cmap].name, encoding)) break; /* Unknown CMap */ if (cmap == NUMBER_OF_CMAPS) return -1; /* Check whether this CMap is supported in the desired PDF version */ if (cmaps[cmap].compatibility > p->compatibility) { pdc_set_errmsg(p->pdc, PDF_E_DOC_PDFVERSION, encoding, pdc_errprintf(p->pdc, "%d.%d", p->compatibility/10, p->compatibility % 10), 0, 0); if (font->verbose) pdc_error(p->pdc, -1, 0, 0, 0, 0); return -2; } /* Check whether the font name is among the known CID fonts */ for (metric = 0; metric < SIZEOF_CID_METRICS; metric++) { if (!strcmp(pdf_cid_metrics[metric].name, fontname)) break; } /* Unknown font */ if (metric == SIZEOF_CID_METRICS) { pdc_set_errmsg(p->pdc, PDF_E_CJK_NOSTANDARD, fontname, 0, 0, 0); if (font->verbose) pdc_error(p->pdc, -1, 0, 0, 0, 0); return -2; } /* Selected CMap and font don't match */ if (cmaps[cmap].charcoll != cc_identity && cmaps[cmap].charcoll != pdf_cid_metrics[metric].charcoll) { pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, fontname, encoding, 0, 0); if (font->verbose) pdc_error(p->pdc, -1, 0, 0, 0, 0); return -2; } /* For Unicode capable language wrappers only UCS2 CMaps allowed */ if (cmaps[cmap].codesize == 0 && p->textformat == pdc_auto2) { pdc_set_errmsg(p->pdc, PDF_E_FONT_NEEDUCS2, encoding, fontname, 0, 0); if (font->verbose) pdc_error(p->pdc, -1, 0, 0, 0, 0); return -2; } p->fonts_number++; /* Code size of CMap */ font->codeSize = 0; font->numOfCodes = 0; /* Fill up the font struct */ pdc_fill_font_metric(p->pdc, font, &pdf_cid_metrics[metric]); /* Now everything is fine; fill the remaining entries */ font->encoding = pdc_cid; font->cmapname = pdc_strdup(p->pdc, encoding); font->ttname = pdc_strdup(p->pdc, fontname); font->apiname = pdc_strdup(p->pdc, fontname); font->obj_id = pdc_alloc_id(p->out); font->embedding = pdc_false; font->kerning = pdc_false; font->subsetting = pdc_false; font->autocidfont = pdc_false; font->unicodemap = pdc_false; font->autosubsetting = pdc_false; /* return valid font descriptor */ return slot; }
pdc_resopt * pdc_parse_optionlist(pdc_core *pdc, const char *optlist, const pdc_defopt *defopt, const pdc_clientdata *clientdata, pdc_bool verbose) { static const char *fn = "pdc_parse_optionlist"; pdc_bool logg5 = pdc_logg_is_enabled(pdc, 5, trc_optlist); const char *stemp1 = NULL, *stemp2 = NULL, *stemp3 = NULL, *s1, *s2; char **items = NULL, *keyword = NULL; char **values = NULL, *value = NULL, **strings = NULL; int i, j, k, nd, is, iss, it, iv, icoord; int numdef, nitems = 0, nvalues, ncoords = 0, errcode = 0; void *resval; double dz, maxval; int retval, iz; pdc_sint32 lz = 0; pdc_uint32 ulz = 0; size_t len; const pdc_defopt *dopt = NULL; pdc_resopt *resopt = NULL; pdc_bool ignore = pdc_false; pdc_bool boolval = pdc_false; pdc_bool tocheck = pdc_false; pdc_bool issorted = pdc_true; pdc_bool ishandle = pdc_true; pdc_bool isutf8 = pdc_false; pdc_logg_cond(pdc, 1, trc_optlist, "\n\tOption list: \"%T\"\n", optlist ? optlist : "", 0); /* split option list */ if (optlist != NULL) { nitems = pdc_split_stringlist(pdc, optlist, PDC_OPT_LISTSEPS, PDC_SPLIT_ISOPTLIST, &items); isutf8 = pdc_is_utf8_bytecode(optlist); } if (nitems < 0) { keyword = (char *) optlist; errcode = PDC_E_OPT_NOTBAL; goto PDC_OPT_SYNTAXERROR; } /* initialize result list */ for (numdef = 0; defopt[numdef].name != NULL; numdef++) { /* */ ; } /* allocate temporary memory for option parser result struct */ resopt = (pdc_resopt *) pdc_calloc_tmp(pdc, numdef * sizeof(pdc_resopt), fn, pdc, pdc_cleanup_optionlist_tmp); for (i = 0; i < numdef; i++) { resopt[i].numdef = numdef; resopt[i].defopt = &defopt[i]; if (defopt[i].flags & PDC_OPT_IGNOREIF1 || defopt[i].flags & PDC_OPT_IGNOREIF2 || defopt[i].flags & PDC_OPT_REQUIRIF1 || defopt[i].flags & PDC_OPT_REQUIRIF2 || defopt[i].flags & PDC_OPT_REQUIRED) tocheck = pdc_true; if (i && issorted) issorted = (strcmp(defopt[i-1].name, defopt[i].name) <= 0) ? pdc_true : pdc_false; } /* loop over all option list elements */ for (is = 0; is < nitems; is++) { pdc_bool isequal = pdc_false; /* search keyword */ boolval = pdc_undef; keyword = items[is]; for (it = 0; it < numdef; it++) { s1 = keyword; s2 = defopt[it].name; /* if (!pdc_stricmp(keyword, defopt[it].name)) * isequal = pdc_true; */ for (; *s1; ++s1, ++s2) { if (pdc_tolower(*s1) != pdc_tolower(*s2)) break; } if (pdc_tolower(*s1) == pdc_tolower(*s2)) isequal = pdc_true; /* special handling for booleans */ if (defopt[it].type == pdc_booleanlist) { if (isequal || (keyword[1] != 0 && !pdc_stricmp(&keyword[2], defopt[it].name))) { iss = is + 1; if (iss == nitems || (pdc_stricmp(items[iss], "true") && pdc_stricmp(items[iss], "false"))) { i = pdc_strincmp(defopt[it].name, "no", 2) ? 0 : 2; if (!pdc_strincmp(&keyword[i], "no", 2)) { boolval = pdc_false; break; } else if (isequal) { boolval = pdc_true; break; } } } } if (isequal) break; } if (logg5) pdc_logg(pdc, "\t\t\toption \"%s\" specified: ", keyword); if (it == numdef) { errcode = PDC_E_OPT_UNKNOWNKEY; goto PDC_OPT_SYNTAXERROR; } /* initialize */ dopt = &defopt[it]; ignore = pdc_false; nvalues = 1; values = NULL; ishandle = pdc_true; /* compatibility */ if (clientdata && clientdata->compatibility) { int compatibility = clientdata->compatibility; for (iv = PDC_1_3; iv <= PDC_X_X_LAST; iv++) { if (logg5 && (dopt->flags & (1L<<iv))) pdc_logg(pdc, "(compatibility >= %s) ", pdc_get_pdfversion(pdc, iv)); if ((dopt->flags & (1L<<iv)) && compatibility < iv) { if (logg5) pdc_logg(pdc, "\n"); stemp2 = pdc_get_pdfversion(pdc, compatibility); errcode = PDC_E_OPT_VERSION; goto PDC_OPT_SYNTAXERROR; } } } /* not supported */ if (dopt->flags & PDC_OPT_UNSUPP) { if (logg5) pdc_logg(pdc, "(unsupported)\n"); keyword = (char *) dopt->name; errcode = PDC_E_OPT_UNSUPP; goto PDC_OPT_SYNTAXERROR; } /* parse values */ if (boolval == pdc_undef) { is++; if (is == nitems) { errcode = PDC_E_OPT_NOVALUES; goto PDC_OPT_SYNTAXERROR; } if (!ignore) { if (dopt->type == pdc_stringlist && pdc_is_utf8_bytecode(items[is])) resopt[it].flags |= PDC_OPT_ISUTF8; if (dopt->type != pdc_stringlist || dopt->maxnum > 1) nvalues = pdc_split_stringlist(pdc, items[is], (dopt->flags & PDC_OPT_SUBOPTLIST) ? PDC_OPT_LISTSEPS : NULL, PDC_SPLIT_ISOPTLIST, &values); if (dopt->flags & PDC_OPT_DUPORIGVAL) resopt[it].origval = pdc_strdup(pdc, items[is]); } } /* ignore */ if (ignore) continue; /* number of values check */ if (nvalues < dopt->minnum) { stemp2 = pdc_errprintf(pdc, "%d", dopt->minnum); errcode = PDC_E_OPT_TOOFEWVALUES; goto PDC_OPT_SYNTAXERROR; } else if (nvalues > dopt->maxnum) { stemp2 = pdc_errprintf(pdc, "%d", dopt->maxnum); errcode = PDC_E_OPT_TOOMANYVALUES; goto PDC_OPT_SYNTAXERROR; } /* number of values must be even */ if (dopt->flags & PDC_OPT_EVENNUM && (nvalues % 2)) { errcode = PDC_E_OPT_ODDNUM; goto PDC_OPT_SYNTAXERROR; } /* number of values must be odd */ if (dopt->flags & PDC_OPT_ODDNUM && !(nvalues % 2)) { errcode = PDC_E_OPT_EVENNUM; goto PDC_OPT_SYNTAXERROR; } /* deprecated option since PDFlib 7 */ if (dopt->flags & PDC_OPT_PDFLIB_7) { pdc_logg_cond(pdc, 2, trc_api, "[Option \"%s\" is deprecated since PDFlib 7]\n", keyword); } /* option already exists */ if (resopt[it].num) { pdc_delete_optvalue(pdc, &resopt[it]); } /* no values */ if (!nvalues ) continue; /* maximal value */ switch (dopt->type) { case pdc_3ddatahandle: maxval = clientdata->max3ddata; break; case pdc_3dviewhandle: maxval = clientdata->max3dview; break; case pdc_actionhandle: maxval = clientdata->maxaction; break; case pdc_bookmarkhandle: maxval = clientdata->maxbookmark; break; case pdc_colorhandle: maxval = clientdata->maxcolor; break; case pdc_documenthandle: maxval = clientdata->maxdocument; break; case pdc_fonthandle: maxval = clientdata->maxfont; break; case pdc_gstatehandle: maxval = clientdata->maxgstate; break; case pdc_iccprofilehandle: maxval = clientdata->maxiccprofile; break; case pdc_imagehandle: maxval = clientdata->maximage; break; case pdc_layerhandle: maxval = clientdata->maxlayer; break; case pdc_pagehandle: maxval = clientdata->maxpage; break; case pdc_patternhandle: maxval = clientdata->maxpattern; break; case pdc_shadinghandle: maxval = clientdata->maxshading; break; case pdc_tablehandle: maxval = clientdata->maxtable; break; case pdc_templatehandle: maxval = clientdata->maxtemplate; break; case pdc_textflowhandle: maxval = clientdata->maxtextflow; break; case pdc_stringhandle: maxval = clientdata->maxstring; break; case pdc_polylinelist: ncoords = 0; default: maxval = dopt->maxval; ishandle = pdc_false; break; } /* allocate value array */ resopt[it].val = pdc_calloc(pdc, (size_t) (nvalues * pdc_typesizes[dopt->type]), fn); resopt[it].num = nvalues; resopt[it].currind = it; if (dopt->flags & PDC_OPT_PERCENT) memset(resopt[it].pcbits, 0, PDC_PCBITS_SIZE); if (logg5) pdc_logg(pdc, "{"); /* analyze type */ resval = resopt[it].val; for (iv = 0; iv < nvalues; iv++) { errcode = 0; if (dopt->maxnum > 1 && nvalues) value = values[iv]; else value = items[is]; if (logg5) pdc_logg(pdc, "%s{%T}", iv ? " " : "", value, 0); switch (dopt->type) { /* boolean list */ case pdc_booleanlist: if (boolval == pdc_true || !pdc_stricmp(value, "true")) { *(pdc_bool *) resval = pdc_true; } else if (boolval == pdc_false || !pdc_stricmp(value, "false")) { *(pdc_bool *) resval = pdc_false; } else { errcode = PDC_E_OPT_ILLBOOLEAN; } break; /* string list */ case pdc_stringlist: if (dopt->flags & PDC_OPT_NOSPACES) { if (pdc_split_stringlist(pdc, value, NULL, 0, &strings) > 1) errcode = PDC_E_OPT_ILLSPACES; pdc_cleanup_stringlist(pdc, strings); } if (!errcode) { len = strlen(value); dz = (double) len; if (dz < dopt->minval) { stemp3 = pdc_errprintf(pdc, "%d", (int) dopt->minval); errcode = PDC_E_OPT_TOOSHORTSTR; } else if (dz > maxval) { stemp3 = pdc_errprintf(pdc, "%d", (int) maxval); errcode = PDC_E_OPT_TOOLONGSTR; } if (dopt->flags & PDC_OPT_CONVUTF8) { int flags = PDC_CONV_EBCDIC | PDC_CONV_WITHBOM; if (isutf8 || (resopt[it].flags & PDC_OPT_ISUTF8)) flags |= PDC_CONV_ISUTF8; *((char **) resval) = pdc_convert_name(pdc, value, 0, flags); } else { *((char **) resval) = pdc_strdup(pdc, value); } } break; /* keyword list */ case pdc_keywordlist: if (dopt->flags & PDC_OPT_CASESENS) iz = pdc_get_keycode(value, dopt->keylist); else iz = pdc_get_keycode_ci(value, dopt->keylist); if (iz == PDC_KEY_NOTFOUND) { errcode = PDC_E_OPT_ILLKEYWORD; } else { *(int *) resval = iz; } break; /* character list */ case pdc_unicharlist: iz = pdc_string2unicode(pdc, value, dopt->flags, dopt->keylist, pdc_false); if (iz < 0) { errcode = PDC_E_OPT_ILLCHAR; break; } dz = iz; if (dz < dopt->minval) { stemp3 = pdc_errprintf(pdc, "%g", dopt->minval); errcode = PDC_E_OPT_TOOSMALLVAL; } else if (dz > maxval) { stemp3 = pdc_errprintf(pdc, "%g", maxval); errcode = PDC_E_OPT_TOOBIGVAL; } *(int *) resval = iz; break; /* string list */ case pdc_polylinelist: { int np = pdc_split_stringlist(pdc, value, NULL, 0, &strings); pdc_polyline *pl = (pdc_polyline *) resval; pl->np = np / 2; pl->p = NULL; /* number of coordinates must be even */ if (np % 2) { errcode = PDC_E_OPT_ODDNUM; np = 0; } /* polyline must be a box */ else if ((dopt->flags & PDC_OPT_ISBOX) && np != 4) { errcode = PDC_E_OPT_ILLBOX; np = 0; } /* polyline will be closed */ else if ((dopt->flags & PDC_OPT_CLOSEPOLY) && np <= 4) { errcode = PDC_E_OPT_ILLPOLYLINE; np = 0; } /* polyline not empty */ if (np) { if (dopt->flags & PDC_OPT_CLOSEPOLY) pl->np += 1; pl->p = (pdc_vector *) pdc_malloc(pdc, pl->np * sizeof(pdc_vector), fn); iz = PDC_KEY_NOTFOUND; j = 0; icoord = ncoords; for (i = 0; i < np; i++) { char *sk = strings[i]; if (dopt->keylist) { /* optional keyword list */ if (dopt->flags & PDC_OPT_CASESENS) iz = pdc_get_keycode(sk, dopt->keylist); else iz = pdc_get_keycode_ci(sk, dopt->keylist); } if (iz == PDC_KEY_NOTFOUND) { /* percentage */ if (dopt->flags & PDC_OPT_PERCENT) { k = (int) strlen(sk) - 1; if (sk[k] == '%') { sk[k] = 0; if (ncoords < PDC_MAX_PERCENTS) { pdc_setbit(resopt[it].pcbits, ncoords); } else { errcode = PDC_E_OPT_TOOMANYPERCVALS; } } } retval = pdc_str2double(sk, &dz); if (!retval) { errcode = PDC_E_OPT_ILLNUMBER; } else if (pdc_getbit(resopt[it].pcbits, ncoords)) { if (dopt->flags & PDC_OPT_PERCRANGE) { if (dz < 0) errcode = PDC_E_OPT_TOOSMALLPERCVAL; if (dz > 100) errcode = PDC_E_OPT_TOOBIGPERCVAL; } dz /= 100.0; } } else { dz = (double) iz; } if (!(i % 2)) { pl->p[j].x = dz; } else { pl->p[j].y = dz; j++; } ncoords++; } if (dopt->flags & PDC_OPT_CLOSEPOLY) { pl->p[pl->np - 1] = pl->p[0]; if (pdc_getbit(resopt[it].pcbits, icoord)) pdc_setbit(resopt[it].pcbits, ncoords); ncoords++; if (pdc_getbit(resopt[it].pcbits, icoord + 1)) pdc_setbit(resopt[it].pcbits, ncoords); ncoords++; } } pdc_cleanup_stringlist(pdc, strings); } break; /* number list */ case pdc_3ddatahandle: case pdc_3dviewhandle: case pdc_actionhandle: case pdc_bookmarkhandle: case pdc_colorhandle: case pdc_documenthandle: case pdc_fonthandle: case pdc_gstatehandle: case pdc_iccprofilehandle: case pdc_imagehandle: case pdc_layerhandle: case pdc_pagehandle: case pdc_patternhandle: case pdc_shadinghandle: case pdc_tablehandle: case pdc_templatehandle: case pdc_textflowhandle: case pdc_integerlist: case pdc_floatlist: case pdc_doublelist: case pdc_scalarlist: if (dopt->keylist && (!(dopt->flags & PDC_OPT_KEYLIST1) || !iv)) { /* optional keyword and/or allowed integer list */ if (dopt->flags & PDC_OPT_CASESENS) iz = pdc_get_keycode(value, dopt->keylist); else iz = pdc_get_keycode_ci(value, dopt->keylist); if (iz == PDC_KEY_NOTFOUND) { if (dopt->flags & PDC_OPT_INTLIST) { errcode = PDC_E_OPT_ILLINTEGER; break; } } else { switch (dopt->type) { default: case pdc_integerlist: *(int *) resval = iz; break; case pdc_floatlist: *(float *) resval = (float) iz; break; case pdc_doublelist: *(double *) resval = (double) iz; break; case pdc_scalarlist: *(pdc_scalar *) resval = (pdc_scalar) iz; break; } break; } } /* percentage */ if (dopt->flags & PDC_OPT_PERCENT) { i = (int) strlen(value) - 1; if (value[i] == '%') { value[i] = 0; if (iv < PDC_MAX_PERCENTS) { pdc_setbit(resopt[it].pcbits, iv); } else { errcode = PDC_E_OPT_TOOMANYPERCVALS; } } } case pdc_stringhandle: if (dopt->type == pdc_floatlist || dopt->type == pdc_doublelist || dopt->type == pdc_scalarlist) { retval = pdc_str2double(value, &dz); } else { if (dopt->minval >= 0) { retval = pdc_str2integer(value, PDC_INT_UNSIGNED, &ulz); dz = ulz; } else { retval = pdc_str2integer(value, 0, &lz); dz = lz; } if (retval && ishandle && pdc->hastobepos && dopt->type != pdc_bookmarkhandle && dopt->type != pdc_stringhandle) { dz -= 1; lz = (pdc_sint32) dz; ulz = (pdc_uint32) dz; } } if (!retval) { errcode = PDC_E_OPT_ILLNUMBER; } else { if (pdc_getbit(resopt[it].pcbits, iv)) { if (dopt->flags & PDC_OPT_PERCRANGE) { if (dz < 0) errcode = PDC_E_OPT_TOOSMALLPERCVAL; if (dz > 100) errcode = PDC_E_OPT_TOOBIGPERCVAL; } dz /= 100.0; } if (errcode == 0) { if (dz < dopt->minval) { if (ishandle) { stemp3 = pdc_get_keyword(dopt->type, pdc_handletypes); errcode = PDC_E_OPT_ILLHANDLE; } else { stemp3 = pdc_errprintf(pdc, "%g", dopt->minval); errcode = PDC_E_OPT_TOOSMALLVAL; } } else if (dz > maxval) { if (ishandle) { stemp3 = pdc_get_keyword(dopt->type, pdc_handletypes); errcode = PDC_E_OPT_ILLHANDLE; } else { stemp3 = pdc_errprintf(pdc, "%g", maxval); errcode = PDC_E_OPT_TOOBIGVAL; } } else if (dopt->flags & PDC_OPT_NOZERO && fabs(dz) < PDC_FLOAT_PREC) { errcode = PDC_E_OPT_ZEROVAL; } else if (dopt->type == pdc_scalarlist) { *(pdc_scalar *) resval = dz; } else if (dopt->type == pdc_doublelist) { *(double *) resval = dz; } else if (dopt->type == pdc_floatlist) { *(float *) resval = (float) dz; } else { if (dopt->minval >= 0) *(pdc_uint32 *) resval = ulz; else *(pdc_sint32 *) resval = lz; } } } break; } if (errcode) { stemp2 = pdc_errprintf(pdc, "%.*s", PDC_ERR_MAXSTRLEN, value); goto PDC_OPT_SYNTAXERROR; } /* increment value pointer */ resval = (void *) ((char *)(resval) + pdc_typesizes[dopt->type]); } pdc_cleanup_stringlist(pdc, values); values = NULL; if (logg5) pdc_logg(pdc, "}\n"); /* build OR bit pattern */ if (dopt->flags & PDC_OPT_BUILDOR && nvalues > 1) { int *bcode = (int *) resopt[it].val; for (iv = 1; iv < nvalues; iv++) { bcode[0] |= bcode[iv]; } resopt[it].num = 1; } } pdc_cleanup_stringlist(pdc, items); items = NULL; /* required and to be ignored options */ for (is = 0; tocheck && is < numdef; is++) { /* to be ignored option */ if (resopt[is].num) { nd = 0; if (defopt[is].flags & PDC_OPT_IGNOREIF1) nd = 1; if (defopt[is].flags & PDC_OPT_IGNOREIF2) nd = 2; for (it = is - 1; it >= is - nd && it >= 0; it--) { if (resopt[it].num) { pdc_delete_optvalue(pdc, &resopt[is]); if (verbose) pdc_warning(pdc, PDC_E_OPT_IGNORE, defopt[is].name, defopt[it].name, 0, 0); } } } /* required option */ if (!resopt[is].num && ((defopt[is].flags & PDC_OPT_REQUIRED) || (defopt[is].flags & PDC_OPT_REQUIRIF1 && resopt[is-1].num) || (defopt[is].flags & PDC_OPT_REQUIRIF2 && (resopt[is-1].num || resopt[is-2].num)))) { keyword = (char *) defopt[is].name; errcode = PDC_E_OPT_NOTFOUND; goto PDC_OPT_SYNTAXERROR; } } /* is no sorted */ if (!issorted) { qsort((void *)resopt, (size_t) numdef, sizeof(pdc_resopt), pdc_optname_compare); } /* global UTF-8 check after sort */ if (isutf8) resopt[0].isutf8 = pdc_true; /* index of last got option */ resopt[0].lastind = -1; /* protocol */ if (pdc_logg_is_enabled(pdc, 1, trc_optlist)) { for (is = 0; is < numdef; is++) { if (resopt[is].num) pdc_logg(pdc, "\tOption \"%s\": %d value%s found\n", resopt[is].defopt->name, resopt[is].num, resopt[is].num == 1 ? "" : "s"); else if (logg5) pdc_logg(pdc, "\t\t\toption \"%s\" not specified\n", resopt[is].defopt->name); for (iv = 0; iv < resopt[is].num; iv++) { switch (resopt[is].defopt->type) { case pdc_booleanlist: case pdc_keywordlist: case pdc_integerlist: case pdc_3ddatahandle: case pdc_3dviewhandle: case pdc_actionhandle: case pdc_bookmarkhandle: case pdc_colorhandle: case pdc_documenthandle: case pdc_fonthandle: case pdc_gstatehandle: case pdc_iccprofilehandle: case pdc_imagehandle: case pdc_layerhandle: case pdc_pagehandle: case pdc_patternhandle: case pdc_shadinghandle: case pdc_tablehandle: case pdc_templatehandle: case pdc_textflowhandle: case pdc_stringhandle: pdc_logg(pdc, "\tValue %d: %d\n", iv + 1, *((int *) resopt[is].val + iv)); break; case pdc_stringlist: pdc_logg(pdc, "\tValue %d: \"%T\"\n", iv + 1, *((char **) resopt[is].val + iv), 0); break; case pdc_floatlist: pdc_logg(pdc, "\tValue %d: %f\n", iv + 1, *((float *) resopt[is].val + iv)); break; case pdc_doublelist: pdc_logg(pdc, "\tValue %d: %f\n", iv + 1, *((double *) resopt[is].val + iv)); break; case pdc_scalarlist: pdc_logg(pdc, "\tValue %d: %f\n", iv + 1, *((pdc_scalar *) resopt[is].val + iv)); break; case pdc_unicharlist: pdc_logg(pdc, "\tValue %d: %d\n", iv + 1, *((int *) resopt[is].val + iv)); break; case pdc_polylinelist: pdc_logg(pdc, "\t\t#%d: ", iv + 1); { pdc_polyline *pl = (pdc_polyline *) resopt[is].val + iv; for (j = 0; j < pl->np; j++) pdc_logg(pdc, "%f,%f ", pl->p[j].x, pl->p[j].y); pdc_logg(pdc, "\n"); } break; } } } } return resopt; PDC_OPT_SYNTAXERROR: stemp1 = pdc_errprintf(pdc, "%.*s", PDC_ERR_MAXSTRLEN, keyword); pdc_cleanup_stringlist(pdc, items); pdc_cleanup_stringlist(pdc, values); pdc_set_errmsg(pdc, errcode, stemp1, stemp2, stemp3, 0); if (verbose) pdc_error(pdc, -1, 0, 0, 0, 0); return NULL; }
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[PDC_GEN_BUFSIZE]; 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; pdc_sprintf(p->pdc, pdc_false, optlist, "%s %s", key, 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_pdflib_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: pdc_sprintf(p->pdc, pdc_false, optlist, "filename %s", 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 */
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; pdc_scalar tbc; 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 (urx < llx) { tbc = llx; llx = urx; urx = tbc; } if (ury < lly) { tbc = lly; lly = ury; ury = tbc; } 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_glyphmetrics); } pdc_pop_errmsg(p->pdc); if (!p->pdc->smokerun) pdc_logg_cond(p->pdc, 1, trc_api, "[Begin glyph %d]\n", ig); }
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"; 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 */ fontname = pdf_convert_name(p, fontname, len, PDC_CONV_WITHBOM | PDC_CONV_TMPALLOC); if (fontname == NULL || *fontname == '\0') pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0); 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); }
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 = NULL; pdc_file *fp = NULL; const char *stemp = NULL; pdc_byte magic[PFA_TESTBYTE]; char fullname[PDC_FILENAMELEN]; int fflags = PDC_FILE_BINARY; pdc_bool ispfb = pdc_true; if (filename) { pdc_bool retval = pdc_true; pdc_bool fnamegiven = (strcmp(filename, FNT_MISSING_FILENAME) == 0) ? pdc_false : pdc_true; (void) retval; if (fnamegiven) { fp = pdc_fsearch_fopen(p->pdc, filename, fullname, "PostScript Type1 ", fflags); if (fp == NULL) { if (t1src) PDC_RETHROW(p->pdc); 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_RETHROW(p->pdc); 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 = (t1_private_data *) t1src->private_data; if (filename) { pdc_fclose(fp); if (ispfb) { t1->fontfile = pdc_fsearch_fopen(p->pdc, fullname, NULL, "PFB ", fflags); } else { t1->fontfile = pdc_fsearch_fopen(p->pdc, fullname, NULL, "PFA ", PDC_FILE_TEXT); } if (t1->fontfile == NULL) PDC_RETHROW(p->pdc); } else if (font->ft.img) { /* only for virtual PFB files */ t1->fontfile = NULL; t1->img = font->ft.img; t1->pos = font->ft.img; t1->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_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" "\tVertical font: %s\n", font->ft.name, font->ft.m.name, PDC_BOOLSTR(font->opt.embedding), PDC_BOOLSTR(font->ft.vertical)); 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; }
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 = NULL, *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; }
PDFLIB_API void PDFLIB_CALL PDF_set_parameter(PDF *p, const char *key, const char *value) { static const char fn[] = "PDF_set_parameter"; pdc_usebox usebox = use_none; pdc_text_format textformat = pdc_auto; int i, k; if (key == NULL || !*key) pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "key", 0, 0, 0); i = get_index(key); if (!pdf_enter_api(p, fn, (pdf_state) pdf_state_all, "(p[%p], \"%s\", \"%s\")\n", (void *) p, key, value)) return; if (i == -1) pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0); if ((p->state_stack[p->state_sp] & parms[i].set_scope) == 0) pdc_error(p->pdc, PDF_E_DOC_SCOPE_SET, key, pdf_current_scope(p), 0, 0); if (value == NULL) pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "value", 0, 0, 0); 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(value, pdf_usebox_keylist); if (k == PDC_KEY_NOTFOUND) pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); usebox = (pdc_usebox) k; break; case PDF_PARAMETER_TEXTFORMAT: case PDF_PARAMETER_HYPERTEXTFORMAT: k = pdc_get_keycode(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_FLUSH: if (p->binding != NULL && strcmp(p->binding, "C++")) break; if (!strcmp(value, "none")) p->flush = pdf_flush_none; else if (!strcmp(value, "page")) p->flush = (pdf_flush_state) (p->flush | pdf_flush_page); else if (!strcmp(value, "content")) p->flush = (pdf_flush_state) (p->flush | pdf_flush_content); else if (!strcmp(value, "heavy")) p->flush = (pdf_flush_state) (p->flush | pdf_flush_heavy); else pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); break; case PDF_PARAMETER_DEBUG: { const unsigned char *c; for (c = (const unsigned char *) value; *c; c++) { p->debug[(int) *c] = 1; if (*c == 't') { pdc_set_trace(p->pdc, "PDFlib " PDFLIB_VERSIONSTRING); } } break; } case PDF_PARAMETER_NODEBUG: { const unsigned char *c; for (c = (const unsigned char *) value; *c; c++) { if (*c == 't') pdc_set_trace(p->pdc, NULL); p->debug[(int) *c] = 0; } break; } case PDF_PARAMETER_BINDING: if (!p->binding) p->binding = pdc_strdup(p->pdc, value); break; case PDF_PARAMETER_HASTOBEPOS: p->hastobepos = pdf_bool_value(p, key, value); break; case PDF_PARAMETER_UNDERLINE: p->underline = pdf_bool_value(p, key, value); break; case PDF_PARAMETER_OVERLINE: p->overline = pdf_bool_value(p, key, value); break; case PDF_PARAMETER_STRIKEOUT: p->strikeout = pdf_bool_value(p, key, value); break; case PDF_PARAMETER_KERNING: pdc_warning(p->pdc, PDF_E_UNSUPP_KERNING, 0, 0, 0, 0); break; case PDF_PARAMETER_AUTOSUBSETTING: pdc_warning(p->pdc, PDF_E_UNSUPP_SUBSET, 0, 0, 0, 0); break; case PDF_PARAMETER_AUTOCIDFONT: pdc_warning(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0); break; case PDF_PARAMETER_UNICODEMAP: pdc_warning(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0); 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: if (!strcmp(value, "1.3")) p->compatibility = PDC_1_3; else if (!strcmp(value, "1.4")) p->compatibility = PDC_1_4; else if (!strcmp(value, "1.5")) p->compatibility = PDC_1_5; else pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); break; case PDF_PARAMETER_PDFX: pdc_warning(p->pdc, PDF_E_UNSUPP_PDFX, 0, 0, 0, 0); break; case PDF_PARAMETER_RESOURCEFILE: if (p->resourcefilename) { pdc_free(p->pdc, p->resourcefilename); p->resourcefilename = NULL; } p->resourcefilename = pdc_strdup(p->pdc, value); p->resfilepending = pdc_true; break; case PDF_PARAMETER_PREFIX: if (p->prefix) { pdc_free(p->pdc, p->prefix); p->prefix = NULL; } /* because of downward compatibility */ p->prefix = pdc_strdup(p->pdc, &value[value[0] == '/' ? 1 : 0]); break; case PDF_PARAMETER_WARNING: pdc_set_warnings(p->pdc, pdf_bool_value(p, key, value)); break; case PDF_PARAMETER_OPENWARNING: p->debug['o'] = (char) pdf_bool_value(p, key, value); break; case PDF_PARAMETER_FONTWARNING: p->debug['F'] = (char) pdf_bool_value(p, key, value); break; case PDF_PARAMETER_ICCWARNING: p->debug['I'] = (char) pdf_bool_value(p, key, value); break; case PDF_PARAMETER_IMAGEWARNING: p->debug['i'] = (char) pdf_bool_value(p, key, value); break; case PDF_PARAMETER_PDIWARNING: p->debug['p'] = (char) pdf_bool_value(p, key, value); break; case PDF_PARAMETER_HONORICCPROFILE: p->debug['e'] = (char) pdf_bool_value(p, key, value); break; case PDF_PARAMETER_GLYPHWARNING: p->debug['g'] = (char) pdf_bool_value(p, key, value); break; case PDF_PARAMETER_RENDERINGINTENT: k = pdc_get_keycode(value, gs_renderingintents); 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_INHERITGSTATE: p->inheritgs = pdf_bool_value(p, key, value); break; case PDF_PARAMETER_PDISTRICT: p->pdi_strict = pdf_bool_value(p, key, value); break; case PDF_PARAMETER_PDIUSEBOX: p->pdi_usebox = usebox; break; case PDF_PARAMETER_PASSTHROUGH: p->debug['P'] = (char) !pdf_bool_value(p, key, value); break; case PDF_PARAMETER_HIDETOOLBAR: if (pdf_bool_value(p, key, value)) p->ViewerPreferences.flags |= HideToolbar; break; case PDF_PARAMETER_HIDEMENUBAR: if (pdf_bool_value(p, key, value)) p->ViewerPreferences.flags |= HideMenubar; break; case PDF_PARAMETER_HIDEWINDOWUI: if (pdf_bool_value(p, key, value)) p->ViewerPreferences.flags |= HideWindowUI; break; case PDF_PARAMETER_FITWINDOW: if (pdf_bool_value(p, key, value)) p->ViewerPreferences.flags |= FitWindow; break; case PDF_PARAMETER_CENTERWINDOW: if (pdf_bool_value(p, key, value)) p->ViewerPreferences.flags |= CenterWindow; break; case PDF_PARAMETER_DISPLAYDOCTITLE: if (pdf_bool_value(p, key, value)) p->ViewerPreferences.flags |= DisplayDocTitle; break; case PDF_PARAMETER_NONFULLSCREENPAGEMODE: if (!strcmp(value, "useoutlines")) { p->ViewerPreferences.flags |= NonFullScreenPageModeOutlines; p->ViewerPreferences.flags &= ~NonFullScreenPageModeThumbs; } else if (!strcmp(value, "usethumbs")) { p->ViewerPreferences.flags &= ~NonFullScreenPageModeOutlines; p->ViewerPreferences.flags |= NonFullScreenPageModeThumbs; } else if (!strcmp(value, "usenone")) { p->ViewerPreferences.flags &= ~NonFullScreenPageModeOutlines; p->ViewerPreferences.flags &= ~NonFullScreenPageModeThumbs; } else { pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); } break; case PDF_PARAMETER_DIRECTION: if (!strcmp(value, "r2l")) { p->ViewerPreferences.flags |= DirectionR2L; } else if (!strcmp(value, "l2r")) { p->ViewerPreferences.flags &= ~DirectionR2L; } else { pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); } break; case PDF_PARAMETER_VIEWAREA: p->ViewerPreferences.ViewArea = usebox; break; case PDF_PARAMETER_VIEWCLIP: p->ViewerPreferences.ViewClip = usebox; break; case PDF_PARAMETER_PRINTAREA: p->ViewerPreferences.PrintArea = usebox; break; case PDF_PARAMETER_PRINTCLIP: p->ViewerPreferences.PrintClip = usebox; break; case PDF_PARAMETER_TOPDOWN: if (pdf_bool_value(p, key, value)) p->ydirection = (float) -1.0; else p->ydirection = (float) 1.0; break; case PDF_PARAMETER_USERCOORDINATES: p->usercoordinates = pdf_bool_value(p, key, value); break; case PDF_PARAMETER_OPENACTION: pdf_cleanup_destination(p, &p->open_action); pdf_parse_destination_optlist(p, value, &p->open_action, 1, pdf_openaction); break; case PDF_PARAMETER_OPENMODE: if (!strcmp(value, "none")) { p->open_mode = open_none; } else if (!strcmp(value, "bookmarks")) { p->open_mode = open_bookmarks; } else if (!strcmp(value, "thumbnails")) { p->open_mode = open_thumbnails; } else if (!strcmp(value, "fullscreen")) { p->open_mode = open_fullscreen; } else { pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); } break; case PDF_PARAMETER_BOOKMARKDEST: pdf_cleanup_destination(p, &p->bookmark_dest); pdf_parse_destination_optlist(p, value, &p->bookmark_dest, 0, pdf_bookmark); break; case PDF_PARAMETER_FILLRULE: if (!strcmp(value, "winding")) { p->fillrule = pdf_fill_winding; } else if (!strcmp(value, "evenodd")) { p->fillrule = pdf_fill_evenodd; } else { pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); } break; case PDF_PARAMETER_TEXTFORMAT: p->textformat = textformat; break; case PDF_PARAMETER_HYPERTEXTFORMAT: p->hypertextformat = textformat; break; case PDF_PARAMETER_HYPERTEXTENCODING: { pdc_encoding enc; if (!*value) { enc = pdc_unicode; } else { enc = pdf_find_encoding(p, (const char *) value); if (enc == pdc_invalidenc) enc = pdf_insert_encoding(p, (const char *) value); if (enc < 0 && enc != pdc_unicode) pdc_error(p->pdc, PDC_E_PAR_ILLPARAM, value, key, 0, 0); } p->hypertextencoding = enc; break; } /* deprecated */ case PDF_PARAMETER_NATIVEUNICODE: (void) pdf_bool_value(p, key, value); break; case PDF_PARAMETER_TRANSITION: pdf_set_transition(p, value); break; case PDF_PARAMETER_BASE: if (p->base) { pdc_free(p->pdc, p->base); p->base = NULL; } p->base = pdc_strdup(p->pdc, 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_TRACE: if (pdf_bool_value(p, key, value)) { p->debug['t'] = 1; pdc_set_trace(p->pdc, "PDFlib " PDFLIB_VERSIONSTRING); } else { pdc_set_trace(p->pdc, NULL); p->debug['t'] = 0; } break; case PDF_PARAMETER_TRACEFILE: pdc_set_tracefile(p->pdc, value); break; case PDF_PARAMETER_TRACEMSG: /* do nothing -- client-supplied string will show up in the trace */ break; case PDF_PARAMETER_SERIAL: case PDF_PARAMETER_LICENSE: break; case PDF_PARAMETER_LICENSEFILE: break; default: pdc_error(p->pdc, PDC_E_PAR_UNKNOWNKEY, key, 0, 0, 0); break; } /* switch */ } /* PDF_set_parameter */
/* ** 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; }
static void pdf_read_resourcefile(PDF *p, const char *filename) { pdc_file *fp = NULL; char **linelist; char *line; char *category = NULL; char *uprfilename = NULL; #if defined(AS400) || defined(WIN32) #define BUFSIZE 2048 char buffer[BUFSIZE]; #ifdef WIN32 char regkey[128]; HKEY hKey = NULL; DWORD size, lType; #endif #endif int il, nlines = 0, nextcat, begin; #ifdef WIN32 /* don't add patchlevel's to registry searchpath */ #define stringiz1(x) #x #define stringiz(x) stringiz1(x) #define PDFLIBKEY "Software\\PDFlib\\PDFlib\\" strcpy(regkey, PDFLIBKEY); strcat(regkey, PDFLIB_VERSIONSTRING); /* process registry entries */ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L, (REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { size = BUFSIZE - 2; if (RegQueryValueExA(hKey, "SearchPath", (LPDWORD) NULL, &lType, (LPBYTE) buffer, &size) == ERROR_SUCCESS && *buffer) { char **pathlist; int ip, np; np = pdc_split_stringlist(p->pdc, buffer, ";", &pathlist); for (ip = 0; ip < np; ip++) pdf_add_resource(p, "SearchPath", pathlist[ip]); pdc_cleanup_stringlist(p->pdc, pathlist); } size = BUFSIZE - 2; if (RegQueryValueExA(hKey, "prefix", (LPDWORD) NULL, &lType, (LPBYTE) buffer, &size) == ERROR_SUCCESS && *buffer) { /* '/' because of downward compatibility */ if (p->prefix) { pdc_free(p->pdc, p->prefix); p->prefix = NULL; } p->prefix = pdc_strdup(p->pdc, &buffer[buffer[0] == '/' ? 1 : 0]); } RegCloseKey(hKey); } #endif /* WIN32 */ #ifdef AS400 strcpy (buffer, "/pdflib/"); strcat (buffer, PDFLIB_VERSIONSTRING); il = (int) strlen(buffer); strcat (buffer, "/fonts"); pdf_add_resource(p, "SearchPath", buffer); strcpy(&buffer[il], "/bind/data"); pdf_add_resource(p, "SearchPath", buffer); #endif /* AS400 */ /* searching for name of upr file */ uprfilename = (char *)filename; if (!uprfilename || *uprfilename == '\0') { /* user-supplied upr file */ uprfilename = pdc_getenv(RESOURCEFILE); if (!uprfilename || *uprfilename == '\0') { uprfilename = DEFAULTRESOURCEFILE; /* user-supplied upr file */ fp = pdf_fopen(p, uprfilename, NULL, 0); if (fp == NULL) { uprfilename = NULL; #ifdef WIN32 /* process registry entries */ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L, (REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { size = BUFSIZE - 2; if (RegQueryValueExA(hKey, "resourcefile", (LPDWORD) NULL, &lType, (LPBYTE) buffer, &size) == ERROR_SUCCESS && *buffer) { uprfilename = buffer; } RegCloseKey(hKey); } #endif /* WIN32 */ } } if (!uprfilename || *uprfilename == '\0') return; if (p->resourcefilename) { pdc_free(p->pdc, p->resourcefilename); p->resourcefilename = NULL; } p->resourcefilename = pdc_strdup(p->pdc, uprfilename); } /* read upr file */ if ((fp == NULL) && ((fp = pdf_fopen(p, uprfilename, "UPR ", 0)) == NULL)) pdc_error(p->pdc, -1, 0, 0, 0, 0); nlines = pdc_read_textfile(p->pdc, fp, &linelist); pdc_fclose(fp); if (!nlines) return; /* Lines loop */ begin = 1; nextcat = 0; for (il = 0; il < nlines; il++) { line = linelist[il]; /* Next category */ if (line[0] == '.' && strlen(line) == 1) { begin = 0; nextcat = 1; continue; } /* Skip category list */ if (begin) continue; /* Prefiex or category expected */ if (nextcat) { /* Directory prefix */ if (line[0] == '/') { if (p->prefix) { pdc_free(p->pdc, p->prefix); p->prefix = NULL; } p->prefix = pdc_strdup(p->pdc, &line[1]); continue; } /* Ressource Category */ category = line; nextcat = 0; continue; } /* Add resource */ pdf_add_resource(p, category, line); } pdc_cleanup_stringlist(p->pdc, linelist); }
void pdf_add_resource(PDF *p, const char *category, const char *resource) { static const char fn[] = "pdf_add_resource"; pdf_rescategory rescat; pdf_category *cat, *lastcat = NULL; pdf_res *res, *lastres = NULL; char *name; char *value; char *prefix = NULL; size_t len; int k, absolut; /* We no longer raise an error but silently ignore unknown categories */ k = pdc_get_keycode(category, pdf_rescategories); if (k == PDC_KEY_NOTFOUND) return; rescat = (pdf_rescategory) k; /* Read resource configuration file if it is pending */ if (p->resfilepending) { p->resfilepending = pdc_false; pdf_read_resourcefile(p, p->resourcefilename); } /* Find start of this category's resource list, if the category exists */ for (cat = p->resources; cat != (pdf_category *) NULL; cat = cat->next) { lastcat = cat; if (!strcmp(cat->category, category)) break; } if (cat == NULL) { cat = (pdf_category *) pdc_malloc(p->pdc, sizeof(pdf_category), fn); cat->category = pdc_strdup(p->pdc, category); cat->kids = NULL; cat->next = NULL; if (lastcat) lastcat->next = cat; else p->resources = cat; } /* Determine name and value of resource */ absolut = 0; len = strlen(resource); value = strchr(resource, '='); if (value) { len = (size_t) (value - resource); value++; if (*value == '=') { absolut = 1; value++; } /* file name is assumed */ if (value[0] != '\0' && value[0] == '.' && value[1] == '/') { value += 2; } } /* Copy resource name */ name = (char *) pdc_malloc(p->pdc, len + 1, fn); strncpy(name, resource, len); name[len] = 0; pdc_strtrim(name); /* Find resource name in resource list */ for (res = cat->kids; res != (pdf_res *) NULL; res = res->next) { if (!strcmp(res->name, name)) break; lastres = res; } /* New resource */ if (res) { pdc_free(p->pdc, name); } else { res = (pdf_res *) pdc_calloc(p->pdc, sizeof(pdf_res), fn); if (lastres) lastres->next = res; else cat->kids = res; res->prev = lastres; res->name = name; } /* New value */ if (res->value) pdc_free(p->pdc, res->value); res->value = NULL; if (!value) { value = ""; } else if (!absolut && p->prefix) { /* Directory prefix */ prefix = p->prefix; if (prefix[0] != '\0' && prefix[0] == '.' && prefix[1] == '/') prefix += 2; if (prefix) { len = strlen(prefix) + strlen(value) + 6; res->value = (char *) pdc_malloc(p->pdc, len, fn); pdc_file_fullname(prefix, value, res->value); } } if (!res->value) { res->value = pdc_strdup(p->pdc, value); pdc_str2trim(res->value); } #undef PDF_TEST_RESOURCE #ifdef PDF_TEST_RESOURCE printf("%s.%s: '%s'\n", category, res->name, res->value); #endif switch (rescat) { case pdf_FontOutline: case pdf_FontAFM: case pdf_FontPFM: case pdf_HostFont: case pdf_Encoding: case pdf_ICCProfile: if (!strlen(res->name) || !strlen(res->value)) pdc_error(p->pdc, PDF_E_RES_BADRES, resource, category, 0, 0); break; default: break; } }
/* * Fill font metric struct from core metric struct */ void fnt_fill_font_metric(pdc_core *pdc, fnt_font *font, pdc_bool kerning, const fnt_font_metric *metric) { static const char fn[] = "fnt_fill_font_metric"; (void) kerning; /* Fill font metric struct. Font struct must be initialized */ font->m = *metric; font->m.charcoll = abs(font->m.charcoll); font->m.name = pdc_strdup(pdc, metric->name); font->name = pdc_strdup(pdc, metric->name); /* Fill glyph widths array (double mapping Unicode <-> code <-> width) */ if (font->m.numglwidths) { font->m.glw = (fnt_glyphwidth *) pdc_calloc(pdc, metric->numglwidths * sizeof(fnt_glyphwidth), fn); memcpy(font->m.glw, metric->glw, metric->numglwidths * sizeof(fnt_glyphwidth)); } /* Fill glyph width array (mapping Unicode interval <-> width) */ if (metric->numinters) { /* We must convert */ if (font->m.type == fnt_Type1) { int i, j, iw, iwe; pdc_ushort uv; for (i = 0; i < metric->numinters; i++) { if (i && metric->ciw[i-1].width != 0) font->m.numglwidths += metric->ciw[i].startcode - metric->ciw[i-1].startcode; } font->m.glw = (fnt_glyphwidth *) pdc_calloc(pdc, font->m.numglwidths * sizeof(fnt_glyphwidth), fn); j = 0; iw = 0; for (i = 0; i < metric->numinters; i++) { if (i && metric->ciw[j].width != 0) { uv = metric->ciw[j].startcode; iwe = iw + metric->ciw[i].startcode - uv; for (; iw < iwe; iw++) { font->m.glw[iw].unicode = uv; font->m.glw[iw].width = metric->ciw[j].width; uv++; } } j = i; } font->m.numinters = 0; font->m.ciw = NULL; } else { font->m.ciw = (fnt_interwidth *) pdc_calloc(pdc, font->m.numinters * sizeof(fnt_interwidth), fn); memcpy(font->m.ciw, metric->ciw, metric->numinters * sizeof(fnt_interwidth)); } } #ifdef PDF_CJKFONTWIDTHS_SUPPORTED /* Fill glyph width array (mapping CID -> width) */ if (font->m.type == fnt_CIDFontType0) fnt_parse_cid_widths(pdc, font); #endif /* PDF_CJKFONTWIDTHS_SUPPORTED */ /* Number of glyphs */ if (font->m.type == fnt_Type1) font->numglyphs = font->m.numglwidths; /* font weight */ font->weight = fnt_stemv2weight(font->m.StdVW); /* standard Adobe font */ font->isstdfont = pdc_true; /* symbol font */ if (!(font->m.flags & FNT_SYMBOL)) font->issymbfont = pdc_false; }
void pdf__begin_glyph( PDF *p, const char *glyphname, float wx, float llx, float lly, float urx, float ury) { static const char fn[] = "pdf__begin_glyph"; pdc_t3font *t3font; pdc_t3glyph *glyph; int i; t3font = p->t3font; if (t3font->colorized == pdc_true && (llx != (float) 0 || lly != (float) 0 || urx != (float) 0 || ury != (float) 0)) pdc_error(p->pdc, PDF_E_T3_BADBBOX, t3font->fontname, 0, 0, 0); PDF_SET_STATE(p, pdf_state_glyph); for (i = 0; i < t3font->next_glyph; ++i) { if (!strcmp(t3font->glyphs[i].name, glyphname)) { pdc_error(p->pdc, PDF_E_T3_GLYPH, glyphname, t3font->fontname, 0, 0); } } if (t3font->next_glyph == t3font->capacity) { t3font->capacity *= 2; t3font->glyphs = (pdc_t3glyph *) pdc_realloc(p->pdc, t3font->glyphs, t3font->capacity * sizeof (pdc_t3glyph), fn); } glyph = &t3font->glyphs[t3font->next_glyph]; glyph->charproc_id = pdc_begin_obj(p->out, PDC_NEW_ID); glyph->name = pdc_strdup(p->pdc, glyphname); /* see comment in p_font.c for explanation */ glyph->width = 1000 * wx * t3font->matrix.a; /* if the strdup above fails, cleanup won't touch this slot. */ ++t3font->next_glyph; p->contents = c_page; /* glyph description */ pdc_begin_dict(p->out); /* glyph description dict */ p->length_id = pdc_alloc_id(p->out); pdc_printf(p->out, "/Length %ld 0 R\n", p->length_id); if (pdc_get_compresslevel(p->out)) pdc_puts(p->out, "/Filter/FlateDecode\n"); pdc_end_dict(p->out); /* glyph description dict */ pdc_begin_pdfstream(p->out); /* glyph description stream */ p->next_content++; if (t3font->colorized == pdc_true) pdc_printf(p->out, "%f 0 d0\n", wx); else { pdc_printf(p->out, "%f 0 %f %f %f %f d1\n", wx, llx, lly, urx, ury); /* adjust the font's bounding box */ if (llx < t3font->bbox.llx) t3font->bbox.llx = llx; if (lly < t3font->bbox.lly) t3font->bbox.lly = lly; if (urx > t3font->bbox.urx) t3font->bbox.urx = urx; if (ury > t3font->bbox.ury) t3font->bbox.ury = ury; } }
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_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->ft.bbox = deffont->ft.bbox; 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; }
void pdf__begin_font( PDF *p, const char *fontname, float a, float b, float c, float d, float e, float f, const char *optlist) { static const char fn[] = "pdf__begin_font"; pdc_resopt *results; pdc_font *font; float det; int colorized = pdc_false; int slot; /* parsing optlist */ results = pdc_parse_optionlist(p->pdc, optlist, pdf_begin_font_options, NULL, pdc_true); pdc_get_optvalues(p->pdc, "colorized", results, &colorized, NULL); pdc_cleanup_optionlist(p->pdc, results); 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); /* look for an already existing font */ for (slot = 0; slot < p->fonts_number; slot++) { if (!strcmp(p->fonts[slot].apiname, fontname)) { pdc_error(p->pdc, PDF_E_T3_FONTEXISTS, fontname, 0, 0, 0); } } PDF_SET_STATE(p, pdf_state_font); pdf_init_tstate(p); pdf_init_gstate(p); pdf_init_cstate(p); /* slot for new font struct */ slot = pdf_init_newfont(p); font = &p->fonts[slot]; p->fonts_number++; /* * 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. */ font->type = pdc_Type3; font->obj_id = pdc_alloc_id(p->out); font->name = NULL; font->apiname = pdc_strdup(p->pdc, fontname); font->encoding = pdc_invalidenc; /* initially there is no encoding */ font->widths = (int *) pdc_calloc(p->pdc, font->numOfCodes * sizeof(int), fn); font->t3font = (pdc_t3font*) pdc_malloc(p->pdc, sizeof(pdc_t3font), fn); pdf_init_t3font_struct(p, font->t3font, T3GLYPHS_CHUNKSIZE); font->t3font->fontname = pdc_strdup(p->pdc, fontname); font->t3font->colorized = colorized; /* the resource id is needed until the font dict is written */ font->t3font->res_id = pdc_alloc_id(p->out); font->t3font->matrix.a = a; font->t3font->matrix.b = b; font->t3font->matrix.c = c; font->t3font->matrix.d = d; font->t3font->matrix.e = e; font->t3font->matrix.f = f; /* We won't receive glyph bounding box values for colorized true, * so we use the font matrix to get an approximation instead. * * Writing the font matrix should be optional according to the * PDF reference, but we must write it in order to work around a * display bug in Acrobat. */ if (font->t3font->colorized == pdc_true) { font->t3font->bbox.llx = 0; font->t3font->bbox.lly = 0; font->t3font->bbox.urx = (d-b)/det; font->t3font->bbox.ury = (a-c)/det; } /* * 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->t3font = font->t3font; }
int pdf_handle_t3font(PDF *p, const char *fontname, pdc_encoding enc, int oldslot) { static const char fn[] = "pdf_handle_t3font"; char *fname; int slot, i; unsigned int namlen; pdc_font *oldfont, *newfont; pdc_encodingvector *ev = p->encodings[enc].ev; oldfont = &p->fonts[oldslot]; /* slot of new font struct - initialized in pdf__load_font */ slot = p->fonts_number; newfont = &p->fonts[slot]; /* font name incl. encoding name */ namlen = strlen(fontname) + (int) strlen(ev->apiname) + 2; fname = (char *) pdc_malloc(p->pdc, namlen, fn); sprintf(fname, "%s.%s", fontname, ev->apiname); /* * This is a fresh font which has never been used. * Enter the new encoding, and we're done. */ if (oldfont->encoding == pdc_invalidenc) { oldfont->encoding = enc; for (i = 0; i < oldfont->numOfCodes; i++) { oldfont->widths[i] = name2width(oldfont->t3font, ev->chars[i]); if (newfont->monospace && oldfont->widths[i]) oldfont->widths[i] = newfont->monospace; } ev->flags |= PDC_ENC_USED; oldfont->name = fname; return oldslot; } p->fonts_number++; /* copy the complete font structure */ memcpy(newfont, oldfont, sizeof(pdc_font)); /* make copies of relevant strings to ensure correct cleanup */ newfont->name = fname; newfont->apiname = pdc_strdup(p->pdc, fontname); /* modify relevant entries */ newfont->used_on_current_page = pdc_false; newfont->encoding = enc; newfont->obj_id = pdc_alloc_id(p->out); newfont->t3font = (pdc_t3font*)pdc_malloc(p->pdc, sizeof(pdc_t3font), fn); pdf_init_t3font_struct(p, newfont->t3font, oldfont->t3font->capacity); /* copy relevant entries of Type 3 structure */ newfont->t3font->charprocs_id = oldfont->t3font->charprocs_id; newfont->t3font->res_id = oldfont->t3font->res_id; newfont->t3font->colorized = oldfont->t3font->colorized; memcpy(&newfont->t3font->matrix, &oldfont->t3font->matrix, sizeof(pdc_matrix)); memcpy(&newfont->t3font->bbox, &oldfont->t3font->bbox, sizeof(pdc_rectangle)); /* copy the glyph/width list from oldfont to newfont */ newfont->t3font->next_glyph = oldfont->t3font->next_glyph; for (i = 0; i < newfont->t3font->next_glyph; ++i) { newfont->t3font->glyphs[i].width = oldfont->t3font->glyphs[i].width; newfont->t3font->glyphs[i].charproc_id = oldfont->t3font->glyphs[i].charproc_id; newfont->t3font->glyphs[i].name = pdc_strdup(p->pdc, oldfont->t3font->glyphs[i].name); } newfont->widths = (int *) pdc_calloc(p->pdc, newfont->numOfCodes * sizeof(int), fn); for (i = 0; i < newfont->numOfCodes; i++) { newfont->widths[i] = name2width(newfont->t3font, p->encodings[enc].ev->chars[i]); if (newfont->monospace && oldfont->widths[i]) newfont->widths[i] = newfont->monospace; } p->encodings[enc].ev->flags |= PDC_ENC_USED; return slot; }