TGFX - 腾讯开源的轻量级 2D 渲染引擎

TGFX - 腾讯开源的轻量级 2D 渲染引擎

  • 首页
  • 下载
  • 文档
  • 案例
  • CN
  • GitHub
  • 论坛交流
  • Languages iconCN
    • EN

›绘图基础

快速开始

  • TGFX 简介
  • 平台与后端支持
  • 环境准备与编译
  • Hello2D 示例

API 参考与概述

    绘图基础

    • Canvas Overview
    • Paint Overview
    • Path Overview
    • BlendMode Overview
    • Picture 录制与回放

    几何与变换

    • 几何与变换

    图像与像素

    • Image
    • Bitmap 与像素操作
    • 图像编解码
    • 视频与外部纹理

    文本渲染

    • 文本与字体

    着色与效果

    • 着色与效果

    图层系统

    • 图层系统

    进阶主题

    • 自定义 Shader
    • 色彩管理

架构设计

  • 渲染管线
  • GPU 硬件抽象层
  • 图层渲染系统
  • 缓存系统
  • 文字图集渲染
  • GPU Hairline 极细描边
  • 广色域渲染
  • SIMD 加速

API 文档

  • API 文档

Path Overview

Path 是 2D 矢量图形的基础构建工具。它包含了几何体(Geometry)的轮廓信息,可能为空,也可能由一组描述线条、曲线的曲线命令(Verbs)和控制点(Points)组成。在路径的构建中,tgfx 支持直线(Line)、二次贝塞尔曲线(Quad)、三次贝塞尔曲线(Cubic)以及圆锥曲线(Conic)等多种线型。

同时,Path 本身携带填充规则(Fill Type)属性,支持 Winding(非零环绕规则)、EvenOdd(奇偶规则)及其相应的 Inverse(反转)模式,这决定了在路径发生重叠或自交时,哪些区域被判定为“内部”。

通过调用 Canvas 的 drawPath() 等绘制方法,并结合 Paint 设定的填充(Fill)或描边(Stroke)样式,可以将构建好的 Path 渲染出任意复杂的二维图形。


1. 路径构建 (Path Construction)

Path 由一组连续的曲线命令(PathVerb)和控制点构成,形成一个或多个轮廓(Contour)。每一次 moveTo 都会开启一个新的轮廓,而后续的线条和曲线命令会将新的坐标点连接到当前轮廓上。

核心构建方法

#include "tgfx/core/Path.h"
#include "tgfx/core/Point.h"

tgfx::Path path;

// 1. moveTo:将画笔移动到起点 (10, 10),开启新轮廓
path.moveTo(10.0f, 10.0f);

// 2. lineTo:从当前点连一条直线到 (50, 10)
path.lineTo(50.0f, 10.0f);

// 3. quadTo:添加二阶贝塞尔曲线,控制点 (100, 10),终点 (100, 50)
path.quadTo(100.0f, 10.0f, 100.0f, 50.0f);

// 4. cubicTo:添加三阶贝塞尔曲线,两个控制点,终点 (150, 100)
path.cubicTo(100.0f, 80.0f, 120.0f, 100.0f, 150.0f, 100.0f);

// 5. conicTo:添加圆锥曲线(带有权重 weight),权重为 1 等价于 quadTo
path.conicTo(180.0f, 100.0f, 180.0f, 150.0f, 0.707f); 

// 6. close:闭合当前轮廓(从当前点连一条直线回到起点)
path.close();

控制点图解

以下是五种路径构建命令的控制点原理图解:

![路径控制点图解](/img/docs-images/Path-Overview/path-verbs-control-points.png)
  • lineTo: 包含 1 个终点。
  • quadTo: 包含 1 个控制点、1 个终点。
  • cubicTo: 包含 2 个控制点、1 个终点。
  • conicTo: 包含 1 个控制点、1 个终点,外加一个 weight(权重参数,weight < 1 为椭圆弧,weight == 1 为抛物线且等价于二次贝塞尔曲线,weight > 1 为双曲线)。

2. 几何体快捷方法 (Geometry Shortcuts)

如果你需要绘制标准的几何图形,Path 提供了一系列 addXXX 快捷方法。

tgfx::Path path;

// 添加矩形 (Rect)
tgfx::Rect rect = tgfx::Rect::MakeXYWH(10, 10, 100, 50);
path.addRect(rect);

// 添加圆角矩形 (RoundRect)
// radiusX 和 radiusY 控制圆角大小
path.addRoundRect(rect, 10.0f, 10.0f);

// 添加椭圆 (Oval)。快捷技巧:传入一个正方形的 Rect 即可生成完美圆形。
path.addOval(rect);

// 添加椭圆弧段 (Arc)
// startAngle 为起始角度(0度在X轴正方向),sweepAngle 为扫过的角度(正数为顺时针)
path.addArc(rect, 0.0f, 90.0f);

// 追加其他路径
tgfx::Path anotherPath;
anotherPath.addRect(tgfx::Rect::MakeWH(50, 50));
path.addPath(anotherPath); // 默认使用 Append 模式将顶点数据追加进来

3. 填充规则 (Fill Rules)

PathFillType 决定了当路径存在自交,或者包含了多个相交的子轮廓时,哪些区域属于“内部”(被填充),哪些区域属于“外部”(被掏空)。

// 默认的填充规则是 Winding
tgfx::PathFillType type = path.getFillType();

// 更改填充规则为 EvenOdd
path.setFillType(tgfx::PathFillType::EvenOdd);

