diff options
105 files changed, 8660 insertions, 6003 deletions
@@ -14,6 +14,8 @@ else ifeq "$(build)" "release" CFLAGS += -pipe -O2 -DNDEBUG -fomit-frame-pointer else ifeq "$(build)" "native" CFLAGS += -pipe -O2 -DNDEBUG -fomit-frame-pointer -march=native -mfpmath=sse +else ifeq "$(build)" "memento" +CFLAGS += -pipe -g -DMEMENTO else $(error unknown build setting: '$(build)') endif diff --git a/apps/pdfapp.c b/apps/pdfapp.c index 0ef61e2d..7dabd93e 100644 --- a/apps/pdfapp.c +++ b/apps/pdfapp.c @@ -68,12 +68,13 @@ char *pdfapp_usage(pdfapp_t *app) ; } -void pdfapp_init(pdfapp_t *app) +void pdfapp_init(fz_context *ctx, pdfapp_t *app) { memset(app, 0, sizeof(pdfapp_t)); app->scrw = 640; app->scrh = 480; app->resolution = 72; + app->ctx = ctx; } void pdfapp_invert(pdfapp_t *app, fz_bbox rect) @@ -99,20 +100,25 @@ void pdfapp_invert(pdfapp_t *app, fz_bbox rect) static void pdfapp_open_pdf(pdfapp_t *app, char *filename, int fd) { - fz_error error; fz_stream *file; char *password = ""; fz_obj *obj; fz_obj *info; + fz_context *ctx = app->ctx; /* * Open PDF and load xref table */ - file = fz_open_fd(fd); - error = pdf_open_xref_with_stream(&app->xref, file, NULL); - if (error) - pdfapp_error(app, fz_rethrow(error, "cannot open document '%s'", filename)); + file = fz_open_fd(ctx, fd); + fz_try(ctx) + { + app->xref = pdf_open_xref_with_stream(file, NULL); + } + fz_catch(ctx) + { + pdfapp_error(app, fz_error_note(1, "cannot open document '%s'", filename)); + } fz_close(file); /* @@ -144,7 +150,7 @@ static void pdfapp_open_pdf(pdfapp_t *app, char *filename, int fd) { obj = fz_dict_gets(info, "Title"); if (obj) - app->doctitle = pdf_to_utf8(obj); + app->doctitle = pdf_to_utf8(ctx, obj); } if (!app->doctitle) { @@ -153,32 +159,41 @@ static void pdfapp_open_pdf(pdfapp_t *app, char *filename, int fd) app->doctitle = strrchr(app->doctitle, '\\') + 1; if (strrchr(app->doctitle, '/')) app->doctitle = strrchr(app->doctitle, '/') + 1; - app->doctitle = fz_strdup(app->doctitle); + app->doctitle = fz_strdup(ctx, app->doctitle); } /* * Start at first page */ - error = pdf_load_page_tree(app->xref); - if (error) - pdfapp_error(app, fz_rethrow(error, "cannot load page tree")); + fz_try(ctx) + { + pdf_load_page_tree(app->xref); + } + fz_catch(ctx) + { + pdfapp_error(app, fz_error_note(1, "cannot load page tree")); + } app->pagecount = pdf_count_pages(app->xref); } static void pdfapp_open_xps(pdfapp_t *app, char *filename, int fd) { - fz_error error; fz_stream *file; - file = fz_open_fd(fd); - error = xps_open_stream(&app->xps, file); - if (error) - pdfapp_error(app, fz_rethrow(error, "cannot open document '%s'", filename)); + file = fz_open_fd(app->ctx, fd); + fz_try(app->ctx) + { + app->xps = xps_open_stream(file); + } + fz_catch(app->ctx) + { + pdfapp_error(app, fz_error_note(-1, "cannot open document '%s'", filename)); + } fz_close(file); - app->doctitle = fz_strdup(filename); + app->doctitle = fz_strdup(app->ctx, filename); app->pagecount = xps_count_pages(app->xps); } @@ -190,7 +205,7 @@ void pdfapp_open(pdfapp_t *app, char *filename, int fd, int reload) else pdfapp_open_pdf(app, filename, fd); - app->cache = fz_new_glyph_cache(); + app->cache = fz_new_glyph_cache(app->ctx); if (app->pageno < 1) app->pageno = 1; @@ -215,27 +230,27 @@ void pdfapp_open(pdfapp_t *app, char *filename, int fd, int reload) void pdfapp_close(pdfapp_t *app) { if (app->page_list) - fz_free_display_list(app->page_list); + fz_free_display_list(app->ctx, app->page_list); app->page_list = NULL; if (app->page_text) - fz_free_text_span(app->page_text); + fz_free_text_span(app->ctx, app->page_text); app->page_text = NULL; if (app->page_links) - pdf_free_link(app->page_links); + pdf_free_link(app->ctx, app->page_links); app->page_links = NULL; if (app->doctitle) - fz_free(app->doctitle); + fz_free(app->ctx, app->doctitle); app->doctitle = NULL; if (app->cache) - fz_free_glyph_cache(app->cache); + fz_free_glyph_cache(app->ctx, app->cache); app->cache = NULL; if (app->image) - fz_drop_pixmap(app->image); + fz_drop_pixmap(app->ctx, app->image); app->image = NULL; if (app->outline) @@ -245,7 +260,7 @@ void pdfapp_close(pdfapp_t *app) if (app->xref) { if (app->xref->store) - pdf_free_store(app->xref->store); + pdf_free_store(app->ctx, app->xref->store); app->xref->store = NULL; pdf_free_xref(app->xref); @@ -258,7 +273,7 @@ void pdfapp_close(pdfapp_t *app) app->xps = NULL; } - fz_flush_warnings(); + fz_flush_warnings(app->ctx); } static fz_matrix pdfapp_viewctm(pdfapp_t *app) @@ -301,12 +316,16 @@ static void pdfapp_panview(pdfapp_t *app, int newx, int newy) static void pdfapp_loadpage_pdf(pdfapp_t *app) { pdf_page *page; - fz_error error; fz_device *mdev; - error = pdf_load_page(&page, app->xref, app->pageno - 1); - if (error) - pdfapp_error(app, error); + fz_try(app->ctx) + { + page = pdf_load_page(app->xref, app->pageno - 1); + } + fz_catch(app->ctx) + { + pdfapp_error(app, 1); + } app->page_bbox = page->mediabox; app->page_rotate = page->rotate; @@ -314,30 +333,36 @@ static void pdfapp_loadpage_pdf(pdfapp_t *app) page->links = NULL; /* Create display list */ - app->page_list = fz_new_display_list(); - mdev = fz_new_list_device(app->page_list); - error = pdf_run_page(app->xref, page, mdev, fz_identity); - if (error) + app->page_list = fz_new_display_list(app->ctx); + mdev = fz_new_list_device(app->ctx, app->page_list); + fz_try(app->ctx) { - error = fz_rethrow(error, "cannot draw page %d in '%s'", app->pageno, app->doctitle); - pdfapp_error(app, error); + pdf_run_page(app->xref, page, mdev, fz_identity); + } + fz_catch(app->ctx) + { + pdfapp_error(app, fz_error_note(-1, "cannot draw page %d in '%s'", app->pageno, app->doctitle)); } fz_free_device(mdev); - pdf_free_page(page); + pdf_free_page(app->ctx, page); - pdf_age_store(app->xref->store, 3); + pdf_age_store(app->ctx, app->xref->store, 3); } static void pdfapp_loadpage_xps(pdfapp_t *app) { xps_page *page; fz_device *mdev; - fz_error error; - error = xps_load_page(&page, app->xps, app->pageno - 1); - if (error) - pdfapp_error(app, fz_rethrow(error, "cannot load page %d in file '%s'", app->pageno, app->doctitle)); + fz_try(app->ctx) + { + page = xps_load_page(app->xps, app->pageno - 1); + } + fz_catch(app->ctx) + { + pdfapp_error(app, fz_error_note(1, "cannot load page %d in file '%s'", app->pageno, app->doctitle)); + } app->page_bbox.x0 = 0; app->page_bbox.y0 = 0; @@ -347,8 +372,8 @@ static void pdfapp_loadpage_xps(pdfapp_t *app) app->page_links = NULL; /* Create display list */ - app->page_list = fz_new_display_list(); - mdev = fz_new_list_device(app->page_list); + app->page_list = fz_new_display_list(app->ctx); + mdev = fz_new_list_device(app->ctx, app->page_list); app->xps->dev = mdev; xps_parse_fixed_page(app->xps, fz_identity, page); app->xps->dev = NULL; @@ -371,11 +396,11 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai if (loadpage) { if (app->page_list) - fz_free_display_list(app->page_list); + fz_free_display_list(app->ctx, app->page_list); if (app->page_text) - fz_free_text_span(app->page_text); + fz_free_text_span(app->ctx, app->page_text); if (app->page_links) - pdf_free_link(app->page_links); + pdf_free_link(app->ctx, app->page_links); if (app->xref) pdfapp_loadpage_pdf(app); @@ -387,8 +412,8 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai app->hitlen = 0; /* Extract text */ - app->page_text = fz_new_text_span(); - tdev = fz_new_text_device(app->page_text); + app->page_text = fz_new_text_span(app->ctx); + tdev = fz_new_text_device(app->ctx, app->page_text); fz_execute_display_list(app->page_list, tdev, fz_identity, fz_infinite_bbox); fz_free_device(tdev); } @@ -404,7 +429,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai /* Draw */ if (app->image) - fz_drop_pixmap(app->image); + fz_drop_pixmap(app->ctx, app->image); if (app->grayscale) colorspace = fz_device_gray; else @@ -413,9 +438,9 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai #else colorspace = fz_device_rgb; #endif - app->image = fz_new_pixmap_with_rect(colorspace, bbox); + app->image = fz_new_pixmap_with_rect(app->ctx, colorspace, bbox); fz_clear_pixmap_with_color(app->image, 255); - idev = fz_new_draw_device(app->cache, app->image); + idev = fz_new_draw_device(app->ctx, app->cache, app->image); fz_execute_display_list(app->page_list, idev, ctm, bbox); fz_free_device(idev); } @@ -445,17 +470,18 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai wincursor(app, ARROW); } - fz_flush_warnings(); + fz_flush_warnings(app->ctx); } static void pdfapp_gotouri(pdfapp_t *app, fz_obj *uri) { char *buf; - buf = fz_malloc(fz_to_str_len(uri) + 1); - memcpy(buf, fz_to_str_buf(uri), fz_to_str_len(uri)); - buf[fz_to_str_len(uri)] = 0; + int n = fz_to_str_len(uri); + buf = fz_malloc(app->ctx, n + 1); + memcpy(buf, fz_to_str_buf(uri), n); + buf[n] = 0; winopenuri(app, buf); - fz_free(buf); + fz_free(app->ctx, buf); } static void pdfapp_gotopage(pdfapp_t *app, fz_obj *obj) diff --git a/apps/pdfapp.h b/apps/pdfapp.h index 270c450a..e617333d 100644 --- a/apps/pdfapp.h +++ b/apps/pdfapp.h @@ -32,7 +32,7 @@ struct pdfapp_s char *doctitle; pdf_xref *xref; fz_outline *outline; - xps_context *xps; + xps_document *xps; int pagecount; fz_glyph_cache *cache; @@ -88,9 +88,11 @@ struct pdfapp_s /* client context storage */ void *userdata; + + fz_context *ctx; }; -void pdfapp_init(pdfapp_t *app); +void pdfapp_init(fz_context *ctx, pdfapp_t *app); void pdfapp_open(pdfapp_t *app, char *filename, int fd, int reload); void pdfapp_close(pdfapp_t *app); diff --git a/apps/pdfclean.c b/apps/pdfclean.c index b436a9cb..2c492951 100644 --- a/apps/pdfclean.c +++ b/apps/pdfclean.c @@ -24,10 +24,11 @@ static int doexpand = 0; static int doascii = 0; static pdf_xref *xref = NULL; +static fz_context *ctx = NULL; void die(fz_error error) { - fz_catch(error, "aborting"); + fz_error_handle(error, "aborting"); if (xref) pdf_free_xref(xref); exit(1); @@ -61,12 +62,18 @@ static void sweepobj(fz_obj *obj) sweepref(obj); else if (fz_is_dict(obj)) - for (i = 0; i < fz_dict_len(obj); i++) + { + int n = fz_dict_len(obj); + for (i = 0; i < n; i++) sweepobj(fz_dict_get_val(obj, i)); + } else if (fz_is_array(obj)) - for (i = 0; i < fz_array_len(obj); i++) + { + int n = fz_array_len(obj); + for (i = 0; i < n; i++) sweepobj(fz_array_get(obj, i)); + } } static void sweepref(fz_obj *obj) @@ -176,16 +183,18 @@ static void compactxref(void) static void renumberobj(fz_obj *obj) { int i; + fz_context *ctx = xref->ctx; if (fz_is_dict(obj)) { - for (i = 0; i < fz_dict_len(obj); i++) + int n = fz_dict_len(obj); + for (i = 0; i < n; i++) { fz_obj *key = fz_dict_get_key(obj, i); fz_obj *val = fz_dict_get_val(obj, i); if (fz_is_indirect(val)) { - val = fz_new_indirect(renumbermap[fz_to_num(val)], 0, xref); + val = fz_new_indirect(ctx, renumbermap[fz_to_num(val)], 0, xref); fz_dict_put(obj, key, val); fz_drop_obj(val); } @@ -198,12 +207,13 @@ static void renumberobj(fz_obj *obj) else if (fz_is_array(obj)) { - for (i = 0; i < fz_array_len(obj); i++) + int n = fz_array_len(obj); + for (i = 0; i < n; i++) { fz_obj *val = fz_array_get(obj, i); if (fz_is_indirect(val)) { - val = fz_new_indirect(renumbermap[fz_to_num(val)], 0, xref); + val = fz_new_indirect(ctx, renumbermap[fz_to_num(val)], 0, xref); fz_array_put(obj, i, val); fz_drop_obj(val); } @@ -229,7 +239,7 @@ static void renumberobjs(void) if (fz_is_indirect(obj)) { - obj = fz_new_indirect(renumbermap[fz_to_num(obj)], 0, xref); + obj = fz_new_indirect(ctx, renumbermap[fz_to_num(obj)], 0, xref); pdf_update_object(xref, num, 0, obj); fz_drop_obj(obj); } @@ -241,7 +251,7 @@ static void renumberobjs(void) /* Create new table for the reordered, compacted xref */ oldxref = xref->table; - xref->table = fz_calloc(xref->len, sizeof(pdf_xref_entry)); + xref->table = fz_malloc_array(xref->ctx, xref->len, sizeof(pdf_xref_entry)); xref->table[0] = oldxref[0]; /* Move used objects into the new compacted xref */ @@ -261,7 +271,7 @@ static void renumberobjs(void) } } - fz_free(oldxref); + fz_free(xref->ctx, oldxref); /* Update the used objects count in compacted xref */ xref->len = newlen + 1; @@ -277,13 +287,17 @@ static void renumberobjs(void) static void retainpages(int argc, char **argv) { - fz_error error; fz_obj *oldroot, *root, *pages, *kids, *countobj, *parent, *olddests; /* Load the old page tree */ - error = pdf_load_page_tree(xref); - if (error) - die(fz_rethrow(error, "cannot load page tree")); + fz_try(xref->ctx) + { + pdf_load_page_tree(xref); + } + fz_catch(xref->ctx) + { + die(fz_error_note(1, "cannot load page tree")); + } /* Keep only pages/type and (reduced) dest entries to avoid * references to unretained pages */ @@ -291,7 +305,7 @@ static void retainpages(int argc, char **argv) pages = fz_dict_gets(oldroot, "Pages"); olddests = pdf_load_name_tree(xref, "Dests"); - root = fz_new_dict(2); + root = fz_new_dict(ctx, 2); fz_dict_puts(root, "Type", fz_dict_gets(oldroot, "Type")); fz_dict_puts(root, "Pages", fz_dict_gets(oldroot, "Pages")); @@ -300,8 +314,8 @@ static void retainpages(int argc, char **argv) fz_drop_obj(root); /* Create a new kids array with only the pages we want to keep */ - parent = fz_new_indirect(fz_to_num(pages), fz_to_gen(pages), xref); - kids = fz_new_array(1); + parent = fz_new_indirect(ctx, fz_to_num(pages), fz_to_gen(pages), xref); + kids = fz_new_array(ctx, 1); /* Retain pages specified */ while (argc - fz_optind) @@ -356,7 +370,7 @@ static void retainpages(int argc, char **argv) fz_drop_obj(parent); /* Update page count and kids array */ - countobj = fz_new_int(fz_array_len(kids)); + countobj = fz_new_int(ctx, fz_array_len(kids)); fz_dict_puts(pages, "Count", countobj); fz_drop_obj(countobj); fz_dict_puts(pages, "Kids", kids); @@ -366,15 +380,15 @@ static void retainpages(int argc, char **argv) if (olddests) { int i; - fz_obj *names = fz_new_dict(1); - fz_obj *dests = fz_new_dict(1); - fz_obj *names_list = fz_new_array(32); + fz_obj *names = fz_new_dict(ctx, 1); + fz_obj *dests = fz_new_dict(ctx, 1); + fz_obj *names_list = fz_new_array(ctx, 32); for (i = 0; i < fz_dict_len(olddests); i++) { fz_obj *key = fz_dict_get_key(olddests, i); fz_obj *val = fz_dict_get_val(olddests, i); - fz_obj *key_str = fz_new_string(fz_to_name(key), strlen(fz_to_name(key))); + fz_obj *key_str = fz_new_string(ctx, fz_to_name(key), strlen(fz_to_name(key))); fz_obj *dest = fz_dict_gets(val, "D"); dest = fz_array_get(dest ? dest : val, 0); @@ -404,7 +418,6 @@ static void retainpages(int argc, char **argv) static void preloadobjstms(void) { - fz_error error; fz_obj *obj; int num; @@ -412,9 +425,14 @@ static void preloadobjstms(void) { if (xref->table[num].type == 'o') { - error = pdf_load_object(&obj, xref, num, 0); - if (error) - die(error); + fz_try(ctx) + { + obj = pdf_load_object(xref, num, 0); + } + fz_catch(ctx) + { + die(1); + } fz_drop_obj(obj); } } @@ -446,7 +464,7 @@ static fz_buffer *hexbuf(unsigned char *p, int n) fz_buffer *buf; int x = 0; - buf = fz_new_buffer(n * 2 + (n / 32) + 2); + buf = fz_new_buffer(ctx, n * 2 + (n / 32) + 2); while (n--) { @@ -471,8 +489,8 @@ static void addhexfilter(fz_obj *dict) fz_obj *f, *dp, *newf, *newdp; fz_obj *ahx, *nullobj; - ahx = fz_new_name("ASCIIHexDecode"); - nullobj = fz_new_null(); + ahx = fz_new_name(ctx, "ASCIIHexDecode"); + nullobj = fz_new_null(ctx); newf = newdp = NULL; f = fz_dict_gets(dict, "Filter"); @@ -480,13 +498,13 @@ static void addhexfilter(fz_obj *dict) if (fz_is_name(f)) { - newf = fz_new_array(2); + newf = fz_new_array(ctx, 2); fz_array_push(newf, ahx); fz_array_push(newf, f); f = newf; if (fz_is_dict(dp)) { - newdp = fz_new_array(2); + newdp = fz_new_array(ctx, 2); fz_array_push(newdp, nullobj); fz_array_push(newdp, dp); dp = newdp; @@ -515,23 +533,27 @@ static void addhexfilter(fz_obj *dict) static void copystream(fz_obj *obj, int num, int gen) { - fz_error error; fz_buffer *buf, *tmp; fz_obj *newlen; - error = pdf_load_raw_stream(&buf, xref, num, gen); - if (error) - die(error); + fz_try(ctx) + { + buf = pdf_load_raw_stream(xref, num, gen); + } + fz_catch(ctx) + { + die(1); + } if (doascii && isbinarystream(buf)) { tmp = hexbuf(buf->data, buf->len); - fz_drop_buffer(buf); + fz_drop_buffer(ctx, buf); buf = tmp; addhexfilter(obj); - newlen = fz_new_int(buf->len); + newlen = fz_new_int(ctx, buf->len); fz_dict_puts(obj, "Length", newlen); fz_drop_obj(newlen); } @@ -542,18 +564,22 @@ static void copystream(fz_obj *obj, int num, int gen) fwrite(buf->data, 1, buf->len, out); fprintf(out, "endstream\nendobj\n\n"); - fz_drop_buffer(buf); + fz_drop_buffer(ctx, buf); } static void expandstream(fz_obj *obj, int num, int gen) { - fz_error error; fz_buffer *buf, *tmp; fz_obj *newlen; - error = pdf_load_stream(&buf, xref, num, gen); - if (error) - die(error); + fz_try(ctx) + { + buf = pdf_load_stream(xref, num, gen); + } + fz_catch(ctx) + { + die(1); + } fz_dict_dels(obj, "Filter"); fz_dict_dels(obj, "DecodeParms"); @@ -561,13 +587,13 @@ static void expandstream(fz_obj *obj, int num, int gen) if (doascii && isbinarystream(buf)) { tmp = hexbuf(buf->data, buf->len); - fz_drop_buffer(buf); + fz_drop_buffer(ctx, buf); buf = tmp; addhexfilter(obj); } - newlen = fz_new_int(buf->len); + newlen = fz_new_int(ctx, buf->len); fz_dict_puts(obj, "Length", newlen); fz_drop_obj(newlen); @@ -577,18 +603,22 @@ static void expandstream(fz_obj *obj, int num, int gen) fwrite(buf->data, 1, buf->len, out); fprintf(out, "endstream\nendobj\n\n"); - fz_drop_buffer(buf); + fz_drop_buffer(ctx, buf); } static void writeobject(int num, int gen) { - fz_error error; fz_obj *obj; fz_obj *type; - error = pdf_load_object(&obj, xref, num, gen); - if (error) - die(error); + fz_try(ctx) + { + obj = pdf_load_object(xref, num, gen); + } + fz_catch(ctx) + { + die(1); + } /* skip ObjStm and XRef objects */ if (fz_is_dict(obj)) @@ -616,7 +646,7 @@ static void writeobject(int num, int gen) } else { - if (doexpand && !pdf_is_jpx_image(obj)) + if (doexpand && !pdf_is_jpx_image(ctx, obj)) expandstream(obj, num, gen); else copystream(obj, num, gen); @@ -644,9 +674,9 @@ static void writexref(void) } fprintf(out, "\n"); - trailer = fz_new_dict(5); + trailer = fz_new_dict(ctx, 5); - obj = fz_new_int(xref->len); + obj = fz_new_int(ctx, xref->len); fz_dict_puts(trailer, "Size", obj); fz_drop_obj(obj); @@ -713,7 +743,6 @@ static void writepdf(void) int main(int argc, char **argv) { - fz_error error; char *infile; char *outfile = "out.pdf"; char *password = ""; @@ -747,21 +776,30 @@ int main(int argc, char **argv) if (argc - fz_optind > 0) subset = 1; - error = pdf_open_xref(&xref, infile, password); - if (error) - die(fz_rethrow(error, "cannot open input file '%s'", infile)); + ctx = fz_new_context(&fz_alloc_default); + if (ctx == NULL) + die(fz_error_note(1, "failed to initialise context")); + + fz_try(ctx) + { + xref = pdf_open_xref(ctx, infile, password); + } + fz_catch(ctx) + { + die(fz_error_note(1, "cannot open input file '%s'", infile)); + } out = fopen(outfile, "wb"); if (!out) - die(fz_throw("cannot open output file '%s'", outfile)); + die(fz_error_make("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)); + uselist = fz_malloc_array(ctx, xref->len + 1, sizeof(char)); + ofslist = fz_malloc_array(ctx, xref->len + 1, sizeof(int)); + genlist = fz_malloc_array(ctx, xref->len + 1, sizeof(int)); + renumbermap = fz_malloc_array(ctx, xref->len + 1, sizeof(int)); for (num = 0; num < xref->len; num++) { @@ -800,16 +838,15 @@ int main(int argc, char **argv) writepdf(); if (fclose(out)) - die(fz_throw("cannot close output file '%s'", outfile)); + die(fz_error_make("cannot close output file '%s'", outfile)); - fz_free(uselist); - fz_free(ofslist); - fz_free(genlist); - fz_free(renumbermap); + fz_free(xref->ctx, uselist); + fz_free(xref->ctx, ofslist); + fz_free(xref->ctx, genlist); + fz_free(xref->ctx, renumbermap); pdf_free_xref(xref); - - fz_flush_warnings(); - + fz_flush_warnings(ctx); + fz_free_context(ctx); return 0; } diff --git a/apps/pdfdraw.c b/apps/pdfdraw.c index 9ad2b56c..c1d2a779 100644 --- a/apps/pdfdraw.c +++ b/apps/pdfdraw.c @@ -38,7 +38,7 @@ struct { static void die(fz_error error) { - fz_catch(error, "aborting"); + fz_error_handle(error, "aborting"); exit(1); } @@ -94,36 +94,46 @@ static int isrange(char *s) static void drawpage(pdf_xref *xref, int pagenum) { - fz_error error; pdf_page *page; fz_display_list *list; fz_device *dev; int start; + fz_context *ctx = xref->ctx; if (showtime) { start = gettime(); } - error = pdf_load_page(&page, xref, pagenum - 1); - if (error) - die(fz_rethrow(error, "cannot load page %d in file '%s'", pagenum, filename)); + fz_try(ctx) + { + page = pdf_load_page(xref, pagenum - 1); + } + fz_catch(ctx) + { + die(fz_error_note(1, "cannot load page %d in file '%s'", pagenum, filename)); + } list = NULL; if (uselist) { - list = fz_new_display_list(); - dev = fz_new_list_device(list); - error = pdf_run_page(xref, page, dev, fz_identity); - if (error) - die(fz_rethrow(error, "cannot draw page %d in file '%s'", pagenum, filename)); + list = fz_new_display_list(ctx); + dev = fz_new_list_device(ctx, list); + fz_try(ctx) + { + pdf_run_page(xref, page, dev, fz_identity); + } + fz_catch(ctx) + { + die(fz_error_note(1, "cannot draw page %d in file '%s'", pagenum, filename)); + } fz_free_device(dev); } if (showxml) { - dev = fz_new_trace_device(); + dev = fz_new_trace_device(ctx); printf("<page number=\"%d\">\n", pagenum); if (list) fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox); @@ -135,8 +145,8 @@ static void drawpage(pdf_xref *xref, int pagenum) if (showtext) { - fz_text_span *text = fz_new_text_span(); - dev = fz_new_text_device(text); + fz_text_span *text = fz_new_text_span(ctx); + dev = fz_new_text_device(ctx, text); if (list) fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox); else @@ -148,7 +158,7 @@ static void drawpage(pdf_xref *xref, int pagenum) else fz_debug_text_span(text); printf("\n"); - fz_free_text_span(text); + fz_free_text_span(ctx, text); } if (showmd5 || showtime) @@ -170,14 +180,14 @@ static void drawpage(pdf_xref *xref, int pagenum) /* TODO: banded rendering and multi-page ppm */ - pix = fz_new_pixmap_with_rect(colorspace, bbox); + pix = fz_new_pixmap_with_rect(ctx, colorspace, bbox); if (savealpha) fz_clear_pixmap(pix); else fz_clear_pixmap_with_color(pix, 255); - dev = fz_new_draw_device(glyphcache, pix); + dev = fz_new_draw_device(ctx, glyphcache, pix); if (list) fz_execute_display_list(list, dev, ctm, bbox); else @@ -197,17 +207,17 @@ static void drawpage(pdf_xref *xref, int pagenum) char buf[512]; sprintf(buf, output, pagenum); if (strstr(output, ".pgm") || strstr(output, ".ppm") || strstr(output, ".pnm")) - fz_write_pnm(pix, buf); + fz_write_pnm(ctx, pix, buf); else if (strstr(output, ".pam")) - fz_write_pam(pix, buf, savealpha); + fz_write_pam(ctx, pix, buf, savealpha); else if (strstr(output, ".png")) - fz_write_png(pix, buf, savealpha); + fz_write_png(ctx, pix, buf, savealpha); else if (strstr(output, ".pbm")) { - fz_halftone *ht = fz_get_default_halftone(1); - fz_bitmap *bit = fz_halftone_pixmap(pix, ht); - fz_write_pbm(bit, buf); - fz_drop_bitmap(bit); - fz_drop_halftone(ht); + fz_halftone *ht = fz_get_default_halftone(ctx, 1); + fz_bitmap *bit = fz_halftone_pixmap(ctx, pix, ht); + fz_write_pbm(ctx, bit, buf); + fz_drop_bitmap(ctx, bit); + fz_drop_halftone(ctx, ht); } } @@ -226,13 +236,13 @@ static void drawpage(pdf_xref *xref, int pagenum) printf("%02x", digest[i]); } - fz_drop_pixmap(pix); + fz_drop_pixmap(ctx, pix); } if (list) - fz_free_display_list(list); + fz_free_display_list(ctx, list); - pdf_free_page(page); + pdf_free_page(ctx, page); if (showtime) { @@ -258,9 +268,9 @@ static void drawpage(pdf_xref *xref, int pagenum) if (showmd5 || showtime) printf("\n"); - pdf_age_store(xref->store, 3); + pdf_age_store(ctx, xref->store, 3); - fz_flush_warnings(); + fz_flush_warnings(ctx); } static void drawrange(pdf_xref *xref, char *range) @@ -318,6 +328,7 @@ int main(int argc, char **argv) pdf_xref *xref; fz_error error; int c; + fz_context *ctx; while ((c = fz_getopt(argc, argv, "lo:p:r:R:Aab:dgmtx5G:I")) != -1) { @@ -343,8 +354,6 @@ int main(int argc, char **argv) } } - fz_set_aa_level(alphabits); - if (fz_optind == argc) usage(); @@ -357,7 +366,16 @@ int main(int argc, char **argv) if (accelerate) fz_accelerate(); - glyphcache = fz_new_glyph_cache(); + ctx = fz_new_context(&fz_alloc_default); + if (ctx == NULL) + { + fprintf(stderr, "Failed to init context\n"); + exit(1); + } + + fz_set_aa_level(ctx, alphabits); + + glyphcache = fz_new_glyph_cache(ctx); colorspace = fz_device_rgb; if (grayscale) @@ -383,13 +401,23 @@ int main(int argc, char **argv) { filename = argv[fz_optind++]; - error = pdf_open_xref(&xref, filename, password); - if (error) - die(fz_rethrow(error, "cannot open document: %s", filename)); + fz_try(ctx) + { + xref = pdf_open_xref(ctx, filename, password); + } + fz_catch(ctx) + { + die(fz_error_note(error, "cannot open document: %s", filename)); + } - error = pdf_load_page_tree(xref); - if (error) - die(fz_rethrow(error, "cannot load page tree: %s", filename)); + fz_try(ctx) + { + pdf_load_page_tree(xref); + } + fz_catch(ctx) + { + die(fz_error_note(error, "cannot load page tree: %s", filename)); + } if (showxml) printf("<document name=\"%s\">\n", filename); @@ -419,9 +447,8 @@ int main(int argc, char **argv) printf("slowest page %d: %dms\n", timing.maxpage, timing.max); } - fz_free_glyph_cache(glyphcache); - - fz_flush_warnings(); - + fz_free_glyph_cache(ctx, glyphcache); + fz_flush_warnings(ctx); + fz_free_context(ctx); return 0; } diff --git a/apps/pdfextract.c b/apps/pdfextract.c index 7e6e4ace..bf0a74ed 100644 --- a/apps/pdfextract.c +++ b/apps/pdfextract.c @@ -6,11 +6,12 @@ #include "mupdf.h" static pdf_xref *xref = NULL; +static fz_context *ctx = NULL; static int dorgb = 0; void die(fz_error error) { - fz_catch(error, "aborting"); + fz_error_handle(error, "aborting"); if (xref) pdf_free_xref(xref); exit(1); @@ -38,25 +39,29 @@ static int isfontdesc(fz_obj *obj) static void saveimage(int num) { - fz_error error; fz_pixmap *img; fz_obj *ref; char name[1024]; - ref = fz_new_indirect(num, 0, xref); + ref = fz_new_indirect(ctx, num, 0, xref); /* TODO: detect DCTD and save as jpeg */ - error = pdf_load_image(&img, xref, ref); - if (error) - die(error); + fz_try(ctx) + { + img = pdf_load_image(xref, ref); + } + fz_catch(ctx) + { + die(1); + } if (dorgb && img->colorspace && img->colorspace != fz_device_rgb) { fz_pixmap *temp; - temp = fz_new_pixmap_with_rect(fz_device_rgb, fz_bound_pixmap(img)); - fz_convert_pixmap(img, temp); - fz_drop_pixmap(img); + temp = fz_new_pixmap_with_rect(ctx, fz_device_rgb, fz_bound_pixmap(img)); + fz_convert_pixmap(ctx, img, temp); + fz_drop_pixmap(ctx, img); img = temp; } @@ -64,22 +69,21 @@ static void saveimage(int num) { sprintf(name, "img-%04d.png", num); printf("extracting image %s\n", name); - fz_write_png(img, name, 0); + fz_write_png(ctx, img, name, 0); } else { sprintf(name, "img-%04d.pam", num); printf("extracting image %s\n", name); - fz_write_pam(img, name, 0); + fz_write_pam(ctx, img, name, 0); } - fz_drop_pixmap(img); + fz_drop_pixmap(ctx, img); fz_drop_obj(ref); } static void savefont(fz_obj *dict, int num) { - fz_error error; char name[1024]; char *subtype; fz_buffer *buf; @@ -115,7 +119,7 @@ static void savefont(fz_obj *dict, int num) obj = fz_dict_gets(obj, "Subtype"); if (obj && !fz_is_name(obj)) - die(fz_throw("Invalid font descriptor subtype")); + die(fz_error_make("Invalid font descriptor subtype")); subtype = fz_to_name(obj); if (!strcmp(subtype, "Type1C")) @@ -123,49 +127,56 @@ static void savefont(fz_obj *dict, int num) else if (!strcmp(subtype, "CIDFontType0C")) ext = "cid"; else - die(fz_throw("Unhandled font type '%s'", subtype)); + die(fz_error_make("Unhandled font type '%s'", subtype)); } if (!stream) { - fz_warn("Unhandled font type"); + fz_warn(ctx, "Unhandled font type"); return; } - buf = fz_new_buffer(0); - - error = pdf_load_stream(&buf, xref, fz_to_num(stream), fz_to_gen(stream)); - if (error) - die(error); + fz_try(ctx) + { + buf = pdf_load_stream(xref, fz_to_num(stream), fz_to_gen(stream)); + } + fz_catch(ctx) + { + die(1); + } sprintf(name, "%s-%04d.%s", fontname, num, ext); printf("extracting font %s\n", name); f = fopen(name, "wb"); if (f == NULL) - die(fz_throw("Error creating font file")); + die(fz_error_make("Error creating font file")); n = fwrite(buf->data, 1, buf->len, f); if (n < buf->len) - die(fz_throw("Error writing font file")); + die(fz_error_make("Error writing font file")); if (fclose(f) < 0) - die(fz_throw("Error closing font file")); + die(fz_error_make("Error closing font file")); - fz_drop_buffer(buf); + fz_drop_buffer(ctx, buf); } static void showobject(int num) { - fz_error error; fz_obj *obj; if (!xref) - die(fz_throw("no file specified")); + die(fz_error_make("no file specified")); - error = pdf_load_object(&obj, xref, num, 0); - if (error) - die(error); + fz_try(ctx) + { + obj = pdf_load_object(xref, num, 0); + } + fz_catch(ctx) + { + die(1); + } if (isimage(obj)) saveimage(num); @@ -177,7 +188,6 @@ static void showobject(int num) int main(int argc, char **argv) { - fz_error error; char *infile; char *password = ""; int c, o; @@ -196,9 +206,19 @@ int main(int argc, char **argv) usage(); infile = argv[fz_optind++]; - error = pdf_open_xref(&xref, infile, password); - if (error) - die(fz_rethrow(error, "cannot open input file '%s'", infile)); + + ctx = fz_new_context(&fz_alloc_default); + if (ctx == NULL) + die(fz_error_note(1, "failed to initialise context")); + + fz_try(ctx) + { + xref = pdf_open_xref(ctx, infile, password); + } + fz_catch(ctx) + { + die(fz_error_note(1, "cannot open input file '%s'", infile)); + } if (fz_optind == argc) { @@ -215,8 +235,7 @@ int main(int argc, char **argv) } pdf_free_xref(xref); - - fz_flush_warnings(); - + fz_flush_warnings(ctx); + fz_free_context(ctx); return 0; } diff --git a/apps/pdfinfo.c b/apps/pdfinfo.c index d8948264..d2aa0bb4 100644 --- a/apps/pdfinfo.c +++ b/apps/pdfinfo.c @@ -7,13 +7,14 @@ #include "mupdf.h" pdf_xref *xref; +fz_context *ctx; int pagecount; void closexref(void); void die(fz_error error) { - fz_catch(error, "aborting"); + fz_error_handle(error, "aborting"); closexref(); exit(1); } @@ -107,57 +108,57 @@ void closexref(void) if (dim) { for (i = 0; i < dims; i++) - fz_free(dim[i].u.dim.bbox); - fz_free(dim); + fz_free(ctx, dim[i].u.dim.bbox); + fz_free(ctx, dim); dim = NULL; dims = 0; } if (font) { - fz_free(font); + fz_free(ctx, font); font = NULL; fonts = 0; } if (image) { - fz_free(image); + fz_free(ctx, image); image = NULL; images = 0; } if (shading) { - fz_free(shading); + fz_free(ctx, shading); shading = NULL; shadings = 0; } if (pattern) { - fz_free(pattern); + fz_free(ctx, pattern); pattern = NULL; patterns = 0; } if (form) { - fz_free(form); + fz_free(ctx, form); form = NULL; forms = 0; } if (psobj) { - fz_free(psobj); + fz_free(ctx, psobj); psobj = NULL; psobjs = 0; } if (xref && xref->store) { - pdf_free_store(xref->store); + pdf_free_store(ctx, xref->store); xref->store = NULL; } } @@ -212,7 +213,7 @@ gatherdimensions(int page, fz_obj *pageref, fz_obj *pageobj) if (!fz_is_array(obj)) return; - bbox = pdf_to_rect(obj); + bbox = pdf_to_rect(ctx, obj); for (j = 0; j < dims; j++) if (!memcmp(dim[j].u.dim.bbox, &bbox, sizeof (fz_rect))) @@ -223,11 +224,11 @@ gatherdimensions(int page, fz_obj *pageref, fz_obj *pageobj) dims++; - dim = fz_realloc(dim, dims, sizeof(struct info)); + dim = fz_resize_array(ctx, dim, dims, sizeof(struct info)); dim[dims - 1].page = page; dim[dims - 1].pageref = pageref; dim[dims - 1].pageobj = pageobj; - dim[dims - 1].u.dim.bbox = fz_malloc(sizeof(fz_rect)); + dim[dims - 1].u.dim.bbox = fz_malloc(ctx, sizeof(fz_rect)); memcpy(dim[dims - 1].u.dim.bbox, &bbox, sizeof (fz_rect)); return; @@ -236,9 +237,10 @@ gatherdimensions(int page, fz_obj *pageref, fz_obj *pageobj) static void gatherfonts(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) { - int i; + int i, n; - for (i = 0; i < fz_dict_len(dict); i++) + n = fz_dict_len(dict); + for (i = 0; i < n; i++) { fz_obj *fontdict = NULL; fz_obj *subtype = NULL; @@ -249,7 +251,7 @@ gatherfonts(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) fontdict = fz_dict_get_val(dict, i); if (!fz_is_dict(fontdict)) { - fz_warn("not a font dict (%d %d R)", fz_to_num(fontdict), fz_to_gen(fontdict)); + fz_warn(ctx, "not a font dict (%d %d R)", fz_to_num(fontdict), fz_to_gen(fontdict)); continue; } @@ -267,7 +269,7 @@ gatherfonts(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) fonts++; - font = fz_realloc(font, fonts, sizeof(struct info)); + font = fz_resize_array(ctx, font, fonts, sizeof(struct info)); font[fonts - 1].page = page; font[fonts - 1].pageref = pageref; font[fonts - 1].pageobj = pageobj; @@ -280,9 +282,10 @@ gatherfonts(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) static void gatherimages(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) { - int i; + int i, n; - for (i = 0; i < fz_dict_len(dict); i++) + n = fz_dict_len(dict); + for (i = 0; i < n; i++) { fz_obj *imagedict; fz_obj *type; @@ -297,7 +300,7 @@ gatherimages(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) imagedict = fz_dict_get_val(dict, i); if (!fz_is_dict(imagedict)) { - fz_warn("not an image dict (%d %d R)", fz_to_num(imagedict), fz_to_gen(imagedict)); + fz_warn(ctx, "not an image dict (%d %d R)", fz_to_num(imagedict), fz_to_gen(imagedict)); continue; } @@ -335,7 +338,7 @@ gatherimages(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) images++; - image = fz_realloc(image, images, sizeof(struct info)); + image = fz_resize_array(ctx, image, images, sizeof(struct info)); image[images - 1].page = page; image[images - 1].pageref = pageref; image[images - 1].pageobj = pageobj; @@ -352,9 +355,10 @@ gatherimages(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) static void gatherforms(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) { - int i; + int i, n; - for (i = 0; i < fz_dict_len(dict); i++) + n = fz_dict_len(dict); + for (i = 0; i < n; i++) { fz_obj *xobjdict; fz_obj *type; @@ -367,7 +371,7 @@ gatherforms(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) xobjdict = fz_dict_get_val(dict, i); if (!fz_is_dict(xobjdict)) { - fz_warn("not a xobject dict (%d %d R)", fz_to_num(xobjdict), fz_to_gen(xobjdict)); + fz_warn(ctx, "not a xobject dict (%d %d R)", fz_to_num(xobjdict), fz_to_gen(xobjdict)); continue; } @@ -392,7 +396,7 @@ gatherforms(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) forms++; - form = fz_realloc(form, forms, sizeof(struct info)); + form = fz_resize_array(ctx, form, forms, sizeof(struct info)); form[forms - 1].page = page; form[forms - 1].pageref = pageref; form[forms - 1].pageobj = pageobj; @@ -405,9 +409,10 @@ gatherforms(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) static void gatherpsobjs(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) { - int i; + int i, n; - for (i = 0; i < fz_dict_len(dict); i++) + n = fz_dict_len(dict); + for (i = 0; i < n; i++) { fz_obj *xobjdict; fz_obj *type; @@ -417,7 +422,7 @@ gatherpsobjs(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) xobjdict = fz_dict_get_val(dict, i); if (!fz_is_dict(xobjdict)) { - fz_warn("not a xobject dict (%d %d R)", fz_to_num(xobjdict), fz_to_gen(xobjdict)); + fz_warn(ctx, "not a xobject dict (%d %d R)", fz_to_num(xobjdict), fz_to_gen(xobjdict)); continue; } @@ -436,7 +441,7 @@ gatherpsobjs(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) psobjs++; - psobj = fz_realloc(psobj, psobjs, sizeof(struct info)); + psobj = fz_resize_array(ctx, psobj, psobjs, sizeof(struct info)); psobj[psobjs - 1].page = page; psobj[psobjs - 1].pageref = pageref; psobj[psobjs - 1].pageobj = pageobj; @@ -447,9 +452,10 @@ gatherpsobjs(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) static void gathershadings(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) { - int i; + int i, n; - for (i = 0; i < fz_dict_len(dict); i++) + n = fz_dict_len(dict); + for (i = 0; i < n; i++) { fz_obj *shade; fz_obj *type; @@ -458,14 +464,14 @@ gathershadings(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) shade = fz_dict_get_val(dict, i); if (!fz_is_dict(shade)) { - fz_warn("not a shading dict (%d %d R)", fz_to_num(shade), fz_to_gen(shade)); + fz_warn(ctx, "not a shading dict (%d %d R)", fz_to_num(shade), fz_to_gen(shade)); continue; } type = fz_dict_gets(shade, "ShadingType"); if (!fz_is_int(type) || fz_to_int(type) < 1 || fz_to_int(type) > 7) { - fz_warn("not a shading type (%d %d R)", fz_to_num(shade), fz_to_gen(shade)); + fz_warn(ctx, "not a shading type (%d %d R)", fz_to_num(shade), fz_to_gen(shade)); type = NULL; } @@ -478,7 +484,7 @@ gathershadings(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) shadings++; - shading = fz_realloc(shading, shadings, sizeof(struct info)); + shading = fz_resize_array(ctx, shading, shadings, sizeof(struct info)); shading[shadings - 1].page = page; shading[shadings - 1].pageref = pageref; shading[shadings - 1].pageobj = pageobj; @@ -490,9 +496,10 @@ gathershadings(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) static void gatherpatterns(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) { - int i; + int i, n; - for (i = 0; i < fz_dict_len(dict); i++) + n = fz_dict_len(dict); + for (i = 0; i < n; i++) { fz_obj *patterndict; fz_obj *type; @@ -504,14 +511,14 @@ gatherpatterns(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) patterndict = fz_dict_get_val(dict, i); if (!fz_is_dict(patterndict)) { - fz_warn("not a pattern dict (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict)); + fz_warn(ctx, "not a pattern dict (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict)); continue; } type = fz_dict_gets(patterndict, "PatternType"); if (!fz_is_int(type) || fz_to_int(type) < 1 || fz_to_int(type) > 2) { - fz_warn("not a pattern type (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict)); + fz_warn(ctx, "not a pattern type (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict)); type = NULL; } @@ -520,14 +527,14 @@ gatherpatterns(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) paint = fz_dict_gets(patterndict, "PaintType"); if (!fz_is_int(paint) || fz_to_int(paint) < 1 || fz_to_int(paint) > 2) { - fz_warn("not a pattern paint type (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict)); + fz_warn(ctx, "not a pattern paint type (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict)); paint = NULL; } tiling = fz_dict_gets(patterndict, "TilingType"); if (!fz_is_int(tiling) || fz_to_int(tiling) < 1 || fz_to_int(tiling) > 3) { - fz_warn("not a pattern tiling type (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict)); + fz_warn(ctx, "not a pattern tiling type (%d %d R)", fz_to_num(patterndict), fz_to_gen(patterndict)); tiling = NULL; } } @@ -545,7 +552,7 @@ gatherpatterns(int page, fz_obj *pageref, fz_obj *pageobj, fz_obj *dict) patterns++; - pattern = fz_realloc(pattern, patterns, sizeof(struct info)); + pattern = fz_resize_array(ctx, pattern, patterns, sizeof(struct info)); pattern[patterns - 1].page = page; pattern[patterns - 1].pageref = pageref; pattern[patterns - 1].pageobj = pageobj; @@ -573,14 +580,16 @@ gatherresourceinfo(int page, fz_obj *rsrc) pageref = xref->page_refs[page-1]; if (!pageobj) - die(fz_throw("cannot retrieve info from page %d", page)); + die(fz_error_make("cannot retrieve info from page %d", page)); font = fz_dict_gets(rsrc, "Font"); if (font) { - gatherfonts(page, pageref, pageobj, font); + int n; - for (i = 0; i < fz_dict_len(font); i++) + gatherfonts(page, pageref, pageobj, font); + n = fz_dict_len(font); + for (i = 0; i < n; i++) { fz_obj *obj = fz_dict_get_val(font, i); @@ -593,11 +602,13 @@ gatherresourceinfo(int page, fz_obj *rsrc) xobj = fz_dict_gets(rsrc, "XObject"); if (xobj) { + int n; + gatherimages(page, pageref, pageobj, xobj); gatherforms(page, pageref, pageobj, xobj); gatherpsobjs(page, pageref, pageobj, xobj); - - for (i = 0; i < fz_dict_len(xobj); i++) + n = fz_dict_len(xobj); + for (i = 0; i < n; i++) { fz_obj *obj = fz_dict_get_val(xobj, i); subrsrc = fz_dict_gets(obj, "Resources"); @@ -613,9 +624,10 @@ gatherresourceinfo(int page, fz_obj *rsrc) pattern = fz_dict_gets(rsrc, "Pattern"); if (pattern) { + int n; gatherpatterns(page, pageref, pageobj, pattern); - - for (i = 0; i < fz_dict_len(pattern); i++) + n = fz_dict_len(pattern); + for (i = 0; i < n; i++) { fz_obj *obj = fz_dict_get_val(pattern, i); subrsrc = fz_dict_gets(obj, "Resources"); @@ -636,7 +648,7 @@ gatherpageinfo(int page) pageref = xref->page_refs[page-1]; if (!pageobj) - die(fz_throw("cannot retrieve info from page %d", page)); + die(fz_error_make("cannot retrieve info from page %d", page)); gatherdimensions(page, pageref, pageobj); @@ -696,10 +708,12 @@ printinfo(char *filename, int show, int page) fz_to_num(image[i].pageref), fz_to_gen(image[i].pageref)); if (fz_is_array(image[i].u.image.filter)) - for (j = 0; j < fz_array_len(image[i].u.image.filter); j++) + { + int n = fz_array_len(image[i].u.image.filter); + for (j = 0; j < n; j++) { fz_obj *obj = fz_array_get(image[i].u.image.filter, j); - char *filter = fz_strdup(fz_to_name(obj)); + char *filter = fz_strdup(ctx, fz_to_name(obj)); if (strstr(filter, "Decode")) *(strstr(filter, "Decode")) = '\0'; @@ -707,25 +721,26 @@ printinfo(char *filename, int show, int page) printf("%s%s", filter, j == fz_array_len(image[i].u.image.filter) - 1 ? "" : " "); - fz_free(filter); + fz_free(ctx, filter); } + } else if (image[i].u.image.filter) { fz_obj *obj = image[i].u.image.filter; - char *filter = fz_strdup(fz_to_name(obj)); + char *filter = fz_strdup(ctx, fz_to_name(obj)); if (strstr(filter, "Decode")) *(strstr(filter, "Decode")) = '\0'; printf("%s", filter); - fz_free(filter); + fz_free(ctx, filter); } else printf("Raw"); if (image[i].u.image.cs) { - cs = fz_strdup(fz_to_name(image[i].u.image.cs)); + cs = fz_strdup(ctx, fz_to_name(image[i].u.image.cs)); if (!strncmp(cs, "Device", 6)) { @@ -744,7 +759,7 @@ printinfo(char *filename, int show, int page) } if (image[i].u.image.altcs) { - altcs = fz_strdup(fz_to_name(image[i].u.image.altcs)); + altcs = fz_strdup(ctx, fz_to_name(image[i].u.image.altcs)); if (!strncmp(altcs, "Device", 6)) { @@ -771,8 +786,8 @@ printinfo(char *filename, int show, int page) image[i].u.image.altcs ? altcs : "", fz_to_num(image[i].u.image.obj), fz_to_gen(image[i].u.image.obj)); - fz_free(cs); - fz_free(altcs); + fz_free(ctx, cs); + fz_free(ctx, altcs); } printf("\n"); } @@ -966,6 +981,10 @@ int main(int argc, char **argv) if (fz_optind == argc) infousage(); + ctx = fz_new_context(); + if (ctx == NULL) + die(fz_error_make("failed to initialise context")); + state = NO_FILE_OPENED; while (fz_optind < argc) { @@ -981,13 +1000,13 @@ int main(int argc, char **argv) filename = argv[fz_optind]; printf("%s:\n", filename); - error = pdf_open_xref(&xref, filename, password); + error = pdf_open_xref(ctx, &xref, filename, password); if (error) - die(fz_rethrow(error, "cannot open input file '%s'", filename)); + die(fz_error_note(error, "cannot open input file '%s'", filename)); error = pdf_load_page_tree(xref); if (error) - die(fz_rethrow(error, "cannot load page tree: %s", filename)); + die(fz_error_note(error, "cannot load page tree: %s", filename)); pagecount = pdf_count_pages(xref); showglobalinfo(); @@ -1006,6 +1025,6 @@ int main(int argc, char **argv) showinfo(filename, show, "1-"); closexref(); - + fz_free_context(ctx); return 0; } diff --git a/apps/pdfshow.c b/apps/pdfshow.c index 5e74042b..fee20d2f 100644 --- a/apps/pdfshow.c +++ b/apps/pdfshow.c @@ -6,13 +6,14 @@ #include "mupdf.h" static pdf_xref *xref = NULL; +static fz_context *ctx = NULL; static int showbinary = 0; static int showdecode = 1; static int showcolumn; void die(fz_error error) { - fz_catch(error, "aborting"); + fz_error_handle(error, "aborting"); if (xref) pdf_free_xref(xref); exit(1); @@ -30,7 +31,7 @@ static void usage(void) static void showtrailer(void) { if (!xref) - die(fz_throw("no file specified")); + die(fz_error_make("no file specified")); printf("trailer\n"); fz_debug_obj(xref->trailer); printf("\n"); @@ -39,26 +40,30 @@ static void showtrailer(void) static void showxref(void) { if (!xref) - die(fz_throw("no file specified")); + die(fz_error_make("no file specified")); pdf_debug_xref(xref); printf("\n"); } static void showpagetree(void) { - fz_error error; fz_obj *ref; int count; int i; if (!xref) - die(fz_throw("no file specified")); + die(fz_error_make("no file specified")); if (!xref->page_len) { - error = pdf_load_page_tree(xref); - if (error) - die(fz_rethrow(error, "cannot load page tree")); + fz_try(xref->ctx) + { + pdf_load_page_tree(xref); + } + fz_catch(xref->ctx) + { + die(fz_error_note(1, "cannot load page tree")); + } } count = pdf_count_pages(xref); @@ -95,19 +100,23 @@ static void showsafe(unsigned char *buf, int n) static void showstream(int num, int gen) { - fz_error error; fz_stream *stm; unsigned char buf[2048]; int n; showcolumn = 0; - if (showdecode) - error = pdf_open_stream(&stm, xref, num, gen); - else - error = pdf_open_raw_stream(&stm, xref, num, gen); - if (error) - die(error); + fz_try(xref->ctx) + { + if (showdecode) + stm = pdf_open_stream(xref, num, gen); + else + stm = pdf_open_raw_stream(xref, num, gen); + } + fz_catch(xref->ctx) + { + die(1); + } while (1) { @@ -127,15 +136,19 @@ static void showstream(int num, int gen) static void showobject(int num, int gen) { - fz_error error; fz_obj *obj; if (!xref) - die(fz_throw("no file specified")); + die(fz_error_make("no file specified")); - error = pdf_load_object(&obj, xref, num, gen); - if (error) - die(error); + fz_try(ctx) + { + obj = pdf_load_object(xref, num, gen); + } + fz_catch(ctx) + { + die(1); + } if (pdf_is_stream(xref, num, gen)) { @@ -165,7 +178,6 @@ static void showobject(int num, int gen) static void showgrep(char *filename) { - fz_error error; fz_obj *obj; int i; @@ -173,9 +185,14 @@ static void showgrep(char *filename) { if (xref->table[i].type == 'n' || xref->table[i].type == 'o') { - error = pdf_load_object(&obj, xref, i, 0); - if (error) - die(error); + fz_try(ctx) + { + obj = pdf_load_object(xref, i, 0); + } + fz_catch(ctx) + { + die(1); + } fz_sort_dict(obj); @@ -194,7 +211,6 @@ int main(int argc, char **argv) { char *password = NULL; /* don't throw errors if encrypted */ char *filename; - fz_error error; int c; while ((c = fz_getopt(argc, argv, "p:be")) != -1) @@ -212,9 +228,19 @@ int main(int argc, char **argv) usage(); filename = argv[fz_optind++]; - error = pdf_open_xref(&xref, filename, password); - if (error) - die(fz_rethrow(error, "cannot open document: %s", filename)); + + ctx = fz_new_context(&fz_alloc_default); + if (ctx == NULL) + die(fz_error_note(1, "failed to initialise context")); + + fz_try(ctx) + { + xref = pdf_open_xref(ctx, filename, password); + } + fz_catch(ctx) + { + die(fz_error_note(1, "cannot open document: %s", filename)); + } if (fz_optind == argc) showtrailer(); @@ -233,8 +259,7 @@ int main(int argc, char **argv) } pdf_free_xref(xref); - - fz_flush_warnings(); - + fz_flush_warnings(ctx); + fz_free_context(ctx); return 0; } diff --git a/apps/win_main.c b/apps/win_main.c index da97b011..3e293957 100644 --- a/apps/win_main.c +++ b/apps/win_main.c @@ -37,6 +37,7 @@ static pdfapp_t gapp; static wchar_t wbuf[1024]; static char filename[1024]; +static fz_context *context; /* * Create registry keys to associate MuPDF with PDF and XPS files. @@ -98,7 +99,7 @@ void winerror(pdfapp_t *app, fz_error error) int i; /* TODO: redirect stderr to a log file and display here */ - fz_catch(error, "displaying error message to user"); + fz_error_handle(error, "displaying error message to user"); fz_strlcpy(msgbuf, "An error has occurred.\n\n", sizeof msgbuf); for (i = 0; i < fz_get_error_count(); i++) @@ -122,7 +123,7 @@ void win32error(char *msg) code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buf, 0, NULL); - winerror(&gapp, fz_throw("%s:\n%s", msg, buf)); + winerror(&gapp, fz_error_make("%s:\n%s", msg, buf)); } int winfilename(wchar_t *buf, int len) @@ -247,9 +248,9 @@ dloginfoproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) #define SETUCS(ID) \ { \ unsigned short *ucs; \ - ucs = pdf_to_ucs2(obj); \ + ucs = pdf_to_ucs2(xref->ctx, obj); \ SetDlgItemTextW(hwnd, ID, ucs); \ - fz_free(ucs); \ + fz_free(context, ucs); \ } if ((obj = fz_dict_gets(info, "Title"))) @@ -617,7 +618,7 @@ void winreloadfile(pdfapp_t *app) fd = _wopen(wbuf, O_BINARY | O_RDONLY, 0666); if (fd < 0) - winerror(&gapp, fz_throw("cannot reload file '%s'", filename)); + winerror(&gapp, fz_error_make("cannot reload file '%s'", filename)); pdfapp_open(app, filename, fd, 1); } @@ -853,10 +854,17 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShow MSG msg; int fd; int code; + fz_context *ctx; fz_accelerate(); - pdfapp_init(&gapp); + ctx = fz_new_context(&fz_alloc_default); + if (ctx == NULL) + { + fprintf(stderr, "Failed to init context"); + exit(1); + } + pdfapp_init(ctx, &gapp); GetModuleFileNameA(NULL, argv0, sizeof argv0); install_app(argv0); @@ -875,7 +883,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShow fd = _wopen(wbuf, O_BINARY | O_RDONLY, 0666); if (fd < 0) - winerror(&gapp, fz_throw("cannot open file '%s'", filename)); + winerror(&gapp, fz_error_make("cannot open file '%s'", filename)); code = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, filename, sizeof filename, NULL, NULL); if (code == 0) diff --git a/apps/x11_main.c b/apps/x11_main.c index a2d36ac5..5b19a176 100644 --- a/apps/x11_main.c +++ b/apps/x11_main.c @@ -105,7 +105,7 @@ void winwarn(pdfapp_t *app, char *msg) void winerror(pdfapp_t *app, fz_error error) { - fz_catch(error, "aborting"); + fz_error_handle(error, "aborting"); exit(1); } @@ -127,7 +127,7 @@ static void winopen(void) xdpy = XOpenDisplay(NULL); if (!xdpy) - winerror(&gapp, fz_throw("cannot open display")); + winerror(&gapp, fz_error_make("cannot open display")); XA_TARGETS = XInternAtom(xdpy, "TARGETS", False); XA_TIMESTAMP = XInternAtom(xdpy, "TIMESTAMP", False); @@ -161,7 +161,7 @@ static void winopen(void) 0, NULL); if (xwin == None) - winerror(&gapp, fz_throw("cannot create window")); + winerror(&gapp, fz_error_make("cannot create window")); XSetWindowColormap(xdpy, xwin, ximage_get_colormap()); XSelectInput(xdpy, xwin, @@ -501,7 +501,7 @@ void winreloadfile(pdfapp_t *app) fd = open(filename, O_BINARY | O_RDONLY, 0666); if (fd < 0) - winerror(app, fz_throw("cannot reload file '%s'", filename)); + winerror(app, fz_error_make("cannot reload file '%s'", filename)); pdfapp_open(app, filename, fd, 1); } @@ -581,10 +581,14 @@ int main(int argc, char **argv) fd_set fds; int width = -1; int height = -1; +<<<<<<< HEAD + fz_context *ctx; +======= struct timeval tmo_at; struct timeval now; struct timeval tmo; struct timeval *timeout; +>>>>>>> master while ((c = fz_getopt(argc, argv, "p:r:b:A")) != -1) { @@ -609,8 +613,18 @@ int main(int argc, char **argv) if (accelerate) fz_accelerate(); + ctx = fz_new_context(); + if (ctx == NULL) + { + fprintf(stderr, "failed to initialise context"); + exit(1); + } + winopen(); +<<<<<<< HEAD + pdfapp_init(ctx, &gapp); +======= if (resolution == -1) resolution = winresolution(); if (resolution < MINRES) @@ -619,6 +633,7 @@ int main(int argc, char **argv) resolution = MAXRES; pdfapp_init(&gapp); +>>>>>>> master gapp.scrw = DisplayWidth(xdpy, xscr); gapp.scrh = DisplayHeight(xdpy, xscr); gapp.resolution = resolution; @@ -626,7 +641,7 @@ int main(int argc, char **argv) fd = open(filename, O_BINARY | O_RDONLY, 0666); if (fd < 0) - winerror(&gapp, fz_throw("cannot open file '%s'", filename)); + winerror(&gapp, fz_error_make("cannot open file '%s'", filename)); pdfapp_open(&gapp, filename, fd, 0); @@ -812,5 +827,7 @@ int main(int argc, char **argv) XCloseDisplay(xdpy); + fz_free_context(ctx); + return 0; } diff --git a/apps/xpsdraw.c b/apps/xpsdraw.c index 1d2992bc..4ac40b72 100644 --- a/apps/xpsdraw.c +++ b/apps/xpsdraw.c @@ -21,6 +21,7 @@ int uselist = 1; fz_colorspace *colorspace; fz_glyph_cache *glyphcache; char *filename; +fz_context *ctx; struct { int count, total; @@ -30,7 +31,7 @@ struct { static void die(fz_error error) { - fz_catch(error, "aborting"); + fz_error_handle(error, "aborting"); exit(1); } @@ -79,60 +80,64 @@ static int isrange(char *s) } static void -xps_run_page(xps_context *ctx, xps_page *page, fz_device *dev, fz_matrix ctm) +xps_run_page(xps_document *doc, xps_page *page, fz_device *dev, fz_matrix ctm) { - ctx->dev = dev; - xps_parse_fixed_page(ctx, ctm, page); - ctx->dev = NULL; + doc->dev = dev; + xps_parse_fixed_page(doc, ctm, page); + doc->dev = NULL; } -static void drawpage(xps_context *ctx, int pagenum) +static void drawpage(xps_document *doc, int pagenum) { xps_page *page; fz_display_list *list; fz_device *dev; int start; - int code; if (showtime) { start = gettime(); } - code = xps_load_page(&page, ctx, pagenum - 1); - if (code) - die(fz_rethrow(code, "cannot load page %d in file '%s'", pagenum, filename)); + fz_try(doc->ctx) + { + page = xps_load_page(doc, pagenum - 1); + } + fz_catch(doc->ctx) + { + die(fz_error_note(1, "cannot load page %d in file '%s'", pagenum, filename)); + } list = NULL; if (uselist) { - list = fz_new_display_list(); - dev = fz_new_list_device(list); - xps_run_page(ctx, page, dev, fz_identity); + list = fz_new_display_list(doc->ctx); + dev = fz_new_list_device(doc->ctx, list); + xps_run_page(doc, page, dev, fz_identity); fz_free_device(dev); } if (showxml) { - dev = fz_new_trace_device(); + dev = fz_new_trace_device(doc->ctx); printf("<page number=\"%d\">\n", pagenum); if (list) fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox); else - xps_run_page(ctx, page, dev, fz_identity); + xps_run_page(doc, page, dev, fz_identity); printf("</page>\n"); fz_free_device(dev); } if (showtext) { - fz_text_span *text = fz_new_text_span(); - dev = fz_new_text_device(text); + fz_text_span *text = fz_new_text_span(doc->ctx); + dev = fz_new_text_device(doc->ctx, text); if (list) fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox); else - xps_run_page(ctx, page, dev, fz_identity); + xps_run_page(doc, page, dev, fz_identity); fz_free_device(dev); printf("[Page %d]\n", pagenum); if (showtext > 1) @@ -140,7 +145,7 @@ static void drawpage(xps_context *ctx, int pagenum) else fz_debug_text_span(text); printf("\n"); - fz_free_text_span(text); + fz_free_text_span(doc->ctx, text); } if (showmd5 || showtime) @@ -165,18 +170,18 @@ static void drawpage(xps_context *ctx, int pagenum) /* TODO: banded rendering and multi-page ppm */ - pix = fz_new_pixmap_with_rect(colorspace, bbox); + pix = fz_new_pixmap_with_rect(doc->ctx, colorspace, bbox); if (savealpha) fz_clear_pixmap(pix); else fz_clear_pixmap_with_color(pix, 255); - dev = fz_new_draw_device(glyphcache, pix); + dev = fz_new_draw_device(doc->ctx, glyphcache, pix); if (list) fz_execute_display_list(list, dev, ctm, bbox); else - xps_run_page(ctx, page, dev, ctm); + xps_run_page(doc, page, dev, ctm); fz_free_device(dev); if (output) @@ -184,11 +189,11 @@ static void drawpage(xps_context *ctx, int pagenum) char buf[512]; sprintf(buf, output, pagenum); if (strstr(output, ".pgm") || strstr(output, ".ppm") || strstr(output, ".pnm")) - fz_write_pnm(pix, buf); + fz_write_pnm(doc->ctx, pix, buf); else if (strstr(output, ".pam")) - fz_write_pam(pix, buf, savealpha); + fz_write_pam(doc->ctx, pix, buf, savealpha); else if (strstr(output, ".png")) - fz_write_png(pix, buf, savealpha); + fz_write_png(doc->ctx, pix, buf, savealpha); } if (showmd5) @@ -206,11 +211,11 @@ static void drawpage(xps_context *ctx, int pagenum) printf("%02x", digest[i]); } - fz_drop_pixmap(pix); + fz_drop_pixmap(doc->ctx, pix); } if (list) - fz_free_display_list(list); + fz_free_display_list(doc->ctx, list); if (showtime) { @@ -237,7 +242,7 @@ static void drawpage(xps_context *ctx, int pagenum) printf("\n"); } -static void drawrange(xps_context *ctx, char *range) +static void drawrange(xps_document *doc, char *range) { int page, spage, epage; char *spec, *dash; @@ -248,7 +253,7 @@ static void drawrange(xps_context *ctx, char *range) dash = strchr(spec, '-'); if (dash == spec) - spage = epage = xps_count_pages(ctx); + spage = epage = xps_count_pages(doc); else spage = epage = atoi(spec); @@ -257,26 +262,26 @@ static void drawrange(xps_context *ctx, char *range) if (strlen(dash) > 1) epage = atoi(dash + 1); else - epage = xps_count_pages(ctx); + epage = xps_count_pages(doc); } - spage = CLAMP(spage, 1, xps_count_pages(ctx)); - epage = CLAMP(epage, 1, xps_count_pages(ctx)); + spage = CLAMP(spage, 1, xps_count_pages(doc)); + epage = CLAMP(epage, 1, xps_count_pages(doc)); if (spage < epage) for (page = spage; page <= epage; page++) - drawpage(ctx, page); + drawpage(doc, page); else for (page = spage; page >= epage; page--) - drawpage(ctx, page); + drawpage(doc, page); spec = fz_strsep(&range, ","); } } -static void drawoutline(xps_context *ctx) +static void drawoutline(xps_document *doc) { - fz_outline *outline = xps_load_outline(ctx); + fz_outline *outline = xps_load_outline(doc); if (showoutline > 1) fz_debug_outline_xml(outline, 0); else @@ -288,8 +293,7 @@ int main(int argc, char **argv) { int grayscale = 0; int accelerate = 1; - xps_context *ctx; - int code; + xps_document *doc; int c; while ((c = fz_getopt(argc, argv, "o:p:r:Aadglmtx5")) != -1) @@ -323,7 +327,14 @@ int main(int argc, char **argv) if (accelerate) fz_accelerate(); - glyphcache = fz_new_glyph_cache(); + ctx = fz_new_context(&fz_alloc_default); + if (ctx == NULL) + { + fprintf(stderr, "failed to initialise context"); + exit(1); + } + + glyphcache = fz_new_glyph_cache(ctx); colorspace = fz_device_rgb; if (grayscale) @@ -347,28 +358,33 @@ int main(int argc, char **argv) { filename = argv[fz_optind++]; - code = xps_open_file(&ctx, filename); - if (code) - die(fz_rethrow(code, "cannot open document: %s", filename)); + fz_try(ctx) + { + doc = xps_open_file(ctx, filename); + } + fz_catch(ctx) + { + die(fz_error_note(-1, "cannot open document: %s", filename)); + } if (showxml) printf("<document name=\"%s\">\n", filename); if (showoutline) - drawoutline(ctx); + drawoutline(doc); if (showtext || showxml || showtime || showmd5 || output) { if (fz_optind == argc || !isrange(argv[fz_optind])) - drawrange(ctx, "1-"); + drawrange(doc, "1-"); if (fz_optind < argc && isrange(argv[fz_optind])) - drawrange(ctx, argv[fz_optind++]); + drawrange(doc, argv[fz_optind++]); } if (showxml) printf("</document>\n"); - xps_free_context(ctx); + xps_free_context(doc); } if (showtime) @@ -379,7 +395,8 @@ int main(int argc, char **argv) printf("slowest page %d: %dms\n", timing.maxpage, timing.max); } - fz_free_glyph_cache(glyphcache); + fz_free_glyph_cache(ctx, glyphcache); + fz_free_context(ctx); return 0; } diff --git a/draw/draw_device.c b/draw/draw_device.c index 788d8148..cb6760ea 100644 --- a/draw/draw_device.c +++ b/draw/draw_device.c @@ -53,6 +53,7 @@ struct fz_draw_device_s { fz_glyph_cache *cache; fz_gel *gel; + fz_context *ctx; fz_pixmap *dest; fz_pixmap *shape; @@ -101,20 +102,19 @@ static void fz_grow_stack(fz_draw_device *dev) if (dev->stack == &dev->init_stack[0]) { - stack = fz_malloc(sizeof(*stack) * max); + stack = fz_malloc(dev->ctx, sizeof(*stack) * max); memcpy(stack, dev->stack, sizeof(*stack) * dev->stack_max); } else { - stack = fz_realloc(dev->stack, max, sizeof(*stack)); + stack = fz_resize_array(dev->ctx, dev->stack, max, sizeof(*stack)); } dev->stack = stack; dev->stack_max = max; } -static void fz_knockout_begin(void *user) +static void fz_knockout_begin(fz_draw_device *dev) { - fz_draw_device *dev = user; fz_bbox bbox; fz_pixmap *dest, *shape; int isolated = dev->blendmode & FZ_BLEND_ISOLATED; @@ -127,7 +127,7 @@ static void fz_knockout_begin(void *user) bbox = fz_bound_pixmap(dev->dest); bbox = fz_intersect_bbox(bbox, dev->scissor); - dest = fz_new_pixmap_with_rect(dev->dest->colorspace, bbox); + dest = fz_new_pixmap_with_rect(dev->ctx, dev->dest->colorspace, bbox); if (isolated) { @@ -151,7 +151,7 @@ static void fz_knockout_begin(void *user) } else { - shape = fz_new_pixmap_with_rect(NULL, bbox); + shape = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(shape); } dev->stack[dev->top].blendmode = dev->blendmode; @@ -169,9 +169,8 @@ static void fz_knockout_begin(void *user) dev->blendmode &= ~FZ_BLEND_MODEMASK; } -static void fz_knockout_end(void *user) +static void fz_knockout_end(fz_draw_device *dev) { - fz_draw_device *dev = user; fz_pixmap *group = dev->dest; fz_pixmap *shape = dev->shape; int blendmode; @@ -212,14 +211,14 @@ static void fz_knockout_end(void *user) else fz_blend_pixmap(dev->dest, group, 255, blendmode, isolated, shape); - fz_drop_pixmap(group); + fz_drop_pixmap(dev->ctx, group); if (shape != dev->shape) { if (dev->shape) { fz_paint_pixmap(dev->shape, shape, 255); } - fz_drop_pixmap(shape); + fz_drop_pixmap(dev->ctx, shape); } #ifdef DUMP_GROUP_BLENDS fz_dump_blend(dev->dest, " to get "); @@ -231,10 +230,10 @@ static void fz_knockout_end(void *user) } static void -fz_draw_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm, +fz_draw_fill_path(fz_device *devp, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; float expansion = fz_matrix_expansion(ctm); float flatness = 0.3f / expansion; @@ -256,7 +255,7 @@ fz_draw_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm, if (dev->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_begin(dev); - fz_convert_color(colorspace, color, model, colorfv); + fz_convert_color(dev->ctx, colorspace, color, model, colorfv); for (i = 0; i < model->n; i++) colorbv[i] = colorfv[i] * 255; colorbv[i] = alpha * 255; @@ -277,10 +276,10 @@ fz_draw_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm, } static void -fz_draw_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, +fz_draw_stroke_path(fz_device *devp, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; float expansion = fz_matrix_expansion(ctm); float flatness = 0.3f / expansion; @@ -309,7 +308,7 @@ fz_draw_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matri if (dev->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_begin(dev); - fz_convert_color(colorspace, color, model, colorfv); + fz_convert_color(dev->ctx, colorspace, color, model, colorfv); for (i = 0; i < model->n; i++) colorbv[i] = colorfv[i] * 255; colorbv[i] = alpha * 255; @@ -333,9 +332,9 @@ fz_draw_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matri } static void -fz_draw_clip_path(void *user, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) +fz_draw_clip_path(fz_device *devp, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; float expansion = fz_matrix_expansion(ctm); float flatness = 0.3f / expansion; @@ -369,14 +368,14 @@ fz_draw_clip_path(void *user, fz_path *path, fz_rect *rect, int even_odd, fz_mat return; } - mask = fz_new_pixmap_with_rect(NULL, bbox); + mask = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(mask); - dest = fz_new_pixmap_with_rect(model, bbox); + dest = fz_new_pixmap_with_rect(dev->ctx, model, bbox); /* FIXME: See note #1 */ fz_clear_pixmap(dest); if (dev->shape) { - shape = fz_new_pixmap_with_rect(NULL, bbox); + shape = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(shape); } else @@ -400,9 +399,9 @@ fz_draw_clip_path(void *user, fz_path *path, fz_rect *rect, int even_odd, fz_mat } static void -fz_draw_clip_stroke_path(void *user, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) +fz_draw_clip_stroke_path(fz_device *devp, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; float expansion = fz_matrix_expansion(ctm); float flatness = 0.3f / expansion; @@ -428,14 +427,14 @@ fz_draw_clip_stroke_path(void *user, fz_path *path, fz_rect *rect, fz_stroke_sta if (rect) bbox = fz_intersect_bbox(bbox, fz_round_rect(*rect)); - mask = fz_new_pixmap_with_rect(NULL, bbox); + mask = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(mask); - dest = fz_new_pixmap_with_rect(model, bbox); + dest = fz_new_pixmap_with_rect(dev->ctx, model, bbox); /* FIXME: See note #1 */ fz_clear_pixmap(dest); if (dev->shape) { - shape = fz_new_pixmap_with_rect(NULL, bbox); + shape = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(shape); } else @@ -496,10 +495,10 @@ draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_pixmap *msk, } static void -fz_draw_fill_text(void *user, fz_text *text, fz_matrix ctm, +fz_draw_fill_text(fz_device *devp, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; unsigned char colorbv[FZ_MAX_COLORS + 1]; unsigned char shapebv; @@ -511,7 +510,7 @@ fz_draw_fill_text(void *user, fz_text *text, fz_matrix ctm, if (dev->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_begin(dev); - fz_convert_color(colorspace, color, model, colorfv); + fz_convert_color(dev->ctx, colorspace, color, model, colorfv); for (i = 0; i < model->n; i++) colorbv[i] = colorfv[i] * 255; colorbv[i] = alpha * 255; @@ -533,7 +532,7 @@ fz_draw_fill_text(void *user, fz_text *text, fz_matrix ctm, trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); - glyph = fz_render_glyph(dev->cache, text->font, gid, trm, model); + glyph = fz_render_glyph(dev->ctx, dev->cache, text->font, gid, trm, model); if (glyph) { if (glyph->n == 1) @@ -547,7 +546,7 @@ fz_draw_fill_text(void *user, fz_text *text, fz_matrix ctm, fz_matrix ctm = {glyph->w, 0.0, 0.0, -glyph->h, x + glyph->x, y + glyph->y + glyph->h}; fz_paint_image(dev->dest, dev->scissor, dev->shape, glyph, ctm, alpha * 255); } - fz_drop_pixmap(glyph); + fz_drop_pixmap(dev->ctx, glyph); } } @@ -556,10 +555,10 @@ fz_draw_fill_text(void *user, fz_text *text, fz_matrix ctm, } static void -fz_draw_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, +fz_draw_stroke_text(fz_device *devp, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; unsigned char colorbv[FZ_MAX_COLORS + 1]; float colorfv[FZ_MAX_COLORS]; @@ -570,7 +569,7 @@ fz_draw_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matri if (dev->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_begin(dev); - fz_convert_color(colorspace, color, model, colorfv); + fz_convert_color(dev->ctx, colorspace, color, model, colorfv); for (i = 0; i < model->n; i++) colorbv[i] = colorfv[i] * 255; colorbv[i] = alpha * 255; @@ -591,13 +590,13 @@ fz_draw_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matri trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); - glyph = fz_render_stroked_glyph(dev->cache, text->font, gid, trm, ctm, stroke); + glyph = fz_render_stroked_glyph(dev->ctx, dev->cache, text->font, gid, trm, ctm, stroke); if (glyph) { draw_glyph(colorbv, dev->dest, glyph, x, y, dev->scissor); if (dev->shape) draw_glyph(colorbv, dev->shape, glyph, x, y, dev->scissor); - fz_drop_pixmap(glyph); + fz_drop_pixmap(dev->ctx, glyph); } } @@ -606,9 +605,9 @@ fz_draw_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matri } static void -fz_draw_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate) +fz_draw_clip_text(fz_device *devp, fz_text *text, fz_matrix ctm, int accumulate) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; fz_bbox bbox; fz_pixmap *mask, *dest, *shape; @@ -637,14 +636,14 @@ fz_draw_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate) if (accumulate == 0 || accumulate == 1) { - mask = fz_new_pixmap_with_rect(NULL, bbox); + mask = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(mask); - dest = fz_new_pixmap_with_rect(model, bbox); + dest = fz_new_pixmap_with_rect(dev->ctx, model, bbox); /* FIXME: See note #1 */ fz_clear_pixmap(dest); if (dev->shape) { - shape = fz_new_pixmap_with_rect(NULL, bbox); + shape = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(shape); } else @@ -687,22 +686,22 @@ fz_draw_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate) trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); - glyph = fz_render_glyph(dev->cache, text->font, gid, trm, model); + glyph = fz_render_glyph(dev->ctx, dev->cache, text->font, gid, trm, model); if (glyph) { draw_glyph(NULL, mask, glyph, x, y, bbox); if (dev->shape) draw_glyph(NULL, dev->shape, glyph, x, y, bbox); - fz_drop_pixmap(glyph); + fz_drop_pixmap(dev->ctx, glyph); } } } } static void -fz_draw_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) +fz_draw_clip_stroke_text(fz_device *devp, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; fz_bbox bbox; fz_pixmap *mask, *dest, *shape; @@ -717,14 +716,14 @@ fz_draw_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_ bbox = fz_round_rect(fz_bound_text(text, ctm)); bbox = fz_intersect_bbox(bbox, dev->scissor); - mask = fz_new_pixmap_with_rect(NULL, bbox); + mask = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(mask); - dest = fz_new_pixmap_with_rect(model, bbox); + dest = fz_new_pixmap_with_rect(dev->ctx, model, bbox); /* FIXME: See note #1 */ fz_clear_pixmap(dest); if (dev->shape) { - shape = fz_new_pixmap_with_rect(NULL, bbox); + shape = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(shape); } else @@ -762,27 +761,27 @@ fz_draw_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_ trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); - glyph = fz_render_stroked_glyph(dev->cache, text->font, gid, trm, ctm, stroke); + glyph = fz_render_stroked_glyph(dev->ctx, dev->cache, text->font, gid, trm, ctm, stroke); if (glyph) { draw_glyph(NULL, mask, glyph, x, y, bbox); if (dev->shape) draw_glyph(NULL, dev->shape, glyph, x, y, bbox); - fz_drop_pixmap(glyph); + fz_drop_pixmap(dev->ctx, glyph); } } } } static void -fz_draw_ignore_text(void *user, fz_text *text, fz_matrix ctm) +fz_draw_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) { } static void -fz_draw_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) +fz_draw_fill_shade(fz_device *devp, fz_shade *shade, fz_matrix ctm, float alpha) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; fz_pixmap *dest = dev->dest; fz_rect bounds; @@ -801,13 +800,13 @@ fz_draw_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) if (!model) { - fz_warn("cannot render shading directly to an alpha mask"); + fz_warn(dev->ctx, "cannot render shading directly to an alpha mask"); return; } if (alpha < 1) { - dest = fz_new_pixmap_with_rect(dev->dest->colorspace, bbox); + dest = fz_new_pixmap_with_rect(dev->ctx, dev->dest->colorspace, bbox); fz_clear_pixmap(dest); } @@ -818,7 +817,7 @@ fz_draw_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) { unsigned char *s; int x, y, n, i; - fz_convert_color(shade->colorspace, shade->background, model, colorfv); + fz_convert_color(dev->ctx, shade->colorspace, shade->background, model, colorfv); for (i = 0; i < model->n; i++) colorbv[i] = colorfv[i] * 255; colorbv[i] = 255; @@ -846,14 +845,14 @@ fz_draw_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) } } - fz_paint_shade(shade, ctm, dest, bbox); + fz_paint_shade(dev->ctx, shade, ctm, dest, bbox); if (dev->shape) fz_clear_pixmap_rect_with_color(dev->shape, 255, bbox); if (alpha < 1) { fz_paint_pixmap(dev->dest, dest, alpha * 255); - fz_drop_pixmap(dest); + fz_drop_pixmap(dev->ctx, dest); } if (dev->blendmode & FZ_BLEND_KNOCKOUT) @@ -861,7 +860,7 @@ fz_draw_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) } static fz_pixmap * -fz_transform_pixmap(fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int dy, int gridfit) +fz_transform_pixmap(fz_context *ctx, fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int dy, int gridfit) { fz_pixmap *scaled; @@ -871,7 +870,7 @@ fz_transform_pixmap(fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int fz_matrix m = *ctm; if (gridfit) fz_gridfit_matrix(&m); - scaled = fz_scale_pixmap(image, m.e, m.f, m.a, m.d); + scaled = fz_scale_pixmap(ctx, image, m.e, m.f, m.a, m.d); if (scaled == NULL) return NULL; ctm->a = scaled->w; @@ -887,7 +886,7 @@ fz_transform_pixmap(fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int fz_matrix m = *ctm; if (gridfit) fz_gridfit_matrix(&m); - scaled = fz_scale_pixmap(image, m.f, m.e, m.b, m.c); + scaled = fz_scale_pixmap(ctx, image, m.f, m.e, m.b, m.c); if (scaled == NULL) return NULL; ctm->b = scaled->w; @@ -900,7 +899,7 @@ fz_transform_pixmap(fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int /* Downscale, non rectilinear case */ if (dx > 0 && dy > 0) { - scaled = fz_scale_pixmap(image, 0, 0, (float)dx, (float)dy); + scaled = fz_scale_pixmap(ctx, image, 0, 0, (float)dx, (float)dy); return scaled; } @@ -908,9 +907,9 @@ fz_transform_pixmap(fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int } static void -fz_draw_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) +fz_draw_fill_image(fz_device *devp, fz_pixmap *image, fz_matrix ctm, float alpha) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; fz_pixmap *converted = NULL; fz_pixmap *scaled = NULL; @@ -919,7 +918,7 @@ fz_draw_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) if (!model) { - fz_warn("cannot render image directly to an alpha mask"); + fz_warn(dev->ctx, "cannot render image directly to an alpha mask"); return; } @@ -939,8 +938,8 @@ fz_draw_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) if (image->colorspace != model && !after) { - converted = fz_new_pixmap_with_rect(model, fz_bound_pixmap(image)); - fz_convert_pixmap(image, converted); + converted = fz_new_pixmap_with_rect(dev->ctx, model, fz_bound_pixmap(image)); + fz_convert_pixmap(dev->ctx, image, converted); image = converted; } @@ -949,14 +948,14 @@ fz_draw_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) if (dx < image->w && dy < image->h) { int gridfit = alpha == 1.0f && !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3); - scaled = fz_transform_pixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy, gridfit); + scaled = fz_transform_pixmap(dev->ctx, image, &ctm, dev->dest->x, dev->dest->y, dx, dy, gridfit); if (scaled == NULL) { if (dx < 1) dx = 1; if (dy < 1) dy = 1; - scaled = fz_scale_pixmap(image, image->x, image->y, dx, dy); + scaled = fz_scale_pixmap(dev->ctx, image, image->x, image->y, dx, dy); } if (scaled != NULL) image = scaled; @@ -971,8 +970,8 @@ fz_draw_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) } else { - converted = fz_new_pixmap_with_rect(model, fz_bound_pixmap(image)); - fz_convert_pixmap(image, converted); + converted = fz_new_pixmap_with_rect(dev->ctx, model, fz_bound_pixmap(image)); + fz_convert_pixmap(dev->ctx, image, converted); image = converted; } } @@ -980,19 +979,19 @@ fz_draw_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) fz_paint_image(dev->dest, dev->scissor, dev->shape, image, ctm, alpha * 255); if (scaled) - fz_drop_pixmap(scaled); + fz_drop_pixmap(dev->ctx, scaled); if (converted) - fz_drop_pixmap(converted); + fz_drop_pixmap(dev->ctx, converted); if (dev->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_end(dev); } static void -fz_draw_fill_image_mask(void *user, fz_pixmap *image, fz_matrix ctm, +fz_draw_fill_image_mask(fz_device *devp, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; unsigned char colorbv[FZ_MAX_COLORS + 1]; float colorfv[FZ_MAX_COLORS]; @@ -1011,20 +1010,20 @@ fz_draw_fill_image_mask(void *user, fz_pixmap *image, fz_matrix ctm, if (dx < image->w && dy < image->h) { int gridfit = alpha == 1.0f && !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3); - scaled = fz_transform_pixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy, gridfit); + scaled = fz_transform_pixmap(dev->ctx, image, &ctm, dev->dest->x, dev->dest->y, dx, dy, gridfit); if (scaled == NULL) { if (dx < 1) dx = 1; if (dy < 1) dy = 1; - scaled = fz_scale_pixmap(image, image->x, image->y, dx, dy); + scaled = fz_scale_pixmap(dev->ctx, image, image->x, image->y, dx, dy); } if (scaled != NULL) image = scaled; } - fz_convert_color(colorspace, color, model, colorfv); + fz_convert_color(dev->ctx, colorspace, color, model, colorfv); for (i = 0; i < model->n; i++) colorbv[i] = colorfv[i] * 255; colorbv[i] = alpha * 255; @@ -1032,16 +1031,16 @@ fz_draw_fill_image_mask(void *user, fz_pixmap *image, fz_matrix ctm, fz_paint_image_with_color(dev->dest, dev->scissor, dev->shape, image, ctm, colorbv); if (scaled) - fz_drop_pixmap(scaled); + fz_drop_pixmap(dev->ctx, scaled); if (dev->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_begin(dev); } static void -fz_draw_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) +fz_draw_clip_image_mask(fz_device *devp, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; fz_bbox bbox; fz_pixmap *mask, *dest, *shape; @@ -1071,14 +1070,14 @@ fz_draw_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix c if (rect) bbox = fz_intersect_bbox(bbox, fz_round_rect(*rect)); - mask = fz_new_pixmap_with_rect(NULL, bbox); + mask = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(mask); - dest = fz_new_pixmap_with_rect(model, bbox); + dest = fz_new_pixmap_with_rect(dev->ctx, model, bbox); /* FIXME: See note #1 */ fz_clear_pixmap(dest); if (dev->shape) { - shape = fz_new_pixmap_with_rect(NULL, bbox); + shape = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(shape); } else @@ -1089,14 +1088,14 @@ fz_draw_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix c if (dx < image->w && dy < image->h) { int gridfit = !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3); - scaled = fz_transform_pixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy, gridfit); + scaled = fz_transform_pixmap(dev->ctx, image, &ctm, dev->dest->x, dev->dest->y, dx, dy, gridfit); if (scaled == NULL) { if (dx < 1) dx = 1; if (dy < 1) dy = 1; - scaled = fz_scale_pixmap(image, image->x, image->y, dx, dy); + scaled = fz_scale_pixmap(dev->ctx, image, image->x, image->y, dx, dy); } if (scaled != NULL) image = scaled; @@ -1105,7 +1104,7 @@ fz_draw_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix c fz_paint_image(mask, bbox, dev->shape, image, ctm, 255); if (scaled) - fz_drop_pixmap(scaled); + fz_drop_pixmap(dev->ctx, scaled); dev->stack[dev->top].scissor = dev->scissor; dev->stack[dev->top].mask = mask; @@ -1120,9 +1119,9 @@ fz_draw_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix c } static void -fz_draw_pop_clip(void *user) +fz_draw_pop_clip(fz_device *devp) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_pixmap *mask, *dest, *shape; if (dev->top > 0) { @@ -1156,11 +1155,11 @@ fz_draw_pop_clip(void *user) { assert(shape != dev->shape); fz_paint_pixmap_with_mask(shape, dev->shape, mask); - fz_drop_pixmap(dev->shape); + fz_drop_pixmap(dev->ctx, dev->shape); dev->shape = shape; } - fz_drop_pixmap(mask); - fz_drop_pixmap(dev->dest); + fz_drop_pixmap(dev->ctx, mask); + fz_drop_pixmap(dev->ctx, dev->dest); dev->dest = dest; #ifdef DUMP_GROUP_BLENDS fz_dump_blend(dev->dest, " to get "); @@ -1181,9 +1180,9 @@ fz_draw_pop_clip(void *user) } static void -fz_draw_begin_mask(void *user, fz_rect rect, int luminosity, fz_colorspace *colorspace, float *colorfv) +fz_draw_begin_mask(fz_device *devp, fz_rect rect, int luminosity, fz_colorspace *colorspace, float *colorfv) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_pixmap *dest; fz_pixmap *shape = dev->shape; fz_bbox bbox; @@ -1193,7 +1192,7 @@ fz_draw_begin_mask(void *user, fz_rect rect, int luminosity, fz_colorspace *colo bbox = fz_round_rect(rect); bbox = fz_intersect_bbox(bbox, dev->scissor); - dest = fz_new_pixmap_with_rect(fz_device_gray, bbox); + dest = fz_new_pixmap_with_rect(dev->ctx, fz_device_gray, bbox); if (dev->shape) { /* FIXME: If we ever want to support AIS true, then we @@ -1210,7 +1209,7 @@ fz_draw_begin_mask(void *user, fz_rect rect, int luminosity, fz_colorspace *colo float bc; if (!colorspace) colorspace = fz_device_gray; - fz_convert_color(colorspace, colorfv, fz_device_gray, &bc); + fz_convert_color(dev->ctx, colorspace, colorfv, fz_device_gray, &bc); fz_clear_pixmap_with_color(dest, bc * 255); if (shape) fz_clear_pixmap_with_color(shape, 255); @@ -1238,9 +1237,9 @@ fz_draw_begin_mask(void *user, fz_rect rect, int luminosity, fz_colorspace *colo } static void -fz_draw_end_mask(void *user) +fz_draw_end_mask(fz_device *devp) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_pixmap *mask = dev->dest; fz_pixmap *maskshape = dev->shape; fz_pixmap *temp, *dest; @@ -1260,13 +1259,13 @@ fz_draw_end_mask(void *user) dev->shape = dev->stack[dev->top].shape; /* convert to alpha mask */ - temp = fz_alpha_from_gray(mask, luminosity); - fz_drop_pixmap(mask); - fz_drop_pixmap(maskshape); + temp = fz_alpha_from_gray(dev->ctx, mask, luminosity); + fz_drop_pixmap(dev->ctx, mask); + fz_drop_pixmap(dev->ctx, maskshape); /* create new dest scratch buffer */ bbox = fz_bound_pixmap(temp); - dest = fz_new_pixmap_with_rect(dev->dest->colorspace, bbox); + dest = fz_new_pixmap_with_rect(dev->ctx, dev->dest->colorspace, bbox); /* FIXME: See note #1 */ fz_clear_pixmap(dest); @@ -1281,7 +1280,7 @@ fz_draw_end_mask(void *user) if (dev->shape) { dev->stack[dev->top].shape = dev->shape; - dev->shape = fz_new_pixmap_with_rect(NULL, bbox); + dev->shape = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(dev->shape); } dev->scissor = bbox; @@ -1294,16 +1293,16 @@ fz_draw_end_mask(void *user) } static void -fz_draw_begin_group(void *user, fz_rect rect, int isolated, int knockout, int blendmode, float alpha) +fz_draw_begin_group(fz_device *devp, fz_rect rect, int isolated, int knockout, int blendmode, float alpha) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; fz_bbox bbox; fz_pixmap *dest, *shape; if (dev->top == dev->stack_max) { - fz_warn("assert: too many buffers on stack"); + fz_warn(dev->ctx, "assert: too many buffers on stack"); return; } @@ -1312,7 +1311,7 @@ fz_draw_begin_group(void *user, fz_rect rect, int isolated, int knockout, int bl bbox = fz_round_rect(rect); bbox = fz_intersect_bbox(bbox, dev->scissor); - dest = fz_new_pixmap_with_rect(model, bbox); + dest = fz_new_pixmap_with_rect(dev->ctx, model, bbox); #ifndef ATTEMPT_KNOCKOUT_AND_ISOLATED knockout = 0; @@ -1336,7 +1335,7 @@ fz_draw_begin_group(void *user, fz_rect rect, int isolated, int knockout, int bl } else { - shape = fz_new_pixmap_with_rect(NULL, bbox); + shape = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox); fz_clear_pixmap(shape); } @@ -1357,9 +1356,9 @@ fz_draw_begin_group(void *user, fz_rect rect, int isolated, int knockout, int bl } static void -fz_draw_end_group(void *user) +fz_draw_end_group(fz_device *devp) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_pixmap *group = dev->dest; fz_pixmap *shape = dev->shape; int blendmode; @@ -1399,14 +1398,14 @@ fz_draw_end_group(void *user) else fz_blend_pixmap(dev->dest, group, alpha * 255, blendmode, isolated, shape); - fz_drop_pixmap(group); + fz_drop_pixmap(dev->ctx, group); if (shape != dev->shape) { if (dev->shape) { fz_paint_pixmap(dev->shape, shape, alpha * 255); } - fz_drop_pixmap(shape); + fz_drop_pixmap(dev->ctx, shape); } #ifdef DUMP_GROUP_BLENDS fz_dump_blend(dev->dest, " to get "); @@ -1421,9 +1420,9 @@ fz_draw_end_group(void *user) } static void -fz_draw_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) +fz_draw_begin_tile(fz_device *devp, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_colorspace *model = dev->dest->colorspace; fz_pixmap *dest; fz_bbox bbox; @@ -1443,7 +1442,7 @@ fz_draw_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ys * failed. */ assert(bbox.x0 > dev->dest->x || bbox.x1 < dev->dest->x + dev->dest->w || bbox.y0 > dev->dest->y || bbox.y1 < dev->dest->y + dev->dest->h); - dest = fz_new_pixmap_with_rect(model, bbox); + dest = fz_new_pixmap_with_rect(dev->ctx, model, bbox); /* FIXME: See note #1 */ fz_clear_pixmap(dest); @@ -1466,9 +1465,9 @@ fz_draw_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ys } static void -fz_draw_end_tile(void *user) +fz_draw_end_tile(fz_device *devp) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; fz_pixmap *tile = dev->dest; float xstep, ystep; fz_matrix ctm, ttm; @@ -1509,7 +1508,7 @@ fz_draw_end_tile(void *user) } } - fz_drop_pixmap(tile); + fz_drop_pixmap(dev->ctx, tile); } if (dev->blendmode & FZ_BLEND_KNOCKOUT) @@ -1517,30 +1516,31 @@ fz_draw_end_tile(void *user) } static void -fz_draw_free_user(void *user) +fz_draw_free_user(fz_device *devp) { - fz_draw_device *dev = user; + fz_draw_device *dev = devp->user; /* TODO: pop and free the stacks */ if (dev->top > 0) - fz_warn("items left on stack in draw device: %d", dev->top); + fz_warn(dev->ctx, "items left on stack in draw device: %d", dev->top); if (dev->stack != &dev->init_stack[0]) - fz_free(dev->stack); + fz_free(dev->ctx, dev->stack); fz_free_gel(dev->gel); - fz_free(dev); + fz_free(devp->ctx, dev); } fz_device * -fz_new_draw_device(fz_glyph_cache *cache, fz_pixmap *dest) +fz_new_draw_device(fz_context *ctx, fz_glyph_cache *cache, fz_pixmap *dest) { fz_device *dev; - fz_draw_device *ddev = fz_malloc(sizeof(fz_draw_device)); + fz_draw_device *ddev = fz_malloc(ctx, sizeof(fz_draw_device)); ddev->cache = cache; - ddev->gel = fz_new_gel(); + ddev->gel = fz_new_gel(ctx); ddev->dest = dest; ddev->shape = NULL; ddev->top = 0; ddev->blendmode = 0; ddev->flags = 0; + ddev->ctx = ctx; ddev->stack = &ddev->init_stack[0]; ddev->stack_max = STACK_SIZE; @@ -1549,7 +1549,7 @@ fz_new_draw_device(fz_glyph_cache *cache, fz_pixmap *dest) ddev->scissor.x1 = dest->x + dest->w; ddev->scissor.y1 = dest->y + dest->h; - dev = fz_new_device(ddev); + dev = fz_new_device(ctx, ddev); dev->free_user = fz_draw_free_user; dev->fill_path = fz_draw_fill_path; @@ -1582,9 +1582,9 @@ fz_new_draw_device(fz_glyph_cache *cache, fz_pixmap *dest) } fz_device * -fz_new_draw_device_type3(fz_glyph_cache *cache, fz_pixmap *dest) +fz_new_draw_device_type3(fz_context *ctx, fz_glyph_cache *cache, fz_pixmap *dest) { - fz_device *dev = fz_new_draw_device(cache, dest); + fz_device *dev = fz_new_draw_device(ctx, cache, dest); fz_draw_device *ddev = dev->user; ddev->flags |= FZ_DRAWDEV_FLAGS_TYPE3; return dev; diff --git a/draw/draw_edge.c b/draw/draw_edge.c index 123c3268..ec1c1ea8 100644 --- a/draw/draw_edge.c +++ b/draw/draw_edge.c @@ -15,15 +15,43 @@ static inline int fz_idiv(int a, int b) * antialiasing is done. If it is undefined to we will leave the antialiasing * accuracy as a run time choice. */ +struct fz_aa_context_s +{ + int hscale; + int vscale; + int scale; + int level; +}; +void fz_new_aa_context(fz_context *ctx) +{ #ifndef AA_BITS + ctx->aa = fz_malloc(ctx, sizeof(*ctx->aa)); + ctx->aa->hscale = 17; + ctx->aa->vscale = 15; + ctx->aa->scale = 256; + ctx->aa->level = 8; + +#define fz_aa_hscale ((ctxaa)->hscale) +#define fz_aa_vscale ((ctxaa)->vscale) +#define fz_aa_scale ((ctxaa)->scale) +#define fz_aa_level ((ctxaa)->level) #define AA_SCALE(x) ((x * fz_aa_scale) >> 8) -static int fz_aa_hscale = 17; -static int fz_aa_vscale = 15; -static int fz_aa_scale = 256; -static int fz_aa_level = 8; -#elif AA_BITS > 6 +#endif +} + +void fz_free_aa_context(fz_context *ctx) +{ +#ifndef AA_BITS + fz_free(ctx, ctx->aa); + ctx->aa = NULL; +#endif +} + +#ifdef AA_BITS + +#if AA_BITS > 6 #define AA_SCALE(x) (x) #define fz_aa_hscale 17 #define fz_aa_vscale 15 @@ -54,18 +82,21 @@ static int fz_aa_level = 8; #define fz_aa_level 0 #endif +#endif int -fz_get_aa_level(void) +fz_get_aa_level(fz_context *ctx) { + fz_aa_context *ctxaa = ctx->aa; return fz_aa_level; } void -fz_set_aa_level(int level) +fz_set_aa_level(fz_context *ctx, int level) { + fz_aa_context *ctxaa = ctx->aa; #ifdef AA_BITS - fz_warn("anti-aliasing was compiled with a fixed precision of %d bits", fz_aa_level); + fz_warn(ctx, "anti-aliasing was compiled with a fixed precision of %d bits", fz_aa_level); #else if (level > 6) { @@ -127,17 +158,19 @@ struct fz_gel_s fz_edge *edges; int acap, alen; fz_edge **active; + fz_context *ctx; }; fz_gel * -fz_new_gel(void) +fz_new_gel(fz_context *ctx) { fz_gel *gel; - gel = fz_malloc(sizeof(fz_gel)); + gel = fz_malloc(ctx, sizeof(fz_gel)); + gel->ctx = ctx; gel->cap = 512; gel->len = 0; - gel->edges = fz_calloc(gel->cap, sizeof(fz_edge)); + gel->edges = fz_malloc_array(ctx, gel->cap, sizeof(fz_edge)); gel->clip.x0 = gel->clip.y0 = BBOX_MAX; gel->clip.x1 = gel->clip.y1 = BBOX_MIN; @@ -147,7 +180,7 @@ fz_new_gel(void) gel->acap = 64; gel->alen = 0; - gel->active = fz_calloc(gel->acap, sizeof(fz_edge*)); + gel->active = fz_malloc_array(ctx, gel->acap, sizeof(fz_edge*)); return gel; } @@ -155,6 +188,8 @@ fz_new_gel(void) void fz_reset_gel(fz_gel *gel, fz_bbox clip) { + fz_aa_context *ctxaa = gel->ctx->aa; + if (fz_is_infinite_rect(clip)) { gel->clip.x0 = gel->clip.y0 = BBOX_MAX; @@ -176,15 +211,16 @@ fz_reset_gel(fz_gel *gel, fz_bbox clip) void fz_free_gel(fz_gel *gel) { - fz_free(gel->active); - fz_free(gel->edges); - fz_free(gel); + fz_free(gel->ctx, gel->active); + fz_free(gel->ctx, gel->edges); + fz_free(gel->ctx, gel); } fz_bbox fz_bound_gel(fz_gel *gel) { fz_bbox bbox; + fz_aa_context *ctxaa = gel->ctx->aa; if (gel->len == 0) return fz_empty_bbox; bbox.x0 = fz_idiv(gel->bbox.x0, fz_aa_hscale); @@ -253,7 +289,7 @@ fz_insert_gel_raw(fz_gel *gel, int x0, int y0, int x1, int y1) if (gel->len + 1 == gel->cap) { gel->cap = gel->cap + 512; - gel->edges = fz_realloc(gel->edges, gel->cap, sizeof(fz_edge)); + gel->edges = fz_resize_array(gel->ctx, gel->edges, gel->cap, sizeof(fz_edge)); } edge = &gel->edges[gel->len++]; @@ -293,6 +329,7 @@ fz_insert_gel(fz_gel *gel, float fx0, float fy0, float fx1, float fy1) { int x0, y0, x1, y1; int d, v; + fz_aa_context *ctxaa = gel->ctx->aa; fx0 = floorf(fx0 * fz_aa_hscale); fx1 = floorf(fx1 * fz_aa_hscale); @@ -443,7 +480,7 @@ insert_active(fz_gel *gel, int y, int *e) while (*e < gel->len && gel->edges[*e].y == y) { if (gel->alen + 1 == gel->acap) { int newcap = gel->acap + 64; - fz_edge **newactive = fz_realloc(gel->active, newcap, sizeof(fz_edge*)); + fz_edge **newactive = fz_resize_array(gel->ctx, gel->active, newcap, sizeof(fz_edge*)); gel->active = newactive; gel->acap = newcap; } @@ -487,7 +524,7 @@ advance_active(fz_gel *gel) * Anti-aliased scan conversion. */ -static inline void add_span_aa(int *list, int x0, int x1, int xofs) +static inline void add_span_aa(fz_aa_context *ctxaa, int *list, int x0, int x1, int xofs) { int x0pix, x0sub; int x1pix, x1sub; @@ -524,12 +561,14 @@ static inline void non_zero_winding_aa(fz_gel *gel, int *list, int xofs) int winding = 0; int x = 0; int i; + fz_aa_context *ctxaa = gel->ctx->aa; + for (i = 0; i < gel->alen; i++) { if (!winding && (winding + gel->active[i]->ydir)) x = gel->active[i]->x; if (winding && !(winding + gel->active[i]->ydir)) - add_span_aa(list, x, gel->active[i]->x, xofs); + add_span_aa(ctxaa, list, x, gel->active[i]->x, xofs); winding += gel->active[i]->ydir; } } @@ -539,17 +578,19 @@ static inline void even_odd_aa(fz_gel *gel, int *list, int xofs) int even = 0; int x = 0; int i; + fz_aa_context *ctxaa = gel->ctx->aa; + for (i = 0; i < gel->alen; i++) { if (!even) x = gel->active[i]->x; else - add_span_aa(list, x, gel->active[i]->x, xofs); + add_span_aa(ctxaa, list, x, gel->active[i]->x, xofs); even = !even; } } -static inline void undelta_aa(unsigned char * restrict out, int * restrict in, int n) +static inline void undelta_aa(fz_aa_context *ctxaa, unsigned char * restrict out, int * restrict in, int n) { int d = 0; while (n--) @@ -578,6 +619,8 @@ fz_scan_convert_aa(fz_gel *gel, int eofill, fz_bbox clip, int *deltas; int y, e; int yd, yc; + fz_context *ctx = gel->ctx; + fz_aa_context *ctxaa = ctx->aa; int xmin = fz_idiv(gel->bbox.x0, fz_aa_hscale); int xmax = fz_idiv(gel->bbox.x1, fz_aa_hscale) + 1; @@ -593,8 +636,8 @@ fz_scan_convert_aa(fz_gel *gel, int eofill, fz_bbox clip, assert(clip.x0 >= xmin); assert(clip.x1 <= xmax); - alphas = fz_malloc(xmax - xmin + 1); - deltas = fz_malloc((xmax - xmin + 1) * sizeof(int)); + alphas = fz_malloc(ctx, xmax - xmin + 1); + deltas = fz_malloc(ctx, (xmax - xmin + 1) * sizeof(int)); memset(deltas, 0, (xmax - xmin + 1) * sizeof(int)); e = 0; @@ -609,7 +652,7 @@ fz_scan_convert_aa(fz_gel *gel, int eofill, fz_bbox clip, { if (yd >= clip.y0 && yd < clip.y1) { - undelta_aa(alphas, deltas, skipx + clipn); + undelta_aa(ctxaa, alphas, deltas, skipx + clipn); blit_aa(dst, xmin + skipx, yd, alphas + skipx, clipn, color); memset(deltas, 0, (skipx + clipn) * sizeof(int)); } @@ -636,12 +679,12 @@ fz_scan_convert_aa(fz_gel *gel, int eofill, fz_bbox clip, if (yd >= clip.y0 && yd < clip.y1) { - undelta_aa(alphas, deltas, skipx + clipn); + undelta_aa(ctxaa, alphas, deltas, skipx + clipn); blit_aa(dst, xmin + skipx, yd, alphas + skipx, clipn, color); } - fz_free(deltas); - fz_free(alphas); + fz_free(ctx, deltas); + fz_free(ctx, alphas); } /* @@ -728,6 +771,8 @@ void fz_scan_convert(fz_gel *gel, int eofill, fz_bbox clip, fz_pixmap *dst, unsigned char *color) { + fz_aa_context *ctxaa = gel->ctx->aa; + if (fz_aa_level > 0) fz_scan_convert_aa(gel, eofill, clip, dst, color); else diff --git a/draw/draw_glyph.c b/draw/draw_glyph.c index 95f3955d..6cb1518a 100644 --- a/draw/draw_glyph.c +++ b/draw/draw_glyph.c @@ -22,19 +22,19 @@ struct fz_glyph_key_s }; fz_glyph_cache * -fz_new_glyph_cache(void) +fz_new_glyph_cache(fz_context *ctx) { fz_glyph_cache *cache; - cache = fz_malloc(sizeof(fz_glyph_cache)); - cache->hash = fz_new_hash_table(509, sizeof(fz_glyph_key)); + cache = fz_malloc(ctx, sizeof(fz_glyph_cache)); + cache->hash = fz_new_hash_table(ctx, 509, sizeof(fz_glyph_key)); cache->total = 0; return cache; } static void -fz_evict_glyph_cache(fz_glyph_cache *cache) +fz_evict_glyph_cache(fz_context *ctx, fz_glyph_cache *cache) { fz_glyph_key *key; fz_pixmap *pixmap; @@ -44,10 +44,10 @@ fz_evict_glyph_cache(fz_glyph_cache *cache) { key = fz_hash_get_key(cache->hash, i); if (key->font) - fz_drop_font(key->font); + fz_drop_font(ctx, key->font); pixmap = fz_hash_get_val(cache->hash, i); if (pixmap) - fz_drop_pixmap(pixmap); + fz_drop_pixmap(ctx, pixmap); } cache->total = 0; @@ -56,23 +56,23 @@ fz_evict_glyph_cache(fz_glyph_cache *cache) } void -fz_free_glyph_cache(fz_glyph_cache *cache) +fz_free_glyph_cache(fz_context *ctx, fz_glyph_cache *cache) { - fz_evict_glyph_cache(cache); + fz_evict_glyph_cache(ctx, cache); fz_free_hash(cache->hash); - fz_free(cache); + fz_free(ctx, cache); } fz_pixmap * -fz_render_stroked_glyph(fz_glyph_cache *cache, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *stroke) +fz_render_stroked_glyph(fz_context *ctx, fz_glyph_cache *cache, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *stroke) { if (font->ft_face) - return fz_render_ft_stroked_glyph(font, gid, trm, ctm, stroke); - return fz_render_glyph(cache, font, gid, trm, NULL); + return fz_render_ft_stroked_glyph(ctx, font, gid, trm, ctm, stroke); + return fz_render_glyph(ctx, cache, font, gid, trm, NULL); } fz_pixmap * -fz_render_glyph(fz_glyph_cache *cache, fz_font *font, int gid, fz_matrix ctm, fz_colorspace *model) +fz_render_glyph(fz_context *ctx, fz_glyph_cache *cache, fz_font *font, int gid, fz_matrix ctm, fz_colorspace *model) { fz_glyph_key key; fz_pixmap *val; @@ -81,7 +81,7 @@ fz_render_glyph(fz_glyph_cache *cache, fz_font *font, int gid, fz_matrix ctm, fz if (size > MAX_FONT_SIZE) { /* TODO: this case should be handled by rendering glyph as a path fill */ - fz_warn("font size too large (%g), not rendering glyph", size); + fz_warn(ctx, "font size too large (%g), not rendering glyph", size); return NULL; } @@ -104,15 +104,15 @@ fz_render_glyph(fz_glyph_cache *cache, fz_font *font, int gid, fz_matrix ctm, fz if (font->ft_face) { - val = fz_render_ft_glyph(font, gid, ctm); + val = fz_render_ft_glyph(ctx, font, gid, ctm); } else if (font->t3procs) { - val = fz_render_t3_glyph(font, gid, ctm, model); + val = fz_render_t3_glyph(ctx, font, gid, ctm, model); } else { - fz_warn("assert: uninitialized font structure"); + fz_warn(ctx, "assert: uninitialized font structure"); return NULL; } @@ -121,7 +121,7 @@ fz_render_glyph(fz_glyph_cache *cache, fz_font *font, int gid, fz_matrix ctm, fz if (val->w < MAX_GLYPH_SIZE && val->h < MAX_GLYPH_SIZE) { if (cache->total + val->w * val->h > MAX_CACHE_SIZE) - fz_evict_glyph_cache(cache); + fz_evict_glyph_cache(ctx, cache); fz_keep_font(key.font); fz_hash_insert(cache->hash, &key, val); cache->total += val->w * val->h; diff --git a/draw/draw_mesh.c b/draw/draw_mesh.c index 4254cb64..ef4ed95b 100644 --- a/draw/draw_mesh.c +++ b/draw/draw_mesh.c @@ -481,7 +481,7 @@ fz_paint_radial(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) } static void -fz_paint_mesh(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) +fz_paint_mesh(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) { float tri[3][MAXN]; fz_point p; @@ -509,7 +509,7 @@ fz_paint_mesh(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) tri[k][2] = *mesh++ * 255; else { - fz_convert_color(shade->colorspace, mesh, dest->colorspace, tri[k] + 2); + fz_convert_color(ctx, shade->colorspace, mesh, dest->colorspace, tri[k] + 2); for (i = 0; i < dest->colorspace->n; i++) tri[k][i + 2] *= 255; mesh += shade->colorspace->n; @@ -520,7 +520,7 @@ fz_paint_mesh(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) } void -fz_paint_shade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) +fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) { unsigned char clut[256][FZ_MAX_COLORS]; fz_pixmap *temp, *conv; @@ -533,13 +533,13 @@ fz_paint_shade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) { for (i = 0; i < 256; i++) { - fz_convert_color(shade->colorspace, shade->function[i], dest->colorspace, color); + fz_convert_color(ctx, shade->colorspace, shade->function[i], dest->colorspace, color); for (k = 0; k < dest->colorspace->n; k++) clut[i][k] = color[k] * 255; clut[i][k] = shade->function[i][shade->colorspace->n] * 255; } - conv = fz_new_pixmap_with_rect(dest->colorspace, bbox); - temp = fz_new_pixmap_with_rect(fz_device_gray, bbox); + conv = fz_new_pixmap_with_rect(ctx, dest->colorspace, bbox); + temp = fz_new_pixmap_with_rect(ctx, fz_device_gray, bbox); fz_clear_pixmap(temp); } else @@ -551,7 +551,7 @@ fz_paint_shade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) { case FZ_LINEAR: fz_paint_linear(shade, ctm, temp, bbox); break; case FZ_RADIAL: fz_paint_radial(shade, ctm, temp, bbox); break; - case FZ_MESH: fz_paint_mesh(shade, ctm, temp, bbox); break; + case FZ_MESH: fz_paint_mesh(ctx, shade, ctm, temp, bbox); break; } if (shade->use_function) @@ -568,7 +568,7 @@ fz_paint_shade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) *d++ = a; } fz_paint_pixmap(dest, conv, 255); - fz_drop_pixmap(conv); - fz_drop_pixmap(temp); + fz_drop_pixmap(ctx, conv); + fz_drop_pixmap(ctx, temp); } } diff --git a/draw/draw_path.c b/draw/draw_path.c index efa881ef..ca33f5f2 100644 --- a/draw/draw_path.c +++ b/draw/draw_path.c @@ -542,10 +542,7 @@ fz_flatten_stroke_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_m i = 0; if (path->len > 0 && path->items[0].k != FZ_MOVETO) - { - fz_warn("assert: path must begin with moveto"); return; - } p0.x = p0.y = 0; @@ -750,10 +747,7 @@ fz_flatten_dash_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_mat s.cap = stroke->start_cap; if (path->len > 0 && path->items[0].k != FZ_MOVETO) - { - fz_warn("assert: path must begin with moveto"); return; - } phase_len = 0; for (i = 0; i < stroke->dash_len; i++) diff --git a/draw/draw_scale.c b/draw/draw_scale.c index b7aa72f3..fd3c3798 100644 --- a/draw/draw_scale.c +++ b/draw/draw_scale.c @@ -271,7 +271,7 @@ struct fz_weights_s }; static fz_weights * -new_weights(fz_scale_filter *filter, int src_w, float dst_w, int dst_w_i, int n, int flip) +new_weights(fz_context *ctx, fz_scale_filter *filter, int src_w, float dst_w, int dst_w_i, int n, int flip) { int max_len; fz_weights *weights; @@ -297,7 +297,7 @@ new_weights(fz_scale_filter *filter, int src_w, float dst_w, int dst_w_i, int n, * plus (2+max_len)*sizeof(int) for the weights * plus room for an extra set of weights for reordering. */ - weights = fz_malloc(sizeof(*weights)+(max_len+3)*(dst_w_i+1)*sizeof(int)); + weights = fz_malloc(ctx, sizeof(*weights)+(max_len+3)*(dst_w_i+1)*sizeof(int)); if (weights == NULL) return NULL; weights->count = -1; @@ -505,7 +505,7 @@ check_weights(fz_weights *weights, int j, int w, float x, float wf) } static fz_weights * -make_weights(int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int n, int flip) +make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int n, int flip) { fz_weights *weights; float F, G; @@ -526,7 +526,7 @@ make_weights(int src_w, float x, float dst_w, fz_scale_filter *filter, int verti } window = filter->width / F; DBUG(("make_weights src_w=%d x=%g dst_w=%g dst_w_int=%d F=%g window=%g\n", src_w, x, dst_w, dst_w_int, F, window)); - weights = new_weights(filter, src_w, dst_w, dst_w_int, n, flip); + weights = new_weights(ctx, filter, src_w, dst_w, dst_w_int, n, flip); if (weights == NULL) return NULL; for (j = 0; j < dst_w_int; j++) @@ -1206,8 +1206,9 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in } #endif /* SINGLE_PIXEL_SPECIALS */ + fz_pixmap * -fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h) +fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h) { fz_scale_filter *filter = &fz_scale_filter_simple; fz_weights *contrib_rows = NULL; @@ -1289,7 +1290,7 @@ fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h) else #endif /* SINGLE_PIXEL_SPECIALS */ { - contrib_cols = make_weights(src->w, x, w, filter, 0, dst_w_int, src->n, flip_x); + contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, src->n, flip_x); if (contrib_cols == NULL) goto cleanup; } @@ -1301,14 +1302,14 @@ fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h) else #endif /* SINGLE_PIXEL_SPECIALS */ { - contrib_rows = make_weights(src->h, y, h, filter, 1, dst_h_int, src->n, flip_y); + contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, src->n, flip_y); if (contrib_rows == NULL) goto cleanup; } assert(contrib_cols == NULL || contrib_cols->count == dst_w_int); assert(contrib_rows == NULL || contrib_rows->count == dst_h_int); - output = fz_new_pixmap(src->colorspace, dst_w_int, dst_h_int); + output = fz_new_pixmap(ctx, src->colorspace, dst_w_int, dst_h_int); output->x = dst_x_int; output->y = dst_y_int; @@ -1342,7 +1343,7 @@ fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h) temp_rows = contrib_rows->max_len; if (temp_span <= 0 || temp_rows > INT_MAX / temp_span) goto cleanup; - temp = fz_calloc(temp_span*temp_rows, sizeof(int)); + temp = fz_malloc_array(ctx, temp_span*temp_rows, sizeof(int)); if (temp == NULL) goto cleanup; switch (src->n) @@ -1383,11 +1384,11 @@ fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h) DBUG(("scaling row %d from temp\n", row)); scale_row_from_temp(&output->samples[row*output->w*output->n], temp, contrib_rows, temp_span, row); } - fz_free(temp); + fz_free(ctx, temp); } cleanup: - fz_free(contrib_rows); - fz_free(contrib_cols); + fz_free(ctx, contrib_rows); + fz_free(ctx, contrib_cols); return output; } diff --git a/draw/draw_simple_scale.c b/draw/draw_simple_scale.c index c2d429b1..dcd5cd68 100644 --- a/draw/draw_simple_scale.c +++ b/draw/draw_simple_scale.c @@ -227,7 +227,7 @@ struct fz_weights_s }; static fz_weights * -new_weights(fz_scale_filter *filter, int src_w, float dst_w, int dst_w_i, int n, int flip) +new_weights(fz_context *ctx, fz_scale_filter *filter, int src_w, float dst_w, int dst_w_i, int n, int flip) { int max_len; fz_weights *weights; @@ -253,7 +253,7 @@ new_weights(fz_scale_filter *filter, int src_w, float dst_w, int dst_w_i, int n, * plus (2+max_len)*sizeof(int) for the weights * plus room for an extra set of weights for reordering. */ - weights = fz_malloc(sizeof(*weights)+(max_len+3)*(dst_w_i+1)*sizeof(int)); + weights = fz_malloc(ctx, sizeof(*weights)+(max_len+3)*(dst_w_i+1)*sizeof(int)); if (weights == NULL) return NULL; weights->count = -1; @@ -443,7 +443,7 @@ check_weights(fz_weights *weights, int j, int w, float x, float wf) } static fz_weights * -make_weights(int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int n, int flip) +make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int n, int flip) { fz_weights *weights; float F, G; @@ -464,7 +464,7 @@ make_weights(int src_w, float x, float dst_w, fz_scale_filter *filter, int verti } window = filter->width / F; DBUG(("make_weights src_w=%d x=%g dst_w=%g dst_w_int=%d F=%g window=%g\n", src_w, x, dst_w, dst_w_int, F, window)); - weights = new_weights(filter, src_w, dst_w, dst_w_int, n, flip); + weights = new_weights(ctx, filter, src_w, dst_w, dst_w_int, n, flip); if (weights == NULL) return NULL; for (j = 0; j < dst_w_int; j++) @@ -1167,7 +1167,7 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in #endif /* SINGLE_PIXEL_SPECIALS */ fz_pixmap * -fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h) +fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h) { fz_scale_filter *filter = &fz_scale_filter_simple; fz_weights *contrib_rows = NULL; @@ -1249,7 +1249,7 @@ fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h) else #endif /* SINGLE_PIXEL_SPECIALS */ { - contrib_cols = make_weights(src->w, x, w, filter, 0, dst_w_int, src->n, flip_x); + contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, src->n, flip_x); if (contrib_cols == NULL) goto cleanup; } @@ -1261,14 +1261,14 @@ fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h) else #endif /* SINGLE_PIXEL_SPECIALS */ { - contrib_rows = make_weights(src->h, y, h, filter, 1, dst_h_int, src->n, flip_y); + contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, src->n, flip_y); if (contrib_rows == NULL) goto cleanup; } assert(contrib_cols == NULL || contrib_cols->count == dst_w_int); assert(contrib_rows == NULL || contrib_rows->count == dst_h_int); - output = fz_new_pixmap(src->colorspace, dst_w_int, dst_h_int); + output = fz_new_pixmap(ctx, src->colorspace, dst_w_int, dst_h_int); output->x = dst_x_int; output->y = dst_y_int; @@ -1302,7 +1302,7 @@ fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h) temp_rows = contrib_rows->max_len; if (temp_span <= 0 || temp_rows > INT_MAX / temp_span) goto cleanup; - temp = fz_calloc(temp_span*temp_rows, sizeof(unsigned char)); + temp = fz_calloc(ctx, temp_span*temp_rows, sizeof(unsigned char)); if (temp == NULL) goto cleanup; switch (src->n) @@ -1343,11 +1343,11 @@ fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h) DBUG(("scaling row %d from temp\n", row)); scale_row_from_temp(&output->samples[row*output->w*output->n], temp, contrib_rows, temp_span, row); } - fz_free(temp); + fz_free(ctx, temp); } cleanup: - fz_free(contrib_rows); - fz_free(contrib_cols); + fz_free(ctx, contrib_rows); + fz_free(ctx, contrib_cols); return output; } diff --git a/fitz/base_context.c b/fitz/base_context.c new file mode 100644 index 00000000..d828509e --- /dev/null +++ b/fitz/base_context.c @@ -0,0 +1,77 @@ +#include "fitz.h" + +static fz_obj * +fz_resolve_indirect_null(fz_obj *ref) +{ + return ref; +} + +fz_obj *(*fz_resolve_indirect)(fz_obj*) = fz_resolve_indirect_null; + +void +fz_free_context(fz_context *ctx) +{ + if (ctx == NULL) + return; + + /* Other finalisation calls go here (in reverse order) */ + fz_free_aa_context(ctx); + fz_free_font_context(ctx); + + if (ctx->error) + { + assert(ctx->error->top == -1); + fz_free(ctx, ctx->error); + } + + /* Free the context itself */ + ctx->alloc->free(ctx->alloc->user, ctx); +} + +fz_context * +fz_new_context(fz_alloc_context *alloc) +{ + fz_context *ctx; + + ctx = alloc->malloc(alloc->user, sizeof(fz_context)); + if (!ctx) + return NULL; + memset(ctx, 0, sizeof *ctx); + ctx->alloc = alloc; + + ctx->error = fz_malloc_no_throw(ctx, sizeof(fz_error_context)); + if (!ctx->error) + goto cleanup; + ctx->error->top = -1; + ctx->error->message[0] = 0; + + ctx->warn = fz_malloc_no_throw(ctx, sizeof(fz_warn_context)); + if (!ctx->warn) + goto cleanup; + ctx->warn->message[0] = 0; + ctx->warn->count = 0; + + /* New initialisation calls for context entries go here */ + fz_try(ctx) + { + fz_new_font_context(ctx); + fz_new_aa_context(ctx); + } + fz_catch(ctx) + { + goto cleanup; + } + + return ctx; + +cleanup: + fprintf(stderr, "cannot create context\n"); + fz_free_context(ctx); + return NULL; +} + +fz_context * +fz_clone_context(fz_context *ctx) +{ + return fz_new_context(ctx->alloc); +} diff --git a/fitz/base_error.c b/fitz/base_error.c index a0efa290..b844fb6a 100644 --- a/fitz/base_error.c +++ b/fitz/base_error.c @@ -1,77 +1,109 @@ #include "fitz.h" -enum { LINE_LEN = 160, LINE_COUNT = 25 }; +/* Warning context */ -static char warn_message[LINE_LEN] = ""; -static int warn_count = 0; - -void fz_flush_warnings(void) +void fz_flush_warnings(fz_context *ctx) { - if (warn_count > 1) - fprintf(stderr, "warning: ... repeated %d times ...\n", warn_count); - warn_message[0] = 0; - warn_count = 0; + if (ctx->warn->count > 1) + fprintf(stderr, "warning: ... repeated %d times ...\n", ctx->warn->count); + ctx->warn->message[0] = 0; + ctx->warn->count = 0; } -void fz_warn(char *fmt, ...) +void fz_warn(fz_context *ctx, char *fmt, ...) { va_list ap; - char buf[LINE_LEN]; + char buf[sizeof ctx->warn->message]; va_start(ap, fmt); vsnprintf(buf, sizeof buf, fmt, ap); va_end(ap); - if (!strcmp(buf, warn_message)) + if (!strcmp(buf, ctx->warn->message)) { - warn_count++; + ctx->warn->count++; } else { - fz_flush_warnings(); + fz_flush_warnings(ctx); fprintf(stderr, "warning: %s\n", buf); - fz_strlcpy(warn_message, buf, sizeof warn_message); - warn_count = 1; + fz_strlcpy(ctx->warn->message, buf, sizeof ctx->warn->message); + ctx->warn->count = 1; } } -static char error_message[LINE_COUNT][LINE_LEN]; -static int error_count = 0; +/* Error context */ -static void -fz_emit_error(char what, char *location, char *message) +static void throw(fz_error_context *ex) { - fz_flush_warnings(); - - fprintf(stderr, "%c %s%s\n", what, location, message); + if (ex->top >= 0) { + longjmp(ex->stack[ex->top--].buffer, 1); + } else { + fprintf(stderr, "uncaught exception: %s\n", ex->message); + exit(EXIT_FAILURE); + } +} - if (error_count < LINE_COUNT) +void fz_push_try(fz_error_context *ex) +{ + assert(ex != NULL); + if (ex->top + 1 >= nelem(ex->stack)) { - fz_strlcpy(error_message[error_count], location, LINE_LEN); - fz_strlcat(error_message[error_count], message, LINE_LEN); - error_count++; + fprintf(stderr, "exception stack overflow!\n"); + exit(EXIT_FAILURE); } + ex->top++; +} + +char *fz_caught(fz_context *ctx) +{ + assert(ctx != NULL); + assert(ctx->error != NULL); + return ctx->error->message; +} + +void fz_throw(fz_context *ctx, char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vsnprintf(ctx->error->message, sizeof ctx->error->message, fmt, args); + va_end(args); + + fprintf(stderr, "error: %s\n", ctx->error->message); + + throw(ctx->error); +} + +void fz_rethrow(fz_context *ctx) +{ + throw(ctx->error); +} + +/* Deprecated error bubbling */ + +static void +fz_emit_error(char what, char *location, char *message) +{ + fprintf(stderr, "%c %s%s\n", what, location, message); } int fz_get_error_count(void) { - return error_count; + return 0; } char * fz_get_error_line(int n) { - return error_message[n]; + return ""; } fz_error -fz_throw_imp(const char *file, int line, const char *func, char *fmt, ...) +fz_error_make_imp(const char *file, int line, const char *func, char *fmt, ...) { va_list ap; - char one[LINE_LEN], two[LINE_LEN]; - - error_count = 0; + char one[256], two[256]; snprintf(one, sizeof one, "%s:%d: %s(): ", file, line, func); va_start(ap, fmt); @@ -84,10 +116,10 @@ fz_throw_imp(const char *file, int line, const char *func, char *fmt, ...) } fz_error -fz_rethrow_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) +fz_error_note_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) { va_list ap; - char one[LINE_LEN], two[LINE_LEN]; + char one[256], two[256]; snprintf(one, sizeof one, "%s:%d: %s(): ", file, line, func); va_start(ap, fmt); @@ -100,10 +132,10 @@ fz_rethrow_imp(const char *file, int line, const char *func, fz_error cause, cha } void -fz_catch_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) +fz_error_handle_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) { va_list ap; - char one[LINE_LEN], two[LINE_LEN]; + char one[256], two[256]; snprintf(one, sizeof one, "%s:%d: %s(): ", file, line, func); va_start(ap, fmt); @@ -114,12 +146,10 @@ fz_catch_imp(const char *file, int line, const char *func, fz_error cause, char } fz_error -fz_throw_impx(char *fmt, ...) +fz_error_make_impx(char *fmt, ...) { va_list ap; - char buf[LINE_LEN]; - - error_count = 0; + char buf[256]; va_start(ap, fmt); vsnprintf(buf, sizeof buf, fmt, ap); @@ -131,10 +161,10 @@ fz_throw_impx(char *fmt, ...) } fz_error -fz_rethrow_impx(fz_error cause, char *fmt, ...) +fz_error_note_impx(fz_error cause, char *fmt, ...) { va_list ap; - char buf[LINE_LEN]; + char buf[256]; va_start(ap, fmt); vsnprintf(buf, sizeof buf, fmt, ap); @@ -146,10 +176,10 @@ fz_rethrow_impx(fz_error cause, char *fmt, ...) } void -fz_catch_impx(fz_error cause, char *fmt, ...) +fz_error_handle_impx(fz_error cause, char *fmt, ...) { va_list ap; - char buf[LINE_LEN]; + char buf[256]; va_start(ap, fmt); vsnprintf(buf, sizeof buf, fmt, ap); diff --git a/fitz/base_hash.c b/fitz/base_hash.c index fcfc1f61..d6ff8ca0 100644 --- a/fitz/base_hash.c +++ b/fitz/base_hash.c @@ -19,6 +19,7 @@ struct fz_hash_entry_s struct fz_hash_table_s { + fz_context *ctx; int keylen; int size; int load; @@ -42,17 +43,18 @@ static unsigned hash(unsigned char *s, int len) } fz_hash_table * -fz_new_hash_table(int initialsize, int keylen) +fz_new_hash_table(fz_context *ctx, int initialsize, int keylen) { fz_hash_table *table; assert(keylen <= MAX_KEY_LEN); - table = fz_malloc(sizeof(fz_hash_table)); + table = fz_malloc(ctx, sizeof(fz_hash_table)); + table->ctx = ctx; table->keylen = keylen; table->size = initialsize; table->load = 0; - table->ents = fz_calloc(table->size, sizeof(fz_hash_entry)); + table->ents = fz_malloc_array(ctx, table->size, sizeof(fz_hash_entry)); memset(table->ents, 0, sizeof(fz_hash_entry) * table->size); return table; @@ -86,8 +88,8 @@ fz_hash_get_val(fz_hash_table *table, int idx) void fz_free_hash(fz_hash_table *table) { - fz_free(table->ents); - fz_free(table); + fz_free(table->ctx, table->ents); + fz_free(table->ctx, table); } static void @@ -100,11 +102,11 @@ fz_resize_hash(fz_hash_table *table, int newsize) if (newsize < oldload * 8 / 10) { - fz_throw("assert: resize hash too small"); + fz_warn(table->ctx, "assert: resize hash too small"); return; } - table->ents = fz_calloc(newsize, sizeof(fz_hash_entry)); + table->ents = fz_malloc_array(table->ctx, newsize, sizeof(fz_hash_entry)); memset(table->ents, 0, sizeof(fz_hash_entry) * newsize); table->size = newsize; table->load = 0; @@ -117,7 +119,7 @@ fz_resize_hash(fz_hash_table *table, int newsize) } } - fz_free(oldents); + fz_free(table->ctx, oldents); } void * @@ -166,7 +168,7 @@ fz_hash_insert(fz_hash_table *table, void *key, void *val) } if (memcmp(key, ents[pos].key, table->keylen) == 0) - fz_warn("assert: overwrite hash slot"); + fz_warn(table->ctx, "assert: overwrite hash slot"); pos = (pos + 1) % size; } @@ -184,7 +186,7 @@ fz_hash_remove(fz_hash_table *table, void *key) { if (!ents[pos].val) { - fz_warn("assert: remove inexistant hash entry"); + fz_warn(table->ctx, "assert: remove inexistant hash entry"); return; } diff --git a/fitz/base_memory.c b/fitz/base_memory.c index f1b668eb..43ec0dd9 100644 --- a/fitz/base_memory.c +++ b/fitz/base_memory.c @@ -1,77 +1,181 @@ #include "fitz.h" void * -fz_malloc(int size) +fz_malloc(fz_context *ctx, unsigned int size) { - void *p = malloc(size); - if (!p) + void *p = ctx->alloc->malloc(ctx->alloc->user, size); + if (p == NULL) + fz_throw(ctx, "malloc of %d bytes failed", size); + return p; +} + +void * +fz_malloc_no_throw(fz_context *ctx, unsigned int size) +{ + return ctx->alloc->malloc(ctx->alloc->user, size); +} + +void * +fz_malloc_array(fz_context *ctx, unsigned int count, unsigned int size) +{ + void *p; + + if (count == 0 || size == 0) + return 0; + + if (count > UINT_MAX / size) + fz_throw(ctx, "malloc of array (%d x %d bytes) failed (integer overflow)", count, size); + + p = ctx->alloc->malloc(ctx->alloc->user, count * size); + if (p == NULL) + fz_throw(ctx, "malloc of array (%d x %d bytes) failed", count, size); + return p; +} + +void * +fz_malloc_array_no_throw(fz_context *ctx, unsigned int count, unsigned int size) +{ + if (count == 0 || size == 0) + return 0; + + if (count > UINT_MAX / size) { - fprintf(stderr, "fatal error: out of memory\n"); - abort(); + fprintf(stderr, "error: malloc of array (%d x %d bytes) failed (integer overflow)", count, size); + return NULL; } + + return ctx->alloc->malloc(ctx->alloc->user, count * size); +} + +void * +fz_calloc(fz_context *ctx, unsigned int count, unsigned int size) +{ + void *p; + + if (count == 0 || size == 0) + return 0; + + if (count > UINT_MAX / size) + { + fz_throw(ctx, "calloc (%d x %d bytes) failed (integer overflow)", count, size); + } + + p = ctx->alloc->malloc(ctx->alloc->user, count * size); + if (p == NULL) + { + fz_throw(ctx, "calloc (%d x %d bytes) failed", count, size); + } + memset(p, 0, count*size); return p; } void * -fz_calloc(int count, int size) +fz_calloc_no_throw(fz_context *ctx, unsigned int count, unsigned int size) { void *p; if (count == 0 || size == 0) return 0; - if (count < 0 || size < 0 || count > INT_MAX / size) + if (count > UINT_MAX / size) { - fprintf(stderr, "fatal error: out of memory (integer overflow)\n"); - abort(); + fprintf(stderr, "error: calloc (%d x %d bytes) failed (integer overflow)\n", count, size); + return NULL; } - p = malloc(count * size); - if (!p) + p = ctx->alloc->malloc(ctx->alloc->user, count * size); + if (p != NULL) { - fprintf(stderr, "fatal error: out of memory\n"); - abort(); + memset(p, 0, count*size); } return p; } void * -fz_realloc(void *p, int count, int size) +fz_resize_array(fz_context *ctx, void *p, unsigned int count, unsigned int size) { void *np; if (count == 0 || size == 0) { - fz_free(p); + fz_free(ctx, p); return 0; } - if (count < 0 || size < 0 || count > INT_MAX / size) + if (count > UINT_MAX / size) + fz_throw(ctx, "resize array (%d x %d bytes) failed (integer overflow)", count, size); + + np = ctx->alloc->realloc(ctx->alloc->user, p, count * size); + if (np == NULL) + fz_throw(ctx, "resize array (%d x %d bytes) failed", count, size); + return np; +} + +void * +fz_resize_array_no_throw(fz_context *ctx, void *p, unsigned int count, unsigned int size) +{ + if (count == 0 || size == 0) { - fprintf(stderr, "fatal error: out of memory (integer overflow)\n"); - abort(); + fz_free(ctx, p); + return 0; } - np = realloc(p, count * size); - if (np == NULL) + if (count > UINT_MAX / size) { - fprintf(stderr, "fatal error: out of memory\n"); - abort(); + fprintf(stderr, "error: resize array (%d x %d bytes) failed (integer overflow)\n", count, size); + return NULL; } - return np; + + return ctx->alloc->realloc(ctx->alloc->user, p, count * size); } void -fz_free(void *p) +fz_free(fz_context *ctx, void *p) { - free(p); + ctx->alloc->free(ctx->alloc->user, p); } char * -fz_strdup(char *s) +fz_strdup(fz_context *ctx, char *s) { int len = strlen(s) + 1; - char *ns = fz_malloc(len); + char *ns = fz_malloc(ctx, len); memcpy(ns, s, len); return ns; } + +char * +fz_strdup_no_throw(fz_context *ctx, char *s) +{ + int len = strlen(s) + 1; + char *ns = fz_malloc_no_throw(ctx, len); + if (ns != NULL) + memcpy(ns, s, len); + return ns; +} + +static void * +fz_malloc_default(void *opaque, unsigned int size) +{ + return malloc(size); +} + +static void * +fz_realloc_default(void *opaque, void *old, unsigned int size) +{ + return realloc(old, size); +} + +static void +fz_free_default(void *opaque, void *ptr) +{ + free(ptr); +} + +fz_alloc_context fz_alloc_default = +{ + NULL, + fz_malloc_default, + fz_realloc_default, + fz_free_default +} ;
\ No newline at end of file diff --git a/fitz/base_object.c b/fitz/base_object.c index 8e8ac313..8c79e4c6 100644 --- a/fitz/base_object.c +++ b/fitz/base_object.c @@ -23,6 +23,7 @@ struct fz_obj_s { int refs; fz_objkind kind; + fz_context *ctx; union { int b; @@ -52,26 +53,21 @@ struct fz_obj_s } u; }; -static fz_obj *fz_resolve_indirect_null(fz_obj *ref) -{ - return ref; -} - -fz_obj* (*fz_resolve_indirect)(fz_obj*) = fz_resolve_indirect_null; - fz_obj * -fz_new_null(void) +fz_new_null(fz_context *ctx) { - fz_obj *obj = fz_malloc(sizeof(fz_obj)); + fz_obj *obj = fz_malloc(ctx, sizeof(fz_obj)); + obj->ctx = ctx; obj->refs = 1; obj->kind = FZ_NULL; return obj; } fz_obj * -fz_new_bool(int b) +fz_new_bool(fz_context *ctx, int b) { - fz_obj *obj = fz_malloc(sizeof(fz_obj)); + fz_obj *obj = fz_malloc(ctx, sizeof(fz_obj)); + obj->ctx = ctx; obj->refs = 1; obj->kind = FZ_BOOL; obj->u.b = b; @@ -79,9 +75,10 @@ fz_new_bool(int b) } fz_obj * -fz_new_int(int i) +fz_new_int(fz_context *ctx, int i) { - fz_obj *obj = fz_malloc(sizeof(fz_obj)); + fz_obj *obj = fz_malloc(ctx, sizeof(fz_obj)); + obj->ctx = ctx; obj->refs = 1; obj->kind = FZ_INT; obj->u.i = i; @@ -89,9 +86,10 @@ fz_new_int(int i) } fz_obj * -fz_new_real(float f) +fz_new_real(fz_context *ctx, float f) { - fz_obj *obj = fz_malloc(sizeof(fz_obj)); + fz_obj *obj = fz_malloc(ctx, sizeof(fz_obj)); + obj->ctx = ctx; obj->refs = 1; obj->kind = FZ_REAL; obj->u.f = f; @@ -99,9 +97,10 @@ fz_new_real(float f) } fz_obj * -fz_new_string(char *str, int len) +fz_new_string(fz_context *ctx, char *str, int len) { - fz_obj *obj = fz_malloc(offsetof(fz_obj, u.s.buf) + len + 1); + fz_obj *obj = fz_malloc(ctx, offsetof(fz_obj, u.s.buf) + len + 1); + obj->ctx = ctx; obj->refs = 1; obj->kind = FZ_STRING; obj->u.s.len = len; @@ -111,9 +110,10 @@ fz_new_string(char *str, int len) } fz_obj * -fz_new_name(char *str) +fz_new_name(fz_context *ctx, char *str) { - fz_obj *obj = fz_malloc(offsetof(fz_obj, u.n) + strlen(str) + 1); + fz_obj *obj = fz_malloc(ctx, offsetof(fz_obj, u.n) + strlen(str) + 1); + obj->ctx = ctx; obj->refs = 1; obj->kind = FZ_NAME; strcpy(obj->u.n, str); @@ -121,9 +121,10 @@ fz_new_name(char *str) } fz_obj * -fz_new_indirect(int num, int gen, void *xref) +fz_new_indirect(fz_context *ctx, int num, int gen, void *xref) { - fz_obj *obj = fz_malloc(sizeof(fz_obj)); + fz_obj *obj = fz_malloc(ctx, sizeof(fz_obj)); + obj->ctx = ctx; obj->refs = 1; obj->kind = FZ_INDIRECT; obj->u.r.num = num; @@ -375,19 +376,20 @@ fz_objkindstr(fz_obj *obj) } fz_obj * -fz_new_array(int initialcap) +fz_new_array(fz_context *ctx, int initialcap) { fz_obj *obj; int i; - obj = fz_malloc(sizeof(fz_obj)); + obj = fz_malloc(ctx, sizeof(fz_obj)); + obj->ctx = ctx; 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*)); + obj->u.a.items = fz_malloc_array(ctx, obj->u.a.cap, sizeof(fz_obj*)); for (i = 0; i < obj->u.a.cap; i++) obj->u.a.items[i] = NULL; @@ -400,23 +402,25 @@ fz_array_grow(fz_obj *obj) int i; obj->u.a.cap = (obj->u.a.cap * 3) / 2; - obj->u.a.items = fz_realloc(obj->u.a.items, obj->u.a.cap, sizeof(fz_obj*)); + obj->u.a.items = fz_resize_array(obj->ctx, obj->u.a.items, obj->u.a.cap, sizeof(fz_obj*)); for (i = obj->u.a.len ; i < obj->u.a.cap; i++) obj->u.a.items[i] = NULL; } fz_obj * -fz_copy_array(fz_obj *obj) +fz_copy_array(fz_context *ctx, fz_obj *obj) { fz_obj *new; int i; + int n; if (fz_is_indirect(obj) || !fz_is_array(obj)) - fz_warn("assert: not an array (%s)", fz_objkindstr(obj)); + fz_warn(obj->ctx, "assert: not an array (%s)", fz_objkindstr(obj)); - new = fz_new_array(fz_array_len(obj)); - for (i = 0; i < fz_array_len(obj); i++) + new = fz_new_array(ctx, fz_array_len(obj)); + n = fz_array_len(obj); + for (i = 0; i < n; i++) fz_array_push(new, fz_array_get(obj, i)); return new; @@ -451,11 +455,11 @@ fz_array_put(fz_obj *obj, int i, fz_obj *item) obj = fz_resolve_indirect(obj); if (!fz_is_array(obj)) - fz_warn("assert: not an array (%s)", fz_objkindstr(obj)); + fz_warn(obj->ctx, "assert: not an array (%s)", fz_objkindstr(obj)); else if (i < 0) - fz_warn("assert: index %d < 0", i); + fz_warn(obj->ctx, "assert: index %d < 0", i); else if (i >= obj->u.a.len) - fz_warn("assert: index %d > length %d", i, obj->u.a.len); + fz_warn(obj->ctx, "assert: index %d > length %d", i, obj->u.a.len); else { if (obj->u.a.items[i]) @@ -470,7 +474,7 @@ fz_array_push(fz_obj *obj, fz_obj *item) obj = fz_resolve_indirect(obj); if (!fz_is_array(obj)) - fz_warn("assert: not an array (%s)", fz_objkindstr(obj)); + fz_warn(obj->ctx, "assert: not an array (%s)", fz_objkindstr(obj)); else { if (obj->u.a.len + 1 > obj->u.a.cap) @@ -486,7 +490,7 @@ fz_array_insert(fz_obj *obj, fz_obj *item) obj = fz_resolve_indirect(obj); if (!fz_is_array(obj)) - fz_warn("assert: not an array (%s)", fz_objkindstr(obj)); + fz_warn(obj->ctx, "assert: not an array (%s)", fz_objkindstr(obj)); else { if (obj->u.a.len + 1 > obj->u.a.cap) @@ -519,12 +523,13 @@ static int keyvalcmp(const void *ap, const void *bp) } fz_obj * -fz_new_dict(int initialcap) +fz_new_dict(fz_context *ctx, int initialcap) { fz_obj *obj; int i; - obj = fz_malloc(sizeof(fz_obj)); + obj = fz_malloc(ctx, sizeof(fz_obj)); + obj->ctx = ctx; obj->refs = 1; obj->kind = FZ_DICT; @@ -532,7 +537,7 @@ fz_new_dict(int initialcap) obj->u.d.len = 0; obj->u.d.cap = initialcap > 1 ? initialcap : 10; - obj->u.d.items = fz_calloc(obj->u.d.cap, sizeof(struct keyval)); + obj->u.d.items = fz_malloc_array(ctx, obj->u.d.cap, sizeof(struct keyval)); for (i = 0; i < obj->u.d.cap; i++) { obj->u.d.items[i].k = NULL; @@ -548,7 +553,7 @@ fz_dict_grow(fz_obj *obj) int i; obj->u.d.cap = (obj->u.d.cap * 3) / 2; - obj->u.d.items = fz_realloc(obj->u.d.items, obj->u.d.cap, sizeof(struct keyval)); + obj->u.d.items = fz_resize_array(obj->ctx, obj->u.d.items, obj->u.d.cap, sizeof(struct keyval)); for (i = obj->u.d.len; i < obj->u.d.cap; i++) { @@ -558,16 +563,17 @@ fz_dict_grow(fz_obj *obj) } fz_obj * -fz_copy_dict(fz_obj *obj) +fz_copy_dict(fz_context *ctx, fz_obj *obj) { fz_obj *new; - int i; + int i, n; if (fz_is_indirect(obj) || !fz_is_dict(obj)) - fz_throw("assert: not a dict (%s)", fz_objkindstr(obj)); + fz_warn(ctx, "assert: not a dict (%s)", fz_objkindstr(obj)); - new = fz_new_dict(fz_dict_len(obj)); - for (i = 0; i < fz_dict_len(obj); i++) + n = fz_dict_len(obj); + new = fz_new_dict(ctx, n); + for (i = 0; i < n; i++) fz_dict_put(new, fz_dict_get_key(obj, i), fz_dict_get_val(obj, i)); return new; @@ -701,7 +707,7 @@ fz_dict_put(fz_obj *obj, fz_obj *key, fz_obj *val) if (!fz_is_dict(obj)) { - fz_warn("assert: not a dict (%s)", fz_objkindstr(obj)); + fz_warn(obj->ctx, "assert: not a dict (%s)", fz_objkindstr(obj)); return; } @@ -709,13 +715,13 @@ fz_dict_put(fz_obj *obj, fz_obj *key, fz_obj *val) s = fz_to_name(key); else { - fz_warn("assert: key is not a name (%s)", fz_objkindstr(obj)); + fz_warn(obj->ctx, "assert: key is not a name (%s)", fz_objkindstr(obj)); return; } if (!val) { - fz_warn("assert: val does not exist for key (%s)", s); + fz_warn(obj->ctx, "assert: val does not exist for key (%s)", s); return; } @@ -748,7 +754,7 @@ fz_dict_put(fz_obj *obj, fz_obj *key, fz_obj *val) void fz_dict_puts(fz_obj *obj, char *key, fz_obj *val) { - fz_obj *keyobj = fz_new_name(key); + fz_obj *keyobj = fz_new_name(obj->ctx, key); fz_dict_put(obj, keyobj, val); fz_drop_obj(keyobj); } @@ -759,7 +765,7 @@ fz_dict_dels(fz_obj *obj, char *key) obj = fz_resolve_indirect(obj); if (!fz_is_dict(obj)) - fz_warn("assert: not a dict (%s)", fz_objkindstr(obj)); + fz_warn(obj->ctx, "assert: not a dict (%s)", fz_objkindstr(obj)); else { int i = fz_dict_finds(obj, key, NULL); @@ -780,7 +786,7 @@ fz_dict_del(fz_obj *obj, fz_obj *key) if (fz_is_name(key)) fz_dict_dels(obj, fz_to_name(key)); else - fz_warn("assert: key is not a name (%s)", fz_objkindstr(obj)); + fz_warn(obj->ctx, "assert: key is not a name (%s)", fz_objkindstr(obj)); } void @@ -805,8 +811,8 @@ fz_free_array(fz_obj *obj) if (obj->u.a.items[i]) fz_drop_obj(obj->u.a.items[i]); - fz_free(obj->u.a.items); - fz_free(obj); + fz_free(obj->ctx, obj->u.a.items); + fz_free(obj->ctx, obj); } static void @@ -821,21 +827,357 @@ fz_free_dict(fz_obj *obj) fz_drop_obj(obj->u.d.items[i].v); } - fz_free(obj->u.d.items); - fz_free(obj); + fz_free(obj->ctx, obj->u.d.items); + fz_free(obj->ctx, obj); } void fz_drop_obj(fz_obj *obj) { - assert(obj != NULL); - if (--obj->refs == 0) + if (obj == NULL) + return; + if (--obj->refs) + return; + if (obj->kind == FZ_ARRAY) + fz_free_array(obj); + else if (obj->kind == FZ_DICT) + fz_free_dict(obj); + else + fz_free(obj->ctx, obj); +} + +/* Pretty printing objects */ + +struct fmt +{ + char *buf; + int cap; + int len; + int indent; + int tight; + int col; + int sep; + int last; +}; + +static void fmt_obj(struct fmt *fmt, fz_obj *obj); + +static inline int iswhite(int ch) +{ + return + ch == '\000' || + ch == '\011' || + ch == '\012' || + ch == '\014' || + ch == '\015' || + ch == '\040'; +} + +static inline int isdelim(int ch) +{ + return ch == '(' || ch == ')' || + ch == '<' || ch == '>' || + ch == '[' || ch == ']' || + ch == '{' || ch == '}' || + ch == '/' || + ch == '%'; +} + +static inline void fmt_putc(struct fmt *fmt, int c) +{ + if (fmt->sep && !isdelim(fmt->last) && !isdelim(c)) { + fmt->sep = 0; + fmt_putc(fmt, ' '); + } + fmt->sep = 0; + + if (fmt->buf && fmt->len < fmt->cap) + fmt->buf[fmt->len] = c; + + if (c == '\n') + fmt->col = 0; + else + fmt->col ++; + + fmt->len ++; + + fmt->last = c; +} + +static inline void fmt_indent(struct fmt *fmt) +{ + int i = fmt->indent; + while (i--) { + fmt_putc(fmt, ' '); + fmt_putc(fmt, ' '); + } +} + +static inline void fmt_puts(struct fmt *fmt, char *s) +{ + while (*s) + fmt_putc(fmt, *s++); +} + +static inline void fmt_sep(struct fmt *fmt) +{ + fmt->sep = 1; +} + +static void fmt_str(struct fmt *fmt, fz_obj *obj) +{ + char *s = fz_to_str_buf(obj); + int n = fz_to_str_len(obj); + int i, c; + + fmt_putc(fmt, '('); + for (i = 0; i < n; i++) + { + c = (unsigned char)s[i]; + if (c == '\n') + fmt_puts(fmt, "\\n"); + else if (c == '\r') + fmt_puts(fmt, "\\r"); + else if (c == '\t') + fmt_puts(fmt, "\\t"); + else if (c == '\b') + fmt_puts(fmt, "\\b"); + else if (c == '\f') + fmt_puts(fmt, "\\f"); + else if (c == '(') + fmt_puts(fmt, "\\("); + else if (c == ')') + fmt_puts(fmt, "\\)"); + else if (c < 32 || c >= 127) { + char buf[16]; + fmt_putc(fmt, '\\'); + sprintf(buf, "%03o", c); + fmt_puts(fmt, buf); + } + else + fmt_putc(fmt, c); + } + fmt_putc(fmt, ')'); +} + +static void fmt_hex(struct fmt *fmt, fz_obj *obj) +{ + char *s = fz_to_str_buf(obj); + int n = fz_to_str_len(obj); + int i, b, c; + + fmt_putc(fmt, '<'); + for (i = 0; i < n; i++) { + b = (unsigned char) s[i]; + c = (b >> 4) & 0x0f; + fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); + c = (b) & 0x0f; + fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); + } + fmt_putc(fmt, '>'); +} + +static void fmt_name(struct fmt *fmt, fz_obj *obj) +{ + unsigned char *s = (unsigned char *) fz_to_name(obj); + int i, c; + + fmt_putc(fmt, '/'); + + for (i = 0; s[i]; i++) + { + if (isdelim(s[i]) || iswhite(s[i]) || + s[i] == '#' || s[i] < 32 || s[i] >= 127) + { + fmt_putc(fmt, '#'); + c = (s[i] >> 4) & 0xf; + fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); + c = s[i] & 0xf; + fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); + } + else + { + fmt_putc(fmt, s[i]); + } + } +} + +static void fmt_array(struct fmt *fmt, fz_obj *obj) +{ + int i, n; + + n = fz_array_len(obj); + if (fmt->tight) { + fmt_putc(fmt, '['); + for (i = 0; i < n; i++) { + fmt_obj(fmt, fz_array_get(obj, i)); + fmt_sep(fmt); + } + fmt_putc(fmt, ']'); + } + else { + fmt_puts(fmt, "[ "); + for (i = 0; i < n; i++) { + if (fmt->col > 60) { + fmt_putc(fmt, '\n'); + fmt_indent(fmt); + } + fmt_obj(fmt, fz_array_get(obj, i)); + fmt_putc(fmt, ' '); + } + fmt_putc(fmt, ']'); + fmt_sep(fmt); + } +} + +static void fmt_dict(struct fmt *fmt, fz_obj *obj) +{ + int i, n; + fz_obj *key, *val; + + n = fz_dict_len(obj); + if (fmt->tight) { + fmt_puts(fmt, "<<"); + for (i = 0; i < n; i++) { + fmt_obj(fmt, fz_dict_get_key(obj, i)); + fmt_sep(fmt); + fmt_obj(fmt, fz_dict_get_val(obj, i)); + fmt_sep(fmt); + } + fmt_puts(fmt, ">>"); + } + else { + fmt_puts(fmt, "<<\n"); + fmt->indent ++; + for (i = 0; i < n; i++) { + key = fz_dict_get_key(obj, i); + val = fz_dict_get_val(obj, i); + fmt_indent(fmt); + fmt_obj(fmt, key); + fmt_putc(fmt, ' '); + if (!fz_is_indirect(val) && fz_is_array(val)) + fmt->indent ++; + fmt_obj(fmt, val); + fmt_putc(fmt, '\n'); + if (!fz_is_indirect(val) && fz_is_array(val)) + fmt->indent --; + } + fmt->indent --; + fmt_indent(fmt); + fmt_puts(fmt, ">>"); + } +} + +static void fmt_obj(struct fmt *fmt, fz_obj *obj) +{ + char buf[256]; + + if (!obj) + fmt_puts(fmt, "<NULL>"); + else if (fz_is_indirect(obj)) + { + sprintf(buf, "%d %d R", fz_to_num(obj), fz_to_gen(obj)); + fmt_puts(fmt, buf); + } + else if (fz_is_null(obj)) + fmt_puts(fmt, "null"); + else if (fz_is_bool(obj)) + fmt_puts(fmt, fz_to_bool(obj) ? "true" : "false"); + else if (fz_is_int(obj)) + { + sprintf(buf, "%d", fz_to_int(obj)); + fmt_puts(fmt, buf); + } + else if (fz_is_real(obj)) + { + sprintf(buf, "%g", fz_to_real(obj)); + if (strchr(buf, 'e')) /* bad news! */ + sprintf(buf, fabsf(fz_to_real(obj)) > 1 ? "%1.1f" : "%1.8f", fz_to_real(obj)); + fmt_puts(fmt, buf); + } + else if (fz_is_string(obj)) { - if (obj->kind == FZ_ARRAY) - fz_free_array(obj); - else if (obj->kind == FZ_DICT) - fz_free_dict(obj); + char *str = fz_to_str_buf(obj); + int len = fz_to_str_len(obj); + int added = 0; + int i, c; + for (i = 0; i < len; i++) { + c = (unsigned char)str[i]; + if (strchr("()\\\n\r\t\b\f", c)) + added ++; + else if (c < 32 || c >= 127) + added += 3; + } + if (added < len) + fmt_str(fmt, obj); else - fz_free(obj); + fmt_hex(fmt, obj); } + else if (fz_is_name(obj)) + fmt_name(fmt, obj); + else if (fz_is_array(obj)) + fmt_array(fmt, obj); + else if (fz_is_dict(obj)) + fmt_dict(fmt, obj); + else + fmt_puts(fmt, "<unknown object>"); +} + +static int +fz_sprint_obj(char *s, int n, fz_obj *obj, int tight) +{ + struct fmt fmt; + + fmt.indent = 0; + fmt.col = 0; + fmt.sep = 0; + fmt.last = 0; + + fmt.tight = tight; + fmt.buf = s; + fmt.cap = n; + fmt.len = 0; + fmt_obj(&fmt, obj); + + if (fmt.buf && fmt.len < fmt.cap) + fmt.buf[fmt.len] = '\0'; + + return fmt.len; +} + +int +fz_fprint_obj(FILE *fp, fz_obj *obj, int tight) +{ + char buf[1024]; + char *ptr; + int n; + + n = fz_sprint_obj(NULL, 0, obj, tight); + if ((n + 1) < sizeof buf) + { + fz_sprint_obj(buf, sizeof buf, obj, tight); + fputs(buf, fp); + fputc('\n', fp); + } + else + { + ptr = fz_malloc(obj->ctx, n + 1); + fz_sprint_obj(ptr, n + 1, obj, tight); + fputs(ptr, fp); + fputc('\n', fp); + fz_free(obj->ctx, ptr); + } + return n; +} + +void +fz_debug_obj(fz_obj *obj) +{ + fz_fprint_obj(stdout, obj, 0); +} + +void +fz_debug_ref(fz_obj *ref) +{ + fz_debug_obj(fz_resolve_indirect(ref)); } diff --git a/fitz/dev_bbox.c b/fitz/dev_bbox.c index 179ff030..766adefa 100644 --- a/fitz/dev_bbox.c +++ b/fitz/dev_bbox.c @@ -3,70 +3,70 @@ /* TODO: add clip stack and use to intersect bboxes */ static void -fz_bbox_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm, +fz_bbox_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_bbox *result = user; + fz_bbox *result = dev->user; fz_bbox bbox = fz_round_rect(fz_bound_path(path, NULL, ctm)); *result = fz_union_bbox(*result, bbox); } static void -fz_bbox_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, +fz_bbox_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_bbox *result = user; + fz_bbox *result = dev->user; fz_bbox bbox = fz_round_rect(fz_bound_path(path, stroke, ctm)); *result = fz_union_bbox(*result, bbox); } static void -fz_bbox_fill_text(void *user, fz_text *text, fz_matrix ctm, +fz_bbox_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_bbox *result = user; + fz_bbox *result = dev->user; fz_bbox bbox = fz_round_rect(fz_bound_text(text, ctm)); *result = fz_union_bbox(*result, bbox); } static void -fz_bbox_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, +fz_bbox_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_bbox *result = user; + fz_bbox *result = dev->user; fz_bbox bbox = fz_round_rect(fz_bound_text(text, ctm)); *result = fz_union_bbox(*result, bbox); } static void -fz_bbox_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) +fz_bbox_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) { - fz_bbox *result = user; + fz_bbox *result = dev->user; fz_bbox bbox = fz_round_rect(fz_bound_shade(shade, ctm)); *result = fz_union_bbox(*result, bbox); } static void -fz_bbox_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) +fz_bbox_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha) { - fz_bbox *result = user; + fz_bbox *result = dev->user; fz_bbox bbox = fz_round_rect(fz_transform_rect(ctm, fz_unit_rect)); *result = fz_union_bbox(*result, bbox); } static void -fz_bbox_fill_image_mask(void *user, fz_pixmap *image, fz_matrix ctm, +fz_bbox_fill_image_mask(fz_device *dev, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_bbox_fill_image(user, image, ctm, alpha); + fz_bbox_fill_image(dev, image, ctm, alpha); } fz_device * -fz_new_bbox_device(fz_bbox *result) +fz_new_bbox_device(fz_context *ctx, fz_bbox *result) { fz_device *dev; - dev = fz_new_device(result); + dev = fz_new_device(ctx, result); dev->fill_path = fz_bbox_fill_path; dev->stroke_path = fz_bbox_stroke_path; diff --git a/fitz/dev_list.c b/fitz/dev_list.c index 955824f9..63e9eee0 100644 --- a/fitz/dev_list.c +++ b/fitz/dev_list.c @@ -64,13 +64,13 @@ struct fz_display_list_s enum { ISOLATED = 1, KNOCKOUT = 2 }; static fz_display_node * -fz_new_display_node(fz_display_command cmd, fz_matrix ctm, +fz_new_display_node(fz_context *ctx, fz_display_command cmd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { fz_display_node *node; int i; - node = fz_malloc(sizeof(fz_display_node)); + node = fz_malloc(ctx, sizeof(fz_display_node)); node->cmd = cmd; node->next = NULL; node->rect = fz_empty_rect; @@ -97,9 +97,9 @@ fz_new_display_node(fz_display_command cmd, fz_matrix ctm, } static fz_stroke_state * -fz_clone_stroke_state(fz_stroke_state *stroke) +fz_clone_stroke_state(fz_context *ctx, fz_stroke_state *stroke) { - fz_stroke_state *newstroke = fz_malloc(sizeof(fz_stroke_state)); + fz_stroke_state *newstroke = fz_malloc(ctx, sizeof(fz_stroke_state)); *newstroke = *stroke; return newstroke; } @@ -184,7 +184,7 @@ fz_append_display_node(fz_display_list *list, fz_display_node *node) } static void -fz_free_display_node(fz_display_node *node) +fz_free_display_node(fz_context *ctx, fz_display_node *node) { switch (node->cmd) { @@ -192,22 +192,22 @@ fz_free_display_node(fz_display_node *node) case FZ_CMD_STROKE_PATH: case FZ_CMD_CLIP_PATH: case FZ_CMD_CLIP_STROKE_PATH: - fz_free_path(node->item.path); + fz_free_path(ctx, node->item.path); break; case FZ_CMD_FILL_TEXT: case FZ_CMD_STROKE_TEXT: case FZ_CMD_CLIP_TEXT: case FZ_CMD_CLIP_STROKE_TEXT: case FZ_CMD_IGNORE_TEXT: - fz_free_text(node->item.text); + fz_free_text(ctx, node->item.text); break; case FZ_CMD_FILL_SHADE: - fz_drop_shade(node->item.shade); + fz_drop_shade(ctx, node->item.shade); break; case FZ_CMD_FILL_IMAGE: case FZ_CMD_FILL_IMAGE_MASK: case FZ_CMD_CLIP_IMAGE_MASK: - fz_drop_pixmap(node->item.image); + fz_drop_pixmap(ctx, node->item.image); break; case FZ_CMD_POP_CLIP: case FZ_CMD_BEGIN_MASK: @@ -219,214 +219,214 @@ fz_free_display_node(fz_display_node *node) break; } if (node->stroke) - fz_free(node->stroke); + fz_free(ctx, node->stroke); if (node->colorspace) - fz_drop_colorspace(node->colorspace); - fz_free(node); + fz_drop_colorspace(ctx, node->colorspace); + fz_free(ctx, node); } static void -fz_list_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm, +fz_list_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_FILL_PATH, ctm, colorspace, color, alpha); + node = fz_new_display_node(dev->ctx, FZ_CMD_FILL_PATH, ctm, colorspace, color, alpha); node->rect = fz_bound_path(path, NULL, ctm); - node->item.path = fz_clone_path(path); + node->item.path = fz_clone_path(dev->ctx, path); node->flag = even_odd; - fz_append_display_node(user, node); + fz_append_display_node(dev->user, node); } static void -fz_list_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, +fz_list_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_STROKE_PATH, ctm, colorspace, color, alpha); + node = fz_new_display_node(dev->ctx, FZ_CMD_STROKE_PATH, ctm, colorspace, color, alpha); node->rect = fz_bound_path(path, stroke, ctm); - node->item.path = fz_clone_path(path); - node->stroke = fz_clone_stroke_state(stroke); - fz_append_display_node(user, node); + node->item.path = fz_clone_path(dev->ctx, path); + node->stroke = fz_clone_stroke_state(dev->ctx, stroke); + fz_append_display_node(dev->user, node); } static void -fz_list_clip_path(void *user, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) +fz_list_clip_path(fz_device *dev, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_CLIP_PATH, ctm, NULL, NULL, 0); + node = fz_new_display_node(dev->ctx, FZ_CMD_CLIP_PATH, ctm, NULL, NULL, 0); node->rect = fz_bound_path(path, NULL, ctm); if (rect != NULL) node->rect = fz_intersect_rect(node->rect, *rect); - node->item.path = fz_clone_path(path); + node->item.path = fz_clone_path(dev->ctx, path); node->flag = even_odd; - fz_append_display_node(user, node); + fz_append_display_node(dev->user, node); } static void -fz_list_clip_stroke_path(void *user, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) +fz_list_clip_stroke_path(fz_device *dev, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_CLIP_STROKE_PATH, ctm, NULL, NULL, 0); + node = fz_new_display_node(dev->ctx, FZ_CMD_CLIP_STROKE_PATH, ctm, NULL, NULL, 0); node->rect = fz_bound_path(path, stroke, ctm); if (rect != NULL) node->rect = fz_intersect_rect(node->rect, *rect); - node->item.path = fz_clone_path(path); - node->stroke = fz_clone_stroke_state(stroke); - fz_append_display_node(user, node); + node->item.path = fz_clone_path(dev->ctx, path); + node->stroke = fz_clone_stroke_state(dev->ctx, stroke); + fz_append_display_node(dev->user, node); } static void -fz_list_fill_text(void *user, fz_text *text, fz_matrix ctm, +fz_list_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_FILL_TEXT, ctm, colorspace, color, alpha); + node = fz_new_display_node(dev->ctx, FZ_CMD_FILL_TEXT, ctm, colorspace, color, alpha); node->rect = fz_bound_text(text, ctm); - node->item.text = fz_clone_text(text); - fz_append_display_node(user, node); + node->item.text = fz_clone_text(dev->ctx, text); + fz_append_display_node(dev->user, node); } static void -fz_list_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, +fz_list_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_STROKE_TEXT, ctm, colorspace, color, alpha); + node = fz_new_display_node(dev->ctx, FZ_CMD_STROKE_TEXT, ctm, colorspace, color, alpha); node->rect = fz_bound_text(text, ctm); - node->item.text = fz_clone_text(text); - node->stroke = fz_clone_stroke_state(stroke); - fz_append_display_node(user, node); + node->item.text = fz_clone_text(dev->ctx, text); + node->stroke = fz_clone_stroke_state(dev->ctx, stroke); + fz_append_display_node(dev->user, node); } static void -fz_list_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate) +fz_list_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_CLIP_TEXT, ctm, NULL, NULL, 0); + node = fz_new_display_node(dev->ctx, FZ_CMD_CLIP_TEXT, ctm, NULL, NULL, 0); node->rect = fz_bound_text(text, ctm); - node->item.text = fz_clone_text(text); + node->item.text = fz_clone_text(dev->ctx, text); node->flag = accumulate; /* when accumulating, be conservative about culling */ if (accumulate) node->rect = fz_infinite_rect; - fz_append_display_node(user, node); + fz_append_display_node(dev->user, node); } static void -fz_list_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) +fz_list_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_CLIP_STROKE_TEXT, ctm, NULL, NULL, 0); + node = fz_new_display_node(dev->ctx, FZ_CMD_CLIP_STROKE_TEXT, ctm, NULL, NULL, 0); node->rect = fz_bound_text(text, ctm); - node->item.text = fz_clone_text(text); - node->stroke = fz_clone_stroke_state(stroke); - fz_append_display_node(user, node); + node->item.text = fz_clone_text(dev->ctx, text); + node->stroke = fz_clone_stroke_state(dev->ctx, stroke); + fz_append_display_node(dev->user, node); } static void -fz_list_ignore_text(void *user, fz_text *text, fz_matrix ctm) +fz_list_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_IGNORE_TEXT, ctm, NULL, NULL, 0); + node = fz_new_display_node(dev->ctx, FZ_CMD_IGNORE_TEXT, ctm, NULL, NULL, 0); node->rect = fz_bound_text(text, ctm); - node->item.text = fz_clone_text(text); - fz_append_display_node(user, node); + node->item.text = fz_clone_text(dev->ctx, text); + fz_append_display_node(dev->user, node); } static void -fz_list_pop_clip(void *user) +fz_list_pop_clip(fz_device *dev) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_POP_CLIP, fz_identity, NULL, NULL, 0); - fz_append_display_node(user, node); + node = fz_new_display_node(dev->ctx, FZ_CMD_POP_CLIP, fz_identity, NULL, NULL, 0); + fz_append_display_node(dev->user, node); } static void -fz_list_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) +fz_list_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_FILL_SHADE, ctm, NULL, NULL, alpha); + node = fz_new_display_node(dev->ctx, FZ_CMD_FILL_SHADE, ctm, NULL, NULL, alpha); node->rect = fz_bound_shade(shade, ctm); node->item.shade = fz_keep_shade(shade); - fz_append_display_node(user, node); + fz_append_display_node(dev->user, node); } static void -fz_list_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) +fz_list_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_FILL_IMAGE, ctm, NULL, NULL, alpha); + node = fz_new_display_node(dev->ctx, FZ_CMD_FILL_IMAGE, ctm, NULL, NULL, alpha); node->rect = fz_transform_rect(ctm, fz_unit_rect); node->item.image = fz_keep_pixmap(image); - fz_append_display_node(user, node); + fz_append_display_node(dev->user, node); } static void -fz_list_fill_image_mask(void *user, fz_pixmap *image, fz_matrix ctm, +fz_list_fill_image_mask(fz_device *dev, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_FILL_IMAGE_MASK, ctm, colorspace, color, alpha); + node = fz_new_display_node(dev->ctx, FZ_CMD_FILL_IMAGE_MASK, ctm, colorspace, color, alpha); node->rect = fz_transform_rect(ctm, fz_unit_rect); node->item.image = fz_keep_pixmap(image); - fz_append_display_node(user, node); + fz_append_display_node(dev->user, node); } static void -fz_list_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) +fz_list_clip_image_mask(fz_device *dev, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_CLIP_IMAGE_MASK, ctm, NULL, NULL, 0); + node = fz_new_display_node(dev->ctx, FZ_CMD_CLIP_IMAGE_MASK, ctm, NULL, NULL, 0); node->rect = fz_transform_rect(ctm, fz_unit_rect); if (rect != NULL) node->rect = fz_intersect_rect(node->rect, *rect); node->item.image = fz_keep_pixmap(image); - fz_append_display_node(user, node); + fz_append_display_node(dev->user, node); } static void -fz_list_begin_mask(void *user, fz_rect rect, int luminosity, fz_colorspace *colorspace, float *color) +fz_list_begin_mask(fz_device *dev, fz_rect rect, int luminosity, fz_colorspace *colorspace, float *color) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_BEGIN_MASK, fz_identity, colorspace, color, 0); + node = fz_new_display_node(dev->ctx, FZ_CMD_BEGIN_MASK, fz_identity, colorspace, color, 0); node->rect = rect; node->flag = luminosity; - fz_append_display_node(user, node); + fz_append_display_node(dev->user, node); } static void -fz_list_end_mask(void *user) +fz_list_end_mask(fz_device *dev) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_END_MASK, fz_identity, NULL, NULL, 0); - fz_append_display_node(user, node); + node = fz_new_display_node(dev->ctx, FZ_CMD_END_MASK, fz_identity, NULL, NULL, 0); + fz_append_display_node(dev->user, node); } static void -fz_list_begin_group(void *user, fz_rect rect, int isolated, int knockout, int blendmode, float alpha) +fz_list_begin_group(fz_device *dev, fz_rect rect, int isolated, int knockout, int blendmode, float alpha) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_BEGIN_GROUP, fz_identity, NULL, NULL, alpha); + node = fz_new_display_node(dev->ctx, FZ_CMD_BEGIN_GROUP, fz_identity, NULL, NULL, alpha); node->rect = rect; node->item.blendmode = blendmode; node->flag |= isolated ? ISOLATED : 0; node->flag |= knockout ? KNOCKOUT : 0; - fz_append_display_node(user, node); + fz_append_display_node(dev->user, node); } static void -fz_list_end_group(void *user) +fz_list_end_group(fz_device *dev) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_END_GROUP, fz_identity, NULL, NULL, 0); - fz_append_display_node(user, node); + node = fz_new_display_node(dev->ctx, FZ_CMD_END_GROUP, fz_identity, NULL, NULL, 0); + fz_append_display_node(dev->user, node); } static void -fz_list_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) +fz_list_begin_tile(fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_BEGIN_TILE, ctm, NULL, NULL, 0); + node = fz_new_display_node(dev->ctx, FZ_CMD_BEGIN_TILE, ctm, NULL, NULL, 0); node->rect = area; node->color[0] = xstep; node->color[1] = ystep; @@ -434,21 +434,21 @@ fz_list_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ys node->color[3] = view.y0; node->color[4] = view.x1; node->color[5] = view.y1; - fz_append_display_node(user, node); + fz_append_display_node(dev->user, node); } static void -fz_list_end_tile(void *user) +fz_list_end_tile(fz_device *dev) { fz_display_node *node; - node = fz_new_display_node(FZ_CMD_END_TILE, fz_identity, NULL, NULL, 0); - fz_append_display_node(user, node); + node = fz_new_display_node(dev->ctx, FZ_CMD_END_TILE, fz_identity, NULL, NULL, 0); + fz_append_display_node(dev->user, node); } fz_device * -fz_new_list_device(fz_display_list *list) +fz_new_list_device(fz_context *ctx, fz_display_list *list) { - fz_device *dev = fz_new_device(list); + fz_device *dev = fz_new_device(ctx, list); dev->fill_path = fz_list_fill_path; dev->stroke_path = fz_list_stroke_path; @@ -480,9 +480,9 @@ fz_new_list_device(fz_display_list *list) } fz_display_list * -fz_new_display_list(void) +fz_new_display_list(fz_context *ctx) { - fz_display_list *list = fz_malloc(sizeof(fz_display_list)); + fz_display_list *list = fz_malloc(ctx, sizeof(fz_display_list)); list->first = NULL; list->last = NULL; list->top = 0; @@ -491,16 +491,16 @@ fz_new_display_list(void) } void -fz_free_display_list(fz_display_list *list) +fz_free_display_list(fz_context *ctx, fz_display_list *list) { fz_display_node *node = list->first; while (node) { fz_display_node *next = node->next; - fz_free_display_node(node); + fz_free_display_node(ctx, node); node = next; } - fz_free(list); + fz_free(ctx, list); } void diff --git a/fitz/dev_null.c b/fitz/dev_null.c index 508be7e0..dc6105f4 100644 --- a/fitz/dev_null.c +++ b/fitz/dev_null.c @@ -1,13 +1,14 @@ #include "fitz.h" fz_device * -fz_new_device(void *user) +fz_new_device(fz_context *ctx, void *user) { - fz_device *dev = fz_malloc(sizeof(fz_device)); - memset(dev, 0, sizeof(fz_device)); + fz_device *dev = fz_malloc(ctx, sizeof(fz_device)); + memset(dev, 0, sizeof *dev); dev->hints = 0; dev->flags = 0; dev->user = user; + dev->ctx = ctx; return dev; } @@ -15,8 +16,8 @@ void fz_free_device(fz_device *dev) { if (dev->free_user) - dev->free_user(dev->user); - fz_free(dev); + dev->free_user(dev); + fz_free(dev->ctx, dev); } void @@ -24,7 +25,7 @@ fz_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { if (dev->fill_path) - dev->fill_path(dev->user, path, even_odd, ctm, colorspace, color, alpha); + dev->fill_path(dev, path, even_odd, ctm, colorspace, color, alpha); } void @@ -32,21 +33,21 @@ fz_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix fz_colorspace *colorspace, float *color, float alpha) { if (dev->stroke_path) - dev->stroke_path(dev->user, path, stroke, ctm, colorspace, color, alpha); + dev->stroke_path(dev, path, stroke, ctm, colorspace, color, alpha); } void fz_clip_path(fz_device *dev, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) { if (dev->clip_path) - dev->clip_path(dev->user, path, rect, even_odd, ctm); + dev->clip_path(dev, path, rect, even_odd, ctm); } void fz_clip_stroke_path(fz_device *dev, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) { if (dev->clip_stroke_path) - dev->clip_stroke_path(dev->user, path, rect, stroke, ctm); + dev->clip_stroke_path(dev, path, rect, stroke, ctm); } void @@ -54,7 +55,7 @@ fz_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { if (dev->fill_text) - dev->fill_text(dev->user, text, ctm, colorspace, color, alpha); + dev->fill_text(dev, text, ctm, colorspace, color, alpha); } void @@ -62,49 +63,49 @@ fz_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix fz_colorspace *colorspace, float *color, float alpha) { if (dev->stroke_text) - dev->stroke_text(dev->user, text, stroke, ctm, colorspace, color, alpha); + dev->stroke_text(dev, text, stroke, ctm, colorspace, color, alpha); } void fz_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate) { if (dev->clip_text) - dev->clip_text(dev->user, text, ctm, accumulate); + dev->clip_text(dev, text, ctm, accumulate); } void fz_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) { if (dev->clip_stroke_text) - dev->clip_stroke_text(dev->user, text, stroke, ctm); + dev->clip_stroke_text(dev, text, stroke, ctm); } void fz_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) { if (dev->ignore_text) - dev->ignore_text(dev->user, text, ctm); + dev->ignore_text(dev, text, ctm); } void fz_pop_clip(fz_device *dev) { if (dev->pop_clip) - dev->pop_clip(dev->user); + dev->pop_clip(dev); } void fz_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) { if (dev->fill_shade) - dev->fill_shade(dev->user, shade, ctm, alpha); + dev->fill_shade(dev, shade, ctm, alpha); } void fz_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha) { if (dev->fill_image) - dev->fill_image(dev->user, image, ctm, alpha); + dev->fill_image(dev, image, ctm, alpha); } void @@ -112,54 +113,54 @@ fz_fill_image_mask(fz_device *dev, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { if (dev->fill_image_mask) - dev->fill_image_mask(dev->user, image, ctm, colorspace, color, alpha); + dev->fill_image_mask(dev, image, ctm, colorspace, color, alpha); } void fz_clip_image_mask(fz_device *dev, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) { if (dev->clip_image_mask) - dev->clip_image_mask(dev->user, image, rect, ctm); + dev->clip_image_mask(dev, image, rect, ctm); } void fz_begin_mask(fz_device *dev, fz_rect area, int luminosity, fz_colorspace *colorspace, float *bc) { if (dev->begin_mask) - dev->begin_mask(dev->user, area, luminosity, colorspace, bc); + dev->begin_mask(dev, area, luminosity, colorspace, bc); } void fz_end_mask(fz_device *dev) { if (dev->end_mask) - dev->end_mask(dev->user); + dev->end_mask(dev); } void fz_begin_group(fz_device *dev, fz_rect area, int isolated, int knockout, int blendmode, float alpha) { if (dev->begin_group) - dev->begin_group(dev->user, area, isolated, knockout, blendmode, alpha); + dev->begin_group(dev, area, isolated, knockout, blendmode, alpha); } void fz_end_group(fz_device *dev) { if (dev->end_group) - dev->end_group(dev->user); + dev->end_group(dev); } void fz_begin_tile(fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) { if (dev->begin_tile) - dev->begin_tile(dev->user, area, view, xstep, ystep, ctm); + dev->begin_tile(dev, area, view, xstep, ystep, ctm); } void fz_end_tile(fz_device *dev) { if (dev->end_tile) - dev->end_tile(dev->user); + dev->end_tile(dev); } diff --git a/fitz/dev_text.c b/fitz/dev_text.c index fb75c944..bf304778 100644 --- a/fitz/dev_text.c +++ b/fitz/dev_text.c @@ -17,10 +17,10 @@ struct fz_text_device_s }; fz_text_span * -fz_new_text_span(void) +fz_new_text_span(fz_context *ctx) { fz_text_span *span; - span = fz_malloc(sizeof(fz_text_span)); + span = fz_malloc(ctx, sizeof(fz_text_span)); span->font = NULL; span->wmode = 0; span->size = 0; @@ -33,28 +33,28 @@ fz_new_text_span(void) } void -fz_free_text_span(fz_text_span *span) +fz_free_text_span(fz_context *ctx, fz_text_span *span) { fz_text_span *next; while (span) { if (span->font) - fz_drop_font(span->font); + fz_drop_font(ctx, span->font); next = span->next; - fz_free(span->text); - fz_free(span); + fz_free(ctx, span->text); + fz_free(ctx, span); span = next; } } static void -fz_add_text_char_imp(fz_text_span *span, int c, fz_bbox bbox) +fz_add_text_char_imp(fz_context *ctx, fz_text_span *span, int c, fz_bbox bbox) { if (span->len + 1 >= span->cap) { span->cap = span->cap > 1 ? (span->cap * 3) / 2 : 80; - span->text = fz_realloc(span->text, span->cap, sizeof(fz_text_char)); + span->text = fz_resize_array(ctx, span->text, span->cap, sizeof(fz_text_char)); } span->text[span->len].c = c; span->text[span->len].bbox = bbox; @@ -72,7 +72,7 @@ fz_split_bbox(fz_bbox bbox, int i, int n) } static void -fz_add_text_char(fz_text_span **last, fz_font *font, float size, int wmode, int c, fz_bbox bbox) +fz_add_text_char(fz_context *ctx, fz_text_span **last, fz_font *font, float size, int wmode, int c, fz_bbox bbox) { fz_text_span *span = *last; @@ -84,7 +84,7 @@ fz_add_text_char(fz_text_span **last, fz_font *font, float size, int wmode, int if ((span->font != font || span->size != size || span->wmode != wmode) && c != 32) { - span = fz_new_text_span(); + span = fz_new_text_span(ctx); span->font = fz_keep_font(font); span->size = size; span->wmode = wmode; @@ -97,34 +97,34 @@ fz_add_text_char(fz_text_span **last, fz_font *font, float size, int wmode, int case -1: /* ignore when one unicode character maps to multiple glyphs */ break; case 0xFB00: /* ff */ - fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 0, 2)); - fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 1, 2)); + fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 0, 2)); + fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 1, 2)); break; case 0xFB01: /* fi */ - fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 0, 2)); - fz_add_text_char_imp(span, 'i', fz_split_bbox(bbox, 1, 2)); + fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 0, 2)); + fz_add_text_char_imp(ctx, span, 'i', fz_split_bbox(bbox, 1, 2)); break; case 0xFB02: /* fl */ - fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 0, 2)); - fz_add_text_char_imp(span, 'l', fz_split_bbox(bbox, 1, 2)); + fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 0, 2)); + fz_add_text_char_imp(ctx, span, 'l', fz_split_bbox(bbox, 1, 2)); break; case 0xFB03: /* ffi */ - fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 0, 3)); - fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 1, 3)); - fz_add_text_char_imp(span, 'i', fz_split_bbox(bbox, 2, 3)); + fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 0, 3)); + fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 1, 3)); + fz_add_text_char_imp(ctx, span, 'i', fz_split_bbox(bbox, 2, 3)); break; case 0xFB04: /* ffl */ - fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 0, 3)); - fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 1, 3)); - fz_add_text_char_imp(span, 'l', fz_split_bbox(bbox, 2, 3)); + fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 0, 3)); + fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 1, 3)); + fz_add_text_char_imp(ctx, span, 'l', fz_split_bbox(bbox, 2, 3)); break; case 0xFB05: /* long st */ case 0xFB06: /* st */ - fz_add_text_char_imp(span, 's', fz_split_bbox(bbox, 0, 2)); - fz_add_text_char_imp(span, 't', fz_split_bbox(bbox, 1, 2)); + fz_add_text_char_imp(ctx, span, 's', fz_split_bbox(bbox, 0, 2)); + fz_add_text_char_imp(ctx, span, 't', fz_split_bbox(bbox, 1, 2)); break; default: - fz_add_text_char_imp(span, c, bbox); + fz_add_text_char_imp(ctx, span, c, bbox); break; } } @@ -141,10 +141,10 @@ fz_divide_text_chars(fz_text_span **last, int n, fz_bbox bbox) } static void -fz_add_text_newline(fz_text_span **last, fz_font *font, float size, int wmode) +fz_add_text_newline(fz_context *ctx, fz_text_span **last, fz_font *font, float size, int wmode) { fz_text_span *span; - span = fz_new_text_span(); + span = fz_new_text_span(ctx); span->font = fz_keep_font(font); span->size = size; span->wmode = wmode; @@ -218,7 +218,7 @@ fz_debug_text_span(fz_text_span *span) } static void -fz_text_extract_span(fz_text_span **last, fz_text *text, fz_matrix ctm, fz_point *pen) +fz_text_extract_span(fz_context *ctx, fz_text_span **last, fz_text *text, fz_matrix ctm, fz_point *pen) { fz_font *font = text->font; FT_Face face = font->ft_face; @@ -242,7 +242,7 @@ fz_text_extract_span(fz_text_span **last, fz_text *text, fz_matrix ctm, fz_point { err = FT_Set_Char_Size(font->ft_face, 64, 64, 72, 72); if (err) - fz_warn("freetype set character size: %s", ft_error_string(err)); + fz_warn(ctx, "freetype set character size: %s", ft_error_string(err)); ascender = (float)face->ascender / face->units_per_EM; descender = (float)face->descender / face->units_per_EM; } @@ -276,7 +276,7 @@ fz_text_extract_span(fz_text_span **last, fz_text *text, fz_matrix ctm, fz_point { if (text->items[i].gid < 0) { - fz_add_text_char(last, font, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); + fz_add_text_char(ctx, last, font, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); multi ++; fz_divide_text_chars(last, multi, fz_round_rect(rect)); continue; @@ -304,7 +304,7 @@ fz_text_extract_span(fz_text_span **last, fz_text *text, fz_matrix ctm, fz_point if (dist > size * LINE_DIST) { - fz_add_text_newline(last, font, size, text->wmode); + fz_add_text_newline(ctx, last, font, size, text->wmode); } else if (fabsf(dot) > 0.95f && dist > size * SPACE_DIST) { @@ -316,7 +316,7 @@ fz_text_extract_span(fz_text_span **last, fz_text *text, fz_matrix ctm, fz_point spacerect.x1 = 0; spacerect.y1 = 1; spacerect = fz_transform_rect(trm, spacerect); - fz_add_text_char(last, font, size, text->wmode, ' ', fz_round_rect(spacerect)); + fz_add_text_char(ctx, last, font, size, text->wmode, ' ', fz_round_rect(spacerect)); } } } @@ -351,71 +351,71 @@ fz_text_extract_span(fz_text_span **last, fz_text *text, fz_matrix ctm, fz_point pen->x = trm.e + dir.x * adv; pen->y = trm.f + dir.y * adv; - fz_add_text_char(last, font, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); + fz_add_text_char(ctx, last, font, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); } } static void -fz_text_fill_text(void *user, fz_text *text, fz_matrix ctm, +fz_text_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_text_device *tdev = user; - fz_text_extract_span(&tdev->span, text, ctm, &tdev->point); + fz_text_device *tdev = dev->user; + fz_text_extract_span(dev->ctx, &tdev->span, text, ctm, &tdev->point); } static void -fz_text_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, +fz_text_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_text_device *tdev = user; - fz_text_extract_span(&tdev->span, text, ctm, &tdev->point); + fz_text_device *tdev = dev->user; + fz_text_extract_span(dev->ctx, &tdev->span, text, ctm, &tdev->point); } static void -fz_text_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate) +fz_text_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate) { - fz_text_device *tdev = user; - fz_text_extract_span(&tdev->span, text, ctm, &tdev->point); + fz_text_device *tdev = dev->user; + fz_text_extract_span(dev->ctx, &tdev->span, text, ctm, &tdev->point); } static void -fz_text_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) +fz_text_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) { - fz_text_device *tdev = user; - fz_text_extract_span(&tdev->span, text, ctm, &tdev->point); + fz_text_device *tdev = dev->user; + fz_text_extract_span(dev->ctx, &tdev->span, text, ctm, &tdev->point); } static void -fz_text_ignore_text(void *user, fz_text *text, fz_matrix ctm) +fz_text_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) { - fz_text_device *tdev = user; - fz_text_extract_span(&tdev->span, text, ctm, &tdev->point); + fz_text_device *tdev = dev->user; + fz_text_extract_span(dev->ctx, &tdev->span, text, ctm, &tdev->point); } static void -fz_text_free_user(void *user) +fz_text_free_user(fz_device *dev) { - fz_text_device *tdev = user; + fz_text_device *tdev = dev->user; tdev->span->eol = 1; /* TODO: unicode NFC normalization */ /* TODO: bidi logical reordering */ - fz_free(tdev); + fz_free(dev->ctx, tdev); } fz_device * -fz_new_text_device(fz_text_span *root) +fz_new_text_device(fz_context *ctx, fz_text_span *root) { fz_device *dev; - fz_text_device *tdev = fz_malloc(sizeof(fz_text_device)); + fz_text_device *tdev = fz_malloc(ctx, sizeof(fz_text_device)); tdev->head = root; tdev->span = root; tdev->point.x = -1; tdev->point.y = -1; - dev = fz_new_device(tdev); + dev = fz_new_device(ctx, tdev); dev->hints = FZ_IGNORE_IMAGE | FZ_IGNORE_SHADE; dev->free_user = fz_text_free_user; dev->fill_text = fz_text_fill_text; diff --git a/fitz/dev_trace.c b/fitz/dev_trace.c index a98eb898..62661a3d 100644 --- a/fitz/dev_trace.c +++ b/fitz/dev_trace.c @@ -67,7 +67,7 @@ fz_trace_path(fz_path *path, int indent) } static void -fz_trace_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm, +fz_trace_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { printf("<fill_path "); @@ -83,7 +83,7 @@ fz_trace_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm, } static void -fz_trace_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, +fz_trace_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { int i; @@ -112,7 +112,7 @@ fz_trace_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matr } static void -fz_trace_clip_path(void *user, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) +fz_trace_clip_path(fz_device *dev, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) { printf("<clip_path "); if (even_odd) @@ -127,7 +127,7 @@ fz_trace_clip_path(void *user, fz_path *path, fz_rect *rect, int even_odd, fz_ma } static void -fz_trace_clip_stroke_path(void *user, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) +fz_trace_clip_stroke_path(fz_device *dev, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) { printf("<clip_stroke_path "); fz_trace_matrix(ctm); @@ -137,7 +137,7 @@ fz_trace_clip_stroke_path(void *user, fz_path *path, fz_rect *rect, fz_stroke_st } static void -fz_trace_fill_text(void *user, fz_text *text, fz_matrix ctm, +fz_trace_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { printf("<fill_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode); @@ -150,7 +150,7 @@ fz_trace_fill_text(void *user, fz_text *text, fz_matrix ctm, } static void -fz_trace_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, +fz_trace_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { printf("<stroke_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode); @@ -163,7 +163,7 @@ fz_trace_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matr } static void -fz_trace_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate) +fz_trace_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate) { printf("<clip_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode); printf("accumulate=\"%d\" ", accumulate); @@ -175,7 +175,7 @@ fz_trace_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate) } static void -fz_trace_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) +fz_trace_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) { printf("<clip_stroke_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode); fz_trace_matrix(ctm); @@ -186,7 +186,7 @@ fz_trace_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz } static void -fz_trace_ignore_text(void *user, fz_text *text, fz_matrix ctm) +fz_trace_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) { printf("<ignore_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode); fz_trace_matrix(ctm); @@ -197,7 +197,7 @@ fz_trace_ignore_text(void *user, fz_text *text, fz_matrix ctm) } static void -fz_trace_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) +fz_trace_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha) { printf("<fill_image alpha=\"%g\" ", alpha); fz_trace_matrix(ctm); @@ -205,7 +205,7 @@ fz_trace_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) } static void -fz_trace_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) +fz_trace_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) { printf("<fill_shade alpha=\"%g\" ", alpha); fz_trace_matrix(ctm); @@ -213,7 +213,7 @@ fz_trace_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) } static void -fz_trace_fill_image_mask(void *user, fz_pixmap *image, fz_matrix ctm, +fz_trace_fill_image_mask(fz_device *dev, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { printf("<fill_image_mask "); @@ -223,7 +223,7 @@ fz_colorspace *colorspace, float *color, float alpha) } static void -fz_trace_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) +fz_trace_clip_image_mask(fz_device *dev, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) { printf("<clip_image_mask "); fz_trace_matrix(ctm); @@ -231,13 +231,13 @@ fz_trace_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix } static void -fz_trace_pop_clip(void *user) +fz_trace_pop_clip(fz_device *dev) { printf("<pop_clip />\n"); } static void -fz_trace_begin_mask(void *user, fz_rect bbox, int luminosity, fz_colorspace *colorspace, float *color) +fz_trace_begin_mask(fz_device *dev, fz_rect bbox, int luminosity, fz_colorspace *colorspace, float *color) { printf("<mask bbox=\"%g %g %g %g\" s=\"%s\" ", bbox.x0, bbox.y0, bbox.x1, bbox.y1, @@ -247,13 +247,13 @@ fz_trace_begin_mask(void *user, fz_rect bbox, int luminosity, fz_colorspace *col } static void -fz_trace_end_mask(void *user) +fz_trace_end_mask(fz_device *dev) { printf("</mask>\n"); } static void -fz_trace_begin_group(void *user, fz_rect bbox, int isolated, int knockout, int blendmode, float alpha) +fz_trace_begin_group(fz_device *dev, fz_rect bbox, int isolated, int knockout, int blendmode, float alpha) { printf("<group bbox=\"%g %g %g %g\" isolated=\"%d\" knockout=\"%d\" blendmode=\"%s\" alpha=\"%g\">\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1, @@ -261,13 +261,13 @@ fz_trace_begin_group(void *user, fz_rect bbox, int isolated, int knockout, int b } static void -fz_trace_end_group(void *user) +fz_trace_end_group(fz_device *dev) { printf("</group>\n"); } static void -fz_trace_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) +fz_trace_begin_tile(fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) { printf("<tile "); printf("area=\"%g %g %g %g\" ", area.x0, area.y0, area.x1, area.y1); @@ -278,14 +278,14 @@ fz_trace_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float y } static void -fz_trace_end_tile(void *user) +fz_trace_end_tile(fz_device *dev) { printf("</tile>\n"); } -fz_device *fz_new_trace_device(void) +fz_device *fz_new_trace_device(fz_context *ctx) { - fz_device *dev = fz_new_device(NULL); + fz_device *dev = fz_new_device(ctx, NULL); dev->fill_path = fz_trace_fill_path; dev->stroke_path = fz_trace_stroke_path; diff --git a/fitz/doc_outline.c b/fitz/doc_outline.c index ea3906ac..f6d07405 100644 --- a/fitz/doc_outline.c +++ b/fitz/doc_outline.c @@ -7,8 +7,8 @@ fz_free_outline(fz_outline *outline) { fz_outline *next = outline->next; fz_free_outline(outline->down); - fz_free(outline->title); - fz_free(outline); + fz_free(outline->ctx, outline->title); + fz_free(outline->ctx, outline); outline = next; } } diff --git a/fitz/filt_basic.c b/fitz/filt_basic.c index feb13076..0842ec36 100644 --- a/fitz/filt_basic.c +++ b/fitz/filt_basic.c @@ -23,7 +23,7 @@ read_null(fz_stream *stm, unsigned char *buf, int len) int amount = MIN(len, state->remain); int n = fz_read(state->chain, buf, amount); if (n < 0) - return fz_rethrow(n, "read error in null filter"); + return fz_error_note(n, "read error in null filter"); state->remain -= n; return n; } @@ -32,8 +32,10 @@ static void close_null(fz_stream *stm) { struct null_filter *state = stm->state; - fz_close(state->chain); - fz_free(state); + fz_stream *chain = state->chain; + + fz_free(stm->ctx, state); + fz_close(chain); } fz_stream * @@ -41,11 +43,12 @@ fz_open_null(fz_stream *chain, int len) { struct null_filter *state; - state = fz_malloc(sizeof(struct null_filter)); + assert(chain != NULL); + state = fz_malloc(chain->ctx, sizeof(struct null_filter)); state->chain = chain; state->remain = len; - return fz_new_stream(state, read_null, close_null); + return fz_new_stream(chain->ctx, state, read_null, close_null); } /* ASCII Hex Decode */ @@ -124,7 +127,7 @@ read_ahxd(fz_stream *stm, unsigned char *buf, int len) } else if (!iswhite(c)) { - return fz_throw("bad data in ahxd: '%c'", c); + return fz_error_make("bad data in ahxd: '%c'", c); } } @@ -135,8 +138,10 @@ static void close_ahxd(fz_stream *stm) { fz_ahxd *state = stm->state; - fz_close(state->chain); - fz_free(state); + fz_stream *chain = state->chain; + + fz_free(stm->ctx, state); + fz_close(chain); } fz_stream * @@ -144,11 +149,11 @@ fz_open_ahxd(fz_stream *chain) { fz_ahxd *state; - state = fz_malloc(sizeof(fz_ahxd)); + state = fz_malloc(chain->ctx, sizeof(fz_ahxd)); state->chain = chain; state->eod = 0; - return fz_new_stream(state, read_ahxd, close_ahxd); + return fz_new_stream(chain->ctx, state, read_ahxd, close_ahxd); } /* ASCII 85 Decode */ @@ -222,13 +227,13 @@ read_a85d(fz_stream *stm, unsigned char *buf, int len) { c = fz_read_byte(state->chain); if (c != '>') - fz_warn("bad eod marker in a85d"); + fz_warn(stm->ctx, "bad eod marker in a85d"); switch (count) { case 0: break; case 1: - return fz_throw("partial final byte in a85d"); + return fz_error_make("partial final byte in a85d"); case 2: word = word * (85 * 85 * 85) + 0xffffff; state->bp[0] = word >> 24; @@ -256,7 +261,7 @@ read_a85d(fz_stream *stm, unsigned char *buf, int len) else if (!iswhite(c)) { - return fz_throw("bad data in a85d: '%c'", c); + return fz_error_make("bad data in a85d: '%c'", c); } while (state->rp < state->wp && p < ep) @@ -270,8 +275,10 @@ static void close_a85d(fz_stream *stm) { fz_a85d *state = stm->state; - fz_close(state->chain); - fz_free(state); + fz_stream *chain = state->chain; + + fz_free(stm->ctx, state); + fz_close(chain); } fz_stream * @@ -279,13 +286,14 @@ fz_open_a85d(fz_stream *chain) { fz_a85d *state; - state = fz_malloc(sizeof(fz_a85d)); + assert(chain != NULL); + state = fz_malloc(chain->ctx, sizeof(fz_a85d)); state->chain = chain; state->rp = state->bp; state->wp = state->bp; state->eod = 0; - return fz_new_stream(state, read_a85d, close_a85d); + return fz_new_stream(chain->ctx, state, read_a85d, close_a85d); } /* Run Length Decode */ @@ -322,7 +330,7 @@ read_rld(fz_stream *stm, unsigned char *buf, int len) state->n = 257 - state->run; state->c = fz_read_byte(state->chain); if (state->c < 0) - return fz_throw("premature end of data in run length decode"); + return fz_error_make("premature end of data in run length decode"); } } @@ -332,7 +340,7 @@ read_rld(fz_stream *stm, unsigned char *buf, int len) { int c = fz_read_byte(state->chain); if (c < 0) - return fz_throw("premature end of data in run length decode"); + return fz_error_make("premature end of data in run length decode"); *p++ = c; state->n--; } @@ -355,8 +363,10 @@ static void close_rld(fz_stream *stm) { fz_rld *state = stm->state; - fz_close(state->chain); - fz_free(state); + fz_stream *chain = state->chain; + + fz_free(stm->ctx, state); + fz_close(chain); } fz_stream * @@ -364,13 +374,14 @@ fz_open_rld(fz_stream *chain) { fz_rld *state; - state = fz_malloc(sizeof(fz_rld)); + assert(chain != NULL); + state = fz_malloc(chain->ctx, sizeof(fz_rld)); state->chain = chain; state->run = 0; state->n = 0; state->c = 0; - return fz_new_stream(state, read_rld, close_rld); + return fz_new_stream(chain->ctx, state, read_rld, close_rld); } /* RC4 Filter */ @@ -391,7 +402,7 @@ read_arc4(fz_stream *stm, unsigned char *buf, int len) n = fz_read(state->chain, buf, len); if (n < 0) - return fz_rethrow(n, "read error in arc4 filter"); + return fz_error_note(n, "read error in arc4 filter"); fz_arc4_encrypt(&state->arc4, buf, buf, n); @@ -402,8 +413,10 @@ static void close_arc4(fz_stream *stm) { fz_arc4c *state = stm->state; - fz_close(state->chain); - fz_free(state); + fz_stream *chain = state->chain; + + fz_free(stm->ctx, state); + fz_close(chain); } fz_stream * @@ -411,11 +424,11 @@ fz_open_arc4(fz_stream *chain, unsigned char *key, unsigned keylen) { fz_arc4c *state; - state = fz_malloc(sizeof(fz_arc4c)); + state = fz_malloc(chain->ctx, sizeof(fz_arc4c)); state->chain = chain; fz_arc4_init(&state->arc4, key, keylen); - return fz_new_stream(state, read_arc4, close_arc4); + return fz_new_stream(chain->ctx, state, read_arc4, close_arc4); } /* AES Filter */ @@ -443,7 +456,7 @@ read_aesd(fz_stream *stm, unsigned char *buf, int len) { int c = fz_read_byte(state->chain); if (c < 0) - return fz_throw("premature end in aes filter"); + return fz_error_make("premature end in aes filter"); state->iv[state->ivcount++] = c; } @@ -454,11 +467,11 @@ read_aesd(fz_stream *stm, unsigned char *buf, int len) { int n = fz_read(state->chain, state->bp, 16); if (n < 0) - return fz_rethrow(n, "read error in aes filter"); + return fz_error_note(n, "read error in aes filter"); else if (n == 0) return p - buf; else if (n < 16) - return fz_throw("partial block in aes filter"); + return fz_error_make("partial block in aes filter"); aes_crypt_cbc(&state->aes, AES_DECRYPT, 16, state->iv, state->bp, state->bp); state->rp = state->bp; @@ -469,7 +482,7 @@ read_aesd(fz_stream *stm, unsigned char *buf, int len) { int pad = state->bp[15]; if (pad < 1 || pad > 16) - return fz_throw("aes padding out of range: %d", pad); + return fz_error_make("aes padding out of range: %d", pad); state->wp -= pad; } @@ -484,8 +497,10 @@ static void close_aesd(fz_stream *stm) { fz_aesd *state = stm->state; - fz_close(state->chain); - fz_free(state); + fz_stream *chain = state->chain; + + fz_free(stm->ctx, state); + fz_close(chain); } fz_stream * @@ -493,12 +508,13 @@ fz_open_aesd(fz_stream *chain, unsigned char *key, unsigned keylen) { fz_aesd *state; - state = fz_malloc(sizeof(fz_aesd)); + assert(chain != NULL); + state = fz_malloc(chain->ctx, sizeof(fz_aesd)); state->chain = chain; aes_setkey_dec(&state->aes, key, keylen * 8); state->ivcount = 0; state->rp = state->bp; state->wp = state->bp; - return fz_new_stream(state, read_aesd, close_aesd); + return fz_new_stream(chain->ctx, state, read_aesd, close_aesd); } diff --git a/fitz/filt_dctd.c b/fitz/filt_dctd.c index 0e24b794..fb0e77e7 100644 --- a/fitz/filt_dctd.c +++ b/fitz/filt_dctd.c @@ -8,6 +8,7 @@ typedef struct fz_dctd_s fz_dctd; struct fz_dctd_s { fz_stream *chain; + fz_context *ctx; int color_transform; int init; int stride; @@ -51,7 +52,7 @@ static boolean fill_input_buffer(j_decompress_ptr cinfo) if (src->bytes_in_buffer == 0) { static unsigned char eoi[2] = { 0xFF, JPEG_EOI }; - fz_warn("premature end of file in jpeg"); + fz_warn(state->ctx, "premature end of file in jpeg"); src->next_input_byte = eoi; src->bytes_in_buffer = 2; } @@ -86,7 +87,7 @@ read_dctd(fz_stream *stm, unsigned char *buf, int len) { if (cinfo->src) state->chain->rp = state->chain->wp - cinfo->src->bytes_in_buffer; - return fz_throw("jpeg error: %s", state->msg); + return fz_error_make("jpeg error: %s", state->msg); } if (!state->init) @@ -144,7 +145,7 @@ read_dctd(fz_stream *stm, unsigned char *buf, int len) jpeg_start_decompress(cinfo); state->stride = cinfo->output_width * cinfo->output_components; - state->scanline = fz_malloc(state->stride); + state->scanline = fz_malloc(state->ctx, state->stride); state->rp = state->scanline; state->wp = state->scanline; @@ -186,7 +187,7 @@ close_dctd(fz_stream *stm) if (setjmp(state->jb)) { state->chain->rp = state->chain->wp - state->cinfo.src->bytes_in_buffer; - fz_warn("jpeg error: %s", state->msg); + fz_warn(state->ctx, "jpeg error: %s", state->msg); goto skip; } @@ -196,9 +197,9 @@ close_dctd(fz_stream *stm) skip: state->chain->rp = state->chain->wp - state->cinfo.src->bytes_in_buffer; jpeg_destroy_decompress(&state->cinfo); - fz_free(state->scanline); + fz_free(stm->ctx, state->scanline); fz_close(state->chain); - fz_free(state); + fz_free(stm->ctx, state); } fz_stream * @@ -207,8 +208,9 @@ fz_open_dctd(fz_stream *chain, fz_obj *params) fz_dctd *state; fz_obj *obj; - state = fz_malloc(sizeof(fz_dctd)); + state = fz_malloc(chain->ctx, sizeof(fz_dctd)); memset(state, 0, sizeof(fz_dctd)); + state->ctx = chain->ctx; state->chain = chain; state->color_transform = -1; /* unset */ state->init = 0; @@ -217,5 +219,5 @@ fz_open_dctd(fz_stream *chain, fz_obj *params) if (obj) state->color_transform = fz_to_int(obj); - return fz_new_stream(state, read_dctd, close_dctd); + return fz_new_stream(chain->ctx, state, read_dctd, close_dctd); } diff --git a/fitz/filt_faxd.c b/fitz/filt_faxd.c index dcf56cf3..14a71a87 100644 --- a/fitz/filt_faxd.c +++ b/fitz/filt_faxd.c @@ -345,13 +345,13 @@ dec1d(fz_faxd *fax) code = get_code(fax, cf_white_decode, cfd_white_initial_bits); if (code == UNCOMPRESSED) - return fz_throw("uncompressed data in faxd"); + return fz_error_make("uncompressed data in faxd"); if (code < 0) - return fz_throw("negative code in 1d faxd"); + return fz_error_make("negative code in 1d faxd"); if (fax->a + code > fax->columns) - return fz_throw("overflow in 1d faxd"); + return fz_error_make("overflow in 1d faxd"); if (fax->c) setbits(fax->dst, fax->a, fax->a + code); @@ -386,13 +386,13 @@ dec2d(fz_faxd *fax) code = get_code(fax, cf_white_decode, cfd_white_initial_bits); if (code == UNCOMPRESSED) - return fz_throw("uncompressed data in faxd"); + return fz_error_make("uncompressed data in faxd"); if (code < 0) - return fz_throw("negative code in 2d faxd"); + return fz_error_make("negative code in 2d faxd"); if (fax->a + code > fax->columns) - return fz_throw("overflow in 2d faxd"); + return fz_error_make("overflow in 2d faxd"); if (fax->c) setbits(fax->dst, fax->a, fax->a + code); @@ -485,13 +485,13 @@ dec2d(fz_faxd *fax) break; case UNCOMPRESSED: - return fz_throw("uncompressed data in faxd"); + return fz_error_make("uncompressed data in faxd"); case ERROR: - return fz_throw("invalid code in 2d faxd"); + return fz_error_make("invalid code in 2d faxd"); default: - return fz_throw("invalid code in 2d faxd (%d)", code); + return fz_error_make("invalid code in 2d faxd (%d)", code); } return 0; @@ -560,14 +560,14 @@ loop: fax->eolc = 0; error = dec1d(fax); if (error) - return fz_rethrow(error, "cannot decode 1d code"); + return fz_error_note(error, "cannot decode 1d code"); } else if (fax->dim == 2) { fax->eolc = 0; error = dec2d(fax); if (error) - return fz_rethrow(error, "cannot decode 2d code"); + return fz_error_note(error, "cannot decode 2d code"); } /* no eol check after makeup codes nor in the middle of an H code */ @@ -662,9 +662,9 @@ close_faxd(fz_stream *stm) fz_unread_byte(fax->chain); fz_close(fax->chain); - fz_free(fax->ref); - fz_free(fax->dst); - fz_free(fax); + fz_free(stm->ctx, fax->ref); + fz_free(stm->ctx, fax->dst); + fz_free(stm->ctx, fax); } fz_stream * @@ -672,8 +672,11 @@ fz_open_faxd(fz_stream *chain, fz_obj *params) { fz_faxd *fax; fz_obj *obj; + fz_context *ctx; - fax = fz_malloc(sizeof(fz_faxd)); + assert(chain != NULL); + ctx = chain->ctx; + fax = fz_malloc(ctx, sizeof(fz_faxd)); fax->chain = chain; fax->ref = NULL; @@ -719,13 +722,13 @@ fz_open_faxd(fz_stream *chain, fz_obj *params) fax->dim = fax->k < 0 ? 2 : 1; fax->eolc = 0; - fax->ref = fz_malloc(fax->stride); - fax->dst = fz_malloc(fax->stride); + fax->ref = fz_malloc(ctx, fax->stride); + fax->dst = fz_malloc(ctx, fax->stride); fax->rp = fax->dst; fax->wp = fax->dst + fax->stride; memset(fax->ref, 0, fax->stride); memset(fax->dst, 0, fax->stride); - return fz_new_stream(fax, read_faxd, close_faxd); + return fz_new_stream(ctx, fax, read_faxd, close_faxd); } diff --git a/fitz/filt_flate.c b/fitz/filt_flate.c index e7d4c9f7..11100c94 100644 --- a/fitz/filt_flate.c +++ b/fitz/filt_flate.c @@ -12,12 +12,12 @@ struct fz_flate_s static void *zalloc(void *opaque, unsigned int items, unsigned int size) { - return fz_calloc(items, size); + return fz_malloc_array(opaque, items, size); } static void zfree(void *opaque, void *ptr) { - fz_free(ptr); + fz_free(opaque, ptr); } static int @@ -49,17 +49,17 @@ read_flated(fz_stream *stm, unsigned char *outbuf, int outlen) } else if (code == Z_BUF_ERROR) { - fz_warn("premature end of data in flate filter"); + fz_warn(stm->ctx, "premature end of data in flate filter"); return outlen - zp->avail_out; } else if (code == Z_DATA_ERROR && zp->avail_in == 0) { - fz_warn("ignoring zlib error: %s", zp->msg); + fz_warn(stm->ctx, "ignoring zlib error: %s", zp->msg); return outlen - zp->avail_out; } else if (code != Z_OK) { - return fz_throw("zlib error: %s", zp->msg); + return fz_error_make("zlib error: %s", zp->msg); } } @@ -74,10 +74,10 @@ close_flated(fz_stream *stm) code = inflateEnd(&state->z); if (code != Z_OK) - fz_warn("zlib error: inflateEnd: %s", state->z.msg); + fz_warn(stm->ctx, "zlib error: inflateEnd: %s", state->z.msg); fz_close(state->chain); - fz_free(state); + fz_free(stm->ctx, state); } fz_stream * @@ -86,18 +86,18 @@ fz_open_flated(fz_stream *chain) fz_flate *state; int code; - state = fz_malloc(sizeof(fz_flate)); + state = fz_malloc(chain->ctx, sizeof(fz_flate)); state->chain = chain; state->z.zalloc = zalloc; state->z.zfree = zfree; - state->z.opaque = NULL; + state->z.opaque = chain->ctx; state->z.next_in = NULL; state->z.avail_in = 0; code = inflateInit(&state->z); if (code != Z_OK) - fz_warn("zlib error: inflateInit: %s", state->z.msg); + fz_warn(chain->ctx, "zlib error: inflateInit: %s", state->z.msg); - return fz_new_stream(state, read_flated, close_flated); + return fz_new_stream(chain->ctx, state, read_flated, close_flated); } diff --git a/fitz/filt_jbig2d.c b/fitz/filt_jbig2d.c index 4dbe542c..18aa0a22 100644 --- a/fitz/filt_jbig2d.c +++ b/fitz/filt_jbig2d.c @@ -38,7 +38,7 @@ close_jbig2d(fz_stream *stm) jbig2_global_ctx_free(state->gctx); jbig2_ctx_free(state->ctx); fz_close(state->chain); - fz_free(state); + fz_free(stm->ctx, state); } static int @@ -57,7 +57,7 @@ read_jbig2d(fz_stream *stm, unsigned char *buf, int len) { n = fz_read(state->chain, tmp, sizeof tmp); if (n < 0) - return fz_rethrow(n, "read error in jbig2 filter"); + return fz_error_note(n, "read error in jbig2 filter"); if (n == 0) break; jbig2_data_in(state->ctx, tmp, n); @@ -67,7 +67,7 @@ read_jbig2d(fz_stream *stm, unsigned char *buf, int len) state->page = jbig2_page_out(state->ctx); if (!state->page) - return fz_throw("jbig2_page_out failed"); + return fz_error_make("jbig2_page_out failed"); } s = state->page->data; @@ -85,7 +85,7 @@ fz_open_jbig2d(fz_stream *chain, fz_buffer *globals) { fz_jbig2d *state; - state = fz_malloc(sizeof(fz_jbig2d)); + state = fz_malloc(chain->ctx, sizeof(fz_jbig2d)); state->chain = chain; state->ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, NULL, NULL, NULL); state->gctx = NULL; @@ -99,5 +99,5 @@ fz_open_jbig2d(fz_stream *chain, fz_buffer *globals) state->ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, state->gctx, NULL, NULL); } - return fz_new_stream(state, read_jbig2d, close_jbig2d); + return fz_new_stream(chain->ctx, state, read_jbig2d, close_jbig2d); } diff --git a/fitz/filt_jpxd.c b/fitz/filt_jpxd.c index 101f4e10..64197a08 100644 --- a/fitz/filt_jpxd.c +++ b/fitz/filt_jpxd.c @@ -5,12 +5,14 @@ static void fz_opj_error_callback(const char *msg, void *client_data) { - fz_warn("openjpeg error: %s", msg); + fz_context *ctx = (fz_context *)client_data; + fz_warn(ctx, "openjpeg error: %s", msg); } static void fz_opj_warning_callback(const char *msg, void *client_data) { - fz_warn("openjpeg warning: %s", msg); + fz_context *ctx = (fz_context *)client_data; + fz_warn(ctx, "openjpeg warning: %s", msg); } static void fz_opj_info_callback(const char *msg, void *client_data) @@ -18,8 +20,8 @@ static void fz_opj_info_callback(const char *msg, void *client_data) /* fz_warn("openjpeg info: %s", msg); */ } -fz_error -fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace *defcs) +fz_pixmap * +fz_load_jpx_image(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs) { fz_pixmap *img; opj_event_mgr_t evtmgr; @@ -34,7 +36,7 @@ fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace int x, y, k, v; if (size < 2) - return fz_throw("not enough data to determine image format"); + fz_throw(ctx, "not enough data to determine image format"); /* Check for SOC marker -- if found we have a bare J2K stream */ if (data[0] == 0xFF && data[1] == 0x4F) @@ -50,6 +52,7 @@ fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace opj_set_default_decoder_parameters(¶ms); info = opj_create_decompress(format); + info->client_data = (void *)ctx; opj_set_event_mgr((opj_common_ptr)info, &evtmgr, stderr); opj_setup_decoder(info, ¶ms); @@ -61,16 +64,16 @@ fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace opj_destroy_decompress(info); if (!jpx) - return fz_throw("opj_decode failed"); + fz_throw(ctx, "opj_decode failed"); for (k = 1; k < jpx->numcomps; k++) { if (jpx->comps[k].w != jpx->comps[0].w) - return fz_throw("image components have different width"); + fz_throw(ctx, "image components have different width"); if (jpx->comps[k].h != jpx->comps[0].h) - return fz_throw("image components have different height"); + fz_throw(ctx, "image components have different height"); if (jpx->comps[k].prec != jpx->comps[0].prec) - return fz_throw("image components have different precision"); + fz_throw(ctx, "image components have different precision"); } n = jpx->numcomps; @@ -93,7 +96,7 @@ fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace } else { - fz_warn("jpx file and dict colorspaces do not match"); + fz_warn(ctx, "jpx file and dict colorspaces do not match"); defcs = NULL; } } @@ -108,11 +111,11 @@ fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace } } - img = fz_new_pixmap_with_limit(colorspace, w, h); + img = fz_new_pixmap_with_limit(ctx, colorspace, w, h); if (!img) { opj_image_destroy(jpx); - return fz_throw("out of memory"); + fz_throw(ctx, "out of memory"); } p = img->samples; @@ -138,9 +141,9 @@ fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace { if (n == 4) { - fz_pixmap *tmp = fz_new_pixmap(fz_device_rgb, w, h); - fz_convert_pixmap(img, tmp); - fz_drop_pixmap(img); + fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb, w, h); + fz_convert_pixmap(ctx, img, tmp); + fz_drop_pixmap(ctx, img); img = tmp; } fz_premultiply_pixmap(img); @@ -148,6 +151,5 @@ fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace opj_image_destroy(jpx); - *imgp = img; - return fz_okay; + return img; } diff --git a/fitz/filt_lzwd.c b/fitz/filt_lzwd.c index 942e5837..76cad305 100644 --- a/fitz/filt_lzwd.c +++ b/fitz/filt_lzwd.c @@ -104,7 +104,7 @@ read_lzwd(fz_stream *stm, unsigned char *buf, int len) else if (code == next_code) table[next_code].value = table[next_code].first_char; else - fz_warn("out of range code encountered in lzw decode"); + fz_warn(stm->ctx, "out of range code encountered in lzw decode"); next_code ++; @@ -160,7 +160,7 @@ close_lzwd(fz_stream *stm) { fz_lzwd *lzw = stm->state; fz_close(lzw->chain); - fz_free(lzw); + fz_free(stm->ctx, lzw); } fz_stream * @@ -170,7 +170,8 @@ fz_open_lzwd(fz_stream *chain, fz_obj *params) fz_obj *obj; int i; - lzw = fz_malloc(sizeof(fz_lzwd)); + assert(chain != NULL); + lzw = fz_malloc(chain->ctx, sizeof(fz_lzwd)); lzw->chain = chain; lzw->eod = 0; lzw->early_change = 1; @@ -202,5 +203,5 @@ fz_open_lzwd(fz_stream *chain, fz_obj *params) lzw->rp = lzw->bp; lzw->wp = lzw->bp; - return fz_new_stream(lzw, read_lzwd, close_lzwd); + return fz_new_stream(chain->ctx, lzw, read_lzwd, close_lzwd); } diff --git a/fitz/filt_predict.c b/fitz/filt_predict.c index 94f2718a..ed0d6d98 100644 --- a/fitz/filt_predict.c +++ b/fitz/filt_predict.c @@ -154,7 +154,7 @@ read_predict(fz_stream *stm, unsigned char *buf, int len) { n = fz_read(state->chain, state->in, state->stride + ispng); if (n < 0) - return fz_rethrow(n, "read error in prediction filter"); + return fz_error_note(n, "read error in prediction filter"); if (n == 0) return p - buf; @@ -183,10 +183,10 @@ close_predict(fz_stream *stm) { fz_predict *state = stm->state; fz_close(state->chain); - fz_free(state->in); - fz_free(state->out); - fz_free(state->ref); - fz_free(state); + fz_free(stm->ctx, state->in); + fz_free(stm->ctx, state->out); + fz_free(stm->ctx, state->ref); + fz_free(stm->ctx, state); } fz_stream * @@ -194,8 +194,9 @@ fz_open_predict(fz_stream *chain, fz_obj *params) { fz_predict *state; fz_obj *obj; + fz_context *ctx = chain->ctx; - state = fz_malloc(sizeof(fz_predict)); + state = fz_malloc(ctx, sizeof(fz_predict)); state->chain = chain; state->predictor = 1; @@ -212,7 +213,7 @@ fz_open_predict(fz_stream *chain, fz_obj *params) state->predictor != 12 && state->predictor != 13 && state->predictor != 14 && state->predictor != 15) { - fz_warn("invalid predictor: %d", state->predictor); + fz_warn(ctx, "invalid predictor: %d", state->predictor); state->predictor = 1; } @@ -231,13 +232,13 @@ fz_open_predict(fz_stream *chain, fz_obj *params) state->stride = (state->bpc * state->colors * state->columns + 7) / 8; state->bpp = (state->bpc * state->colors + 7) / 8; - state->in = fz_malloc(state->stride + 1); - state->out = fz_malloc(state->stride); - state->ref = fz_malloc(state->stride); + state->in = fz_malloc(ctx, state->stride + 1); + state->out = fz_malloc(ctx, state->stride); + state->ref = fz_malloc(ctx, state->stride); state->rp = state->out; state->wp = state->out; memset(state->ref, 0, state->stride); - return fz_new_stream(state, read_predict, close_predict); + return fz_new_stream(ctx, state, read_predict, close_predict); } diff --git a/fitz/fitz.h b/fitz/fitz.h index d0054f3e..70d14086 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -18,6 +18,10 @@ #include <float.h> /* FLT_EPSILON */ #include <fcntl.h> /* O_RDONLY & co */ +#include <setjmp.h> + +#include "memento.h" + #define nelem(x) (sizeof(x)/sizeof((x)[0])) #define ABS(x) ( (x) < 0 ? -(x) : (x) ) @@ -66,33 +70,33 @@ int gettimeofday(struct timeval *tv, struct timezone *tz); #if __STDC_VERSION__ == 199901L /* C99 */ -#define fz_throw(...) fz_throw_imp(__FILE__, __LINE__, __func__, __VA_ARGS__) -#define fz_rethrow(cause, ...) fz_rethrow_imp(__FILE__, __LINE__, __func__, cause, __VA_ARGS__) -#define fz_catch(cause, ...) fz_catch_imp(__FILE__, __LINE__, __func__, cause, __VA_ARGS__) +#define fz_error_make(...) fz_error_make_imp(__FILE__, __LINE__, __func__, __VA_ARGS__) +#define fz_error_note(cause, ...) fz_error_note_imp(__FILE__, __LINE__, __func__, cause, __VA_ARGS__) +#define fz_error_handle(cause, ...) fz_error_handle_imp(__FILE__, __LINE__, __func__, cause, __VA_ARGS__) #elif _MSC_VER >= 1500 /* MSVC 9 or newer */ #define inline __inline #define restrict __restrict -#define fz_throw(...) fz_throw_imp(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) -#define fz_rethrow(cause, ...) fz_rethrow_imp(__FILE__, __LINE__, __FUNCTION__, cause, __VA_ARGS__) -#define fz_catch(cause, ...) fz_catch_imp(__FILE__, __LINE__, __FUNCTION__, cause, __VA_ARGS__) +#define fz_error_make(...) fz_error_make_imp(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) +#define fz_error_note(cause, ...) fz_error_note_imp(__FILE__, __LINE__, __FUNCTION__, cause, __VA_ARGS__) +#define fz_error_handle(cause, ...) fz_error_handle_imp(__FILE__, __LINE__, __FUNCTION__, cause, __VA_ARGS__) #elif __GNUC__ >= 3 /* GCC 3 or newer */ #define inline __inline #define restrict __restrict -#define fz_throw(fmt...) fz_throw_imp(__FILE__, __LINE__, __FUNCTION__, fmt) -#define fz_rethrow(cause, fmt...) fz_rethrow_imp(__FILE__, __LINE__, __FUNCTION__, cause, fmt) -#define fz_catch(cause, fmt...) fz_catch_imp(__FILE__, __LINE__, __FUNCTION__, cause, fmt) +#define fz_error_make(fmt...) fz_error_make_imp(__FILE__, __LINE__, __FUNCTION__, fmt) +#define fz_error_note(cause, fmt...) fz_error_note_imp(__FILE__, __LINE__, __FUNCTION__, cause, fmt) +#define fz_error_handle(cause, fmt...) fz_error_handle_imp(__FILE__, __LINE__, __FUNCTION__, cause, fmt) #else /* Unknown or ancient */ #define inline #define restrict -#define fz_throw fz_throw_impx -#define fz_rethrow fz_rethrow_impx -#define fz_catch fz_catch_impx +#define fz_error_make fz_error_make_impx +#define fz_error_note fz_error_note_impx +#define fz_error_handle fz_error_handle_impx #endif @@ -110,38 +114,116 @@ int gettimeofday(struct timeval *tv, struct timezone *tz); #endif /* - * Error handling + * Deprecated error handling. */ typedef int fz_error; #define fz_okay ((fz_error)0) -void fz_warn(char *fmt, ...) __printflike(1, 2); -void fz_flush_warnings(void); - -fz_error fz_throw_imp(const char *file, int line, const char *func, char *fmt, ...) __printflike(4, 5); -fz_error fz_rethrow_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) __printflike(5, 6); -void fz_catch_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) __printflike(5, 6); +fz_error fz_error_make_imp(const char *file, int line, const char *func, char *fmt, ...) __printflike(4, 5); +fz_error fz_error_note_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) __printflike(5, 6); +void fz_error_handle_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) __printflike(5, 6); -fz_error fz_throw_impx(char *fmt, ...) __printflike(1, 2); -fz_error fz_rethrow_impx(fz_error cause, char *fmt, ...) __printflike(2, 3); -void fz_catch_impx(fz_error cause, char *fmt, ...) __printflike(2, 3); +fz_error fz_error_make_impx(char *fmt, ...) __printflike(1, 2); +fz_error fz_error_note_impx(fz_error cause, char *fmt, ...) __printflike(2, 3); +void fz_error_handle_impx(fz_error cause, char *fmt, ...) __printflike(2, 3); /* extract the last error stack trace */ int fz_get_error_count(void); char *fz_get_error_line(int n); +/* Contexts */ + +typedef struct fz_alloc_context_s fz_alloc_context; +typedef struct fz_error_context_s fz_error_context; +typedef struct fz_warn_context_s fz_warn_context; +typedef struct fz_font_context_s fz_font_context; +typedef struct fz_aa_context_s fz_aa_context; +typedef struct fz_context_s fz_context; + +struct fz_alloc_context_s +{ + void *user; + void *(*malloc)(void *, unsigned int); + void *(*realloc)(void *, void *, unsigned int); + void (*free)(void *, void *); +}; + +/* Default allocator */ +extern fz_alloc_context fz_alloc_default; + +struct fz_error_context_s +{ + int top; + struct { + jmp_buf buffer; + } stack[256]; + char message[256]; +}; + +#define fz_try(ctx) \ + if (fz_push_try(ctx->error), \ + !setjmp(ctx->error->stack[ctx->error->top].buffer)) \ + { do { + +#define fz_catch(ctx) \ + } while(0); \ + ctx->error->top--; \ + } \ + else + +void fz_push_try(fz_error_context *ex); +void fz_throw(fz_context *, char *, ...) __printflike(2, 3); +void fz_rethrow(fz_context *); + +struct fz_warn_context_s +{ + char message[256]; + int count; +}; + +void fz_warn(fz_context *ctx, char *fmt, ...) __printflike(2, 3); +void fz_flush_warnings(fz_context *ctx); + +struct fz_context_s +{ + fz_alloc_context *alloc; + fz_error_context *error; + fz_warn_context *warn; + fz_font_context *font; + fz_aa_context *aa; +}; + +fz_context *fz_new_context(fz_alloc_context *alloc); +fz_context *fz_clone_context(fz_context *ctx); +void fz_free_context(fz_context *ctx); + +void fz_new_aa_context(fz_context *ctx); +void fz_free_aa_context(fz_context *ctx); + /* * Basic runtime and utility functions */ /* memory allocation */ -void *fz_malloc(int size); -void *fz_calloc(int count, int size); -void *fz_realloc(void *p, int count, int size); -void fz_free(void *p); -char *fz_strdup(char *s); + +/* The following throw exceptions on failure to allocate */ +void *fz_malloc(fz_context *ctx, unsigned int size); +void *fz_malloc_array(fz_context *ctx, unsigned int count, unsigned int size); +void *fz_calloc(fz_context *ctx, unsigned int count, unsigned int size); +void *fz_resize_array(fz_context *ctx, void *p, unsigned int count, unsigned int size); +char *fz_strdup(fz_context *ctx, char *s); + +void fz_free(fz_context *ctx, void *p); + +/* The following returns NULL on failure to allocate */ +void *fz_malloc_no_throw(fz_context *ctx, unsigned int size); +void *fz_malloc_array_no_throw(fz_context *ctx, unsigned int count, unsigned int size); +void *fz_calloc_no_throw(fz_context *ctx, unsigned int count, unsigned int size); +void *fz_resize_array_no_throw(fz_context *ctx, void *p, unsigned int count, unsigned int size); +char *fz_strdup_no_throw(fz_context *ctx, char *s); + /* runtime (hah!) test for endian-ness */ int fz_is_big_endian(void); @@ -170,7 +252,7 @@ extern char *fz_optarg; typedef struct fz_hash_table_s fz_hash_table; -fz_hash_table *fz_new_hash_table(int initialsize, int keylen); +fz_hash_table *fz_new_hash_table(fz_context *ctx, int initialsize, int keylen); void fz_debug_hash(fz_hash_table *table); void fz_empty_hash(fz_hash_table *table); void fz_free_hash(fz_hash_table *table); @@ -357,20 +439,20 @@ void aes_crypt_cbc( fz_aes *ctx, int mode, int length, typedef struct fz_obj_s fz_obj; -extern fz_obj* (*fz_resolve_indirect)(fz_obj*); +extern fz_obj *(*fz_resolve_indirect)(fz_obj *obj); -fz_obj *fz_new_null(void); -fz_obj *fz_new_bool(int b); -fz_obj *fz_new_int(int i); -fz_obj *fz_new_real(float f); -fz_obj *fz_new_name(char *str); -fz_obj *fz_new_string(char *str, int len); -fz_obj *fz_new_indirect(int num, int gen, void *xref); +fz_obj *fz_new_null(fz_context *ctx); +fz_obj *fz_new_bool(fz_context *ctx, int b); +fz_obj *fz_new_int(fz_context *ctx, int i); +fz_obj *fz_new_real(fz_context *ctx, float f); +fz_obj *fz_new_name(fz_context *ctx, char *str); +fz_obj *fz_new_string(fz_context *ctx, char *str, int len); +fz_obj *fz_new_indirect(fz_context *ctx, int num, int gen, void *xref); -fz_obj *fz_new_array(int initialcap); -fz_obj *fz_new_dict(int initialcap); -fz_obj *fz_copy_array(fz_obj *array); -fz_obj *fz_copy_dict(fz_obj *dict); +fz_obj *fz_new_array(fz_context *ctx, int initialcap); +fz_obj *fz_new_dict(fz_context *ctx, int initialcap); +fz_obj *fz_copy_array(fz_context *ctx, fz_obj *array); +fz_obj *fz_copy_dict(fz_context *ctx, fz_obj *dict); fz_obj *fz_keep_obj(fz_obj *obj); void fz_drop_obj(fz_obj *obj); @@ -388,7 +470,7 @@ int fz_is_indirect(fz_obj *obj); int fz_objcmp(fz_obj *a, fz_obj *b); -/* safe, silent failure, no error reporting */ +/* safe, silent failure, no error reporting on type mismatches */ int fz_to_bool(fz_obj *obj); int fz_to_int(fz_obj *obj); float fz_to_real(fz_obj *obj); @@ -437,12 +519,12 @@ struct fz_buffer_s int cap, len; }; -fz_buffer *fz_new_buffer(int size); +fz_buffer *fz_new_buffer(fz_context *ctx, int size); fz_buffer *fz_keep_buffer(fz_buffer *buf); -void fz_drop_buffer(fz_buffer *buf); +void fz_drop_buffer(fz_context *ctx, fz_buffer *buf); -void fz_resize_buffer(fz_buffer *buf, int size); -void fz_grow_buffer(fz_buffer *buf); +void fz_resize_buffer(fz_context *ctx, fz_buffer *buf, int size); +void fz_grow_buffer(fz_context *ctx, fz_buffer *buf); /* * Buffered reader. @@ -453,6 +535,7 @@ typedef struct fz_stream_s fz_stream; struct fz_stream_s { + fz_context *ctx; int refs; int error; int eof; @@ -467,14 +550,14 @@ struct fz_stream_s unsigned char buf[4096]; }; -fz_stream *fz_open_fd(int file); -fz_stream *fz_open_file(const char *filename); -fz_stream *fz_open_file_w(const wchar_t *filename); /* only on win32 */ -fz_stream *fz_open_buffer(fz_buffer *buf); -fz_stream *fz_open_memory(unsigned char *data, int len); +fz_stream *fz_open_fd(fz_context *ctx, int file); +fz_stream *fz_open_file(fz_context *ctx, const char *filename); +fz_stream *fz_open_file_w(fz_context *ctx, const wchar_t *filename); /* only on win32 */ +fz_stream *fz_open_buffer(fz_context *ctx, fz_buffer *buf); +fz_stream *fz_open_memory(fz_context *ctx, unsigned char *data, int len); void fz_close(fz_stream *stm); -fz_stream *fz_new_stream(void*, int(*)(fz_stream*, unsigned char*, int), void(*)(fz_stream *)); +fz_stream *fz_new_stream(fz_context *ctx, void*, int(*)(fz_stream*, unsigned char*, int), void(*)(fz_stream *)); fz_stream *fz_keep_stream(fz_stream *stm); void fz_fill_buffer(fz_stream *stm); @@ -483,7 +566,7 @@ void fz_seek(fz_stream *stm, int offset, int whence); int fz_read(fz_stream *stm, unsigned char *buf, int len); void fz_read_line(fz_stream *stm, char *buf, int max); -fz_error fz_read_all(fz_buffer **bufp, fz_stream *stm, int initial); +fz_buffer *fz_read_all(fz_stream *stm, int initial); static inline int fz_read_byte(fz_stream *stm) { @@ -613,32 +696,32 @@ struct fz_pixmap_s }; /* will return NULL if soft limit is exceeded */ -fz_pixmap *fz_new_pixmap_with_limit(fz_colorspace *colorspace, int w, int h); +fz_pixmap *fz_new_pixmap_with_limit(fz_context *ctx, fz_colorspace *colorspace, int w, int h); -fz_pixmap *fz_new_pixmap_with_data(fz_colorspace *colorspace, int w, int h, unsigned char *samples); -fz_pixmap *fz_new_pixmap_with_rect(fz_colorspace *, fz_bbox bbox); -fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_colorspace *, fz_bbox bbox, unsigned char *samples); -fz_pixmap *fz_new_pixmap(fz_colorspace *, int w, int h); +fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples); +fz_pixmap *fz_new_pixmap_with_rect(fz_context *ctx, fz_colorspace *, fz_bbox bbox); +fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, fz_colorspace *, fz_bbox bbox, unsigned char *samples); +fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *, int w, int h); fz_pixmap *fz_keep_pixmap(fz_pixmap *pix); -void fz_drop_pixmap(fz_pixmap *pix); +void fz_drop_pixmap(fz_context *ctx, fz_pixmap *pix); void fz_clear_pixmap(fz_pixmap *pix); void fz_clear_pixmap_with_color(fz_pixmap *pix, int value); void fz_clear_pixmap_rect_with_color(fz_pixmap *pix, int value, fz_bbox r); void fz_copy_pixmap_rect(fz_pixmap *dest, fz_pixmap *src, fz_bbox r); void fz_premultiply_pixmap(fz_pixmap *pix); void fz_unmultiply_pixmap(fz_pixmap *pix); -fz_pixmap *fz_alpha_from_gray(fz_pixmap *gray, int luminosity); +fz_pixmap *fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity); fz_bbox fz_bound_pixmap(fz_pixmap *pix); void fz_invert_pixmap(fz_pixmap *pix); void fz_gamma_pixmap(fz_pixmap *pix, float gamma); -fz_pixmap *fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h); +fz_pixmap *fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h); -fz_error fz_write_pnm(fz_pixmap *pixmap, char *filename); -fz_error fz_write_pam(fz_pixmap *pixmap, char *filename, int savealpha); -fz_error fz_write_png(fz_pixmap *pixmap, char *filename, int savealpha); +void fz_write_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename); +void fz_write_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha); +void fz_write_png(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha); -fz_error fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace *dcs); +fz_pixmap *fz_load_jpx_image(fz_context *ctx, unsigned char *data, int size, fz_colorspace *dcs); /* * Bitmaps have 1 component per bit. Only used for creating halftoned versions @@ -655,12 +738,12 @@ struct fz_bitmap_s unsigned char *samples; }; -fz_bitmap *fz_new_bitmap(int w, int h, int n); +fz_bitmap *fz_new_bitmap(fz_context *ctx, int w, int h, int n); fz_bitmap *fz_keep_bitmap(fz_bitmap *bit); void fz_clear_bitmap(fz_bitmap *bit); -void fz_drop_bitmap(fz_bitmap *bit); +void fz_drop_bitmap(fz_context *ctx, fz_bitmap *bit); -fz_error fz_write_pbm(fz_bitmap *bitmap, char *filename); +void fz_write_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename); /* * A halftone is a set of threshold tiles, one per component. Each threshold @@ -676,12 +759,12 @@ struct fz_halftone_s fz_pixmap *comp[1]; }; -fz_halftone *fz_new_halftone(int num_comps); -fz_halftone *fz_get_default_halftone(int num_comps); +fz_halftone *fz_new_halftone(fz_context *ctx, int num_comps); +fz_halftone *fz_get_default_halftone(fz_context *ctx, int num_comps); fz_halftone *fz_keep_halftone(fz_halftone *half); -void fz_drop_halftone(fz_halftone *half); +void fz_drop_halftone(fz_context *ctx, fz_halftone *half); -fz_bitmap *fz_halftone_pixmap(fz_pixmap *pix, fz_halftone *ht); +fz_bitmap *fz_halftone_pixmap(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht); /* * Colorspace resources. @@ -697,18 +780,18 @@ struct fz_colorspace_s int refs; char name[16]; int n; - void (*to_rgb)(fz_colorspace *, float *src, float *rgb); - void (*from_rgb)(fz_colorspace *, float *rgb, float *dst); - void (*free_data)(fz_colorspace *); + void (*to_rgb)(fz_context *ctx, fz_colorspace *, float *src, float *rgb); + void (*from_rgb)(fz_context *ctx, fz_colorspace *, float *rgb, float *dst); + void (*free_data)(fz_context *Ctx, fz_colorspace *); void *data; }; -fz_colorspace *fz_new_colorspace(char *name, int n); +fz_colorspace *fz_new_colorspace(fz_context *ctx, char *name, int n); fz_colorspace *fz_keep_colorspace(fz_colorspace *colorspace); -void fz_drop_colorspace(fz_colorspace *colorspace); +void fz_drop_colorspace(fz_context *ctx, fz_colorspace *colorspace); -void fz_convert_color(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv); -void fz_convert_pixmap(fz_pixmap *src, fz_pixmap *dst); +void fz_convert_color(fz_context *ctx, fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv); +void fz_convert_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst); fz_colorspace *fz_find_device_colorspace(char *name); @@ -744,7 +827,7 @@ struct fz_font_s fz_buffer **t3procs; /* has 256 entries if used */ float *t3widths; /* has 256 entries if used */ void *t3xref; /* a pdf_xref for the callback */ - fz_error (*t3run)(void *xref, fz_obj *resources, fz_buffer *contents, + void (*t3run)(void *xref, fz_obj *resources, fz_buffer *contents, struct fz_device_s *dev, fz_matrix ctm); fz_rect bbox; @@ -754,13 +837,16 @@ struct fz_font_s int *width_table; }; -fz_font *fz_new_type3_font(char *name, fz_matrix matrix); +void fz_new_font_context(fz_context *ctx); +void fz_free_font_context(fz_context *ctx); + +fz_font *fz_new_type3_font(fz_context *ctx, char *name, fz_matrix matrix); -fz_error fz_new_font_from_memory(fz_font **fontp, unsigned char *data, int len, int index); -fz_error fz_new_font_from_file(fz_font **fontp, char *path, int index); +fz_font *fz_new_font_from_memory(fz_context *ctx, unsigned char *data, int len, int index); +fz_font *fz_new_font_from_file(fz_context *ctx, char *path, int index); fz_font *fz_keep_font(fz_font *font); -void fz_drop_font(fz_font *font); +void fz_drop_font(fz_context *ctx, fz_font *font); void fz_debug_font(fz_font *font); void fz_set_font_bbox(fz_font *font, float xmin, float ymin, float xmax, float ymax); @@ -810,18 +896,18 @@ struct fz_stroke_state_s float dash_list[32]; }; -fz_path *fz_new_path(void); -void fz_moveto(fz_path*, float x, float y); -void fz_lineto(fz_path*, float x, float y); -void fz_curveto(fz_path*, float, float, float, float, float, float); -void fz_curvetov(fz_path*, float, float, float, float); -void fz_curvetoy(fz_path*, float, float, float, float); -void fz_closepath(fz_path*); -void fz_free_path(fz_path *path); +fz_path *fz_new_path(fz_context *ctx); +void fz_moveto(fz_context*, fz_path*, float x, float y); +void fz_lineto(fz_context*, fz_path*, float x, float y); +void fz_curveto(fz_context*,fz_path*, float, float, float, float, float, float); +void fz_curvetov(fz_context*,fz_path*, float, float, float, float); +void fz_curvetoy(fz_context*,fz_path*, float, float, float, float); +void fz_closepath(fz_context*,fz_path*); +void fz_free_path(fz_context *ctx, fz_path *path); void fz_transform_path(fz_path *path, fz_matrix transform); -fz_path *fz_clone_path(fz_path *old); +fz_path *fz_clone_path(fz_context *ctx, fz_path *old); fz_rect fz_bound_path(fz_path *path, fz_stroke_state *stroke, fz_matrix ctm); void fz_debug_path(fz_path *, int indent); @@ -857,12 +943,12 @@ struct fz_text_s fz_text_item *items; }; -fz_text *fz_new_text(fz_font *face, fz_matrix trm, int wmode); -void fz_add_text(fz_text *text, int gid, int ucs, float x, float y); -void fz_free_text(fz_text *text); +fz_text *fz_new_text(fz_context *ctx, fz_font *face, fz_matrix trm, int wmode); +void fz_add_text(fz_context *ctx, fz_text *text, int gid, int ucs, float x, float y); +void fz_free_text(fz_context *ctx, fz_text *text); void fz_debug_text(fz_text*, int indent); fz_rect fz_bound_text(fz_text *text, fz_matrix ctm); -fz_text *fz_clone_text(fz_text *old); +fz_text *fz_clone_text(fz_context *ctx, fz_text *old); /* * The shading code uses gouraud shaded triangle meshes. @@ -900,11 +986,11 @@ struct fz_shade_s }; fz_shade *fz_keep_shade(fz_shade *shade); -void fz_drop_shade(fz_shade *shade); +void fz_drop_shade(fz_context *ctx, fz_shade *shade); void fz_debug_shade(fz_shade *shade); fz_rect fz_bound_shade(fz_shade *shade, fz_matrix ctm); -void fz_paint_shade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox); +void fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox); /* * Glyph cache @@ -912,24 +998,24 @@ void fz_paint_shade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbo typedef struct fz_glyph_cache_s fz_glyph_cache; -fz_glyph_cache *fz_new_glyph_cache(void); -fz_pixmap *fz_render_ft_glyph(fz_font *font, int cid, fz_matrix trm); -fz_pixmap *fz_render_t3_glyph(fz_font *font, int cid, fz_matrix trm, fz_colorspace *model); -fz_pixmap *fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *state); -fz_pixmap *fz_render_glyph(fz_glyph_cache*, fz_font*, int, fz_matrix, fz_colorspace *model); -fz_pixmap *fz_render_stroked_glyph(fz_glyph_cache*, fz_font*, int, fz_matrix, fz_matrix, fz_stroke_state *stroke); -void fz_free_glyph_cache(fz_glyph_cache *); +fz_glyph_cache *fz_new_glyph_cache(fz_context *ctx); +fz_pixmap *fz_render_ft_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm); +fz_pixmap *fz_render_t3_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm, fz_colorspace *model); +fz_pixmap *fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *state); +fz_pixmap *fz_render_glyph(fz_context *ctx, fz_glyph_cache*, fz_font*, int, fz_matrix, fz_colorspace *model); +fz_pixmap *fz_render_stroked_glyph(fz_context *ctx, fz_glyph_cache*, fz_font*, int, fz_matrix, fz_matrix, fz_stroke_state *stroke); +void fz_free_glyph_cache(fz_context *ctx, fz_glyph_cache *); /* * Scan converter */ -int fz_get_aa_level(void); -void fz_set_aa_level(int bits); +int fz_get_aa_level(fz_context *ctx); +void fz_set_aa_level(fz_context *ctx, int bits); typedef struct fz_gel_s fz_gel; -fz_gel *fz_new_gel(void); +fz_gel *fz_new_gel(fz_context *ctx); void fz_insert_gel(fz_gel *gel, float x0, float y0, float x1, float y1); void fz_reset_gel(fz_gel *gel, fz_bbox clip); void fz_sort_gel(fz_gel *gel); @@ -966,33 +1052,34 @@ struct fz_device_s int flags; void *user; - void (*free_user)(void *); - - void (*fill_path)(void *, fz_path *, int even_odd, fz_matrix, fz_colorspace *, float *color, float alpha); - void (*stroke_path)(void *, fz_path *, fz_stroke_state *, fz_matrix, fz_colorspace *, float *color, float alpha); - void (*clip_path)(void *, fz_path *, fz_rect *rect, int even_odd, fz_matrix); - void (*clip_stroke_path)(void *, fz_path *, fz_rect *rect, fz_stroke_state *, fz_matrix); - - void (*fill_text)(void *, fz_text *, fz_matrix, fz_colorspace *, float *color, float alpha); - void (*stroke_text)(void *, fz_text *, fz_stroke_state *, fz_matrix, fz_colorspace *, float *color, float alpha); - void (*clip_text)(void *, fz_text *, fz_matrix, int accumulate); - void (*clip_stroke_text)(void *, fz_text *, fz_stroke_state *, fz_matrix); - void (*ignore_text)(void *, fz_text *, fz_matrix); - - void (*fill_shade)(void *, fz_shade *shd, fz_matrix ctm, float alpha); - void (*fill_image)(void *, fz_pixmap *img, fz_matrix ctm, float alpha); - void (*fill_image_mask)(void *, fz_pixmap *img, fz_matrix ctm, fz_colorspace *, float *color, float alpha); - void (*clip_image_mask)(void *, fz_pixmap *img, fz_rect *rect, fz_matrix ctm); - - void (*pop_clip)(void *); - - void (*begin_mask)(void *, fz_rect, int luminosity, fz_colorspace *, float *bc); - void (*end_mask)(void *); - void (*begin_group)(void *, fz_rect, int isolated, int knockout, int blendmode, float alpha); - void (*end_group)(void *); - - void (*begin_tile)(void *, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm); - void (*end_tile)(void *); + void (*free_user)(fz_device *); + fz_context *ctx; + + void (*fill_path)(fz_device *, fz_path *, int even_odd, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*stroke_path)(fz_device *, fz_path *, fz_stroke_state *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*clip_path)(fz_device *, fz_path *, fz_rect *rect, int even_odd, fz_matrix); + void (*clip_stroke_path)(fz_device *, fz_path *, fz_rect *rect, fz_stroke_state *, fz_matrix); + + void (*fill_text)(fz_device *, fz_text *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*stroke_text)(fz_device *, fz_text *, fz_stroke_state *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*clip_text)(fz_device *, fz_text *, fz_matrix, int accumulate); + void (*clip_stroke_text)(fz_device *, fz_text *, fz_stroke_state *, fz_matrix); + void (*ignore_text)(fz_device *, fz_text *, fz_matrix); + + void (*fill_shade)(fz_device *, fz_shade *shd, fz_matrix ctm, float alpha); + void (*fill_image)(fz_device *, fz_pixmap *img, fz_matrix ctm, float alpha); + void (*fill_image_mask)(fz_device *, fz_pixmap *img, fz_matrix ctm, fz_colorspace *, float *color, float alpha); + void (*clip_image_mask)(fz_device *, fz_pixmap *img, fz_rect *rect, fz_matrix ctm); + + void (*pop_clip)(fz_device *); + + void (*begin_mask)(fz_device *, fz_rect, int luminosity, fz_colorspace *, float *bc); + void (*end_mask)(fz_device *); + void (*begin_group)(fz_device *, fz_rect, int isolated, int knockout, int blendmode, float alpha); + void (*end_group)(fz_device *); + + void (*begin_tile)(fz_device *, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm); + void (*end_tile)(fz_device *); }; void fz_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); @@ -1016,13 +1103,13 @@ void fz_end_group(fz_device *dev); void fz_begin_tile(fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm); void fz_end_tile(fz_device *dev); -fz_device *fz_new_device(void *user); +fz_device *fz_new_device(fz_context *ctx, void *user); void fz_free_device(fz_device *dev); -fz_device *fz_new_trace_device(void); -fz_device *fz_new_bbox_device(fz_bbox *bboxp); -fz_device *fz_new_draw_device(fz_glyph_cache *cache, fz_pixmap *dest); -fz_device *fz_new_draw_device_type3(fz_glyph_cache *cache, fz_pixmap *dest); +fz_device *fz_new_trace_device(fz_context *ctx); +fz_device *fz_new_bbox_device(fz_context *ctx, fz_bbox *bboxp); +fz_device *fz_new_draw_device(fz_context *ctx, fz_glyph_cache *cache, fz_pixmap *dest); +fz_device *fz_new_draw_device_type3(fz_context *ctx, fz_glyph_cache *cache, fz_pixmap *dest); /* * Text extraction device @@ -1048,12 +1135,12 @@ struct fz_text_span_s int eol; }; -fz_text_span *fz_new_text_span(void); -void fz_free_text_span(fz_text_span *line); +fz_text_span *fz_new_text_span(fz_context *ctx); +void fz_free_text_span(fz_context *ctx, fz_text_span *line); void fz_debug_text_span(fz_text_span *line); void fz_debug_text_span_xml(fz_text_span *span); -fz_device *fz_new_text_device(fz_text_span *text); +fz_device *fz_new_text_device(fz_context *ctx, fz_text_span *text); /* * Display list device -- record and play back device commands. @@ -1061,9 +1148,9 @@ fz_device *fz_new_text_device(fz_text_span *text); typedef struct fz_display_list_s fz_display_list; -fz_display_list *fz_new_display_list(void); -void fz_free_display_list(fz_display_list *list); -fz_device *fz_new_list_device(fz_display_list *list); +fz_display_list *fz_new_display_list(fz_context *ctx); +void fz_free_display_list(fz_context *ctx, fz_display_list *list); +fz_device *fz_new_list_device(fz_context *ctx, fz_display_list *list); void fz_execute_display_list(fz_display_list *list, fz_device *dev, fz_matrix ctm, fz_bbox area); /* @@ -1074,6 +1161,7 @@ typedef struct fz_outline_s fz_outline; struct fz_outline_s { + fz_context *ctx; char *title; int page; fz_outline *next; diff --git a/fitz/memento.c b/fitz/memento.c new file mode 100644 index 00000000..24e19e3a --- /dev/null +++ b/fitz/memento.c @@ -0,0 +1,1049 @@ +/* Copyright (C) 2011 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, modified + or distributed except as expressly authorized under the terms of that + license. Refer to licensing information at http://www.artifex.com/ + or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, + San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. +*/ + +/* Inspired by Fortify by Simon P Bullen. */ + +/* Set the following if you're only looking for leaks, not memory overwrites + * to speed the operation */ +#undef MEMENTO_LEAKONLY + +#ifndef MEMENTO_STACKTRACE_METHOD +#ifdef __GNUC__ +#define MEMENTO_STACKTRACE_METHOD 1 +#endif +#endif + +/* Don't keep blocks around if they'd mean losing more than a quarter of + * the freelist. */ +#define MEMENTO_FREELIST_MAX_SINGLE_BLOCK (MEMENTO_FREELIST_MAX/4) + +#define COMPILING_MEMENTO_C +#include "memento.h" +#include <stdio.h> +#include <stdlib.h> + +#if defined(__linux__) +#define MEMENTO_HAS_FORK +#elif defined(__APPLE__) && defined(__MACH__) +#define MEMENTO_HAS_FORK +#endif + +/* Define the underlying allocators, just in case */ +void *MEMENTO_UNDERLYING_MALLOC(size_t); +void MEMENTO_UNDERLYING_FREE(void *); +void *MEMENTO_UNDERLYING_REALLOC(void *,size_t); +void *MEMENTO_UNDERLYING_CALLOC(size_t,size_t); + +/* And some other standard functions we use. We don't include the header + * files, just in case they pull in unexpected others. */ +int atoi(const char *); +char *getenv(const char *); +//void *memset(void *,int,size_t); +//int atexit(void (*)(void)); + +#ifdef MEMENTO + +#ifdef HAVE_VALGRIND +#include "valgrind/memcheck.h" +#else +#define VALGRIND_MAKE_MEM_NOACCESS(p,s) do { } while (0==1) +#define VALGRIND_MAKE_MEM_UNDEFINED(p,s) do { } while (0==1) +#define VALGRIND_MAKE_MEM_DEFINED(p,s) do { } while (0==1) +#endif + +enum { + Memento_PreSize = 16, + Memento_PostSize = 16 +}; + +typedef struct Memento_BlkHeader Memento_BlkHeader; + +struct Memento_BlkHeader +{ + size_t rawsize; + int sequence; + int lastCheckedOK; + Memento_BlkHeader *next; + char preblk[Memento_PreSize]; +}; + +/* In future this could (should) be a smarter data structure, like, say, + * splay trees. For now, we use a list. + */ +typedef struct Memento_Blocks +{ + Memento_BlkHeader *head; + Memento_BlkHeader **tail; +} Memento_Blocks; + +/* And our global structure */ +static struct { + int inited; + Memento_Blocks used; + Memento_Blocks free; + size_t freeListSize; + int sequence; + int paranoia; + int paranoidAt; + int countdown; + int lastChecked; + int breakAt; + int failAt; + int failing; + int squeezeAt; + int squeezing; + int squeezed; + size_t alloc; + size_t peakAlloc; + size_t totalAlloc; + size_t numMallocs; + size_t numFrees; + size_t numReallocs; +} globals; + + +#define MEMENTO_EXTRASIZE (sizeof(Memento_BlkHeader) + Memento_PostSize) + +/* Round up size S to the next multiple of N (where N is a power of 2) */ +#define MEMENTO_ROUNDUP(S,N) ((S + N-1)&~(N-1)) + +#define MEMBLK_SIZE(s) MEMENTO_ROUNDUP(s + MEMENTO_EXTRASIZE, MEMENTO_MAXALIGN) + +#define MEMBLK_FROMBLK(B) (&((Memento_BlkHeader*)(void *)(B))[-1]) +#define MEMBLK_TOBLK(B) ((void*)(&((Memento_BlkHeader*)(void*)(B))[1])) +#define MEMBLK_POSTPTR(B) \ + (&((char *)(void *)(B))[(B)->rawsize + sizeof(Memento_BlkHeader)]) + +void Memento_breakpoint(void) +{ + /* A handy externally visible function for breakpointing */ +#if 0 /* Enable this to force automatic breakpointing */ +#ifdef DEBUG +#ifdef _MSC_VER + __asm int 3; +#endif +#endif +#endif +} + +static void Memento_addBlockHead(Memento_Blocks *blks, + Memento_BlkHeader *b, + int type) +{ + if (blks->tail == &blks->head) { + /* Adding into an empty list, means the tail changes too */ + blks->tail = &b->next; + } + b->next = blks->head; + blks->head = b; +#ifndef MEMENTO_LEAKONLY + memset(b->preblk, MEMENTO_PREFILL, Memento_PreSize); + memset(MEMBLK_POSTPTR(b), MEMENTO_POSTFILL, Memento_PostSize); +#endif + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(b), Memento_PostSize); + if (type == 0) { /* malloc */ + VALGRIND_MAKE_MEM_UNDEFINED(MEMBLK_TOBLK(b), b->rawsize); + } else if (type == 1) { /* free */ + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_TOBLK(b), b->rawsize); + } + VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader)); +} + +static void Memento_addBlockTail(Memento_Blocks *blks, + Memento_BlkHeader *b, + int type) +{ + VALGRIND_MAKE_MEM_DEFINED(blks->tail, sizeof(Memento_BlkHeader *)); + *blks->tail = b; + blks->tail = &b->next; + b->next = NULL; + VALGRIND_MAKE_MEM_NOACCESS(blks->tail, sizeof(Memento_BlkHeader *)); +#ifndef MEMENTO_LEAKONLY + memset(b->preblk, MEMENTO_PREFILL, Memento_PreSize); + memset(MEMBLK_POSTPTR(b), MEMENTO_POSTFILL, Memento_PostSize); +#endif + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(b), Memento_PostSize); + if (type == 0) { /* malloc */ + VALGRIND_MAKE_MEM_UNDEFINED(MEMBLK_TOBLK(b), b->rawsize); + } else if (type == 1) { /* free */ + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_TOBLK(b), b->rawsize); + } + VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader)); +} + +typedef struct BlkCheckData { + int found; + int preCorrupt; + int postCorrupt; + int freeCorrupt; + int index; +} BlkCheckData; + +static int Memento_Internal_checkAllocedBlock(Memento_BlkHeader *b, void *arg) +{ +#ifndef MEMENTO_LEAKONLY + int i; + char *p; + int corrupt = 0; + BlkCheckData *data = (BlkCheckData *)arg; + + p = b->preblk; + i = Memento_PreSize; + do { + corrupt |= (*p++ ^ (char)MEMENTO_PREFILL); + } while (--i); + if (corrupt) { + data->preCorrupt = 1; + } + p = MEMBLK_POSTPTR(b); + i = Memento_PreSize; + do { + corrupt |= (*p++ ^ (char)MEMENTO_POSTFILL); + } while (--i); + if (corrupt) { + data->postCorrupt = 1; + } + if ((data->freeCorrupt | data->preCorrupt | data->postCorrupt) == 0) { + b->lastCheckedOK = globals.sequence; + } + data->found |= 1; +#endif + return 0; +} + +static int Memento_Internal_checkFreedBlock(Memento_BlkHeader *b, void *arg) +{ +#ifndef MEMENTO_LEAKONLY + int i; + char *p; + BlkCheckData *data = (BlkCheckData *)arg; + + p = MEMBLK_TOBLK(b); + i = b->rawsize; + /* Attempt to speed this up by checking an (aligned) int at a time */ + do { + if (((size_t)p) & 1) { + if (*p++ != (char)MEMENTO_FREEFILL) + break; + i--; + if (i == 0) + break; + } + if ((i >= 2) && (((size_t)p) & 2)) { + if (*(short *)p != (short)(MEMENTO_FREEFILL | (MEMENTO_FREEFILL<<8))) + goto mismatch; + p += 2; + i -= 2; + if (i == 0) + break; + } + i -= 4; + while (i >= 0) { + if (*(int *)p != (MEMENTO_FREEFILL | + (MEMENTO_FREEFILL<<8) | + (MEMENTO_FREEFILL<<16) | + (MEMENTO_FREEFILL<<24))) + goto mismatch; + p += 4; + i -= 4; + } + i += 4; + if ((i >= 2) && (((size_t)p) & 2)) { + if (*(short *)p != (short)(MEMENTO_FREEFILL | (MEMENTO_FREEFILL<<8))) + goto mismatch; + p += 2; + i -= 2; + } +mismatch: + while (i) { + if (*p++ != (char)MEMENTO_FREEFILL) + break; + i--; + } + } while (0); + if (i) { + data->freeCorrupt = 1; + data->index = b->rawsize-i; + } + return Memento_Internal_checkAllocedBlock(b, arg); +#else + return 0; +#endif +} + +static void Memento_removeBlock(Memento_Blocks *blks, + Memento_BlkHeader *b) +{ + Memento_BlkHeader *head = blks->head; + Memento_BlkHeader *prev = NULL; + while ((head) && (head != b)) { + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head)); + prev = head; + head = head->next; + VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev)); + } + if (head == NULL) { + /* FAIL! Will have been reported to user earlier, so just exit. */ + return; + } + if (*blks->tail == head) { + /* Removing the tail of the list */ + if (prev == NULL) { + /* Which is also the head */ + blks->tail = &blks->head; + } else { + /* Which isn't the head */ + blks->tail = &prev->next; + } + } + if (prev == NULL) { + /* Removing from the head of the list */ + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head)); + blks->head = head->next; + VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(*head)); + } else { + /* Removing from not-the-head */ + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head)); + VALGRIND_MAKE_MEM_DEFINED(prev, sizeof(*prev)); + prev->next = head->next; + VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(*head)); + VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev)); + } +} + +static int Memento_Internal_makeSpace(size_t space) +{ + /* If too big, it can never go on the freelist */ + if (space > MEMENTO_FREELIST_MAX_SINGLE_BLOCK) + return 0; + /* Pretend we added it on. */ + globals.freeListSize += space; + /* Ditch blocks until it fits within our limit */ + while (globals.freeListSize > MEMENTO_FREELIST_MAX) { + Memento_BlkHeader *head = globals.free.head; + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head)); + globals.free.head = head->next; + globals.freeListSize -= MEMBLK_SIZE(head->rawsize); + MEMENTO_UNDERLYING_FREE(head); + } + /* Make sure we haven't just completely emptied the free list */ + /* (This should never happen, but belt and braces... */ + if (globals.free.head == NULL) + globals.free.tail = &globals.free.head; + return 1; +} + +static int Memento_appBlocks(Memento_Blocks *blks, + int (*app)(Memento_BlkHeader *, + void *), + void *arg) +{ + Memento_BlkHeader *head = blks->head; + Memento_BlkHeader *next; + int result; + while (head) { + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader)); + VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(head), + head->rawsize + Memento_PostSize); + result = app(head, arg); + next = head->next; + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize); + VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(Memento_BlkHeader)); + if (result) + return result; + head = next; + } + return 0; +} + +static int Memento_appBlock(Memento_Blocks *blks, + int (*app)(Memento_BlkHeader *, + void *), + void *arg, + Memento_BlkHeader *b) +{ + Memento_BlkHeader *head = blks->head; + Memento_BlkHeader *next; + int result; + while (head && head != b) { + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader)); + next = head->next; + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize); + head = next; + } + if (head == b) { + VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader)); + VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(head), + head->rawsize + Memento_PostSize); + result = app(head, arg); + VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize); + VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(Memento_BlkHeader)); + return result; + } + return 0; +} + +static int Memento_listBlock(Memento_BlkHeader *b, + void *arg) +{ + int *counts = (int *)arg; + fprintf(stderr, " 0x%p:(size=%d,num=%d)\n", + MEMBLK_TOBLK(b), (int)b->rawsize, b->sequence); + counts[0]++; + counts[1]+= b->rawsize; + return 0; +} + +static void Memento_listBlocks(void) { + int counts[2]; + counts[0] = 0; + counts[1] = 0; + fprintf(stderr, "Allocated blocks:\n"); + Memento_appBlocks(&globals.used, Memento_listBlock, &counts[0]); + fprintf(stderr, " Total number of blocks = %d\n", counts[0]); + fprintf(stderr, " Total size of blocks = %d\n", counts[1]); +} + +static void Memento_fin(void) +{ + Memento_checkAllMemory(); + fprintf(stderr, "Total memory malloced = %d bytes\n", globals.totalAlloc); + fprintf(stderr, "Peak memory malloced = %d bytes\n", globals.peakAlloc); + fprintf(stderr, "%d mallocs, %d frees, %d reallocs\n", globals.numMallocs, + globals.numFrees, globals.numReallocs); + fprintf(stderr, "Average allocation size %d bytes\n", + globals.totalAlloc/globals.numMallocs); + if (globals.used.head != NULL) { + Memento_listBlocks(); + Memento_breakpoint(); + } + if (globals.squeezed) { + fprintf(stderr, "Memory squeezing @ %d complete\n", globals.squeezed); + } +} + +static void Memento_inited(void) +{ + /* A good place for a breakpoint */ +} + +static void Memento_init(void) +{ + char *env; + memset(&globals, 0, sizeof(globals)); + globals.inited = 1; + globals.used.head = NULL; + globals.used.tail = &globals.used.head; + globals.free.head = NULL; + globals.free.tail = &globals.free.head; + globals.sequence = 0; + globals.countdown = 1024; + + env = getenv("MEMENTO_FAILAT"); + globals.failAt = (env ? atoi(env) : 0); + + env = getenv("MEMENTO_PARANOIA"); + globals.paranoia = (env ? atoi(env) : 0); + if (globals.paranoia == 0) + globals.paranoia = 1024; + + env = getenv("MEMENTO_PARANOIDAT"); + globals.paranoidAt = (env ? atoi(env) : 0); + + env = getenv("MEMENTO_SQUEEZEAT"); + globals.squeezeAt = (env ? atoi(env) : 0); + + atexit(Memento_fin); + + Memento_inited(); +} + +static void Memento_event(void) +{ + globals.sequence++; + if ((globals.sequence >= globals.paranoidAt) && (globals.paranoidAt != 0)) { + globals.paranoia = 1; + globals.countdown = 1; + } + if ((globals.sequence >= globals.failAt) && (globals.failAt != 0)) { + globals.failing = 1; + } + if ((globals.sequence >= globals.squeezeAt) && (globals.squeezeAt != 0)) { + globals.squeezing = 1; + } + + if (--globals.countdown == 0) { + Memento_checkAllMemory(); + globals.countdown = globals.paranoia; + } + + if (globals.sequence == globals.breakAt) { + fprintf(stderr, "Breaking at event %d\n", globals.breakAt); + Memento_breakpoint(); + } +} + +int Memento_breakAt(int event) +{ + globals.breakAt = event; + return event; +} + +#ifdef MEMENTO_HAS_FORK +#include <unistd.h> +#include <sys/wait.h> +#include <signal.h> +#ifdef MEMENTO_STACKTRACE_METHOD +#if MEMENTO_STACKTRACE_METHOD == 1 +#include <signal.h> +#endif +#endif + +/* FIXME: Find some portable way of getting this */ +/* MacOSX has 10240, Ubuntu seems to have 256 */ +#define OPEN_MAX 10240 + +/* stashed_map[j] = i means that filedescriptor i-1 was duplicated to j */ +int stashed_map[OPEN_MAX]; + +static void Memento_signal(void) +{ + fprintf(stderr, "SEGV after Memory squeezing @ %d\n", globals.squeezed); + +#ifdef MEMENTO_STACKTRACE_METHOD +#if MEMENTO_STACKTRACE_METHOD == 1 + { + void *array[100]; + size_t size; + + size = backtrace(array, 100); + fprintf(stderr, "------------------------------------------------------------------------\n"); + fprintf(stderr, "Backtrace:\n"); + backtrace_symbols_fd(array, size, 2); + fprintf(stderr, "------------------------------------------------------------------------\n"); + } +#endif +#endif + + exit(1); +} + +static void squeeze(void) +{ + pid_t pid; + int i, status; + + fprintf(stderr, "Memory squeezing @ %d\n", globals.sequence); + + /* When we fork below, the child is going to snaffle all our file pointers + * and potentially corrupt them. Let's make copies of all of them before + * we fork, so we can restore them when we restart. */ + for (i = 0; i < OPEN_MAX; i++) { + if (stashed_map[i] == 0) { + int j = dup(i); + stashed_map[j] = i+1; + } + } + + pid = fork(); + if (pid == 0) { + /* Child */ + signal(SIGSEGV, Memento_signal); + /* We must fail all new allocations from here */ + globals.failing = 1; + globals.squeezed = globals.sequence; + return; + } + + /* Wait for pid to finish */ + waitpid(pid, &status, 0); + + /* Put the files back */ + for (i = 0; i < OPEN_MAX; i++) { + if (stashed_map[i] != 0) { + dup2(i, stashed_map[i]-1); + close(i); + stashed_map[i] = 0; + } + } +} +#else +void squeeze(void) +{ + fprintf(stderr, "Memento memory squeezing disabled as no fork!\n"); +} +#endif + +int Memento_failThisEvent(void) +{ + if (!globals.inited) + Memento_init(); + + Memento_event(); + + if ((globals.squeezing) && (!globals.squeezed)) + squeeze(); + + return globals.failing; +} + +void *Memento_malloc(size_t s) +{ + Memento_BlkHeader *memblk; + size_t smem = MEMBLK_SIZE(s); + + if (!globals.inited) + Memento_init(); + + Memento_event(); + + if ((globals.squeezing) && (!globals.squeezed)) + squeeze(); + + if (globals.failing) + return NULL; + + if (s == 0) + return NULL; + + globals.numMallocs++; + + memblk = MEMENTO_UNDERLYING_MALLOC(smem); + if (memblk == NULL) + return NULL; + + globals.alloc += s; + globals.totalAlloc += s; + if (globals.peakAlloc < globals.alloc) + globals.peakAlloc = globals.alloc; +#ifndef MEMENTO_LEAKONLY + memset(MEMBLK_TOBLK(memblk), MEMENTO_ALLOCFILL, s); +#endif + memblk->rawsize = s; + memblk->sequence = globals.sequence; + memblk->lastCheckedOK = memblk->sequence; + Memento_addBlockHead(&globals.used, memblk, 0); + return MEMBLK_TOBLK(memblk); +} + +void *Memento_calloc(size_t n, size_t s) +{ + void *block = Memento_malloc(n*s); + + if (block) + memset(block, 0, n*s); + return block; +} + +static int checkBlock(Memento_BlkHeader *memblk, const char *action) +{ +#ifndef MEMENTO_LEAKONLY + BlkCheckData data; + + memset(&data, 0, sizeof(data)); + Memento_appBlock(&globals.used, Memento_Internal_checkAllocedBlock, + &data, memblk); + if (!data.found) { + /* Failure! */ + fprintf(stderr, "Attempt to %s block 0x%p(size=%d,num=%d) not on allocated list!\n", + action, memblk, memblk->rawsize, memblk->sequence); + Memento_breakpoint(); + return 1; + } else if (data.preCorrupt || data.postCorrupt) { + fprintf(stderr, "Block 0x%p(size=%d,num=%d) found to be corrupted on %s!\n", + action, memblk->rawsize, memblk->sequence, action); + if (data.preCorrupt) { + fprintf(stderr, "Preguard corrupted\n"); + } + if (data.postCorrupt) { + fprintf(stderr, "Postguard corrupted\n"); + } + fprintf(stderr, "Block last checked OK at allocation %d. Now %d.\n", + memblk->lastCheckedOK, globals.sequence); + Memento_breakpoint(); + return 1; + } +#endif + return 0; +} + +void Memento_free(void *blk) +{ + Memento_BlkHeader *memblk; + + if (!globals.inited) + Memento_init(); + + Memento_event(); + + if (blk == NULL) + return; + + memblk = MEMBLK_FROMBLK(blk); + VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk)); + if (checkBlock(memblk, "free")) + return; + + VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk)); + globals.alloc -= memblk->rawsize; + globals.numFrees++; + + Memento_removeBlock(&globals.used, memblk); + + VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk)); + if (Memento_Internal_makeSpace(MEMBLK_SIZE(memblk->rawsize))) { + VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk)); + VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(memblk), + memblk->rawsize + Memento_PostSize); +#ifndef MEMENTO_LEAKONLY + memset(MEMBLK_TOBLK(memblk), MEMENTO_FREEFILL, memblk->rawsize); +#endif + Memento_addBlockTail(&globals.free, memblk, 1); + } else { + MEMENTO_UNDERLYING_FREE(memblk); + } +} + +void *Memento_realloc(void *blk, size_t newsize) +{ + Memento_BlkHeader *memblk, *newmemblk; + size_t newsizemem; + + if (!globals.inited) + Memento_init(); + + if (blk == NULL) + return Memento_malloc(newsize); + if (newsize == 0) { + Memento_free(blk); + return NULL; + } + if ((globals.squeezing) && (!globals.squeezed)) + squeeze(); + if (globals.failing) + return NULL; + + memblk = MEMBLK_FROMBLK(blk); + + Memento_event(); + + if (checkBlock(memblk, "realloc")) + return NULL; + + newsizemem = MEMBLK_SIZE(newsize); + Memento_removeBlock(&globals.used, memblk); + newmemblk = MEMENTO_UNDERLYING_REALLOC(memblk, newsizemem); + if (newmemblk == NULL) + { + Memento_addBlockHead(&globals.used, memblk, 2); + return NULL; + } + globals.numReallocs++; + globals.totalAlloc += newsize; + globals.alloc -= newmemblk->rawsize; + globals.alloc += newsize; + if (globals.peakAlloc < globals.alloc) + globals.peakAlloc = globals.alloc; + if (newmemblk->rawsize < newsize) { + char *newbytes = ((char *)MEMBLK_TOBLK(newmemblk))+newmemblk->rawsize; +#ifndef MEMENTO_LEAKONLY + memset(newbytes, MEMENTO_ALLOCFILL, newsize - newmemblk->rawsize); +#endif + VALGRIND_MAKE_MEM_UNDEFINED(newbytes, newsize - newmemblk->rawsize); + } + newmemblk->rawsize = newsize; +#ifndef MEMENTO_LEAKONLY + memset(newmemblk->preblk, MEMENTO_PREFILL, Memento_PreSize); + memset(MEMBLK_POSTPTR(newmemblk), MEMENTO_POSTFILL, Memento_PostSize); +#endif + Memento_addBlockHead(&globals.used, newmemblk, 2); + return MEMBLK_TOBLK(newmemblk); +} + +int Memento_checkBlock(void *blk) +{ + Memento_BlkHeader *memblk; + + if (blk == NULL) + return 0; + memblk = MEMBLK_FROMBLK(blk); + return checkBlock(memblk, "check"); +} + +static int Memento_Internal_checkAllAlloced(Memento_BlkHeader *memblk, void *arg) +{ + BlkCheckData *data = (BlkCheckData *)arg; + + Memento_Internal_checkAllocedBlock(memblk, data); + if (data->preCorrupt || data->postCorrupt) { + if ((data->found & 2) == 0) { + fprintf(stderr, "Allocated blocks:\n"); + data->found |= 2; + } + fprintf(stderr, " Block 0x%p(size=%d,num=%d)", + memblk, memblk->rawsize, memblk->sequence); + if (data->preCorrupt) { + fprintf(stderr, " Preguard "); + } + if (data->postCorrupt) { + fprintf(stderr, "%s Postguard ", + (data->preCorrupt ? "&" : "")); + } + fprintf(stderr, "corrupted.\n " + "Block last checked OK at allocation %d. Now %d.\n", + memblk->lastCheckedOK, globals.sequence); + data->preCorrupt = 0; + data->postCorrupt = 0; + data->freeCorrupt = 0; + } + return 0; +} + +static int Memento_Internal_checkAllFreed(Memento_BlkHeader *memblk, void *arg) +{ + BlkCheckData *data = (BlkCheckData *)arg; + + Memento_Internal_checkFreedBlock(memblk, data); + if (data->preCorrupt || data->postCorrupt || data->freeCorrupt) { + if ((data->found & 4) == 0) { + fprintf(stderr, "Freed blocks:\n"); + data->found |= 4; + } + fprintf(stderr, " 0x%p(size=%d,num=%d) ", + MEMBLK_TOBLK(memblk), memblk->rawsize, memblk->sequence); + if (data->freeCorrupt) { + fprintf(stderr, "index %d (address 0x%p) onwards ", data->index, + &((char *)MEMBLK_TOBLK(memblk))[data->index]); + if (data->preCorrupt) { + fprintf(stderr, "+ preguard "); + } + if (data->postCorrupt) { + fprintf(stderr, "+ postguard "); + } + } else { + if (data->preCorrupt) { + fprintf(stderr, " preguard "); + } + if (data->postCorrupt) { + fprintf(stderr, "%s Postguard ", + (data->preCorrupt ? "+" : "")); + } + } + fprintf(stderr, "corrupted.\n " + "Block last checked OK at allocation %d. Now %d.\n", + memblk->lastCheckedOK, globals.sequence); + data->preCorrupt = 0; + data->postCorrupt = 0; + data->freeCorrupt = 0; + } + return 0; +} + +int Memento_checkAllMemory(void) +{ +#ifndef MEMENTO_LEAKONLY + BlkCheckData data; + + memset(&data, 0, sizeof(data)); + Memento_appBlocks(&globals.used, Memento_Internal_checkAllAlloced, &data); + Memento_appBlocks(&globals.free, Memento_Internal_checkAllFreed, &data); + if (data.found & 6) { + Memento_breakpoint(); + return 1; + } +#endif + return 0; +} + +int Memento_setParanoia(int i) +{ + globals.paranoia = i; + globals.countdown = globals.paranoia; + return i; +} + +int Memento_paranoidAt(int i) +{ + globals.paranoidAt = i; + return i; +} + +int Memento_getBlockNum(void *b) +{ + Memento_BlkHeader *memblk; + if (b == NULL) + return 0; + memblk = MEMBLK_FROMBLK(b); + return (memblk->sequence); +} + +int Memento_check(void) +{ + int result; + + fprintf(stderr, "Checking memory\n"); + result = Memento_checkAllMemory(); + fprintf(stderr, "Memory checked!\n"); + return result; +} + +typedef struct findBlkData { + void *addr; + Memento_BlkHeader *blk; + int flags; +} findBlkData; + +static int Memento_containsAddr(Memento_BlkHeader *b, + void *arg) +{ + findBlkData *data = (findBlkData *)arg; + char *blkend = &((char *)MEMBLK_TOBLK(b))[b->rawsize]; + if ((MEMBLK_TOBLK(b) <= data->addr) && + ((void *)blkend > data->addr)) { + data->blk = b; + data->flags = 1; + return 1; + } + if (((void *)b <= data->addr) && + (MEMBLK_TOBLK(b) > data->addr)) { + data->blk = b; + data->flags = 2; + return 1; + } + if (((void *)blkend <= data->addr) && + ((void *)(blkend + Memento_PostSize) > data->addr)) { + data->blk = b; + data->flags = 3; + return 1; + } + return 0; +} + +int Memento_find(void *a) +{ + findBlkData data; + + data.addr = a; + data.blk = NULL; + data.flags = 0; + Memento_appBlocks(&globals.used, Memento_containsAddr, &data); + if (data.blk != NULL) { + fprintf(stderr, "Address 0x%p is in %sallocated block 0x%p(size=%d,num=%d)\n", + data.addr, + (data.flags == 1 ? "" : (data.flags == 2 ? + "preguard of " : "postguard of ")), + MEMBLK_TOBLK(data.blk), data.blk->rawsize, data.blk->sequence); + return data.blk->sequence; + } + data.blk = NULL; + data.flags = 0; + Memento_appBlocks(&globals.free, Memento_containsAddr, &data); + if (data.blk != NULL) { + fprintf(stderr, "Address 0x%p is in %sfreed block 0x%p(size=%d,num=%d)\n", + data.addr, + (data.flags == 1 ? "" : (data.flags == 2 ? + "preguard of " : "postguard of ")), + MEMBLK_TOBLK(data.blk), data.blk->rawsize, data.blk->sequence); + return data.blk->sequence; + } + return 0; +} + +int Memento_failAt(int i) +{ + globals.failAt = i; + if ((globals.sequence > globals.failAt) && + (globals.failing != 0)) + globals.failing = 1; + return i; +} + +#else + +/* Just in case anyone has left some debugging code in... */ +void (Memento_breakpoint)(void) +{ +} + +int (Memento_checkBlock)(void *b) +{ + return 0; +} + +int (Memento_checkAllMemory)(void) +{ + return 0; +} + +int (Memento_check)(void) +{ + return 0; +} + +int (Memento_setParanoia)(int i) +{ + return 0; +} + +int (Memento_paranoidAt)(int i) +{ + return 0; +} + +int (Memento_breakAt)(int i) +{ + return 0; +} + +int (Memento_getBlockNum)(void *i) +{ + return 0; +} + +int (Memento_find)(void *a) +{ + return 0; +} + +int (Memento_failAt)(int i) +{ + return 0; +} + +#undef Memento_malloc +#undef Memento_free +#undef Memento_realloc +#undef Memento_calloc + +void *Memento_malloc(size_t size) +{ + return MEMENTO_UNDERLYING_MALLOC(size); +} + +void Memento_free(void *b) +{ + MEMENTO_UNDERLYING_FREE(b); +} + +void *Memento_realloc(void *b, size_t s) +{ + return MEMENTO_UNDERLYING_REALLOC(b, s); +} + +void *Memento_calloc(size_t n, size_t s) +{ + return MEMENTO_UNDERLYING_CALLOC(n, s); +} + + +#endif diff --git a/fitz/memento.h b/fitz/memento.h new file mode 100644 index 00000000..a2b4b724 --- /dev/null +++ b/fitz/memento.h @@ -0,0 +1,213 @@ +/* Copyright (C) 2011 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, modified + or distributed except as expressly authorized under the terms of that + license. Refer to licensing information at http://www.artifex.com/ + or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, + San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. +*/ + +/* Memento: A library to aid debugging of memory leaks/heap corruption. + * + * Usage: + * First, build your project with MEMENTO defined, and include this + * header file whereever you use malloc, realloc or free. + * This header file will use macros to point malloc, realloc and free to + * point to Memento_malloc, Memento_realloc, Memento_free. + * + * Run your program, and all mallocs/frees/reallocs should be redirected + * through here. When the program exits, you will get a list of all the + * leaked blocks, together with some helpful statistics. You can get the + * same list of allocated blocks at any point during program execution by + * calling Memento_listBlocks(); + * + * Every call to malloc/free/realloc counts as an 'allocation event'. + * On each event Memento increments a counter. Every block is tagged with + * the current counter on allocation. Every so often during program + * execution, the heap is checked for consistency. By default this happens + * every 1024 events. This can be changed at runtime by using + * Memento_setParanoia(int level). 0 turns off such checking, 1 sets + * checking to happen on every event, any other number n sets checking to + * happen once every n events. + * + * Memento keeps blocks around for a while after they have been freed, and + * checks them as part of these heap checks to see if they have been + * written to (or are freed twice etc). + * + * A given heap block can be checked for consistency (it's 'pre' and + * 'post' guard blocks are checked to see if they have been written to) + * by calling Memento_checkBlock(void *blockAddress); + * + * A check of all the memory can be triggered by calling Memento_check(); + * (or Memento_checkAllMemory(); if you'd like it to be quieter). + * + * A good place to breakpoint is Memento_breakpoint, as this will then + * trigger your debugger if an error is detected. This is done + * automatically for debug windows builds. + * + * If a block is found to be corrupt, information will be printed to the + * console, including the address of the block, the size of the block, + * the type of corruption, the number of the block and the event on which + * it last passed a check for correctness. + * + * If you rerun, and call Memento_paranoidAt(int event); with this number + * the the code will wait until it reaches that event and then start + * checking the heap after every allocation event. Assuming it is a + * deterministic failure, you should then find out where in your program + * the error is occuring (between event x-1 and event x). + * + * Then you can rerun the program again, and call + * Memento_breakAt(int event); and the program will call + * Memento_Breakpoint() when event x is reached, enabling you to step + * through. + * + * Memento_find(address) will tell you what block (if any) the given + * address is in. + * + * An example: + * Suppose we have a gs invocation that crashes with memory corruption. + * * Build with -DMEMENTO. + * * In your debugger put breakpoints on Memento_inited and + * Memento_Breakpoint. + * * Run the program. It will stop in Memento_inited. + * * Execute Memento_setParanoia(1); (In VS use Ctrl-Alt-Q). (Note #1) + * * Continue execution. + * * It will detect the memory corruption on the next allocation event + * after it happens, and stop in Memento_breakpoint. The console should + * show something like: + * + * Freed blocks: + * 0x172e610(size=288,num=1415) index 256 (0x172e710) onwards corrupted + * Block last checked OK at allocation 1457. Now 1458. + * + * * This means that the block became corrupted between allocation 1457 + * and 1458 - so if we rerun and stop the program at 1457, we can then + * step through, possibly with a data breakpoint at 0x172e710 and see + * when it occurs. + * * So restart the program from the beginning. When we hit Memento_inited + * execute Memento_breakAt(1457); (and maybe Memento_setParanoia(1), or + * Memento_setParanoidAt(1457)) + * * Continue execution until we hit Memento_breakpoint. + * * Now you can step through and watch the memory corruption happen. + * + * Note #1: Using Memento_setParanoia(1) can cause your program to run + * very slowly. You may instead choose to use Memento_setParanoia(100) + * (or some other figure). This will only exhaustively check memory on + * every 100th allocation event. This trades speed for the size of the + * average allocation event range in which detection of memory corruption + * occurs. You may (for example) choose to run once checking every 100 + * allocations and discover that the corruption happens between events + * X and X+100. You can then rerun using Memento_paranoidAt(X), and + * it'll only start exhaustively checking when it reaches X. + * + * More than one memory allocator? + * + * If you have more than one memory allocator in the system (like for + * instance the ghostscript chunk allocator, that builds on top of the + * standard malloc and returns chunks itself), then there are some things + * to note: + * + * * If the secondary allocator gets its underlying blocks from calling + * malloc, then those will be checked by Memento, but 'subblocks' that + * are returned to the secondary allocator will not. There is currently + * no way to fix this other than trying to bypass the secondary + * allocator. One way I have found to do this with the chunk allocator + * is to tweak its idea of a 'large block' so that it puts every + * allocation in its own chunk. Clearly this negates the point of having + * a secondary allocator, and is therefore not recommended for general + * use. + * + * * Again, if the secondary allocator gets its underlying blocks from + * calling malloc (and hence Memento) leak detection should still work + * (but whole blocks will be detected rather than subblocks). + * + * * If on every allocation attempt the secondary allocator calls into + * Memento_failThisEvent(), and fails the allocation if it returns true + * then more useful features can be used; firstly memory squeezing will + * work, and secondly, Memento will have a "finer grained" paranoia + * available to it. + */ + +#ifndef MEMENTO_H + +#include <memory.h> + +#define MEMENTO_H + +#ifndef MEMENTO_UNDERLYING_MALLOC +#define MEMENTO_UNDERLYING_MALLOC malloc +#endif +#ifndef MEMENTO_UNDERLYING_FREE +#define MEMENTO_UNDERLYING_FREE free +#endif +#ifndef MEMENTO_UNDERLYING_REALLOC +#define MEMENTO_UNDERLYING_REALLOC realloc +#endif +#ifndef MEMENTO_UNDERLYING_CALLOC +#define MEMENTO_UNDERLYING_CALLOC calloc +#endif + +#ifndef MEMENTO_MAXALIGN +#define MEMENTO_MAXALIGN (sizeof(int)) +#endif + +#define MEMENTO_PREFILL 0xa6 +#define MEMENTO_POSTFILL 0xa7 +#define MEMENTO_ALLOCFILL 0xa8 +#define MEMENTO_FREEFILL 0xa9 + +#define MEMENTO_FREELIST_MAX 0x2000000 + +int Memento_checkBlock(void *); +int Memento_checkAllMemory(void); +int Memento_check(void); + +int Memento_setParanoia(int); +int Memento_paranoidAt(int); +int Memento_breakAt(int); +int Memento_getBlockNum(void *); +int Memento_find(void *a); +void Memento_breakpoint(void); +int Memento_failAt(int); +int Memento_failThisEvent(void); + +void *Memento_malloc(size_t s); +void *Memento_realloc(void *, size_t s); +void Memento_free(void *); +void *Memento_calloc(size_t, size_t); + +#ifdef MEMENTO + +#ifndef COMPILING_MEMENTO_C +#define malloc Memento_malloc +#define free Memento_free +#define realloc Memento_realloc +#define calloc Memento_calloc +#endif + +#else + +#define Memento_malloc MEMENTO_UNDERLYING_MALLOC +#define Memento_free MEMENTO_UNDERLYING_FREE +#define Memento_realloc MEMENTO_UNDERLYING_REALLOC +#define Memento_calloc MEMENTO_UNDERLYING_CALLOC + +#define Memento_checkBlock(A) 0 +#define Memento_checkAllMemory() 0 +#define Memento_check() 0 +#define Memento_setParanoia(A) 0 +#define Memento_paranoidAt(A) 0 +#define Memento_breakAt(A) 0 +#define Memento_getBlockNum(A) 0 +#define Memento_find(A) 0 +#define Memento_breakpoint() do {} while (0) +#define Memento_failAt(A) 0 +#define Memento_failThisEvent() 0 + +#endif /* MEMENTO */ + +#endif /* MEMENTO_H */ diff --git a/fitz/obj_print.c b/fitz/obj_print.c deleted file mode 100644 index 30b34d95..00000000 --- a/fitz/obj_print.c +++ /dev/null @@ -1,335 +0,0 @@ -#include "fitz.h" - -struct fmt -{ - char *buf; - int cap; - int len; - int indent; - int tight; - int col; - int sep; - int last; -}; - -static void fmt_obj(struct fmt *fmt, fz_obj *obj); - -static inline int iswhite(int ch) -{ - return - ch == '\000' || - ch == '\011' || - ch == '\012' || - ch == '\014' || - ch == '\015' || - ch == '\040'; -} - -static inline int isdelim(int ch) -{ - return ch == '(' || ch == ')' || - ch == '<' || ch == '>' || - ch == '[' || ch == ']' || - ch == '{' || ch == '}' || - ch == '/' || - ch == '%'; -} - -static inline void fmt_putc(struct fmt *fmt, int c) -{ - if (fmt->sep && !isdelim(fmt->last) && !isdelim(c)) { - fmt->sep = 0; - fmt_putc(fmt, ' '); - } - fmt->sep = 0; - - if (fmt->buf && fmt->len < fmt->cap) - fmt->buf[fmt->len] = c; - - if (c == '\n') - fmt->col = 0; - else - fmt->col ++; - - fmt->len ++; - - fmt->last = c; -} - -static inline void fmt_indent(struct fmt *fmt) -{ - int i = fmt->indent; - while (i--) { - fmt_putc(fmt, ' '); - fmt_putc(fmt, ' '); - } -} - -static inline void fmt_puts(struct fmt *fmt, char *s) -{ - while (*s) - fmt_putc(fmt, *s++); -} - -static inline void fmt_sep(struct fmt *fmt) -{ - fmt->sep = 1; -} - -static void fmt_str(struct fmt *fmt, fz_obj *obj) -{ - char *s = fz_to_str_buf(obj); - int n = fz_to_str_len(obj); - int i, c; - - fmt_putc(fmt, '('); - for (i = 0; i < n; i++) - { - c = (unsigned char)s[i]; - if (c == '\n') - fmt_puts(fmt, "\\n"); - else if (c == '\r') - fmt_puts(fmt, "\\r"); - else if (c == '\t') - fmt_puts(fmt, "\\t"); - else if (c == '\b') - fmt_puts(fmt, "\\b"); - else if (c == '\f') - fmt_puts(fmt, "\\f"); - else if (c == '(') - fmt_puts(fmt, "\\("); - else if (c == ')') - fmt_puts(fmt, "\\)"); - else if (c < 32 || c >= 127) { - char buf[16]; - fmt_putc(fmt, '\\'); - sprintf(buf, "%03o", c); - fmt_puts(fmt, buf); - } - else - fmt_putc(fmt, c); - } - fmt_putc(fmt, ')'); -} - -static void fmt_hex(struct fmt *fmt, fz_obj *obj) -{ - char *s = fz_to_str_buf(obj); - int n = fz_to_str_len(obj); - int i, b, c; - - fmt_putc(fmt, '<'); - for (i = 0; i < n; i++) { - b = (unsigned char) s[i]; - c = (b >> 4) & 0x0f; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - c = (b) & 0x0f; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - } - fmt_putc(fmt, '>'); -} - -static void fmt_name(struct fmt *fmt, fz_obj *obj) -{ - unsigned char *s = (unsigned char *) fz_to_name(obj); - int i, c; - - fmt_putc(fmt, '/'); - - for (i = 0; s[i]; i++) - { - if (isdelim(s[i]) || iswhite(s[i]) || - s[i] == '#' || s[i] < 32 || s[i] >= 127) - { - fmt_putc(fmt, '#'); - c = (s[i] >> 4) & 0xf; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - c = s[i] & 0xf; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - } - else - { - fmt_putc(fmt, s[i]); - } - } -} - -static void fmt_array(struct fmt *fmt, fz_obj *obj) -{ - int i; - - if (fmt->tight) { - fmt_putc(fmt, '['); - for (i = 0; i < fz_array_len(obj); i++) { - fmt_obj(fmt, fz_array_get(obj, i)); - fmt_sep(fmt); - } - fmt_putc(fmt, ']'); - } - else { - fmt_puts(fmt, "[ "); - for (i = 0; i < fz_array_len(obj); i++) { - if (fmt->col > 60) { - fmt_putc(fmt, '\n'); - fmt_indent(fmt); - } - fmt_obj(fmt, fz_array_get(obj, i)); - fmt_putc(fmt, ' '); - } - fmt_putc(fmt, ']'); - fmt_sep(fmt); - } -} - -static void fmt_dict(struct fmt *fmt, fz_obj *obj) -{ - int i; - fz_obj *key, *val; - - if (fmt->tight) { - fmt_puts(fmt, "<<"); - for (i = 0; i < fz_dict_len(obj); i++) { - fmt_obj(fmt, fz_dict_get_key(obj, i)); - fmt_sep(fmt); - fmt_obj(fmt, fz_dict_get_val(obj, i)); - fmt_sep(fmt); - } - fmt_puts(fmt, ">>"); - } - else { - fmt_puts(fmt, "<<\n"); - fmt->indent ++; - for (i = 0; i < fz_dict_len(obj); i++) { - key = fz_dict_get_key(obj, i); - val = fz_dict_get_val(obj, i); - fmt_indent(fmt); - fmt_obj(fmt, key); - fmt_putc(fmt, ' '); - if (!fz_is_indirect(val) && fz_is_array(val)) - fmt->indent ++; - fmt_obj(fmt, val); - fmt_putc(fmt, '\n'); - if (!fz_is_indirect(val) && fz_is_array(val)) - fmt->indent --; - } - fmt->indent --; - fmt_indent(fmt); - fmt_puts(fmt, ">>"); - } -} - -static void fmt_obj(struct fmt *fmt, fz_obj *obj) -{ - char buf[256]; - - if (!obj) - fmt_puts(fmt, "<NULL>"); - else if (fz_is_indirect(obj)) - { - sprintf(buf, "%d %d R", fz_to_num(obj), fz_to_gen(obj)); - fmt_puts(fmt, buf); - } - else if (fz_is_null(obj)) - fmt_puts(fmt, "null"); - else if (fz_is_bool(obj)) - fmt_puts(fmt, fz_to_bool(obj) ? "true" : "false"); - else if (fz_is_int(obj)) - { - sprintf(buf, "%d", fz_to_int(obj)); - fmt_puts(fmt, buf); - } - else if (fz_is_real(obj)) - { - sprintf(buf, "%g", fz_to_real(obj)); - if (strchr(buf, 'e')) /* bad news! */ - sprintf(buf, fabsf(fz_to_real(obj)) > 1 ? "%1.1f" : "%1.8f", fz_to_real(obj)); - fmt_puts(fmt, buf); - } - else if (fz_is_string(obj)) - { - char *str = fz_to_str_buf(obj); - int len = fz_to_str_len(obj); - int added = 0; - int i, c; - for (i = 0; i < len; i++) { - c = (unsigned char)str[i]; - if (strchr("()\\\n\r\t\b\f", c)) - added ++; - else if (c < 32 || c >= 127) - added += 3; - } - if (added < len) - fmt_str(fmt, obj); - else - fmt_hex(fmt, obj); - } - else if (fz_is_name(obj)) - fmt_name(fmt, obj); - else if (fz_is_array(obj)) - fmt_array(fmt, obj); - else if (fz_is_dict(obj)) - fmt_dict(fmt, obj); - else - fmt_puts(fmt, "<unknown object>"); -} - -static int -fz_sprint_obj(char *s, int n, fz_obj *obj, int tight) -{ - struct fmt fmt; - - fmt.indent = 0; - fmt.col = 0; - fmt.sep = 0; - fmt.last = 0; - - fmt.tight = tight; - fmt.buf = s; - fmt.cap = n; - fmt.len = 0; - fmt_obj(&fmt, obj); - - if (fmt.buf && fmt.len < fmt.cap) - fmt.buf[fmt.len] = '\0'; - - return fmt.len; -} - -int -fz_fprint_obj(FILE *fp, fz_obj *obj, int tight) -{ - char buf[1024]; - char *ptr; - int n; - - n = fz_sprint_obj(NULL, 0, obj, tight); - if ((n + 1) < sizeof buf) - { - fz_sprint_obj(buf, sizeof buf, obj, tight); - fputs(buf, fp); - fputc('\n', fp); - } - else - { - ptr = fz_malloc(n + 1); - fz_sprint_obj(ptr, n + 1, obj, tight); - fputs(ptr, fp); - fputc('\n', fp); - fz_free(ptr); - } - return n; -} - -void -fz_debug_obj(fz_obj *obj) -{ - fz_fprint_obj(stdout, obj, 0); -} - -void -fz_debug_ref(fz_obj *ref) -{ - fz_obj *obj; - obj = fz_resolve_indirect(ref); - fz_debug_obj(obj); -} diff --git a/fitz/res_bitmap.c b/fitz/res_bitmap.c index 0b852af2..02bb6f44 100644 --- a/fitz/res_bitmap.c +++ b/fitz/res_bitmap.c @@ -1,11 +1,11 @@ #include "fitz.h" fz_bitmap * -fz_new_bitmap(int w, int h, int n) +fz_new_bitmap(fz_context *ctx, int w, int h, int n) { fz_bitmap *bit; - bit = fz_malloc(sizeof(fz_bitmap)); + bit = fz_malloc(ctx, sizeof(fz_bitmap)); bit->refs = 1; bit->w = w; bit->h = h; @@ -14,7 +14,7 @@ fz_new_bitmap(int w, int h, int n) * use SSE2 etc. */ bit->stride = ((n * w + 31) & ~31) >> 3; - bit->samples = fz_calloc(h, bit->stride); + bit->samples = fz_malloc_array(ctx, h, bit->stride); return bit; } @@ -27,12 +27,12 @@ fz_keep_bitmap(fz_bitmap *pix) } void -fz_drop_bitmap(fz_bitmap *bit) +fz_drop_bitmap(fz_context *ctx, fz_bitmap *bit) { if (bit && --bit->refs == 0) { - fz_free(bit->samples); - fz_free(bit); + fz_free(ctx, bit->samples); + fz_free(ctx, bit); } } @@ -46,8 +46,8 @@ fz_clear_bitmap(fz_bitmap *bit) * Write bitmap to PBM file */ -fz_error -fz_write_pbm(fz_bitmap *bitmap, char *filename) +void +fz_write_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename) { FILE *fp; unsigned char *p; @@ -55,7 +55,7 @@ fz_write_pbm(fz_bitmap *bitmap, char *filename) fp = fopen(filename, "wb"); if (!fp) - return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); + fz_throw(ctx, "cannot open file '%s': %s", filename, strerror(errno)); assert(bitmap->n == 1); @@ -72,5 +72,4 @@ fz_write_pbm(fz_bitmap *bitmap, char *filename) } fclose(fp); - return fz_okay; } diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c index 47df2b34..85556b62 100644 --- a/fitz/res_colorspace.c +++ b/fitz/res_colorspace.c @@ -3,9 +3,9 @@ #define SLOWCMYK fz_colorspace * -fz_new_colorspace(char *name, int n) +fz_new_colorspace(fz_context *ctx, char *name, int n) { - fz_colorspace *cs = fz_malloc(sizeof(fz_colorspace)); + fz_colorspace *cs = fz_malloc(ctx, sizeof(fz_colorspace)); cs->refs = 1; fz_strlcpy(cs->name, name, sizeof cs->name); cs->n = n; @@ -26,28 +26,28 @@ fz_keep_colorspace(fz_colorspace *cs) } void -fz_drop_colorspace(fz_colorspace *cs) +fz_drop_colorspace(fz_context *ctx, fz_colorspace *cs) { if (cs && cs->refs < 0) return; if (cs && --cs->refs == 0) { if (cs->free_data && cs->data) - cs->free_data(cs); - fz_free(cs); + cs->free_data(ctx, cs); + fz_free(ctx, cs); } } /* Device colorspace definitions */ -static void gray_to_rgb(fz_colorspace *cs, float *gray, float *rgb) +static void gray_to_rgb(fz_context *ctx, fz_colorspace *cs, float *gray, float *rgb) { rgb[0] = gray[0]; rgb[1] = gray[0]; rgb[2] = gray[0]; } -static void rgb_to_gray(fz_colorspace *cs, float *rgb, float *gray) +static void rgb_to_gray(fz_context *ctx, fz_colorspace *cs, float *rgb, float *gray) { float r = rgb[0]; float g = rgb[1]; @@ -55,28 +55,28 @@ static void rgb_to_gray(fz_colorspace *cs, float *rgb, float *gray) gray[0] = r * 0.3f + g * 0.59f + b * 0.11f; } -static void rgb_to_rgb(fz_colorspace *cs, float *rgb, float *xyz) +static void rgb_to_rgb(fz_context *ctx, fz_colorspace *cs, float *rgb, float *xyz) { xyz[0] = rgb[0]; xyz[1] = rgb[1]; xyz[2] = rgb[2]; } -static void bgr_to_rgb(fz_colorspace *cs, float *bgr, float *rgb) +static void bgr_to_rgb(fz_context *ctx, fz_colorspace *cs, float *bgr, float *rgb) { rgb[0] = bgr[2]; rgb[1] = bgr[1]; rgb[2] = bgr[0]; } -static void rgb_to_bgr(fz_colorspace *cs, float *rgb, float *bgr) +static void rgb_to_bgr(fz_context *ctx, fz_colorspace *cs, float *rgb, float *bgr) { bgr[0] = rgb[2]; bgr[1] = rgb[1]; bgr[2] = rgb[0]; } -static void cmyk_to_rgb(fz_colorspace *cs, float *cmyk, float *rgb) +static void cmyk_to_rgb(fz_context *ctx, fz_colorspace *cs, float *cmyk, float *rgb) { #ifdef SLOWCMYK /* from poppler */ float c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3]; @@ -139,7 +139,7 @@ static void cmyk_to_rgb(fz_colorspace *cs, float *cmyk, float *rgb) #endif } -static void rgb_to_cmyk(fz_colorspace *cs, float *rgb, float *cmyk) +static void rgb_to_cmyk(fz_context *ctx, fz_colorspace *cs, float *rgb, float *cmyk) { float c, m, y, k; c = 1 - rgb[0]; @@ -173,7 +173,7 @@ fz_find_device_colorspace(char *name) return fz_device_bgr; if (!strcmp(name, "DeviceCMYK")) return fz_device_cmyk; - fz_warn("unknown device colorspace: %s", name); + assert(!"unknown device colorspace"); return NULL; } @@ -299,7 +299,7 @@ static void fast_cmyk_to_gray(fz_pixmap *src, fz_pixmap *dst) } } -static void fast_cmyk_to_rgb(fz_pixmap *src, fz_pixmap *dst) +static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -312,7 +312,7 @@ static void fast_cmyk_to_rgb(fz_pixmap *src, fz_pixmap *dst) cmyk[1] = s[1] / 255.0f; cmyk[2] = s[2] / 255.0f; cmyk[3] = s[3] / 255.0f; - cmyk_to_rgb(NULL, cmyk, rgb); + cmyk_to_rgb(ctx, NULL, cmyk, rgb); d[0] = rgb[0] * 255; d[1] = rgb[1] * 255; d[2] = rgb[2] * 255; @@ -327,7 +327,7 @@ static void fast_cmyk_to_rgb(fz_pixmap *src, fz_pixmap *dst) } } -static void fast_cmyk_to_bgr(fz_pixmap *src, fz_pixmap *dst) +static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -340,7 +340,7 @@ static void fast_cmyk_to_bgr(fz_pixmap *src, fz_pixmap *dst) cmyk[1] = s[1] / 255.0f; cmyk[2] = s[2] / 255.0f; cmyk[3] = s[3] / 255.0f; - cmyk_to_rgb(NULL, cmyk, rgb); + cmyk_to_rgb(ctx, NULL, cmyk, rgb); d[0] = rgb[2] * 255; d[1] = rgb[1] * 255; d[2] = rgb[0] * 255; @@ -372,7 +372,7 @@ static void fast_rgb_to_bgr(fz_pixmap *src, fz_pixmap *dst) } static void -fz_std_conv_pixmap(fz_pixmap *src, fz_pixmap *dst) +fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst) { float srcv[FZ_MAX_COLORS]; float dstv[FZ_MAX_COLORS]; @@ -403,7 +403,7 @@ fz_std_conv_pixmap(fz_pixmap *src, fz_pixmap *dst) srcv[1] = *s++ - 128; srcv[2] = *s++ - 128; - fz_convert_color(ss, srcv, ds, dstv); + fz_convert_color(ctx, ss, srcv, ds, dstv); for (k = 0; k < dstn; k++) *d++ = dstv[k] * 255; @@ -423,7 +423,7 @@ fz_std_conv_pixmap(fz_pixmap *src, fz_pixmap *dst) for (k = 0; k < srcn; k++) srcv[k] = *s++ / 255.0f; - fz_convert_color(ss, srcv, ds, dstv); + fz_convert_color(ctx, ss, srcv, ds, dstv); for (k = 0; k < dstn; k++) *d++ = dstv[k] * 255; @@ -441,7 +441,7 @@ fz_std_conv_pixmap(fz_pixmap *src, fz_pixmap *dst) for (i = 0; i < 256; i++) { srcv[0] = i / 255.0f; - fz_convert_color(ss, srcv, ds, dstv); + fz_convert_color(ctx, ss, srcv, ds, dstv); for (k = 0; k < dstn; k++) lookup[i * dstn + k] = dstv[k] * 255; } @@ -464,7 +464,7 @@ fz_std_conv_pixmap(fz_pixmap *src, fz_pixmap *dst) fz_hash_table *lookup; unsigned char *color; - lookup = fz_new_hash_table(509, srcn); + lookup = fz_new_hash_table(ctx, 509, srcn); for (y = 0; y < src->h; y++) { @@ -482,7 +482,7 @@ fz_std_conv_pixmap(fz_pixmap *src, fz_pixmap *dst) { for (k = 0; k < srcn; k++) srcv[k] = *s++ / 255.0f; - fz_convert_color(ss, srcv, ds, dstv); + fz_convert_color(ctx, ss, srcv, ds, dstv); for (k = 0; k < dstn; k++) *d++ = dstv[k] * 255; @@ -498,7 +498,7 @@ fz_std_conv_pixmap(fz_pixmap *src, fz_pixmap *dst) } void -fz_convert_pixmap(fz_pixmap *sp, fz_pixmap *dp) +fz_convert_pixmap(fz_context *ctx, fz_pixmap *sp, fz_pixmap *dp) { fz_colorspace *ss = sp->colorspace; fz_colorspace *ds = dp->colorspace; @@ -514,7 +514,7 @@ fz_convert_pixmap(fz_pixmap *sp, fz_pixmap *dp) if (ds == fz_device_rgb) fast_gray_to_rgb(sp, dp); else if (ds == fz_device_bgr) fast_gray_to_rgb(sp, dp); /* bgr == rgb here */ else if (ds == fz_device_cmyk) fast_gray_to_cmyk(sp, dp); - else fz_std_conv_pixmap(sp, dp); + else fz_std_conv_pixmap(ctx, sp, dp); } else if (ss == fz_device_rgb) @@ -522,7 +522,7 @@ fz_convert_pixmap(fz_pixmap *sp, fz_pixmap *dp) if (ds == fz_device_gray) fast_rgb_to_gray(sp, dp); else if (ds == fz_device_bgr) fast_rgb_to_bgr(sp, dp); else if (ds == fz_device_cmyk) fast_rgb_to_cmyk(sp, dp); - else fz_std_conv_pixmap(sp, dp); + else fz_std_conv_pixmap(ctx, sp, dp); } else if (ss == fz_device_bgr) @@ -530,24 +530,24 @@ fz_convert_pixmap(fz_pixmap *sp, fz_pixmap *dp) if (ds == fz_device_gray) fast_bgr_to_gray(sp, dp); else if (ds == fz_device_rgb) fast_rgb_to_bgr(sp, dp); /* bgr = rgb here */ else if (ds == fz_device_cmyk) fast_bgr_to_cmyk(sp, dp); - else fz_std_conv_pixmap(sp, dp); + else fz_std_conv_pixmap(ctx, sp, dp); } else if (ss == fz_device_cmyk) { if (ds == fz_device_gray) fast_cmyk_to_gray(sp, dp); - else if (ds == fz_device_bgr) fast_cmyk_to_bgr(sp, dp); - else if (ds == fz_device_rgb) fast_cmyk_to_rgb(sp, dp); - else fz_std_conv_pixmap(sp, dp); + else if (ds == fz_device_bgr) fast_cmyk_to_bgr(ctx, sp, dp); + else if (ds == fz_device_rgb) fast_cmyk_to_rgb(ctx, sp, dp); + else fz_std_conv_pixmap(ctx, sp, dp); } - else fz_std_conv_pixmap(sp, dp); + else fz_std_conv_pixmap(ctx, sp, dp); } /* Convert a single color */ static void -fz_std_conv_color(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv) +fz_std_conv_color(fz_context *ctx, fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv) { float rgb[3]; int i; @@ -555,8 +555,8 @@ fz_std_conv_color(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float * if (srcs != dsts) { assert(srcs->to_rgb && dsts->from_rgb); - srcs->to_rgb(srcs, srcv, rgb); - dsts->from_rgb(dsts, rgb, dstv); + srcs->to_rgb(ctx, srcs, srcv, rgb); + dsts->from_rgb(ctx, dsts, rgb, dstv); for (i = 0; i < dsts->n; i++) dstv[i] = CLAMP(dstv[i], 0, 1); } @@ -568,7 +568,7 @@ fz_std_conv_color(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float * } void -fz_convert_color(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv) +fz_convert_color(fz_context *ctx, fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv) { if (ss == fz_device_gray) { @@ -586,7 +586,7 @@ fz_convert_color(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv) dv[3] = sv[0]; } else - fz_std_conv_color(ss, sv, ds, dv); + fz_std_conv_color(ctx, ss, sv, ds, dv); } else if (ss == fz_device_rgb) @@ -613,7 +613,7 @@ fz_convert_color(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv) dv[3] = k; } else - fz_std_conv_color(ss, sv, ds, dv); + fz_std_conv_color(ctx, ss, sv, ds, dv); } else if (ss == fz_device_bgr) @@ -640,7 +640,7 @@ fz_convert_color(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv) dv[3] = k; } else - fz_std_conv_color(ss, sv, ds, dv); + fz_std_conv_color(ctx, ss, sv, ds, dv); } else if (ss == fz_device_cmyk) @@ -655,7 +655,7 @@ fz_convert_color(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv) else if (ds == fz_device_rgb) { #ifdef SLOWCMYK - cmyk_to_rgb(NULL, sv, dv); + cmyk_to_rgb(ctx, NULL, sv, dv); #else dv[0] = 1 - MIN(sv[0] + sv[3], 1); dv[1] = 1 - MIN(sv[1] + sv[3], 1); @@ -666,7 +666,7 @@ fz_convert_color(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv) { #ifdef SLOWCMYK float rgb[3]; - cmyk_to_rgb(NULL, sv, rgb); + cmyk_to_rgb(ctx, NULL, sv, rgb); dv[0] = rgb[2]; dv[1] = rgb[1]; dv[2] = rgb[0]; @@ -677,9 +677,9 @@ fz_convert_color(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv) #endif } else - fz_std_conv_color(ss, sv, ds, dv); + fz_std_conv_color(ctx, ss, sv, ds, dv); } else - fz_std_conv_color(ss, sv, ds, dv); + fz_std_conv_color(ctx, ss, sv, ds, dv); } diff --git a/fitz/res_font.c b/fitz/res_font.c index ffee1d46..4b30d424 100644 --- a/fitz/res_font.c +++ b/fitz/res_font.c @@ -4,14 +4,14 @@ #include FT_FREETYPE_H #include FT_STROKER_H -static void fz_finalize_freetype(void); +static void fz_finalize_freetype(fz_context *ctx); static fz_font * -fz_new_font(char *name) +fz_new_font(fz_context *ctx, char *name) { fz_font *font; - font = fz_malloc(sizeof(fz_font)); + font = fz_malloc(ctx, sizeof(fz_font)); font->refs = 1; if (name) @@ -55,7 +55,7 @@ fz_keep_font(fz_font *font) } void -fz_drop_font(fz_font *font) +fz_drop_font(fz_context *ctx, fz_font *font) { int fterr; int i; @@ -68,28 +68,28 @@ fz_drop_font(fz_font *font) fz_drop_obj(font->t3resources); for (i = 0; i < 256; i++) if (font->t3procs[i]) - fz_drop_buffer(font->t3procs[i]); - fz_free(font->t3procs); - fz_free(font->t3widths); + fz_drop_buffer(ctx, font->t3procs[i]); + fz_free(ctx, font->t3procs); + fz_free(ctx, font->t3widths); } if (font->ft_face) { fterr = FT_Done_Face((FT_Face)font->ft_face); if (fterr) - fz_warn("freetype finalizing face: %s", ft_error_string(fterr)); - fz_finalize_freetype(); + fz_warn(ctx, "freetype finalizing face: %s", ft_error_string(fterr)); + fz_finalize_freetype(ctx); } if (font->ft_file) - fz_free(font->ft_file); + fz_free(ctx, font->ft_file); if (font->ft_data) - fz_free(font->ft_data); + fz_free(ctx, font->ft_data); if (font->width_table) - fz_free(font->width_table); + fz_free(ctx, font->width_table); - fz_free(font); + fz_free(ctx, font); } } @@ -106,8 +106,10 @@ fz_set_font_bbox(fz_font *font, float xmin, float ymin, float xmax, float ymax) * Freetype hooks */ -static FT_Library fz_ftlib = NULL; -static int fz_ftlib_refs = 0; +struct fz_font_context_s { + FT_Library ftlib; + int ftlib_refs; +}; #undef __FTERRORS_H__ #define FT_ERRORDEF(e, v, s) { (e), (s) }, @@ -120,6 +122,22 @@ struct ft_error char *str; }; +void fz_new_font_context(fz_context *ctx) +{ + ctx->font = fz_malloc(ctx, sizeof(*ctx->font)); + ctx->font->ftlib = NULL; + ctx->font->ftlib_refs = 0; +} + +void fz_free_font_context(fz_context *ctx) +{ + if (ctx->font == NULL) + return; + /* assert(ctx->ftlib == NULL); */ + /* assert(ctx->ftlib_refs == 0); */ + fz_free(ctx, ctx->font); +} + static const struct ft_error ft_errors[] = { #include FT_ERRORS_H @@ -137,104 +155,104 @@ char *ft_error_string(int err) } static fz_error -fz_init_freetype(void) +fz_init_freetype(fz_context *ctx) { int fterr; int maj, min, pat; + fz_font_context *fct = ctx->font; - if (fz_ftlib) + if (fct->ftlib) { - fz_ftlib_refs++; + fct->ftlib_refs++; return fz_okay; } - fterr = FT_Init_FreeType(&fz_ftlib); + fterr = FT_Init_FreeType(&fct->ftlib); if (fterr) - return fz_throw("cannot init freetype: %s", ft_error_string(fterr)); + return fz_error_make("cannot init freetype: %s", ft_error_string(fterr)); - FT_Library_Version(fz_ftlib, &maj, &min, &pat); + FT_Library_Version(fct->ftlib, &maj, &min, &pat); if (maj == 2 && min == 1 && pat < 7) { - fterr = FT_Done_FreeType(fz_ftlib); + fterr = FT_Done_FreeType(fct->ftlib); if (fterr) - fz_warn("freetype finalizing: %s", ft_error_string(fterr)); - return fz_throw("freetype version too old: %d.%d.%d", maj, min, pat); + fz_warn(ctx, "freetype finalizing: %s", ft_error_string(fterr)); + return fz_error_make("freetype version too old: %d.%d.%d", maj, min, pat); } - fz_ftlib_refs++; + fct->ftlib_refs++; return fz_okay; } static void -fz_finalize_freetype(void) +fz_finalize_freetype(fz_context *ctx) { int fterr; + fz_font_context *fct = ctx->font; - if (--fz_ftlib_refs == 0) + if (--fct->ftlib_refs == 0) { - fterr = FT_Done_FreeType(fz_ftlib); + fterr = FT_Done_FreeType(fct->ftlib); if (fterr) - fz_warn("freetype finalizing: %s", ft_error_string(fterr)); - fz_ftlib = NULL; + fz_warn(ctx, "freetype finalizing: %s", ft_error_string(fterr)); + fct->ftlib = NULL; } } -fz_error -fz_new_font_from_file(fz_font **fontp, char *path, int index) +fz_font * +fz_new_font_from_file(fz_context *ctx, char *path, int index) { FT_Face face; fz_error error; fz_font *font; int fterr; - error = fz_init_freetype(); + error = fz_init_freetype(ctx); if (error) - return fz_rethrow(error, "cannot init freetype library"); + fz_throw(ctx, "cannot init freetype library"); - fterr = FT_New_Face(fz_ftlib, path, index, &face); + fterr = FT_New_Face(ctx->font->ftlib, path, index, &face); if (fterr) - return fz_throw("freetype: cannot load font: %s", ft_error_string(fterr)); + fz_throw(ctx, "freetype: cannot load font: %s", ft_error_string(fterr)); - font = fz_new_font(face->family_name); + font = fz_new_font(ctx, face->family_name); font->ft_face = face; font->bbox.x0 = face->bbox.xMin * 1000 / face->units_per_EM; font->bbox.y0 = face->bbox.yMin * 1000 / face->units_per_EM; font->bbox.x1 = face->bbox.xMax * 1000 / face->units_per_EM; font->bbox.y1 = face->bbox.yMax * 1000 / face->units_per_EM; - *fontp = font; - return fz_okay; + return font; } -fz_error -fz_new_font_from_memory(fz_font **fontp, unsigned char *data, int len, int index) +fz_font * +fz_new_font_from_memory(fz_context *ctx, unsigned char *data, int len, int index) { FT_Face face; fz_error error; fz_font *font; int fterr; - error = fz_init_freetype(); + error = fz_init_freetype(ctx); if (error) - return fz_rethrow(error, "cannot init freetype library"); + fz_throw(ctx, "cannot init freetype library"); - fterr = FT_New_Memory_Face(fz_ftlib, data, len, index, &face); + fterr = FT_New_Memory_Face(ctx->font->ftlib, data, len, index, &face); if (fterr) - return fz_throw("freetype: cannot load font: %s", ft_error_string(fterr)); + fz_throw(ctx, "freetype: cannot load font: %s", ft_error_string(fterr)); - font = fz_new_font(face->family_name); + font = fz_new_font(ctx, face->family_name); font->ft_face = face; font->bbox.x0 = face->bbox.xMin * 1000 / face->units_per_EM; font->bbox.y0 = face->bbox.yMin * 1000 / face->units_per_EM; font->bbox.x1 = face->bbox.xMax * 1000 / face->units_per_EM; font->bbox.y1 = face->bbox.yMax * 1000 / face->units_per_EM; - *fontp = font; - return fz_okay; + return font; } static fz_matrix -fz_adjust_ft_glyph_width(fz_font *font, int gid, fz_matrix trm) +fz_adjust_ft_glyph_width(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) { /* Fudge the font matrix to stretch the glyph if we've substituted the font. */ if (font->ft_substitute && gid < font->width_count) @@ -247,12 +265,12 @@ fz_adjust_ft_glyph_width(fz_font *font, int gid, fz_matrix trm) /* TODO: use FT_Get_Advance */ fterr = FT_Set_Char_Size(font->ft_face, 1000, 1000, 72, 72); if (fterr) - fz_warn("freetype setting character size: %s", ft_error_string(fterr)); + fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr)); fterr = FT_Load_Glyph(font->ft_face, gid, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); if (fterr) - fz_warn("freetype failed to load glyph: %s", ft_error_string(fterr)); + fz_warn(ctx, "freetype failed to load glyph: %s", ft_error_string(fterr)); realw = ((FT_Face)font->ft_face)->glyph->metrics.horiAdvance; subw = font->width_table[gid]; @@ -268,12 +286,12 @@ fz_adjust_ft_glyph_width(fz_font *font, int gid, fz_matrix trm) } static fz_pixmap * -fz_copy_ft_bitmap(int left, int top, FT_Bitmap *bitmap) +fz_copy_ft_bitmap(fz_context *ctx, int left, int top, FT_Bitmap *bitmap) { fz_pixmap *pixmap; int y; - pixmap = fz_new_pixmap(NULL, bitmap->width, bitmap->rows); + pixmap = fz_new_pixmap(ctx, NULL, bitmap->width, bitmap->rows); pixmap->x = left; pixmap->y = top - bitmap->rows; @@ -311,14 +329,14 @@ fz_copy_ft_bitmap(int left, int top, FT_Bitmap *bitmap) } fz_pixmap * -fz_render_ft_glyph(fz_font *font, int gid, fz_matrix trm) +fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) { FT_Face face = font->ft_face; FT_Matrix m; FT_Vector v; FT_Error fterr; - trm = fz_adjust_ft_glyph_width(font, gid, trm); + trm = fz_adjust_ft_glyph_width(ctx, font, gid, trm); if (font->ft_italic) trm = fz_concat(fz_shear(0.3f, 0), trm); @@ -340,10 +358,10 @@ fz_render_ft_glyph(fz_font *font, int gid, fz_matrix trm) fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ if (fterr) - fz_warn("freetype setting character size: %s", ft_error_string(fterr)); + fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr)); FT_Set_Transform(face, &m, &v); - if (fz_get_aa_level() == 0) + if (fz_get_aa_level(ctx) == 0) { /* If you really want grid fitting, enable this code. */ float scale = fz_matrix_expansion(trm); @@ -356,11 +374,11 @@ fz_render_ft_glyph(fz_font *font, int gid, fz_matrix trm) fterr = FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72); if (fterr) - fz_warn("freetype setting character size: %s", ft_error_string(fterr)); + fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr)); FT_Set_Transform(face, &m, &v); fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_TARGET_MONO); if (fterr) - fz_warn("freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); + fz_warn(ctx, "freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); } else if (font->ft_hint) { @@ -373,14 +391,14 @@ fz_render_ft_glyph(fz_font *font, int gid, fz_matrix trm) */ fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP); if (fterr) - fz_warn("freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); + fz_warn(ctx, "freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); } else { fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); if (fterr) { - fz_warn("freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); + fz_warn(ctx, "freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); return NULL; } } @@ -392,18 +410,18 @@ fz_render_ft_glyph(fz_font *font, int gid, fz_matrix trm) FT_Outline_Translate(&face->glyph->outline, -strength * 32, -strength * 32); } - fterr = FT_Render_Glyph(face->glyph, fz_get_aa_level() > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); + fterr = FT_Render_Glyph(face->glyph, fz_get_aa_level(ctx) > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); if (fterr) { - fz_warn("freetype render glyph (gid %d): %s", gid, ft_error_string(fterr)); + fz_warn(ctx, "freetype render glyph (gid %d): %s", gid, ft_error_string(fterr)); return NULL; } - return fz_copy_ft_bitmap(face->glyph->bitmap_left, face->glyph->bitmap_top, &face->glyph->bitmap); + return fz_copy_ft_bitmap(ctx, face->glyph->bitmap_left, face->glyph->bitmap_top, &face->glyph->bitmap); } fz_pixmap * -fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *state) +fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *state) { FT_Face face = font->ft_face; float expansion = fz_matrix_expansion(ctm); @@ -416,7 +434,7 @@ fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, FT_BitmapGlyph bitmap; fz_pixmap *pixmap; - trm = fz_adjust_ft_glyph_width(font, gid, trm); + trm = fz_adjust_ft_glyph_width(ctx, font, gid, trm); if (font->ft_italic) trm = fz_concat(fz_shear(0.3f, 0), trm); @@ -431,7 +449,7 @@ fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ if (fterr) { - fz_warn("FT_Set_Char_Size: %s", ft_error_string(fterr)); + fz_warn(ctx, "FT_Set_Char_Size: %s", ft_error_string(fterr)); return NULL; } @@ -440,14 +458,14 @@ fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); if (fterr) { - fz_warn("FT_Load_Glyph(gid %d): %s", gid, ft_error_string(fterr)); + fz_warn(ctx, "FT_Load_Glyph(gid %d): %s", gid, ft_error_string(fterr)); return NULL; } - fterr = FT_Stroker_New(fz_ftlib, &stroker); + fterr = FT_Stroker_New(ctx->font->ftlib, &stroker); if (fterr) { - fz_warn("FT_Stroker_New: %s", ft_error_string(fterr)); + fz_warn(ctx, "FT_Stroker_New: %s", ft_error_string(fterr)); return NULL; } @@ -456,7 +474,7 @@ fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fterr = FT_Get_Glyph(face->glyph, &glyph); if (fterr) { - fz_warn("FT_Get_Glyph: %s", ft_error_string(fterr)); + fz_warn(ctx, "FT_Get_Glyph: %s", ft_error_string(fterr)); FT_Stroker_Done(stroker); return NULL; } @@ -464,7 +482,7 @@ fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fterr = FT_Glyph_Stroke(&glyph, stroker, 1); if (fterr) { - fz_warn("FT_Glyph_Stroke: %s", ft_error_string(fterr)); + fz_warn(ctx, "FT_Glyph_Stroke: %s", ft_error_string(fterr)); FT_Done_Glyph(glyph); FT_Stroker_Done(stroker); return NULL; @@ -472,16 +490,16 @@ fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, FT_Stroker_Done(stroker); - fterr = FT_Glyph_To_Bitmap(&glyph, fz_get_aa_level() > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, 0, 1); + fterr = FT_Glyph_To_Bitmap(&glyph, fz_get_aa_level(ctx) > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, 0, 1); if (fterr) { - fz_warn("FT_Glyph_To_Bitmap: %s", ft_error_string(fterr)); + fz_warn(ctx, "FT_Glyph_To_Bitmap: %s", ft_error_string(fterr)); FT_Done_Glyph(glyph); return NULL; } bitmap = (FT_BitmapGlyph)glyph; - pixmap = fz_copy_ft_bitmap(bitmap->left, bitmap->top, &bitmap->bitmap); + pixmap = fz_copy_ft_bitmap(ctx, bitmap->left, bitmap->top, &bitmap->bitmap); FT_Done_Glyph(glyph); return pixmap; @@ -492,14 +510,14 @@ fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, */ fz_font * -fz_new_type3_font(char *name, fz_matrix matrix) +fz_new_type3_font(fz_context *ctx, char *name, fz_matrix matrix) { fz_font *font; int i; - font = fz_new_font(name); - font->t3procs = fz_calloc(256, sizeof(fz_buffer*)); - font->t3widths = fz_calloc(256, sizeof(float)); + font = fz_new_font(ctx, name); + font->t3procs = fz_malloc_array(ctx, 256, sizeof(fz_buffer*)); + font->t3widths = fz_malloc_array(ctx, 256, sizeof(float)); font->t3matrix = matrix; for (i = 0; i < 256; i++) @@ -512,9 +530,8 @@ fz_new_type3_font(char *name, fz_matrix matrix) } fz_pixmap * -fz_render_t3_glyph(fz_font *font, int gid, fz_matrix trm, fz_colorspace *model) +fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_colorspace *model) { - fz_error error; fz_matrix ctm; fz_buffer *contents; fz_bbox bbox; @@ -531,25 +548,24 @@ fz_render_t3_glyph(fz_font *font, int gid, fz_matrix trm, fz_colorspace *model) return NULL; ctm = fz_concat(font->t3matrix, trm); - dev = fz_new_bbox_device(&bbox); - error = font->t3run(font->t3xref, font->t3resources, contents, dev, ctm); - if (error) - fz_catch(error, "cannot draw type3 glyph"); + dev = fz_new_bbox_device(ctx, &bbox); + font->t3run(font->t3xref, font->t3resources, contents, dev, ctm); + /* RJW: "cannot draw type3 glyph" */ if (dev->flags & FZ_CHARPROC_MASK) { if (dev->flags & FZ_CHARPROC_COLOR) - fz_warn("type3 glyph claims to be both masked and colored"); + fz_warn(ctx, "type3 glyph claims to be both masked and colored"); model = NULL; } else if (dev->flags & FZ_CHARPROC_COLOR) { if (model == NULL) - fz_warn("colored type3 glyph wanted in masked context"); + fz_warn(ctx, "colored type3 glyph wanted in masked context"); } else { - fz_warn("type3 glyph doesn't specify masked or colored"); + fz_warn(ctx, "type3 glyph doesn't specify masked or colored"); model = NULL; /* Treat as masked */ } @@ -560,21 +576,20 @@ fz_render_t3_glyph(fz_font *font, int gid, fz_matrix trm, fz_colorspace *model) bbox.x1++; bbox.y1++; - glyph = fz_new_pixmap_with_rect(model ? model : fz_device_gray, bbox); + glyph = fz_new_pixmap_with_rect(ctx, model ? model : fz_device_gray, bbox); fz_clear_pixmap(glyph); - cache = fz_new_glyph_cache(); - dev = fz_new_draw_device_type3(cache, glyph); - error = font->t3run(font->t3xref, font->t3resources, contents, dev, ctm); - if (error) - fz_catch(error, "cannot draw type3 glyph"); + cache = fz_new_glyph_cache(ctx); + dev = fz_new_draw_device_type3(ctx, cache, glyph); + font->t3run(font->t3xref, font->t3resources, contents, dev, ctm); + /* RJW: "cannot draw type3 glyph" */ fz_free_device(dev); - fz_free_glyph_cache(cache); + fz_free_glyph_cache(ctx, cache); if (model == NULL) { - result = fz_alpha_from_gray(glyph, 0); - fz_drop_pixmap(glyph); + result = fz_alpha_from_gray(ctx, glyph, 0); + fz_drop_pixmap(ctx, glyph); } else result = glyph; diff --git a/fitz/res_halftone.c b/fitz/res_halftone.c index e45454ea..ad2ab694 100644 --- a/fitz/res_halftone.c +++ b/fitz/res_halftone.c @@ -1,12 +1,12 @@ #include "fitz.h" fz_halftone * -fz_new_halftone(int comps) +fz_new_halftone(fz_context *ctx, int comps) { fz_halftone *ht; int i; - ht = fz_malloc(sizeof(fz_halftone) + (comps-1)*sizeof(fz_pixmap *)); + ht = fz_malloc(ctx, sizeof(fz_halftone) + (comps-1)*sizeof(fz_pixmap *)); ht->refs = 1; ht->n = comps; for (i = 0; i < comps; i++) @@ -23,15 +23,15 @@ fz_keep_halftone(fz_halftone *ht) } void -fz_drop_halftone(fz_halftone *ht) +fz_drop_halftone(fz_context *ctx, fz_halftone *ht) { int i; if (!ht || --ht->refs != 0) return; for (i = 0; i < ht->n; i++) - fz_drop_pixmap(ht->comp[i]); - fz_free(ht); + fz_drop_pixmap(ctx, ht->comp[i]); + fz_free(ctx, ht); } /* Default mono halftone, lifted from Ghostscript. */ @@ -55,11 +55,11 @@ static unsigned char mono_ht[] = 0xF2, 0x72, 0xD2, 0x52, 0xFA, 0x7A, 0xDA, 0x5A, 0xF0, 0x70, 0xD0, 0x50, 0xF8, 0x78, 0xD8, 0x58 }; -fz_halftone *fz_get_default_halftone(int num_comps) +fz_halftone *fz_get_default_halftone(fz_context *ctx, int num_comps) { - fz_halftone *ht = fz_new_halftone(num_comps); + fz_halftone *ht = fz_new_halftone(ctx, num_comps); assert(num_comps == 1); /* Only support 1 component for now */ - ht->comp[0] = fz_new_pixmap_with_data(NULL, 16, 16, mono_ht); + ht->comp[0] = fz_new_pixmap_with_data(ctx, NULL, 16, 16, mono_ht); return ht; } @@ -156,7 +156,7 @@ static void do_threshold_1(unsigned char *ht_line, unsigned char *pixmap, unsign *out++ = h; } -fz_bitmap *fz_halftone_pixmap(fz_pixmap *pix, fz_halftone *ht) +fz_bitmap *fz_halftone_pixmap(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht) { fz_bitmap *out; unsigned char *ht_line, *o, *p; @@ -168,8 +168,8 @@ fz_bitmap *fz_halftone_pixmap(fz_pixmap *pix, fz_halftone *ht) assert(pix->n == 2); /* Mono + Alpha */ n = pix->n-1; /* Remove alpha */ - ht_line = fz_malloc(pix->w * n); - out = fz_new_bitmap(pix->w, pix->h, n); + ht_line = fz_malloc(ctx, pix->w * n); + out = fz_new_bitmap(ctx, pix->w, pix->h, n); o = out->samples; p = pix->samples; diff --git a/fitz/res_path.c b/fitz/res_path.c index 328e5ac1..cea720e9 100644 --- a/fitz/res_path.c +++ b/fitz/res_path.c @@ -1,11 +1,12 @@ +#include <assert.h> #include "fitz.h" fz_path * -fz_new_path(void) +fz_new_path(fz_context *ctx) { fz_path *path; - path = fz_malloc(sizeof(fz_path)); + path = fz_malloc(ctx, sizeof(fz_path)); path->len = 0; path->cap = 0; path->items = NULL; @@ -14,71 +15,72 @@ fz_new_path(void) } fz_path * -fz_clone_path(fz_path *old) +fz_clone_path(fz_context *ctx, fz_path *old) { fz_path *path; - path = fz_malloc(sizeof(fz_path)); + assert(old != NULL); + path = fz_malloc(ctx, sizeof(fz_path)); path->len = old->len; path->cap = old->len; - path->items = fz_calloc(path->cap, sizeof(fz_path_item)); + path->items = fz_malloc_array(ctx, path->cap, sizeof(fz_path_item)); memcpy(path->items, old->items, sizeof(fz_path_item) * path->len); return path; } void -fz_free_path(fz_path *path) +fz_free_path(fz_context *ctx, fz_path *path) { - fz_free(path->items); - fz_free(path); + fz_free(ctx, path->items); + fz_free(ctx, path); } static void -grow_path(fz_path *path, int n) +grow_path(fz_context *ctx, fz_path *path, int n) { if (path->len + n < path->cap) return; while (path->len + n > path->cap) path->cap = path->cap + 36; - path->items = fz_realloc(path->items, path->cap, sizeof(fz_path_item)); + path->items = fz_resize_array(ctx, path->items, path->cap, sizeof(fz_path_item)); } void -fz_moveto(fz_path *path, float x, float y) +fz_moveto(fz_context *ctx, fz_path *path, float x, float y) { - grow_path(path, 3); + grow_path(ctx, path, 3); path->items[path->len++].k = FZ_MOVETO; path->items[path->len++].v = x; path->items[path->len++].v = y; } void -fz_lineto(fz_path *path, float x, float y) +fz_lineto(fz_context *ctx, fz_path *path, float x, float y) { if (path->len == 0) { - fz_warn("lineto with no current point"); + fz_warn(ctx, "lineto with no current point"); return; } - grow_path(path, 3); + grow_path(ctx, path, 3); path->items[path->len++].k = FZ_LINETO; path->items[path->len++].v = x; path->items[path->len++].v = y; } void -fz_curveto(fz_path *path, +fz_curveto(fz_context *ctx, fz_path *path, float x1, float y1, float x2, float y2, float x3, float y3) { if (path->len == 0) { - fz_warn("curveto with no current point"); + fz_warn(ctx, "curveto with no current point"); return; } - grow_path(path, 7); + grow_path(ctx, path, 7); path->items[path->len++].k = FZ_CURVETO; path->items[path->len++].v = x1; path->items[path->len++].v = y1; @@ -89,34 +91,34 @@ fz_curveto(fz_path *path, } void -fz_curvetov(fz_path *path, float x2, float y2, float x3, float y3) +fz_curvetov(fz_context *ctx, fz_path *path, float x2, float y2, float x3, float y3) { float x1, y1; if (path->len == 0) { - fz_warn("curvetov with no current point"); + fz_warn(ctx, "curvetov with no current point"); return; } x1 = path->items[path->len-2].v; y1 = path->items[path->len-1].v; - fz_curveto(path, x1, y1, x2, y2, x3, y3); + fz_curveto(ctx, path, x1, y1, x2, y2, x3, y3); } void -fz_curvetoy(fz_path *path, float x1, float y1, float x3, float y3) +fz_curvetoy(fz_context *ctx, fz_path *path, float x1, float y1, float x3, float y3) { - fz_curveto(path, x1, y1, x3, y3, x3, y3); + fz_curveto(ctx, path, x1, y1, x3, y3, x3, y3); } void -fz_closepath(fz_path *path) +fz_closepath(fz_context *ctx, fz_path *path) { if (path->len == 0) { - fz_warn("closepath with no current point"); + fz_warn(ctx, "closepath with no current point"); return; } - grow_path(path, 1); + grow_path(ctx, path, 1); path->items[path->len++].k = FZ_CLOSE_PATH; } diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index b1f151c3..1dfc8ad0 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -4,11 +4,11 @@ static int fz_memory_limit = 256 << 20; static int fz_memory_used = 0; fz_pixmap * -fz_new_pixmap_with_data(fz_colorspace *colorspace, int w, int h, unsigned char *samples) +fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples) { fz_pixmap *pix; - pix = fz_malloc(sizeof(fz_pixmap)); + pix = fz_malloc(ctx, sizeof(fz_pixmap)); pix->refs = 1; pix->x = 0; pix->y = 0; @@ -35,7 +35,7 @@ fz_new_pixmap_with_data(fz_colorspace *colorspace, int w, int h, unsigned char * else { fz_memory_used += pix->w * pix->h * pix->n; - pix->samples = fz_calloc(pix->h, pix->w * pix->n); + pix->samples = fz_malloc_array(ctx, pix->h, pix->w * pix->n); pix->free_samples = 1; } @@ -43,40 +43,40 @@ fz_new_pixmap_with_data(fz_colorspace *colorspace, int w, int h, unsigned char * } fz_pixmap * -fz_new_pixmap_with_limit(fz_colorspace *colorspace, int w, int h) +fz_new_pixmap_with_limit(fz_context *ctx, fz_colorspace *colorspace, int w, int h) { int n = colorspace ? colorspace->n + 1 : 1; int size = w * h * n; if (fz_memory_used + size > fz_memory_limit) { - fz_warn("pixmap memory exceeds soft limit %dM + %dM > %dM", + fz_warn(ctx, "pixmap memory exceeds soft limit %dM + %dM > %dM", fz_memory_used/(1<<20), size/(1<<20), fz_memory_limit/(1<<20)); return NULL; } - return fz_new_pixmap_with_data(colorspace, w, h, NULL); + return fz_new_pixmap_with_data(ctx, colorspace, w, h, NULL); } fz_pixmap * -fz_new_pixmap(fz_colorspace *colorspace, int w, int h) +fz_new_pixmap(fz_context *ctx, fz_colorspace *colorspace, int w, int h) { - return fz_new_pixmap_with_data(colorspace, w, h, NULL); + return fz_new_pixmap_with_data(ctx, colorspace, w, h, NULL); } fz_pixmap * -fz_new_pixmap_with_rect(fz_colorspace *colorspace, fz_bbox r) +fz_new_pixmap_with_rect(fz_context *ctx, fz_colorspace *colorspace, fz_bbox r) { fz_pixmap *pixmap; - pixmap = fz_new_pixmap(colorspace, r.x1 - r.x0, r.y1 - r.y0); + pixmap = fz_new_pixmap(ctx, colorspace, r.x1 - r.x0, r.y1 - r.y0); pixmap->x = r.x0; pixmap->y = r.y0; return pixmap; } fz_pixmap * -fz_new_pixmap_with_rect_and_data(fz_colorspace *colorspace, fz_bbox r, unsigned char *samples) +fz_new_pixmap_with_rect_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_bbox r, unsigned char *samples) { fz_pixmap *pixmap; - pixmap = fz_new_pixmap_with_data(colorspace, r.x1 - r.x0, r.y1 - r.y0, samples); + pixmap = fz_new_pixmap_with_data(ctx, colorspace, r.x1 - r.x0, r.y1 - r.y0, samples); pixmap->x = r.x0; pixmap->y = r.y0; return pixmap; @@ -90,18 +90,18 @@ fz_keep_pixmap(fz_pixmap *pix) } void -fz_drop_pixmap(fz_pixmap *pix) +fz_drop_pixmap(fz_context *ctx, fz_pixmap *pix) { if (pix && --pix->refs == 0) { fz_memory_used -= pix->w * pix->h * pix->n; if (pix->mask) - fz_drop_pixmap(pix->mask); + fz_drop_pixmap(ctx, pix->mask); if (pix->colorspace) - fz_drop_colorspace(pix->colorspace); + fz_drop_colorspace(ctx, pix->colorspace); if (pix->free_samples) - fz_free(pix->samples); - fz_free(pix); + fz_free(ctx, pix->samples); + fz_free(ctx, pix); } } @@ -247,7 +247,7 @@ fz_unmultiply_pixmap(fz_pixmap *pix) } fz_pixmap * -fz_alpha_from_gray(fz_pixmap *gray, int luminosity) +fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity) { fz_pixmap *alpha; unsigned char *sp, *dp; @@ -255,7 +255,7 @@ fz_alpha_from_gray(fz_pixmap *gray, int luminosity) assert(gray->n == 2); - alpha = fz_new_pixmap_with_rect(NULL, fz_bound_pixmap(gray)); + alpha = fz_new_pixmap_with_rect(ctx, NULL, fz_bound_pixmap(gray)); dp = alpha->samples; sp = gray->samples; if (!luminosity) @@ -313,19 +313,19 @@ fz_gamma_pixmap(fz_pixmap *pix, float gamma) * Write pixmap to PNM file (without alpha channel) */ -fz_error -fz_write_pnm(fz_pixmap *pixmap, char *filename) +void +fz_write_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename) { FILE *fp; unsigned char *p; int len; if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4) - return fz_throw("pixmap must be grayscale or rgb to write as pnm"); + fz_throw(ctx, "pixmap must be grayscale or rgb to write as pnm"); fp = fopen(filename, "wb"); if (!fp) - return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); + fz_throw(ctx, "cannot open file '%s': %s", filename, strerror(errno)); if (pixmap->n == 1 || pixmap->n == 2) fprintf(fp, "P5\n"); @@ -360,15 +360,14 @@ fz_write_pnm(fz_pixmap *pixmap, char *filename) } fclose(fp); - return fz_okay; } /* * Write pixmap to PAM file (with or without alpha channel) */ -fz_error -fz_write_pam(fz_pixmap *pixmap, char *filename, int savealpha) +void +fz_write_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha) { unsigned char *sp; int y, w, k; @@ -381,7 +380,7 @@ fz_write_pam(fz_pixmap *pixmap, char *filename, int savealpha) fp = fopen(filename, "wb"); if (!fp) - return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); + fz_throw(ctx, "cannot open file '%s': %s", filename, strerror(errno)); fprintf(fp, "P7\n"); fprintf(fp, "WIDTH %d\n", pixmap->w); @@ -412,8 +411,6 @@ fz_write_pam(fz_pixmap *pixmap, char *filename, int savealpha) } fclose(fp); - - return fz_okay; } /* @@ -450,8 +447,8 @@ static void putchunk(char *tag, unsigned char *data, int size, FILE *fp) put32(sum, fp); } -fz_error -fz_write_png(fz_pixmap *pixmap, char *filename, int savealpha) +void +fz_write_png(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha) { static const unsigned char pngsig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; FILE *fp; @@ -463,7 +460,7 @@ fz_write_png(fz_pixmap *pixmap, char *filename, int savealpha) int err; if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4) - return fz_throw("pixmap must be grayscale or rgb to write as png"); + fz_throw(ctx, "pixmap must be grayscale or rgb to write as png"); sn = pixmap->n; dn = pixmap->n; @@ -481,8 +478,8 @@ fz_write_png(fz_pixmap *pixmap, char *filename, int savealpha) usize = (pixmap->w * dn + 1) * pixmap->h; csize = compressBound(usize); - udata = fz_malloc(usize); - cdata = fz_malloc(csize); + udata = fz_malloc(ctx, usize); + cdata = fz_malloc(ctx, csize); sp = pixmap->samples; dp = udata; @@ -506,17 +503,17 @@ fz_write_png(fz_pixmap *pixmap, char *filename, int savealpha) err = compress(cdata, &csize, udata, usize); if (err != Z_OK) { - fz_free(udata); - fz_free(cdata); - return fz_throw("cannot compress image data"); + fz_free(ctx, udata); + fz_free(ctx, cdata); + fz_throw(ctx, "cannot compress image data"); } fp = fopen(filename, "wb"); if (!fp) { - fz_free(udata); - fz_free(cdata); - return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); + fz_free(ctx, udata); + fz_free(ctx, cdata); + fz_throw(ctx, "cannot open file '%s': %s", filename, strerror(errno)); } big32(head+0, pixmap->w); @@ -533,7 +530,6 @@ fz_write_png(fz_pixmap *pixmap, char *filename, int savealpha) putchunk("IEND", head, 0, fp); fclose(fp); - fz_free(udata); - fz_free(cdata); - return fz_okay; + fz_free(ctx, udata); + fz_free(ctx, cdata); } diff --git a/fitz/res_shade.c b/fitz/res_shade.c index 7faff3bf..b7617161 100644 --- a/fitz/res_shade.c +++ b/fitz/res_shade.c @@ -8,14 +8,14 @@ fz_keep_shade(fz_shade *shade) } void -fz_drop_shade(fz_shade *shade) +fz_drop_shade(fz_context *ctx, fz_shade *shade) { if (shade && --shade->refs == 0) { if (shade->colorspace) - fz_drop_colorspace(shade->colorspace); - fz_free(shade->mesh); - fz_free(shade); + fz_drop_colorspace(ctx, shade->colorspace); + fz_free(ctx, shade->mesh); + fz_free(ctx, shade); } } diff --git a/fitz/res_text.c b/fitz/res_text.c index d38637f1..5eaf12b0 100644 --- a/fitz/res_text.c +++ b/fitz/res_text.c @@ -1,11 +1,11 @@ #include "fitz.h" fz_text * -fz_new_text(fz_font *font, fz_matrix trm, int wmode) +fz_new_text(fz_context *ctx, fz_font *font, fz_matrix trm, int wmode) { fz_text *text; - text = fz_malloc(sizeof(fz_text)); + text = fz_malloc(ctx, sizeof(fz_text)); text->font = fz_keep_font(font); text->trm = trm; text->wmode = wmode; @@ -17,25 +17,25 @@ fz_new_text(fz_font *font, fz_matrix trm, int wmode) } void -fz_free_text(fz_text *text) +fz_free_text(fz_context *ctx, fz_text *text) { - fz_drop_font(text->font); - fz_free(text->items); - fz_free(text); + fz_drop_font(ctx, text->font); + fz_free(ctx, text->items); + fz_free(ctx, text); } fz_text * -fz_clone_text(fz_text *old) +fz_clone_text(fz_context *ctx, fz_text *old) { fz_text *text; - text = fz_malloc(sizeof(fz_text)); + text = fz_malloc(ctx, sizeof(fz_text)); text->font = fz_keep_font(old->font); text->trm = old->trm; text->wmode = old->wmode; text->len = old->len; text->cap = text->len; - text->items = fz_calloc(text->len, sizeof(fz_text_item)); + text->items = fz_malloc_array(ctx, text->len, sizeof(fz_text_item)); memcpy(text->items, old->items, text->len * sizeof(fz_text_item)); return text; @@ -91,19 +91,19 @@ fz_bound_text(fz_text *text, fz_matrix ctm) } static void -fz_grow_text(fz_text *text, int n) +fz_grow_text(fz_context *ctx, fz_text *text, int n) { if (text->len + n < text->cap) return; while (text->len + n > text->cap) text->cap = text->cap + 36; - text->items = fz_realloc(text->items, text->cap, sizeof(fz_text_item)); + text->items = fz_resize_array(ctx, text->items, text->cap, sizeof(fz_text_item)); } void -fz_add_text(fz_text *text, int gid, int ucs, float x, float y) +fz_add_text(fz_context *ctx, fz_text *text, int gid, int ucs, float x, float y) { - fz_grow_text(text, 1); + fz_grow_text(ctx, text, 1); text->items[text->len].ucs = ucs; text->items[text->len].gid = gid; text->items[text->len].x = x; diff --git a/fitz/stm_buffer.c b/fitz/stm_buffer.c index 4c7410c3..eb96cd2f 100644 --- a/fitz/stm_buffer.c +++ b/fitz/stm_buffer.c @@ -1,15 +1,15 @@ #include "fitz.h" fz_buffer * -fz_new_buffer(int size) +fz_new_buffer(fz_context *ctx, int size) { fz_buffer *b; size = size > 1 ? size : 16; - b = fz_malloc(sizeof(fz_buffer)); + b = fz_malloc(ctx, sizeof(fz_buffer)); b->refs = 1; - b->data = fz_malloc(size); + b->data = fz_malloc(ctx, size); b->cap = size; b->len = 0; @@ -24,26 +24,26 @@ fz_keep_buffer(fz_buffer *buf) } void -fz_drop_buffer(fz_buffer *buf) +fz_drop_buffer(fz_context *ctx, fz_buffer *buf) { if (--buf->refs == 0) { - fz_free(buf->data); - fz_free(buf); + fz_free(ctx, buf->data); + fz_free(ctx, buf); } } void -fz_resize_buffer(fz_buffer *buf, int size) +fz_resize_buffer(fz_context *ctx, fz_buffer *buf, int size) { - buf->data = fz_realloc(buf->data, size, 1); + buf->data = fz_resize_array(ctx, buf->data, size, 1); buf->cap = size; if (buf->len > buf->cap) buf->len = buf->cap; } void -fz_grow_buffer(fz_buffer *buf) +fz_grow_buffer(fz_context *ctx, fz_buffer *buf) { - fz_resize_buffer(buf, (buf->cap * 3) / 2); + fz_resize_buffer(ctx, buf, (buf->cap * 3) / 2); } diff --git a/fitz/stm_open.c b/fitz/stm_open.c index 74346f73..aa99451b 100644 --- a/fitz/stm_open.c +++ b/fitz/stm_open.c @@ -1,13 +1,13 @@ #include "fitz.h" fz_stream * -fz_new_stream(void *state, +fz_new_stream(fz_context *ctx, void *state, int(*read)(fz_stream *stm, unsigned char *buf, int len), void(*close)(fz_stream *stm)) { fz_stream *stm; - stm = fz_malloc(sizeof(fz_stream)); + stm = fz_malloc(ctx, sizeof(fz_stream)); stm->refs = 1; stm->error = 0; @@ -26,6 +26,7 @@ fz_new_stream(void *state, stm->read = read; stm->close = close; stm->seek = NULL; + stm->ctx = ctx; return stm; } @@ -40,12 +41,14 @@ fz_keep_stream(fz_stream *stm) void fz_close(fz_stream *stm) { + if (stm == NULL) + return; stm->refs --; if (stm->refs == 0) { if (stm->close) stm->close(stm); - fz_free(stm); + fz_free(stm->ctx, stm); } } @@ -55,7 +58,7 @@ static int read_file(fz_stream *stm, unsigned char *buf, int len) { int n = read(*(int*)stm->state, buf, len); if (n < 0) - return fz_throw("read error: %s", strerror(errno)); + return fz_error_make("read error: %s", strerror(errno)); return n; } @@ -63,7 +66,7 @@ static void seek_file(fz_stream *stm, int offset, int whence) { int n = lseek(*(int*)stm->state, offset, whence); if (n < 0) - fz_warn("cannot lseek: %s", strerror(errno)); + fz_warn(stm->ctx, "cannot lseek: %s", strerror(errno)); stm->pos = n; stm->rp = stm->bp; stm->wp = stm->bp; @@ -73,42 +76,42 @@ static void close_file(fz_stream *stm) { int n = close(*(int*)stm->state); if (n < 0) - fz_warn("close error: %s", strerror(errno)); - fz_free(stm->state); + fz_warn(stm->ctx, "close error: %s", strerror(errno)); + fz_free(stm->ctx, stm->state); } fz_stream * -fz_open_fd(int fd) +fz_open_fd(fz_context *ctx, int fd) { fz_stream *stm; int *state; - state = fz_malloc(sizeof(int)); + state = fz_malloc(ctx, sizeof(int)); *state = fd; - stm = fz_new_stream(state, read_file, close_file); + stm = fz_new_stream(ctx, state, read_file, close_file); stm->seek = seek_file; return stm; } fz_stream * -fz_open_file(const char *name) +fz_open_file(fz_context *ctx, const char *name) { int fd = open(name, O_BINARY | O_RDONLY, 0); if (fd == -1) - return NULL; - return fz_open_fd(fd); + fz_throw(ctx, "Failed to open %s", name); + return fz_open_fd(ctx, fd); } #ifdef _WIN32 fz_stream * -fz_open_file_w(const wchar_t *name) +fz_open_file_w(fz_context *ctx, const wchar_t *name) { int fd = _wopen(name, O_BINARY | O_RDONLY, 0); if (fd == -1) return NULL; - return fz_open_fd(fd); + return fz_open_fd(ctx, fd); } #endif @@ -134,15 +137,15 @@ static void seek_buffer(fz_stream *stm, int offset, int whence) static void close_buffer(fz_stream *stm) { if (stm->state) - fz_drop_buffer(stm->state); + fz_drop_buffer(stm->ctx, stm->state); } fz_stream * -fz_open_buffer(fz_buffer *buf) +fz_open_buffer(fz_context *ctx, fz_buffer *buf) { fz_stream *stm; - stm = fz_new_stream(fz_keep_buffer(buf), read_buffer, close_buffer); + stm = fz_new_stream(ctx, fz_keep_buffer(buf), read_buffer, close_buffer); stm->seek = seek_buffer; stm->bp = buf->data; @@ -156,11 +159,11 @@ fz_open_buffer(fz_buffer *buf) } fz_stream * -fz_open_memory(unsigned char *data, int len) +fz_open_memory(fz_context *ctx, unsigned char *data, int len) { fz_stream *stm; - stm = fz_new_stream(NULL, read_buffer, close_buffer); + stm = fz_new_stream(ctx, NULL, read_buffer, close_buffer); stm->seek = seek_buffer; stm->bp = data; diff --git a/fitz/stm_read.c b/fitz/stm_read.c index ff97340f..5622a24f 100644 --- a/fitz/stm_read.c +++ b/fitz/stm_read.c @@ -23,7 +23,7 @@ fz_read(fz_stream *stm, unsigned char *buf, int len) if (n < 0) { stm->error = 1; - return fz_rethrow(n, "read error"); + return fz_error_note(n, "read error"); } else if (n == 0) { @@ -50,7 +50,7 @@ fz_read(fz_stream *stm, unsigned char *buf, int len) if (n < 0) { stm->error = 1; - return fz_rethrow(n, "read error"); + return fz_error_note(n, "read error"); } else if (n == 0) { @@ -80,7 +80,7 @@ fz_fill_buffer(fz_stream *stm) if (n < 0) { stm->error = 1; - fz_catch(n, "read error; treating as end of file"); + fz_error_handle(n, "read error; treating as end of file"); } else if (n == 0) { @@ -94,33 +94,34 @@ fz_fill_buffer(fz_stream *stm) } } -fz_error -fz_read_all(fz_buffer **bufp, fz_stream *stm, int initial) +fz_buffer * +fz_read_all(fz_stream *stm, int initial) { fz_buffer *buf; int n; + fz_context *ctx = stm->ctx; if (initial < 1024) initial = 1024; - buf = fz_new_buffer(initial); + buf = fz_new_buffer(ctx, initial); while (1) { if (buf->len == buf->cap) - fz_grow_buffer(buf); + fz_grow_buffer(ctx, buf); if (buf->len / 200 > initial) { - fz_drop_buffer(buf); - return fz_throw("compression bomb detected"); + fz_drop_buffer(ctx, buf); + fz_throw(ctx, "compression bomb detected"); } n = fz_read(stm, buf->data + buf->len, buf->cap - buf->len); if (n < 0) { - fz_drop_buffer(buf); - return fz_rethrow(n, "read error"); + fz_drop_buffer(ctx, buf); + fz_throw(ctx, "read error"); } if (n == 0) break; @@ -128,8 +129,7 @@ fz_read_all(fz_buffer **bufp, fz_stream *stm, int initial) buf->len += n; } - *bufp = buf; - return fz_okay; + return buf; } void @@ -191,11 +191,11 @@ fz_seek(fz_stream *stm, int offset, int whence) if (whence == 0) offset -= fz_tell(stm); if (offset < 0) - fz_warn("cannot seek backwards"); + fz_warn(stm->ctx, "cannot seek backwards"); /* dog slow, but rare enough */ while (offset-- > 0) fz_read_byte(stm); } else - fz_warn("cannot seek"); + fz_warn(stm->ctx, "cannot seek"); } diff --git a/pdf/mupdf.h b/pdf/mupdf.h index e03f6efc..79560dab 100644 --- a/pdf/mupdf.h +++ b/pdf/mupdf.h @@ -25,19 +25,19 @@ enum PDF_NUM_TOKENS }; -fz_error pdf_lex(int *tok, fz_stream *f, char *buf, int n, int *len); +int pdf_lex(fz_stream *f, char *buf, int n, int *len); -fz_error pdf_parse_array(fz_obj **op, pdf_xref *xref, fz_stream *f, char *buf, int cap); -fz_error pdf_parse_dict(fz_obj **op, pdf_xref *xref, fz_stream *f, char *buf, int cap); -fz_error pdf_parse_stm_obj(fz_obj **op, pdf_xref *xref, fz_stream *f, char *buf, int cap); -fz_error pdf_parse_ind_obj(fz_obj **op, pdf_xref *xref, fz_stream *f, char *buf, int cap, int *num, int *gen, int *stm_ofs); +fz_obj *pdf_parse_array(pdf_xref *xref, fz_stream *f, char *buf, int cap); +fz_obj *pdf_parse_dict(pdf_xref *xref, fz_stream *f, char *buf, int cap); +fz_obj *pdf_parse_stm_obj(pdf_xref *xref, fz_stream *f, char *buf, int cap); +fz_obj * pdf_parse_ind_obj(pdf_xref *xref, fz_stream *f, char *buf, int cap, int *num, int *gen, int *stm_ofs); -fz_rect pdf_to_rect(fz_obj *array); -fz_matrix pdf_to_matrix(fz_obj *array); -char *pdf_to_utf8(fz_obj *src); -unsigned short *pdf_to_ucs2(fz_obj *src); -fz_obj *pdf_to_utf8_name(fz_obj *src); -char *pdf_from_ucs2(unsigned short *str); +fz_rect pdf_to_rect(fz_context *ctx, fz_obj *array); +fz_matrix pdf_to_matrix(fz_context *ctx, fz_obj *array); +char *pdf_to_utf8(fz_context *ctx, fz_obj *src); +unsigned short *pdf_to_ucs2(fz_context *ctx, fz_obj *src); +fz_obj *pdf_to_utf8_name(fz_context *ctx, fz_obj *src); +char *pdf_from_ucs2(fz_context *ctx, unsigned short *str); /* * xref and object / stream api @@ -73,6 +73,7 @@ struct pdf_ocg_descriptor_s struct pdf_xref_s { + fz_context *ctx; fz_stream *file; int version; int startxref; @@ -95,25 +96,25 @@ struct pdf_xref_s }; fz_obj *pdf_resolve_indirect(fz_obj *ref); -fz_error pdf_cache_object(pdf_xref *, int num, int gen); -fz_error pdf_load_object(fz_obj **objp, pdf_xref *, int num, int gen); +void pdf_cache_object(pdf_xref *, int num, int gen); +fz_obj *pdf_load_object(pdf_xref *, int num, int gen); void pdf_update_object( pdf_xref *xref, int num, int gen, fz_obj *newobj); int pdf_is_stream(pdf_xref *xref, int num, int gen); fz_stream *pdf_open_inline_stream(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int length); -fz_error pdf_load_raw_stream(fz_buffer **bufp, pdf_xref *xref, int num, int gen); -fz_error pdf_load_stream(fz_buffer **bufp, pdf_xref *xref, int num, int gen); -fz_error pdf_open_raw_stream(fz_stream **stmp, pdf_xref *, int num, int gen); -fz_error pdf_open_stream(fz_stream **stmp, pdf_xref *, int num, int gen); -fz_error pdf_open_stream_at(fz_stream **stmp, pdf_xref *xref, int num, int gen, fz_obj *dict, int stm_ofs); - -fz_error pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password); -fz_error pdf_open_xref(pdf_xref **xrefp, const char *filename, char *password); +fz_buffer *pdf_load_raw_stream(pdf_xref *xref, int num, int gen); +fz_buffer *pdf_load_stream(pdf_xref *xref, int num, int gen); +fz_stream *pdf_open_raw_stream(pdf_xref *, int num, int gen); +fz_stream *pdf_open_stream(pdf_xref *, int num, int gen); +fz_stream *pdf_open_stream_at(pdf_xref *xref, int num, int gen, fz_obj *dict, int stm_ofs); + +pdf_xref *pdf_open_xref_with_stream(fz_stream *file, char *password); +pdf_xref *pdf_open_xref(fz_context *ctx, const char *filename, char *password); void pdf_free_xref(pdf_xref *); /* private */ -fz_error pdf_repair_xref(pdf_xref *xref, char *buf, int bufsize); -fz_error pdf_repair_obj_stms(pdf_xref *xref); +void pdf_repair_xref(pdf_xref *xref, char *buf, int bufsize); +void pdf_repair_obj_stms(pdf_xref *xref); void pdf_debug_xref(pdf_xref *); void pdf_resize_xref(pdf_xref *xref, int newcap); @@ -134,10 +135,10 @@ enum PDF_DEFAULT_PERM_FLAGS = 0xfffc }; -fz_error pdf_new_crypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id); -void pdf_free_crypt(pdf_crypt *crypt); +pdf_crypt *pdf_new_crypt(fz_context *ctx, fz_obj *enc, fz_obj *id); +void pdf_free_crypt(fz_context *ctx, pdf_crypt *crypt); -void pdf_crypt_obj(pdf_crypt *crypt, fz_obj *obj, int num, int gen); +void pdf_crypt_obj(fz_context *ctx, pdf_crypt *crypt, fz_obj *obj, int num, int gen); fz_stream *pdf_open_crypt(fz_stream *chain, pdf_crypt *crypt, int num, int gen); fz_stream *pdf_open_crypt_with_filter(fz_stream *chain, pdf_crypt *crypt, char *name, int num, int gen); @@ -158,14 +159,17 @@ void pdf_debug_crypt(pdf_crypt *crypt); typedef struct pdf_store_s pdf_store; -pdf_store *pdf_new_store(void); -void pdf_free_store(pdf_store *store); -void pdf_debug_store(pdf_store *store); +pdf_store *pdf_new_store(fz_context *ctx); +void pdf_free_store(fz_context *ctx, pdf_store *store); +void pdf_debug_store(fz_context *ctx, pdf_store *store); -void pdf_store_item(pdf_store *store, void *keepfn, void *dropfn, fz_obj *key, void *val); -void *pdf_find_item(pdf_store *store, void *dropfn, fz_obj *key); -void pdf_remove_item(pdf_store *store, void *dropfn, fz_obj *key); -void pdf_age_store(pdf_store *store, int maxage); +typedef void *(pdf_store_keep_fn)(void *); +typedef void (pdf_store_drop_fn)(fz_context *, void *); + +void pdf_store_item(fz_context *ctx, pdf_store *store, pdf_store_keep_fn *keepfn, pdf_store_drop_fn *dropfn, fz_obj *key, void *val); +void *pdf_find_item(fz_context *ctx, pdf_store *store, pdf_store_drop_fn *dropfn, fz_obj *key); +void pdf_remove_item(fz_context *ctx, pdf_store *store, pdf_store_drop_fn *dropfn, fz_obj *key); +void pdf_age_store(fz_context *ctx, pdf_store *store, int maxage); /* * Functions, Colorspaces, Shadings and Images @@ -173,19 +177,19 @@ void pdf_age_store(pdf_store *store, int maxage); typedef struct pdf_function_s pdf_function; -fz_error pdf_load_function(pdf_function **func, pdf_xref *xref, fz_obj *ref); -void pdf_eval_function(pdf_function *func, float *in, int inlen, float *out, int outlen); +pdf_function *pdf_load_function(pdf_xref *xref, fz_obj *ref); +void pdf_eval_function(fz_context *ctx, pdf_function *func, float *in, int inlen, float *out, int outlen); pdf_function *pdf_keep_function(pdf_function *func); -void pdf_drop_function(pdf_function *func); +void pdf_drop_function(fz_context *ctx, pdf_function *func); -fz_error pdf_load_colorspace(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj); -fz_pixmap *pdf_expand_indexed_pixmap(fz_pixmap *src); +fz_colorspace *pdf_load_colorspace(pdf_xref *xref, fz_obj *obj); +fz_pixmap *pdf_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src); -fz_error pdf_load_shading(fz_shade **shadep, pdf_xref *xref, fz_obj *obj); +fz_shade *pdf_load_shading(pdf_xref *xref, fz_obj *obj); -fz_error pdf_load_inline_image(fz_pixmap **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *file); -fz_error pdf_load_image(fz_pixmap **imgp, pdf_xref *xref, fz_obj *obj); -int pdf_is_jpx_image(fz_obj *dict); +fz_pixmap *pdf_load_inline_image(pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *file); +fz_pixmap *pdf_load_image(pdf_xref *xref, fz_obj *obj); +int pdf_is_jpx_image(fz_context *ctx, fz_obj *dict); /* * Pattern @@ -205,9 +209,9 @@ struct pdf_pattern_s fz_buffer *contents; }; -fz_error pdf_load_pattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *obj); +pdf_pattern *pdf_load_pattern(pdf_xref *xref, fz_obj *obj); pdf_pattern *pdf_keep_pattern(pdf_pattern *pat); -void pdf_drop_pattern(pdf_pattern *pat); +void pdf_drop_pattern(fz_context *ctx, pdf_pattern *pat); /* * XObject @@ -228,9 +232,9 @@ struct pdf_xobject_s fz_buffer *contents; }; -fz_error pdf_load_xobject(pdf_xobject **xobjp, pdf_xref *xref, fz_obj *obj); +pdf_xobject *pdf_load_xobject(pdf_xref *xref, fz_obj *obj); pdf_xobject *pdf_keep_xobject(pdf_xobject *xobj); -void pdf_drop_xobject(pdf_xobject *xobj); +void pdf_drop_xobject(fz_context *ctx, pdf_xobject *xobj); /* * CMap @@ -276,29 +280,29 @@ struct pdf_cmap_s unsigned short *table; }; -pdf_cmap *pdf_new_cmap(void); +pdf_cmap *pdf_new_cmap(fz_context *ctx); pdf_cmap *pdf_keep_cmap(pdf_cmap *cmap); -void pdf_drop_cmap(pdf_cmap *cmap); +void pdf_drop_cmap(fz_context *ctx, pdf_cmap *cmap); void pdf_debug_cmap(pdf_cmap *cmap); int pdf_get_wmode(pdf_cmap *cmap); void pdf_set_wmode(pdf_cmap *cmap, int wmode); -void pdf_set_usecmap(pdf_cmap *cmap, pdf_cmap *usecmap); +void pdf_set_usecmap(fz_context *ctx, pdf_cmap *cmap, pdf_cmap *usecmap); -void pdf_add_codespace(pdf_cmap *cmap, int low, int high, int n); -void pdf_map_range_to_table(pdf_cmap *cmap, int low, int *map, int len); -void pdf_map_range_to_range(pdf_cmap *cmap, int srclo, int srchi, int dstlo); -void pdf_map_one_to_many(pdf_cmap *cmap, int one, int *many, int len); -void pdf_sort_cmap(pdf_cmap *cmap); +void pdf_add_codespace(fz_context *ctx, pdf_cmap *cmap, int low, int high, int n); +void pdf_map_range_to_table(fz_context *ctx, pdf_cmap *cmap, int low, int *map, int len); +void pdf_map_range_to_range(fz_context *ctx, pdf_cmap *cmap, int srclo, int srchi, int dstlo); +void pdf_map_one_to_many(fz_context *ctx, pdf_cmap *cmap, int one, int *many, int len); +void pdf_sort_cmap(fz_context *ctx, pdf_cmap *cmap); int pdf_lookup_cmap(pdf_cmap *cmap, int cpt); int pdf_lookup_cmap_full(pdf_cmap *cmap, int cpt, int *out); unsigned char *pdf_decode_cmap(pdf_cmap *cmap, unsigned char *s, int *cpt); -pdf_cmap *pdf_new_identity_cmap(int wmode, int bytes); -fz_error pdf_parse_cmap(pdf_cmap **cmapp, fz_stream *file); -fz_error pdf_load_embedded_cmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *ref); -fz_error pdf_load_system_cmap(pdf_cmap **cmapp, char *name); +pdf_cmap *pdf_new_identity_cmap(fz_context *ctx, int wmode, int bytes); +pdf_cmap *pdf_parse_cmap(fz_stream *file); +pdf_cmap *pdf_load_embedded_cmap(pdf_xref *xref, fz_obj *ref); +pdf_cmap *pdf_load_system_cmap(fz_context *ctx, char *name); pdf_cmap *pdf_find_builtin_cmap(char *cmap_name); /* @@ -393,14 +397,14 @@ struct pdf_font_desc_s void pdf_set_font_wmode(pdf_font_desc *font, int wmode); void pdf_set_default_hmtx(pdf_font_desc *font, int w); void pdf_set_default_vmtx(pdf_font_desc *font, int y, int w); -void pdf_add_hmtx(pdf_font_desc *font, int lo, int hi, int w); -void pdf_add_vmtx(pdf_font_desc *font, int lo, int hi, int x, int y, int w); +void pdf_add_hmtx(fz_context *ctx, pdf_font_desc *font, int lo, int hi, int w); +void pdf_add_vmtx(fz_context *ctx, pdf_font_desc *font, int lo, int hi, int x, int y, int w); void pdf_end_hmtx(pdf_font_desc *font); void pdf_end_vmtx(pdf_font_desc *font); pdf_hmtx pdf_get_hmtx(pdf_font_desc *font, int cid); pdf_vmtx pdf_get_vmtx(pdf_font_desc *font, int cid); -fz_error pdf_load_to_unicode(pdf_font_desc *font, pdf_xref *xref, char **strings, char *collection, fz_obj *cmapstm); +void pdf_load_to_unicode(pdf_font_desc *font, pdf_xref *xref, char **strings, char *collection, fz_obj *cmapstm); int pdf_font_cid_to_gid(pdf_font_desc *fontdesc, int cid); @@ -408,12 +412,12 @@ unsigned char *pdf_find_builtin_font(char *name, unsigned int *len); unsigned char *pdf_find_substitute_font(int mono, int serif, int bold, int italic, unsigned int *len); unsigned char *pdf_find_substitute_cjk_font(int ros, int serif, unsigned int *len); -fz_error pdf_load_type3_font(pdf_font_desc **fontp, pdf_xref *xref, fz_obj *rdb, fz_obj *obj); -fz_error pdf_load_font(pdf_font_desc **fontp, pdf_xref *xref, fz_obj *rdb, fz_obj *obj); +pdf_font_desc *pdf_load_type3_font(pdf_xref *xref, fz_obj *rdb, fz_obj *obj); +pdf_font_desc *pdf_load_font(pdf_xref *xref, fz_obj *rdb, fz_obj *obj); -pdf_font_desc *pdf_new_font_desc(void); +pdf_font_desc *pdf_new_font_desc(fz_context *ctx); pdf_font_desc *pdf_keep_font(pdf_font_desc *fontdesc); -void pdf_drop_font(pdf_font_desc *font); +void pdf_drop_font(fz_context *ctx, pdf_font_desc *font); void pdf_debug_font(pdf_font_desc *fontdesc); @@ -458,10 +462,10 @@ fz_outline *pdf_load_outline(pdf_xref *xref); pdf_link *pdf_load_link(pdf_xref *xref, fz_obj *dict); void pdf_load_links(pdf_link **, pdf_xref *, fz_obj *annots); -void pdf_free_link(pdf_link *link); +void pdf_free_link(fz_context *ctx, pdf_link *link); void pdf_load_annots(pdf_annot **, pdf_xref *, fz_obj *annots); -void pdf_free_annot(pdf_annot *link); +void pdf_free_annot(fz_context *ctx, pdf_annot *link); /* * Page tree, pages and related objects @@ -480,19 +484,19 @@ struct pdf_page_s pdf_annot *annots; }; -fz_error pdf_load_page_tree(pdf_xref *xref); +void pdf_load_page_tree(pdf_xref *xref); int pdf_find_page_number(pdf_xref *xref, fz_obj *pageobj); int pdf_count_pages(pdf_xref *xref); -fz_error pdf_load_page(pdf_page **pagep, pdf_xref *xref, int number); -void pdf_free_page(pdf_page *page); +pdf_page *pdf_load_page(pdf_xref *xref, int number); +void pdf_free_page(fz_context *ctx, pdf_page *page); /* * Content stream parsing */ -fz_error pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, char *event); -fz_error pdf_run_page(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm); -fz_error pdf_run_glyph(pdf_xref *xref, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm); +void pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, char *event); +void pdf_run_page(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm); +void pdf_run_glyph(pdf_xref *xref, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm); #endif diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c index 2fc9d7bb..2a569e5c 100644 --- a/pdf/pdf_annot.c +++ b/pdf/pdf_annot.c @@ -2,13 +2,19 @@ #include "mupdf.h" void -pdf_free_link(pdf_link *link) +pdf_free_link(fz_context *ctx, pdf_link *link) { - if (link->next) - pdf_free_link(link->next); - if (link->dest) - fz_drop_obj(link->dest); - fz_free(link); + pdf_link *next; + + do + { + next = link->next; + if (link->dest) + fz_drop_obj(link->dest); + fz_free(ctx, link); + link = next; + } + while(link != NULL); } static fz_obj * @@ -45,12 +51,13 @@ pdf_load_link(pdf_xref *xref, fz_obj *dict) fz_obj *obj; fz_rect bbox; pdf_link_kind kind; + fz_context *ctx = xref->ctx; dest = NULL; obj = fz_dict_gets(dict, "Rect"); if (obj) - bbox = pdf_to_rect(obj); + bbox = pdf_to_rect(ctx, obj); else bbox = fz_empty_rect; @@ -103,7 +110,7 @@ pdf_load_link(pdf_xref *xref, fz_obj *dict) if (dest) { - pdf_link *link = fz_malloc(sizeof(pdf_link)); + pdf_link *link = fz_malloc(ctx, sizeof(pdf_link)); link->kind = kind; link->rect = bbox; link->dest = fz_keep_obj(dest); @@ -119,12 +126,13 @@ pdf_load_links(pdf_link **linkp, pdf_xref *xref, fz_obj *annots) { pdf_link *link, *head, *tail; fz_obj *obj; - int i; + int i, n; head = tail = NULL; link = NULL; - for (i = 0; i < fz_array_len(annots); i++) + n = fz_array_len(annots); + for (i = 0; i < n; i++) { obj = fz_array_get(annots, i); link = pdf_load_link(xref, obj); @@ -144,15 +152,21 @@ pdf_load_links(pdf_link **linkp, pdf_xref *xref, fz_obj *annots) } void -pdf_free_annot(pdf_annot *annot) +pdf_free_annot(fz_context *ctx, pdf_annot *annot) { - if (annot->next) - pdf_free_annot(annot->next); - if (annot->ap) - pdf_drop_xobject(annot->ap); - if (annot->obj) - fz_drop_obj(annot->obj); - fz_free(annot); + pdf_annot *next; + + do + { + next = annot->next; + if (annot->ap) + pdf_drop_xobject(ctx, annot->ap); + if (annot->obj) + fz_drop_obj(annot->obj); + fz_free(ctx, annot); + annot = next; + } + while (annot != NULL); } static void @@ -178,13 +192,14 @@ pdf_load_annots(pdf_annot **annotp, pdf_xref *xref, fz_obj *annots) pdf_annot *annot, *head, *tail; fz_obj *obj, *ap, *as, *n, *rect; pdf_xobject *form; - fz_error error; - int i; + int i, len; + fz_context *ctx = xref->ctx; head = tail = NULL; annot = NULL; - for (i = 0; i < fz_array_len(annots); i++) + len = fz_array_len(annots); + for (i = 0; i < len; i++) { obj = fz_array_get(annots, i); @@ -201,16 +216,19 @@ pdf_load_annots(pdf_annot **annotp, pdf_xref *xref, fz_obj *annots) if (pdf_is_stream(xref, fz_to_num(n), fz_to_gen(n))) { - error = pdf_load_xobject(&form, xref, n); - if (error) + fz_try(ctx) + { + form = pdf_load_xobject(xref, n); + } + fz_catch(ctx) { - fz_catch(error, "ignoring broken annotation"); + fz_warn(ctx, "ignoring broken annotation"); continue; } - annot = fz_malloc(sizeof(pdf_annot)); + annot = fz_malloc(ctx, sizeof(pdf_annot)); annot->obj = fz_keep_obj(obj); - annot->rect = pdf_to_rect(rect); + annot->rect = pdf_to_rect(ctx, rect); annot->ap = form; annot->next = NULL; diff --git a/pdf/pdf_cmap.c b/pdf/pdf_cmap.c index 2c5048ae..8ae40fc5 100644 --- a/pdf/pdf_cmap.c +++ b/pdf/pdf_cmap.c @@ -31,11 +31,11 @@ */ pdf_cmap * -pdf_new_cmap(void) +pdf_new_cmap(fz_context *ctx) { pdf_cmap *cmap; - cmap = fz_malloc(sizeof(pdf_cmap)); + cmap = fz_malloc(ctx, sizeof(pdf_cmap)); cmap->refs = 1; strcpy(cmap->cmap_name, ""); @@ -64,28 +64,28 @@ pdf_keep_cmap(pdf_cmap *cmap) } void -pdf_drop_cmap(pdf_cmap *cmap) +pdf_drop_cmap(fz_context *ctx, pdf_cmap *cmap) { if (cmap->refs >= 0) { if (--cmap->refs == 0) { if (cmap->usecmap) - pdf_drop_cmap(cmap->usecmap); - fz_free(cmap->ranges); - fz_free(cmap->table); - fz_free(cmap); + pdf_drop_cmap(ctx, cmap->usecmap); + fz_free(ctx, cmap->ranges); + fz_free(ctx, cmap->table); + fz_free(ctx, cmap); } } } void -pdf_set_usecmap(pdf_cmap *cmap, pdf_cmap *usecmap) +pdf_set_usecmap(fz_context *ctx, pdf_cmap *cmap, pdf_cmap *usecmap) { int i; if (cmap->usecmap) - pdf_drop_cmap(cmap->usecmap); + pdf_drop_cmap(ctx, cmap->usecmap); cmap->usecmap = pdf_keep_cmap(usecmap); if (cmap->codespace_len == 0) @@ -161,11 +161,11 @@ pdf_debug_cmap(pdf_cmap *cmap) * multi-byte encoded strings. */ void -pdf_add_codespace(pdf_cmap *cmap, int low, int high, int n) +pdf_add_codespace(fz_context *ctx, pdf_cmap *cmap, int low, int high, int n) { if (cmap->codespace_len + 1 == nelem(cmap->codespace)) { - fz_warn("assert: too many code space ranges"); + fz_warn(ctx, "assert: too many code space ranges"); return; } @@ -179,17 +179,17 @@ pdf_add_codespace(pdf_cmap *cmap, int low, int high, int n) * Add an integer to the table. */ static void -add_table(pdf_cmap *cmap, int value) +add_table(fz_context *ctx, pdf_cmap *cmap, int value) { if (cmap->tlen == USHRT_MAX) { - fz_warn("cmap table is full; ignoring additional entries"); + fz_warn(ctx, "cmap table is full; ignoring additional entries"); return; } if (cmap->tlen + 1 > cmap->tcap) { cmap->tcap = cmap->tcap > 1 ? (cmap->tcap * 3) / 2 : 256; - cmap->table = fz_realloc(cmap->table, cmap->tcap, sizeof(unsigned short)); + cmap->table = fz_resize_array(ctx, cmap->table, cmap->tcap, sizeof(unsigned short)); } cmap->table[cmap->tlen++] = value; } @@ -198,19 +198,19 @@ add_table(pdf_cmap *cmap, int value) * Add a range. */ static void -add_range(pdf_cmap *cmap, int low, int high, int flag, int offset) +add_range(fz_context *ctx, pdf_cmap *cmap, int low, int high, int flag, int offset) { /* If the range is too large to be represented, split it */ if (high - low > 0x3fff) { - add_range(cmap, low, low+0x3fff, flag, offset); - add_range(cmap, low+0x3fff, high, flag, offset+0x3fff); + add_range(ctx, cmap, low, low+0x3fff, flag, offset); + add_range(ctx, cmap, low+0x3fff, high, flag, offset+0x3fff); return; } if (cmap->rlen + 1 > cmap->rcap) { cmap->rcap = cmap->rcap > 1 ? (cmap->rcap * 3) / 2 : 256; - cmap->ranges = fz_realloc(cmap->ranges, cmap->rcap, sizeof(pdf_range)); + cmap->ranges = fz_resize_array(ctx, cmap->ranges, cmap->rcap, sizeof(pdf_range)); } cmap->ranges[cmap->rlen].low = low; pdf_range_set_high(&cmap->ranges[cmap->rlen], high); @@ -223,18 +223,18 @@ add_range(pdf_cmap *cmap, int low, int high, int flag, int offset) * Add a range-to-table mapping. */ void -pdf_map_range_to_table(pdf_cmap *cmap, int low, int *table, int len) +pdf_map_range_to_table(fz_context *ctx, pdf_cmap *cmap, int low, int *table, int len) { int i; int high = low + len; int offset = cmap->tlen; if (cmap->tlen + len >= USHRT_MAX) - fz_warn("cannot map range to table; table is full"); + fz_warn(ctx, "cannot map range to table; table is full"); else { for (i = 0; i < len; i++) - add_table(cmap, table[i]); - add_range(cmap, low, high, PDF_CMAP_TABLE, offset); + add_table(ctx, cmap, table[i]); + add_range(ctx, cmap, low, high, PDF_CMAP_TABLE, offset); } } @@ -242,28 +242,28 @@ pdf_map_range_to_table(pdf_cmap *cmap, int low, int *table, int len) * Add a range of contiguous one-to-one mappings (ie 1..5 maps to 21..25) */ void -pdf_map_range_to_range(pdf_cmap *cmap, int low, int high, int offset) +pdf_map_range_to_range(fz_context *ctx, pdf_cmap *cmap, int low, int high, int offset) { - add_range(cmap, low, high, high - low == 0 ? PDF_CMAP_SINGLE : PDF_CMAP_RANGE, offset); + add_range(ctx, cmap, low, high, high - low == 0 ? PDF_CMAP_SINGLE : PDF_CMAP_RANGE, offset); } /* * Add a single one-to-many mapping. */ void -pdf_map_one_to_many(pdf_cmap *cmap, int low, int *values, int len) +pdf_map_one_to_many(fz_context *ctx, pdf_cmap *cmap, int low, int *values, int len) { int offset, i; if (len == 1) { - add_range(cmap, low, low, PDF_CMAP_SINGLE, values[0]); + add_range(ctx, cmap, low, low, PDF_CMAP_SINGLE, values[0]); return; } if (len > 8) { - fz_warn("one to many mapping is too large (%d); truncating", len); + fz_warn(ctx, "one to many mapping is too large (%d); truncating", len); len = 8; } @@ -271,19 +271,19 @@ pdf_map_one_to_many(pdf_cmap *cmap, int low, int *values, int len) values[0] >= 0xD800 && values[0] <= 0xDBFF && values[1] >= 0xDC00 && values[1] <= 0xDFFF) { - fz_warn("ignoring surrogate pair mapping in cmap"); + fz_warn(ctx, "ignoring surrogate pair mapping in cmap"); return; } if (cmap->tlen + len + 1 >= USHRT_MAX) - fz_warn("cannot map one to many; table is full"); + fz_warn(ctx, "cannot map one to many; table is full"); else { offset = cmap->tlen; - add_table(cmap, len); + add_table(ctx, cmap, len); for (i = 0; i < len; i++) - add_table(cmap, values[i]); - add_range(cmap, low, low, PDF_CMAP_MULTI, offset); + add_table(ctx, cmap, values[i]); + add_range(ctx, cmap, low, low, PDF_CMAP_MULTI, offset); } } @@ -299,7 +299,7 @@ static int cmprange(const void *va, const void *vb) } void -pdf_sort_cmap(pdf_cmap *cmap) +pdf_sort_cmap(fz_context *ctx, pdf_cmap *cmap) { pdf_range *a; /* last written range on output */ pdf_range *b; /* current range examined on input */ @@ -311,7 +311,7 @@ pdf_sort_cmap(pdf_cmap *cmap) if (cmap->tlen == USHRT_MAX) { - fz_warn("cmap table is full; will not combine ranges"); + fz_warn(ctx, "cmap table is full; will not combine ranges"); return; } @@ -343,7 +343,7 @@ pdf_sort_cmap(pdf_cmap *cmap) else if (pdf_range_flags(a) == PDF_CMAP_TABLE && pdf_range_flags(b) == PDF_CMAP_SINGLE && (pdf_range_high(b) - a->low <= 0x3fff)) { pdf_range_set_high(a, pdf_range_high(b)); - add_table(cmap, b->offset); + add_table(ctx, cmap, b->offset); } /* LR -> LR */ @@ -367,8 +367,8 @@ pdf_sort_cmap(pdf_cmap *cmap) { pdf_range_set_flags(a, PDF_CMAP_TABLE); pdf_range_set_high(a, pdf_range_high(b)); - add_table(cmap, a->offset); - add_table(cmap, b->offset); + add_table(ctx, cmap, a->offset); + add_table(ctx, cmap, b->offset); a->offset = cmap->tlen - 2; } @@ -376,7 +376,7 @@ pdf_sort_cmap(pdf_cmap *cmap) else if (pdf_range_flags(a) == PDF_CMAP_TABLE && pdf_range_flags(b) == PDF_CMAP_SINGLE && (pdf_range_high(b) - a->low <= 0x3fff)) { pdf_range_set_high(a, pdf_range_high(b)); - add_table(cmap, b->offset); + add_table(ctx, cmap, b->offset); } /* XX -> XX */ @@ -398,7 +398,7 @@ pdf_sort_cmap(pdf_cmap *cmap) cmap->rlen = a - cmap->ranges + 1; - fz_flush_warnings(); + fz_flush_warnings(ctx); } /* diff --git a/pdf/pdf_cmap_load.c b/pdf/pdf_cmap_load.c index 12adeb40..15bd8406 100644 --- a/pdf/pdf_cmap_load.c +++ b/pdf/pdf_cmap_load.c @@ -4,8 +4,8 @@ /* * Load CMap stream in PDF file */ -fz_error -pdf_load_embedded_cmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmobj) +pdf_cmap * +pdf_load_embedded_cmap(pdf_xref *xref, fz_obj *stmobj) { fz_error error = fz_okay; fz_stream *file = NULL; @@ -13,81 +13,75 @@ pdf_load_embedded_cmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmobj) pdf_cmap *usecmap; fz_obj *wmode; fz_obj *obj; + fz_context *ctx = xref->ctx; + volatile int phase = 0; - if ((*cmapp = pdf_find_item(xref->store, pdf_drop_cmap, stmobj))) + if ((cmap = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_cmap, stmobj))) { - pdf_keep_cmap(*cmapp); - return fz_okay; + pdf_keep_cmap(cmap); + return cmap; } - error = pdf_open_stream(&file, xref, fz_to_num(stmobj), fz_to_gen(stmobj)); - if (error) + fz_try(ctx) { - error = fz_rethrow(error, "cannot open cmap stream (%d %d R)", fz_to_num(stmobj), fz_to_gen(stmobj)); - goto cleanup; - } - - error = pdf_parse_cmap(&cmap, file); - if (error) - { - error = fz_rethrow(error, "cannot parse cmap stream (%d %d R)", fz_to_num(stmobj), fz_to_gen(stmobj)); - goto cleanup; - } - fz_close(file); - - wmode = fz_dict_gets(stmobj, "WMode"); - if (fz_is_int(wmode)) - pdf_set_wmode(cmap, fz_to_int(wmode)); + file = pdf_open_stream(xref, fz_to_num(stmobj), fz_to_gen(stmobj)); + phase = 1; + cmap = pdf_parse_cmap(file); + phase = 2; + fz_close(file); + file = NULL; - obj = fz_dict_gets(stmobj, "UseCMap"); - if (fz_is_name(obj)) - { - error = pdf_load_system_cmap(&usecmap, fz_to_name(obj)); - if (error) + wmode = fz_dict_gets(stmobj, "WMode"); + if (fz_is_int(wmode)) + pdf_set_wmode(cmap, fz_to_int(wmode)); + obj = fz_dict_gets(stmobj, "UseCMap"); + if (fz_is_name(obj)) { - error = fz_rethrow(error, "cannot load system usecmap '%s'", fz_to_name(obj)); - goto cleanup; + usecmap = pdf_load_system_cmap(ctx, fz_to_name(obj)); + pdf_set_usecmap(ctx, cmap, usecmap); + pdf_drop_cmap(ctx, usecmap); } - pdf_set_usecmap(cmap, usecmap); - pdf_drop_cmap(usecmap); - } - else if (fz_is_indirect(obj)) - { - error = pdf_load_embedded_cmap(&usecmap, xref, obj); - if (error) + else if (fz_is_indirect(obj)) { - error = fz_rethrow(error, "cannot load embedded usecmap (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); - goto cleanup; + phase = 3; + usecmap = pdf_load_embedded_cmap(xref, obj); + pdf_set_usecmap(ctx, cmap, usecmap); + pdf_drop_cmap(ctx, usecmap); } - pdf_set_usecmap(cmap, usecmap); - pdf_drop_cmap(usecmap); - } - - pdf_store_item(xref->store, pdf_keep_cmap, pdf_drop_cmap, stmobj, cmap); - *cmapp = cmap; - return fz_okay; + pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)pdf_keep_cmap, (pdf_store_drop_fn *)pdf_drop_cmap, stmobj, cmap); + } + fz_catch(ctx) + { + if (file) + fz_close(file); + if (cmap) + pdf_drop_cmap(ctx, cmap); + if (phase < 1) + fz_throw(ctx, "cannot open cmap stream (%d %d R)", fz_to_num(stmobj), fz_to_gen(stmobj)); + else if (phase < 2) + fz_throw(ctx, "cannot parse cmap stream (%d %d R)", fz_to_num(stmobj), fz_to_gen(stmobj)); + else if (phase < 3) + fz_throw(ctx, "cannot load system usecmap '%s'", fz_to_name(obj)); + else + fz_throw(ctx, "cannot load embedded usecmap (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); + } -cleanup: - if (file) - fz_close(file); - if (cmap) - pdf_drop_cmap(cmap); - return error; /* already rethrown */ + return cmap; } /* * Create an Identity-* CMap (for both 1 and 2-byte encodings) */ pdf_cmap * -pdf_new_identity_cmap(int wmode, int bytes) +pdf_new_identity_cmap(fz_context *ctx, int wmode, int bytes) { - pdf_cmap *cmap = pdf_new_cmap(); + pdf_cmap *cmap = pdf_new_cmap(ctx); sprintf(cmap->cmap_name, "Identity-%c", wmode ? 'V' : 'H'); - pdf_add_codespace(cmap, 0x0000, 0xffff, bytes); - pdf_map_range_to_range(cmap, 0x0000, 0xffff, 0); - pdf_sort_cmap(cmap); + pdf_add_codespace(ctx, cmap, 0x0000, 0xffff, bytes); + pdf_map_range_to_range(ctx, cmap, 0x0000, 0xffff, 0); + pdf_sort_cmap(ctx, cmap); pdf_set_wmode(cmap, wmode); return cmap; } @@ -95,24 +89,23 @@ pdf_new_identity_cmap(int wmode, int bytes) /* * Load predefined CMap from system. */ -fz_error -pdf_load_system_cmap(pdf_cmap **cmapp, char *cmap_name) +pdf_cmap * +pdf_load_system_cmap(fz_context *ctx, char *cmap_name) { pdf_cmap *usecmap; pdf_cmap *cmap; cmap = pdf_find_builtin_cmap(cmap_name); if (!cmap) - return fz_throw("no builtin cmap file: %s", cmap_name); + fz_throw(ctx, "no builtin cmap file: %s", cmap_name); if (cmap->usecmap_name[0] && !cmap->usecmap) { usecmap = pdf_find_builtin_cmap(cmap->usecmap_name); if (!usecmap) - return fz_throw("nu builtin cmap file: %s", cmap->usecmap_name); - pdf_set_usecmap(cmap, usecmap); + fz_throw(ctx, "nu builtin cmap file: %s", cmap->usecmap_name); + pdf_set_usecmap(ctx, cmap, usecmap); } - *cmapp = cmap; - return fz_okay; + return cmap; } diff --git a/pdf/pdf_cmap_parse.c b/pdf/pdf_cmap_parse.c index edd97de8..4dcc76c5 100644 --- a/pdf/pdf_cmap_parse.c +++ b/pdf/pdf_cmap_parse.c @@ -48,65 +48,54 @@ pdf_code_from_string(char *buf, int len) return a; } -static fz_error -pdf_lex_cmap(int *tok, fz_stream *file, char *buf, int n, int *sl) +static int +pdf_lex_cmap(fz_stream *file, char *buf, int n, int *sl) { - fz_error error; + int tok = pdf_lex(file, buf, n, sl); - error = pdf_lex(tok, file, buf, n, sl); - if (error) - return fz_rethrow(error, "cannot parse cmap token"); + /* RJW: Lost debugging here: "cannot parse cmap token" */ - if (*tok == PDF_TOK_KEYWORD) - *tok = pdf_cmap_token_from_keyword(buf); + if (tok == PDF_TOK_KEYWORD) + tok = pdf_cmap_token_from_keyword(buf); - return fz_okay; + return tok; } -static fz_error +static void pdf_parse_cmap_name(pdf_cmap *cmap, fz_stream *file) { - fz_error error; char buf[256]; int tok; int len; - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: Lost debugging: "syntaxerror in cmap" */ if (tok == PDF_TOK_NAME) fz_strlcpy(cmap->cmap_name, buf, sizeof(cmap->cmap_name)); else - fz_warn("expected name after CMapName in cmap"); - - return fz_okay; + fz_warn(file->ctx, "expected name after CMapName in cmap"); } -static fz_error +static void pdf_parse_wmode(pdf_cmap *cmap, fz_stream *file) { - fz_error error; char buf[256]; int tok; int len; - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: Lost debugging: "syntaxerror in cmap" */ if (tok == PDF_TOK_INT) pdf_set_wmode(cmap, atoi(buf)); else - fz_warn("expected integer after WMode in cmap"); - - return fz_okay; + fz_warn(file->ctx, "expected integer after WMode in cmap"); } -static fz_error +static void pdf_parse_codespace_range(pdf_cmap *cmap, fz_stream *file) { - fz_error error; char buf[256]; int tok; int len; @@ -114,23 +103,21 @@ pdf_parse_codespace_range(pdf_cmap *cmap, fz_stream *file) while (1) { - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: Lost debugging: "syntaxerror in cmap" */ if (tok == TOK_END_CODESPACE_RANGE) - return fz_okay; + return; else if (tok == PDF_TOK_STRING) { lo = pdf_code_from_string(buf, len); - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: Lost debugging: "syntaxerror in cmap" */ if (tok == PDF_TOK_STRING) { hi = pdf_code_from_string(buf, len); - pdf_add_codespace(cmap, lo, hi, len); + pdf_add_codespace(file->ctx, cmap, lo, hi, len); } else break; } @@ -138,13 +125,12 @@ pdf_parse_codespace_range(pdf_cmap *cmap, fz_stream *file) else break; } - return fz_throw("expected string or endcodespacerange"); + fz_throw(file->ctx, "expected string or endcodespacerange"); } -static fz_error +static void pdf_parse_cid_range(pdf_cmap *cmap, fz_stream *file) { - fz_error error; char buf[256]; int tok; int len; @@ -152,42 +138,38 @@ pdf_parse_cid_range(pdf_cmap *cmap, fz_stream *file) while (1) { - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: Lost debugging: "syntaxerror in cmap" */ if (tok == TOK_END_CID_RANGE) - return fz_okay; + return; else if (tok != PDF_TOK_STRING) - return fz_throw("expected string or endcidrange"); + fz_throw(file->ctx, "expected string or endcidrange"); lo = pdf_code_from_string(buf, len); - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: Lost debugging: "syntaxerror in cmap" */ if (tok != PDF_TOK_STRING) - return fz_throw("expected string"); + fz_throw(file->ctx, "expected string"); hi = pdf_code_from_string(buf, len); - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: Lost debugging: "syntaxerror in cmap" */ if (tok != PDF_TOK_INT) - return fz_throw("expected integer"); + fz_throw(file->ctx, "expected integer"); dst = atoi(buf); - pdf_map_range_to_range(cmap, lo, hi, dst); + pdf_map_range_to_range(file->ctx, cmap, lo, hi, dst); } } -static fz_error +static void pdf_parse_cid_char(pdf_cmap *cmap, fz_stream *file) { - fz_error error; char buf[256]; int tok; int len; @@ -195,34 +177,32 @@ pdf_parse_cid_char(pdf_cmap *cmap, fz_stream *file) while (1) { - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: "syntaxerror in cmap" */ if (tok == TOK_END_CID_CHAR) - return fz_okay; + return; else if (tok != PDF_TOK_STRING) - return fz_throw("expected string or endcidchar"); + fz_throw(file->ctx, "expected string or endcidchar"); src = pdf_code_from_string(buf, len); - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: "syntaxerror in cmap" */ + if (tok != PDF_TOK_INT) - return fz_throw("expected integer"); + fz_throw(file->ctx, "expected integer"); dst = atoi(buf); - pdf_map_range_to_range(cmap, src, src, dst); + pdf_map_range_to_range(file->ctx, cmap, src, src, dst); } } -static fz_error +static void pdf_parse_bf_range_array(pdf_cmap *cmap, fz_stream *file, int lo, int hi) { - fz_error error; char buf[256]; int tok; int len; @@ -231,33 +211,31 @@ pdf_parse_bf_range_array(pdf_cmap *cmap, fz_stream *file, int lo, int hi) while (1) { - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: "syntaxerror in cmap" */ if (tok == PDF_TOK_CLOSE_ARRAY) - return fz_okay; + return; /* Note: does not handle [ /Name /Name ... ] */ else if (tok != PDF_TOK_STRING) - return fz_throw("expected string or ]"); + fz_throw(file->ctx, "expected string or ]"); if (len / 2) { for (i = 0; i < len / 2; i++) dst[i] = pdf_code_from_string(buf + i * 2, 2); - pdf_map_one_to_many(cmap, lo, dst, len / 2); + pdf_map_one_to_many(file->ctx, cmap, lo, dst, len / 2); } lo ++; } } -static fz_error +static void pdf_parse_bf_range(pdf_cmap *cmap, fz_stream *file) { - fz_error error; char buf[256]; int tok; int len; @@ -265,36 +243,33 @@ pdf_parse_bf_range(pdf_cmap *cmap, fz_stream *file) while (1) { - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: "syntaxerror in cmap" */ if (tok == TOK_END_BF_RANGE) - return fz_okay; + return; else if (tok != PDF_TOK_STRING) - return fz_throw("expected string or endbfrange"); + fz_throw(file->ctx, "expected string or endbfrange"); lo = pdf_code_from_string(buf, len); - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: "syntaxerror in cmap" */ if (tok != PDF_TOK_STRING) - return fz_throw("expected string"); + fz_throw(file->ctx, "expected string"); hi = pdf_code_from_string(buf, len); - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: "syntaxerror in cmap" */ if (tok == PDF_TOK_STRING) { if (len == 2) { dst = pdf_code_from_string(buf, len); - pdf_map_range_to_range(cmap, lo, hi, dst); + pdf_map_range_to_range(file->ctx, cmap, lo, hi, dst); } else { @@ -309,7 +284,7 @@ pdf_parse_bf_range(pdf_cmap *cmap, fz_stream *file) while (lo <= hi) { dststr[i-1] ++; - pdf_map_one_to_many(cmap, lo, dststr, i); + pdf_map_one_to_many(file->ctx, cmap, lo, dststr, i); lo ++; } } @@ -318,22 +293,20 @@ pdf_parse_bf_range(pdf_cmap *cmap, fz_stream *file) else if (tok == PDF_TOK_OPEN_ARRAY) { - error = pdf_parse_bf_range_array(cmap, file, lo, hi); - if (error) - return fz_rethrow(error, "cannot map bfrange"); + pdf_parse_bf_range_array(cmap, file, lo, hi); + /* RJW: "cannot map bfrange" */ } else { - return fz_throw("expected string or array or endbfrange"); + fz_throw(file->ctx, "expected string or array or endbfrange"); } } } -static fz_error +static void pdf_parse_bf_char(pdf_cmap *cmap, fz_stream *file) { - fz_error error; char buf[256]; int tok; int len; @@ -343,148 +316,118 @@ pdf_parse_bf_char(pdf_cmap *cmap, fz_stream *file) while (1) { - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: "syntaxerror in cmap" */ if (tok == TOK_END_BF_CHAR) - return fz_okay; + return; else if (tok != PDF_TOK_STRING) - return fz_throw("expected string or endbfchar"); + fz_throw(file->ctx, "expected string or endbfchar"); src = pdf_code_from_string(buf, len); - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "syntaxerror in cmap"); + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); + /* RJW: "syntaxerror in cmap" */ /* Note: does not handle /dstName */ if (tok != PDF_TOK_STRING) - return fz_throw("expected string"); + fz_throw(file->ctx, "expected string"); if (len / 2) { for (i = 0; i < len / 2; i++) dst[i] = pdf_code_from_string(buf + i * 2, 2); - pdf_map_one_to_many(cmap, src, dst, i); + pdf_map_one_to_many(file->ctx, cmap, src, dst, i); } } } -fz_error -pdf_parse_cmap(pdf_cmap **cmapp, fz_stream *file) +pdf_cmap * +pdf_parse_cmap(fz_stream *file) { - fz_error error; pdf_cmap *cmap; char key[64]; char buf[256]; int tok; int len; + const char *where; + fz_context *ctx = file->ctx; - cmap = pdf_new_cmap(); + cmap = pdf_new_cmap(ctx); strcpy(key, ".notdef"); - while (1) + fz_try(ctx) { - error = pdf_lex_cmap(&tok, file, buf, sizeof buf, &len); - if (error) + while (1) { - error = fz_rethrow(error, "syntaxerror in cmap"); - goto cleanup; - } + where = ""; + tok = pdf_lex_cmap(file, buf, sizeof buf, &len); - if (tok == PDF_TOK_EOF || tok == TOK_END_CMAP) - break; + if (tok == PDF_TOK_EOF || tok == TOK_END_CMAP) + break; - else if (tok == PDF_TOK_NAME) - { - if (!strcmp(buf, "CMapName")) + else if (tok == PDF_TOK_NAME) { - error = pdf_parse_cmap_name(cmap, file); - if (error) + if (!strcmp(buf, "CMapName")) { - error = fz_rethrow(error, "syntaxerror in cmap after CMapName"); - goto cleanup; + where = " after CMapName"; + pdf_parse_cmap_name(cmap, file); } - } - else if (!strcmp(buf, "WMode")) - { - error = pdf_parse_wmode(cmap, file); - if (error) + else if (!strcmp(buf, "WMode")) { - error = fz_rethrow(error, "syntaxerror in cmap after WMode"); - goto cleanup; + where = " after WMode"; + pdf_parse_wmode(cmap, file); } + else + fz_strlcpy(key, buf, sizeof key); } - else - fz_strlcpy(key, buf, sizeof key); - } - else if (tok == TOK_USECMAP) - { - fz_strlcpy(cmap->usecmap_name, key, sizeof(cmap->usecmap_name)); - } + else if (tok == TOK_USECMAP) + { + fz_strlcpy(cmap->usecmap_name, key, sizeof(cmap->usecmap_name)); + } - else if (tok == TOK_BEGIN_CODESPACE_RANGE) - { - error = pdf_parse_codespace_range(cmap, file); - if (error) + else if (tok == TOK_BEGIN_CODESPACE_RANGE) { - error = fz_rethrow(error, "syntaxerror in cmap codespacerange"); - goto cleanup; + where = " codespacerange"; + pdf_parse_codespace_range(cmap, file); } - } - else if (tok == TOK_BEGIN_BF_CHAR) - { - error = pdf_parse_bf_char(cmap, file); - if (error) + else if (tok == TOK_BEGIN_BF_CHAR) { - error = fz_rethrow(error, "syntaxerror in cmap bfchar"); - goto cleanup; + where = " bfchar"; + pdf_parse_bf_char(cmap, file); } - } - else if (tok == TOK_BEGIN_CID_CHAR) - { - error = pdf_parse_cid_char(cmap, file); - if (error) + else if (tok == TOK_BEGIN_CID_CHAR) { - error = fz_rethrow(error, "syntaxerror in cmap cidchar"); - goto cleanup; + where = " cidchar"; + pdf_parse_cid_char(cmap, file); } - } - else if (tok == TOK_BEGIN_BF_RANGE) - { - error = pdf_parse_bf_range(cmap, file); - if (error) + else if (tok == TOK_BEGIN_BF_RANGE) { - error = fz_rethrow(error, "syntaxerror in cmap bfrange"); - goto cleanup; + where = " bfrange"; + pdf_parse_bf_range(cmap, file); } - } - else if (tok == TOK_BEGIN_CID_RANGE) - { - error = pdf_parse_cid_range(cmap, file); - if (error) + else if (tok == TOK_BEGIN_CID_RANGE) { - error = fz_rethrow(error, "syntaxerror in cmap cidrange"); - goto cleanup; + where = "cidrange"; + pdf_parse_cid_range(cmap, file); } + + /* ignore everything else */ } - /* ignore everything else */ + pdf_sort_cmap(file->ctx, cmap); + } + fz_catch(ctx) + { + pdf_drop_cmap(file->ctx, cmap); + fz_throw(ctx, "syntaxerror in cmap%s", where); } - pdf_sort_cmap(cmap); - - *cmapp = cmap; - return fz_okay; - -cleanup: - pdf_drop_cmap(cmap); - return error; /* already rethrown */ + return cmap; } diff --git a/pdf/pdf_colorspace.c b/pdf/pdf_colorspace.c index b7ea51a3..c386b34c 100644 --- a/pdf/pdf_colorspace.c +++ b/pdf/pdf_colorspace.c @@ -3,8 +3,8 @@ /* ICCBased */ -static fz_error -load_icc_based(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict) +static fz_colorspace * +load_icc_based(pdf_xref *xref, fz_obj *dict) { int n; @@ -12,12 +12,13 @@ load_icc_based(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict) switch (n) { - case 1: *csp = fz_device_gray; return fz_okay; - case 3: *csp = fz_device_rgb; return fz_okay; - case 4: *csp = fz_device_cmyk; return fz_okay; + case 1: return fz_device_gray; + case 3: return fz_device_rgb; + case 4: return fz_device_cmyk; } - return fz_throw("syntaxerror: ICCBased must have 1, 3 or 4 components"); + fz_throw(xref->ctx, "syntaxerror: ICCBased must have 1, 3 or 4 components"); + return NULL; /* Stupid MSVC */ } /* Lab */ @@ -30,7 +31,7 @@ static inline float fung(float x) } static void -lab_to_rgb(fz_colorspace *cs, float *lab, float *rgb) +lab_to_rgb(fz_context *ctx, fz_colorspace *cs, float *lab, float *rgb) { /* input is in range (0..100, -128..127, -128..127) not (0..1, 0..1, 0..1) */ float lstar, astar, bstar, l, m, n, x, y, z, r, g, b; @@ -52,9 +53,9 @@ lab_to_rgb(fz_colorspace *cs, float *lab, float *rgb) } static void -rgb_to_lab(fz_colorspace *cs, float *rgb, float *lab) +rgb_to_lab(fz_context *ctx, fz_colorspace *cs, float *rgb, float *lab) { - fz_warn("cannot convert into L*a*b colorspace"); + fz_warn(ctx, "cannot convert into L*a*b colorspace"); lab[0] = rgb[0]; lab[1] = rgb[1]; lab[2] = rgb[2]; @@ -72,29 +73,29 @@ struct separation }; static void -separation_to_rgb(fz_colorspace *cs, float *color, float *rgb) +separation_to_rgb(fz_context *ctx, fz_colorspace *cs, float *color, float *rgb) { struct separation *sep = cs->data; float alt[FZ_MAX_COLORS]; - pdf_eval_function(sep->tint, color, cs->n, alt, sep->base->n); - sep->base->to_rgb(sep->base, alt, rgb); + pdf_eval_function(ctx, sep->tint, color, cs->n, alt, sep->base->n); + sep->base->to_rgb(ctx, sep->base, alt, rgb); } static void -free_separation(fz_colorspace *cs) +free_separation(fz_context *ctx, fz_colorspace *cs) { struct separation *sep = cs->data; - fz_drop_colorspace(sep->base); - pdf_drop_function(sep->tint); - fz_free(sep); + fz_drop_colorspace(ctx, sep->base); + pdf_drop_function(ctx, sep->tint); + fz_free(ctx, sep); } -static fz_error -load_separation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) +static fz_colorspace * +load_separation(pdf_xref *xref, fz_obj *array) { - fz_error error; fz_colorspace *cs; struct separation *sep; + fz_context *ctx = xref->ctx; fz_obj *nameobj = fz_array_get(array, 1); fz_obj *baseobj = fz_array_get(array, 2); fz_obj *tintobj = fz_array_get(array, 3); @@ -108,30 +109,25 @@ load_separation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) n = 1; if (n > FZ_MAX_COLORS) - return fz_throw("too many components in colorspace"); + fz_throw(ctx, "too many components in colorspace"); - error = pdf_load_colorspace(&base, xref, baseobj); - if (error) - return fz_rethrow(error, "cannot load base colorspace (%d %d R)", fz_to_num(baseobj), fz_to_gen(baseobj)); + base = pdf_load_colorspace(xref, baseobj); + /* RJW: "cannot load base colorspace (%d %d R)", fz_to_num(baseobj), fz_to_gen(baseobj) */ - error = pdf_load_function(&tint, xref, tintobj); - if (error) - { - fz_drop_colorspace(base); - return fz_rethrow(error, "cannot load tint function (%d %d R)", fz_to_num(tintobj), fz_to_gen(tintobj)); - } + tint = pdf_load_function(xref, tintobj); + /* RJW: fz_drop_colorspace(ctx, base); + * "cannot load tint function (%d %d R)", fz_to_num(tintobj), fz_to_gen(tintobj) */ - sep = fz_malloc(sizeof(struct separation)); + sep = fz_malloc(ctx, sizeof(struct separation)); sep->base = base; sep->tint = tint; - cs = fz_new_colorspace(n == 1 ? "Separation" : "DeviceN", n); + cs = fz_new_colorspace(ctx, n == 1 ? "Separation" : "DeviceN", n); cs->to_rgb = separation_to_rgb; cs->free_data = free_separation; cs->data = sep; - *csp = cs; - return fz_okay; + return cs; } /* Indexed */ @@ -144,7 +140,7 @@ struct indexed }; static void -indexed_to_rgb(fz_colorspace *cs, float *color, float *rgb) +indexed_to_rgb(fz_context *ctx, fz_colorspace *cs, float *color, float *rgb) { struct indexed *idx = cs->data; float alt[FZ_MAX_COLORS]; @@ -153,21 +149,21 @@ indexed_to_rgb(fz_colorspace *cs, float *color, float *rgb) i = CLAMP(i, 0, idx->high); for (k = 0; k < idx->base->n; k++) alt[k] = idx->lookup[i * idx->base->n + k] / 255.0f; - idx->base->to_rgb(idx->base, alt, rgb); + idx->base->to_rgb(ctx, idx->base, alt, rgb); } static void -free_indexed(fz_colorspace *cs) +free_indexed(fz_context *ctx, fz_colorspace *cs) { struct indexed *idx = cs->data; if (idx->base) - fz_drop_colorspace(idx->base); - fz_free(idx->lookup); - fz_free(idx); + fz_drop_colorspace(ctx, idx->base); + fz_free(ctx, idx->lookup); + fz_free(ctx, idx); } fz_pixmap * -pdf_expand_indexed_pixmap(fz_pixmap *src) +pdf_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src) { struct indexed *idx; fz_pixmap *dst; @@ -183,7 +179,7 @@ pdf_expand_indexed_pixmap(fz_pixmap *src) lookup = idx->lookup; n = idx->base->n; - dst = fz_new_pixmap_with_rect(idx->base, fz_bound_pixmap(src)); + dst = fz_new_pixmap_with_rect(ctx, idx->base, fz_bound_pixmap(src)); s = src->samples; d = dst->samples; @@ -207,31 +203,28 @@ pdf_expand_indexed_pixmap(fz_pixmap *src) return dst; } -static fz_error -load_indexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) +static fz_colorspace * +load_indexed(pdf_xref *xref, fz_obj *array) { - fz_error error; - fz_colorspace *cs; struct indexed *idx; + fz_context *ctx = xref->ctx; fz_obj *baseobj = fz_array_get(array, 1); fz_obj *highobj = fz_array_get(array, 2); fz_obj *lookup = fz_array_get(array, 3); - fz_colorspace *base; + fz_colorspace *base, *cs; int i, n; - error = pdf_load_colorspace(&base, xref, baseobj); - if (error) - return fz_rethrow(error, "cannot load base colorspace (%d %d R)", fz_to_num(baseobj), fz_to_gen(baseobj)); + base = pdf_load_colorspace(xref, baseobj); + /* "cannot load base colorspace (%d %d R)", fz_to_num(baseobj), fz_to_gen(baseobj) */ - idx = fz_malloc(sizeof(struct indexed)); + idx = fz_malloc(ctx, sizeof(struct indexed)); idx->base = base; idx->high = fz_to_int(highobj); idx->high = CLAMP(idx->high, 0, 255); n = base->n * (idx->high + 1); - idx->lookup = fz_malloc(n); - memset(idx->lookup, 0, n); + idx->lookup = fz_malloc_array(ctx, 1, n); - cs = fz_new_colorspace("Indexed", 1); + cs = fz_new_colorspace(ctx, "Indexed", 1); cs->to_rgb = indexed_to_rgb; cs->free_data = free_indexed; cs->data = idx; @@ -246,56 +239,57 @@ load_indexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) { fz_stream *file; - error = pdf_open_stream(&file, xref, fz_to_num(lookup), fz_to_gen(lookup)); - if (error) + fz_try(ctx) { - fz_drop_colorspace(cs); - return fz_rethrow(error, "cannot open colorspace lookup table (%d 0 R)", fz_to_num(lookup)); + file = pdf_open_stream(xref, fz_to_num(lookup), fz_to_gen(lookup)); + } + fz_catch(ctx) + { + fz_drop_colorspace(ctx, cs); + fz_throw(ctx, "cannot open colorspace lookup table (%d 0 R)", fz_to_num(lookup)); } i = fz_read(file, idx->lookup, n); if (i < 0) { - fz_drop_colorspace(cs); - return fz_throw("cannot read colorspace lookup table (%d 0 R)", fz_to_num(lookup)); + fz_drop_colorspace(ctx, cs); + fz_throw(ctx, "cannot read colorspace lookup table (%d 0 R)", fz_to_num(lookup)); } fz_close(file); } else { - fz_drop_colorspace(cs); - return fz_throw("cannot parse colorspace lookup table"); + fz_drop_colorspace(ctx, cs); + fz_throw(ctx, "cannot parse colorspace lookup table"); } - *csp = cs; - return fz_okay; + return cs; } /* Parse and create colorspace from PDF object */ -static fz_error -pdf_load_colorspace_imp(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj) +static fz_colorspace * +pdf_load_colorspace_imp(pdf_xref *xref, fz_obj *obj) { if (fz_is_name(obj)) { if (!strcmp(fz_to_name(obj), "Pattern")) - *csp = fz_device_gray; + return fz_device_gray; else if (!strcmp(fz_to_name(obj), "G")) - *csp = fz_device_gray; + return fz_device_gray; else if (!strcmp(fz_to_name(obj), "RGB")) - *csp = fz_device_rgb; + return fz_device_rgb; else if (!strcmp(fz_to_name(obj), "CMYK")) - *csp = fz_device_cmyk; + return fz_device_cmyk; else if (!strcmp(fz_to_name(obj), "DeviceGray")) - *csp = fz_device_gray; + return fz_device_gray; else if (!strcmp(fz_to_name(obj), "DeviceRGB")) - *csp = fz_device_rgb; + return fz_device_rgb; else if (!strcmp(fz_to_name(obj), "DeviceCMYK")) - *csp = fz_device_cmyk; + return fz_device_cmyk; else - return fz_throw("unknown colorspace: %s", fz_to_name(obj)); - return fz_okay; + fz_throw(xref->ctx, "unknown colorspace: %s", fz_to_name(obj)); } else if (fz_is_array(obj)) @@ -307,81 +301,75 @@ pdf_load_colorspace_imp(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj) /* load base colorspace instead */ if (!strcmp(fz_to_name(name), "Pattern")) { - fz_error error; - obj = fz_array_get(obj, 1); if (!obj) { - *csp = fz_device_gray; - return fz_okay; + return fz_device_gray; } - error = pdf_load_colorspace(csp, xref, obj); - if (error) - return fz_rethrow(error, "cannot load pattern (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); + return pdf_load_colorspace(xref, obj); + /* RJW: "cannot load pattern (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */ } else if (!strcmp(fz_to_name(name), "G")) - *csp = fz_device_gray; + return fz_device_gray; else if (!strcmp(fz_to_name(name), "RGB")) - *csp = fz_device_rgb; + return fz_device_rgb; else if (!strcmp(fz_to_name(name), "CMYK")) - *csp = fz_device_cmyk; + return fz_device_cmyk; else if (!strcmp(fz_to_name(name), "DeviceGray")) - *csp = fz_device_gray; + return fz_device_gray; else if (!strcmp(fz_to_name(name), "DeviceRGB")) - *csp = fz_device_rgb; + return fz_device_rgb; else if (!strcmp(fz_to_name(name), "DeviceCMYK")) - *csp = fz_device_cmyk; + return fz_device_cmyk; else if (!strcmp(fz_to_name(name), "CalGray")) - *csp = fz_device_gray; + return fz_device_gray; else if (!strcmp(fz_to_name(name), "CalRGB")) - *csp = fz_device_rgb; + return fz_device_rgb; else if (!strcmp(fz_to_name(name), "CalCMYK")) - *csp = fz_device_cmyk; + return fz_device_cmyk; else if (!strcmp(fz_to_name(name), "Lab")) - *csp = fz_device_lab; + return fz_device_lab; else if (!strcmp(fz_to_name(name), "ICCBased")) - return load_icc_based(csp, xref, fz_array_get(obj, 1)); + return load_icc_based(xref, fz_array_get(obj, 1)); else if (!strcmp(fz_to_name(name), "Indexed")) - return load_indexed(csp, xref, obj); + return load_indexed(xref, obj); else if (!strcmp(fz_to_name(name), "I")) - return load_indexed(csp, xref, obj); + return load_indexed(xref, obj); else if (!strcmp(fz_to_name(name), "Separation")) - return load_separation(csp, xref, obj); + return load_separation(xref, obj); else if (!strcmp(fz_to_name(name), "DeviceN")) - return load_separation(csp, xref, obj); + return load_separation(xref, obj); else - return fz_throw("syntaxerror: unknown colorspace %s", fz_to_name(name)); - - return fz_okay; + fz_throw(xref->ctx, "syntaxerror: unknown colorspace %s", fz_to_name(name)); } } - return fz_throw("syntaxerror: could not parse color space (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); + fz_throw(xref->ctx, "syntaxerror: could not parse color space (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); + return NULL; /* Stupid MSVC */ } -fz_error -pdf_load_colorspace(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj) +fz_colorspace * +pdf_load_colorspace(pdf_xref *xref, fz_obj *obj) { - fz_error error; + fz_context *ctx = xref->ctx; + fz_colorspace *cs; - if ((*csp = pdf_find_item(xref->store, fz_drop_colorspace, obj))) + if ((cs = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)fz_drop_colorspace, obj))) { - fz_keep_colorspace(*csp); - return fz_okay; + return fz_keep_colorspace(cs); } - error = pdf_load_colorspace_imp(csp, xref, obj); - if (error) - return fz_rethrow(error, "cannot load colorspace (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); + cs = pdf_load_colorspace_imp(xref, obj); + /* RJW: "cannot load colorspace (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */ - pdf_store_item(xref->store, fz_keep_colorspace, fz_drop_colorspace, obj, *csp); + pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)fz_keep_colorspace, (pdf_store_drop_fn *)fz_drop_colorspace, obj, cs); - return fz_okay; + return cs; } diff --git a/pdf/pdf_crypt.c b/pdf/pdf_crypt.c index 81ee5649..98ad0159 100644 --- a/pdf/pdf_crypt.c +++ b/pdf/pdf_crypt.c @@ -37,37 +37,37 @@ struct pdf_crypt_s int encrypt_metadata; unsigned char key[32]; /* decryption key generated from password */ + fz_context *ctx; }; -static fz_error pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *dict, char *name, int defaultlength); +static fz_error pdf_parse_crypt_filter(fz_context *ctx, pdf_crypt_filter *cf, fz_obj *dict, char *name, int defaultlength); /* * Create crypt object for decrypting strings and streams * given the Encryption and ID objects. */ -fz_error -pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) +pdf_crypt * +pdf_new_crypt(fz_context *ctx, fz_obj *dict, fz_obj *id) { pdf_crypt *crypt; - fz_error error; fz_obj *obj; - crypt = fz_malloc(sizeof(pdf_crypt)); - memset(crypt, 0x00, sizeof(pdf_crypt)); + crypt = fz_malloc(ctx, sizeof(pdf_crypt)); + memset(crypt, 0, sizeof *crypt); /* Common to all security handlers (PDF 1.7 table 3.18) */ obj = fz_dict_gets(dict, "Filter"); if (!fz_is_name(obj)) { - pdf_free_crypt(crypt); - return fz_throw("unspecified encryption handler"); + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "unspecified encryption handler"); } if (strcmp(fz_to_name(obj), "Standard") != 0) { - pdf_free_crypt(crypt); - return fz_throw("unknown encryption handler: '%s'", fz_to_name(obj)); + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "unknown encryption handler: '%s'", fz_to_name(obj)); } crypt->v = 0; @@ -76,8 +76,8 @@ pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) crypt->v = fz_to_int(obj); if (crypt->v != 1 && crypt->v != 2 && crypt->v != 4 && crypt->v != 5) { - pdf_free_crypt(crypt); - return fz_throw("unknown encryption version"); + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "unknown encryption version"); } crypt->length = 40; @@ -93,13 +93,13 @@ pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) if (crypt->length % 8 != 0) { - pdf_free_crypt(crypt); - return fz_throw("invalid encryption key length"); + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "invalid encryption key length"); } if (crypt->length > 256) { - pdf_free_crypt(crypt); - return fz_throw("invalid encryption key length"); + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "invalid encryption key length"); } } @@ -133,26 +133,20 @@ pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) crypt->cf = NULL; } - obj = fz_dict_gets(dict, "StmF"); - if (fz_is_name(obj)) + fz_try(ctx) { - error = pdf_parse_crypt_filter(&crypt->stmf, crypt->cf, fz_to_name(obj), crypt->length); - if (error) - { - pdf_free_crypt(crypt); - return fz_rethrow(error, "cannot parse stream crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); - } - } + obj = fz_dict_gets(dict, "StmF"); + if (fz_is_name(obj)) + pdf_parse_crypt_filter(ctx, &crypt->stmf, crypt->cf, fz_to_name(obj), crypt->length); - obj = fz_dict_gets(dict, "StrF"); - if (fz_is_name(obj)) + obj = fz_dict_gets(dict, "StrF"); + if (fz_is_name(obj)) + pdf_parse_crypt_filter(ctx, &crypt->strf, crypt->cf, fz_to_name(obj), crypt->length); + } + fz_catch(ctx) { - error = pdf_parse_crypt_filter(&crypt->strf, crypt->cf, fz_to_name(obj), crypt->length); - if (error) - { - pdf_free_crypt(crypt); - return fz_rethrow(error, "cannot parse string crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); - } + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "cannot parse string crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); } /* in crypt revision 4, the crypt filter determines the key length */ @@ -167,8 +161,8 @@ pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) crypt->r = fz_to_int(obj); else { - pdf_free_crypt(crypt); - return fz_throw("encryption dictionary missing revision value"); + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "encryption dictionary missing revision value"); } obj = fz_dict_gets(dict, "O"); @@ -179,8 +173,8 @@ pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) memcpy(crypt->o, fz_to_str_buf(obj), 48); else { - pdf_free_crypt(crypt); - return fz_throw("encryption dictionary missing owner password"); + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "encryption dictionary missing owner password"); } obj = fz_dict_gets(dict, "U"); @@ -190,13 +184,13 @@ pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) memcpy(crypt->u, fz_to_str_buf(obj), 48); else if (fz_is_string(obj) && fz_to_str_len(obj) < 32) { - fz_warn("encryption password key too short (%d)", fz_to_str_len(obj)); + fz_warn(ctx, "encryption password key too short (%d)", fz_to_str_len(obj)); memcpy(crypt->u, fz_to_str_buf(obj), fz_to_str_len(obj)); } else { - pdf_free_crypt(crypt); - return fz_throw("encryption dictionary missing user password"); + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "encryption dictionary missing user password"); } obj = fz_dict_gets(dict, "P"); @@ -204,8 +198,8 @@ pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) crypt->p = fz_to_int(obj); else { - pdf_free_crypt(crypt); - return fz_throw("encryption dictionary missing permissions value"); + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "encryption dictionary missing permissions value"); } if (crypt->r == 5) @@ -213,16 +207,16 @@ pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) obj = fz_dict_gets(dict, "OE"); if (!fz_is_string(obj) || fz_to_str_len(obj) != 32) { - pdf_free_crypt(crypt); - return fz_throw("encryption dictionary missing owner encryption key"); + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "encryption dictionary missing owner encryption key"); } memcpy(crypt->oe, fz_to_str_buf(obj), 32); obj = fz_dict_gets(dict, "UE"); if (!fz_is_string(obj) || fz_to_str_len(obj) != 32) { - pdf_free_crypt(crypt); - return fz_throw("encryption dictionary missing user encryption key"); + pdf_free_crypt(ctx, crypt); + fz_throw(ctx, "encryption dictionary missing user encryption key"); } memcpy(crypt->ue, fz_to_str_buf(obj), 32); } @@ -241,18 +235,17 @@ pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) crypt->id = fz_keep_obj(obj); } else - fz_warn("missing file identifier, may not be able to do decryption"); + fz_warn(ctx, "missing file identifier, may not be able to do decryption"); - *cryptp = crypt; - return fz_okay; + return crypt; } void -pdf_free_crypt(pdf_crypt *crypt) +pdf_free_crypt(fz_context *ctx, pdf_crypt *crypt) { if (crypt->id) fz_drop_obj(crypt->id); if (crypt->cf) fz_drop_obj(crypt->cf); - fz_free(crypt); + fz_free(ctx, crypt); } /* @@ -260,7 +253,7 @@ pdf_free_crypt(pdf_crypt *crypt) */ static fz_error -pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *cf_obj, char *name, int defaultlength) +pdf_parse_crypt_filter(fz_context *ctx, pdf_crypt_filter *cf, fz_obj *cf_obj, char *name, int defaultlength) { fz_obj *obj; fz_obj *dict; @@ -269,7 +262,7 @@ pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *cf_obj, char *name, int def if (!is_identity && !is_stdcf) { - return fz_throw("Crypt Filter not Identity or StdCF (%d %d R)", fz_to_num(cf_obj), fz_to_gen(cf_obj)); + return fz_error_make("Crypt Filter not Identity or StdCF (%d %d R)", fz_to_num(cf_obj), fz_to_gen(cf_obj)); } cf->method = PDF_CRYPT_NONE; cf->length = defaultlength; @@ -283,7 +276,7 @@ pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *cf_obj, char *name, int def dict = fz_dict_gets(cf_obj, name); if (!fz_is_dict(dict)) { - return fz_throw("cannot parse crypt filter (%d %d R)", fz_to_num(cf_obj), fz_to_gen(cf_obj)); + return fz_error_make("cannot parse crypt filter (%d %d R)", fz_to_num(cf_obj), fz_to_gen(cf_obj)); } obj = fz_dict_gets(dict, "CFM"); if (fz_is_name(obj)) @@ -297,7 +290,7 @@ pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *cf_obj, char *name, int def else if (!strcmp(fz_to_name(obj), "AESV3")) cf->method = PDF_CRYPT_AESV3; else - fz_throw("unknown encryption method: %s", fz_to_name(obj)); + fz_warn(ctx, "unknown encryption method: %s", fz_to_name(obj)); } obj = fz_dict_gets(dict, "Length"); @@ -309,7 +302,7 @@ pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *cf_obj, char *name, int def cf->length = cf->length * 8; if ((cf->length % 8) != 0) - return fz_throw("invalid key length: %d", cf->length); + return fz_error_make("invalid key length: %d", cf->length); return fz_okay; } @@ -707,7 +700,7 @@ pdf_compute_object_key(pdf_crypt *crypt, pdf_crypt_filter *cf, int num, int gen, */ static void -pdf_crypt_obj_imp(pdf_crypt *crypt, fz_obj *obj, unsigned char *key, int keylen) +pdf_crypt_obj_imp(fz_context *ctx, pdf_crypt *crypt, fz_obj *obj, unsigned char *key, int keylen) { unsigned char *s; int i, n; @@ -717,7 +710,7 @@ pdf_crypt_obj_imp(pdf_crypt *crypt, fz_obj *obj, unsigned char *key, int keylen) if (fz_is_string(obj)) { - s = (unsigned char *) fz_to_str_buf(obj); + s = (unsigned char *)fz_to_str_buf(obj); n = fz_to_str_len(obj); if (crypt->strf.method == PDF_CRYPT_RC4) @@ -734,7 +727,7 @@ pdf_crypt_obj_imp(pdf_crypt *crypt, fz_obj *obj, unsigned char *key, int keylen) /* Empty strings are permissible */ } else if (n & 15 || n < 32) - fz_warn("invalid string length for aes encryption"); + fz_warn(ctx, "invalid string length for aes encryption"); else { unsigned char iv[16]; @@ -744,7 +737,7 @@ pdf_crypt_obj_imp(pdf_crypt *crypt, fz_obj *obj, unsigned char *key, int keylen) aes_crypt_cbc(&aes, AES_DECRYPT, n - 16, iv, s + 16, s); /* delete space used for iv and padding bytes at end */ if (s[n - 17] < 1 || s[n - 17] > 16) - fz_warn("aes padding out of range"); + fz_warn(ctx, "aes padding out of range"); else fz_set_str_len(obj, n - 16 - s[n - 17]); } @@ -756,7 +749,7 @@ pdf_crypt_obj_imp(pdf_crypt *crypt, fz_obj *obj, unsigned char *key, int keylen) n = fz_array_len(obj); for (i = 0; i < n; i++) { - pdf_crypt_obj_imp(crypt, fz_array_get(obj, i), key, keylen); + pdf_crypt_obj_imp(ctx, crypt, fz_array_get(obj, i), key, keylen); } } @@ -765,20 +758,20 @@ pdf_crypt_obj_imp(pdf_crypt *crypt, fz_obj *obj, unsigned char *key, int keylen) n = fz_dict_len(obj); for (i = 0; i < n; i++) { - pdf_crypt_obj_imp(crypt, fz_dict_get_val(obj, i), key, keylen); + pdf_crypt_obj_imp(ctx, crypt, fz_dict_get_val(obj, i), key, keylen); } } } void -pdf_crypt_obj(pdf_crypt *crypt, fz_obj *obj, int num, int gen) +pdf_crypt_obj(fz_context *ctx, pdf_crypt *crypt, fz_obj *obj, int num, int gen) { unsigned char key[32]; int len; len = pdf_compute_object_key(crypt, &crypt->strf, num, gen, key); - pdf_crypt_obj_imp(crypt, obj, key, len); + pdf_crypt_obj_imp(ctx, crypt, obj, key, len); } /* @@ -792,6 +785,7 @@ pdf_open_crypt_imp(fz_stream *chain, pdf_crypt *crypt, pdf_crypt_filter *stmf, i unsigned char key[32]; int len; + crypt->ctx = chain->ctx; len = pdf_compute_object_key(crypt, stmf, num, gen, key); if (stmf->method == PDF_CRYPT_RC4) @@ -817,9 +811,9 @@ pdf_open_crypt_with_filter(fz_stream *chain, pdf_crypt *crypt, char *name, int n if (strcmp(name, "Identity")) { - error = pdf_parse_crypt_filter(&cf, crypt->cf, name, crypt->length); + error = pdf_parse_crypt_filter(chain->ctx, &cf, crypt->cf, name, crypt->length); if (error) - fz_catch(error, "cannot parse crypt filter (%d %d R)", num, gen); + fz_error_handle(error, "cannot parse crypt filter (%d %d R)", num, gen); else return pdf_open_crypt_imp(chain, crypt, &cf, num, gen); } diff --git a/pdf/pdf_font.c b/pdf/pdf_font.c index e7da43c0..3a94527b 100644 --- a/pdf/pdf_font.c +++ b/pdf/pdf_font.c @@ -5,7 +5,7 @@ #include FT_FREETYPE_H #include FT_XFREE86_H -static fz_error pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_xref *xref, fz_obj *dict, char *collection, char *basefont); +static void pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_xref *xref, fz_obj *dict, char *collection, char *basefont); static char *base_font_names[14][7] = { @@ -144,14 +144,14 @@ pdf_font_cid_to_gid(pdf_font_desc *fontdesc, int cid) return cid; } -static int ft_width(pdf_font_desc *fontdesc, int cid) +static int ft_width(fz_context *ctx, pdf_font_desc *fontdesc, int cid) { int gid = ft_cid_to_gid(fontdesc, cid); int fterr = FT_Load_Glyph(fontdesc->font->ft_face, gid, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); if (fterr) { - fz_warn("freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); + fz_warn(ctx, "freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); return 0; } return ((FT_Face)fontdesc->font->ft_face)->glyph->advance.x; @@ -170,71 +170,60 @@ static int lookup_mre_code(char *name) * Load font files. */ -static fz_error -pdf_load_builtin_font(pdf_font_desc *fontdesc, char *fontname) +static void +pdf_load_builtin_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname) { - fz_error error; unsigned char *data; unsigned int len; data = pdf_find_builtin_font(fontname, &len); if (!data) - return fz_throw("cannot find builtin font: '%s'", fontname); + fz_throw(ctx, "cannot find builtin font: '%s'", fontname); - error = fz_new_font_from_memory(&fontdesc->font, data, len, 0); - if (error) - return fz_rethrow(error, "cannot load freetype font from memory"); + fontdesc->font = fz_new_font_from_memory(ctx, data, len, 0); + /* RJW: "cannot load freetype font from memory" */ if (!strcmp(fontname, "Symbol") || !strcmp(fontname, "ZapfDingbats")) fontdesc->flags |= PDF_FD_SYMBOLIC; - - return fz_okay; } -static fz_error -pdf_load_substitute_font(pdf_font_desc *fontdesc, int mono, int serif, int bold, int italic) +static void +pdf_load_substitute_font(fz_context *ctx, pdf_font_desc *fontdesc, int mono, int serif, int bold, int italic) { - fz_error error; unsigned char *data; unsigned int len; data = pdf_find_substitute_font(mono, serif, bold, italic, &len); if (!data) - return fz_throw("cannot find substitute font"); + fz_throw(ctx, "cannot find substitute font"); - error = fz_new_font_from_memory(&fontdesc->font, data, len, 0); - if (error) - return fz_rethrow(error, "cannot load freetype font from memory"); + fontdesc->font = fz_new_font_from_memory(ctx, data, len, 0); + /* RJW: "cannot load freetype font from memory" */ fontdesc->font->ft_substitute = 1; fontdesc->font->ft_bold = bold && !ft_is_bold(fontdesc->font->ft_face); fontdesc->font->ft_italic = italic && !ft_is_italic(fontdesc->font->ft_face); - return fz_okay; } -static fz_error -pdf_load_substitute_cjk_font(pdf_font_desc *fontdesc, int ros, int serif) +static void +pdf_load_substitute_cjk_font(fz_context *ctx, pdf_font_desc *fontdesc, int ros, int serif) { - fz_error error; unsigned char *data; unsigned int len; data = pdf_find_substitute_cjk_font(ros, serif, &len); if (!data) - return fz_throw("cannot find builtin CJK font"); + fz_throw(ctx, "cannot find builtin CJK font"); - error = fz_new_font_from_memory(&fontdesc->font, data, len, 0); - if (error) - return fz_rethrow(error, "cannot load builtin CJK font"); + fontdesc->font = fz_new_font_from_memory(ctx, data, len, 0); + /* RJW: "cannot load builtin CJK font" */ fontdesc->font->ft_substitute = 1; - return fz_okay; } -static fz_error -pdf_load_system_font(pdf_font_desc *fontdesc, char *fontname, char *collection) +static void +pdf_load_system_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname, char *collection) { - fz_error error; int bold = 0; int italic = 0; int serif = 0; @@ -259,48 +248,53 @@ pdf_load_system_font(pdf_font_desc *fontdesc, char *fontname, char *collection) if (collection) { if (!strcmp(collection, "Adobe-CNS1")) - return pdf_load_substitute_cjk_font(fontdesc, PDF_ROS_CNS, serif); + pdf_load_substitute_cjk_font(ctx, fontdesc, PDF_ROS_CNS, serif); else if (!strcmp(collection, "Adobe-GB1")) - return pdf_load_substitute_cjk_font(fontdesc, PDF_ROS_GB, serif); + pdf_load_substitute_cjk_font(ctx, fontdesc, PDF_ROS_GB, serif); else if (!strcmp(collection, "Adobe-Japan1")) - return pdf_load_substitute_cjk_font(fontdesc, PDF_ROS_JAPAN, serif); + pdf_load_substitute_cjk_font(ctx, fontdesc, PDF_ROS_JAPAN, serif); else if (!strcmp(collection, "Adobe-Korea1")) - return pdf_load_substitute_cjk_font(fontdesc, PDF_ROS_KOREA, serif); - return fz_throw("unknown cid collection: %s", collection); + pdf_load_substitute_cjk_font(ctx, fontdesc, PDF_ROS_KOREA, serif); + else + fz_throw(ctx, "unknown cid collection: %s", collection); + return; } - error = pdf_load_substitute_font(fontdesc, mono, serif, bold, italic); - if (error) - return fz_rethrow(error, "cannot load substitute font"); - - return fz_okay; + pdf_load_substitute_font(ctx, fontdesc, mono, serif, bold, italic); + /* RJW: "cannot load substitute font" */ } -static fz_error +static void pdf_load_embedded_font(pdf_font_desc *fontdesc, pdf_xref *xref, fz_obj *stmref) { - fz_error error; fz_buffer *buf; + fz_context *ctx = xref->ctx; - error = pdf_load_stream(&buf, xref, fz_to_num(stmref), fz_to_gen(stmref)); - if (error) - return fz_rethrow(error, "cannot load font stream (%d %d R)", fz_to_num(stmref), fz_to_gen(stmref)); + fz_try(ctx) + { + buf = pdf_load_stream(xref, fz_to_num(stmref), fz_to_gen(stmref)); + } + fz_catch(ctx) + { + fz_throw(ctx, "cannot load font stream (%d %d R)", fz_to_num(stmref), fz_to_gen(stmref)); + } - error = fz_new_font_from_memory(&fontdesc->font, buf->data, buf->len, 0); - if (error) + fz_try(ctx) + { + fontdesc->font = fz_new_font_from_memory(ctx, buf->data, buf->len, 0); + } + fz_catch(ctx) { - fz_drop_buffer(buf); - return fz_rethrow(error, "cannot load embedded font (%d %d R)", fz_to_num(stmref), fz_to_gen(stmref)); + fz_drop_buffer(ctx, buf); + fz_throw(ctx, "cannot load embedded font (%d %d R)", fz_to_num(stmref), fz_to_gen(stmref)); } /* save the buffer so we can free it later */ fontdesc->font->ft_data = buf->data; fontdesc->font->ft_size = buf->len; - fz_free(buf); /* only free the fz_buffer struct, not the contained data */ + fz_free(ctx, buf); /* only free the fz_buffer struct, not the contained data */ fontdesc->is_embedded = 1; - - return fz_okay; } /* @@ -315,32 +309,32 @@ pdf_keep_font(pdf_font_desc *fontdesc) } void -pdf_drop_font(pdf_font_desc *fontdesc) +pdf_drop_font(fz_context *ctx, pdf_font_desc *fontdesc) { if (fontdesc && --fontdesc->refs == 0) { if (fontdesc->font) - fz_drop_font(fontdesc->font); + fz_drop_font(ctx, fontdesc->font); if (fontdesc->encoding) - pdf_drop_cmap(fontdesc->encoding); + pdf_drop_cmap(ctx, fontdesc->encoding); if (fontdesc->to_ttf_cmap) - pdf_drop_cmap(fontdesc->to_ttf_cmap); + pdf_drop_cmap(ctx, fontdesc->to_ttf_cmap); if (fontdesc->to_unicode) - pdf_drop_cmap(fontdesc->to_unicode); - fz_free(fontdesc->cid_to_gid); - fz_free(fontdesc->cid_to_ucs); - fz_free(fontdesc->hmtx); - fz_free(fontdesc->vmtx); - fz_free(fontdesc); + pdf_drop_cmap(ctx, fontdesc->to_unicode); + fz_free(ctx, fontdesc->cid_to_gid); + fz_free(ctx, fontdesc->cid_to_ucs); + fz_free(ctx, fontdesc->hmtx); + fz_free(ctx, fontdesc->vmtx); + fz_free(ctx, fontdesc); } } pdf_font_desc * -pdf_new_font_desc(void) +pdf_new_font_desc(fz_context *ctx) { pdf_font_desc *fontdesc; - fontdesc = fz_malloc(sizeof(pdf_font_desc)); + fontdesc = fz_malloc(ctx, sizeof(pdf_font_desc)); fontdesc->refs = 1; fontdesc->font = NULL; @@ -390,15 +384,14 @@ pdf_new_font_desc(void) * Simple fonts (Type1 and TrueType) */ -static fz_error -pdf_load_simple_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *dict) +static pdf_font_desc * +pdf_load_simple_font(pdf_xref *xref, fz_obj *dict) { - fz_error error; fz_obj *descriptor; fz_obj *encoding; fz_obj *widths; unsigned short *etable = NULL; - pdf_font_desc *fontdesc; + pdf_font_desc * volatile fontdesc; FT_Face face; FT_CharMap cmap; int symbolic; @@ -410,303 +403,300 @@ pdf_load_simple_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *dict) char ebuffer[256][32]; int i, k, n; int fterr; + fz_context *ctx = xref->ctx; basefont = fz_to_name(fz_dict_gets(dict, "BaseFont")); fontname = clean_font_name(basefont); /* Load font file */ + fz_try(ctx) + { + fontdesc = pdf_new_font_desc(ctx); - fontdesc = pdf_new_font_desc(); + descriptor = fz_dict_gets(dict, "FontDescriptor"); + if (descriptor) + pdf_load_font_descriptor(fontdesc, xref, descriptor, NULL, basefont); + else + pdf_load_builtin_font(ctx, fontdesc, fontname); - descriptor = fz_dict_gets(dict, "FontDescriptor"); - if (descriptor) - error = pdf_load_font_descriptor(fontdesc, xref, descriptor, NULL, basefont); - else - error = pdf_load_builtin_font(fontdesc, fontname); - if (error) - goto cleanup; - - /* Some chinese documents mistakenly consider WinAnsiEncoding to be codepage 936 */ - if (!*fontdesc->font->name && - !fz_dict_gets(dict, "ToUnicode") && - !strcmp(fz_to_name(fz_dict_gets(dict, "Encoding")), "WinAnsiEncoding") && - fz_to_int(fz_dict_gets(descriptor, "Flags")) == 4) - { - /* note: without the comma, pdf_load_font_descriptor would prefer /FontName over /BaseFont */ - char *cp936fonts[] = { - "\xCB\xCE\xCC\xE5", "SimSun,Regular", - "\xBA\xDA\xCC\xE5", "SimHei,Regular", - "\xBF\xAC\xCC\xE5_GB2312", "SimKai,Regular", - "\xB7\xC2\xCB\xCE_GB2312", "SimFang,Regular", - "\xC1\xA5\xCA\xE9", "SimLi,Regular", - NULL - }; - for (i = 0; cp936fonts[i]; i += 2) - if (!strcmp(basefont, cp936fonts[i])) - break; - if (cp936fonts[i]) + /* Some chinese documents mistakenly consider WinAnsiEncoding to be codepage 936 */ + if (!*fontdesc->font->name && + !fz_dict_gets(dict, "ToUnicode") && + !strcmp(fz_to_name(fz_dict_gets(dict, "Encoding")), "WinAnsiEncoding") && + fz_to_int(fz_dict_gets(descriptor, "Flags")) == 4) { - fz_warn("workaround for S22PDF lying about chinese font encodings"); - pdf_drop_font(fontdesc); - fontdesc = pdf_new_font_desc(); - error = pdf_load_font_descriptor(fontdesc, xref, descriptor, "Adobe-GB1", cp936fonts[i+1]); - error |= pdf_load_system_cmap(&fontdesc->encoding, "GBK-EUC-H"); - error |= pdf_load_system_cmap(&fontdesc->to_unicode, "Adobe-GB1-UCS2"); - error |= pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-GB1-UCS2"); - if (error) - return fz_rethrow(error, "cannot load font"); - - face = fontdesc->font->ft_face; - kind = ft_kind(face); - goto skip_encoding; + /* note: without the comma, pdf_load_font_descriptor would prefer /FontName over /BaseFont */ + char *cp936fonts[] = { + "\xCB\xCE\xCC\xE5", "SimSun,Regular", + "\xBA\xDA\xCC\xE5", "SimHei,Regular", + "\xBF\xAC\xCC\xE5_GB2312", "SimKai,Regular", + "\xB7\xC2\xCB\xCE_GB2312", "SimFang,Regular", + "\xC1\xA5\xCA\xE9", "SimLi,Regular", + NULL + }; + for (i = 0; cp936fonts[i]; i += 2) + if (!strcmp(basefont, cp936fonts[i])) + break; + if (cp936fonts[i]) + { + fz_warn(ctx, "workaround for S22PDF lying about chinese font encodings"); + pdf_drop_font(ctx, fontdesc); + fontdesc = pdf_new_font_desc(ctx); + pdf_load_font_descriptor(fontdesc, xref, descriptor, "Adobe-GB1", cp936fonts[i+1]); + fontdesc->encoding = pdf_load_system_cmap(ctx, "GBK-EUC-H"); + fontdesc->to_unicode = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); + fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); + /* RJW: "cannot load font" */ + + face = fontdesc->font->ft_face; + kind = ft_kind(face); + goto skip_encoding; + } } - } - face = fontdesc->font->ft_face; - kind = ft_kind(face); + face = fontdesc->font->ft_face; + kind = ft_kind(face); - /* Encoding */ + /* Encoding */ - symbolic = fontdesc->flags & 4; + symbolic = fontdesc->flags & 4; - if (face->num_charmaps > 0) - cmap = face->charmaps[0]; - else - cmap = NULL; - - for (i = 0; i < face->num_charmaps; i++) - { - FT_CharMap test = face->charmaps[i]; + if (face->num_charmaps > 0) + cmap = face->charmaps[0]; + else + cmap = NULL; - if (kind == TYPE1) + for (i = 0; i < face->num_charmaps; i++) { - if (test->platform_id == 7) - cmap = test; + FT_CharMap test = face->charmaps[i]; + + if (kind == TYPE1) + { + if (test->platform_id == 7) + cmap = test; + } + + if (kind == TRUETYPE) + { + if (test->platform_id == 1 && test->encoding_id == 0) + cmap = test; + if (test->platform_id == 3 && test->encoding_id == 1) + cmap = test; + } } - if (kind == TRUETYPE) + if (cmap) { - if (test->platform_id == 1 && test->encoding_id == 0) - cmap = test; - if (test->platform_id == 3 && test->encoding_id == 1) - cmap = test; + fterr = FT_Set_Charmap(face, cmap); + if (fterr) + fz_warn(ctx, "freetype could not set cmap: %s", ft_error_string(fterr)); } - } - - if (cmap) - { - fterr = FT_Set_Charmap(face, cmap); - if (fterr) - fz_warn("freetype could not set cmap: %s", ft_error_string(fterr)); - } - else - fz_warn("freetype could not find any cmaps"); - - etable = fz_calloc(256, sizeof(unsigned short)); - for (i = 0; i < 256; i++) - { - estrings[i] = NULL; - etable[i] = 0; - } - - encoding = fz_dict_gets(dict, "Encoding"); - if (encoding) - { - if (fz_is_name(encoding)) - pdf_load_encoding(estrings, fz_to_name(encoding)); + else + fz_warn(ctx, "freetype could not find any cmaps"); - if (fz_is_dict(encoding)) + etable = fz_malloc_array(ctx, 256, sizeof(unsigned short)); + for (i = 0; i < 256; i++) { - fz_obj *base, *diff, *item; + estrings[i] = NULL; + etable[i] = 0; + } - base = fz_dict_gets(encoding, "BaseEncoding"); - if (fz_is_name(base)) - pdf_load_encoding(estrings, fz_to_name(base)); - else if (!fontdesc->is_embedded && !symbolic) - pdf_load_encoding(estrings, "StandardEncoding"); + encoding = fz_dict_gets(dict, "Encoding"); + if (encoding) + { + if (fz_is_name(encoding)) + pdf_load_encoding(estrings, fz_to_name(encoding)); - diff = fz_dict_gets(encoding, "Differences"); - if (fz_is_array(diff)) + if (fz_is_dict(encoding)) { - n = fz_array_len(diff); - k = 0; - for (i = 0; i < n; i++) + fz_obj *base, *diff, *item; + + base = fz_dict_gets(encoding, "BaseEncoding"); + if (fz_is_name(base)) + pdf_load_encoding(estrings, fz_to_name(base)); + else if (!fontdesc->is_embedded && !symbolic) + pdf_load_encoding(estrings, "StandardEncoding"); + + diff = fz_dict_gets(encoding, "Differences"); + if (fz_is_array(diff)) { - item = fz_array_get(diff, i); - if (fz_is_int(item)) - k = fz_to_int(item); - if (fz_is_name(item)) - estrings[k++] = fz_to_name(item); - if (k < 0) k = 0; - if (k > 255) k = 255; + n = fz_array_len(diff); + k = 0; + for (i = 0; i < n; i++) + { + item = fz_array_get(diff, i); + if (fz_is_int(item)) + k = fz_to_int(item); + if (fz_is_name(item)) + estrings[k++] = fz_to_name(item); + if (k < 0) k = 0; + if (k > 255) k = 255; + } } } } - } - /* start with the builtin encoding */ - for (i = 0; i < 256; i++) - etable[i] = ft_char_index(face, i); - - /* encode by glyph name where we can */ - if (kind == TYPE1) - { + /* start with the builtin encoding */ for (i = 0; i < 256; i++) + etable[i] = ft_char_index(face, i); + + /* encode by glyph name where we can */ + if (kind == TYPE1) { - if (estrings[i]) + for (i = 0; i < 256; i++) { - etable[i] = FT_Get_Name_Index(face, estrings[i]); - if (etable[i] == 0) + if (estrings[i]) { - int aglcode = pdf_lookup_agl(estrings[i]); - const char **dupnames = pdf_lookup_agl_duplicates(aglcode); - while (*dupnames) + etable[i] = FT_Get_Name_Index(face, estrings[i]); + if (etable[i] == 0) { - etable[i] = FT_Get_Name_Index(face, (char*)*dupnames); - if (etable[i]) - break; - dupnames++; + int aglcode = pdf_lookup_agl(estrings[i]); + const char **dupnames = pdf_lookup_agl_duplicates(aglcode); + while (*dupnames) + { + etable[i] = FT_Get_Name_Index(face, (char*)*dupnames); + if (etable[i]) + break; + dupnames++; + } } } } } - } - /* encode by glyph name where we can */ - if (kind == TRUETYPE) - { - /* Unicode cmap */ - if (!symbolic && face->charmap && face->charmap->platform_id == 3) + /* encode by glyph name where we can */ + if (kind == TRUETYPE) { - for (i = 0; i < 256; i++) + /* Unicode cmap */ + if (!symbolic && face->charmap && face->charmap->platform_id == 3) { - if (estrings[i]) + for (i = 0; i < 256; i++) { - int aglcode = pdf_lookup_agl(estrings[i]); - if (!aglcode) - etable[i] = FT_Get_Name_Index(face, estrings[i]); - else - etable[i] = ft_char_index(face, aglcode); + if (estrings[i]) + { + int aglcode = pdf_lookup_agl(estrings[i]); + if (!aglcode) + etable[i] = FT_Get_Name_Index(face, estrings[i]); + else + etable[i] = ft_char_index(face, aglcode); + } } } - } - /* MacRoman cmap */ - else if (!symbolic && face->charmap && face->charmap->platform_id == 1) - { - for (i = 0; i < 256; i++) + /* MacRoman cmap */ + else if (!symbolic && face->charmap && face->charmap->platform_id == 1) { - if (estrings[i]) + for (i = 0; i < 256; i++) { - k = lookup_mre_code(estrings[i]); - if (k <= 0) - etable[i] = FT_Get_Name_Index(face, estrings[i]); - else - etable[i] = ft_char_index(face, k); + if (estrings[i]) + { + k = lookup_mre_code(estrings[i]); + if (k <= 0) + etable[i] = FT_Get_Name_Index(face, estrings[i]); + else + etable[i] = ft_char_index(face, k); + } } } - } - /* Symbolic cmap */ - else - { - for (i = 0; i < 256; i++) + /* Symbolic cmap */ + else { - if (estrings[i]) + for (i = 0; i < 256; i++) { - etable[i] = FT_Get_Name_Index(face, estrings[i]); - if (etable[i] == 0) - etable[i] = ft_char_index(face, i); + if (estrings[i]) + { + etable[i] = FT_Get_Name_Index(face, estrings[i]); + if (etable[i] == 0) + etable[i] = ft_char_index(face, i); + } } } } - } - /* try to reverse the glyph names from the builtin encoding */ - for (i = 0; i < 256; i++) - { - if (etable[i] && !estrings[i]) + /* try to reverse the glyph names from the builtin encoding */ + for (i = 0; i < 256; i++) { - if (FT_HAS_GLYPH_NAMES(face)) + if (etable[i] && !estrings[i]) { - fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); - if (fterr) - fz_warn("freetype get glyph name (gid %d): %s", etable[i], ft_error_string(fterr)); - if (ebuffer[i][0]) - estrings[i] = ebuffer[i]; - } - else - { - estrings[i] = (char*) pdf_win_ansi[i]; /* discard const */ + if (FT_HAS_GLYPH_NAMES(face)) + { + fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); + if (fterr) + fz_warn(ctx, "freetype get glyph name (gid %d): %s", etable[i], ft_error_string(fterr)); + if (ebuffer[i][0]) + estrings[i] = ebuffer[i]; + } + else + { + estrings[i] = (char*) pdf_win_ansi[i]; /* discard const */ + } } } - } - fontdesc->encoding = pdf_new_identity_cmap(0, 1); - fontdesc->cid_to_gid_len = 256; - fontdesc->cid_to_gid = etable; + fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1); + fontdesc->cid_to_gid_len = 256; + fontdesc->cid_to_gid = etable; - error = pdf_load_to_unicode(fontdesc, xref, estrings, NULL, fz_dict_gets(dict, "ToUnicode")); - if (error) - fz_catch(error, "cannot load to_unicode"); + pdf_load_to_unicode(fontdesc, xref, estrings, NULL, fz_dict_gets(dict, "ToUnicode")); + /* RJW: "cannot load to_unicode" */ -skip_encoding: + skip_encoding: - /* Widths */ + /* Widths */ - pdf_set_default_hmtx(fontdesc, fontdesc->missing_width); + pdf_set_default_hmtx(fontdesc, fontdesc->missing_width); - widths = fz_dict_gets(dict, "Widths"); - if (widths) - { - int first, last; + widths = fz_dict_gets(dict, "Widths"); + if (widths) + { + int first, last; - first = fz_to_int(fz_dict_gets(dict, "FirstChar")); - last = fz_to_int(fz_dict_gets(dict, "LastChar")); + first = fz_to_int(fz_dict_gets(dict, "FirstChar")); + last = fz_to_int(fz_dict_gets(dict, "LastChar")); - if (first < 0 || last > 255 || first > last) - first = last = 0; + if (first < 0 || last > 255 || first > last) + first = last = 0; - for (i = 0; i < last - first + 1; i++) + for (i = 0; i < last - first + 1; i++) + { + int wid = fz_to_int(fz_array_get(widths, i)); + pdf_add_hmtx(ctx, fontdesc, i + first, i + first, wid); + } + } + else { - int wid = fz_to_int(fz_array_get(widths, i)); - pdf_add_hmtx(fontdesc, i + first, i + first, wid); + fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); + if (fterr) + fz_warn(ctx, "freetype set character size: %s", ft_error_string(fterr)); + for (i = 0; i < 256; i++) + { + pdf_add_hmtx(ctx, fontdesc, i, i, ft_width(ctx, fontdesc, i)); + } } + + pdf_end_hmtx(fontdesc); } - else + fz_catch(ctx) { - fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); - if (fterr) - fz_warn("freetype set character size: %s", ft_error_string(fterr)); - for (i = 0; i < 256; i++) - { - pdf_add_hmtx(fontdesc, i, i, ft_width(fontdesc, i)); - } + if (etable != fontdesc->cid_to_gid) + fz_free(ctx, etable); + pdf_drop_font(ctx, fontdesc); + fz_throw(ctx, "cannot load simple font (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); } - - pdf_end_hmtx(fontdesc); - - *fontdescp = fontdesc; - return fz_okay; - -cleanup: - if (etable != fontdesc->cid_to_gid) - fz_free(etable); - pdf_drop_font(fontdesc); - return fz_rethrow(error, "cannot load simple font (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + return fontdesc; } /* * CID Fonts */ -static fz_error -load_cid_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *encoding, fz_obj *to_unicode) +static pdf_font_desc * +load_cid_font(pdf_xref *xref, fz_obj *dict, fz_obj *encoding, fz_obj *to_unicode) { - fz_error error; fz_obj *widths; fz_obj *descriptor; - pdf_font_desc *fontdesc; + pdf_font_desc * volatile fontdesc; FT_Face face; int kind; char collection[256]; @@ -714,204 +704,144 @@ load_cid_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *e int i, k, fterr; fz_obj *obj; int dw; + fz_context *ctx = xref->ctx; - /* Get font name and CID collection */ - - basefont = fz_to_name(fz_dict_gets(dict, "BaseFont")); - + fz_try(ctx) { - fz_obj *cidinfo; - char tmpstr[64]; - int tmplen; - - cidinfo = fz_dict_gets(dict, "CIDSystemInfo"); - if (!cidinfo) - return fz_throw("cid font is missing info"); - - obj = fz_dict_gets(cidinfo, "Registry"); - tmplen = MIN(sizeof tmpstr - 1, fz_to_str_len(obj)); - memcpy(tmpstr, fz_to_str_buf(obj), tmplen); - tmpstr[tmplen] = '\0'; - fz_strlcpy(collection, tmpstr, sizeof collection); - - fz_strlcat(collection, "-", sizeof collection); - - obj = fz_dict_gets(cidinfo, "Ordering"); - tmplen = MIN(sizeof tmpstr - 1, fz_to_str_len(obj)); - memcpy(tmpstr, fz_to_str_buf(obj), tmplen); - tmpstr[tmplen] = '\0'; - fz_strlcat(collection, tmpstr, sizeof collection); - } - - /* Load font file */ + /* Get font name and CID collection */ - fontdesc = pdf_new_font_desc(); + basefont = fz_to_name(fz_dict_gets(dict, "BaseFont")); - descriptor = fz_dict_gets(dict, "FontDescriptor"); - if (descriptor) - error = pdf_load_font_descriptor(fontdesc, xref, descriptor, collection, basefont); - else - error = fz_throw("syntaxerror: missing font descriptor"); - if (error) - goto cleanup; + { + fz_obj *cidinfo; + char tmpstr[64]; + int tmplen; + + cidinfo = fz_dict_gets(dict, "CIDSystemInfo"); + if (!cidinfo) + fz_throw(ctx, "cid font is missing info"); + + obj = fz_dict_gets(cidinfo, "Registry"); + tmplen = MIN(sizeof tmpstr - 1, fz_to_str_len(obj)); + memcpy(tmpstr, fz_to_str_buf(obj), tmplen); + tmpstr[tmplen] = '\0'; + fz_strlcpy(collection, tmpstr, sizeof collection); + + fz_strlcat(collection, "-", sizeof collection); + + obj = fz_dict_gets(cidinfo, "Ordering"); + tmplen = MIN(sizeof tmpstr - 1, fz_to_str_len(obj)); + memcpy(tmpstr, fz_to_str_buf(obj), tmplen); + tmpstr[tmplen] = '\0'; + fz_strlcat(collection, tmpstr, sizeof collection); + } - face = fontdesc->font->ft_face; - kind = ft_kind(face); + /* Load font file */ - /* Encoding */ + fontdesc = pdf_new_font_desc(ctx); - error = fz_okay; - if (fz_is_name(encoding)) - { - if (!strcmp(fz_to_name(encoding), "Identity-H")) - fontdesc->encoding = pdf_new_identity_cmap(0, 2); - else if (!strcmp(fz_to_name(encoding), "Identity-V")) - fontdesc->encoding = pdf_new_identity_cmap(1, 2); - else - error = pdf_load_system_cmap(&fontdesc->encoding, fz_to_name(encoding)); - } - else if (fz_is_indirect(encoding)) - { - error = pdf_load_embedded_cmap(&fontdesc->encoding, xref, encoding); - } - else - { - error = fz_throw("syntaxerror: font missing encoding"); - } - if (error) - goto cleanup; + descriptor = fz_dict_gets(dict, "FontDescriptor"); + if (descriptor == NULL) + fz_throw(ctx, "syntaxerror: missing font descriptor"); + pdf_load_font_descriptor(fontdesc, xref, descriptor, collection, basefont); - pdf_set_font_wmode(fontdesc, pdf_get_wmode(fontdesc->encoding)); + face = fontdesc->font->ft_face; + kind = ft_kind(face); - if (kind == TRUETYPE) - { - fz_obj *cidtogidmap; + /* Encoding */ - cidtogidmap = fz_dict_gets(dict, "CIDToGIDMap"); - if (fz_is_indirect(cidtogidmap)) + if (fz_is_name(encoding)) { - fz_buffer *buf; - - error = pdf_load_stream(&buf, xref, fz_to_num(cidtogidmap), fz_to_gen(cidtogidmap)); - if (error) - goto cleanup; - - fontdesc->cid_to_gid_len = (buf->len) / 2; - fontdesc->cid_to_gid = fz_calloc(fontdesc->cid_to_gid_len, sizeof(unsigned short)); - for (i = 0; i < fontdesc->cid_to_gid_len; i++) - fontdesc->cid_to_gid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1]; - - fz_drop_buffer(buf); + if (!strcmp(fz_to_name(encoding), "Identity-H")) + fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 2); + else if (!strcmp(fz_to_name(encoding), "Identity-V")) + fontdesc->encoding = pdf_new_identity_cmap(ctx, 1, 2); + else + fontdesc->encoding = pdf_load_system_cmap(ctx, fz_to_name(encoding)); } - - /* if truetype font is external, cidtogidmap should not be identity */ - /* so we map from cid to unicode and then map that through the (3 1) */ - /* unicode cmap to get a glyph id */ - else if (fontdesc->font->ft_substitute) + else if (fz_is_indirect(encoding)) { - fterr = FT_Select_Charmap(face, ft_encoding_unicode); - if (fterr) - { - error = fz_throw("fonterror: no unicode cmap when emulating CID font: %s", ft_error_string(fterr)); - goto cleanup; - } + fontdesc->encoding = pdf_load_embedded_cmap(xref, encoding); + } + else + { + fz_throw(ctx, "syntaxerror: font missing encoding"); + } - if (!strcmp(collection, "Adobe-CNS1")) - error = pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-CNS1-UCS2"); - else if (!strcmp(collection, "Adobe-GB1")) - error = pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-GB1-UCS2"); - else if (!strcmp(collection, "Adobe-Japan1")) - error = pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-Japan1-UCS2"); - else if (!strcmp(collection, "Adobe-Japan2")) - error = pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-Japan2-UCS2"); - else if (!strcmp(collection, "Adobe-Korea1")) - error = pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-Korea1-UCS2"); - else - error = fz_okay; + pdf_set_font_wmode(fontdesc, pdf_get_wmode(fontdesc->encoding)); - if (error) - { - error = fz_rethrow(error, "cannot load system cmap %s", collection); - goto cleanup; - } - } - } + if (kind == TRUETYPE) + { + fz_obj *cidtogidmap; - error = pdf_load_to_unicode(fontdesc, xref, NULL, collection, to_unicode); - if (error) - fz_catch(error, "cannot load to_unicode"); + cidtogidmap = fz_dict_gets(dict, "CIDToGIDMap"); + if (fz_is_indirect(cidtogidmap)) + { + fz_buffer *buf; - /* Horizontal */ + buf = pdf_load_stream(xref, fz_to_num(cidtogidmap), fz_to_gen(cidtogidmap)); - dw = 1000; - obj = fz_dict_gets(dict, "DW"); - if (obj) - dw = fz_to_int(obj); - pdf_set_default_hmtx(fontdesc, dw); + fontdesc->cid_to_gid_len = (buf->len) / 2; + fontdesc->cid_to_gid = fz_malloc_array(ctx, fontdesc->cid_to_gid_len, sizeof(unsigned short)); + for (i = 0; i < fontdesc->cid_to_gid_len; i++) + fontdesc->cid_to_gid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1]; - widths = fz_dict_gets(dict, "W"); - if (widths) - { - int c0, c1, w; + fz_drop_buffer(ctx, buf); + } - for (i = 0; i < fz_array_len(widths); ) - { - c0 = fz_to_int(fz_array_get(widths, i)); - obj = fz_array_get(widths, i + 1); - if (fz_is_array(obj)) + /* if truetype font is external, cidtogidmap should not be identity */ + /* so we map from cid to unicode and then map that through the (3 1) */ + /* unicode cmap to get a glyph id */ + else if (fontdesc->font->ft_substitute) { - for (k = 0; k < fz_array_len(obj); k++) + fterr = FT_Select_Charmap(face, ft_encoding_unicode); + if (fterr) { - w = fz_to_int(fz_array_get(obj, k)); - pdf_add_hmtx(fontdesc, c0 + k, c0 + k, w); + fz_throw(ctx, "fonterror: no unicode cmap when emulating CID font: %s", ft_error_string(fterr)); } - i += 2; - } - else - { - c1 = fz_to_int(obj); - w = fz_to_int(fz_array_get(widths, i + 2)); - pdf_add_hmtx(fontdesc, c0, c1, w); - i += 3; + + if (!strcmp(collection, "Adobe-CNS1")) + fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-CNS1-UCS2"); + else if (!strcmp(collection, "Adobe-GB1")) + fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); + else if (!strcmp(collection, "Adobe-Japan1")) + fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Japan1-UCS2"); + else if (!strcmp(collection, "Adobe-Japan2")) + fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Japan2-UCS2"); + else if (!strcmp(collection, "Adobe-Korea1")) + fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Korea1-UCS2"); + /* RJW: "cannot load system cmap %s", collection */ } } - } - pdf_end_hmtx(fontdesc); + pdf_load_to_unicode(fontdesc, xref, NULL, collection, to_unicode); + /* RJW: "cannot load to_unicode" */ - /* Vertical */ - - if (pdf_get_wmode(fontdesc->encoding) == 1) - { - int dw2y = 880; - int dw2w = -1000; + /* Horizontal */ - obj = fz_dict_gets(dict, "DW2"); + dw = 1000; + obj = fz_dict_gets(dict, "DW"); if (obj) - { - dw2y = fz_to_int(fz_array_get(obj, 0)); - dw2w = fz_to_int(fz_array_get(obj, 1)); - } - - pdf_set_default_vmtx(fontdesc, dw2y, dw2w); + dw = fz_to_int(obj); + pdf_set_default_hmtx(fontdesc, dw); - widths = fz_dict_gets(dict, "W2"); + widths = fz_dict_gets(dict, "W"); if (widths) { - int c0, c1, w, x, y; + int c0, c1, w, n, m; - for (i = 0; i < fz_array_len(widths); ) + n = fz_array_len(widths); + for (i = 0; i < n; ) { c0 = fz_to_int(fz_array_get(widths, i)); obj = fz_array_get(widths, i + 1); if (fz_is_array(obj)) { - for (k = 0; k * 3 < fz_array_len(obj); k ++) + m = fz_array_len(obj); + for (k = 0; k < m; k++) { - w = fz_to_int(fz_array_get(obj, k * 3 + 0)); - x = fz_to_int(fz_array_get(obj, k * 3 + 1)); - y = fz_to_int(fz_array_get(obj, k * 3 + 2)); - pdf_add_vmtx(fontdesc, c0 + k, c0 + k, x, y, w); + w = fz_to_int(fz_array_get(obj, k)); + pdf_add_hmtx(ctx, fontdesc, c0 + k, c0 + k, w); } i += 2; } @@ -919,29 +849,79 @@ load_cid_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *e { c1 = fz_to_int(obj); w = fz_to_int(fz_array_get(widths, i + 2)); - x = fz_to_int(fz_array_get(widths, i + 3)); - y = fz_to_int(fz_array_get(widths, i + 4)); - pdf_add_vmtx(fontdesc, c0, c1, x, y, w); - i += 5; + pdf_add_hmtx(ctx, fontdesc, c0, c1, w); + i += 3; } } } - pdf_end_vmtx(fontdesc); - } + pdf_end_hmtx(fontdesc); + + /* Vertical */ + + if (pdf_get_wmode(fontdesc->encoding) == 1) + { + int dw2y = 880; + int dw2w = -1000; + + obj = fz_dict_gets(dict, "DW2"); + if (obj) + { + dw2y = fz_to_int(fz_array_get(obj, 0)); + dw2w = fz_to_int(fz_array_get(obj, 1)); + } + + pdf_set_default_vmtx(fontdesc, dw2y, dw2w); + + widths = fz_dict_gets(dict, "W2"); + if (widths) + { + int c0, c1, w, x, y, n; - *fontdescp = fontdesc; - return fz_okay; + n = fz_array_len(widths); + for (i = 0; i < n; ) + { + c0 = fz_to_int(fz_array_get(widths, i)); + obj = fz_array_get(widths, i + 1); + if (fz_is_array(obj)) + { + int m = fz_array_len(obj); + for (k = 0; k * 3 < m; k ++) + { + w = fz_to_int(fz_array_get(obj, k * 3 + 0)); + x = fz_to_int(fz_array_get(obj, k * 3 + 1)); + y = fz_to_int(fz_array_get(obj, k * 3 + 2)); + pdf_add_vmtx(ctx, fontdesc, c0 + k, c0 + k, x, y, w); + } + i += 2; + } + else + { + c1 = fz_to_int(obj); + w = fz_to_int(fz_array_get(widths, i + 2)); + x = fz_to_int(fz_array_get(widths, i + 3)); + y = fz_to_int(fz_array_get(widths, i + 4)); + pdf_add_vmtx(ctx, fontdesc, c0, c1, x, y, w); + i += 5; + } + } + } -cleanup: - pdf_drop_font(fontdesc); - return fz_rethrow(error, "cannot load cid font (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + pdf_end_vmtx(fontdesc); + } + } + fz_catch(ctx) + { + pdf_drop_font(ctx, fontdesc); + fz_throw(ctx, "cannot load cid font (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + } + + return fontdesc; } -static fz_error -pdf_load_type0_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *dict) +static pdf_font_desc * +pdf_load_type0_font(pdf_xref *xref, fz_obj *dict) { - fz_error error; fz_obj *dfonts; fz_obj *dfont; fz_obj *subtype; @@ -950,7 +930,7 @@ pdf_load_type0_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *dict) dfonts = fz_dict_gets(dict, "DescendantFonts"); if (!dfonts) - return fz_throw("cid font is missing descendant fonts"); + fz_throw(xref->ctx, "cid font is missing descendant fonts"); dfont = fz_array_get(dfonts, 0); @@ -959,29 +939,27 @@ pdf_load_type0_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *dict) to_unicode = fz_dict_gets(dict, "ToUnicode"); if (fz_is_name(subtype) && !strcmp(fz_to_name(subtype), "CIDFontType0")) - error = load_cid_font(fontdescp, xref, dfont, encoding, to_unicode); + return load_cid_font(xref, dfont, encoding, to_unicode); else if (fz_is_name(subtype) && !strcmp(fz_to_name(subtype), "CIDFontType2")) - error = load_cid_font(fontdescp, xref, dfont, encoding, to_unicode); + return load_cid_font(xref, dfont, encoding, to_unicode); else - error = fz_throw("syntaxerror: unknown cid font type"); - if (error) - return fz_rethrow(error, "cannot load descendant font (%d %d R)", fz_to_num(dfont), fz_to_gen(dfont)); - - return fz_okay; + fz_throw(xref->ctx, "syntaxerror: unknown cid font type"); + /* RJW: "cannot load descendant font (%d %d R)", fz_to_num(dfont), fz_to_gen(dfont) */ + return NULL; /* Stupid MSVC */ } /* * FontDescriptor */ -static fz_error +static void pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_xref *xref, fz_obj *dict, char *collection, char *basefont) { - fz_error error; fz_obj *obj1, *obj2, *obj3, *obj; char *fontname; char *origname; FT_Face face; + fz_context *ctx = xref->ctx; if (!strchr(basefont, ',') || strchr(basefont, '+')) origname = fz_to_name(fz_dict_gets(dict, "FontName")); @@ -1004,26 +982,27 @@ pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_xref *xref, fz_obj *dict, if (fz_is_indirect(obj)) { - error = pdf_load_embedded_font(fontdesc, xref, obj); - if (error) + fz_try(ctx) { - fz_catch(error, "ignored error when loading embedded font, attempting to load system font"); + pdf_load_embedded_font(fontdesc, xref, obj); + } + fz_catch(ctx) + { + fz_error_handle(-1, "ignored error when loading embedded font, attempting to load system font"); if (origname != fontname) - error = pdf_load_builtin_font(fontdesc, fontname); + pdf_load_builtin_font(ctx, fontdesc, fontname); else - error = pdf_load_system_font(fontdesc, fontname, collection); - if (error) - return fz_rethrow(error, "cannot load font descriptor (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + pdf_load_system_font(ctx, fontdesc, fontname, collection); + /* RJW: "cannot load font descriptor (%d %d R)", fz_to_num(dict), fz_to_gen(dict) */ } } else { if (origname != fontname) - error = pdf_load_builtin_font(fontdesc, fontname); + pdf_load_builtin_font(ctx, fontdesc, fontname); else - error = pdf_load_system_font(fontdesc, fontname, collection); - if (error) - return fz_rethrow(error, "cannot load font descriptor (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + pdf_load_system_font(ctx, fontdesc, fontname, collection); + /* RJW: "cannot load font descriptor (%d %d R)", fz_to_num(dict), fz_to_gen(dict) */ } fz_strlcpy(fontdesc->font->name, fontname, sizeof fontdesc->font->name); @@ -1035,13 +1014,10 @@ pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_xref *xref, fz_obj *dict, if (FT_IS_TRICKY(face) || is_dynalab(fontdesc->font->name)) fontdesc->font->ft_hint = 1; } - - return fz_okay; - } static void -pdf_make_width_table(pdf_font_desc *fontdesc) +pdf_make_width_table(fz_context *ctx, pdf_font_desc *fontdesc) { fz_font *font = fontdesc->font; int i, k, cid, gid; @@ -1059,8 +1035,7 @@ pdf_make_width_table(pdf_font_desc *fontdesc) } font->width_count ++; - font->width_table = fz_calloc(font->width_count, sizeof(int)); - memset(font->width_table, 0, sizeof(int) * font->width_count); + font->width_table = fz_malloc_array(ctx, font->width_count, sizeof(int)); for (i = 0; i < fontdesc->hmtx_len; i++) { @@ -1074,18 +1049,19 @@ pdf_make_width_table(pdf_font_desc *fontdesc) } } -fz_error -pdf_load_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) +pdf_font_desc * +pdf_load_font(pdf_xref *xref, fz_obj *rdb, fz_obj *dict) { - fz_error error; char *subtype; fz_obj *dfonts; fz_obj *charprocs; + fz_context *ctx = xref->ctx; + pdf_font_desc *fontdesc; - if ((*fontdescp = pdf_find_item(xref->store, pdf_drop_font, dict))) + if ((fontdesc = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_font, dict))) { - pdf_keep_font(*fontdescp); - return fz_okay; + pdf_keep_font(fontdesc); + return fontdesc; } subtype = fz_to_name(fz_dict_gets(dict, "Subtype")); @@ -1093,40 +1069,39 @@ pdf_load_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *di charprocs = fz_dict_gets(dict, "CharProcs"); if (subtype && !strcmp(subtype, "Type0")) - error = pdf_load_type0_font(fontdescp, xref, dict); + fontdesc = pdf_load_type0_font(xref, dict); else if (subtype && !strcmp(subtype, "Type1")) - error = pdf_load_simple_font(fontdescp, xref, dict); + fontdesc = pdf_load_simple_font(xref, dict); else if (subtype && !strcmp(subtype, "MMType1")) - error = pdf_load_simple_font(fontdescp, xref, dict); + fontdesc = pdf_load_simple_font(xref, dict); else if (subtype && !strcmp(subtype, "TrueType")) - error = pdf_load_simple_font(fontdescp, xref, dict); + fontdesc = pdf_load_simple_font(xref, dict); else if (subtype && !strcmp(subtype, "Type3")) - error = pdf_load_type3_font(fontdescp, xref, rdb, dict); + fontdesc = pdf_load_type3_font(xref, rdb, dict); else if (charprocs) { - fz_warn("unknown font format, guessing type3."); - error = pdf_load_type3_font(fontdescp, xref, rdb, dict); + fz_warn(ctx, "unknown font format, guessing type3."); + fontdesc = pdf_load_type3_font(xref, rdb, dict); } else if (dfonts) { - fz_warn("unknown font format, guessing type0."); - error = pdf_load_type0_font(fontdescp, xref, dict); + fz_warn(ctx, "unknown font format, guessing type0."); + fontdesc = pdf_load_type0_font(xref, dict); } else { - fz_warn("unknown font format, guessing type1 or truetype."); - error = pdf_load_simple_font(fontdescp, xref, dict); + fz_warn(ctx, "unknown font format, guessing type1 or truetype."); + fontdesc = pdf_load_simple_font(xref, dict); } - if (error) - return fz_rethrow(error, "cannot load font (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + /* RJW: "cannot load font (%d %d R)", fz_to_num(dict), fz_to_gen(dict) */ /* Save the widths to stretch non-CJK substitute fonts */ - if ((*fontdescp)->font->ft_substitute && !(*fontdescp)->to_ttf_cmap) - pdf_make_width_table(*fontdescp); + if (fontdesc->font->ft_substitute && !fontdesc->to_ttf_cmap) + pdf_make_width_table(ctx, fontdesc); - pdf_store_item(xref->store, pdf_keep_font, pdf_drop_font, dict, *fontdescp); + pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)pdf_keep_font, (pdf_store_drop_fn *)pdf_drop_font, dict, fontdesc); - return fz_okay; + return fontdesc; } void diff --git a/pdf/pdf_function.c b/pdf/pdf_function.c index c1132365..3ef0d75f 100644 --- a/pdf/pdf_function.c +++ b/pdf/pdf_function.c @@ -295,7 +295,7 @@ ps_index(ps_stack *st, int n) } static void -ps_run(psobj *code, ps_stack *st, int pc) +ps_run(fz_context *ctx, psobj *code, ps_stack *st, int pc) { int i1, i2; float r1, r2; @@ -642,16 +642,16 @@ ps_run(psobj *code, ps_stack *st, int pc) case PS_OP_IF: b1 = ps_pop_bool(st); if (b1) - ps_run(code, st, code[pc + 1].u.block); + ps_run(ctx, code, st, code[pc + 1].u.block); pc = code[pc + 2].u.block; break; case PS_OP_IFELSE: b1 = ps_pop_bool(st); if (b1) - ps_run(code, st, code[pc + 1].u.block); + ps_run(ctx, code, st, code[pc + 1].u.block); else - ps_run(code, st, code[pc + 0].u.block); + ps_run(ctx, code, st, code[pc + 0].u.block); pc = code[pc + 2].u.block; break; @@ -659,60 +659,59 @@ ps_run(psobj *code, ps_stack *st, int pc) return; default: - fz_warn("foreign operator in calculator function"); + fz_warn(ctx, "foreign operator in calculator function"); return; } break; default: - fz_warn("foreign object in calculator function"); + fz_warn(ctx, "foreign object in calculator function"); return; } } } static void -resize_code(pdf_function *func, int newsize) +resize_code(fz_context *ctx, pdf_function *func, int newsize) { if (newsize >= func->u.p.cap) { func->u.p.cap = func->u.p.cap + 64; - func->u.p.code = fz_realloc(func->u.p.code, func->u.p.cap, sizeof(psobj)); + func->u.p.code = fz_resize_array(ctx, func->u.p.code, func->u.p.cap, sizeof(psobj)); } } -static fz_error +static void parse_code(pdf_function *func, fz_stream *stream, int *codeptr) { - fz_error error; char buf[64]; int len; int tok; int opptr, elseptr, ifptr; int a, b, mid, cmp; + fz_context *ctx = stream->ctx; memset(buf, 0, sizeof(buf)); while (1) { - error = pdf_lex(&tok, stream, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "calculator function lexical error"); + tok = pdf_lex(stream, buf, sizeof buf, &len); + /* RJW: "calculator function lexical error" */ switch(tok) { case PDF_TOK_EOF: - return fz_throw("truncated calculator function"); + fz_throw(ctx, "truncated calculator function"); case PDF_TOK_INT: - resize_code(func, *codeptr); + resize_code(ctx, func, *codeptr); func->u.p.code[*codeptr].type = PS_INT; func->u.p.code[*codeptr].u.i = atoi(buf); ++*codeptr; break; case PDF_TOK_REAL: - resize_code(func, *codeptr); + resize_code(ctx, func, *codeptr); func->u.p.code[*codeptr].type = PS_REAL; func->u.p.code[*codeptr].u.f = fz_atof(buf); ++*codeptr; @@ -722,76 +721,68 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr) opptr = *codeptr; *codeptr += 4; - resize_code(func, *codeptr); + resize_code(ctx, func, *codeptr); ifptr = *codeptr; - error = parse_code(func, stream, codeptr); - if (error) - return fz_rethrow(error, "error in 'if' branch"); + parse_code(func, stream, codeptr); + /* RJW: "error in 'if' branch" */ - error = pdf_lex(&tok, stream, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "calculator function syntax error"); + tok = pdf_lex(stream, buf, sizeof buf, &len); + /* RJW: "calculator function syntax error" */ if (tok == PDF_TOK_OPEN_BRACE) { elseptr = *codeptr; - error = parse_code(func, stream, codeptr); - if (error) - return fz_rethrow(error, "error in 'else' branch"); + parse_code(func, stream, codeptr); + /* RJW: "error in 'else' branch" */ - error = pdf_lex(&tok, stream, buf, sizeof buf, &len); - if (error) - return fz_rethrow(error, "calculator function syntax error"); + tok = pdf_lex(stream, buf, sizeof buf, &len); + /* RJW: "calculator function syntax error" */ } else { elseptr = -1; } - if (tok == PDF_TOK_KEYWORD) + if (tok != PDF_TOK_KEYWORD) + fz_throw(ctx, "missing keyword in 'if-else' context"); + + if (!strcmp(buf, "if")) { - if (!strcmp(buf, "if")) - { - if (elseptr >= 0) - return fz_throw("too many branches for 'if'"); - func->u.p.code[opptr].type = PS_OPERATOR; - func->u.p.code[opptr].u.op = PS_OP_IF; - func->u.p.code[opptr+2].type = PS_BLOCK; - func->u.p.code[opptr+2].u.block = ifptr; - func->u.p.code[opptr+3].type = PS_BLOCK; - func->u.p.code[opptr+3].u.block = *codeptr; - } - else if (!strcmp(buf, "ifelse")) - { - if (elseptr < 0) - return fz_throw("not enough branches for 'ifelse'"); - func->u.p.code[opptr].type = PS_OPERATOR; - func->u.p.code[opptr].u.op = PS_OP_IFELSE; - func->u.p.code[opptr+1].type = PS_BLOCK; - func->u.p.code[opptr+1].u.block = elseptr; - func->u.p.code[opptr+2].type = PS_BLOCK; - func->u.p.code[opptr+2].u.block = ifptr; - func->u.p.code[opptr+3].type = PS_BLOCK; - func->u.p.code[opptr+3].u.block = *codeptr; - } - else - { - return fz_throw("unknown keyword in 'if-else' context: '%s'", buf); - } + if (elseptr >= 0) + fz_throw(ctx, "too many branches for 'if'"); + func->u.p.code[opptr].type = PS_OPERATOR; + func->u.p.code[opptr].u.op = PS_OP_IF; + func->u.p.code[opptr+2].type = PS_BLOCK; + func->u.p.code[opptr+2].u.block = ifptr; + func->u.p.code[opptr+3].type = PS_BLOCK; + func->u.p.code[opptr+3].u.block = *codeptr; + } + else if (!strcmp(buf, "ifelse")) + { + if (elseptr < 0) + fz_throw(ctx, "not enough branches for 'ifelse'"); + func->u.p.code[opptr].type = PS_OPERATOR; + func->u.p.code[opptr].u.op = PS_OP_IFELSE; + func->u.p.code[opptr+1].type = PS_BLOCK; + func->u.p.code[opptr+1].u.block = elseptr; + func->u.p.code[opptr+2].type = PS_BLOCK; + func->u.p.code[opptr+2].u.block = ifptr; + func->u.p.code[opptr+3].type = PS_BLOCK; + func->u.p.code[opptr+3].u.block = *codeptr; } else { - return fz_throw("missing keyword in 'if-else' context"); + fz_throw(ctx, "unknown keyword in 'if-else' context: '%s'", buf); } break; case PDF_TOK_CLOSE_BRACE: - resize_code(func, *codeptr); + resize_code(ctx, func, *codeptr); func->u.p.code[*codeptr].type = PS_OPERATOR; func->u.p.code[*codeptr].u.op = PS_OP_RETURN; ++*codeptr; - return fz_okay; + return; case PDF_TOK_KEYWORD: cmp = -1; @@ -809,64 +800,58 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr) a = b = mid; } if (cmp != 0) - return fz_throw("unknown operator: '%s'", buf); + fz_throw(ctx, "unknown operator: '%s'", buf); - resize_code(func, *codeptr); + resize_code(ctx, func, *codeptr); func->u.p.code[*codeptr].type = PS_OPERATOR; func->u.p.code[*codeptr].u.op = a; ++*codeptr; break; default: - return fz_throw("calculator function syntax error"); + fz_throw(ctx, "calculator function syntax error"); } } } -static fz_error +static void load_postscript_func(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, int gen) { - fz_error error; - fz_stream *stream; + fz_stream * volatile stream = NULL; int codeptr; char buf[64]; int tok; int len; + fz_context *ctx = xref->ctx; - error = pdf_open_stream(&stream, xref, num, gen); - if (error) - return fz_rethrow(error, "cannot open calculator function stream"); - - error = pdf_lex(&tok, stream, buf, sizeof buf, &len); - if (error) + fz_try(ctx) { - fz_close(stream); - return fz_rethrow(error, "stream is not a calculator function"); - } + stream = pdf_open_stream(xref, num, gen); + /* RJW: "cannot open calculator function stream" */ - if (tok != PDF_TOK_OPEN_BRACE) - { - fz_close(stream); - return fz_throw("stream is not a calculator function"); - } + tok = pdf_lex(stream, buf, sizeof buf, &len); + if (tok != PDF_TOK_OPEN_BRACE) + { + fz_throw(ctx, "stream is not a calculator function"); + } - func->u.p.code = NULL; - func->u.p.cap = 0; + func->u.p.code = NULL; + func->u.p.cap = 0; - codeptr = 0; - error = parse_code(func, stream, &codeptr); - if (error) + codeptr = 0; + parse_code(func, stream, &codeptr); + } + fz_catch(ctx) { fz_close(stream); - return fz_rethrow(error, "cannot parse calculator function (%d %d R)", num, gen); + fz_throw(ctx, "cannot parse calculator function (%d %d R)", num, gen); } fz_close(stream); - return fz_okay; } static void -eval_postscript_func(pdf_function *func, float *in, float *out) +eval_postscript_func(fz_context *ctx, pdf_function *func, float *in, float *out) { ps_stack st; float x; @@ -880,7 +865,7 @@ eval_postscript_func(pdf_function *func, float *in, float *out) ps_push_real(&st, x); } - ps_run(func->u.p.code, &st, 0); + ps_run(ctx, func->u.p.code, &st, 0); for (i = func->n - 1; i >= 0; i--) { @@ -893,10 +878,10 @@ eval_postscript_func(pdf_function *func, float *in, float *out) * Sample function */ -static fz_error +static void load_sample_func(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, int gen) { - fz_error error; + fz_context *ctx = xref->ctx; fz_stream *stream; fz_obj *obj; int samplecount; @@ -907,20 +892,20 @@ load_sample_func(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, int obj = fz_dict_gets(dict, "Size"); if (!fz_is_array(obj) || fz_array_len(obj) != func->m) - return fz_throw("malformed /Size"); + fz_throw(ctx, "malformed /Size"); for (i = 0; i < func->m; i++) func->u.sa.size[i] = fz_to_int(fz_array_get(obj, i)); obj = fz_dict_gets(dict, "BitsPerSample"); if (!fz_is_int(obj)) - return fz_throw("malformed /BitsPerSample"); + fz_throw(ctx, "malformed /BitsPerSample"); func->u.sa.bps = bps = fz_to_int(obj); obj = fz_dict_gets(dict, "Encode"); if (fz_is_array(obj)) { if (fz_array_len(obj) != func->m * 2) - return fz_throw("malformed /Encode"); + fz_throw(ctx, "malformed /Encode"); for (i = 0; i < func->m; i++) { func->u.sa.encode[i][0] = fz_to_real(fz_array_get(obj, i*2+0)); @@ -940,7 +925,7 @@ load_sample_func(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, int if (fz_is_array(obj)) { if (fz_array_len(obj) != func->n * 2) - return fz_throw("malformed /Decode"); + fz_throw(ctx, "malformed /Decode"); for (i = 0; i < func->n; i++) { func->u.sa.decode[i][0] = fz_to_real(fz_array_get(obj, i*2+0)); @@ -959,11 +944,10 @@ load_sample_func(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, int for (i = 0, samplecount = func->n; i < func->m; i++) samplecount *= func->u.sa.size[i]; - func->u.sa.samples = fz_calloc(samplecount, sizeof(float)); + func->u.sa.samples = fz_malloc_array(ctx, samplecount, sizeof(float)); - error = pdf_open_stream(&stream, xref, num, gen); - if (error) - return fz_rethrow(error, "cannot open samples stream (%d %d R)", num, gen); + stream = pdf_open_stream(xref, num, gen); + /* RJW: "cannot open samples stream (%d %d R)", num, gen */ /* read samples */ for (i = 0; i < samplecount; i++) @@ -974,7 +958,7 @@ load_sample_func(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, int if (fz_is_eof_bits(stream)) { fz_close(stream); - return fz_throw("truncated sample stream"); + fz_throw(ctx, "truncated sample stream"); } switch (bps) @@ -1004,15 +988,13 @@ load_sample_func(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, int break; default: fz_close(stream); - return fz_throw("sample stream bit depth %d unsupported", bps); + fz_throw(ctx, "sample stream bit depth %d unsupported", bps); } func->u.sa.samples[i] = s; } fz_close(stream); - - return fz_okay; } static float @@ -1039,7 +1021,7 @@ interpolate_sample(pdf_function *func, int *scale, int *e0, int *e1, float *efra } static void -eval_sample_func(pdf_function *func, float *in, float *out) +eval_sample_func(fz_context *ctx, pdf_function *func, float *in, float *out) { int e0[MAXM], e1[MAXM], scale[MAXM]; float efrac[MAXM]; @@ -1107,17 +1089,17 @@ eval_sample_func(pdf_function *func, float *in, float *out) */ static fz_error -load_exponential_func(pdf_function *func, fz_obj *dict) +load_exponential_func(fz_context *ctx, pdf_function *func, fz_obj *dict) { fz_obj *obj; int i; if (func->m != 1) - return fz_throw("/Domain must be one dimension (%d)", func->m); + return fz_error_make("/Domain must be one dimension (%d)", func->m); obj = fz_dict_gets(dict, "N"); if (!fz_is_int(obj) && !fz_is_real(obj)) - return fz_throw("malformed /N"); + return fz_error_make("malformed /N"); func->u.e.n = fz_to_real(obj); obj = fz_dict_gets(dict, "C0"); @@ -1125,7 +1107,7 @@ load_exponential_func(pdf_function *func, fz_obj *dict) { func->n = fz_array_len(obj); if (func->n >= MAXN) - return fz_throw("exponential function result array out of range"); + return fz_error_make("exponential function result array out of range"); for (i = 0; i < func->n; i++) func->u.e.c0[i] = fz_to_real(fz_array_get(obj, i)); } @@ -1139,14 +1121,14 @@ load_exponential_func(pdf_function *func, fz_obj *dict) if (fz_is_array(obj)) { if (fz_array_len(obj) != func->n) - return fz_throw("/C1 must match /C0 length"); + return fz_error_make("/C1 must match /C0 length"); for (i = 0; i < func->n; i++) func->u.e.c1[i] = fz_to_real(fz_array_get(obj, i)); } else { if (func->n != 1) - return fz_throw("/C1 must match /C0 length"); + return fz_error_make("/C1 must match /C0 length"); func->u.e.c1[0] = 1; } @@ -1154,7 +1136,7 @@ load_exponential_func(pdf_function *func, fz_obj *dict) } static void -eval_exponential_func(pdf_function *func, float in, float *out) +eval_exponential_func(fz_context *ctx, pdf_function *func, float in, float *out) { float x = in; float tmp; @@ -1165,7 +1147,7 @@ eval_exponential_func(pdf_function *func, float in, float *out) /* constraint */ if ((func->u.e.n != (int)func->u.e.n && x < 0) || (func->u.e.n < 0 && x == 0)) { - fz_warn("constraint error"); + fz_warn(ctx, "constraint error"); return; } @@ -1182,11 +1164,11 @@ eval_exponential_func(pdf_function *func, float in, float *out) * Stitching function */ -static fz_error +static void load_stitching_func(pdf_function *func, pdf_xref *xref, fz_obj *dict) { + fz_context *ctx = xref->ctx; pdf_function **funcs; - fz_error error; fz_obj *obj; fz_obj *sub; fz_obj *num; @@ -1196,76 +1178,73 @@ load_stitching_func(pdf_function *func, pdf_xref *xref, fz_obj *dict) func->u.st.k = 0; if (func->m != 1) - return fz_throw("/Domain must be one dimension (%d)", func->m); + fz_throw(ctx, "/Domain must be one dimension (%d)", func->m); obj = fz_dict_gets(dict, "Functions"); if (!fz_is_array(obj)) - return fz_throw("stitching function has no input functions"); + fz_throw(ctx, "stitching function has no input functions"); { k = fz_array_len(obj); - func->u.st.funcs = fz_calloc(k, sizeof(pdf_function*)); - func->u.st.bounds = fz_calloc(k - 1, sizeof(float)); - func->u.st.encode = fz_calloc(k * 2, sizeof(float)); + func->u.st.funcs = fz_malloc_array(ctx, k, sizeof(pdf_function*)); + func->u.st.bounds = fz_malloc_array(ctx, k - 1, sizeof(float)); + func->u.st.encode = fz_malloc_array(ctx, k * 2, sizeof(float)); funcs = func->u.st.funcs; for (i = 0; i < k; i++) { sub = fz_array_get(obj, i); - error = pdf_load_function(&funcs[i], xref, sub); - if (error) - return fz_rethrow(error, "cannot load sub function %d (%d %d R)", i, fz_to_num(sub), fz_to_gen(sub)); + funcs[i] = pdf_load_function(xref, sub); + /* RJW: "cannot load sub function %d (%d %d R)", i, fz_to_num(sub), fz_to_gen(sub) */ if (funcs[i]->m != 1 || funcs[i]->n != funcs[0]->n) - return fz_throw("sub function %d /Domain or /Range mismatch", i); + fz_throw(ctx, "sub function %d /Domain or /Range mismatch", i); func->u.st.k ++; } if (!func->n) func->n = funcs[0]->n; else if (func->n != funcs[0]->n) - return fz_throw("sub function /Domain or /Range mismatch"); + fz_throw(ctx, "sub function /Domain or /Range mismatch"); } obj = fz_dict_gets(dict, "Bounds"); if (!fz_is_array(obj)) - return fz_throw("stitching function has no bounds"); + fz_throw(ctx, "stitching function has no bounds"); { if (!fz_is_array(obj) || fz_array_len(obj) != k - 1) - return fz_throw("malformed /Bounds (not array or wrong length)"); + fz_throw(ctx, "malformed /Bounds (not array or wrong length)"); for (i = 0; i < k-1; i++) { num = fz_array_get(obj, i); if (!fz_is_int(num) && !fz_is_real(num)) - return fz_throw("malformed /Bounds (item not real)"); + fz_throw(ctx, "malformed /Bounds (item not real)"); func->u.st.bounds[i] = fz_to_real(num); if (i && func->u.st.bounds[i-1] > func->u.st.bounds[i]) - return fz_throw("malformed /Bounds (item not monotonic)"); + fz_throw(ctx, "malformed /Bounds (item not monotonic)"); } if (k != 1 && (func->domain[0][0] > func->u.st.bounds[0] || func->domain[0][1] < func->u.st.bounds[k-2])) - fz_warn("malformed shading function bounds (domain mismatch), proceeding anyway."); + fz_warn(ctx, "malformed shading function bounds (domain mismatch), proceeding anyway."); } obj = fz_dict_gets(dict, "Encode"); if (!fz_is_array(obj)) - return fz_throw("stitching function is missing encoding"); + fz_throw(ctx, "stitching function is missing encoding"); { if (!fz_is_array(obj) || fz_array_len(obj) != k * 2) - return fz_throw("malformed /Encode"); + fz_throw(ctx, "malformed /Encode"); for (i = 0; i < k; i++) { func->u.st.encode[i*2+0] = fz_to_real(fz_array_get(obj, i*2+0)); func->u.st.encode[i*2+1] = fz_to_real(fz_array_get(obj, i*2+1)); } } - - return fz_okay; } static void -eval_stitching_func(pdf_function *func, float in, float *out) +eval_stitching_func(fz_context *ctx, pdf_function *func, float in, float *out) { float low, high; int k = func->u.st.k; @@ -1303,7 +1282,7 @@ eval_stitching_func(pdf_function *func, float in, float *out) in = lerp(in, low, high, func->u.st.encode[i*2+0], func->u.st.encode[i*2+1]); - pdf_eval_function(func->u.st.funcs[i], &in, 1, out, func->n); + pdf_eval_function(ctx, func->u.st.funcs[i], &in, 1, out, func->n); } /* @@ -1318,7 +1297,7 @@ pdf_keep_function(pdf_function *func) } void -pdf_drop_function(pdf_function *func) +pdf_drop_function(fz_context *ctx, pdf_function *func) { int i; if (--func->refs == 0) @@ -1326,41 +1305,41 @@ pdf_drop_function(pdf_function *func) switch(func->type) { case SAMPLE: - fz_free(func->u.sa.samples); + fz_free(ctx, func->u.sa.samples); break; case EXPONENTIAL: break; case STITCHING: for (i = 0; i < func->u.st.k; i++) - pdf_drop_function(func->u.st.funcs[i]); - fz_free(func->u.st.funcs); - fz_free(func->u.st.bounds); - fz_free(func->u.st.encode); + pdf_drop_function(ctx, func->u.st.funcs[i]); + fz_free(ctx, func->u.st.funcs); + fz_free(ctx, func->u.st.bounds); + fz_free(ctx, func->u.st.encode); break; case POSTSCRIPT: - fz_free(func->u.p.code); + fz_free(ctx, func->u.p.code); break; } - fz_free(func); + fz_free(ctx, func); } } -fz_error -pdf_load_function(pdf_function **funcp, pdf_xref *xref, fz_obj *dict) +pdf_function * +pdf_load_function(pdf_xref *xref, fz_obj *dict) { - fz_error error; - pdf_function *func; + fz_context *ctx = xref->ctx; + pdf_function * volatile func; fz_obj *obj; int i; - if ((*funcp = pdf_find_item(xref->store, pdf_drop_function, dict))) + if ((func = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_function, dict))) { - pdf_keep_function(*funcp); - return fz_okay; + pdf_keep_function(func); + return func; } - func = fz_malloc(sizeof(pdf_function)); - memset(func, 0, sizeof(pdf_function)); + func = fz_malloc(ctx, sizeof(pdf_function)); + memset(func, 0, sizeof *func); func->refs = 1; obj = fz_dict_gets(dict, "FunctionType"); @@ -1395,81 +1374,73 @@ pdf_load_function(pdf_function **funcp, pdf_xref *xref, fz_obj *dict) if (func->m >= MAXM || func->n >= MAXN) { - fz_free(func); - return fz_throw("assert: /Domain or /Range too big"); + fz_free(ctx, func); + fz_throw(ctx, "assert: /Domain or /Range too big"); } - switch(func->type) + fz_try(ctx) { - case SAMPLE: - error = load_sample_func(func, xref, dict, fz_to_num(dict), fz_to_gen(dict)); - if (error) + switch(func->type) { - pdf_drop_function(func); - return fz_rethrow(error, "cannot load sampled function (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); - } - break; + case SAMPLE: + load_sample_func(func, xref, dict, fz_to_num(dict), fz_to_gen(dict)); + break; - case EXPONENTIAL: - error = load_exponential_func(func, dict); - if (error) - { - pdf_drop_function(func); - return fz_rethrow(error, "cannot load exponential function (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); - } - break; + case EXPONENTIAL: + load_exponential_func(ctx, func, dict); + break; - case STITCHING: - error = load_stitching_func(func, xref, dict); - if (error) - { - pdf_drop_function(func); - return fz_rethrow(error, "cannot load stitching function (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); - } - break; + case STITCHING: + load_stitching_func(func, xref, dict); + break; - case POSTSCRIPT: - error = load_postscript_func(func, xref, dict, fz_to_num(dict), fz_to_gen(dict)); - if (error) - { - pdf_drop_function(func); - return fz_rethrow(error, "cannot load calculator function (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); - } - break; + case POSTSCRIPT: + load_postscript_func(func, xref, dict, fz_to_num(dict), fz_to_gen(dict)); + break; - default: - fz_free(func); - return fz_throw("unknown function type (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + default: + fz_free(ctx, func); + fz_throw(ctx, "unknown function type (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + } + } + fz_catch(ctx) + { + pdf_drop_function(ctx, func); + fz_throw(ctx, "cannot load %s function (%d %d R)", + (func->type == SAMPLE ? "sampled" : + (func->type == EXPONENTIAL ? "exponential" : + (func->type == STITCHING ? "stitching" : + (func->type == POSTSCRIPT ? "calculator" : + "unknown")))), fz_to_num(dict), fz_to_gen(dict)); } - pdf_store_item(xref->store, pdf_keep_function, pdf_drop_function, dict, func); + pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)pdf_keep_function, (pdf_store_drop_fn *)pdf_drop_function, dict, func); - *funcp = func; - return fz_okay; + return func; } void -pdf_eval_function(pdf_function *func, float *in, int inlen, float *out, int outlen) +pdf_eval_function(fz_context *ctx, pdf_function *func, float *in, int inlen, float *out, int outlen) { memset(out, 0, sizeof(float) * outlen); if (inlen != func->m) { - fz_warn("tried to evaluate function with wrong number of inputs"); + fz_warn(ctx, "tried to evaluate function with wrong number of inputs"); return; } if (func->n != outlen) { - fz_warn("tried to evaluate function with wrong number of outputs"); + fz_warn(ctx, "tried to evaluate function with wrong number of outputs"); return; } switch(func->type) { - case SAMPLE: eval_sample_func(func, in, out); break; - case EXPONENTIAL: eval_exponential_func(func, *in, out); break; - case STITCHING: eval_stitching_func(func, *in, out); break; - case POSTSCRIPT: eval_postscript_func(func, in, out); break; + case SAMPLE: eval_sample_func(ctx, func, in, out); break; + case EXPONENTIAL: eval_exponential_func(ctx, func, *in, out); break; + case STITCHING: eval_stitching_func(ctx, func, *in, out); break; + case POSTSCRIPT: eval_postscript_func(ctx, func, in, out); break; } } diff --git a/pdf/pdf_image.c b/pdf/pdf_image.c index 3ae0fdfc..41be8fac 100644 --- a/pdf/pdf_image.c +++ b/pdf/pdf_image.c @@ -4,7 +4,7 @@ /* TODO: store JPEG compressed samples */ /* TODO: store flate compressed samples */ -static fz_error pdf_load_jpx_image(fz_pixmap **imgp, pdf_xref *xref, fz_obj *dict); +static fz_pixmap *pdf_load_jpx_image(pdf_xref *xref, fz_obj *dict); static void pdf_mask_color_key(fz_pixmap *pix, int n, int *colorkey) @@ -25,349 +25,335 @@ pdf_mask_color_key(fz_pixmap *pix, int n, int *colorkey) } } -static fz_error -pdf_load_image_imp(fz_pixmap **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cstm, int forcemask) +static fz_pixmap * +pdf_load_image_imp(pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cstm, int forcemask) { - fz_stream *stm; - fz_pixmap *tile; + fz_stream * volatile stm = NULL; + fz_pixmap * volatile tile = NULL; 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 */ + fz_colorspace * volatile colorspace = NULL; + fz_pixmap * volatile mask = NULL; /* explicit mask/softmask image */ int usecolorkey; int colorkey[FZ_MAX_COLORS * 2]; float decode[FZ_MAX_COLORS * 2]; int stride; - unsigned char *samples; + unsigned char * volatile samples = NULL; int i, len; + fz_context *ctx = xref->ctx; - /* special case for JPEG2000 images */ - if (pdf_is_jpx_image(dict)) + fz_try(ctx) { - tile = NULL; - error = pdf_load_jpx_image(&tile, xref, dict); - if (error) - return fz_rethrow(error, "cannot load jpx image"); - if (forcemask) + /* special case for JPEG2000 images */ + if (pdf_is_jpx_image(ctx, dict)) { - if (tile->n != 2) + tile = pdf_load_jpx_image(xref, dict); + /* RJW: "cannot load jpx image" */ + if (forcemask) { - fz_drop_pixmap(tile); - return fz_throw("softmask must be grayscale"); + if (tile->n != 2) + fz_throw(ctx, "softmask must be grayscale"); + mask = fz_alpha_from_gray(ctx, tile, 1); + fz_drop_pixmap(ctx, tile); + tile = mask; + mask = NULL; } - mask = fz_alpha_from_gray(tile, 1); - fz_drop_pixmap(tile); - *imgp = mask; - return fz_okay; + break; /* Out of fz_try */ } - *imgp = tile; - return fz_okay; - } - w = fz_to_int(fz_dict_getsa(dict, "Width", "W")); - h = fz_to_int(fz_dict_getsa(dict, "Height", "H")); - bpc = fz_to_int(fz_dict_getsa(dict, "BitsPerComponent", "BPC")); - imagemask = fz_to_bool(fz_dict_getsa(dict, "ImageMask", "IM")); - interpolate = fz_to_bool(fz_dict_getsa(dict, "Interpolate", "I")); - - indexed = 0; - usecolorkey = 0; - colorspace = NULL; - mask = NULL; - - 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 (bpc > 16) - return fz_throw("image depth is too large: %d", bpc); - if (w > (1 << 16)) - return fz_throw("image is too wide"); - if (h > (1 << 16)) - return fz_throw("image is too high"); - - obj = fz_dict_getsa(dict, "ColorSpace", "CS"); - if (obj && !imagemask && !forcemask) - { - /* colorspace resource lookup is only done for inline images */ - if (fz_is_name(obj)) + w = fz_to_int(fz_dict_getsa(dict, "Width", "W")); + h = fz_to_int(fz_dict_getsa(dict, "Height", "H")); + bpc = fz_to_int(fz_dict_getsa(dict, "BitsPerComponent", "BPC")); + imagemask = fz_to_bool(fz_dict_getsa(dict, "ImageMask", "IM")); + interpolate = fz_to_bool(fz_dict_getsa(dict, "Interpolate", "I")); + + indexed = 0; + usecolorkey = 0; + mask = NULL; + + if (imagemask) + bpc = 1; + + if (w == 0) + fz_throw(ctx, "image width is zero"); + if (h == 0) + fz_throw(ctx, "image height is zero"); + if (bpc == 0) + fz_throw(ctx, "image depth is zero"); + if (bpc > 16) + fz_throw(ctx, "image depth is too large: %d", bpc); + if (w > (1 << 16)) + fz_throw(ctx, "image is too wide"); + if (h > (1 << 16)) + fz_throw(ctx, "image is too high"); + + obj = fz_dict_getsa(dict, "ColorSpace", "CS"); + if (obj && !imagemask && !forcemask) { - res = fz_dict_get(fz_dict_gets(rdb, "ColorSpace"), obj); - if (res) - obj = res; - } + /* colorspace resource lookup is only done for inline images */ + if (fz_is_name(obj)) + { + res = fz_dict_get(fz_dict_gets(rdb, "ColorSpace"), obj); + if (res) + obj = res; + } - error = pdf_load_colorspace(&colorspace, xref, obj); - if (error) - return fz_rethrow(error, "cannot load image colorspace"); + colorspace = pdf_load_colorspace(xref, obj); + /* RJW: "cannot load image colorspace" */ - if (!strcmp(colorspace->name, "Indexed")) - indexed = 1; + if (!strcmp(colorspace->name, "Indexed")) + indexed = 1; - n = colorspace->n; - } - else - { - n = 1; - } + n = colorspace->n; + } + else + { + n = 1; + } - obj = fz_dict_getsa(dict, "Decode", "D"); - if (obj) - { - for (i = 0; i < n * 2; i++) - decode[i] = fz_to_real(fz_array_get(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_dict_getsa(dict, "Decode", "D"); + if (obj) + { + for (i = 0; i < n * 2; i++) + decode[i] = fz_to_real(fz_array_get(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_dict_getsa(dict, "SMask", "Mask"); - if (fz_is_dict(obj)) - { - /* Not allowed for inline images */ - if (!cstm) + obj = fz_dict_getsa(dict, "SMask", "Mask"); + if (fz_is_dict(obj)) { - error = pdf_load_image_imp(&mask, xref, rdb, obj, NULL, 1); - if (error) + /* Not allowed for inline images */ + if (!cstm) { - if (colorspace) - fz_drop_colorspace(colorspace); - return fz_rethrow(error, "cannot load image mask/softmask"); + mask = pdf_load_image_imp(xref, rdb, obj, NULL, 1); + /* RJW: "cannot load image mask/softmask" */ } } - } - else if (fz_is_array(obj)) - { - usecolorkey = 1; - for (i = 0; i < n * 2; i++) + else if (fz_is_array(obj)) { - if (!fz_is_int(fz_array_get(obj, i))) + usecolorkey = 1; + for (i = 0; i < n * 2; i++) { - fz_warn("invalid value in color key mask"); - usecolorkey = 0; + if (!fz_is_int(fz_array_get(obj, i))) + { + fz_warn(ctx, "invalid value in color key mask"); + usecolorkey = 0; + } + colorkey[i] = fz_to_int(fz_array_get(obj, i)); } - colorkey[i] = fz_to_int(fz_array_get(obj, i)); } - } - /* Allocate now, to fail early if we run out of memory */ - tile = fz_new_pixmap_with_limit(colorspace, w, h); - if (!tile) - { - if (colorspace) - fz_drop_colorspace(colorspace); - if (mask) - fz_drop_pixmap(mask); - return fz_throw("out of memory"); - } + /* Allocate now, to fail early if we run out of memory */ + tile = fz_new_pixmap_with_limit(ctx, colorspace, w, h); + if (!tile) + { + fz_throw(ctx, "out of memory"); + } - if (colorspace) - fz_drop_colorspace(colorspace); + if (colorspace) + { + fz_drop_colorspace(ctx, colorspace); + colorspace = NULL; + } - tile->mask = mask; - tile->interpolate = interpolate; + tile->mask = mask; + mask = NULL; + tile->interpolate = interpolate; - stride = (w * n * bpc + 7) / 8; + stride = (w * n * bpc + 7) / 8; - if (cstm) - { - stm = pdf_open_inline_stream(cstm, xref, dict, stride * h); - } - else - { - error = pdf_open_stream(&stm, xref, fz_to_num(dict), fz_to_gen(dict)); - if (error) + if (cstm) { - fz_drop_pixmap(tile); - return fz_rethrow(error, "cannot open image data stream (%d 0 R)", fz_to_num(dict)); + stm = pdf_open_inline_stream(cstm, xref, dict, stride * h); + } + else + { + stm = pdf_open_stream(xref, fz_to_num(dict), fz_to_gen(dict)); + /* RJW: "cannot open image data stream (%d 0 R)", fz_to_num(dict) */ } - } - samples = fz_calloc(h, stride); + samples = fz_malloc_array(ctx, h, stride); - len = fz_read(stm, samples, h * stride); - if (len < 0) - { - fz_close(stm); - fz_free(samples); - fz_drop_pixmap(tile); - return fz_rethrow(len, "cannot read image data"); - } + len = fz_read(stm, samples, h * stride); + if (len < 0) + { + fz_throw(ctx, "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"); - } + /* 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_error_handle(tlen, "ignoring error at end of image"); + if (tlen > 0) + fz_warn(ctx, "ignoring garbage at end of image"); + } - fz_close(stm); + fz_close(stm); + stm = NULL; - /* Pad truncated images */ - if (len < stride * h) - { - fz_warn("padding truncated image (%d 0 R)", fz_to_num(dict)); - memset(samples + len, 0, stride * h - len); - } + /* Pad truncated images */ + if (len < stride * h) + { + fz_warn(ctx, "padding truncated image (%d 0 R)", fz_to_num(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]; - } + /* 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]; + } - fz_unpack_tile(tile, samples, n, bpc, stride, indexed); + fz_unpack_tile(tile, samples, n, bpc, stride, indexed); - fz_free(samples); + fz_free(ctx, samples); + samples = NULL; - if (usecolorkey) - pdf_mask_color_key(tile, n, colorkey); + if (usecolorkey) + pdf_mask_color_key(tile, n, colorkey); - if (indexed) - { - fz_pixmap *conv; - fz_decode_indexed_tile(tile, decode, (1 << bpc) - 1); - conv = pdf_expand_indexed_pixmap(tile); - fz_drop_pixmap(tile); - tile = conv; + if (indexed) + { + fz_pixmap *conv; + fz_decode_indexed_tile(tile, decode, (1 << bpc) - 1); + conv = pdf_expand_indexed_pixmap(ctx, tile); + fz_drop_pixmap(ctx, tile); + tile = conv; + } + else + { + fz_decode_tile(tile, decode); + } } - else + fz_catch(ctx) { - fz_decode_tile(tile, decode); + if (colorspace) + fz_drop_colorspace(ctx, colorspace); + if (mask) + fz_drop_pixmap(ctx, mask); + if (tile) + fz_drop_pixmap(ctx, tile); + fz_close(stm); + fz_free(ctx, samples); + + fz_rethrow(ctx); } - *imgp = tile; - return fz_okay; + return tile; } -fz_error -pdf_load_inline_image(fz_pixmap **pixp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *file) +fz_pixmap * +pdf_load_inline_image(pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *file) { - fz_error error; - - error = pdf_load_image_imp(pixp, xref, rdb, dict, file, 0); - if (error) - return fz_rethrow(error, "cannot load inline image"); - - return fz_okay; + return pdf_load_image_imp(xref, rdb, dict, file, 0); + /* RJW: "cannot load inline image" */ } int -pdf_is_jpx_image(fz_obj *dict) +pdf_is_jpx_image(fz_context *ctx, fz_obj *dict) { fz_obj *filter; - int i; + int i, n; filter = fz_dict_gets(dict, "Filter"); if (!strcmp(fz_to_name(filter), "JPXDecode")) return 1; - for (i = 0; i < fz_array_len(filter); i++) + n = fz_array_len(filter); + for (i = 0; i < n; i++) if (!strcmp(fz_to_name(fz_array_get(filter, i)), "JPXDecode")) return 1; return 0; } -static fz_error -pdf_load_jpx_image(fz_pixmap **imgp, pdf_xref *xref, fz_obj *dict) +static fz_pixmap * +pdf_load_jpx_image(pdf_xref *xref, fz_obj *dict) { - fz_error error; - fz_buffer *buf; - fz_colorspace *colorspace; + fz_buffer * volatile buf = NULL; + fz_colorspace * volatile colorspace = NULL; fz_pixmap *img; fz_obj *obj; + fz_context *ctx = xref->ctx; - colorspace = NULL; - - error = pdf_load_stream(&buf, xref, fz_to_num(dict), fz_to_gen(dict)); - if (error) - return fz_rethrow(error, "cannot load jpx image data"); + buf = pdf_load_stream(xref, fz_to_num(dict), fz_to_gen(dict)); + /* RJW: "cannot load jpx image data" */ - obj = fz_dict_gets(dict, "ColorSpace"); - if (obj) + fz_try(ctx) { - error = pdf_load_colorspace(&colorspace, xref, obj); - if (error) - fz_catch(error, "cannot load image colorspace"); - } + obj = fz_dict_gets(dict, "ColorSpace"); + if (obj) + { + colorspace = pdf_load_colorspace(xref, obj); + /* RJW: "cannot load image colorspace" */ + } - error = fz_load_jpx_image(&img, buf->data, buf->len, colorspace); - if (error) - { - if (colorspace) - fz_drop_colorspace(colorspace); - fz_drop_buffer(buf); - return fz_rethrow(error, "cannot load jpx image"); - } + img = fz_load_jpx_image(ctx, buf->data, buf->len, colorspace); + /* RJW: "cannot load jpx image" */ - if (colorspace) - fz_drop_colorspace(colorspace); - fz_drop_buffer(buf); + if (colorspace) + fz_drop_colorspace(ctx, colorspace); + fz_drop_buffer(ctx, buf); - obj = fz_dict_getsa(dict, "SMask", "Mask"); - if (fz_is_dict(obj)) - { - error = pdf_load_image_imp(&img->mask, xref, NULL, obj, NULL, 1); - if (error) + obj = fz_dict_getsa(dict, "SMask", "Mask"); + if (fz_is_dict(obj)) { - fz_drop_pixmap(img); - return fz_rethrow(error, "cannot load image mask/softmask"); + img->mask = pdf_load_image_imp(xref, NULL, obj, NULL, 1); + /* RJW: "cannot load image mask/softmask" */ } - } - obj = fz_dict_getsa(dict, "Decode", "D"); - if (obj) - { - float decode[FZ_MAX_COLORS * 2]; - int i; + obj = fz_dict_getsa(dict, "Decode", "D"); + if (obj) + { + float decode[FZ_MAX_COLORS * 2]; + int i; - for (i = 0; i < img->n * 2; i++) - decode[i] = fz_to_real(fz_array_get(obj, i)); + for (i = 0; i < img->n * 2; i++) + decode[i] = fz_to_real(fz_array_get(obj, i)); - fz_decode_tile(img, decode); + fz_decode_tile(img, decode); + } } - - *imgp = img; - return fz_okay; + fz_catch(ctx) + { + if (colorspace) + fz_drop_colorspace(ctx, colorspace); + fz_drop_buffer(ctx, buf); + fz_drop_pixmap(ctx, img); + } + return img; } -fz_error -pdf_load_image(fz_pixmap **pixp, pdf_xref *xref, fz_obj *dict) +fz_pixmap * +pdf_load_image(pdf_xref *xref, fz_obj *dict) { - fz_error error; + fz_context *ctx = xref->ctx; + fz_pixmap *pix; - if ((*pixp = pdf_find_item(xref->store, fz_drop_pixmap, dict))) + if ((pix = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)fz_drop_pixmap, dict))) { - fz_keep_pixmap(*pixp); - return fz_okay; + return fz_keep_pixmap(pix); } - error = pdf_load_image_imp(pixp, xref, NULL, dict, NULL, 0); - if (error) - return fz_rethrow(error, "cannot load image (%d 0 R)", fz_to_num(dict)); + pix = pdf_load_image_imp(xref, NULL, dict, NULL, 0); + /* RJW: "cannot load image (%d 0 R)", fz_to_num(dict) */ - pdf_store_item(xref->store, fz_keep_pixmap, fz_drop_pixmap, dict, *pixp); + pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)fz_keep_pixmap, (pdf_store_drop_fn *)fz_drop_pixmap, dict, pix); - return fz_okay; + return pix; } diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c index f598e9fb..6d312724 100644 --- a/pdf/pdf_interpret.c +++ b/pdf/pdf_interpret.c @@ -99,8 +99,8 @@ struct pdf_csi_s int gtop; }; -static fz_error pdf_run_buffer(pdf_csi *csi, fz_obj *rdb, fz_buffer *contents); -static fz_error pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix transform); +static void pdf_run_buffer(pdf_csi *csi, fz_obj *rdb, fz_buffer *contents); +static void pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix transform); static void pdf_show_pattern(pdf_csi *csi, pdf_pattern *pat, fz_rect area, int what); static int @@ -301,7 +301,6 @@ static void pdf_begin_group(pdf_csi *csi, fz_rect bbox) { pdf_gstate *gstate = csi->gstate + csi->gtop; - fz_error error; if (gstate->softmask) { @@ -314,9 +313,8 @@ pdf_begin_group(pdf_csi *csi, fz_rect bbox) fz_begin_mask(csi->dev, bbox, gstate->luminosity, softmask->colorspace, gstate->softmask_bc); - error = pdf_run_xobject(csi, NULL, softmask, fz_identity); - if (error) - fz_catch(error, "cannot run softmask"); + pdf_run_xobject(csi, NULL, softmask, fz_identity); + /* RJW: "cannot run softmask" */ fz_end_mask(csi->dev); gstate->softmask = softmask; @@ -425,15 +423,16 @@ pdf_show_image(pdf_csi *csi, fz_pixmap *image) static void pdf_show_path(pdf_csi *csi, int doclose, int dofill, int dostroke, int even_odd) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gstate = csi->gstate + csi->gtop; fz_path *path; fz_rect bbox; path = csi->path; - csi->path = fz_new_path(); + csi->path = fz_new_path(ctx); if (doclose) - fz_closepath(path); + fz_closepath(ctx, path); if (dostroke) bbox = fz_bound_path(path, &gstate->stroke_state, gstate->ctm); @@ -514,7 +513,7 @@ pdf_show_path(pdf_csi *csi, int doclose, int dofill, int dostroke, int even_odd) if (dofill || dostroke) pdf_end_group(csi); - fz_free_path(path); + fz_free_path(ctx, path); } /* @@ -531,6 +530,7 @@ pdf_flush_text(pdf_csi *csi) int doclip = 0; int doinvisible = 0; fz_rect bbox; + fz_context *ctx = csi->dev->ctx; if (!csi->text) return; @@ -628,12 +628,13 @@ pdf_flush_text(pdf_csi *csi) pdf_end_group(csi); - fz_free_text(text); + fz_free_text(ctx, text); } static void pdf_show_char(pdf_csi *csi, int cid) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_font_desc *fontdesc = gstate->font; fz_matrix tsm, trm; @@ -689,18 +690,18 @@ pdf_show_char(pdf_csi *csi, int cid) { pdf_flush_text(csi); - csi->text = fz_new_text(fontdesc->font, trm, fontdesc->wmode); + csi->text = fz_new_text(ctx, fontdesc->font, trm, fontdesc->wmode); csi->text->trm.e = 0; csi->text->trm.f = 0; csi->text_mode = gstate->render; } /* add glyph to textobject */ - fz_add_text(csi->text, gid, ucsbuf[0], trm.e, trm.f); + fz_add_text(ctx, csi->text, gid, ucsbuf[0], trm.e, trm.f); /* add filler glyphs for one-to-many unicode mapping */ for (i = 1; i < ucslen; i++) - fz_add_text(csi->text, -1, ucsbuf[i], trm.e, trm.f); + fz_add_text(ctx, csi->text, -1, ucsbuf[i], trm.e, trm.f); if (fontdesc->wmode == 0) { @@ -721,12 +722,13 @@ pdf_show_char(pdf_csi *csi, int cid) static void pdf_show_space(pdf_csi *csi, float tadj) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_font_desc *fontdesc = gstate->font; if (!fontdesc) { - fz_warn("cannot draw text since font and size not set"); + fz_warn(ctx, "cannot draw text since font and size not set"); return; } @@ -739,6 +741,7 @@ pdf_show_space(pdf_csi *csi, float tadj) static void pdf_show_string(pdf_csi *csi, unsigned char *buf, int len) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_font_desc *fontdesc = gstate->font; unsigned char *end = buf + len; @@ -746,7 +749,7 @@ pdf_show_string(pdf_csi *csi, unsigned char *buf, int len) if (!fontdesc) { - fz_warn("cannot draw text since font and size not set"); + fz_warn(ctx, "cannot draw text since font and size not set"); return; } @@ -757,7 +760,7 @@ pdf_show_string(pdf_csi *csi, unsigned char *buf, int len) if (cid >= 0) pdf_show_char(csi, cid); else - fz_warn("cannot encode character with code point %#x", cpt); + fz_warn(ctx, "cannot encode character with code point %#x", cpt); if (cpt == 32) pdf_show_space(csi, gstate->word_space); } @@ -771,7 +774,8 @@ pdf_show_text(pdf_csi *csi, fz_obj *text) if (fz_is_array(text)) { - for (i = 0; i < fz_array_len(text); i++) + int n = fz_array_len(text); + for (i = 0; i < n; i++) { fz_obj *item = fz_array_get(text, i); if (fz_is_string(item)) @@ -840,7 +844,7 @@ pdf_new_csi(pdf_xref *xref, fz_device *dev, fz_matrix ctm, char *event) { pdf_csi *csi; - csi = fz_malloc(sizeof(pdf_csi)); + csi = fz_malloc(dev->ctx, sizeof(pdf_csi)); csi->xref = xref; csi->dev = dev; csi->event = event; @@ -855,7 +859,7 @@ pdf_new_csi(pdf_xref *xref, fz_device *dev, fz_matrix ctm, char *event) csi->in_text = 0; csi->in_hidden_ocg = 0; - csi->path = fz_new_path(); + csi->path = fz_new_path(xref->ctx); csi->clip = 0; csi->clip_even_odd = 0; @@ -902,25 +906,26 @@ pdf_keep_material(pdf_material *mat) } static pdf_material * -pdf_drop_material(pdf_material *mat) +pdf_drop_material(fz_context *ctx, pdf_material *mat) { if (mat->colorspace) - fz_drop_colorspace(mat->colorspace); + fz_drop_colorspace(ctx, mat->colorspace); if (mat->pattern) - pdf_drop_pattern(mat->pattern); + pdf_drop_pattern(ctx, mat->pattern); if (mat->shade) - fz_drop_shade(mat->shade); + fz_drop_shade(ctx, mat->shade); return mat; } static void pdf_gsave(pdf_csi *csi) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gs = csi->gstate + csi->gtop; if (csi->gtop == nelem(csi->gstate) - 1) { - fz_warn("gstate overflow in content stream"); + fz_warn(ctx, "gstate overflow in content stream"); return; } @@ -939,21 +944,22 @@ pdf_gsave(pdf_csi *csi) static void pdf_grestore(pdf_csi *csi) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gs = csi->gstate + csi->gtop; int clip_depth = gs->clip_depth; if (csi->gtop == 0) { - fz_warn("gstate underflow in content stream"); + fz_warn(ctx, "gstate underflow in content stream"); return; } - pdf_drop_material(&gs->stroke); - pdf_drop_material(&gs->fill); + pdf_drop_material(ctx, &gs->stroke); + pdf_drop_material(ctx, &gs->fill); if (gs->font) - pdf_drop_font(gs->font); + pdf_drop_font(ctx, gs->font); if (gs->softmask) - pdf_drop_xobject(gs->softmask); + pdf_drop_xobject(ctx, gs->softmask); csi->gtop --; @@ -968,25 +974,27 @@ pdf_grestore(pdf_csi *csi) static void pdf_free_csi(pdf_csi *csi) { + fz_context *ctx = csi->dev->ctx; + while (csi->gtop) pdf_grestore(csi); - pdf_drop_material(&csi->gstate[0].fill); - pdf_drop_material(&csi->gstate[0].stroke); + pdf_drop_material(ctx, &csi->gstate[0].fill); + pdf_drop_material(ctx, &csi->gstate[0].stroke); if (csi->gstate[0].font) - pdf_drop_font(csi->gstate[0].font); + pdf_drop_font(ctx, csi->gstate[0].font); if (csi->gstate[0].softmask) - pdf_drop_xobject(csi->gstate[0].softmask); + pdf_drop_xobject(ctx, csi->gstate[0].softmask); while (csi->gstate[0].clip_depth--) fz_pop_clip(csi->dev); - if (csi->path) fz_free_path(csi->path); - if (csi->text) fz_free_text(csi->text); + if (csi->path) fz_free_path(ctx, csi->path); + if (csi->text) fz_free_text(ctx, csi->text); pdf_clear_stack(csi); - fz_free(csi); + fz_free(ctx, csi); } /* @@ -996,6 +1004,7 @@ pdf_free_csi(pdf_csi *csi) static void pdf_set_colorspace(pdf_csi *csi, int what, fz_colorspace *colorspace) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gs = csi->gstate + csi->gtop; pdf_material *mat; @@ -1003,7 +1012,7 @@ pdf_set_colorspace(pdf_csi *csi, int what, fz_colorspace *colorspace) mat = what == PDF_FILL ? &gs->fill : &gs->stroke; - fz_drop_colorspace(mat->colorspace); + fz_drop_colorspace(ctx, mat->colorspace); mat->kind = PDF_MAT_COLOR; mat->colorspace = fz_keep_colorspace(colorspace); @@ -1017,6 +1026,7 @@ pdf_set_colorspace(pdf_csi *csi, int what, fz_colorspace *colorspace) static void pdf_set_color(pdf_csi *csi, int what, float *v) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gs = csi->gstate + csi->gtop; pdf_material *mat; int i; @@ -1039,13 +1049,14 @@ pdf_set_color(pdf_csi *csi, int what, float *v) mat->v[i] = v[i]; break; default: - fz_warn("color incompatible with material"); + fz_warn(ctx, "color incompatible with material"); } } static void pdf_set_shade(pdf_csi *csi, int what, fz_shade *shade) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gs = csi->gstate + csi->gtop; pdf_material *mat; @@ -1054,7 +1065,7 @@ pdf_set_shade(pdf_csi *csi, int what, fz_shade *shade) mat = what == PDF_FILL ? &gs->fill : &gs->stroke; if (mat->shade) - fz_drop_shade(mat->shade); + fz_drop_shade(ctx, mat->shade); mat->kind = PDF_MAT_SHADE; mat->shade = fz_keep_shade(shade); @@ -1063,6 +1074,7 @@ pdf_set_shade(pdf_csi *csi, int what, fz_shade *shade) static void pdf_set_pattern(pdf_csi *csi, int what, pdf_pattern *pat, float *v) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gs = csi->gstate + csi->gtop; pdf_material *mat; @@ -1071,7 +1083,7 @@ pdf_set_pattern(pdf_csi *csi, int what, pdf_pattern *pat, float *v) mat = what == PDF_FILL ? &gs->fill : &gs->stroke; if (mat->pattern) - pdf_drop_pattern(mat->pattern); + pdf_drop_pattern(ctx, mat->pattern); mat->kind = PDF_MAT_PATTERN; if (pat) @@ -1086,13 +1098,14 @@ pdf_set_pattern(pdf_csi *csi, int what, pdf_pattern *pat, float *v) static void pdf_unset_pattern(pdf_csi *csi, int what) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gs = csi->gstate + csi->gtop; pdf_material *mat; mat = what == PDF_FILL ? &gs->fill : &gs->stroke; if (mat->kind == PDF_MAT_PATTERN) { if (mat->pattern) - pdf_drop_pattern(mat->pattern); + pdf_drop_pattern(ctx, mat->pattern); mat->pattern = NULL; mat->kind = PDF_MAT_COLOR; } @@ -1105,10 +1118,10 @@ pdf_unset_pattern(pdf_csi *csi, int what) static void pdf_show_pattern(pdf_csi *csi, pdf_pattern *pat, fz_rect area, int what) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gstate; fz_matrix ptm, invptm; fz_matrix oldtopctm; - fz_error error; int x0, y0, x1, y1; int oldtop; @@ -1121,13 +1134,13 @@ pdf_show_pattern(pdf_csi *csi, pdf_pattern *pat, fz_rect area, int what) pdf_unset_pattern(csi, PDF_STROKE); if (what == PDF_FILL) { - pdf_drop_material(&gstate->stroke); + pdf_drop_material(ctx, &gstate->stroke); pdf_keep_material(&gstate->fill); gstate->stroke = gstate->fill; } if (what == PDF_STROKE) { - pdf_drop_material(&gstate->fill); + pdf_drop_material(ctx, &gstate->fill); pdf_keep_material(&gstate->stroke); gstate->fill = gstate->stroke; } @@ -1141,7 +1154,7 @@ pdf_show_pattern(pdf_csi *csi, pdf_pattern *pat, fz_rect area, int what) /* don't apply softmasks to objects in the pattern as well */ if (gstate->softmask) { - pdf_drop_xobject(gstate->softmask); + pdf_drop_xobject(ctx, gstate->softmask); gstate->softmask = NULL; } @@ -1174,9 +1187,8 @@ pdf_show_pattern(pdf_csi *csi, pdf_pattern *pat, fz_rect area, int what) gstate->ctm = ptm; csi->top_ctm = gstate->ctm; pdf_gsave(csi); - error = pdf_run_buffer(csi, pat->resources, pat->contents); - if (error) - fz_catch(error, "cannot render pattern tile"); + pdf_run_buffer(csi, pat->resources, pat->contents); + /* RJW: "cannot render pattern tile" */ pdf_grestore(csi); while (oldtop < csi->gtop) pdf_grestore(csi); @@ -1192,29 +1204,33 @@ pdf_show_pattern(pdf_csi *csi, pdf_pattern *pat, fz_rect area, int what) gstate->ctm = fz_concat(fz_translate(x * pat->xstep, y * pat->ystep), ptm); csi->top_ctm = gstate->ctm; pdf_gsave(csi); - error = pdf_run_buffer(csi, pat->resources, pat->contents); + fz_try(ctx) + { + pdf_run_buffer(csi, pat->resources, pat->contents); + } + fz_catch(ctx) + { + pdf_grestore(csi); + while (oldtop < csi->gtop) + pdf_grestore(csi); + csi->top_ctm = oldtopctm; + fz_throw(ctx, "cannot render pattern tile"); + } pdf_grestore(csi); while (oldtop < csi->gtop) pdf_grestore(csi); - if (error) - { - fz_catch(error, "cannot render pattern tile"); - goto cleanup; - } } } } -cleanup: - csi->top_ctm = oldtopctm; pdf_grestore(csi); } -static fz_error +static void pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix transform) { - fz_error error; + fz_context *ctx = csi->dev->ctx; pdf_gstate *gstate; fz_matrix oldtopctm; int oldtop; @@ -1243,12 +1259,11 @@ pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix tr fz_begin_mask(csi->dev, bbox, gstate->luminosity, softmask->colorspace, gstate->softmask_bc); - error = pdf_run_xobject(csi, resources, softmask, fz_identity); - if (error) - return fz_rethrow(error, "cannot run softmask"); + pdf_run_xobject(csi, resources, softmask, fz_identity); + /* RJW: "cannot run softmask" */ fz_end_mask(csi->dev); - pdf_drop_xobject(softmask); + pdf_drop_xobject(ctx, softmask); } fz_begin_group(csi->dev, @@ -1262,11 +1277,11 @@ pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix tr /* clip to the bounds */ - fz_moveto(csi->path, xobj->bbox.x0, xobj->bbox.y0); - fz_lineto(csi->path, xobj->bbox.x1, xobj->bbox.y0); - fz_lineto(csi->path, xobj->bbox.x1, xobj->bbox.y1); - fz_lineto(csi->path, xobj->bbox.x0, xobj->bbox.y1); - fz_closepath(csi->path); + fz_moveto(ctx, csi->path, xobj->bbox.x0, xobj->bbox.y0); + fz_lineto(ctx, csi->path, xobj->bbox.x1, xobj->bbox.y0); + fz_lineto(ctx, csi->path, xobj->bbox.x1, xobj->bbox.y1); + fz_lineto(ctx, csi->path, xobj->bbox.x0, xobj->bbox.y1); + fz_closepath(ctx, csi->path); csi->clip = 1; pdf_show_path(csi, 0, 0, 0, 0); @@ -1278,9 +1293,8 @@ pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix tr if (xobj->resources) resources = xobj->resources; - error = pdf_run_buffer(csi, resources, xobj->contents); - if (error) - fz_catch(error, "cannot interpret XObject stream"); + pdf_run_buffer(csi, resources, xobj->contents); + /* RJW: "cannot interpret XObject stream" */ csi->top_ctm = oldtopctm; @@ -1297,20 +1311,20 @@ pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix tr if (popmask) fz_pop_clip(csi->dev); } - - return fz_okay; } -static fz_error +static void pdf_run_extgstate(pdf_csi *csi, fz_obj *rdb, fz_obj *extgstate) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gstate = csi->gstate + csi->gtop; fz_colorspace *colorspace; - int i, k; + int i, k, n; pdf_flush_text(csi); - for (i = 0; i < fz_dict_len(extgstate); i++) + n = fz_dict_len(extgstate); + for (i = 0; i < n; i++) { fz_obj *key = fz_dict_get_key(extgstate, i); fz_obj *val = fz_dict_get_val(extgstate, i); @@ -1320,24 +1334,22 @@ pdf_run_extgstate(pdf_csi *csi, fz_obj *rdb, fz_obj *extgstate) { if (fz_is_array(val) && fz_array_len(val) == 2) { - fz_error error; fz_obj *font = fz_array_get(val, 0); if (gstate->font) { - pdf_drop_font(gstate->font); + pdf_drop_font(ctx, gstate->font); gstate->font = NULL; } - error = pdf_load_font(&gstate->font, csi->xref, rdb, font); - if (error) - return fz_rethrow(error, "cannot load font (%d %d R)", fz_to_num(font), fz_to_gen(font)); + gstate->font = pdf_load_font(csi->xref, rdb, font); + /* RJW: "cannot load font (%d %d R)", fz_to_num(font), fz_to_gen(font) */ if (!gstate->font) - return fz_throw("cannot find font in store"); + fz_throw(ctx, "cannot find font in store"); gstate->size = fz_to_real(fz_array_get(val, 1)); } else - return fz_throw("malformed /Font dictionary"); + fz_throw(ctx, "malformed /Font dictionary"); } else if (!strcmp(s, "LC")) @@ -1364,7 +1376,7 @@ pdf_run_extgstate(pdf_csi *csi, fz_obj *rdb, fz_obj *extgstate) gstate->stroke_state.dash_phase = fz_to_real(fz_array_get(val, 1)); } else - return fz_throw("malformed /D"); + fz_throw(ctx, "malformed /D"); } else if (!strcmp(s, "CA")) @@ -1384,22 +1396,20 @@ pdf_run_extgstate(pdf_csi *csi, fz_obj *rdb, fz_obj *extgstate) { if (fz_is_dict(val)) { - fz_error error; pdf_xobject *xobj; fz_obj *group, *luminosity, *bc; if (gstate->softmask) { - pdf_drop_xobject(gstate->softmask); + pdf_drop_xobject(ctx, gstate->softmask); gstate->softmask = NULL; } group = fz_dict_gets(val, "G"); if (!group) - return fz_throw("cannot load softmask xobject (%d %d R)", fz_to_num(val), fz_to_gen(val)); - error = pdf_load_xobject(&xobj, csi->xref, group); - if (error) - return fz_rethrow(error, "cannot load xobject (%d %d R)", fz_to_num(val), fz_to_gen(val)); + fz_throw(ctx, "cannot load softmask xobject (%d %d R)", fz_to_num(val), fz_to_gen(val)); + xobj = pdf_load_xobject(csi->xref, group); + /* RJW: "cannot load xobject (%d %d R)", fz_to_num(val), fz_to_gen(val) */ colorspace = xobj->colorspace; if (!colorspace) @@ -1427,7 +1437,7 @@ pdf_run_extgstate(pdf_csi *csi, fz_obj *rdb, fz_obj *extgstate) { if (gstate->softmask) { - pdf_drop_xobject(gstate->softmask); + pdf_drop_xobject(ctx, gstate->softmask); gstate->softmask = NULL; } } @@ -1436,11 +1446,9 @@ pdf_run_extgstate(pdf_csi *csi, fz_obj *rdb, fz_obj *extgstate) else if (!strcmp(s, "TR")) { if (fz_is_name(val) && strcmp(fz_to_name(val), "Identity")) - fz_warn("ignoring transfer function"); + fz_warn(ctx, "ignoring transfer function"); } } - - return fz_okay; } /* @@ -1476,18 +1484,17 @@ static void pdf_run_BDC(pdf_csi *csi, fz_obj *rdb) csi->in_hidden_ocg++; } -static fz_error pdf_run_BI(pdf_csi *csi, fz_obj *rdb, fz_stream *file) +static void pdf_run_BI(pdf_csi *csi, fz_obj *rdb, fz_stream *file) { + fz_context *ctx = csi->dev->ctx; int ch; - fz_error error; char *buf = csi->xref->scratch; int buflen = sizeof(csi->xref->scratch); fz_pixmap *img; fz_obj *obj; - error = pdf_parse_dict(&obj, csi->xref, file, buf, buflen); - if (error) - return fz_rethrow(error, "cannot parse inline image dictionary"); + obj = pdf_parse_dict(csi->xref, file, buf, buflen); + /* RJW: "cannot parse inline image dictionary" */ /* read whitespace after ID keyword */ ch = fz_read_byte(file); @@ -1495,14 +1502,13 @@ static fz_error pdf_run_BI(pdf_csi *csi, fz_obj *rdb, fz_stream *file) if (fz_peek_byte(file) == '\n') fz_read_byte(file); - error = pdf_load_inline_image(&img, csi->xref, rdb, obj, file); + img = pdf_load_inline_image(csi->xref, rdb, obj, file); fz_drop_obj(obj); - if (error) - return fz_rethrow(error, "cannot load inline image"); + /* RJW: "cannot load inline image" */ pdf_show_image(csi, img); - fz_drop_pixmap(img); + fz_drop_pixmap(ctx, img); /* find EI */ ch = fz_read_byte(file); @@ -1510,9 +1516,7 @@ static fz_error pdf_run_BI(pdf_csi *csi, fz_obj *rdb, fz_stream *file) ch = fz_read_byte(file); ch = fz_read_byte(file); if (ch != 'I') - return fz_rethrow(error, "syntax error after inline image"); - - return fz_okay; + fz_throw(ctx, "syntax error after inline image"); } static void pdf_run_B(pdf_csi *csi) @@ -1548,11 +1552,11 @@ static void pdf_run_Bstar(pdf_csi *csi) pdf_show_path(csi, 0, 1, 1, 1); } -static fz_error pdf_run_cs_imp(pdf_csi *csi, fz_obj *rdb, int what) +static void pdf_run_cs_imp(pdf_csi *csi, fz_obj *rdb, int what) { + fz_context *ctx = csi->dev->ctx; fz_colorspace *colorspace; fz_obj *obj, *dict; - fz_error error; if (!strcmp(csi->name, "Pattern")) { @@ -1570,63 +1574,57 @@ static fz_error pdf_run_cs_imp(pdf_csi *csi, fz_obj *rdb, int what) { dict = fz_dict_gets(rdb, "ColorSpace"); if (!dict) - return fz_throw("cannot find ColorSpace dictionary"); + fz_throw(ctx, "cannot find ColorSpace dictionary"); obj = fz_dict_gets(dict, csi->name); if (!obj) - return fz_throw("cannot find colorspace resource '%s'", csi->name); - error = pdf_load_colorspace(&colorspace, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load colorspace (%d 0 R)", fz_to_num(obj)); + fz_throw(ctx, "cannot find colorspace resource '%s'", csi->name); + colorspace = pdf_load_colorspace(csi->xref, obj); + /* RJW: "cannot load colorspace (%d 0 R)", fz_to_num(obj) */ } pdf_set_colorspace(csi, what, colorspace); - fz_drop_colorspace(colorspace); + fz_drop_colorspace(ctx, colorspace); } - return fz_okay; } static void pdf_run_CS(pdf_csi *csi, fz_obj *rdb) { - fz_error error; - error = pdf_run_cs_imp(csi, rdb, PDF_STROKE); - if (error) - fz_catch(error, "cannot set colorspace"); + pdf_run_cs_imp(csi, rdb, PDF_STROKE); + /* RJW: "cannot set colorspace" */ } static void pdf_run_cs(pdf_csi *csi, fz_obj *rdb) { - fz_error error; - error = pdf_run_cs_imp(csi, rdb, PDF_FILL); - if (error) - fz_catch(error, "cannot set colorspace"); + pdf_run_cs_imp(csi, rdb, PDF_FILL); + /* RJW: "cannot set colorspace" */ } static void pdf_run_DP(pdf_csi *csi) { } -static fz_error pdf_run_Do(pdf_csi *csi, fz_obj *rdb) +static void pdf_run_Do(pdf_csi *csi, fz_obj *rdb) { + fz_context *ctx = csi->dev->ctx; fz_obj *dict; fz_obj *obj; fz_obj *subtype; - fz_error error; dict = fz_dict_gets(rdb, "XObject"); if (!dict) - return fz_throw("cannot find XObject dictionary when looking for: '%s'", csi->name); + fz_throw(ctx, "cannot find XObject dictionary when looking for: '%s'", csi->name); obj = fz_dict_gets(dict, csi->name); if (!obj) - return fz_throw("cannot find xobject resource: '%s'", csi->name); + fz_throw(ctx, "cannot find xobject resource: '%s'", csi->name); subtype = fz_dict_gets(obj, "Subtype"); if (!fz_is_name(subtype)) - return fz_throw("no XObject subtype specified"); + fz_throw(ctx, "no XObject subtype specified"); if (pdf_is_hidden_ocg(fz_dict_gets(obj, "OC"), csi, rdb)) - return fz_okay; + return; if (!strcmp(fz_to_name(subtype), "Form") && fz_dict_gets(obj, "Subtype2")) subtype = fz_dict_gets(obj, "Subtype2"); @@ -1635,19 +1633,17 @@ static fz_error pdf_run_Do(pdf_csi *csi, fz_obj *rdb) { pdf_xobject *xobj; - error = pdf_load_xobject(&xobj, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load xobject (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); + xobj = pdf_load_xobject(csi->xref, obj); + /* RJW: "cannot load xobject (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */ /* Inherit parent resources, in case this one was empty XXX check where it's loaded */ if (!xobj->resources) xobj->resources = fz_keep_obj(rdb); - error = pdf_run_xobject(csi, xobj->resources, xobj, fz_identity); - if (error) - return fz_rethrow(error, "cannot draw xobject (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); + pdf_run_xobject(csi, xobj->resources, xobj, fz_identity); + /* RJW: "cannot draw xobject (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */ - pdf_drop_xobject(xobj); + pdf_drop_xobject(ctx, xobj); } else if (!strcmp(fz_to_name(subtype), "Image")) @@ -1655,25 +1651,22 @@ static fz_error pdf_run_Do(pdf_csi *csi, fz_obj *rdb) if ((csi->dev->hints & FZ_IGNORE_IMAGE) == 0) { fz_pixmap *img; - error = pdf_load_image(&img, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load image (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); + img = pdf_load_image(csi->xref, obj); + /* RJW: "cannot load image (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */ pdf_show_image(csi, img); - fz_drop_pixmap(img); + fz_drop_pixmap(ctx, img); } } else if (!strcmp(fz_to_name(subtype), "PS")) { - fz_warn("ignoring XObject with subtype PS"); + fz_warn(ctx, "ignoring XObject with subtype PS"); } else { - return fz_throw("unknown XObject subtype: '%s'", fz_to_name(subtype)); + fz_throw(ctx, "unknown XObject subtype: '%s'", fz_to_name(subtype)); } - - return fz_okay; } static void pdf_run_EMC(pdf_csi *csi) @@ -1745,9 +1738,9 @@ static void pdf_run_S(pdf_csi *csi) pdf_show_path(csi, 0, 0, 1, 0); } -static fz_error pdf_run_SC_imp(pdf_csi *csi, fz_obj *rdb, int what, pdf_material *mat) +static void pdf_run_SC_imp(pdf_csi *csi, fz_obj *rdb, int what, pdf_material *mat) { - fz_error error; + fz_context *ctx = csi->dev->ctx; fz_obj *patterntype; fz_obj *dict; fz_obj *obj; @@ -1760,7 +1753,7 @@ static fz_error pdf_run_SC_imp(pdf_csi *csi, fz_obj *rdb, int what, pdf_material switch (kind) { case PDF_MAT_NONE: - return fz_throw("cannot set color in mask objects"); + fz_throw(ctx, "cannot set color in mask objects"); case PDF_MAT_COLOR: pdf_set_color(csi, what, csi->stack); @@ -1769,61 +1762,53 @@ static fz_error pdf_run_SC_imp(pdf_csi *csi, fz_obj *rdb, int what, pdf_material case PDF_MAT_PATTERN: dict = fz_dict_gets(rdb, "Pattern"); if (!dict) - return fz_throw("cannot find Pattern dictionary"); + fz_throw(ctx, "cannot find Pattern dictionary"); obj = fz_dict_gets(dict, csi->name); if (!obj) - return fz_throw("cannot find pattern resource '%s'", csi->name); + fz_throw(ctx, "cannot find pattern resource '%s'", csi->name); patterntype = fz_dict_gets(obj, "PatternType"); if (fz_to_int(patterntype) == 1) { pdf_pattern *pat; - error = pdf_load_pattern(&pat, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load pattern (%d 0 R)", fz_to_num(obj)); + pat = pdf_load_pattern(csi->xref, obj); + /* RJW: "cannot load pattern (%d 0 R)", fz_to_num(obj) */ pdf_set_pattern(csi, what, pat, csi->top > 0 ? csi->stack : NULL); - pdf_drop_pattern(pat); + pdf_drop_pattern(ctx, pat); } else if (fz_to_int(patterntype) == 2) { fz_shade *shd; - error = pdf_load_shading(&shd, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load shading (%d 0 R)", fz_to_num(obj)); + shd = pdf_load_shading(csi->xref, obj); + /* RJW: "cannot load shading (%d 0 R)", fz_to_num(obj) */ pdf_set_shade(csi, what, shd); - fz_drop_shade(shd); + fz_drop_shade(ctx, shd); } else { - return fz_throw("unknown pattern type: %d", fz_to_int(patterntype)); + fz_throw(ctx, "unknown pattern type: %d", fz_to_int(patterntype)); } break; case PDF_MAT_SHADE: - return fz_throw("cannot set color in shade objects"); + fz_throw(ctx, "cannot set color in shade objects"); } - - return fz_okay; } static void pdf_run_SC(pdf_csi *csi, fz_obj *rdb) { - fz_error error; pdf_gstate *gstate = csi->gstate + csi->gtop; - error = pdf_run_SC_imp(csi, rdb, PDF_STROKE, &gstate->stroke); - if (error) - fz_catch(error, "cannot set color and colorspace"); + pdf_run_SC_imp(csi, rdb, PDF_STROKE, &gstate->stroke); + /* RJW: "cannot set color and colorspace" */ } static void pdf_run_sc(pdf_csi *csi, fz_obj *rdb) { - fz_error error; pdf_gstate *gstate = csi->gstate + csi->gtop; - error = pdf_run_SC_imp(csi, rdb, PDF_FILL, &gstate->fill); - if (error) - fz_catch(error, "cannot set color and colorspace"); + pdf_run_SC_imp(csi, rdb, PDF_FILL, &gstate->fill); + /* RJW: "cannot set color and colorspace" */ } static void pdf_run_Tc(pdf_csi *csi) @@ -1852,31 +1837,28 @@ static void pdf_run_TL(pdf_csi *csi) gstate->leading = csi->stack[0]; } -static fz_error pdf_run_Tf(pdf_csi *csi, fz_obj *rdb) +static void pdf_run_Tf(pdf_csi *csi, fz_obj *rdb) { + fz_context *ctx = csi->dev->ctx; pdf_gstate *gstate = csi->gstate + csi->gtop; - fz_error error; fz_obj *dict; fz_obj *obj; gstate->size = csi->stack[0]; if (gstate->font) - pdf_drop_font(gstate->font); + pdf_drop_font(ctx, gstate->font); gstate->font = NULL; dict = fz_dict_gets(rdb, "Font"); if (!dict) - return fz_throw("cannot find Font dictionary"); + fz_throw(ctx, "cannot find Font dictionary"); obj = fz_dict_gets(dict, csi->name); if (!obj) - return fz_throw("cannot find font resource: '%s'", csi->name); + fz_throw(ctx, "cannot find font resource: '%s'", csi->name); - error = pdf_load_font(&gstate->font, csi->xref, rdb, obj); - if (error) - return fz_rethrow(error, "cannot load font (%d 0 R)", fz_to_num(obj)); - - return fz_okay; + gstate->font = pdf_load_font(csi->xref, rdb, obj); + /* RJW: "cannot load font (%d 0 R)", fz_to_num(obj) */ } static void pdf_run_Tr(pdf_csi *csi) @@ -1975,7 +1957,7 @@ static void pdf_run_c(pdf_csi *csi) d = csi->stack[3]; e = csi->stack[4]; f = csi->stack[5]; - fz_curveto(csi->path, a, b, c, d, e, f); + fz_curveto(csi->dev->ctx, csi->path, a, b, c, d, e, f); } static void pdf_run_cm(pdf_csi *csi) @@ -2032,29 +2014,27 @@ static void pdf_run_g(pdf_csi *csi) pdf_set_color(csi, PDF_FILL, csi->stack); } -static fz_error pdf_run_gs(pdf_csi *csi, fz_obj *rdb) +static void pdf_run_gs(pdf_csi *csi, fz_obj *rdb) { - fz_error error; fz_obj *dict; fz_obj *obj; + fz_context *ctx = csi->dev->ctx; dict = fz_dict_gets(rdb, "ExtGState"); if (!dict) - return fz_throw("cannot find ExtGState dictionary"); + fz_throw(ctx, "cannot find ExtGState dictionary"); obj = fz_dict_gets(dict, csi->name); if (!obj) - return fz_throw("cannot find extgstate resource '%s'", csi->name); + fz_throw(ctx, "cannot find extgstate resource '%s'", csi->name); - error = pdf_run_extgstate(csi, rdb, obj); - if (error) - return fz_rethrow(error, "cannot set ExtGState (%d 0 R)", fz_to_num(obj)); - return fz_okay; + pdf_run_extgstate(csi, rdb, obj); + /* RJW: "cannot set ExtGState (%d 0 R)", fz_to_num(obj) */ } static void pdf_run_h(pdf_csi *csi) { - fz_closepath(csi->path); + fz_closepath(csi->dev->ctx, csi->path); } static void pdf_run_i(pdf_csi *csi) @@ -2078,7 +2058,7 @@ static void pdf_run_l(pdf_csi *csi) float a, b; a = csi->stack[0]; b = csi->stack[1]; - fz_lineto(csi->path, a, b); + fz_lineto(csi->dev->ctx, csi->path, a, b); } static void pdf_run_m(pdf_csi *csi) @@ -2086,7 +2066,7 @@ static void pdf_run_m(pdf_csi *csi) float a, b; a = csi->stack[0]; b = csi->stack[1]; - fz_moveto(csi->path, a, b); + fz_moveto(csi->dev->ctx, csi->path, a, b); } static void pdf_run_n(pdf_csi *csi) @@ -2101,6 +2081,7 @@ static void pdf_run_q(pdf_csi *csi) static void pdf_run_re(pdf_csi *csi) { + fz_context *ctx = csi->dev->ctx; float x, y, w, h; x = csi->stack[0]; @@ -2108,11 +2089,11 @@ static void pdf_run_re(pdf_csi *csi) w = csi->stack[2]; h = csi->stack[3]; - fz_moveto(csi->path, x, y); - fz_lineto(csi->path, x + w, y); - fz_lineto(csi->path, x + w, y + h); - fz_lineto(csi->path, x, y + h); - fz_closepath(csi->path); + fz_moveto(ctx, csi->path, x, y); + fz_lineto(ctx, csi->path, x + w, y); + fz_lineto(ctx, csi->path, x + w, y + h); + fz_lineto(ctx, csi->path, x, y + h); + fz_closepath(ctx, csi->path); } static void pdf_run_rg(pdf_csi *csi) @@ -2130,30 +2111,28 @@ static void pdf_run(pdf_csi *csi) pdf_show_path(csi, 1, 0, 1, 0); } -static fz_error pdf_run_sh(pdf_csi *csi, fz_obj *rdb) +static void pdf_run_sh(pdf_csi *csi, fz_obj *rdb) { + fz_context *ctx = csi->dev->ctx; fz_obj *dict; fz_obj *obj; fz_shade *shd; - fz_error error; dict = fz_dict_gets(rdb, "Shading"); if (!dict) - return fz_throw("cannot find shading dictionary"); + fz_throw(ctx, "cannot find shading dictionary"); obj = fz_dict_gets(dict, csi->name); if (!obj) - return fz_throw("cannot find shading resource: '%s'", csi->name); + fz_throw(ctx, "cannot find shading resource: '%s'", csi->name); if ((csi->dev->hints & FZ_IGNORE_SHADE) == 0) { - error = pdf_load_shading(&shd, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load shading (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); + shd = pdf_load_shading(csi->xref, obj); + /* RJW: "cannot load shading (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */ pdf_show_shade(csi, shd); - fz_drop_shade(shd); + fz_drop_shade(ctx, shd); } - return fz_okay; } static void pdf_run_v(pdf_csi *csi) @@ -2163,7 +2142,7 @@ static void pdf_run_v(pdf_csi *csi) b = csi->stack[1]; c = csi->stack[2]; d = csi->stack[3]; - fz_curvetov(csi->path, a, b, c, d); + fz_curvetov(csi->dev->ctx, csi->path, a, b, c, d); } static void pdf_run_w(pdf_csi *csi) @@ -2180,7 +2159,7 @@ static void pdf_run_y(pdf_csi *csi) b = csi->stack[1]; c = csi->stack[2]; d = csi->stack[3]; - fz_curvetoy(csi->path, a, b, c, d); + fz_curvetoy(csi->dev->ctx, csi->path, a, b, c, d); } static void pdf_run_squote(pdf_csi *csi) @@ -2220,10 +2199,10 @@ static void pdf_run_dquote(pdf_csi *csi) #define B(a,b) (a | b << 8) #define C(a,b,c) (a | b << 8 | c << 16) -static fz_error +static void pdf_run_keyword(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf) { - fz_error error; + fz_context *ctx = csi->dev->ctx; int key; key = buf[0]; @@ -2246,9 +2225,8 @@ pdf_run_keyword(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf) case B('B','*'): pdf_run_Bstar(csi); break; case C('B','D','C'): pdf_run_BDC(csi, rdb); break; case B('B','I'): - error = pdf_run_BI(csi, rdb, file); - if (error) - return fz_rethrow(error, "cannot draw inline image"); + pdf_run_BI(csi, rdb, file); + /* RJW: "cannot draw inline image" */ break; case C('B','M','C'): pdf_run_BMC(csi); break; case B('B','T'): pdf_run_BT(csi); break; @@ -2256,9 +2234,14 @@ pdf_run_keyword(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf) case B('C','S'): pdf_run_CS(csi, rdb); break; case B('D','P'): pdf_run_DP(csi); break; case B('D','o'): - error = pdf_run_Do(csi, rdb); - if (error) - fz_catch(error, "cannot draw xobject/image"); + fz_try(ctx) + { + pdf_run_Do(csi, rdb); + } + fz_catch(ctx) + { + fz_warn(ctx, "cannot draw xobject/image"); + } break; case C('E','M','C'): pdf_run_EMC(csi); break; case B('E','T'): pdf_run_ET(csi); break; @@ -2281,9 +2264,14 @@ pdf_run_keyword(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf) case B('T','c'): pdf_run_Tc(csi); break; case B('T','d'): pdf_run_Td(csi); break; case B('T','f'): - error = pdf_run_Tf(csi, rdb); - if (error) - fz_catch(error, "cannot set font"); + fz_try(ctx) + { + pdf_run_Tf(csi, rdb); + } + fz_catch(ctx) + { + fz_warn(ctx, "cannot set font"); + } break; case B('T','j'): pdf_run_Tj(csi); break; case B('T','m'): pdf_run_Tm(csi); break; @@ -2305,9 +2293,14 @@ pdf_run_keyword(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf) case B('f','*'): pdf_run_fstar(csi); break; case A('g'): pdf_run_g(csi); break; case B('g','s'): - error = pdf_run_gs(csi, rdb); - if (error) - fz_catch(error, "cannot set graphics state"); + fz_try(ctx) + { + pdf_run_gs(csi, rdb); + } + fz_catch(ctx) + { + fz_warn(ctx, "cannot set graphics state"); + } break; case A('h'): pdf_run_h(csi); break; case A('i'): pdf_run_i(csi); break; @@ -2324,26 +2317,29 @@ pdf_run_keyword(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf) case B('s','c'): pdf_run_sc(csi, rdb); break; case C('s','c','n'): pdf_run_sc(csi, rdb); break; case B('s','h'): - error = pdf_run_sh(csi, rdb); - if (error) - fz_catch(error, "cannot draw shading"); + fz_try(ctx) + { + pdf_run_sh(csi, rdb); + } + fz_catch(ctx) + { + fz_warn(ctx, "cannot draw shading"); + } break; case A('v'): pdf_run_v(csi); break; case A('w'): pdf_run_w(csi); break; case A('y'): pdf_run_y(csi); break; default: if (!csi->xbalance) - fz_warn("unknown keyword: '%s'", buf); + fz_warn(ctx, "unknown keyword: '%s'", buf); break; } - - return fz_okay; } -static fz_error +static void pdf_run_stream(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen) { - fz_error error; + fz_context *ctx = csi->dev->ctx; int tok, len, in_array; /* make sure we have a clean slate if we come here from flush_text */ @@ -2353,11 +2349,10 @@ pdf_run_stream(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen while (1) { if (csi->top == nelem(csi->stack) - 1) - return fz_throw("stack overflow"); + fz_throw(ctx, "stack overflow"); - error = pdf_lex(&tok, file, buf, buflen, &len); - if (error) - return fz_rethrow(error, "lexical error in content stream"); + tok = pdf_lex(file, buf, buflen, &len); + /* RJW: "lexical error in content stream" */ if (in_array) { @@ -2377,28 +2372,27 @@ pdf_run_stream(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen else if (tok == PDF_TOK_KEYWORD) { if (!strcmp(buf, "Tw") || !strcmp(buf, "Tc")) - fz_warn("ignoring keyword '%s' inside array", buf); + fz_warn(ctx, "ignoring keyword '%s' inside array", buf); else - return fz_throw("syntax error in array"); + fz_throw(ctx, "syntax error in array"); } else if (tok == PDF_TOK_EOF) - return fz_okay; + return; else - return fz_throw("syntax error in array"); + fz_throw(ctx, "syntax error in array"); } else switch (tok) { case PDF_TOK_ENDSTREAM: case PDF_TOK_EOF: - return fz_okay; + return; case PDF_TOK_OPEN_ARRAY: if (!csi->in_text) { - error = pdf_parse_array(&csi->obj, csi->xref, file, buf, buflen); - if (error) - return fz_rethrow(error, "cannot parse array"); + csi->obj = pdf_parse_array(csi->xref, file, buf, buflen); + /* RJW: "cannot parse array" */ } else { @@ -2407,9 +2401,8 @@ pdf_run_stream(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen break; case PDF_TOK_OPEN_DICT: - error = pdf_parse_dict(&csi->obj, csi->xref, file, buf, buflen); - if (error) - return fz_rethrow(error, "cannot parse dictionary"); + csi->obj = pdf_parse_dict(csi->xref, file, buf, buflen); + /* RJW: "cannot parse dictionary" */ break; case PDF_TOK_NAME: @@ -2434,19 +2427,18 @@ pdf_run_stream(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen } else { - csi->obj = fz_new_string(buf, len); + csi->obj = fz_new_string(ctx, buf, len); } break; case PDF_TOK_KEYWORD: - error = pdf_run_keyword(csi, rdb, file, buf); - if (error) - return fz_rethrow(error, "cannot run keyword"); + pdf_run_keyword(csi, rdb, file, buf); + /* RJW: "cannot run keyword" */ pdf_clear_stack(csi); break; default: - return fz_throw("syntax error in content stream"); + fz_throw(ctx, "syntax error in content stream"); } } } @@ -2455,40 +2447,56 @@ pdf_run_stream(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen * Entry points */ -static fz_error +static void pdf_run_buffer(pdf_csi *csi, fz_obj *rdb, fz_buffer *contents) { - fz_error error; + fz_context *ctx = csi->dev->ctx; int len = sizeof csi->xref->scratch; - char *buf = fz_malloc(len); /* we must be re-entrant for type3 fonts */ - fz_stream *file = fz_open_buffer(contents); - int save_in_text = csi->in_text; - csi->in_text = 0; - error = pdf_run_stream(csi, rdb, file, buf, len); - csi->in_text = save_in_text; + char * volatile buf = NULL; + fz_stream * volatile file = NULL; + int save_in_text; + + fz_try(ctx) + { + buf = fz_malloc(ctx, len); /* we must be re-entrant for type3 fonts */ + file = fz_open_buffer(ctx, contents); + save_in_text = csi->in_text; + csi->in_text = 0; + pdf_run_stream(csi, rdb, file, buf, len); + csi->in_text = save_in_text; + } + fz_catch(ctx) + { + fz_close(file); + fz_free(ctx, buf); + fz_throw(ctx, "cannot parse context stream"); + } fz_close(file); - fz_free(buf); - if (error) - return fz_rethrow(error, "cannot parse content stream"); - return fz_okay; + fz_free(ctx, buf); } -fz_error +void pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, char *event) { pdf_csi *csi; - fz_error error; pdf_annot *annot; int flags; + fz_context *ctx = dev->ctx; if (page->transparency) fz_begin_group(dev, fz_transform_rect(ctm, page->mediabox), 1, 0, 0, 1); csi = pdf_new_csi(xref, dev, ctm, event); - error = pdf_run_buffer(csi, page->resources, page->contents); + fz_try(ctx) + { + pdf_run_buffer(csi, page->resources, page->contents); + } + fz_catch(ctx) + { + pdf_free_csi(csi); + fz_throw(ctx, "cannot parse page content stream"); + } pdf_free_csi(csi); - if (error) - return fz_rethrow(error, "cannot parse page content stream"); for (annot = page->annots; annot; annot = annot->next) { @@ -2505,32 +2513,43 @@ pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matri csi = pdf_new_csi(xref, dev, ctm, event); if (!pdf_is_hidden_ocg(fz_dict_gets(annot->obj, "OC"), csi, page->resources)) { - error = pdf_run_xobject(csi, page->resources, annot->ap, annot->matrix); + fz_try(ctx) + { + pdf_run_xobject(csi, page->resources, annot->ap, annot->matrix); + } + fz_catch(ctx) + { + pdf_free_csi(csi); + fz_throw(ctx, "cannot parse annotation appearance stream"); + } } pdf_free_csi(csi); - if (error) - return fz_rethrow(error, "cannot parse annotation appearance stream"); } if (page->transparency) fz_end_group(dev); - - return fz_okay; } -fz_error +void pdf_run_page(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm) { - return pdf_run_page_with_usage(xref, page, dev, ctm, "View"); + pdf_run_page_with_usage(xref, page, dev, ctm, "View"); } -fz_error +void pdf_run_glyph(pdf_xref *xref, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm) { pdf_csi *csi = pdf_new_csi(xref, dev, ctm, "View"); - fz_error error = pdf_run_buffer(csi, resources, contents); + fz_context *ctx = xref->ctx; + + fz_try(ctx) + { + pdf_run_buffer(csi, resources, contents); + } + fz_catch(ctx) + { + pdf_free_csi(csi); + fz_throw(ctx, "cannot parse glyph content stream"); + } pdf_free_csi(csi); - if (error) - return fz_rethrow(error, "cannot parse glyph content stream"); - return fz_okay; } diff --git a/pdf/pdf_lex.c b/pdf/pdf_lex.c index 23a5781f..edb27b7b 100644 --- a/pdf/pdf_lex.c +++ b/pdf/pdf_lex.c @@ -333,7 +333,7 @@ lex_hex_string(fz_stream *f, char *buf, int n) case EOF: goto end; default: - fz_warn("ignoring invalid character in hex string: '%c'", c); + fz_warn(f->ctx, "ignoring invalid character in hex string: '%c'", c); } } end: @@ -379,8 +379,8 @@ pdf_token_from_keyword(char *key) return PDF_TOK_KEYWORD; } -fz_error -pdf_lex(int *tok, fz_stream *f, char *buf, int n, int *sl) +int +pdf_lex(fz_stream *f, char *buf, int n, int *sl) { while (1) { @@ -388,8 +388,7 @@ pdf_lex(int *tok, fz_stream *f, char *buf, int n, int *sl) switch (c) { case EOF: - *tok = PDF_TOK_EOF; - return fz_okay; + return PDF_TOK_EOF; case IS_WHITE: lex_white(f); break; @@ -399,63 +398,51 @@ pdf_lex(int *tok, fz_stream *f, char *buf, int n, int *sl) case '/': lex_name(f, buf, n); *sl = strlen(buf); - *tok = PDF_TOK_NAME; - return fz_okay; + return PDF_TOK_NAME; case '(': *sl = lex_string(f, buf, n); - *tok = PDF_TOK_STRING; - return fz_okay; + return PDF_TOK_STRING; case ')': - *tok = PDF_TOK_ERROR; - goto cleanuperror; + fz_throw(f->ctx, "lexical error (unexpected ')')"); case '<': c = fz_read_byte(f); if (c == '<') { - *tok = PDF_TOK_OPEN_DICT; + return PDF_TOK_OPEN_DICT; } else { fz_unread_byte(f); *sl = lex_hex_string(f, buf, n); - *tok = PDF_TOK_STRING; + return PDF_TOK_STRING; } - return fz_okay; case '>': c = fz_read_byte(f); if (c == '>') { - *tok = PDF_TOK_CLOSE_DICT; - return fz_okay; + return PDF_TOK_CLOSE_DICT; } - *tok = PDF_TOK_ERROR; - goto cleanuperror; + fz_throw(f->ctx, "lexical error (unexpected '>')"); case '[': - *tok = PDF_TOK_OPEN_ARRAY; - return fz_okay; + return PDF_TOK_OPEN_ARRAY; case ']': - *tok = PDF_TOK_CLOSE_ARRAY; - return fz_okay; + return PDF_TOK_CLOSE_ARRAY; case '{': - *tok = PDF_TOK_OPEN_BRACE; - return fz_okay; + return PDF_TOK_OPEN_BRACE; case '}': - *tok = PDF_TOK_CLOSE_BRACE; - return fz_okay; + return PDF_TOK_CLOSE_BRACE; case IS_NUMBER: - fz_unread_byte(f); - *sl = lex_number(f, buf, n, tok); - return fz_okay; + { + int tok; + fz_unread_byte(f); + *sl = lex_number(f, buf, n, &tok); + return tok; + } default: /* isregular: !isdelim && !iswhite && c != EOF */ fz_unread_byte(f); lex_name(f, buf, n); *sl = strlen(buf); - *tok = pdf_token_from_keyword(buf); - return fz_okay; + return pdf_token_from_keyword(buf); } } - -cleanuperror: - *tok = PDF_TOK_ERROR; - return fz_throw("lexical error"); } diff --git a/pdf/pdf_metrics.c b/pdf/pdf_metrics.c index 2fc085de..3aa0ef24 100644 --- a/pdf/pdf_metrics.c +++ b/pdf/pdf_metrics.c @@ -21,12 +21,12 @@ pdf_set_default_vmtx(pdf_font_desc *font, int y, int w) } void -pdf_add_hmtx(pdf_font_desc *font, int lo, int hi, int w) +pdf_add_hmtx(fz_context *ctx, pdf_font_desc *font, int lo, int hi, int w) { if (font->hmtx_len + 1 >= font->hmtx_cap) { font->hmtx_cap = font->hmtx_cap + 16; - font->hmtx = fz_realloc(font->hmtx, font->hmtx_cap, sizeof(pdf_hmtx)); + font->hmtx = fz_resize_array(ctx, font->hmtx, font->hmtx_cap, sizeof(pdf_hmtx)); } font->hmtx[font->hmtx_len].lo = lo; @@ -36,12 +36,12 @@ pdf_add_hmtx(pdf_font_desc *font, int lo, int hi, int w) } void -pdf_add_vmtx(pdf_font_desc *font, int lo, int hi, int x, int y, int w) +pdf_add_vmtx(fz_context *ctx, pdf_font_desc *font, int lo, int hi, int x, int y, int w) { if (font->vmtx_len + 1 >= font->vmtx_cap) { font->vmtx_cap = font->vmtx_cap + 16; - font->vmtx = fz_realloc(font->vmtx, font->vmtx_cap, sizeof(pdf_vmtx)); + font->vmtx = fz_resize_array(ctx, font->vmtx, font->vmtx_cap, sizeof(pdf_vmtx)); } font->vmtx[font->vmtx_len].lo = lo; diff --git a/pdf/pdf_nametree.c b/pdf/pdf_nametree.c index e2b3e160..d84f2e8b 100644 --- a/pdf/pdf_nametree.c +++ b/pdf/pdf_nametree.c @@ -2,7 +2,7 @@ #include "mupdf.h" static fz_obj * -pdf_lookup_name_imp(fz_obj *node, fz_obj *needle) +pdf_lookup_name_imp(fz_context *ctx, fz_obj *node, fz_obj *needle) { fz_obj *kids = fz_dict_gets(node, "Kids"); fz_obj *names = fz_dict_gets(node, "Names"); @@ -25,7 +25,7 @@ pdf_lookup_name_imp(fz_obj *node, fz_obj *needle) else if (fz_objcmp(needle, last) > 0) l = m + 1; else - return pdf_lookup_name_imp(kid, needle); + return pdf_lookup_name_imp(ctx, kid, needle); } } @@ -57,15 +57,19 @@ pdf_lookup_name_imp(fz_obj *node, fz_obj *needle) fz_obj * pdf_lookup_name(pdf_xref *xref, char *which, fz_obj *needle) { + fz_context *ctx = xref->ctx; + fz_obj *root = fz_dict_gets(xref->trailer, "Root"); fz_obj *names = fz_dict_gets(root, "Names"); fz_obj *tree = fz_dict_gets(names, which); - return pdf_lookup_name_imp(tree, needle); + return pdf_lookup_name_imp(ctx, tree, needle); } fz_obj * pdf_lookup_dest(pdf_xref *xref, fz_obj *needle) { + fz_context *ctx = xref->ctx; + fz_obj *root = fz_dict_gets(xref->trailer, "Root"); fz_obj *dests = fz_dict_gets(root, "Dests"); fz_obj *names = fz_dict_gets(root, "Names"); @@ -84,7 +88,7 @@ pdf_lookup_dest(pdf_xref *xref, fz_obj *needle) if (names && !dest) { fz_obj *tree = fz_dict_gets(names, "Dests"); - return pdf_lookup_name_imp(tree, needle); + return pdf_lookup_name_imp(ctx, tree, needle); } return NULL; @@ -93,6 +97,7 @@ pdf_lookup_dest(pdf_xref *xref, fz_obj *needle) static void pdf_load_name_tree_imp(fz_obj *dict, pdf_xref *xref, fz_obj *node) { + fz_context *ctx = xref->ctx; fz_obj *kids = fz_dict_gets(node, "Kids"); fz_obj *names = fz_dict_gets(node, "Names"); int i; @@ -111,7 +116,7 @@ pdf_load_name_tree_imp(fz_obj *dict, pdf_xref *xref, fz_obj *node) fz_obj *val = fz_array_get(names, i + 1); if (fz_is_string(key)) { - key = pdf_to_utf8_name(key); + key = pdf_to_utf8_name(ctx, key); fz_dict_put(dict, key, val); fz_drop_obj(key); } @@ -126,12 +131,14 @@ pdf_load_name_tree_imp(fz_obj *dict, pdf_xref *xref, fz_obj *node) fz_obj * pdf_load_name_tree(pdf_xref *xref, char *which) { + fz_context *ctx = xref->ctx; + fz_obj *root = fz_dict_gets(xref->trailer, "Root"); fz_obj *names = fz_dict_gets(root, "Names"); fz_obj *tree = fz_dict_gets(names, which); if (fz_is_dict(tree)) { - fz_obj *dict = fz_new_dict(100); + fz_obj *dict = fz_new_dict(ctx, 100); pdf_load_name_tree_imp(dict, xref, tree); return dict; } diff --git a/pdf/pdf_outline.c b/pdf/pdf_outline.c index d1f5f575..9353d892 100644 --- a/pdf/pdf_outline.c +++ b/pdf/pdf_outline.c @@ -4,6 +4,7 @@ static fz_outline * pdf_load_outline_imp(pdf_xref *xref, fz_obj *dict) { + fz_context *ctx = xref->ctx; pdf_link *link; fz_outline *node; fz_obj *obj; @@ -11,7 +12,8 @@ pdf_load_outline_imp(pdf_xref *xref, fz_obj *dict) if (fz_is_null(dict)) return NULL; - node = fz_malloc(sizeof(fz_outline)); + node = fz_malloc(ctx, sizeof(fz_outline)); + node->ctx = ctx; node->title = NULL; node->page = 0; node->down = NULL; @@ -19,14 +21,14 @@ pdf_load_outline_imp(pdf_xref *xref, fz_obj *dict) obj = fz_dict_gets(dict, "Title"); if (obj) - node->title = pdf_to_utf8(obj); + node->title = pdf_to_utf8(ctx, obj); if (fz_dict_gets(dict, "Dest") || fz_dict_gets(dict, "A")) { link = pdf_load_link(xref, dict); if (link->kind == PDF_LINK_GOTO) node->page = pdf_find_page_number(xref, fz_array_get(link->dest, 0)); - pdf_free_link(link); + pdf_free_link(xref->ctx, link); } obj = fz_dict_gets(dict, "First"); diff --git a/pdf/pdf_page.c b/pdf/pdf_page.c index 3719ed00..fdc48ff3 100644 --- a/pdf/pdf_page.c +++ b/pdf/pdf_page.c @@ -31,6 +31,7 @@ pdf_load_page_tree_node(pdf_xref *xref, fz_obj *node, struct info info) fz_obj *dict, *kids, *count; fz_obj *obj, *tmp; int i, n; + fz_context *ctx = xref->ctx; /* prevent infinite recursion */ if (fz_dict_gets(node, ".seen")) @@ -54,7 +55,7 @@ pdf_load_page_tree_node(pdf_xref *xref, fz_obj *node, struct info info) if (obj) info.rotate = obj; - tmp = fz_new_null(); + tmp = fz_new_null(ctx); fz_dict_puts(node, ".seen", tmp); fz_drop_obj(tmp); @@ -82,10 +83,10 @@ pdf_load_page_tree_node(pdf_xref *xref, fz_obj *node, struct info info) if (xref->page_len == xref->page_cap) { - fz_warn("found more pages than expected"); + fz_warn(ctx, "found more pages than expected"); xref->page_cap ++; - xref->page_refs = fz_realloc(xref->page_refs, xref->page_cap, sizeof(fz_obj*)); - xref->page_objs = fz_realloc(xref->page_objs, xref->page_cap, sizeof(fz_obj*)); + xref->page_refs = fz_resize_array(ctx, xref->page_refs, xref->page_cap, sizeof(fz_obj*)); + xref->page_objs = fz_resize_array(ctx, xref->page_objs, xref->page_cap, sizeof(fz_obj*)); } xref->page_refs[xref->page_len] = fz_keep_obj(node); @@ -94,23 +95,24 @@ pdf_load_page_tree_node(pdf_xref *xref, fz_obj *node, struct info info) } } -fz_error +void pdf_load_page_tree(pdf_xref *xref) { struct info info; + fz_context *ctx = xref->ctx; fz_obj *catalog = fz_dict_gets(xref->trailer, "Root"); fz_obj *pages = fz_dict_gets(catalog, "Pages"); fz_obj *count = fz_dict_gets(pages, "Count"); if (!fz_is_dict(pages)) - return fz_throw("missing page tree"); + fz_throw(ctx, "missing page tree"); if (!fz_is_int(count)) - return fz_throw("missing page count"); + fz_throw(ctx, "missing page count"); xref->page_cap = fz_to_int(count); xref->page_len = 0; - xref->page_refs = fz_calloc(xref->page_cap, sizeof(fz_obj*)); - xref->page_objs = fz_calloc(xref->page_cap, sizeof(fz_obj*)); + xref->page_refs = fz_malloc_array(ctx, xref->page_cap, sizeof(fz_obj*)); + xref->page_objs = fz_malloc_array(ctx, xref->page_cap, sizeof(fz_obj*)); info.resources = NULL; info.mediabox = NULL; @@ -118,16 +120,14 @@ pdf_load_page_tree(pdf_xref *xref) info.rotate = NULL; pdf_load_page_tree_node(xref, pages, info); - - return fz_okay; } /* We need to know whether to install a page-level transparency group */ -static int pdf_resources_use_blending(fz_obj *rdb); +static int pdf_resources_use_blending(fz_context *ctx, fz_obj *rdb); static int -pdf_extgstate_uses_blending(fz_obj *dict) +pdf_extgstate_uses_blending(fz_context *ctx, fz_obj *dict) { fz_obj *obj = fz_dict_gets(dict, "BM"); if (fz_is_name(obj) && strcmp(fz_to_name(obj), "Normal")) @@ -136,33 +136,29 @@ pdf_extgstate_uses_blending(fz_obj *dict) } static int -pdf_pattern_uses_blending(fz_obj *dict) +pdf_pattern_uses_blending(fz_context *ctx, fz_obj *dict) { fz_obj *obj; obj = fz_dict_gets(dict, "Resources"); - if (pdf_resources_use_blending(obj)) + if (pdf_resources_use_blending(ctx, obj)) return 1; obj = fz_dict_gets(dict, "ExtGState"); - if (pdf_extgstate_uses_blending(obj)) - return 1; - return 0; + return pdf_extgstate_uses_blending(ctx, obj); } static int -pdf_xobject_uses_blending(fz_obj *dict) +pdf_xobject_uses_blending(fz_context *ctx, fz_obj *dict) { fz_obj *obj = fz_dict_gets(dict, "Resources"); - if (pdf_resources_use_blending(obj)) - return 1; - return 0; + return pdf_resources_use_blending(ctx, obj); } static int -pdf_resources_use_blending(fz_obj *rdb) +pdf_resources_use_blending(fz_context *ctx, fz_obj *rdb) { fz_obj *dict; fz_obj *tmp; - int i; + int i, n; if (!rdb) return 0; @@ -171,29 +167,32 @@ pdf_resources_use_blending(fz_obj *rdb) if (fz_dict_gets(rdb, ".useBM")) return fz_to_bool(fz_dict_gets(rdb, ".useBM")); - tmp = fz_new_bool(0); + tmp = fz_new_bool(ctx, 0); fz_dict_puts(rdb, ".useBM", tmp); fz_drop_obj(tmp); dict = fz_dict_gets(rdb, "ExtGState"); - for (i = 0; i < fz_dict_len(dict); i++) - if (pdf_extgstate_uses_blending(fz_dict_get_val(dict, i))) + n = fz_dict_len(dict); + for (i = 0; i < n; i++) + if (pdf_extgstate_uses_blending(ctx, fz_dict_get_val(dict, i))) goto found; dict = fz_dict_gets(rdb, "Pattern"); - for (i = 0; i < fz_dict_len(dict); i++) - if (pdf_pattern_uses_blending(fz_dict_get_val(dict, i))) + n = fz_dict_len(dict); + for (i = 0; i < n; i++) + if (pdf_pattern_uses_blending(ctx, fz_dict_get_val(dict, i))) goto found; dict = fz_dict_gets(rdb, "XObject"); - for (i = 0; i < fz_dict_len(dict); i++) - if (pdf_xobject_uses_blending(fz_dict_get_val(dict, i))) + n = fz_dict_len(dict); + for (i = 0; i < n; i++) + if (pdf_xobject_uses_blending(ctx, fz_dict_get_val(dict, i))) goto found; return 0; found: - tmp = fz_new_bool(1); + tmp = fz_new_bool(ctx, 1); fz_dict_puts(rdb, ".useBM", tmp); fz_drop_obj(tmp); return 1; @@ -201,110 +200,106 @@ found: /* we need to combine all sub-streams into one for the content stream interpreter */ -static fz_error -pdf_load_page_contents_array(fz_buffer **bigbufp, pdf_xref *xref, fz_obj *list) +static fz_buffer * +pdf_load_page_contents_array(pdf_xref *xref, fz_obj *list) { - fz_error error; fz_buffer *big; fz_buffer *one; int i, n; + fz_context *ctx = xref->ctx; - big = fz_new_buffer(32 * 1024); + big = fz_new_buffer(ctx, 32 * 1024); n = fz_array_len(list); for (i = 0; i < n; i++) { fz_obj *stm = fz_array_get(list, i); - error = pdf_load_stream(&one, xref, fz_to_num(stm), fz_to_gen(stm)); - if (error) + fz_try(ctx) + { + one = pdf_load_stream(xref, fz_to_num(stm), fz_to_gen(stm)); + } + fz_catch(ctx) { - fz_catch(error, "cannot load content stream part %d/%d", i + 1, n); + fz_warn(ctx, "cannot load content stream part %d/%d", i + 1, n); continue; } if (big->len + one->len + 1 > big->cap) - fz_resize_buffer(big, big->len + one->len + 1); + fz_resize_buffer(ctx, big, big->len + one->len + 1); memcpy(big->data + big->len, one->data, one->len); big->data[big->len + one->len] = ' '; big->len += one->len + 1; - fz_drop_buffer(one); + fz_drop_buffer(ctx, one); } if (n > 0 && big->len == 0) { - fz_drop_buffer(big); - return fz_throw("cannot load content stream"); + fz_drop_buffer(ctx, big); + fz_throw(ctx, "cannot load content stream"); } - *bigbufp = big; - return fz_okay; + return big; } -static fz_error -pdf_load_page_contents(fz_buffer **bufp, pdf_xref *xref, fz_obj *obj) +static fz_buffer * +pdf_load_page_contents(pdf_xref *xref, fz_obj *obj) { - fz_error error; + fz_context *ctx = xref->ctx; if (fz_is_array(obj)) { - error = pdf_load_page_contents_array(bufp, xref, obj); - if (error) - return fz_rethrow(error, "cannot load content stream array"); + return pdf_load_page_contents_array(xref, obj); + /* RJW: "cannot load content stream array" */ } else if (pdf_is_stream(xref, fz_to_num(obj), fz_to_gen(obj))) { - error = pdf_load_stream(bufp, xref, fz_to_num(obj), fz_to_gen(obj)); - if (error) - return fz_rethrow(error, "cannot load content stream (%d 0 R)", fz_to_num(obj)); - } - else - { - fz_warn("page contents missing, leaving page blank"); - *bufp = fz_new_buffer(0); + return pdf_load_stream(xref, fz_to_num(obj), fz_to_gen(obj)); + /* RJW: "cannot load content stream (%d 0 R)", fz_to_num(obj) */ } - return fz_okay; + fz_warn(ctx, "page contents missing, leaving page blank"); + return fz_new_buffer(ctx, 0); } -fz_error -pdf_load_page(pdf_page **pagep, pdf_xref *xref, int number) +pdf_page * +pdf_load_page(pdf_xref *xref, int number) { - fz_error error; pdf_page *page; pdf_annot *annot; fz_obj *pageobj, *pageref; fz_obj *obj; fz_rect mediabox, cropbox; + fz_context *ctx = xref->ctx; if (number < 0 || number >= xref->page_len) - return fz_throw("cannot find page %d", number + 1); + fz_throw(ctx, "cannot find page %d", number + 1); /* Ensure that we have a store for resource objects */ if (!xref->store) - xref->store = pdf_new_store(); + xref->store = pdf_new_store(ctx); pageobj = xref->page_objs[number]; pageref = xref->page_refs[number]; - page = fz_malloc(sizeof(pdf_page)); + page = fz_malloc(ctx, sizeof(pdf_page)); page->resources = NULL; page->contents = NULL; page->transparency = 0; page->links = NULL; page->annots = NULL; - mediabox = pdf_to_rect(fz_dict_gets(pageobj, "MediaBox")); + mediabox = pdf_to_rect(ctx, fz_dict_gets(pageobj, "MediaBox")); if (fz_is_empty_rect(mediabox)) { - fz_warn("cannot find page size for page %d", number + 1); + fz_warn(ctx, "cannot find page size for page %d", number + 1); mediabox.x0 = 0; mediabox.y0 = 0; mediabox.x1 = 612; mediabox.y1 = 792; } - cropbox = pdf_to_rect(fz_dict_gets(pageobj, "CropBox")); + cropbox = pdf_to_rect(ctx, fz_dict_gets(pageobj, "CropBox")); if (!fz_is_empty_rect(cropbox)) mediabox = fz_intersect_rect(mediabox, cropbox); @@ -315,7 +310,7 @@ pdf_load_page(pdf_page **pagep, pdf_xref *xref, int number) if (page->mediabox.x1 - page->mediabox.x0 < 1 || page->mediabox.y1 - page->mediabox.y0 < 1) { - fz_warn("invalid page size in page %d", number + 1); + fz_warn(ctx, "invalid page size in page %d", number + 1); page->mediabox = fz_unit_rect; } @@ -333,34 +328,36 @@ pdf_load_page(pdf_page **pagep, pdf_xref *xref, int number) fz_keep_obj(page->resources); obj = fz_dict_gets(pageobj, "Contents"); - error = pdf_load_page_contents(&page->contents, xref, obj); - if (error) + fz_try(ctx) + { + page->contents = pdf_load_page_contents(xref, obj); + } + fz_catch(ctx) { - pdf_free_page(page); - return fz_rethrow(error, "cannot load page %d contents (%d 0 R)", number + 1, fz_to_num(pageref)); + pdf_free_page(ctx, page); + fz_throw(ctx, "cannot load page %d contents (%d 0 R)", number + 1, fz_to_num(pageref)); } - if (pdf_resources_use_blending(page->resources)) + if (pdf_resources_use_blending(ctx, page->resources)) page->transparency = 1; for (annot = page->annots; annot && !page->transparency; annot = annot->next) - if (pdf_resources_use_blending(annot->ap->resources)) + if (pdf_resources_use_blending(ctx, annot->ap->resources)) page->transparency = 1; - *pagep = page; - return fz_okay; + return page; } void -pdf_free_page(pdf_page *page) +pdf_free_page(fz_context *ctx, pdf_page *page) { if (page->resources) fz_drop_obj(page->resources); if (page->contents) - fz_drop_buffer(page->contents); + fz_drop_buffer(ctx, page->contents); if (page->links) - pdf_free_link(page->links); + pdf_free_link(ctx, page->links); if (page->annots) - pdf_free_annot(page->annots); - fz_free(page); + pdf_free_annot(ctx, page->annots); + fz_free(ctx, page); } diff --git a/pdf/pdf_parse.c b/pdf/pdf_parse.c index 54ed97c1..4e393370 100644 --- a/pdf/pdf_parse.c +++ b/pdf/pdf_parse.c @@ -2,7 +2,7 @@ #include "mupdf.h" fz_rect -pdf_to_rect(fz_obj *array) +pdf_to_rect(fz_context *ctx, fz_obj *array) { fz_rect r; float a = fz_to_real(fz_array_get(array, 0)); @@ -17,7 +17,7 @@ pdf_to_rect(fz_obj *array) } fz_matrix -pdf_to_matrix(fz_obj *array) +pdf_to_matrix(fz_context *ctx, fz_obj *array) { fz_matrix m; m.a = fz_to_real(fz_array_get(array, 0)); @@ -31,7 +31,7 @@ pdf_to_matrix(fz_obj *array) /* Convert Unicode/PdfDocEncoding string into utf-8 */ char * -pdf_to_utf8(fz_obj *src) +pdf_to_utf8(fz_context *ctx, fz_obj *src) { unsigned char *srcptr = (unsigned char *) fz_to_str_buf(src); char *dstptr, *dst; @@ -48,7 +48,7 @@ pdf_to_utf8(fz_obj *src) dstlen += runelen(ucs); } - dstptr = dst = fz_malloc(dstlen + 1); + dstptr = dst = fz_malloc(ctx, dstlen + 1); for (i = 2; i < srclen; i += 2) { @@ -64,7 +64,7 @@ pdf_to_utf8(fz_obj *src) dstlen += runelen(ucs); } - dstptr = dst = fz_malloc(dstlen + 1); + dstptr = dst = fz_malloc(ctx, dstlen + 1); for (i = 2; i + 1 < srclen; i += 2) { @@ -77,7 +77,7 @@ pdf_to_utf8(fz_obj *src) for (i = 0; i < srclen; i++) dstlen += runelen(pdf_doc_encoding[srcptr[i]]); - dstptr = dst = fz_malloc(dstlen + 1); + dstptr = dst = fz_malloc(ctx, dstlen + 1); for (i = 0; i < srclen; i++) { @@ -92,7 +92,7 @@ pdf_to_utf8(fz_obj *src) /* Convert Unicode/PdfDocEncoding string into ucs-2 */ unsigned short * -pdf_to_ucs2(fz_obj *src) +pdf_to_ucs2(fz_context *ctx, fz_obj *src) { unsigned char *srcptr = (unsigned char *) fz_to_str_buf(src); unsigned short *dstptr, *dst; @@ -101,19 +101,19 @@ pdf_to_ucs2(fz_obj *src) if (srclen >= 2 && srcptr[0] == 254 && srcptr[1] == 255) { - dstptr = dst = fz_calloc((srclen - 2) / 2 + 1, sizeof(short)); + dstptr = dst = fz_malloc_array(ctx, (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)); + dstptr = dst = fz_malloc_array(ctx, (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)); + dstptr = dst = fz_malloc_array(ctx, srclen + 1, sizeof(short)); for (i = 0; i < srclen; i++) *dstptr++ = pdf_doc_encoding[srcptr[i]]; } @@ -124,7 +124,7 @@ pdf_to_ucs2(fz_obj *src) /* Convert UCS-2 string into PdfDocEncoding for authentication */ char * -pdf_from_ucs2(unsigned short *src) +pdf_from_ucs2(fz_context *ctx, unsigned short *src) { int i, j, len; char *docstr; @@ -133,7 +133,7 @@ pdf_from_ucs2(unsigned short *src) while (src[len]) len++; - docstr = fz_malloc(len + 1); + docstr = fz_malloc(ctx, len + 1); for (i = 0; i < len; i++) { @@ -152,7 +152,7 @@ pdf_from_ucs2(unsigned short *src) /* fail, if a character can't be encoded */ if (!docstr[i]) { - fz_free(docstr); + fz_free(ctx, docstr); return NULL; } } @@ -162,409 +162,359 @@ pdf_from_ucs2(unsigned short *src) } fz_obj * -pdf_to_utf8_name(fz_obj *src) +pdf_to_utf8_name(fz_context *ctx, fz_obj *src) { - char *buf = pdf_to_utf8(src); - fz_obj *dst = fz_new_name(buf); - fz_free(buf); + char *buf = pdf_to_utf8(ctx, src); + fz_obj *dst = fz_new_name(ctx, buf); + fz_free(ctx, buf); return dst; } -fz_error -pdf_parse_array(fz_obj **op, pdf_xref *xref, fz_stream *file, char *buf, int cap) +fz_obj * +pdf_parse_array(pdf_xref *xref, fz_stream *file, char *buf, int cap) { - fz_error error = fz_okay; fz_obj *ary = NULL; fz_obj *obj = NULL; int a = 0, b = 0, n = 0; int tok; int len; + fz_context *ctx = file->ctx; + fz_obj *op; - ary = fz_new_array(4); + ary = fz_new_array(ctx, 4); - while (1) + fz_try(ctx) { - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) + while (1) { - fz_drop_obj(ary); - return fz_rethrow(error, "cannot parse array"); - } + tok = pdf_lex(file, buf, cap, &len); - if (tok != PDF_TOK_INT && tok != PDF_TOK_R) - { - if (n > 0) + if (tok != PDF_TOK_INT && tok != PDF_TOK_R) { - obj = fz_new_int(a); + if (n > 0) + { + obj = fz_new_int(ctx, a); + fz_array_push(ary, obj); + fz_drop_obj(obj); + } + if (n > 1) + { + obj = fz_new_int(ctx, b); + fz_array_push(ary, obj); + fz_drop_obj(obj); + } + n = 0; + } + + if (tok == PDF_TOK_INT && n == 2) + { + obj = fz_new_int(ctx, a); fz_array_push(ary, obj); fz_drop_obj(obj); + a = b; + n --; } - if (n > 1) + + switch (tok) { - obj = fz_new_int(b); + case PDF_TOK_CLOSE_ARRAY: + op = ary; + goto end; + + case PDF_TOK_INT: + if (n == 0) + a = atoi(buf); + if (n == 1) + b = atoi(buf); + n ++; + break; + + case PDF_TOK_R: + if (n != 2) + { + fz_drop_obj(ary); + fz_throw(ctx, "cannot parse indirect reference in array"); + } + obj = fz_new_indirect(ctx, a, b, xref); fz_array_push(ary, obj); fz_drop_obj(obj); - } - n = 0; - } + n = 0; + break; - if (tok == PDF_TOK_INT && n == 2) - { - obj = fz_new_int(a); - fz_array_push(ary, obj); - fz_drop_obj(obj); - a = b; - n --; - } + case PDF_TOK_OPEN_ARRAY: + obj = pdf_parse_array(xref, file, buf, cap); + fz_array_push(ary, obj); + fz_drop_obj(obj); + break; - switch (tok) - { - case PDF_TOK_CLOSE_ARRAY: - *op = ary; - return fz_okay; - - case PDF_TOK_INT: - if (n == 0) - a = atoi(buf); - if (n == 1) - b = atoi(buf); - n ++; - break; - - case PDF_TOK_R: - if (n != 2) - { - fz_drop_obj(ary); - return fz_throw("cannot parse indirect reference in array"); - } - obj = fz_new_indirect(a, b, xref); - fz_array_push(ary, obj); - fz_drop_obj(obj); - n = 0; - break; - - case PDF_TOK_OPEN_ARRAY: - error = pdf_parse_array(&obj, xref, file, buf, cap); - if (error) - { - fz_drop_obj(ary); - return fz_rethrow(error, "cannot parse array"); - } - fz_array_push(ary, obj); - fz_drop_obj(obj); - break; + case PDF_TOK_OPEN_DICT: + obj = pdf_parse_dict(xref, file, buf, cap); + fz_array_push(ary, obj); + fz_drop_obj(obj); + break; - case PDF_TOK_OPEN_DICT: - error = pdf_parse_dict(&obj, xref, file, buf, cap); - if (error) - { + case PDF_TOK_NAME: + obj = fz_new_name(ctx, buf); + fz_array_push(ary, obj); + fz_drop_obj(obj); + break; + case PDF_TOK_REAL: + obj = fz_new_real(ctx, fz_atof(buf)); + fz_array_push(ary, obj); + fz_drop_obj(obj); + break; + case PDF_TOK_STRING: + obj = fz_new_string(ctx, buf, len); + fz_array_push(ary, obj); + fz_drop_obj(obj); + break; + case PDF_TOK_TRUE: + obj = fz_new_bool(ctx, 1); + fz_array_push(ary, obj); + fz_drop_obj(obj); + break; + case PDF_TOK_FALSE: + obj = fz_new_bool(ctx, 0); + fz_array_push(ary, obj); + fz_drop_obj(obj); + break; + case PDF_TOK_NULL: + obj = fz_new_null(ctx); + fz_array_push(ary, obj); + fz_drop_obj(obj); + break; + + default: fz_drop_obj(ary); - return fz_rethrow(error, "cannot parse array"); + fz_throw(ctx, "cannot parse token in array"); } - fz_array_push(ary, obj); - fz_drop_obj(obj); - break; - - case PDF_TOK_NAME: - obj = fz_new_name(buf); - fz_array_push(ary, obj); - fz_drop_obj(obj); - break; - case PDF_TOK_REAL: - obj = fz_new_real(fz_atof(buf)); - fz_array_push(ary, obj); - fz_drop_obj(obj); - break; - case PDF_TOK_STRING: - obj = fz_new_string(buf, len); - fz_array_push(ary, obj); - fz_drop_obj(obj); - break; - case PDF_TOK_TRUE: - obj = fz_new_bool(1); - fz_array_push(ary, obj); - fz_drop_obj(obj); - break; - case PDF_TOK_FALSE: - obj = fz_new_bool(0); - fz_array_push(ary, obj); - fz_drop_obj(obj); - break; - case PDF_TOK_NULL: - obj = fz_new_null(); - fz_array_push(ary, obj); - fz_drop_obj(obj); - break; - - default: - fz_drop_obj(ary); - return fz_throw("cannot parse token in array"); } +end: + {} + } + fz_catch(ctx) + { + fz_drop_obj(ary); + fz_throw(ctx, "cannot parse array"); } + return op; } -fz_error -pdf_parse_dict(fz_obj **op, pdf_xref *xref, fz_stream *file, char *buf, int cap) +fz_obj * +pdf_parse_dict(pdf_xref *xref, fz_stream *file, char *buf, int cap) { - fz_error error = fz_okay; - fz_obj *dict = NULL; - fz_obj *key = NULL; - fz_obj *val = NULL; + fz_obj * volatile dict = NULL; + fz_obj * volatile key = NULL; + fz_obj * volatile val = NULL; int tok; int len; int a, b; + fz_context *ctx = file->ctx; - dict = fz_new_dict(8); + dict = fz_new_dict(ctx, 8); - while (1) + fz_try(ctx) { - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) + while (1) { - fz_drop_obj(dict); - return fz_rethrow(error, "cannot parse dict"); - } - -skip: - if (tok == PDF_TOK_CLOSE_DICT) - { - *op = dict; - return fz_okay; - } + tok = pdf_lex(file, buf, cap, &len); + skip: + if (tok == PDF_TOK_CLOSE_DICT) + break; - /* for BI .. ID .. EI in content streams */ - if (tok == PDF_TOK_KEYWORD && !strcmp(buf, "ID")) - { - *op = dict; - return fz_okay; - } + /* for BI .. ID .. EI in content streams */ + if (tok == PDF_TOK_KEYWORD && !strcmp(buf, "ID")) + break; - if (tok != PDF_TOK_NAME) - { - fz_drop_obj(dict); - return fz_throw("invalid key in dict"); - } + if (tok != PDF_TOK_NAME) + fz_throw(ctx, "invalid key in dict"); - key = fz_new_name(buf); + key = fz_new_name(ctx, buf); - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - { - fz_drop_obj(key); - fz_drop_obj(dict); - return fz_rethrow(error, "cannot parse dict"); - } + tok = pdf_lex(file, buf, cap, &len); - switch (tok) - { - case PDF_TOK_OPEN_ARRAY: - error = pdf_parse_array(&val, xref, file, buf, cap); - if (error) + switch (tok) { - fz_drop_obj(key); - fz_drop_obj(dict); - return fz_rethrow(error, "cannot parse dict"); - } - break; + case PDF_TOK_OPEN_ARRAY: + val = pdf_parse_array(xref, file, buf, cap); + break; - case PDF_TOK_OPEN_DICT: - error = pdf_parse_dict(&val, xref, file, buf, cap); - if (error) - { - fz_drop_obj(key); - fz_drop_obj(dict); - return fz_rethrow(error, "cannot parse dict"); - } - break; - - case PDF_TOK_NAME: val = fz_new_name(buf); break; - case PDF_TOK_REAL: val = fz_new_real(fz_atof(buf)); break; - case PDF_TOK_STRING: val = fz_new_string(buf, len); break; - case PDF_TOK_TRUE: val = fz_new_bool(1); break; - case PDF_TOK_FALSE: val = fz_new_bool(0); break; - case PDF_TOK_NULL: val = fz_new_null(); break; - - case PDF_TOK_INT: - /* 64-bit to allow for numbers > INT_MAX and overflow */ - a = (int) strtoll(buf, 0, 10); - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - { - fz_drop_obj(key); - fz_drop_obj(dict); - return fz_rethrow(error, "cannot parse dict"); - } - if (tok == PDF_TOK_CLOSE_DICT || tok == PDF_TOK_NAME || - (tok == PDF_TOK_KEYWORD && !strcmp(buf, "ID"))) - { - val = fz_new_int(a); - fz_dict_put(dict, key, val); - fz_drop_obj(val); - fz_drop_obj(key); - goto skip; - } - if (tok == PDF_TOK_INT) - { - b = atoi(buf); - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) + case PDF_TOK_OPEN_DICT: + val = pdf_parse_dict(xref, file, buf, cap); + break; + + case PDF_TOK_NAME: val = fz_new_name(ctx, buf); break; + case PDF_TOK_REAL: val = fz_new_real(ctx, fz_atof(buf)); break; + case PDF_TOK_STRING: val = fz_new_string(ctx, buf, len); break; + case PDF_TOK_TRUE: val = fz_new_bool(ctx, 1); break; + case PDF_TOK_FALSE: val = fz_new_bool(ctx, 0); break; + case PDF_TOK_NULL: val = fz_new_null(ctx); break; + + case PDF_TOK_INT: + /* 64-bit to allow for numbers > INT_MAX and overflow */ + a = (int) strtoll(buf, 0, 10); + tok = pdf_lex(file, buf, cap, &len); + if (tok == PDF_TOK_CLOSE_DICT || tok == PDF_TOK_NAME || + (tok == PDF_TOK_KEYWORD && !strcmp(buf, "ID"))) { + val = fz_new_int(ctx, a); + fz_dict_put(dict, key, val); + fz_drop_obj(val); fz_drop_obj(key); - fz_drop_obj(dict); - return fz_rethrow(error, "cannot parse dict"); + goto skip; } - if (tok == PDF_TOK_R) + if (tok == PDF_TOK_INT) { - val = fz_new_indirect(a, b, xref); - break; + b = atoi(buf); + tok = pdf_lex(file, buf, cap, &len); + if (tok == PDF_TOK_R) + { + val = fz_new_indirect(ctx, a, b, xref); + break; + } } + fz_throw(ctx, "invalid indirect reference in dict"); + + default: + fz_drop_obj(key); + fz_drop_obj(dict); + fz_throw(ctx, "unknown token in dict"); } - fz_drop_obj(key); - fz_drop_obj(dict); - return fz_throw("invalid indirect reference in dict"); - default: + fz_dict_put(dict, key, val); + fz_drop_obj(val); fz_drop_obj(key); - fz_drop_obj(dict); - return fz_throw("unknown token in dict"); + key = NULL; } - - fz_dict_put(dict, key, val); - fz_drop_obj(val); + } + fz_catch(ctx) + { + fz_drop_obj(dict); fz_drop_obj(key); + fz_throw(ctx, "cannot parse dict"); } + return dict; } -fz_error -pdf_parse_stm_obj(fz_obj **op, pdf_xref *xref, fz_stream *file, char *buf, int cap) +fz_obj * +pdf_parse_stm_obj(pdf_xref *xref, fz_stream *file, char *buf, int cap) { - fz_error error; int tok; int len; + fz_context *ctx = file->ctx; - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - return fz_rethrow(error, "cannot parse token in object stream"); + tok = pdf_lex(file, buf, cap, &len); + /* RJW: "cannot parse token in object stream") */ switch (tok) { case PDF_TOK_OPEN_ARRAY: - error = pdf_parse_array(op, xref, file, buf, cap); - if (error) - return fz_rethrow(error, "cannot parse object stream"); - break; + return pdf_parse_array(xref, file, buf, cap); + /* RJW: "cannot parse object stream" */ case PDF_TOK_OPEN_DICT: - error = pdf_parse_dict(op, xref, file, buf, cap); - if (error) - return fz_rethrow(error, "cannot parse object stream"); - break; - case PDF_TOK_NAME: *op = fz_new_name(buf); break; - case PDF_TOK_REAL: *op = fz_new_real(fz_atof(buf)); break; - case PDF_TOK_STRING: *op = fz_new_string(buf, len); break; - case PDF_TOK_TRUE: *op = fz_new_bool(1); break; - case PDF_TOK_FALSE: *op = fz_new_bool(0); break; - case PDF_TOK_NULL: *op = fz_new_null(); break; - case PDF_TOK_INT: *op = fz_new_int(atoi(buf)); break; - default: return fz_throw("unknown token in object stream"); + return pdf_parse_dict(xref, file, buf, cap); + /* RJW: "cannot parse object stream" */ + case PDF_TOK_NAME: return fz_new_name(ctx, buf); break; + case PDF_TOK_REAL: return fz_new_real(ctx, fz_atof(buf)); break; + case PDF_TOK_STRING: return fz_new_string(ctx, buf, len); break; + case PDF_TOK_TRUE: return fz_new_bool(ctx, 1); break; + case PDF_TOK_FALSE: return fz_new_bool(ctx, 0); break; + case PDF_TOK_NULL: return fz_new_null(ctx); break; + case PDF_TOK_INT: return fz_new_int(ctx, atoi(buf)); break; + default: fz_throw(ctx, "unknown token in object stream"); } - - return fz_okay; + return NULL; /* Stupid MSVC */ } -fz_error -pdf_parse_ind_obj(fz_obj **op, pdf_xref *xref, +fz_obj * +pdf_parse_ind_obj(pdf_xref *xref, fz_stream *file, char *buf, int cap, int *onum, int *ogen, int *ostmofs) { - fz_error error = fz_okay; - fz_obj *obj = NULL; + fz_obj * volatile obj = NULL; int num = 0, gen = 0, stm_ofs; int tok; int len; int a, b; + fz_context *ctx = file->ctx; - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - return fz_rethrow(error, "cannot parse indirect object (%d %d R)", num, gen); + tok = pdf_lex(file, buf, cap, &len); + /* RJW: cannot parse indirect object (%d %d R)", num, gen */ if (tok != PDF_TOK_INT) - return fz_throw("expected object number (%d %d R)", num, gen); + fz_throw(ctx, "expected object number (%d %d R)", num, gen); num = atoi(buf); - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - return fz_rethrow(error, "cannot parse indirect object (%d %d R)", num, gen); + tok = pdf_lex(file, buf, cap, &len); + /* RJW: "cannot parse indirect object (%d %d R)", num, gen */ if (tok != PDF_TOK_INT) - return fz_throw("expected generation number (%d %d R)", num, gen); + fz_throw(ctx, "expected generation number (%d %d R)", num, gen); gen = atoi(buf); - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - return fz_rethrow(error, "cannot parse indirect object (%d %d R)", num, gen); + tok = pdf_lex(file, buf, cap, &len); + /* RJW: "cannot parse indirect object (%d %d R)", num, gen */ if (tok != PDF_TOK_OBJ) - return fz_throw("expected 'obj' keyword (%d %d R)", num, gen); + fz_throw(ctx, "expected 'obj' keyword (%d %d R)", num, gen); - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - return fz_rethrow(error, "cannot parse indirect object (%d %d R)", num, gen); + tok = pdf_lex(file, buf, cap, &len); + /* RJW: "cannot parse indirect object (%d %d R)", num, gen */ switch (tok) { case PDF_TOK_OPEN_ARRAY: - error = pdf_parse_array(&obj, xref, file, buf, cap); - if (error) - return fz_rethrow(error, "cannot parse indirect object (%d %d R)", num, gen); + obj = pdf_parse_array(xref, file, buf, cap); + /* RJW: "cannot parse indirect object (%d %d R)", num, gen */ break; case PDF_TOK_OPEN_DICT: - error = pdf_parse_dict(&obj, xref, file, buf, cap); - if (error) - return fz_rethrow(error, "cannot parse indirect object (%d %d R)", num, gen); + obj = pdf_parse_dict(xref, file, buf, cap); + /* RJW: "cannot parse indirect object (%d %d R)", num, gen */ break; - case PDF_TOK_NAME: obj = fz_new_name(buf); break; - case PDF_TOK_REAL: obj = fz_new_real(fz_atof(buf)); break; - case PDF_TOK_STRING: obj = fz_new_string(buf, len); break; - case PDF_TOK_TRUE: obj = fz_new_bool(1); break; - case PDF_TOK_FALSE: obj = fz_new_bool(0); break; - case PDF_TOK_NULL: obj = fz_new_null(); break; + case PDF_TOK_NAME: obj = fz_new_name(ctx, buf); break; + case PDF_TOK_REAL: obj = fz_new_real(ctx, fz_atof(buf)); break; + case PDF_TOK_STRING: obj = fz_new_string(ctx, buf, len); break; + case PDF_TOK_TRUE: obj = fz_new_bool(ctx, 1); break; + case PDF_TOK_FALSE: obj = fz_new_bool(ctx, 0); break; + case PDF_TOK_NULL: obj = fz_new_null(ctx); break; case PDF_TOK_INT: a = atoi(buf); - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - return fz_rethrow(error, "cannot parse indirect object (%d %d R)", num, gen); + tok = pdf_lex(file, buf, cap, &len); + /* "cannot parse indirect object (%d %d R)", num, gen */ if (tok == PDF_TOK_STREAM || tok == PDF_TOK_ENDOBJ) { - obj = fz_new_int(a); + obj = fz_new_int(ctx, a); goto skip; } if (tok == PDF_TOK_INT) { b = atoi(buf); - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - return fz_rethrow(error, "cannot parse indirect object (%d %d R)", num, gen); + tok = pdf_lex(file, buf, cap, &len); + /* RJW: "cannot parse indirect object (%d %d R)", num, gen); */ if (tok == PDF_TOK_R) { - obj = fz_new_indirect(a, b, xref); + obj = fz_new_indirect(ctx, a, b, xref); break; } } - return fz_throw("expected 'R' keyword (%d %d R)", num, gen); + fz_throw(ctx, "expected 'R' keyword (%d %d R)", num, gen); case PDF_TOK_ENDOBJ: - obj = fz_new_null(); + obj = fz_new_null(ctx); goto skip; default: - return fz_throw("syntax error in object (%d %d R)", num, gen); + fz_throw(ctx, "syntax error in object (%d %d R)", num, gen); } - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) + fz_try(ctx) + { + tok = pdf_lex(file, buf, cap, &len); + } + fz_catch(ctx) { fz_drop_obj(obj); - return fz_rethrow(error, "cannot parse indirect object (%d %d R)", num, gen); + fz_throw(ctx, "cannot parse indirect object (%d %d R)", num, gen); } skip: @@ -577,7 +527,7 @@ skip: { c = fz_peek_byte(file); if (c != '\n') - fz_warn("line feed missing after stream begin marker (%d %d R)", num, gen); + fz_warn(ctx, "line feed missing after stream begin marker (%d %d R)", num, gen); else fz_read_byte(file); } @@ -589,13 +539,12 @@ skip: } else { - fz_warn("expected 'endobj' or 'stream' keyword (%d %d R)", num, gen); + fz_warn(ctx, "expected 'endobj' or 'stream' keyword (%d %d R)", num, gen); stm_ofs = 0; } if (onum) *onum = num; if (ogen) *ogen = gen; if (ostmofs) *ostmofs = stm_ofs; - *op = obj; - return fz_okay; + return obj; } diff --git a/pdf/pdf_pattern.c b/pdf/pdf_pattern.c index 33d84c99..194d9650 100644 --- a/pdf/pdf_pattern.c +++ b/pdf/pdf_pattern.c @@ -1,37 +1,36 @@ #include "fitz.h" #include "mupdf.h" -fz_error -pdf_load_pattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict) +pdf_pattern * +pdf_load_pattern(pdf_xref *xref, fz_obj *dict) { - fz_error error; pdf_pattern *pat; fz_obj *obj; + fz_context *ctx = xref->ctx; - if ((*patp = pdf_find_item(xref->store, pdf_drop_pattern, dict))) + if ((pat = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_pattern, dict))) { - pdf_keep_pattern(*patp); - return fz_okay; + return pdf_keep_pattern(pat); } - pat = fz_malloc(sizeof(pdf_pattern)); + pat = fz_malloc(ctx, sizeof(pdf_pattern)); pat->refs = 1; pat->resources = NULL; pat->contents = NULL; /* Store pattern now, to avoid possible recursion if objects refer back to this one */ - pdf_store_item(xref->store, pdf_keep_pattern, pdf_drop_pattern, dict, pat); + pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)pdf_keep_pattern, (pdf_store_drop_fn *)pdf_drop_pattern, dict, pat); pat->ismask = fz_to_int(fz_dict_gets(dict, "PaintType")) == 2; pat->xstep = fz_to_real(fz_dict_gets(dict, "XStep")); pat->ystep = fz_to_real(fz_dict_gets(dict, "YStep")); obj = fz_dict_gets(dict, "BBox"); - pat->bbox = pdf_to_rect(obj); + pat->bbox = pdf_to_rect(ctx, obj); obj = fz_dict_gets(dict, "Matrix"); if (obj) - pat->matrix = pdf_to_matrix(obj); + pat->matrix = pdf_to_matrix(ctx, obj); else pat->matrix = fz_identity; @@ -39,16 +38,17 @@ pdf_load_pattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict) if (pat->resources) fz_keep_obj(pat->resources); - error = pdf_load_stream(&pat->contents, xref, fz_to_num(dict), fz_to_gen(dict)); - if (error) + fz_try(ctx) { - pdf_remove_item(xref->store, pdf_drop_pattern, dict); - pdf_drop_pattern(pat); - return fz_rethrow(error, "cannot load pattern stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + pat->contents = pdf_load_stream(xref, fz_to_num(dict), fz_to_gen(dict)); } - - *patp = pat; - return fz_okay; + fz_catch(ctx) + { + pdf_remove_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_pattern, dict); + pdf_drop_pattern(ctx, pat); + fz_throw(ctx, "cannot load pattern stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + } + return pat; } pdf_pattern * @@ -59,14 +59,14 @@ pdf_keep_pattern(pdf_pattern *pat) } void -pdf_drop_pattern(pdf_pattern *pat) +pdf_drop_pattern(fz_context *ctx, pdf_pattern *pat) { if (pat && --pat->refs == 0) { if (pat->resources) fz_drop_obj(pat->resources); if (pat->contents) - fz_drop_buffer(pat->contents); - fz_free(pat); + fz_drop_buffer(ctx, pat->contents); + fz_free(ctx, pat); } } diff --git a/pdf/pdf_repair.c b/pdf/pdf_repair.c index dc376dc3..abc443cc 100644 --- a/pdf/pdf_repair.c +++ b/pdf/pdf_repair.c @@ -12,33 +12,35 @@ struct entry int stm_len; }; -static fz_error +static void pdf_repair_obj(fz_stream *file, char *buf, int cap, int *stmofsp, int *stmlenp, fz_obj **encrypt, fz_obj **id) { - fz_error error; int tok; int stm_len; int len; int n; + fz_context *ctx = file->ctx; *stmofsp = 0; *stmlenp = -1; stm_len = 0; - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - return fz_rethrow(error, "cannot parse object"); + tok = pdf_lex(file, buf, cap, &len); + /* RJW: "cannot parse object" */ if (tok == PDF_TOK_OPEN_DICT) { fz_obj *dict, *obj; /* Send NULL xref so we don't try to resolve references */ - error = pdf_parse_dict(&dict, NULL, file, buf, cap); - if (error) + fz_try(ctx) { - fz_catch(error, "cannot parse object - repair will be incomplete"); - dict = fz_new_dict(2); + dict = pdf_parse_dict(NULL, file, buf, cap); + } + fz_catch(ctx) + { + /* Silently swallow the error */ + dict = fz_new_dict(ctx, 2); } obj = fz_dict_gets(dict, "Type"); @@ -74,9 +76,8 @@ pdf_repair_obj(fz_stream *file, char *buf, int cap, int *stmofsp, int *stmlenp, tok != PDF_TOK_EOF && tok != PDF_TOK_INT ) { - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - return fz_rethrow(error, "cannot scan for endobj or stream token"); + tok = pdf_lex(file, buf, cap, &len); + /* RJW: "cannot scan for endobj or stream token" */ } if (tok == PDF_TOK_INT) @@ -95,14 +96,19 @@ pdf_repair_obj(fz_stream *file, char *buf, int cap, int *stmofsp, int *stmlenp, *stmofsp = fz_tell(file); if (*stmofsp < 0) - return fz_throw("cannot seek in file"); + fz_throw(ctx, "cannot seek in file"); if (stm_len > 0) { fz_seek(file, *stmofsp + stm_len, 0); - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - fz_catch(error, "cannot find endstream token, falling back to scanning"); + fz_try(ctx) + { + tok = pdf_lex(file, buf, cap, &len); + } + fz_catch(ctx) + { + fz_error_handle(1, "cannot find endstream token, falling back to scanning"); + } if (tok == PDF_TOK_ENDSTREAM) goto atobjend; fz_seek(file, *stmofsp, 0); @@ -110,7 +116,7 @@ pdf_repair_obj(fz_stream *file, char *buf, int cap, int *stmofsp, int *stmlenp, n = fz_read(file, (unsigned char *) buf, 9); if (n < 0) - return fz_rethrow(n, "cannot read from file"); + fz_throw(ctx, "cannot read from file"); while (memcmp(buf, "endstream", 9) != 0) { @@ -124,82 +130,74 @@ pdf_repair_obj(fz_stream *file, char *buf, int cap, int *stmofsp, int *stmlenp, *stmlenp = fz_tell(file) - *stmofsp - 9; atobjend: - error = pdf_lex(&tok, file, buf, cap, &len); - if (error) - return fz_rethrow(error, "cannot scan for endobj token"); + tok = pdf_lex(file, buf, cap, &len); + /* RJW: "cannot scan for endobj token" */ if (tok != PDF_TOK_ENDOBJ) - fz_warn("object missing 'endobj' token"); + fz_warn(ctx, "object missing 'endobj' token"); } - - return fz_okay; } -static fz_error +static void pdf_repair_obj_stm(pdf_xref *xref, int num, int gen) { - fz_error error; fz_obj *obj; fz_stream *stm; int tok; int i, n, count; char buf[256]; + fz_context *ctx = xref->ctx; - error = pdf_load_object(&obj, xref, num, gen); - if (error) - return fz_rethrow(error, "cannot load object stream object (%d %d R)", num, gen); + fz_try(ctx) + { + obj = pdf_load_object(xref, num, gen); - count = fz_to_int(fz_dict_gets(obj, "N")); + count = fz_to_int(fz_dict_gets(obj, "N")); - fz_drop_obj(obj); + fz_drop_obj(obj); - error = pdf_open_stream(&stm, xref, num, gen); - if (error) - return fz_rethrow(error, "cannot open object stream object (%d %d R)", num, gen); + stm = pdf_open_stream(xref, num, gen); - for (i = 0; i < count; i++) - { - error = pdf_lex(&tok, stm, buf, sizeof buf, &n); - if (error || tok != PDF_TOK_INT) + for (i = 0; i < count; i++) { - fz_close(stm); - return fz_rethrow(error, "corrupt object stream (%d %d R)", num, gen); - } - - n = atoi(buf); - if (n >= xref->len) - pdf_resize_xref(xref, n + 1); - - xref->table[n].ofs = num; - xref->table[n].gen = i; - xref->table[n].stm_ofs = 0; - xref->table[n].obj = NULL; - xref->table[n].type = 'o'; - - error = pdf_lex(&tok, stm, buf, sizeof buf, &n); - if (error || tok != PDF_TOK_INT) - { - fz_close(stm); - return fz_rethrow(error, "corrupt object stream (%d %d R)", num, gen); + tok = pdf_lex(stm, buf, sizeof buf, &n); + if (tok != PDF_TOK_INT) + fz_throw(ctx, "corrupt object stream (%d %d R)", num, gen); + + n = atoi(buf); + if (n >= xref->len) + pdf_resize_xref(xref, n + 1); + + xref->table[n].ofs = num; + xref->table[n].gen = i; + xref->table[n].stm_ofs = 0; + xref->table[n].obj = NULL; + xref->table[n].type = 'o'; + + tok = pdf_lex(stm, buf, sizeof buf, &n); + if (tok != PDF_TOK_INT) + fz_throw(ctx, "corrupt object stream (%d %d R)", num, gen); } } - + fz_catch(ctx) + { + fz_close(stm); + fz_throw(ctx, "cannot load object stream object (%d %d R)", num, gen); + } fz_close(stm); - return fz_okay; } -fz_error +void pdf_repair_xref(pdf_xref *xref, char *buf, int bufsize) { - fz_error error; fz_obj *dict, *obj; fz_obj *length; - fz_obj *encrypt = NULL; - fz_obj *id = NULL; - fz_obj *root = NULL; - fz_obj *info = NULL; + fz_obj * volatile encrypt = NULL; + fz_obj * volatile id = NULL; + fz_obj * volatile root = NULL; + fz_obj * volatile info = NULL; - struct entry *list = NULL; + struct entry * volatile list = NULL; int listlen; int listcap; int maxnum = 0; @@ -211,247 +209,229 @@ pdf_repair_xref(pdf_xref *xref, char *buf, int bufsize) int tok; int next; int i, n, c; + fz_context *ctx = xref->ctx; fz_seek(xref->file, 0, 0); - listlen = 0; - listcap = 1024; - list = fz_calloc(listcap, sizeof(struct entry)); - - /* look for '%PDF' version marker within first kilobyte of file */ - n = fz_read(xref->file, (unsigned char *)buf, MAX(bufsize, 1024)); - if (n < 0) + fz_try(ctx) { - error = fz_rethrow(n, "cannot read from file"); - goto cleanup; - } + listlen = 0; + listcap = 1024; + list = fz_malloc_array(ctx, listcap, sizeof(struct entry)); - fz_seek(xref->file, 0, 0); - for (i = 0; i < n - 4; i++) - { - if (memcmp(buf + i, "%PDF", 4) == 0) + /* look for '%PDF' version marker within first kilobyte of file */ + n = fz_read(xref->file, (unsigned char *)buf, MAX(bufsize, 1024)); + if (n < 0) + fz_throw(ctx, "cannot read from file"); + + fz_seek(xref->file, 0, 0); + for (i = 0; i < n - 4; i++) { - fz_seek(xref->file, i + 8, 0); /* skip "%PDF-X.Y" */ - break; + if (memcmp(buf + i, "%PDF", 4) == 0) + { + fz_seek(xref->file, i + 8, 0); /* skip "%PDF-X.Y" */ + break; + } } - } - /* skip comment line after version marker since some generators - * forget to terminate the comment with a newline */ - c = fz_read_byte(xref->file); - while (c >= 0 && (c == ' ' || c == '%')) + /* skip comment line after version marker since some generators + * forget to terminate the comment with a newline */ c = fz_read_byte(xref->file); - fz_unread_byte(xref->file); + while (c >= 0 && (c == ' ' || c == '%')) + c = fz_read_byte(xref->file); + fz_unread_byte(xref->file); - while (1) - { - tmpofs = fz_tell(xref->file); - if (tmpofs < 0) + while (1) { - error = fz_throw("cannot tell in file"); - goto cleanup; - } + tmpofs = fz_tell(xref->file); + if (tmpofs < 0) + fz_throw(ctx, "cannot tell in file"); - error = pdf_lex(&tok, xref->file, buf, bufsize, &n); - if (error) - { - fz_catch(error, "ignoring the rest of the file"); - break; - } + tok = pdf_lex(xref->file, buf, bufsize, &n); + /* RJW: "ignoring the rest of the file" */ - if (tok == PDF_TOK_INT) - { - numofs = genofs; - num = gen; - genofs = tmpofs; - gen = atoi(buf); - } + if (tok == PDF_TOK_INT) + { + numofs = genofs; + num = gen; + genofs = tmpofs; + gen = atoi(buf); + } - else if (tok == PDF_TOK_OBJ) - { - error = pdf_repair_obj(xref->file, buf, bufsize, &stm_ofs, &stm_len, &encrypt, &id); - if (error) + else if (tok == PDF_TOK_OBJ) { - error = fz_rethrow(error, "cannot parse object (%d %d R)", num, gen); - goto cleanup; + pdf_repair_obj(xref->file, buf, bufsize, &stm_ofs, &stm_len, &encrypt, &id); + /* RJW: "cannot parse object (%d %d R)", num, gen); */ + + if (listlen + 1 == listcap) + { + listcap = (listcap * 3) / 2; + list = fz_resize_array(ctx, list, listcap, sizeof(struct entry)); + } + + list[listlen].num = num; + list[listlen].gen = gen; + list[listlen].ofs = numofs; + list[listlen].stm_ofs = stm_ofs; + list[listlen].stm_len = stm_len; + listlen ++; + + if (num > maxnum) + maxnum = num; } - if (listlen + 1 == listcap) + /* trailer dictionary */ + else if (tok == PDF_TOK_OPEN_DICT) { - listcap = (listcap * 3) / 2; - list = fz_realloc(list, listcap, sizeof(struct entry)); + dict = pdf_parse_dict(xref, xref->file, buf, bufsize); + /* RJW: "cannot parse object" */ + + obj = fz_dict_gets(dict, "Encrypt"); + if (obj) + { + if (encrypt) + fz_drop_obj(encrypt); + encrypt = fz_keep_obj(obj); + } + + obj = fz_dict_gets(dict, "ID"); + if (obj) + { + if (id) + fz_drop_obj(id); + id = fz_keep_obj(obj); + } + + obj = fz_dict_gets(dict, "Root"); + if (obj) + { + if (root) + fz_drop_obj(root); + root = fz_keep_obj(obj); + } + + obj = fz_dict_gets(dict, "Info"); + if (obj) + { + if (info) + fz_drop_obj(info); + info = fz_keep_obj(obj); + } + + fz_drop_obj(dict); } - list[listlen].num = num; - list[listlen].gen = gen; - list[listlen].ofs = numofs; - list[listlen].stm_ofs = stm_ofs; - list[listlen].stm_len = stm_len; - listlen ++; + else if (tok == PDF_TOK_ERROR) + fz_read_byte(xref->file); - if (num > maxnum) - maxnum = num; + else if (tok == PDF_TOK_EOF) + break; } - /* trailer dictionary */ - else if (tok == PDF_TOK_OPEN_DICT) + /* make xref reasonable */ + + pdf_resize_xref(xref, maxnum + 1); + + for (i = 0; i < listlen; i++) { - error = pdf_parse_dict(&dict, xref, xref->file, buf, bufsize); - if (error) - { - error = fz_rethrow(error, "cannot parse object"); - goto cleanup; - } + xref->table[list[i].num].type = 'n'; + xref->table[list[i].num].ofs = list[i].ofs; + xref->table[list[i].num].gen = list[i].gen; - obj = fz_dict_gets(dict, "Encrypt"); - if (obj) - { - if (encrypt) - fz_drop_obj(encrypt); - encrypt = fz_keep_obj(obj); - } + xref->table[list[i].num].stm_ofs = list[i].stm_ofs; - obj = fz_dict_gets(dict, "ID"); - if (obj) + /* corrected stream length */ + if (list[i].stm_len >= 0) { - if (id) - fz_drop_obj(id); - id = fz_keep_obj(obj); - } + dict = pdf_load_object(xref, list[i].num, list[i].gen); + /* RJW: "cannot load stream object (%d %d R)", list[i].num, list[i].gen */ - obj = fz_dict_gets(dict, "Root"); - if (obj) - { - if (root) - fz_drop_obj(root); - root = fz_keep_obj(obj); - } + length = fz_new_int(ctx, list[i].stm_len); + fz_dict_puts(dict, "Length", length); + fz_drop_obj(length); - obj = fz_dict_gets(dict, "Info"); - if (obj) - { - if (info) - fz_drop_obj(info); - info = fz_keep_obj(obj); + fz_drop_obj(dict); } - fz_drop_obj(dict); } - else if (tok == PDF_TOK_ERROR) - fz_read_byte(xref->file); - - else if (tok == PDF_TOK_EOF) - break; - } - - /* make xref reasonable */ - - pdf_resize_xref(xref, maxnum + 1); + xref->table[0].type = 'f'; + xref->table[0].ofs = 0; + xref->table[0].gen = 65535; + xref->table[0].stm_ofs = 0; + xref->table[0].obj = NULL; - for (i = 0; i < listlen; i++) - { - xref->table[list[i].num].type = 'n'; - xref->table[list[i].num].ofs = list[i].ofs; - xref->table[list[i].num].gen = list[i].gen; - - xref->table[list[i].num].stm_ofs = list[i].stm_ofs; - - /* corrected stream length */ - if (list[i].stm_len >= 0) + next = 0; + for (i = xref->len - 1; i >= 0; i--) { - error = pdf_load_object(&dict, xref, list[i].num, list[i].gen); - if (error) + if (xref->table[i].type == 'f') { - error = fz_rethrow(error, "cannot load stream object (%d %d R)", list[i].num, list[i].gen); - goto cleanup; + xref->table[i].ofs = next; + if (xref->table[i].gen < 65535) + xref->table[i].gen ++; + next = i; } - - length = fz_new_int(list[i].stm_len); - fz_dict_puts(dict, "Length", length); - fz_drop_obj(length); - - fz_drop_obj(dict); } - } + /* create a repaired trailer, Root will be added later */ - xref->table[0].type = 'f'; - xref->table[0].ofs = 0; - xref->table[0].gen = 65535; - xref->table[0].stm_ofs = 0; - xref->table[0].obj = NULL; + xref->trailer = fz_new_dict(ctx, 5); - next = 0; - for (i = xref->len - 1; i >= 0; i--) - { - if (xref->table[i].type == 'f') + obj = fz_new_int(ctx, maxnum + 1); + fz_dict_puts(xref->trailer, "Size", obj); + fz_drop_obj(obj); + + if (root) { - xref->table[i].ofs = next; - if (xref->table[i].gen < 65535) - xref->table[i].gen ++; - next = i; + fz_dict_puts(xref->trailer, "Root", root); + fz_drop_obj(root); + } + if (info) + { + fz_dict_puts(xref->trailer, "Info", info); + fz_drop_obj(info); } - } - - /* create a repaired trailer, Root will be added later */ - - xref->trailer = fz_new_dict(5); - - obj = fz_new_int(maxnum + 1); - fz_dict_puts(xref->trailer, "Size", obj); - fz_drop_obj(obj); - - if (root) - { - fz_dict_puts(xref->trailer, "Root", root); - fz_drop_obj(root); - } - if (info) - { - fz_dict_puts(xref->trailer, "Info", info); - fz_drop_obj(info); - } - if (encrypt) - { - if (fz_is_indirect(encrypt)) + if (encrypt) { - /* create new reference with non-NULL xref pointer */ - obj = fz_new_indirect(fz_to_num(encrypt), fz_to_gen(encrypt), xref); + if (fz_is_indirect(encrypt)) + { + /* create new reference with non-NULL xref pointer */ + obj = fz_new_indirect(ctx, fz_to_num(encrypt), fz_to_gen(encrypt), xref); + fz_drop_obj(encrypt); + encrypt = obj; + } + fz_dict_puts(xref->trailer, "Encrypt", encrypt); fz_drop_obj(encrypt); - encrypt = obj; } - fz_dict_puts(xref->trailer, "Encrypt", encrypt); - fz_drop_obj(encrypt); - } - if (id) - { - if (fz_is_indirect(id)) + if (id) { - /* create new reference with non-NULL xref pointer */ - obj = fz_new_indirect(fz_to_num(id), fz_to_gen(id), xref); + if (fz_is_indirect(id)) + { + /* create new reference with non-NULL xref pointer */ + obj = fz_new_indirect(ctx, fz_to_num(id), fz_to_gen(id), xref); + fz_drop_obj(id); + id = obj; + } + fz_dict_puts(xref->trailer, "ID", id); fz_drop_obj(id); - id = obj; } - fz_dict_puts(xref->trailer, "ID", id); - fz_drop_obj(id); - } - fz_free(list); - return fz_okay; - -cleanup: - if (encrypt) fz_drop_obj(encrypt); - if (id) fz_drop_obj(id); - if (root) fz_drop_obj(root); - if (info) fz_drop_obj(info); - fz_free(list); - return error; /* already rethrown */ + fz_free(ctx, list); + } + fz_catch(ctx) + { + if (encrypt) fz_drop_obj(encrypt); + if (id) fz_drop_obj(id); + if (root) fz_drop_obj(root); + if (info) fz_drop_obj(info); + fz_free(ctx, list); + fz_rethrow(ctx); + } } -fz_error +void pdf_repair_obj_stms(pdf_xref *xref) { fz_obj *dict; @@ -461,12 +441,10 @@ pdf_repair_obj_stms(pdf_xref *xref) { if (xref->table[i].stm_ofs) { - pdf_load_object(&dict, xref, i, 0); + dict = pdf_load_object(xref, i, 0); if (!strcmp(fz_to_name(fz_dict_gets(dict, "Type")), "ObjStm")) pdf_repair_obj_stm(xref, i, 0); fz_drop_obj(dict); } } - - return fz_okay; } diff --git a/pdf/pdf_shade.c b/pdf/pdf_shade.c index 1e0bf5ff..b281542b 100644 --- a/pdf/pdf_shade.c +++ b/pdf/pdf_shade.c @@ -13,7 +13,7 @@ struct vertex }; static void -pdf_grow_mesh(fz_shade *shade, int amount) +pdf_grow_mesh(fz_context *ctx, fz_shade *shade, int amount) { if (shade->mesh_len + amount < shade->mesh_cap) return; @@ -24,15 +24,15 @@ pdf_grow_mesh(fz_shade *shade, int amount) while (shade->mesh_len + amount > shade->mesh_cap) shade->mesh_cap = (shade->mesh_cap * 3) / 2; - shade->mesh = fz_realloc(shade->mesh, shade->mesh_cap, sizeof(float)); + shade->mesh = fz_resize_array(ctx, shade->mesh, shade->mesh_cap, sizeof(float)); } static void -pdf_add_vertex(fz_shade *shade, struct vertex *v) +pdf_add_vertex(fz_context *ctx, fz_shade *shade, struct vertex *v) { int ncomp = shade->use_function ? 1 : shade->colorspace->n; int i; - pdf_grow_mesh(shade, 2 + ncomp); + pdf_grow_mesh(ctx, shade, 2 + ncomp); shade->mesh[shade->mesh_len++] = v->x; shade->mesh[shade->mesh_len++] = v->y; for (i = 0; i < ncomp; i++) @@ -40,25 +40,25 @@ pdf_add_vertex(fz_shade *shade, struct vertex *v) } static void -pdf_add_triangle(fz_shade *shade, +pdf_add_triangle(fz_context *ctx, fz_shade *shade, struct vertex *v0, struct vertex *v1, struct vertex *v2) { - pdf_add_vertex(shade, v0); - pdf_add_vertex(shade, v1); - pdf_add_vertex(shade, v2); + pdf_add_vertex(ctx, shade, v0); + pdf_add_vertex(ctx, shade, v1); + pdf_add_vertex(ctx, shade, v2); } static void -pdf_add_quad(fz_shade *shade, +pdf_add_quad(fz_context *ctx, fz_shade *shade, struct vertex *v0, struct vertex *v1, struct vertex *v2, struct vertex *v3) { - pdf_add_triangle(shade, v0, v1, v3); - pdf_add_triangle(shade, v1, v3, v2); + pdf_add_triangle(ctx, shade, v0, v1, v3); + pdf_add_triangle(ctx, shade, v1, v3, v2); } /* Subdivide and tesselate tensor-patches */ @@ -72,7 +72,7 @@ struct pdf_tensor_patch_s }; static void -triangulate_patch(pdf_tensor_patch p, fz_shade *shade) +triangulate_patch(fz_context *ctx, pdf_tensor_patch p, fz_shade *shade) { struct vertex v0, v1, v2, v3; @@ -92,7 +92,7 @@ triangulate_patch(pdf_tensor_patch p, fz_shade *shade) v3.y = p.pole[3][0].y; memcpy(v3.c, p.color[3], sizeof(v3.c)); - pdf_add_quad(shade, &v0, &v1, &v2, &v3); + pdf_add_quad(ctx, shade, &v0, &v1, &v2, &v3); } static inline void midcolor(float *c, float *c1, float *c2) @@ -163,7 +163,7 @@ split_stripe(pdf_tensor_patch *p, pdf_tensor_patch *s0, pdf_tensor_patch *s1) } static void -draw_stripe(pdf_tensor_patch *p, fz_shade *shade, int depth) +draw_stripe(fz_context *ctx, pdf_tensor_patch *p, fz_shade *shade, int depth) { pdf_tensor_patch s0, s1; @@ -174,14 +174,14 @@ draw_stripe(pdf_tensor_patch *p, fz_shade *shade, int depth) if (depth == 0) { /* if no more subdividing, draw two new patches... */ - triangulate_patch(s0, shade); - triangulate_patch(s1, shade); + triangulate_patch(ctx, s0, shade); + triangulate_patch(ctx, s1, shade); } else { /* ...otherwise, continue subdividing. */ - draw_stripe(&s0, shade, depth); - draw_stripe(&s1, shade, depth); + draw_stripe(ctx, &s0, shade, depth); + draw_stripe(ctx, &s1, shade, depth); } } @@ -210,7 +210,7 @@ split_patch(pdf_tensor_patch *p, pdf_tensor_patch *s0, pdf_tensor_patch *s1) } static void -draw_patch(fz_shade *shade, pdf_tensor_patch *p, int depth, int origdepth) +draw_patch(fz_context *ctx, fz_shade *shade, pdf_tensor_patch *p, int depth, int origdepth) { pdf_tensor_patch s0, s1; @@ -221,14 +221,14 @@ draw_patch(fz_shade *shade, pdf_tensor_patch *p, int depth, int origdepth) if (depth == 0) { /* if no more subdividing, draw two new patches... */ - draw_stripe(&s0, shade, origdepth); - draw_stripe(&s1, shade, origdepth); + draw_stripe(ctx, &s0, shade, origdepth); + draw_stripe(ctx, &s1, shade, origdepth); } else { /* ...otherwise, continue subdividing. */ - draw_patch(shade, &s0, depth, origdepth); - draw_patch(shade, &s1, depth, origdepth); + draw_patch(ctx, shade, &s0, depth, origdepth); + draw_patch(ctx, shade, &s1, depth, origdepth); } } @@ -322,7 +322,7 @@ pdf_make_tensor_patch(pdf_tensor_patch *p, int type, fz_point *pt) /* Sample various functions into lookup tables */ static void -pdf_sample_composite_shade_function(fz_shade *shade, pdf_function *func, float t0, float t1) +pdf_sample_composite_shade_function(fz_context *ctx, fz_shade *shade, pdf_function *func, float t0, float t1) { int i; float t; @@ -330,13 +330,13 @@ pdf_sample_composite_shade_function(fz_shade *shade, pdf_function *func, float t for (i = 0; i < 256; i++) { t = t0 + (i / 255.0f) * (t1 - t0); - pdf_eval_function(func, &t, 1, shade->function[i], shade->colorspace->n); + pdf_eval_function(ctx, func, &t, 1, shade->function[i], shade->colorspace->n); shade->function[i][shade->colorspace->n] = 1; } } static void -pdf_sample_component_shade_function(fz_shade *shade, int funcs, pdf_function **func, float t0, float t1) +pdf_sample_component_shade_function(fz_context *ctx, fz_shade *shade, int funcs, pdf_function **func, float t0, float t1) { int i, k; float t; @@ -345,19 +345,19 @@ pdf_sample_component_shade_function(fz_shade *shade, int funcs, pdf_function **f { t = t0 + (i / 255.0f) * (t1 - t0); for (k = 0; k < funcs; k++) - pdf_eval_function(func[k], &t, 1, &shade->function[i][k], 1); + pdf_eval_function(ctx, func[k], &t, 1, &shade->function[i][k], 1); shade->function[i][k] = 1; } } static void -pdf_sample_shade_function(fz_shade *shade, int funcs, pdf_function **func, float t0, float t1) +pdf_sample_shade_function(fz_context *ctx, fz_shade *shade, int funcs, pdf_function **func, float t0, float t1) { shade->use_function = 1; if (funcs == 1) - pdf_sample_composite_shade_function(shade, func[0], t0, t1); + pdf_sample_composite_shade_function(ctx, shade, func[0], t0, t1); else - pdf_sample_component_shade_function(shade, funcs, func, t0, t1); + pdf_sample_component_shade_function(ctx, shade, funcs, func, t0, t1); } /* Type 1-3 -- Function-based, axial and radial shadings */ @@ -373,6 +373,7 @@ pdf_load_function_based_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, p float x, y; float xn, yn; int i; + fz_context *ctx = xref->ctx; x0 = y0 = 0; x1 = y1 = 1; @@ -388,7 +389,7 @@ pdf_load_function_based_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, p matrix = fz_identity; obj = fz_dict_gets(dict, "Matrix"); if (fz_array_len(obj) == 6) - matrix = pdf_to_matrix(obj); + matrix = pdf_to_matrix(ctx, obj); for (yy = 0; yy < FUNSEGS; yy++) { @@ -412,7 +413,7 @@ pdf_load_function_based_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, p fv[0] = v[i].x; fv[1] = v[i].y; - pdf_eval_function(func, fv, 2, v[i].c, shade->colorspace->n); + pdf_eval_function(ctx, func, fv, 2, v[i].c, shade->colorspace->n); pt.x = v[i].x; pt.y = v[i].y; @@ -421,7 +422,7 @@ pdf_load_function_based_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, p v[i].y = pt.y; } - pdf_add_quad(shade, &v[0], &v[1], &v[2], &v[3]); + pdf_add_quad(ctx, shade, &v[0], &v[1], &v[2], &v[3]); } } } @@ -434,6 +435,7 @@ pdf_load_axial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, int e0, e1; float x0, y0, x1, y1; struct vertex p1, p2; + fz_context *ctx = xref->ctx; obj = fz_dict_gets(dict, "Coords"); x0 = fz_to_real(fz_array_get(obj, 0)); @@ -458,7 +460,7 @@ pdf_load_axial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, e1 = fz_to_bool(fz_array_get(obj, 1)); } - pdf_sample_shade_function(shade, funcs, func, d0, d1); + pdf_sample_shade_function(ctx, shade, funcs, func, d0, d1); shade->type = FZ_LINEAR; @@ -468,12 +470,12 @@ pdf_load_axial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, p1.x = x0; p1.y = y0; p1.c[0] = 0; - pdf_add_vertex(shade, &p1); + pdf_add_vertex(ctx, shade, &p1); p2.x = x1; p2.y = y1; p2.c[0] = 0; - pdf_add_vertex(shade, &p2); + pdf_add_vertex(ctx, shade, &p2); } static void @@ -484,6 +486,7 @@ pdf_load_radial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs int e0, e1; float x0, y0, r0, x1, y1, r1; struct vertex p1, p2; + fz_context *ctx = xref->ctx; obj = fz_dict_gets(dict, "Coords"); x0 = fz_to_real(fz_array_get(obj, 0)); @@ -510,7 +513,7 @@ pdf_load_radial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs e1 = fz_to_bool(fz_array_get(obj, 1)); } - pdf_sample_shade_function(shade, funcs, func, d0, d1); + pdf_sample_shade_function(ctx, shade, funcs, func, d0, d1); shade->type = FZ_RADIAL; @@ -520,12 +523,12 @@ pdf_load_radial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs p1.x = x0; p1.y = y0; p1.c[0] = r0; - pdf_add_vertex(shade, &p1); + pdf_add_vertex(ctx, shade, &p1); p2.x = x1; p2.y = y1; p2.c[0] = r1; - pdf_add_vertex(shade, &p2); + pdf_add_vertex(ctx, shade, &p2); } /* Type 4-7 -- Triangle and patch mesh shadings */ @@ -603,6 +606,7 @@ static void pdf_load_type4_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func, fz_stream *stream) { + fz_context *ctx = xref->ctx; struct mesh_params p; struct vertex va, vb, vc, vd; int ncomp; @@ -614,7 +618,7 @@ pdf_load_type4_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, if (funcs > 0) { ncomp = 1; - pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]); + pdf_sample_shade_function(ctx, shade, funcs, func, p.c0[0], p.c1[0]); } else ncomp = shade->colorspace->n; @@ -644,20 +648,20 @@ pdf_load_type4_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, for (i = 0; i < ncomp; i++) vc.c[i] = read_sample(stream, p.bpcomp, p.c0[i], p.c1[i]); - pdf_add_triangle(shade, &va, &vb, &vc); + pdf_add_triangle(ctx, shade, &va, &vb, &vc); break; case 1: /* Vb, Vc, Vd */ va = vb; vb = vc; vc = vd; - pdf_add_triangle(shade, &va, &vb, &vc); + pdf_add_triangle(ctx, shade, &va, &vb, &vc); break; case 2: /* Va, Vc, Vd */ vb = vc; vc = vd; - pdf_add_triangle(shade, &va, &vb, &vc); + pdf_add_triangle(ctx, shade, &va, &vb, &vc); break; } } @@ -667,6 +671,7 @@ static void pdf_load_type5_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func, fz_stream *stream) { + fz_context *ctx = xref->ctx; struct mesh_params p; struct vertex *buf, *ref; int first; @@ -678,13 +683,13 @@ pdf_load_type5_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, if (funcs > 0) { ncomp = 1; - pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]); + pdf_sample_shade_function(ctx, shade, funcs, func, p.c0[0], p.c1[0]); } else ncomp = shade->colorspace->n; - ref = fz_calloc(p.vprow, sizeof(struct vertex)); - buf = fz_calloc(p.vprow, sizeof(struct vertex)); + ref = fz_malloc_array(ctx, p.vprow, sizeof(struct vertex)); + buf = fz_malloc_array(ctx, p.vprow, sizeof(struct vertex)); first = 1; while (!fz_is_eof_bits(stream)) @@ -699,7 +704,7 @@ pdf_load_type5_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, if (!first) for (i = 0; i < p.vprow - 1; i++) - pdf_add_quad(shade, + pdf_add_quad(ctx, shade, &ref[i], &ref[i+1], &buf[i+1], &buf[i]); memcpy(ref, buf, p.vprow * sizeof(struct vertex)); @@ -716,6 +721,7 @@ static void pdf_load_type6_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func, fz_stream *stream) { + fz_context *ctx = xref->ctx; struct mesh_params p; int haspatch, hasprevpatch; float prevc[4][FZ_MAX_COLORS]; @@ -728,7 +734,7 @@ pdf_load_type6_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, if (funcs > 0) { ncomp = 1; - pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]); + pdf_sample_shade_function(ctx, shade, funcs, func, p.c0[0], p.c1[0]); } else ncomp = shade->colorspace->n; @@ -817,7 +823,7 @@ pdf_load_type6_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, for (i = 0; i < 4; i++) memcpy(patch.color[i], c[i], ncomp * sizeof(float)); - draw_patch(shade, &patch, SUBDIV, SUBDIV); + draw_patch(ctx, shade, &patch, SUBDIV, SUBDIV); for (i = 0; i < 12; i++) prevp[i] = v[i]; @@ -834,6 +840,7 @@ static void pdf_load_type7_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func, fz_stream *stream) { + fz_context *ctx = xref->ctx; struct mesh_params p; int haspatch, hasprevpatch; float prevc[4][FZ_MAX_COLORS]; @@ -846,7 +853,7 @@ pdf_load_type7_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, if (funcs > 0) { ncomp = 1; - pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]); + pdf_sample_shade_function(ctx, shade, funcs, func, p.c0[0], p.c1[0]); } else ncomp = shade->colorspace->n; @@ -935,7 +942,7 @@ pdf_load_type7_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, for (i = 0; i < 4; i++) memcpy(patch.color[i], c[i], ncomp * sizeof(float)); - draw_patch(shade, &patch, SUBDIV, SUBDIV); + draw_patch(ctx, shade, &patch, SUBDIV, SUBDIV); for (i = 0; i < 16; i++) prevp[i] = v[i]; @@ -950,153 +957,133 @@ pdf_load_type7_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, /* Load all of the shading dictionary parameters, then switch on the shading type. */ -static fz_error -pdf_load_shading_dict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_matrix transform) +static fz_shade * +pdf_load_shading_dict(pdf_xref *xref, fz_obj *dict, fz_matrix transform) { - fz_error error; - fz_shade *shade; - pdf_function *func[FZ_MAX_COLORS] = { NULL }; - fz_stream *stream = NULL; + fz_shade * volatile shade = NULL; + pdf_function * volatile func[FZ_MAX_COLORS] = { NULL }; + fz_stream * volatile stream = NULL; fz_obj *obj; int funcs; int type; int i; + fz_context *ctx = xref->ctx; - shade = fz_malloc(sizeof(fz_shade)); - shade->refs = 1; - shade->type = FZ_MESH; - shade->use_background = 0; - shade->use_function = 0; - shade->matrix = transform; - shade->bbox = fz_infinite_rect; - shade->extend[0] = 0; - shade->extend[1] = 0; - - shade->mesh_len = 0; - shade->mesh_cap = 0; - shade->mesh = NULL; - - shade->colorspace = NULL; - - funcs = 0; + fz_try(ctx) + { + shade = fz_malloc(ctx, sizeof(fz_shade)); + shade->refs = 1; + shade->type = FZ_MESH; + shade->use_background = 0; + shade->use_function = 0; + shade->matrix = transform; + shade->bbox = fz_infinite_rect; + shade->extend[0] = 0; + shade->extend[1] = 0; - obj = fz_dict_gets(dict, "ShadingType"); - type = fz_to_int(obj); + shade->mesh_len = 0; + shade->mesh_cap = 0; + shade->mesh = NULL; - obj = fz_dict_gets(dict, "ColorSpace"); - if (!obj) - { - fz_drop_shade(shade); - return fz_throw("shading colorspace is missing"); - } - error = pdf_load_colorspace(&shade->colorspace, xref, obj); - if (error) - { - fz_drop_shade(shade); - return fz_rethrow(error, "cannot load colorspace (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); - } + shade->colorspace = NULL; - obj = fz_dict_gets(dict, "Background"); - if (obj) - { - shade->use_background = 1; - for (i = 0; i < shade->colorspace->n; i++) - shade->background[i] = fz_to_real(fz_array_get(obj, i)); - } + funcs = 0; - obj = fz_dict_gets(dict, "BBox"); - if (fz_is_array(obj)) - { - shade->bbox = pdf_to_rect(obj); - } + obj = fz_dict_gets(dict, "ShadingType"); + type = fz_to_int(obj); - obj = fz_dict_gets(dict, "Function"); - if (fz_is_dict(obj)) - { - funcs = 1; + obj = fz_dict_gets(dict, "ColorSpace"); + if (!obj) + fz_throw(ctx, "shading colorspace is missing"); + shade->colorspace = pdf_load_colorspace(xref, obj); + /* RJW: "cannot load colorspace (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */ - error = pdf_load_function(&func[0], xref, obj); - if (error) + obj = fz_dict_gets(dict, "Background"); + if (obj) { - error = fz_rethrow(error, "cannot load shading function (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); - goto cleanup; + shade->use_background = 1; + for (i = 0; i < shade->colorspace->n; i++) + shade->background[i] = fz_to_real(fz_array_get(obj, i)); } - } - else if (fz_is_array(obj)) - { - funcs = fz_array_len(obj); - if (funcs != 1 && funcs != shade->colorspace->n) + + obj = fz_dict_gets(dict, "BBox"); + if (fz_is_array(obj)) { - error = fz_throw("incorrect number of shading functions"); - goto cleanup; + shade->bbox = pdf_to_rect(ctx, obj); } - for (i = 0; i < funcs; i++) + obj = fz_dict_gets(dict, "Function"); + if (fz_is_dict(obj)) { - error = pdf_load_function(&func[i], xref, fz_array_get(obj, i)); - if (error) + funcs = 1; + + func[0] = pdf_load_function(xref, obj); + /* RJW: "cannot load shading function (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */ + } + else if (fz_is_array(obj)) + { + funcs = fz_array_len(obj); + if (funcs != 1 && funcs != shade->colorspace->n) + fz_throw(ctx, "incorrect number of shading functions"); + + for (i = 0; i < funcs; i++) { - error = fz_rethrow(error, "cannot load shading function (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); - goto cleanup; + func[i] = pdf_load_function(xref, fz_array_get(obj, i)); + if (func[i] == NULL) + fz_throw(ctx, "cannot load shading function (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); } } - } - if (type >= 4 && type <= 7) - { - error = pdf_open_stream(&stream, xref, fz_to_num(dict), fz_to_gen(dict)); - if (error) + if (type >= 4 && type <= 7) { - error = fz_rethrow(error, "cannot open shading stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); - goto cleanup; + stream = pdf_open_stream(xref, fz_to_num(dict), fz_to_gen(dict)); + /* RJW: "cannot open shading stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict) */ } - } - - switch (type) - { - case 1: pdf_load_function_based_shading(shade, xref, dict, func[0]); break; - case 2: pdf_load_axial_shading(shade, xref, dict, funcs, func); break; - case 3: pdf_load_radial_shading(shade, xref, dict, funcs, func); break; - case 4: pdf_load_type4_shade(shade, xref, dict, funcs, func, stream); break; - case 5: pdf_load_type5_shade(shade, xref, dict, funcs, func, stream); break; - case 6: pdf_load_type6_shade(shade, xref, dict, funcs, func, stream); break; - case 7: pdf_load_type7_shade(shade, xref, dict, funcs, func, stream); break; - default: - error = fz_throw("unknown shading type: %d", type); - goto cleanup; - } - if (stream) - fz_close(stream); - for (i = 0; i < funcs; i++) - if (func[i]) - pdf_drop_function(func[i]); - - *shadep = shade; - return fz_okay; + switch (type) + { + case 1: pdf_load_function_based_shading(shade, xref, dict, func[0]); break; + case 2: pdf_load_axial_shading(shade, xref, dict, funcs, func); break; + case 3: pdf_load_radial_shading(shade, xref, dict, funcs, func); break; + case 4: pdf_load_type4_shade(shade, xref, dict, funcs, func, stream); break; + case 5: pdf_load_type5_shade(shade, xref, dict, funcs, func, stream); break; + case 6: pdf_load_type6_shade(shade, xref, dict, funcs, func, stream); break; + case 7: pdf_load_type7_shade(shade, xref, dict, funcs, func, stream); break; + default: + fz_throw(ctx, "unknown shading type: %d", type); + } -cleanup: - if (stream) - fz_close(stream); - for (i = 0; i < funcs; i++) - if (func[i]) - pdf_drop_function(func[i]); - fz_drop_shade(shade); + if (stream) + fz_close(stream); + for (i = 0; i < funcs; i++) + if (func[i]) + pdf_drop_function(ctx, func[i]); + } + fz_catch(ctx) + { + if (stream) + fz_close(stream); + for (i = 0; i < funcs; i++) + if (func[i]) + pdf_drop_function(ctx, func[i]); + fz_drop_shade(ctx, shade); - return fz_rethrow(error, "cannot load shading type %d (%d %d R)", type, fz_to_num(dict), fz_to_gen(dict)); + fz_throw(ctx, "cannot load shading type %d (%d %d R)", type, fz_to_num(dict), fz_to_gen(dict)); + } + return shade; } -fz_error -pdf_load_shading(fz_shade **shadep, pdf_xref *xref, fz_obj *dict) +fz_shade * +pdf_load_shading(pdf_xref *xref, fz_obj *dict) { - fz_error error; fz_matrix mat; fz_obj *obj; + fz_context *ctx = xref->ctx; + fz_shade *shade; - if ((*shadep = pdf_find_item(xref->store, fz_drop_shade, dict))) + if ((shade = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)fz_drop_shade, dict))) { - fz_keep_shade(*shadep); - return fz_okay; + return fz_keep_shade(shade); } /* Type 2 pattern dictionary */ @@ -1104,7 +1091,7 @@ pdf_load_shading(fz_shade **shadep, pdf_xref *xref, fz_obj *dict) { obj = fz_dict_gets(dict, "Matrix"); if (obj) - mat = pdf_to_matrix(obj); + mat = pdf_to_matrix(ctx, obj); else mat = fz_identity; @@ -1113,28 +1100,26 @@ pdf_load_shading(fz_shade **shadep, pdf_xref *xref, fz_obj *dict) { if (fz_dict_gets(obj, "CA") || fz_dict_gets(obj, "ca")) { - fz_warn("shading with alpha not supported"); + fz_warn(ctx, "shading with alpha not supported"); } } obj = fz_dict_gets(dict, "Shading"); if (!obj) - return fz_throw("syntaxerror: missing shading dictionary"); + fz_throw(ctx, "syntaxerror: missing shading dictionary"); - error = pdf_load_shading_dict(shadep, xref, obj, mat); - if (error) - return fz_rethrow(error, "cannot load shading dictionary (%d %d R)", fz_to_num(obj), fz_to_gen(obj)); + shade = pdf_load_shading_dict(xref, obj, mat); + /* RJW: "cannot load shading dictionary (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */ } /* Naked shading dictionary */ else { - error = pdf_load_shading_dict(shadep, xref, dict, fz_identity); - if (error) - return fz_rethrow(error, "cannot load shading dictionary (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + shade = pdf_load_shading_dict(xref, dict, fz_identity); + /* RJW: "cannot load shading dictionary (%d %d R)", fz_to_num(dict), fz_to_gen(dict) */ } - pdf_store_item(xref->store, fz_keep_shade, fz_drop_shade, dict, *shadep); + pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)fz_keep_shade, (pdf_store_drop_fn *)fz_drop_shade, dict, shade); - return fz_okay; + return shade; } diff --git a/pdf/pdf_store.c b/pdf/pdf_store.c index a57f839a..4d20e859 100644 --- a/pdf/pdf_store.c +++ b/pdf/pdf_store.c @@ -5,7 +5,7 @@ typedef struct pdf_item_s pdf_item; struct pdf_item_s { - void *drop_func; + pdf_store_drop_fn *drop_func; fz_obj *key; void *val; int age; @@ -14,7 +14,7 @@ struct pdf_item_s struct refkey { - void *drop_func; + pdf_store_drop_fn *drop_func; int num; int gen; }; @@ -26,27 +26,27 @@ struct pdf_store_s }; pdf_store * -pdf_new_store(void) +pdf_new_store(fz_context *ctx) { pdf_store *store; - store = fz_malloc(sizeof(pdf_store)); - store->hash = fz_new_hash_table(4096, sizeof(struct refkey)); + store = fz_malloc(ctx, sizeof(pdf_store)); + store->hash = fz_new_hash_table(ctx, 4096, sizeof(struct refkey)); store->root = NULL; return store; } void -pdf_store_item(pdf_store *store, void *keepfunc, void *drop_func, fz_obj *key, void *val) +pdf_store_item(fz_context *ctx, pdf_store *store, pdf_store_keep_fn *keep_func, pdf_store_drop_fn *drop_func, fz_obj *key, void *val) { pdf_item *item; if (!store) return; - item = fz_malloc(sizeof(pdf_item)); + item = fz_malloc(ctx, sizeof(pdf_item)); item->drop_func = drop_func; item->key = fz_keep_obj(key); - item->val = ((void*(*)(void*))keepfunc)(val); + item->val = keep_func(val); item->age = 0; item->next = NULL; @@ -66,7 +66,7 @@ pdf_store_item(pdf_store *store, void *keepfunc, void *drop_func, fz_obj *key, v } void * -pdf_find_item(pdf_store *store, void *drop_func, fz_obj *key) +pdf_find_item(fz_context *ctx, pdf_store *store, pdf_store_drop_fn *drop_func, fz_obj *key) { struct refkey refkey; pdf_item *item; @@ -105,7 +105,7 @@ pdf_find_item(pdf_store *store, void *drop_func, fz_obj *key) } void -pdf_remove_item(pdf_store *store, void *drop_func, fz_obj *key) +pdf_remove_item(fz_context *ctx, pdf_store *store, pdf_store_drop_fn *drop_func, fz_obj *key) { struct refkey refkey; pdf_item *item, *prev, *next; @@ -119,9 +119,9 @@ pdf_remove_item(pdf_store *store, void *drop_func, fz_obj *key) if (item) { fz_hash_remove(store->hash, &refkey); - ((void(*)(void*))item->drop_func)(item->val); + item->drop_func(ctx, item->val); fz_drop_obj(item->key); - fz_free(item); + fz_free(ctx, item); } } else @@ -136,9 +136,9 @@ pdf_remove_item(pdf_store *store, void *drop_func, fz_obj *key) store->root = next; else prev->next = next; - ((void(*)(void*))item->drop_func)(item->val); + item->drop_func(ctx, item->val); fz_drop_obj(item->key); - fz_free(item); + fz_free(ctx, item); } else prev = item; @@ -147,22 +147,23 @@ pdf_remove_item(pdf_store *store, void *drop_func, fz_obj *key) } void -pdf_age_store(pdf_store *store, int maxage) +pdf_age_store(fz_context *ctx, pdf_store *store, int maxage) { struct refkey *refkey; pdf_item *item, *prev, *next; - int i; + int i, n; - for (i = 0; i < fz_hash_len(store->hash); i++) + n = fz_hash_len(store->hash); + for (i = 0; i < n; i++) { refkey = fz_hash_get_key(store->hash, i); item = fz_hash_get_val(store->hash, i); if (item && ++item->age > maxage) { fz_hash_remove(store->hash, refkey); - ((void(*)(void*))item->drop_func)(item->val); + item->drop_func(ctx, item->val); fz_drop_obj(item->key); - fz_free(item); + fz_free(ctx, item); i--; /* items with same hash may move into place */ } } @@ -177,9 +178,9 @@ pdf_age_store(pdf_store *store, int maxage) store->root = next; else prev->next = next; - ((void(*)(void*))item->drop_func)(item->val); + item->drop_func(ctx, item->val); fz_drop_obj(item->key); - fz_free(item); + fz_free(ctx, item); } else prev = item; @@ -187,24 +188,25 @@ pdf_age_store(pdf_store *store, int maxage) } void -pdf_free_store(pdf_store *store) +pdf_free_store(fz_context *ctx, pdf_store *store) { - pdf_age_store(store, 0); + pdf_age_store(ctx, store, 0); fz_free_hash(store->hash); - fz_free(store); + fz_free(ctx, store); } void -pdf_debug_store(pdf_store *store) +pdf_debug_store(fz_context *ctx, pdf_store *store) { pdf_item *item; pdf_item *next; struct refkey *refkey; - int i; + int i, n; printf("-- resource store contents --\n"); - for (i = 0; i < fz_hash_len(store->hash); i++) + n = fz_hash_len(store->hash); + for (i = 0; i < n; i++) { refkey = fz_hash_get_key(store->hash, i); item = fz_hash_get_val(store->hash, i); diff --git a/pdf/pdf_stream.c b/pdf/pdf_stream.c index c2dd8578..614f076a 100644 --- a/pdf/pdf_stream.c +++ b/pdf/pdf_stream.c @@ -7,17 +7,11 @@ int pdf_is_stream(pdf_xref *xref, int num, int gen) { - fz_error error; - if (num < 0 || num >= xref->len) return 0; - error = pdf_cache_object(xref, num, gen); - if (error) - { - fz_catch(error, "cannot load object, ignoring error"); - return 0; - } + pdf_cache_object(xref, num, gen); + /* RJW: "cannot load object, ignoring error" */ return xref->table[num].stm_ofs > 0; } @@ -26,7 +20,7 @@ pdf_is_stream(pdf_xref *xref, int num, int gen) * Scan stream dictionary for an explicit /Crypt filter */ static int -pdf_stream_has_crypt(fz_obj *stm) +pdf_stream_has_crypt(fz_context *ctx, fz_obj *stm) { fz_obj *filters; fz_obj *obj; @@ -39,7 +33,8 @@ pdf_stream_has_crypt(fz_obj *stm) return 1; if (fz_is_array(filters)) { - for (i = 0; i < fz_array_len(filters); i++) + int n = fz_array_len(filters); + for (i = 0; i < n; i++) { obj = fz_array_get(filters, i); if (!strcmp(fz_to_name(obj), "Crypt")) @@ -56,8 +51,8 @@ pdf_stream_has_crypt(fz_obj *stm) static fz_stream * build_filter(fz_stream *chain, pdf_xref * xref, fz_obj * f, fz_obj * p, int num, int gen) { - fz_error error; char *s; + fz_context *ctx = chain->ctx; s = fz_to_name(f); @@ -98,11 +93,10 @@ build_filter(fz_stream *chain, pdf_xref * xref, fz_obj * f, fz_obj * p, int num, if (obj) { fz_buffer *globals; - error = pdf_load_stream(&globals, xref, fz_to_num(obj), fz_to_gen(obj)); - if (error) - fz_catch(error, "cannot load jbig2 global segments"); + globals = pdf_load_stream(xref, fz_to_num(obj), fz_to_gen(obj)); + /* RJW: "cannot load jbig2 global segments" */ chain = fz_open_jbig2d(chain, globals); - fz_drop_buffer(globals); + fz_drop_buffer(ctx, globals); return chain; } return fz_open_jbig2d(chain, NULL); @@ -117,7 +111,7 @@ build_filter(fz_stream *chain, pdf_xref * xref, fz_obj * f, fz_obj * p, int num, if (!xref->crypt) { - fz_warn("crypt filter in unencrypted document"); + fz_warn(ctx, "crypt filter in unencrypted document"); return chain; } @@ -128,7 +122,7 @@ build_filter(fz_stream *chain, pdf_xref * xref, fz_obj * f, fz_obj * p, int num, return chain; } - fz_warn("unknown filter name (%s)", s); + fz_warn(ctx, "unknown filter name (%s)", s); return chain; } @@ -142,9 +136,10 @@ build_filter_chain(fz_stream *chain, pdf_xref *xref, fz_obj *fs, fz_obj *ps, int { fz_obj *f; fz_obj *p; - int i; + int i, n; - for (i = 0; i < fz_array_len(fs); i++) + n = fz_array_len(fs); + for (i = 0; i < n; i++) { f = fz_array_get(fs, i); p = fz_array_get(ps, i); @@ -164,6 +159,7 @@ pdf_open_raw_filter(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int num, i { int hascrypt; int len; + fz_context *ctx = chain->ctx; /* don't close chain when we close this filter */ fz_keep_stream(chain); @@ -171,7 +167,7 @@ pdf_open_raw_filter(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int num, i len = fz_to_int(fz_dict_gets(stmobj, "Length")); chain = fz_open_null(chain, len); - hascrypt = pdf_stream_has_crypt(stmobj); + hascrypt = pdf_stream_has_crypt(ctx, stmobj); if (xref->crypt && !hascrypt) chain = pdf_open_crypt(chain, xref->crypt, num, gen); @@ -229,29 +225,26 @@ pdf_open_inline_stream(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int len * Open a stream for reading the raw (compressed but decrypted) data. * Using xref->file while this is open is a bad idea. */ -fz_error -pdf_open_raw_stream(fz_stream **stmp, pdf_xref *xref, int num, int gen) +fz_stream * +pdf_open_raw_stream(pdf_xref *xref, int num, int gen) { - pdf_xref_entry *x; - fz_error error; + pdf_xref_entry * volatile x; + fz_stream *stm; if (num < 0 || num >= xref->len) - return fz_throw("object id out of range (%d %d R)", num, gen); + fz_throw(xref->ctx, "object id out of range (%d %d R)", num, gen); x = xref->table + num; - error = pdf_cache_object(xref, num, gen); - if (error) - return fz_rethrow(error, "cannot load stream object (%d %d R)", num, gen); + pdf_cache_object(xref, num, gen); + /* RJW: "cannot load stream object (%d %d R)", num, gen */ - if (x->stm_ofs) - { - *stmp = pdf_open_raw_filter(xref->file, xref, x->obj, num, gen); - fz_seek(xref->file, x->stm_ofs, 0); - return fz_okay; - } + if (x->stm_ofs == 0) + fz_throw(xref->ctx, "object is not a stream"); - return fz_throw("object is not a stream"); + stm = pdf_open_raw_filter(xref->file, xref, x->obj, num, gen); + fz_seek(xref->file, x->stm_ofs, 0); + return stm; } /* @@ -259,75 +252,67 @@ pdf_open_raw_stream(fz_stream **stmp, pdf_xref *xref, int num, int gen) * Put the opened file in xref->stream. * Using xref->file while a stream is open is a Bad idea. */ -fz_error -pdf_open_stream(fz_stream **stmp, pdf_xref *xref, int num, int gen) +fz_stream * +pdf_open_stream(pdf_xref *xref, int num, int gen) { pdf_xref_entry *x; - fz_error error; + fz_stream *stm; if (num < 0 || num >= xref->len) - return fz_throw("object id out of range (%d %d R)", num, gen); + fz_throw(xref->ctx, "object id out of range (%d %d R)", num, gen); x = xref->table + num; - error = pdf_cache_object(xref, num, gen); - if (error) - return fz_rethrow(error, "cannot load stream object (%d %d R)", num, gen); + pdf_cache_object(xref, num, gen); + /* RJW: "cannot load stream object (%d %d R)", num, gen */ - if (x->stm_ofs) - { - *stmp = pdf_open_filter(xref->file, xref, x->obj, num, gen); - fz_seek(xref->file, x->stm_ofs, 0); - return fz_okay; - } + if (x->stm_ofs == 0) + fz_throw(xref->ctx, "object is not a stream"); - return fz_throw("object is not a stream"); + stm = pdf_open_filter(xref->file, xref, x->obj, num, gen); + fz_seek(xref->file, x->stm_ofs, 0); + return stm; } -fz_error -pdf_open_stream_at(fz_stream **stmp, pdf_xref *xref, int num, int gen, fz_obj *dict, int stm_ofs) +fz_stream * +pdf_open_stream_at(pdf_xref *xref, int num, int gen, fz_obj *dict, int stm_ofs) { - if (stm_ofs) - { - *stmp = pdf_open_filter(xref->file, xref, dict, num, gen); - fz_seek(xref->file, stm_ofs, 0); - return fz_okay; - } - return fz_throw("object is not a stream"); + fz_stream *stm; + + if (stm_ofs == 0) + fz_throw(xref->ctx, "object is not a stream"); + + stm = pdf_open_filter(xref->file, xref, dict, num, gen); + fz_seek(xref->file, stm_ofs, 0); + return stm; } /* * Load raw (compressed but decrypted) contents of a stream into buf. */ -fz_error -pdf_load_raw_stream(fz_buffer **bufp, pdf_xref *xref, int num, int gen) +fz_buffer * +pdf_load_raw_stream(pdf_xref *xref, int num, int gen) { - fz_error error; fz_stream *stm; fz_obj *dict; int len; + fz_buffer *buf; - error = pdf_load_object(&dict, xref, num, gen); - if (error) - return fz_rethrow(error, "cannot load stream dictionary (%d %d R)", num, gen); + dict = pdf_load_object(xref, num, gen); + /* RJW: "cannot load stream dictionary (%d %d R)", num, gen */ len = fz_to_int(fz_dict_gets(dict, "Length")); fz_drop_obj(dict); - error = pdf_open_raw_stream(&stm, xref, num, gen); - if (error) - return fz_rethrow(error, "cannot open raw stream (%d %d R)", num, gen); + stm = pdf_open_raw_stream(xref, num, gen); + /* RJW: "cannot open raw stream (%d %d R)", num, gen */ - error = fz_read_all(bufp, stm, len); - if (error) - { - fz_close(stm); - return fz_rethrow(error, "cannot read raw stream (%d %d R)", num, gen); - } + buf = fz_read_all(stm, len); + /* RJW: "cannot read raw stream (%d %d R)", num, gen */ fz_close(stm); - return fz_okay; + return buf; } static int @@ -349,37 +334,40 @@ pdf_guess_filter_length(int len, char *filter) /* * Load uncompressed contents of a stream into buf. */ -fz_error -pdf_load_stream(fz_buffer **bufp, pdf_xref *xref, int num, int gen) +fz_buffer * +pdf_load_stream(pdf_xref *xref, int num, int gen) { - fz_error error; + fz_context *ctx = xref->ctx; fz_stream *stm; fz_obj *dict, *obj; - int i, len; + int i, len, n; + fz_buffer * volatile buf; - error = pdf_open_stream(&stm, xref, num, gen); - if (error) - return fz_rethrow(error, "cannot open stream (%d %d R)", num, gen); + stm = pdf_open_stream(xref, num, gen); + /* RJW: "cannot open stream (%d %d R)", num, gen */ - error = pdf_load_object(&dict, xref, num, gen); - if (error) - return fz_rethrow(error, "cannot load stream dictionary (%d %d R)", num, gen); + dict = pdf_load_object(xref, num, gen); + /* RJW: "cannot load stream dictionary (%d %d R)", num, gen */ len = fz_to_int(fz_dict_gets(dict, "Length")); obj = fz_dict_gets(dict, "Filter"); len = pdf_guess_filter_length(len, fz_to_name(obj)); - for (i = 0; i < fz_array_len(obj); i++) + n = fz_array_len(obj); + for (i = 0; i < n; i++) len = pdf_guess_filter_length(len, fz_to_name(fz_array_get(obj, i))); fz_drop_obj(dict); - error = fz_read_all(bufp, stm, len); - if (error) + fz_try(ctx) + { + buf = fz_read_all(stm, len); + } + fz_catch(ctx) { fz_close(stm); - return fz_rethrow(error, "cannot read raw stream (%d %d R)", num, gen); + fz_throw(ctx, "cannot read raw stream (%d %d R)", num, gen); } fz_close(stm); - return fz_okay; + return buf; } diff --git a/pdf/pdf_type3.c b/pdf/pdf_type3.c index 1d851ebe..c129350a 100644 --- a/pdf/pdf_type3.c +++ b/pdf/pdf_type3.c @@ -1,16 +1,15 @@ #include "fitz.h" #include "mupdf.h" -static fz_error +static void pdf_run_glyph_func(void *xref, fz_obj *rdb, fz_buffer *contents, fz_device *dev, fz_matrix ctm) { - return pdf_run_glyph(xref, rdb, contents, dev, ctm); + pdf_run_glyph(xref, rdb, contents, dev, ctm); } -fz_error -pdf_load_type3_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) +pdf_font_desc * +pdf_load_type3_font(pdf_xref *xref, fz_obj *rdb, fz_obj *dict) { - fz_error error; char buf[256]; char *estrings[256]; pdf_font_desc *fontdesc; @@ -22,137 +21,133 @@ pdf_load_type3_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_o int i, k, n; fz_rect bbox; fz_matrix matrix; + fz_context *ctx = xref->ctx; - obj = fz_dict_gets(dict, "Name"); - if (fz_is_name(obj)) - fz_strlcpy(buf, fz_to_name(obj), sizeof buf); - else - sprintf(buf, "Unnamed-T3"); + fz_try(ctx) + { + obj = fz_dict_gets(dict, "Name"); + if (fz_is_name(obj)) + fz_strlcpy(buf, fz_to_name(obj), sizeof buf); + else + sprintf(buf, "Unnamed-T3"); - fontdesc = pdf_new_font_desc(); + fontdesc = pdf_new_font_desc(ctx); - obj = fz_dict_gets(dict, "FontMatrix"); - matrix = pdf_to_matrix(obj); + obj = fz_dict_gets(dict, "FontMatrix"); + matrix = pdf_to_matrix(ctx, obj); - obj = fz_dict_gets(dict, "FontBBox"); - bbox = pdf_to_rect(obj); + obj = fz_dict_gets(dict, "FontBBox"); + bbox = pdf_to_rect(ctx, obj); - fontdesc->font = fz_new_type3_font(buf, matrix); + fontdesc->font = fz_new_type3_font(ctx, buf, matrix); - fz_set_font_bbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); + fz_set_font_bbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); - /* Encoding */ + /* Encoding */ - for (i = 0; i < 256; i++) - estrings[i] = NULL; + for (i = 0; i < 256; i++) + estrings[i] = NULL; - encoding = fz_dict_gets(dict, "Encoding"); - if (!encoding) - { - error = fz_throw("syntaxerror: Type3 font missing Encoding"); - goto cleanup; - } + encoding = fz_dict_gets(dict, "Encoding"); + if (!encoding) + { + fz_throw(ctx, "syntaxerror: Type3 font missing Encoding"); + } - if (fz_is_name(encoding)) - pdf_load_encoding(estrings, fz_to_name(encoding)); + if (fz_is_name(encoding)) + pdf_load_encoding(estrings, fz_to_name(encoding)); - if (fz_is_dict(encoding)) - { - fz_obj *base, *diff, *item; + if (fz_is_dict(encoding)) + { + fz_obj *base, *diff, *item; - base = fz_dict_gets(encoding, "BaseEncoding"); - if (fz_is_name(base)) - pdf_load_encoding(estrings, fz_to_name(base)); + base = fz_dict_gets(encoding, "BaseEncoding"); + if (fz_is_name(base)) + pdf_load_encoding(estrings, fz_to_name(base)); - diff = fz_dict_gets(encoding, "Differences"); - if (fz_is_array(diff)) - { - n = fz_array_len(diff); - k = 0; - for (i = 0; i < n; i++) + diff = fz_dict_gets(encoding, "Differences"); + if (fz_is_array(diff)) { - item = fz_array_get(diff, i); - if (fz_is_int(item)) - k = fz_to_int(item); - if (fz_is_name(item)) - estrings[k++] = fz_to_name(item); - if (k < 0) k = 0; - if (k > 255) k = 255; + n = fz_array_len(diff); + k = 0; + for (i = 0; i < n; i++) + { + item = fz_array_get(diff, i); + if (fz_is_int(item)) + k = fz_to_int(item); + if (fz_is_name(item)) + estrings[k++] = fz_to_name(item); + if (k < 0) k = 0; + if (k > 255) k = 255; + } } } - } - fontdesc->encoding = pdf_new_identity_cmap(0, 1); + fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1); - error = pdf_load_to_unicode(fontdesc, xref, estrings, NULL, fz_dict_gets(dict, "ToUnicode")); - if (error) - goto cleanup; + pdf_load_to_unicode(fontdesc, xref, estrings, NULL, fz_dict_gets(dict, "ToUnicode")); - /* Widths */ + /* Widths */ - pdf_set_default_hmtx(fontdesc, 0); + pdf_set_default_hmtx(fontdesc, 0); - first = fz_to_int(fz_dict_gets(dict, "FirstChar")); - last = fz_to_int(fz_dict_gets(dict, "LastChar")); + first = fz_to_int(fz_dict_gets(dict, "FirstChar")); + last = fz_to_int(fz_dict_gets(dict, "LastChar")); - widths = fz_dict_gets(dict, "Widths"); - if (!widths) - { - error = fz_throw("syntaxerror: Type3 font missing Widths"); - goto cleanup; - } + widths = fz_dict_gets(dict, "Widths"); + if (!widths) + { + fz_throw(ctx, "syntaxerror: Type3 font missing Widths"); + } - for (i = first; i <= last; i++) - { - float w = fz_to_real(fz_array_get(widths, i - first)); - w = fontdesc->font->t3matrix.a * w * 1000; - fontdesc->font->t3widths[i] = w * 0.001f; - pdf_add_hmtx(fontdesc, i, i, w); - } + for (i = first; i <= last; i++) + { + float w = fz_to_real(fz_array_get(widths, i - first)); + w = fontdesc->font->t3matrix.a * w * 1000; + fontdesc->font->t3widths[i] = w * 0.001f; + pdf_add_hmtx(ctx, fontdesc, i, i, w); + } - pdf_end_hmtx(fontdesc); + pdf_end_hmtx(fontdesc); - /* Resources -- inherit page resources if the font doesn't have its own */ + /* Resources -- inherit page resources if the font doesn't have its own */ - fontdesc->font->t3resources = fz_dict_gets(dict, "Resources"); - if (!fontdesc->font->t3resources) - fontdesc->font->t3resources = rdb; - if (fontdesc->font->t3resources) - fz_keep_obj(fontdesc->font->t3resources); - if (!fontdesc->font->t3resources) - fz_warn("no resource dictionary for type 3 font!"); + fontdesc->font->t3resources = fz_dict_gets(dict, "Resources"); + if (!fontdesc->font->t3resources) + fontdesc->font->t3resources = rdb; + if (fontdesc->font->t3resources) + fz_keep_obj(fontdesc->font->t3resources); + if (!fontdesc->font->t3resources) + fz_warn(ctx, "no resource dictionary for type 3 font!"); - fontdesc->font->t3xref = xref; - fontdesc->font->t3run = pdf_run_glyph_func; + fontdesc->font->t3xref = xref; + fontdesc->font->t3run = pdf_run_glyph_func; - /* CharProcs */ + /* CharProcs */ - charprocs = fz_dict_gets(dict, "CharProcs"); - if (!charprocs) - { - error = fz_throw("syntaxerror: Type3 font missing CharProcs"); - goto cleanup; - } + charprocs = fz_dict_gets(dict, "CharProcs"); + if (!charprocs) + { + fz_throw(ctx, "syntaxerror: Type3 font missing CharProcs"); + } - for (i = 0; i < 256; i++) - { - if (estrings[i]) + for (i = 0; i < 256; i++) { - obj = fz_dict_gets(charprocs, estrings[i]); - if (pdf_is_stream(xref, fz_to_num(obj), fz_to_gen(obj))) + if (estrings[i]) { - error = pdf_load_stream(&fontdesc->font->t3procs[i], xref, fz_to_num(obj), fz_to_gen(obj)); - if (error) - goto cleanup; + obj = fz_dict_gets(charprocs, estrings[i]); + if (pdf_is_stream(xref, fz_to_num(obj), fz_to_gen(obj))) + { + fontdesc->font->t3procs[i] = pdf_load_stream(xref, fz_to_num(obj), fz_to_gen(obj)); + } } } } - - *fontdescp = fontdesc; - return fz_okay; - -cleanup: - fz_drop_font(fontdesc->font); - fz_free(fontdesc); - return fz_rethrow(error, "cannot load type3 font (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + fz_catch(ctx) + { + fz_drop_font(ctx, fontdesc->font); + fz_free(ctx, fontdesc); + fz_throw(ctx, "cannot load type3 font (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + } + return fontdesc; } diff --git a/pdf/pdf_unicode.c b/pdf/pdf_unicode.c index 2b28b608..7968036a 100644 --- a/pdf/pdf_unicode.c +++ b/pdf/pdf_unicode.c @@ -3,24 +3,23 @@ /* Load or synthesize ToUnicode map for fonts */ -fz_error +void pdf_load_to_unicode(pdf_font_desc *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; + fz_context *ctx = xref->ctx; if (pdf_is_stream(xref, fz_to_num(cmapstm), fz_to_gen(cmapstm))) { - error = pdf_load_embedded_cmap(&cmap, xref, cmapstm); - if (error) - return fz_rethrow(error, "cannot load embedded cmap (%d %d R)", fz_to_num(cmapstm), fz_to_gen(cmapstm)); + cmap = pdf_load_embedded_cmap(xref, cmapstm); + /* RJW: "cannot load embedded cmap (%d %d R)", fz_to_num(cmapstm), fz_to_gen(cmapstm) */ - font->to_unicode = pdf_new_cmap(); + font->to_unicode = pdf_new_cmap(ctx); for (i = 0; i < (strings ? 256 : 65536); i++) { @@ -29,32 +28,30 @@ pdf_load_to_unicode(pdf_font_desc *font, pdf_xref *xref, { ucslen = pdf_lookup_cmap_full(cmap, i, ucsbuf); if (ucslen == 1) - pdf_map_range_to_range(font->to_unicode, cid, cid, ucsbuf[0]); + pdf_map_range_to_range(ctx, font->to_unicode, cid, cid, ucsbuf[0]); if (ucslen > 1) - pdf_map_one_to_many(font->to_unicode, cid, ucsbuf, ucslen); + pdf_map_one_to_many(ctx, font->to_unicode, cid, ucsbuf, ucslen); } } - pdf_sort_cmap(font->to_unicode); + pdf_sort_cmap(ctx, font->to_unicode); - pdf_drop_cmap(cmap); + pdf_drop_cmap(ctx, cmap); } else if (collection) { - error = fz_okay; - if (!strcmp(collection, "Adobe-CNS1")) - error = pdf_load_system_cmap(&font->to_unicode, "Adobe-CNS1-UCS2"); + font->to_unicode = pdf_load_system_cmap(ctx, "Adobe-CNS1-UCS2"); else if (!strcmp(collection, "Adobe-GB1")) - error = pdf_load_system_cmap(&font->to_unicode, "Adobe-GB1-UCS2"); + font->to_unicode = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); else if (!strcmp(collection, "Adobe-Japan1")) - error = pdf_load_system_cmap(&font->to_unicode, "Adobe-Japan1-UCS2"); + font->to_unicode = pdf_load_system_cmap(ctx, "Adobe-Japan1-UCS2"); else if (!strcmp(collection, "Adobe-Korea1")) - error = pdf_load_system_cmap(&font->to_unicode, "Adobe-Korea1-UCS2"); + font->to_unicode = pdf_load_system_cmap(ctx, "Adobe-Korea1-UCS2"); - if (error) - return fz_rethrow(error, "cannot load ToUnicode system cmap %s-UCS2", collection); + return; + /* RJW: "cannot load ToUnicode system cmap %s-UCS2", collection */ } if (strings) @@ -62,7 +59,7 @@ pdf_load_to_unicode(pdf_font_desc *font, pdf_xref *xref, /* TODO one-to-many mappings */ font->cid_to_ucs_len = 256; - font->cid_to_ucs = fz_calloc(256, sizeof(unsigned short)); + font->cid_to_ucs = fz_malloc_array(ctx, 256, sizeof(unsigned short)); for (i = 0; i < 256; i++) { @@ -78,6 +75,4 @@ pdf_load_to_unicode(pdf_font_desc *font, pdf_xref *xref, /* 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; } diff --git a/pdf/pdf_xobject.c b/pdf/pdf_xobject.c index 6228377f..81ef52fa 100644 --- a/pdf/pdf_xobject.c +++ b/pdf/pdf_xobject.c @@ -1,34 +1,33 @@ #include "fitz.h" #include "mupdf.h" -fz_error -pdf_load_xobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict) +pdf_xobject * +pdf_load_xobject(pdf_xref *xref, fz_obj *dict) { - fz_error error; pdf_xobject *form; fz_obj *obj; + fz_context *ctx = xref->ctx; - if ((*formp = pdf_find_item(xref->store, pdf_drop_xobject, dict))) + if ((form = pdf_find_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_xobject, dict))) { - pdf_keep_xobject(*formp); - return fz_okay; + return pdf_keep_xobject(form); } - form = fz_malloc(sizeof(pdf_xobject)); + form = fz_malloc(ctx, sizeof(pdf_xobject)); form->refs = 1; form->resources = NULL; form->contents = NULL; form->colorspace = NULL; /* Store item immediately, to avoid possible recursion if objects refer back to this one */ - pdf_store_item(xref->store, pdf_keep_xobject, pdf_drop_xobject, dict, form); + pdf_store_item(ctx, xref->store, (pdf_store_keep_fn *)pdf_keep_xobject, (pdf_store_drop_fn *)pdf_drop_xobject, dict, form); obj = fz_dict_gets(dict, "BBox"); - form->bbox = pdf_to_rect(obj); + form->bbox = pdf_to_rect(ctx, obj); obj = fz_dict_gets(dict, "Matrix"); if (obj) - form->matrix = pdf_to_matrix(obj); + form->matrix = pdf_to_matrix(ctx, obj); else form->matrix = fz_identity; @@ -51,9 +50,9 @@ pdf_load_xobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict) obj = fz_dict_gets(attrs, "CS"); if (obj) { - error = pdf_load_colorspace(&form->colorspace, xref, obj); - if (error) - fz_catch(error, "cannot load xobject colorspace"); + form->colorspace = pdf_load_colorspace(xref, obj); + if (form->colorspace == NULL) + fz_throw(ctx, "cannot load xobject colorspace"); } } @@ -61,16 +60,18 @@ pdf_load_xobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict) if (form->resources) fz_keep_obj(form->resources); - error = pdf_load_stream(&form->contents, xref, fz_to_num(dict), fz_to_gen(dict)); - if (error) + fz_try(ctx) + { + form->contents = pdf_load_stream(xref, fz_to_num(dict), fz_to_gen(dict)); + } + fz_catch(ctx) { - pdf_remove_item(xref->store, pdf_drop_xobject, dict); - pdf_drop_xobject(form); - return fz_rethrow(error, "cannot load xobject content stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); + pdf_remove_item(ctx, xref->store, (pdf_store_drop_fn *)pdf_drop_xobject, dict); + pdf_drop_xobject(ctx, form); + fz_throw(ctx, "cannot load xobject content stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); } - *formp = form; - return fz_okay; + return form; } pdf_xobject * @@ -81,16 +82,16 @@ pdf_keep_xobject(pdf_xobject *xobj) } void -pdf_drop_xobject(pdf_xobject *xobj) +pdf_drop_xobject(fz_context *ctx, pdf_xobject *xobj) { if (xobj && --xobj->refs == 0) { if (xobj->colorspace) - fz_drop_colorspace(xobj->colorspace); + fz_drop_colorspace(ctx, xobj->colorspace); if (xobj->resources) fz_drop_obj(xobj->resources); if (xobj->contents) - fz_drop_buffer(xobj->contents); - fz_free(xobj); + fz_drop_buffer(ctx, xobj->contents); + fz_free(ctx, xobj); } } diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c index a14ac6d9..501db660 100644 --- a/pdf/pdf_xref.c +++ b/pdf/pdf_xref.c @@ -12,7 +12,7 @@ static inline int iswhite(int ch) * magic version tag and startxref */ -static fz_error +static void pdf_load_version(pdf_xref *xref) { char buf[20]; @@ -20,14 +20,12 @@ pdf_load_version(pdf_xref *xref) fz_seek(xref->file, 0, 0); fz_read_line(xref->file, buf, sizeof buf); if (memcmp(buf, "%PDF-", 5) != 0) - return fz_throw("cannot recognize version marker"); + fz_throw(xref->ctx, "cannot recognize version marker"); xref->version = atoi(buf + 5) * 10 + atoi(buf + 7); - - return fz_okay; } -static fz_error +static void pdf_read_start_xref(pdf_xref *xref) { unsigned char buf[1024]; @@ -43,7 +41,7 @@ pdf_read_start_xref(pdf_xref *xref) n = fz_read(xref->file, buf, sizeof buf); if (n < 0) - return fz_rethrow(n, "cannot read from file"); + fz_throw(xref->ctx, "cannot read from file"); for (i = n - 9; i >= 0; i--) { @@ -53,21 +51,20 @@ pdf_read_start_xref(pdf_xref *xref) while (iswhite(buf[i]) && i < n) i ++; xref->startxref = atoi((char*)(buf + i)); - return fz_okay; + return; } } - return fz_throw("cannot find startxref"); + fz_throw(xref->ctx, "cannot find startxref"); } /* * trailer dictionary */ -static fz_error +static void pdf_read_old_trailer(pdf_xref *xref, char *buf, int cap) { - fz_error error; int len; char *s; int n; @@ -77,7 +74,7 @@ pdf_read_old_trailer(pdf_xref *xref, char *buf, int cap) fz_read_line(xref->file, buf, cap); if (strncmp(buf, "xref", 4) != 0) - return fz_throw("cannot find xref marker"); + fz_throw(xref->ctx, "cannot find xref marker"); while (1) { @@ -89,7 +86,7 @@ pdf_read_old_trailer(pdf_xref *xref, char *buf, int cap) s = buf; fz_strsep(&s, " "); /* ignore ofs */ if (!s) - return fz_throw("invalid range marker in xref"); + fz_throw(xref->ctx, "invalid range marker in xref"); len = atoi(fz_strsep(&s, " ")); /* broken pdfs where the section is not on a separate line */ @@ -98,43 +95,45 @@ pdf_read_old_trailer(pdf_xref *xref, char *buf, int cap) t = fz_tell(xref->file); if (t < 0) - return fz_throw("cannot tell in file"); + fz_throw(xref->ctx, "cannot tell in file"); fz_seek(xref->file, t + 20 * len, 0); } - error = pdf_lex(&tok, xref->file, buf, cap, &n); - if (error) - return fz_rethrow(error, "cannot parse trailer"); - if (tok != PDF_TOK_TRAILER) - return fz_throw("expected trailer marker"); - - error = pdf_lex(&tok, xref->file, buf, cap, &n); - if (error) - return fz_rethrow(error, "cannot parse trailer"); - if (tok != PDF_TOK_OPEN_DICT) - return fz_throw("expected trailer dictionary"); - - error = pdf_parse_dict(&xref->trailer, xref, xref->file, buf, cap); - if (error) - return fz_rethrow(error, "cannot parse trailer"); - return fz_okay; + fz_try(xref->ctx) + { + tok = pdf_lex(xref->file, buf, cap, &n); + if (tok != PDF_TOK_TRAILER) + fz_throw(xref->ctx, "expected trailer marker"); + + tok = pdf_lex(xref->file, buf, cap, &n); + if (tok != PDF_TOK_OPEN_DICT) + fz_throw(xref->ctx, "expected trailer dictionary"); + + xref->trailer = pdf_parse_dict(xref, xref->file, buf, cap); + } + fz_catch(xref->ctx) + { + fz_throw(xref->ctx, "cannot parse trailer"); + } } -static fz_error +static void pdf_read_new_trailer(pdf_xref *xref, char *buf, int cap) { - fz_error error; - error = pdf_parse_ind_obj(&xref->trailer, xref, xref->file, buf, cap, NULL, NULL, NULL); - if (error) - return fz_rethrow(error, "cannot parse trailer (compressed)"); - return fz_okay; + fz_try(xref->ctx) + { + xref->trailer = pdf_parse_ind_obj(xref, xref->file, buf, cap, NULL, NULL, NULL); + } + fz_catch(xref->ctx) + { + fz_throw(xref->ctx, "cannot parse trailer (compressed)"); + } } -static fz_error +static void pdf_read_trailer(pdf_xref *xref, char *buf, int cap) { - fz_error error; int c; fz_seek(xref->file, xref->startxref, 0); @@ -142,25 +141,20 @@ pdf_read_trailer(pdf_xref *xref, char *buf, int cap) while (iswhite(fz_peek_byte(xref->file))) fz_read_byte(xref->file); - c = fz_peek_byte(xref->file); - if (c == 'x') + fz_try(xref->ctx) { - error = pdf_read_old_trailer(xref, buf, cap); - if (error) - return fz_rethrow(error, "cannot read trailer"); - } - else if (c >= '0' && c <= '9') - { - error = pdf_read_new_trailer(xref, buf, cap); - if (error) - return fz_rethrow(error, "cannot read trailer"); + c = fz_peek_byte(xref->file); + if (c == 'x') + pdf_read_old_trailer(xref, buf, cap); + else if (c >= '0' && c <= '9') + pdf_read_new_trailer(xref, buf, cap); + else + fz_throw(xref->ctx, "cannot recognize xref format: '%c'", c); } - else + fz_catch(xref->ctx) { - return fz_throw("cannot recognize xref format: '%c'", c); + fz_throw(xref->ctx, "cannot read trailer"); } - - return fz_okay; } /* @@ -172,7 +166,7 @@ pdf_resize_xref(pdf_xref *xref, int newlen) { int i; - xref->table = fz_realloc(xref->table, newlen, sizeof(pdf_xref_entry)); + xref->table = fz_resize_array(xref->ctx, xref->table, newlen, sizeof(pdf_xref_entry)); for (i = xref->len; i < newlen; i++) { xref->table[i].type = 0; @@ -184,20 +178,20 @@ pdf_resize_xref(pdf_xref *xref, int newlen) xref->len = newlen; } -static fz_error -pdf_read_old_xref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) +static fz_obj * +pdf_read_old_xref(pdf_xref *xref, char *buf, int cap) { - fz_error error; int ofs, len; char *s; int n; int tok; int i; int c; + fz_obj *trailer; fz_read_line(xref->file, buf, cap); if (strncmp(buf, "xref", 4) != 0) - return fz_throw("cannot find xref marker"); + fz_throw(xref->ctx, "cannot find xref marker"); while (1) { @@ -213,14 +207,14 @@ pdf_read_old_xref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) /* broken pdfs where the section is not on a separate line */ if (s && *s != '\0') { - fz_warn("broken xref section. proceeding anyway."); + fz_warn(xref->ctx, "broken xref section. proceeding anyway."); fz_seek(xref->file, -(2 + (int)strlen(s)), 1); } /* broken pdfs where size in trailer undershoots entries in xref sections */ if (ofs + len > xref->len) { - fz_warn("broken xref section, proceeding anyway."); + fz_warn(xref->ctx, "broken xref section, proceeding anyway."); pdf_resize_xref(xref, ofs + len); } @@ -228,7 +222,7 @@ pdf_read_old_xref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) { n = fz_read(xref->file, (unsigned char *) buf, 20); if (n < 0) - return fz_rethrow(n, "cannot read xref table"); + fz_throw(xref->ctx, "cannot read xref table"); if (!xref->table[i].type) { s = buf; @@ -241,36 +235,37 @@ pdf_read_old_xref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) xref->table[i].gen = atoi(s + 11); xref->table[i].type = s[17]; if (s[17] != 'f' && s[17] != 'n' && s[17] != 'o') - return fz_throw("unexpected xref type: %#x (%d %d R)", s[17], i, xref->table[i].gen); + fz_throw(xref->ctx, "unexpected xref type: %#x (%d %d R)", s[17], i, xref->table[i].gen); } } } - error = pdf_lex(&tok, xref->file, buf, cap, &n); - if (error) - return fz_rethrow(error, "cannot parse trailer"); - if (tok != PDF_TOK_TRAILER) - return fz_throw("expected trailer marker"); - - error = pdf_lex(&tok, xref->file, buf, cap, &n); - if (error) - return fz_rethrow(error, "cannot parse trailer"); - if (tok != PDF_TOK_OPEN_DICT) - return fz_throw("expected trailer dictionary"); - - error = pdf_parse_dict(trailerp, xref, xref->file, buf, cap); - if (error) - return fz_rethrow(error, "cannot parse trailer"); - return fz_okay; + fz_try(xref->ctx) + { + tok = pdf_lex(xref->file, buf, cap, &n); + if (tok != PDF_TOK_TRAILER) + fz_throw(xref->ctx, "expected trailer marker"); + + tok = pdf_lex(xref->file, buf, cap, &n); + if (tok != PDF_TOK_OPEN_DICT) + fz_throw(xref->ctx, "expected trailer dictionary"); + + trailer = pdf_parse_dict(xref, xref->file, buf, cap); + } + fz_catch(xref->ctx) + { + fz_throw(xref->ctx, "cannot parse trailer"); + } + return trailer; } -static fz_error +static void pdf_read_new_xref_section(pdf_xref *xref, fz_stream *stm, int i0, int i1, int w0, int w1, int w2) { int i, n; if (i0 < 0 || i0 + i1 > xref->len) - return fz_throw("xref stream has too many entries"); + fz_throw(xref->ctx, "xref stream has too many entries"); for (i = i0; i < i0 + i1; i++) { @@ -279,7 +274,7 @@ pdf_read_new_xref_section(pdf_xref *xref, fz_stream *stm, int i0, int i1, int w0 int c = 0; if (fz_is_eof(stm)) - return fz_throw("truncated xref stream"); + fz_throw(xref->ctx, "truncated xref stream"); for (n = 0; n < w0; n++) a = (a << 8) + fz_read_byte(stm); @@ -296,219 +291,185 @@ pdf_read_new_xref_section(pdf_xref *xref, fz_stream *stm, int i0, int i1, int w0 xref->table[i].gen = w2 ? c : 0; } } - - return fz_okay; } -static fz_error -pdf_read_new_xref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) +static fz_obj * +pdf_read_new_xref(pdf_xref *xref, char *buf, int cap) { - fz_error error; fz_stream *stm; - fz_obj *trailer; - fz_obj *index; - fz_obj *obj; + fz_obj * volatile trailer = NULL; + fz_obj *index = NULL; + fz_obj *obj = NULL; int num, gen, stm_ofs; int size, w0, w1, w2; int t; + fz_context *ctx = xref->ctx; - error = pdf_parse_ind_obj(&trailer, xref, xref->file, buf, cap, &num, &gen, &stm_ofs); - if (error) - return fz_rethrow(error, "cannot parse compressed xref stream object"); - - obj = fz_dict_gets(trailer, "Size"); - if (!obj) + fz_try(ctx) { - fz_drop_obj(trailer); - return fz_throw("xref stream missing Size entry (%d %d R)", num, gen); + trailer = pdf_parse_ind_obj(xref, xref->file, buf, cap, &num, &gen, &stm_ofs); } - size = fz_to_int(obj); - - if (size > xref->len) + fz_catch(ctx) { - pdf_resize_xref(xref, size); + fz_throw(ctx, "cannot parse compressed xref stream object"); } - if (num < 0 || num >= xref->len) + fz_try(ctx) { - fz_drop_obj(trailer); - return fz_throw("object id (%d %d R) out of range (0..%d)", num, gen, xref->len - 1); - } + obj = fz_dict_gets(trailer, "Size"); + if (!obj) + fz_throw(ctx, "xref stream missing Size entry (%d %d R)", num, gen); - obj = fz_dict_gets(trailer, "W"); - if (!obj) { - fz_drop_obj(trailer); - return fz_throw("xref stream missing W entry (%d %d R)", num, gen); - } - w0 = fz_to_int(fz_array_get(obj, 0)); - w1 = fz_to_int(fz_array_get(obj, 1)); - w2 = fz_to_int(fz_array_get(obj, 2)); + size = fz_to_int(obj); + if (size > xref->len) + pdf_resize_xref(xref, size); - index = fz_dict_gets(trailer, "Index"); + if (num < 0 || num >= xref->len) + fz_throw(ctx, "object id (%d %d R) out of range (0..%d)", num, gen, xref->len - 1); - error = pdf_open_stream_at(&stm, xref, num, gen, trailer, stm_ofs); - if (error) - { - fz_drop_obj(trailer); - return fz_rethrow(error, "cannot open compressed xref stream (%d %d R)", num, gen); - } + obj = fz_dict_gets(trailer, "W"); + if (!obj) + fz_throw(ctx, "xref stream missing W entry (%d %d R)", num, gen); + w0 = fz_to_int(fz_array_get(obj, 0)); + w1 = fz_to_int(fz_array_get(obj, 1)); + w2 = fz_to_int(fz_array_get(obj, 2)); - if (!index) - { - error = pdf_read_new_xref_section(xref, stm, 0, size, w0, w1, w2); - if (error) + index = fz_dict_gets(trailer, "Index"); + + stm = pdf_open_stream_at(xref, num, gen, trailer, stm_ofs); + /* RJW: Ensure pdf_open_stream does fz_throw(ctx, "cannot open compressed xref stream (%d %d R)", num, gen); */ + + if (!index) { - fz_close(stm); - fz_drop_obj(trailer); - return fz_rethrow(error, "cannot read xref stream (%d %d R)", num, gen); + pdf_read_new_xref_section(xref, stm, 0, size, w0, w1, w2); + /* RJW: Ensure above does fz_throw(ctx, "cannot read xref stream (%d %d R)", num, gen); */ } - } - else - { - for (t = 0; t < fz_array_len(index); t += 2) + else { - int i0 = fz_to_int(fz_array_get(index, t + 0)); - int i1 = fz_to_int(fz_array_get(index, t + 1)); - error = pdf_read_new_xref_section(xref, stm, i0, i1, w0, w1, w2); - if (error) + int n = fz_array_len(index); + for (t = 0; t < n; t += 2) { - fz_close(stm); - fz_drop_obj(trailer); - return fz_rethrow(error, "cannot read xref stream section (%d %d R)", num, gen); + int i0 = fz_to_int(fz_array_get(index, t + 0)); + int i1 = fz_to_int(fz_array_get(index, t + 1)); + pdf_read_new_xref_section(xref, stm, i0, i1, w0, w1, w2); } } } + fz_catch(ctx) + { + fz_close(stm); + fz_drop_obj(trailer); + fz_drop_obj(index); + fz_drop_obj(obj); + fz_rethrow(ctx); + } fz_close(stm); - *trailerp = trailer; - - return fz_okay; + return trailer; } -static fz_error -pdf_read_xref(fz_obj **trailerp, pdf_xref *xref, int ofs, char *buf, int cap) +static fz_obj * +pdf_read_xref(pdf_xref *xref, int ofs, char *buf, int cap) { - fz_error error; int c; + fz_context *ctx = xref->ctx; + fz_obj *trailer; fz_seek(xref->file, ofs, 0); while (iswhite(fz_peek_byte(xref->file))) fz_read_byte(xref->file); - c = fz_peek_byte(xref->file); - if (c == 'x') - { - error = pdf_read_old_xref(trailerp, xref, buf, cap); - if (error) - return fz_rethrow(error, "cannot read xref (ofs=%d)", ofs); - } - else if (c >= '0' && c <= '9') + fz_try(ctx) { - error = pdf_read_new_xref(trailerp, xref, buf, cap); - if (error) - return fz_rethrow(error, "cannot read xref (ofs=%d)", ofs); + c = fz_peek_byte(xref->file); + if (c == 'x') + trailer = pdf_read_old_xref(xref, buf, cap); + else if (c >= '0' && c <= '9') + trailer = pdf_read_new_xref(xref, buf, cap); + else + fz_throw(ctx, "cannot recognize xref format"); } - else + fz_catch(ctx) { - return fz_throw("cannot recognize xref format"); + fz_throw(ctx, "cannot read xref (ofs=%d)", ofs); } - - return fz_okay; + return trailer; } -static fz_error +static void pdf_read_xref_sections(pdf_xref *xref, int ofs, char *buf, int cap) { - fz_error error; - fz_obj *trailer; - fz_obj *prev; - fz_obj *xrefstm; - - error = pdf_read_xref(&trailer, xref, ofs, buf, cap); - if (error) - return fz_rethrow(error, "cannot read xref section"); + fz_obj *trailer = NULL; + fz_obj *xrefstm = NULL; + fz_obj *prev = NULL; + fz_context *ctx = xref->ctx; - /* FIXME: do we overwrite free entries properly? */ - xrefstm = fz_dict_gets(trailer, "XRefStm"); - if (xrefstm) + fz_try(ctx) { - error = pdf_read_xref_sections(xref, fz_to_int(xrefstm), buf, cap); - if (error) - { - fz_drop_obj(trailer); - return fz_rethrow(error, "cannot read /XRefStm xref section"); - } - } + trailer = pdf_read_xref(xref, ofs, buf, cap); + + /* FIXME: do we overwrite free entries properly? */ + xrefstm = fz_dict_gets(trailer, "XRefStm"); + if (xrefstm) + pdf_read_xref_sections(xref, fz_to_int(xrefstm), buf, cap); - prev = fz_dict_gets(trailer, "Prev"); - if (prev) + prev = fz_dict_gets(trailer, "Prev"); + if (prev) + pdf_read_xref_sections(xref, fz_to_int(prev), buf, cap); + } + fz_catch(ctx) { - error = pdf_read_xref_sections(xref, fz_to_int(prev), buf, cap); - if (error) - { - fz_drop_obj(trailer); - return fz_rethrow(error, "cannot read /Prev xref section"); - } + fz_drop_obj(trailer); + fz_throw(ctx, "Failed to read xref at offset %d", ofs); } fz_drop_obj(trailer); - return fz_okay; } /* * load xref tables from pdf */ -static fz_error +static void pdf_load_xref(pdf_xref *xref, char *buf, int bufsize) { - fz_error error; fz_obj *size; int i; + fz_context *ctx = xref->ctx; - error = pdf_load_version(xref); - if (error) - return fz_rethrow(error, "cannot read version marker"); + pdf_load_version(xref); - error = pdf_read_start_xref(xref); - if (error) - return fz_rethrow(error, "cannot read startxref"); + pdf_read_start_xref(xref); - error = pdf_read_trailer(xref, buf, bufsize); - if (error) - return fz_rethrow(error, "cannot read trailer"); + pdf_read_trailer(xref, buf, bufsize); size = fz_dict_gets(xref->trailer, "Size"); if (!size) - return fz_throw("trailer missing Size entry"); + fz_throw(ctx, "trailer missing Size entry"); pdf_resize_xref(xref, fz_to_int(size)); - error = pdf_read_xref_sections(xref, xref->startxref, buf, bufsize); - if (error) - return fz_rethrow(error, "cannot read xref"); + pdf_read_xref_sections(xref, xref->startxref, buf, bufsize); /* broken pdfs where first object is not free */ if (xref->table[0].type != 'f') - return fz_throw("first object in xref is not free"); + fz_throw(ctx, "first object in xref is not free"); /* broken pdfs where object offsets are out of range */ for (i = 0; i < xref->len; i++) { if (xref->table[i].type == 'n') if (xref->table[i].ofs <= 0 || xref->table[i].ofs >= xref->file_size) - return fz_throw("object offset out of range: %d (%d 0 R)", xref->table[i].ofs, i); + fz_throw(ctx, "object offset out of range: %d (%d 0 R)", xref->table[i].ofs, i); if (xref->table[i].type == 'o') if (xref->table[i].ofs <= 0 || xref->table[i].ofs >= xref->len || xref->table[xref->table[i].ofs].type != 'n') - return fz_throw("invalid reference to an objstm that does not exist: %d (%d 0 R)", xref->table[i].ofs, i); + fz_throw(ctx, "invalid reference to an objstm that does not exist: %d (%d 0 R)", xref->table[i].ofs, i); } - - return fz_okay; } -fz_error +void pdf_ocg_set_config(pdf_xref *xref, int config) { int i, j, len, len2; @@ -520,21 +481,21 @@ pdf_ocg_set_config(pdf_xref *xref, int config) if (obj == NULL) { if (config == 0) - return fz_okay; + return; else - return fz_throw("Unknown OCG config (None known!)"); + fz_throw(xref->ctx, "Unknown OCG config (None known!)"); } if (config == 0) { cobj = fz_dict_gets(obj, "D"); if (cobj == NULL) - return fz_throw("No default OCG config"); + fz_throw(xref->ctx, "No default OCG config"); } else { cobj = fz_array_get(fz_dict_gets(obj, "Configs"), config); if (cobj == NULL) - return fz_throw("Illegal OCG config"); + fz_throw(xref->ctx, "Illegal OCG config"); } if (desc->intent != NULL) @@ -611,51 +572,60 @@ pdf_ocg_set_config(pdf_xref *xref, int config) * an app that needs it) */ /* FIXME: Make 'Locked' available via the descriptor (when we have * an app that needs it) */ - return fz_okay; } -static fz_error +static void pdf_read_ocg(pdf_xref *xref) { fz_obj *obj, *ocg; int len, i; - pdf_ocg_descriptor *desc; + pdf_ocg_descriptor * volatile desc; + fz_context *ctx = xref->ctx; obj = fz_dict_gets(fz_dict_gets(xref->trailer, "Root"), "OCProperties"); if (obj == NULL) - return fz_okay; + return; 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; + return; 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_try(ctx) + { + desc = fz_calloc(ctx, 1, sizeof(*desc)); + desc->len = len; + desc->ocgs = fz_calloc(ctx, 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; + } + fz_catch(ctx) { - 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; + if (desc != NULL) + fz_free(ctx, desc->ocgs); + fz_free(ctx, desc); + fz_rethrow(ctx); } - xref->ocg = desc; - return pdf_ocg_set_config(xref, 0); + pdf_ocg_set_config(xref, 0); } static void -pdf_free_ocg(pdf_ocg_descriptor *desc) +pdf_free_ocg(fz_context *ctx, pdf_ocg_descriptor *desc) { if (desc == NULL) return; if (desc->intent) fz_drop_obj(desc->intent); - fz_free(desc->ocgs); - fz_free(desc); + fz_free(ctx, desc->ocgs); + fz_free(ctx, desc); } /* @@ -663,31 +633,35 @@ pdf_free_ocg(pdf_ocg_descriptor *desc) * If password is not null, try to decrypt. */ -fz_error -pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password) +pdf_xref * +pdf_open_xref_with_stream(fz_stream *file, char *password) { pdf_xref *xref; - fz_error error; fz_obj *encrypt, *id; - fz_obj *dict, *obj; + fz_obj *dict = NULL; + fz_obj *obj; + fz_obj *nobj; int i, repaired = 0; + fz_context *ctx = file->ctx; + + //fz_var(dict); /* install pdf specific callback */ fz_resolve_indirect = pdf_resolve_indirect; - xref = fz_malloc(sizeof(pdf_xref)); - - memset(xref, 0, sizeof(pdf_xref)); - + xref = fz_calloc(ctx, 1, sizeof(pdf_xref)); xref->file = fz_keep_stream(file); + xref->ctx = ctx; - error = pdf_load_xref(xref, xref->scratch, sizeof xref->scratch); - if (error) + fz_try(ctx) + { + pdf_load_xref(xref, xref->scratch, sizeof xref->scratch); + } + fz_catch(ctx) { - fz_catch(error, "trying to repair"); if (xref->table) { - fz_free(xref->table); + fz_free(xref->ctx, xref->table); xref->table = NULL; xref->len = 0; } @@ -696,50 +670,31 @@ pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password) fz_drop_obj(xref->trailer); xref->trailer = NULL; } - error = pdf_repair_xref(xref, xref->scratch, sizeof xref->scratch); - if (error) - { - pdf_free_xref(xref); - return fz_rethrow(error, "cannot repair document"); - } + pdf_repair_xref(xref, xref->scratch, sizeof xref->scratch); repaired = 1; } - encrypt = fz_dict_gets(xref->trailer, "Encrypt"); - id = fz_dict_gets(xref->trailer, "ID"); - if (fz_is_dict(encrypt)) + fz_try(ctx) { - error = pdf_new_crypt(&xref->crypt, encrypt, id); - if (error) - { - pdf_free_xref(xref); - return fz_rethrow(error, "cannot decrypt document"); - } - } + int hasroot, hasinfo; - if (pdf_needs_password(xref)) - { - /* Only care if we have a password */ - if (password) + encrypt = fz_dict_gets(xref->trailer, "Encrypt"); + id = fz_dict_gets(xref->trailer, "ID"); + if (fz_is_dict(encrypt)) + xref->crypt = pdf_new_crypt(ctx, encrypt, id); + + if (pdf_needs_password(xref)) { - int okay = pdf_authenticate_password(xref, password); - if (!okay) + /* Only care if we have a password */ + if (password) { - pdf_free_xref(xref); - return fz_throw("invalid password"); + pdf_authenticate_password(xref, password); } } - } - if (repaired) - { - int hasroot, hasinfo; - - error = pdf_repair_obj_stms(xref); - if (error) + if (repaired) { - pdf_free_xref(xref); - return fz_rethrow(error, "cannot repair document"); + pdf_repair_obj_stms(xref); } hasroot = fz_dict_gets(xref->trailer, "Root") != NULL; @@ -750,10 +705,13 @@ pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password) if (xref->table[i].type == 0 || xref->table[i].type == 'f') continue; - error = pdf_load_object(&dict, xref, i, 0); - if (error) + fz_try(ctx) + { + dict = pdf_load_object(xref, i, 0); + } + fz_catch(ctx) { - fz_catch(error, "ignoring broken object (%d 0 R)", i); + fz_warn(ctx, "ignoring broken object (%d 0 R)", i); continue; } @@ -762,9 +720,10 @@ pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password) obj = fz_dict_gets(dict, "Type"); if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "Catalog")) { - obj = fz_new_indirect(i, 0, xref); - fz_dict_puts(xref->trailer, "Root", obj); - fz_drop_obj(obj); + nobj = fz_new_indirect(ctx, i, 0, xref); + fz_dict_puts(xref->trailer, "Root", nobj); + fz_drop_obj(nobj); + nobj = NULL; } } @@ -772,34 +731,46 @@ pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password) { if (fz_dict_gets(dict, "Creator") || fz_dict_gets(dict, "Producer")) { - obj = fz_new_indirect(i, 0, xref); - fz_dict_puts(xref->trailer, "Info", obj); - fz_drop_obj(obj); + nobj = fz_new_indirect(ctx, i, 0, xref); + fz_dict_puts(xref->trailer, "Info", nobj); + fz_drop_obj(nobj); + nobj = NULL; } } fz_drop_obj(dict); + dict = NULL; } } + fz_catch(ctx) + { + fz_drop_obj(dict); + fz_drop_obj(nobj); + pdf_free_xref(xref); + fz_throw(ctx, "cannot open document"); + } - error = pdf_read_ocg(xref); - if (error) + fz_try(ctx) + { + pdf_read_ocg(xref); + } + fz_catch(ctx) { pdf_free_xref(xref); - return fz_rethrow(error, "Broken Optional Content"); + fz_throw(ctx, "Broken Optional Content"); } - *xrefp = xref; - return fz_okay; + return xref; } void pdf_free_xref(pdf_xref *xref) { int i; + fz_context *ctx = xref->ctx; if (xref->store) - pdf_free_store(xref->store); + pdf_free_store(ctx, xref->store); if (xref->table) { @@ -811,21 +782,21 @@ pdf_free_xref(pdf_xref *xref) xref->table[i].obj = NULL; } } - fz_free(xref->table); + fz_free(xref->ctx, xref->table); } if (xref->page_objs) { for (i = 0; i < xref->page_len; i++) fz_drop_obj(xref->page_objs[i]); - fz_free(xref->page_objs); + fz_free(ctx, xref->page_objs); } if (xref->page_refs) { for (i = 0; i < xref->page_len; i++) fz_drop_obj(xref->page_refs[i]); - fz_free(xref->page_refs); + fz_free(ctx, xref->page_refs); } if (xref->file) @@ -833,11 +804,11 @@ pdf_free_xref(pdf_xref *xref) if (xref->trailer) fz_drop_obj(xref->trailer); if (xref->crypt) - pdf_free_crypt(xref->crypt); + pdf_free_crypt(ctx, xref->crypt); - pdf_free_ocg(xref->ocg); + pdf_free_ocg(ctx, xref->ocg); - fz_free(xref); + fz_free(ctx, xref); } void @@ -859,176 +830,171 @@ pdf_debug_xref(pdf_xref *xref) * compressed object streams */ -static fz_error +static void pdf_load_obj_stm(pdf_xref *xref, int num, int gen, char *buf, int cap) { - fz_error error; fz_stream *stm; fz_obj *objstm; - int *numbuf; - int *ofsbuf; + int * volatile numbuf = NULL; + int * volatile ofsbuf = NULL; fz_obj *obj; int first; int count; int i, n; int tok; + fz_context *ctx = xref->ctx; - error = pdf_load_object(&objstm, xref, num, gen); - if (error) - return fz_rethrow(error, "cannot load object stream object (%d %d R)", num, gen); - - count = fz_to_int(fz_dict_gets(objstm, "N")); - first = fz_to_int(fz_dict_gets(objstm, "First")); - - numbuf = fz_calloc(count, sizeof(int)); - ofsbuf = fz_calloc(count, sizeof(int)); - - error = pdf_open_stream(&stm, xref, num, gen); - if (error) + //fz_var(numbuf); + //fz_var(ofsbuf); + fz_try(ctx) { - error = fz_rethrow(error, "cannot open object stream (%d %d R)", num, gen); - goto cleanupbuf; - } + objstm = pdf_load_object(xref, num, gen); - for (i = 0; i < count; i++) - { - error = pdf_lex(&tok, stm, buf, cap, &n); - if (error || tok != PDF_TOK_INT) - { - error = fz_rethrow(error, "corrupt object stream (%d %d R)", num, gen); - goto cleanupstm; - } - numbuf[i] = atoi(buf); + count = fz_to_int(fz_dict_gets(objstm, "N")); + first = fz_to_int(fz_dict_gets(objstm, "First")); + + numbuf = fz_calloc(ctx, count, sizeof(int)); + ofsbuf = fz_calloc(ctx, count, sizeof(int)); - error = pdf_lex(&tok, stm, buf, cap, &n); - if (error || tok != PDF_TOK_INT) + stm = pdf_open_stream(xref, num, gen); + for (i = 0; i < count; i++) { - error = fz_rethrow(error, "corrupt object stream (%d %d R)", num, gen); - goto cleanupstm; + tok = pdf_lex(stm, buf, cap, &n); + if (tok != PDF_TOK_INT) + fz_throw(ctx, "corrupt object stream (%d %d R)", num, gen); + numbuf[i] = atoi(buf); + + tok = pdf_lex(stm, buf, cap, &n); + if (tok != PDF_TOK_INT) + fz_throw(ctx, "corrupt object stream (%d %d R)", num, gen); + ofsbuf[i] = atoi(buf); } - ofsbuf[i] = atoi(buf); - } - - fz_seek(stm, first, 0); - for (i = 0; i < count; i++) - { - fz_seek(stm, first + ofsbuf[i], 0); + fz_seek(stm, first, 0); - error = pdf_parse_stm_obj(&obj, xref, stm, buf, cap); - if (error) + for (i = 0; i < count; i++) { - error = fz_rethrow(error, "cannot parse object %d in stream (%d %d R)", i, num, gen); - goto cleanupstm; - } + fz_seek(stm, first + ofsbuf[i], 0); - if (numbuf[i] < 1 || numbuf[i] >= xref->len) - { - fz_drop_obj(obj); - error = fz_throw("object id (%d 0 R) out of range (0..%d)", numbuf[i], xref->len - 1); - goto cleanupstm; - } + obj = pdf_parse_stm_obj(xref, stm, buf, cap); + /* RJW: Ensure above does fz_throw(ctx, "cannot parse object %d in stream (%d %d R)", i, num, gen); */ - if (xref->table[numbuf[i]].type == 'o' && xref->table[numbuf[i]].ofs == num) - { - if (xref->table[numbuf[i]].obj) - fz_drop_obj(xref->table[numbuf[i]].obj); - xref->table[numbuf[i]].obj = obj; - } - else - { - fz_drop_obj(obj); + if (numbuf[i] < 1 || numbuf[i] >= xref->len) + { + fz_drop_obj(obj); + fz_throw(ctx, "object id (%d 0 R) out of range (0..%d)", numbuf[i], xref->len - 1); + } + + if (xref->table[numbuf[i]].type == 'o' && xref->table[numbuf[i]].ofs == num) + { + if (xref->table[numbuf[i]].obj) + fz_drop_obj(xref->table[numbuf[i]].obj); + xref->table[numbuf[i]].obj = obj; + } + else + { + fz_drop_obj(obj); + } } } - - fz_close(stm); - fz_free(ofsbuf); - fz_free(numbuf); - fz_drop_obj(objstm); - return fz_okay; - -cleanupstm: + fz_catch(ctx) + { + fz_close(stm); + fz_free(xref->ctx, ofsbuf); + fz_free(xref->ctx, numbuf); + fz_drop_obj(objstm); + fz_throw(ctx, "cannot open object stream (%d %d R)", num, gen); + } fz_close(stm); -cleanupbuf: - fz_free(ofsbuf); - fz_free(numbuf); + fz_free(xref->ctx, ofsbuf); + fz_free(xref->ctx, numbuf); fz_drop_obj(objstm); - return error; /* already rethrown */ } /* * object loading */ -fz_error +void pdf_cache_object(pdf_xref *xref, int num, int gen) { - fz_error error; pdf_xref_entry *x; int rnum, rgen; + fz_context *ctx = xref->ctx; if (num < 0 || num >= xref->len) - return fz_throw("object out of range (%d %d R); xref size %d", num, gen, xref->len); + fz_throw(ctx, "object out of range (%d %d R); xref size %d", num, gen, xref->len); x = &xref->table[num]; if (x->obj) - return fz_okay; + return; if (x->type == 'f') { - x->obj = fz_new_null(); - return fz_okay; + x->obj = fz_new_null(ctx); + return; } else if (x->type == 'n') { fz_seek(xref->file, x->ofs, 0); - error = pdf_parse_ind_obj(&x->obj, xref, xref->file, xref->scratch, sizeof xref->scratch, - &rnum, &rgen, &x->stm_ofs); - if (error) - return fz_rethrow(error, "cannot parse object (%d %d R)", num, gen); + fz_try(ctx) + { + x->obj = pdf_parse_ind_obj(xref, xref->file, xref->scratch, sizeof xref->scratch, + &rnum, &rgen, &x->stm_ofs); + } + fz_catch(ctx) + { + fz_throw(ctx, "cannot parse object (%d %d R)", num, gen); + } if (rnum != num) - return fz_throw("found object (%d %d R) instead of (%d %d R)", rnum, rgen, num, gen); + fz_throw(ctx, "found object (%d %d R) instead of (%d %d R)", rnum, rgen, num, gen); if (xref->crypt) - pdf_crypt_obj(xref->crypt, x->obj, num, gen); + pdf_crypt_obj(ctx, xref->crypt, x->obj, num, gen); } else if (x->type == 'o') { if (!x->obj) { - error = pdf_load_obj_stm(xref, x->ofs, 0, xref->scratch, sizeof xref->scratch); - if (error) - return fz_rethrow(error, "cannot load object stream containing object (%d %d R)", num, gen); + fz_try(ctx) + { + pdf_load_obj_stm(xref, x->ofs, 0, xref->scratch, sizeof xref->scratch); + } + fz_catch(ctx) + { + fz_throw(ctx, "cannot load object stream containing object (%d %d R)", num, gen); + } if (!x->obj) - return fz_throw("object (%d %d R) was not found in its object stream", num, gen); + fz_throw(ctx, "object (%d %d R) was not found in its object stream", num, gen); } } else { - return fz_throw("assert: corrupt xref struct"); + fz_throw(ctx, "assert: corrupt xref struct"); } - - return fz_okay; } -fz_error -pdf_load_object(fz_obj **objp, pdf_xref *xref, int num, int gen) +fz_obj * +pdf_load_object(pdf_xref *xref, int num, int gen) { - fz_error error; + fz_context *ctx = xref->ctx; - error = pdf_cache_object(xref, num, gen); - if (error) - return fz_rethrow(error, "cannot load object (%d %d R) into cache", num, gen); + fz_try(ctx) + { + pdf_cache_object(xref, num, gen); + } + fz_catch(ctx) + { + fz_throw(ctx, "cannot load object (%d %d R) into cache", num, gen); + } assert(xref->table[num].obj); - *objp = fz_keep_obj(xref->table[num].obj); - - return fz_okay; + return fz_keep_obj(xref->table[num].obj); } fz_obj * @@ -1037,14 +1003,18 @@ pdf_resolve_indirect(fz_obj *ref) if (fz_is_indirect(ref)) { pdf_xref *xref = fz_get_indirect_xref(ref); + fz_context *ctx = xref->ctx; int num = fz_to_num(ref); int gen = fz_to_gen(ref); if (xref) { - fz_error error = pdf_cache_object(xref, num, gen); - if (error) + fz_try(ctx) { - fz_catch(error, "cannot load object (%d %d R) into cache", num, gen); + pdf_cache_object(xref, num, gen); + } + fz_catch(ctx) + { + fz_warn(ctx, "cannot load object (%d %d R) into cache", num, gen); return ref; } if (xref->table[num].obj) @@ -1062,7 +1032,7 @@ pdf_update_object(pdf_xref *xref, int num, int gen, fz_obj *newobj) if (num < 0 || num >= xref->len) { - fz_warn("object out of range (%d %d R); xref size %d", num, gen, xref->len); + fz_warn(xref->ctx, "object out of range (%d %d R); xref size %d", num, gen, xref->len); return; } @@ -1080,20 +1050,24 @@ pdf_update_object(pdf_xref *xref, int num, int gen, fz_obj *newobj) * Convenience function to open a file then call pdf_open_xref_with_stream. */ -fz_error -pdf_open_xref(pdf_xref **xrefp, const char *filename, char *password) +pdf_xref * +pdf_open_xref(fz_context *ctx, const char *filename, char *password) { - fz_error error; - fz_stream *file; - - file = fz_open_file(filename); - if (!file) - return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); + fz_stream *file = NULL; + pdf_xref *xref; - error = pdf_open_xref_with_stream(xrefp, file, password); - if (error) - return fz_rethrow(error, "cannot load document '%s'", filename); + //fz_var(file); + fz_try(ctx) + { + file = fz_open_file(ctx, filename); + xref = pdf_open_xref_with_stream(file, password); + } + fz_catch(ctx) + { + fz_close(file); + fz_throw(ctx, "cannot load document '%s'", filename); + } fz_close(file); - return fz_okay; + return xref; } diff --git a/scripts/cmapdump.c b/scripts/cmapdump.c index 68a5c3cf..be7a456e 100644 --- a/scripts/cmapdump.c +++ b/scripts/cmapdump.c @@ -3,9 +3,13 @@ #include <stdio.h> #include <string.h> +/* We never want to build memento versions of the cmapdump util */ +#undef MEMENTO + #include "fitz.h" #include "mupdf.h" +#include "../fitz/base_context.c" #include "../fitz/base_error.c" #include "../fitz/base_memory.c" #include "../fitz/base_string.c" @@ -38,6 +42,7 @@ main(int argc, char **argv) char name[256]; char *realname; int i, k; + fz_context *ctx; if (argc < 3) { @@ -45,6 +50,13 @@ main(int argc, char **argv) return 1; } + ctx = fz_new_context(&fz_alloc_default); + if (ctx == NULL) + { + fprintf(stderr, "failed to initialise!\n"); + return 1; + } + fo = fopen(argv[1], "wb"); if (!fo) { @@ -73,14 +85,17 @@ main(int argc, char **argv) strcpy(name, realname); clean(name); - fi = fz_open_file(argv[i]); + fi = fz_open_file(ctx, argv[i]); if (!fi) - fz_throw("cmapdump: could not open input file '%s'\n", argv[i]); + fz_error_make("cmapdump: could not open input file '%s'\n", argv[i]); - error = pdf_parse_cmap(&cmap, fi); - if (error) + fz_try(ctx) { - fz_catch(error, "cmapdump: could not parse input cmap '%s'\n", argv[i]); + cmap = pdf_parse_cmap(fi); + } + fz_catch(ctx) + { + fz_error_handle(error, "cmapdump: could not parse input cmap '%s'\n", argv[i]); return 1; } @@ -154,5 +169,22 @@ main(int argc, char **argv) return 1; } + fz_free_context(ctx); return 0; } + +void fz_new_font_context(fz_context *ctx) +{ +} + +void fz_free_font_context(fz_context *ctx) +{ +} + +void fz_new_aa_context(fz_context *ctx) +{ +} + +void fz_free_aa_context(fz_context *ctx) +{ +} diff --git a/viewer/ximage.o b/viewer/ximage.o Binary files differnew file mode 100644 index 00000000..ec5a5d10 --- /dev/null +++ b/viewer/ximage.o diff --git a/viewer/xmain.c b/viewer/xmain.c new file mode 100644 index 00000000..6223f1b6 --- /dev/null +++ b/viewer/xmain.c @@ -0,0 +1,382 @@ +#include "aekit.h" + +#include <xcb/xcb.h> +#include <xcb/xcb_icccm.h> /* for wm-hints */ +#include <xcb/xcb_image.h> /* for pixmap-from-bitmap-data */ + +#include "ximage.h" + +#define GENBASE 1000 +#define GENID (GENBASE + __LINE__) + +#ifndef XCB_ATOM_STRING +#define XCB_ATOM_STRING 31 +#endif + +#define DEFW 612 // 595 /* 612 */ +#define DEFH 792 // 842 /* 792 */ + +void ui_main_loop(void); + +char *title = "aekit"; + +void die(char *msg) +{ + fprintf(stderr, "error: %s\n", msg); + exit(1); +} + +static const char *xcb_error_name_list[] = { + "None", "Request", "Value", "Window", "Pixmap", "Atom", + "Cursor", "Font", "Match", "Drawable", "Access", "Alloc", + "Colormap", "GContext", "IDChoice", "Name", "Length", + "Implementation", +}; + +const char *xcb_get_error_name(int detail) +{ + if (detail >= 0 && detail < nelem(xcb_error_name_list)) + return xcb_error_name_list[detail]; + return "Unknown"; +} + +static xcb_screen_t * +find_screen_by_number(const xcb_setup_t *setup, int screen) +{ + xcb_screen_iterator_t i = xcb_setup_roots_iterator(setup); + for (; i.rem; --screen, xcb_screen_next(&i)) + if (screen == 0) + return i.data; + return 0; +} + +struct unifont *font; +struct image dstk; +struct image *dst = &dstk; +struct ui ui = { 0 }; + +struct color btn_brown = { 206, 193, 180 }; +struct color btn_brown_hi = { 218, 205, 192 }; +struct color btn_brown_lo = { 173, 160, 147 }; +struct color border = { 80, 80, 80 }; +struct color gray = { 153, 153, 153 }; +struct color black = { 0, 0, 0 }; + +#define icon_width 16 +#define icon_height 16 +static unsigned char icon_bits[] = { + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x2b, 0x80, 0x55, 0x8c, 0x62, 0x8c, 0x51, + 0x9c, 0x61, 0x1c, 0x35, 0x3c, 0x1f, 0x3c, 0x0f, 0xfc, 0x0f, 0xec, 0x0d, + 0xec, 0x0d, 0xcc, 0x0c, 0xcc, 0x0c, 0x00, 0x00 }; + +#define icon_mask_width 16 +#define icon_mask_height 16 +static unsigned char icon_mask_bits[] = { + 0x00, 0x1e, 0x00, 0x3f, 0x80, 0x7f, 0xce, 0xff, 0xde, 0xff, 0xde, 0xff, + 0xfe, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, + 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xce, 0x1c }; + +struct ximage *surface; +xcb_connection_t *conn; +xcb_screen_t *screen; +xcb_window_t window; +xcb_gcontext_t gc; +int dirty; + +void +on_resize(int w, int h) +{ + if (dst->samples && dst->w == w && dst->h == h) + return; + + free(dst->samples); + + dst->w = w; + dst->h = h; + dst->stride = dst->w * 4; + dst->samples = malloc(dst->h * dst->stride); + + memset(dst->samples, 192, dst->h * dst->stride); + + ui.key = 0; + ui_main_loop(); + + dirty = 1; +} + +void +ui_start_frame(void) +{ + ui.hot = 0; +} + +void +ui_end_frame(void) +{ + if (!(ui.down & 1)) + ui.active = 0; + else if (!ui.active) + ui.active = -1; /* click outside widgets, mark as unavailable */ + dirty = 1; +} + +int +ui_region_hit(int x, int y, int w, int h) +{ + return ui.x >= x && ui.y >= y && ui.x < x + w && ui.y < y + h; +} + +int +ui_button(int id, int x, int y, char *label) +{ + int w = ui_measure_unifont_string(font, label) + 12; + int h = 25; + int b = 2; + + if (ui_region_hit(x, y, w, h)) { + ui.hot = id; + if (!ui.active && (ui.down & 1)) + ui.active = id; + } + + int x0 = x; + int y0 = y; + int x1 = x + w - 1; + int y1 = y + h - 1; + + ui_fill_rect(dst, x0, y0, x1+1, y0+1, border); + ui_fill_rect(dst, x0, y1, x1+1, y1+1, border); + ui_fill_rect(dst, x0, y0, x0+1, y1, border); + ui_fill_rect(dst, x1, y0, x1+1, y1, border); + + x0++; y0++; x1--; y1--; + ui_fill_rect(dst, x0, y0, x1+1, y0+1, btn_brown_hi); + ui_fill_rect(dst, x0, y1, x1+1, y1+1, btn_brown_lo); + ui_fill_rect(dst, x0, y0, x0+1, y1, btn_brown_hi); + ui_fill_rect(dst, x1, y0, x1+1, y1, btn_brown_lo); + + if (ui.active == id && (ui.down & 1)) { + if (ui.hot == id) + ui_fill_rect(dst, x+b-1, y+b-1, x+w-b+1, y+h-b+1, btn_brown_lo); + else + ui_fill_rect(dst, x+b, y+b, x+w-b, y+h-b, btn_brown); + } + else + ui_fill_rect(dst, x+b, y+b, x+w-b, y+h-b, btn_brown); + + ui_draw_unifont_string(dst, font, label, x+b+4, y+b+2, black); + + return !(ui.down & 1) && ui.hot == id && ui.active == id; +} + +void +ui_main_loop(void) +{ + ui_start_frame(); + + if (ui_button(GENID, 30, 30, "☑ Hello, world!")) puts("click 1"); + if (ui_button(GENID, 30, 60, "☐ 你好")) puts("click 2"); + if (ui_button(GENID, 30, 90, "Γεια σου")) puts("click 3"); + if (ui_button(GENID, 30, 120, "My ♚ will eat your ♖!")) puts("click 4"); + if (ui_button(GENID, 30, 150, "おはよう")) puts("click 5"); + if (ui_button(GENID, 30, 180, "안녕하세요")) puts("click 6"); + if (ui_button(GENID, 30, 210, "☏ xin chào")) puts("click 7"); + if (ui_button(GENID, 30, 240, "[ ☢ ☣ ☥ ☭ ☯ ]")) puts("click 7"); + if (ui_button(GENID, 30, 270, "(♃♄♅♆♇♈♉♊♋♌♍ ...)")) puts("click 7"); + + ui_end_frame(); +} + +int +main(int argc, char **argv) +{ + const xcb_setup_t *setup; + xcb_generic_event_t *event; + int screen_num; + xcb_wm_hints_t hints; + xcb_pixmap_t icon, icon_mask; + uint32_t mask; + uint32_t attrs[2]; + int w, h; + int button; + + font = ui_load_unifont("unifont.dat"); + if (!font) + die("cannot load 'unifont.dat'"); + + /* Connect and find the screen */ + + conn = xcb_connect(NULL, &screen_num); + if (!conn) + die("cannot connect to display"); + + if (xcb_connection_has_error(conn)) + die("cannot connect to display"); + + setup = xcb_get_setup(conn); + if (!setup) + die("cannot get display setup"); + + screen = find_screen_by_number(setup, screen_num); + if (!screen) + die("cannot find screen"); + + /* Create window */ + + mask = XCB_CW_EVENT_MASK; + attrs[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_KEY_PRESS | + XCB_EVENT_MASK_POINTER_MOTION | + XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE; + + window = xcb_generate_id(conn); + xcb_create_window(conn, 0, window, screen->root, + 20, 20, DEFW, DEFH, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, + mask, attrs); + + /* Set title and icon */ + + xcb_set_wm_name(conn, window, XCB_ATOM_STRING, strlen(title), title); + xcb_set_wm_icon_name(conn, window, XCB_ATOM_STRING, strlen(title), title); + + icon = xcb_create_pixmap_from_bitmap_data(conn, window, + icon_bits, icon_width, icon_height, 1, + screen->black_pixel, screen->white_pixel, NULL); + icon_mask = xcb_create_pixmap_from_bitmap_data(conn, window, + icon_mask_bits, icon_mask_width, icon_mask_height, 1, + screen->black_pixel, screen->white_pixel, NULL); + + memset(&hints, 0, sizeof hints); + xcb_wm_hints_set_icon_pixmap(&hints, icon); + xcb_wm_hints_set_icon_mask(&hints, icon_mask); + xcb_set_wm_hints(conn, window, &hints); + + xcb_map_window(conn, window); + + /* Create GC */ + + mask = XCB_GC_FOREGROUND; + attrs[0] = screen->black_pixel; + + gc = xcb_generate_id(conn); + xcb_create_gc(conn, gc, window, mask, attrs); + + xcb_flush(conn); + + /* Enter the event loop */ + + if (xcb_connection_has_error(conn)) + die("display connection problem 1"); + + surface = ximage_create(conn, screen, screen->root_visual); + + if (xcb_connection_has_error(conn)) + die("display connection problem 2"); + + dirty = 0; + w = h = 0; + + dst->w = 0; + dst->h = 0; + dst->samples = NULL; + + while (1) { + event = xcb_wait_for_event(conn); + if (!event) + break; + + while (event) { + switch (event->response_type & 0x7f) { + case 0: { + printf("xcb error: Bad%s\n", xcb_get_error_name(event->pad0)); + break; + } + case XCB_EXPOSE: { + dirty = 1; + break; + } + case XCB_REPARENT_NOTIFY: + case XCB_MAP_NOTIFY: + case XCB_UNMAP_NOTIFY: + break; + case XCB_CONFIGURE_NOTIFY: { + xcb_configure_notify_event_t *config; + config = (xcb_configure_notify_event_t*)event; + w = config->width; + h = config->height; + if (w != dst->w || h != dst->h) + dirty = 1; + break; + } + case XCB_BUTTON_PRESS: { + xcb_button_press_event_t *press; + press = (xcb_button_press_event_t*)event; + button = 1 << (press->detail - 1); +printf("press %d\n", button); + ui.x = press->event_x; + ui.y = press->event_y; + ui.down |= button; + ui.key = 0; + ui_main_loop(); + break; + } + case XCB_BUTTON_RELEASE: { + xcb_button_release_event_t *release; + release = (xcb_button_release_event_t*)event; + button = 1 << (release->detail - 1); +printf("release %d\n", button); + ui.x = release->event_x; + ui.y = release->event_y; + ui.down &= ~button; + ui.key = 0; + ui_main_loop(); + break; + } + case XCB_MOTION_NOTIFY: { + xcb_motion_notify_event_t *motion; + motion = (xcb_motion_notify_event_t*)event; + ui.x = motion->event_x; + ui.y = motion->event_y; + ui.key = 0; + /* TODO: coalesce motion events */ + if (ui.active > 0) { +//puts("motion while active"); + ui_main_loop(); + } + break; + } + case XCB_KEY_PRESS: { + xcb_key_press_event_t *key; + key = (xcb_key_press_event_t*)event; + ui.x = key->event_x; + ui.y = key->event_y; + ui.key = key->detail; + ui_main_loop(); + break; + } + default: + printf("got unknown event %d\n", event->response_type); + break; + } + event = xcb_poll_for_event(conn); + } + + if (dirty) { +//printf("dirty, repainting\n"); + if (w != dst->w || h != dst->h) + on_resize(w, h); + ximage_draw(conn, window, gc, surface, + 0, 0, dst->w, dst->h, dst->samples); + dirty = 0; + } + } + + printf("disconnecting\n"); + + ximage_destroy(surface); + + xcb_disconnect(conn); + + return 0; +} diff --git a/win32/libmupdf.vcproj b/win32/libmupdf.vcproj index 3d15f397..52977dca 100644 --- a/win32/libmupdf.vcproj +++ b/win32/libmupdf.vcproj @@ -42,6 +42,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\scripts;..\fitz;..\pdf;..\thirdparty\jbig2dec;..\thirdparty\jpeg-8c;..\thirdparty\openjpeg-1.4\libopenjpeg;..\thirdparty\zlib-1.2.5;..\thirdparty\freetype-2.4.4\include" + PreprocessorDefinitions="DEBUG=1" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -139,6 +140,69 @@ Name="VCPostBuildEventTool" /> </Configuration> + <Configuration + Name="Memento|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)\$(ProjectName)" + ConfigurationType="4" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + Description="Generate CMap and Font source files" + CommandLine="generate.bat" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\scripts;..\fitz;..\pdf;..\thirdparty\jbig2dec;..\thirdparty\jpeg-8c;..\thirdparty\openjpeg-1.4\libopenjpeg;..\thirdparty\zlib-1.2.5;..\thirdparty\freetype-2.4.4\include" + PreprocessorDefinitions="MEMENTO=1;DEBUG=1" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + WarningLevel="3" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> </Configurations> <References> </References> @@ -275,6 +339,10 @@ Name="fitz" > <File + RelativePath="..\fitz\base_context.c" + > + </File> + <File RelativePath="..\fitz\base_error.c" > </File> @@ -323,10 +391,6 @@ > </File> <File - RelativePath="..\fitz\doc_outline.c" - > - </File> - <File RelativePath="..\fitz\dev_bbox.c" > </File> @@ -347,6 +411,10 @@ > </File> <File + RelativePath="..\fitz\doc_outline.c" + > + </File> + <File RelativePath="..\fitz\filt_basic.c" > </File> @@ -383,7 +451,11 @@ > </File> <File - RelativePath="..\fitz\obj_print.c" + RelativePath="..\fitz\memento.c" + > + </File> + <File + RelativePath="..\fitz\memento.h" > </File> <File @@ -483,6 +555,10 @@ Name="xps" > <File + RelativePath="..\xps\muxps.h" + > + </File> + <File RelativePath="..\xps\xps_common.c" > </File> diff --git a/win32/libthirdparty.vcproj b/win32/libthirdparty.vcproj index 6b3cc70b..703b0eb2 100644 --- a/win32/libthirdparty.vcproj +++ b/win32/libthirdparty.vcproj @@ -40,7 +40,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\scripts;..\thirdparty\jbig2dec;..\thirdparty\jpeg-8c;..\thirdparty\openjpeg-1.4\libopenjpeg;..\thirdparty\zlib-1.2.5;..\thirdparty\freetype-2.4.4\include" - PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY;OPJ_STATIC;FT_CONFIG_MODULES_H=\"slimftmodules.h\";FT_CONFIG_OPTIONS_H=\"slimftoptions.h\"" + PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY;OPJ_STATIC;FT_CONFIG_MODULES_H=\"slimftmodules.h\";FT_CONFIG_OPTIONS_H=\"slimftoptions.h\";DEBUG=1" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -137,6 +137,67 @@ Name="VCPostBuildEventTool" /> </Configuration> + <Configuration + Name="Memento|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)\$(ProjectName)" + ConfigurationType="4" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\scripts;..\thirdparty\jbig2dec;..\thirdparty\jpeg-8c;..\thirdparty\openjpeg-1.4\libopenjpeg;..\thirdparty\zlib-1.2.5;..\thirdparty\freetype-2.4.4\include" + PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY;OPJ_STATIC;FT_CONFIG_MODULES_H=\"slimftmodules.h\";FT_CONFIG_OPTIONS_H=\"slimftoptions.h\";MEMENTO=1;DEBUG=1" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + WarningLevel="3" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> </Configurations> <References> </References> diff --git a/win32/mupdf.sln b/win32/mupdf.sln index 54793c52..ba2875a6 100644 --- a/win32/mupdf.sln +++ b/win32/mupdf.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 +# Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupdf", "mupdf.vcproj", "{E74F29F0-FA43-4ADC-B92C-6AFA08E4A417}" ProjectSection(ProjectDependencies) = postProject {5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519} @@ -44,39 +44,56 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Memento|Win32 = Memento|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E74F29F0-FA43-4ADC-B92C-6AFA08E4A417}.Debug|Win32.ActiveCfg = Debug|Win32 {E74F29F0-FA43-4ADC-B92C-6AFA08E4A417}.Debug|Win32.Build.0 = Debug|Win32 + {E74F29F0-FA43-4ADC-B92C-6AFA08E4A417}.Memento|Win32.ActiveCfg = Memento|Win32 + {E74F29F0-FA43-4ADC-B92C-6AFA08E4A417}.Memento|Win32.Build.0 = Memento|Win32 {E74F29F0-FA43-4ADC-B92C-6AFA08E4A417}.Release|Win32.ActiveCfg = Release|Win32 {E74F29F0-FA43-4ADC-B92C-6AFA08E4A417}.Release|Win32.Build.0 = Release|Win32 {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}.Debug|Win32.ActiveCfg = Debug|Win32 {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}.Debug|Win32.Build.0 = Debug|Win32 + {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}.Memento|Win32.ActiveCfg = Memento|Win32 + {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}.Memento|Win32.Build.0 = Memento|Win32 {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}.Release|Win32.ActiveCfg = Release|Win32 {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}.Release|Win32.Build.0 = Release|Win32 {5F615F91-DFF8-4F05-BF48-6222B7D86519}.Debug|Win32.ActiveCfg = Debug|Win32 {5F615F91-DFF8-4F05-BF48-6222B7D86519}.Debug|Win32.Build.0 = Debug|Win32 + {5F615F91-DFF8-4F05-BF48-6222B7D86519}.Memento|Win32.ActiveCfg = Memento|Win32 + {5F615F91-DFF8-4F05-BF48-6222B7D86519}.Memento|Win32.Build.0 = Memento|Win32 {5F615F91-DFF8-4F05-BF48-6222B7D86519}.Release|Win32.ActiveCfg = Release|Win32 {5F615F91-DFF8-4F05-BF48-6222B7D86519}.Release|Win32.Build.0 = Release|Win32 {26C5D7C3-BEE9-4886-9CDB-846D26F5BCDB}.Debug|Win32.ActiveCfg = Debug|Win32 {26C5D7C3-BEE9-4886-9CDB-846D26F5BCDB}.Debug|Win32.Build.0 = Debug|Win32 + {26C5D7C3-BEE9-4886-9CDB-846D26F5BCDB}.Memento|Win32.ActiveCfg = Memento|Win32 + {26C5D7C3-BEE9-4886-9CDB-846D26F5BCDB}.Memento|Win32.Build.0 = Memento|Win32 {26C5D7C3-BEE9-4886-9CDB-846D26F5BCDB}.Release|Win32.ActiveCfg = Release|Win32 {26C5D7C3-BEE9-4886-9CDB-846D26F5BCDB}.Release|Win32.Build.0 = Release|Win32 {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Debug|Win32.ActiveCfg = Debug|Win32 {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Debug|Win32.Build.0 = Debug|Win32 + {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Memento|Win32.ActiveCfg = Memento|Win32 + {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Memento|Win32.Build.0 = Memento|Win32 {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Release|Win32.ActiveCfg = Release|Win32 {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Release|Win32.Build.0 = Release|Win32 {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Debug|Win32.ActiveCfg = Debug|Win32 {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Debug|Win32.Build.0 = Debug|Win32 + {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Memento|Win32.ActiveCfg = Memento|Win32 + {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Memento|Win32.Build.0 = Memento|Win32 {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Release|Win32.ActiveCfg = Release|Win32 {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Release|Win32.Build.0 = Release|Win32 {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Debug|Win32.ActiveCfg = Debug|Win32 {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Debug|Win32.Build.0 = Debug|Win32 + {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Memento|Win32.ActiveCfg = Memento|Win32 + {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Memento|Win32.Build.0 = Memento|Win32 {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Release|Win32.ActiveCfg = Release|Win32 {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Release|Win32.Build.0 = Release|Win32 {E6A93617-41BD-45B2-BF61-4F7ED263CDF2}.Debug|Win32.ActiveCfg = Debug|Win32 {E6A93617-41BD-45B2-BF61-4F7ED263CDF2}.Debug|Win32.Build.0 = Debug|Win32 + {E6A93617-41BD-45B2-BF61-4F7ED263CDF2}.Memento|Win32.ActiveCfg = Memento|Win32 + {E6A93617-41BD-45B2-BF61-4F7ED263CDF2}.Memento|Win32.Build.0 = Memento|Win32 {E6A93617-41BD-45B2-BF61-4F7ED263CDF2}.Release|Win32.ActiveCfg = Release|Win32 {E6A93617-41BD-45B2-BF61-4F7ED263CDF2}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection diff --git a/win32/mupdf.vcproj b/win32/mupdf.vcproj index b0e899e1..c61cb34d 100644 --- a/win32/mupdf.vcproj +++ b/win32/mupdf.vcproj @@ -5,7 +5,6 @@ Name="mupdf" ProjectGUID="{E74F29F0-FA43-4ADC-B92C-6AFA08E4A417}" RootNamespace="mupdf" - TargetFrameworkVersion="196613" > <Platforms> <Platform @@ -41,7 +40,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\fitz;..\pdf;..\xps" - PreprocessorDefinitions="FT2_BUILD_LIBRARY;OPJ_STATIC" + PreprocessorDefinitions="FT2_BUILD_LIBRARY;OPJ_STATIC;DEBUG=1" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -81,6 +80,9 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> @@ -152,6 +154,81 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Memento|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)\$(ProjectName)" + ConfigurationType="1" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\fitz;..\pdf;..\xps" + PreprocessorDefinitions="FT2_BUILD_LIBRARY;OPJ_STATIC;MEMENTO=1;DEBUG=1" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + WarningLevel="3" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + GenerateDebugInformation="true" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> @@ -164,6 +241,10 @@ > </File> <File + RelativePath="..\apps\pdfapp.h" + > + </File> + <File RelativePath="..\apps\win_main.c" > </File> diff --git a/win32/pdfclean.vcproj b/win32/pdfclean.vcproj index 2c6e5655..b3bdcb6c 100644 --- a/win32/pdfclean.vcproj +++ b/win32/pdfclean.vcproj @@ -5,7 +5,6 @@ Name="pdfclean" ProjectGUID="{923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}" RootNamespace="mupdf" - TargetFrameworkVersion="196613" > <Platforms> <Platform @@ -41,6 +40,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\fitz;..\pdf" + PreprocessorDefinitions="DEBUG=1" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -80,6 +80,9 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> @@ -151,6 +154,81 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Memento|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)\$(ProjectName)" + ConfigurationType="1" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\fitz;..\pdf" + PreprocessorDefinitions="MEMENTO=1;DEBUG=1" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + WarningLevel="3" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + GenerateDebugInformation="true" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> diff --git a/win32/pdfdraw.vcproj b/win32/pdfdraw.vcproj index 769c2b19..5ae5bdfe 100644 --- a/win32/pdfdraw.vcproj +++ b/win32/pdfdraw.vcproj @@ -5,7 +5,6 @@ Name="pdfdraw" ProjectGUID="{26C5D7C3-BEE9-4886-9CDB-846D26F5BCDB}" RootNamespace="mupdf" - TargetFrameworkVersion="196613" > <Platforms> <Platform @@ -41,6 +40,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\fitz;..\pdf" + PreprocessorDefinitions="DEBUG=1" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -80,6 +80,9 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> @@ -151,6 +154,81 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Memento|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)\$(ProjectName)" + ConfigurationType="1" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\fitz;..\pdf" + PreprocessorDefinitions="MEMENTO=1;DEBUG=1" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + WarningLevel="3" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + GenerateDebugInformation="true" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> diff --git a/win32/pdfextract.vcproj b/win32/pdfextract.vcproj index 91e975f9..1d14b6c6 100644 --- a/win32/pdfextract.vcproj +++ b/win32/pdfextract.vcproj @@ -5,7 +5,6 @@ Name="pdfextract" ProjectGUID="{BD4473E7-2DBE-4568-A0FC-38EED70182DC}" RootNamespace="mupdf" - TargetFrameworkVersion="196613" > <Platforms> <Platform @@ -41,6 +40,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\fitz;..\pdf" + PreprocessorDefinitions="DEBUG=1" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -80,6 +80,9 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> @@ -151,6 +154,81 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Memento|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)\$(ProjectName)" + ConfigurationType="1" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\fitz;..\pdf" + PreprocessorDefinitions="MEMENTO=1;DEBUG=1" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + WarningLevel="3" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + GenerateDebugInformation="true" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> diff --git a/win32/pdfshow.vcproj b/win32/pdfshow.vcproj index a115fd20..30fd1784 100644 --- a/win32/pdfshow.vcproj +++ b/win32/pdfshow.vcproj @@ -5,7 +5,6 @@ Name="pdfshow" ProjectGUID="{50644121-C85F-4EE9-9C54-F7D1BDFAE354}" RootNamespace="mupdf" - TargetFrameworkVersion="196613" > <Platforms> <Platform @@ -41,6 +40,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\fitz;..\pdf" + PreprocessorDefinitions="DEBUG=1" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -80,6 +80,9 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> @@ -151,6 +154,81 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Memento|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)\$(ProjectName)" + ConfigurationType="1" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\fitz;..\pdf" + PreprocessorDefinitions="MEMENTO=1;DEBUG=1" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + WarningLevel="3" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + GenerateDebugInformation="true" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> diff --git a/win32/xpsdraw.vcproj b/win32/xpsdraw.vcproj index 52357d31..d2db91fa 100644 --- a/win32/xpsdraw.vcproj +++ b/win32/xpsdraw.vcproj @@ -40,6 +40,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\fitz;..\xps" + PreprocessorDefinitions="DEBUG=1" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -58,8 +59,6 @@ <Tool Name="VCLinkerTool" GenerateDebugInformation="true" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1" /> <Tool @@ -81,6 +80,9 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> @@ -131,8 +133,6 @@ GenerateDebugInformation="true" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1" /> <Tool @@ -154,6 +154,81 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Memento|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)\$(ProjectName)" + ConfigurationType="1" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\fitz;..\xps" + PreprocessorDefinitions="MEMENTO=1;DEBUG=1" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + WarningLevel="3" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + GenerateDebugInformation="true" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> diff --git a/xps/muxps.h b/xps/muxps.h index 172a8535..18ca528e 100644 --- a/xps/muxps.h +++ b/xps/muxps.h @@ -11,7 +11,7 @@ typedef unsigned char byte; * XPS and ZIP constants. */ -typedef struct xps_context_s xps_context; +typedef struct xps_document_s xps_document; #define REL_START_PART \ "http://schemas.microsoft.com/xps/2005/06/fixedrepresentation" @@ -40,12 +40,12 @@ void xps_absolute_path(char *output, char *base_uri, char *path, int output_size typedef struct element xml_element; -xml_element *xml_parse_document(byte *buf, int len); +xml_element *xml_parse_document(fz_context *doc, byte *buf, int len); xml_element *xml_next(xml_element *item); xml_element *xml_down(xml_element *item); char *xml_tag(xml_element *item); char *xml_att(xml_element *item, const char *att); -void xml_free_element(xml_element *item); +void xml_free_element(fz_context *doc, xml_element *item); void xml_print_element(xml_element *item, int level); /* @@ -62,23 +62,23 @@ struct xps_part_s byte *data; }; -xps_part *xps_new_part(xps_context *ctx, char *name, int size); -xps_part *xps_read_part(xps_context *ctx, char *partname); -void xps_free_part(xps_context *ctx, xps_part *part); +xps_part *xps_new_part(xps_document *doc, char *name, int size); +xps_part *xps_read_part(xps_document *doc, char *partname); +void xps_free_part(xps_document *doc, xps_part *part); /* * Document structure. */ -typedef struct xps_document_s xps_document; +typedef struct xps_fixdoc_s xps_fixdoc; typedef struct xps_page_s xps_page; typedef struct xps_target_s xps_target; -struct xps_document_s +struct xps_fixdoc_s { char *name; char *outline; - xps_document *next; + xps_fixdoc *next; }; struct xps_page_s @@ -98,25 +98,25 @@ struct xps_target_s xps_target *next; }; -int xps_read_page_list(xps_context *ctx); -void xps_debug_page_list(xps_context *ctx); -void xps_free_page_list(xps_context *ctx); +int xps_read_page_list(xps_document *doc); +void xps_debug_page_list(xps_document *doc); +void xps_free_page_list(xps_document *doc); -int xps_count_pages(xps_context *ctx); -int xps_load_page(xps_page **page, xps_context *ctx, int number); -void xps_free_page(xps_context *ctx, xps_page *page); +int xps_count_pages(xps_document *doc); +xps_page *xps_load_page(xps_document *doc, int number); +void xps_free_page(xps_document *doc, xps_page *page); -fz_outline *xps_load_outline(xps_context *ctx); +fz_outline *xps_load_outline(xps_document *doc); -int xps_find_link_target(xps_context *ctx, char *target_uri); +int xps_find_link_target(xps_document *doc, char *target_uri); /* * Images, fonts, and colorspaces. */ -int xps_decode_jpeg(fz_pixmap **imagep, byte *rbuf, int rlen); -int xps_decode_png(fz_pixmap **imagep, byte *rbuf, int rlen); -int xps_decode_tiff(fz_pixmap **imagep, byte *rbuf, int rlen); +fz_pixmap *xps_decode_jpeg(fz_context *doc, byte *rbuf, int rlen); +fz_pixmap *xps_decode_png(fz_context *doc, byte *rbuf, int rlen); +fz_pixmap *xps_decode_tiff(fz_context *doc, byte *rbuf, int rlen); typedef struct xps_font_cache_s xps_font_cache; @@ -139,12 +139,12 @@ void xps_identify_font_encoding(fz_font *font, int idx, int *pid, int *eid); void xps_select_font_encoding(fz_font *font, int idx); int xps_encode_font_char(fz_font *font, int key); -void xps_measure_font_glyph(xps_context *ctx, fz_font *font, int gid, xps_glyph_metrics *mtx); +void xps_measure_font_glyph(xps_document *doc, fz_font *font, int gid, xps_glyph_metrics *mtx); -void xps_debug_path(xps_context *ctx); +void xps_debug_path(xps_document *doc); -void xps_parse_color(xps_context *ctx, char *base_uri, char *hexstring, fz_colorspace **csp, float *samples); -void xps_set_color(xps_context *ctx, fz_colorspace *colorspace, float *samples); +void xps_parse_color(xps_document *doc, char *base_uri, char *hexstring, fz_colorspace **csp, float *samples); +void xps_set_color(xps_document *doc, fz_colorspace *colorspace, float *samples); /* * Resource dictionaries. @@ -162,9 +162,9 @@ struct xps_resource_s xps_resource *parent; /* up to the previous dict in the stack */ }; -int xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, xml_element *root); -void xps_free_resource_dictionary(xps_context *ctx, xps_resource *dict); -void xps_resolve_resource_reference(xps_context *ctx, xps_resource *dict, char **attp, xml_element **tagp, char **urip); +int xps_parse_resource_dictionary(xps_document *doc, xps_resource **dictp, char *base_uri, xml_element *root); +void xps_free_resource_dictionary(xps_document *doc, xps_resource *dict); +void xps_resolve_resource_reference(xps_document *doc, xps_resource *dict, char **attp, xml_element **tagp, char **urip); void xps_debug_resource_dictionary(xps_resource *dict); @@ -172,29 +172,29 @@ void xps_debug_resource_dictionary(xps_resource *dict); * Fixed page/graphics parsing. */ -void xps_parse_fixed_page(xps_context *ctx, fz_matrix ctm, xps_page *page); -void xps_parse_canvas(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_solid_color_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_linear_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_radial_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_fixed_page(xps_document *doc, fz_matrix ctm, xps_page *page); +void xps_parse_canvas(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_path(xps_document *doc, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_glyphs(xps_document *doc, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_solid_color_brush(xps_document *doc, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_image_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_visual_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_linear_gradient_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_radial_gradient_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root, void(*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*), void *user); +void xps_parse_tiling_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root, void(*func)(xps_document*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*), void *user); -void xps_parse_matrix_transform(xps_context *ctx, xml_element *root, fz_matrix *matrix); -void xps_parse_render_transform(xps_context *ctx, char *text, fz_matrix *matrix); -void xps_parse_rectangle(xps_context *ctx, char *text, fz_rect *rect); +void xps_parse_matrix_transform(xps_document *doc, xml_element *root, fz_matrix *matrix); +void xps_parse_render_transform(xps_document *doc, char *text, fz_matrix *matrix); +void xps_parse_rectangle(xps_document *doc, char *text, fz_rect *rect); -void xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, char *opacity_att, xml_element *opacity_mask_tag); -void xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict, char *opacity_att, xml_element *opacity_mask_tag); +void xps_begin_opacity(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, char *opacity_att, xml_element *opacity_mask_tag); +void xps_end_opacity(xps_document *doc, char *base_uri, xps_resource *dict, char *opacity_att, xml_element *opacity_mask_tag); -void xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_element(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_element(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_clip(xps_context *ctx, fz_matrix ctm, xps_resource *dict, char *clip_att, xml_element *clip_tag); +void xps_clip(xps_document *doc, fz_matrix ctm, xps_resource *dict, char *clip_att, xml_element *clip_tag); /* * The interpreter context. @@ -210,16 +210,17 @@ struct xps_entry_s int usize; }; -struct xps_context_s +struct xps_document_s { + fz_context *ctx; char *directory; fz_stream *file; int zip_count; xps_entry *zip_table; char *start_part; /* fixed document sequence */ - xps_document *first_fixdoc; /* first fixed document */ - xps_document *last_fixdoc; /* last fixed document */ + xps_fixdoc *first_fixdoc; /* first fixed document */ + xps_fixdoc *last_fixdoc; /* last fixed document */ xps_page *first_page; /* first page of document */ xps_page *last_page; /* last page of document */ int page_count; @@ -245,8 +246,8 @@ struct xps_context_s fz_device *dev; }; -int xps_open_file(xps_context **ctxp, char *filename); -int xps_open_stream(xps_context **ctxp, fz_stream *file); -void xps_free_context(xps_context *ctx); +xps_document *xps_open_file(fz_context *ctx, char *filename); +xps_document *xps_open_stream(fz_stream *file); +void xps_free_context(xps_document *doc); #endif diff --git a/xps/xps_common.c b/xps/xps_common.c index 894a4941..745d1be1 100644 --- a/xps/xps_common.c +++ b/xps/xps_common.c @@ -10,35 +10,35 @@ static inline int unhex(int a) } void -xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node) +xps_parse_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node) { /* SolidColorBrushes are handled in a special case and will never show up here */ if (!strcmp(xml_tag(node), "ImageBrush")) - xps_parse_image_brush(ctx, ctm, area, base_uri, dict, node); + xps_parse_image_brush(doc, ctm, area, base_uri, dict, node); else if (!strcmp(xml_tag(node), "VisualBrush")) - xps_parse_visual_brush(ctx, ctm, area, base_uri, dict, node); + xps_parse_visual_brush(doc, ctm, area, base_uri, dict, node); else if (!strcmp(xml_tag(node), "LinearGradientBrush")) - xps_parse_linear_gradient_brush(ctx, ctm, area, base_uri, dict, node); + xps_parse_linear_gradient_brush(doc, ctm, area, base_uri, dict, node); else if (!strcmp(xml_tag(node), "RadialGradientBrush")) - xps_parse_radial_gradient_brush(ctx, ctm, area, base_uri, dict, node); + xps_parse_radial_gradient_brush(doc, ctm, area, base_uri, dict, node); else - fz_warn("unknown brush tag: %s", xml_tag(node)); + fz_warn(doc->ctx, "unknown brush tag: %s", xml_tag(node)); } void -xps_parse_element(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node) +xps_parse_element(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node) { if (!strcmp(xml_tag(node), "Path")) - xps_parse_path(ctx, ctm, base_uri, dict, node); + xps_parse_path(doc, ctm, base_uri, dict, node); if (!strcmp(xml_tag(node), "Glyphs")) - xps_parse_glyphs(ctx, ctm, base_uri, dict, node); + xps_parse_glyphs(doc, ctm, base_uri, dict, node); if (!strcmp(xml_tag(node), "Canvas")) - xps_parse_canvas(ctx, ctm, area, base_uri, dict, node); + xps_parse_canvas(doc, ctm, area, base_uri, dict, node); /* skip unknown tags (like Foo.Resources and similar) */ } void -xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area, +xps_begin_opacity(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, char *opacity_att, xml_element *opacity_mask_tag) { @@ -61,45 +61,45 @@ xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area, { fz_colorspace *colorspace; float samples[32]; - xps_parse_color(ctx, base_uri, scb_color_att, &colorspace, samples); + xps_parse_color(doc, base_uri, scb_color_att, &colorspace, samples); opacity = opacity * samples[0]; } opacity_mask_tag = NULL; } - if (ctx->opacity_top + 1 < nelem(ctx->opacity)) + if (doc->opacity_top + 1 < nelem(doc->opacity)) { - ctx->opacity[ctx->opacity_top + 1] = ctx->opacity[ctx->opacity_top] * opacity; - ctx->opacity_top++; + doc->opacity[doc->opacity_top + 1] = doc->opacity[doc->opacity_top] * opacity; + doc->opacity_top++; } if (opacity_mask_tag) { - fz_begin_mask(ctx->dev, area, 0, NULL, NULL); - xps_parse_brush(ctx, ctm, area, base_uri, dict, opacity_mask_tag); - fz_end_mask(ctx->dev); + fz_begin_mask(doc->dev, area, 0, NULL, NULL); + xps_parse_brush(doc, ctm, area, base_uri, dict, opacity_mask_tag); + fz_end_mask(doc->dev); } } void -xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict, +xps_end_opacity(xps_document *doc, char *base_uri, xps_resource *dict, char *opacity_att, xml_element *opacity_mask_tag) { if (!opacity_att && !opacity_mask_tag) return; - if (ctx->opacity_top > 0) - ctx->opacity_top--; + if (doc->opacity_top > 0) + doc->opacity_top--; if (opacity_mask_tag) { if (strcmp(xml_tag(opacity_mask_tag), "SolidColorBrush")) - fz_pop_clip(ctx->dev); + fz_pop_clip(doc->dev); } } void -xps_parse_render_transform(xps_context *ctx, char *transform, fz_matrix *matrix) +xps_parse_render_transform(xps_document *doc, char *transform, fz_matrix *matrix) { float args[6]; char *s = transform; @@ -124,7 +124,7 @@ xps_parse_render_transform(xps_context *ctx, char *transform, fz_matrix *matrix) } void -xps_parse_matrix_transform(xps_context *ctx, xml_element *root, fz_matrix *matrix) +xps_parse_matrix_transform(xps_document *doc, xml_element *root, fz_matrix *matrix) { char *transform; @@ -134,12 +134,12 @@ xps_parse_matrix_transform(xps_context *ctx, xml_element *root, fz_matrix *matri { transform = xml_att(root, "Matrix"); if (transform) - xps_parse_render_transform(ctx, transform, matrix); + xps_parse_render_transform(doc, transform, matrix); } } void -xps_parse_rectangle(xps_context *ctx, char *text, fz_rect *rect) +xps_parse_rectangle(xps_document *doc, char *text, fz_rect *rect) { float args[4]; char *s = text; @@ -176,7 +176,7 @@ static int count_commas(char *s) } void -xps_parse_color(xps_context *ctx, char *base_uri, char *string, +xps_parse_color(xps_document *doc, char *base_uri, char *string, fz_colorspace **csp, float *samples) { char *p; @@ -230,7 +230,7 @@ xps_parse_color(xps_context *ctx, char *base_uri, char *string, profile = strchr(buf, ' '); if (!profile) { - fz_warn("cannot find icc profile uri in '%s'", string); + fz_warn(doc->ctx, "cannot find icc profile uri in '%s'", string); return; } @@ -238,7 +238,7 @@ xps_parse_color(xps_context *ctx, char *base_uri, char *string, p = strchr(profile, ' '); if (!p) { - fz_warn("cannot find component values in '%s'", profile); + fz_warn(doc->ctx, "cannot find component values in '%s'", profile); return; } @@ -272,11 +272,11 @@ xps_parse_color(xps_context *ctx, char *base_uri, char *string, } void -xps_set_color(xps_context *ctx, fz_colorspace *colorspace, float *samples) +xps_set_color(xps_document *doc, fz_colorspace *colorspace, float *samples) { int i; - ctx->colorspace = colorspace; + doc->colorspace = colorspace; for (i = 0; i < colorspace->n; i++) - ctx->color[i] = samples[i + 1]; - ctx->alpha = samples[0] * ctx->opacity[ctx->opacity_top]; + doc->color[i] = samples[i + 1]; + doc->alpha = samples[0] * doc->opacity[doc->opacity_top]; } diff --git a/xps/xps_doc.c b/xps/xps_doc.c index e0ab7d61..6b6c0c08 100644 --- a/xps/xps_doc.c +++ b/xps/xps_doc.c @@ -21,13 +21,13 @@ xps_rels_for_part(char *buf, char *name, int buflen) */ void -xps_debug_page_list(xps_context *ctx) +xps_debug_page_list(xps_document *doc) { - xps_document *fixdoc = ctx->first_fixdoc; - xps_page *page = ctx->first_page; + xps_fixdoc *fixdoc = doc->first_fixdoc; + xps_page *page = doc->first_page; - if (ctx->start_part) - printf("start part %s\n", ctx->start_part); + if (doc->start_part) + printf("start part %s\n", doc->start_part); while (fixdoc) { @@ -43,135 +43,135 @@ xps_debug_page_list(xps_context *ctx) } static void -xps_add_fixed_document(xps_context *ctx, char *name) +xps_add_fixed_document(xps_document *doc, char *name) { - xps_document *fixdoc; + xps_fixdoc *fixdoc; /* Check for duplicates first */ - for (fixdoc = ctx->first_fixdoc; fixdoc; fixdoc = fixdoc->next) + for (fixdoc = doc->first_fixdoc; fixdoc; fixdoc = fixdoc->next) if (!strcmp(fixdoc->name, name)) return; - fixdoc = fz_malloc(sizeof(xps_document)); - fixdoc->name = fz_strdup(name); + fixdoc = fz_malloc(doc->ctx, sizeof(xps_fixdoc)); + fixdoc->name = fz_strdup(doc->ctx, name); fixdoc->outline = NULL; fixdoc->next = NULL; - if (!ctx->first_fixdoc) + if (!doc->first_fixdoc) { - ctx->first_fixdoc = fixdoc; - ctx->last_fixdoc = fixdoc; + doc->first_fixdoc = fixdoc; + doc->last_fixdoc = fixdoc; } else { - ctx->last_fixdoc->next = fixdoc; - ctx->last_fixdoc = fixdoc; + doc->last_fixdoc->next = fixdoc; + doc->last_fixdoc = fixdoc; } } static void -xps_add_fixed_page(xps_context *ctx, char *name, int width, int height) +xps_add_fixed_page(xps_document *doc, char *name, int width, int height) { xps_page *page; /* Check for duplicates first */ - for (page = ctx->first_page; page; page = page->next) + for (page = doc->first_page; page; page = page->next) if (!strcmp(page->name, name)) return; - page = fz_malloc(sizeof(xps_page)); - page->name = fz_strdup(name); - page->number = ctx->page_count++; + page = fz_malloc(doc->ctx, sizeof(xps_page)); + page->name = fz_strdup(doc->ctx, name); + page->number = doc->page_count++; page->width = width; page->height = height; page->root = NULL; page->next = NULL; - if (!ctx->first_page) + if (!doc->first_page) { - ctx->first_page = page; - ctx->last_page = page; + doc->first_page = page; + doc->last_page = page; } else { - ctx->last_page->next = page; - ctx->last_page = page; + doc->last_page->next = page; + doc->last_page = page; } } static void -xps_add_link_target(xps_context *ctx, char *name) +xps_add_link_target(xps_document *doc, char *name) { - xps_page *page = ctx->last_page; - xps_target *target = fz_malloc(sizeof *target); - target->name = fz_strdup(name); + xps_page *page = doc->last_page; + xps_target *target = fz_malloc(doc->ctx, sizeof *target); + target->name = fz_strdup(doc->ctx, name); target->page = page->number; - target->next = ctx->target; - ctx->target = target; + target->next = doc->target; + doc->target = target; } int -xps_find_link_target(xps_context *ctx, char *target_uri) +xps_find_link_target(xps_document *doc, char *target_uri) { xps_target *target; char *needle = strrchr(target_uri, '#'); needle = needle ? needle + 1 : target_uri; - for (target = ctx->target; target; target = target->next) + for (target = doc->target; target; target = target->next) if (!strcmp(target->name, needle)) return target->page; return 0; } static void -xps_free_link_targets(xps_context *ctx) +xps_free_link_targets(xps_document *doc) { - xps_target *target = ctx->target, *next; + xps_target *target = doc->target, *next; while (target) { next = target->next; - fz_free(target->name); - fz_free(target); + fz_free(doc->ctx, target->name); + fz_free(doc->ctx, target); target = next; } } static void -xps_free_fixed_pages(xps_context *ctx) +xps_free_fixed_pages(xps_document *doc) { - xps_page *page = ctx->first_page; + xps_page *page = doc->first_page; while (page) { xps_page *next = page->next; - xps_free_page(ctx, page); - fz_free(page->name); - fz_free(page); + xps_free_page(doc, page); + fz_free(doc->ctx, page->name); + fz_free(doc->ctx, page); page = next; } - ctx->first_page = NULL; - ctx->last_page = NULL; + doc->first_page = NULL; + doc->last_page = NULL; } static void -xps_free_fixed_documents(xps_context *ctx) +xps_free_fixed_documents(xps_document *doc) { - xps_document *fixdoc = ctx->first_fixdoc; + xps_fixdoc *fixdoc = doc->first_fixdoc; while (fixdoc) { - xps_document *next = fixdoc->next; - fz_free(fixdoc->name); - fz_free(fixdoc); + xps_fixdoc *next = fixdoc->next; + fz_free(doc->ctx, fixdoc->name); + fz_free(doc->ctx, fixdoc); fixdoc = next; } - ctx->first_fixdoc = NULL; - ctx->last_fixdoc = NULL; + doc->first_fixdoc = NULL; + doc->last_fixdoc = NULL; } void -xps_free_page_list(xps_context *ctx) +xps_free_page_list(xps_document *doc) { - xps_free_fixed_documents(ctx); - xps_free_fixed_pages(ctx); - xps_free_link_targets(ctx); + xps_free_fixed_documents(doc); + xps_free_fixed_pages(doc); + xps_free_link_targets(doc); } /* @@ -179,7 +179,7 @@ xps_free_page_list(xps_context *ctx) */ static void -xps_parse_metadata_imp(xps_context *ctx, xml_element *item, xps_document *fixdoc) +xps_parse_metadata_imp(xps_document *doc, xml_element *item, xps_fixdoc *fixdoc) { while (item) { @@ -190,11 +190,11 @@ xps_parse_metadata_imp(xps_context *ctx, xml_element *item, xps_document *fixdoc if (target && type) { char tgtbuf[1024]; - xps_absolute_path(tgtbuf, ctx->base_uri, target, sizeof tgtbuf); + xps_absolute_path(tgtbuf, doc->base_uri, target, sizeof tgtbuf); if (!strcmp(type, REL_START_PART)) - ctx->start_part = fz_strdup(tgtbuf); + doc->start_part = fz_strdup(doc->ctx, tgtbuf); if (!strcmp(type, REL_DOC_STRUCTURE) && fixdoc) - fixdoc->outline = fz_strdup(tgtbuf); + fixdoc->outline = fz_strdup(doc->ctx, tgtbuf); } } @@ -204,8 +204,8 @@ xps_parse_metadata_imp(xps_context *ctx, xml_element *item, xps_document *fixdoc if (source) { char srcbuf[1024]; - xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); - xps_add_fixed_document(ctx, srcbuf); + xps_absolute_path(srcbuf, doc->base_uri, source, sizeof srcbuf); + xps_add_fixed_document(doc, srcbuf); } } @@ -219,8 +219,8 @@ xps_parse_metadata_imp(xps_context *ctx, xml_element *item, xps_document *fixdoc if (source) { char srcbuf[1024]; - xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); - xps_add_fixed_page(ctx, srcbuf, width, height); + xps_absolute_path(srcbuf, doc->base_uri, source, sizeof srcbuf); + xps_add_fixed_page(doc, srcbuf, width, height); } } @@ -228,17 +228,17 @@ xps_parse_metadata_imp(xps_context *ctx, xml_element *item, xps_document *fixdoc { char *name = xml_att(item, "Name"); if (name) - xps_add_link_target(ctx, name); + xps_add_link_target(doc, name); } - xps_parse_metadata_imp(ctx, xml_down(item), fixdoc); + xps_parse_metadata_imp(doc, xml_down(item), fixdoc); item = xml_next(item); } } static int -xps_parse_metadata(xps_context *ctx, xps_part *part, xps_document *fixdoc) +xps_parse_metadata(xps_document *doc, xps_part *part, xps_fixdoc *fixdoc) { xml_element *root; char buf[1024]; @@ -258,110 +258,110 @@ xps_parse_metadata(xps_context *ctx, xps_part *part, xps_document *fixdoc) if (s) *s = 0; - ctx->base_uri = buf; - ctx->part_uri = part->name; + doc->base_uri = buf; + doc->part_uri = part->name; - root = xml_parse_document(part->data, part->size); + root = xml_parse_document(doc->ctx, part->data, part->size); if (!root) - return fz_rethrow(-1, "cannot parse metadata part '%s'", part->name); + return fz_error_note(-1, "cannot parse metadata part '%s'", part->name); - xps_parse_metadata_imp(ctx, root, fixdoc); + xps_parse_metadata_imp(doc, root, fixdoc); - xml_free_element(root); + xml_free_element(doc->ctx, root); - ctx->base_uri = NULL; - ctx->part_uri = NULL; + doc->base_uri = NULL; + doc->part_uri = NULL; return fz_okay; } static int -xps_read_and_process_metadata_part(xps_context *ctx, char *name, xps_document *fixdoc) +xps_read_and_process_metadata_part(xps_document *doc, char *name, xps_fixdoc *fixdoc) { xps_part *part; int code; - part = xps_read_part(ctx, name); + part = xps_read_part(doc, name); if (!part) - return fz_rethrow(-1, "cannot read zip part '%s'", name); + return fz_error_note(-1, "cannot read zip part '%s'", name); - code = xps_parse_metadata(ctx, part, fixdoc); + code = xps_parse_metadata(doc, part, fixdoc); if (code) - return fz_rethrow(code, "cannot process metadata part '%s'", name); + return fz_error_note(code, "cannot process metadata part '%s'", name); - xps_free_part(ctx, part); + xps_free_part(doc, part); return fz_okay; } int -xps_read_page_list(xps_context *ctx) +xps_read_page_list(xps_document *doc) { - xps_document *fixdoc; + xps_fixdoc *fixdoc; int code; - code = xps_read_and_process_metadata_part(ctx, "/_rels/.rels", NULL); + code = xps_read_and_process_metadata_part(doc, "/_rels/.rels", NULL); if (code) - return fz_rethrow(code, "cannot process root relationship part"); + return fz_error_note(code, "cannot process root relationship part"); - if (!ctx->start_part) - return fz_throw("cannot find fixed document sequence start part"); + if (!doc->start_part) + return fz_error_make("cannot find fixed document sequence start part"); - code = xps_read_and_process_metadata_part(ctx, ctx->start_part, NULL); + code = xps_read_and_process_metadata_part(doc, doc->start_part, NULL); if (code) - return fz_rethrow(code, "cannot process FixedDocumentSequence part"); + return fz_error_note(code, "cannot process FixedDocumentSequence part"); - for (fixdoc = ctx->first_fixdoc; fixdoc; fixdoc = fixdoc->next) + for (fixdoc = doc->first_fixdoc; fixdoc; fixdoc = fixdoc->next) { char relbuf[1024]; xps_rels_for_part(relbuf, fixdoc->name, sizeof relbuf); - code = xps_read_and_process_metadata_part(ctx, relbuf, fixdoc); + code = xps_read_and_process_metadata_part(doc, relbuf, fixdoc); if (code) - fz_catch(code, "cannot process FixedDocument rels part"); + fz_error_handle(code, "cannot process FixedDocument rels part"); - code = xps_read_and_process_metadata_part(ctx, fixdoc->name, fixdoc); + code = xps_read_and_process_metadata_part(doc, fixdoc->name, fixdoc); if (code) - return fz_rethrow(code, "cannot process FixedDocument part"); + return fz_error_note(code, "cannot process FixedDocument part"); } return fz_okay; } int -xps_count_pages(xps_context *ctx) +xps_count_pages(xps_document *doc) { - return ctx->page_count; + return doc->page_count; } static int -xps_load_fixed_page(xps_context *ctx, xps_page *page) +xps_load_fixed_page(xps_document *doc, xps_page *page) { xps_part *part; xml_element *root; char *width_att; char *height_att; - part = xps_read_part(ctx, page->name); + part = xps_read_part(doc, page->name); if (!part) - return fz_rethrow(-1, "cannot read zip part '%s'", page->name); + return fz_error_note(-1, "cannot read zip part '%s'", page->name); - root = xml_parse_document(part->data, part->size); + root = xml_parse_document(doc->ctx, part->data, part->size); if (!root) - return fz_rethrow(-1, "cannot parse xml part '%s'", page->name); + return fz_error_note(-1, "cannot parse xml part '%s'", page->name); - xps_free_part(ctx, part); + xps_free_part(doc, part); if (strcmp(xml_tag(root), "FixedPage")) - return fz_throw("expected FixedPage element (found %s)", xml_tag(root)); + return fz_error_make("expected FixedPage element (found %s)", xml_tag(root)); width_att = xml_att(root, "Width"); if (!width_att) - return fz_throw("FixedPage missing required attribute: Width"); + return fz_error_make("FixedPage missing required attribute: Width"); height_att = xml_att(root, "Height"); if (!height_att) - return fz_throw("FixedPage missing required attribute: Height"); + return fz_error_make("FixedPage missing required attribute: Height"); page->width = atoi(width_att); page->height = atoi(height_att); @@ -370,37 +370,35 @@ xps_load_fixed_page(xps_context *ctx, xps_page *page) return 0; } -int -xps_load_page(xps_page **pagep, xps_context *ctx, int number) +xps_page * +xps_load_page(xps_document *doc, int number) { xps_page *page; - int code; int n = 0; - for (page = ctx->first_page; page; page = page->next) + for (page = doc->first_page; page; page = page->next) { if (n == number) { if (!page->root) { - code = xps_load_fixed_page(ctx, page); - if (code) - return fz_rethrow(code, "cannot load page %d", number + 1); + xps_load_fixed_page(doc, page); + /* RJW: "cannot load page %d", number + 1 */ } - *pagep = page; - return fz_okay; + return page; } n ++; } - return fz_throw("cannot find page %d", number + 1); + fz_throw(doc->ctx, "cannot find page %d", number + 1); + return NULL; /* Stupid MSVC */ } void -xps_free_page(xps_context *ctx, xps_page *page) +xps_free_page(xps_document *doc, xps_page *page) { /* only free the XML contents */ if (page->root) - xml_free_element(page->root); + xml_free_element(doc->ctx, page->root); page->root = NULL; } diff --git a/xps/xps_glyphs.c b/xps/xps_glyphs.c index 4b7a8ceb..56e6e4c6 100644 --- a/xps/xps_glyphs.c +++ b/xps/xps_glyphs.c @@ -53,7 +53,7 @@ xps_encode_font_char(fz_font *font, int code) } void -xps_measure_font_glyph(xps_context *ctx, fz_font *font, int gid, xps_glyph_metrics *mtx) +xps_measure_font_glyph(xps_document *doc, fz_font *font, int gid, xps_glyph_metrics *mtx) { int mask = FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING | FT_LOAD_IGNORE_TRANSFORM; FT_Face face = font->ft_face; @@ -69,23 +69,23 @@ xps_measure_font_glyph(xps_context *ctx, fz_font *font, int gid, xps_glyph_metri } static fz_font * -xps_lookup_font(xps_context *ctx, char *name) +xps_lookup_font(xps_document *doc, char *name) { xps_font_cache *cache; - for (cache = ctx->font_table; cache; cache = cache->next) + for (cache = doc->font_table; cache; cache = cache->next) if (!xps_strcasecmp(cache->name, name)) return fz_keep_font(cache->font); return NULL; } static void -xps_insert_font(xps_context *ctx, char *name, fz_font *font) +xps_insert_font(xps_document *doc, char *name, fz_font *font) { - xps_font_cache *cache = fz_malloc(sizeof(xps_font_cache)); - cache->name = fz_strdup(name); + xps_font_cache *cache = fz_malloc(doc->ctx, sizeof(xps_font_cache)); + cache->name = fz_strdup(doc->ctx, name); cache->font = fz_keep_font(font); - cache->next = ctx->font_table; - ctx->font_table = cache; + cache->next = doc->font_table; + doc->font_table = cache; } /* @@ -93,7 +93,7 @@ xps_insert_font(xps_context *ctx, char *name, fz_font *font) * data with the GUID in the fontname. */ static void -xps_deobfuscate_font_resource(xps_context *ctx, xps_part *part) +xps_deobfuscate_font_resource(xps_document *doc, xps_part *part) { byte buf[33]; byte key[16]; @@ -113,7 +113,7 @@ xps_deobfuscate_font_resource(xps_context *ctx, xps_part *part) if (i != 32) { - fz_warn("cannot extract GUID from obfuscated font part name"); + fz_warn(doc->ctx, "cannot extract GUID from obfuscated font part name"); return; } @@ -128,7 +128,7 @@ xps_deobfuscate_font_resource(xps_context *ctx, xps_part *part) } static void -xps_select_best_font_encoding(fz_font *font) +xps_select_best_font_encoding(xps_document *doc, fz_font *font) { static struct { int pid, eid; } xps_cmap_list[] = { @@ -160,7 +160,7 @@ xps_select_best_font_encoding(fz_font *font) } } - fz_warn("cannot find a suitable cmap"); + fz_warn(doc->ctx, "cannot find a suitable cmap"); } /* @@ -251,7 +251,7 @@ xps_parse_glyph_metrics(char *s, float *advance, float *uofs, float *vofs) * Calculate metrics for positioning. */ static fz_text * -xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, +xps_parse_glyphs_imp(xps_document *doc, fz_matrix ctm, fz_font *font, float size, float originx, float originy, int is_sideways, int bidi_level, char *indices, char *unicode) @@ -267,7 +267,7 @@ xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, int un = 0; if (!unicode && !indices) - fz_warn("glyphs element with neither characters nor indices"); + fz_warn(doc->ctx, "glyphs element with neither characters nor indices"); if (us) { @@ -281,7 +281,7 @@ xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, else tm = fz_scale(size, -size); - text = fz_new_text(font, tm, is_sideways); + text = fz_new_text(doc->ctx, font, tm, is_sideways); while ((us && un > 0) || (is && *is)) { @@ -323,7 +323,7 @@ xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, if (glyph_index == -1) glyph_index = xps_encode_font_char(font, char_code); - xps_measure_font_glyph(ctx, font, glyph_index, &mtx); + xps_measure_font_glyph(doc, font, glyph_index, &mtx); if (is_sideways) advance = mtx.vadv * 100; else if (bidi_level & 1) @@ -355,7 +355,7 @@ xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, f = y - v_offset; } - fz_add_text(text, glyph_index, char_code, e, f); + fz_add_text(doc->ctx, text, glyph_index, char_code, e, f); x += advance * 0.01f * size; } @@ -365,11 +365,10 @@ xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, } void -xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, +xps_parse_glyphs(xps_document *doc, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *root) { xml_element *node; - int code; char *fill_uri; char *opacity_mask_uri; @@ -446,17 +445,17 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, fill_uri = base_uri; opacity_mask_uri = base_uri; - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &clip_att, &clip_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &fill_att, &fill_tag, &fill_uri); - xps_resolve_resource_reference(ctx, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); + xps_resolve_resource_reference(doc, dict, &transform_att, &transform_tag, NULL); + xps_resolve_resource_reference(doc, dict, &clip_att, &clip_tag, NULL); + xps_resolve_resource_reference(doc, dict, &fill_att, &fill_tag, &fill_uri); + xps_resolve_resource_reference(doc, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); /* * Check that we have all the necessary information. */ if (!font_size_att || !font_uri_att || !origin_x_att || !origin_y_att) { - fz_warn("missing attributes in glyphs element"); + fz_warn(doc->ctx, "missing attributes in glyphs element"); return; } @@ -481,37 +480,41 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, *subfont = 0; } - font = xps_lookup_font(ctx, partname); + font = xps_lookup_font(doc, partname); if (!font) { - part = xps_read_part(ctx, partname); + part = xps_read_part(doc, partname); if (!part) { - fz_warn("cannot find font resource part '%s'", partname); + fz_warn(doc->ctx, "cannot find font resource part '%s'", partname); return; } /* deobfuscate if necessary */ if (strstr(part->name, ".odttf")) - xps_deobfuscate_font_resource(ctx, part); + xps_deobfuscate_font_resource(doc, part); if (strstr(part->name, ".ODTTF")) - xps_deobfuscate_font_resource(ctx, part); + xps_deobfuscate_font_resource(doc, part); - code = fz_new_font_from_memory(&font, part->data, part->size, subfontid); - if (code) { - fz_catch(code, "cannot load font resource '%s'", partname); - xps_free_part(ctx, part); + fz_try(doc->ctx) + { + font = fz_new_font_from_memory(doc->ctx, part->data, part->size, subfontid); + } + fz_catch(doc->ctx) + { + fz_error_handle(1, "cannot load font resource '%s'", partname); + xps_free_part(doc, part); return; } - xps_select_best_font_encoding(font); + xps_select_best_font_encoding(doc, font); - xps_insert_font(ctx, part->name, font); + xps_insert_font(doc, part->name, font); /* NOTE: we keep part->data in the font */ font->ft_data = part->data; font->ft_size = part->size; - fz_free(part->name); - fz_free(part); + fz_free(doc->ctx, part->name); + fz_free(doc->ctx, part); } /* @@ -522,24 +525,24 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, { fz_matrix transform; if (transform_att) - xps_parse_render_transform(ctx, transform_att, &transform); + xps_parse_render_transform(doc, transform_att, &transform); if (transform_tag) - xps_parse_matrix_transform(ctx, transform_tag, &transform); + xps_parse_matrix_transform(doc, transform_tag, &transform); ctm = fz_concat(transform, ctm); } if (clip_att || clip_tag) - xps_clip(ctx, ctm, dict, clip_att, clip_tag); + xps_clip(doc, ctm, dict, clip_att, clip_tag); font_size = fz_atof(font_size_att); - text = xps_parse_glyphs_imp(ctx, ctm, font, font_size, + text = xps_parse_glyphs_imp(doc, ctm, font, font_size, fz_atof(origin_x_att), fz_atof(origin_y_att), is_sideways, bidi_level, indices_att, unicode_att); area = fz_bound_text(text, ctm); - xps_begin_opacity(ctx, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); + xps_begin_opacity(doc, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); /* If it's a solid color brush fill/stroke do a simple fill */ @@ -555,30 +558,30 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, float samples[32]; fz_colorspace *colorspace; - xps_parse_color(ctx, base_uri, fill_att, &colorspace, samples); + xps_parse_color(doc, base_uri, fill_att, &colorspace, samples); if (fill_opacity_att) samples[0] = fz_atof(fill_opacity_att); - xps_set_color(ctx, colorspace, samples); + xps_set_color(doc, colorspace, samples); - fz_fill_text(ctx->dev, text, ctm, - ctx->colorspace, ctx->color, ctx->alpha); + fz_fill_text(doc->dev, text, ctm, + doc->colorspace, doc->color, doc->alpha); } /* If it's a complex brush, use the charpath as a clip mask */ if (fill_tag) { - fz_clip_text(ctx->dev, text, ctm, 0); - xps_parse_brush(ctx, ctm, area, fill_uri, dict, fill_tag); - fz_pop_clip(ctx->dev); + fz_clip_text(doc->dev, text, ctm, 0); + xps_parse_brush(doc, ctm, area, fill_uri, dict, fill_tag); + fz_pop_clip(doc->dev); } - xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); + xps_end_opacity(doc, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - fz_free_text(text); + fz_free_text(doc->ctx, text); if (clip_att || clip_tag) - fz_pop_clip(ctx->dev); + fz_pop_clip(doc->dev); - fz_drop_font(font); + fz_drop_font(doc->ctx, font); } diff --git a/xps/xps_gradient.c b/xps/xps_gradient.c index f73d33fe..b13d14ef 100644 --- a/xps/xps_gradient.c +++ b/xps/xps_gradient.c @@ -35,7 +35,7 @@ static inline float lerp(float a, float b, float x) } static int -xps_parse_gradient_stops(xps_context *ctx, char *base_uri, xml_element *node, +xps_parse_gradient_stops(xps_document *doc, char *base_uri, xml_element *node, struct stop *stops, int maxcount) { fz_colorspace *colorspace; @@ -59,9 +59,9 @@ xps_parse_gradient_stops(xps_context *ctx, char *base_uri, xml_element *node, { stops[count].offset = fz_atof(offset); - xps_parse_color(ctx, base_uri, color, &colorspace, sample); + xps_parse_color(doc, base_uri, color, &colorspace, sample); - fz_convert_color(colorspace, sample + 1, fz_device_rgb, rgb); + fz_convert_color(doc->ctx, colorspace, sample + 1, fz_device_rgb, rgb); stops[count].r = rgb[0]; stops[count].g = rgb[1]; @@ -76,7 +76,7 @@ xps_parse_gradient_stops(xps_context *ctx, char *base_uri, xml_element *node, if (count == 0) { - fz_warn("gradient brush has no gradient stops"); + fz_warn(doc->ctx, "gradient brush has no gradient stops"); stops[0].offset = 0; stops[0].r = 0; stops[0].g = 0; @@ -91,7 +91,7 @@ xps_parse_gradient_stops(xps_context *ctx, char *base_uri, xml_element *node, } if (count == maxcount) - fz_warn("gradient brush exceeded maximum number of gradient stops"); + fz_warn(doc->ctx, "gradient brush exceeded maximum number of gradient stops"); /* Postprocess to make sure the range of offsets is 0.0 to 1.0 */ @@ -203,7 +203,7 @@ xps_sample_gradient_stops(fz_shade *shade, struct stop *stops, int count) */ static void -xps_draw_one_radial_gradient(xps_context *ctx, fz_matrix ctm, +xps_draw_one_radial_gradient(xps_document *doc, fz_matrix ctm, struct stop *stops, int count, int extend, float x0, float y0, float r0, @@ -212,7 +212,7 @@ xps_draw_one_radial_gradient(xps_context *ctx, fz_matrix ctm, fz_shade *shade; /* TODO: this (and the stuff in pdf_shade) should move to res_shade.c */ - shade = fz_malloc(sizeof(fz_shade)); + shade = fz_malloc(doc->ctx, sizeof(fz_shade)); shade->refs = 1; shade->colorspace = fz_device_rgb; shade->bbox = fz_infinite_rect; @@ -227,7 +227,7 @@ xps_draw_one_radial_gradient(xps_context *ctx, fz_matrix ctm, shade->mesh_len = 6; shade->mesh_cap = 6; - shade->mesh = fz_calloc(shade->mesh_cap, sizeof(float)); + shade->mesh = fz_malloc_array(doc->ctx, shade->mesh_cap, sizeof(float)); shade->mesh[0] = x0; shade->mesh[1] = y0; shade->mesh[2] = r0; @@ -235,9 +235,9 @@ xps_draw_one_radial_gradient(xps_context *ctx, fz_matrix ctm, shade->mesh[4] = y1; shade->mesh[5] = r1; - fz_fill_shade(ctx->dev, shade, ctm, 1); + fz_fill_shade(doc->dev, shade, ctm, 1); - fz_drop_shade(shade); + fz_drop_shade(doc->ctx, shade); } /* @@ -245,7 +245,7 @@ xps_draw_one_radial_gradient(xps_context *ctx, fz_matrix ctm, */ static void -xps_draw_one_linear_gradient(xps_context *ctx, fz_matrix ctm, +xps_draw_one_linear_gradient(xps_document *doc, fz_matrix ctm, struct stop *stops, int count, int extend, float x0, float y0, float x1, float y1) @@ -253,7 +253,7 @@ xps_draw_one_linear_gradient(xps_context *ctx, fz_matrix ctm, fz_shade *shade; /* TODO: this (and the stuff in pdf_shade) should move to res_shade.c */ - shade = fz_malloc(sizeof(fz_shade)); + shade = fz_malloc(doc->ctx, sizeof(fz_shade)); shade->refs = 1; shade->colorspace = fz_device_rgb; shade->bbox = fz_infinite_rect; @@ -268,7 +268,7 @@ xps_draw_one_linear_gradient(xps_context *ctx, fz_matrix ctm, shade->mesh_len = 6; shade->mesh_cap = 6; - shade->mesh = fz_calloc(shade->mesh_cap, sizeof(float)); + shade->mesh = fz_malloc_array(doc->ctx, shade->mesh_cap, sizeof(float)); shade->mesh[0] = x0; shade->mesh[1] = y0; shade->mesh[2] = 0; @@ -276,9 +276,9 @@ xps_draw_one_linear_gradient(xps_context *ctx, fz_matrix ctm, shade->mesh[4] = y1; shade->mesh[5] = 0; - fz_fill_shade(ctx->dev, shade, ctm, 1); + fz_fill_shade(doc->dev, shade, ctm, 1); - fz_drop_shade(shade); + fz_drop_shade(doc->ctx, shade); } /* @@ -297,7 +297,7 @@ static inline float point_inside_circle(float px, float py, float x, float y, fl } static void -xps_draw_radial_gradient(xps_context *ctx, fz_matrix ctm, +xps_draw_radial_gradient(xps_document *doc, fz_matrix ctm, struct stop *stops, int count, xml_element *root, int spread) { @@ -331,7 +331,7 @@ xps_draw_radial_gradient(xps_context *ctx, fz_matrix ctm, r0 = 0; r1 = xrad; - xps_draw_one_radial_gradient(ctx, ctm, stops, count, 1, x0, y0, r0, x1, y1, r1); + xps_draw_one_radial_gradient(doc, ctm, stops, count, 1, x0, y0, r0, x1, y1, r1); } /* @@ -340,7 +340,7 @@ xps_draw_radial_gradient(xps_context *ctx, fz_matrix ctm, */ static void -xps_draw_linear_gradient(xps_context *ctx, fz_matrix ctm, +xps_draw_linear_gradient(xps_document *doc, fz_matrix ctm, struct stop *stops, int count, xml_element *root, int spread) { @@ -357,7 +357,7 @@ xps_draw_linear_gradient(xps_context *ctx, fz_matrix ctm, if (end_point_att) sscanf(end_point_att, "%g,%g", &x1, &y1); - xps_draw_one_linear_gradient(ctx, ctm, stops, count, 1, x0, y0, x1, y1); + xps_draw_one_linear_gradient(doc, ctm, stops, count, 1, x0, y0, x1, y1); } /* @@ -366,9 +366,9 @@ xps_draw_linear_gradient(xps_context *ctx, fz_matrix ctm, */ static void -xps_parse_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, +xps_parse_gradient_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root, - void (*draw)(xps_context *, fz_matrix, struct stop *, int, xml_element *, int)) + void (*draw)(xps_document *, fz_matrix, struct stop *, int, xml_element *, int)) { xml_element *node; @@ -404,7 +404,7 @@ xps_parse_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, stop_tag = xml_down(node); } - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); + xps_resolve_resource_reference(doc, dict, &transform_att, &transform_tag, NULL); spread_method = SPREAD_PAD; if (spread_att) @@ -419,40 +419,40 @@ xps_parse_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, transform = fz_identity; if (transform_att) - xps_parse_render_transform(ctx, transform_att, &transform); + xps_parse_render_transform(doc, transform_att, &transform); if (transform_tag) - xps_parse_matrix_transform(ctx, transform_tag, &transform); + xps_parse_matrix_transform(doc, transform_tag, &transform); ctm = fz_concat(transform, ctm); if (!stop_tag) { - fz_warn("missing gradient stops tag"); + fz_warn(doc->ctx, "missing gradient stops tag"); return; } - stop_count = xps_parse_gradient_stops(ctx, base_uri, stop_tag, stop_list, MAX_STOPS); + stop_count = xps_parse_gradient_stops(doc, base_uri, stop_tag, stop_list, MAX_STOPS); if (stop_count == 0) { - fz_warn("no gradient stops found"); + fz_warn(doc->ctx, "no gradient stops found"); return; } - xps_begin_opacity(ctx, ctm, area, base_uri, dict, opacity_att, NULL); + xps_begin_opacity(doc, ctm, area, base_uri, dict, opacity_att, NULL); - draw(ctx, ctm, stop_list, stop_count, root, spread_method); + draw(doc, ctm, stop_list, stop_count, root, spread_method); - xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL); + xps_end_opacity(doc, base_uri, dict, opacity_att, NULL); } void -xps_parse_linear_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, +xps_parse_linear_gradient_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root) { - xps_parse_gradient_brush(ctx, ctm, area, base_uri, dict, root, xps_draw_linear_gradient); + xps_parse_gradient_brush(doc, ctm, area, base_uri, dict, root, xps_draw_linear_gradient); } void -xps_parse_radial_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, +xps_parse_radial_gradient_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root) { - xps_parse_gradient_brush(ctx, ctm, area, base_uri, dict, root, xps_draw_radial_gradient); + xps_parse_gradient_brush(doc, ctm, area, base_uri, dict, root, xps_draw_radial_gradient); } diff --git a/xps/xps_image.c b/xps/xps_image.c index 4a347435..129637d9 100644 --- a/xps/xps_image.c +++ b/xps/xps_image.c @@ -1,44 +1,41 @@ #include "fitz.h" #include "muxps.h" -static int -xps_decode_image(fz_pixmap **imagep, byte *buf, int len) +static fz_pixmap * +xps_decode_image(fz_context *ctx, byte *buf, int len) { - int error; + fz_pixmap *image; if (len < 8) - return fz_throw("unknown image file format"); + fz_throw(ctx, "unknown image file format"); if (buf[0] == 0xff && buf[1] == 0xd8) { - error = xps_decode_jpeg(imagep, buf, len); - if (error) - return fz_rethrow(error, "cannot decode jpeg image"); + image = xps_decode_jpeg(ctx, buf, len); + /* RJW: "cannot decode jpeg image" */ } else if (memcmp(buf, "\211PNG\r\n\032\n", 8) == 0) { - error = xps_decode_png(imagep, buf, len); - if (error) - return fz_rethrow(error, "cannot decode png image"); + image = xps_decode_png(ctx, buf, len); + /* RJW: "cannot decode png image" */ } else if (memcmp(buf, "II", 2) == 0 && buf[2] == 0xBC) { - return fz_throw("JPEG-XR codec is not available"); + fz_throw(ctx, "JPEG-XR codec is not available"); } else if (memcmp(buf, "MM", 2) == 0 || memcmp(buf, "II", 2) == 0) { - error = xps_decode_tiff(imagep, buf, len); - if (error) - return fz_rethrow(error, "cannot decode TIFF image"); + image = xps_decode_tiff(ctx, buf, len); + /* RJW: "cannot decode TIFF image" */ } else - return fz_throw("unknown image file format"); + fz_throw(ctx, "unknown image file format"); - return fz_okay; + return image; } static void -xps_paint_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, +xps_paint_image_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root, void *vimage) { fz_pixmap *pixmap = vimage; @@ -47,11 +44,11 @@ xps_paint_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_ fz_matrix im = fz_scale(xs, -ys); im.f = ys; ctm = fz_concat(im, ctm); - fz_fill_image(ctx->dev, pixmap, ctm, ctx->opacity[ctx->opacity_top]); + fz_fill_image(doc->dev, pixmap, ctm, doc->opacity[doc->opacity_top]); } static xps_part * -xps_find_image_brush_source_part(xps_context *ctx, char *base_uri, xml_element *root) +xps_find_image_brush_source_part(xps_document *doc, char *base_uri, xml_element *root) { char *image_source_att; char buf[1024]; @@ -97,32 +94,35 @@ xps_find_image_brush_source_part(xps_context *ctx, char *base_uri, xml_element * xps_absolute_path(partname, base_uri, image_name, sizeof partname); - return xps_read_part(ctx, partname); + return xps_read_part(doc, partname); } void -xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, +xps_parse_image_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root) { xps_part *part; fz_pixmap *image; - int code; - part = xps_find_image_brush_source_part(ctx, base_uri, root); + part = xps_find_image_brush_source_part(doc, base_uri, root); if (!part) { - fz_warn("cannot find image source"); + fz_warn(doc->ctx, "cannot find image source"); return; } - code = xps_decode_image(&image, part->data, part->size); - if (code < 0) { - xps_free_part(ctx, part); - fz_catch(-1, "cannot decode image resource"); + fz_try(doc->ctx) + { + image = xps_decode_image(doc->ctx, part->data, part->size); + } + fz_catch(doc->ctx) + { + xps_free_part(doc, part); + fz_error_handle(-1, "cannot decode image resource"); return; } - xps_parse_tiling_brush(ctx, ctm, area, base_uri, dict, root, xps_paint_image_brush, image); + xps_parse_tiling_brush(doc, ctm, area, base_uri, dict, root, xps_paint_image_brush, image); - fz_drop_pixmap(image); - xps_free_part(ctx, part); + fz_drop_pixmap(doc->ctx, image); + xps_free_part(doc, part); } diff --git a/xps/xps_jpeg.c b/xps/xps_jpeg.c index 68bb5eb9..381baffd 100644 --- a/xps/xps_jpeg.c +++ b/xps/xps_jpeg.c @@ -47,8 +47,8 @@ static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) } } -int -xps_decode_jpeg(fz_pixmap **imagep, byte *rbuf, int rlen) +fz_pixmap * +xps_decode_jpeg(fz_context *ctx, byte *rbuf, int rlen) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr_jmp err; @@ -63,8 +63,8 @@ xps_decode_jpeg(fz_pixmap **imagep, byte *rbuf, int rlen) if (setjmp(err.env)) { if (image) - fz_drop_pixmap(image); - return fz_throw("jpeg error: %s", err.msg); + fz_drop_pixmap(ctx, image); + fz_throw(ctx, "jpeg error: %s", err.msg); } cinfo.err = jpeg_std_error(&err.super); @@ -92,14 +92,14 @@ xps_decode_jpeg(fz_pixmap **imagep, byte *rbuf, int rlen) else if (cinfo.output_components == 4) colorspace = fz_device_cmyk; else - return fz_throw("bad number of components in jpeg: %d", cinfo.output_components); + fz_throw(ctx, "bad number of components in jpeg: %d", cinfo.output_components); - image = fz_new_pixmap_with_limit(colorspace, cinfo.output_width, cinfo.output_height); + image = fz_new_pixmap_with_limit(ctx, colorspace, cinfo.output_width, cinfo.output_height); if (!image) { jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); - return fz_throw("out of memory"); + fz_throw(ctx, "out of memory"); } if (cinfo.density_unit == 1) @@ -115,7 +115,7 @@ xps_decode_jpeg(fz_pixmap **imagep, byte *rbuf, int rlen) fz_clear_pixmap(image); - row[0] = fz_malloc(cinfo.output_components * cinfo.output_width); + row[0] = fz_malloc(ctx, cinfo.output_components * cinfo.output_width); dp = image->samples; while (cinfo.output_scanline < cinfo.output_height) { @@ -128,11 +128,10 @@ xps_decode_jpeg(fz_pixmap **imagep, byte *rbuf, int rlen) *dp++ = 255; } } - fz_free(row[0]); + fz_free(ctx, row[0]); jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); - *imagep = image; - return fz_okay; + return image; } diff --git a/xps/xps_outline.c b/xps/xps_outline.c index a4ab6c19..48eb100b 100644 --- a/xps/xps_outline.c +++ b/xps/xps_outline.c @@ -16,7 +16,7 @@ xps_find_last_outline_at_level(fz_outline *node, int level, int target_level) } static fz_outline * -xps_parse_document_outline(xps_context *ctx, xml_element *root) +xps_parse_document_outline(xps_document *doc, xml_element *root) { xml_element *node; fz_outline *head = NULL, *entry, *tail; @@ -31,9 +31,9 @@ xps_parse_document_outline(xps_context *ctx, xml_element *root) if (!target || !description) continue; - entry = fz_malloc(sizeof *entry); - entry->title = fz_strdup(description); - entry->page = xps_find_link_target(ctx, target); + entry = fz_malloc(doc->ctx, sizeof *entry); + entry->title = fz_strdup(doc->ctx, description); + entry->page = xps_find_link_target(doc, target); entry->down = NULL; entry->next = NULL; @@ -59,7 +59,7 @@ xps_parse_document_outline(xps_context *ctx, xml_element *root) } static fz_outline * -xps_parse_document_structure(xps_context *ctx, xml_element *root) +xps_parse_document_structure(xps_document *doc, xml_element *root) { xml_element *node; if (!strcmp(xml_tag(root), "DocumentStructure")) @@ -69,48 +69,48 @@ xps_parse_document_structure(xps_context *ctx, xml_element *root) { node = xml_down(node); if (!strcmp(xml_tag(node), "DocumentOutline")) - return xps_parse_document_outline(ctx, node); + return xps_parse_document_outline(doc, node); } } return NULL; } static fz_outline * -xps_load_document_structure(xps_context *ctx, xps_document *fixdoc) +xps_load_document_structure(xps_document *doc, xps_fixdoc *fixdoc) { xps_part *part; xml_element *root; fz_outline *outline; - part = xps_read_part(ctx, fixdoc->outline); + part = xps_read_part(doc, fixdoc->outline); if (!part) return NULL; - root = xml_parse_document(part->data, part->size); + root = xml_parse_document(doc->ctx, part->data, part->size); if (!root) { - fz_catch(-1, "cannot parse document structure part '%s'", part->name); - xps_free_part(ctx, part); + fz_error_handle(-1, "cannot parse document structure part '%s'", part->name); + xps_free_part(doc, part); return NULL; } - outline = xps_parse_document_structure(ctx, root); + outline = xps_parse_document_structure(doc, root); - xml_free_element(root); - xps_free_part(ctx, part); + xml_free_element(doc->ctx, root); + xps_free_part(doc, part); return outline; } fz_outline * -xps_load_outline(xps_context *ctx) +xps_load_outline(xps_document *doc) { - xps_document *fixdoc; + xps_fixdoc *fixdoc; fz_outline *head = NULL, *tail, *outline; - for (fixdoc = ctx->first_fixdoc; fixdoc; fixdoc = fixdoc->next) { + for (fixdoc = doc->first_fixdoc; fixdoc; fixdoc = fixdoc->next) { if (fixdoc->outline) { - outline = xps_load_document_structure(ctx, fixdoc); + outline = xps_load_document_structure(doc, fixdoc); if (outline) { if (!head) head = outline; diff --git a/xps/xps_path.c b/xps/xps_path.c index 33526262..ead2c7fa 100644 --- a/xps/xps_path.c +++ b/xps/xps_path.c @@ -41,7 +41,7 @@ fz_currentpoint(fz_path *path) * without transforming the line width. */ static void -xps_draw_arc_segment(fz_path *path, fz_matrix mtx, float th0, float th1, int iscw) +xps_draw_arc_segment(fz_context *doc, fz_path *path, fz_matrix mtx, float th0, float th1, int iscw) { float t, d; fz_point p; @@ -56,18 +56,18 @@ xps_draw_arc_segment(fz_path *path, fz_matrix mtx, float th0, float th1, int isc p.x = cosf(th0); p.y = sinf(th0); p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); + fz_lineto(doc, path, p.x, p.y); for (t = th0; t < th1; t += d) { p.x = cosf(t); p.y = sinf(t); p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); + fz_lineto(doc, path, p.x, p.y); } p.x = cosf(th1); p.y = sinf(th1); p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); + fz_lineto(doc, path, p.x, p.y); } else { @@ -75,18 +75,18 @@ xps_draw_arc_segment(fz_path *path, fz_matrix mtx, float th0, float th1, int isc p.x = cosf(th0); p.y = sinf(th0); p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); + fz_lineto(doc, path, p.x, p.y); for (t = th0; t > th1; t -= d) { p.x = cosf(t); p.y = sinf(t); p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); + fz_lineto(doc, path, p.x, p.y); } p.x = cosf(th1); p.y = sinf(th1); p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); + fz_lineto(doc, path, p.x, p.y); } } @@ -107,7 +107,7 @@ angle_between(const fz_point u, const fz_point v) } static void -xps_draw_arc(fz_path *path, +xps_draw_arc(fz_context *doc, fz_path *path, float size_x, float size_y, float rotation_angle, int is_large_arc, int is_clockwise, float point_x, float point_y) @@ -147,7 +147,7 @@ xps_draw_arc(fz_path *path, ry = fabsf(ry); if (rx < 0.001f || ry < 0.001f) { - fz_lineto(path, x2, y2); + fz_lineto(doc, path, x2, y2); return; } @@ -207,9 +207,9 @@ xps_draw_arc(fz_path *path, mtx = fz_concat(fz_translate(cx, cy), mtx); mtx = fz_concat(fz_rotate(rotation_angle), mtx); mtx = fz_concat(fz_scale(rx, ry), mtx); - xps_draw_arc_segment(path, mtx, th1, th1 + dth, is_clockwise); + xps_draw_arc_segment(doc, path, mtx, th1, th1 + dth, is_clockwise); - fz_lineto(path, point_x, point_y); + fz_lineto(doc, path, point_x, point_y); } /* @@ -219,7 +219,7 @@ xps_draw_arc(fz_path *path, */ static fz_path * -xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) +xps_parse_abbreviated_geometry(xps_document *doc, char *geom, int *fill_rule) { fz_path *path; char **args; @@ -232,9 +232,9 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) float smooth_x, smooth_y; /* saved cubic bezier control point for smooth curves */ int reset_smooth; - path = fz_new_path(); + path = fz_new_path(doc->ctx); - args = fz_calloc(strlen(geom) + 1, sizeof(char*)); + args = fz_malloc_array(doc->ctx, strlen(geom) + 1, sizeof(char*)); pargs = args; while (*s) @@ -291,44 +291,44 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) break; case 'M': - fz_moveto(path, fz_atof(args[i]), fz_atof(args[i+1])); + fz_moveto(doc->ctx, path, fz_atof(args[i]), fz_atof(args[i+1])); i += 2; break; case 'm': pt = fz_currentpoint(path); - fz_moveto(path, pt.x + fz_atof(args[i]), pt.y + fz_atof(args[i+1])); + fz_moveto(doc->ctx, path, pt.x + fz_atof(args[i]), pt.y + fz_atof(args[i+1])); i += 2; break; case 'L': - fz_lineto(path, fz_atof(args[i]), fz_atof(args[i+1])); + fz_lineto(doc->ctx, path, fz_atof(args[i]), fz_atof(args[i+1])); i += 2; break; case 'l': pt = fz_currentpoint(path); - fz_lineto(path, pt.x + fz_atof(args[i]), pt.y + fz_atof(args[i+1])); + fz_lineto(doc->ctx, path, pt.x + fz_atof(args[i]), pt.y + fz_atof(args[i+1])); i += 2; break; case 'H': pt = fz_currentpoint(path); - fz_lineto(path, fz_atof(args[i]), pt.y); + fz_lineto(doc->ctx, path, fz_atof(args[i]), pt.y); i += 1; break; case 'h': pt = fz_currentpoint(path); - fz_lineto(path, pt.x + fz_atof(args[i]), pt.y); + fz_lineto(doc->ctx, path, pt.x + fz_atof(args[i]), pt.y); i += 1; break; case 'V': pt = fz_currentpoint(path); - fz_lineto(path, pt.x, fz_atof(args[i])); + fz_lineto(doc->ctx, path, pt.x, fz_atof(args[i])); i += 1; break; case 'v': pt = fz_currentpoint(path); - fz_lineto(path, pt.x, pt.y + fz_atof(args[i])); + fz_lineto(doc->ctx, path, pt.x, pt.y + fz_atof(args[i])); i += 1; break; @@ -339,7 +339,7 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) y2 = fz_atof(args[i+3]); x3 = fz_atof(args[i+4]); y3 = fz_atof(args[i+5]); - fz_curveto(path, x1, y1, x2, y2, x3, y3); + fz_curveto(doc->ctx, path, x1, y1, x2, y2, x3, y3); i += 6; reset_smooth = 0; smooth_x = x3 - x2; @@ -354,7 +354,7 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) y2 = fz_atof(args[i+3]) + pt.y; x3 = fz_atof(args[i+4]) + pt.x; y3 = fz_atof(args[i+5]) + pt.y; - fz_curveto(path, x1, y1, x2, y2, x3, y3); + fz_curveto(doc->ctx, path, x1, y1, x2, y2, x3, y3); i += 6; reset_smooth = 0; smooth_x = x3 - x2; @@ -367,7 +367,7 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) y1 = fz_atof(args[i+1]); x2 = fz_atof(args[i+2]); y2 = fz_atof(args[i+3]); - fz_curveto(path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); + fz_curveto(doc->ctx, path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); i += 4; reset_smooth = 0; smooth_x = x2 - x1; @@ -380,7 +380,7 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) y1 = fz_atof(args[i+1]) + pt.y; x2 = fz_atof(args[i+2]) + pt.x; y2 = fz_atof(args[i+3]) + pt.y; - fz_curveto(path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); + fz_curveto(doc->ctx, path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); i += 4; reset_smooth = 0; smooth_x = x2 - x1; @@ -393,7 +393,7 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) y1 = fz_atof(args[i+1]); x2 = fz_atof(args[i+2]); y2 = fz_atof(args[i+3]); - fz_curveto(path, + fz_curveto(doc->ctx, path, (pt.x + 2 * x1) / 3, (pt.y + 2 * y1) / 3, (x2 + 2 * x1) / 3, (y2 + 2 * y1) / 3, x2, y2); @@ -405,7 +405,7 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) y1 = fz_atof(args[i+1]) + pt.y; x2 = fz_atof(args[i+2]) + pt.x; y2 = fz_atof(args[i+3]) + pt.y; - fz_curveto(path, + fz_curveto(doc->ctx, path, (pt.x + 2 * x1) / 3, (pt.y + 2 * y1) / 3, (x2 + 2 * x1) / 3, (y2 + 2 * y1) / 3, x2, y2); @@ -413,7 +413,7 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) break; case 'A': - xps_draw_arc(path, + xps_draw_arc(doc->ctx, path, fz_atof(args[i+0]), fz_atof(args[i+1]), fz_atof(args[i+2]), atoi(args[i+3]), atoi(args[i+4]), fz_atof(args[i+5]), fz_atof(args[i+6])); @@ -421,7 +421,7 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) break; case 'a': pt = fz_currentpoint(path); - xps_draw_arc(path, + xps_draw_arc(doc->ctx, path, fz_atof(args[i+0]), fz_atof(args[i+1]), fz_atof(args[i+2]), atoi(args[i+3]), atoi(args[i+4]), fz_atof(args[i+5]) + pt.x, fz_atof(args[i+6]) + pt.y); @@ -430,7 +430,7 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) case 'Z': case 'z': - fz_closepath(path); + fz_closepath(doc->ctx, path); break; default: @@ -441,12 +441,12 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) old = cmd; } - fz_free(args); + fz_free(doc->ctx, args); return path; } static void -xps_parse_arc_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) +xps_parse_arc_segment(fz_context *doc, fz_path *path, xml_element *root, int stroking, int *skipped_stroke) { /* ArcSegment pretty much follows the SVG algorithm for converting an * arc in endpoint representation to an arc in centerpoint @@ -468,7 +468,7 @@ xps_parse_arc_segment(fz_path *path, xml_element *root, int stroking, int *skipp if (!point_att || !size_att || !rotation_angle_att || !is_large_arc_att || !sweep_direction_att) { - fz_warn("ArcSegment element is missing attributes"); + fz_warn(doc, "ArcSegment element is missing attributes"); return; } @@ -486,15 +486,15 @@ xps_parse_arc_segment(fz_path *path, xml_element *root, int stroking, int *skipp if (stroking && !is_stroked) { - fz_moveto(path, point_x, point_y); + fz_moveto(doc, path, point_x, point_y); return; } - xps_draw_arc(path, size_x, size_y, rotation_angle, is_large_arc, is_clockwise, point_x, point_y); + xps_draw_arc(doc, path, size_x, size_y, rotation_angle, is_large_arc, is_clockwise, point_x, point_y); } static void -xps_parse_poly_quadratic_bezier_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) +xps_parse_poly_quadratic_bezier_segment(fz_context *doc, fz_path *path, xml_element *root, int stroking, int *skipped_stroke) { char *points_att = xml_att(root, "Points"); char *is_stroked_att = xml_att(root, "IsStroked"); @@ -506,7 +506,7 @@ xps_parse_poly_quadratic_bezier_segment(fz_path *path, xml_element *root, int st if (!points_att) { - fz_warn("PolyQuadraticBezierSegment element has no points"); + fz_warn(doc, "PolyQuadraticBezierSegment element has no points"); return; } @@ -528,12 +528,12 @@ xps_parse_poly_quadratic_bezier_segment(fz_path *path, xml_element *root, int st { if (stroking && !is_stroked) { - fz_moveto(path, x[1], y[1]); + fz_moveto(doc, path, x[1], y[1]); } else { pt = fz_currentpoint(path); - fz_curveto(path, + fz_curveto(doc, path, (pt.x + 2 * x[0]) / 3, (pt.y + 2 * y[0]) / 3, (x[1] + 2 * x[0]) / 3, (y[1] + 2 * y[0]) / 3, x[1], y[1]); @@ -544,7 +544,7 @@ xps_parse_poly_quadratic_bezier_segment(fz_path *path, xml_element *root, int st } static void -xps_parse_poly_bezier_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) +xps_parse_poly_bezier_segment(fz_context *doc, fz_path *path, xml_element *root, int stroking, int *skipped_stroke) { char *points_att = xml_att(root, "Points"); char *is_stroked_att = xml_att(root, "IsStroked"); @@ -555,7 +555,7 @@ xps_parse_poly_bezier_segment(fz_path *path, xml_element *root, int stroking, in if (!points_att) { - fz_warn("PolyBezierSegment element has no points"); + fz_warn(doc, "PolyBezierSegment element has no points"); return; } @@ -576,16 +576,16 @@ xps_parse_poly_bezier_segment(fz_path *path, xml_element *root, int stroking, in if (n == 3) { if (stroking && !is_stroked) - fz_moveto(path, x[2], y[2]); + fz_moveto(doc, path, x[2], y[2]); else - fz_curveto(path, x[0], y[0], x[1], y[1], x[2], y[2]); + fz_curveto(doc, path, x[0], y[0], x[1], y[1], x[2], y[2]); n = 0; } } } static void -xps_parse_poly_line_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) +xps_parse_poly_line_segment(fz_context *doc, fz_path *path, xml_element *root, int stroking, int *skipped_stroke) { char *points_att = xml_att(root, "Points"); char *is_stroked_att = xml_att(root, "IsStroked"); @@ -595,7 +595,7 @@ xps_parse_poly_line_segment(fz_path *path, xml_element *root, int stroking, int if (!points_att) { - fz_warn("PolyLineSegment element has no points"); + fz_warn(doc, "PolyLineSegment element has no points"); return; } @@ -611,15 +611,15 @@ xps_parse_poly_line_segment(fz_path *path, xml_element *root, int stroking, int while (*s == ' ') s++; sscanf(s, "%g,%g", &x, &y); if (stroking && !is_stroked) - fz_moveto(path, x, y); + fz_moveto(doc, path, x, y); else - fz_lineto(path, x, y); + fz_lineto(doc, path, x, y); while (*s != ' ' && *s != 0) s++; } } static void -xps_parse_path_figure(fz_path *path, xml_element *root, int stroking) +xps_parse_path_figure(fz_context *doc, fz_path *path, xml_element *root, int stroking) { xml_element *node; @@ -648,31 +648,31 @@ xps_parse_path_figure(fz_path *path, xml_element *root, int stroking) if (!stroking && !is_filled) /* not filled, when filling */ return; - fz_moveto(path, start_x, start_y); + fz_moveto(doc, path, start_x, start_y); for (node = xml_down(root); node; node = xml_next(node)) { if (!strcmp(xml_tag(node), "ArcSegment")) - xps_parse_arc_segment(path, node, stroking, &skipped_stroke); + xps_parse_arc_segment(doc, path, node, stroking, &skipped_stroke); if (!strcmp(xml_tag(node), "PolyBezierSegment")) - xps_parse_poly_bezier_segment(path, node, stroking, &skipped_stroke); + xps_parse_poly_bezier_segment(doc, path, node, stroking, &skipped_stroke); if (!strcmp(xml_tag(node), "PolyLineSegment")) - xps_parse_poly_line_segment(path, node, stroking, &skipped_stroke); + xps_parse_poly_line_segment(doc, path, node, stroking, &skipped_stroke); if (!strcmp(xml_tag(node), "PolyQuadraticBezierSegment")) - xps_parse_poly_quadratic_bezier_segment(path, node, stroking, &skipped_stroke); + xps_parse_poly_quadratic_bezier_segment(doc, path, node, stroking, &skipped_stroke); } if (is_closed) { if (stroking && skipped_stroke) - fz_lineto(path, start_x, start_y); /* we've skipped using fz_moveto... */ + fz_lineto(doc, path, start_x, start_y); /* we've skipped using fz_moveto... */ else - fz_closepath(path); /* no skipped segments, safe to closepath properly */ + fz_closepath(doc, path); /* no skipped segments, safe to closepath properly */ } } fz_path * -xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xml_element *root, int stroking, int *fill_rule) +xps_parse_path_geometry(xps_document *doc, xps_resource *dict, xml_element *root, int stroking, int *fill_rule) { xml_element *node; @@ -696,8 +696,8 @@ xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xml_element *root, transform_tag = xml_down(node); } - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &figures_att, &figures_tag, NULL); + xps_resolve_resource_reference(doc, dict, &transform_att, &transform_tag, NULL); + xps_resolve_resource_reference(doc, dict, &figures_att, &figures_tag, NULL); if (fill_rule_att) { @@ -709,22 +709,22 @@ xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xml_element *root, transform = fz_identity; if (transform_att) - xps_parse_render_transform(ctx, transform_att, &transform); + xps_parse_render_transform(doc, transform_att, &transform); if (transform_tag) - xps_parse_matrix_transform(ctx, transform_tag, &transform); + xps_parse_matrix_transform(doc, transform_tag, &transform); if (figures_att) - path = xps_parse_abbreviated_geometry(ctx, figures_att, fill_rule); + path = xps_parse_abbreviated_geometry(doc, figures_att, fill_rule); else - path = fz_new_path(); + path = fz_new_path(doc->ctx); if (figures_tag) - xps_parse_path_figure(path, figures_tag, stroking); + xps_parse_path_figure(doc->ctx, path, figures_tag, stroking); for (node = xml_down(root); node; node = xml_next(node)) { if (!strcmp(xml_tag(node), "PathFigure")) - xps_parse_path_figure(path, node, stroking); + xps_parse_path_figure(doc->ctx, path, node, stroking); } if (transform_att || transform_tag) @@ -747,19 +747,19 @@ xps_parse_line_cap(char *attr) } void -xps_clip(xps_context *ctx, fz_matrix ctm, xps_resource *dict, char *clip_att, xml_element *clip_tag) +xps_clip(xps_document *doc, fz_matrix ctm, xps_resource *dict, char *clip_att, xml_element *clip_tag) { fz_path *path; int fill_rule = 0; if (clip_att) - path = xps_parse_abbreviated_geometry(ctx, clip_att, &fill_rule); + path = xps_parse_abbreviated_geometry(doc, clip_att, &fill_rule); else if (clip_tag) - path = xps_parse_path_geometry(ctx, dict, clip_tag, 0, &fill_rule); + path = xps_parse_path_geometry(doc, dict, clip_tag, 0, &fill_rule); else - path = fz_new_path(); - fz_clip_path(ctx->dev, path, NULL, fill_rule == 0, ctm); - fz_free_path(path); + path = fz_new_path(doc->ctx); + fz_clip_path(doc->dev, path, NULL, fill_rule == 0, ctm); + fz_free_path(doc->ctx, path); } /* @@ -768,7 +768,7 @@ xps_clip(xps_context *ctx, fz_matrix ctm, xps_resource *dict, char *clip_att, xm */ void -xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *root) +xps_parse_path(xps_document *doc, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *root) { xml_element *node; @@ -852,12 +852,12 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di stroke_uri = base_uri; opacity_mask_uri = base_uri; - xps_resolve_resource_reference(ctx, dict, &data_att, &data_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &clip_att, &clip_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &fill_att, &fill_tag, &fill_uri); - xps_resolve_resource_reference(ctx, dict, &stroke_att, &stroke_tag, &stroke_uri); - xps_resolve_resource_reference(ctx, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); + xps_resolve_resource_reference(doc, dict, &data_att, &data_tag, NULL); + xps_resolve_resource_reference(doc, dict, &clip_att, &clip_tag, NULL); + xps_resolve_resource_reference(doc, dict, &transform_att, &transform_tag, NULL); + xps_resolve_resource_reference(doc, dict, &fill_att, &fill_tag, &fill_uri); + xps_resolve_resource_reference(doc, dict, &stroke_att, &stroke_tag, &stroke_uri); + xps_resolve_resource_reference(doc, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); /* * Act on the information we have gathered: @@ -921,70 +921,70 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di transform = fz_identity; if (transform_att) - xps_parse_render_transform(ctx, transform_att, &transform); + xps_parse_render_transform(doc, transform_att, &transform); if (transform_tag) - xps_parse_matrix_transform(ctx, transform_tag, &transform); + xps_parse_matrix_transform(doc, transform_tag, &transform); ctm = fz_concat(transform, ctm); if (clip_att || clip_tag) - xps_clip(ctx, ctm, dict, clip_att, clip_tag); + xps_clip(doc, ctm, dict, clip_att, clip_tag); fill_rule = 0; if (data_att) - path = xps_parse_abbreviated_geometry(ctx, data_att, &fill_rule); + path = xps_parse_abbreviated_geometry(doc, data_att, &fill_rule); else if (data_tag) - path = xps_parse_path_geometry(ctx, dict, data_tag, 0, &fill_rule); + path = xps_parse_path_geometry(doc, dict, data_tag, 0, &fill_rule); if (stroke_att || stroke_tag) area = fz_bound_path(path, &stroke, ctm); else area = fz_bound_path(path, NULL, ctm); - xps_begin_opacity(ctx, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); + xps_begin_opacity(doc, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); if (fill_att) { - xps_parse_color(ctx, base_uri, fill_att, &colorspace, samples); + xps_parse_color(doc, base_uri, fill_att, &colorspace, samples); if (fill_opacity_att) samples[0] = fz_atof(fill_opacity_att); - xps_set_color(ctx, colorspace, samples); + xps_set_color(doc, colorspace, samples); - fz_fill_path(ctx->dev, path, fill_rule == 0, ctm, - ctx->colorspace, ctx->color, ctx->alpha); + fz_fill_path(doc->dev, path, fill_rule == 0, ctm, + doc->colorspace, doc->color, doc->alpha); } if (fill_tag) { area = fz_bound_path(path, NULL, ctm); - fz_clip_path(ctx->dev, path, NULL, fill_rule == 0, ctm); - xps_parse_brush(ctx, ctm, area, fill_uri, dict, fill_tag); - fz_pop_clip(ctx->dev); + fz_clip_path(doc->dev, path, NULL, fill_rule == 0, ctm); + xps_parse_brush(doc, ctm, area, fill_uri, dict, fill_tag); + fz_pop_clip(doc->dev); } if (stroke_att) { - xps_parse_color(ctx, base_uri, stroke_att, &colorspace, samples); + xps_parse_color(doc, base_uri, stroke_att, &colorspace, samples); if (stroke_opacity_att) samples[0] = fz_atof(stroke_opacity_att); - xps_set_color(ctx, colorspace, samples); + xps_set_color(doc, colorspace, samples); - fz_stroke_path(ctx->dev, path, &stroke, ctm, - ctx->colorspace, ctx->color, ctx->alpha); + fz_stroke_path(doc->dev, path, &stroke, ctm, + doc->colorspace, doc->color, doc->alpha); } if (stroke_tag) { - fz_clip_stroke_path(ctx->dev, path, NULL, &stroke, ctm); - xps_parse_brush(ctx, ctm, area, stroke_uri, dict, stroke_tag); - fz_pop_clip(ctx->dev); + fz_clip_stroke_path(doc->dev, path, NULL, &stroke, ctm); + xps_parse_brush(doc, ctm, area, stroke_uri, dict, stroke_tag); + fz_pop_clip(doc->dev); } - xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); + xps_end_opacity(doc, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - fz_free_path(path); + fz_free_path(doc->ctx, path); path = NULL; if (clip_att || clip_tag) - fz_pop_clip(ctx->dev); + fz_pop_clip(doc->dev); } diff --git a/xps/xps_png.c b/xps/xps_png.c index 245dd285..d9e952a7 100644 --- a/xps/xps_png.c +++ b/xps/xps_png.c @@ -5,6 +5,7 @@ struct info { + fz_context *ctx; int width, height, depth, n; int interlace, indexed; int size; @@ -61,12 +62,12 @@ static const unsigned char png_signature[8] = static void *zalloc(void *opaque, unsigned int items, unsigned int size) { - return fz_calloc(items, size); + return fz_malloc_array(opaque, items, size); } static void zfree(void *opaque, void *address) { - fz_free(address); + fz_free(opaque, address); } static inline int paeth(int a, int b, int c) @@ -188,7 +189,7 @@ png_deinterlace(struct info *info, int *passw, int *passh, int *passofs) unsigned char *output; int p, x, y, k; - output = fz_calloc(info->height, stride); + output = fz_malloc_array(info->ctx, info->height, stride); for (p = 0; p < 7; p++) { @@ -214,7 +215,7 @@ png_deinterlace(struct info *info, int *passw, int *passh, int *passofs) } } - fz_free(info->samples); + fz_free(info->ctx, info->samples); info->samples = output; } @@ -224,7 +225,7 @@ png_read_ihdr(struct info *info, unsigned char *p, int size) int color, compression, filter; if (size != 13) - return fz_throw("IHDR chunk is the wrong size"); + return fz_error_make("IHDR chunk is the wrong size"); info->width = getint(p + 0); info->height = getint(p + 4); @@ -236,21 +237,21 @@ png_read_ihdr(struct info *info, unsigned char *p, int size) info->interlace = p[12]; if (info->width <= 0) - return fz_throw("image width must be > 0"); + return fz_error_make("image width must be > 0"); if (info->height <= 0) - return fz_throw("image height must be > 0"); + return fz_error_make("image height must be > 0"); if (info->depth != 1 && info->depth != 2 && info->depth != 4 && info->depth != 8 && info->depth != 16) - return fz_throw("image bit depth must be one of 1, 2, 4, 8, 16"); + return fz_error_make("image bit depth must be one of 1, 2, 4, 8, 16"); if (color == 2 && info->depth < 8) - return fz_throw("illegal bit depth for truecolor"); + return fz_error_make("illegal bit depth for truecolor"); if (color == 3 && info->depth > 8) - return fz_throw("illegal bit depth for indexed"); + return fz_error_make("illegal bit depth for indexed"); if (color == 4 && info->depth < 8) - return fz_throw("illegal bit depth for grayscale with alpha"); + return fz_error_make("illegal bit depth for grayscale with alpha"); if (color == 6 && info->depth < 8) - return fz_throw("illegal bit depth for truecolor with alpha"); + return fz_error_make("illegal bit depth for truecolor with alpha"); info->indexed = 0; if (color == 0) /* gray */ @@ -267,14 +268,14 @@ png_read_ihdr(struct info *info, unsigned char *p, int size) info->n = 1; } else - return fz_throw("unknown color type"); + return fz_error_make("unknown color type"); if (compression != 0) - return fz_throw("unknown compression method"); + return fz_error_make("unknown compression method"); if (filter != 0) - return fz_throw("unknown filter method"); + return fz_error_make("unknown filter method"); if (info->interlace != 0 && info->interlace != 1) - return fz_throw("interlace method not supported"); + return fz_error_make("interlace method not supported"); return fz_okay; } @@ -286,7 +287,7 @@ png_read_plte(struct info *info, unsigned char *p, int size) int i; if (n > 256 || n > (1 << info->depth)) - return fz_throw("too many samples in palette"); + return fz_error_make("too many samples in palette"); for (i = 0; i < n; i++) { @@ -308,14 +309,14 @@ png_read_trns(struct info *info, unsigned char *p, int size) if (info->indexed) { if (size > 256 || size > (1 << info->depth)) - return fz_throw("too many samples in transparency table"); + return fz_error_make("too many samples in transparency table"); for (i = 0; i < size; i++) info->palette[i * 4 + 3] = p[i]; } else { if (size != info->n * 2) - return fz_throw("tRNS chunk is the wrong size"); + return fz_error_make("tRNS chunk is the wrong size"); for (i = 0; i < info->n; i++) info->trns[i] = (p[i * 2] << 8 | p[i * 2 + 1]) & ((1 << info->depth) - 1); } @@ -333,12 +334,12 @@ png_read_idat(struct info *info, unsigned char *p, int size, z_stream *stm) code = inflate(stm, Z_SYNC_FLUSH); if (code != Z_OK && code != Z_STREAM_END) - return fz_throw("zlib error: %s", stm->msg); + return fz_error_make("zlib error: %s", stm->msg); if (stm->avail_in != 0) { if (stm->avail_out == 0) - return fz_throw("ran out of output before input"); - return fz_throw("inflate did not consume buffer (%d remaining)", stm->avail_in); + return fz_error_make("ran out of output before input"); + return fz_error_make("inflate did not consume buffer (%d remaining)", stm->avail_in); } return fz_okay; @@ -348,7 +349,7 @@ static int png_read_phys(struct info *info, unsigned char *p, int size) { if (size != 9) - return fz_throw("pHYs chunk is the wrong size"); + return fz_error_make("pHYs chunk is the wrong size"); if (p[8] == 1) { info->xres = getint(p) * 254 / 10000; @@ -372,7 +373,7 @@ png_read_image(struct info *info, unsigned char *p, int total) /* Read signature */ if (total < 8 + 12 || memcmp(p, png_signature, 8)) - return fz_throw("not a png image (wrong signature)"); + return fz_error_make("not a png image (wrong signature)"); p += 8; total -= 8; @@ -382,16 +383,16 @@ png_read_image(struct info *info, unsigned char *p, int total) size = getint(p); if (size + 12 > total) - return fz_throw("premature end of data in png image"); + return fz_error_make("premature end of data in png image"); if (!memcmp(p + 4, "IHDR", 4)) { code = png_read_ihdr(info, p + 8, size); if (code) - return fz_rethrow(code, "cannot read png header"); + return fz_error_note(code, "cannot read png header"); } else - return fz_throw("png file must start with IHDR chunk"); + return fz_error_make("png file must start with IHDR chunk"); p += size + 12; total -= size + 12; @@ -408,18 +409,18 @@ png_read_image(struct info *info, unsigned char *p, int total) info->size = passofs[7]; } - info->samples = fz_malloc(info->size); + info->samples = fz_malloc(info->ctx, info->size); stm.zalloc = zalloc; stm.zfree = zfree; - stm.opaque = NULL; + stm.opaque = info->ctx; stm.next_out = info->samples; stm.avail_out = info->size; code = inflateInit(&stm); if (code != Z_OK) - return fz_throw("zlib error: %s", stm.msg); + return fz_error_make("zlib error: %s", stm.msg); /* Read remaining chunks until IEND */ @@ -428,34 +429,34 @@ png_read_image(struct info *info, unsigned char *p, int total) size = getint(p); if (size + 12 > total) - return fz_throw("premature end of data in png image"); + return fz_error_make("premature end of data in png image"); if (!memcmp(p + 4, "PLTE", 4)) { code = png_read_plte(info, p + 8, size); if (code) - return fz_rethrow(code, "cannot read png palette"); + return fz_error_note(code, "cannot read png palette"); } if (!memcmp(p + 4, "tRNS", 4)) { code = png_read_trns(info, p + 8, size); if (code) - return fz_rethrow(code, "cannot read png transparency"); + return fz_error_note(code, "cannot read png transparency"); } if (!memcmp(p + 4, "pHYs", 4)) { code = png_read_phys(info, p + 8, size); if (code) - return fz_rethrow(code, "cannot read png resolution"); + return fz_error_note(code, "cannot read png resolution"); } if (!memcmp(p + 4, "IDAT", 4)) { code = png_read_idat(info, p + 8, size, &stm); if (code) - return fz_rethrow(code, "cannot read png image data"); + return fz_error_note(code, "cannot read png image data"); } if (!memcmp(p + 4, "IEND", 4)) @@ -467,7 +468,7 @@ png_read_image(struct info *info, unsigned char *p, int total) code = inflateEnd(&stm); if (code != Z_OK) - return fz_throw("zlib error: %s", stm.msg); + return fz_error_make("zlib error: %s", stm.msg); /* Apply prediction filter and deinterlacing */ @@ -480,9 +481,9 @@ png_read_image(struct info *info, unsigned char *p, int total) } static fz_pixmap * -png_expand_palette(struct info *info, fz_pixmap *src) +png_expand_palette(fz_context *ctx, struct info *info, fz_pixmap *src) { - fz_pixmap *dst = fz_new_pixmap(fz_device_rgb, src->w, src->h); + fz_pixmap *dst = fz_new_pixmap(ctx, fz_device_rgb, src->w, src->h); unsigned char *sp = src->samples; unsigned char *dp = dst->samples; int x, y; @@ -503,7 +504,7 @@ png_expand_palette(struct info *info, fz_pixmap *src) } } - fz_drop_pixmap(src); + fz_drop_pixmap(info->ctx, src); return dst; } @@ -531,18 +532,23 @@ png_mask_transparency(struct info *info, fz_pixmap *dst) } } -int -xps_decode_png(fz_pixmap **imagep, byte *p, int total) +fz_pixmap * +xps_decode_png(fz_context *ctx, byte *p, int total) { fz_pixmap *image; fz_colorspace *colorspace; struct info png; - int code; int stride; - code = png_read_image(&png, p, total); - if (code) - return fz_rethrow(code, "cannot read png image"); + png.ctx = ctx; + fz_try(ctx) + { + png_read_image(&png, p, total); + } + fz_catch(ctx) + { + fz_throw(ctx, "cannot read png image"); + } if (png.n == 3 || png.n == 4) colorspace = fz_device_rgb; @@ -551,11 +557,11 @@ xps_decode_png(fz_pixmap **imagep, byte *p, int total) stride = (png.width * png.n * png.depth + 7) / 8; - image = fz_new_pixmap_with_limit(colorspace, png.width, png.height); + image = fz_new_pixmap_with_limit(ctx, colorspace, png.width, png.height); if (!image) { - fz_free(png.samples); - return fz_throw("out of memory"); + fz_free(png.ctx, png.samples); + fz_throw(ctx, "out of memory"); } image->xres = png.xres; @@ -564,15 +570,14 @@ xps_decode_png(fz_pixmap **imagep, byte *p, int total) fz_unpack_tile(image, png.samples, png.n, png.depth, stride, png.indexed); if (png.indexed) - image = png_expand_palette(&png, image); + image = png_expand_palette(ctx, &png, image); else if (png.transparency) png_mask_transparency(&png, image); if (png.transparency || png.n == 2 || png.n == 4) fz_premultiply_pixmap(image); - fz_free(png.samples); + fz_free(png.ctx, png.samples); - *imagep = image; - return fz_okay; + return image; } diff --git a/xps/xps_resource.c b/xps/xps_resource.c index c96f3619..4a084b29 100644 --- a/xps/xps_resource.c +++ b/xps/xps_resource.c @@ -2,7 +2,7 @@ #include "muxps.h" static xml_element * -xps_find_resource(xps_context *ctx, xps_resource *dict, char *name, char **urip) +xps_find_resource(xps_document *doc, xps_resource *dict, char *name, char **urip) { xps_resource *head, *node; for (head = dict; head; head = head->parent) @@ -21,7 +21,7 @@ xps_find_resource(xps_context *ctx, xps_resource *dict, char *name, char **urip) } static xml_element * -xps_parse_resource_reference(xps_context *ctx, xps_resource *dict, char *att, char **urip) +xps_parse_resource_reference(xps_document *doc, xps_resource *dict, char *att, char **urip) { char name[1024]; char *s; @@ -34,16 +34,16 @@ xps_parse_resource_reference(xps_context *ctx, xps_resource *dict, char *att, ch if (s) *s = 0; - return xps_find_resource(ctx, dict, name, urip); + return xps_find_resource(doc, dict, name, urip); } void -xps_resolve_resource_reference(xps_context *ctx, xps_resource *dict, +xps_resolve_resource_reference(xps_document *doc, xps_resource *dict, char **attp, xml_element **tagp, char **urip) { if (*attp) { - xml_element *rsrc = xps_parse_resource_reference(ctx, dict, *attp, urip); + xml_element *rsrc = xps_parse_resource_reference(doc, dict, *attp, urip); if (rsrc) { *attp = NULL; @@ -53,7 +53,7 @@ xps_resolve_resource_reference(xps_context *ctx, xps_resource *dict, } static int -xps_parse_remote_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, char *source_att) +xps_parse_remote_resource_dictionary(xps_document *doc, xps_resource **dictp, char *base_uri, char *source_att) { char part_name[1024]; char part_uri[1024]; @@ -65,24 +65,24 @@ xps_parse_remote_resource_dictionary(xps_context *ctx, xps_resource **dictp, cha /* External resource dictionaries MUST NOT reference other resource dictionaries */ xps_absolute_path(part_name, base_uri, source_att, sizeof part_name); - part = xps_read_part(ctx, part_name); + part = xps_read_part(doc, part_name); if (!part) { - return fz_throw("cannot find remote resource part '%s'", part_name); + return fz_error_make("cannot find remote resource part '%s'", part_name); } - xml = xml_parse_document(part->data, part->size); + xml = xml_parse_document(doc->ctx, part->data, part->size); if (!xml) { - xps_free_part(ctx, part); - return fz_rethrow(-1, "cannot parse xml"); + xps_free_part(doc, part); + return fz_error_note(-1, "cannot parse xml"); } if (strcmp(xml_tag(xml), "ResourceDictionary")) { - xml_free_element(xml); - xps_free_part(ctx, part); - return fz_throw("expected ResourceDictionary element (found %s)", xml_tag(xml)); + xml_free_element(doc->ctx, xml); + xps_free_part(doc, part); + return fz_error_make("expected ResourceDictionary element (found %s)", xml_tag(xml)); } fz_strlcpy(part_uri, part_name, sizeof part_uri); @@ -90,24 +90,24 @@ xps_parse_remote_resource_dictionary(xps_context *ctx, xps_resource **dictp, cha if (s) s[1] = 0; - code = xps_parse_resource_dictionary(ctx, &dict, part_uri, xml); + code = xps_parse_resource_dictionary(doc, &dict, part_uri, xml); if (code) { - xml_free_element(xml); - xps_free_part(ctx, part); - return fz_rethrow(code, "cannot parse remote resource dictionary: %s", part_uri); + xml_free_element(doc->ctx, xml); + xps_free_part(doc, part); + return fz_error_note(code, "cannot parse remote resource dictionary: %s", part_uri); } dict->base_xml = xml; /* pass on ownership */ - xps_free_part(ctx, part); + xps_free_part(doc, part); *dictp = dict; return fz_okay; } int -xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, xml_element *root) +xps_parse_resource_dictionary(xps_document *doc, xps_resource **dictp, char *base_uri, xml_element *root) { xps_resource *head; xps_resource *entry; @@ -119,9 +119,9 @@ xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base source = xml_att(root, "Source"); if (source) { - code = xps_parse_remote_resource_dictionary(ctx, dictp, base_uri, source); + code = xps_parse_remote_resource_dictionary(doc, dictp, base_uri, source); if (code) - return fz_rethrow(code, "cannot parse remote resource dictionary"); + return fz_error_note(code, "cannot parse remote resource dictionary"); return fz_okay; } @@ -132,7 +132,7 @@ xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base key = xml_att(node, "x:Key"); if (key) { - entry = fz_malloc(sizeof(xps_resource)); + entry = fz_malloc(doc->ctx, sizeof(xps_resource)); entry->name = key; entry->base_uri = NULL; entry->base_xml = NULL; @@ -144,26 +144,26 @@ xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base } if (head) - head->base_uri = fz_strdup(base_uri); + head->base_uri = fz_strdup(doc->ctx, base_uri); else - return fz_throw("empty resource dictionary"); + return fz_error_make("empty resource dictionary"); *dictp = head; return fz_okay; } void -xps_free_resource_dictionary(xps_context *ctx, xps_resource *dict) +xps_free_resource_dictionary(xps_document *doc, xps_resource *dict) { xps_resource *next; while (dict) { next = dict->next; if (dict->base_xml) - xml_free_element(dict->base_xml); + xml_free_element(doc->ctx, dict->base_xml); if (dict->base_uri) - fz_free(dict->base_uri); - fz_free(dict); + fz_free(doc->ctx, dict->base_uri); + fz_free(doc->ctx, dict); dict = next; } } diff --git a/xps/xps_tiff.c b/xps/xps_tiff.c index 8c58b4d1..b9571465 100644 --- a/xps/xps_tiff.c +++ b/xps/xps_tiff.c @@ -56,6 +56,7 @@ struct tiff fz_colorspace *colorspace; byte *samples; int stride; + fz_context *ctx; }; enum @@ -139,7 +140,7 @@ xps_decode_tiff_uncompressed(struct tiff *tiff, fz_stream *stm, byte *wp, int wl int n = fz_read(stm, wp, wlen); fz_close(stm); if (n < 0) - return fz_rethrow(n, "cannot read uncompressed strip"); + return fz_error_note(n, "cannot read uncompressed strip"); return fz_okay; } @@ -150,7 +151,7 @@ xps_decode_tiff_packbits(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen int n = fz_read(stm, wp, wlen); fz_close(stm); if (n < 0) - return fz_rethrow(n, "cannot read packbits strip"); + return fz_error_note(n, "cannot read packbits strip"); return fz_okay; } @@ -161,7 +162,7 @@ xps_decode_tiff_lzw(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen) int n = fz_read(stm, wp, wlen); fz_close(stm); if (n < 0) - return fz_rethrow(n, "cannot read lzw strip"); + return fz_error_note(n, "cannot read lzw strip"); return fz_okay; } static int @@ -171,7 +172,7 @@ xps_decode_tiff_flate(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen) int n = fz_read(stm, wp, wlen); fz_close(stm); if (n < 0) - return fz_rethrow(n, "cannot read flate strip"); + return fz_error_note(n, "cannot read flate strip"); return fz_okay; } @@ -182,14 +183,15 @@ xps_decode_tiff_fax(struct tiff *tiff, int comp, fz_stream *chain, byte *wp, int fz_obj *params; fz_obj *columns, *rows, *black_is_1, *k, *encoded_byte_align; int n; + fz_context *ctx = tiff->ctx; - columns = fz_new_int(tiff->imagewidth); - rows = fz_new_int(tiff->imagelength); - black_is_1 = fz_new_bool(tiff->photometric == 0); - k = fz_new_int(comp == 4 ? -1 : 0); - encoded_byte_align = fz_new_bool(comp == 2); + columns = fz_new_int(ctx, tiff->imagewidth); + rows = fz_new_int(ctx, tiff->imagelength); + black_is_1 = fz_new_bool(ctx, tiff->photometric == 0); + k = fz_new_int(ctx, comp == 4 ? -1 : 0); + encoded_byte_align = fz_new_bool(ctx, comp == 2); - params = fz_new_dict(5); + params = fz_new_dict(ctx, 5); fz_dict_puts(params, "Columns", columns); fz_dict_puts(params, "Rows", rows); fz_dict_puts(params, "BlackIs1", black_is_1); @@ -208,7 +210,7 @@ xps_decode_tiff_fax(struct tiff *tiff, int comp, fz_stream *chain, byte *wp, int fz_drop_obj(params); if (n < 0) - return fz_rethrow(n, "cannot read fax strip"); + return fz_error_note(n, "cannot read fax strip"); return fz_okay; } @@ -219,7 +221,7 @@ xps_decode_tiff_jpeg(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen) int n = fz_read(stm, wp, wlen); fz_close(stm); if (n < 0) - return fz_rethrow(n, "cannot read jpeg strip"); + return fz_error_note(n, "cannot read jpeg strip"); return fz_okay; } @@ -311,14 +313,14 @@ xps_expand_tiff_colormap(struct tiff *tiff) /* image can be with or without extrasamples: comps is 1 or 2 */ if (tiff->samplesperpixel != 1 && tiff->samplesperpixel != 2) - return fz_throw("invalid number of samples for RGBPal"); + return fz_error_make("invalid number of samples for RGBPal"); if (tiff->bitspersample != 4 && tiff->bitspersample != 8) - return fz_throw("invalid number of bits for RGBPal"); + return fz_error_make("invalid number of bits for RGBPal"); stride = tiff->imagewidth * (tiff->samplesperpixel + 2); - samples = fz_malloc(stride * tiff->imagelength); + samples = fz_malloc(tiff->ctx, stride * tiff->imagelength); for (y = 0; y < tiff->imagelength; y++) { @@ -374,10 +376,10 @@ xps_decode_tiff_strips(struct tiff *tiff) unsigned i; if (!tiff->rowsperstrip || !tiff->stripoffsets || !tiff->rowsperstrip) - return fz_throw("no image data in tiff; maybe it is tiled"); + return fz_error_make("no image data in tiff; maybe it is tiled"); if (tiff->planar != 1) - return fz_throw("image data is not in chunky format"); + return fz_error_make("image data is not in chunky format"); tiff->stride = (tiff->imagewidth * tiff->samplesperpixel * tiff->bitspersample + 7) / 8; @@ -403,7 +405,7 @@ xps_decode_tiff_strips(struct tiff *tiff) tiff->colorspace = fz_device_rgb; break; default: - return fz_throw("unknown photometric: %d", tiff->photometric); + return fz_error_make("unknown photometric: %d", tiff->photometric); } switch (tiff->resolutionunit) @@ -428,7 +430,7 @@ xps_decode_tiff_strips(struct tiff *tiff) tiff->yresolution = 96; } - tiff->samples = fz_calloc(tiff->imagelength, tiff->stride); + tiff->samples = fz_malloc_array(tiff->ctx, tiff->imagelength, tiff->stride); memset(tiff->samples, 0x55, tiff->imagelength * tiff->stride); wp = tiff->samples; @@ -444,7 +446,7 @@ xps_decode_tiff_strips(struct tiff *tiff) wlen = tiff->samples + tiff->stride * tiff->imagelength - wp; if (rp + rlen > tiff->ep) - return fz_throw("strip extends beyond the end of the file"); + return fz_error_make("strip extends beyond the end of the file"); /* the bits are in un-natural order */ if (tiff->fillorder == 2) @@ -452,7 +454,7 @@ xps_decode_tiff_strips(struct tiff *tiff) rp[i] = bitrev[rp[i]]; /* the strip decoders will close this */ - stm = fz_open_memory(rp, rlen); + stm = fz_open_memory(tiff->ctx, rp, rlen); switch (tiff->compression) { @@ -472,7 +474,7 @@ xps_decode_tiff_strips(struct tiff *tiff) error = xps_decode_tiff_lzw(tiff, stm, wp, wlen); break; case 6: - error = fz_throw("deprecated JPEG in TIFF compression not supported"); + error = fz_error_make("deprecated JPEG in TIFF compression not supported"); break; case 7: error = xps_decode_tiff_jpeg(tiff, stm, wp, wlen); @@ -484,11 +486,11 @@ xps_decode_tiff_strips(struct tiff *tiff) error = xps_decode_tiff_packbits(tiff, stm, wp, wlen); break; default: - error = fz_throw("unknown TIFF compression: %d", tiff->compression); + error = fz_error_make("unknown TIFF compression: %d", tiff->compression); } if (error) - return fz_rethrow(error, "cannot decode strip %d", row / tiff->rowsperstrip); + return fz_error_note(error, "cannot decode strip %d", row / tiff->rowsperstrip); /* scramble the bits back into original order */ if (tiff->fillorder == 2) @@ -515,7 +517,7 @@ xps_decode_tiff_strips(struct tiff *tiff) { error = xps_expand_tiff_colormap(tiff); if (error) - return fz_rethrow(error, "cannot expand colormap"); + return fz_error_note(error, "cannot expand colormap"); } /* WhiteIsZero .. invert */ @@ -673,7 +675,7 @@ xps_read_tiff_tag(struct tiff *tiff, unsigned offset) break; case ICCProfile: - tiff->profile = fz_malloc(count); + tiff->profile = fz_malloc(tiff->ctx, count); /* ICC profile data type is set to UNDEFINED. * TBYTE reading not correct in xps_read_tiff_tag_value */ xps_read_tiff_bytes(tiff->profile, tiff, value, count); @@ -681,23 +683,23 @@ xps_read_tiff_tag(struct tiff *tiff, unsigned offset) break; case JPEGTables: - fz_warn("jpeg tables in tiff not implemented"); + fz_warn(tiff->ctx, "jpeg tables in tiff not implemented"); tiff->jpegtables = tiff->bp + value; tiff->jpegtableslen = count; break; case StripOffsets: - tiff->stripoffsets = fz_calloc(count, sizeof(unsigned)); + tiff->stripoffsets = fz_malloc_array(tiff->ctx, count, sizeof(unsigned)); xps_read_tiff_tag_value(tiff->stripoffsets, tiff, type, value, count); break; case StripByteCounts: - tiff->stripbytecounts = fz_calloc(count, sizeof(unsigned)); + tiff->stripbytecounts = fz_malloc_array(tiff->ctx, count, sizeof(unsigned)); xps_read_tiff_tag_value(tiff->stripbytecounts, tiff, type, value, count); break; case ColorMap: - tiff->colormap = fz_calloc(count, sizeof(unsigned)); + tiff->colormap = fz_malloc_array(tiff->ctx, count, sizeof(unsigned)); xps_read_tiff_tag_value(tiff->colormap, tiff, type, value, count); break; @@ -705,7 +707,7 @@ xps_read_tiff_tag(struct tiff *tiff, unsigned offset) case TileLength: case TileOffsets: case TileByteCounts: - return fz_throw("tiled tiffs not supported"); + return fz_error_make("tiled tiffs not supported"); default: /* printf("unknown tag: %d t=%d n=%d\n", tag, type, count); */ @@ -763,12 +765,12 @@ xps_decode_tiff_header(struct tiff *tiff, byte *buf, int len) tiff->order = TII; tiff->order = readshort(tiff); if (tiff->order != TII && tiff->order != TMM) - return fz_throw("not a TIFF file, wrong magic marker"); + return fz_error_make("not a TIFF file, wrong magic marker"); /* check version */ version = readshort(tiff); if (version != 42) - return fz_throw("not a TIFF file, wrong version marker"); + return fz_error_make("not a TIFF file, wrong version marker"); /* get offset of IFD */ offset = readlong(tiff); @@ -786,32 +788,30 @@ xps_decode_tiff_header(struct tiff *tiff, byte *buf, int len) { error = xps_read_tiff_tag(tiff, offset); if (error) - return fz_rethrow(error, "cannot read TIFF header tag"); + return fz_error_note(error, "cannot read TIFF header tag"); offset += 12; } return fz_okay; } -int -xps_decode_tiff(fz_pixmap **imagep, byte *buf, int len) +fz_pixmap * +xps_decode_tiff(fz_context *ctx, byte *buf, int len) { - int error; fz_pixmap *image; struct tiff tiff; - error = xps_decode_tiff_header(&tiff, buf, len); - if (error) - return fz_rethrow(error, "cannot decode tiff header"); + tiff.ctx = ctx; + xps_decode_tiff_header(&tiff, buf, len); + /* RJW: "cannot decode tiff header" */ /* Decode the image strips */ if (tiff.rowsperstrip > tiff.imagelength) tiff.rowsperstrip = tiff.imagelength; - error = xps_decode_tiff_strips(&tiff); - if (error) - return fz_rethrow(error, "cannot decode image data"); + xps_decode_tiff_strips(&tiff); + /* RJW: "cannot decode image data" */ /* Byte swap 16-bit images to big endian if necessary */ if (tiff.bitspersample == 16) @@ -822,14 +822,14 @@ xps_decode_tiff(fz_pixmap **imagep, byte *buf, int len) /* Expand into fz_pixmap struct */ - image = fz_new_pixmap_with_limit(tiff.colorspace, tiff.imagewidth, tiff.imagelength); + image = fz_new_pixmap_with_limit(tiff.ctx, tiff.colorspace, tiff.imagewidth, tiff.imagelength); if (!image) { - if (tiff.colormap) fz_free(tiff.colormap); - if (tiff.stripoffsets) fz_free(tiff.stripoffsets); - if (tiff.stripbytecounts) fz_free(tiff.stripbytecounts); - if (tiff.samples) fz_free(tiff.samples); - return fz_throw("out of memory"); + if (tiff.colormap) fz_free(ctx, tiff.colormap); + if (tiff.stripoffsets) fz_free(ctx, tiff.stripoffsets); + if (tiff.stripbytecounts) fz_free(ctx, tiff.stripbytecounts); + if (tiff.samples) fz_free(ctx, tiff.samples); + fz_throw(ctx, "out of memory"); } image->xres = tiff.xresolution; @@ -843,11 +843,11 @@ xps_decode_tiff(fz_pixmap **imagep, byte *buf, int len) /* CMYK is a subtractive colorspace, we want additive for premul alpha */ if (image->n == 5) { - fz_pixmap *rgb = fz_new_pixmap(fz_device_rgb, image->w, image->h); - fz_convert_pixmap(image, rgb); + fz_pixmap *rgb = fz_new_pixmap(tiff.ctx, fz_device_rgb, image->w, image->h); + fz_convert_pixmap(tiff.ctx, image, rgb); rgb->xres = image->xres; rgb->yres = image->yres; - fz_drop_pixmap(image); + fz_drop_pixmap(ctx, image); image = rgb; } fz_premultiply_pixmap(image); @@ -855,11 +855,10 @@ xps_decode_tiff(fz_pixmap **imagep, byte *buf, int len) /* Clean up scratch memory */ - if (tiff.colormap) fz_free(tiff.colormap); - if (tiff.stripoffsets) fz_free(tiff.stripoffsets); - if (tiff.stripbytecounts) fz_free(tiff.stripbytecounts); - if (tiff.samples) fz_free(tiff.samples); + if (tiff.colormap) fz_free(ctx, tiff.colormap); + if (tiff.stripoffsets) fz_free(ctx, tiff.stripoffsets); + if (tiff.stripbytecounts) fz_free(ctx, tiff.stripbytecounts); + if (tiff.samples) fz_free(ctx, tiff.samples); - *imagep = image; - return fz_okay; + return image; } diff --git a/xps/xps_tile.c b/xps/xps_tile.c index d67a9b24..f6a2143f 100644 --- a/xps/xps_tile.c +++ b/xps/xps_tile.c @@ -16,57 +16,57 @@ struct closure xps_resource *dict; xml_element *root; void *user; - void (*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*); + void (*func)(xps_document*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*); }; static void -xps_paint_tiling_brush_clipped(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, struct closure *c) +xps_paint_tiling_brush_clipped(xps_document *doc, fz_matrix ctm, fz_rect viewbox, struct closure *c) { - fz_path *path = fz_new_path(); - fz_moveto(path, viewbox.x0, viewbox.y0); - fz_lineto(path, viewbox.x0, viewbox.y1); - fz_lineto(path, viewbox.x1, viewbox.y1); - fz_lineto(path, viewbox.x1, viewbox.y0); - fz_closepath(path); - fz_clip_path(ctx->dev, path, NULL, 0, ctm); - fz_free_path(path); - c->func(ctx, ctm, viewbox, c->base_uri, c->dict, c->root, c->user); - fz_pop_clip(ctx->dev); + fz_path *path = fz_new_path(doc->ctx); + fz_moveto(doc->ctx, path, viewbox.x0, viewbox.y0); + fz_lineto(doc->ctx, path, viewbox.x0, viewbox.y1); + fz_lineto(doc->ctx, path, viewbox.x1, viewbox.y1); + fz_lineto(doc->ctx, path, viewbox.x1, viewbox.y0); + fz_closepath(doc->ctx, path); + fz_clip_path(doc->dev, path, NULL, 0, ctm); + fz_free_path(doc->ctx, path); + c->func(doc, ctm, viewbox, c->base_uri, c->dict, c->root, c->user); + fz_pop_clip(doc->dev); } static void -xps_paint_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, int tile_mode, struct closure *c) +xps_paint_tiling_brush(xps_document *doc, fz_matrix ctm, fz_rect viewbox, int tile_mode, struct closure *c) { fz_matrix ttm; - xps_paint_tiling_brush_clipped(ctx, ctm, viewbox, c); + xps_paint_tiling_brush_clipped(doc, ctm, viewbox, c); if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y) { ttm = fz_concat(fz_translate(viewbox.x1 * 2, 0), ctm); ttm = fz_concat(fz_scale(-1, 1), ttm); - xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); + xps_paint_tiling_brush_clipped(doc, ttm, viewbox, c); } if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y) { ttm = fz_concat(fz_translate(0, viewbox.y1 * 2), ctm); ttm = fz_concat(fz_scale(1, -1), ttm); - xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); + xps_paint_tiling_brush_clipped(doc, ttm, viewbox, c); } if (tile_mode == TILE_FLIP_X_Y) { ttm = fz_concat(fz_translate(viewbox.x1 * 2, viewbox.y1 * 2), ctm); ttm = fz_concat(fz_scale(-1, -1), ttm); - xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); + xps_paint_tiling_brush_clipped(doc, ttm, viewbox, c); } } void -xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, +xps_parse_tiling_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root, - void (*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*), void *user) + void (*func)(xps_document*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*), void *user) { xml_element *node; struct closure c; @@ -110,22 +110,22 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, transform_tag = xml_down(node); } - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); + xps_resolve_resource_reference(doc, dict, &transform_att, &transform_tag, NULL); transform = fz_identity; if (transform_att) - xps_parse_render_transform(ctx, transform_att, &transform); + xps_parse_render_transform(doc, transform_att, &transform); if (transform_tag) - xps_parse_matrix_transform(ctx, transform_tag, &transform); + xps_parse_matrix_transform(doc, transform_tag, &transform); ctm = fz_concat(transform, ctm); viewbox = fz_unit_rect; if (viewbox_att) - xps_parse_rectangle(ctx, viewbox_att, &viewbox); + xps_parse_rectangle(doc, viewbox_att, &viewbox); viewport = fz_unit_rect; if (viewport_att) - xps_parse_rectangle(ctx, viewport_att, &viewport); + xps_parse_rectangle(doc, viewport_att, &viewport); /* some sanity checks on the viewport/viewbox size */ if (fabsf(viewport.x1 - viewport.x0) < 0.01f) return; @@ -159,7 +159,7 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y) ystep *= 2; - xps_begin_opacity(ctx, ctm, area, base_uri, dict, opacity_att, NULL); + xps_begin_opacity(doc, ctm, area, base_uri, dict, opacity_att, NULL); ctm = fz_concat(fz_translate(viewport.x0, viewport.y0), ctm); ctm = fz_concat(fz_scale(xscale, yscale), ctm); @@ -184,9 +184,9 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, fz_rect bigview = viewbox; bigview.x1 = bigview.x0 + xstep; bigview.y1 = bigview.y0 + ystep; - fz_begin_tile(ctx->dev, area, bigview, xstep, ystep, ctm); - xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c); - fz_end_tile(ctx->dev); + fz_begin_tile(doc->dev, area, bigview, xstep, ystep, ctm); + xps_paint_tiling_brush(doc, ctm, viewbox, tile_mode, &c); + fz_end_tile(doc->dev); } else { @@ -196,28 +196,28 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, for (x = x0; x < x1; x++) { fz_matrix ttm = fz_concat(fz_translate(xstep * x, ystep * y), ctm); - xps_paint_tiling_brush(ctx, ttm, viewbox, tile_mode, &c); + xps_paint_tiling_brush(doc, ttm, viewbox, tile_mode, &c); } } } } else { - xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c); + xps_paint_tiling_brush(doc, ctm, viewbox, tile_mode, &c); } - xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL); + xps_end_opacity(doc, base_uri, dict, opacity_att, NULL); } static void -xps_paint_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, +xps_paint_visual_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root, void *visual_tag) { - xps_parse_element(ctx, ctm, area, base_uri, dict, (xml_element *)visual_tag); + xps_parse_element(doc, ctm, area, base_uri, dict, (xml_element *)visual_tag); } void -xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, +xps_parse_visual_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root) { xml_element *node; @@ -235,17 +235,17 @@ xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, } visual_uri = base_uri; - xps_resolve_resource_reference(ctx, dict, &visual_att, &visual_tag, &visual_uri); + xps_resolve_resource_reference(doc, dict, &visual_att, &visual_tag, &visual_uri); if (visual_tag) { - xps_parse_tiling_brush(ctx, ctm, area, + xps_parse_tiling_brush(doc, ctm, area, visual_uri, dict, root, xps_paint_visual_brush, visual_tag); } } void -xps_parse_canvas(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root) +xps_parse_canvas(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root) { xps_resource *new_dict = NULL; xml_element *node; @@ -272,9 +272,9 @@ xps_parse_canvas(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, { if (!strcmp(xml_tag(node), "Canvas.Resources") && xml_down(node)) { - code = xps_parse_resource_dictionary(ctx, &new_dict, base_uri, xml_down(node)); + code = xps_parse_resource_dictionary(doc, &new_dict, base_uri, xml_down(node)); if (code) - fz_catch(code, "cannot load Canvas.Resources"); + fz_error_handle(code, "cannot load Canvas.Resources"); else { new_dict->parent = dict; @@ -291,38 +291,38 @@ xps_parse_canvas(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, } opacity_mask_uri = base_uri; - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &clip_att, &clip_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); + xps_resolve_resource_reference(doc, dict, &transform_att, &transform_tag, NULL); + xps_resolve_resource_reference(doc, dict, &clip_att, &clip_tag, NULL); + xps_resolve_resource_reference(doc, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); transform = fz_identity; if (transform_att) - xps_parse_render_transform(ctx, transform_att, &transform); + xps_parse_render_transform(doc, transform_att, &transform); if (transform_tag) - xps_parse_matrix_transform(ctx, transform_tag, &transform); + xps_parse_matrix_transform(doc, transform_tag, &transform); ctm = fz_concat(transform, ctm); if (clip_att || clip_tag) - xps_clip(ctx, ctm, dict, clip_att, clip_tag); + xps_clip(doc, ctm, dict, clip_att, clip_tag); - xps_begin_opacity(ctx, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); + xps_begin_opacity(doc, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); for (node = xml_down(root); node; node = xml_next(node)) { - xps_parse_element(ctx, ctm, area, base_uri, dict, node); + xps_parse_element(doc, ctm, area, base_uri, dict, node); } - xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); + xps_end_opacity(doc, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); if (clip_att || clip_tag) - fz_pop_clip(ctx->dev); + fz_pop_clip(doc->dev); if (new_dict) - xps_free_resource_dictionary(ctx, new_dict); + xps_free_resource_dictionary(doc, new_dict); } void -xps_parse_fixed_page(xps_context *ctx, fz_matrix ctm, xps_page *page) +xps_parse_fixed_page(xps_document *doc, fz_matrix ctm, xps_page *page) { xml_element *node; xps_resource *dict; @@ -338,8 +338,8 @@ xps_parse_fixed_page(xps_context *ctx, fz_matrix ctm, xps_page *page) dict = NULL; - ctx->opacity_top = 0; - ctx->opacity[0] = 1; + doc->opacity_top = 0; + doc->opacity[0] = 1; if (!page->root) return; @@ -350,15 +350,15 @@ xps_parse_fixed_page(xps_context *ctx, fz_matrix ctm, xps_page *page) { if (!strcmp(xml_tag(node), "FixedPage.Resources") && xml_down(node)) { - code = xps_parse_resource_dictionary(ctx, &dict, base_uri, xml_down(node)); + code = xps_parse_resource_dictionary(doc, &dict, base_uri, xml_down(node)); if (code) - fz_catch(code, "cannot load FixedPage.Resources"); + fz_error_handle(code, "cannot load FixedPage.Resources"); } - xps_parse_element(ctx, ctm, area, base_uri, dict, node); + xps_parse_element(doc, ctm, area, base_uri, dict, node); } if (dict) { - xps_free_resource_dictionary(ctx, dict); + xps_free_resource_dictionary(doc, dict); } } diff --git a/xps/xps_xml.c b/xps/xps_xml.c index aacabd5a..d92804af 100644 --- a/xps/xps_xml.c +++ b/xps/xps_xml.c @@ -18,6 +18,7 @@ struct element struct parser { struct element *head; + fz_context *ctx; }; static inline void indent(int n) @@ -70,26 +71,26 @@ char *xml_att(struct element *item, const char *name) return NULL; } -static void xml_free_attribute(struct attribute *att) +static void xml_free_attribute(fz_context *ctx, struct attribute *att) { while (att) { struct attribute *next = att->next; if (att->value) - fz_free(att->value); - fz_free(att); + fz_free(ctx, att->value); + fz_free(ctx, att); att = next; } } -void xml_free_element(struct element *item) +void xml_free_element(fz_context *ctx, struct element *item) { while (item) { struct element *next = item->next; if (item->atts) - xml_free_attribute(item->atts); + xml_free_attribute(ctx, item->atts); if (item->down) - xml_free_element(item->down); - fz_free(item); + xml_free_element(ctx, item->down); + fz_free(ctx, item); item = next; } } @@ -133,7 +134,7 @@ static void xml_emit_open_tag(struct parser *parser, char *a, char *b) { struct element *head, *tail; - head = fz_malloc(sizeof(struct element)); + head = fz_malloc(parser->ctx, sizeof(struct element)); if (b - a > sizeof(head->name)) b = a + sizeof(head->name); memcpy(head->name, a, b - a); @@ -162,7 +163,7 @@ static void xml_emit_att_name(struct parser *parser, char *a, char *b) struct element *head = parser->head; struct attribute *att; - att = fz_malloc(sizeof(struct attribute)); + att = fz_malloc(parser->ctx, sizeof(struct attribute)); if (b - a > sizeof(att->name)) b = a + sizeof(att->name); memcpy(att->name, a, b - a); @@ -180,7 +181,7 @@ static void xml_emit_att_value(struct parser *parser, char *a, char *b) int c; /* entities are all longer than UTFmax so runetochar is safe */ - s = att->value = fz_malloc(b - a + 1); + s = att->value = fz_malloc(parser->ctx, b - a + 1); while (a < b) { if (*a == '&') { a += xml_parse_entity(&c, a); @@ -329,14 +330,14 @@ parse_attribute_value: return "end of data in attribute value"; } -static char *convert_to_utf8(unsigned char *s, int n) +static char *convert_to_utf8(fz_context *doc, unsigned char *s, int n) { unsigned char *e = s + n; char *dst, *d; int c; if (s[0] == 0xFE && s[1] == 0xFF) { - dst = d = fz_malloc(n * 2); + dst = d = fz_malloc(doc, n * 2); while (s + 1 < e) { c = s[0] << 8 | s[1]; d += runetochar(d, &c); @@ -347,7 +348,7 @@ static char *convert_to_utf8(unsigned char *s, int n) } if (s[0] == 0xFF && s[1] == 0xFE) { - dst = d = fz_malloc(n * 2); + dst = d = fz_malloc(doc, n * 2); while (s + 1 < e) { c = s[0] | s[1] << 8; d += runetochar(d, &c); @@ -361,7 +362,7 @@ static char *convert_to_utf8(unsigned char *s, int n) } struct element * -xml_parse_document(unsigned char *s, int n) +xml_parse_document(fz_context *ctx, unsigned char *s, int n) { struct parser parser; struct element root; @@ -371,17 +372,18 @@ xml_parse_document(unsigned char *s, int n) memset(&root, 0, sizeof(root)); parser.head = &root; + parser.ctx = ctx; - p = convert_to_utf8(s, n); + p = convert_to_utf8(ctx, s, n); error = xml_parse_document_imp(&parser, p); if (error) { - fz_throw("%s", error); + fz_throw(ctx, "%s", error); return NULL; } if (p != (char*)s) - fz_free(p); + fz_free(ctx, p); return root.down; } diff --git a/xps/xps_zip.c b/xps/xps_zip.c index a0c981bf..f02bf33e 100644 --- a/xps/xps_zip.c +++ b/xps/xps_zip.c @@ -4,25 +4,25 @@ #include <zlib.h> xps_part * -xps_new_part(xps_context *ctx, char *name, int size) +xps_new_part(xps_document *doc, char *name, int size) { xps_part *part; - part = fz_malloc(sizeof(xps_part)); - part->name = fz_strdup(name); + part = fz_malloc(doc->ctx, sizeof(xps_part)); + part->name = fz_strdup(doc->ctx, name); part->size = size; - part->data = fz_malloc(size + 1); + part->data = fz_malloc(doc->ctx, size + 1); part->data[size] = 0; /* null-terminate for xml parser */ return part; } void -xps_free_part(xps_context *ctx, xps_part *part) +xps_free_part(xps_document *doc, xps_part *part) { - fz_free(part->name); - fz_free(part->data); - fz_free(part); + fz_free(doc->ctx, part->name); + fz_free(doc->ctx, part->data); + fz_free(doc->ctx, part); } static inline int getshort(fz_stream *file) @@ -42,15 +42,15 @@ static inline int getlong(fz_stream *file) } static void * -xps_zip_alloc_items(xps_context *ctx, int items, int size) +xps_zip_alloc_items(xps_document *doc, int items, int size) { - return fz_calloc(items, size); + return fz_malloc_array(doc->ctx, items, size); } static void -xps_zip_free(xps_context *ctx, void *ptr) +xps_zip_free(xps_document *doc, void *ptr) { - fz_free(ptr); + fz_free(doc->ctx, ptr); } static int @@ -62,26 +62,26 @@ xps_compare_entries(const void *a0, const void *b0) } static xps_entry * -xps_find_zip_entry(xps_context *ctx, char *name) +xps_find_zip_entry(xps_document *doc, char *name) { int l = 0; - int r = ctx->zip_count - 1; + int r = doc->zip_count - 1; while (l <= r) { int m = (l + r) >> 1; - int c = xps_strcasecmp(name, ctx->zip_table[m].name); + int c = xps_strcasecmp(name, doc->zip_table[m].name); if (c < 0) r = m - 1; else if (c > 0) l = m + 1; else - return &ctx->zip_table[m]; + return &doc->zip_table[m]; } return NULL; } static int -xps_read_zip_entry(xps_context *ctx, xps_entry *ent, unsigned char *outbuf) +xps_read_zip_entry(xps_document *doc, xps_entry *ent, unsigned char *outbuf) { z_stream stream; unsigned char *inbuf; @@ -90,39 +90,39 @@ xps_read_zip_entry(xps_context *ctx, xps_entry *ent, unsigned char *outbuf) int namelength, extralength; int code; - fz_seek(ctx->file, ent->offset, 0); + fz_seek(doc->file, ent->offset, 0); - sig = getlong(ctx->file); + sig = getlong(doc->file); if (sig != ZIP_LOCAL_FILE_SIG) - return fz_throw("wrong zip local file signature (0x%x)", sig); + return fz_error_make("wrong zip local file signature (0x%x)", sig); - version = getshort(ctx->file); - general = getshort(ctx->file); - method = getshort(ctx->file); - (void) getshort(ctx->file); /* file time */ - (void) getshort(ctx->file); /* file date */ - (void) getlong(ctx->file); /* crc-32 */ - (void) getlong(ctx->file); /* csize */ - (void) getlong(ctx->file); /* usize */ - namelength = getshort(ctx->file); - extralength = getshort(ctx->file); + version = getshort(doc->file); + general = getshort(doc->file); + method = getshort(doc->file); + (void) getshort(doc->file); /* file time */ + (void) getshort(doc->file); /* file date */ + (void) getlong(doc->file); /* crc-32 */ + (void) getlong(doc->file); /* csize */ + (void) getlong(doc->file); /* usize */ + namelength = getshort(doc->file); + extralength = getshort(doc->file); - fz_seek(ctx->file, namelength + extralength, 1); + fz_seek(doc->file, namelength + extralength, 1); if (method == 0) { - fz_read(ctx->file, outbuf, ent->usize); + fz_read(doc->file, outbuf, ent->usize); } else if (method == 8) { - inbuf = fz_malloc(ent->csize); + inbuf = fz_malloc(doc->ctx, ent->csize); - fz_read(ctx->file, inbuf, ent->csize); + fz_read(doc->file, inbuf, ent->csize); memset(&stream, 0, sizeof(z_stream)); stream.zalloc = (alloc_func) xps_zip_alloc_items; stream.zfree = (free_func) xps_zip_free; - stream.opaque = ctx; + stream.opaque = doc; stream.next_in = inbuf; stream.avail_in = ent->csize; stream.next_out = outbuf; @@ -130,22 +130,22 @@ xps_read_zip_entry(xps_context *ctx, xps_entry *ent, unsigned char *outbuf) code = inflateInit2(&stream, -15); if (code != Z_OK) - return fz_throw("zlib inflateInit2 error: %s", stream.msg); + return fz_error_make("zlib inflateInit2 error: %s", stream.msg); code = inflate(&stream, Z_FINISH); if (code != Z_STREAM_END) { inflateEnd(&stream); - return fz_throw("zlib inflate error: %s", stream.msg); + return fz_error_make("zlib inflate error: %s", stream.msg); } code = inflateEnd(&stream); if (code != Z_OK) - return fz_throw("zlib inflateEnd error: %s", stream.msg); + return fz_error_make("zlib inflateEnd error: %s", stream.msg); - fz_free(inbuf); + fz_free(doc->ctx, inbuf); } else { - return fz_throw("unknown compression method (%d)", method); + return fz_error_make("unknown compression method (%d)", method); } return fz_okay; @@ -156,104 +156,103 @@ xps_read_zip_entry(xps_context *ctx, xps_entry *ent, unsigned char *outbuf) */ static int -xps_read_zip_dir(xps_context *ctx, int start_offset) +xps_read_zip_dir(xps_document *doc, int start_offset) { int sig; int offset, count; int namesize, metasize, commentsize; int i; - fz_seek(ctx->file, start_offset, 0); + fz_seek(doc->file, start_offset, 0); - sig = getlong(ctx->file); + sig = getlong(doc->file); if (sig != ZIP_END_OF_CENTRAL_DIRECTORY_SIG) - return fz_throw("wrong zip end of central directory signature (0x%x)", sig); + return fz_error_make("wrong zip end of central directory signature (0x%x)", sig); - (void) getshort(ctx->file); /* this disk */ - (void) getshort(ctx->file); /* start disk */ - (void) getshort(ctx->file); /* entries in this disk */ - count = getshort(ctx->file); /* entries in central directory disk */ - (void) getlong(ctx->file); /* size of central directory */ - offset = getlong(ctx->file); /* offset to central directory */ + (void) getshort(doc->file); /* this disk */ + (void) getshort(doc->file); /* start disk */ + (void) getshort(doc->file); /* entries in this disk */ + count = getshort(doc->file); /* entries in central directory disk */ + (void) getlong(doc->file); /* size of central directory */ + offset = getlong(doc->file); /* offset to central directory */ - ctx->zip_count = count; - ctx->zip_table = fz_calloc(count, sizeof(xps_entry)); - memset(ctx->zip_table, 0, sizeof(xps_entry) * count); + doc->zip_count = count; + doc->zip_table = fz_malloc_array(doc->ctx, count, sizeof(xps_entry)); - fz_seek(ctx->file, offset, 0); + fz_seek(doc->file, offset, 0); for (i = 0; i < count; i++) { - sig = getlong(ctx->file); + sig = getlong(doc->file); if (sig != ZIP_CENTRAL_DIRECTORY_SIG) - return fz_throw("wrong zip central directory signature (0x%x)", sig); - - (void) getshort(ctx->file); /* version made by */ - (void) getshort(ctx->file); /* version to extract */ - (void) getshort(ctx->file); /* general */ - (void) getshort(ctx->file); /* method */ - (void) getshort(ctx->file); /* last mod file time */ - (void) getshort(ctx->file); /* last mod file date */ - (void) getlong(ctx->file); /* crc-32 */ - ctx->zip_table[i].csize = getlong(ctx->file); - ctx->zip_table[i].usize = getlong(ctx->file); - namesize = getshort(ctx->file); - metasize = getshort(ctx->file); - commentsize = getshort(ctx->file); - (void) getshort(ctx->file); /* disk number start */ - (void) getshort(ctx->file); /* int file atts */ - (void) getlong(ctx->file); /* ext file atts */ - ctx->zip_table[i].offset = getlong(ctx->file); - - ctx->zip_table[i].name = fz_malloc(namesize + 1); - fz_read(ctx->file, (unsigned char*)ctx->zip_table[i].name, namesize); - ctx->zip_table[i].name[namesize] = 0; - - fz_seek(ctx->file, metasize, 1); - fz_seek(ctx->file, commentsize, 1); + return fz_error_make("wrong zip central directory signature (0x%x)", sig); + + (void) getshort(doc->file); /* version made by */ + (void) getshort(doc->file); /* version to extract */ + (void) getshort(doc->file); /* general */ + (void) getshort(doc->file); /* method */ + (void) getshort(doc->file); /* last mod file time */ + (void) getshort(doc->file); /* last mod file date */ + (void) getlong(doc->file); /* crc-32 */ + doc->zip_table[i].csize = getlong(doc->file); + doc->zip_table[i].usize = getlong(doc->file); + namesize = getshort(doc->file); + metasize = getshort(doc->file); + commentsize = getshort(doc->file); + (void) getshort(doc->file); /* disk number start */ + (void) getshort(doc->file); /* int file atts */ + (void) getlong(doc->file); /* ext file atts */ + doc->zip_table[i].offset = getlong(doc->file); + + doc->zip_table[i].name = fz_malloc(doc->ctx, namesize + 1); + fz_read(doc->file, (unsigned char*)doc->zip_table[i].name, namesize); + doc->zip_table[i].name[namesize] = 0; + + fz_seek(doc->file, metasize, 1); + fz_seek(doc->file, commentsize, 1); } - qsort(ctx->zip_table, count, sizeof(xps_entry), xps_compare_entries); + qsort(doc->zip_table, count, sizeof(xps_entry), xps_compare_entries); return fz_okay; } static int -xps_find_and_read_zip_dir(xps_context *ctx) +xps_find_and_read_zip_dir(xps_document *doc) { unsigned char buf[512]; int file_size, back, maxback; int i, n; - fz_seek(ctx->file, 0, SEEK_END); - file_size = fz_tell(ctx->file); + fz_seek(doc->file, 0, SEEK_END); + file_size = fz_tell(doc->file); maxback = MIN(file_size, 0xFFFF + sizeof buf); back = MIN(maxback, sizeof buf); while (back < maxback) { - fz_seek(ctx->file, file_size - back, 0); + fz_seek(doc->file, file_size - back, 0); - n = fz_read(ctx->file, buf, sizeof buf); + n = fz_read(doc->file, buf, sizeof buf); if (n < 0) - return fz_throw("cannot read end of central directory"); + return fz_error_make("cannot read end of central directory"); for (i = n - 4; i > 0; i--) if (!memcmp(buf + i, "PK\5\6", 4)) - return xps_read_zip_dir(ctx, file_size - back + i); + return xps_read_zip_dir(doc, file_size - back + i); back += sizeof buf - 4; } - return fz_throw("cannot find end of central directory"); + return fz_error_make("cannot find end of central directory"); } /* * Read and interleave split parts from a ZIP file. */ static xps_part * -xps_read_zip_part(xps_context *ctx, char *partname) +xps_read_zip_part(xps_document *doc, char *partname) { char buf[2048]; xps_entry *ent; @@ -266,11 +265,11 @@ xps_read_zip_part(xps_context *ctx, char *partname) name ++; /* All in one piece */ - ent = xps_find_zip_entry(ctx, name); + ent = xps_find_zip_entry(doc, name); if (ent) { - part = xps_new_part(ctx, partname, ent->usize); - xps_read_zip_entry(ctx, ent, part->data); + part = xps_new_part(doc, partname, ent->usize); + xps_read_zip_entry(doc, ent, part->data); return part; } @@ -280,11 +279,11 @@ xps_read_zip_part(xps_context *ctx, char *partname) while (1) { sprintf(buf, "%s/[%d].piece", name, count); - ent = xps_find_zip_entry(ctx, buf); + ent = xps_find_zip_entry(doc, buf); if (!ent) { sprintf(buf, "%s/[%d].last.piece", name, count); - ent = xps_find_zip_entry(ctx, buf); + ent = xps_find_zip_entry(doc, buf); } if (!ent) break; @@ -295,7 +294,7 @@ xps_read_zip_part(xps_context *ctx, char *partname) /* Inflate the pieces */ if (count) { - part = xps_new_part(ctx, partname, size); + part = xps_new_part(doc, partname, size); offset = 0; for (i = 0; i < count; i++) { @@ -303,8 +302,8 @@ xps_read_zip_part(xps_context *ctx, char *partname) sprintf(buf, "%s/[%d].piece", name, i); else sprintf(buf, "%s/[%d].last.piece", name, i); - ent = xps_find_zip_entry(ctx, buf); - xps_read_zip_entry(ctx, ent, part->data + offset); + ent = xps_find_zip_entry(doc, buf); + xps_read_zip_entry(doc, ent, part->data + offset); offset += ent->usize; } return part; @@ -317,14 +316,14 @@ xps_read_zip_part(xps_context *ctx, char *partname) * Read and interleave split parts from files in the directory. */ static xps_part * -xps_read_dir_part(xps_context *ctx, char *name) +xps_read_dir_part(xps_document *doc, char *name) { char buf[2048]; xps_part *part; FILE *file; int count, size, offset, i, n; - fz_strlcpy(buf, ctx->directory, sizeof buf); + fz_strlcpy(buf, doc->directory, sizeof buf); fz_strlcat(buf, name, sizeof buf); /* All in one piece */ @@ -334,7 +333,7 @@ xps_read_dir_part(xps_context *ctx, char *name) fseek(file, 0, SEEK_END); size = ftell(file); fseek(file, 0, SEEK_SET); - part = xps_new_part(ctx, name, size); + part = xps_new_part(doc, name, size); fread(part->data, 1, size, file); fclose(file); return part; @@ -345,11 +344,11 @@ xps_read_dir_part(xps_context *ctx, char *name) size = 0; while (1) { - sprintf(buf, "%s%s/[%d].piece", ctx->directory, name, count); + sprintf(buf, "%s%s/[%d].piece", doc->directory, name, count); file = fopen(buf, "rb"); if (!file) { - sprintf(buf, "%s%s/[%d].last.piece", ctx->directory, name, count); + sprintf(buf, "%s%s/[%d].last.piece", doc->directory, name, count); file = fopen(buf, "rb"); } if (!file) @@ -363,14 +362,14 @@ xps_read_dir_part(xps_context *ctx, char *name) /* Inflate the pieces */ if (count) { - part = xps_new_part(ctx, name, size); + part = xps_new_part(doc, name, size); offset = 0; for (i = 0; i < count; i++) { if (i < count - 1) - sprintf(buf, "%s%s/[%d].piece", ctx->directory, name, i); + sprintf(buf, "%s%s/[%d].piece", doc->directory, name, i); else - sprintf(buf, "%s%s/[%d].last.piece", ctx->directory, name, i); + sprintf(buf, "%s%s/[%d].last.piece", doc->directory, name, i); file = fopen(buf, "rb"); n = fread(part->data + offset, 1, size - offset, file); offset += n; @@ -383,71 +382,79 @@ xps_read_dir_part(xps_context *ctx, char *name) } xps_part * -xps_read_part(xps_context *ctx, char *partname) +xps_read_part(xps_document *doc, char *partname) { - if (ctx->directory) - return xps_read_dir_part(ctx, partname); - return xps_read_zip_part(ctx, partname); + if (doc->directory) + return xps_read_dir_part(doc, partname); + return xps_read_zip_part(doc, partname); } -static int -xps_open_directory(xps_context **ctxp, char *directory) +static xps_document * +xps_open_directory(fz_context *ctx, char *directory) { - xps_context *ctx; - int code; + xps_document *doc; - ctx = fz_malloc(sizeof(xps_context)); - memset(ctx, 0, sizeof(xps_context)); + doc = fz_malloc(ctx, sizeof(xps_document)); + memset(doc, 0, sizeof *doc); - ctx->directory = fz_strdup(directory); + doc->directory = fz_strdup(ctx, directory); + doc->ctx = ctx; - code = xps_read_page_list(ctx); - if (code) + fz_try(ctx) { - xps_free_context(ctx); - return fz_rethrow(code, "cannot read page list"); + xps_read_page_list(doc); + } + fz_catch(ctx) + { + xps_free_context(doc); + fz_throw(ctx, "cannot read page list"); } - *ctxp = ctx; - return fz_okay; + return doc; } -int -xps_open_stream(xps_context **ctxp, fz_stream *file) +xps_document * +xps_open_stream(fz_stream *file) { - xps_context *ctx; - int code; + xps_document *doc; + fz_context *ctx = file->ctx; - ctx = fz_malloc(sizeof(xps_context)); - memset(ctx, 0, sizeof(xps_context)); + doc = fz_malloc(ctx, sizeof(xps_document)); + memset(doc, 0, sizeof *doc); - ctx->file = fz_keep_stream(file); + doc->ctx = ctx; + doc->file = fz_keep_stream(file); - code = xps_find_and_read_zip_dir(ctx); - if (code < 0) + fz_try(ctx) + { + xps_find_and_read_zip_dir(doc); + } + fz_catch(ctx) { - xps_free_context(ctx); - return fz_rethrow(code, "cannot read zip central directory"); + xps_free_context(doc); + fz_throw(ctx, "cannot read zip central directory"); } - code = xps_read_page_list(ctx); - if (code) + fz_try(ctx) { - xps_free_context(ctx); - return fz_rethrow(code, "cannot read page list"); + xps_read_page_list(doc); + } + fz_catch(ctx) + { + xps_free_context(doc); + fz_throw(ctx, "cannot read page list"); } - *ctxp = ctx; - return fz_okay; + return doc; } -int -xps_open_file(xps_context **ctxp, char *filename) +xps_document * +xps_open_file(fz_context *ctx, char *filename) { char buf[2048]; fz_stream *file; char *p; - int code; + xps_document *doc; if (strstr(filename, "/_rels/.rels") || strstr(filename, "\\_rels\\.rels")) { @@ -456,46 +463,52 @@ xps_open_file(xps_context **ctxp, char *filename) if (!p) p = strstr(buf, "\\_rels\\.rels"); *p = 0; - return xps_open_directory(ctxp, buf); + return xps_open_directory(ctx, buf); } - file = fz_open_file(filename); + file = fz_open_file(ctx, filename); if (!file) - return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); + fz_throw(ctx, "cannot open file '%s': %s", filename, strerror(errno)); - code = xps_open_stream(ctxp, file); + fz_try(ctx) + { + doc = xps_open_stream(file); + } + fz_catch(ctx) + { + fz_close(file); + fz_throw(ctx, "cannot load document '%s'", filename); + } fz_close(file); - if (code) - return fz_rethrow(code, "cannot load document '%s'", filename); - return fz_okay; + return doc; } void -xps_free_context(xps_context *ctx) +xps_free_context(xps_document *doc) { xps_font_cache *font, *next; int i; - if (ctx->file) - fz_close(ctx->file); + if (doc->file) + fz_close(doc->file); - for (i = 0; i < ctx->zip_count; i++) - fz_free(ctx->zip_table[i].name); - fz_free(ctx->zip_table); + for (i = 0; i < doc->zip_count; i++) + fz_free(doc->ctx, doc->zip_table[i].name); + fz_free(doc->ctx, doc->zip_table); - font = ctx->font_table; + font = doc->font_table; while (font) { next = font->next; - fz_drop_font(font->font); - fz_free(font->name); - fz_free(font); + fz_drop_font(doc->ctx, font->font); + fz_free(doc->ctx, font->name); + fz_free(doc->ctx, font); font = next; } - xps_free_page_list(ctx); + xps_free_page_list(doc); - fz_free(ctx->start_part); - fz_free(ctx->directory); - fz_free(ctx); + fz_free(doc->ctx, doc->start_part); + fz_free(doc->ctx, doc->directory); + fz_free(doc->ctx, doc); } |