📄 svg_base_da.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - Jean le Feuvre * Copyright (c) 2005-200X ENST * All rights reserved * * This file is part of GPAC / SVG Rendering sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "visualsurface2d.h"#ifndef GPAC_DISABLE_SVG#include "svg_stacks.h"void svg_check_focus_upon_destroy(GF_Node *n){ Render2D *r2d; GF_Renderer *sr = gf_sr_get_renderer(n); if (sr) { r2d = (Render2D *)sr->visual_renderer->user_priv; if (r2d->focus_node==n) r2d->focus_node = NULL; }}static Bool svg_is_focus_target(GF_Node *elt){ u32 i, count; if (gf_node_get_tag(elt)==TAG_SVG_a) return 1; count = gf_dom_listener_count(elt); for (i=0; i<count; i++) { GF_FieldInfo info; GF_Node *l = gf_dom_listener_get(elt, i); if (gf_svg_get_attribute_by_tag(l, TAG_SVG_ATT_event, 0, 0, &info)==GF_OK) { switch ( ((XMLEV_Event*)info.far_ptr)->type) { case GF_EVENT_FOCUSIN: case GF_EVENT_FOCUSOUT: case GF_EVENT_ACTIVATE: return 1; } } } return 0;}static GF_Node *svg_set_focus_prev(Render2D *sr, GF_Node *elt, Bool current_focus){ u32 i, count; GF_Node *n; SVGAllAttributes atts; if (gf_node_get_tag(elt) <= GF_NODE_FIRST_DOM_NODE_TAG) return NULL; gf_svg_flatten_attributes((SVG_Element *)elt, &atts); if (atts.display && (*atts.display==SVG_DISPLAY_NONE)) return NULL; if (!current_focus) { Bool is_auto = 1; if (atts.focusable) { if (*atts.focusable==SVG_FOCUSABLE_TRUE) return elt; if (*atts.focusable==SVG_FOCUSABLE_FALSE) is_auto = 0; } if (is_auto && svg_is_focus_target(elt)) return elt; } /**/ if (atts.nav_prev) { switch (atts.nav_prev->type) { case SVG_FOCUS_SELF: /*focus locked on element*/ return elt; case SVG_FOCUS_IRI: if (!atts.nav_prev->target.target) { if (!atts.nav_prev->target.string) return NULL; atts.nav_prev->target.target = gf_sg_find_node_by_name(sr->compositor->scene, atts.nav_prev->target.string+1); } return atts.nav_prev->target.target; default: break; } } /*check all children except if current focus*/ if (current_focus) return NULL; count = gf_node_list_get_count( ((SVG_Element*)elt)->children ); for (i=count; i>0; i--) { /*get in the subtree*/ n = gf_node_list_get_child( ((SVG_Element*)elt)->children, i-1); n = svg_set_focus_prev(sr, n, current_focus); if (n) return n; } return NULL;}static GF_Node *svg_browse_parent_for_focus_prev(Render2D *sr, GF_Node *elt){ s32 idx = 0; u32 i, count; GF_Node *n; SVG_Element *par; /*not found, browse parent list*/ par = (SVG_Element *)gf_node_get_parent((GF_Node*)elt, 0); /*root, return NULL if next, current otherwise*/ if (!par) return NULL; /*locate element*/ count = gf_node_list_get_count(par->children); idx = gf_node_list_find_child(par->children, elt); if (idx<0) idx=count; for (i=idx; i>0; i--) { n = gf_node_list_get_child(par->children, i-1); /*get in the subtree*/ n = svg_set_focus_prev(sr, n, 0); if (n) return n; } /*up one level*/ return svg_browse_parent_for_focus_prev(sr, (GF_Node*)par);}static GF_Node *svg_set_focus_next(Render2D *sr, GF_Node *elt, Bool current_focus){ GF_ChildNodeItem *child; GF_Node *n; SVGAllAttributes atts; if (gf_node_get_tag(elt) <= GF_NODE_FIRST_DOM_NODE_TAG) return NULL; gf_svg_flatten_attributes((SVG_Element *)elt, &atts); if (atts.display && (*atts.display==SVG_DISPLAY_NONE)) return NULL; if (!current_focus) { Bool is_auto = 1; if (atts.focusable) { if (*atts.focusable==SVG_FOCUSABLE_TRUE) return elt; if (*atts.focusable==SVG_FOCUSABLE_FALSE) is_auto = 0; } if (is_auto && svg_is_focus_target(elt)) return elt; } /*check next*/ if (atts.nav_next) { switch (atts.nav_next->type) { case SVG_FOCUS_SELF: /*focus locked on element*/ return elt; case SVG_FOCUS_IRI: if (!atts.nav_next->target.target) { if (!atts.nav_next->target.string) return NULL; atts.nav_next->target.target = gf_sg_find_node_by_name(sr->compositor->scene, atts.nav_next->target.string+1); } return atts.nav_next->target.target; default: break; } } /*check all children */ child = ((SVG_Element*)elt)->children; while (child) { /*get in the subtree*/ n = svg_set_focus_next(sr, child->node, 0); if (n) return n; child = child->next; } return NULL;}static GF_Node *svg_browse_parent_for_focus_next(Render2D *sr, GF_Node *elt){ s32 idx = 0; GF_ChildNodeItem *child; GF_Node *n; SVG_Element *par; /*not found, browse parent list*/ par = (SVG_Element *)gf_node_get_parent((GF_Node*)elt, 0); /*root, return NULL if next, current otherwise*/ if (!par) return NULL; /*locate element*/ child = par->children; idx = gf_node_list_find_child(child, elt); while (child) { if (idx<0) { /*get in the subtree*/ n = svg_set_focus_next(sr, child->node, 0); if (n) return n; } idx--; child = child->next; } /*up one level*/ return svg_browse_parent_for_focus_next(sr, (GF_Node*)par);}u32 svg_focus_switch_ring(Render2D *sr, Bool move_prev){ GF_DOM_Event evt; Bool current_focus = 1; u32 ret = 0; GF_Node *n, *prev; prev = sr->focus_node; if (!sr->focus_node) { sr->focus_node = gf_sg_get_root_node(sr->compositor->scene); if (!sr->focus_node) return 0; current_focus = 0; } /*get focus in current doc order*/ if (move_prev) { n = svg_set_focus_prev(sr, sr->focus_node, current_focus); if (!n) n = svg_browse_parent_for_focus_prev(sr, sr->focus_node); } else { n = svg_set_focus_next(sr, sr->focus_node, current_focus); if (!n) n = svg_browse_parent_for_focus_next(sr, sr->focus_node); } sr->focus_node = n; ret = 0; if (prev != sr->focus_node) { /*the event is already handled, even though no listeners may be present*/ ret = 1; memset(&evt, 0, sizeof(GF_DOM_Event)); if (prev) { evt.bubbles = 1; evt.target = prev; evt.type = GF_EVENT_FOCUSOUT; gf_dom_event_fire(prev, NULL, &evt); } if (sr->focus_node) { evt.bubbles = 1; evt.target = sr->focus_node; evt.type = GF_EVENT_FOCUSIN; gf_dom_event_fire(sr->focus_node, NULL, &evt); } //invalidate in case we draw focus rect gf_sr_invalidate(sr->compositor, NULL); } return ret;}u32 svg_focus_navigate(Render2D *sr, u32 key_code){ SVGAllAttributes atts; GF_DOM_Event evt; u32 ret = 0; GF_Node *n; SVG_Focus *focus = NULL; if (!sr->focus_node) return 0; n=NULL; gf_svg_flatten_attributes((SVG_Element *)sr->focus_node, &atts); switch (key_code) { case GF_KEY_LEFT: focus = atts.nav_left; break; case GF_KEY_RIGHT: focus = atts.nav_right; break; case GF_KEY_UP: focus = atts.nav_up; break; case GF_KEY_DOWN: focus = atts.nav_down; break; default: return 0; } if (!focus) return 0; if (focus->type==SVG_FOCUS_SELF) return 0; if (focus->type==SVG_FOCUS_AUTO) return 0; if (!focus->target.target) { if (!focus->target.string) return 0; focus->target.target = gf_sg_find_node_by_name(sr->compositor->scene, focus->target.string+1); } n = focus->target.target; ret = 0; if (n != sr->focus_node) { /*the event is already handled, even though no listeners may be present*/ ret = 1; memset(&evt, 0, sizeof(GF_DOM_Event)); evt.bubbles = 1; if (sr->focus_node) { evt.target = sr->focus_node; evt.type = GF_EVENT_FOCUSOUT; gf_dom_event_fire(sr->focus_node, NULL, &evt); } if (n) { evt.relatedTarget = n; evt.type = GF_EVENT_FOCUSIN; gf_dom_event_fire(n, NULL, &evt); } sr->focus_node = n; //invalidate in case we draw focus rect gf_sr_invalidate(sr->compositor, NULL); } return ret;}/* This is the generic routine for child traversing - note we are not duplicating the effect*/void svg_render_node(GF_Node *node, RenderEffect2D *eff){#if 0 Bool has_listener = gf_dom_listener_count(node);// fprintf(stdout, "rendering %s of type %s\n", gf_node_get_name(node), gf_node_get_class_name(node)); if (has_listener) { eff->nb_listeners++; gf_node_render(node, eff); eff->nb_listeners--; } else { gf_node_render(node, eff); }#else gf_node_render(node, eff);#endif}void svg_render_node_list(GF_ChildNodeItem *children, RenderEffect2D *eff){ while (children) { svg_render_node(children->node, eff); children = children->next; }}Bool svg_is_display_off(SVGPropertiesPointers *props){ return (props->display && (*(props->display) == SVG_DISPLAY_NONE)) ? 1 : 0;}void svg_get_nodes_bounds(GF_Node *self, GF_ChildNodeItem *children, RenderEffect2D *eff){ GF_Rect rc; GF_Matrix2D cur_mx; gf_mx2d_copy(cur_mx, eff->transform); rc = gf_rect_center(0,0); while (children) { gf_mx2d_init(eff->transform); eff->bounds = gf_rect_center(0,0); gf_node_render(children->node, eff); /*we hit the target node*/ if (children->node == eff->for_node) { eff->for_node = NULL; return; } gf_mx2d_apply_rect(&eff->transform, &eff->bounds); gf_rect_union(&rc, &eff->bounds); children = children->next; } gf_mx2d_copy(eff->transform, cur_mx); gf_mx2d_apply_rect(&eff->transform, &rc); eff->bounds = rc;}void svg_apply_local_transformation(RenderEffect2D *eff, SVGAllAttributes *atts, GF_Matrix2D *backup_matrix){ gf_mx2d_copy(*backup_matrix, eff->transform); if (atts->transform && atts->transform->is_ref) gf_mx2d_copy(eff->transform, eff->vb_transform); if (atts->motionTransform) gf_mx2d_pre_multiply(&eff->transform, atts->motionTransform); if (atts->transform) gf_mx2d_pre_multiply(&eff->transform, &atts->transform->mat);}void svg_restore_parent_transformation(RenderEffect2D *eff, GF_Matrix2D *backup_matrix){ gf_mx2d_copy(eff->transform, *backup_matrix); }void svg_render_base(GF_Node *node, SVGAllAttributes *all_atts, RenderEffect2D *eff, SVGPropertiesPointers *backup_props, u32 *backup_flags){ u32 inherited_flags_mask; memcpy(backup_props, eff->svg_props, sizeof(SVGPropertiesPointers)); *backup_flags = eff->svg_flags;#if 0 // applying inheritance and determining which group of properties are being inherited inherited_flags_mask = gf_svg_apply_inheritance(all_atts, eff->svg_props); gf_svg_apply_animations(node, eff->svg_props); // including again inheritance if values are 'inherit'#else /* animation (including possibly inheritance) then full inheritance */ gf_svg_apply_animations(node, eff->svg_props); inherited_flags_mask = gf_svg_apply_inheritance(all_atts, eff->svg_props);#endif eff->svg_flags &= inherited_flags_mask; eff->svg_flags |= gf_node_dirty_get(node);}static void svg_set_viewport_transformation(RenderEffect2D *eff, SVGAllAttributes *atts, Bool is_root) { u32 dpi = 90; /* Should retrieve the dpi from the system */ Fixed real_width, real_height;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -