Beispiel #1
0
void
fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_bbox r)
{
	const unsigned char *srcp;
	unsigned char *destp;
	int y, w, destspan, srcspan;

	r = fz_intersect_bbox(r, fz_bound_pixmap(dest));
	r = fz_intersect_bbox(r, fz_bound_pixmap(src));
	w = r.x1 - r.x0;
	y = r.y1 - r.y0;
	if (w <= 0 || y <= 0)
		return;

	w *= src->n;
	srcspan = src->w * src->n;
	srcp = src->samples + srcspan * (r.y0 - src->y) + src->n * (r.x0 - src->x);
	destspan = dest->w * dest->n;
	destp = dest->samples + destspan * (r.y0 - dest->y) + dest->n * (r.x0 - dest->x);
	do
	{
		memcpy(destp, srcp, w);
		srcp += srcspan;
		destp += destspan;
	}
	while (--y);
}
Beispiel #2
0
static void
draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_pixmap *msk,
	int xorig, int yorig, fz_bbox scissor)
{
	unsigned char *dp, *mp;
	fz_bbox bbox;
	int x, y, w, h;

	bbox = fz_bound_pixmap(msk);
	bbox.x0 += xorig;
	bbox.y0 += yorig;
	bbox.x1 += xorig;
	bbox.y1 += yorig;

	bbox = fz_intersect_bbox(bbox, scissor); /* scissor < dst */
	x = bbox.x0;
	y = bbox.y0;
	w = bbox.x1 - bbox.x0;
	h = bbox.y1 - bbox.y0;

	mp = msk->samples + ((y - msk->y - yorig) * msk->w + (x - msk->x - xorig));
	dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;

	assert(msk->n == 1);

	while (h--)
	{
		if (dst->colorspace)
			fz_paint_span_with_color(dp, mp, dst->n, w, colorbv);
		else
			fz_paint_span(dp, mp, 1, w, 255);
		dp += dst->w * dst->n;
		mp += msk->w;
	}
}
Beispiel #3
0
void
fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *dest, int value, fz_bbox r)
{
	unsigned char *destp;
	int x, y, w, k, destspan;

	r = fz_intersect_bbox(r, fz_bound_pixmap(dest));
	w = r.x1 - r.x0;
	y = r.y1 - r.y0;
	if (w <= 0 || y <= 0)
		return;

	destspan = dest->w * dest->n;
	destp = dest->samples + destspan * (r.y0 - dest->y) + dest->n * (r.x0 - dest->x);
	if (value == 255)
		do
		{
			memset(destp, 255, w * dest->n);
			destp += destspan;
		}
		while (--y);
	else
		do
		{
			unsigned char *s = destp;
			for (x = 0; x < w; x++)
			{
				for (k = 0; k < dest->n - 1; k++)
					*s++ = value;
				*s++ = 255;
			}
			destp += destspan;
		}
		while (--y);
}
Beispiel #4
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;
}
Beispiel #5
0
static void
fz_draw_end_mask(fz_context *ctx, void *user)
{
	fz_draw_device *dev = user;
	fz_pixmap *mask = dev->dest;
	fz_pixmap *maskshape = dev->shape;
	fz_pixmap *temp, *dest;
	fz_bbox bbox;
	int luminosity;

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

	if (dev->top > 0)
	{
		/* pop soft mask buffer */
		dev->top--;
		luminosity = dev->stack[dev->top].luminosity;
		dev->scissor = dev->stack[dev->top].scissor;
		dev->dest = dev->stack[dev->top].dest;
		dev->shape = dev->stack[dev->top].shape;

		/* convert to alpha mask */
		temp = fz_alpha_from_gray(ctx, mask, luminosity);
		fz_drop_pixmap(ctx, mask);
		fz_drop_pixmap(ctx, maskshape);

		/* create new dest scratch buffer */
		bbox = fz_bound_pixmap(temp);
		dest = fz_new_pixmap_with_rect(ctx, dev->dest->colorspace, bbox);
		/* FIXME: See note #1 */
		fz_clear_pixmap(dest);

		/* push soft mask as clip mask */
		dev->stack[dev->top].scissor = dev->scissor;
		dev->stack[dev->top].mask = temp;
		dev->stack[dev->top].dest = dev->dest;
		/* FIXME: See note #1 */
		dev->stack[dev->top].blendmode = dev->blendmode | FZ_BLEND_ISOLATED;
		/* If we have a shape, then it'll need to be masked with the
		 * clip mask when we pop. So create a new shape now. */
		if (dev->shape)
		{
			dev->stack[dev->top].shape = dev->shape;
			dev->shape = fz_new_pixmap_with_rect(ctx, NULL, bbox);
			fz_clear_pixmap(dev->shape);
		}
		dev->scissor = bbox;
		dev->dest = dest;
#ifdef DUMP_GROUP_BLENDS
		dump_spaces(dev->top, "Mask -> Clip\n");
#endif
		dev->top++;
	}
}
Beispiel #6
0
static void
fz_draw_end_mask(void *user)
{
	fz_draw_device *dev = user;
	fz_pixmap *mask = dev->dest;
	fz_pixmap *temp, *dest;
	fz_bbox bbox;
	int luminosity;

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

	if (dev->top > 0)
	{
		/* pop soft mask buffer */
		dev->top--;
		luminosity = dev->stack[dev->top].luminosity;
		dev->scissor = dev->stack[dev->top].scissor;
		dev->dest = dev->stack[dev->top].dest;

		/* convert to alpha mask */
		temp = fz_alpha_from_gray(mask, luminosity);
		fz_drop_pixmap(mask);

		/* create new dest scratch buffer */
		bbox = fz_bound_pixmap(temp);
		dest = fz_new_pixmap_with_rect(dev->dest->colorspace, bbox);
		fz_clear_pixmap(dest);

		/* push soft mask as clip mask */
		dev->stack[dev->top].scissor = dev->scissor;
		dev->stack[dev->top].mask = temp;
		dev->stack[dev->top].dest = dev->dest;
		dev->scissor = bbox;
		dev->dest = dest;
		dev->top++;
	}
}
fz_pixmap *
pdf_expand_indexed_pixmap(fz_pixmap *src)
{
	struct indexed *idx;
	fz_pixmap *dst;
	unsigned char *s, *d;
	int y, x, k, n, high;
	unsigned char *lookup;

	assert(src->colorspace->to_rgb == indexed_to_rgb);
	assert(src->n == 2);

	idx = src->colorspace->data;
	high = idx->high;
	lookup = idx->lookup;
	n = idx->base->n;

	dst = fz_new_pixmap_with_rect(idx->base, fz_bound_pixmap(src));
	s = src->samples;
	d = dst->samples;

	for (y = 0; y < src->h; y++)
	{
		for (x = 0; x < src->w; x++)
		{
			int v = *s++;
			int a = *s++;
			v = MIN(v, high);
			for (k = 0; k < n; k++)
				*d++ = fz_mul255(lookup[v * n + k], a);
			*d++ = a;
		}
	}

	if (src->mask)
		dst->mask = fz_keep_pixmap(src->mask);
	dst->interpolate = src->interpolate;

	return dst;
}
Beispiel #8
0
static void saveimage(int num)
{
	fz_error error;
	fz_pixmap *img;
	fz_obj *ref;
	char name[1024];

	ref = fz_new_indirect(ctx, num, 0, xref);

	/* TODO: detect DCTD and save as jpeg */

	error = pdf_load_image(&img, xref, ref);
	if (error)
		die(error);

	if (dorgb && img->colorspace && img->colorspace != fz_device_rgb)
	{
		fz_pixmap *temp;
		temp = fz_new_pixmap_with_rect(ctx, fz_device_rgb, fz_bound_pixmap(img));
		fz_convert_pixmap(ctx, img, temp);
		fz_drop_pixmap(ctx, img);
		img = temp;
	}

	if (img->n <= 4)
	{
		sprintf(name, "img-%04d.png", num);
		printf("extracting image %s\n", name);
		fz_write_png(ctx, img, name, 0);
	}
	else
	{
		sprintf(name, "img-%04d.pam", num);
		printf("extracting image %s\n", name);
		fz_write_pam(ctx, img, name, 0);
	}

	fz_drop_pixmap(ctx, img);
	fz_drop_obj(ctx, ref);
}
Beispiel #9
0
fz_pixmap *
fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity)
{
	fz_pixmap *alpha;
	unsigned char *sp, *dp;
	int len;

	assert(gray->n == 2);

	alpha = fz_new_pixmap_with_rect(ctx, NULL, fz_bound_pixmap(gray));
	dp = alpha->samples;
	sp = gray->samples;
	if (!luminosity)
		sp ++;

	len = gray->w * gray->h;
	while (len--)
	{
		*dp++ = sp[0];
		sp += 2;
	}

	return alpha;
}
Beispiel #10
0
static void
fz_draw_fill_image(fz_context *ctx, void *user, fz_pixmap *image, fz_matrix ctm, float alpha)
{
	fz_draw_device *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	fz_pixmap *converted = NULL;
	fz_pixmap *scaled = NULL;
	int after;
	int dx, dy;

	if (!model)
	{
		fz_warn(ctx, "cannot render image directly to an alpha mask");
		return;
	}

	if (image->w == 0 || image->h == 0)
		return;

	/* convert images with more components (cmyk->rgb) before scaling */
	/* convert images with fewer components (gray->rgb after scaling */
	/* convert images with expensive colorspace transforms after scaling */

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

	after = 0;
	if (image->colorspace == fz_device_gray)
		after = 1;

	if (image->colorspace != model && !after)
	{
		converted = fz_new_pixmap_with_rect(ctx, model, fz_bound_pixmap(image));
		fz_convert_pixmap(ctx, image, converted);
		image = converted;
	}

	dx = sqrtf(ctm.a * ctm.a + ctm.b * ctm.b);
	dy = sqrtf(ctm.c * ctm.c + ctm.d * ctm.d);
	if (dx < image->w && dy < image->h)
	{
		int gridfit = alpha == 1.0f && !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3);
		scaled = fz_transform_pixmap(ctx, image, &ctm, dev->dest->x, dev->dest->y, dx, dy, gridfit);
		if (scaled == NULL)
		{
			if (dx < 1)
				dx = 1;
			if (dy < 1)
				dy = 1;
			scaled = fz_scale_pixmap(ctx, image, image->x, image->y, dx, dy);
		}
		if (scaled != NULL)
			image = scaled;
	}

	if (image->colorspace != model)
	{
		if ((image->colorspace == fz_device_gray && model == fz_device_rgb) ||
			(image->colorspace == fz_device_gray && model == fz_device_bgr))
		{
			/* We have special case rendering code for gray -> rgb/bgr */
		}
		else
		{
			converted = fz_new_pixmap_with_rect(ctx, model, fz_bound_pixmap(image));
			fz_convert_pixmap(ctx, image, converted);
			image = converted;
		}
	}

	fz_paint_image(dev->dest, dev->scissor, dev->shape, image, ctm, alpha * 255);

	if (scaled)
		fz_drop_pixmap(ctx, scaled);
	if (converted)
		fz_drop_pixmap(ctx, converted);

	if (dev->blendmode & FZ_BLEND_KNOCKOUT)
		fz_knockout_end(ctx, dev);
}
Beispiel #11
0
static void
fz_draw_fill_text(fz_context *ctx, void *user, fz_text *text, fz_matrix ctm,
	fz_colorspace *colorspace, float *color, float alpha)
{
	fz_draw_device *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	unsigned char colorbv[FZ_MAX_COLORS + 1];
	unsigned char shapebv;
	float colorfv[FZ_MAX_COLORS];
	fz_matrix tm, trm;
	fz_pixmap *glyph;
	int i, x, y, gid;

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

	fz_convert_color(ctx, colorspace, color, model, colorfv);
	for (i = 0; i < model->n; i++)
		colorbv[i] = colorfv[i] * 255;
	colorbv[i] = alpha * 255;
	shapebv = 255;

	tm = text->trm;

	for (i = 0; i < text->len; i++)
	{
		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);
		trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX);
		trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX);

		glyph = fz_render_glyph(ctx, dev->cache, text->font, gid, trm, model);
		if (glyph)
		{
			/* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1746 */
			if (glyph->n > 1 && text->font->t3procs)
			{
				float light;
				fz_convert_color(ctx, colorspace, color, fz_device_gray, &light);
				if (light != 0)
				{
					fz_pixmap *gray = fz_new_pixmap_with_rect(ctx, fz_device_gray, fz_bound_pixmap(glyph));
					fz_convert_pixmap(ctx, glyph, gray);
					fz_drop_pixmap(ctx, glyph);
					glyph = fz_alpha_from_gray(ctx, gray, 0);
					fz_drop_pixmap(ctx, gray);
				}
			}
			if (glyph->n == 1)
			{
				draw_glyph(colorbv, dev->dest, glyph, x, y, dev->scissor);
				if (dev->shape)
					draw_glyph(&shapebv, dev->shape, glyph, x, y, dev->scissor);
			}
			else
			{
				fz_matrix ctm = {glyph->w, 0.0, 0.0, -glyph->h, x + glyph->x, y + glyph->y + glyph->h};
				fz_paint_image(dev->dest, dev->scissor, dev->shape, glyph, ctm, alpha * 255);
			}
			fz_drop_pixmap(ctx, glyph);
		}
	}

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