diff options
-rw-r--r-- | apps/pdfapp.c | 21 | ||||
-rw-r--r-- | apps/pdfapp.h | 1 | ||||
-rw-r--r-- | fitz/dev_list.c | 179 | ||||
-rw-r--r-- | fitz/fitz.h | 3 | ||||
-rw-r--r-- | pdf/pdf_interpret.c | 190 |
5 files changed, 222 insertions, 172 deletions
diff --git a/apps/pdfapp.c b/apps/pdfapp.c index b4ec4fbf..2a8ae3b5 100644 --- a/apps/pdfapp.c +++ b/apps/pdfapp.c @@ -229,6 +229,7 @@ static void pdfapp_loadpage(pdfapp_t *app) { fz_device *mdev = NULL; int errored = 0; + fz_cookie cookie = { 0 }; fz_var(mdev); @@ -270,7 +271,12 @@ static void pdfapp_loadpage(pdfapp_t *app) /* Create display list */ app->page_list = fz_new_display_list(app->ctx); mdev = fz_new_list_device(app->ctx, app->page_list); - fz_run_page(app->doc, app->page, mdev, fz_identity, NULL); + fz_run_page(app->doc, app->page, mdev, fz_identity, &cookie); + if (cookie.errors) + { + pdfapp_warn(app, "Errors found on page"); + errored = 1; + } } fz_always(app->ctx) { @@ -291,6 +297,8 @@ static void pdfapp_loadpage(pdfapp_t *app) if (!errored) pdfapp_warn(app, "Cannot load page"); } + + app->errored = errored; } #define MAX_TITLE 256 @@ -303,6 +311,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai fz_colorspace *colorspace; fz_matrix ctm; fz_bbox bbox; + fz_cookie cookie = { 0 }; wincursor(app, WAIT); @@ -318,7 +327,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai app->page_sheet = fz_new_text_sheet(app->ctx); app->page_text = fz_new_text_page(app->ctx, app->page_bbox); tdev = fz_new_text_device(app->ctx, app->page_sheet, app->page_text); - fz_run_display_list(app->page_list, tdev, fz_identity, fz_infinite_bbox, NULL); + fz_run_display_list(app->page_list, tdev, fz_identity, fz_infinite_bbox, &cookie); fz_free_device(tdev); } @@ -357,7 +366,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai app->image = fz_new_pixmap_with_bbox(app->ctx, colorspace, bbox); fz_clear_pixmap_with_value(app->ctx, app->image, 255); idev = fz_new_draw_device(app->ctx, app->image); - fz_run_display_list(app->page_list, idev, ctm, bbox, NULL); + fz_run_display_list(app->page_list, idev, ctm, bbox, &cookie); fz_free_device(idev); if (app->invert) fz_invert_pixmap(app->ctx, app->image); @@ -388,6 +397,12 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai wincursor(app, ARROW); } + if (cookie.errors && app->errored == 0) + { + app->errored = 1; + pdfapp_warn(app, "Errors found on page. Page rendering may be incomplete."); + } + fz_flush_warnings(app->ctx); } diff --git a/apps/pdfapp.h b/apps/pdfapp.h index f93b816a..31ad18e1 100644 --- a/apps/pdfapp.h +++ b/apps/pdfapp.h @@ -56,6 +56,7 @@ struct pdfapp_s fz_text_page *page_text; fz_text_sheet *page_sheet; fz_link *page_links; + int errored; /* snapback history */ int hist[256]; diff --git a/fitz/dev_list.c b/fitz/dev_list.c index 1ca8bf98..d84fb15b 100644 --- a/fitz/dev_list.c +++ b/fitz/dev_list.c @@ -593,6 +593,7 @@ fz_run_display_list(fz_display_list *list, fz_device *dev, fz_matrix top_ctm, fz int tiled = 0; int empty; int progress = 0; + fz_context *ctx = dev->ctx; if (cookie) { @@ -658,93 +659,103 @@ fz_run_display_list(fz_display_list *list, fz_device *dev, fz_matrix top_ctm, fz visible: ctm = fz_concat(node->ctm, top_ctm); - switch (node->cmd) - { - case FZ_CMD_FILL_PATH: - fz_fill_path(dev, node->item.path, node->flag, ctm, - node->colorspace, node->color, node->alpha); - break; - case FZ_CMD_STROKE_PATH: - fz_stroke_path(dev, node->item.path, node->stroke, ctm, - node->colorspace, node->color, node->alpha); - break; - case FZ_CMD_CLIP_PATH: - { - fz_rect trect = fz_transform_rect(top_ctm, node->rect); - fz_clip_path(dev, node->item.path, &trect, node->flag, ctm); - break; - } - case FZ_CMD_CLIP_STROKE_PATH: + fz_try(ctx) { - fz_rect trect = fz_transform_rect(top_ctm, node->rect); - fz_clip_stroke_path(dev, node->item.path, &trect, node->stroke, ctm); - break; + switch (node->cmd) + { + case FZ_CMD_FILL_PATH: + fz_fill_path(dev, node->item.path, node->flag, ctm, + node->colorspace, node->color, node->alpha); + break; + case FZ_CMD_STROKE_PATH: + fz_stroke_path(dev, node->item.path, node->stroke, ctm, + node->colorspace, node->color, node->alpha); + break; + case FZ_CMD_CLIP_PATH: + { + fz_rect trect = fz_transform_rect(top_ctm, node->rect); + fz_clip_path(dev, node->item.path, &trect, node->flag, ctm); + break; + } + case FZ_CMD_CLIP_STROKE_PATH: + { + fz_rect trect = fz_transform_rect(top_ctm, node->rect); + fz_clip_stroke_path(dev, node->item.path, &trect, node->stroke, ctm); + break; + } + case FZ_CMD_FILL_TEXT: + fz_fill_text(dev, node->item.text, ctm, + node->colorspace, node->color, node->alpha); + break; + case FZ_CMD_STROKE_TEXT: + fz_stroke_text(dev, node->item.text, node->stroke, ctm, + node->colorspace, node->color, node->alpha); + break; + case FZ_CMD_CLIP_TEXT: + fz_clip_text(dev, node->item.text, ctm, node->flag); + break; + case FZ_CMD_CLIP_STROKE_TEXT: + fz_clip_stroke_text(dev, node->item.text, node->stroke, ctm); + break; + case FZ_CMD_IGNORE_TEXT: + fz_ignore_text(dev, node->item.text, ctm); + break; + case FZ_CMD_FILL_SHADE: + fz_fill_shade(dev, node->item.shade, ctm, node->alpha); + break; + case FZ_CMD_FILL_IMAGE: + fz_fill_image(dev, node->item.image, ctm, node->alpha); + break; + case FZ_CMD_FILL_IMAGE_MASK: + fz_fill_image_mask(dev, node->item.image, ctm, + node->colorspace, node->color, node->alpha); + break; + case FZ_CMD_CLIP_IMAGE_MASK: + { + fz_rect trect = fz_transform_rect(top_ctm, node->rect); + fz_clip_image_mask(dev, node->item.image, &trect, ctm); + break; + } + case FZ_CMD_POP_CLIP: + fz_pop_clip(dev); + break; + case FZ_CMD_BEGIN_MASK: + rect = fz_transform_rect(top_ctm, node->rect); + fz_begin_mask(dev, rect, node->flag, node->colorspace, node->color); + break; + case FZ_CMD_END_MASK: + fz_end_mask(dev); + break; + case FZ_CMD_BEGIN_GROUP: + rect = fz_transform_rect(top_ctm, node->rect); + fz_begin_group(dev, rect, + (node->flag & ISOLATED) != 0, (node->flag & KNOCKOUT) != 0, + node->item.blendmode, node->alpha); + break; + case FZ_CMD_END_GROUP: + fz_end_group(dev); + break; + case FZ_CMD_BEGIN_TILE: + tiled++; + rect.x0 = node->color[2]; + rect.y0 = node->color[3]; + rect.x1 = node->color[4]; + rect.y1 = node->color[5]; + fz_begin_tile(dev, node->rect, rect, + node->color[0], node->color[1], ctm); + break; + case FZ_CMD_END_TILE: + tiled--; + fz_end_tile(dev); + break; + } } - case FZ_CMD_FILL_TEXT: - fz_fill_text(dev, node->item.text, ctm, - node->colorspace, node->color, node->alpha); - break; - case FZ_CMD_STROKE_TEXT: - fz_stroke_text(dev, node->item.text, node->stroke, ctm, - node->colorspace, node->color, node->alpha); - break; - case FZ_CMD_CLIP_TEXT: - fz_clip_text(dev, node->item.text, ctm, node->flag); - break; - case FZ_CMD_CLIP_STROKE_TEXT: - fz_clip_stroke_text(dev, node->item.text, node->stroke, ctm); - break; - case FZ_CMD_IGNORE_TEXT: - fz_ignore_text(dev, node->item.text, ctm); - break; - case FZ_CMD_FILL_SHADE: - fz_fill_shade(dev, node->item.shade, ctm, node->alpha); - break; - case FZ_CMD_FILL_IMAGE: - fz_fill_image(dev, node->item.image, ctm, node->alpha); - break; - case FZ_CMD_FILL_IMAGE_MASK: - fz_fill_image_mask(dev, node->item.image, ctm, - node->colorspace, node->color, node->alpha); - break; - case FZ_CMD_CLIP_IMAGE_MASK: + fz_catch(ctx) { - fz_rect trect = fz_transform_rect(top_ctm, node->rect); - fz_clip_image_mask(dev, node->item.image, &trect, ctm); - break; - } - case FZ_CMD_POP_CLIP: - fz_pop_clip(dev); - break; - case FZ_CMD_BEGIN_MASK: - rect = fz_transform_rect(top_ctm, node->rect); - fz_begin_mask(dev, rect, node->flag, node->colorspace, node->color); - break; - case FZ_CMD_END_MASK: - fz_end_mask(dev); - break; - case FZ_CMD_BEGIN_GROUP: - rect = fz_transform_rect(top_ctm, node->rect); - fz_begin_group(dev, rect, - (node->flag & ISOLATED) != 0, (node->flag & KNOCKOUT) != 0, - node->item.blendmode, node->alpha); - break; - case FZ_CMD_END_GROUP: - fz_end_group(dev); - break; - case FZ_CMD_BEGIN_TILE: - tiled++; - rect.x0 = node->color[2]; - rect.y0 = node->color[3]; - rect.x1 = node->color[4]; - rect.y1 = node->color[5]; - fz_begin_tile(dev, node->rect, rect, - node->color[0], node->color[1], ctm); - break; - case FZ_CMD_END_TILE: - tiled--; - fz_end_tile(dev); - break; + /* Swallow the error */ + if (cookie) + cookie->errors++; + fz_warn(ctx, "Ignoring error during interpretation"); } } } diff --git a/fitz/fitz.h b/fitz/fitz.h index a10fd4dc..1892bc5e 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1750,12 +1750,15 @@ typedef struct fz_cookie_s fz_cookie; may change from -1 to a positive value once an upper bound is known, so take this into consideration when comparing the value of progress to that of progress_max. + + errors: count of errors during current rendering. */ struct fz_cookie_s { int abort; int progress; int progress_max; /* -1 for unknown */ + int errors; }; /* diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c index 8851be6e..870050df 100644 --- a/pdf/pdf_interpret.c +++ b/pdf/pdf_interpret.c @@ -2434,7 +2434,7 @@ pdf_run_keyword(pdf_csi *csi, pdf_obj *rdb, fz_stream *file, char *buf) } fz_catch(ctx) { - fz_warn(ctx, "cannot draw xobject/image"); + fz_throw(ctx, "cannot draw xobject/image"); } break; case C('E','M','C'): pdf_run_EMC(csi); break; @@ -2464,7 +2464,7 @@ pdf_run_keyword(pdf_csi *csi, pdf_obj *rdb, fz_stream *file, char *buf) } fz_catch(ctx) { - fz_warn(ctx, "cannot set font"); + fz_throw(ctx, "cannot set font"); } break; case B('T','j'): pdf_run_Tj(csi); break; @@ -2493,7 +2493,7 @@ pdf_run_keyword(pdf_csi *csi, pdf_obj *rdb, fz_stream *file, char *buf) } fz_catch(ctx) { - fz_warn(ctx, "cannot set graphics state"); + fz_throw(ctx, "cannot set graphics state"); } break; case A('h'): pdf_run_h(csi); break; @@ -2517,7 +2517,7 @@ pdf_run_keyword(pdf_csi *csi, pdf_obj *rdb, fz_stream *file, char *buf) } fz_catch(ctx) { - fz_warn(ctx, "cannot draw shading"); + fz_throw(ctx, "cannot draw shading"); } break; case A('v'): pdf_run_v(csi); break; @@ -2525,7 +2525,7 @@ pdf_run_keyword(pdf_csi *csi, pdf_obj *rdb, fz_stream *file, char *buf) case A('y'): pdf_run_y(csi); break; default: if (!csi->xbalance) - fz_warn(ctx, "unknown keyword: '%s'", buf); + fz_throw(ctx, "unknown keyword: '%s'", buf); break; } } @@ -2540,13 +2540,15 @@ pdf_run_stream(pdf_csi *csi, pdf_obj *rdb, fz_stream *file, pdf_lexbuf *buf) pdf_clear_stack(csi); in_array = 0; + fz_var(in_array); + if (csi->cookie) { csi->cookie->progress_max = -1; csi->cookie->progress = 0; } - while (1) + do { if (csi->top == nelem(csi->stack) - 1) fz_throw(ctx, "stack overflow"); @@ -2555,105 +2557,123 @@ pdf_run_stream(pdf_csi *csi, pdf_obj *rdb, fz_stream *file, pdf_lexbuf *buf) if (csi->cookie) { if (csi->cookie->abort) + { + tok = PDF_TOK_EOF; break; + } csi->cookie->progress++; } - tok = pdf_lex(file, buf); - /* RJW: "lexical error in content stream" */ - - if (in_array) + fz_try(ctx) { - if (tok == PDF_TOK_CLOSE_ARRAY) - { - in_array = 0; - } - else if (tok == PDF_TOK_REAL) - { - pdf_gstate *gstate = csi->gstate + csi->gtop; - pdf_show_space(csi, -buf->f * gstate->size * 0.001f); - } - else if (tok == PDF_TOK_INT) - { - pdf_gstate *gstate = csi->gstate + csi->gtop; - pdf_show_space(csi, -buf->i * gstate->size * 0.001f); - } - else if (tok == PDF_TOK_STRING) - { - pdf_show_string(csi, (unsigned char *)buf->scratch, buf->len); - } - else if (tok == PDF_TOK_KEYWORD) + tok = pdf_lex(file, buf); + /* RJW: "lexical error in content stream" */ + + if (in_array) { - if (!strcmp(buf->scratch, "Tw") || !strcmp(buf->scratch, "Tc")) - fz_warn(ctx, "ignoring keyword '%s' inside array", buf->scratch); + if (tok == PDF_TOK_CLOSE_ARRAY) + { + in_array = 0; + } + else if (tok == PDF_TOK_REAL) + { + pdf_gstate *gstate = csi->gstate + csi->gtop; + pdf_show_space(csi, -buf->f * gstate->size * 0.001f); + } + else if (tok == PDF_TOK_INT) + { + pdf_gstate *gstate = csi->gstate + csi->gtop; + pdf_show_space(csi, -buf->i * gstate->size * 0.001f); + } + else if (tok == PDF_TOK_STRING) + { + pdf_show_string(csi, (unsigned char *)buf->scratch, buf->len); + } + else if (tok == PDF_TOK_KEYWORD) + { + if (!strcmp(buf->scratch, "Tw") || !strcmp(buf->scratch, "Tc")) + fz_warn(ctx, "ignoring keyword '%s' inside array", buf->scratch); + else + fz_throw(ctx, "syntax error in array"); + } + else if (tok == PDF_TOK_EOF) + break; else fz_throw(ctx, "syntax error in array"); } - else if (tok == PDF_TOK_EOF) - return; - else - fz_throw(ctx, "syntax error in array"); - } - - else switch (tok) - { - case PDF_TOK_ENDSTREAM: - case PDF_TOK_EOF: - return; - case PDF_TOK_OPEN_ARRAY: - if (!csi->in_text) - { - csi->obj = pdf_parse_array(csi->xref, file, buf); - /* RJW: "cannot parse array" */ - } - else + else switch (tok) { - in_array = 1; - } - break; + case PDF_TOK_ENDSTREAM: + case PDF_TOK_EOF: + tok = PDF_TOK_EOF; + break; - case PDF_TOK_OPEN_DICT: - csi->obj = pdf_parse_dict(csi->xref, file, buf); - /* RJW: "cannot parse dictionary" */ - break; + case PDF_TOK_OPEN_ARRAY: + if (!csi->in_text) + { + csi->obj = pdf_parse_array(csi->xref, file, buf); + /* RJW: "cannot parse array" */ + } + else + { + in_array = 1; + } + break; - case PDF_TOK_NAME: - fz_strlcpy(csi->name, buf->scratch, sizeof(csi->name)); - break; + case PDF_TOK_OPEN_DICT: + csi->obj = pdf_parse_dict(csi->xref, file, buf); + /* RJW: "cannot parse dictionary" */ + break; - case PDF_TOK_INT: - csi->stack[csi->top] = buf->i; - csi->top ++; - break; + case PDF_TOK_NAME: + fz_strlcpy(csi->name, buf->scratch, sizeof(csi->name)); + break; - case PDF_TOK_REAL: - csi->stack[csi->top] = buf->f; - csi->top ++; - break; + case PDF_TOK_INT: + csi->stack[csi->top] = buf->i; + csi->top ++; + break; - case PDF_TOK_STRING: - if (buf->len <= sizeof(csi->string)) - { - memcpy(csi->string, buf->scratch, buf->len); - csi->string_len = buf->len; - } - else - { - csi->obj = pdf_new_string(ctx, buf->scratch, buf->len); - } - break; + case PDF_TOK_REAL: + csi->stack[csi->top] = buf->f; + csi->top ++; + break; - case PDF_TOK_KEYWORD: - pdf_run_keyword(csi, rdb, file, buf->scratch); - /* RJW: "cannot run keyword" */ - pdf_clear_stack(csi); - break; + case PDF_TOK_STRING: + if (buf->len <= sizeof(csi->string)) + { + memcpy(csi->string, buf->scratch, buf->len); + csi->string_len = buf->len; + } + else + { + csi->obj = pdf_new_string(ctx, buf->scratch, buf->len); + } + break; + + case PDF_TOK_KEYWORD: + pdf_run_keyword(csi, rdb, file, buf->scratch); + /* RJW: "cannot run keyword" */ + pdf_clear_stack(csi); + break; - default: - fz_throw(ctx, "syntax error in content stream"); + default: + fz_throw(ctx, "syntax error in content stream"); + } + } + fz_catch(ctx) + { + /* Swallow the error */ + if (csi->cookie) + csi->cookie->errors++; + fz_warn(ctx, "Ignoring error during rendering"); + /* If we do catch an error, then reset ourselves to a + * base lexing state */ + in_array = 0; } } + while (tok != PDF_TOK_EOF); } /* |