Exemplo n.º 1
0
static void text_check_changes(GF_Node *node, TextStack *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node) || tr_state->visual->compositor->reset_fonts) {
		text_clean_paths(tr_state->visual->compositor, stack);
		build_text(stack, (M_Text*)node, tr_state);
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack->graph, tr_state);
	}
	
	if (tr_state->visual->compositor->edited_text && (tr_state->visual->compositor->focus_node==node)) {
		drawable_mark_modified(stack->graph, tr_state);	
		tr_state->visual->has_text_edit = 1;
		if (!stack->bounds.width) stack->bounds.width = INT2FIX(1)/100;
		if (!stack->bounds.height) stack->bounds.height = INT2FIX(1)/100;
	}
}
Exemplo n.º 2
0
static void ellipse_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		drawable_reset_path(stack);
		gf_path_add_ellipse(stack->path, 0, 0, ((M_Ellipse *) node)->radius.x*2, ((M_Ellipse *) node)->radius.y*2);
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Exemplo n.º 3
0
static void circle_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		Fixed a = ((M_Circle *) node)->radius * 2;
		drawable_reset_path(stack);
		gf_path_add_ellipse(stack->path, 0, 0, a, a);
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Exemplo n.º 4
0
static void rectangle_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	/*if modified update node - we don't update for other traversing mode in order not to mess up the dirty
	rect tracking (otherwise we would miss geometry changes with same bounds)*/
	if (gf_node_dirty_get(node)) {
		drawable_reset_path(stack);
		gf_path_add_rect_center(stack->path, 0, 0, ((M_Rectangle *) node)->size.x, ((M_Rectangle *) node)->size.y);
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Exemplo n.º 5
0
static void disk2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		Fixed a = ((X_Disk2D *) node)->outerRadius * 2;
		drawable_reset_path(stack);
		gf_path_add_ellipse(stack->path, 0, 0, a, a);
		a = ((X_Disk2D *) node)->innerRadius * 2;
		if (a) gf_path_add_ellipse(stack->path, 0, 0, a, a);
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Exemplo n.º 6
0
static void arc2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		drawable_reset_path(stack);
		if (gf_node_get_tag(node)==TAG_X3D_Arc2D) {
			X_Arc2D *a = (X_Arc2D *) node;
			gf_path_add_arc(stack->path, a->radius, a->startAngle, a->endAngle, 0);
		} else {
			X_ArcClose2D *a = (X_ArcClose2D *) node;
			gf_path_add_arc(stack->path, a->radius, a->startAngle, a->endAngle, !stricmp(a->closureType.buffer, "PIE") ? 2 : 1);
		}
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Exemplo n.º 7
0
static void polyline2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		u32 i;
		X_Polyline2D *a = (X_Polyline2D *) node;
		drawable_reset_path(stack);
		for (i=0; i<a->lineSegments.count; i++) {
			if (i) {
				gf_path_add_line_to(stack->path, a->lineSegments.vals[i].x, a->lineSegments.vals[i].y);
			} else {
				gf_path_add_move_to(stack->path, a->lineSegments.vals[i].x, a->lineSegments.vals[i].y);
			}
		}
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Exemplo n.º 8
0
static void triangleset2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		u32 i, count;
		X_TriangleSet2D *p = (X_TriangleSet2D *)node;
		drawable_reset_path(stack);
		count = p->vertices.count;
		while (count%3) count--;
		for (i=0; i<count; i+=3) {
			gf_path_add_move_to(stack->path, p->vertices.vals[i].x, p->vertices.vals[i].y);
			gf_path_add_line_to(stack->path, p->vertices.vals[i+1].x, p->vertices.vals[i+1].y);
			gf_path_add_line_to(stack->path, p->vertices.vals[i+2].x, p->vertices.vals[i+2].y);
			gf_path_close(stack->path);
		}
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
static void ifs2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	u32 i;
	SFVec2f *pts;
	u32 ci_count, c_count;
	Bool started;
	M_IndexedFaceSet2D *ifs2D;
	M_Coordinate2D *coord;

	if (! gf_node_dirty_get(node)) return;

	ifs2D = (M_IndexedFaceSet2D *)node;
	coord = (M_Coordinate2D *)ifs2D->coord;
	drawable_reset_path(stack);
	gf_node_dirty_clear(node, 0);
	drawable_mark_modified(stack, tr_state);


	c_count = coord->point.count;
	ci_count = ifs2D->coordIndex.count;
	pts = coord->point.vals;

	if (ci_count > 0) {
		started = 0;
		for (i=0; i < ci_count; i++) {
			if (ifs2D->coordIndex.vals[i] == -1) {
				gf_path_close(stack->path);
				started = 0;
			} else if (!started) {
				started = 1;
				gf_path_add_move_to_vec(stack->path, &pts[ifs2D->coordIndex.vals[i]]);
			} else {
				gf_path_add_line_to_vec(stack->path, &pts[ifs2D->coordIndex.vals[i]]);
			}
		}
		if (started) gf_path_close(stack->path);
	} else if (c_count) {
		gf_path_add_move_to_vec(stack->path, &pts[0]);
		for (i=1; i < c_count; i++) {
			gf_path_add_line_to_vec(stack->path, &pts[i]);
		}
		gf_path_close(stack->path);
	}
}
Exemplo n.º 10
0
static void pointset2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	u32 i;
	Fixed w, h;
	M_Coordinate2D *coord;

	if (!gf_node_dirty_get(node)) return;
	coord = (M_Coordinate2D *) ((M_PointSet2D *)node)->coord;

	drawable_reset_path(stack);

	get_point_size(&tr_state->transform, &w, &h);
	/*for PS2D don't add to avoid too  much antialiasing, just try to fill the given pixel*/
	for (i=0; i < coord->point.count; i++)
		gf_path_add_rect(stack->path, coord->point.vals[i].x, coord->point.vals[i].y, w, h);

	stack->path->flags |= GF_PATH_FILL_ZERO_NONZERO;

	gf_node_dirty_clear(node, 0);
	drawable_mark_modified(stack, tr_state);
}
Exemplo n.º 11
0
static void ils2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	u32 i;
	Bool started;
	SFVec2f *pts;
	M_IndexedLineSet2D *ils2D;
	M_Coordinate2D *coord;

	if (! gf_node_dirty_get(node)) return;

	drawable_reset_path(stack);
	gf_node_dirty_clear(node, 0);
	drawable_mark_modified(stack, tr_state);

	ils2D = (M_IndexedLineSet2D *)node;
	coord = (M_Coordinate2D *)ils2D->coord;

	pts = coord->point.vals;
	if (ils2D->coordIndex.count > 0) {
		started = 0;
		for (i=0; i < ils2D->coordIndex.count; i++) {
			/*NO close on ILS2D*/
			if (ils2D->coordIndex.vals[i] == -1) {
				started = 0;
			} else if (!started) {
				started = 1;
				gf_path_add_move_to(stack->path, pts[ils2D->coordIndex.vals[i]].x, pts[ils2D->coordIndex.vals[i]].y);
			} else {
				gf_path_add_line_to(stack->path, pts[ils2D->coordIndex.vals[i]].x, pts[ils2D->coordIndex.vals[i]].y);
			}
		}
	} else if (coord->point.count) {
		gf_path_add_move_to(stack->path, pts[0].x, pts[0].y);
		for (i=1; i < coord->point.count; i++) {
			gf_path_add_line_to(stack->path, pts[i].x, pts[i].y);
		}
	}
	stack->path->flags |= GF_PATH_FILL_ZERO_NONZERO;
}
Exemplo n.º 12
0
static void svg_traverse_textArea(GF_Node *node, void *rs, Bool is_destroy)
{
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	GF_Matrix mx3d;
	GF_Matrix2D backup_matrix;
	DrawableContext *ctx = NULL;
	GF_ChildNodeItem *child;
	SVG_TextStack *st = (SVG_TextStack *)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVG_Element *text = (SVG_Element *)node;
	SVGAllAttributes atts;

	if (is_destroy) {
		drawable_del(st->drawable);
		svg_reset_text_stack(st);
		gf_list_del(st->spans);
		gf_free(st);
		return;
	}

	if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) {
		svg_text_draw_2d(st, tr_state);
		return;
	}
	else if (tr_state->traversing_mode==TRAVERSE_GET_TEXT) {
		tr_state->text_parent = node;
		gf_font_spans_get_selection(node, st->spans, tr_state);
		/*and browse children*/
		child = ((GF_ParentNode *) text)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
			case TAG_SVG_a:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
		tr_state->text_parent = NULL;
		return;
	}


	gf_svg_flatten_attributes(text, &atts);
	if (!compositor_svg_traverse_base(node, &atts, tr_state, &backup_props, &backup_flags))
		return;

	tr_state->text_parent = node;
	tr_state->in_svg_text_area++;

	if (tr_state->traversing_mode==TRAVERSE_PICK) {
		if (*tr_state->svg_props->pointer_events!=SVG_POINTEREVENTS_NONE) {
			compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d);
			gf_font_spans_pick(node, st->spans, tr_state, &st->bounds, GF_TRUE, st->drawable);

			/*and browse children*/
			child = ((GF_ParentNode *) node)->children;
			while (child) {
				gf_node_traverse(child->node, tr_state);
				child = child->next;
			}
			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d);
			memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
			tr_state->svg_flags = backup_flags;
		}
		tr_state->in_svg_text_area--;
		tr_state->text_parent = NULL;
		return;
	}

	compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d);

	if ( (st->prev_size != tr_state->svg_props->font_size->value) ||
	        (st->prev_flags != *tr_state->svg_props->font_style) ||
	        (st->prev_anchor != *tr_state->svg_props->text_anchor) ||
	        (gf_node_dirty_get(node) & (GF_SG_SVG_GEOMETRY_DIRTY | GF_SG_CHILD_DIRTY) )
	        || tr_state->visual->compositor->reset_fonts
	   ) {
		u32 mode;

		child = ((GF_ParentNode *) text)->children;

		svg_reset_text_stack(st);
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(st->drawable, tr_state);
		drawable_reset_path(st->drawable);

		tr_state->max_length = (atts.width ? (atts.width->type == SVG_NUMBER_AUTO ? FIX_MAX : atts.width->value) : FIX_MAX);
		tr_state->max_height = (atts.height ? (atts.height->type == SVG_NUMBER_AUTO ? FIX_MAX : atts.height->value) : FIX_MAX);
		tr_state->base_x = (atts.x ? atts.x->value : 0);
		tr_state->base_y = (atts.y ? atts.y->value : 0);
		/*init the xml:space algo*/
		tr_state->last_char_type = 0;
		/*let it initialize from first font*/
		tr_state->line_spacing = 0;
		tr_state->text_end_x = 0;
		tr_state->text_end_y = (tr_state->svg_props->line_increment->type == SVG_NUMBER_AUTO ? 0 : tr_state->svg_props->line_increment->value);

		tr_state->x_anchors = gf_list_new();

		if (tr_state->svg_props->font_size && (tr_state->svg_props->font_size->value <= tr_state->max_height)) {
			Fixed remain;
			u32 c, refresh_to_idx, prev_refresh;
			/*switch to bounds mode, and recompute children*/
			mode = tr_state->traversing_mode;
			tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;

			prev_refresh = tr_state->refresh_children_bounds;
			tr_state->refresh_children_bounds = 0;
			c = refresh_to_idx = 0;
			child = ((GF_ParentNode *) text)->children;
			while (child) {
				c++;
				switch  (gf_node_get_tag(child->node)) {
				case TAG_DOMText:
					svg_traverse_dom_text_area(child->node, &atts, tr_state, st->spans);
					break;
				case TAG_SVG_tspan:
					/*mark tspan as dirty to force rebuild*/
					gf_node_dirty_set(child->node, 0, GF_FALSE);
					gf_node_traverse(child->node, tr_state);
					break;
				case TAG_SVG_switch:
				case TAG_SVG_a:
				case TAG_SVG_tbreak:
					gf_node_traverse(child->node, tr_state);
					break;
				default:
					break;
				}
				if (tr_state->refresh_children_bounds) {
					tr_state->refresh_children_bounds=0;
					refresh_to_idx=c;
				}

				child=child->next;
			}
			st->prev_size = tr_state->svg_props->font_size->value;
			st->prev_flags = *tr_state->svg_props->font_style;
			st->prev_anchor = *tr_state->svg_props->text_anchor;

			svg_text_area_reset_state(tr_state);
			gf_list_del(tr_state->x_anchors);
			tr_state->x_anchors = NULL;

			remain = 0;
			if (tr_state->refresh_children_bounds) {
				refresh_to_idx = (u32) -1;
				tr_state->base_shift = 0;
			}
			if (tr_state->svg_props->display_align) {
				switch (*tr_state->svg_props->display_align) {
				case SVG_DISPLAYALIGN_CENTER:
					remain = (tr_state->max_height-tr_state->text_end_y) / 2;
					break;
				case SVG_DISPLAYALIGN_AFTER:
					remain = tr_state->max_height - tr_state->text_end_y;
					break;
				default:
					remain = 0;
					break;
				}
				if (remain<0) remain=0;
				if (remain) {
					refresh_to_idx = (u32) -1;
					tr_state->base_shift = remain;
					svg_text_area_shift_bounds(st, tr_state);
				}
			}

			if (refresh_to_idx) {
				tr_state->refresh_children_bounds=1;
				/*and retraverse in case of bounds adjustements*/
				child = ((GF_ParentNode *) text)->children;
				while (child) {
					switch (gf_node_get_tag(child->node)) {
					case TAG_DOMText:
						break;
					case TAG_SVG_tspan:
					case TAG_SVG_switch:
					case TAG_SVG_a:
						gf_node_traverse(child->node, tr_state);
						break;
					default:
						break;
					}
					child=child->next;
					refresh_to_idx--;
					if (!refresh_to_idx) break;
				}
				tr_state->base_shift = 0;
			}
			tr_state->traversing_mode = mode;
			tr_state->refresh_children_bounds = prev_refresh;
		}
		svg_update_bounds(st);
	}

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		if (!compositor_svg_is_display_off(tr_state->svg_props))
			tr_state->bounds = st->bounds;
	} else if ( (tr_state->traversing_mode == TRAVERSE_SORT)
	            && !compositor_svg_is_display_off(tr_state->svg_props)
	            && (*(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN)
	          ) {

		ctx = drawable_init_context_svg(st->drawable, tr_state);
		if (ctx) svg_finalize_sort(ctx, st, tr_state);

		child = ((GF_ParentNode *) text)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_DOMText:
				break;
			case TAG_SVG_tspan:
			case TAG_SVG_switch:
			case TAG_SVG_a:
				gf_node_traverse(child->node, tr_state);
				break;
			default:
				break;
			}
			child = child->next;
		}
	}
	tr_state->in_svg_text_area--;
	tr_state->text_parent = NULL;


	compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d);
	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}
