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); }
/* 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); } }
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; }
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); } }
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; }
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); }
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; }
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)); }
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))); }