void
fz_stdconvpixmap(fz_colorspace *srcs, fz_pixmap *src, fz_colorspace *dsts, fz_pixmap *dst)
{
	float srcv[FZ_MAXCOLORS];
	float dstv[FZ_MAXCOLORS];
	int y, x, k;

	unsigned char *s = src->p;
	unsigned char *d = dst->p;

	printf("convert pixmap from %s to %s\n", srcs->name, dsts->name);

	assert(src->w == dst->w && src->h == dst->h);
	assert(src->n == srcs->n + 1);
	assert(dst->n == dsts->n + 1);

	for (y = 0; y < src->h; y++)
	{
		for (x = 0; x < src->w; x++)
		{
			*d++ = *s++;

			for (k = 0; k < src->n - 1; k++)
				srcv[k] = *s++ / 255.0;

			fz_convertcolor(srcs, srcv, dsts, dstv);

			for (k = 0; k < dst->n - 1; k++)
				*d++ = dstv[k] * 255;
		}
	}
}
Exemple #2
0
static void
fz_drawfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm,
	fz_colorspace *colorspace, float *color, float alpha)
{
	fz_drawdevice *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	unsigned char colorbv[FZ_MAXCOLORS + 1];
	float colorfv[FZ_MAXCOLORS];
	fz_pixmap *scaled = nil;
	int dx, dy;
	int i;

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

#ifdef SMOOTHSCALE
	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)
	{
		scaled = fz_smoothtransformpixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy);
		if (scaled == NULL)
		{
			if (dx < 1)
				dx = 1;
			if (dy < 1)
				dy = 1;
			scaled = fz_smoothscalepixmap(image, image->x, image->y, dx, dy);
		}
		if (scaled != NULL)
			image = scaled;
	}
#else
	if (fz_calcimagescale(image, ctm, &dx, &dy))
	{
		scaled = fz_scalepixmap(image, dx, dy);
		image = scaled;
	}
#endif

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

	fz_paintimagecolor(dev->dest, dev->scissor, image, ctm, colorbv);

	if (scaled)
		fz_droppixmap(scaled);
}
Exemple #3
0
static fz_error *
rendersolid(fz_renderer *gc, fz_solidnode *solid, fz_matrix ctm)
{
	fz_error *error;
	float rgb[3];
	unsigned char *p;
	int n;

	if (gc->maskonly)
		return fz_throw("assert: mask only renderer");
	if (gc->model->n != 3)
		return fz_throw("assert: non-rgb renderer");

	fz_convertcolor(solid->cs, solid->samples, gc->model, rgb);
	gc->rgb[0] = rgb[0] * 255;
	gc->rgb[1] = rgb[1] * 255;
	gc->rgb[2] = rgb[2] * 255;

DEBUG("solid %s [%d %d %d];\n", solid->cs->name, gc->rgb[0], gc->rgb[1], gc->rgb[2]);

	if (gc->flag == FOVER)
	{
		p = gc->over->samples;
		n = gc->over->w * gc->over->h;
	}
	else
	{
		error = fz_newpixmapwithrect(&gc->dest, gc->clip, 4);
		if (error)
			return error;
		p = gc->dest->samples;
		n = gc->dest->w * gc->dest->h;
	}

	while (n--)
	{
		p[0] = 255;
		p[1] = gc->rgb[0];
		p[2] = gc->rgb[1];
		p[3] = gc->rgb[2];
		p += 4;
	}

	return nil;
}
Exemple #4
0
static void
fz_drawstroketext(void *user, fz_text *text, fz_strokestate *stroke, fz_matrix ctm,
	fz_colorspace *colorspace, float *color, float alpha)
{
	fz_drawdevice *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	unsigned char colorbv[FZ_MAXCOLORS + 1];
	float colorfv[FZ_MAXCOLORS];
	fz_matrix tm, trm;
	fz_pixmap *glyph;
	int i, x, y, gid;

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

	tm = text->trm;

	for (i = 0; i < text->len; i++)
	{
		gid = text->els[i].gid;
		if (gid < 0)
			continue;

		tm.e = text->els[i].x;
		tm.f = text->els[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_renderstrokedglyph(dev->cache, text->font, gid, trm, ctm, stroke);
		if (glyph)
		{
			drawglyph(colorbv, dev->dest, glyph, x, y, dev->scissor);
			fz_droppixmap(glyph);
		}
	}
}
Exemple #5
0
static void
fz_drawstrokepath(void *user, fz_path *path, fz_strokestate *stroke, fz_matrix ctm,
	fz_colorspace *colorspace, float *color, float alpha)
{
	fz_drawdevice *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	float expansion = fz_matrixexpansion(ctm);
	float flatness = 0.3f / expansion;
	float linewidth = stroke->linewidth;
	unsigned char colorbv[FZ_MAXCOLORS + 1];
	float colorfv[FZ_MAXCOLORS];
	fz_bbox bbox;
	int i;

	if (linewidth * expansion < 0.1f)
		linewidth = 1 / expansion;

	fz_resetgel(dev->gel, dev->scissor);
	if (stroke->dashlen > 0)
		fz_dashpath(dev->gel, path, stroke, ctm, flatness, linewidth);
	else
		fz_strokepath(dev->gel, path, stroke, ctm, flatness, linewidth);
	fz_sortgel(dev->gel);

	bbox = fz_boundgel(dev->gel);
	bbox = fz_intersectbbox(bbox, dev->scissor);

	if (fz_isemptyrect(bbox))
		return;

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

	fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, colorbv);
}
Exemple #6
0
static void
fz_drawfillshade(void *user, fz_shade *shade, fz_matrix ctm, float alpha)
{
	fz_drawdevice *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	fz_pixmap *dest = dev->dest;
	fz_rect bounds;
	fz_bbox bbox;
	float colorfv[FZ_MAXCOLORS];
	unsigned char colorbv[FZ_MAXCOLORS + 1];

	bounds = fz_boundshade(shade, ctm);
	bbox = fz_intersectbbox(fz_roundrect(bounds), dev->scissor);

	// TODO: proper clip by shade->bbox
	if (!fz_isemptyrect(shade->bbox))
	{
		bounds = fz_transformrect(fz_concat(shade->matrix, ctm), shade->bbox);
		bbox = fz_intersectbbox(fz_roundrect(bounds), bbox);
	}

	if (fz_isemptyrect(bbox))
		return;

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

	if (alpha < 1)
	{
		dest = fz_newpixmapwithrect(dev->dest->colorspace, bbox);
		fz_clearpixmap(dest, 0);
	}

	if (shade->usebackground)
	{
		unsigned char *s;
		int x, y, n, i;
		fz_convertcolor(shade->cs, shade->background, model, colorfv);
		for (i = 0; i < model->n; i++)
			colorbv[i] = colorfv[i] * 255;
		colorbv[i] = 255;

		n = dest->n;
		for (y = bbox.y0; y < bbox.y1; y++)
		{
			s = dest->samples + ((bbox.x0 - dest->x) + (y - dest->y) * dest->w) * dest->n;
			for (x = bbox.x0; x < bbox.x1; x++)
			{
				for (i = 0; i < n; i++)
					*s++ = colorbv[i];
			}
		}
	}

	fz_rendershade(shade, ctm, dest, bbox);

	if (alpha < 1)
	{
		fz_paintpixmap(dev->dest, dest, alpha * 255);
		fz_droppixmap(dest);
	}
}
Exemple #7
0
static fz_error *
rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
{
	fz_error *error;
	int oldmaskonly;
	fz_pixmap *oldover;
	fz_irect oldclip;
	fz_irect bbox;
	fz_irect clip;
	fz_pixmap *shapepix = nil;
	fz_pixmap *colorpix = nil;
	fz_node *shape;
	fz_node *color;
	float rgb[3];

	shape = mask->super.first;
	color = shape->next;

	/* special case black voodo */
	if (gc->flag & FOVER)
	{
		if (fz_issolidnode(color))
		{
			fz_solidnode *solid = (fz_solidnode*)color;

			fz_convertcolor(solid->cs, solid->samples, gc->model, rgb);
			gc->argb[0] = solid->a * 255;
			gc->argb[1] = rgb[0] * solid->a * 255;
			gc->argb[2] = rgb[1] * solid->a * 255;
			gc->argb[3] = rgb[2] * solid->a * 255;
			gc->argb[4] = rgb[0] * 255;
			gc->argb[5] = rgb[1] * 255;
			gc->argb[6] = rgb[2] * 255;
			gc->flag |= FRGB;

			/* we know these can handle the FRGB shortcut */
			if (fz_ispathnode(shape))
				return renderpath(gc, (fz_pathnode*)shape, ctm);
			if (fz_istextnode(shape))
				return rendertext(gc, (fz_textnode*)shape, ctm);
			if (fz_isimagenode(shape))
				return renderimage(gc, (fz_imagenode*)shape, ctm);
		}
	}

	oldclip = gc->clip;
	oldover = gc->over;

	bbox = fz_roundrect(fz_boundnode(shape, ctm));
	clip = fz_intersectirects(bbox, gc->clip);
	bbox = fz_roundrect(fz_boundnode(color, ctm));
	clip = fz_intersectirects(bbox, clip);

	if (fz_isemptyrect(clip))
		return fz_okay;

DEBUG("mask [%d %d %d %d]\n{\n", clip.x0, clip.y0, clip.x1, clip.y1);

{
fz_irect sbox = fz_roundrect(fz_boundnode(shape, ctm));
fz_irect cbox = fz_roundrect(fz_boundnode(color, ctm));
if (cbox.x0 >= sbox.x0 && cbox.x1 <= sbox.x1)
if (cbox.y0 >= sbox.y0 && cbox.y1 <= sbox.y1)
DEBUG("potentially useless mask\n");
}

	gc->clip = clip;
	gc->over = nil;

	oldmaskonly = gc->maskonly;
	gc->maskonly = 1;

	error = rendernode(gc, shape, ctm);
	if (error)
		goto cleanup;
	shapepix = gc->dest;
	gc->dest = nil;

	gc->maskonly = oldmaskonly;

	error = rendernode(gc, color, ctm);
	if (error)
		goto cleanup;
	colorpix = gc->dest;
	gc->dest = nil;

	gc->clip = oldclip;
	gc->over = oldover;

	if (shapepix && colorpix)
	{
		if (gc->over)
		{
			blendmask(gc, colorpix, shapepix, gc->over, 1);
		}
		else
		{
			clip.x0 = MAX(colorpix->x, shapepix->x);
			clip.y0 = MAX(colorpix->y, shapepix->y);
			clip.x1 = MIN(colorpix->x+colorpix->w, shapepix->x+shapepix->w);
			clip.y1 = MIN(colorpix->y+colorpix->h, shapepix->y+shapepix->h);
			error = fz_newpixmapwithrect(&gc->dest, clip, colorpix->n);
			if (error)
				goto cleanup;
			blendmask(gc, colorpix, shapepix, gc->dest, 0);
		}
	}

DEBUG("}\n");

	if (shapepix) fz_droppixmap(shapepix);
	if (colorpix) fz_droppixmap(colorpix);
	return fz_okay;

cleanup:
	if (shapepix) fz_droppixmap(shapepix);
	if (colorpix) fz_droppixmap(colorpix);
	return error;
}
Exemple #8
0
static fz_error *
rendersolid(fz_renderer *gc, fz_solidnode *solid, fz_matrix ctm)
{
	fz_error *error;
	float rgb[3];
	unsigned char a, r, g, b;
	unsigned char *p;
	int n;

	if (gc->maskonly)
		return fz_throw("assert: mask only renderer");
	if (gc->model->n != 3)
		return fz_throw("assert: non-rgb renderer");

	fz_convertcolor(solid->cs, solid->samples, gc->model, rgb);
	gc->argb[0] = solid->a * 255;
	gc->argb[1] = rgb[0] * solid->a * 255;
	gc->argb[2] = rgb[1] * solid->a * 255;
	gc->argb[3] = rgb[2] * solid->a * 255;
	gc->argb[4] = rgb[0] * 255;
	gc->argb[5] = rgb[1] * 255;
	gc->argb[6] = rgb[2] * 255;

DEBUG("solid %s [%d %d %d %d];\n", solid->cs->name, gc->argb[0], gc->argb[1], gc->argb[2], gc->argb[3]);

	if (gc->flag == FOVER)
	{
		p = gc->over->samples;
		n = gc->over->w * gc->over->h;
	}
	else
	{
		error = fz_newpixmapwithrect(&gc->dest, gc->clip, 4);
		if (error)
			return error;
		p = gc->dest->samples;
		n = gc->dest->w * gc->dest->h;
	}
	
	a = gc->argb[0];
	r = gc->argb[1];
	g = gc->argb[2];
	b = gc->argb[3];
	if (((unsigned)p & 3)) {
	while (n--)
	{
		p[0] = a;
		p[1] = r;
		p[2] = g;
		p[3] = b;
		p += 4;
	}
	}
	else
	{
		unsigned *pw = (unsigned *)p;
#if BYTE_ORDER == LITTLE_ENDIAN
		unsigned argb = a | (r << 8) | (g << 16) | (b << 24);
#else
		unsigned argb = (a << 24) | (r << 16) | (g << 8) | b;
#endif
		while (n--)
		{
			*pw++ = argb;
		}
	}

	return fz_okay;
}
Exemple #9
0
fz_error
fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_colorspace *destcs, fz_pixmap *dest)
{
	unsigned char clut[256][3];
	unsigned char *s, *d;
	fz_error error;
	fz_pixmap *temp;
	float rgb[3];
	float tri[3][MAXN];
	fz_point p;
	int i, j, k, n;

	assert(dest->n == 4);

	ctm = fz_concat(shade->matrix, ctm);

	if (shade->usefunction)
	{
		n = 3;
		error = fz_newpixmap(&temp, dest->x, dest->y, dest->w, dest->h, 2);
		if (error)
			return error;
	}
	else if (shade->cs != destcs)
	{
		n = 2 + shade->cs->n;
		error = fz_newpixmap(&temp, dest->x, dest->y, dest->w, dest->h,
			shade->cs->n + 1);
		if (error)
			return error;
	}
	else
	{
		n = 2 + shade->cs->n;
		temp = dest;
	}

	fz_clearpixmap(temp);

	for (i = 0; i < shade->meshlen; i++)
	{
		for (k = 0; k < 3; k++)
		{
			p.x = shade->mesh[(i * 3 + k) * n + 0];
			p.y = shade->mesh[(i * 3 + k) * n + 1];
			p = fz_transformpoint(ctm, p);
			if (isnan(p.y) || isnan(p.x)) // How is this happening?
			goto baddata;
			tri[k][0] = p.x;
			tri[k][1] = p.y;
			for (j = 2; j < n; j++)
				tri[k][j] = shade->mesh[( i * 3 + k) * n + j] * 255;
		}
		fz_drawtriangle(temp, tri[0], tri[1], tri[2], n);
baddata:
		;
	}

	if (shade->usefunction)
	{
		for (i = 0; i < 256; i++)
		{
			fz_convertcolor(shade->cs, shade->function[i], destcs, rgb);
			clut[i][0] = rgb[0] * 255;
			clut[i][1] = rgb[1] * 255;
			clut[i][2] = rgb[2] * 255;
		}

		n = temp->w * temp->h;
		s = temp->samples;
		d = dest->samples;

		while (n--)
		{
			d[0] = s[0];
			d[1] = fz_mul255(s[0], clut[s[1]][0]);
			d[2] = fz_mul255(s[0], clut[s[1]][1]);
			d[3] = fz_mul255(s[0], clut[s[1]][2]);
			s += 2;
			d += 4;
		}

		fz_droppixmap(temp);
	}

	else if (shade->cs != destcs)
	{
		fz_convertpixmap(shade->cs, temp, destcs, dest);
		fz_droppixmap(temp);
	}

	return fz_okay;
}
Exemple #10
0
static void
fz_stdconvpixmap(fz_pixmap *src, fz_pixmap *dst)
{
	float srcv[FZ_MAXCOLORS];
	float dstv[FZ_MAXCOLORS];
	int srcn, dstn;
	int y, x, k, i;

	fz_colorspace *ss = src->colorspace;
	fz_colorspace *ds = dst->colorspace;

	unsigned char *s = src->samples;
	unsigned char *d = dst->samples;

	assert(src->w == dst->w && src->h == dst->h);
	assert(src->n == ss->n + 1);
	assert(dst->n == ds->n + 1);

	srcn = ss->n;
	dstn = ds->n;

	/* Special case for Lab colorspace (scaling of components to float) */
	if (!strcmp(ss->name, "Lab") && srcn == 3)
	{
		for (y = 0; y < src->h; y++)
		{
			for (x = 0; x < src->w; x++)
			{
				srcv[0] = *s++ / 255.0f * 100;
				srcv[1] = *s++ - 128;
				srcv[2] = *s++ - 128;

				fz_convertcolor(ss, srcv, ds, dstv);

				for (k = 0; k < dstn; k++)
					*d++ = dstv[k] * 255;

				*d++ = *s++;
			}
		}
	}

	/* Brute-force for small images */
	else if (src->w * src->h < 256)
	{
		for (y = 0; y < src->h; y++)
		{
			for (x = 0; x < src->w; x++)
			{
				for (k = 0; k < srcn; k++)
					srcv[k] = *s++ / 255.0f;

				fz_convertcolor(ss, srcv, ds, dstv);

				for (k = 0; k < dstn; k++)
					*d++ = dstv[k] * 255;

				*d++ = *s++;
			}
		}
	}

	/* 1-d lookup table for separation and similar colorspaces */
	else if (srcn == 1)
	{
		unsigned char lookup[FZ_MAXCOLORS * 256];

		for (i = 0; i < 256; i++)
		{
			srcv[0] = i / 255.0f;
			fz_convertcolor(ss, srcv, ds, dstv);
			for (k = 0; k < dstn; k++)
				lookup[i * dstn + k] = dstv[k] * 255;
		}

		for (y = 0; y < src->h; y++)
		{
			for (x = 0; x < src->w; x++)
			{
				i = *s++;
				for (k = 0; k < dstn; k++)
					*d++ = lookup[i * dstn + k];
				*d++ = *s++;
			}
		}
	}

	/* Memoize colors using a hash table for the general case */
	else
	{
		fz_hashtable *lookup;
		unsigned char *color;

		lookup = fz_newhash(509, srcn);

		for (y = 0; y < src->h; y++)
		{
			for (x = 0; x < src->w; x++)
			{
				color = fz_hashfind(lookup, s);
				if (color)
				{
					memcpy(d, color, dstn);
					s += srcn;
					d += dstn;
					*d++ = *s++;
				}
				else
				{
					for (k = 0; k < srcn; k++)
						srcv[k] = *s++ / 255.0f;
					fz_convertcolor(ss, srcv, ds, dstv);
					for (k = 0; k < dstn; k++)
						*d++ = dstv[k] * 255;

					fz_hashinsert(lookup, s - srcn, d - dstn);

					*d++ = *s++;
				}
			}
		}

		fz_freehash(lookup);
	}
}