Beispiel #1
0
static int ft_cubic_to(const FT_Vector *c1, const FT_Vector *c2, const FT_Vector *to, void *user)
{
	ft_outliner *ftol = (ft_outliner *)user;
	gf_path_add_cubic_to(ftol->path, INT2FIX(c1->x), INT2FIX(c1->y), INT2FIX(c2->x), INT2FIX(c2->y), INT2FIX(to->x), INT2FIX(to->y) );
	if ( (ftol->last_x == to->x) && (ftol->last_y == to->y)) gf_path_close(ftol->path);
	return 0;
}
Beispiel #2
0
/* TODO: update for elliptical arcs */		
GF_EXPORT
void gf_svg_path_build(GF_Path *path, GF_List *commands, GF_List *points)
{
	u32 i, j, command_count;
	SVG_Point orig, ct_orig, ct_end, end, *tmp;
	command_count = gf_list_count(commands);
	orig.x = orig.y = ct_orig.x = ct_orig.y = 0;

	for (i=0, j=0; i<command_count; i++) {
		u8 *command = (u8 *)gf_list_get(commands, i);
		switch (*command) {
		case SVG_PATHCOMMAND_M: /* Move To */
			tmp = (SVG_Point*)gf_list_get(points, j);
			orig = *tmp;
			gf_path_add_move_to(path, orig.x, orig.y);
			j++;
			/*provision for nextCurveTo when no curve is specified:
				"If there is no previous command or if the previous command was not an C, c, S or s, 
				assume the first control point is coincident with the current point.
			*/
			ct_orig = orig;
			break;
		case SVG_PATHCOMMAND_L: /* Line To */
			tmp = (SVG_Point*)gf_list_get(points, j);
			end = *tmp;

			gf_path_add_line_to(path, end.x, end.y);
			j++;
			orig = end;
			/*cf above*/
			ct_orig = orig;
			break;
		case SVG_PATHCOMMAND_C: /* Curve To */
			tmp = (SVG_Point*)gf_list_get(points, j);
			ct_orig = *tmp;
			tmp = (SVG_Point*)gf_list_get(points, j+1);
			ct_end = *tmp;
			tmp = (SVG_Point*)gf_list_get(points, j+2);
			end = *tmp;
			gf_path_add_cubic_to(path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
			ct_orig = ct_end;
			orig = end;
			j+=3;
			break;
		case SVG_PATHCOMMAND_S: /* Next Curve To */
			ct_orig.x = 2*orig.x - ct_orig.x;
			ct_orig.y = 2*orig.y - ct_orig.y;
			tmp = (SVG_Point*)gf_list_get(points, j);
			ct_end = *tmp;
			tmp = (SVG_Point*)gf_list_get(points, j+1);
			end = *tmp;
			gf_path_add_cubic_to(path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
			ct_orig = ct_end;
			orig = end;
			j+=2;
			break;
		case SVG_PATHCOMMAND_Q: /* Quadratic Curve To */
			tmp = (SVG_Point*)gf_list_get(points, j);
			ct_orig = *tmp;
			tmp = (SVG_Point*)gf_list_get(points, j+1);
			end = *tmp;
			gf_path_add_quadratic_to(path, ct_orig.x, ct_orig.y, end.x, end.y);			
			orig = end;
			j+=2;
			break;
		case SVG_PATHCOMMAND_T: /* Next Quadratic Curve To */
			ct_orig.x = 2*orig.x - ct_orig.x;
			ct_orig.y = 2*orig.y - ct_orig.y;
			tmp = (SVG_Point*)gf_list_get(points, j);
			end = *tmp;
			gf_path_add_quadratic_to(path, ct_orig.x, ct_orig.y, end.x, end.y);
				orig = end;
				j++;
			break;
		case SVG_PATHCOMMAND_Z: /* Close */
			gf_path_close(path);
			break;
		}
	}	
}
Beispiel #3
0
GF_EXPORT
GF_Err gf_path_add_cubic_to_vec(GF_Path *gp, GF_Point2D *c1, GF_Point2D *c2, GF_Point2D *pt)
{
	return gf_path_add_cubic_to(gp, c1->x, c1->y, c2->x, c2->y, pt->x, pt->y);
}
Beispiel #4
0
void curve2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state, MFInt32 *idx)
{
	M_Curve2D *c2D;
	SFVec2f orig, ct_orig, ct_end, end;
	u32 cur_index, i, remain, type_count, pt_count;
	SFVec2f *pts;
	M_Coordinate2D *coord;

	c2D = (M_Curve2D *)node;
	coord = (M_Coordinate2D *)c2D->point;
	drawable_reset_path(stack);
	if (!coord) return;

	stack->path->fineness = c2D->fineness;
	if (tr_state->visual->compositor->high_speed)  stack->path->fineness /= 2;


	pts = coord->point.vals;
	if (!pts)
		return;

	cur_index = c2D->type.count ? 1 : 0;
	/*if the first type is a moveTo skip initial moveTo*/
	i=0;
	if (cur_index) {
		while (c2D->type.vals[i]==0) i++;
	}
	ct_orig = orig = pts[ GET_IDX(i) ];

	gf_path_add_move_to(stack->path, orig.x, orig.y);

	pt_count = coord->point.count;
	type_count = c2D->type.count;
	for (; i<type_count; i++) {

		switch (c2D->type.vals[i]) {
		/*moveTo, 1 point*/
		case 0:
			CHECK_VALID_C2D(0);
			orig = pts[ GET_IDX(cur_index) ];
			if (i) gf_path_add_move_to(stack->path, orig.x, orig.y);
			cur_index += 1;
			break;
		/*lineTo, 1 point*/
		case 1:
			CHECK_VALID_C2D(0);
			end = pts[ GET_IDX(cur_index) ];
			gf_path_add_line_to(stack->path, end.x, end.y);
			orig = end;
			cur_index += 1;
			break;
		/*curveTo, 3 points*/
		case 2:
			CHECK_VALID_C2D(2);
			ct_orig = pts[ GET_IDX(cur_index) ];
			ct_end = pts[ GET_IDX(cur_index+1) ];
			end = pts[ GET_IDX(cur_index+2) ];
			gf_path_add_cubic_to(stack->path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
			cur_index += 3;
			ct_orig = ct_end;
			orig = end;
			break;
		/*nextCurveTo, 2 points (cf spec)*/
		case 3:
			CHECK_VALID_C2D(1);
			ct_orig.x = 2*orig.x - ct_orig.x;
			ct_orig.y = 2*orig.y - ct_orig.y;
			ct_end = pts[ GET_IDX(cur_index) ];
			end = pts[ GET_IDX(cur_index+1) ];
			gf_path_add_cubic_to(stack->path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
			cur_index += 2;
			ct_orig = ct_end;
			orig = end;
			break;

		/*all XCurve2D specific*/

		/*CW and CCW ArcTo*/
		case 4:
		case 5:
			CHECK_VALID_C2D(2);
			ct_orig = pts[ GET_IDX(cur_index) ];
			ct_end = pts[ GET_IDX(cur_index+1) ];
			end = pts[ GET_IDX(cur_index+2) ];
			gf_path_add_arc_to(stack->path, end.x, end.y, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, (c2D->type.vals[i]==5) ? 1 : 0);
			cur_index += 3;
			ct_orig = ct_end;
			orig = end;
			break;
		/*ClosePath*/
		case 6:
			gf_path_close(stack->path);
			break;
		/*quadratic CurveTo, 2 points*/
		case 7:
			CHECK_VALID_C2D(1);
			ct_end = pts[ GET_IDX(cur_index) ];
			end = pts[ GET_IDX(cur_index+1) ];
			gf_path_add_quadratic_to(stack->path, ct_end.x, ct_end.y, end.x, end.y);
			cur_index += 2;
			ct_orig = ct_end;
			orig = end;
			break;
		}
	}

	/*what's left is an N-bezier spline*/
	if (!idx && (pt_count > cur_index) ) {
		/*first moveto*/
		if (!cur_index) cur_index++;

		remain = pt_count - cur_index;

		if (remain>1)
			gf_path_add_bezier(stack->path, &pts[cur_index], remain);
	}

	gf_node_dirty_clear(node, 0);
	drawable_mark_modified(stack, tr_state);
}
Beispiel #5
0
static void build_shape(FSStack *st, GF_Node *node)
{
	GF_FieldInfo field;
	MFVec2f *coords;
	MFInt32 *com, *widthIndex, *lineIndex, *fillIndex, *coordIndex;
	MFFloat *widths;
	MFColor *colors;
	u32 wi, li, fi, ci, command, i, has_ci;
	FSItem *fill_item, *line_item;
	Fixed w;
	SFVec2f cur, pt, ct1={0,0}, ct2, *pts;
	GF_Rect rc;
	u32 line_col, fill_col;
	Bool need_line, need_fill;

	/*get all fields*/
	gf_node_get_field(node, 0, &field);
	coords = field.far_ptr;
	gf_node_get_field(node, 1, &field);
	com = field.far_ptr;
	gf_node_get_field(node, 2, &field);
	widths = field.far_ptr;
	gf_node_get_field(node, 3, &field);
	colors = field.far_ptr;
	gf_node_get_field(node, 4, &field);
	widthIndex = field.far_ptr;
	gf_node_get_field(node, 5, &field);
	lineIndex = field.far_ptr;
	gf_node_get_field(node, 6, &field);
	fillIndex = field.far_ptr;
	gf_node_get_field(node, 7, &field);
	coordIndex = field.far_ptr;

	wi = li = fi = ci = 0;
	w = 0;

	st->max_width = 0;
	cur.x = cur.y = 0;
	fill_item = line_item = NULL;
	need_line = need_fill = 0;
	cur.x = cur.y = 0;
	has_ci = coordIndex->count ? 1 : 0;
	pts = coords->vals;
	line_col = fill_col = 0;

	/*implicit commands: 0 1 2 3*/

/*
	if (widthIndex->count) {
		w = (widthIndex->vals[wi]==-1) ? 0 : widths->vals[widthIndex->vals[wi]];
		if (!w) {
			need_line = 0;
			line_item = NULL;
		} else {
			need_line = 1;
			if (st->max_width<w) st->max_width = w;
		}
		wi++;
	}
	if (lineIndex->count) {
		if (w) {
			line_col = SFCOL_MAKE_ARGB(colors->vals[lineIndex->vals[li]]);
			need_line = 1;
		}
		li++;
	}
	if (fillIndex->count) {
		if (fillIndex->vals[fi]==-1) {
			fill_col = 0;
			fill_item = NULL;
		} else {
			fill_col = SFCOL_MAKE_ARGB(colors->vals[fillIndex->vals[fi]]);
			need_fill = 1;
		}
		fi++;
	}
	if (!coordIndex->count) return;
	cur = coords->vals[coordIndex->vals[ci]];
	ci++;
*/

	for (command=0; command<com->count; command++) {
		switch (com->vals[command]) {
		/*set line width*/
		case 0:
			if (wi >= widthIndex->count) return;
			w = (widthIndex->vals[wi]==-1) ? 0 : widths->vals[widthIndex->vals[wi]];
			if (!w) 
				line_item = NULL;
			else {
				need_line = 1;
				if (st->max_width<w) st->max_width = w;
			}
			wi++;
			break;
		/*set line color*/
		case 1:
			if (li > lineIndex->count) return;
			if (w) {
				line_col = SFCOL_MAKE_ARGB(colors->vals[lineIndex->vals[li]]);
				need_line = 1;
			}
			li++;
			break;
		/*set fill color*/
		case 2:
			if (fi >= fillIndex->count) return;
			if (fillIndex->vals[fi]==-1) {
				fill_col = 0;
				fill_item = NULL;
			} else {
				fill_col = SFCOL_MAKE_ARGB(colors->vals[fillIndex->vals[fi]]);
				need_fill = 1;
			}
			fi++;
			break;
		/*moveTo*/
		case 3:
			if ((has_ci && ci >= coordIndex->count) || (!has_ci && ci >= coords->count) ) return;
			if (need_fill) {
				fill_item = new_fs_item(st, 0, fill_col, 0);
				need_fill = 0;
			}
			if (need_line) {
				line_item = new_fs_item(st, line_col, 0, w);
				need_line = 0;
			}
			if (has_ci) {
				pt = pts[coordIndex->vals[ci]];
			} else {
				pt = pts[ci];
			}
			if (fill_item) gf_path_add_move_to(fill_item->path, pt.x, pt.y);
			if (line_item) gf_path_add_move_to(line_item->path, pt.x, pt.y);
			ct1 = pt;
			cur = pt;
			ci++;
			break;
		/*lineTo*/
		case 4:
			if ((has_ci && ci >= coordIndex->count) || (!has_ci && ci >= coords->count) ) return;
			if (need_fill) {
				fill_item = new_fs_item(st, 0, fill_col, 0);
				gf_path_add_move_to(fill_item->path, cur.x, cur.y);
				need_fill = 0;
			}
			if (need_line) {
				line_item = new_fs_item(st, line_col, 0, w);
				gf_path_add_move_to(line_item->path, cur.x, cur.y);
				need_line = 0;
			}
			if (has_ci) {
				pt = pts[coordIndex->vals[ci]];
			} else {
				pt = pts[ci];
			}
			if (fill_item) gf_path_add_line_to(fill_item->path, pt.x, pt.y);
			if (line_item) gf_path_add_line_to(line_item->path, pt.x, pt.y);
			cur = pt;
			ci++;
			break;
		/*cubic curveTo*/
		case 5:
			if ((has_ci && ci + 2 >= coordIndex->count) || (!has_ci && ci + 2>= coords->count) ) return;
			if (need_fill) {
				fill_item = new_fs_item(st, 0, fill_col, 0);
				gf_path_add_move_to(fill_item->path, cur.x, cur.y);
				need_fill = 0;
			}
			if (need_line) {
				line_item = new_fs_item(st, line_col, 0, w);
				gf_path_add_move_to(line_item->path, cur.x, cur.y);
				need_line = 0;
			}
			if (has_ci) {
				ct1 = pts[coordIndex->vals[ci]];
				ct2 = pts[coordIndex->vals[ci+1]];
				pt = pts[coordIndex->vals[ci+2]];
			} else {
				ct1 = pts[ci];
				ct2 = pts[ci+1];
				pt = pts[ci+2];
			}
			if (fill_item) gf_path_add_cubic_to(fill_item->path, ct1.x, ct1.y, ct2.x, ct2.y, pt.x, pt.y);
			if (line_item) gf_path_add_cubic_to(line_item->path, ct1.x, ct1.y, ct2.x, ct2.y, pt.x, pt.y);
			ct1 = ct2;
			cur = pt;
			ci += 3;
			break;
		/*cubic nextCurveTo*/
		case 6:
			if ((has_ci && ci + 1 >= coordIndex->count) || (!has_ci && ci + 1>= coords->count) ) return;
			if (need_fill) {
				fill_item = new_fs_item(st, 0, fill_col, 0);
				gf_path_add_move_to(fill_item->path, cur.x, cur.y);
				need_fill = 0;
			}
			if (need_line) {
				line_item = new_fs_item(st, line_col, 0, w);
				gf_path_add_move_to(line_item->path, cur.x, cur.y);
				need_line = 0;
			}
			ct1.x = 2*cur.x - ct1.x;
			ct1.y = 2*cur.y - ct1.y;
			if (has_ci) {
				ct2 = pts[coordIndex->vals[ci]];
				pt = pts[coordIndex->vals[ci+1]];
			} else {
				ct2 = pts[ci];
				pt = pts[ci+1];
			}
			if (fill_item) gf_path_add_cubic_to(fill_item->path, ct1.x, ct1.y, ct2.x, ct2.y, pt.x, pt.y);
			if (line_item) gf_path_add_cubic_to(line_item->path, ct1.x, ct1.y, ct2.x, ct2.y, pt.x, pt.y);
			ct1 = ct2;
			cur = pt;
			ci += 2;
			break;
		/*quadratic CurveTo*/
		case 7:
			if ((has_ci && ci + 1 >= coordIndex->count) || (!has_ci && ci + 1>= coords->count) ) return;
			if (need_fill) {
				fill_item = new_fs_item(st, 0, fill_col, 0);
				gf_path_add_move_to(fill_item->path, cur.x, cur.y);
				need_fill = 0;
			}
			if (need_line) {
				line_item = new_fs_item(st, line_col, 0, w);
				gf_path_add_move_to(line_item->path, cur.x, cur.y);
				need_line = 0;
			}
			if (has_ci) {
				ct1 = pts[coordIndex->vals[ci]];
				pt = pts[coordIndex->vals[ci+1]];
			} else {
				ct1 = pts[ci];
				pt = pts[ci+1];
			}
			if (fill_item) gf_path_add_quadratic_to(fill_item->path, ct1.x, ct1.y, pt.x, pt.y);
			if (line_item) gf_path_add_quadratic_to(line_item->path, ct1.x, ct1.y, pt.x, pt.y);
			cur = pt;
			ci += 2;
			break;
		/*quadratic nextCurveTo*/
		case 8:
			if ((has_ci && ci >= coordIndex->count) || (!has_ci && ci >= coords->count) ) return;
			if (need_fill) {
				fill_item = new_fs_item(st, 0, fill_col, 0);
				gf_path_add_move_to(fill_item->path, cur.x, cur.y);
				need_fill = 0;
			}
			if (need_line) {
				line_item = new_fs_item(st, line_col, 0, w);
				gf_path_add_move_to(line_item->path, cur.x, cur.y);
				need_line = 0;
			}
			ct1.x = 2*cur.x - ct1.x;
			ct1.y = 2*cur.y - ct1.y;
			if (has_ci) {
				pt = pts[coordIndex->vals[ci]];
			} else {
				pt = pts[ci];
			}
			if (fill_item) gf_path_add_quadratic_to(fill_item->path, ct1.x, ct1.y, pt.x, pt.y);
			if (line_item) gf_path_add_quadratic_to(line_item->path, ct1.x, ct1.y, pt.x, pt.y);
			cur = pt;
			ci += 2;
			break;
		/*close*/
		case 9:
			if (fill_item) gf_path_close(fill_item->path);
			if (line_item) gf_path_close(line_item->path);
			break;
		}
	}
	
	/*compute bounds*/
	st->bounds.width = st->bounds.height = 0;
	for (i=0; i<gf_list_count(st->items); i++) {
		line_item = gf_list_get(st->items, i);
		gf_path_get_bounds(line_item->path, &rc);
		gf_rect_union(&st->bounds, &rc);
	}
}
Beispiel #6
0
static GF_Glyph *gdip_load_glyph(GF_FontReader *dr, u32 glyph_name)
{
	GF_Rect bounds;
	GF_Glyph *glyph;
	GpPath *path_tmp;
	GpStringFormat *fmt;
	GpMatrix *mat;
	Float est_advance_h;
	unsigned short str[4];
	int i;
	FontPriv *ctx = (FontPriv *)dr->udta;

	if (!ctx->font) return NULL;

	RectF rc;
	rc.X = rc.Y = 0;
	rc.Width = rc.Height = 0;

	GdipCreateStringFormat(StringFormatFlagsNoWrap | StringFormatFlagsNoFitBlackBox | StringFormatFlagsMeasureTrailingSpaces, LANG_NEUTRAL, &fmt);
	GdipSetStringFormatAlign(fmt, StringAlignmentNear);
	GdipCreatePath(FillModeAlternate, &path_tmp);

	if (glyph_name==0x20) {
		est_advance_h = ctx->whitespace_width;
	} else {
		/*to compute first glyph alignment (say 'x', we figure out its bounding full box by using the '_' char as wrapper (eg, "_x_")
		then the bounding box starting from xMin of the glyph ('x_'). The difference between both will give us a good approx 
		of the glyph alignment*/
		str[0] = glyph_name;
		str[1] = (unsigned short) '_';
		str[2] = (unsigned short) 0;
		GdipAddPathString(path_tmp, (const WCHAR *)str, -1, ctx->font, ctx->font_style, ctx->em_size, &rc, fmt);
		GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL);
		est_advance_h = rc.Width - ctx->underscore_width;
	}
	
	GdipResetPath(path_tmp);

	str[0] = glyph_name;
	str[1] = (unsigned short) 0;
	rc.X = rc.Y = 0;
	rc.Width = rc.Height = 0;
	GdipAddPathString(path_tmp, (const WCHAR *)str, -1, ctx->font, ctx->font_style, ctx->em_size, &rc, fmt);

	GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL);

	/*flip so that we are in a font coordinate system - also move back the glyph to x=0 and y=baseline, GdiPlus doesn't do so*/
	GdipCreateMatrix(&mat);
	GdipTranslateMatrix(mat, - rc.X, -ctx->ascent, MatrixOrderAppend);
	GdipScaleMatrix(mat, 1, -1, MatrixOrderAppend);
	GdipTransformPath(path_tmp, mat);
	GdipDeleteMatrix(mat);


	/*start enum*/
	s32 count;
	GdipGetPointCount(path_tmp, &count);
	GpPointF *pts = new GpPointF[count];
	BYTE *types = new BYTE[count];
	GdipGetPathTypes(path_tmp, types, count);
	GdipGetPathPoints(path_tmp, pts, count);

	GF_SAFEALLOC(glyph, GF_Glyph);
	GF_SAFEALLOC(glyph->path, GF_Path);

	for (i=0; i<count; ) {
		BOOL closed = 0;
		s32 sub_type;
		
		sub_type = types[i] & PathPointTypePathTypeMask;

		if (sub_type == PathPointTypeStart) {
			gf_path_add_move_to(glyph->path, FLT2FIX(pts[i].X), FLT2FIX(pts[i].Y));
			i++;
		}
		else if (sub_type == PathPointTypeLine) {
			gf_path_add_line_to(glyph->path, FLT2FIX(pts[i].X), FLT2FIX(pts[i].Y));
		
			if (types[i] & PathPointTypeCloseSubpath) gf_path_close(glyph->path);

			i++;
		}
		else if (sub_type == PathPointTypeBezier) {
			assert(i+2<=count);
			gf_path_add_cubic_to(glyph->path, FLT2FIX(pts[i].X), FLT2FIX(pts[i].Y), FLT2FIX(pts[i+1].X), FLT2FIX(pts[i+1].Y), FLT2FIX(pts[i+2].X), FLT2FIX(pts[i+2].Y));

			if (types[i+2] & PathPointTypeCloseSubpath) gf_path_close(glyph->path);

			i += 3;
		} else {
			assert(0);
			break;
		}
	}
	
	delete [] pts;
	delete [] types;
	GdipDeleteStringFormat(fmt);
	GdipDeletePath(path_tmp);

	glyph->ID = glyph_name;
	glyph->utf_name = glyph_name;
	glyph->vert_advance = (s32) (ctx->ascent-ctx->descent);
	glyph->horiz_advance = (s32) est_advance_h;
	gf_path_get_bounds(glyph->path, &bounds);
	glyph->width = FIX2INT(bounds.width);
	glyph->height = FIX2INT(bounds.height);
	return glyph;
}