static void scan_Coverage(fz_context *ctx, struct ft2vert_st *ret, const FT_Bytes top) { int i; FT_Bytes s = top; struct Coverage_st *t; t = &ret->SubTable[ret->SubTableCount].Coverage; t->CoverageFormat = BYTE2(s); switch (t->CoverageFormat) { case 1: t->GlyphCount = BYTE2(s); t->GlyphArray = fz_calloc(ctx, t->GlyphCount, sizeof(t->GlyphArray[0])); memset(t->GlyphArray, 0, t->GlyphCount * sizeof(t->GlyphArray[0])); for (i = 0; i < t->GlyphCount; i++) t->GlyphArray[i] = BYTE2(s); break; case 2: t->RangeCount = BYTE2(s); t->RangeRecord = fz_calloc(ctx, t->RangeCount, sizeof(t->RangeRecord[0])); memset(t->RangeRecord, 0, t->RangeCount * sizeof(t->RangeRecord[0])); for (i = 0; i < t->RangeCount; i++) { t->RangeRecord[i].Start = BYTE2(s); t->RangeRecord[i].End = BYTE2(s); s += 2; /* drop StartCoverageIndex */ } break; default: fz_warn(ctx, "scan_Coverage: unknown CoverageFormat (%d).", t->CoverageFormat); return; } ret->SubTableCount++; }
/* Convert Unicode/PdfDocEncoding string into ucs-2 */ unsigned short * pdf_to_ucs2(fz_obj *src) { unsigned char *srcptr = (unsigned char *) fz_to_str_buf(src); unsigned short *dstptr, *dst; int srclen = fz_to_str_len(src); int i; if (srclen >= 2 && srcptr[0] == 254 && srcptr[1] == 255) { dstptr = dst = fz_calloc((srclen - 2) / 2 + 1, sizeof(short)); for (i = 2; i + 1 < srclen; i += 2) *dstptr++ = srcptr[i] << 8 | srcptr[i+1]; } else if (srclen >= 2 && srcptr[0] == 255 && srcptr[1] == 254) { dstptr = dst = fz_calloc((srclen - 2) / 2 + 1, sizeof(short)); for (i = 2; i + 1 < srclen; i += 2) *dstptr++ = srcptr[i] | srcptr[i+1] << 8; } else { dstptr = dst = fz_calloc(srclen + 1, sizeof(short)); for (i = 0; i < srclen; i++) *dstptr++ = pdf_doc_encoding[srcptr[i]]; } *dstptr = '\0'; return dst; }
static void pdf_makewidthtable(pdf_fontdesc *fontdesc) { fz_font *font = fontdesc->font; int i, k, cid, gid; font->widthcount = 0; for (i = 0; i < fontdesc->nhmtx; i++) { for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++) { cid = pdf_lookupcmap(fontdesc->encoding, k); gid = pdf_fontcidtogid(fontdesc, cid); if (gid > font->widthcount) font->widthcount = gid; } } font->widthcount ++; font->widthtable = fz_calloc(font->widthcount, sizeof(int)); memset(font->widthtable, 0, sizeof(int) * font->widthcount); for (i = 0; i < fontdesc->nhmtx; i++) { for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++) { cid = pdf_lookupcmap(fontdesc->encoding, k); gid = pdf_fontcidtogid(fontdesc, cid); if (gid >= 0 && gid < font->widthcount) font->widthtable[gid] = fontdesc->hmtx[i].w; } } }
/* Used while reading the individual xref sections from a file */ pdf_xref_entry *pdf_get_populating_xref_entry(pdf_document *doc, int num) { /* Return an entry within the xref currently being populated */ pdf_xref *xref; int i; if (doc->num_xref_sections == 0) { doc->xref_sections = fz_calloc(doc->ctx, 1, sizeof(pdf_xref)); doc->num_xref_sections = 1; } /* Ensure all xref sections map this entry */ for (i = doc->num_xref_sections - 1; i >= 0; i--) { xref = &doc->xref_sections[i]; if (num >= xref->len) pdf_resize_xref(doc->ctx, xref, num+1); else break; /* Remaining sections already of sufficient size */ } /* Loop leaves xref pointing at the populating section */ return &doc->xref_sections[doc->num_xref_sections-1].table[num]; }
static void scan_SubTable(fz_context *ctx, struct ft2vert_st *ret, const FT_Bytes top) { int i; FT_Bytes s = top; FT_Offset Coverage; struct SingleSubst_st *t; t = &ret->SubTable[ret->SubTableCount].SingleSubst; t->SubstFormat = BYTE2(s); Coverage = BYTE2(s); scan_Coverage(ctx, ret, top + Coverage); switch (t->SubstFormat) { case 1: /* SingleSubstFormat1 */ t->DeltaGlyphID = BYTE2(s); break; case 2: /* SingleSubstFormat2 */ t->GlyphCount = BYTE2(s); t->Substitute = fz_calloc(ctx, t->GlyphCount, sizeof(t->Substitute[0])); memset(t->Substitute, 0, t->GlyphCount * sizeof(t->Substitute[0])); for (i = 0; i < t->GlyphCount; i++) t->Substitute[i] = BYTE2(s); break; default: fz_warn(ctx, "scan_SubTable: unknown SubstFormat (%d).", t->SubstFormat); } }
static fz_error pdf_read_ocg(pdf_xref *xref) { fz_obj *obj, *ocg; int len, i; pdf_ocg_descriptor *desc; obj = fz_dict_gets(fz_dict_gets(xref->trailer, "Root"), "OCProperties"); if (obj == NULL) return fz_okay; ocg = fz_dict_gets(obj, "OCGs"); if (ocg == NULL || !fz_is_array(ocg)) /* Not ever supposed to happen, but live with it. */ return fz_okay; len = fz_array_len(ocg); desc = fz_malloc(sizeof(*desc)); desc->len = len; desc->ocgs = fz_calloc(len, sizeof(*desc->ocgs)); desc->intent = NULL; for (i=0; i < len; i++) { fz_obj *o = fz_array_get(ocg, i); desc->ocgs[i].num = fz_to_num(o); desc->ocgs[i].gen = fz_to_gen(o); desc->ocgs[i].state = 0; } xref->ocg = desc; return pdf_ocg_set_config(xref, 0); }
fz_device * fz_new_device_of_size(fz_context *ctx, int size) { fz_device *dev = Memento_label(fz_calloc(ctx, 1, size), "fz_device"); dev->refs = 1; return dev; }
/* Ensure we have an incremental xref section where we can store updated versions of indirect objects */ static void ensure_incremental_xref(pdf_document *doc) { fz_context *ctx = doc->ctx; if (!doc->xref_altered) { pdf_xref *xref = &doc->xref_sections[0]; pdf_xref *pxref; pdf_xref_entry *new_table = fz_calloc(ctx, xref->len, sizeof(pdf_xref_entry)); pdf_obj *trailer = NULL; fz_var(trailer); fz_try(ctx) { trailer = pdf_copy_dict(xref->trailer); doc->xref_sections = fz_resize_array(ctx, doc->xref_sections, doc->num_xref_sections + 1, sizeof(pdf_xref)); xref = &doc->xref_sections[0]; pxref = &doc->xref_sections[1]; memmove(pxref, xref, doc->num_xref_sections * sizeof(pdf_xref)); /* xref->len is already correct */ xref->table = new_table; xref->trailer = trailer; doc->num_xref_sections++; doc->xref_altered = 1; } fz_catch(ctx) { fz_free(ctx, new_table); pdf_drop_obj(trailer); fz_rethrow(ctx); } }
static void pdf_load_type5_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func, fz_stream *stream) { struct mesh_params p; struct vertex *buf, *ref; int first; int ncomp; int i, k; fz_context *ctx = xref->ctx; pdf_load_mesh_params(xref, dict, &p); if (funcs > 0) { ncomp = 1; pdf_sample_shade_function(ctx, shade, funcs, func, p.c0[0], p.c1[0]); } else ncomp = shade->colorspace->n; ref = fz_calloc(ctx, p.vprow, sizeof(struct vertex)); buf = fz_calloc(ctx, p.vprow, sizeof(struct vertex)); first = 1; while (!fz_is_eof_bits(stream)) { for (i = 0; i < p.vprow; i++) { buf[i].x = read_sample(stream, p.bpcoord, p.x0, p.x1); buf[i].y = read_sample(stream, p.bpcoord, p.y0, p.y1); for (k = 0; k < ncomp; k++) buf[i].c[k] = read_sample(stream, p.bpcomp, p.c0[k], p.c1[k]); } if (!first) for (i = 0; i < p.vprow - 1; i++) pdf_add_quad(ctx, shade, &ref[i], &ref[i+1], &buf[i+1], &buf[i]); memcpy(ref, buf, p.vprow * sizeof(struct vertex)); first = 0; } fz_free(ctx, ref); fz_free(ctx, buf); }
fz_archive * fz_new_archive_of_size(fz_context *ctx, fz_stream *file, int size) { fz_archive *arch; arch = Memento_label(fz_calloc(ctx, 1, size), "fz_archive"); arch->file = fz_keep_stream(ctx, file); return arch; }
fz_ael * fz_newael(void) { fz_ael *ael; ael = fz_malloc(sizeof(fz_ael)); ael->cap = 64; ael->len = 0; ael->edges = fz_calloc(ael->cap, sizeof(fz_edge*)); return ael; }
static void renumberobjs(void) { pdf_xrefentry *oldxref; int newlen; int num; /* Apply renumber map to indirect references in all objects in xref */ renumberobj(xref->trailer); for (num = 0; num < xref->len; num++) { fz_obj *obj = xref->table[num].obj; if (fz_isindirect(obj)) { obj = fz_newindirect(renumbermap[fz_tonum(obj)], 0, xref); pdf_updateobject(xref, num, 0, obj); fz_dropobj(obj); } else { renumberobj(obj); } } /* Create new table for the reordered, compacted xref */ oldxref = xref->table; xref->table = fz_calloc(xref->len, sizeof(pdf_xrefentry)); xref->table[0] = oldxref[0]; /* Move used objects into the new compacted xref */ newlen = 0; for (num = 1; num < xref->len; num++) { if (uselist[num]) { if (newlen < renumbermap[num]) newlen = renumbermap[num]; xref->table[renumbermap[num]] = oldxref[num]; } else { if (oldxref[num].obj) fz_dropobj(oldxref[num].obj); } } fz_free(oldxref); /* Update the used objects count in compacted xref */ xref->len = newlen + 1; /* Update list of used objects to fit with compacted xref */ for (num = 1; num < xref->len; num++) uselist[num] = 1; }
void *fz_new_rasterizer_of_size(fz_context *ctx, int size, const fz_rasterizer_fns *fns) { fz_rasterizer *rast = fz_calloc(ctx, 1, size); rast->fns = *fns; rast->clip.x0 = rast->clip.y0 = BBOX_MIN; rast->clip.x1 = rast->clip.y1 = BBOX_MAX; rast->bbox.x0 = rast->bbox.y0 = BBOX_MAX; rast->bbox.x1 = rast->bbox.y1 = BBOX_MIN; return rast; }
fz_path * fz_clone_path(fz_path *old) { fz_path *path; path = fz_malloc(sizeof(fz_path)); path->len = old->len; path->cap = old->len; path->items = fz_calloc(path->cap, sizeof(fz_path_item)); memcpy(path->items, old->items, sizeof(fz_path_item) * path->len); return path; }
fz_path * fz_clonepath(fz_path *old) { fz_path *path; path = fz_malloc(sizeof(fz_path)); path->len = old->len; path->cap = old->len; path->els = fz_calloc(path->cap, sizeof(fz_pathel)); memcpy(path->els, old->els, sizeof(fz_pathel) * path->len); return path; }
fz_gel * fz_new_gel(fz_context *ctx) { fz_gel *gel; gel = fz_malloc(ctx, sizeof(fz_gel)); gel->ctx = ctx; gel->cap = 512; gel->len = 0; gel->edges = fz_calloc(ctx, gel->cap, sizeof(fz_edge)); gel->clip.x0 = gel->clip.y0 = BBOX_MAX; gel->clip.x1 = gel->clip.y1 = BBOX_MIN; gel->bbox.x0 = gel->bbox.y0 = BBOX_MAX; gel->bbox.x1 = gel->bbox.y1 = BBOX_MIN; gel->acap = 64; gel->alen = 0; gel->active = fz_calloc(ctx, gel->acap, sizeof(fz_edge*)); return gel; }
fz_stream * fz_open_concat(fz_context *ctx, int len, int pad) { struct concat_filter *state; state = fz_calloc(ctx, 1, sizeof(struct concat_filter) + (len-1)*sizeof(fz_stream *)); state->max = len; state->count = 0; state->current = 0; state->pad = pad; state->ws = 0; /* We never send padding byte at the start */ return fz_new_stream(ctx, state, read_concat, close_concat); }
fz_stream * fz_open_concat(fz_context *ctx, int len, int pad) { struct concat_filter *state; state = fz_calloc(ctx, 1, sizeof(struct concat_filter) + (len-1)*sizeof(fz_stream *)); state->max = len; state->count = 0; state->current = 0; state->pad = pad; state->ws_buf = 32; return fz_new_stream(ctx, state, next_concat, close_concat, rebind_concat); }
fz_text * fz_clonetext(fz_text *old) { fz_text *text; text = fz_malloc(sizeof(fz_text)); text->font = fz_keepfont(old->font); text->trm = old->trm; text->wmode = old->wmode; text->len = old->len; text->cap = text->len; text->els = fz_calloc(text->len, sizeof(fz_textel)); memcpy(text->els, old->els, text->len * sizeof(fz_textel)); return text; }
fz_gel * fz_newgel(void) { fz_gel *gel; gel = fz_malloc(sizeof(fz_gel)); gel->cap = 512; gel->len = 0; gel->edges = fz_calloc(gel->cap, sizeof(fz_edge)); gel->clip.x0 = gel->clip.y0 = BBOX_MAX; gel->clip.x1 = gel->clip.y1 = BBOX_MIN; gel->bbox.x0 = gel->bbox.y0 = BBOX_MAX; gel->bbox.x1 = gel->bbox.y1 = BBOX_MIN; return gel; }
fz_obj * fz_new_array(fz_context *ctx, int initialcap) { fz_obj *obj; int i; obj = fz_malloc(ctx, sizeof(fz_obj)); obj->refs = 1; obj->kind = FZ_ARRAY; obj->u.a.len = 0; obj->u.a.cap = initialcap > 1 ? initialcap : 6; obj->u.a.items = fz_calloc(ctx, obj->u.a.cap, sizeof(fz_obj*)); for (i = 0; i < obj->u.a.cap; i++) obj->u.a.items[i] = NULL; return obj; }
fz_obj * fz_newarray(int initialcap) { fz_obj *obj; int i; obj = fz_malloc(sizeof(fz_obj)); obj->refs = 1; obj->kind = FZ_ARRAY; obj->u.a.len = 0; obj->u.a.cap = initialcap > 1 ? initialcap : 6; obj->u.a.items = fz_calloc(obj->u.a.cap, sizeof(fz_obj*)); for (i = 0; i < obj->u.a.cap; i++) obj->u.a.items[i] = nil; return obj; }
static fz_error parseTTCs(char *path, pdf_xref *xref) { FONT_COLLECTION fontcollection; ULONG i, numFonts, *offsettable = NULL; fz_error err; fz_stream *file = fz_open_file(xref->ctx, path); if (!file) { err = fz_error_make(xref->ctx, "fonterror : %s not found", path); goto cleanup; } err = safe_read(file, (char *)&fontcollection, sizeof(FONT_COLLECTION)); if (err) goto cleanup; if (BEtoHl(fontcollection.Tag) != TTAG_ttcf) { err = fz_error_make(xref->ctx, "fonterror : wrong format"); goto cleanup; } if (BEtoHl(fontcollection.Version) != TTC_VERSION1 && BEtoHl(fontcollection.Version) != TTC_VERSION2) { err = fz_error_make(xref->ctx, "fonterror : invalid version"); goto cleanup; } numFonts = BEtoHl(fontcollection.NumFonts); offsettable = fz_calloc(xref->ctx, numFonts, sizeof(ULONG)); err = safe_read(file, (char *)offsettable, numFonts * sizeof(ULONG)); for (i = 0; i < numFonts && !err; i++) err = parseTTF(file, BEtoHl(offsettable[i]), i, path, xref); cleanup: fz_free(xref->ctx, offsettable); if (file) fz_close(file); return err; }
pdf_graft_map * pdf_new_graft_map(fz_context *ctx, pdf_document *src) { pdf_graft_map *map = NULL; map = fz_malloc_struct(ctx, pdf_graft_map); fz_try(ctx) { map->len = pdf_xref_len(ctx, src); map->dst_from_src = fz_calloc(ctx, map->len, sizeof(int)); } fz_catch(ctx) { fz_free(ctx, map); fz_rethrow(ctx); } map->refs = 1; return map; }
/* source and dest can be same */ static fz_error decodeunicodeBE(fz_context *ctx, char* source, int sourcelen, char* dest, int destlen) { WCHAR *tmp; int converted, i; if (sourcelen % 2 != 0) return fz_error_make(ctx, "fonterror : invalid unicode string"); tmp = fz_calloc(ctx, sourcelen / 2 + 1, sizeof(WCHAR)); for (i = 0; i < sourcelen / 2; i++) tmp[i] = BEtoHs(((WCHAR *)source)[i]); tmp[sourcelen / 2] = '\0'; converted = WideCharToMultiByte(CP_UTF8, 0, tmp, -1, dest, destlen, NULL, NULL); fz_free(ctx, tmp); if (!converted) return fz_error_make(ctx, "fonterror : invalid unicode string"); return fz_okay; }
static void scan_Lookup(fz_context *ctx, struct ft2vert_st *ret, const FT_Bytes top) { int i; FT_Bytes s = top; FT_UShort LookupType; FT_UShort LookupFlag; FT_UShort SubTableCount; FT_UShort SubTable; LookupType = BYTE2(s); LookupFlag = BYTE2(s); SubTableCount = BYTE2(s); SubTable = BYTE2(s); ret->SubTable = fz_calloc(ctx, SubTableCount, sizeof(ret->SubTable[0])); memset(ret->SubTable, 0, SubTableCount * sizeof(ret->SubTable[0])); for (i = 0; i < SubTableCount; i++) scan_SubTable(ctx, ret, top + SubTable); if (ret->SubTableCount != SubTableCount) fz_warn(ctx, "scan_Lookup: SubTableCount (=%d) is not expected (=%d).\n", ret->SubTableCount, SubTableCount); }
int main(int argc, char **argv) { fz_error error; char *infile; char *outfile = "out.pdf"; char *password = ""; int c, num; int subset; while ((c = fz_getopt(argc, argv, "adgp:")) != -1) { switch (c) { case 'p': password = fz_optarg; break; case 'g': dogarbage ++; break; case 'd': doexpand ++; break; case 'a': doascii ++; break; default: usage(); break; } } if (argc - fz_optind < 1) usage(); infile = argv[fz_optind++]; if (argc - fz_optind > 0 && (strstr(argv[fz_optind], ".pdf") || strstr(argv[fz_optind], ".PDF"))) { outfile = argv[fz_optind++]; } subset = 0; if (argc - fz_optind > 0) subset = 1; error = pdf_openxref(&xref, infile, password); if (error) die(fz_rethrow(error, "cannot open input file '%s'", infile)); out = fopen(outfile, "wb"); if (!out) die(fz_throw("cannot open output file '%s'", outfile)); fprintf(out, "%%PDF-%d.%d\n", xref->version / 10, xref->version % 10); fprintf(out, "%%\316\274\341\277\246\n\n"); uselist = fz_calloc(xref->len + 1, sizeof(char)); ofslist = fz_calloc(xref->len + 1, sizeof(int)); genlist = fz_calloc(xref->len + 1, sizeof(int)); renumbermap = fz_calloc(xref->len + 1, sizeof(int)); for (num = 0; num < xref->len; num++) { uselist[num] = 0; ofslist[num] = 0; genlist[num] = 0; renumbermap[num] = num; } /* Make sure any objects hidden in compressed streams have been loaded */ preloadobjstms(); /* Only retain the specified subset of the pages */ if (subset) retainpages(argc, argv); /* Sweep & mark objects from the trailer */ if (dogarbage >= 1) sweepobj(xref->trailer); /* Coalesce and renumber duplicate objects */ if (dogarbage >= 3) removeduplicateobjs(); /* Compact xref by renumbering and removing unused objects */ if (dogarbage >= 2) compactxref(); /* Make renumbering affect all indirect references and update xref */ if (dogarbage >= 2) renumberobjs(); writepdf(); if (fclose(out)) die(fz_throw("cannot close output file '%s'", outfile)); fz_free(uselist); fz_free(ofslist); fz_free(genlist); fz_free(renumbermap); pdf_freexref(xref); fz_flushwarnings(); return 0; }
void fz_output_pcl_bitmap(fz_output *out, const fz_bitmap *bitmap, fz_pcl_options *pcl) { unsigned char *data, *out_data; int y, ss, rmask, line_size; fz_context *ctx; int num_blank_lines; int compression = -1; unsigned char *prev_row = NULL; unsigned char *out_row_mode_2 = NULL; unsigned char *out_row_mode_3 = NULL; int out_count; int max_mode_2_size; int max_mode_3_size; if (!out || !bitmap) return; ctx = out->ctx; if (pcl->features & HACK__IS_A_OCE9050) { /* Enter HPGL/2 mode, begin plot, Initialise (start plot), Enter PCL mode */ fz_puts(out, "\033%1BBPIN;\033%1A"); } pcl_header(out, pcl, 1, bitmap->xres); fz_var(prev_row); fz_var(out_row_mode_2); fz_var(out_row_mode_3); fz_try(ctx) { num_blank_lines = 0; rmask = ~0 << (-bitmap->w & 7); line_size = (bitmap->w + 7)/8; max_mode_2_size = line_size + (line_size/127) + 1; max_mode_3_size = line_size + (line_size/8) + 1; prev_row = fz_calloc(ctx, line_size, sizeof(unsigned char)); out_row_mode_2 = fz_calloc(ctx, max_mode_2_size, sizeof(unsigned char)); out_row_mode_3 = fz_calloc(ctx, max_mode_3_size, sizeof(unsigned char)); /* Transfer raster graphics. */ data = bitmap->samples; ss = bitmap->stride; for (y = 0; y < bitmap->h; y++, data += ss) { unsigned char *end_data = data + line_size; if ((end_data[-1] & rmask) == 0) { end_data--; while (end_data > data && end_data[-1] == 0) end_data--; } if (end_data == data) { /* Blank line */ num_blank_lines++; continue; } wind(); /* We've reached a non-blank line. */ /* Put out a spacing command if necessary. */ if (num_blank_lines == y) { /* We're at the top of a page. */ if (pcl->features & PCL_ANY_SPACING) { if (num_blank_lines > 0) fz_printf(out, "\033*p+%dY", num_blank_lines * bitmap->yres); /* Start raster graphics. */ fz_puts(out, "\033*r1A"); } else if (pcl->features & PCL_MODE_3_COMPRESSION) { /* Start raster graphics. */ fz_puts(out, "\033*r1A"); for (; num_blank_lines; num_blank_lines--) fz_puts(out, "\033*b0W"); } else { /* Start raster graphics. */ fz_puts(out, "\033*r1A"); for (; num_blank_lines; num_blank_lines--) fz_puts(out, "\033*bW"); } } /* Skip blank lines if any */ else if (num_blank_lines != 0) { /* Moving down from current position causes head * motion on the DeskJet, so if the number of lines * is small, we're better off printing blanks. * * For Canon LBP4i and some others, <ESC>*b<n>Y * doesn't properly clear the seed row if we are in * compression mode 3. */ if ((num_blank_lines < MIN_SKIP_LINES && compression != 3) || !(pcl->features & PCL_ANY_SPACING)) { int mode_3ns = ((pcl->features & PCL_MODE_3_COMPRESSION) && !(pcl->features & PCL_ANY_SPACING)); if (mode_3ns && compression != 2) { /* Switch to mode 2 */ fz_puts(out, from3to2); compression = 2; } if (pcl->features & PCL_MODE_3_COMPRESSION) { /* Must clear the seed row. */ fz_puts(out, "\033*b1Y"); num_blank_lines--; } if (mode_3ns) { for (; num_blank_lines; num_blank_lines--) fz_puts(out, "\033*b0W"); } else { for (; num_blank_lines; num_blank_lines--) fz_puts(out, "\033*bW"); } } else if (pcl->features & PCL3_SPACING) fz_printf(out, "\033*p+%dY", num_blank_lines * bitmap->yres); else fz_printf(out, "\033*b%dY", num_blank_lines); /* Clear the seed row (only matters for mode 3 compression). */ memset(prev_row, 0, line_size); } num_blank_lines = 0; /* Choose the best compression mode for this particular line. */ if (pcl->features & PCL_MODE_3_COMPRESSION) { /* Compression modes 2 and 3 are both available. Try * both and see which produces the least output data. */ int count3 = mode3compress(out_row_mode_3, data, prev_row, line_size); int count2 = mode2compress(out_row_mode_2, data, line_size); int penalty3 = (compression == 3 ? 0 : penalty_from2to3); int penalty2 = (compression == 2 ? 0 : penalty_from3to2); if (count3 + penalty3 < count2 + penalty2) { if (compression != 3) fz_puts(out, from2to3); compression = 3; out_data = (unsigned char *)out_row_mode_3; out_count = count3; } else { if (compression != 2) fz_puts(out, from3to2); compression = 2; out_data = (unsigned char *)out_row_mode_2; out_count = count2; } } else if (pcl->features & PCL_MODE_2_COMPRESSION) { out_data = out_row_mode_2; out_count = mode2compress(out_row_mode_2, data, line_size); } else { out_data = data; out_count = line_size; } /* Transfer the data */ fz_printf(out, "\033*b%dW", out_count); fz_write(out, out_data, out_count); } /* end raster graphics and eject page */ fz_puts(out, "\033*rB\f"); if (pcl->features & HACK__IS_A_OCE9050) { /* Pen up, pen select, advance full page, reset */ fz_puts(out, "\033%1BPUSP0PG;\033E"); } } fz_always(ctx) { fz_free(ctx, prev_row); fz_free(ctx, out_row_mode_2); fz_free(ctx, out_row_mode_3); } fz_catch(ctx) { fz_rethrow(ctx); } }
void * pdf_new_processor(fz_context *ctx, int size) { return Memento_label(fz_calloc(ctx, 1, size), "pdf_processor"); }
fz_error pdf_loadtounicode(pdf_fontdesc *font, pdf_xref *xref, char **strings, char *collection, fz_obj *cmapstm) { fz_error error = fz_okay; pdf_cmap *cmap; int cid; int ucsbuf[8]; int ucslen; int i; if (pdf_isstream(xref, fz_tonum(cmapstm), fz_togen(cmapstm))) { pdf_logfont("tounicode embedded cmap\n"); error = pdf_loadembeddedcmap(&cmap, xref, cmapstm); if (error) return fz_rethrow(error, "cannot load embedded cmap (%d %d R)", fz_tonum(cmapstm), fz_togen(cmapstm)); font->tounicode = pdf_newcmap(); for (i = 0; i < (strings ? 256 : 65536); i++) { cid = pdf_lookupcmap(font->encoding, i); if (cid >= 0) { ucslen = pdf_lookupcmapfull(cmap, i, ucsbuf); if (ucslen == 1) pdf_maprangetorange(font->tounicode, cid, cid, ucsbuf[0]); if (ucslen > 1) pdf_maponetomany(font->tounicode, cid, ucsbuf, ucslen); } } pdf_sortcmap(font->tounicode); pdf_dropcmap(cmap); } else if (collection) { pdf_logfont("tounicode cid collection (%s)\n", collection); error = fz_okay; if (!strcmp(collection, "Adobe-CNS1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-CNS1-UCS2"); else if (!strcmp(collection, "Adobe-GB1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-GB1-UCS2"); else if (!strcmp(collection, "Adobe-Japan1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan1-UCS2"); else if (!strcmp(collection, "Adobe-Japan2")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan2-UCS2"); /* where's this? */ else if (!strcmp(collection, "Adobe-Korea1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Korea1-UCS2"); if (error) return fz_rethrow(error, "cannot load tounicode system cmap %s-UCS2", collection); } if (strings) { pdf_logfont("tounicode strings\n"); /* TODO one-to-many mappings */ font->ncidtoucs = 256; font->cidtoucs = fz_calloc(256, sizeof(unsigned short)); for (i = 0; i < 256; i++) { if (strings[i]) font->cidtoucs[i] = pdf_lookupagl(strings[i]); else font->cidtoucs[i] = '?'; } } if (!font->tounicode && !font->cidtoucs) { pdf_logfont("tounicode could not be loaded\n"); /* TODO: synthesize a ToUnicode if it's a freetype font with * cmap and/or post tables or if it has glyph names. */ } return fz_okay; }