diff options
Diffstat (limited to 'source/fitz/draw-device.c')
-rw-r--r-- | source/fitz/draw-device.c | 316 |
1 files changed, 193 insertions, 123 deletions
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c index 3a5ae1db..cadd7d57 100644 --- a/source/fitz/draw-device.c +++ b/source/fitz/draw-device.c @@ -46,6 +46,7 @@ struct fz_draw_device_s fz_rasterizer *rast; fz_default_colorspaces *default_cs; int flags; + int resolve_spots; int top; fz_scale_cache *cache_x; fz_scale_cache *cache_y; @@ -116,9 +117,8 @@ static void stack_change(fz_context *ctx, fz_draw_device *dev, char *s) * in a color space that is our target color space or a transparency group * color space decide if we should be using the proof color space at this time */ static fz_colorspace * -fz_proof_cs(fz_context *ctx, fz_device *devp) +fz_proof_cs(fz_context *ctx, fz_draw_device *dev) { - fz_draw_device *dev = (fz_draw_device*)devp; fz_colorspace *prf = fz_default_output_intent(ctx, dev->default_cs); fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; @@ -329,6 +329,68 @@ static inline fz_matrix concat(const fz_matrix *one, const fz_matrix *two) } static void +resolve_color(fz_context *ctx, const float *color, fz_colorspace *colorspace, float alpha, const fz_color_params *color_params, unsigned char *colorbv, fz_pixmap *dest, fz_colorspace *prf) +{ + float colorfv[FZ_MAX_COLORS]; + int i; + int n = dest->n - dest->alpha; + fz_colorspace *model = dest->colorspace; + + if (colorspace == NULL && model != NULL) + fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color"); + + if (color_params == NULL) + color_params = fz_default_color_params(ctx); + + if (n == 0) + i = 0; + else if (fz_colorspace_is_device_n(ctx, colorspace) && dest->seps) + { + fz_convert_separation_colors(ctx, color_params, dest->colorspace, dest->seps, colorfv, colorspace, color); + for (i = 0; i < n; i++) + colorbv[i] = colorfv[i] * 255; + } + else + { + int c = n - dest->s; + fz_convert_color(ctx, color_params, prf, dest->colorspace, colorfv, colorspace, color); + for (i = 0; i < c; i++) + colorbv[i] = colorfv[i] * 255; + for (; i < n; i++) + colorbv[i] = 0; + } + colorbv[i] = alpha * 255; +} + +static fz_draw_state * +push_group_for_separations(fz_context *ctx, fz_draw_device *dev, fz_colorspace *prf, fz_default_colorspaces *default_cs) +{ + fz_separations *clone = fz_clone_separations_for_overprint(ctx, dev->stack[0].dest->seps); + + /* Not needed */ + if (clone == NULL) + { + dev->resolve_spots = 0; + return &dev->stack[0]; + } + + /* Make a new pixmap to render to. */ + fz_try(ctx) + { + dev->stack[1] = dev->stack[0]; + dev->stack[1].dest = NULL; /* So we are safe to destroy */ + dev->stack[1].dest = fz_clone_pixmap_area_with_different_seps(ctx, dev->stack[0].dest, &dev->stack[0].scissor, fz_device_cmyk(ctx), clone, prf, default_cs); + dev->top++; + } + fz_always(ctx) + fz_drop_separations(ctx, clone); + fz_catch(ctx) + fz_rethrow(ctx); + + return &dev->stack[1]; +} + +static void fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int even_odd, const fz_matrix *in_ctm, fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params) { @@ -336,21 +398,15 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve fz_matrix ctm = concat(in_ctm, &dev->transform); fz_rasterizer *rast = dev->rast; fz_colorspace *colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in); - fz_colorspace *prf = fz_proof_cs(ctx, devp); + fz_colorspace *prf = fz_proof_cs(ctx, dev); float expansion = fz_matrix_expansion(&ctm); float flatness = 0.3f / expansion; unsigned char colorbv[FZ_MAX_COLORS + 1]; - float colorfv[FZ_MAX_COLORS]; fz_irect bbox; - int i, n; fz_draw_state *state = &dev->stack[dev->top]; - fz_colorspace *model = state->dest->colorspace; - - if (colorspace == NULL && model != NULL) - fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color"); - if (color_params == NULL) - color_params = fz_default_color_params(ctx); + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, prf, dev->default_cs); if (flatness < 0.001f) flatness = 0.001f; @@ -362,16 +418,7 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve if (state->blendmode & FZ_BLEND_KNOCKOUT) state = fz_knockout_begin(ctx, dev); - n = fz_colorspace_n(ctx, model); - if (n > 0) - { - fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color); - for (i = 0; i < n; i++) - colorbv[i] = colorfv[i] * 255; - } - else - i = 0; - colorbv[i] = alpha * 255; + resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf); fz_convert_rasterizer(ctx, rast, even_odd, state->dest, colorbv); if (state->shape) @@ -395,25 +442,18 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const fz_matrix ctm = concat(in_ctm, &dev->transform); fz_rasterizer *rast = dev->rast; fz_colorspace *colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in); - fz_colorspace *prf = fz_proof_cs(ctx, devp); + fz_colorspace *prf = fz_proof_cs(ctx, dev); float expansion = fz_matrix_expansion(&ctm); float flatness = 0.3f / expansion; float linewidth = stroke->linewidth; unsigned char colorbv[FZ_MAX_COLORS + 1]; - float colorfv[FZ_MAX_COLORS]; fz_irect bbox; - int i, n; float aa_level = 2.0f/(fz_rasterizer_graphics_aa_level(rast)+2); fz_draw_state *state = &dev->stack[dev->top]; - fz_colorspace *model = state->dest->colorspace; float mlw = fz_rasterizer_graphics_min_line_width(rast); - - if (colorspace == NULL && model != NULL) - fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color"); - - if (color_params == NULL) - color_params = fz_default_color_params(ctx); + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, prf, dev->default_cs); if (mlw > aa_level) aa_level = mlw; @@ -429,16 +469,7 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const if (state->blendmode & FZ_BLEND_KNOCKOUT) state = fz_knockout_begin(ctx, dev); - n = fz_colorspace_n(ctx, model); - if (n > 0) - { - fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color); - for (i = 0; i < n; i++) - colorbv[i] = colorfv[i] * 255; - } - else - i = 0; - colorbv[i] = alpha * 255; + resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf); #ifdef DUMP_GROUP_BLENDS dump_spaces(dev->top, ""); @@ -483,6 +514,9 @@ fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve fz_irect local_scissor; fz_irect *scissor_ptr = &state->scissor; + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs); + if (flatness < 0.001f) flatness = 0.001f; @@ -551,6 +585,9 @@ fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, fz_irect local_scissor; fz_irect *scissor_ptr = &state->scissor; + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs); + if (mlw > aa_level) aa_level = mlw; if (linewidth * expansion < aa_level) @@ -692,13 +729,15 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f fz_colorspace *model = state->dest->colorspace; unsigned char colorbv[FZ_MAX_COLORS + 1]; unsigned char shapebv; - float colorfv[FZ_MAX_COLORS]; fz_text_span *span; - int i, n; + int i; fz_colorspace *colorspace = NULL; - fz_colorspace *prf = fz_proof_cs(ctx, devp); + fz_colorspace *prf = fz_proof_cs(ctx, dev); fz_rasterizer *rast = dev->rast; + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, prf, dev->default_cs); + if (colorspace_in) colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in); @@ -711,16 +750,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f if (state->blendmode & FZ_BLEND_KNOCKOUT) state = fz_knockout_begin(ctx, dev); - n = fz_colorspace_n(ctx, model); - if (n > 0) - { - fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color); - for (i = 0; i < n; i++) - colorbv[i] = colorfv[i] * 255; - } - else - i = 0; - colorbv[i] = alpha * 255; + resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf); shapebv = 255; for (span = text->head; span; span = span->next) @@ -789,37 +819,23 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_draw_device *dev = (fz_draw_device*)devp; fz_matrix ctm = concat(in_ctm, &dev->transform); fz_draw_state *state = &dev->stack[dev->top]; - fz_colorspace *model = state->dest->colorspace; unsigned char colorbv[FZ_MAX_COLORS + 1]; - float colorfv[FZ_MAX_COLORS]; fz_text_span *span; - int i, n; + int i; fz_colorspace *colorspace = NULL; - fz_colorspace *prf = fz_proof_cs(ctx, devp); + fz_colorspace *prf = fz_proof_cs(ctx, dev); int aa = fz_rasterizer_text_aa_level(dev->rast); + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, prf, dev->default_cs); + if (colorspace_in) colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in); - if (colorspace == NULL && model != NULL) - fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color"); - - if (color_params == NULL) - color_params = fz_default_color_params(ctx); - if (state->blendmode & FZ_BLEND_KNOCKOUT) state = fz_knockout_begin(ctx, dev); - n = fz_colorspace_n(ctx, model); - if (n > 0) - { - fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color); - for (i = 0; i < n; i++) - colorbv[i] = colorfv[i] * 255; - } - else - i = 0; - colorbv[i] = alpha * 255; + resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf); for (span = text->head; span; span = span->next) { @@ -885,6 +901,9 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f fz_rect rect; fz_rasterizer *rast = dev->rast; + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs); + state = push_stack(ctx, dev); STACK_PUSHED("clip text"); model = state->dest->colorspace; @@ -1014,6 +1033,9 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, fz_rect rect; int aa = fz_rasterizer_text_aa_level(dev->rast); + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs); + STACK_PUSHED("clip stroke text"); /* make the mask the exact size needed */ fz_irect_from_rect(&bbox, fz_bound_text(ctx, text, stroke, &ctm, &rect)); @@ -1134,11 +1156,12 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m fz_rect bounds; fz_irect bbox, scissor; fz_pixmap *dest, *shape; - float colorfv[FZ_MAX_COLORS]; unsigned char colorbv[FZ_MAX_COLORS + 1]; fz_draw_state *state = &dev->stack[dev->top]; - fz_colorspace *model = state->dest->colorspace; - fz_colorspace *prf = fz_proof_cs(ctx, devp); + fz_colorspace *prf = fz_proof_cs(ctx, dev); + + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, prf, dev->default_cs); fz_bound_shade(ctx, shade, &ctm, &bounds); scissor = state->scissor; @@ -1174,16 +1197,8 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m { unsigned char *s; int x, y, n, i; - n = fz_colorspace_n(ctx, model); - if (n > 0) - { - fz_convert_color(ctx, color_params, prf, model, colorfv, fz_default_colorspace(ctx, dev->default_cs, shade->colorspace), shade->background); - for (i = 0; i < n; i++) - colorbv[i] = colorfv[i] * 255; - } - else - i = 0; - colorbv[i] = 255; + + resolve_color(ctx, shade->background, fz_default_colorspace(ctx, dev->default_cs, shade->colorspace), alpha, color_params, colorbv, state->dest, prf); n = dest->n; for (y = scissor.y0; y < scissor.y1; y++) @@ -1313,7 +1328,10 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m fz_matrix inverse; fz_irect src_area; fz_colorspace *src_cs; - fz_colorspace *prf = fz_proof_cs(ctx, devp); + fz_colorspace *prf = fz_proof_cs(ctx, dev); + + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, prf, dev->default_cs); fz_intersect_irect(fz_pixmap_bbox(ctx, state->dest, &clip), &state->scissor); @@ -1434,28 +1452,22 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const fz_draw_device *dev = (fz_draw_device*)devp; fz_matrix local_ctm = concat(in_ctm, &dev->transform); unsigned char colorbv[FZ_MAX_COLORS + 1]; - float colorfv[FZ_MAX_COLORS]; fz_pixmap *scaled = NULL; fz_pixmap *pixmap; int dx, dy; - int i, n; fz_draw_state *state = &dev->stack[dev->top]; - fz_colorspace *model = state->dest->colorspace; fz_irect clip; fz_matrix inverse; fz_irect src_area; fz_colorspace *colorspace = NULL; - fz_colorspace *prf = fz_proof_cs(ctx, devp); + fz_colorspace *prf = fz_proof_cs(ctx, dev); + + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, prf, dev->default_cs); if (colorspace_in) colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in); - if (color_params == NULL) - color_params = fz_default_color_params(ctx); - - if (colorspace == NULL && model != NULL) - fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color"); - fz_pixmap_bbox(ctx, state->dest, &clip); fz_intersect_irect(&clip, &state->scissor); @@ -1525,16 +1537,7 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const } } - n = fz_colorspace_n(ctx, model); - if (n > 0) - { - fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color); - for (i = 0; i < n; i++) - colorbv[i] = colorfv[i] * 255; - } - else - i = 0; - colorbv[i] = alpha * 255; + resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf); fz_paint_image_with_color(state->dest, &state->scissor, state->shape, pixmap, &local_ctm, colorbv, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED); @@ -1561,6 +1564,9 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const fz_irect clip; fz_rect urect; + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs); + STACK_PUSHED("clip image mask"); fz_pixmap_bbox(ctx, state->dest, &clip); fz_intersect_irect(&clip, &state->scissor); @@ -1722,6 +1728,9 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu fz_rect trect = *rect; fz_colorspace *colorspace = NULL; + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs); + if (colorspace_in) colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in); @@ -1858,6 +1867,9 @@ fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, fz_co fz_colorspace *model = state->dest->colorspace; fz_rect trect = *rect; + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs); + if (cs != NULL) model = fz_default_colorspace(ctx, dev->default_cs, cs); @@ -2101,6 +2113,9 @@ fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const fz_colorspace *model = state->dest->colorspace; fz_rect local_view = *view; + if (dev->top == 0 && dev->resolve_spots) + state = push_group_for_separations(ctx, dev, fz_proof_cs(ctx, dev), dev->default_cs); + /* area, view, xstep, ystep are in pattern space */ /* ctm maps from pattern space to device space */ @@ -2364,6 +2379,37 @@ fz_draw_set_default_colorspaces(fz_context *ctx, fz_device *devp, fz_default_col } static void +fz_draw_close_device(fz_context *ctx, fz_device *devp) +{ + fz_draw_device *dev = (fz_draw_device*)devp; + fz_colorspace *prf = fz_proof_cs(ctx, dev); + + /* pop and free the stacks */ + if (dev->top > dev->resolve_spots) + fz_warn(ctx, "items left on stack in draw device: %d", dev->top); + + while(dev->top > dev->resolve_spots) + { + fz_draw_state *state = &dev->stack[--dev->top]; + 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); + } + + if (dev->resolve_spots && dev->top) + { + fz_draw_state *state = &dev->stack[--dev->top]; + fz_copy_pixmap_area_converting_seps(ctx, state[0].dest, state[1].dest, prf, dev->default_cs); + fz_drop_pixmap(ctx, state[1].dest); + assert(state[1].mask == NULL); + assert(state[1].shape == NULL); + } +} + +static void fz_draw_drop_device(fz_context *ctx, fz_device *devp) { fz_draw_device *dev = (fz_draw_device*)devp; @@ -2373,7 +2419,7 @@ fz_draw_drop_device(fz_context *ctx, fz_device *devp) /* pop and free the stacks */ if (dev->top > 0) - fz_warn(ctx, "items left on stack in draw device: %d", dev->top+1); + fz_warn(ctx, "items left on stack in draw device: %d", dev->top); while(dev->top-- > 0) { @@ -2385,6 +2431,7 @@ fz_draw_drop_device(fz_context *ctx, fz_device *devp) if (state[1].shape != state[0].shape) fz_drop_pixmap(ctx, state[1].shape); } + /* We never free the dest/mask/shape at level 0, as: * 1) dest is passed in and ownership remains with the caller. * 2) shape and mask are NULL at level 0. @@ -2397,11 +2444,12 @@ fz_draw_drop_device(fz_context *ctx, fz_device *devp) } fz_device * -new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_aa_context *aa) +new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_aa_context *aa, const fz_irect *clip) { fz_draw_device *dev = fz_new_derived_device(ctx, fz_draw_device); dev->super.drop_device = fz_draw_drop_device; + dev->super.close_device = fz_draw_close_device; dev->super.fill_path = fz_draw_fill_path; dev->super.stroke_path = fz_draw_stroke_path; @@ -2434,6 +2482,7 @@ new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, co dev->transform = transform ? *transform : fz_identity; dev->flags = 0; + dev->resolve_spots = 0; dev->top = 0; dev->stack = &dev->init_stack[0]; dev->stack_cap = STACK_SIZE; @@ -2446,6 +2495,38 @@ new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, co dev->stack[0].scissor.x1 = dest->x + dest->w; dev->stack[0].scissor.y1 = dest->y + dest->h; + if (clip) + { + if (clip->x0 > dev->stack[0].scissor.x0) + dev->stack[0].scissor.x0 = clip->x0; + if (clip->x1 < dev->stack[0].scissor.x1) + dev->stack[0].scissor.x1 = clip->x1; + if (clip->y0 > dev->stack[0].scissor.y0) + dev->stack[0].scissor.y0 = clip->y0; + if (clip->y1 < dev->stack[0].scissor.y1) + dev->stack[0].scissor.y1 = clip->y1; + } + + /* If we have no separations structure at all, then we want a + * simple composite rendering (with no overprint simulation). + * If we do have a separations structure, so: 1) Any + * 'disabled' separations are ignored. 2) Any 'composite' + * separations means we will need to do an overprint + * simulation. + * + * The supplied pixmaps 's' will match the number of + * 'spots' separations. If we have any 'composite' + * separations therefore, we'll need to make a new pixmap + * with a new (completely 'spots') separations structure, + * render to that, and then map down at the end. + * + * Unfortunately we can't produce this until we know what + * the default_colorspaces etc are, so set a flag for us + * to trigger on later. + */ + if (dest->seps) + dev->resolve_spots = 1; + fz_try(ctx) { dev->rast = fz_new_rasterizer(ctx, aa); @@ -2464,24 +2545,13 @@ new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, co fz_device * fz_new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest) { - return new_draw_device(ctx, transform, dest, NULL); + return new_draw_device(ctx, transform, dest, NULL, NULL); } fz_device * fz_new_draw_device_with_bbox(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_irect *clip) { - fz_draw_device *dev = (fz_draw_device*)fz_new_draw_device(ctx, transform, dest); - - if (clip->x0 > dev->stack[0].scissor.x0) - dev->stack[0].scissor.x0 = clip->x0; - if (clip->x1 < dev->stack[0].scissor.x1) - dev->stack[0].scissor.x1 = clip->x1; - if (clip->y0 > dev->stack[0].scissor.y0) - dev->stack[0].scissor.y0 = clip->y0; - if (clip->y1 < dev->stack[0].scissor.y1) - dev->stack[0].scissor.y1 = clip->y1; - - return (fz_device*)dev; + return new_draw_device(ctx, transform, dest, NULL, clip); } fz_device * |