⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 path2d_stroker.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
			  point += 2;			  tags  += 2;			  vec1 = point[-2];			  vec2 = point[-1];			  if ( point <= limit ) {				  GF_Point2D  vec;				  vec = point[0];				  error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec );				  if ( error )					  goto Exit;				  continue;			  }			  error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start );			  goto Close;		  }		  break;		  }	  }Close:	  if ( error ) goto Exit;	  error = FT_Stroker_EndSubPath(stroker, (outline->tags[outline->contours[n]]==GF_PATH_CLOSE) ? 1 : 0);	  if ( error )		  goto Exit;	  first = last + 1;	}	return 0;Exit:	return error;Invalid_Outline:	return -1;}#define GF_PATH_DOT_LEN		1#define GF_PATH_DOT_SPACE	2#define GF_PATH_DASH_LEN	3static Fixed gf_path_get_dash(GF_PenSettings *pen, u32 dash_slot, u32 *next_slot){	Fixed ret = 0;	switch (pen->dash) {	case GF_DASH_STYLE_DOT:		if (dash_slot==0) ret = GF_PATH_DOT_LEN;		else if (dash_slot==1) ret = GF_PATH_DOT_SPACE;		*next_slot = (dash_slot + 1) % 2;		return ret * pen->width;	case GF_DASH_STYLE_DASH:		if (dash_slot==0) ret = GF_PATH_DASH_LEN;		else if (dash_slot==1) ret = GF_PATH_DOT_SPACE;		*next_slot = (dash_slot + 1) % 2;		return ret * pen->width;	case GF_DASH_STYLE_DASH_DOT:		if (dash_slot==0) ret = GF_PATH_DASH_LEN;		else if (dash_slot==1) ret = GF_PATH_DOT_SPACE;		else if (dash_slot==2) ret = GF_PATH_DOT_LEN;		else if (dash_slot==3) ret = GF_PATH_DOT_SPACE;		*next_slot = (dash_slot + 1) % 4;		return ret * pen->width;	case GF_DASH_STYLE_DASH_DASH_DOT:		if (dash_slot==0) ret = GF_PATH_DASH_LEN;		else if (dash_slot==1) ret = GF_PATH_DOT_SPACE;		else if (dash_slot==2) ret = GF_PATH_DASH_LEN;		else if (dash_slot==3) ret = GF_PATH_DOT_SPACE;		else if (dash_slot==4) ret = GF_PATH_DOT_LEN;		else if (dash_slot==5) ret = GF_PATH_DOT_SPACE;		*next_slot = (dash_slot + 1) % 6;		return ret * pen->width;	case GF_DASH_STYLE_DASH_DOT_DOT:		if (dash_slot==0) ret = GF_PATH_DASH_LEN;		else if (dash_slot==1) ret = GF_PATH_DOT_SPACE;		else if (dash_slot==2) ret = GF_PATH_DOT_LEN;		else if (dash_slot==3) ret = GF_PATH_DOT_SPACE;		else if (dash_slot==4) ret = GF_PATH_DOT_LEN;		else if (dash_slot==5) ret = GF_PATH_DOT_SPACE;		*next_slot = (dash_slot + 1) % 6;		return ret * pen->width;	case GF_DASH_STYLE_CUSTOM:	case GF_DASH_STYLE_CUSTOM_ABS:		if (!pen->dash_set || !pen->dash_set->num_dash) return 0;		if (dash_slot>=pen->dash_set->num_dash) dash_slot = 0;		ret = pen->dash_set->dashes[dash_slot];		*next_slot = (1 + dash_slot) % pen->dash_set->num_dash;		if (pen->dash==GF_DASH_STYLE_CUSTOM_ABS) return ret;		/*custom dashes are of type Fixed !!*/		return gf_mulfix(ret, pen->width);	default:	case GF_DASH_STYLE_PLAIN:		*next_slot = 0;		return 0;	}}/* Credits go to Raph Levien for libart / art_vpath_dash *//* FIXEME - NOT DONE - Merge first and last subpaths when first and last dash segment are joined a closepath. */static GF_Err gf_path_mergedashes(GF_Path *gp, u32 start_contour_index){	u32 i, dash_first_pt, dash_nb_pts;	if (start_contour_index) {		dash_nb_pts = gp->contours[start_contour_index] - gp->contours[start_contour_index-1];		dash_first_pt = gp->contours[start_contour_index-1]+1;	} else {		dash_nb_pts = gp->contours[start_contour_index]+1;		dash_first_pt = 0;	}	/*skip first point of first dash in subpath (same as last point of last dash)*/	for (i=1;i<dash_nb_pts; i++) {		GF_Err e = gf_path_add_line_to_vec(gp, &gp->points[dash_first_pt + i]);		if (e) return e;	}	/*remove initial dash*/	gp->n_points -= dash_nb_pts;	memmove(gp->points + dash_first_pt, gp->points + dash_first_pt + dash_nb_pts, sizeof(GF_Point2D)*(gp->n_points - dash_first_pt));	memmove(gp->tags + dash_first_pt, gp->tags + dash_first_pt + dash_nb_pts, sizeof(u8)*(gp->n_points - dash_first_pt));	for (i=start_contour_index; i<gp->n_contours-1; i++) {		gp->contours[i] = gp->contours[i+1] - dash_nb_pts; 	}	gp->n_contours--;	gp->contours = (u32 *)realloc(gp->contours, sizeof(u32)*gp->n_contours);/*	gp->points = realloc(gp->points, sizeof(GF_Point2D)*gp->n_points);	gp->tags = realloc(gp->tags, sizeof(u8)*gp->n_points);	gp->n_alloc_points = gp->n_points;*/	return GF_OK;}static GF_Err evg_dash_subpath(GF_Path *dashed, GF_Point2D *pts, u32 nb_pts, GF_PenSettings *pen, Fixed length_scale){	Fixed *dists;	Fixed totaldist;	Fixed dash;	Fixed dist;	s32 offsetinit;	u32 next_offset;	s32 toggleinit;	s32 firstindex;	Bool toggle_check;	GF_Err e;	u32 i, start_ind;	Fixed phase;	s32 offset, toggle;		dists = (Fixed *)malloc(sizeof (Fixed) * nb_pts);	if (dists == NULL) return GF_OUT_OF_MEM;		/* initial values */	toggleinit = 1;	offsetinit = 0;	dash = gf_path_get_dash(pen, offsetinit, &next_offset);	if (length_scale) dash = gf_mulfix(dash, length_scale);	firstindex = -1;	toggle_check = 0;	start_ind = 0;	dist = 0;	/* calculate line lengths and update offset*/	totaldist = 0;	for (i = 0; i < nb_pts - 1; i++) {		GF_Point2D diff;		diff.x = pts[i+1].x - pts[i].x;		diff.y = pts[i+1].y - pts[i].y;		dists[i] = gf_v2d_len(&diff);				if (pen->dash_offset > dists[i]) {			pen->dash_offset -= dists[i];			dists[i] = 0;		} else if (pen->dash_offset) {			Fixed a, x, y, dx, dy;			a = gf_divfix(pen->dash_offset, dists[i]);			dx = pts[i + 1].x - pts[i].x;			dy = pts[i + 1].y - pts[i].y;			x = pts[i].x + gf_mulfix(a, dx);			y = pts[i].y + gf_mulfix(a, dy);			e = gf_path_add_move_to(dashed, x, y);			if (e) goto err_exit;			totaldist += dists[i];			dist = pen->dash_offset;			pen->dash_offset = 0;			start_ind = i;		} else {			totaldist += dists[i];		}	}	/* subpath fits within first dash and no offset*/	if (!dist && totaldist <= dash) {		if (toggleinit) {			gf_path_add_move_to_vec(dashed, &pts[0]); 			for (i=1; i<nb_pts; i++) {				gf_path_add_line_to_vec(dashed, &pts[i]); 			}		}		free(dists);		return GF_OK;	}		/* subpath is composed of at least one dash */	phase = 0;	offset = offsetinit;	toggle = toggleinit;	i = start_ind;		if (toggle && !dist) {		e = gf_path_add_move_to_vec(dashed, &pts[i]);		if (e) goto err_exit;		firstindex = dashed->n_contours - 1;	}		while (i < nb_pts - 1) {		/* dash boundary is next */		if (dists[i] - dist > dash - phase) {			Fixed a, x, y, dx, dy;			dist += dash - phase;			a = gf_divfix(dist, dists[i]);			dx = pts[i + 1].x - pts[i].x;			dy = pts[i + 1].y - pts[i].y;			x = pts[i].x + gf_mulfix(a, dx);			y = pts[i].y + gf_mulfix(a, dy);						if (!toggle_check || ((x != pts[i].x) || (y != pts[i].y))) {				if (toggle) {					e = gf_path_add_line_to(dashed, x, y);					if (e) goto err_exit;				}				else {					e = gf_path_add_move_to(dashed, x, y);					if (e) goto err_exit;				}			}						/* advance to next dash */			toggle = !toggle;			phase = 0;			offset = next_offset;			dash = gf_path_get_dash(pen, offset, &next_offset);			if (length_scale) dash = gf_mulfix(dash, length_scale);		}		/* end of line in subpath is next */		else {			phase += dists[i] - dist;			i ++;			toggle_check = 0;			dist = 0;			if (toggle) {				e = gf_path_add_line_to_vec(dashed, &pts[i]);				if (e) goto err_exit;				toggle_check = 1;								if ( (firstindex>=0) && (i == (nb_pts - 1) && ((firstindex + 1) != (s32) start_ind ) ))  {					/*merge if closed path*/					if ((pts[0].x==pts[nb_pts-1].x) && (pts[0].y==pts[nb_pts-1].y)) {						e = gf_path_mergedashes(dashed, firstindex);						if (e) goto err_exit;					}				}			}		}	}err_exit://	pen->dash_offset = dist;	free(dists);	return GF_OK;}static GF_Path *gf_path_dash(GF_Path *path, GF_PenSettings *pen){	u32 i, j, nb_pts;	GF_Point2D *pts;	Fixed length_scale = 0;	Fixed dash_off = pen->dash_offset;	GF_Path *dashed = gf_path_new();	/* calculate line lengths and update offset*/	if (pen->path_length) {		Fixed totaldist = 0;		nb_pts = 0;		for (i=0; i<path->n_contours; i++) {			pts = &path->points[nb_pts];			nb_pts = 1+path->contours[i] - nb_pts;			for (j=0; j<nb_pts-1; j++) {				GF_Point2D diff;				diff.x = pts[j+1].x - pts[j].x;				diff.y = pts[j+1].y - pts[j].y;				totaldist += gf_v2d_len(&diff);			}			nb_pts = 1+path->contours[i];		}		length_scale = gf_divfix(totaldist, pen->path_length);		pen->dash_offset = gf_mulfix(pen->dash_offset, length_scale);	}	nb_pts = 0;	for (i=0; i<path->n_contours; i++) {		pts = &path->points[nb_pts];		nb_pts = 1+path->contours[i] - nb_pts;		evg_dash_subpath(dashed, pts, nb_pts, pen, length_scale);		nb_pts = 1+path->contours[i];//		if (length_scale) pen->dash_offset = gf_mulfix(pen->dash_offset, length_scale);	}	pen->dash_offset = dash_off;	dashed->flags |= GF_PATH_FILL_ZERO_NONZERO;	return dashed;}GF_EXPORTGF_Path *gf_path_get_outline(GF_Path *path, GF_PenSettings pen){	s32 error;	GF_Path *outline;	GF_Path *dashed;	GF_Path *scaled;	FT_Stroker stroker;	memset(&stroker, 0, sizeof(stroker));    stroker.borders[0].start = -1;    stroker.borders[1].start = -1;	stroker.line_cap = pen.cap;	stroker.line_join = pen.join;	stroker.miter_limit = pen.miterLimit;	stroker.radius = pen.width/2;	/*security: some SVG paths use a single MoveTo for points drawing but the stroker needs at least 2 points*/	if (path->n_points==1) 		gf_path_add_line_to(path, path->points[0].x, path->points[0].y);	gf_path_flatten(path);	scaled = NULL;	/*if not centered, simply scale path...*/	if (pen.align) {		Fixed sx, sy;		GF_Rect bounds;		gf_path_get_bounds(path, &bounds);		if (pen.align==GF_PATH_LINE_OUTSIDE) {			sx = gf_divfix(bounds.width+pen.width, bounds.width);			sy = gf_divfix(bounds.height+pen.width, bounds.height);		} else {			/*note: this may result in negative scaling, not our pb but the author's one*/			sx = gf_divfix(bounds.width-pen.width, bounds.width);			sy = gf_divfix(bounds.height-pen.width, bounds.height);		}		if (sx && sy) {			u32 i;			scaled = gf_path_clone(path);			for (i=0; i<scaled->n_points; i++) {				scaled->points[i].x = gf_mulfix(scaled->points[i].x, sx);				scaled->points[i].y = gf_mulfix(scaled->points[i].y, sy);			}			path = scaled;		}	}	/*if dashing, first flatten path then dash all segments*/	dashed = NULL;	/*security, seen in some SVG files*/	if (pen.dash_set && (pen.dash_set->num_dash==1) && (pen.dash_set->dashes[0]==0)) pen.dash = GF_DASH_STYLE_PLAIN;	if (pen.dash) {		GF_Path *flat;		flat = gf_path_get_flatten(path);		if (!flat) return NULL;		dashed = gf_path_dash(flat, &pen);		gf_path_del(flat);		if (!dashed) return NULL;		path = dashed;	}	outline = NULL;	error = FT_Stroker_ParseOutline(&stroker, path);	if (!error) {		u32 nb_pt, nb_cnt;		error = FT_Stroker_GetCounts(&stroker, &nb_pt, &nb_cnt);		if (!error) {			FT_StrokeBorder sborder;			outline = gf_path_new();			if (nb_pt) {				outline->points = (GF_Point2D *) malloc(sizeof(GF_Point2D)*nb_pt);				outline->tags = (u8 *) malloc(sizeof(u8)*nb_pt);				outline->contours = (u32 *) malloc(sizeof(u32)*nb_cnt);				outline->n_alloc_points = nb_pt;				sborder = &stroker.borders[0];				if (sborder->valid ) ft_stroke_border_export(sborder, outline);				sborder = &stroker.borders[1];				/*if left border is valid this is a closed path, used odd/even rule - we will have issues at recovering				segments...*/				if (sborder->valid && sborder->num_points) {					ft_stroke_border_export(sborder, outline);				}				/*otherwise this is an open path, use zero/non-zero*/				else {					outline->flags |= GF_PATH_FILL_ZERO_NONZERO;				}			}			outline->flags |= GF_PATH_BBOX_DIRTY;			/*our caps are cubic bezier!!*/			if ( (path->flags & GF_PATH_FLATTENED) && (pen.cap!=GF_LINE_CAP_ROUND) && (pen.join!=GF_LINE_JOIN_ROUND) )				outline->flags |= GF_PATH_FLATTENED;		}	}	if (stroker.borders[0].points) free(stroker.borders[0].points);	if (stroker.borders[0].tags) free(stroker.borders[0].tags);	if (stroker.borders[1].points) free(stroker.borders[1].points);	if (stroker.borders[1].tags) free(stroker.borders[1].tags);		if (dashed) gf_path_del(dashed);	if (scaled) gf_path_del(scaled);	return outline;}

⌨️ 快捷键说明

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