summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/pdfapp.c21
-rw-r--r--apps/pdfapp.h1
-rw-r--r--fitz/dev_list.c179
-rw-r--r--fitz/fitz.h3
-rw-r--r--pdf/pdf_interpret.c190
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);
}
/*