node_optimize.c.svn-base

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

SVN-BASE
315
字号
#include "fitz-base.h"#include "fitz-world.h"/* * Remove (mask ... white) until we get something not white */static int iswhitenode(fz_solidnode *node){	if (!strcmp(node->cs->name, "DeviceGray"))		return fabs(node->samples[0] - 1.0) < FLT_EPSILON;	if (!strcmp(node->cs->name, "DeviceRGB"))		return fabs(node->samples[0] - 1.0) < FLT_EPSILON &&				fabs(node->samples[1] - 1.0) < FLT_EPSILON &&				fabs(node->samples[2] - 1.0) < FLT_EPSILON;	if (!strcmp(node->cs->name, "DeviceCMYK"))		return fabs(node->samples[0]) < FLT_EPSILON &&				fabs(node->samples[1]) < FLT_EPSILON &&				fabs(node->samples[2]) < FLT_EPSILON &&				fabs(node->samples[3]) < FLT_EPSILON;	return 0;}static int cleanwhite(fz_node *node){	fz_node *current;	fz_node *next;	fz_node *shape;	fz_node *color;	for (current = node->first; current; current = next)	{		next = current->next;		if (fz_islinknode(current))			return 1;		else if (fz_isimagenode(current))			return 1;		else if (fz_isshadenode(current))			return 1;		else if (fz_issolidnode(current))		{			if (!iswhitenode((fz_solidnode*)current))				return 1;		}		else if (fz_ismasknode(current))		{			shape = current->first;			color = shape->next;			if (fz_issolidnode(color))			{				if (iswhitenode((fz_solidnode*)color))					fz_removenode(current);				else					return 1;			}			else			{				if (cleanwhite(current))					return 1;			}		}		else		{			if (cleanwhite(current))				return 1;		}	}	return 0;}/* * Remove useless overs that only have one child. */static void cleanovers(fz_node *node){	fz_node *prev;	fz_node *next;	fz_node *current;	fz_node *child;	prev = nil;	for (current = node->first; current; current = next)	{		next = current->next;		if (fz_isovernode(current))		{			if (current->first == current->last)			{				child = current->first;				fz_removenode(current);				if (child)				{					if (prev)						fz_insertnodeafter(prev, child);					else						fz_insertnodefirst(node, child);				}				current = child;			}		}		if (current)			prev = current;	}	for (current = node->first; current; current = current->next)		cleanovers(current);}/* * Remove rectangular clip-masks whose contents fit... */static int getrect(fz_pathnode *path, fz_rect *bboxp){	float x, y, w, h;	/* move x y, line x+w y, line x+w y+h, line x y+h, close */	if (path->len != 13)		return 0;	if (path->els[0].k != FZ_MOVETO) return 0;	x = path->els[1].v;	y = path->els[2].v;	if (path->els[3].k != FZ_LINETO) return 0;	w = path->els[4].v - x;	if (path->els[5].v != y) return 0;	if (path->els[6].k != FZ_LINETO) return 0;	if (path->els[7].v != x + w) return 0;	h = path->els[8].v - y;	if (path->els[9].k != FZ_LINETO) return 0;	if (path->els[10].v != x) return 0;	if (path->els[11].v != y + h) return 0;	if (path->els[12].k != FZ_CLOSEPATH) return 0;	bboxp->x0 = MIN(x, x + w);	bboxp->y0 = MIN(y, y + h);	bboxp->x1 = MAX(x, x + w);	bboxp->y1 = MAX(y, y + h);	return 1;}static int fitsinside(fz_node *node, fz_rect clip){	fz_rect bbox;	bbox = fz_boundnode(node, fz_identity());	if (fz_isinfiniterect(bbox)) return 0;	if (fz_isemptyrect(bbox)) return 1;	if (bbox.x0 < clip.x0) return 0;	if (bbox.x1 > clip.x1) return 0;	if (bbox.y0 < clip.y0) return 0;	if (bbox.y1 > clip.y1) return 0;	return 1;}static void cleanmasks(fz_node *node){	fz_node *prev;	fz_node *current;	fz_node *shape;	fz_node *color;	fz_rect bbox;	for (current = node->first; current; current = current->next)		cleanmasks(current);	prev = nil;	for (current = node->first; current; current = current->next)	{retry:		if (!current)			break;		if (fz_ismasknode(current))		{			shape = current->first;			color = shape->next;			if (color == nil)			{				fz_removenode(current);				prev = nil;				current = node->first;				goto retry;			}			if (fz_ispathnode(shape))			{				if (getrect((fz_pathnode*)shape, &bbox))				{					if (fitsinside(color, bbox))					{						fz_removenode(current);						if (prev)							fz_insertnodeafter(prev, color);						else							fz_insertnodefirst(node, color);						current = color;						goto retry;					}				}			}		}		prev = current;	}}/* * Turn 1x1 images into rectangle fills */static fz_error *clean1x1(fz_node *node){	fz_error *error;	fz_node *current;	fz_node *color;	fz_pathnode *rect;	fz_node *mask;	fz_image *image;	fz_pixmap *pix;	float v[FZ_MAXCOLORS];	int i;	for (current = node->first; current; current = current->next)	{		if (fz_isimagenode(current))		{			image = ((fz_imagenode*)current)->image;			if (image->w == 1 && image->h == 1)			{				error = fz_newpathnode(&rect);				fz_moveto(rect, 0, 0);				fz_lineto(rect, 1, 0);				fz_lineto(rect, 1, 1);				fz_lineto(rect, 0, 1);				fz_closepath(rect);				fz_endpath(rect, FZ_FILL, nil, nil);				if (image->cs)				{					error = fz_newpixmap(&pix, 0, 0, 1, 1, image->n + 1);					if (error)						return fz_rethrow(error, "cannot create 1x1 pixmap");					error = image->loadtile(image, pix);					if (error)						return fz_rethrow(error, "cannot load pixmap tile");					for (i = 0; i < image->n; i++)						v[i] = pix->samples[i + 1] / 255.0;					fz_droppixmap(pix);					error = fz_newsolidnode(&color, 1.0, image->cs, image->n, v);					if (error)						return fz_rethrow(error, "cannot create color node");					error = fz_newmasknode(&mask);					if (error)						return fz_rethrow(error, "cannot create mask node");					fz_insertnodeafter(current, mask);					fz_insertnodelast(mask, (fz_node*)rect);					fz_insertnodelast(mask, color);					fz_removenode(current);					current = mask;				}				else				{					/* pray that the 1x1 image mask is all opaque */					fz_insertnodeafter(current, (fz_node*)rect);					fz_removenode(current);					current = (fz_node*)rect;				}			}		}		error = clean1x1(current);		if (error)			return fz_rethrow(error, "cannot perform clean1x1 optimization");	}	return fz_okay;}/* * */fz_error *fz_optimizetree(fz_tree *tree){	if (getenv("DONTOPT"))		return fz_okay;	cleanwhite(tree->root);	cleanovers(tree->root);	cleanmasks(tree->root);	clean1x1(tree->root);	return fz_okay;}

⌨️ 快捷键说明

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