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); }
static void svg_traverse_svg(GF_Node *node, void *rs, Bool is_destroy) { Bool rootmost_svg, send_resize; u32 viewport_color; SVGsvgStack *stack; GF_Matrix2D backup_matrix, vb_bck; #ifndef GPAC_DISABLE_3D GF_Matrix bck_mx; #endif Bool is_dirty; GF_IRect top_clip; SFVec2f prev_vp; SVGPropertiesPointers backup_props, *prev_props; u32 backup_flags; Bool invalidate_flag; u32 styling_size = sizeof(SVGPropertiesPointers); GF_TraverseState *tr_state = (GF_TraverseState *) rs; SVGAllAttributes all_atts; stack = gf_node_get_private(node); if (is_destroy) { if (stack->svg_props) { gf_svg_properties_reset_pointers(stack->svg_props); gf_free(stack->svg_props); } gf_sc_check_focus_upon_destroy(node); if (stack->vp_fill) drawable_del(stack->vp_fill); gf_free(stack); return; } prev_props = tr_state->svg_props; /*SVG props not set: we are either the root-most <svg> of the compositor or an <svg> inside an <animation>*/ if (!tr_state->svg_props) { tr_state->svg_props = stack->svg_props; if (!tr_state->svg_props) return; } gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); if (!compositor_svg_traverse_base(node, &all_atts, tr_state, &backup_props, &backup_flags)) { tr_state->svg_props = prev_props; return; } /*enable or disable navigation*/ tr_state->visual->compositor->navigation_disabled = (all_atts.zoomAndPan && *all_atts.zoomAndPan == SVG_ZOOMANDPAN_DISABLE) ? 1 : 0; 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; } top_clip = tr_state->visual->top_clipper; gf_mx2d_copy(backup_matrix, tr_state->transform); gf_mx2d_copy(vb_bck, tr_state->vb_transform); #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) gf_mx_copy(bck_mx, tr_state->model_matrix); #endif invalidate_flag = tr_state->invalidate_all; is_dirty = gf_node_dirty_get(node); if (is_dirty & GF_SG_CHILD_DIRTY) drawable_reset_group_highlight(tr_state, node); gf_node_dirty_clear(node, 0); send_resize = 0; if ((stack->parent_vp.x != tr_state->vp_size.x) || (stack->parent_vp.y != tr_state->vp_size.y)) { is_dirty = 1; send_resize = 1; } if (is_dirty || tr_state->visual->compositor->recompute_ar) { svg_recompute_viewport_transformation(node, stack, tr_state, &all_atts); } gf_mx2d_copy(tr_state->vb_transform, stack->viewbox_mx); rootmost_svg = (stack->root_svg && !tr_state->parent_anim_atts) ? 1 : 0; if (tr_state->traversing_mode == TRAVERSE_SORT) { SVG_Paint *vp_fill = NULL; Fixed vp_opacity; if (tr_state->parent_anim_atts) { vp_fill = tr_state->parent_anim_atts->viewport_fill; vp_opacity = tr_state->parent_anim_atts->viewport_fill_opacity ? tr_state->parent_anim_atts->viewport_fill_opacity->value : FIX_ONE; } else { vp_fill = tr_state->svg_props->viewport_fill; vp_opacity = tr_state->svg_props->viewport_fill_opacity ? tr_state->svg_props->viewport_fill_opacity->value : FIX_ONE; } if (vp_fill && (vp_fill->type != SVG_PAINT_NONE) && vp_opacity) { Bool col_dirty = 0; viewport_color = GF_COL_ARGB_FIXED(vp_opacity, vp_fill->color.red, vp_fill->color.green, vp_fill->color.blue); if (stack->prev_color != viewport_color) { stack->prev_color = viewport_color; col_dirty = 1; } if (!rootmost_svg) { DrawableContext *ctx; Fixed width = tr_state->parent_anim_atts->width->value; Fixed height = tr_state->parent_anim_atts->height->value; if (!stack->vp_fill) { stack->vp_fill = drawable_new(); stack->vp_fill->node = node; } if ((width != stack->vp_fill->path->bbox.width) || (height != stack->vp_fill->path->bbox.height)) { drawable_reset_path(stack->vp_fill); gf_path_add_rect(stack->vp_fill->path, 0, 0, width, -height); } ctx = drawable_init_context_svg(stack->vp_fill, tr_state); if (ctx) { ctx->flags &= ~CTX_IS_TRANSPARENT; ctx->aspect.pen_props.width = 0; ctx->aspect.fill_color = viewport_color; ctx->aspect.fill_texture = NULL; if (col_dirty) ctx->flags |= CTX_APP_DIRTY; drawable_finalize_sort(ctx, tr_state, NULL); } } else if (col_dirty) { tr_state->visual->compositor->back_color = viewport_color; /*invalidate the entire visual*/ tr_state->invalidate_all = 1; } } } if (!stack->root_svg && (all_atts.x || all_atts.y)) gf_mx2d_add_translation(&tr_state->vb_transform, all_atts.x->value, all_atts.y->value); #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) { if (tr_state->traversing_mode==TRAVERSE_SORT) { GF_Matrix tmp; visual_3d_matrix_push(tr_state->visual); gf_mx_from_mx2d(&tmp, &tr_state->vb_transform); visual_3d_matrix_add(tr_state->visual, tmp.m); } else { gf_mx_add_matrix_2d(&tr_state->model_matrix, &tr_state->vb_transform); } } else #endif { gf_mx2d_pre_multiply(&tr_state->transform, &tr_state->vb_transform); } /*store VP and move it to current VP (eg, the one used to compute the vb_transform)*/ prev_vp = tr_state->vp_size; tr_state->vp_size = stack->vp; /*the event may trigger scripts which may delete nodes / modify the scene. We therefore send the resize event before traversing the scene*/ if (send_resize) { GF_DOM_Event evt; memset(&evt, 0, sizeof(GF_DOM_Event)); evt.bubbles = 1; evt.type = GF_EVENT_RESIZE; gf_dom_event_fire(node, &evt); } if ((stack->vp.x != prev_vp.x) || (stack->vp.y != prev_vp.y)) { GF_Scene *scene = node->sgprivate->scenegraph->userpriv; if (scene) { GF_DOM_Event evt; memset(&evt, 0, sizeof(GF_DOM_Event)); evt.bubbles = 0; evt.screen_rect.width = stack->vpw; evt.screen_rect.height = stack->vph; evt.screen_rect.x = stack->dx; evt.screen_rect.y = stack->dy; evt.prev_translate.x = stack->vp.x; evt.prev_translate.y = stack->vp.y; evt.type = GF_EVENT_VP_RESIZE; gf_scene_notify_event(scene, 0, NULL, &evt, GF_OK); } } 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); } tr_state->vp_size = prev_vp; #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d) { if (tr_state->traversing_mode==TRAVERSE_SORT) visual_3d_matrix_pop(tr_state->visual); gf_mx_copy(tr_state->model_matrix, bck_mx); } #endif gf_mx2d_copy(tr_state->transform, backup_matrix); gf_mx2d_copy(tr_state->vb_transform, vb_bck); memcpy(tr_state->svg_props, &backup_props, styling_size); tr_state->svg_flags = backup_flags; tr_state->visual->top_clipper = top_clip; if (!stack->root_svg) { tr_state->invalidate_all = invalidate_flag; } tr_state->svg_props = prev_props; }