Ejemplo n.º 1
0
static int ft_conic_to(const FT_Vector * control, const FT_Vector *to, void *user)
{
	ft_outliner *ftol = (ft_outliner *)user;
	gf_path_add_quadratic_to(ftol->path, INT2FIX(control->x), INT2FIX(control->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;
}
Ejemplo n.º 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;
		}
	}	
}
Ejemplo n.º 3
0
Archivo: path2d.c Proyecto: erelh/gpac
GF_EXPORT
GF_Err gf_path_add_quadratic_to_vec(GF_Path *gp, GF_Point2D *c, GF_Point2D *pt)
{
	return gf_path_add_quadratic_to(gp, c->x, c->y, pt->x, pt->y);
}
Ejemplo n.º 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);
}
Ejemplo n.º 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);
	}
}
Ejemplo n.º 6
0
static void svg_sani_render_rect(GF_Node *node, void *rs, Bool is_destroy)
{
	Drawable *cs = (Drawable *)gf_node_get_private(node);
	SVG_SANI_rectElement *rect = (SVG_SANI_rectElement *)node;
	RenderEffect2D *eff = (RenderEffect2D *)rs;

	if (is_destroy) {
		DestroyDrawableNode(node);
		return;
	}
	if (eff->traversing_mode==TRAVERSE_DRAW) {
		drawable_draw(eff);
		return;
	}
	else if (eff->traversing_mode==TRAVERSE_PICK) {
		drawable_pick(eff);
		return;
	}

	svg_sani_render_base(node, (RenderEffect2D *)rs);
	
	/* 3) for a leaf node
	   Recreates the path (i.e the shape) only if the node is dirty 
	   (has changed compared to the previous rendering phase) */
	if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) {
		Fixed rx = rect->rx.value;
		Fixed ry = rect->ry.value;
		Fixed x = rect->x.value;
		Fixed y = rect->y.value;
		Fixed width = rect->width.value;
		Fixed height = rect->height.value;

		//fprintf(stdout, "Rebuilding rect %8x\n",rect);
		drawable_reset_path(cs);
		if (rx || ry) {
			if (rx >= width/2) rx = width/2;
			if (ry >= height/2) ry = height/2;
			if (rx == 0) rx = ry;
			if (ry == 0) ry = rx;
			gf_path_add_move_to(cs->path, x+rx, y);
			gf_path_add_line_to(cs->path, x+width-rx, y);
			gf_path_add_quadratic_to(cs->path, x+width, y, x+width, y+ry);
			gf_path_add_line_to(cs->path, x+width, y+height-ry);
			gf_path_add_quadratic_to(cs->path, x+width, y+height, x+width-rx, y+height);
			gf_path_add_line_to(cs->path, x+rx, y+height);
			gf_path_add_quadratic_to(cs->path, x, y+height, x, y+height-ry);
			gf_path_add_line_to(cs->path, x, y+ry);
			gf_path_add_quadratic_to(cs->path, x, y, x+rx, y);
			gf_path_close(cs->path);
		} else {
			gf_path_add_move_to(cs->path, x, y);
			gf_path_add_line_to(cs->path, x+width, y);		
			gf_path_add_line_to(cs->path, x+width, y+height);		
			gf_path_add_line_to(cs->path, x, y+height);		
			gf_path_close(cs->path);		
		}
		gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY);
		cs->flags |= DRAWABLE_HAS_CHANGED;
	}
	svg_sani_DrawablePostRender(cs, (SVG_SANI_TransformableElement *)rect, (RenderEffect2D *)rs, 1, 0);
}