Example #1
0
static void svg_finalize_sort(DrawableContext *ctx, SVG_TextStack *st, GF_TraverseState * tr_state)
{
#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		gf_font_spans_draw_3d(st->spans, tr_state, &ctx->aspect, 0, GF_FALSE);

		drawable_check_focus_highlight(ctx->drawable->node, tr_state, &st->bounds);
		ctx->drawable = NULL;
		return;
	}
#endif
	/*if text selection mode, we must force redraw of the entire text span because we don't
	if glyphs have been (un)selected*/
	if (!tr_state->immediate_draw &&
	        /*text selection on*/
	        (tr_state->visual->compositor->text_selection
	         /*text sel release*/
	         || (tr_state->visual->compositor->store_text_state==GF_SC_TSEL_RELEASED))
	   ) {
		GF_TextSpan *span;
		u32 i = 0;
		Bool unselect = (tr_state->visual->compositor->store_text_state==GF_SC_TSEL_RELEASED) ? GF_TRUE : GF_FALSE;
		while ((span = (GF_TextSpan*)gf_list_enum(st->spans, &i))) {
			if (span->flags & GF_TEXT_SPAN_SELECTED) {
				if (unselect) span->flags &= ~GF_TEXT_SPAN_SELECTED;
				ctx->flags |= CTX_APP_DIRTY;
			}
		}
	}
	drawable_finalize_sort(ctx, tr_state, &st->bounds);
}
Example #2
0
static void svg_traverse_a(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
	SVGPropertiesPointers backup_props;
	u32 styling_size = sizeof(SVGPropertiesPointers);
	u32 backup_flags;
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVGAllAttributes all_atts;

	if (is_destroy) {
		gf_sc_check_focus_upon_destroy(node);
		return;
	}

	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);

	if (!compositor_svg_traverse_base(node, &all_atts, tr_state, &backup_props, &backup_flags))
		return;

	if (compositor_svg_is_display_off(tr_state->svg_props)) {
		/*u32 prev_flags = tr_state->switched_off;
		tr_state->switched_off = 1;
		compositor_svg_traverse_children(((SVG_Element *)node)->children, tr_state);
		tr_state->switched_off = prev_flags;*/

		memcpy(tr_state->svg_props, &backup_props, styling_size);
		tr_state->svg_flags = backup_flags;
		return;
	}	
	
	compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);
	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		gf_sc_get_nodes_bounds(node, ((SVG_Element *)node)->children, tr_state, NULL);
	} else {
		compositor_svg_traverse_children(((SVG_Element *)node)->children, tr_state);
		if (tr_state->traversing_mode==TRAVERSE_SORT)
			drawable_check_focus_highlight(node, tr_state, NULL);
	}
	compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
	memcpy(tr_state->svg_props, &backup_props, styling_size);
	tr_state->svg_flags = backup_flags;
}
Example #3
0
static void svg_traverse_resource(GF_Node *node, void *rs, Bool is_destroy, Bool is_foreign_object)
{
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
  	GF_Matrix2D translate;
	SVGPropertiesPointers backup_props;
	u32 backup_flags, dirty;
	Bool is_fragment;
	GF_Node *used_node;
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVGAllAttributes all_atts;
	SVGlinkStack *stack = gf_node_get_private(node);
	SFVec2f prev_vp;
	SVG_Number *prev_opacity;

	if (is_destroy) {
		if (stack->resource) gf_mo_unload_xlink_resource(node, stack->resource);
		gf_free(stack);
		return;
	}


	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);
	if (!all_atts.xlink_href) return;

	if (!compositor_svg_traverse_base(node, &all_atts, tr_state, &backup_props, &backup_flags))
		return;

	dirty = gf_node_dirty_get(node);
	if (dirty & GF_SG_CHILD_DIRTY) drawable_reset_group_highlight(tr_state, node);

	if (dirty & GF_SG_SVG_XLINK_HREF_DIRTY) {
		stack->fragment_id = NULL;
		stack->inline_sg = NULL;
		if (all_atts.xlink_href->string && (all_atts.xlink_href->string[0]=='#')) {
			stack->fragment_id = all_atts.xlink_href->string;
			stack->inline_sg = gf_node_get_graph(node);
		} else {
			GF_MediaObject *new_res = gf_mo_load_xlink_resource(node, is_foreign_object, 0, -1);
			if (new_res != stack->resource) {
				if (stack->resource) gf_mo_unload_xlink_resource(node, stack->resource);
				stack->resource = new_res;
			}
		}
	}
	gf_node_dirty_clear(node, 0);

	/*locate the used node - this is done at each step to handle progressive loading*/
	is_fragment = 0;
	used_node = NULL;
	if (!stack->inline_sg && !stack->fragment_id && all_atts.xlink_href) {
		if (all_atts.xlink_href->type == XMLRI_ELEMENTID) {
			used_node = all_atts.xlink_href->target;
			is_fragment = 1;
		} else if (stack->resource) {
			stack->inline_sg = gf_mo_get_scenegraph(stack->resource);
			if (!is_foreign_object) {
				stack->fragment_id = strchr(all_atts.xlink_href->string, '#');
			}
		}
	}
	if (!used_node && stack->inline_sg) {
		if (stack->fragment_id) {
			used_node = gf_sg_find_node_by_name(stack->inline_sg, (char *) stack->fragment_id+1);
			is_fragment = 1;
		} else if (is_foreign_object) {
			used_node = gf_sg_get_root_node(stack->inline_sg);
		}
	}
	if (!used_node) goto end;

	/*stack use nodes for picking*/
	gf_list_add(tr_state->use_stack, used_node);
	gf_list_add(tr_state->use_stack, node);

	gf_mx2d_init(translate);
	translate.m[2] = (all_atts.x ? all_atts.x->value : 0);
	translate.m[5] = (all_atts.y ? all_atts.y->value : 0);

	/*update VP size (SVG 1.1)*/
	prev_vp = tr_state->vp_size;
	if (all_atts.width && all_atts.height) {
		tr_state->vp_size.x = gf_sc_svg_convert_length_to_display(tr_state->visual->compositor, all_atts.width);
		tr_state->vp_size.y = gf_sc_svg_convert_length_to_display(tr_state->visual->compositor, all_atts.height);
	}

	prev_opacity = tr_state->parent_use_opacity;
	tr_state->parent_use_opacity = all_atts.opacity;

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);
		if (!compositor_svg_is_display_off(tr_state->svg_props)) {
			gf_node_traverse(used_node, tr_state);
			gf_mx2d_apply_rect(&translate, &tr_state->bounds);
		} 
		compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
	}
	/*SORT mode and visible, traverse*/
	else 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);

#ifndef GPAC_DISABLE_3D
		if (tr_state->visual->type_3d) {
			gf_mx_add_matrix_2d(&tr_state->model_matrix, &translate);

			if (tr_state->traversing_mode==TRAVERSE_SORT) {
				GF_Matrix tmp;
				gf_mx_from_mx2d(&tmp, &translate);
				visual_3d_matrix_add(tr_state->visual, tmp.m);
			}
		} else 
#endif
			gf_mx2d_pre_multiply(&tr_state->transform, &translate);


		drawable_check_focus_highlight(node, tr_state, NULL);
		if (is_fragment) {
			gf_node_traverse(used_node, tr_state);
		} else {
			gf_sc_traverse_subscene(tr_state->visual->compositor, node, stack->inline_sg, tr_state);
		}
		compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);  

	}
	gf_list_rem_last(tr_state->use_stack);
	gf_list_rem_last(tr_state->use_stack);
	tr_state->vp_size = prev_vp;

	tr_state->parent_use_opacity = prev_opacity;

end:
	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}
Example #4
0
static void svg_traverse_switch(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	s32 *selected_idx = gf_node_get_private(node);
	u32 styling_size = sizeof(SVGPropertiesPointers);
	SVGAllAttributes all_atts;
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;

	if (is_destroy) {
		gf_free(selected_idx);
		gf_sc_check_focus_upon_destroy(node);
		return;
	}

	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);
	if (gf_node_dirty_get(node)) {
		u32 pos = 0;
		GF_ChildNodeItem *child = ((SVG_Element*)node)->children;
		*selected_idx = -1;
		while (child) {
			SVGAllAttributes atts;
			gf_svg_flatten_attributes((SVG_Element *)child->node, &atts);
			if (compositor_svg_evaluate_conditional(tr_state->visual->compositor, &atts)) {
				*selected_idx = pos;
				break;
			}
			pos++;
			child = child->next;
		}
		drawable_reset_group_highlight(tr_state, node);
		gf_node_dirty_clear(node, 0);
	}

	if (!compositor_svg_traverse_base(node, &all_atts, tr_state, &backup_props, &backup_flags))
		return;

	if (compositor_svg_is_display_off(tr_state->svg_props)) {
		memcpy(tr_state->svg_props, &backup_props, styling_size);
		tr_state->svg_flags = backup_flags;
		return;
	}
	
	if (*selected_idx >= 0) {
		compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);
		if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
			gf_sc_get_nodes_bounds(node, ((SVG_Element *)node)->children, tr_state, selected_idx);
		} else if (*selected_idx >= 0) {
			GF_Node *child = gf_node_list_get_child(((SVG_Element *)node)->children, *selected_idx);
			gf_node_traverse(child, tr_state);

			drawable_check_focus_highlight(node, tr_state, NULL);
		}
		compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
	}

	memcpy(tr_state->svg_props, &backup_props, styling_size);
	tr_state->svg_flags = backup_flags;
}
Example #5
0
static void svg_traverse_g(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	u32 styling_size = sizeof(SVGPropertiesPointers);

	GF_TraverseState *tr_state = (GF_TraverseState *) rs;

	SVGAllAttributes all_atts;

	if (is_destroy) {
		SVGgStack *group = gf_node_get_private(node);
#ifdef GF_SR_USE_VIDEO_CACHE
		group_2d_destroy_svg(node, group);
#else
		if (group->cache) group_cache_del(group->cache);
#endif
		gf_free(group);
		gf_sc_check_focus_upon_destroy(node);
		return;
	}
	/*group cache traverse routine*/
	else if (tr_state->traversing_mode == TRAVERSE_DRAW_2D) {
		SVGgStack *group = gf_node_get_private(node);
		group_cache_draw(group->cache, tr_state);
		return;
	}

	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);

	if (!compositor_svg_traverse_base(node, &all_atts, tr_state, &backup_props, &backup_flags))
		return;

	if (compositor_svg_is_display_off(tr_state->svg_props)) {
/*		u32 prev_flags = tr_state->switched_off;
		tr_state->switched_off = 1;
		compositor_svg_traverse_children(((SVG_Element *)node)->children, tr_state);
		tr_state->switched_off = prev_flags;*/

		memcpy(tr_state->svg_props, &backup_props, styling_size);
		tr_state->svg_flags = backup_flags;
		return;
	}	
	
	compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);
	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		gf_sc_get_nodes_bounds(node, ((SVG_Element *)node)->children, tr_state, NULL);
	} else if (tr_state->traversing_mode == TRAVERSE_SORT) {
#ifdef GF_SR_USE_DEPTH
		Fixed scale, offset, dscale, doffset;
#endif
		Fixed opacity = FIX_ONE;
		Bool clear = 0;
		SVGgStack *group;
		
		if (!tr_state->in_svg_filter && all_atts.filter && all_atts.filter->iri.target) {
			svg_draw_filter(all_atts.filter->iri.target, node, tr_state);
			return;
		}
		group = gf_node_get_private(node);

		if (tr_state->parent_use_opacity) {
			opacity = tr_state->parent_use_opacity->value;
			tr_state->parent_use_opacity = NULL;
		}
		if (all_atts.opacity) {
			opacity = gf_mulfix(opacity, all_atts.opacity->value);
		}
		if (gf_node_dirty_get(node)&GF_SG_CHILD_DIRTY) {
			drawable_reset_group_highlight(tr_state, node);
			clear=1;
		}

#ifdef GF_SR_USE_DEPTH
		dscale = FIX_ONE;
		doffset=0;
		if (all_atts.gpac_depthGain && all_atts.gpac_depthGain->type==SVG_NUMBER_VALUE) dscale = all_atts.gpac_depthGain->value;
		if (all_atts.gpac_depthOffset && all_atts.gpac_depthOffset->type==SVG_NUMBER_VALUE) doffset = all_atts.gpac_depthOffset->value;
		scale = tr_state->depth_gain;
		offset = tr_state->depth_offset;
		// new offset is multiplied by parent gain and added to parent offset
		tr_state->depth_offset = gf_mulfix(doffset, scale) + offset;
		// gain is multiplied by parent gain
		tr_state->depth_gain = gf_mulfix(scale, dscale);
#endif

		if (opacity < FIX_ONE) {
			if (!group->cache) {
				group->cache = group_cache_new(tr_state->visual->compositor, node);
				group->cache->force_recompute = 1;
			}
			group->cache->opacity = opacity;
			if (tr_state->visual->compositor->zoom_changed)
				group->cache->force_recompute = 1;
			group->flags |= GROUP_IS_CACHED | GROUP_PERMANENT_CACHE;
#ifdef GF_SR_USE_VIDEO_CACHE
			group_2d_cache_traverse(node, group, tr_state);
#else
			group_cache_traverse(node, group->cache, tr_state, group->cache->force_recompute, 0, 0);
#endif
		} else {
#ifdef GF_SR_USE_VIDEO_CACHE
			Bool group_cached;

			group_cached = group_2d_cache_traverse(node, group, tr_state);
			gf_node_dirty_clear(node, GF_SG_CHILD_DIRTY);
			/*group is not cached, traverse the children*/
			if (!group_cached) {
				GF_ChildNodeItem *child;
				DrawableContext *first_ctx = tr_state->visual->cur_context;
				u32 cache_too_small = 0;
				Bool skip_first_ctx = (first_ctx && first_ctx->drawable) ? 1 : 0;
				u32 traverse_time = gf_sys_clock();
				u32 last_cache_idx = gf_list_count(tr_state->visual->compositor->cached_groups_queue);
				tr_state->cache_too_small = 0;

				child = ((GF_ParentNode *)node)->children;
				while (child) {
					gf_node_traverse(child->node, tr_state);
					child = child->next;
					if (tr_state->cache_too_small) 
						cache_too_small++;
				}

				if (cache_too_small) {
					tr_state->cache_too_small = 1;
				} else {
					/*get the traversal time for each group*/	
					traverse_time = gf_sys_clock() - traverse_time;
					group->traverse_time += traverse_time;
					/*record the traversal information and turn cache on if possible*/
					group_2d_cache_evaluate(node, group, tr_state, first_ctx, skip_first_ctx, last_cache_idx);
				}
			}
#else
			compositor_svg_traverse_children(((SVG_Element *)node)->children, tr_state);
#endif
		}
		if (clear) gf_node_dirty_clear(node, 0);

		drawable_check_focus_highlight(node, tr_state, NULL);

#ifdef GF_SR_USE_DEPTH
		tr_state->depth_gain = scale;
		tr_state->depth_offset = offset;
#endif
	} else {
			compositor_svg_traverse_children(((SVG_Element *)node)->children, tr_state);
	}
	compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
	memcpy(tr_state->svg_props, &backup_props, styling_size);
	tr_state->svg_flags = backup_flags;
}