pdc_id pdc_begin_obj(pdc_output *out, pdc_id obj_id) { if (obj_id == PDC_NEW_ID) obj_id = pdc_alloc_id(out); out->file_offset[obj_id] = pdc_tell_out(out); pdc_printf(out, "%ld 0 obj\n", obj_id); return obj_id; }
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__end_font(PDF *p) { int i; pdc_t3font *t3font; PDF_SET_STATE(p, pdf_state_document); t3font = p->t3font; t3font->charprocs_id = pdc_alloc_id(p->out); pdc_begin_obj(p->out, t3font->charprocs_id); /* CharProcs dict */ pdc_begin_dict(p->out); for (i = 0; i < t3font->next_glyph; i++) { pdc_put_pdfname(p->out, t3font->glyphs[i].name, strlen(t3font->glyphs[i].name)); pdc_printf(p->out, " %ld 0 R\n", t3font->glyphs[i].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 */ p->t3font = (pdc_t3font *) NULL; if (p->flush & pdf_flush_content) pdc_flush_stream(p->out); }
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_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 */
/* 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; }
/* 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; }
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__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_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); }
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; }
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; }
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; } }
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; }
PDFLIB_API int PDFLIB_CALL PDF_create_gstate(PDF *p, const char *optlist) { static const char fn[] = "PDF_create_gstate"; pdf_extgstateresource *gs; int slot = -1; int font = pdc_undef; int inum; pdc_clientdata data; pdc_resopt *results; if (!pdf_enter_api(p, fn, (pdf_state) (pdf_state_document | pdf_state_content), "(p[%p], \"%s\")", (void *) p, optlist)) { PDF_RETURN_HANDLE(p, slot) } 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 */ data.compatibility = p->compatibility; data.maxfont = p->fonts_number - 1; data.hastobepos = p->hastobepos; results = pdc_parse_optionlist(p->pdc, optlist, pdf_create_gstate_options, &data, pdc_true); pdc_get_optvalues(p->pdc, "alphaisshape", results, &gs->alpha_is_shape, NULL); if (pdc_get_optvalues(p->pdc, "blendmode", results, &inum, NULL)) gs->blendmode = (pdf_blendmode) inum; gs->dash_count = pdc_get_optvalues(p->pdc, "dasharray", results, NULL, (void **) &gs->dash_array); pdc_get_optvalues(p->pdc, "dashphase", results, &gs->dash_phase, NULL); pdc_get_optvalues(p->pdc, "flatness", results, &gs->flatness, NULL); pdc_get_optvalues(p->pdc, "font", results, &font, NULL); if (font != pdc_undef) gs->font_obj = p->fonts[font].obj_id; pdc_get_optvalues(p->pdc, "fontsize", results, &gs->font_size, NULL); pdc_get_optvalues(p->pdc, "linecap", results, &gs->line_cap, NULL); pdc_get_optvalues(p->pdc, "linejoin", results, &gs->line_join, NULL); pdc_get_optvalues(p->pdc, "linewidth", results, &gs->line_width, NULL); pdc_get_optvalues(p->pdc, "miterlimit", results, &gs->miter_limit, NULL); pdc_get_optvalues(p->pdc, "opacityfill", results, &gs->opacity_fill, NULL); pdc_get_optvalues(p->pdc, "opacitystroke", results, &gs->opacity_stroke, NULL); pdc_get_optvalues(p->pdc, "overprintfill", results, &gs->overprint_fill, NULL); pdc_get_optvalues(p->pdc, "overprintmode", results, &gs->overprint_mode, NULL); pdc_get_optvalues(p->pdc, "overprintstroke", results, &gs->overprint_stroke, NULL); if (pdc_get_optvalues(p->pdc, "renderingintent", results, &inum, NULL)) gs->ri = (pdf_renderingintent) inum; pdc_get_optvalues(p->pdc, "smoothness", results, &gs->smoothness, NULL); pdc_get_optvalues(p->pdc, "strokeadjust", results, &gs->stroke_adjust, NULL); pdc_get_optvalues(p->pdc, "textknockout", results, &gs->text_knockout, NULL); pdc_cleanup_optionlist(p->pdc, results); PDF_RETURN_HANDLE(p, slot) }