示例#1
0
文件: svg_text.c 项目: Brilon314/gpac
static void svg_text_area_reset_state(GF_TraverseState *tr_state)
{
	Fixed remain = 0;
	u32 i, count;
	count = gf_list_count(tr_state->x_anchors);

	if (tr_state->svg_props->text_align && tr_state->text_end_x) {
		switch(*tr_state->svg_props->text_align) {
		case SVG_TEXTALIGN_CENTER:
			remain = (tr_state->max_length - tr_state->text_end_x) / 2;
			break;
		case SVG_TEXTALIGN_END:
			remain = tr_state->max_length - tr_state->text_end_x;
			break;
		default:
			remain = 0;
			break;
		}
	}


	for (i=0; i<count; i++) {
		textArea_state *st = (textArea_state*)gf_list_get(tr_state->x_anchors, i);
		if (remain) {
			u32 j;
			for (j=st->first_glyph; j<st->last_glyph; j++) {
				st->span->dx[j] += remain;
			}
			tr_state->refresh_children_bounds = 1;
		}
		gf_free(st);
	}
	gf_list_reset(tr_state->x_anchors);
}
示例#2
0
/* assumes that the list of time values is sorted */
static void gf_smil_timing_init_interval_list(SMIL_Timing_RTI *rti)
{
	u32 i, count;
	SMIL_Time *begin;
	SMILTimingAttributesPointers *timingp = rti->timingp;

	if (!timingp) return;

	count = gf_list_count(rti->intervals);
	for (i = 0; i<count; i++) {
		SMIL_Interval *interval = (SMIL_Interval *)gf_list_get(rti->intervals, i);
		free(interval);
	}
	gf_list_reset(rti->intervals);

	count = (timingp->begin ? gf_list_count(*timingp->begin) : 0);
	if (count) {
		for (i = 0; i < count; i ++) {
			begin = (SMIL_Time*)gf_list_get(*timingp->begin, i);
			if (GF_SMIL_TIME_IS_CLOCK(begin->type) ) {
				/* we create an acceptable only if begin is unspecified or defined (clock or wallclock) */
				gf_smil_timing_add_new_interval(rti, NULL, begin->clock, i);
			} else {
				/* this is not an acceptable value for a begin */
			}
		} 
	}
	/*conditional has a default begin value of indefinite*/
	else if (rti->timed_elt->sgprivate->tag != TAG_SVG_conditional) {
		gf_smil_timing_add_new_interval(rti, NULL, 0, 0);
	}
}
示例#3
0
static void TTD_ResetDisplay(TTDPriv *priv)
{
	gf_list_reset(priv->blink_nodes);
	gf_node_unregister_children((GF_Node*)priv->dlist, priv->dlist->children);
	priv->dlist->children = NULL;
	gf_node_changed((GF_Node *) priv->dlist, NULL);
	priv->tr_scroll = NULL;
}
示例#4
0
void svg_clone_use_stack(GF_Compositor *compositor, GF_TraverseState *tr_state)
{
	u32 i, count;
	count = gf_list_count(tr_state->use_stack);
	gf_list_reset(compositor->hit_use_stack);
	for (i=0; i<count; i++) {
		GF_Node *node = gf_list_get(tr_state->use_stack, i);
		gf_list_add(compositor->hit_use_stack, node);
	}
}
示例#5
0
GF_EXPORT
GF_Err gf_odf_codec_encode(GF_ODCodec *codec, u32 cleanup_type)
{
	GF_ODCom *com;
	GF_Err e = GF_OK;
	u32 i;

	if (!codec) return GF_BAD_PARAM;

	//check our bitstream: if existing, this means the previous encoded AU was not retrieved
	//we DON'T allow that
	if (codec->bs) return GF_BAD_PARAM;
	codec->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
	if (!codec->bs) return GF_OUT_OF_MEM;

	/*encode each command*/
	i = 0;
	while ((com = (GF_ODCom *)gf_list_enum(codec->CommandList, &i))) {
		e = gf_odf_write_command(codec->bs, com);
		if (e) goto err_exit;
		//don't forget OD Commands are aligned...
		gf_bs_align(codec->bs);
	}

	//if an error occurs, delete the GF_BitStream and empty the codec
err_exit:
	if (e) {
		gf_bs_del(codec->bs);
		codec->bs = NULL;
	}
	if (cleanup_type == 1) {
		while (gf_list_count(codec->CommandList)) {
			com = (GF_ODCom *)gf_list_get(codec->CommandList, 0);
			gf_odf_delete_command(com);
			gf_list_rem(codec->CommandList, 0);
		}
	}
	if (cleanup_type == 0) {
		gf_list_reset(codec->CommandList);
	}
	return e;
}
示例#6
0
void visual_2d_pick_node(GF_VisualManager *visual, GF_TraverseState *tr_state, GF_Event *ev, GF_ChildNodeItem *children)
{
	GF_Matrix2D backup;
	visual->bounds_tracker_modif_flag = DRAWABLE_HAS_CHANGED_IN_LAST_TRAVERSE;

	gf_mx2d_copy(backup, tr_state->transform);

	visual_2d_setup_projection(visual, tr_state);

	visual->compositor->hit_node = NULL;
	tr_state->ray.orig.x = INT2FIX(ev->mouse.x);
	tr_state->ray.orig.y = INT2FIX(ev->mouse.y);
	tr_state->ray.orig.z = 0;
	tr_state->ray.dir.x = 0;
	tr_state->ray.dir.y = 0;
	tr_state->ray.dir.z = -FIX_ONE;

	visual->compositor->hit_world_point = tr_state->ray.orig;
	visual->compositor->hit_world_ray = tr_state->ray;
	visual->compositor->hit_square_dist = 0;

	gf_list_reset(visual->compositor->sensors);
	tr_state->traversing_mode = TRAVERSE_PICK;

	/*not the root scene, use children list*/
	if (visual->compositor->visual != visual) {
		while (children) {
			gf_node_traverse(children->node, tr_state);
			children = children->next;
		}
	} else {
		u32 i = 0;
		GF_SceneGraph *sg = visual->compositor->scene;
		GF_Node *root = gf_sg_get_root_node(sg);
		gf_node_traverse(root, tr_state);
		while ((sg = (GF_SceneGraph*)gf_list_enum(visual->compositor->extra_scenes, &i))) {
			gf_sc_traverse_subscene(visual->compositor, root, sg, tr_state);
		}
	}
	gf_mx2d_copy(tr_state->transform, backup);
}
示例#7
0
Bool compositor_compositetexture_handle_event(GF_Compositor *compositor, GF_Node *composite_appear, GF_Event *ev, Bool is_flush)
{
	GF_Ray ray;
	Fixed dist;
	Bool had_text_sel=0;
	GF_Matrix mx;
	GF_TraverseState *tr_state;
	GF_ChildNodeItem *children, *l;
	Bool res;
	SFVec3f txcoord, loc_pt, world_pt;
	GF_Matrix l2w_mx, w2l_mx;
	CompositeTextureStack *stack;
	GF_Node *appear, *prev_appear;
	M_Appearance *ap = (M_Appearance *)composite_appear;
	assert(ap && ap->texture);

	if (ev->type > GF_EVENT_MOUSEMOVE) return 0;
	stack = gf_node_get_private(ap->texture);
	if (!stack->txh.tx_io) return 0;

    tr_state = NULL;
    children = NULL;


	if (!is_flush) {
		txcoord.x = compositor->hit_texcoords.x;
		txcoord.y = compositor->hit_texcoords.y;
		txcoord.z = 0;
		if (gf_sc_texture_get_transform(&stack->txh, ap->textureTransform, &mx, 1)) {
			/*tx coords are inverted when mapping, thus applying directly the matrix will give us the
			untransformed coords*/
			gf_mx_apply_vec(&mx, &txcoord);
			while (txcoord.x<0) txcoord.x += FIX_ONE; while (txcoord.x>FIX_ONE) txcoord.x -= FIX_ONE;
			while (txcoord.y<0) txcoord.y += FIX_ONE; while (txcoord.y>FIX_ONE) txcoord.y -= FIX_ONE;
		}

		/*convert to tx space*/
		ev->mouse.x = FIX2INT( (txcoord.x - FIX_ONE/2) * stack->visual->width + FIX_ONE/2);
		ev->mouse.y = FIX2INT( (txcoord.y - FIX_ONE/2) * stack->visual->height + FIX_ONE/2);


		GF_SAFEALLOC(tr_state, GF_TraverseState);
		tr_state->vrml_sensors = gf_list_new();
		tr_state->visual = stack->visual;
		tr_state->traversing_mode = TRAVERSE_PICK;
		tr_state->pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(ap->texture));
		tr_state->vp_size.x = INT2FIX(stack->txh.width);
		tr_state->vp_size.y = INT2FIX(stack->txh.height);
		tr_state->color_mat.identity = 1;

		gf_mx2d_init(tr_state->transform);
#ifndef GPAC_DISABLE_3D
		gf_mx_init(tr_state->model_matrix);
#endif
		/*collect sensors*/
		l = children = ((M_CompositeTexture2D*)ap->texture)->children;
		while (l) {
			GF_SensorHandler *hsens = compositor_mpeg4_get_sensor_handler(l->node);
			if (hsens) gf_list_add(tr_state->vrml_sensors, hsens);
			l = l->next;
		}
	}

	stack->temp_sensors = compositor->sensors;
	stack->temp_previous_sensors = compositor->previous_sensors;
	compositor->sensors = stack->sensors;
	compositor->previous_sensors = stack->previous_sensors;

	ray = compositor->hit_world_ray;
	dist = compositor->hit_square_dist;
	prev_appear = compositor->prev_hit_appear;

	/*protect against destrucion in case of self-destroy*/
	if (prev_appear) {
		gf_node_register(prev_appear, NULL);
	}
	compositor->prev_hit_appear = stack->prev_hit_appear;
	appear = compositor->hit_appear;
	compositor->hit_appear = NULL;

	/*also backup current hit state in case we hit a node in the texture but don't consume the event*/
	loc_pt = compositor->hit_local_point;
	world_pt = compositor->hit_world_point;
	gf_mx_copy(l2w_mx, compositor->hit_local_to_world);
	gf_mx_copy(w2l_mx, compositor->hit_world_to_local);
	
	if (compositor->text_selection) had_text_sel=1;

	if (is_flush) {
		res = 0;
		gf_list_reset(stack->sensors);
		gf_sc_exec_event_vrml(compositor, ev);
	} else {
		res = visual_execute_event(stack->visual, tr_state, ev, children);
	}

	if (!had_text_sel && compositor->edited_text) {
		stack->visual->has_text_edit = 1;
	} else if (!compositor->text_selection) {
		stack->visual->has_text_edit = 0;
	}

	if (!res) {
		compositor->hit_local_point = loc_pt;
		gf_mx_copy(compositor->hit_local_to_world, l2w_mx);
		gf_mx_copy(compositor->hit_world_to_local, w2l_mx);
	}

	stack->prev_hit_appear = compositor->prev_hit_appear;

	if (prev_appear) {
		if (prev_appear->sgprivate->num_instances>1) {
			compositor->prev_hit_appear = prev_appear;
			compositor->hit_appear = appear;
		} else {
			compositor->prev_hit_appear = NULL;
			compositor->hit_appear = NULL;
		}
		gf_node_unregister(prev_appear, NULL);
	} else {
		compositor->prev_hit_appear = prev_appear;
		compositor->hit_appear = appear;
	}

	compositor->hit_world_point = world_pt;
	compositor->hit_world_ray = ray;
	compositor->hit_square_dist = dist;

	stack->sensors = compositor->sensors;
	stack->previous_sensors = compositor->previous_sensors;
	compositor->sensors = stack->temp_sensors;
	stack->temp_sensors = NULL;
	compositor->previous_sensors = stack->temp_previous_sensors;
	stack->temp_previous_sensors = NULL;


	if (!is_flush) {
		gf_list_del(tr_state->vrml_sensors);
#ifndef GPAC_DISABLE_3D
		if (tr_state->layer3d) compositor->traverse_state->layer3d = tr_state->layer3d;
#endif
		gf_free(tr_state);
	}
	return res;
}
示例#8
0
void svg_drawable_pick(GF_Node *node, Drawable *drawable, GF_TraverseState *tr_state)
{
	DrawAspect2D asp;
	GF_Matrix2D inv_2d;
	Fixed x, y;
	Bool picked = 0;
	GF_Compositor *compositor = tr_state->visual->compositor;
	SVGPropertiesPointers backup_props;
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
	SVGAllAttributes all_atts;

	if (!drawable->path) return;

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

	memcpy(&backup_props, tr_state->svg_props, sizeof(SVGPropertiesPointers));
	gf_svg_apply_inheritance(&all_atts, tr_state->svg_props);
	if (compositor_svg_is_display_off(tr_state->svg_props)) return;

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

	memset(&asp, 0, sizeof(DrawAspect2D));
	drawable_get_aspect_2d_svg(node, &asp, tr_state);

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		svg_drawable_3d_pick(drawable, tr_state, &asp);
		compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
		memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
		return;
	} 
#endif
	gf_mx2d_copy(inv_2d, tr_state->transform);
	gf_mx2d_inverse(&inv_2d);
	x = tr_state->ray.orig.x;
	y = tr_state->ray.orig.y;
	gf_mx2d_apply_coords(&inv_2d, &x, &y);

	picked = svg_drawable_is_over(drawable, x, y, &asp, tr_state, NULL);

	if (picked) {
		u32 count, i;
		compositor->hit_local_point.x = x;
		compositor->hit_local_point.y = y;
		compositor->hit_local_point.z = 0;

		gf_mx_from_mx2d(&compositor->hit_world_to_local, &tr_state->transform);
		gf_mx_from_mx2d(&compositor->hit_local_to_world, &inv_2d);

		compositor->hit_node = drawable->node;
		compositor->hit_use_dom_events = 1;
		compositor->hit_normal.x = compositor->hit_normal.y = 0; compositor->hit_normal.z = FIX_ONE;
		compositor->hit_texcoords.x = gf_divfix(x, drawable->path->bbox.width) + FIX_ONE/2;
		compositor->hit_texcoords.y = gf_divfix(y, drawable->path->bbox.height) + FIX_ONE/2;
		svg_clone_use_stack(compositor, tr_state);
		/*not use in SVG patterns*/
		compositor->hit_appear = NULL;

		/*also stack any VRML sensors present at the current level. If the event is not catched
		by a listener in the SVG tree, the event will be forwarded to the VRML tree*/
		gf_list_reset(tr_state->visual->compositor->sensors);
		count = gf_list_count(tr_state->vrml_sensors);
		for (i=0; i<count; i++) {
			gf_list_add(tr_state->visual->compositor->sensors, gf_list_get(tr_state->vrml_sensors, i));
		}

		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SVG Picking] node %s is under mouse - hit %g %g 0\n", gf_node_get_log_name(drawable->node), FIX2FLT(x), FIX2FLT(y)));
	}

	compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
}
示例#9
0
void svg_drawable_3d_pick(Drawable *drawable, GF_TraverseState *tr_state, DrawAspect2D *asp) 
{
	SFVec3f local_pt, world_pt, vdiff;
	SFVec3f hit_normal;
	SFVec2f text_coords;
	u32 i, count;
	Fixed sqdist;
	Bool node_is_over;
	GF_Compositor *compositor;
	GF_Matrix mx;
	GF_Ray r;

	compositor = tr_state->visual->compositor;

	node_is_over = 0;
	r = tr_state->ray;
	gf_mx_copy(mx, tr_state->model_matrix);
	gf_mx_inverse(&mx);
	gf_mx_apply_ray(&mx, &r);

	/*if we already have a hit point don't check anything below...*/
	if (compositor->hit_square_dist && !compositor->grabbed_sensor && !tr_state->layer3d) {
		GF_Plane p;
		GF_BBox box;
		SFVec3f hit = compositor->hit_world_point;
		gf_mx_apply_vec(&mx, &hit);
		p.normal = r.dir;
		p.d = -1 * gf_vec_dot(p.normal, hit);
		gf_bbox_from_rect(&box, &drawable->path->bbox);

		if (gf_bbox_plane_relation(&box, &p) == GF_BBOX_FRONT) {
			GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SVG Picking] bounding box of node %s (DEF %s) below current hit point - skipping\n", gf_node_get_class_name(drawable->node), gf_node_get_name(drawable->node)));
			return;
		}
	}
	node_is_over = 0;
	if (compositor_get_2d_plane_intersection(&r, &local_pt)) {
		node_is_over = svg_drawable_is_over(drawable, local_pt.x, local_pt.y, asp, tr_state, NULL);
	}

	if (!node_is_over) return;

	hit_normal.x = hit_normal.y = 0; hit_normal.z = FIX_ONE;
	text_coords.x = gf_divfix(local_pt.x, drawable->path->bbox.width) + FIX_ONE/2;
	text_coords.y = gf_divfix(local_pt.y, drawable->path->bbox.height) + FIX_ONE/2;

	/*check distance from user and keep the closest hitpoint*/
	world_pt = local_pt;
	gf_mx_apply_vec(&tr_state->model_matrix, &world_pt);

	for (i=0; i<tr_state->num_clip_planes; i++) {
		if (gf_plane_get_distance(&tr_state->clip_planes[i], &world_pt) < 0) {
			GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SVG Picking] node %s (def %s) is not in clipper half space\n", gf_node_get_class_name(drawable->node), gf_node_get_name(drawable->node)));
			return;
		}
	}

	gf_vec_diff(vdiff, world_pt, tr_state->ray.orig);
	sqdist = gf_vec_lensq(vdiff);
	if (compositor->hit_square_dist && (compositor->hit_square_dist+FIX_EPSILON<sqdist)) {
		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SVG Picking] node %s (def %s) is farther (%g) than current pick (%g)\n", gf_node_get_class_name(drawable->node), gf_node_get_name(drawable->node), FIX2FLT(sqdist), FIX2FLT(compositor->hit_square_dist)));
		return;
	}

	compositor->hit_square_dist = sqdist;

	/*also stack any VRML sensors present at the current level. If the event is not catched
	by a listener in the SVG tree, the event will be forwarded to the VRML tree*/
	gf_list_reset(compositor->sensors);
	count = gf_list_count(tr_state->vrml_sensors);
	for (i=0; i<count; i++) {
		gf_list_add(compositor->sensors, gf_list_get(tr_state->vrml_sensors, i));
	}

	gf_mx_copy(compositor->hit_world_to_local, tr_state->model_matrix);
	gf_mx_copy(compositor->hit_local_to_world, mx);
	compositor->hit_local_point = local_pt;
	compositor->hit_world_point = world_pt;
	compositor->hit_world_ray = tr_state->ray;
	compositor->hit_normal = hit_normal;
	compositor->hit_texcoords = text_coords;

	svg_clone_use_stack(compositor, tr_state);
	/*not use in SVG patterns*/
	compositor->hit_appear = NULL;
	compositor->hit_node = drawable->node;
	compositor->hit_text = NULL;
	compositor->hit_use_dom_events = 1;

	GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SVG Picking] node %s (def %s) is under mouse - hit %g %g %g\n", gf_node_get_class_name(drawable->node), gf_node_get_name(drawable->node),
			FIX2FLT(world_pt.x), FIX2FLT(world_pt.y), FIX2FLT(world_pt.z)));
}