Chapter 75 · SVG 引擎

SVG 绘制

SvgDraw 将 SVG 渲染到指定目标矩形,支持像素对齐模式和命中测试。

75

API 速查

函数说明
int xgeSvgDraw(xge_svg pSvg, xge_rect_t tDst, float fTolerance)绘制到目标矩形
int xgeSvgDrawPx(xge_svg pSvg, xge_rect_t tDst, float fTolerance)像素对齐绘制
int xgeSvgContainsPoint(xge_svg pSvg, float fX, float fY, float fTolerance, int* pContains)点命中测试
int xgeSvgDrawContainsPoint(xge_svg pSvg, xge_rect_t tDst, float fX, float fY, float fTolerance, int* pContains)绘制区域命中测试
int xgeSvgGetBounds(xge_svg pSvg, float fTolerance, xge_rect_t* pBounds)获取包围盒
int xgeSvgGetDrawBounds(xge_svg pSvg, xge_rect_t tDst, float fTolerance, xge_rect_t* pBounds)绘制后包围盒

编译本章示例

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

示例:绘制 SVG 图标

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

// 绘制到指定矩形区域
xge_rect_t dst = { 50, 50, 200, 100 };
xgeSvgDraw(logo, dst, 0.25f);

// 像素对齐(适合 UI 图标,避免模糊)
xgeSvgDrawPx(logo, dst, 0.25f);

// 点击检测
int bHit;
xgeSvgDrawContainsPoint(logo, dst,
    mouseX, mouseY, 0.25f, &bHit);
if (bHit) {
    // 用户点击了 logo
}

完整代码

将以下代码保存为 ch75_main.c,编译后运行即可看到 SVG 绘制 + 鼠标点击检测效果:

#include "xge.h"

static xge_svg g_logo = NULL;
static int g_bHover = 0;

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

    xge_rect_t dst = { 300, 200, 200, 200 };

    // 鼠标悬停检测
    float mx, my;
    xgeMouseGet(&mx, &my);
    xgeSvgDrawContainsPoint(g_logo, dst,
        (float)mx, (float)my, 0.25f, &g_bHover);

    // 绘制 SVG(像素对齐)
    xgeSvgDrawPx(g_logo, dst, 0.25f);

    // 悬停时绘制高亮边框
    if (g_bHover) {
        xge_shape_ex hl = NULL;
        xgeShapeExCreate(&hl);
        xgeShapeExAppendRect(hl,
            dst.x-4, dst.y-4, dst.w+8, dst.h+8, 8,8, 1)
        xgeShapeExStrokeColor(hl, 0x4FD8C2FF);
        xgeShapeExStrokeWidth(hl, 2.0f);
        xgeShapeExDraw(hl, 0.25f);
        xgeShapeExDestroy(hl);
    }
    return XGE_OK;
}

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

    xgeSvgCreate(&g_logo);
    xgeSvgLoad(g_logo, "assets/logo.svg");

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

代码讲解

  • SvgDrawPx:像素对齐绘制,避免小图标边缘模糊。
  • DrawContainsPoint:考虑 tDst 坐标映射的命中测试,比 ContainsPoint 更实用。
  • 悬停反馈:鼠标在 SVG 区域内时绘制高亮边框,模拟按钮悬停效果。
  • tDst:目标矩形 {x,y,w,h},SVG 自动缩放到此区域。

要点与陷阱

  • tDst:目标矩形 {x, y, w, h},SVG 会缩放到此区域。
  • DrawPx:对齐像素网格,小尺寸图标更清晰。
  • fTolerance:曲线精度,推荐 0.25。
  • DrawContainsPoint:考虑了 tDst 的坐标映射,比 ContainsPoint 更实用。

进阶练习

  1. 实现 SVG 按钮:DrawContainsPoint 检测点击 + 悬停变色。
  2. 绘制 SVG 到不同大小区域,观察 preserveAspectRatio 效果。
SVG 绘制效果
图:SVG 绘制渲染效果