render.c

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

C
973
字号
			goto cleanup;		fz_convertpixmap(image->cs, tile, gc->model, temp);		fz_droppixmap(tile);		tile = temp;	}	imgmat.a = 1.0 / tile->w;	imgmat.b = 0.0;	imgmat.c = 0.0;	imgmat.d = -1.0 / tile->h;	imgmat.e = 0.0;	imgmat.f = 1.0;	invmat = fz_invertmatrix(fz_concat(imgmat, ctm));	w = clip.x1 - clip.x0;	h = clip.y1 - clip.y0;	x0 = clip.x0;	y0 = clip.y0;	u0 = (invmat.a * (x0+0.5) + invmat.c * (y0+0.5) + invmat.e) * 65536;	v0 = (invmat.b * (x0+0.5) + invmat.d * (y0+0.5) + invmat.f) * 65536;	fa = invmat.a * 65536;	fb = invmat.b * 65536;	fc = invmat.c * 65536;	fd = invmat.d * 65536;#define PSRC tile->samples, tile->w, tile->h#define PDST(p) p->samples + ((y0-p->y) * p->w + (x0-p->x)) * p->n, p->w * p->n#define PCTM u0, v0, fa, fb, fc, fd, w, h	switch (gc->flag)	{	case FNONE:		{DEBUG("  fnone %d x %d\n", w, h);			if (image->cs)				error = fz_newpixmapwithrect(&gc->dest, clip, gc->model->n + 1);			else				error = fz_newpixmapwithrect(&gc->dest, clip, 1);			if (error)				goto cleanup;			if (image->cs)				fz_img_4c4(PSRC, PDST(gc->dest), PCTM);			else				fz_img_1c1(PSRC, PDST(gc->dest), PCTM);		}		break;	case FOVER:		{DEBUG("  fover %d x %d\n", w, h);			if (image->cs)				fz_img_4o4(PSRC, PDST(gc->over), PCTM);			else				fz_img_1o1(PSRC, PDST(gc->over), PCTM);		}		break;	case FOVER | FRGB:DEBUG("  fover+rgb %d x %d\n", w, h);		fz_img_w4i1o4(gc->argb, PSRC, PDST(gc->over), PCTM);		break;	default:		assert(!"impossible flag in image span function");	}DEBUG("}\n");	fz_droppixmap(tile);	return fz_okay;cleanup1:	fz_droppixmap(temp);cleanup:	fz_droppixmap(tile);	return error;}/* * Shade */static fz_error *rendershade(fz_renderer *gc, fz_shadenode *node, fz_matrix ctm){	fz_error *error;	fz_irect bbox;	assert(!gc->maskonly);	DEBUG("shade;\n");	bbox = fz_roundrect(fz_boundnode((fz_node*)node, ctm));	bbox = fz_intersectirects(gc->clip, bbox);	error = fz_newpixmapwithrect(&gc->dest, bbox, gc->model->n + 1);	if (error)		return error;	return fz_rendershade(node->shade, ctm, gc->model, gc->dest);}/* * Over, Mask and Blend */static voidblendover(fz_renderer *gc, fz_pixmap *src, fz_pixmap *dst){	unsigned char *sp, *dp;	fz_irect sr, dr;	int x, y, w, h;	sr.x0 = src->x;	sr.y0 = src->y;	sr.x1 = src->x + src->w;	sr.y1 = src->y + src->h;	dr.x0 = dst->x;	dr.y0 = dst->y;	dr.x1 = dst->x + dst->w;	dr.y1 = dst->y + dst->h;	dr = fz_intersectirects(sr, dr);	x = dr.x0;	y = dr.y0;	w = dr.x1 - dr.x0;	h = dr.y1 - dr.y0;	sp = src->samples + ((y - src->y) * src->w + (x - src->x)) * src->n;	dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;	if (src->n == 1 && dst->n == 1)		fz_duff_1o1(sp, src->w, dp, dst->w, w, h);	else if (src->n == 4 && dst->n == 4)		fz_duff_4o4(sp, src->w * 4, dp, dst->w * 4, w, h);	else if (src->n == dst->n)		fz_duff_non(sp, src->w * src->n, src->n, dp, dst->w * dst->n, w, h);	else		assert(!"blendover src and dst mismatch");}static voidblendmask(fz_renderer *gc, fz_pixmap *src, fz_pixmap *msk, fz_pixmap *dst, int over){	unsigned char *sp, *dp, *mp;	fz_irect sr, dr, mr;	int x, y, w, h;	sr.x0 = src->x;	sr.y0 = src->y;	sr.x1 = src->x + src->w;	sr.y1 = src->y + src->h;	dr.x0 = dst->x;	dr.y0 = dst->y;	dr.x1 = dst->x + dst->w;	dr.y1 = dst->y + dst->h;	mr.x0 = msk->x;	mr.y0 = msk->y;	mr.x1 = msk->x + msk->w;	mr.y1 = msk->y + msk->h;	dr = fz_intersectirects(sr, dr);	dr = fz_intersectirects(dr, mr);	x = dr.x0;	y = dr.y0;	w = dr.x1 - dr.x0;	h = dr.y1 - dr.y0;	sp = src->samples + ((y - src->y) * src->w + (x - src->x)) * src->n;	mp = msk->samples + ((y - msk->y) * msk->w + (x - msk->x)) * msk->n;	dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;	if (over)	{		if (src->n == 1 && msk->n == 1 && dst->n == 1)			fz_duff_1i1o1(sp, src->w, mp, msk->w, dp, dst->w, w, h);		else if (src->n == 4 && msk->n == 1 && dst->n == 4)			fz_duff_4i1o4(sp, src->w * 4, mp, msk->w, dp, dst->w * 4, w, h);		else if (src->n == dst->n)			fz_duff_nimon(sp, src->w * src->n, src->n, mp, msk->w * msk->n, msk->n, dp, dst->w * dst->n, w, h);		else			assert(!"blendmaskover src and msk and dst mismatch");	}	else	{		if (src->n == 1 && msk->n == 1 && dst->n == 1)			fz_duff_1i1c1(sp, src->w, mp, msk->w, dp, dst->w, w, h);		else if (src->n == 4 && msk->n == 1 && dst->n == 4)			fz_duff_4i1c4(sp, src->w * 4, mp, msk->w, dp, dst->w * 4, w, h);		else if (src->n == dst->n)			fz_duff_nimcn(sp, src->w * src->n, src->n, mp, msk->w * msk->n, msk->n, dp, dst->w * dst->n, w, h);		else			assert(!"blendmask src and msk and dst mismatch");	}}static fz_error *renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm){	fz_error *error;	fz_node *child;	int cluster = 0;	if (!gc->over)	{DEBUG("over cluster %d\n{\n", gc->maskonly ? 1 : 4);		cluster = 1;		if (gc->maskonly)			error = fz_newpixmapwithrect(&gc->over, gc->clip, 1);		else			error = fz_newpixmapwithrect(&gc->over, gc->clip, 4);		if (error)			return error;		fz_clearpixmap(gc->over);	}else DEBUG("over\n{\n");	for (child = over->super.first; child; child = child->next)	{		error = rendernode(gc, child, ctm);		if (error)			return error;		if (gc->dest)		{			blendover(gc, gc->dest, gc->over);			fz_droppixmap(gc->dest);			gc->dest = nil;		}	}	if (cluster)	{		gc->dest = gc->over;		gc->over = nil;	}DEBUG("}\n");	return fz_okay;}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;}/* * Dispatch */static fz_error *rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm){	if (!node)		return fz_okay;	gc->flag = FNONE;	if (gc->over)		gc->flag |= FOVER;	switch (node->kind)	{	case FZ_NOVER:		return renderover(gc, (fz_overnode*)node, ctm);	case FZ_NMASK:		return rendermask(gc, (fz_masknode*)node, ctm);	case FZ_NTRANSFORM:		return rendertransform(gc, (fz_transformnode*)node, ctm);	case FZ_NCOLOR:		return rendersolid(gc, (fz_solidnode*)node, ctm);	case FZ_NPATH:		return renderpath(gc, (fz_pathnode*)node, ctm);	case FZ_NTEXT:		return rendertext(gc, (fz_textnode*)node, ctm);	case FZ_NIMAGE:		return renderimage(gc, (fz_imagenode*)node, ctm);	case FZ_NSHADE:		return rendershade(gc, (fz_shadenode*)node, ctm);	case FZ_NLINK:		return rendernode(gc, ((fz_linknode*)node)->tree->root, ctm);	case FZ_NBLEND:		return fz_okay;	}	return fz_okay;}fz_error *fz_rendertree(fz_pixmap **outp,	fz_renderer *gc, fz_tree *tree, fz_matrix ctm,	fz_irect bbox, int white){	fz_error *error;	gc->clip = bbox;	gc->over = nil;	if (gc->maskonly)		error = fz_newpixmapwithrect(&gc->over, bbox, 1);	else		error = fz_newpixmapwithrect(&gc->over, bbox, 4);	if (error)		return error;	if (white)		memset(gc->over->samples, 0xff, gc->over->w * gc->over->h * gc->over->n);	else		memset(gc->over->samples, 0x00, gc->over->w * gc->over->h * gc->over->n);DEBUG("tree %d [%d %d %d %d]\n{\n",gc->maskonly ? 1 : 4,bbox.x0, bbox.y0, bbox.x1, bbox.y1);	error = rendernode(gc, tree->root, ctm);	if (error)		return error;DEBUG("}\n");	if (gc->dest)	{		blendover(gc, gc->dest, gc->over);		fz_droppixmap(gc->dest);		gc->dest = nil;	}	*outp = gc->over;	gc->over = nil;	return fz_okay;}fz_error *fz_rendertreeover(fz_renderer *gc, fz_pixmap *dest, fz_tree *tree, fz_matrix ctm){	fz_error *error;	assert(!gc->maskonly);	assert(dest->n == 4);	gc->clip.x0 = dest->x;	gc->clip.y0 = dest->y;	gc->clip.x1 = dest->x + dest->w;	gc->clip.y1 = dest->y + dest->h;	gc->over = dest;	error = rendernode(gc, tree->root, ctm);	if (error)	{		gc->over = nil;		return error;	}	if (gc->dest)	{		blendover(gc, gc->dest, gc->over);		fz_droppixmap(gc->dest);		gc->dest = nil;	}	gc->over = nil;	return fz_okay;}

⌨️ 快捷键说明

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