📄 svg_base_sani.c
字号:
}void svg_sani_init_path(Render2D *sr, GF_Node *node){ drawable_stack_new(sr, node); gf_node_set_callback_function(node, svg_sani_render_path);}/* end of rendering of basic shapes */static void svg_sani_render_a(GF_Node *node, void *rs, Bool is_destroy){ GF_Matrix2D backup_matrix; SVG_SANI_aElement *a = (SVG_SANI_aElement *) node; RenderEffect2D *eff = (RenderEffect2D *)rs; if (is_destroy) return; svg_sani_render_base(node, eff); if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) { gf_svg_sani_apply_local_transformation(eff, node, &backup_matrix); if (a->display != SVG_DISPLAY_NONE) svg_get_nodes_bounds(node, a->children, eff); gf_svg_sani_restore_parent_transformation(eff, &backup_matrix); return; } if (a->display != SVG_DISPLAY_NONE && a->visibility != SVG_VISIBILITY_HIDDEN) { gf_svg_sani_apply_local_transformation(eff, node, &backup_matrix); svg_render_node_list(a->children, eff); gf_svg_sani_restore_parent_transformation(eff, &backup_matrix); }}static void svg_sani_a_HandleEvent(GF_Node *handler, GF_DOM_Event *event){ GF_Renderer *compositor; GF_Event evt; SVG_SANI_aElement *a; assert(gf_node_get_tag(event->currentTarget)==TAG_SVG_SANI_a); a = (SVG_SANI_aElement *) event->currentTarget; compositor = (GF_Renderer *)gf_node_get_private(handler); if (!compositor->user->EventProc) return; evt.type = GF_EVENT_NAVIGATE; if (a->xlink->href.type == XMLRI_STRING) { evt.navigate.to_url = a->xlink->href.iri; if (evt.navigate.to_url) { evt.navigate.param_count = 1; evt.navigate.parameters = (const char **) &a->target; compositor->user->EventProc(compositor->user->opaque, &evt); } } else { u32 tag; if (!a->xlink->href.target) { /* TODO: check if href can be resolved */ return; } tag = gf_node_get_tag((GF_Node *)a->xlink->href.target); if (tag == TAG_SVG_SANI_set || tag == TAG_SVG_SANI_animate || tag == TAG_SVG_SANI_animateColor || tag == TAG_SVG_SANI_animateTransform || tag == TAG_SVG_SANI_animateMotion || tag == TAG_SVG_SANI_discard) { u32 i, count, found; SVG_SANI_setElement *set = (SVG_SANI_setElement *)a->xlink->href.target; SMIL_Time *begin; GF_SAFEALLOC(begin, SMIL_Time); begin->type = GF_SMIL_TIME_EVENT_RESOLVED; begin->clock = gf_node_get_scene_time((GF_Node *)set); found = 0; count = gf_list_count(set->timing->begin); for (i=0; i<count; i++) { SMIL_Time *first = (SMIL_Time *)gf_list_get(set->timing->begin, i); /*remove past instanciations*/ if ((first->type==GF_SMIL_TIME_EVENT_RESOLVED) && (first->clock < begin->clock)) { gf_list_rem(set->timing->begin, i); free(first); i--; count--; continue; } if ( (first->type == GF_SMIL_TIME_INDEFINITE) || ( (first->type == GF_SMIL_TIME_CLOCK) && (first->clock > begin->clock) ) ) { gf_list_insert(set->timing->begin, begin, i); found = 1; break; } } if (!found) gf_list_add(set->timing->begin, begin); gf_node_changed((GF_Node *)a->xlink->href.target, NULL); } } return;}void svg_sani_init_a(Render2D *sr, GF_Node *node){ SVG_SANI_handlerElement *handler; gf_node_set_callback_function(node, svg_sani_render_a); /*listener for onClick event*/ handler = gf_dom_listener_build(node, GF_EVENT_CLICK, 0, NULL); /*and overwrite handler*/ handler->handle_event = svg_sani_a_HandleEvent; gf_node_set_private((GF_Node *)handler, sr->compositor); /*listener for activate event*/ handler = gf_dom_listener_build(node, GF_EVENT_ACTIVATE, 0, NULL); /*and overwrite handler*/ handler->handle_event = svg_sani_a_HandleEvent; gf_node_set_private((GF_Node *)handler, sr->compositor); /*listener for mouseover event*/ handler = gf_dom_listener_build(node, GF_EVENT_MOUSEOVER, 0, NULL); /*and overwrite handler*/ handler->handle_event = svg_sani_a_HandleEvent; gf_node_set_private((GF_Node *)handler, sr->compositor);}/* end of Interactive SVG elements *//*SVG gradient common stuff*/typedef struct{ GF_TextureHandler txh; u32 *cols; Fixed *keys; u32 nb_col;} SVG_SANI_GradientStack;static void svg_sani_DestroyGradient(GF_Node *node){ SVG_SANI_GradientStack *st = (SVG_SANI_GradientStack *) gf_node_get_private(node); gf_sr_texture_destroy(&st->txh); if (st->cols) free(st->cols); if (st->keys) free(st->keys); free(st);}static void svg_sani_UpdateGradient(SVG_SANI_GradientStack *st, GF_ChildNodeItem *children){ u32 count; Fixed alpha, max_offset; if (!gf_node_dirty_get(st->txh.owner)) return; gf_node_dirty_clear(st->txh.owner, 0); st->txh.needs_refresh = 1; st->txh.transparent = 0; count = gf_node_list_get_count(children); st->nb_col = 0; st->cols = (u32*)realloc(st->cols, sizeof(u32)*count); st->keys = (Fixed*)realloc(st->keys, sizeof(Fixed)*count); max_offset = 0; while (children) { Fixed key; SVG_SANI_stopElement *gstop = (SVG_SANI_stopElement *) children->node; children = children->next; if (gf_node_get_tag((GF_Node *)gstop) != TAG_SVG_SANI_stop) continue; if (gstop->stop_opacity.type==SVG_NUMBER_VALUE) alpha = gstop->stop_opacity.value; else alpha = FIX_ONE; st->cols[st->nb_col] = GF_COL_ARGB_FIXED(alpha, gstop->stop_color.color.red, gstop->stop_color.color.green, gstop->stop_color.color.blue); key = gstop->offset.value; if (gstop->offset.value>FIX_ONE) key/=100; if (key>max_offset) max_offset=key; else key = max_offset; st->keys[st->nb_col] = key; st->nb_col++; if (alpha!=FIX_ONE) st->txh.transparent = 1; } st->txh.compositor->r2d->stencil_set_gradient_interpolation(st->txh.hwtx, st->keys, st->cols, st->nb_col); st->txh.compositor->r2d->stencil_set_gradient_mode(st->txh.hwtx, /*lg->spreadMethod*/ GF_GRADIENT_MODE_PAD);}static void svg_sani_render_PaintServer(GF_Node *node, void *rs, Bool is_destroy){ SVG_SANI_Element *elt = (SVG_SANI_Element *)node; RenderEffect2D *eff = (RenderEffect2D *) rs; if (is_destroy) { if (gf_node_get_private(node)) svg_sani_DestroyGradient(node); return; } svg_sani_render_base(node, eff); if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) { return; } else { svg_render_node_list(elt->children, eff); }}/* linear gradient */static void svg_sani_UpdateLinearGradient(GF_TextureHandler *txh){ SVG_SANI_linearGradientElement *lg = (SVG_SANI_linearGradientElement *) txh->owner; SVG_SANI_GradientStack *st = (SVG_SANI_GradientStack *) gf_node_get_private(txh->owner); if (!txh->hwtx) txh->hwtx = txh->compositor->r2d->stencil_new(txh->compositor->r2d, GF_STENCIL_LINEAR_GRADIENT); svg_sani_UpdateGradient(st, lg->children);}static void svg_sani_LG_ComputeMatrix(GF_TextureHandler *txh, GF_Rect *bounds, GF_Matrix2D *mat){ SFVec2f start, end; SVG_SANI_linearGradientElement *lg = (SVG_SANI_linearGradientElement *) txh->owner; /*create gradient brush if needed*/ if (!txh->hwtx) return; start.x = lg->x1.value; if (lg->x1.type==SVG_NUMBER_PERCENTAGE) start.x /= 100; start.y = lg->y1.value; if (lg->y1.type==SVG_NUMBER_PERCENTAGE) start.y /= 100; end.x = lg->x2.value; if (lg->x2.type==SVG_NUMBER_PERCENTAGE) end.x /= 100; end.y = lg->y2.value; if (lg->y2.type==SVG_NUMBER_PERCENTAGE) end.x /= 100; txh->compositor->r2d->stencil_set_gradient_mode(txh->hwtx, (GF_GradientMode) lg->spreadMethod); gf_mx2d_copy(*mat, lg->gradientTransform.mat); if (lg->gradientUnits==SVG_GRADIENTUNITS_OBJECT) { /*move to local coord system - cf SVG spec*/ gf_mx2d_add_scale(mat, bounds->width, bounds->height); gf_mx2d_add_translation(mat, bounds->x - 1, bounds->y - bounds->height - 1); } txh->compositor->r2d->stencil_set_linear_gradient(txh->hwtx, start.x, start.y, end.x, end.y);}void svg_sani_init_linearGradient(Render2D *sr, GF_Node *node){ SVG_SANI_GradientStack *st; GF_SAFEALLOC(st, SVG_SANI_GradientStack); gf_sr_texture_setup(&st->txh, sr->compositor, node); st->txh.update_texture_fcnt = svg_sani_UpdateLinearGradient; st->txh.compute_gradient_matrix = svg_sani_LG_ComputeMatrix; gf_node_set_private(node, st); gf_node_set_callback_function(node, svg_sani_render_PaintServer);}/* radial gradient */static void svg_sani_UpdateRadialGradient(GF_TextureHandler *txh){ SVG_SANI_radialGradientElement *rg = (SVG_SANI_radialGradientElement *) txh->owner; SVG_SANI_GradientStack *st = (SVG_SANI_GradientStack *) gf_node_get_private(txh->owner); if (!txh->hwtx) txh->hwtx = txh->compositor->r2d->stencil_new(txh->compositor->r2d, GF_STENCIL_RADIAL_GRADIENT); svg_sani_UpdateGradient(st, rg->children);}static void svg_sani_rG_ComputeMatrix(GF_TextureHandler *txh, GF_Rect *bounds, GF_Matrix2D *mat){ SFVec2f center, focal; Fixed radius; SVG_SANI_radialGradientElement *rg = (SVG_SANI_radialGradientElement *) txh->owner; /*create gradient brush if needed*/ if (!txh->hwtx) return; gf_mx2d_copy(*mat, rg->gradientTransform.mat); radius = rg->r.value; if (rg->r.type==SVG_NUMBER_PERCENTAGE) radius /= 100; center.x = rg->cx.value; if (rg->cx.type==SVG_NUMBER_PERCENTAGE) center.x /= 100; center.y = rg->cy.value; if (rg->cy.type==SVG_NUMBER_PERCENTAGE) center.y /= 100; txh->compositor->r2d->stencil_set_gradient_mode(txh->hwtx, (GF_GradientMode) rg->spreadMethod); focal.x = rg->fx.value; if (rg->fx.type==SVG_NUMBER_PERCENTAGE) focal.x /= 100; focal.y = rg->fy.value; if (rg->fy.type==SVG_NUMBER_PERCENTAGE) focal.y /= 100; if (rg->gradientUnits==SVG_GRADIENTUNITS_OBJECT) { /*move to local coord system - cf SVG spec*/ gf_mx2d_add_scale(mat, bounds->width, bounds->height); gf_mx2d_add_translation(mat, bounds->x, bounds->y - bounds->height); } else if ((rg->fx.value==rg->fy.value) && (rg->fx.value==FIX_ONE/2)) { focal.x = center.x; focal.y = center.y; } txh->compositor->r2d->stencil_set_radial_gradient(txh->hwtx, center.x, center.y, focal.x, focal.y, radius, radius);}void svg_sani_init_radialGradient(Render2D *sr, GF_Node *node){ SVG_SANI_GradientStack *st; GF_SAFEALLOC(st, SVG_SANI_GradientStack); gf_sr_texture_setup(&st->txh, sr->compositor, node); st->txh.update_texture_fcnt = svg_sani_UpdateRadialGradient; st->txh.compute_gradient_matrix = svg_sani_rG_ComputeMatrix; gf_node_set_private(node, st); gf_node_set_callback_function(node, svg_sani_render_PaintServer);}void svg_sani_init_solidColor(Render2D *sr, GF_Node *node){ gf_node_set_callback_function(node, svg_sani_render_PaintServer);}void svg_sani_init_stop(Render2D *sr, GF_Node *node){ gf_node_set_callback_function(node, svg_sani_render_PaintServer);}GF_TextureHandler *svg_sani_gradient_get_texture(GF_Node *node){ SVG_SANI_Element *g = (SVG_SANI_Element *)node; SVG_SANI_GradientStack *st; if (g->xlink->href.target) g = g->xlink->href.target; st = (SVG_SANI_GradientStack*) gf_node_get_private((GF_Node *)g); return st->nb_col ? &st->txh : NULL;}void svg_sani_render_base(GF_Node *node, RenderEffect2D *eff){ gf_svg_sani_apply_animations(node); eff->svg_flags |= gf_node_dirty_get(node);}void r2d_render_svg_sani_use(GF_Node *node, GF_Node *sub_root, void *rs){ GF_Matrix2D backup_matrix; GF_Matrix2D translate; GF_Node *prev_use; SVG_SANI_useElement *use = (SVG_SANI_useElement *)node; RenderEffect2D *eff = (RenderEffect2D *)rs; svg_sani_render_base(node, eff); gf_mx2d_init(translate); translate.m[2] = use->x.value; translate.m[5] = use->y.value; if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) { gf_svg_sani_apply_local_transformation(eff, node, &backup_matrix); if (use->display != SVG_DISPLAY_NONE) { gf_node_render((GF_Node*)use->xlink->href.target, eff); gf_mx2d_apply_rect(&translate, &eff->bounds); } gf_svg_sani_restore_parent_transformation(eff, &backup_matrix); return; } if (use->display == SVG_DISPLAY_NONE || use->visibility == SVG_VISIBILITY_HIDDEN) { return; } gf_svg_sani_apply_local_transformation(eff, node, &backup_matrix); gf_mx2d_pre_multiply(&eff->transform, &translate); prev_use = eff->parent_use; eff->parent_use = use->xlink->href.target; gf_node_render(use->xlink->href.target, eff); eff->parent_use = prev_use; gf_svg_sani_restore_parent_transformation(eff, &backup_matrix); }#endif /*GPAC_ENABLE_SVG_SANI*/#endif //GPAC_DISABLE_SVG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -