static fz_colorspace * loadcalrgb(pdf_xref *xref, fz_obj *dict) { struct calrgb *cs; fz_obj *tmp; int i; cs = fz_malloc(sizeof(struct calrgb)); pdf_logrsrc("load CalRGB\n"); initcs((fz_colorspace*)cs, "CalRGB", 3, rgbtoxyz, xyztorgb, nil); cs->white[0] = 1.0; cs->white[1] = 1.0; cs->white[2] = 1.0; cs->black[0] = 0.0; cs->black[1] = 0.0; cs->black[2] = 0.0; cs->gamma[0] = 1.0; cs->gamma[1] = 1.0; cs->gamma[2] = 1.0; cs->matrix[0] = 1.0; cs->matrix[1] = 0.0; cs->matrix[2] = 0.0; cs->matrix[3] = 0.0; cs->matrix[4] = 1.0; cs->matrix[5] = 0.0; cs->matrix[6] = 0.0; cs->matrix[7] = 0.0; cs->matrix[8] = 1.0; tmp = fz_dictgets(dict, "WhitePoint"); if (fz_isarray(tmp)) { cs->white[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->white[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->white[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "BlackPoint"); if (fz_isarray(tmp)) { cs->black[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->black[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->black[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Gamma"); if (fz_isarray(tmp)) { cs->gamma[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->gamma[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->gamma[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Matrix"); if (fz_isarray(tmp)) { for (i = 0; i < 9; i++) cs->matrix[i] = fz_toreal(fz_arrayget(tmp, i)); } fz_invert3x3(cs->invmat, cs->matrix); return (fz_colorspace*) cs; }
fz_error pdf_loadfontdescriptor(pdf_fontdesc *fontdesc, pdf_xref *xref, fz_obj *dict, char *collection, char *basefont) { fz_error error; fz_obj *obj1, *obj2, *obj3, *obj; fz_rect bbox; char *fontname; char *origname; pdf_logfont("load fontdescriptor {\n"); /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1014 */ if (!strchr(basefont, ',') || strchr(basefont, '+')) origname = fz_toname(fz_dictgets(dict, "FontName")); else origname = basefont; fontname = cleanfontname(origname); pdf_logfont("fontname %s -> %s\n", origname, fontname); fontdesc->flags = fz_toint(fz_dictgets(dict, "Flags")); fontdesc->italicangle = fz_toreal(fz_dictgets(dict, "ItalicAngle")); fontdesc->ascent = fz_toreal(fz_dictgets(dict, "Ascent")); fontdesc->descent = fz_toreal(fz_dictgets(dict, "Descent")); fontdesc->capheight = fz_toreal(fz_dictgets(dict, "CapHeight")); fontdesc->xheight = fz_toreal(fz_dictgets(dict, "XHeight")); fontdesc->missingwidth = fz_toreal(fz_dictgets(dict, "MissingWidth")); bbox = pdf_torect(fz_dictgets(dict, "FontBBox")); pdf_logfont("bbox [%g %g %g %g]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); pdf_logfont("flags %d\n", fontdesc->flags); obj1 = fz_dictgets(dict, "FontFile"); obj2 = fz_dictgets(dict, "FontFile2"); obj3 = fz_dictgets(dict, "FontFile3"); obj = obj1 ? obj1 : obj2 ? obj2 : obj3; if (getenv("NOFONT")) obj = nil; if (fz_isindirect(obj)) { error = pdf_loadembeddedfont(fontdesc, xref, obj); if (error) { fz_catch(error, "ignored error when loading embedded font, attempting to load system font"); if (origname != fontname) error = pdf_loadbuiltinfont(fontdesc, fontname); else error = pdf_loadsystemfont(fontdesc, fontname, collection); if (error) return fz_rethrow(error, "cannot load font descriptor (%d %d R)", fz_tonum(dict), fz_togen(dict)); } } else { if (origname != fontname && 0 /* SumatraPDF: prefer system fonts to the built-in ones */) error = pdf_loadbuiltinfont(fontdesc, fontname); else error = pdf_loadsystemfont(fontdesc, fontname, collection); if (error) return fz_rethrow(error, "cannot load font descriptor (%d %d R)", fz_tonum(dict), fz_togen(dict)); } fz_strlcpy(fontdesc->font->name, fontname, sizeof fontdesc->font->name); pdf_logfont("}\n"); return fz_okay; }
static fz_error * loadcalrgb(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict) { fz_error *error; struct calrgb *cs; fz_obj *tmp; int i; error = pdf_resolve(&dict, xref); if (error) return error; cs = fz_malloc(sizeof(struct calrgb)); if (!cs) return fz_outofmem; pdf_logrsrc("load CalRGB\n"); initcs((fz_colorspace*)cs, "CalRGB", 3, rgbtoxyz, xyztorgb, nil); cs->white[0] = 1.0; cs->white[1] = 1.0; cs->white[2] = 1.0; cs->black[0] = 0.0; cs->black[1] = 0.0; cs->black[2] = 0.0; cs->gamma[0] = 1.0; cs->gamma[1] = 1.0; cs->gamma[2] = 1.0; cs->matrix[0] = 1.0; cs->matrix[1] = 0.0; cs->matrix[2] = 0.0; cs->matrix[3] = 0.0; cs->matrix[4] = 1.0; cs->matrix[5] = 0.0; cs->matrix[6] = 0.0; cs->matrix[7] = 0.0; cs->matrix[8] = 1.0; tmp = fz_dictgets(dict, "WhitePoint"); if (fz_isarray(tmp)) { cs->white[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->white[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->white[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "BlackPoint"); if (fz_isarray(tmp)) { cs->black[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->black[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->black[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Gamma"); if (fz_isarray(tmp)) { cs->gamma[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->gamma[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->gamma[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Matrix"); if (fz_isarray(tmp)) { for (i = 0; i < 9; i++) cs->matrix[i] = fz_toreal(fz_arrayget(tmp, i)); } fz_invert3x3(cs->invmat, cs->matrix); fz_dropobj(dict); *csp = (fz_colorspace*) cs; return nil; }
static fz_error * loadlab(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict) { fz_error *error; struct cielab *cs; fz_obj *tmp; error = pdf_resolve(&dict, xref); if (error) return error; cs = fz_malloc(sizeof(struct cielab)); if (!cs) return fz_outofmem; pdf_logrsrc("load Lab\n"); initcs((fz_colorspace*)cs, "Lab", 3, labtoxyz, xyztolab, nil); cs->white[0] = 1.0; cs->white[1] = 1.0; cs->white[2] = 1.0; cs->black[0] = 0.0; cs->black[1] = 0.0; cs->black[2] = 0.0; cs->range[0] = -100; cs->range[1] = 100; cs->range[2] = -100; cs->range[3] = 100; tmp = fz_dictgets(dict, "WhitePoint"); if (fz_isarray(tmp)) { cs->white[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->white[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->white[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "BlackPoint"); if (fz_isarray(tmp)) { cs->black[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->black[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->black[2] = fz_toreal(fz_arrayget(tmp, 2)); } tmp = fz_dictgets(dict, "Range"); if (fz_isarray(tmp)) { cs->range[0] = fz_toreal(fz_arrayget(tmp, 0)); cs->range[1] = fz_toreal(fz_arrayget(tmp, 1)); cs->range[2] = fz_toreal(fz_arrayget(tmp, 2)); cs->range[3] = fz_toreal(fz_arrayget(tmp, 3)); } fz_dropobj(dict); *csp = (fz_colorspace*) cs; return nil; }
fz_error * pdf_loadfontdescriptor(pdf_font *font, pdf_xref *xref, fz_obj *desc, char *collection) { fz_error *error; fz_obj *obj1, *obj2, *obj3, *obj; fz_rect bbox; char *fontname; error = pdf_resolve(&desc, xref); if (error) return fz_rethrow(error, "cannot find font descriptor"); pdf_logfont("load fontdescriptor {\n"); obj = fz_dictgets(desc, "FontName"); if (error) return fz_rethrow(error, "cannot resolve FontName"); fontname = fz_toname(obj); pdf_logfont("fontname %s\n", fontname); font->flags = fz_toint(fz_dictgets(desc, "Flags")); font->italicangle = fz_toreal(fz_dictgets(desc, "ItalicAngle")); font->ascent = fz_toreal(fz_dictgets(desc, "Ascent")); font->descent = fz_toreal(fz_dictgets(desc, "Descent")); font->capheight = fz_toreal(fz_dictgets(desc, "CapHeight")); font->xheight = fz_toreal(fz_dictgets(desc, "XHeight")); font->missingwidth = fz_toreal(fz_dictgets(desc, "MissingWidth")); bbox = pdf_torect(fz_dictgets(desc, "FontBBox")); pdf_logfont("bbox [%g %g %g %g]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); pdf_logfont("flags %d\n", font->flags); obj1 = fz_dictgets(desc, "FontFile"); obj2 = fz_dictgets(desc, "FontFile2"); obj3 = fz_dictgets(desc, "FontFile3"); obj = obj1 ? obj1 : obj2 ? obj2 : obj3; if (getenv("NOFONT")) obj = nil; if (fz_isindirect(obj)) { error = pdf_loadembeddedfont(font, xref, obj); if (error) goto cleanup; } else { error = pdf_loadsystemfont(font, fontname, collection); if (error) goto cleanup; } fz_dropobj(desc); pdf_logfont("}\n"); return fz_okay; cleanup: fz_dropobj(desc); return fz_rethrow(error, "cannot load font descriptor"); }
static fz_error pdf_loadimageimp(fz_pixmap **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cstm, int forcemask) { fz_stream *stm; fz_pixmap *tile; fz_obj *obj, *res; fz_error error; int w, h, bpc, n; int imagemask; int interpolate; int indexed; fz_colorspace *colorspace; fz_pixmap *mask; /* explicit mask/softmask image */ int usecolorkey; int colorkey[FZ_MAXCOLORS * 2]; float decode[FZ_MAXCOLORS * 2]; int scale; int stride; unsigned char *samples; int i, len; /* special case for JPEG2000 images */ if (pdf_isjpximage(dict)) { tile = nil; error = pdf_loadjpximage(&tile, xref, dict); if (error) return fz_rethrow(error, "cannot load jpx image"); if (forcemask) { if (tile->n != 2) { fz_droppixmap(tile); return fz_throw("softmask must be grayscale"); } mask = fz_alphafromgray(tile, 1); fz_droppixmap(tile); *imgp = mask; return fz_okay; } *imgp = tile; return fz_okay; } w = fz_toint(fz_dictgetsa(dict, "Width", "W")); h = fz_toint(fz_dictgetsa(dict, "Height", "H")); bpc = fz_toint(fz_dictgetsa(dict, "BitsPerComponent", "BPC")); imagemask = fz_tobool(fz_dictgetsa(dict, "ImageMask", "IM")); interpolate = fz_tobool(fz_dictgetsa(dict, "Interpolate", "I")); indexed = 0; usecolorkey = 0; colorspace = nil; mask = nil; if (imagemask) bpc = 1; if (w == 0) return fz_throw("image width is zero"); if (h == 0) return fz_throw("image height is zero"); if (bpc == 0) return fz_throw("image depth is zero"); if (w > (1 << 16)) return fz_throw("image is too wide"); if (h > (1 << 16)) return fz_throw("image is too high"); obj = fz_dictgetsa(dict, "ColorSpace", "CS"); if (obj && !imagemask && !forcemask) { /* colorspace resource lookup is only done for inline images */ if (fz_isname(obj)) { res = fz_dictget(fz_dictgets(rdb, "ColorSpace"), obj); if (res) obj = res; } error = pdf_loadcolorspace(&colorspace, xref, obj); if (error) return fz_rethrow(error, "cannot load image colorspace"); if (!strcmp(colorspace->name, "Indexed")) indexed = 1; n = colorspace->n; } else { n = 1; } obj = fz_dictgetsa(dict, "Decode", "D"); if (obj) { for (i = 0; i < n * 2; i++) decode[i] = fz_toreal(fz_arrayget(obj, i)); } else { float maxval = indexed ? (1 << bpc) - 1 : 1; for (i = 0; i < n * 2; i++) decode[i] = i & 1 ? maxval : 0; } obj = fz_dictgetsa(dict, "SMask", "Mask"); if (fz_isdict(obj)) { /* Not allowed for inline images */ if (!cstm) { error = pdf_loadimageimp(&mask, xref, rdb, obj, nil, 1); if (error) { if (colorspace) fz_dropcolorspace(colorspace); return fz_rethrow(error, "cannot load image mask/softmask"); } } } else if (fz_isarray(obj)) { usecolorkey = 1; for (i = 0; i < n * 2; i++) colorkey[i] = fz_toint(fz_arrayget(obj, i)); } stride = (w * n * bpc + 7) / 8; samples = fz_calloc(h, stride); if (cstm) { stm = pdf_openinlinestream(cstm, xref, dict, stride * h); } else { error = pdf_openstream(&stm, xref, fz_tonum(dict), fz_togen(dict)); if (error) { if (colorspace) fz_dropcolorspace(colorspace); if (mask) fz_droppixmap(mask); return fz_rethrow(error, "cannot open image data stream (%d 0 R)", fz_tonum(dict)); } } len = fz_read(stm, samples, h * stride); if (len < 0) { fz_close(stm); if (colorspace) fz_dropcolorspace(colorspace); if (mask) fz_droppixmap(mask); return fz_rethrow(len, "cannot read image data"); } /* Make sure we read the EOF marker (for inline images only) */ if (cstm) { unsigned char tbuf[512]; int tlen = fz_read(stm, tbuf, sizeof tbuf); if (tlen < 0) fz_catch(tlen, "ignoring error at end of image"); if (tlen > 0) fz_warn("ignoring garbage at end of image"); } fz_close(stm); /* Pad truncated images */ if (len < stride * h) { fz_warn("padding truncated image (%d 0 R)", fz_tonum(dict)); memset(samples + len, 0, stride * h - len); } /* Invert 1-bit image masks */ if (imagemask) { /* 0=opaque and 1=transparent so we need to invert */ unsigned char *p = samples; len = h * stride; for (i = 0; i < len; i++) p[i] = ~p[i]; } pdf_logimage("size %dx%d n=%d bpc=%d imagemask=%d indexed=%d\n", w, h, n, bpc, imagemask, indexed); /* Unpack samples into pixmap */ tile = fz_newpixmap(colorspace, 0, 0, w, h); scale = 1; if (!indexed) { switch (bpc) { case 1: scale = 255; break; case 2: scale = 85; break; case 4: scale = 17; break; } } fz_unpacktile(tile, samples, n, bpc, stride, scale); if (usecolorkey) pdf_maskcolorkey(tile, n, colorkey); if (indexed) { fz_pixmap *conv; fz_decodeindexedtile(tile, decode, (1 << bpc) - 1); conv = pdf_expandindexedpixmap(tile); fz_droppixmap(tile); tile = conv; } else { fz_decodetile(tile, decode); } if (colorspace) fz_dropcolorspace(colorspace); tile->mask = mask; tile->interpolate = interpolate; fz_free(samples); *imgp = tile; return fz_okay; }
fz_error * pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; char buf[256]; char *estrings[256]; pdf_font *font; fz_obj *encoding; fz_obj *widths; fz_obj *resources; fz_obj *charprocs; fz_obj *obj; int first, last; int i, k, n; fz_rect bbox; obj = fz_dictgets(dict, "Name"); if (obj) strlcpy(buf, fz_toname(obj), sizeof buf); else sprintf(buf, "Unnamed-T3"); font = pdf_newfont(buf); if (!font) return fz_throw("outofmem: font struct"); pdf_logfont("load type3 font %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), font); pdf_logfont("name %s\n", buf); font->super.render = t3render; font->super.drop = (void(*)(fz_font*)) t3dropfont; obj = fz_dictgets(dict, "FontMatrix"); font->matrix = pdf_tomatrix(obj); pdf_logfont("matrix [%g %g %g %g %g %g]\n", font->matrix.a, font->matrix.b, font->matrix.c, font->matrix.d, font->matrix.e, font->matrix.f); obj = fz_dictgets(dict, "FontBBox"); bbox = pdf_torect(obj); pdf_logfont("bbox [%g %g %g %g]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); bbox = fz_transformaabb(font->matrix, bbox); bbox.x0 = fz_floor(bbox.x0 * 1000); bbox.y0 = fz_floor(bbox.y0 * 1000); bbox.x1 = fz_ceil(bbox.x1 * 1000); bbox.y1 = fz_ceil(bbox.y1 * 1000); fz_setfontbbox((fz_font*)font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* * Encoding */ for (i = 0; i < 256; i++) estrings[i] = nil; encoding = fz_dictgets(dict, "Encoding"); if (!encoding) { error = fz_throw("syntaxerror: Type3 font missing Encoding"); goto cleanup; } error = pdf_resolve(&encoding, xref); if (error) goto cleanup; if (fz_isname(obj)) pdf_loadencoding(estrings, fz_toname(encoding)); if (fz_isdict(encoding)) { fz_obj *base, *diff, *item; base = fz_dictgets(encoding, "BaseEncoding"); if (fz_isname(base)) pdf_loadencoding(estrings, fz_toname(base)); diff = fz_dictgets(encoding, "Differences"); if (fz_isarray(diff)) { n = fz_arraylen(diff); k = 0; for (i = 0; i < n; i++) { item = fz_arrayget(diff, i); if (fz_isint(item)) k = fz_toint(item); if (fz_isname(item)) estrings[k++] = fz_toname(item); if (k < 0) k = 0; if (k > 255) k = 255; } } } fz_dropobj(encoding); error = pdf_newidentitycmap(&font->encoding, 0, 1); if (error) goto cleanup; error = pdf_loadtounicode(font, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* * Widths */ fz_setdefaulthmtx((fz_font*)font, 0); first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); widths = fz_dictgets(dict, "Widths"); if (!widths) { error = fz_throw("syntaxerror: Type3 font missing Widths"); goto cleanup; } error = pdf_resolve(&widths, xref); if (error) goto cleanup; for (i = first; i <= last; i++) { float w = fz_toreal(fz_arrayget(widths, i - first)); w = font->matrix.a * w * 1000.0; error = fz_addhmtx((fz_font*)font, i, i, w); if (error) { fz_dropobj(widths); goto cleanup; } } fz_dropobj(widths); error = fz_endhmtx((fz_font*)font); if (error) goto cleanup; /* * Resources */ resources = nil; obj = fz_dictgets(dict, "Resources"); if (obj) { error = pdf_resolve(&obj, xref); if (error) goto cleanup; error = pdf_loadresources(&resources, xref, obj); fz_dropobj(obj); if (error) goto cleanup; } else pdf_logfont("no resource dict!\n"); /* * CharProcs */ charprocs = fz_dictgets(dict, "CharProcs"); if (!charprocs) { error = fz_throw("syntaxerror: Type3 font missing CharProcs"); goto cleanup2; } error = pdf_resolve(&charprocs, xref); if (error) goto cleanup2; for (i = 0; i < 256; i++) { if (estrings[i]) { obj = fz_dictgets(charprocs, estrings[i]); if (obj) { pdf_logfont("load charproc %s {\n", estrings[i]); error = loadcharproc(&font->charprocs[i], xref, resources, obj); if (error) goto cleanup2; error = fz_optimizetree(font->charprocs[i]); if (error) goto cleanup2; pdf_logfont("}\n"); } } } fz_dropobj(charprocs); if (resources) fz_dropobj(resources); pdf_logfont("}\n"); *fontp = font; return fz_okay; cleanup2: if (resources) fz_dropobj(resources); cleanup: fz_dropfont((fz_font*)font); return fz_rethrow(error, "cannot load type3 font"); }
fz_error pdf_loadtype3font(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) { fz_error error; char buf[256]; char *estrings[256]; pdf_fontdesc *fontdesc; fz_obj *encoding; fz_obj *widths; fz_obj *resources; fz_obj *charprocs; fz_obj *obj; int first, last; int i, k, n; fz_rect bbox; fz_matrix matrix; obj = fz_dictgets(dict, "Name"); if (fz_isname(obj)) strlcpy(buf, fz_toname(obj), sizeof buf); else sprintf(buf, "Unnamed-T3"); fontdesc = pdf_newfontdesc(); pdf_logfont("load type3 font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc); pdf_logfont("name %s\n", buf); obj = fz_dictgets(dict, "FontMatrix"); matrix = pdf_tomatrix(obj); pdf_logfont("matrix [%g %g %g %g %g %g]\n", matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f); obj = fz_dictgets(dict, "FontBBox"); bbox = pdf_torect(obj); pdf_logfont("bbox [%g %g %g %g]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); bbox = fz_transformaabb(matrix, bbox); bbox.x0 = fz_floor(bbox.x0 * 1000); bbox.y0 = fz_floor(bbox.y0 * 1000); bbox.x1 = fz_ceil(bbox.x1 * 1000); bbox.y1 = fz_ceil(bbox.y1 * 1000); fontdesc->font = fz_newtype3font(buf, matrix); fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* * Encoding */ for (i = 0; i < 256; i++) estrings[i] = nil; encoding = fz_dictgets(dict, "Encoding"); if (!encoding) { error = fz_throw("syntaxerror: Type3 font missing Encoding"); goto cleanup; } if (fz_isname(encoding)) pdf_loadencoding(estrings, fz_toname(encoding)); if (fz_isdict(encoding)) { fz_obj *base, *diff, *item; base = fz_dictgets(encoding, "BaseEncoding"); if (fz_isname(base)) pdf_loadencoding(estrings, fz_toname(base)); diff = fz_dictgets(encoding, "Differences"); if (fz_isarray(diff)) { n = fz_arraylen(diff); k = 0; for (i = 0; i < n; i++) { item = fz_arrayget(diff, i); if (fz_isint(item)) k = fz_toint(item); if (fz_isname(item)) estrings[k++] = fz_toname(item); if (k < 0) k = 0; if (k > 255) k = 255; } } } fontdesc->encoding = pdf_newidentitycmap(0, 1); error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* * Widths */ pdf_setdefaulthmtx(fontdesc, 0); first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); widths = fz_dictgets(dict, "Widths"); if (!widths) { error = fz_throw("syntaxerror: Type3 font missing Widths"); goto cleanup; } for (i = first; i <= last; i++) { float w = fz_toreal(fz_arrayget(widths, i - first)); w = fontdesc->font->t3matrix.a * w * 1000.0; fontdesc->font->t3widths[i] = w * 0.001; pdf_addhmtx(fontdesc, i, i, w); } pdf_endhmtx(fontdesc); /* * Resources */ resources = fz_dictgets(dict, "Resources"); /* Inherit page's resource dict if type3 font does not have one */ if (!resources && rdb) resources = rdb; else if (!resources && !rdb) fz_warn("no resource dictionary for type 3 font!"); /* * CharProcs */ charprocs = fz_dictgets(dict, "CharProcs"); if (!charprocs) { error = fz_throw("syntaxerror: Type3 font missing CharProcs"); goto cleanup; } for (i = 0; i < 256; i++) { if (estrings[i]) { obj = fz_dictgets(charprocs, estrings[i]); if (obj) { pdf_logfont("load charproc %s {\n", estrings[i]); error = loadcharproc(&fontdesc->font->t3procs[i], xref, resources, obj); if (error) goto cleanup; pdf_logfont("}\n"); } } } pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: fz_dropfont(fontdesc->font); fz_free(fontdesc); return fz_rethrow(error, "cannot load type3 font"); }
/* TODO error cleanup */ fz_error * pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; pdf_image *img; pdf_image *mask; int ismask; fz_obj *obj; fz_obj *sub; int i; int w, h, bpc; int n = 0; int a = 0; int usecolorkey = 0; fz_colorspace *cs = nil; pdf_indexed *indexed = nil; int stride; #ifndef PSP printf("LI\n"); #endif if ((*imgp = pdf_finditem(xref->store, PDF_KIMAGE, ref))) { fz_keepimage((fz_image*)*imgp); return nil; } img = fz_malloc(sizeof(pdf_image)); if (!img) return fz_outofmem; img->super.refs = 0; pdf_logimage("load image %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), img); /* * Dimensions, BPC and ColorSpace */ w = fz_toint(fz_dictgets(dict, "Width")); h = fz_toint(fz_dictgets(dict, "Height")); bpc = fz_toint(fz_dictgets(dict, "BitsPerComponent")); pdf_logimage("size %dx%d %d\n", w, h, bpc); cs = nil; obj = fz_dictgets(dict, "ColorSpace"); if (obj) { cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj); if (cs) fz_keepcolorspace(cs); else { error = pdf_resolve(&obj, xref); if (error) return error; error = pdf_loadcolorspace(&cs, xref, obj); if (error) return error; fz_dropobj(obj); } if (!strcmp(cs->name, "Indexed")) { pdf_logimage("indexed\n"); indexed = (pdf_indexed*)cs; cs = indexed->base; } n = cs->n; a = 0; pdf_logimage("colorspace %s\n", cs->name); } /* * ImageMask, Mask and SoftMask */ mask = nil; ismask = fz_tobool(fz_dictgets(dict, "ImageMask")); if (ismask) { pdf_logimage("is mask\n"); bpc = 1; n = 0; a = 1; } obj = fz_dictgets(dict, "SMask"); if (fz_isindirect(obj)) { pdf_logimage("has soft mask\n"); error = pdf_loadindirect(&sub, xref, obj); if (error) return error; error = pdf_loadimage(&mask, xref, sub, obj); if (error) return error; if (mask->super.cs != pdf_devicegray) return fz_throw("syntaxerror: SMask must be DeviceGray"); mask->super.cs = 0; mask->super.n = 0; mask->super.a = 1; fz_dropobj(sub); } obj = fz_dictgets(dict, "Mask"); if (fz_isindirect(obj)) { error = pdf_loadindirect(&sub, xref, obj); if (error) return error; if (fz_isarray(sub)) { usecolorkey = 1; loadcolorkey(img->colorkey, bpc, indexed != nil, sub); } else { pdf_logimage("has mask\n"); error = pdf_loadimage(&mask, xref, sub, obj); if (error) return error; } fz_dropobj(sub); } else if (fz_isarray(obj)) { usecolorkey = 1; loadcolorkey(img->colorkey, bpc, indexed != nil, obj); } /* * Decode */ obj = fz_dictgets(dict, "Decode"); if (fz_isarray(obj)) { pdf_logimage("decode array\n"); if (indexed) for (i = 0; i < 2; i++) img->decode[i] = fz_toreal(fz_arrayget(obj, i)); else for (i = 0; i < (n + a) * 2; i++) img->decode[i] = fz_toreal(fz_arrayget(obj, i)); } else { if (indexed) for (i = 0; i < 2; i++) img->decode[i] = i & 1 ? (1 << bpc) - 1 : 0; else for (i = 0; i < (n + a) * 2; i++) img->decode[i] = i & 1; } /* * Load samples */ if (indexed) stride = (w * bpc + 7) / 8; else stride = (w * (n + a) * bpc + 7) / 8; // ccm // do not load images larger than 2MB uncompressed int early_reject = 0; if (h * stride <= 2*1024*1024) { error = pdf_loadstream(&img->samples, xref, fz_tonum(ref), fz_togen(ref)); if (error) { /* TODO: colorspace? */ fz_free(img); return error; } if (img->samples->wp - img->samples->bp < stride * h) { /* TODO: colorspace? */ fz_dropbuffer(img->samples); fz_free(img); return fz_throw("syntaxerror: truncated image data"); } /* 0 means opaque and 1 means transparent, so we invert to get alpha */ if (ismask) { unsigned char *p; for (p = img->samples->bp; p < img->samples->ep; p++) *p = ~*p; } } else { #ifndef PSP printf("LI - %p - early reject\n", img); #endif img->samples = nil; early_reject = 1; } /* * Create image object */ img->super.loadtile = pdf_loadtile; img->super.drop = pdf_dropimage; img->super.cs = cs; img->super.w = w; img->super.h = h; img->super.n = n; img->super.a = a; img->indexed = indexed; img->stride = stride; img->bpc = bpc; img->mask = (fz_image*)mask; img->usecolorkey = usecolorkey; if (img->mask) fz_keepimage(img->mask); // ccm #if 1 int bs = 0; if (img->samples) bs = (int)(img->samples->wp) - (int)(img->samples->rp); if (early_reject || (image_buffers_size + bs >= image_buffers_size_max)) { #ifndef PSP printf("LI - %p - optimized out\n", img); #endif if (img->samples) fz_dropbuffer(img->samples); if (img->mask) fz_dropimage(img->mask); fz_newbuffer(&img->samples, 8); img->super.w = 1; img->super.h = 1; img->super.n = 3; img->super.a = 0; img->super.refs = 0; unsigned char *p; for (p = img->samples->bp; p < img->samples->ep; p++) *p = 0x7f; img->indexed = 0; img->stride = (1 * (3 + 0) * 8 + 7) / 8; //(w * (n + a) * bpc + 7) / 8; img->super.cs = cs; img->super.loadtile = fakeImageTile; img->bpc = 8; img->mask = NULL; img->usecolorkey = 0; } else { image_buffers_size += bs; } #endif pdf_logimage("}\n"); error = pdf_storeitem(xref->store, PDF_KIMAGE, ref, img); if (error) { fz_dropimage((fz_image*)img); return error; } *imgp = img; return nil; }
fz_error * pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *file) { fz_error *error; pdf_image *img; fz_filter *filter; fz_obj *f; fz_obj *cs; fz_obj *d; int ismask; int i; img = fz_malloc(sizeof(pdf_image)); if (!img) return fz_outofmem; pdf_logimage("load inline image %p {\n", img); img->super.loadtile = pdf_loadtile; img->super.drop = pdf_dropimage; img->super.n = 0; img->super.a = 0; img->super.refs = 0; img->indexed = nil; img->usecolorkey = 0; img->mask = nil; img->super.w = fz_toint(fz_dictgetsa(dict, "Width", "W")); img->super.h = fz_toint(fz_dictgetsa(dict, "Height", "H")); img->bpc = fz_toint(fz_dictgetsa(dict, "BitsPerComponent", "BPC")); ismask = fz_tobool(fz_dictgetsa(dict, "ImageMask", "IM")); d = fz_dictgetsa(dict, "Decode", "D"); cs = fz_dictgetsa(dict, "ColorSpace", "CS"); pdf_logimage("size %dx%d %d\n", img->super.w, img->super.h, img->bpc); if (ismask) { pdf_logimage("is mask\n"); img->super.cs = nil; img->super.n = 0; img->super.a = 1; img->bpc = 1; } if (cs) { img->super.cs = nil; if (fz_isname(cs)) { fz_obj *csd = fz_dictgets(rdb, "ColorSpace"); if (csd) { fz_obj *cso = fz_dictget(csd, cs); img->super.cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, cso); if (img->super.cs) fz_keepcolorspace(img->super.cs); } } if (!img->super.cs) { /* XXX danger! danger! does this resolve? */ error = pdf_loadcolorspace(&img->super.cs, xref, cs); if (error) return error; } if (!strcmp(img->super.cs->name, "Indexed")) { pdf_logimage("indexed\n"); img->indexed = (pdf_indexed*)img->super.cs; img->super.cs = img->indexed->base; } pdf_logimage("colorspace %s\n", img->super.cs->name); img->super.n = img->super.cs->n; img->super.a = 0; } if (fz_isarray(d)) { pdf_logimage("decode array\n"); if (img->indexed) for (i = 0; i < 2; i++) img->decode[i] = fz_toreal(fz_arrayget(d, i)); else for (i = 0; i < (img->super.n + img->super.a) * 2; i++) img->decode[i] = fz_toreal(fz_arrayget(d, i)); } else { if (img->indexed) for (i = 0; i < 2; i++) img->decode[i] = i & 1 ? (1 << img->bpc) - 1 : 0; else for (i = 0; i < (img->super.n + img->super.a) * 2; i++) img->decode[i] = i & 1; } if (img->indexed) img->stride = (img->super.w * img->bpc + 7) / 8; else img->stride = (img->super.w * (img->super.n + img->super.a) * img->bpc + 7) / 8; /* load image data */ f = fz_dictgetsa(dict, "Filter", "F"); if (f) { fz_stream *tempfile; error = pdf_buildinlinefilter(&filter, dict); if (error) return error; error = fz_openrfilter(&tempfile, filter, file); if (error) return error; i = fz_readall(&img->samples, tempfile); if (i < 0) return fz_ioerror(tempfile); fz_dropfilter(filter); fz_dropstream(tempfile); } else { error = fz_newbuffer(&img->samples, img->super.h * img->stride); if (error) return error; i = fz_read(file, img->samples->bp, img->super.h * img->stride); if (i < 0) return fz_ioerror(file); img->samples->wp += img->super.h * img->stride; } /* 0 means opaque and 1 means transparent, so we invert to get alpha */ if (ismask) { unsigned char *p; for (p = img->samples->bp; p < img->samples->ep; p++) *p = ~*p; } pdf_logimage("}\n"); *imgp = img; return nil; }
fz_error * pdf_loadtype7shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref) { fz_error *error; fz_stream *stream; fz_obj *obj; int bpcoord; int bpcomp; int bpflag; int ncomp; float x0, x1, y0, y1; float c0[FZ_MAXCOLORS]; float c1[FZ_MAXCOLORS]; int i, n, j; unsigned int t; int flag; fz_point p[16]; pdf_tensorpatch patch; error = nil; ncomp = shade->cs->n; bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate")); bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent")); bpflag = fz_toint(fz_dictgets(shading, "BitsPerFlag")); obj = fz_dictgets(shading, "Decode"); if (fz_isarray(obj)) { pdf_logshade("decode array\n"); x0 = fz_toreal(fz_arrayget(obj, 0)); x1 = fz_toreal(fz_arrayget(obj, 1)); y0 = fz_toreal(fz_arrayget(obj, 2)); y1 = fz_toreal(fz_arrayget(obj, 3)); for (i=0; i < fz_arraylen(obj) / 2; ++i) { c0[i] = fz_toreal(fz_arrayget(obj, i*2+4)); c1[i] = fz_toreal(fz_arrayget(obj, i*2+5)); } } else { error = fz_throw("syntaxerror: No Decode key in Type 6 Shade"); goto cleanup; } obj = fz_dictgets(shading, "Function"); if (obj) { ncomp = 1; pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]); shade->usefunction = 1; } else shade->usefunction = 0; shade->meshcap = 0; shade->mesh = nil; error = growshademesh(shade, 1024); if (error) goto cleanup; n = 2 + shade->cs->n; j = 0; error = pdf_openstream(&stream, xref, fz_tonum(ref), fz_togen(ref)); if (error) goto cleanup; while (fz_peekbyte(stream) != EOF) { flag = getdata(stream, bpflag); for (i = 0; i < 16; ++i) { t = getdata(stream, bpcoord); p[i].x = x0 + (t * (x1 - x0) / (pow(2, bpcoord) - 1.)); t = getdata(stream, bpcoord); p[i].y = y0 + (t * (y1 - y0) / (pow(2, bpcoord) - 1.)); } for (i = 0; i < 4; ++i) { int k; for (k=0; k < ncomp; ++k) { t = getdata(stream, bpcomp); patch.color[i][k] = c0[k] + (t * (c1[k] - c0[k]) / (pow(2, bpcomp) - 1.0f)); } } patch.pole[0][0] = p[0]; patch.pole[0][1] = p[1]; patch.pole[0][2] = p[2]; patch.pole[0][3] = p[3]; patch.pole[1][3] = p[4]; patch.pole[2][3] = p[5]; patch.pole[3][3] = p[6]; patch.pole[3][2] = p[7]; patch.pole[3][1] = p[8]; patch.pole[3][0] = p[9]; patch.pole[2][0] = p[10]; patch.pole[1][0] = p[11]; patch.pole[1][1] = p[12]; patch.pole[1][2] = p[13]; patch.pole[2][2] = p[14]; patch.pole[2][1] = p[15]; j = drawpatch(patch, shade, j, ncomp, 0); } fz_dropstream(stream); shade->meshlen = j / n / 3; cleanup: return nil; }
fz_error * pdf_loadtype5shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref) { fz_error *error; fz_stream *stream; fz_obj *obj; int bpcoord; int bpcomp; int vpr, vpc; int ncomp; float x0, x1, y0, y1; float c0[FZ_MAXCOLORS]; float c1[FZ_MAXCOLORS]; int i, n, j; int p, q; unsigned int t; float *x, *y, *c[FZ_MAXCOLORS]; error = nil; ncomp = shade->cs->n; bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate")); bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent")); vpr = fz_toint(fz_dictgets(shading, "VerticesPerRow")); if (vpr < 2) { error = fz_throw("VerticesPerRow must be greater than or equal to 2"); goto cleanup; } obj = fz_dictgets(shading, "Decode"); if (fz_isarray(obj)) { pdf_logshade("decode array\n"); x0 = fz_toreal(fz_arrayget(obj, 0)); x1 = fz_toreal(fz_arrayget(obj, 1)); y0 = fz_toreal(fz_arrayget(obj, 2)); y1 = fz_toreal(fz_arrayget(obj, 3)); for (i=0; i < fz_arraylen(obj) / 2; ++i) { c0[i] = fz_toreal(fz_arrayget(obj, i*2+4)); c1[i] = fz_toreal(fz_arrayget(obj, i*2+5)); } } else { error = fz_throw("syntaxerror: No Decode key in Type 4 Shade"); goto cleanup; } obj = fz_dictgets(shading, "Function"); if (obj) { ncomp = 1; pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]); shade->usefunction = 1; } else shade->usefunction = 0; n = 2 + shade->cs->n; j = 0; #define BIGNUM 1024 x = fz_malloc(sizeof(float) * vpr * BIGNUM); y = fz_malloc(sizeof(float) * vpr * BIGNUM); for (i = 0; i < ncomp; ++i) { c[i] = fz_malloc(sizeof(float) * vpr * BIGNUM); } q = 0; error = pdf_openstream(&stream, xref, fz_tonum(ref), fz_togen(ref)); if (error) goto cleanup; while (fz_peekbyte(stream) != EOF) { for (p = 0; p < vpr; ++p) { int idx; idx = q * vpr + p; t = getdata(stream, bpcoord); x[idx] = x0 + (t * (x1 - x0) / ((float)pow(2, bpcoord) - 1)); t = getdata(stream, bpcoord); y[idx] = y0 + (t * (y1 - y0) / ((float)pow(2, bpcoord) - 1)); for (i=0; i < ncomp; ++i) { t = getdata(stream, bpcomp); c[i][idx] = c0[i] + (t * (c1[i] - c0[i]) / (float)(pow(2, bpcomp) - 1)); } } q++; } fz_dropstream(stream); #define ADD_VERTEX(idx) \ {\ int z;\ shade->mesh[j++] = x[idx];\ shade->mesh[j++] = y[idx];\ for (z = 0; z < shade->cs->n; ++z) {\ shade->mesh[j++] = c[z][idx];\ }\ }\ vpc = q; shade->meshcap = 0; shade->mesh = fz_malloc(sizeof(float) * 1024); if (!shade) { error = fz_outofmem; goto cleanup; } j = 0; for (p = 0; p < vpr-1; ++p) { for (q = 0; q < vpc-1; ++q) { ADD_VERTEX(q * vpr + p); ADD_VERTEX(q * vpr + p + 1); ADD_VERTEX((q + 1) * vpr + p + 1); ADD_VERTEX(q * vpr + p); ADD_VERTEX((q + 1) * vpr + p + 1); ADD_VERTEX((q + 1) * vpr + p); } } shade->meshlen = j / n / 3; fz_free(x); fz_free(y); for (i = 0; i < ncomp; ++i) { fz_free(c[i]); } cleanup: return nil; }
fz_error * pdf_loadtype4shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref) { fz_error *error; fz_obj *obj; int bpcoord; int bpcomp; int bpflag; int ncomp; float x0, x1, y0, y1; float c0[FZ_MAXCOLORS]; float c1[FZ_MAXCOLORS]; int i, z; int bitspervertex; int bytepervertex; fz_buffer *buf; int n; int j; float cval[16]; int flag; unsigned int t; float x, y; error = nil; ncomp = shade->cs->n; bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate")); bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent")); bpflag = fz_toint(fz_dictgets(shading, "BitsPerFlag")); obj = fz_dictgets(shading, "Decode"); if (fz_isarray(obj)) { pdf_logshade("decode array\n"); x0 = fz_toreal(fz_arrayget(obj, 0)); x1 = fz_toreal(fz_arrayget(obj, 1)); y0 = fz_toreal(fz_arrayget(obj, 2)); y1 = fz_toreal(fz_arrayget(obj, 3)); for (i=0; i < fz_arraylen(obj) / 2; ++i) { c0[i] = fz_toreal(fz_arrayget(obj, i*2+4)); c1[i] = fz_toreal(fz_arrayget(obj, i*2+5)); } } else { error = fz_throw("syntaxerror: No Decode key in Type 4 Shade"); goto cleanup; } obj = fz_dictgets(shading, "Function"); if (obj) { ncomp = 1; pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]); } bitspervertex = bpflag + bpcoord * 2 + bpcomp * ncomp; bytepervertex = (bitspervertex+7) / 8; error = pdf_loadstream(&buf, xref, fz_tonum(ref), fz_togen(ref)); if (error) goto cleanup; shade->usefunction = 0; n = 2 + shade->cs->n; j = 0; for (z = 0; z < (buf->ep - buf->bp) / bytepervertex; ++z) { flag = *buf->rp++; t = *buf->rp++; t = (t << 8) + *buf->rp++; t = (t << 8) + *buf->rp++; x = x0 + (t * (x1 - x0) / (pow(2, 24) - 1)); t = *buf->rp++; t = (t << 8) + *buf->rp++; t = (t << 8) + *buf->rp++; y = y0 + (t * (y1 - y0) / (pow(2, 24) - 1)); for (i=0; i < ncomp; ++i) { t = *buf->rp++; t = (t << 8) + *buf->rp++; } if (flag == 0) { j += n; } if (flag == 1 || flag == 2) { j += 3 * n; } } buf->rp = buf->bp; shade->mesh = (float*) malloc(sizeof(float) * j); /* 8, 24, 16 only */ j = 0; for (z = 0; z < (buf->ep - buf->bp) / bytepervertex; ++z) { flag = *buf->rp++; t = *buf->rp++; t = (t << 8) + *buf->rp++; t = (t << 8) + *buf->rp++; x = x0 + (t * (x1 - x0) / (pow(2, 24) - 1)); t = *buf->rp++; t = (t << 8) + *buf->rp++; t = (t << 8) + *buf->rp++; y = y0 + (t * (y1 - y0) / (pow(2, 24) - 1)); for (i=0; i < ncomp; ++i) { t = *buf->rp++; t = (t << 8) + *buf->rp++; cval[i] = t / (double)(pow(2, 16) - 1); } if (flag == 0) { shade->mesh[j++] = x; shade->mesh[j++] = y; for (i=0; i < ncomp; ++i) { shade->mesh[j++] = cval[i]; } } if (flag == 1) { memcpy(&(shade->mesh[j]), &(shade->mesh[j - 2 * n]), n * sizeof(float)); memcpy(&(shade->mesh[j + 1 * n]), &(shade->mesh[j - 1 * n]), n * sizeof(float)); j+= 2 * n; shade->mesh[j++] = x; shade->mesh[j++] = y; for (i=0; i < ncomp; ++i) { shade->mesh[j++] = cval[i]; } } if (flag == 2) { memcpy(&(shade->mesh[j]), &(shade->mesh[j - 3 * n]), n * sizeof(float)); memcpy(&(shade->mesh[j + 1 * n]), &(shade->mesh[j - 1 * n]), n * sizeof(float)); j+= 2 * n; shade->mesh[j++] = x; shade->mesh[j++] = y; for (i=0; i < ncomp; ++i) { shade->mesh[j++] = cval[i]; } } } shade->meshlen = j / n / 3; fz_dropbuffer(buf); cleanup: return nil; }