Chapter 77 · SVG 引擎

Paint 节点获取

通过 ID 或名称获取 SVG 内部的 Paint 节点,实现运行时动态修改单个元素。

77

API 速查

函数说明
int xgeSvgPaintGetById(xge_svg pSvg, uint32_t iId, xge_svg_paint* ppPaint)按 ID 获取
int xgeSvgPaintGetByName(xge_svg pSvg, const char* sName, xge_svg_paint* ppPaint)按名称获取
int xgeSvgPaintGetPicture(xge_svg pSvg, xge_svg_paint* ppPaint)获取根 Paint
int xgeSvgPaintIdGet(xge_svg_paint pPaint, uint32_t* pId)获取节点 ID
int xgeSvgPaintNameGet(xge_svg_paint pPaint, const char** ppName)获取节点名称
int xgeSvgPaintTypeGet(xge_svg_paint pPaint, int* pType)获取节点类型
int xgeSvgPaintShapeGet(xge_svg_paint pPaint, xge_shape_ex* ppShape)获取关联 Shape
int xgeSvgPaintOwnerGet(xge_svg_paint pPaint, xge_svg* ppSvg)获取所属 SVG
int xgeSvgPaintParentGet(xge_svg_paint pPaint, xge_svg_paint* ppParent)获取父节点
int xgeSvgPaintChildGetCount(xge_svg_paint pPaint, int* pCount)子节点数量
int xgeSvgPaintChildGetAt(xge_svg_paint pPaint, int iIndex, xge_svg_paint* ppChild)按索引获取子节点

编译本章示例

gcc -O2 -I. -o ch77.exe ch77_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch77.exe

示例:动态修改 SVG 元素

xge_svg icon = NULL;
xgeSvgCreate(&icon);
xgeSvgLoad(icon, "assets/character.svg");

// 按名称获取节点(SVG 中的 id 属性)
xge_svg_paint head = NULL;
xgeSvgPaintGetByName(icon, "head", &head);

// 获取关联的 ShapeEx 对象
xge_shape_ex headShape = NULL;
xgeSvgPaintShapeGet(head, &headShape);

// 修改填充颜色
xgeShapeExFillColor(headShape, 0xFFCC88FF);

// 遍历子节点
int count;
xgeSvgPaintChildGetCount(head, &count);
for (int i = 0; i < count; i++) {
    xge_svg_paint child;
    xgeSvgPaintChildGetAt(head, i, &child);
}

完整代码

将以下代码保存为 ch77_main.c,编译后运行即可看到按名称获取 SVG 节点并动态换色效果:

#include "xge.h"

static xge_svg g_svg = NULL;
static int g_iFrame = 0;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    g_iFrame++;

    // 每 60 帧换色
    if (g_iFrame % 60 == 0) {
        xge_svg_paint part = NULL;
        xgeSvgPaintGetByName(g_svg, "body", &part);
        if (part) {
            xge_shape_ex sh = NULL;
            xgeSvgPaintShapeGet(part, &sh);
            if (sh) {
                unsigned int cols[] = {
                    0xFF6B5EFF,0x4FD8C2FF,0xFFB454FF,0x7C6BFFFF};
                xgeShapeExFillColor(sh,
                    cols[(g_iFrame/60)%4]);
            }
        }
    }

    xge_rect_t dst = { 250, 100, 300, 400 };
    xgeSvgDraw(g_svg, dst, 0.25f);
    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch77 - Paint GetByName";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);

    xgeSvgCreate(&g_svg);
    xgeSvgLoad(g_svg, "assets/character.svg");

    xgeRun(onFrame, NULL);
    xgeSvgDestroy(g_svg);
    xgeUnit();
    return 0;
}

代码讲解

  • PaintGetByName:通过 SVG 元素的 id 属性获取 Paint 节点指针。
  • PaintShapeGet:获取节点关联的 ShapeEx 对象,可直接修改填充/描边等样式。
  • 动态换色:每 60 帧切换一次填充颜色,实现“换装”效果。
  • Paint 不拥有:Paint 指针由 SVG 管理,不需 Destroy,SVG 销毁时自动释放。

要点与陷阱

  • Paint 不拥有:Paint 指针由 SVG 管理,不需要 Destroy。
  • ShapeGet:返回的 ShapeEx 可直接修改样式,影响后续绘制。
  • GetByName:对应 SVG 元素的 id 属性(非 class)。
  • 缓存 SVG 注意:LoadCached 共享实例,修改 Paint 影响所有使用者。

进阶练习

  1. 实现 SVG 换装:按名称获取部件,切换不同填充。
  2. 构建 Paint 树形结构面板(类似 DOM 检查器)。
Paint 节点获取效果
图:Paint 节点获取渲染效果