Chapter 40 · ShapeEx 路径构建

SVG path data 互转

直接导入 SVG path 字符串(如 "M10 80 C40 10, 65 10, 95 80"),或将 ShapeEx 路径导出为 SVG path data。

40

概念

  • AppendSvgPath:解析标准 SVG path data 字符串,追加到 ShapeEx 路径中。
  • GetSvgPathData:将当前路径序列化为 SVG path data 字符串。
  • GetPath:获取内部命令/点数组(二进制格式,用于自定义序列化)。
  • AppendPath:从内部命令/点数组恢复路径。

API 速查

函数说明
int xgeShapeExAppendSvgPath(xge_shape_ex pShape, const char* sPath)导入 SVG path data
int xgeShapeExGetSvgPathData(xge_shape_ex pShape, char* sBuffer, int iBufferSize, int* pRequiredSize)导出 SVG path data
int xgeShapeExGetPath(xge_shape_ex pShape, const uint8_t** ppCommands, int* pCommandCount, const xge_vec2_t** ppPoints, int* pPointCount)获取内部路径数据
int xgeShapeExAppendPath(xge_shape_ex pShape, const uint8_t* pCommands, int iCommandCount, const xge_vec2_t* pPoints, int iPointCount)从内部数据恢复路径

编译本章示例

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

示例 1:导入 SVG 路径

xge_shape_ex icon = NULL;
xgeShapeExCreate(&icon);

// 一个 SVG 心形路径
const char* svg =
    "M400 480 C100 300 150 100 400 200 "
    "C650 100 700 300 400 480 Z";

xgeShapeExAppendSvgPath(icon, svg);
xgeShapeExFillColor(icon, 0xFF6B5EFF);
xgeShapeExDraw(icon, 0.25f);

示例 2:导出 SVG 路径

// 构建一个路径
xge_shape_ex shape = NULL;
xgeShapeExCreate(&shape);
xgeShapeExAppendCircle(shape, 200, 200, 100, 100, 1);

// 导出为 SVG path data
char buffer[1024];
int required = 0;
xgeShapeExGetSvgPathData(shape, buffer, sizeof(buffer), &required);
xgeLogWrite(XGE_LOG_INFO, "SVG: %s", buffer);

示例 3:内部路径数据序列化

// 获取内部命令和点数组
const uint8_t* cmds; int cmdCount;
const xge_vec2_t* pts; int ptCount;
xgeShapeExGetPath(shape, &cmds, &cmdCount, &pts, &ptCount);

// 保存到文件 / 网络传输...

// 恢复到新对象
xge_shape_ex restored = NULL;
xgeShapeExCreate(&restored);
xgeShapeExAppendPath(restored, cmds, cmdCount, pts, ptCount);

完整代码

将以下代码保存为 ch40_main.c,编译后运行即可看到 SVG path 导入与导出效果:

#include "xge.h"

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

    // 导入 SVG 心形路径
    xge_shape_ex icon = NULL;
    xgeShapeExCreate(&icon);
    const char* svg =
        "M400 480 C100 300 150 100 400 200 "
        "C650 100 700 300 400 480 Z";
    xgeShapeExAppendSvgPath(icon, svg);
    xgeShapeExFillColor(icon, 0xFF6B5EFF);
    xgeShapeExDraw(icon, 0.25f);

    // 导出为 SVG path data
    char buffer[1024];
    int required = 0;
    xgeShapeExGetSvgPathData(icon, buffer, sizeof(buffer), &required);

    xgeShapeExDestroy(icon);

    // 用 API 构建圆形并导出
    xge_shape_ex circle = NULL;
    xgeShapeExCreate(&circle);
    xgeShapeExAppendCircle(circle, 400, 500, 60, 60, 1);
    xgeShapeExFillColor(circle, 0x4FD8C2FF);
    xgeShapeExDraw(circle, 0.25f);
    xgeShapeExDestroy(circle);

    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch40 - SVG Path";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);
    xgeRun(onFrame, NULL);
    xgeUnit();
    return 0;
}

代码讲解

  • AppendSvgPath:直接解析 SVG path data 字符串,支持 M/L/C/Q/A/Z 等全部命令。
  • GetSvgPathData:将当前路径导出为 SVG 字符串,可用于序列化或与其他工具交换。
  • GetPath/AppendPath:内部二进制格式,适合文件保存/网络传输。
  • 追加语义:AppendSvgPath 不会清除现有路径,是追加到末尾。

要点与陷阱

  • 支持的 SVG 命令:M/m, L/l, H/h, V/v, C/c, S/s, Q/q, T/t, A/a, Z/z(大小写 = 绝对/相对)。
  • GetSvgPathData 缓冲区:若 buffer 太小,*pRequiredSize 返回所需大小,可二次调用。
  • GetPath 返回内部指针:不要 free,生命周期跟随 ShapeEx 对象。
  • AppendSvgPath 追加:不会清除现有路径,是追加到末尾。
  • 坐标系:SVG path 使用 Y 向下坐标,与 XGE 默认一致。

进阶练习

  1. 从 Inkscape/Illustrator 导出一个图标的 SVG path,用 AppendSvgPath 渲染。
  2. 实现路径"录制/回放":用 GetPath 保存,AppendPath 恢复。
  3. 写一个 SVG path 查看器:输入字符串 → 实时渲染 + 显示包围盒。
SVG path data 互转效果
图:SVG path data 互转渲染效果