Exemplo n.º 13
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);
}
Exemplo n.º 14
0
static void SVG_Build_Bitmap_Graph(SVG_video_stack *stack, GF_TraverseState *tr_state)
{
	u32 tag;
	GF_Rect rc, new_rc;
	Fixed x, y, width, height, txwidth, txheight;
	Fixed rectx, recty, rectwidth, rectheight;
	SVGAllAttributes atts;
	SVG_PreserveAspectRatio pAR;
	SVG_Element *e = (SVG_Element *)stack->graph->node;

	gf_svg_flatten_attributes(e, &atts);
	
	tag = gf_node_get_tag(stack->graph->node);
	switch (tag) {
	case TAG_SVG_image:
	case TAG_SVG_video:
		x = (atts.x ? atts.x->value : 0);
		y = (atts.y ? atts.y->value : 0);
		width = (atts.width ? atts.width->value : 0);
		height = (atts.height ? atts.height->value : 0);
		break;
	default:
		return;
	}

	if (!width || !height) return;
	
	txheight = INT2FIX(stack->txh.height);
	txwidth = INT2FIX(stack->txh.width);

	if (!txwidth || !txheight) return;

	if (!atts.preserveAspectRatio) {
		pAR.defer = GF_FALSE;
		pAR.meetOrSlice = SVG_MEETORSLICE_MEET;
		pAR.align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
	} else {
		pAR = *atts.preserveAspectRatio;
	}
	if (pAR.defer) {
		/* TODO */
		rectwidth = width;
		rectheight = height;
		rectx = x+rectwidth/2;
		recty = y+rectheight/2;
	} else {

		if (pAR.align==SVG_PRESERVEASPECTRATIO_NONE) {
			rectwidth = width;
			rectheight = height;				
			rectx = x+rectwidth/2;
			recty = y+rectheight/2;
		} else {
			Fixed scale, scale_w, scale_h;
			scale_w = gf_divfix(width, txwidth);
			scale_h = gf_divfix(height, txheight);
			if (pAR.meetOrSlice==SVG_MEETORSLICE_MEET) {
				if (scale_w > scale_h) {
					scale = scale_h;
					rectwidth = gf_mulfix(txwidth, scale);
					rectheight = height;
				} else {
					scale = scale_w;
					rectwidth = width;
					rectheight = gf_mulfix(txheight, scale);
				}
			} else {
				if (scale_w < scale_h) {
					scale = scale_h;
					rectwidth = gf_mulfix(txwidth, scale);
					rectheight = height;
				} else {
					scale = scale_w;
					rectwidth = width;
					rectheight = gf_mulfix(txheight, scale);
				}
			}

			rectx = x + rectwidth/2;
			recty = y + rectheight/2;
			switch (pAR.align) {
			case SVG_PRESERVEASPECTRATIO_XMINYMIN:
				break;
			case SVG_PRESERVEASPECTRATIO_XMIDYMIN:
				rectx += (width - rectwidth)/ 2; 
				break;
			case SVG_PRESERVEASPECTRATIO_XMAXYMIN:
				rectx += width - rectwidth; 
				break;
			case SVG_PRESERVEASPECTRATIO_XMINYMID:
				recty += (height - rectheight)/ 2; 
				break;
			case SVG_PRESERVEASPECTRATIO_XMIDYMID:
				rectx += (width - rectwidth)/ 2; 
				recty += (height - rectheight) / 2; 
				break;
			case SVG_PRESERVEASPECTRATIO_XMAXYMID:
				rectx += width - rectwidth; 
				recty += ( txheight - rectheight) / 2; 
				break;
			case SVG_PRESERVEASPECTRATIO_XMINYMAX:
				recty += height - rectheight; 
				break;
			case SVG_PRESERVEASPECTRATIO_XMIDYMAX:
				rectx += (width - rectwidth)/ 2; 
				recty += height - rectheight; 
				break;
			case SVG_PRESERVEASPECTRATIO_XMAXYMAX:
				rectx += width  - rectwidth; 
				recty += height - rectheight; 
				break;
			}
		}
	}


	gf_path_get_bounds(stack->graph->path, &rc);
	drawable_reset_path(stack->graph);
	gf_path_add_rect_center(stack->graph->path, rectx, recty, rectwidth, rectheight);
	gf_path_get_bounds(stack->graph->path, &new_rc);
	if (!gf_rect_equal(rc, new_rc)) 
		drawable_mark_modified(stack->graph, tr_state);
	else if (stack->txh.flags & GF_SR_TEXTURE_PRIVATE_MEDIA)
		drawable_mark_modified(stack->graph, tr_state);

	gf_node_dirty_clear(stack->graph->node, GF_SG_SVG_GEOMETRY_DIRTY);
}
Exemplo n.º 15
0
static void svg_traverse_tspan(GF_Node *node, void *rs, Bool is_destroy)
{
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	GF_Matrix2D backup_matrix;
	GF_Matrix mx3d;
	DrawableContext *ctx;
	SVG_TextStack *st = (SVG_TextStack *)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVG_Element *tspan = (SVG_Element *)node;
	SVGAllAttributes atts;
	GF_ChildNodeItem *child;

	if (is_destroy) {
		drawable_del(st->drawable);
		svg_reset_text_stack(st);
		gf_list_del(st->spans);
		gf_free(st);
		return;
	}
	if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) {
		svg_text_draw_2d(st, tr_state);
		return;
	}
	else if (tr_state->traversing_mode==TRAVERSE_GET_TEXT) {
		gf_font_spans_get_selection(node, st->spans, tr_state);
		/*and browse children*/
		child = ((GF_ParentNode *) tspan)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
		return;
	}

	if (!tr_state->in_svg_text && !tr_state->in_svg_text_area) return;

	gf_svg_flatten_attributes(tspan, &atts);
	if (!compositor_svg_traverse_base(node, &atts, tr_state, &backup_props, &backup_flags))
		return;

	if (tr_state->traversing_mode==TRAVERSE_PICK) {
		if (*tr_state->svg_props->pointer_events!=SVG_POINTEREVENTS_NONE)
			gf_font_spans_pick(node, st->spans, tr_state, &st->bounds, GF_TRUE, st->drawable);

		/*and browse children*/
		child = ((GF_ParentNode *) tspan)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
		memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
		tr_state->svg_flags = backup_flags;
		return;
	}

	compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d);

	if ( (st->prev_size != tr_state->svg_props->font_size->value) ||
	        (st->prev_flags != *tr_state->svg_props->font_style) ||
	        (st->prev_anchor != *tr_state->svg_props->text_anchor) ||
	        (gf_node_dirty_get(node) & (GF_SG_SVG_GEOMETRY_DIRTY | GF_SG_CHILD_DIRTY) )
	   ) {
		u32 mode;

		/*tspan has been modified in the SORT stage, which means that an anim local to tspan has modified the node.
		The result of the parent (text, textArea) will thus be wrong if we try to update the tspan. We therefore
		keep the previous computed drawable, and invalidate the parent for next frame*/
		if (tr_state->traversing_mode==TRAVERSE_SORT) {
			gf_node_dirty_set(node, 0, GF_TRUE);
			goto skip_changes;
		}

		/*switch to bounds mode, and recompute children*/
		mode = tr_state->traversing_mode;
		tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;

		svg_reset_text_stack(st);
		child = ((GF_ParentNode *) tspan)->children;

		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_DOMText:
				svg_traverse_domtext(child->node, &atts, tr_state, st->spans, NULL);
				break;
			case TAG_SVG_tspan:
				gf_node_dirty_set(child->node, 0, GF_FALSE);
				gf_node_traverse(child->node, tr_state);
				break;
			case TAG_SVG_switch:
			case TAG_SVG_a:
			case TAG_SVG_tbreak:
				gf_node_traverse(child->node, tr_state);
				break;
			default:
				break;
			}
			child = child->next;
		}
		tr_state->traversing_mode = mode;
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(st->drawable, tr_state);
		st->prev_size = tr_state->svg_props->font_size->value;
		st->prev_flags = *tr_state->svg_props->font_style;
		st->prev_anchor = *tr_state->svg_props->text_anchor;

		svg_update_bounds(st);
	}
skip_changes:

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		if (tr_state->refresh_children_bounds) {
			if (tr_state->base_shift)
				svg_text_area_shift_bounds(st, tr_state);
			else
				svg_update_bounds(st);
			child = ((GF_ParentNode *) tspan)->children;
			while (child) {
				switch  (gf_node_get_tag(child->node)) {
				case TAG_SVG_tspan:
				case TAG_SVG_switch:
				case TAG_SVG_a:
					gf_node_traverse(child->node, tr_state);
					break;
				default:
					break;
				}
				child = child->next;
			}
		}
		if (!compositor_svg_is_display_off(tr_state->svg_props))
			tr_state->bounds = st->bounds;

	}
	else if (
	    (tr_state->traversing_mode == TRAVERSE_SORT)
	    && !compositor_svg_is_display_off(tr_state->svg_props)
	    && ( *(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN)
	) {
		child = ((GF_ParentNode *) tspan)->children;

		ctx = drawable_init_context_svg(st->drawable, tr_state);
		if (ctx) svg_finalize_sort(ctx, st, tr_state);

		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
			case TAG_SVG_switch:
			case TAG_SVG_a:
				gf_node_traverse(child->node, tr_state);
				break;
			default:
				break;
			}
			child = child->next;
		}
	}

	compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d);
	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}
Exemplo n.º 16
0
static void svg_traverse_text(GF_Node *node, void *rs, Bool is_destroy)
{
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	GF_Matrix2D backup_matrix;
	GF_Matrix mx3d;
	GF_ChildNodeItem *child;
	DrawableContext *ctx;
	SVG_TextStack *st = (SVG_TextStack *)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVG_Element *text = (SVG_Element *)node;
	SVGAllAttributes atts;
	u32 i,imax;
	Fixed * lw;

	if (is_destroy) {
		drawable_del(st->drawable);
		svg_reset_text_stack(st);
		gf_list_del(st->spans);
		gf_free(st);
		return;
	}

	if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) {
		svg_text_draw_2d(st, tr_state);
		return;
	}
	else if (tr_state->traversing_mode==TRAVERSE_GET_TEXT) {
		tr_state->text_parent = node;
		gf_font_spans_get_selection(node, st->spans, tr_state);
		/*and browse children*/
		child = ((GF_ParentNode *) text)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
		tr_state->text_parent = NULL;
		return;
	}

	gf_svg_flatten_attributes(text, &atts);
	if (!compositor_svg_traverse_base(node, &atts, tr_state, &backup_props, &backup_flags))
		return;

	tr_state->in_svg_text++;
	tr_state->text_parent = node;

	if (tr_state->traversing_mode==TRAVERSE_PICK) {
		compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d);
		if (*tr_state->svg_props->pointer_events!=SVG_POINTEREVENTS_NONE)
			gf_font_spans_pick(node, st->spans, tr_state, &st->bounds, 1, st->drawable);

		/*and browse children*/
		child = ((GF_ParentNode *) text)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
		memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
		compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d);
		tr_state->svg_flags = backup_flags;
		tr_state->text_parent = NULL;
		tr_state->in_svg_text--;
		return;
	}
	else if (tr_state->traversing_mode==TRAVERSE_GET_TEXT) {
		gf_font_spans_get_selection(node, st->spans, tr_state);
		memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
		tr_state->svg_flags = backup_flags;
		tr_state->text_parent = NULL;
		tr_state->in_svg_text--;
		return;
	}

	compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d);

	if ( (st->prev_size != tr_state->svg_props->font_size->value) ||
	        (st->prev_flags != *tr_state->svg_props->font_style) ||
	        (st->prev_anchor != *tr_state->svg_props->text_anchor) ||
	        (gf_node_dirty_get(node) & (GF_SG_SVG_GEOMETRY_DIRTY | GF_SG_CHILD_DIRTY) )
	        || tr_state->visual->compositor->reset_fonts
	   ) {
		u32 mode;
		child = ((GF_ParentNode *) text)->children;

		svg_reset_text_stack(st);
		tr_state->text_end_x = 0;
		tr_state->text_end_y = 0;
		/*init the xml:space algo*/
		tr_state->last_char_type = 0;

		/*initialize x and y counters - stored at the traverse level for handling tspan & co*/
		if (atts.text_x) tr_state->count_x = gf_list_count(*atts.text_x);
		else tr_state->count_x=0;
		if (atts.text_y) tr_state->count_y = gf_list_count(*atts.text_y);
		else tr_state->count_y=0;
		if (atts.text_rotate) tr_state->count_rotate = gf_list_count(*atts.text_rotate);
		else tr_state->count_rotate=0;

		/*horizontal justifiers container*/
		tr_state->x_anchors = gf_list_new();

		/*compute length of all text blocks*/
		while (child) {
			svg_compute_text_width(child->node, &atts, tr_state);
			child=child->next;
		}

		/*apply justification of all blocks*/
		imax=gf_list_count(tr_state->x_anchors);
		for (i=0; i<imax; i++) {
			lw=gf_list_get(tr_state->x_anchors, i);
			svg_apply_text_anchor(tr_state, lw);
		}

		/*re-initialize x and y counters for final compute*/
		if (atts.text_x) tr_state->count_x = gf_list_count(*atts.text_x);
		else tr_state->count_x=0;
		if (atts.text_y) tr_state->count_y = gf_list_count(*atts.text_y);
		else tr_state->count_y=0;
		if (atts.text_rotate) tr_state->count_rotate = gf_list_count(*atts.text_rotate);
		else tr_state->count_rotate=0;
		tr_state->idx_rotate = 0;
		tr_state->chunk_index = 0;

		/*initialize current text position*/
		if (!tr_state->text_end_x) {
			SVG_Coordinate *xc = (atts.text_x ? (SVG_Coordinate *) gf_list_get(*atts.text_x, 0) : NULL);
			tr_state->text_end_x = (xc ? xc->value : 0);
		}
		if (!tr_state->text_end_y) {
			SVG_Coordinate *yc = (atts.text_y ? (SVG_Coordinate *) gf_list_get(*atts.text_y, 0) : NULL);
			tr_state->text_end_y = (yc ? yc->value : 0);
		}

		/*pass x and y to children*/
		tr_state->text_x = atts.text_x;
		tr_state->text_y = atts.text_y;
		tr_state->text_rotate = atts.text_rotate;

		drawable_reset_path(st->drawable);

		/*switch to bounds mode, and recompute children*/
		mode = tr_state->traversing_mode;
		tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;
		tr_state->last_char_type = 0;

		child = ((GF_ParentNode *) text)->children;
		while (child) {
			svg_traverse_text_block(child->node, &atts, tr_state, st->spans);
			child = child->next;
		}
		tr_state->traversing_mode = mode;
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(st->drawable, tr_state);
		st->prev_size = tr_state->svg_props->font_size->value;
		st->prev_flags = *tr_state->svg_props->font_style;
		st->prev_anchor = *tr_state->svg_props->text_anchor;

		while (gf_list_count(tr_state->x_anchors)) {
			Fixed *f = gf_list_last(tr_state->x_anchors);
			gf_list_rem_last(tr_state->x_anchors);
			gf_free(f);
		}
		gf_list_del(tr_state->x_anchors);
		tr_state->x_anchors = NULL;

		svg_update_bounds(st);
	}

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		if (!compositor_svg_is_display_off(tr_state->svg_props))
			tr_state->bounds = st->bounds;

	} else if ((tr_state->traversing_mode == TRAVERSE_SORT)
	           && !compositor_svg_is_display_off(tr_state->svg_props)
	           && (*(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN)
	          ) {
		ctx = drawable_init_context_svg(st->drawable, tr_state);
		if (ctx) svg_finalize_sort(ctx, st, tr_state);

		/*and browse children*/
		child = ((GF_ParentNode *) text)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
				gf_node_traverse(child->node, tr_state);
				break;
			case TAG_SVG_switch:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
	}
	tr_state->in_svg_text--;
	tr_state->text_parent = NULL;

	compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d);
	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}
