render.c.svn-base

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 973 行 · 第 1/2 页

SVN-BASE
973
字号
#include "fitz-base.h"#include "fitz-world.h"#include "fitz-draw.h"#ifdef _MSC_VER#define noDebug printf#ifndef DEBUG#define DEBUG#endif#else#define noDEBUG(args...) printf(args)#ifndef DEBUG#define DEBUG(args...)#endif#endif#define QUANT(x,a) (((int)((x) * (a))) / (a))#define HSUBPIX 5.0#define VSUBPIX 5.0#define FNONE 0#define FOVER 1#define FRGB 4static fz_error *rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm);fz_error *fz_newrenderer(fz_renderer **gcp, fz_colorspace *pcm, int maskonly, int gcmem){	fz_error *error;	fz_renderer *gc;	gc = fz_malloc(sizeof(fz_renderer));	if (!gc)		return fz_outofmem;	gc->maskonly = maskonly;	gc->model = pcm;	gc->cache = nil;	gc->gel = nil;	gc->ael = nil;	error = fz_newglyphcache(&gc->cache, gcmem / 24, gcmem);	if (error)		goto cleanup;	error = fz_newgel(&gc->gel);	if (error)		goto cleanup;	error = fz_newael(&gc->ael);	if (error)		goto cleanup;	gc->dest = nil;	gc->over = nil;	gc->argb[0] = 255;	gc->argb[1] = 0;	gc->argb[2] = 0;	gc->argb[3] = 0;	gc->argb[4] = 0;	gc->argb[5] = 0;	gc->argb[6] = 0;	gc->flag = 0;	*gcp = gc;	return fz_okay;cleanup:	if (gc->model) fz_dropcolorspace(gc->model);	if (gc->cache) fz_dropglyphcache(gc->cache);	if (gc->gel) fz_dropgel(gc->gel);	if (gc->ael) fz_dropael(gc->ael);	fz_free(gc);	return error;}voidfz_droprenderer(fz_renderer *gc){	if (gc->dest) fz_droppixmap(gc->dest);	if (gc->over) fz_droppixmap(gc->over);	if (gc->model) fz_dropcolorspace(gc->model);	if (gc->cache) fz_dropglyphcache(gc->cache);	if (gc->gel) fz_dropgel(gc->gel);	if (gc->ael) fz_dropael(gc->ael);	fz_free(gc);}/* * Transform */static fz_error *rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm){	fz_error *error;DEBUG("transform [%g %g %g %g %g %g]\n",transform->m.a, transform->m.b,transform->m.c, transform->m.d,transform->m.e, transform->m.f);DEBUG("{\n");	ctm = fz_concat(transform->m, ctm);	error = rendernode(gc, transform->super.first, ctm);DEBUG("}\n");	return error;}/* * Color */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;}/* * Path */static fz_error *renderpath(fz_renderer *gc, fz_pathnode *path, fz_matrix ctm){	fz_error *error;	float flatness;	fz_irect gbox;	fz_irect clip;	float expansion = fz_matrixexpansion(ctm);	flatness = 0.3 / expansion;	if (flatness < 0.1)		flatness = 0.1;	fz_resetgel(gc->gel, gc->clip);	if (path->paint == FZ_STROKE)	{		float lw = path->linewidth;		/* Check for hairline */		if (lw * expansion < 0.1) {			lw = 1.0f / expansion;		}		if (path->dash)			error = fz_dashpath(gc->gel, path, ctm, flatness, lw);		else			error = fz_strokepath(gc->gel, path, ctm, flatness, lw);	}	else		error = fz_fillpath(gc->gel, path, ctm, flatness);	if (error)		return error;	fz_sortgel(gc->gel);	gbox = fz_boundgel(gc->gel);	clip = fz_intersectirects(gc->clip, gbox);	if (fz_isemptyrect(clip))		return fz_okay;DEBUG("path %s;\n", path->paint == FZ_STROKE ? "stroke" : "fill");	if (gc->flag & FRGB)	{DEBUG(" path rgb %d %d %d %d, %d %d %d\n", gc->argb[0], gc->argb[1], gc->argb[2], gc->argb[3], gc->argb[4], gc->argb[5], gc->argb[6]);		return fz_scanconvert(gc->gel, gc->ael, path->paint == FZ_EOFILL,					clip, gc->over, gc->argb, 1);	}	else if (gc->flag & FOVER)	{		return fz_scanconvert(gc->gel, gc->ael, path->paint == FZ_EOFILL,					clip, gc->over, nil, 1);	}	else	{		error = fz_newpixmapwithrect(&gc->dest, clip, 1);		if (error)			return error;		fz_clearpixmap(gc->dest);		return fz_scanconvert(gc->gel, gc->ael, path->paint == FZ_EOFILL,					clip, gc->dest, nil, 0);	}}/* * Text */static void drawglyph(fz_renderer *gc, fz_pixmap *dst, fz_glyph *src, int xorig, int yorig){	unsigned char *dp, *sp;	int w, h;	int dx0 = dst->x;	int dy0 = dst->y;	int dx1 = dst->x + dst->w;	int dy1 = dst->y + dst->h;	int x0 = xorig + src->x;	int y0 = yorig + src->y;	int x1 = x0 + src->w;	int y1 = y0 + src->h;	int sx0 = 0;	int sy0 = 0;	int sx1 = src->w;	int sy1 = src->h;	if (x1 <= dx0 || x0 >= dx1) return;	if (y1 <= dy0 || y0 >= dy1) return;	if (x0 < dx0) { sx0 += dx0 - x0; x0 = dx0; }	if (y0 < dy0) { sy0 += dy0 - y0; y0 = dy0; }	if (x1 > dx1) { sx1 += dx1 - x1; x1 = dx1; }	if (y1 > dy1) { sy1 += dy1 - y1; y1 = dy1; }	sp = src->samples + (sy0 * src->w + sx0);	dp = dst->samples + ((y0 - dst->y) * dst->w + (x0 - dst->x)) * dst->n;	w = sx1 - sx0;	h = sy1 - sy0;	switch (gc->flag)	{	case FNONE:		assert(dst->n == 1);		fz_text_1o1(sp, src->w, dp, dst->w, w, h);		break;	case FOVER:		assert(dst->n == 1);		fz_text_1o1(sp, src->w, dp, dst->w, w, h);		break;	case FOVER | FRGB:		assert(dst->n == 4);		fz_text_w4i1o4(gc->argb, sp, src->w, dp, dst->w * 4, w, h);		break;	default:		assert(!"impossible flag in text span function");	}}static fz_error *rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm){	fz_error *error;	fz_irect tbox;	fz_irect clip;	fz_matrix tm, trm;	fz_glyph glyph;	int i, x, y, cid;	tbox = fz_roundrect(fz_boundnode((fz_node*)text, ctm));	clip = fz_intersectirects(gc->clip, tbox);DEBUG("text %s n=%d [%g %g %g %g];\n",text->font->name, text->len,text->trm.a, text->trm.b, text->trm.c, text->trm.d);	if (fz_isemptyrect(clip))		return fz_okay;	if (!(gc->flag & FOVER))	{		error = fz_newpixmapwithrect(&gc->dest, clip, 1);		if (error)			return error;		fz_clearpixmap(gc->dest);	}	tm = text->trm;	for (i = 0; i < text->len; i++)	{		cid = text->els[i].cid;		tm.e = text->els[i].x;		tm.f = text->els[i].y;		trm = fz_concat(tm, ctm);		x = fz_floor(trm.e);		y = fz_floor(trm.f);		trm.e = QUANT(trm.e - fz_floor(trm.e), HSUBPIX);		trm.f = QUANT(trm.f - fz_floor(trm.f), VSUBPIX);		error = fz_renderglyph(gc->cache, &glyph, text->font, cid, trm);		if (error)			return error;		if (!(gc->flag & FOVER))			drawglyph(gc, gc->dest, &glyph, x, y);		else			drawglyph(gc, gc->over, &glyph, x, y);	}	return fz_okay;}/* * Image */static inline voidcalcimagescale(fz_matrix ctm, int w, int h, int *odx, int *ody){	float sx, sy;	int dx, dy;	sx = sqrt(ctm.a * ctm.a + ctm.b * ctm.b);	dx = 1;	while (((w+dx-1)/dx)/sx > 2.0 && (w+dx-1)/dx > 1)		dx++;	sy = sqrt(ctm.c * ctm.c + ctm.d * ctm.d);	dy = 1;	while (((h+dy-1)/dy)/sy > 2.0 && (h+dy-1)/dy > 1)		dy++;	*odx = dx;	*ody = dy;}static fz_error *renderimage(fz_renderer *gc, fz_imagenode *node, fz_matrix ctm){	fz_error *error;	fz_image *image = node->image;	fz_irect bbox;	fz_irect clip;	int dx, dy;	fz_pixmap *tile;	fz_pixmap *temp;	fz_matrix imgmat;	fz_matrix invmat;	int fa, fb, fc, fd;	int u0, v0;	int x0, y0;	int w, h;	int tileheight;DEBUG("image %dx%d %d+%d %s\n{\n", image->w, image->h, image->n, image->a, image->cs?image->cs->name:"(nil)");	bbox = fz_roundrect(fz_boundnode((fz_node*)node, ctm));	clip = fz_intersectirects(gc->clip, bbox);	if (fz_isemptyrect(clip))		return fz_okay;        if (image->w == 0 || image->h == 0)                return fz_okay;	if (image->n + image->a == 0)		return fz_okay;	calcimagescale(ctm, image->w, image->h, &dx, &dy);	/* try to fit tile into a typical L2 cachce */	tileheight = 512 * 1024 / (image->w * (image->n + image->a));	/* tileheight must be an even multiple of dy, except for last band */	tileheight = (tileheight + dy - 1) / dy * dy;	if ((dx != 1 || dy != 1) && image->h > tileheight) {		int y = 0;		DEBUG("  load image tile size = %dx%d\n", image->w, tileheight);		error = fz_newpixmap(&tile, 0, 0, image->w,				     tileheight, image->n + 1);		if (error)			return error;		error = fz_newscaledpixmap(&temp, image->w, image->h, image->n + 1, dx, dy);		if (error)			goto cleanup;		do {			if (y + tileheight > image->h)				tileheight = image->h - y;			tile->y = y;			tile->h = tileheight;			DEBUG("  tile xywh=%d %d %d %d sxsy=1/%d 1/%d\n",			      0, y, image->w, tileheight, dx, dy);			error = image->loadtile(image, tile);			if (error)				goto cleanup1;			error = fz_scalepixmaptile(temp, 0, y, tile, dx, dy);			if (error)				goto cleanup1;			y += tileheight;		} while (y < image->h);		fz_droppixmap(tile);		tile = temp;	}	else {DEBUG("  load image\n");		error = fz_newpixmap(&tile, 0, 0, image->w, image->h, image->n + 1);		if (error)			return error;		error = image->loadtile(image, tile);		if (error)			goto cleanup;		if (dx != 1 || dy != 1)		{DEBUG("  scale image 1/%d 1/%d\n", dx, dy);			error = fz_scalepixmap(&temp, tile, dx, dy);			if (error)				goto cleanup;			fz_droppixmap(tile);			tile = temp;		}	}	if (image->cs && image->cs != gc->model)	{DEBUG("  convert from %s to %s\n", image->cs->name, gc->model->name);		error = fz_newpixmap(&temp, tile->x, tile->y, tile->w, tile->h, gc->model->n + 1);		if (error)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?