fz_rect fz_boundtextnode(fz_textnode *text, fz_matrix ctm) { fz_matrix trm; fz_rect bbox; fz_rect fbox; int i; if (text->len == 0) return fz_emptyrect; /* find bbox of glyph origins in ctm space */ bbox.x0 = bbox.x1 = text->els[0].x; bbox.y0 = bbox.y1 = text->els[0].y; for (i = 1; i < text->len; i++) { bbox.x0 = MIN(bbox.x0, text->els[i].x); bbox.y0 = MIN(bbox.y0, text->els[i].y); bbox.x1 = MAX(bbox.x1, text->els[i].x); bbox.y1 = MAX(bbox.y1, text->els[i].y); } bbox = fz_transformaabb(ctm, bbox); /* find bbox of font in trm * ctm space */ trm = fz_concat(text->trm, ctm); trm.e = 0; trm.f = 0; fbox.x0 = text->font->bbox.x0 * 0.001; fbox.y0 = text->font->bbox.y0 * 0.001; fbox.x1 = text->font->bbox.x1 * 0.001; fbox.y1 = text->font->bbox.y1 * 0.001; fbox = fz_transformaabb(trm, fbox); /* expand glyph origin bbox by font bbox */ bbox.x0 += fbox.x0; bbox.y0 += fbox.y0; bbox.x1 += fbox.x1; bbox.y1 += fbox.y1; return bbox; }
fz_rect fz_boundimagenode(fz_imagenode *node, fz_matrix ctm) { fz_rect bbox; bbox.x0 = 0; bbox.y0 = 0; bbox.x1 = 1; bbox.y1 = 1; return fz_transformaabb(ctm, bbox); }
void pdfmoz_drawpage(pdfmoz_t *moz, int pagenum) { page_t *page = moz->pages + pagenum; fz_error error; fz_matrix ctm; fz_rect bbox; if (page->image) return; ctm = pdfmoz_pagectm(moz, pagenum); bbox = fz_transformaabb(ctm, page->page->mediabox); error = fz_rendertree(&page->image, moz->rast, page->page->tree, ctm, fz_roundrect(bbox), 1); if (error) pdfmoz_error(moz, error); }
static void recalcScreenMediaBox(PDFContext* ctx) { fz_matrix ctm; fz_rect bbox; float h = ctx->page->mediabox.y1 - ctx->page->mediabox.y0; float w = ctx->page->mediabox.x1 - ctx->page->mediabox.x0; float x = ctx->page->mediabox.x0; float y = ctx->page->mediabox.x0; bbox.x0 = x; bbox.y0 = y; bbox.x1 = x; bbox.y1 = y; ctm = pdfViewctm(ctx); bbox.x1 += w; bbox.y1 += h; bbox = fz_transformaabb(ctm, bbox); screenMediaBox = bbox; //printf("sCMB (%g, %g) - (%g, %g)\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); }
static fz_pixmap* pdfRenderTile(PDFContext* ctx, int x, int y, int w, int h, bool transform = false) { fz_error *error; fz_matrix ctm; fz_rect bbox; bbox.x0 = x; bbox.y0 = y; bbox.x1 = x; bbox.y1 = y; ctm = pdfViewctm(ctx); if (transform) { bbox.x1 += w; bbox.y1 += h; bbox = fz_transformaabb(ctm, bbox); } else { bbox.x0 = x; bbox.y0 = y; bbox.x1 = bbox.x0 + w; bbox.y1 = bbox.y0 + h; } fz_irect ir = fz_roundrect(bbox); /*if (!transform) { ir.x1 = ir.x0 + w; ir.y1 = ir.y0 + h; }*/ fz_pixmap* pix = NULL; error = fz_rendertree(&pix, ctx->rast, ctx->page->tree, ctm, ir, 1); if (error) { return 0; } if (BKUser::options.pdfInvertColors) { unsigned int* s = (unsigned int*)pix->samples; unsigned int n = pix->w * pix->h; for (unsigned int i = 0; i < n; ++i) { *s = ~(*s); ++s; } } return pix; }
static void drawpnm(int pagenum, struct benchmark *loadtimes, struct benchmark *drawtimes) { fz_error error; fz_matrix ctm; fz_irect bbox; fz_pixmap *pix; char name[256]; char pnmhdr[256]; int i, x, y, w, h, b, bh; int fd = -1; long start; long end; long elapsed; fz_md5 digest; if (!drawpattern) fz_md5init(&digest); drawloadpage(pagenum, loadtimes); if (benchmark) gettime(&start); ctm = fz_identity(); ctm = fz_concat(ctm, fz_translate(0, -drawpage->mediabox.y1)); ctm = fz_concat(ctm, fz_scale(drawzoom, -drawzoom)); ctm = fz_concat(ctm, fz_rotate(drawrotate + drawpage->rotate)); bbox = fz_roundrect(fz_transformaabb(ctm, drawpage->mediabox)); w = bbox.x1 - bbox.x0; h = bbox.y1 - bbox.y0; bh = h / drawbands; if (drawpattern) { sprintf(name, drawpattern, drawcount++); fd = open(name, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd < 0) die(fz_throw("ioerror: could not open file '%s'", name)); sprintf(pnmhdr, "P6\n%d %d\n255\n", w, h); write(fd, pnmhdr, strlen(pnmhdr)); } error = fz_newpixmap(&pix, bbox.x0, bbox.y0, w, bh, 4); if (error) die(error); memset(pix->samples, 0xff, pix->h * pix->w * pix->n); for (b = 0; b < drawbands; b++) { if (drawbands > 1) fprintf(stderr, "drawing band %d / %d\n", b + 1, drawbands); error = fz_rendertreeover(drawgc, pix, drawpage->tree, ctm); if (error) die(error); if (drawpattern) { for (y = 0; y < pix->h; y++) { unsigned char *src = pix->samples + y * pix->w * 4; unsigned char *dst = src; for (x = 0; x < pix->w; x++) { dst[x * 3 + 0] = src[x * 4 + 1]; dst[x * 3 + 1] = src[x * 4 + 2]; dst[x * 3 + 2] = src[x * 4 + 3]; } write(fd, dst, pix->w * 3); memset(src, 0xff, pix->w * 4); } } if (!drawpattern) fz_md5update(&digest, pix->samples, pix->h * pix->w * 4); pix->y += bh; if (pix->y + pix->h > bbox.y1) pix->h = bbox.y1 - pix->y; } fz_droppixmap(pix); if (!drawpattern) { unsigned char buf[16]; fz_md5final(&digest, buf); for (i = 0; i < 16; i++) fprintf(stderr, "%02x", buf[i]); } if (drawpattern) close(fd); drawfreepage(); if (benchmark) { gettime(&end); elapsed = end - start; if (elapsed < drawtimes->min) { drawtimes->min = elapsed; drawtimes->minpage = pagenum; } if (elapsed > drawtimes->max) { drawtimes->max = elapsed; drawtimes->maxpage = pagenum; } drawtimes->avg += elapsed; drawtimes->pages++; fprintf(stderr, " time %.3fs", elapsed / 1000000.0); } fprintf(stderr, "\n"); }
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"); }
void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage) { char buf[256]; fz_error *error; fz_matrix ctm; fz_rect bbox; fz_obj *obj; if (loadpage) { wincursor(app, WAIT); if (app->page) pdf_droppage(app->page); app->page = nil; obj = pdf_getpageobject(app->pages, app->pageno - 1); error = pdf_loadpage(&app->page, app->xref, obj); if (error) pdfapp_error(app, error); sprintf(buf, "%s - %d/%d", app->doctitle, app->pageno, pdf_getpagecount(app->pages)); wintitle(app, buf); } if (drawpage) { wincursor(app, WAIT); if (app->image) fz_droppixmap(app->image); app->image = nil; ctm = pdfapp_viewctm(app); bbox = fz_transformaabb(ctm, app->page->mediabox); error = fz_rendertree(&app->image, app->rast, app->page->tree, ctm, fz_roundrect(bbox), 1); if (error) pdfapp_error(app, error); winconvert(app, app->image); } pdfapp_panview(app, app->panx, app->pany); if (app->shrinkwrap) { int w = app->image->w; int h = app->image->h; if (app->winw == w) app->panx = 0; if (app->winh == h) app->pany = 0; if (w > app->scrw * 90 / 100) w = app->scrw * 90 / 100; if (h > app->scrh * 90 / 100) h = app->scrh * 90 / 100; if (w != app->winw || h != app->winh) winresize(app, w, h); } winrepaint(app); wincursor(app, ARROW); }
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"); }
void drawpnm(int pagenum) { fz_error *error; fz_matrix ctm; fz_irect bbox; fz_pixmap *pix; char namebuf[256]; char buf[256]; int x, y, w, h, b, bh; int fd; drawloadpage(pagenum); ctm = fz_identity(); ctm = fz_concat(ctm, fz_translate(0, -drawpage->mediabox.y1)); ctm = fz_concat(ctm, fz_scale(drawzoom, -drawzoom)); ctm = fz_concat(ctm, fz_rotate(drawrotate + drawpage->rotate)); bbox = fz_roundrect(fz_transformaabb(ctm, drawpage->mediabox)); w = bbox.x1 - bbox.x0; h = bbox.y1 - bbox.y0; bh = h / drawbands; if (drawpattern) { sprintf(namebuf, drawpattern, drawcount++); fd = open(namebuf, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd < 0) die(fz_throw("ioerror: could not open file '%s'", namebuf)); } else fd = 1; sprintf(buf, "P6\n%d %d\n255\n", w, h); write(fd, buf, strlen(buf)); error = fz_newpixmap(&pix, bbox.x0, bbox.y0, w, bh, 4); if (error) die(error); memset(pix->samples, 0xff, pix->h * pix->w * pix->n); for (b = 0; b < drawbands; b++) { if (drawbands > 1) fprintf(stderr, "drawing band %d / %d\n", b + 1, drawbands); error = fz_rendertreeover(drawgc, pix, drawpage->tree, ctm); if (error) die(error); for (y = 0; y < pix->h; y++) { unsigned char *src = pix->samples + y * pix->w * 4; unsigned char *dst = src; for (x = 0; x < pix->w; x++) { dst[x * 3 + 0] = src[x * 4 + 1]; dst[x * 3 + 1] = src[x * 4 + 2]; dst[x * 3 + 2] = src[x * 4 + 3]; } write(fd, dst, pix->w * 3); memset(src, 0xff, pix->w * 4); } pix->y += bh; if (pix->y + pix->h > bbox.y1) pix->h = bbox.y1 - pix->y; } fz_droppixmap(pix); if (drawpattern) close(fd); drawfreepage(); }