1. Winding (非零环绕规则)

Winding 填充规则效果

2. EvenOdd (奇偶规则)

EvenOdd 填充规则效果

3. Inverse (反转填充)

Inverse 填充规则效果

  • Winding (非零环绕数规则):如果画一条从该区域指向无穷远处的射线,顺时针穿过射线加1,逆时针穿过射线减1。如果最终环绕数为非零值,则该区域被填充。
  • EvenOdd (奇偶规则):如果从该区域指向无穷远处的射线穿过路径的次数为奇数,则该区域被填充。这通常会在路径自交的地方产生“镂空”效果。
  • InverseWinding:Winding 的反转结果(填充外部区域)。
  • InverseEvenOdd:EvenOdd 的反转结果。

4. 路径变换与布尔运算 (Transform & Boolean Operations)

路径变换

通过 transform 方法,可以对路径的所有顶点进行矩阵变换。这会直接改变 Path 内部的数据。

#include "tgfx/core/Matrix.h"

tgfx::Path path;
path.addRect(tgfx::Rect::MakeWH(100, 100));

// 创建一个平移并缩放的矩阵
tgfx::Matrix matrix;
matrix.postTranslate(50.0f, 50.0f);
matrix.postScale(2.0f, 2.0f);

// 对当前路径应用矩阵变换
path.transform(matrix);

// 注意:如果想合并一条经过变换的路径,可以先将源路径 transform,再调用 addPath
tgfx::Path srcPath;
srcPath.addOval(tgfx::Rect::MakeWH(50, 50));
srcPath.transform(matrix);
path.addPath(srcPath, tgfx::PathOp::Append);

布尔运算

addPath 提供了一个强大的可选参数 PathOp,可以对两条路径执行复杂的布尔运算,生成新的联合路径(内部会自动处理多边形切割和交叉点合并)。

![布尔运算效果图](/img/docs-images/Path-Overview/path-boolean-operations.png)
tgfx::Path circlePath;
circlePath.addOval(tgfx::Rect::MakeXYWH(0, 0, 100, 100));

tgfx::Path rectPath;
rectPath.addRect(tgfx::Rect::MakeXYWH(50, 50, 100, 100));

// 1. Union:合并两个图形,去除内部重叠线段
circlePath.addPath(rectPath, tgfx::PathOp::Union);

// 2. Intersect:仅保留两个图形相交的部分
circlePath.addPath(rectPath, tgfx::PathOp::Intersect);

// 3. Difference:从原路径中减去 rectPath 重叠的部分
circlePath.addPath(rectPath, tgfx::PathOp::Difference);

// 4. XOR:保留两图形总面积,但挖去相交的重叠部分
circlePath.addPath(rectPath, tgfx::PathOp::XOR);

5. 路径查询 (Path Queries)

Path 提供了一组状态查询方法,方便快速判定几何体特征,以便进行绘制优化或碰撞检测。

提示:底层几何特征判定机制大揭秘 不同的 isXXX 方法底层的判断机制存在根本差异,了解这点能避免很多隐蔽的 Bug:

  • isRect():基于顶点拓扑计算。无论是由 addRect 生成,还是手动用 4 条线段闭合拼接的矩形,只要数学上等价就会返回 true。
  • isOval() / isRRect():基于内部标记位判定。对任意曲线进行椭圆或圆角矩形的等效推断成本过高,所以只有通过 addOval() / addRoundRect() 等专门的快捷 API 构造的路径才会返回 true,手动使用贝塞尔曲线完美拼接出来的也是无法被识别的。
  • isLine():基于严格的指令树结构。并不是判断所有点是否共线,而是检查整个路径是否仅仅包含一个 moveTo 加一个 lineTo。就算你用三段共线的 lineTo 拼出一条线段,这里也会返回 false。
tgfx::Path path;

// 1. 获取包围盒:返回能包围路径所有控制点的最小矩形,常用于快速相交测试(视口剔除等)
tgfx::Rect bounds = path.getBounds();

// 2. 几何特征判定
bool isLine = path.isLine();      // 是否刚好只有一条连续的线段(仅含 1 个 moveTo 和 1 个 lineTo)
bool isRect = path.isRect();      // 是否等价于一个矩形(拓扑推断)
bool isOval = path.isOval();      // 是否是一个椭圆或圆(标记位推断)
bool isRRect = path.isRRect();    // 是否是一个圆角矩形(标记位推断)

// 3. 状态查询
bool empty = path.isEmpty();      // 路径内是否包含任何有效顶点

// 4. 点/矩形包含测试:判定给定的坐标是否落在路径所形成的填充区域内(支持复杂的 Winding/EvenOdd 计算)
bool containsPoint = path.contains(50.0f, 50.0f);
bool containsRect  = path.contains(tgfx::Rect::MakeXYWH(10, 10, 5, 5));
← Paint OverviewBlendMode Overview →
  • 1. 路径构建 (Path Construction)
    • 核心构建方法
    • 控制点图解
  • 2. 几何体快捷方法 (Geometry Shortcuts)
  • 3. 填充规则 (Fill Rules)
  • 4. 路径变换与布尔运算 (Transform & Boolean Operations)
    • 路径变换
    • 布尔运算
  • 5. 路径查询 (Path Queries)
公司地址:广东省深圳市南山区海天二路33号腾讯滨海大厦Copyright © 2018 - 2026 Tencent. All Rights Reserved.联系电话:0755-86013388隐私政策