diff options
-rw-r--r-- | draw/draw_device.c | 593 | ||||
-rw-r--r-- | fitz/base_error.c | 6 | ||||
-rw-r--r-- | fitz/dev_null.c | 211 | ||||
-rw-r--r-- | fitz/fitz-internal.h | 3 | ||||
-rw-r--r-- | fitz/fitz.h | 6 |
5 files changed, 525 insertions, 294 deletions
diff --git a/draw/draw_device.c b/draw/draw_device.c index a52c77ca..96c4dd53 100644 --- a/draw/draw_device.c +++ b/draw/draw_device.c @@ -109,6 +109,20 @@ push_stack(fz_draw_device *dev) return state; } +static void emergency_pop_stack(fz_draw_device *dev, fz_draw_state *state) +{ + fz_context *ctx = dev->ctx; + + if (state[1].mask != state[0].mask) + fz_drop_pixmap(ctx, state[1].mask); + if (state[1].dest != state[0].dest) + fz_drop_pixmap(ctx, state[1].dest); + if (state[1].shape != state[0].shape) + fz_drop_pixmap(ctx, state[1].shape); + dev->top--; + fz_rethrow(ctx); +} + static fz_draw_state * fz_knockout_begin(fz_draw_device *dev) { @@ -340,13 +354,17 @@ fz_draw_clip_path(fz_device *devp, fz_path *path, fz_rect *rect, int even_odd, f float expansion = fz_matrix_expansion(ctm); float flatness = 0.3f / expansion; fz_bbox bbox; - fz_draw_state *state = push_stack(dev); - fz_colorspace *model = state->dest->colorspace; + fz_draw_state *state = &dev->stack[dev->top]; + fz_colorspace *model; + fz_context *ctx = dev->ctx; fz_reset_gel(dev->gel, state->scissor); fz_flatten_fill_path(dev->gel, path, ctm, flatness); fz_sort_gel(dev->gel); + state = push_stack(dev); + model = state->dest->colorspace; + bbox = fz_bound_gel(dev->gel); bbox = fz_intersect_bbox(bbox, state->scissor); if (rect) @@ -362,23 +380,30 @@ fz_draw_clip_path(fz_device *devp, fz_path *path, fz_rect *rect, int even_odd, f return; } - state[1].mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); - fz_clear_pixmap(dev->ctx, state[1].mask); - state[1].dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); - fz_clear_pixmap(dev->ctx, state[1].dest); - if (state[1].shape) + fz_try(ctx) { - state[1].shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); - fz_clear_pixmap(dev->ctx, state[1].shape); - } + state[1].mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); + fz_clear_pixmap(dev->ctx, state[1].mask); + state[1].dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); + fz_clear_pixmap(dev->ctx, state[1].dest); + if (state[1].shape) + { + state[1].shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); + fz_clear_pixmap(dev->ctx, state[1].shape); + } - fz_scan_convert(dev->gel, even_odd, bbox, state[1].mask, NULL); + fz_scan_convert(dev->gel, even_odd, bbox, state[1].mask, NULL); - state[1].blendmode |= FZ_BLEND_ISOLATED; - state[1].scissor = bbox; + state[1].blendmode |= FZ_BLEND_ISOLATED; + state[1].scissor = bbox; #ifdef DUMP_GROUP_BLENDS - dump_spaces(dev->top-1, "Clip (non-rectangular) begin\n"); + dump_spaces(dev->top-1, "Clip (non-rectangular) begin\n"); #endif + } + fz_catch(ctx) + { + emergency_pop_stack(dev, state); + } } static void @@ -389,8 +414,9 @@ fz_draw_clip_stroke_path(fz_device *devp, fz_path *path, fz_rect *rect, fz_strok float flatness = 0.3f / expansion; float linewidth = stroke->linewidth; fz_bbox bbox; - fz_draw_state *state = push_stack(dev); - fz_colorspace *model = state->dest->colorspace; + fz_draw_state *state = &dev->stack[dev->top]; + fz_colorspace *model; + fz_context *ctx = dev->ctx; if (linewidth * expansion < 0.1f) linewidth = 1 / expansion; @@ -402,29 +428,39 @@ fz_draw_clip_stroke_path(fz_device *devp, fz_path *path, fz_rect *rect, fz_strok fz_flatten_stroke_path(dev->gel, path, stroke, ctm, flatness, linewidth); fz_sort_gel(dev->gel); + state = push_stack(dev); + model = state->dest->colorspace; + bbox = fz_bound_gel(dev->gel); bbox = fz_intersect_bbox(bbox, state->scissor); if (rect) bbox = fz_intersect_bbox(bbox, fz_bbox_covering_rect(*rect)); - state[1].mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); - fz_clear_pixmap(dev->ctx, state[1].mask); - state[1].dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); - fz_clear_pixmap(dev->ctx, state[1].dest); - if (state->shape) + fz_try(ctx) { - state[1].shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); - fz_clear_pixmap(dev->ctx, state[1].shape); - } + state[1].mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); + fz_clear_pixmap(dev->ctx, state[1].mask); + state[1].dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); + fz_clear_pixmap(dev->ctx, state[1].dest); + if (state->shape) + { + state[1].shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); + fz_clear_pixmap(dev->ctx, state[1].shape); + } - if (!fz_is_empty_rect(bbox)) - fz_scan_convert(dev->gel, 0, bbox, state[1].mask, NULL); + if (!fz_is_empty_rect(bbox)) + fz_scan_convert(dev->gel, 0, bbox, state[1].mask, NULL); - state[1].blendmode |= FZ_BLEND_ISOLATED; - state[1].scissor = bbox; + state[1].blendmode |= FZ_BLEND_ISOLATED; + state[1].scissor = bbox; #ifdef DUMP_GROUP_BLENDS - dump_spaces(dev->top-1, "Clip (stroke) begin\n"); + dump_spaces(dev->top-1, "Clip (stroke) begin\n"); #endif + } + fz_catch(ctx) + { + emergency_pop_stack(dev, state); + } } static void @@ -645,97 +681,106 @@ fz_draw_clip_text(fz_device *devp, fz_text *text, fz_matrix ctm, int accumulate) bbox = state->scissor; } - if (accumulate == 0 || accumulate == 1) + fz_try(ctx) { - mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); - fz_clear_pixmap(dev->ctx, mask); - dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); - fz_clear_pixmap(dev->ctx, dest); - if (state->shape) + if (accumulate == 0 || accumulate == 1) { - shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); - fz_clear_pixmap(dev->ctx, shape); - } - else - shape = NULL; + mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); + fz_clear_pixmap(dev->ctx, mask); + dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); + fz_clear_pixmap(dev->ctx, dest); + if (state->shape) + { + shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); + fz_clear_pixmap(dev->ctx, shape); + } + else + shape = NULL; - state[1].blendmode |= FZ_BLEND_ISOLATED; - state[1].scissor = bbox; - state[1].dest = dest; - state[1].mask = mask; - state[1].shape = shape; + state[1].blendmode |= FZ_BLEND_ISOLATED; + state[1].scissor = bbox; + state[1].dest = dest; + state[1].mask = mask; + state[1].shape = shape; #ifdef DUMP_GROUP_BLENDS - dump_spaces(dev->top-1, "Clip (text) begin\n"); + dump_spaces(dev->top-1, "Clip (text) begin\n"); #endif - } - else - { - mask = state->mask; - dev->top--; - } - - if (!fz_is_empty_rect(bbox) && mask) - { - tm = text->trm; + } + else + { + mask = state->mask; + dev->top--; + } - for (i = 0; i < text->len; i++) + if (!fz_is_empty_rect(bbox) && mask) { - gid = text->items[i].gid; - if (gid < 0) - continue; - - tm.e = text->items[i].x; - tm.f = text->items[i].y; - trm = fz_concat(tm, ctm); - x = floorf(trm.e); - y = floorf(trm.f); - - trunc_trm = trm; - trunc_trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); - trunc_trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); - - glyph = fz_render_glyph(dev->ctx, text->font, gid, trunc_trm, model, bbox); - if (glyph) - { - draw_glyph(NULL, mask, glyph, x, y, bbox); - if (state[1].shape) - draw_glyph(NULL, state[1].shape, glyph, x, y, bbox); - fz_drop_pixmap(dev->ctx, glyph); - } - else + tm = text->trm; + + for (i = 0; i < text->len; i++) { - fz_path *path = fz_outline_glyph(dev->ctx, text->font, gid, trm); - if (path) + gid = text->items[i].gid; + if (gid < 0) + continue; + + tm.e = text->items[i].x; + tm.f = text->items[i].y; + trm = fz_concat(tm, ctm); + x = floorf(trm.e); + y = floorf(trm.f); + + trunc_trm = trm; + trunc_trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); + trunc_trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); + + glyph = fz_render_glyph(dev->ctx, text->font, gid, trunc_trm, model, bbox); + if (glyph) { - fz_pixmap *old_dest; - float white = 1; - - state = &dev->stack[dev->top]; - old_dest = state[0].dest; - state[0].dest = state[0].mask; - state[0].mask = NULL; - fz_try(ctx) - { - fz_draw_fill_path(devp, path, 0, fz_identity, fz_device_gray, &white, 1); - } - fz_always(ctx) + draw_glyph(NULL, mask, glyph, x, y, bbox); + if (state[1].shape) + draw_glyph(NULL, state[1].shape, glyph, x, y, bbox); + fz_drop_pixmap(dev->ctx, glyph); + } + else + { + fz_path *path = fz_outline_glyph(dev->ctx, text->font, gid, trm); + if (path) { - state[0].mask = state[0].dest; - state[0].dest = old_dest; - fz_free_path(dev->ctx, path); + fz_pixmap *old_dest; + float white = 1; + + state = &dev->stack[dev->top]; + old_dest = state[0].dest; + state[0].dest = state[0].mask; + state[0].mask = NULL; + fz_try(ctx) + { + fz_draw_fill_path(devp, path, 0, fz_identity, fz_device_gray, &white, 1); + } + fz_always(ctx) + { + state[0].mask = state[0].dest; + state[0].dest = old_dest; + fz_free_path(dev->ctx, path); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } } - fz_catch(ctx) + else { - fz_rethrow(ctx); + fz_warn(dev->ctx, "cannot render glyph for clipping"); } } - else - { - fz_warn(dev->ctx, "cannot render glyph for clipping"); - } } } } + fz_catch(ctx) + { + if (accumulate == 0 || accumulate == 1) + emergency_pop_stack(dev, state); + fz_rethrow(ctx); + } } static void @@ -755,89 +800,93 @@ fz_draw_clip_stroke_text(fz_device *devp, fz_text *text, fz_stroke_state *stroke bbox = fz_bbox_covering_rect(fz_bound_text(dev->ctx, text, ctm)); bbox = fz_intersect_bbox(bbox, state->scissor); - mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); - fz_clear_pixmap(dev->ctx, mask); - dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); - fz_clear_pixmap(dev->ctx, dest); - if (state->shape) + fz_try(ctx) { - shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); - fz_clear_pixmap(dev->ctx, shape); - } - else - shape = state->shape; + state[1].mask = mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); + fz_clear_pixmap(dev->ctx, mask); + state[1].dest = dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); + fz_clear_pixmap(dev->ctx, dest); + if (state->shape) + { + state[1].shape = shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); + fz_clear_pixmap(dev->ctx, shape); + } + else + shape = state->shape; - state[1].blendmode |= FZ_BLEND_ISOLATED; - state[1].scissor = bbox; - state[1].dest = dest; - state[1].shape = shape; - state[1].mask = mask; + state[1].blendmode |= FZ_BLEND_ISOLATED; + state[1].scissor = bbox; #ifdef DUMP_GROUP_BLENDS - dump_spaces(dev->top-1, "Clip (stroke text) begin\n"); + dump_spaces(dev->top-1, "Clip (stroke text) begin\n"); #endif - if (!fz_is_empty_rect(bbox)) - { - tm = text->trm; - - for (i = 0; i < text->len; i++) + if (!fz_is_empty_rect(bbox)) { - gid = text->items[i].gid; - if (gid < 0) - continue; - - tm.e = text->items[i].x; - tm.f = text->items[i].y; - trm = fz_concat(tm, ctm); - x = floorf(trm.e); - y = floorf(trm.f); - - trunc_trm = trm; - trunc_trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); - trunc_trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); - - glyph = fz_render_stroked_glyph(dev->ctx, text->font, gid, trunc_trm, ctm, stroke, bbox); - if (glyph) - { - draw_glyph(NULL, mask, glyph, x, y, bbox); - if (shape) - draw_glyph(NULL, shape, glyph, x, y, bbox); - fz_drop_pixmap(dev->ctx, glyph); - } - else + tm = text->trm; + + for (i = 0; i < text->len; i++) { - fz_path *path = fz_outline_glyph(dev->ctx, text->font, gid, trm); - if (path) + gid = text->items[i].gid; + if (gid < 0) + continue; + + tm.e = text->items[i].x; + tm.f = text->items[i].y; + trm = fz_concat(tm, ctm); + x = floorf(trm.e); + y = floorf(trm.f); + + trunc_trm = trm; + trunc_trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX); + trunc_trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX); + + glyph = fz_render_stroked_glyph(dev->ctx, text->font, gid, trunc_trm, ctm, stroke, bbox); + if (glyph) { - fz_pixmap *old_dest; - float white = 1; - - state = &dev->stack[dev->top]; - old_dest = state[0].dest; - state[0].dest = state[0].mask; - state[0].mask = NULL; - fz_try(ctx) - { - fz_draw_stroke_path(devp, path, stroke, fz_identity, fz_device_gray, &white, 1); - } - fz_always(ctx) + draw_glyph(NULL, mask, glyph, x, y, bbox); + if (shape) + draw_glyph(NULL, shape, glyph, x, y, bbox); + fz_drop_pixmap(dev->ctx, glyph); + } + else + { + fz_path *path = fz_outline_glyph(dev->ctx, text->font, gid, trm); + if (path) { - state[0].mask = state[0].dest; - state[0].dest = old_dest; - fz_free_path(dev->ctx, path); + fz_pixmap *old_dest; + float white = 1; + + state = &dev->stack[dev->top]; + old_dest = state[0].dest; + state[0].dest = state[0].mask; + state[0].mask = NULL; + fz_try(ctx) + { + fz_draw_stroke_path(devp, path, stroke, fz_identity, fz_device_gray, &white, 1); + } + fz_always(ctx) + { + state[0].mask = state[0].dest; + state[0].dest = old_dest; + fz_free_path(dev->ctx, path); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } } - fz_catch(ctx) + else { - fz_rethrow(ctx); + fz_warn(dev->ctx, "cannot render glyph for stroked clipping"); } } - else - { - fz_warn(dev->ctx, "cannot render glyph for stroked clipping"); - } } } } + fz_catch(ctx) + { + emergency_pop_stack(dev, state); + } } static void @@ -1177,8 +1226,8 @@ fz_draw_clip_image_mask(fz_device *devp, fz_image *image, fz_rect *rect, fz_matr fz_pixmap *dest = NULL; fz_pixmap *shape = NULL; fz_pixmap *scaled = NULL; - fz_pixmap *pixmap; - fz_pixmap *orig_pixmap; + fz_pixmap *pixmap = NULL; + fz_pixmap *orig_pixmap = NULL; int dx, dy; fz_draw_state *state = push_stack(dev); fz_colorspace *model = state->dest->colorspace; @@ -1189,6 +1238,8 @@ fz_draw_clip_image_mask(fz_device *devp, fz_image *image, fz_rect *rect, fz_matr fz_var(mask); fz_var(dest); fz_var(shape); + fz_var(pixmap); + fz_var(orig_pixmap); if (image->w == 0 || image->h == 0) { @@ -1211,22 +1262,26 @@ fz_draw_clip_image_mask(fz_device *devp, fz_image *image, fz_rect *rect, fz_matr dx = sqrtf(ctm.a * ctm.a + ctm.b * ctm.b); dy = sqrtf(ctm.c * ctm.c + ctm.d * ctm.d); - pixmap = fz_image_to_pixmap(ctx, image, dx, dy); - orig_pixmap = pixmap; fz_try(ctx) { - mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); + pixmap = fz_image_to_pixmap(ctx, image, dx, dy); + orig_pixmap = pixmap; + + state[1].mask = mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); fz_clear_pixmap(dev->ctx, mask); - dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); + state[1].dest = dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); fz_clear_pixmap(dev->ctx, dest); if (state->shape) { - shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); + state[1].shape = shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); fz_clear_pixmap(dev->ctx, shape); } + state[1].blendmode |= FZ_BLEND_ISOLATED; + state[1].scissor = bbox; + if (dx < pixmap->w && dy < pixmap->h) { int gridfit = !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3); @@ -1243,7 +1298,6 @@ fz_draw_clip_image_mask(fz_device *devp, fz_image *image, fz_rect *rect, fz_matr pixmap = scaled; } fz_paint_image(mask, bbox, state->shape, pixmap, ctm, 255); - } fz_always(ctx) { @@ -1252,17 +1306,8 @@ fz_draw_clip_image_mask(fz_device *devp, fz_image *image, fz_rect *rect, fz_matr } fz_catch(ctx) { - fz_drop_pixmap(ctx, shape); - fz_drop_pixmap(ctx, dest); - fz_drop_pixmap(ctx, mask); - fz_rethrow(ctx); + emergency_pop_stack(dev, state); } - - state[1].blendmode |= FZ_BLEND_ISOLATED; - state[1].scissor = bbox; - state[1].dest = dest; - state[1].shape = shape; - state[1].mask = mask; } static void @@ -1325,45 +1370,52 @@ fz_draw_begin_mask(fz_device *devp, fz_rect rect, int luminosity, fz_colorspace fz_bbox bbox; fz_draw_state *state = push_stack(dev); fz_pixmap *shape = state->shape; + fz_context *ctx = dev->ctx; bbox = fz_bbox_covering_rect(rect); bbox = fz_intersect_bbox(bbox, state->scissor); - dest = fz_new_pixmap_with_bbox(dev->ctx, fz_device_gray, bbox); - if (state->shape) - { - /* FIXME: If we ever want to support AIS true, then we - * probably want to create a shape pixmap here, using: - * shape = fz_new_pixmap_with_bbox(NULL, bbox); - * then, in the end_mask code, we create the mask from this - * rather than dest. - */ - shape = NULL; - } - if (luminosity) - { - float bc; - if (!colorspace) - colorspace = fz_device_gray; - fz_convert_color(dev->ctx, fz_device_gray, &bc, colorspace, colorfv); - fz_clear_pixmap_with_value(dev->ctx, dest, bc * 255); - if (shape) - fz_clear_pixmap_with_value(dev->ctx, shape, 255); - } - else + fz_try(ctx) { - fz_clear_pixmap(dev->ctx, dest); - if (shape) - fz_clear_pixmap(dev->ctx, shape); - } + state[1].dest = dest = fz_new_pixmap_with_bbox(dev->ctx, fz_device_gray, bbox); + if (state->shape) + { + /* FIXME: If we ever want to support AIS true, then + * we probably want to create a shape pixmap here, + * using: shape = fz_new_pixmap_with_bbox(NULL, bbox); + * then, in the end_mask code, we create the mask + * from this rather than dest. + */ + state[1].shape = shape = NULL; + } + + if (luminosity) + { + float bc; + if (!colorspace) + colorspace = fz_device_gray; + fz_convert_color(dev->ctx, fz_device_gray, &bc, colorspace, colorfv); + fz_clear_pixmap_with_value(dev->ctx, dest, bc * 255); + if (shape) + fz_clear_pixmap_with_value(dev->ctx, shape, 255); + } + else + { + fz_clear_pixmap(dev->ctx, dest); + if (shape) + fz_clear_pixmap(dev->ctx, shape); + } #ifdef DUMP_GROUP_BLENDS - dump_spaces(dev->top-1, "Mask begin\n"); + dump_spaces(dev->top-1, "Mask begin\n"); #endif - state[1].scissor = bbox; - state[1].dest = dest; - state[1].shape = shape; - state[1].luminosity = luminosity; + state[1].scissor = bbox; + state[1].luminosity = luminosity; + } + fz_catch(ctx) + { + emergency_pop_stack(dev, state); + } } static void @@ -1435,51 +1487,49 @@ fz_draw_begin_group(fz_device *devp, fz_rect rect, int isolated, int knockout, i state = push_stack(dev); bbox = fz_bbox_covering_rect(rect); bbox = fz_intersect_bbox(bbox, state->scissor); - dest = fz_new_pixmap_with_bbox(ctx, model, bbox); + + fz_try(ctx) + { + state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, bbox); #ifndef ATTEMPT_KNOCKOUT_AND_ISOLATED - knockout = 0; - isolated = 1; + knockout = 0; + isolated = 1; #endif - if (isolated) - { - fz_clear_pixmap(dev->ctx, dest); - } - else - { - fz_copy_pixmap_rect(dev->ctx, dest, state[0].dest, bbox); - } + if (isolated) + { + fz_clear_pixmap(dev->ctx, dest); + } + else + { + fz_copy_pixmap_rect(dev->ctx, dest, state[0].dest, bbox); + } - if (blendmode == 0 && alpha == 1.0 && isolated) - { - /* We can render direct to any existing shape plane. If there - * isn't one, we don't need to make one. */ - shape = state[0].shape; - } - else - { - fz_try(ctx) + if (blendmode == 0 && alpha == 1.0 && isolated) { - shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox); - fz_clear_pixmap(dev->ctx, shape); + /* We can render direct to any existing shape plane. + * If there isn't one, we don't need to make one. */ + state[1].shape =shape = state[0].shape; } - fz_catch(ctx) + else { - fz_drop_pixmap(ctx, dest); - fz_rethrow(ctx); + state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox); + fz_clear_pixmap(dev->ctx, shape); } - } - state[1].alpha = alpha; + state[1].alpha = alpha; #ifdef DUMP_GROUP_BLENDS - dump_spaces(dev->top-1, "Group begin\n"); + dump_spaces(dev->top-1, "Group begin\n"); #endif - state[1].scissor = bbox; - state[1].dest = dest; - state[1].shape = shape; - state[1].blendmode = blendmode | (isolated ? FZ_BLEND_ISOLATED : 0) | (knockout ? FZ_BLEND_KNOCKOUT : 0); + state[1].scissor = bbox; + state[1].blendmode = blendmode | (isolated ? FZ_BLEND_ISOLATED : 0) | (knockout ? FZ_BLEND_KNOCKOUT : 0); + } + fz_catch(ctx) + { + emergency_pop_stack(dev, state); + } } static void @@ -1568,35 +1618,32 @@ fz_draw_begin_tile(fz_device *devp, fz_rect area, fz_rect view, float xstep, flo * assert(bbox.x0 > state->dest->x || bbox.x1 < state->dest->x + state->dest->w || * bbox.y0 > state->dest->y || bbox.y1 < state->dest->y + state->dest->h); */ - dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); - fz_clear_pixmap(ctx, dest); - shape = state[0].shape; - if (shape) + fz_try(ctx) { - fz_var(shape); - fz_try(ctx) + state[1].dest = dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); + fz_clear_pixmap(ctx, dest); + shape = state[0].shape; + if (shape) { - shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); + state[1].shape = shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); fz_clear_pixmap(ctx, shape); } - fz_catch(ctx) - { - fz_drop_pixmap(ctx, dest); - fz_rethrow(ctx); - } - } - state[1].blendmode |= FZ_BLEND_ISOLATED; - state[1].xstep = xstep; - state[1].ystep = ystep; - state[1].area = area; - state[1].ctm = ctm; + state[1].blendmode |= FZ_BLEND_ISOLATED; + state[1].xstep = xstep; + state[1].ystep = ystep; + state[1].area = area; + state[1].ctm = ctm; #ifdef DUMP_GROUP_BLENDS - dump_spaces(dev->top-1, "Tile begin\n"); + dump_spaces(dev->top-1, "Tile begin\n"); #endif - state[1].scissor = bbox; - state[1].dest = dest; - state[1].shape = shape; + state[1].scissor = bbox; + } + fz_catch(ctx) + { + emergency_pop_stack(dev, state); + } + } static void diff --git a/fitz/base_error.c b/fitz/base_error.c index 0167611a..5ec97a0a 100644 --- a/fitz/base_error.c +++ b/fitz/base_error.c @@ -18,7 +18,7 @@ void fz_flush_warnings(fz_context *ctx) ctx->warn->count = 0; } -void fz_warn(fz_context *ctx, char *fmt, ...) +void fz_warn(fz_context *ctx, const char *fmt, ...) { va_list ap; char buf[sizeof ctx->warn->message]; @@ -100,14 +100,14 @@ int fz_push_try(fz_error_context *ex) return 0; } -char *fz_caught(fz_context *ctx) +const char *fz_caught(fz_context *ctx) { assert(ctx); assert(ctx->error); return ctx->error->message; } -void fz_throw(fz_context *ctx, char *fmt, ...) +void fz_throw(fz_context *ctx, const char *fmt, ...) { va_list args; va_start(args, fmt); diff --git a/fitz/dev_null.c b/fitz/dev_null.c index 886cebe1..ac495cef 100644 --- a/fitz/dev_null.c +++ b/fitz/dev_null.c @@ -8,6 +8,7 @@ fz_new_device(fz_context *ctx, void *user) dev->flags = 0; dev->user = user; dev->ctx = ctx; + dev->error_depth = 0; return dev; } @@ -25,6 +26,8 @@ void fz_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { + if (dev->error_depth) + return; if (dev->fill_path) dev->fill_path(dev, path, even_odd, ctm, colorspace, color, alpha); } @@ -33,6 +36,8 @@ void fz_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { + if (dev->error_depth) + return; if (dev->stroke_path) dev->stroke_path(dev, path, stroke, ctm, colorspace, color, alpha); } @@ -40,21 +45,57 @@ fz_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix 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, path, rect, even_odd, ctm); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->clip_path) + dev->clip_path(dev, path, rect, even_odd, ctm); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } 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, path, rect, stroke, ctm); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->clip_stroke_path) + dev->clip_stroke_path(dev, path, rect, stroke, ctm); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { + if (dev->error_depth) + return; if (dev->fill_text) dev->fill_text(dev, text, ctm, colorspace, color, alpha); } @@ -63,6 +104,8 @@ void fz_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { + if (dev->error_depth) + return; if (dev->stroke_text) dev->stroke_text(dev, text, stroke, ctm, colorspace, color, alpha); } @@ -70,20 +113,59 @@ fz_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix void fz_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate) { - if (dev->clip_text) - dev->clip_text(dev, text, ctm, accumulate); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + if (accumulate == 0 || accumulate == 1) + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->clip_text) + dev->clip_text(dev, text, ctm, accumulate); + } + fz_catch(ctx) + { + if (accumulate == 2) + fz_rethrow(ctx); + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } 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, text, stroke, ctm); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->clip_stroke_text) + dev->clip_stroke_text(dev, text, stroke, ctm); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) { + if (dev->error_depth) + return; if (dev->ignore_text) dev->ignore_text(dev, text, ctm); } @@ -91,6 +173,12 @@ fz_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) void fz_pop_clip(fz_device *dev) { + if (dev->error_depth) + { + dev->error_depth--; + if (dev->error_depth == 0) + fz_throw(dev->ctx, "%s", dev->errmess); + } if (dev->pop_clip) dev->pop_clip(dev); } @@ -98,6 +186,8 @@ fz_pop_clip(fz_device *dev) void fz_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) { + if (dev->error_depth) + return; if (dev->fill_shade) dev->fill_shade(dev, shade, ctm, alpha); } @@ -105,6 +195,8 @@ fz_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) void fz_fill_image(fz_device *dev, fz_image *image, fz_matrix ctm, float alpha) { + if (dev->error_depth) + return; if (dev->fill_image) dev->fill_image(dev, image, ctm, alpha); } @@ -113,6 +205,8 @@ void fz_fill_image_mask(fz_device *dev, fz_image *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { + if (dev->error_depth) + return; if (dev->fill_image_mask) dev->fill_image_mask(dev, image, ctm, colorspace, color, alpha); } @@ -120,20 +214,59 @@ fz_fill_image_mask(fz_device *dev, fz_image *image, fz_matrix ctm, void fz_clip_image_mask(fz_device *dev, fz_image *image, fz_rect *rect, fz_matrix ctm) { - if (dev->clip_image_mask) - dev->clip_image_mask(dev, image, rect, ctm); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->clip_image_mask) + dev->clip_image_mask(dev, image, rect, ctm); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } 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, area, luminosity, colorspace, bc); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->begin_mask) + dev->begin_mask(dev, area, luminosity, colorspace, bc); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_end_mask(fz_device *dev) { + if (dev->error_depth) + { + /* Converts from mask to clip, so no change in stack depth */ + return; + } if (dev->end_mask) dev->end_mask(dev); } @@ -141,13 +274,36 @@ fz_end_mask(fz_device *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, area, isolated, knockout, blendmode, alpha); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->begin_group) + dev->begin_group(dev, area, isolated, knockout, blendmode, alpha); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_end_group(fz_device *dev) { + if (dev->error_depth) + { + dev->error_depth--; + if (dev->error_depth == 0) + fz_throw(dev->ctx, "%s", dev->errmess); + } if (dev->end_group) dev->end_group(dev); } @@ -155,13 +311,36 @@ 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) { - if (dev->begin_tile) - dev->begin_tile(dev, area, view, xstep, ystep, ctm); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->begin_tile) + dev->begin_tile(dev, area, view, xstep, ystep, ctm); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_end_tile(fz_device *dev) { + if (dev->error_depth) + { + dev->error_depth--; + if (dev->error_depth == 0) + fz_throw(dev->ctx, "%s", dev->errmess); + } if (dev->end_tile) dev->end_tile(dev); } diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 0de2e4c2..35b20d71 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -1396,6 +1396,9 @@ struct fz_device_s void (*begin_tile)(fz_device *, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm); void (*end_tile)(fz_device *); + + int error_depth; + char errmess[256]; }; void fz_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); diff --git a/fitz/fitz.h b/fitz/fitz.h index 8f2a6edc..ed515642 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -261,9 +261,11 @@ void fz_var_imp(void *); if (ctx->error->stack[ctx->error->top--].code > 1) int fz_push_try(fz_error_context *ex); -void fz_throw(fz_context *, char *, ...) __printflike(2, 3); +void fz_throw(fz_context *, const char *, ...) __printflike(2, 3); void fz_rethrow(fz_context *); -void fz_warn(fz_context *ctx, char *fmt, ...) __printflike(2, 3); +void fz_warn(fz_context *ctx, const char *fmt, ...) __printflike(2, 3); +const char *fz_caught(fz_context *ctx); + /* fz_flush_warnings: Flush any repeated warnings. |