summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--draw/draw_device.c124
1 files changed, 61 insertions, 63 deletions
diff --git a/draw/draw_device.c b/draw/draw_device.c
index 0efe701a..165cb1a9 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;
@@ -46,18 +61,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
@@ -88,6 +94,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(sizeof(*stack) * max);
+ memcpy(stack, dev->stack, sizeof(*stack) * dev->stack_max);
+ }
+ else
+ {
+ stack = fz_realloc(dev->stack, max, sizeof(*stack));
+ }
+ dev->stack = stack;
+ dev->stack_max = max;
+}
+
static void fz_knockout_begin(void *user)
{
fz_draw_device *dev = user;
@@ -98,11 +122,8 @@ static void fz_knockout_begin(void *user)
if ((dev->blendmode & FZ_BLEND_KNOCKOUT) == 0)
return;
- if (dev->top == STACK_SIZE)
- {
- fz_warn("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);
@@ -159,11 +180,8 @@ static void fz_knockout_end(void *user)
if ((dev->blendmode & FZ_BLEND_KNOCKOUT) == 0)
return;
- if (dev->top == STACK_SIZE)
- {
- fz_warn("assert: too many buffers on stack");
- return;
- }
+ if (dev->top == dev->stack_max)
+ fz_grow_stack(dev);
if (dev->top > 0)
{
@@ -324,11 +342,8 @@ fz_draw_clip_path(void *user, fz_path *path, fz_rect *rect, int even_odd, fz_mat
fz_pixmap *mask, *dest, *shape;
fz_bbox bbox;
- if (dev->top == STACK_SIZE)
- {
- fz_warn("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);
@@ -395,11 +410,8 @@ fz_draw_clip_stroke_path(void *user, fz_path *path, fz_rect *rect, fz_stroke_sta
fz_pixmap *mask, *dest, *shape;
fz_bbox bbox;
- if (dev->top == STACK_SIZE)
- {
- fz_warn("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;
@@ -608,11 +620,8 @@ fz_draw_clip_text(void *user, 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("assert: too many buffers on stack");
- return;
- }
+ if (dev->top == dev->stack_max)
+ fz_grow_stack(dev);
if (accumulate == 0)
{
@@ -701,11 +710,8 @@ fz_draw_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_
fz_pixmap *glyph;
int i, x, y, gid;
- if (dev->top == STACK_SIZE)
- {
- fz_warn("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));
@@ -1042,11 +1048,8 @@ fz_draw_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix c
fz_pixmap *scaled = NULL;
int dx, dy;
- if (dev->top == STACK_SIZE)
- {
- fz_warn("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");
@@ -1185,11 +1188,8 @@ fz_draw_begin_mask(void *user, fz_rect rect, int luminosity, fz_colorspace *colo
fz_pixmap *shape = dev->shape;
fz_bbox bbox;
- if (dev->top == STACK_SIZE)
- {
- fz_warn("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);
@@ -1247,11 +1247,8 @@ fz_draw_end_mask(void *user)
fz_bbox bbox;
int luminosity;
- if (dev->top == STACK_SIZE)
- {
- fz_warn("assert: too many buffers on stack");
- return;
- }
+ if (dev->top == dev->stack_max)
+ fz_grow_stack(dev);
if (dev->top > 0)
{
@@ -1304,7 +1301,7 @@ fz_draw_begin_group(void *user, fz_rect rect, int isolated, int knockout, int bl
fz_bbox bbox;
fz_pixmap *dest, *shape;
- if (dev->top == STACK_SIZE)
+ if (dev->top == dev->stack_max)
{
fz_warn("assert: too many buffers on stack");
return;
@@ -1434,11 +1431,8 @@ fz_draw_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ys
/* area, view, xstep, ystep are in pattern space */
/* ctm maps from pattern space to device space */
- if (dev->top == STACK_SIZE)
- {
- fz_warn("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);
@@ -1524,6 +1518,8 @@ fz_draw_free_user(void *user)
/* TODO: pop and free the stacks */
if (dev->top > 0)
fz_warn("items left on stack in draw device: %d", dev->top);
+ if (dev->stack != &dev->init_stack[0])
+ fz_free(dev->stack);
fz_free_gel(dev->gel);
fz_free(dev);
}
@@ -1540,6 +1536,8 @@ fz_new_draw_device(fz_glyph_cache *cache, fz_pixmap *dest)
ddev->top = 0;
ddev->blendmode = 0;
ddev->flags = 0;
+ ddev->stack = &ddev->init_stack[0];
+ ddev->stack_max = STACK_SIZE;
ddev->scissor.x0 = dest->x;
ddev->scissor.y0 = dest->y;