Exemplo n.º 17
0
static void svg_drawable_traverse(GF_Node *node, void *rs, Bool is_destroy,
							void (*rebuild_path)(GF_Node *, Drawable *, SVGAllAttributes *),
							Bool is_svg_rect, Bool is_svg_path)
{
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
	DrawableContext *ctx;
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	Drawable *drawable = (Drawable *)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVGAllAttributes all_atts;

	if (is_destroy) {
#if USE_GF_PATH
		/* The path is the same as the one in the SVG node, don't delete it here */
		if (is_svg_path) drawable->path = NULL;
#endif
		drawable_node_del(node);
		return;
	}
	assert(tr_state->traversing_mode!=TRAVERSE_DRAW_2D);

	
	if (tr_state->traversing_mode==TRAVERSE_PICK) {
		svg_drawable_pick(node, drawable, tr_state);
		return;
	}

	/*flatten attributes and apply animations + inheritance*/
	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);
	if (!compositor_svg_traverse_base(node, &all_atts, (GF_TraverseState *)rs, &backup_props, &backup_flags))
		return;
	
	/* Recreates the path (i.e the shape) only if the node is dirty */
	if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) {
		/*the rebuild function is responsible for cleaning the path*/
		rebuild_path(node, drawable, &all_atts);
		gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY);
		drawable_mark_modified(drawable, tr_state);
	}
	if (drawable->path) {
		if (*(tr_state->svg_props->fill_rule)==GF_PATH_FILL_ZERO_NONZERO) {
			if (!(drawable->path->flags & GF_PATH_FILL_ZERO_NONZERO)) {
				drawable->path->flags |= GF_PATH_FILL_ZERO_NONZERO;
				drawable_mark_modified(drawable, tr_state);
			}
		} else {
			if (drawable->path->flags & GF_PATH_FILL_ZERO_NONZERO) {
				drawable->path->flags &= ~GF_PATH_FILL_ZERO_NONZERO;
				drawable_mark_modified(drawable, tr_state);
			}
		}
	}

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		if (! compositor_svg_is_display_off(tr_state->svg_props)) {
			DrawAspect2D asp;
			gf_path_get_bounds(drawable->path, &tr_state->bounds);
			if (!tr_state->ignore_strike) {
				memset(&asp, 0, sizeof(DrawAspect2D));
				drawable_get_aspect_2d_svg(node, &asp, tr_state);
				if (asp.pen_props.width) {
					StrikeInfo2D *si = drawable_get_strikeinfo(tr_state->visual->compositor, drawable, &asp, NULL, drawable->path, 0, NULL);
					if (si && si->outline) {
						gf_path_get_bounds(si->outline, &tr_state->bounds);
					}
				}
			}
			compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, NULL);
			if (!tr_state->abort_bounds_traverse)
				gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
			gf_sc_get_nodes_bounds(node, NULL, tr_state, NULL);

			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, NULL);
		}
	} else if (tr_state->traversing_mode == TRAVERSE_SORT) {
		/*reset our flags - this may break reuse of nodes and change-detection in dirty-rect algo */
		gf_node_dirty_clear(node, 0);

		if (!compositor_svg_is_display_off(tr_state->svg_props) &&
			( *(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN) ) {

			compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);

			ctx = drawable_init_context_svg(drawable, tr_state);
			if (ctx) {
				if (is_svg_rect) {
					if (ctx->aspect.fill_texture && ctx->aspect.fill_texture->transparent) {}
					else if (GF_COL_A(ctx->aspect.fill_color) != 0xFF) {}
					else if (ctx->transform.m[1] || ctx->transform.m[3]) {}
					else {
						ctx->flags &= ~CTX_IS_TRANSPARENT;
						if (!ctx->aspect.pen_props.width) 
							ctx->flags |= CTX_NO_ANTIALIAS;
					}
				}

				if (all_atts.pathLength && all_atts.pathLength->type==SVG_NUMBER_VALUE) 
					ctx->aspect.pen_props.path_length = all_atts.pathLength->value;

#ifndef GPAC_DISABLE_3D
				if (tr_state->visual->type_3d) {
					if (!drawable->mesh) {
						drawable->mesh = new_mesh();
						if (drawable->path) mesh_from_path(drawable->mesh, drawable->path);
					}
					visual_3d_draw_from_context(ctx, tr_state);
					ctx->drawable = NULL;
				} else 
#endif
				{
					drawable_finalize_sort(ctx, tr_state, NULL);
				}
			}
			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
		}
	}

	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}