📄 svg_base_da.c
字号:
Fixed y = (all_atts.y ? all_atts.y->value : 0); Fixed width = (all_atts.width ? all_atts.width->value : 0); Fixed height = (all_atts.height ? all_atts.height->value : 0); drawable_reset_path(cs); if (rx || ry) { if (rx >= width/2) rx = width/2; if (ry >= height/2) ry = height/2; if (rx == 0) rx = ry; if (ry == 0) ry = rx; gf_path_add_move_to(cs->path, x+rx, y); gf_path_add_line_to(cs->path, x+width-rx, y); gf_path_add_quadratic_to(cs->path, x+width, y, x+width, y+ry); gf_path_add_line_to(cs->path, x+width, y+height-ry); gf_path_add_quadratic_to(cs->path, x+width, y+height, x+width-rx, y+height); gf_path_add_line_to(cs->path, x+rx, y+height); gf_path_add_quadratic_to(cs->path, x, y+height, x, y+height-ry); gf_path_add_line_to(cs->path, x, y+ry); gf_path_add_quadratic_to(cs->path, x, y, x+rx, y); gf_path_close(cs->path); } else { gf_path_add_move_to(cs->path, x, y); gf_path_add_line_to(cs->path, x+width, y); gf_path_add_line_to(cs->path, x+width, y+height); gf_path_add_line_to(cs->path, x, y+height); gf_path_close(cs->path); } gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY); cs->flags |= DRAWABLE_HAS_CHANGED; } svg_drawable_post_render(cs, &backup_props, &backup_flags, (RenderEffect2D *)rs, 1, 0, &all_atts);}void svg_init_rect(Render2D *sr, GF_Node *node){ drawable_stack_new(sr, node); gf_node_set_callback_function(node, svg_render_rect);}static void svg_render_circle(GF_Node *node, void *rs, Bool is_destroy){ SVGPropertiesPointers backup_props; u32 backup_flags; Drawable *cs = (Drawable *)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; SVGAllAttributes all_atts; if (is_destroy) { DestroyDrawableNode(node); return; } if (eff->traversing_mode==TRAVERSE_DRAW) { drawable_draw(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { drawable_pick(eff); return; } gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); svg_render_base(node, &all_atts, (RenderEffect2D *)rs, &backup_props, &backup_flags); /* 3) for a leaf node Recreates the path (i.e the shape) only if the node is dirty (has changed compared to the previous rendering phase) */ if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) { Fixed r = 2*(all_atts.r ? all_atts.r->value : 0); drawable_reset_path(cs); gf_path_add_ellipse(cs->path, (all_atts.cx ? all_atts.cx->value : 0), (all_atts.cy ? all_atts.cy->value : 0), r, r); gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY); cs->flags |= DRAWABLE_HAS_CHANGED; } svg_drawable_post_render(cs, &backup_props, &backup_flags, (RenderEffect2D *)rs, 1, 0, &all_atts);}void svg_init_circle(Render2D *sr, GF_Node *node){ drawable_stack_new(sr, node); gf_node_set_callback_function(node, svg_render_circle);}static void svg_render_ellipse(GF_Node *node, void *rs, Bool is_destroy){ SVGPropertiesPointers backup_props; u32 backup_flags; Drawable *cs = (Drawable *)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; SVGAllAttributes all_atts; if (is_destroy) { DestroyDrawableNode(node); return; } if (eff->traversing_mode==TRAVERSE_DRAW) { drawable_draw(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { drawable_pick(eff); return; } gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); svg_render_base(node, &all_atts, (RenderEffect2D *)rs, &backup_props, &backup_flags); /* 3) for a leaf node Recreates the path (i.e the shape) only if the node is dirty (has changed compared to the previous rendering phase) */ if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) { drawable_reset_path(cs); gf_path_add_ellipse(cs->path, (all_atts.cx ? all_atts.cx->value : 0), (all_atts.cy ? all_atts.cy->value : 0), (all_atts.rx ? 2*all_atts.rx->value : 0), (all_atts.ry ? 2*all_atts.ry->value : 0)); gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY); cs->flags |= DRAWABLE_HAS_CHANGED; } svg_drawable_post_render(cs, &backup_props, &backup_flags, (RenderEffect2D *)rs, 1, 0, &all_atts);}void svg_init_ellipse(Render2D *sr, GF_Node *node){ drawable_stack_new(sr, node); gf_node_set_callback_function(node, svg_render_ellipse);}static void svg_render_line(GF_Node *node, void *rs, Bool is_destroy){ SVGPropertiesPointers backup_props; u32 backup_flags; Drawable *cs = (Drawable *)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; SVGAllAttributes all_atts; if (is_destroy) { DestroyDrawableNode(node); return; } if (eff->traversing_mode==TRAVERSE_DRAW) { drawable_draw(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { drawable_pick(eff); return; } gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); svg_render_base(node, &all_atts, (RenderEffect2D *)rs, &backup_props, &backup_flags); /* 3) for a leaf node Recreates the path (i.e the shape) only if the node is dirty (has changed compared to the previous rendering phase) */ if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) { drawable_reset_path(cs); gf_path_add_move_to(cs->path, (all_atts.x1 ? all_atts.x1->value : 0), (all_atts.y1 ? all_atts.y1->value : 0)); gf_path_add_line_to(cs->path, (all_atts.x2 ? all_atts.x2->value : 0), (all_atts.y2 ? all_atts.y2->value : 0)); gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY); cs->flags |= DRAWABLE_HAS_CHANGED; } svg_drawable_post_render(cs, &backup_props, &backup_flags, (RenderEffect2D *)rs, 1, 0, &all_atts);}void svg_init_line(Render2D *sr, GF_Node *node){ drawable_stack_new(sr, node); gf_node_set_callback_function(node, svg_render_line);}static void svg_render_polyline(GF_Node *node, void *rs, Bool is_destroy){ SVGPropertiesPointers backup_props; u32 backup_flags; Drawable *cs = (Drawable *)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; SVGAllAttributes all_atts; if (is_destroy) { DestroyDrawableNode(node); return; } if (eff->traversing_mode==TRAVERSE_DRAW) { drawable_draw(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { drawable_pick(eff); return; } gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); svg_render_base(node, &all_atts, (RenderEffect2D *)rs, &backup_props, &backup_flags); /* 3) for a leaf node Recreates the path (i.e the shape) only if the node is dirty (has changed compared to the previous rendering phase) */ if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) { u32 i, nbPoints; if (all_atts.points) nbPoints = gf_list_count(*all_atts.points); else nbPoints = 0; drawable_reset_path(cs); if (nbPoints) { SVG_Point *p = (SVG_Point *)gf_list_get(*all_atts.points, 0); gf_path_add_move_to(cs->path, p->x, p->y); for (i = 1; i < nbPoints; i++) { p = (SVG_Point *)gf_list_get(*all_atts.points, i); gf_path_add_line_to(cs->path, p->x, p->y); } } else { gf_path_add_move_to(cs->path, 0, 0); } gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY); cs->flags |= DRAWABLE_HAS_CHANGED; } svg_drawable_post_render(cs, &backup_props, &backup_flags, (RenderEffect2D *)rs, 1, 0, &all_atts);}void svg_init_polyline(Render2D *sr, GF_Node *node){ drawable_stack_new(sr, node); gf_node_set_callback_function(node, svg_render_polyline);}static void svg_render_polygon(GF_Node *node, void *rs, Bool is_destroy){ SVGPropertiesPointers backup_props; u32 backup_flags; Drawable *cs = (Drawable *)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; SVGAllAttributes all_atts; if (is_destroy) { DestroyDrawableNode(node); return; } if (eff->traversing_mode==TRAVERSE_DRAW) { drawable_draw(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { drawable_pick(eff); return; } gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); svg_render_base(node, &all_atts, (RenderEffect2D *)rs, &backup_props, &backup_flags); /* 3) for a leaf node Recreates the path (i.e the shape) only if the node is dirty (has changed compared to the previous rendering phase) */ if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) { u32 i, nbPoints; if (all_atts.points) nbPoints = gf_list_count(*all_atts.points); else nbPoints = 0; drawable_reset_path(cs); if (nbPoints) { SVG_Point *p = (SVG_Point *)gf_list_get(*all_atts.points, 0); gf_path_add_move_to(cs->path, p->x, p->y); for (i = 1; i < nbPoints; i++) { p = (SVG_Point *)gf_list_get(*all_atts.points, i); gf_path_add_line_to(cs->path, p->x, p->y); } } else { gf_path_add_move_to(cs->path, 0, 0); } /*according to the spec, the polygon path is closed*/ gf_path_close(cs->path); gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY); cs->flags |= DRAWABLE_HAS_CHANGED; } svg_drawable_post_render(cs, &backup_props, &backup_flags, (RenderEffect2D *)rs, 1, 0, &all_atts);}void svg_init_polygon(Render2D *sr, GF_Node *node){ drawable_stack_new(sr, node); gf_node_set_callback_function(node, svg_render_polygon);}static void svg_destroy_path(GF_Node *node){ Drawable *dr = gf_node_get_private(node);#if USE_GF_PATH /* The path is the same as the one in the SVG node, don't delete it here */ dr->path = NULL;#endif drawable_del(dr);}static void svg_render_path(GF_Node *node, void *rs, Bool is_destroy){ SVGPropertiesPointers backup_props; u32 backup_flags; Drawable *cs = (Drawable *)gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; SVGAllAttributes all_atts; if (is_destroy) { svg_destroy_path(node); return; } if (eff->traversing_mode==TRAVERSE_DRAW) { drawable_draw(eff); return; } else if (eff->traversing_mode==TRAVERSE_PICK) { drawable_pick(eff); return; } gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); svg_render_base(node, &all_atts, (RenderEffect2D *)rs, &backup_props, &backup_flags); if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) { #if USE_GF_PATH drawable_reset_path_outline(cs); cs->path = all_atts.d;#else drawable_reset_path(cs); gf_svg_path_build(cs->path, all_atts.d->commands, all_atts.d->points);#endif if (*(eff->svg_props->fill_rule)==GF_PATH_FILL_ZERO_NONZERO) cs->path->flags |= GF_PATH_FILL_ZERO_NONZERO; gf_node_dirty_clear(node, 0); cs->flags |= DRAWABLE_HAS_CHANGED; } svg_drawable_post_render(cs, &backup_props, &backup_flags, eff, 0, (all_atts.pathLength && all_atts.pathLength->type==SVG_NUMBER_VALUE) ? all_atts.pathLength->value : 0, &all_atts);}void svg_init_path(Render2D *sr, GF_Node *node){ Drawable *dr = drawable_stack_new(sr, node); gf_path_del(dr->path); dr->path = NULL; gf_node_set_callback_function(node, svg_render_path);}static void svg_render_a(GF_Node *node, void *rs, Bool is_destroy){ GF_Matrix2D backup_matrix; SVGPropertiesPointers backup_props; u32 styling_size = sizeof(SVGPropertiesPointers); u32 backup_flags; RenderEffect2D *eff = (RenderEffect2D *)rs; SVGAllAttributes all_atts; if (is_destroy) { svg_check_focus_upon_destroy(node); return; } gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); svg_render_base(node, &all_atts, eff, &backup_props, &backup_flags); if (svg_is_display_off(eff->svg_props)) { u32 prev_flags = eff->trav_flags; eff->trav_flags |= GF_SR_TRAV_SWITCHED_OFF; svg_render_node_list(((SVG_Element *)node)->children, eff); eff->trav_flags = prev_flags; memcpy(eff->svg_props, &backup_props, styling_size); eff->svg_flags = backup_flags; return; } svg_apply_local_transformation(eff, &all_atts, &backup_matrix); if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) { svg_get_nodes_bounds(node, ((SVG_Element *)node)->children, eff); } else { svg_render_node_list(((SVG_Element *)node)->children, eff); } svg_restore_parent_transformation(eff, &backup_matrix); memcpy(eff->svg_props, &backup_props, styling_size); eff->svg_flags = backup_flags;}static void svg_a_handle_event(GF_Node *handler, GF_DOM_Event *event){ GF_Renderer *compositor; GF_Event evt; SVG_Element *a; SVGAllAttributes all_atts; assert(gf_node_get_tag(event->currentTarget)==TAG_SVG_a); a = (SVG_Element *) event->currentTarget; gf_svg_flatten_attributes(a, &all_atts); compositor = (GF_Renderer *)gf_node_get_private((GF_Node *)handler); if (!compositor->user->EventProc) return; if (!all_atts.xlink_href) return; if (event->type==GF_EVENT_MOUSEOVER) { evt.type = GF_EVENT_NAVIGATE_INFO; if (all_atts.xlink_title) evt.navigate.to_url = *all_atts.xlink_title; else if (all_atts.xlink_href->string) evt.navigate.to_url = all_atts.xlink_href->string; else { evt.navigate.to_url = gf_node_get_name(all_atts.xlink_href->target); if (!evt.navigate.to_url) evt.navigate.to_url = "document internal link"; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -