void compositor_svg_apply_local_transformation(GF_TraverseState *tr_state, SVGAllAttributes *atts, GF_Matrix2D *backup_matrix_2d, GF_Matrix *backup_matrix) { #ifndef GPAC_DISABLE_3D if (tr_state->visual->type_3d && backup_matrix) { GF_Matrix tmp; Bool is_draw = (tr_state->traversing_mode==TRAVERSE_SORT) ? 1 : 0; gf_mx_copy(*backup_matrix, tr_state->model_matrix); if (is_draw) visual_3d_matrix_push(tr_state->visual); if (atts->transform && atts->transform->is_ref) { gf_mx_from_mx2d(&tr_state->model_matrix, &tr_state->vb_transform); if (is_draw) { GF_Matrix tmp; gf_mx_init(tmp); gf_mx_add_translation(&tmp, -tr_state->camera->width/2, tr_state->camera->height/2, 0); gf_mx_add_scale(&tmp, FIX_ONE, -FIX_ONE, FIX_ONE); gf_mx_add_matrix(&tmp, &tr_state->model_matrix); visual_3d_matrix_load(tr_state->visual, tmp.m); } } if (atts->motionTransform) { if (is_draw) { gf_mx_from_mx2d(&tmp, atts->motionTransform); visual_3d_matrix_add(tr_state->visual, tmp.m); } else { gf_mx_add_matrix_2d(&tr_state->model_matrix, atts->motionTransform); } } if (atts->transform) { if (is_draw) { gf_mx_from_mx2d(&tmp, &atts->transform->mat); visual_3d_matrix_add(tr_state->visual, tmp.m); } else { gf_mx_add_matrix_2d(&tr_state->model_matrix, &atts->transform->mat); } } return; } #endif gf_mx2d_copy(*backup_matrix_2d, tr_state->transform); if (atts->transform && atts->transform->is_ref) gf_mx2d_copy(tr_state->transform, tr_state->vb_transform); if (atts->motionTransform) gf_mx2d_pre_multiply(&tr_state->transform, atts->motionTransform); if (atts->transform) gf_mx2d_pre_multiply(&tr_state->transform, &atts->transform->mat); }
static void traverse_transform(GF_Node *node, Transform2DStack *stack, GF_TraverseState *tr_state) { if (stack->is_null) return; /*note we don't clear dirty flag, this is done in traversing*/ if (stack->is_identity) { group_2d_traverse(node, (GroupingNode2D *)stack, tr_state); } #ifndef GPAC_DISABLE_3D else if (tr_state->visual->type_3d) { GF_Matrix mx_bckup; gf_mx_copy(mx_bckup, tr_state->model_matrix); gf_mx_add_matrix_2d(&tr_state->model_matrix, &stack->mat); group_2d_traverse(node, (GroupingNode2D *)stack, tr_state); gf_mx_copy(tr_state->model_matrix, mx_bckup); } #endif else { GF_Matrix2D bckup; gf_mx2d_copy(bckup, tr_state->transform); gf_mx2d_pre_multiply(&tr_state->transform, &stack->mat); group_2d_traverse(node, (GroupingNode2D *)stack, tr_state); gf_mx2d_copy(tr_state->transform, bckup); } if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) { gf_mx2d_apply_rect(&stack->mat, &tr_state->bounds); } }
void camera_update_stereo(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords, Fixed horizontal_shift, Fixed nominal_view_distance, Fixed view_distance_offset, u32 camera_layout) { Fixed vlen, h, w, ar; SFVec3f corner, center; GF_Matrix post_model_view; if (! (cam->flags & CAM_IS_DIRTY)) return; ar = gf_divfix(cam->width, cam->height); gf_mx_init(post_model_view); if (cam->is_3D) { /*setup perspective*/ if (camera_layout==GF_3D_CAMERA_OFFAXIS) { Fixed left, right, top, bottom, shift, wd2, ndfl, viewing_distance; SFVec3f eye, pos, tar, disp; viewing_distance = nominal_view_distance; wd2 = gf_mulfix(cam->z_near, gf_tan(cam->fieldOfView/2)); ndfl = gf_divfix(cam->z_near, viewing_distance); /*compute h displacement*/ shift = gf_mulfix(horizontal_shift, ndfl); top = wd2; bottom = -top; left = -gf_mulfix(ar, wd2) - shift; right = gf_mulfix(ar, wd2) - shift; gf_mx_init(cam->projection); cam->projection.m[0] = gf_divfix(2*cam->z_near, (right-left)); cam->projection.m[5] = gf_divfix(2*cam->z_near, (top-bottom)); cam->projection.m[8] = gf_divfix(right+left, right-left); cam->projection.m[9] = gf_divfix(top+bottom, top-bottom); cam->projection.m[10] = gf_divfix(cam->z_far+cam->z_near, cam->z_near-cam->z_far); cam->projection.m[11] = -FIX_ONE; cam->projection.m[14] = 2*gf_muldiv(cam->z_near, cam->z_far, cam->z_near-cam->z_far); cam->projection.m[15] = 0; gf_vec_diff(eye, cam->target, cam->position); gf_vec_norm(&eye); disp = gf_vec_cross(eye, cam->up); gf_vec_norm(&disp); gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); shift = gf_mulfix(horizontal_shift, gf_divfix(vlen, viewing_distance)); pos = gf_vec_scale(disp, shift); gf_vec_add(pos, pos, cam->position); gf_vec_add(tar, pos, eye); /*setup modelview*/ gf_mx_lookat(&cam->modelview, pos, tar, cam->up); } else { gf_mx_perspective(&cam->projection, cam->fieldOfView, ar, cam->z_near, cam->z_far); /*setup modelview*/ gf_mx_lookat(&cam->modelview, cam->position, cam->target, cam->up); } if (!center_coords) { gf_mx_add_scale(&post_model_view, FIX_ONE, -FIX_ONE, FIX_ONE); gf_mx_add_translation(&post_model_view, -cam->width / 2, -cam->height / 2, 0); } /*compute center and radius - CHECK ME!*/ vlen = cam->z_far - cam->z_near; h = gf_mulfix(vlen , gf_tan(cam->fieldOfView / 2)); w = gf_mulfix(h, ar); center.x = 0; center.y = 0; center.z = cam->z_near + vlen / 2; corner.x = w; corner.y = h; corner.z = vlen; gf_vec_diff(corner, corner, center); cam->radius = gf_vec_len(corner); gf_vec_diff(cam->center, cam->target, cam->position); gf_vec_norm(&cam->center); cam->center = gf_vec_scale(cam->center, cam->z_near + vlen/2); gf_vec_add(cam->center, cam->center, cam->position); } else { GF_BBox b; Fixed hw, hh; hw = cam->width / 2; hh = cam->height / 2; cam->z_near = INT2FIX(NEAR_PLANE_2D); cam->z_far = INT2FIX(FAR_PLANE_2D); /*setup ortho*/ gf_mx_ortho(&cam->projection, -hw, hw, -hh, hh, cam->z_near, cam->z_far); /*setup modelview*/ gf_mx_init(cam->modelview); #ifdef FORCE_CAMERA_3D if (! (cam->flags & CAM_NO_LOOKAT)) gf_mx_lookat(&cam->modelview, cam->position, cam->target, cam->up); #endif if (!center_coords) { gf_mx_add_scale(&post_model_view, FIX_ONE, -FIX_ONE, FIX_ONE); gf_mx_add_translation(&post_model_view, -hw, -hh, 0); } if (user_transform) { #ifdef FORCE_CAMERA_3D if (! (cam->flags & CAM_NO_LOOKAT)) { GF_Matrix mx; gf_mx_from_mx2d(&mx, user_transform); mx.m[10] = mx.m[0]; gf_mx_add_matrix(&post_model_view, &mx); } else #endif gf_mx_add_matrix_2d(&post_model_view, user_transform); } if (cam->end_zoom != FIX_ONE) gf_mx_add_scale(&post_model_view, cam->end_zoom, cam->end_zoom, cam->end_zoom); if (cam->flags & CAM_HAS_VIEWPORT) gf_mx_add_matrix(&post_model_view, &cam->viewport); /*compute center & radius*/ b.max_edge.x = hw; b.max_edge.y = hh; b.min_edge.x = -hw; b.min_edge.y = -hh; b.min_edge.z = b.max_edge.z = (cam->z_near+cam->z_far) / 2; gf_bbox_refresh(&b); cam->center = b.center; cam->radius = b.radius; if (camera_layout==GF_3D_CAMERA_OFFAXIS) camera_layout=GF_3D_CAMERA_LINEAR; } if (camera_layout == GF_3D_CAMERA_CIRCULAR) { GF_Matrix mx; Fixed viewing_distance = nominal_view_distance; SFVec3f pos, target; Fixed angle; gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); vlen += gf_mulfix(view_distance_offset, gf_divfix(vlen, nominal_view_distance)); gf_vec_diff(pos, cam->target, cam->position); gf_vec_norm(&pos); pos = gf_vec_scale(pos, vlen); gf_vec_add(target, pos, cam->position); gf_mx_init(mx); gf_mx_add_translation(&mx, target.x, target.y, target.z); angle = gf_atan2(horizontal_shift, viewing_distance); gf_mx_add_rotation(&mx, angle, cam->up.x, cam->up.y, cam->up.z); gf_mx_add_translation(&mx, -target.x, -target.y, -target.z); pos = cam->position; gf_mx_apply_vec(&mx, &pos); gf_mx_lookat(&cam->modelview, pos, target, cam->up); } else if (camera_layout == GF_3D_CAMERA_LINEAR) { Fixed viewing_distance = nominal_view_distance + view_distance_offset; GF_Vec eye, disp, pos, tar; gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); vlen += gf_mulfix(view_distance_offset, gf_divfix(vlen, nominal_view_distance)); gf_vec_diff(eye, cam->target, cam->position); gf_vec_norm(&eye); tar = gf_vec_scale(eye, vlen); gf_vec_add(tar, tar, cam->position); disp = gf_vec_cross(eye, cam->up); gf_vec_norm(&disp); disp= gf_vec_scale(disp, gf_divfix(gf_mulfix(vlen, horizontal_shift), viewing_distance)); gf_vec_add(pos, cam->position, disp); gf_mx_lookat(&cam->modelview, pos, tar, cam->up); } gf_mx_add_matrix(&cam->modelview, &post_model_view); /*compute frustum planes*/ gf_mx_copy(cam->unprojection, cam->projection); gf_mx_add_matrix_4x4(&cam->unprojection, &cam->modelview); camera_frustum_from_matrix(cam, &cam->unprojection); /*also compute reverse PM for unprojections*/ gf_mx_inverse_4x4(&cam->unprojection); cam->flags &= ~CAM_IS_DIRTY; }
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; }
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; }
static void svg_traverse_animation(GF_Node *node, void *rs, Bool is_destroy) { SVGAllAttributes all_atts; GF_Matrix2D backup_matrix; GF_Matrix backup_matrix3d; SVGPropertiesPointers backup_props; u32 backup_flags; SFVec2f prev_vp; GF_Rect rc; GF_IRect clip, prev_clip; SVGAllAttributes *prev_vp_atts; GF_TraverseState *tr_state = (GF_TraverseState*)rs; GF_Matrix2D translate; SVGPropertiesPointers *old_props; SVGlinkStack *stack = gf_node_get_private(node); 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 (!stack->inline_sg && !stack->resource) { if (!stack->init_vis_state) { if (all_atts.initialVisibility && (*all_atts.initialVisibility==SVG_INITIALVISIBILTY_ALWAYS)) { stack->init_vis_state = 2; svg_animation_smil_update(node, stack, 0); } else { stack->init_vis_state = 1; } } if (!stack->inline_sg && !stack->resource) return; } if (!all_atts.width || !all_atts.height) return; if (!all_atts.width->value || !all_atts.height->value) return; 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) || *(tr_state->svg_props->visibility) == SVG_VISIBILITY_HIDDEN) { goto end; } compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &backup_matrix3d); /*add x/y translation*/ 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); #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); /*reset SVG props to reload a new inheritance context*/ old_props = tr_state->svg_props; tr_state->svg_props = NULL; /*store this node's attribute to compute PAR/ViewBox of the child <svg>*/ prev_vp_atts = tr_state->parent_anim_atts; tr_state->parent_anim_atts = &all_atts; /*update VP size*/ prev_vp = tr_state->vp_size; 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); /*setup new clipper*/ rc.width = tr_state->vp_size.x; rc.height = tr_state->vp_size.y; rc.x = 0; rc.y = tr_state->vp_size.y; gf_mx2d_apply_rect(&tr_state->transform, &rc); prev_clip = tr_state->visual->top_clipper; clip = gf_rect_pixelize(&rc); // gf_irect_intersect(&tr_state->visual->top_clipper, &clip); if (!stack->inline_sg && stack->resource) { stack->inline_sg = gf_mo_get_scenegraph(stack->resource); } if (stack->inline_sg) { gf_sc_traverse_subscene(tr_state->visual->compositor, node, stack->inline_sg, tr_state); } if (stack->init_vis_state == 2) { stack->init_vis_state = 3; gf_mo_pause(stack->resource); } tr_state->svg_props = old_props; tr_state->visual->top_clipper = prev_clip; tr_state->parent_anim_atts = prev_vp_atts; tr_state->vp_size = prev_vp; compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &backup_matrix3d); end: memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); tr_state->svg_flags = backup_flags; }