📄 svg_base_da.c
字号:
compositor->user->EventProc(compositor->user->opaque, &evt); return; } evt.type = GF_EVENT_NAVIGATE; if (all_atts.xlink_href->type == XMLRI_STRING) { evt.navigate.to_url = all_atts.xlink_href->string; if (evt.navigate.to_url) { evt.navigate.param_count = 1; evt.navigate.parameters = (const char **) &all_atts.target; compositor->user->EventProc(compositor->user->opaque, &evt); } } else { u32 tag; if (!all_atts.xlink_href->target) { /* TODO: check if href can be resolved */ return; } tag = gf_node_get_tag((GF_Node *)all_atts.xlink_href->target); if (tag == TAG_SVG_set || tag == TAG_SVG_animate || tag == TAG_SVG_animateColor || tag == TAG_SVG_animateTransform || tag == TAG_SVG_animateMotion || tag == TAG_SVG_discard) {#if 0 u32 i, count, found; SVGTimedAnimBaseElement *set = (SVGTimedAnimBaseElement*)all_atts.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->timingp->begin); for (i=0; i<count; i++) { SMIL_Time *first = (SMIL_Time *)gf_list_get(*set->timingp->begin, i); /*remove past instanciations*/ if ((first->type==GF_SMIL_TIME_EVENT_RESOLVED) && (first->clock < begin->clock)) { gf_list_rem(*set->timingp->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->timingp->begin, begin, i); found = 1; break; } } if (!found) gf_list_add(*set->timingp->begin, begin); gf_node_changed((GF_Node *)all_atts.xlink_href->target, NULL);#endif gf_smil_timing_insert_clock(all_atts.xlink_href->target, 0, gf_node_get_scene_time((GF_Node *)handler) ); } } return;}void svg_init_a(Render2D *sr, GF_Node *node){ SVG_handlerElement *handler; gf_node_set_callback_function(node, svg_render_a); /*listener for onClick event*/ handler = gf_dom_listener_build(node, GF_EVENT_CLICK, 0, NULL); /*and overwrite handler*/ handler->handle_event = svg_a_handle_event; 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_a_handle_event; gf_node_set_private((GF_Node *)handler, sr->compositor); /*listener for mousemove event*/ handler = gf_dom_listener_build(node, GF_EVENT_MOUSEOVER, 0, NULL); /*and overwrite handler*/ handler->handle_event = svg_a_handle_event; gf_node_set_private((GF_Node *)handler, sr->compositor);}/* TODO: FIX ME we actually ignore the given sub_root since it is only valid when animations have been performed, animations evaluation (Render_base) should be part of the core renderer */void r2d_render_svg_use(GF_Node *node, GF_Node *sub_root, void *rs){ GF_Matrix2D backup_matrix; GF_Matrix2D translate; GF_Node *prev_use; SVGPropertiesPointers backup_props; u32 backup_flags; RenderEffect2D *eff = (RenderEffect2D *)rs; SVGAllAttributes all_atts; gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); svg_render_base(node, &all_atts, eff, &backup_props, &backup_flags); 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); if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) { svg_apply_local_transformation(eff, &all_atts, &backup_matrix); if (!svg_is_display_off(eff->svg_props)) { if (all_atts.xlink_href) gf_node_render(all_atts.xlink_href->target, eff); gf_mx2d_apply_rect(&translate, &eff->bounds); } svg_restore_parent_transformation(eff, &backup_matrix); goto end; } if (svg_is_display_off(eff->svg_props) || (*(eff->svg_props->visibility) == SVG_VISIBILITY_HIDDEN)) { goto end; } svg_apply_local_transformation(eff, &all_atts, &backup_matrix); gf_mx2d_pre_multiply(&eff->transform, &translate); if (all_atts.xlink_href) { prev_use = eff->parent_use; eff->parent_use = node; gf_node_render(all_atts.xlink_href->target, eff); eff->parent_use = prev_use; } svg_restore_parent_transformation(eff, &backup_matrix); end: memcpy(eff->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); eff->svg_flags = backup_flags;}static void SVG_DestroyPaintServer(GF_Node *node){ SVG_GradientStack *st = (SVG_GradientStack *) gf_node_get_private(node); if (st) { gf_sr_texture_destroy(&st->txh); if (st->cols) free(st->cols); if (st->keys) free(st->keys); free(st); }}static void SVG_UpdateGradient(SVG_GradientStack *st, GF_ChildNodeItem *children){ u32 count; Fixed alpha, max_offset; SVGAllAttributes all_atts; 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; GF_Node *stop = children->node; children = children->next; if (gf_node_get_tag((GF_Node *)stop) != TAG_SVG_stop) continue; gf_svg_flatten_attributes((SVG_Element*)stop, &all_atts); alpha = FIX_ONE; if (all_atts.stop_opacity && (all_atts.stop_opacity->type==SVG_NUMBER_VALUE) ) alpha = all_atts.stop_opacity->value; if (all_atts.stop_color) st->cols[st->nb_col] = GF_COL_ARGB_FIXED(alpha, all_atts.stop_color->color.red, all_atts.stop_color->color.green, all_atts.stop_color->color.blue); if (all_atts.offset) { key = all_atts.offset->value; if (all_atts.offset->type==SVG_NUMBER_PERCENTAGE) key/=100; } else { key=0; } 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_Render_PaintServer(GF_Node *node, void *rs, Bool is_destroy){ SVGPropertiesPointers backup_props; SVGAllAttributes all_atts; u32 backup_flags; u32 styling_size = sizeof(SVGPropertiesPointers); SVG_Element *elt = (SVG_Element *)node; RenderEffect2D *eff = (RenderEffect2D *) rs; if (is_destroy) { SVG_DestroyPaintServer(node); return; } gf_svg_flatten_attributes(elt, &all_atts); svg_render_base(node, &all_atts, eff, &backup_props, &backup_flags); if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) { return; } else { svg_render_node_list(elt->children, eff); } memcpy(eff->svg_props, &backup_props, styling_size); eff->svg_flags = backup_flags;}/* linear gradient */static void SVG_UpdateLinearGradient(GF_TextureHandler *txh){ SVG_Element *lg = (SVG_Element *) txh->owner; SVG_GradientStack *st = (SVG_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_UpdateGradient(st, lg->children);}static void SVG_LG_ComputeMatrix(GF_TextureHandler *txh, GF_Rect *bounds, GF_Matrix2D *mat){ SFVec2f start, end; SVGAllAttributes all_atts; /*create gradient brush if needed*/ if (!txh->hwtx) return; gf_svg_flatten_attributes((SVG_Element*)txh->owner, &all_atts); if (all_atts.x1) { start.x = all_atts.x1->value; if (all_atts.x1->type==SVG_NUMBER_PERCENTAGE) start.x /= 100; } else { start.x = 0; } if (all_atts.y1) { start.y = all_atts.y1->value; if (all_atts.y1->type==SVG_NUMBER_PERCENTAGE) start.y /= 100; } else { start.y = 0; } if (all_atts.x2) { end.x = all_atts.x2->value; if (all_atts.x2->type==SVG_NUMBER_PERCENTAGE) end.x /= 100; } else { end.x = 1; } if (all_atts.y2) { end.y = all_atts.y2->value; if (all_atts.y2->type==SVG_NUMBER_PERCENTAGE) end.y /= 100; } else { end.y = 0; } txh->compositor->r2d->stencil_set_gradient_mode(txh->hwtx, (GF_GradientMode) all_atts.spreadMethod ? *(SVG_SpreadMethod*)all_atts.spreadMethod : 0); if (all_atts.gradientTransform) { gf_mx2d_copy(*mat, all_atts.gradientTransform->mat ); } else { gf_mx2d_init(*mat); } if (all_atts.gradientUnits && (*(SVG_GradientUnit*)all_atts.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_init_linearGradient(Render2D *sr, GF_Node *node){ SVG_GradientStack *st; GF_SAFEALLOC(st, SVG_GradientStack); gf_sr_texture_setup(&st->txh, sr->compositor, node); st->txh.update_texture_fcnt = SVG_UpdateLinearGradient; st->txh.compute_gradient_matrix = SVG_LG_ComputeMatrix; gf_node_set_private(node, st); gf_node_set_callback_function(node, SVG_Render_PaintServer);}/* radial gradient */static void SVG_UpdateRadialGradient(GF_TextureHandler *txh){ SVG_Element *rg = (SVG_Element *) txh->owner; SVG_GradientStack *st = (SVG_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_UpdateGradient(st, rg->children);}static void SVG_RG_ComputeMatrix(GF_TextureHandler *txh, GF_Rect *bounds, GF_Matrix2D *mat){ SFVec2f center, focal; Fixed radius; SVGAllAttributes all_atts; /*create gradient brush if needed*/ if (!txh->hwtx) return; gf_svg_flatten_attributes((SVG_Element*)txh->owner, &all_atts); if (all_atts.gradientTransform) gf_mx2d_copy(*mat, all_atts.gradientTransform->mat); else gf_mx2d_init(*mat); if (all_atts.r) { radius = all_atts.r->value; if (all_atts.r->type==SVG_NUMBER_PERCENTAGE) radius /= 100; } else { radius = FIX_ONE/2; } if (all_atts.cx) { center.x = all_atts.cx->value; if (all_atts.cx->type==SVG_NUMBER_PERCENTAGE) center.x /= 100; } else { center.x = FIX_ONE/2; } if (all_atts.cy) { center.y = all_atts.cy->value; if (all_atts.cy->type==SVG_NUMBER_PERCENTAGE) center.y /= 100; } else { center.y = FIX_ONE/2; } txh->compositor->r2d->stencil_set_gradient_mode(txh->hwtx, (GF_GradientMode) all_atts.spreadMethod ? *(SVG_SpreadMethod*)all_atts.spreadMethod : 0); if (all_atts.fx) { focal.x = all_atts.fx->value; if (all_atts.fx->type==SVG_NUMBER_PERCENTAGE) focal.x /= 100; } else { focal.x = FIX_ONE/2; } if (all_atts.fy) { focal.y = all_atts.fx->value; if (all_atts.fy->type==SVG_NUMBER_PERCENTAGE) focal.y /= 100; } else { focal.y = FIX_ONE/2; } if (all_atts.gradientUnits && (*(SVG_GradientUnit*)all_atts.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); } txh->compositor->r2d->stencil_set_radial_gradient(txh->hwtx, center.x, center.y, focal.x, focal.y, radius, radius);}void svg_init_radialGradient(Render2D *sr, GF_Node *node){ SVG_GradientStack *st; GF_SAFEALLOC(st, SVG_GradientStack); gf_sr_texture_setup(&st->txh, sr->compositor, node); st->txh.update_texture_fcnt = SVG_UpdateRadialGradient; st->txh.compute_gradient_matrix = SVG_RG_ComputeMatrix; gf_node_set_private(node, st); gf_node_set_callback_function(node, SVG_Render_PaintServer);}void svg_init_solidColor(Render2D *sr, GF_Node *node){ gf_node_set_callback_function(node, SVG_Render_PaintServer);}void svg_init_stop(Render2D *sr, GF_Node *node){ gf_node_set_callback_function(node, SVG_Render_PaintServer);}GF_TextureHandler *svg_gradient_get_texture(GF_Node *node){ GF_FieldInfo info; GF_Node *g = NULL; SVG_GradientStack *st; /*check gradient redirection ...*/ if (gf_svg_get_attribute_by_tag(node, TAG_SVG_ATT_xlink_href, 0, 0, &info)==GF_OK) { g = ((XMLRI*)info.far_ptr)->target; } if (!g) g = node; st = (SVG_GradientStack*) gf_node_get_private((GF_Node *)g); return st->nb_col ? &st->txh : NULL;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -