Skia图形库中的SkPath路径绘制详解
2025-07-06 06:46:10作者:仰钰奇
什么是SkPath?
SkPath是Skia图形库中用于描述二维路径的核心类,它由一系列连接的线段(Line)和曲线(Curve)组成,这些路径可以被描边(Stroke)或填充(Fill)。在Skia的绘制系统中,SkPath是实现复杂图形绘制的基础构建块。
SkPath的基本组成
轮廓(Contour)
每个SkPath由一个或多个轮廓(Contour)组成,每个轮廓又由一系列连接的线段和曲线构成:
- 轮廓总是以
kMove_Verb
动词开始 - 每个新的
kMove_Verb
都会开始一个新的轮廓 - 轮廓可以是开放的或闭合的
路径元素
路径中的每个元素都由三部分描述:
- 动词(Verb):描述元素类型(移动、直线、二次曲线等)
- 点(Points):定义元素几何形状的坐标点
- 权重(Weight):仅圆锥曲线需要,定义曲线的弯曲程度
SkPath的常见组件
虽然SkPath底层由基本元素组成,但它也提供了高级组件简化常见图形的创建:
- 直线段(Line)
- 圆弧(Arc)
- 矩形(Rect)
- 圆角矩形(Round_Rect)
- 圆形(Circle)
- 椭圆(Oval)
这些组件在添加到路径后可能会失去其原始身份,但SkPath提供了方法检测路径是否描述特定形状。
填充类型(Fill Type)
SkPath的填充类型决定了重叠轮廓如何形成填充或孔洞,以及哪些区域被视为内部:
- 非零环绕规则(Non-Zero)
- 奇偶规则(Even-Odd)
- 反转非零(Inverse Non-Zero)
- 反转奇偶(Inverse Even-Odd)
路径使用示例
基本路径绘制
// 创建一个包含三个轮廓的路径:
// 1. 直线(仅描边)
// 2. 圆形(描边和填充)
// 3. 二次曲线(描边和填充,但不闭合)
SkPath path;
path.moveTo(20, 20);
path.lineTo(100, 20); // 直线轮廓
path.addCircle(150, 50, 30); // 圆形轮廓
path.moveTo(200, 50);
path.quadTo(220, 80, 240, 50); // 二次曲线轮廓
开放与闭合轮廓
// 开放轮廓和闭合轮廓的对比
SkPath path;
path.moveTo(20, 20);
path.lineTo(100, 20);
path.lineTo(60, 60);
// 不调用close(),轮廓保持开放
path.moveTo(120, 20);
path.lineTo(200, 20);
path.lineTo(160, 60);
path.close(); // 闭合轮廓
路径的高级特性
零长度轮廓
即使轮廓的长度为零(所有点重合),根据描边端帽(Stroke Cap)的设置,仍然可能产生可见绘制效果:
SkPath path;
path.moveTo(50, 50);
path.lineTo(50, 50); // 零长度线段
// 设置圆形端帽,零长度线段会显示为点
paint.setStrokeCap(SkPaint::kRound_Cap);
路径的高效复制
SkPath实现了写时复制(Copy-On-Write)优化:
- 路径复制时不立即复制内容
- 只有在修改时才会创建副本
- 减少内存使用并提高性能
实际应用建议
- 重用路径对象:避免频繁创建和销毁路径,尽量重用现有对象
- 合理使用闭合:需要形成封闭区域时记得调用close()
- 注意填充类型:根据需求选择合适的填充规则
- 利用高级组件:优先使用addCircle等高级方法而非手动构建
- 性能优化:复杂路径考虑使用PathEffect进行优化
通过掌握SkPath的这些特性和使用技巧,开发者可以在Skia中高效地实现各种复杂的二维图形绘制需求。