diff options
-rw-r--r-- | Jamfile | 3 | ||||
-rw-r--r-- | include/fitz.h | 1 | ||||
-rw-r--r-- | include/fitz/colorspace.h | 15 | ||||
-rw-r--r-- | include/fitz/font.h | 4 | ||||
-rw-r--r-- | include/fitz/pixmap.h | 6 | ||||
-rw-r--r-- | include/fitz/render.h | 2 | ||||
-rw-r--r-- | include/fitz/tree.h | 12 | ||||
-rw-r--r-- | include/mupdf.h | 31 | ||||
-rw-r--r-- | mupdf/build.c | 18 | ||||
-rw-r--r-- | mupdf/font.c | 14 | ||||
-rw-r--r-- | mupdf/interpret.c | 119 | ||||
-rw-r--r-- | mupdf/page.c | 159 | ||||
-rw-r--r-- | mupdf/pagetree.c | 14 | ||||
-rw-r--r-- | mupdf/resources.c | 60 | ||||
-rw-r--r-- | render/pixmap.c | 6 | ||||
-rw-r--r-- | render/render.c | 65 | ||||
-rw-r--r-- | test/pdfrip.c | 105 | ||||
-rw-r--r-- | tree/colorspace.c | 34 | ||||
-rw-r--r-- | tree/debug.c | 6 | ||||
-rw-r--r-- | tree/font.c | 11 | ||||
-rw-r--r-- | tree/node2.c | 21 |
21 files changed, 518 insertions, 188 deletions
@@ -65,6 +65,7 @@ Library libfitz : # tree tree/cmap.c tree/font.c + tree/colorspace.c tree/tree.c tree/node1.c @@ -99,7 +100,9 @@ Library libmupdf : mupdf/cmap.c mupdf/font.c mupdf/fontfile.c + mupdf/colorspace.c mupdf/resources.c + mupdf/page.c mupdf/pagetree.c mupdf/build.c mupdf/interpret.c diff --git a/include/fitz.h b/include/fitz.h index 30f37649..85ac8118 100644 --- a/include/fitz.h +++ b/include/fitz.h @@ -18,6 +18,7 @@ #include "fitz/cmap.h" #include "fitz/font.h" +#include "fitz/colorspace.h" #include "fitz/tree.h" #include "fitz/path.h" diff --git a/include/fitz/colorspace.h b/include/fitz/colorspace.h new file mode 100644 index 00000000..370c755f --- /dev/null +++ b/include/fitz/colorspace.h @@ -0,0 +1,15 @@ +typedef struct fz_colorspace_s fz_colorspace; + +struct fz_colorspace_s +{ + char name[16]; + int frozen; + int n; + void (*toxyz)(fz_colorspace *, float *src, float *xyz); + void (*fromxyz)(fz_colorspace *, float *xyz, float *dst); + void (*free)(fz_colorspace *); +}; + +void fz_freecolorspace(fz_colorspace *cs); +void fz_convertcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv); + diff --git a/include/fitz/font.h b/include/fitz/font.h index b915755b..d64c1fc3 100644 --- a/include/fitz/font.h +++ b/include/fitz/font.h @@ -37,9 +37,6 @@ struct fz_font_s int nvmtx, vmtxcap; fz_vmtx dvmtx; fz_vmtx *vmtx; - - int ncidtogid; - unsigned short *cidtogid; }; struct fz_glyph_s @@ -53,7 +50,6 @@ void fz_freefont(fz_font *font); void fz_debugfont(fz_font *font); void fz_setfontwmode(fz_font *font, int wmode); void fz_setfontbbox(fz_font *font, int xmin, int ymin, int xmax, int ymax); -void fz_setcidtogid(fz_font *font, int n, unsigned short *map); void fz_setdefaulthmtx(fz_font *font, int w); void fz_setdefaultvmtx(fz_font *font, int y, int w); fz_error *fz_addhmtx(fz_font *font, int lo, int hi, int w); diff --git a/include/fitz/pixmap.h b/include/fitz/pixmap.h index 462b4ad6..f7bab833 100644 --- a/include/fitz/pixmap.h +++ b/include/fitz/pixmap.h @@ -1,16 +1,16 @@ typedef struct fz_pixmap_s fz_pixmap; -typedef struct fz_colorspace_s fz_colorspace; struct fz_pixmap_s { + fz_colorspace *cs; int x, y, w, h; int n, a; int stride; - fz_colorspace *cs; short *samples; }; -fz_error *fz_newpixmap(fz_pixmap **mapp, int x, int y, int w, int h, int n, int a); +fz_error *fz_newpixmap(fz_pixmap **mapp, fz_colorspace *cs, int x, int y, int w, int h, int n, int a); +fz_error *fz_convertpixmap(fz_pixmap **dstp, fz_pixmap *src, fz_colorspace *dstcs); void fz_debugpixmap(fz_pixmap *map); void fz_freepixmap(fz_pixmap *map); void fz_clearpixmap(fz_pixmap *map); diff --git a/include/fitz/render.h b/include/fitz/render.h index 09c439c2..7f4e08db 100644 --- a/include/fitz/render.h +++ b/include/fitz/render.h @@ -1,6 +1,6 @@ typedef struct fz_renderer_s fz_renderer; -fz_error *fz_newrenderer(fz_renderer **gcp); +fz_error *fz_newrenderer(fz_renderer **gcp, fz_colorspace *pcm); void fz_freerenderer(fz_renderer *gc); fz_error *fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm); diff --git a/include/fitz/tree.h b/include/fitz/tree.h index 4d6eb952..6578ab51 100644 --- a/include/fitz/tree.h +++ b/include/fitz/tree.h @@ -102,6 +102,7 @@ struct fz_masknode_s struct fz_blendnode_s { fz_node super; + fz_colorspace *cs; fz_blendkind mode; int isolated; int knockout; @@ -110,7 +111,9 @@ struct fz_blendnode_s struct fz_colornode_s { fz_node super; - float r, g, b; + fz_colorspace *cs; + int n; + float samples[]; }; struct fz_linknode_s @@ -128,6 +131,7 @@ struct fz_metanode_s struct fz_imagenode_s { fz_node super; + fz_colorspace *cs; int w, h, n, a; // XXX fz_image *image; }; @@ -141,7 +145,7 @@ void fz_freenode(fz_node *node); fz_error *fz_newmetanode(fz_node **nodep, fz_obj *info); fz_error *fz_newovernode(fz_node **nodep); fz_error *fz_newmasknode(fz_node **nodep); -fz_error *fz_newblendnode(fz_node **nodep, fz_blendkind b, int k, int i); +fz_error *fz_newblendnode(fz_node **nodep, fz_colorspace *cs, fz_blendkind b, int k, int i); fz_error *fz_newtransformnode(fz_node **nodep, fz_matrix m); int fz_istransformnode(fz_node *node); @@ -152,8 +156,8 @@ int fz_ismetanode(fz_node *node); /* leaf nodes */ fz_error *fz_newlinknode(fz_node **nodep, fz_tree *subtree); -fz_error *fz_newcolornode(fz_node **nodep, float r, float g, float b); -fz_error *fz_newimagenode(fz_node **nodep, int w, int h, int n, int a); +fz_error *fz_newcolornode(fz_node **nodep, fz_colorspace *cs, int n, float *v); +fz_error *fz_newimagenode(fz_node **nodep, fz_colorspace *cs, int w, int h, int n, int a); int fz_islinknode(fz_node *node); int fz_iscolornode(fz_node *node); diff --git a/include/mupdf.h b/include/mupdf.h index 2c423408..cd19e55b 100644 --- a/include/mupdf.h +++ b/include/mupdf.h @@ -131,10 +131,15 @@ fz_error *pdf_decryptpdf(pdf_xref *xref); * high-level semantic objects for resources and pages */ +extern fz_colorspace *pdf_devicegray; +extern fz_colorspace *pdf_devicergb; +extern fz_colorspace *pdf_devicecmyk; + typedef struct pdf_nametree_s pdf_nametree; typedef struct pdf_pagetree_s pdf_pagetree; typedef struct pdf_font_s pdf_font; typedef struct pdf_resources_s pdf_resources; +typedef struct pdf_page_s pdf_page; typedef struct pdf_gstate_s pdf_gstate; typedef struct pdf_csi_s pdf_csi; @@ -171,6 +176,8 @@ struct pdf_font_s /* Encoding (CMap) */ fz_cmap *encoding; + int ncidtogid; + unsigned short *cidtogid; /* Raw data for freetype */ char *filename; @@ -195,6 +202,14 @@ struct pdf_resources_s fz_obj *xform; }; +struct pdf_page_s +{ + fz_rect mediabox; + int rotate; + pdf_resources *rdb; + fz_tree *tree; +}; + struct pdf_gstate_s { /* path stroking */ @@ -206,8 +221,11 @@ struct pdf_gstate_s int dashlen; float dashlist[32]; - /* colors and colorspaces */ - struct { float r, g, b; } stroke, fill; + /* materials */ + fz_colorspace *strokecs; + float stroke[32]; + fz_colorspace *fillcs; + float fill[32]; /* text state */ float charspace; @@ -252,9 +270,15 @@ fz_obj *pdf_lookupnames(pdf_nametree *nt, char *name); /* pagetree.c */ fz_error *pdf_loadpagetree(pdf_pagetree **pp, pdf_xref *xref); +int pdf_getpagecount(pdf_pagetree *pages); +fz_obj *pdf_getpageobject(pdf_pagetree *pages, int p); void pdf_debugpagetree(pdf_pagetree *pages); void pdf_freepagetree(pdf_pagetree *pages); +/* page.c */ +fz_error *pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *ref); +void pdf_freepage(pdf_page *page); + /* cmap.c */ fz_error *pdf_parsecmap(fz_cmap **cmapp, fz_file *file); fz_error *pdf_loadembeddedcmap(fz_cmap **cmapp, pdf_xref *xref, fz_obj *stmref); @@ -271,6 +295,9 @@ fz_error *pdf_loadfontdescriptor(pdf_font *font, pdf_xref *xref, fz_obj *desc, c fz_error *pdf_loadfont(pdf_font **fontp, pdf_xref *xref, fz_obj *font); void pdf_freefont(pdf_font *font); +/* colorspace.c */ +fz_error *pdf_loadcolorspace(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj); + /* resources.c */ fz_error *pdf_loadresources(pdf_resources **rdbp, pdf_xref *xref, fz_obj *resdict); void pdf_freeresources(pdf_resources *rdb); diff --git a/mupdf/build.c b/mupdf/build.c index 0e65f6a4..5747b962 100644 --- a/mupdf/build.c +++ b/mupdf/build.c @@ -14,13 +14,11 @@ pdf_initgstate(pdf_gstate *gs) gs->dashlen = 0; memset(gs->dashlist, 0, sizeof(gs->dashlist)); - gs->stroke.r = 0; - gs->stroke.g = 0; - gs->stroke.b = 0; + gs->strokecs = pdf_devicegray; + gs->stroke[0] = 0; - gs->fill.r = 0; - gs->fill.g = 0; - gs->fill.b = 0; + gs->fillcs = pdf_devicegray; + gs->fill[0] = 0; gs->charspace = 0; gs->wordspace = 0; @@ -71,7 +69,7 @@ pdf_buildfillpath(pdf_gstate *gs, fz_pathnode *path, int eofill) } static fz_error * -addcolorshape(pdf_gstate *gs, fz_node *shape, float r, float g, float b) +addcolorshape(pdf_gstate *gs, fz_node *shape, fz_colorspace *cs, float *v) { fz_error *error; fz_node *mask; @@ -80,7 +78,7 @@ addcolorshape(pdf_gstate *gs, fz_node *shape, float r, float g, float b) error = fz_newmasknode(&mask); if (error) return error; - error = fz_newcolornode(&solid, r, g, b); + error = fz_newcolornode(&solid, cs, cs->n, v); if (error) return error; fz_insertnode(mask, shape); @@ -93,13 +91,13 @@ addcolorshape(pdf_gstate *gs, fz_node *shape, float r, float g, float b) fz_error * pdf_addfillshape(pdf_gstate *gs, fz_node *shape) { - return addcolorshape(gs, shape, gs->fill.r, gs->fill.g, gs->fill.b); + return addcolorshape(gs, shape, gs->fillcs, gs->fill); } fz_error * pdf_addstrokeshape(pdf_gstate *gs, fz_node *shape) { - return addcolorshape(gs, shape, gs->stroke.r, gs->stroke.g, gs->stroke.b); + return addcolorshape(gs, shape, gs->strokecs, gs->stroke); } fz_error * diff --git a/mupdf/font.c b/mupdf/font.c index 5ee65f4f..3835a3b8 100644 --- a/mupdf/font.c +++ b/mupdf/font.c @@ -28,8 +28,8 @@ printf(" type %s\n", kind); static int ftwidth(pdf_font *font, int cid) { int e; - if (font->super.cidtogid) - cid = font->super.cidtogid[cid]; + if (font->cidtogid) + cid = font->cidtogid[cid]; e = FT_Load_Glyph(font->ftface, cid, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); if (e) @@ -47,8 +47,8 @@ ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) FT_Error fterr; int gid; - if (fzfont->cidtogid) - gid = fzfont->cidtogid[cid]; + if (font->cidtogid) + gid = font->cidtogid[cid]; else gid = cid; @@ -415,7 +415,8 @@ printf(" builtin encoding\n"); if (error) goto cleanup; - fz_setcidtogid((fz_font*)font, 256, etable); + font->ncidtogid = 256; + font->cidtogid = etable; /* * Widths @@ -613,7 +614,8 @@ printf(" cidtogidmap %d\n", len / 2); for (i = 0; i < len; i++) map[i] = (buf->rp[i * 2] << 8) + buf->rp[i * 2 + 1]; - fz_setcidtogid((fz_font*)font, len, map); + font->ncidtogid = len; + font->cidtogid = map; fz_freebuffer(buf); } diff --git a/mupdf/interpret.c b/mupdf/interpret.c index ab3b1ea5..14aae160 100644 --- a/mupdf/interpret.c +++ b/mupdf/interpret.c @@ -50,8 +50,8 @@ pdf_newcsi(pdf_csi **csip) csi->tree->root = node; csi->gstate[0].head = node; - error = fz_newcolornode(&node, 1, 1, 1); - fz_insertnode(csi->tree->root, node); +// error = fz_newcolornode(&node, pdf_devicegray, 1); +// fz_insertnode(csi->tree->root, node); csi->clip = nil; @@ -145,6 +145,7 @@ runkeyword(pdf_csi *csi, pdf_resources *rdb, char *buf) float a, b, c, d, e, f; float x, y, w, h; fz_matrix m; + int i; if (strlen(buf) > 1) { @@ -282,22 +283,88 @@ runkeyword(pdf_csi *csi, pdf_resources *rdb, char *buf) if (error) return error; } + else if (!strcmp(buf, "cs")) + { + fz_obj *obj; + + if (csi->top != 1) + goto syntaxerror; + + obj = csi->stack[0]; + + if (!strcmp(fz_toname(obj), "DeviceGray")) + gstate->fillcs = pdf_devicegray; + else if (!strcmp(fz_toname(obj), "DeviceRGB")) + gstate->fillcs = pdf_devicergb; + else if (!strcmp(fz_toname(obj), "DeviceCMYK")) + gstate->fillcs = pdf_devicecmyk; + else + { + obj = fz_dictget(rdb->colorspace, obj); + if (!obj) + return fz_throw("syntaxerror: missing resource"); + gstate->fillcs = fz_topointer(obj); + } + } + + else if (!strcmp(buf, "CS")) + { + fz_obj *obj; + + if (csi->top != 1) + goto syntaxerror; + + obj = csi->stack[0]; + + if (!strcmp(fz_toname(obj), "DeviceGray")) + gstate->strokecs = pdf_devicegray; + else if (!strcmp(fz_toname(obj), "DeviceRGB")) + gstate->strokecs = pdf_devicergb; + else if (!strcmp(fz_toname(obj), "DeviceCMYK")) + gstate->strokecs = pdf_devicecmyk; + else + { + obj = fz_dictget(rdb->colorspace, obj); + if (!obj) + return fz_throw("syntaxerror: missing resource"); + gstate->strokecs = fz_topointer(obj); + } + } + + else if (!strcmp(buf, "sc")) + { + if (csi->top != gstate->fillcs->n) + goto syntaxerror; + for (i = 0; i < csi->top; i++) + gstate->fill[i] = fz_toreal(csi->stack[i]); + } + + else if (!strcmp(buf, "SC")) + { + if (csi->top != gstate->strokecs->n) + goto syntaxerror; + for (i = 0; i < csi->top; i++) + gstate->stroke[i] = fz_toreal(csi->stack[i]); + } + else if (!strcmp(buf, "rg")) { if (csi->top != 3) goto syntaxerror; - gstate->fill.r = fz_toreal(csi->stack[0]); - gstate->fill.g = fz_toreal(csi->stack[1]); - gstate->fill.b = fz_toreal(csi->stack[2]); + gstate->fillcs = pdf_devicergb; + gstate->fill[0] = fz_toreal(csi->stack[0]); + gstate->fill[1] = fz_toreal(csi->stack[1]); + gstate->fill[2] = fz_toreal(csi->stack[2]); } else if (!strcmp(buf, "RG")) { if (csi->top != 3) goto syntaxerror; - gstate->stroke.r = fz_toreal(csi->stack[0]); - gstate->stroke.g = fz_toreal(csi->stack[1]); - gstate->stroke.b = fz_toreal(csi->stack[2]); + gstate->strokecs = pdf_devicergb; + gstate->stroke[0] = fz_toreal(csi->stack[0]); + gstate->stroke[1] = fz_toreal(csi->stack[1]); + gstate->stroke[2] = fz_toreal(csi->stack[2]); } else if (!strcmp(buf, "BT")) @@ -615,43 +682,35 @@ fprintf(stderr, "syntaxerror: unknown keyword '%s'\n", buf); case 'g': if (csi->top != 1) goto syntaxerror; - a = fz_toreal(csi->stack[0]); - gstate->fill.r = a; - gstate->fill.g = a; - gstate->fill.b = a; + gstate->fillcs = pdf_devicegray; + gstate->fill[0] = fz_toreal(csi->stack[0]); break; case 'G': if (csi->top != 1) goto syntaxerror; - a = fz_toreal(csi->stack[0]); - gstate->stroke.r = a; - gstate->stroke.g = a; - gstate->stroke.b = a; + gstate->strokecs = pdf_devicegray; + gstate->stroke[0] = fz_toreal(csi->stack[0]); break; case 'k': if (csi->top != 4) goto syntaxerror; - a = fz_toreal(csi->stack[0]); - b = fz_toreal(csi->stack[1]); - c = fz_toreal(csi->stack[2]); - d = fz_toreal(csi->stack[3]); - gstate->fill.r = 1.0 - MIN(1.0, a + d); - gstate->fill.g = 1.0 - MIN(1.0, b + d); - gstate->fill.b = 1.0 - MIN(1.0, c + d); + gstate->fillcs = pdf_devicecmyk; + gstate->fill[0] = fz_toreal(csi->stack[0]); + gstate->fill[1] = fz_toreal(csi->stack[1]); + gstate->fill[2] = fz_toreal(csi->stack[2]); + gstate->fill[3] = fz_toreal(csi->stack[3]); break; case 'K': if (csi->top != 4) goto syntaxerror; - a = fz_toreal(csi->stack[0]); - b = fz_toreal(csi->stack[1]); - c = fz_toreal(csi->stack[2]); - d = fz_toreal(csi->stack[3]); - gstate->stroke.r = 1.0 - MIN(1.0, a + d); - gstate->stroke.g = 1.0 - MIN(1.0, b + d); - gstate->stroke.b = 1.0 - MIN(1.0, c + d); + gstate->strokecs = pdf_devicecmyk; + gstate->stroke[0] = fz_toreal(csi->stack[0]); + gstate->stroke[1] = fz_toreal(csi->stack[1]); + gstate->stroke[2] = fz_toreal(csi->stack[2]); + gstate->stroke[3] = fz_toreal(csi->stack[3]); break; case '\'': diff --git a/mupdf/page.c b/mupdf/page.c new file mode 100644 index 00000000..4450ae8d --- /dev/null +++ b/mupdf/page.c @@ -0,0 +1,159 @@ +#include <fitz.h> +#include <mupdf.h> + +static fz_error * +runcsi(pdf_xref *xref, pdf_csi *csi, pdf_resources *rdb, fz_obj *stmref) +{ + fz_error *error; + + error = pdf_openstream(xref, fz_tonum(stmref), fz_togen(stmref)); + if (error) + return error; + + error = pdf_runcsi(csi, rdb, xref->stream); + + pdf_closestream(xref); + + return error; +} + +static fz_error * +loadpagecontents(fz_tree **treep, pdf_xref *xref, pdf_resources *rdb, fz_obj *ref) +{ + fz_error *error; + fz_obj *obj; + pdf_csi *csi; + int i; + + error = pdf_newcsi(&csi); + if (error) + return error; + + if (fz_isindirect(ref)) + { + error = pdf_loadindirect(&obj, xref, ref); + if (error) + return error; + + if (fz_isarray(obj)) + { + for (i = 0; i < fz_arraylen(obj); i++) + { + error = runcsi(xref, csi, rdb, fz_arrayget(obj, i)); + if (error) { + fz_dropobj(obj); + goto cleanup; + } + } + } + else + { + error = runcsi(xref, csi, rdb, ref); + if (error) { + fz_dropobj(obj); + goto cleanup; + } + } + + fz_dropobj(obj); + } + + else if (fz_isarray(ref)) + { + for (i = 0; i < fz_arraylen(ref); i++) + { + error = runcsi(xref, csi, rdb, fz_arrayget(ref, i)); + if (error) + goto cleanup; + } + } + + *treep = csi->tree; + csi->tree = nil; + error = nil; + +cleanup: + pdf_freecsi(csi); + return error; +} + +fz_error * +pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) +{ + fz_error *error; + fz_obj *obj; + pdf_page *page; + pdf_resources *rdb; + fz_tree *tree; + fz_rect bbox; + int rotate; + + obj = fz_dictgets(dict, "MediaBox"); + if (!fz_isarray(obj)) + return fz_throw("syntaxerror: Page missing MediaBox"); + bbox.min.x = fz_toint(fz_arrayget(obj, 0)); + bbox.min.y = fz_toint(fz_arrayget(obj, 1)); + bbox.max.x = fz_toint(fz_arrayget(obj, 2)); + bbox.max.y = fz_toint(fz_arrayget(obj, 3)); + + obj = fz_dictgets(dict, "Rotate"); + if (fz_isint(obj)) + rotate = fz_toint(obj); + else + rotate = 0; + + /* + * Load resources + */ + + obj = fz_dictgets(dict, "Resources"); + if (!obj) + return fz_throw("syntaxerror: Page missing Resources"); + error = pdf_resolve(&obj, xref); + if (error) return error; + error = pdf_loadresources(&rdb, xref, obj); + fz_dropobj(obj); + if (error) return error; + + /* + * Interpret content stream to build display tree + */ + + obj = fz_dictgets(dict, "Contents"); + + error = loadpagecontents(&tree, xref, rdb, obj); + if (error) { + pdf_freeresources(rdb); + return error; + } + + /* + * Create page object + */ + + page = *pagep = fz_malloc(sizeof(pdf_page)); + if (!page) { + fz_droptree(tree); + pdf_freeresources(rdb); + return fz_outofmem; + } + + page->mediabox.min.x = MIN(bbox.min.x, bbox.max.x); + page->mediabox.min.y = MIN(bbox.min.y, bbox.max.y); + page->mediabox.max.x = MAX(bbox.min.x, bbox.max.x); + page->mediabox.max.y = MAX(bbox.min.y, bbox.max.y); + page->rotate = rotate; + page->rdb = rdb; + page->tree = tree; + + return nil; +} + +void +pdf_freepage(pdf_page *page) +{ + pdf_freeresources(page->rdb); + fz_droptree(page->tree); + fz_free(page); +} + diff --git a/mupdf/pagetree.c b/mupdf/pagetree.c index 18d07e41..9f6195e6 100644 --- a/mupdf/pagetree.c +++ b/mupdf/pagetree.c @@ -157,6 +157,20 @@ error: return nil; } +int +pdf_getpagecount(pdf_pagetree *pages) +{ + return pages->count; +} + +fz_obj * +pdf_getpageobject(pdf_pagetree *pages, int p) +{ + if (p < 0 || p >= pages->count) + return nil; + return pages->pobj[p]; +} + void pdf_freepagetree(pdf_pagetree *pages) { diff --git a/mupdf/resources.c b/mupdf/resources.c index 487f8713..ef2515a2 100644 --- a/mupdf/resources.c +++ b/mupdf/resources.c @@ -121,6 +121,51 @@ cleanup: return err; } +static fz_error * +loadcolorspaces(pdf_resources *rdb, pdf_xref *xref, fz_obj *dict) +{ + fz_error *err; + fz_colorspace *colorspace; + fz_obj *key, *val; + fz_obj *ptr; + int i; + + for (i = 0; i < fz_dictlen(dict); i++) + { + colorspace = nil; + ptr = nil; + + key = fz_dictgetkey(dict, i); + val = fz_dictgetval(dict, i); + + err = pdf_resolve(&val, xref); + if (err) return err; + + err = pdf_loadcolorspace(&colorspace, xref, val); + if (err) goto cleanup; + +printf(" -> %s\n", colorspace->name); + + err = fz_newpointer(&ptr, colorspace); + if (err) goto cleanup; + + err = fz_dictput(rdb->colorspace, key, ptr); + if (err) goto cleanup; + + fz_dropobj(ptr); + fz_dropobj(val); + colorspace = nil; + } + + return nil; + +cleanup: + if (colorspace) fz_freecolorspace(colorspace); + if (ptr) fz_dropobj(ptr); + fz_dropobj(val); + return err; +} + fz_error * pdf_loadresources(pdf_resources **rdbp, pdf_xref *xref, fz_obj *topdict) { @@ -167,13 +212,26 @@ pdf_loadresources(pdf_resources **rdbp, pdf_xref *xref, fz_obj *topdict) if (err) { pdf_freeresources(rdb); return err; } } + err = fz_newdict(&rdb->colorspace, 5); + if (err) { pdf_freeresources(rdb); return err; } + + subdict = fz_dictgets(topdict, "ColorSpace"); + if (subdict) + { + err = pdf_resolve(&subdict, xref); + if (err) { pdf_freeresources(rdb); return err; } + err = loadcolorspaces(rdb, xref, subdict); + fz_dropobj(subdict); + if (err) { pdf_freeresources(rdb); return err; } + } + return nil; } void pdf_freeresources(pdf_resources *rdb) { - /* TODO freefont */ + /* TODO freefont and freecolorspace */ if (rdb->extgstate) fz_dropobj(rdb->extgstate); if (rdb->colorspace) fz_dropobj(rdb->colorspace); if (rdb->font) fz_dropobj(rdb->font); diff --git a/render/pixmap.c b/render/pixmap.c index 0902c901..5dd8bcda 100644 --- a/render/pixmap.c +++ b/render/pixmap.c @@ -1,7 +1,7 @@ #include <fitz.h> fz_error * -fz_newpixmap(fz_pixmap **pixp, int x, int y, int w, int h, int n, int a) +fz_newpixmap(fz_pixmap **pixp, fz_colorspace *cs, int x, int y, int w, int h, int n, int a) { fz_pixmap *pix; @@ -9,13 +9,13 @@ fz_newpixmap(fz_pixmap **pixp, int x, int y, int w, int h, int n, int a) if (!pix) return fz_outofmem; + pix->cs = cs; pix->x = x; pix->y = y; pix->w = w; pix->h = h; pix->n = n; pix->a = a; - pix->cs = nil; pix->stride = (pix->n + pix->a) * pix->w; pix->samples = fz_malloc(sizeof(short) * pix->stride * pix->h); @@ -83,7 +83,7 @@ fz_debugpixmap(fz_pixmap *pix) void fz_blendover(fz_pixmap *src, fz_pixmap *dst) { - int x, y, k; + int x, y; assert(dst->n == src->n); assert(dst->a == 1); diff --git a/render/render.c b/render/render.c index 183672bf..fab6262d 100644 --- a/render/render.c +++ b/render/render.c @@ -4,6 +4,7 @@ enum { NONE, OVER, MASK }; struct fz_renderer_s { + fz_colorspace *model; fz_glyphcache *cache; fz_gel *gel; fz_ael *ael; @@ -15,7 +16,7 @@ struct fz_renderer_s }; fz_error * -fz_newrenderer(fz_renderer **gcp) +fz_newrenderer(fz_renderer **gcp, fz_colorspace *processcolormodel) { fz_error *error; fz_renderer *gc; @@ -24,6 +25,7 @@ fz_newrenderer(fz_renderer **gcp) if (!gc) return fz_outofmem; + gc->model = processcolormodel; gc->cache = nil; gc->gel = nil; gc->ael = nil; @@ -97,7 +99,7 @@ static void blitglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo) } } -static void blitcolorglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo, short r, short g, short b) +static void blitcolorglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo, fz_renderer *gc) { int sx, sy, dx, dy, sa, ssa; short *p; @@ -118,9 +120,9 @@ static void blitcolorglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo, short r ssa = (1 << 14) - sa; p = out->samples + dx * 4 + dy * out->stride; - p[0] = ((r * sa) >> 14) + ((p[0] * ssa) >> 14); - p[1] = ((g * sa) >> 14) + ((p[1] * ssa) >> 14); - p[2] = ((b * sa) >> 14) + ((p[2] * ssa) >> 14); + p[0] = ((gc->r * sa) >> 14) + ((p[0] * ssa) >> 14); + p[1] = ((gc->g * sa) >> 14) + ((p[1] * ssa) >> 14); + p[2] = ((gc->b * sa) >> 14) + ((p[2] * ssa) >> 14); p[3] = sa + ((ssa * p[3]) >> 14); } } @@ -137,7 +139,7 @@ fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm) puts("render text"); - error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, 0, 1); + error = fz_newpixmap(&gc->tmp, nil, gc->x, gc->y, gc->w, gc->h, 0, 1); if (error) return error; @@ -177,12 +179,14 @@ rcolortext(fz_renderer *gc, fz_textnode *text, fz_colornode *color, fz_matrix ct float x, y; int g, i, ix, iy; fz_matrix tm, trm; + float rgb[3]; puts("render (mask color text)"); - gc->r = color->r * (1 << 14); - gc->g = color->g * (1 << 14); - gc->b = color->b * (1 << 14); + fz_convertcolor(color->cs, color->samples, gc->model, rgb); + gc->r = rgb[0] * (1 << 14); + gc->g = rgb[1] * (1 << 14); + gc->b = rgb[2] * (1 << 14); tm = text->trm; @@ -206,7 +210,7 @@ puts("render (mask color text)"); if (error) return error; - blitcolorglyph(gc->acc, &gl, ix, iy, gc->r, gc->g, gc->b); + blitcolorglyph(gc->acc, &gl, ix, iy, gc); } return nil; @@ -255,7 +259,7 @@ puts("render path"); fz_sortgel(gc->gel); - error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, 0, 1); + error = fz_newpixmap(&gc->tmp, nil, gc->x, gc->y, gc->w, gc->h, 0, 1); if (error) return error; @@ -270,9 +274,6 @@ static void blitcolorspan(int y, int x, int n, short *list, void *userdata) { fz_renderer *gc = userdata; fz_pixmap *pix = gc->acc; - short r = gc->r; - short g = gc->g; - short b = gc->b; short *p; short d, sa, ssa; @@ -289,9 +290,9 @@ static void blitcolorspan(int y, int x, int n, short *list, void *userdata) sa = d * 64; ssa = (1 << 14) - sa; - p[0] = ((r * sa) >> 14) + ((p[0] * ssa) >> 14); - p[1] = ((g * sa) >> 14) + ((p[1] * ssa) >> 14); - p[2] = ((b * sa) >> 14) + ((p[2] * ssa) >> 14); + p[0] = ((gc->r * sa) >> 14) + ((p[0] * ssa) >> 14); + p[1] = ((gc->g * sa) >> 14) + ((p[1] * ssa) >> 14); + p[2] = ((gc->b * sa) >> 14) + ((p[2] * ssa) >> 14); p[3] = sa + ((ssa * p[3]) >> 14); p += 4; @@ -301,6 +302,8 @@ static void blitcolorspan(int y, int x, int n, short *list, void *userdata) static fz_error * rcolorpath(fz_renderer *gc, fz_pathnode *path, fz_colornode *color, fz_matrix ctm) { + float rgb[3]; + puts("render (mask color path)"); float flatness = 0.3 / ctm.a; @@ -319,9 +322,10 @@ puts("render (mask color path)"); fz_sortgel(gc->gel); - gc->r = color->r * (1 << 14); - gc->g = color->g * (1 << 14); - gc->b = color->b * (1 << 14); + fz_convertcolor(color->cs, color->samples, gc->model, rgb); + gc->r = rgb[0] * (1 << 14); + gc->g = rgb[1] * (1 << 14); + gc->b = rgb[2] * (1 << 14); fz_scanconvert(gc->gel, gc->ael, path->paint == FZ_EOFILL, blitcolorspan, gc); @@ -332,14 +336,17 @@ fz_error * fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm) { fz_error *error; - short r = color->r * (1 << 14); - short g = color->g * (1 << 14); - short b = color->b * (1 << 14); int x, y; + float rgb[3]; + + fz_convertcolor(color->cs, color->samples, gc->model, rgb); + gc->r = rgb[0] * (1 << 14); + gc->g = rgb[1] * (1 << 14); + gc->b = rgb[2] * (1 << 14); puts("render color"); - error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, 3, 1); + error = fz_newpixmap(&gc->tmp, color->cs, gc->x, gc->y, gc->w, gc->h, 3, 1); if (error) return error; @@ -348,9 +355,9 @@ puts("render color"); short *p = &gc->tmp->samples[y * gc->tmp->stride]; for (x = 0; x < gc->tmp->w; x++) { - *p++ = r; - *p++ = g; - *p++ = b; + *p++ = gc->r; + *p++ = gc->g; + *p++ = gc->b; *p++ = 1 << 14; } } @@ -398,7 +405,7 @@ fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm) { puts("render over"); oldacc = gc->acc; - error = fz_newpixmap(&gc->acc, gc->x, gc->y, gc->w, gc->h, 3, 1); + error = fz_newpixmap(&gc->acc, gc->model, gc->x, gc->y, gc->w, gc->h, 3, 1); if (error) return error; fz_clearpixmap(gc->acc); @@ -465,7 +472,7 @@ fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm) return error; shapepix = gc->tmp; - error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, colorpix->n, 1); + error = fz_newpixmap(&gc->tmp, colorpix->cs, gc->x, gc->y, gc->w, gc->h, colorpix->n, 1); if (error) return error; diff --git a/test/pdfrip.c b/test/pdfrip.c index f0785055..f7cbc093 100644 --- a/test/pdfrip.c +++ b/test/pdfrip.c @@ -13,95 +13,54 @@ void usage() * Draw page */ -void runcsi(pdf_xref *xref, pdf_csi *csi, pdf_resources *rdb, fz_obj *stmref) +void showpage(pdf_xref *xref, fz_obj *pageobj) { fz_error *error; + pdf_page *page; - error = pdf_openstream(xref, fz_tonum(stmref), fz_togen(stmref)); - if (error) fz_abort(error); - - error = pdf_runcsi(csi, rdb, xref->stream); - if (error) fz_abort(error); - - pdf_closestream(xref); -} - -void showpage(pdf_xref *xref, fz_obj *page) -{ - fz_error *error; - pdf_csi *csi; - pdf_resources *rdb = nil; - fz_obj *resources; - fz_obj *contents; - int i; - - fz_debugobj(page); + fz_debugobj(pageobj); printf("\n"); - resources = fz_dictgets(page, "Resources"); - if (resources) - { - error = pdf_resolve(&resources, xref); - if (error) fz_abort(error); - - error = pdf_loadresources(&rdb, xref, resources); - if (error) fz_abort(error); - - // parse resources into native res dict - fz_dropobj(resources); - } - else - fz_abort(fz_throw("syntaxerror: missing resource dictionary")); - - error = pdf_newcsi(&csi); - if (error) fz_abort(error); + error = pdf_loadpage(&page, xref, pageobj); + if (error) + fz_abort(error); - contents = fz_dictgets(page, "Contents"); - if (contents) + if (showtree) { - if (fz_isarray(contents)) - { - for (i = 0; i < fz_arraylen(contents); i++) - { - runcsi(xref, csi, rdb, fz_arrayget(contents, i)); - } - } - else - { - // XXX resolve and check if it is an array - runcsi(xref, csi, rdb, contents); - } - } + printf("page\n"); + printf(" mediabox [ %g %g %g %g ]\n", + page->mediabox.min.x, page->mediabox.min.y, + page->mediabox.max.x, page->mediabox.max.y); + printf(" rotate %d\n", page->rotate); + + printf(" fonts\n"); + fz_debugobj(page->rdb->font); + printf("\n"); + printf(" colorspaces\n"); + fz_debugobj(page->rdb->colorspace); + printf("\n"); - if (showtree) - { - printf("\nfitz tree:\n"); - fz_debugtree(csi->tree); + printf("tree\n"); + fz_debugtree(page->tree); + printf("endtree"); } { fz_pixmap *pix; fz_renderer *gc; fz_matrix ctm; - fz_rect bbox; - -#define SCALE 1.0 -#define W 700 -#define H 900 - fz_newrenderer(&gc); - - bbox.min.x = 0; - bbox.min.y = 0; - bbox.max.x = W * SCALE; - bbox.max.y = H * SCALE; + error = fz_newrenderer(&gc, pdf_devicergb); + if (error) fz_abort(error); - //ctm = fz_scale(SCALE,SCALE); - ctm = fz_concat(fz_translate(0, -H), fz_scale(SCALE,-SCALE)); + ctm = fz_concat(fz_translate(0, -page->mediabox.max.y), fz_scale(1.0, -1.0)); +printf("ctm %g %g %g %g %g %g\n", + ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f); printf("rendering!\n"); - fz_rendertree(&pix, gc, csi->tree, ctm, bbox); + error = fz_rendertree(&pix, gc, page->tree, ctm, page->mediabox); + if (error) fz_abort(error); printf("done!\n"); fz_debugpixmap(pix); @@ -109,8 +68,6 @@ printf("done!\n"); fz_freerenderer(gc); } - - pdf_freecsi(csi); } int main(int argc, char **argv) @@ -165,10 +122,10 @@ int main(int argc, char **argv) for ( ; optind < argc; optind++) { int page = atoi(argv[optind]); - if (page < 1 || page > pages->count) + if (page < 1 || page > pdf_getpagecount(pages)) fprintf(stderr, "page out of bounds: %d\n", page); printf("page %d\n", page); - showpage(xref, pages->pobj[page - 1]); + showpage(xref, pdf_getpageobject(pages, page - 1)); } pdf_closepdf(xref); diff --git a/tree/colorspace.c b/tree/colorspace.c new file mode 100644 index 00000000..6ff61d3e --- /dev/null +++ b/tree/colorspace.c @@ -0,0 +1,34 @@ +#include <fitz.h> + +void +fz_freecolorspace(fz_colorspace *cs) +{ + if (cs->frozen) + return; + if (cs->free) + cs->free(cs); + fz_free(cs); +} + +void +fz_convertcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv) +{ + float xyz[3]; + int i; + if (srcs != dsts) + { +printf("convert color from %s to %s\n ", srcs->name, dsts->name); +for(i=0;i<srcs->n;i++)printf("%g ", srcv[i]);printf("\n"); + srcs->toxyz(srcs, srcv, xyz); +printf(" %g %g %g\n ", xyz[0], xyz[1], xyz[2]); + dsts->fromxyz(dsts, xyz, dstv); +for(i=0;i<dsts->n;i++)printf("%g ", dstv[i]);printf("\n"); + } + else + { + int i; + for (i = 0; i < srcs->n; i++) + dstv[i] = srcv[i]; + } +} + diff --git a/tree/debug.c b/tree/debug.c index c56464ba..583608f5 100644 --- a/tree/debug.c +++ b/tree/debug.c @@ -68,8 +68,12 @@ static void lisptransform(fz_transformnode *node, int level) static void lispcolor(fz_colornode *node, int level) { + int i; indent(level); - printf("(color %g %g %g)\n", node->r, node->g, node->b); + printf("(color "); + for (i = 0; i < node->n; i++) + printf("%g ", node->samples[i]); + printf(")\n"); } static void lisplink(fz_linknode *node, int level) diff --git a/tree/font.c b/tree/font.c index 207896c5..a8ac016c 100644 --- a/tree/font.c +++ b/tree/font.c @@ -28,9 +28,6 @@ fz_initfont(fz_font *font, char *name) font->dvmtx.x = 0; font->dvmtx.y = 880; font->dvmtx.w = -1000; - - font->ncidtogid = 0; - font->cidtogid = nil; } void @@ -49,13 +46,6 @@ fz_setfontbbox(fz_font *font, int xmin, int ymin, int xmax, int ymax) } void -fz_setcidtogid(fz_font *font, int n, unsigned short *map) -{ - font->ncidtogid = n; - font->cidtogid = map; -} - -void fz_setdefaulthmtx(fz_font *font, int w) { font->dhmtx.w = w; @@ -251,7 +241,6 @@ fz_freefont(fz_font *font) { if (font->free) font->free(font); - fz_free(font->cidtogid); fz_free(font->hmtx); fz_free(font->vmtx); fz_free(font); diff --git a/tree/node2.c b/tree/node2.c index 0e173dbf..d50936ef 100644 --- a/tree/node2.c +++ b/tree/node2.c @@ -89,7 +89,7 @@ fz_boundmasknode(fz_masknode *node, fz_matrix ctm) */ fz_error * -fz_newblendnode(fz_node **nodep, fz_blendkind b, int k, int i) +fz_newblendnode(fz_node **nodep, fz_colorspace *cs, fz_blendkind b, int k, int i) { fz_blendnode *node; @@ -99,6 +99,7 @@ fz_newblendnode(fz_node **nodep, fz_blendkind b, int k, int i) *nodep = (fz_node*)node; fz_initnode((fz_node*)node, FZ_NBLEND); + node->cs = cs; node->mode = b; node->knockout = k; node->isolated = i; @@ -230,19 +231,21 @@ fz_boundlinknode(fz_linknode *node, fz_matrix ctm) */ fz_error * -fz_newcolornode(fz_node **nodep, float r, float g, float b) +fz_newcolornode(fz_node **nodep, fz_colorspace *cs, int n, float *v) { fz_colornode *node; + int i; - node = fz_malloc(sizeof (fz_colornode)); + node = fz_malloc(sizeof(fz_colornode) + sizeof(float) * n); if (!node) return fz_outofmem; *nodep = (fz_node*)node; fz_initnode((fz_node*)node, FZ_NCOLOR); - node->r = r; - node->g = g; - node->b = b; + node->cs = cs; + node->n = n; + for (i = 0; i < n; i++) + node->samples[i] = v[i]; return nil; } @@ -250,8 +253,7 @@ fz_newcolornode(fz_node **nodep, float r, float g, float b) fz_rect fz_boundcolornode(fz_colornode *node, fz_matrix ctm) { - /* min > max => no bounds */ - return (fz_rect) { {1,1}, {-1,-1} }; + return fz_infiniterect(); } /* @@ -259,7 +261,7 @@ fz_boundcolornode(fz_colornode *node, fz_matrix ctm) */ fz_error * -fz_newimagenode(fz_node **nodep, int w, int h, int n, int a) +fz_newimagenode(fz_node **nodep, fz_colorspace *cs, int w, int h, int n, int a) { fz_imagenode *node; @@ -269,6 +271,7 @@ fz_newimagenode(fz_node **nodep, int w, int h, int n, int a) *nodep = (fz_node*)node; fz_initnode((fz_node*)node, FZ_NIMAGE); + node->cs = cs; node->w = w; node->h = h; node->n = n; |