Ejemplo n.º 1
0
static fz_draw_state *
fz_knockout_begin(fz_draw_device *dev)
{
	fz_context *ctx = dev->ctx;
	fz_bbox bbox;
	fz_pixmap *dest, *shape;
	fz_draw_state *state = &dev->stack[dev->top];
	int isolated = state->blendmode & FZ_BLEND_ISOLATED;

	if ((state->blendmode & FZ_BLEND_KNOCKOUT) == 0)
		return state;

	state = push_stack(dev);

	bbox = fz_pixmap_bbox(dev->ctx, state->dest);
	bbox = fz_intersect_bbox(bbox, state->scissor);
	dest = fz_new_pixmap_with_bbox(dev->ctx, state->dest->colorspace, bbox);

	if (isolated)
	{
		fz_clear_pixmap(ctx, dest);
	}
	else
	{
		/* Find the last but one destination to copy */
		int i = dev->top-1; /* i = the one on entry (i.e. the last one) */
		fz_pixmap *prev = state->dest;
		while (i > 0)
		{
			prev = dev->stack[--i].dest;
			if (prev != state->dest)
				break;
		}
		if (prev)
			fz_copy_pixmap_rect(ctx, dest, prev, bbox);
		else
			fz_clear_pixmap(ctx, dest);
	}

	if (state->blendmode == 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->shape;
	}
	else
	{
		shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox);
		fz_clear_pixmap(dev->ctx, shape);
	}
#ifdef DUMP_GROUP_BLENDS
	dump_spaces(dev->top-1, "Knockout begin\n");
#endif
	state[1].scissor = bbox;
	state[1].dest = dest;
	state[1].shape = shape;
	state[1].blendmode &= ~FZ_BLEND_MODEMASK;

	return &state[1];
}
Ejemplo n.º 2
0
static void fz_knockout_begin(fz_context *ctx, void *user)
{
	fz_draw_device *dev = user;
	fz_bbox bbox;
	fz_pixmap *dest, *shape;
	int isolated = dev->blendmode & FZ_BLEND_ISOLATED;

	if ((dev->blendmode & FZ_BLEND_KNOCKOUT) == 0)
		return;

	if (dev->top == dev->stack_max)
		fz_grow_stack(dev);

	bbox = fz_bound_pixmap(dev->dest);
	bbox = fz_intersect_bbox(bbox, dev->scissor);
	dest = fz_new_pixmap_with_rect(ctx, dev->dest->colorspace, bbox);

	if (isolated)
	{
		fz_clear_pixmap(dest);
	}
	else
	{
		fz_pixmap *prev;
		int i  = dev->top;
		do
			prev = dev->stack[--i].dest;
		while (prev == NULL);
		fz_copy_pixmap_rect(dest, prev, bbox);
	}

	if (dev->blendmode == 0 && isolated || 1 /* SumatraPDF: disable crashy shape code */)
	{
		/* We can render direct to any existing shape plane. If there
		 * isn't one, we don't need to make one. */
		shape = dev->shape;
	}
	else
	{
		shape = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox);
		fz_clear_pixmap(shape);
	}
	dev->stack[dev->top].blendmode = dev->blendmode;
	dev->stack[dev->top].scissor = dev->scissor;
	dev->stack[dev->top].dest = dev->dest;
	dev->stack[dev->top].shape = dev->shape;
#ifdef DUMP_GROUP_BLENDS
	dump_spaces(dev->top, "Knockout begin\n");
#endif
	dev->top++;

	dev->scissor = bbox;
	dev->dest = dest;
	dev->shape = shape;
	dev->blendmode &= ~FZ_BLEND_MODEMASK;
}
Ejemplo n.º 3
0
static void
fz_draw_begin_group(fz_context *ctx, void *user, fz_rect rect, int isolated, int knockout, int blendmode, float alpha)
{
	fz_draw_device *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	fz_bbox bbox;
	fz_pixmap *dest, *shape;

	if (dev->top == dev->stack_max)
	{
		fz_warn(ctx, "assert: too many buffers on stack");
		return;
	}

	if (dev->blendmode & FZ_BLEND_KNOCKOUT)
		fz_knockout_begin(ctx, dev);

	bbox = fz_round_rect(rect);
	bbox = fz_intersect_bbox(bbox, dev->scissor);
	dest = fz_new_pixmap_with_rect(ctx, model, bbox);

#ifndef ATTEMPT_KNOCKOUT_AND_ISOLATED
	knockout = 0;
	isolated = 1;
#endif

	if (isolated)
	{
		fz_clear_pixmap(dest);
	}
	else
	{
		fz_copy_pixmap_rect(dest, dev->dest, bbox);
	}

	if (blendmode == 0 && alpha == 1.0 && isolated || 1 /* SumatraPDF: disable crashy shape code */)
	{
		/* We can render direct to any existing shape plane. If there
		 * isn't one, we don't need to make one. */
		shape = dev->shape;
	}
	else
	{
		shape = fz_new_pixmap_with_rect(ctx, NULL, bbox);
		fz_clear_pixmap(shape);
	}

	dev->stack[dev->top].alpha = alpha;
	dev->stack[dev->top].blendmode = dev->blendmode;
	dev->stack[dev->top].scissor = dev->scissor;
	dev->stack[dev->top].dest = dev->dest;
	dev->stack[dev->top].shape = dev->shape;
#ifdef DUMP_GROUP_BLENDS
	dump_spaces(dev->top, "Group Begin\n");
#endif
	dev->top++;

	dev->scissor = bbox;
	dev->dest = dest;
	dev->shape = shape;
	dev->blendmode = blendmode | (isolated ? FZ_BLEND_ISOLATED : 0) | (knockout ? FZ_BLEND_KNOCKOUT : 0);
}
Ejemplo n.º 4
0
static void
fz_draw_begin_group(fz_device *devp, fz_rect rect, int isolated, int knockout, int blendmode, float alpha)
{
	fz_draw_device *dev = devp->user;
	fz_bbox bbox;
	fz_pixmap *dest, *shape;
	fz_context *ctx = dev->ctx;
	fz_draw_state *state = &dev->stack[dev->top];
	fz_colorspace *model = state->dest->colorspace;

	if (state->blendmode & FZ_BLEND_KNOCKOUT)
		fz_knockout_begin(dev);

	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);

#ifndef ATTEMPT_KNOCKOUT_AND_ISOLATED
	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 (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)
		{
			shape = fz_new_pixmap_with_bbox(ctx, NULL, bbox);
			fz_clear_pixmap(dev->ctx, shape);
		}
		fz_catch(ctx)
		{
			fz_drop_pixmap(ctx, dest);
			fz_rethrow(ctx);
		}
	}

	state[1].alpha = alpha;
#ifdef DUMP_GROUP_BLENDS
	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);
}