diff options
Diffstat (limited to 'draw/draw_device.c')
-rw-r--r-- | draw/draw_device.c | 124 |
1 files changed, 61 insertions, 63 deletions
diff --git a/draw/draw_device.c b/draw/draw_device.c index 5407d618..7e40ef3f 100644 --- a/draw/draw_device.c +++ b/draw/draw_device.c @@ -34,6 +34,21 @@ enum { FZ_DRAWDEV_FLAGS_TYPE3 = 1, }; +typedef struct fz_draw_stack_s fz_draw_stack; + +struct fz_draw_stack_s { + fz_bbox scissor; + fz_pixmap *dest; + fz_pixmap *mask; + fz_pixmap *shape; + int blendmode; + int luminosity; + float alpha; + fz_matrix ctm; + float xstep, ystep; + fz_rect area; +}; + struct fz_draw_device_s { fz_glyph_cache *cache; @@ -47,18 +62,9 @@ struct fz_draw_device_s int flags; int top; int blendmode; - struct { - fz_bbox scissor; - fz_pixmap *dest; - fz_pixmap *mask; - fz_pixmap *shape; - int blendmode; - int luminosity; - float alpha; - fz_matrix ctm; - float xstep, ystep; - fz_rect area; - } stack[STACK_SIZE]; + fz_draw_stack *stack; + int stack_max; + fz_draw_stack init_stack[STACK_SIZE]; }; #ifdef DUMP_GROUP_BLENDS @@ -89,6 +95,24 @@ static void dump_spaces(int x, const char *s) #endif +static void fz_grow_stack(fz_draw_device *dev) +{ + int max = dev->stack_max * 2; + fz_draw_stack *stack; + + if (dev->stack == &dev->init_stack[0]) + { + stack = fz_malloc(dev->ctx, sizeof(*stack) * max); + memcpy(stack, dev->stack, sizeof(*stack) * dev->stack_max); + } + else + { + stack = fz_resize_array(dev->ctx, dev->stack, max, sizeof(*stack)); + } + dev->stack = stack; + dev->stack_max = max; +} + static void fz_knockout_begin(fz_draw_device *dev) { fz_bbox bbox; @@ -98,11 +122,8 @@ static void fz_knockout_begin(fz_draw_device *dev) if ((dev->blendmode & FZ_BLEND_KNOCKOUT) == 0) return; - if (dev->top == STACK_SIZE) - { - fz_warn(dev->ctx, "assert: too many buffers on stack"); - return; - } + if (dev->top == dev->stack_max) + fz_grow_stack(dev); bbox = fz_bound_pixmap(dev->dest); bbox = fz_intersect_bbox(bbox, dev->scissor); @@ -158,11 +179,8 @@ static void fz_knockout_end(fz_draw_device *dev) if ((dev->blendmode & FZ_BLEND_KNOCKOUT) == 0) return; - if (dev->top == STACK_SIZE) - { - fz_warn(dev->ctx, "assert: too many buffers on stack"); - return; - } + if (dev->top == dev->stack_max) + fz_grow_stack(dev); if (dev->top > 0) { @@ -323,11 +341,8 @@ fz_draw_clip_path(fz_device *devp, fz_path *path, fz_rect *rect, int even_odd, f fz_pixmap *mask, *dest, *shape; fz_bbox bbox; - if (dev->top == STACK_SIZE) - { - fz_warn(dev->ctx, "assert: too many buffers on stack"); - return; - } + if (dev->top == dev->stack_max) + fz_grow_stack(dev); fz_reset_gel(dev->gel, dev->scissor); fz_flatten_fill_path(dev->gel, path, ctm, flatness); @@ -394,11 +409,8 @@ fz_draw_clip_stroke_path(fz_device *devp, fz_path *path, fz_rect *rect, fz_strok fz_pixmap *mask, *dest, *shape; fz_bbox bbox; - if (dev->top == STACK_SIZE) - { - fz_warn(dev->ctx, "assert: too many buffers on stack"); - return; - } + if (dev->top == dev->stack_max) + fz_grow_stack(dev); if (linewidth * expansion < 0.1f) linewidth = 1 / expansion; @@ -607,11 +619,8 @@ fz_draw_clip_text(fz_device *devp, fz_text *text, fz_matrix ctm, int accumulate) /* If accumulate == 1 then this text object is the first (or only) in a sequence */ /* If accumulate == 2 then this text object is a continuation */ - if (dev->top == STACK_SIZE) - { - fz_warn(dev->ctx, "assert: too many buffers on stack"); - return; - } + if (dev->top == dev->stack_max) + fz_grow_stack(dev); if (accumulate == 0) { @@ -700,11 +709,8 @@ fz_draw_clip_stroke_text(fz_device *devp, fz_text *text, fz_stroke_state *stroke fz_pixmap *glyph; int i, x, y, gid; - if (dev->top == STACK_SIZE) - { - fz_warn(dev->ctx, "assert: too many buffers on stack"); - return; - } + if (dev->top == dev->stack_max) + fz_grow_stack(dev); /* make the mask the exact size needed */ bbox = fz_round_rect(fz_bound_text(text, ctm)); @@ -1041,11 +1047,8 @@ fz_draw_clip_image_mask(fz_device *devp, fz_pixmap *image, fz_rect *rect, fz_mat fz_pixmap *scaled = NULL; int dx, dy; - if (dev->top == STACK_SIZE) - { - fz_warn(dev->ctx, "assert: too many buffers on stack"); - return; - } + if (dev->top == dev->stack_max) + fz_grow_stack(dev); #ifdef DUMP_GROUP_BLENDS dump_spaces(dev->top, "Clip (image mask) begin\n"); @@ -1184,11 +1187,8 @@ fz_draw_begin_mask(fz_device *devp, fz_rect rect, int luminosity, fz_colorspace fz_pixmap *shape = dev->shape; fz_bbox bbox; - if (dev->top == STACK_SIZE) - { - fz_warn(dev->ctx, "assert: too many buffers on stack"); - return; - } + if (dev->top == dev->stack_max) + fz_grow_stack(dev); bbox = fz_round_rect(rect); bbox = fz_intersect_bbox(bbox, dev->scissor); @@ -1246,11 +1246,8 @@ fz_draw_end_mask(fz_device *devp) fz_bbox bbox; int luminosity; - if (dev->top == STACK_SIZE) - { - fz_warn(dev->ctx, "assert: too many buffers on stack"); - return; - } + if (dev->top == dev->stack_max) + fz_grow_stack(dev); if (dev->top > 0) { @@ -1303,7 +1300,7 @@ fz_draw_begin_group(fz_device *devp, fz_rect rect, int isolated, int knockout, i fz_bbox bbox; fz_pixmap *dest, *shape; - if (dev->top == STACK_SIZE) + if (dev->top == dev->stack_max) { fz_warn(dev->ctx, "assert: too many buffers on stack"); return; @@ -1433,11 +1430,8 @@ fz_draw_begin_tile(fz_device *devp, fz_rect area, fz_rect view, float xstep, flo /* area, view, xstep, ystep are in pattern space */ /* ctm maps from pattern space to device space */ - if (dev->top == STACK_SIZE) - { - fz_warn(dev->ctx, "assert: too many buffers on stack"); - return; - } + if (dev->top == dev->stack_max) + fz_grow_stack(dev); if (dev->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_begin(dev); @@ -1523,6 +1517,8 @@ fz_draw_free_user(fz_device *devp) /* TODO: pop and free the stacks */ if (dev->top > 0) fz_warn(dev->ctx, "items left on stack in draw device: %d", dev->top); + if (dev->stack != &dev->init_stack[0]) + fz_free(dev->ctx, dev->stack); fz_free_gel(dev->gel); fz_free(devp->ctx, dev); } @@ -1540,6 +1536,8 @@ fz_new_draw_device(fz_context *ctx, fz_glyph_cache *cache, fz_pixmap *dest) ddev->blendmode = 0; ddev->flags = 0; ddev->ctx = ctx; + ddev->stack = &ddev->init_stack[0]; + ddev->stack_max = STACK_SIZE; ddev->scissor.x0 = dest->x; ddev->scissor.y0 = dest->y; |