SkiaSharp 1.55.0 API 变更解析:SkiaSharp.dll 从 1.54.0 到 1.55.0 的破坏性改动与新 API 详解
SkiaSharp 1.55.0 API 变更解析:SkiaSharp.dll 从 1.54.0 到 1.55.0 的破坏性改动与新 API 详解
本篇基于 SkiaSharp 官方发布的 1.55.0 版本 API diff 文档(documentation/docfx/releases/1.55.0/SkiaSharp/SkiaSharp.md)逐条解析 SkiaSharp.dll 相对 1.54.0 的全部接口变化:哪些签名属于破坏性改动、新增的 SKBlendMode/SKLattice/SKPathMeasure/SKRegion 等类型如何使用,并结合同一仓库中 1.55.0 发布说明 和当前 binding/SkiaSharp/ 目录下的实现源码,给出可落地的迁移对照与升级检查清单。读完本篇后,你将能够:判断自己的代码是否受 1.55.0 破坏性变更影响、按类型逐项完成 API 替换,并理解新版 API(如颜色混合模式、lattice 纹理绘制、路径测量)的设计意图。
1. 版本背景:1.55.0 是一次"API 大扫除"
assembly 版本变更为 1.55.0.0(对比基线 1.54.0.0),该版本于 2016 年 11 月 10 日发布,官方将其定性为 API cleanup(API 清理),主题包括:
- 裁剪公开 API 的可选参数:
SKCanvas、GRContext、SKPath上的多个方法去掉了默认参数值,使重载决议更确定、ABI 更稳定; SKCodecOptions.Subset变为可空类型:从SKRectI改为SKRectI?,更准确地表达"子集是可选的";- 移除一批遗留辅助方法:
SKCodec、SKDocument、SKMatrix上的旧接口被替换或删除。
这一版本在发布索引 documentation/docfx/releases/1.55.0/index.md 中被标记为 ⚠️ breaking,同目录下的 SkiaSharp.breaking.md 则单独列出了 7 类"仅破坏性"变更(去掉默认值、Subset 变可空、HasSubset 失去 setter、删除 GetValidSubset/Close/MapRect 静态签名/SKPictureRecorder 原生句柄构造函数)。下面按"破坏性改动 → 逐类型变更 → 全新类型"的顺序完整展开 diff 文档中的每一项。
2. 破坏性改动详解(必须处理的 3 类)
2.1 公开 API 去掉了默认参数值
diff 文档与 1.55.0 发布说明 均指出:若干方法不再提供默认参数值,调用方必须显式传参或改用匹配的重载,这是一次 ABI 层面的变化,需要重新编译。涉及的方法:
// GRContext
public void Flush (GRContextFlushBits flagsBitfield--- = 0---)
// SKCanvas
public void ClipPath (SKPath path, SKRegionOperation operation--- = 1---, bool antialias = false)
public void ClipRect (SKRect rect, SKRegionOperation operation--- = 1---, bool antialias = false)
public void DrawColor (SKColor color, SKXferMode mode--- = 1---)
其中 --- = 值 --- 的标注表示"默认值被移除"。实际影响:
GRContext.Flush(GRContextFlushBits)之前可省略参数,之后必须显式传入标志位(或改用新的无参Flush(),见 3.1 节);SKCanvas.ClipRect/ClipPath的operation、DrawColor的mode都必须显式给出,例如canvas.ClipRect(rect, SKRegionOperation.Intersect, false);- 动机是避免 C# 可选参数与 P/Invoke 签名绑定的 ABI 漂移问题——默认值只存在于调用方编译期,去掉后接口签名跨版本稳定。
从当前仓库源码结构看,这一思路在后来的版本中被保留并进一步强化:SKCanvas.cs 中 ClipPath (SKPath path, SKClipOperation operation = SKClipOperation.Intersect, bool antialias = false) 的参数类型已从 SKRegionOperation 演进为 1.55.0 引入的 SKClipOperation,说明 1.55.0 的枚举替换是后续演进的基础。
2.2 SKCodecOptions.Subset 变为可空类型
public bool HasSubset { get; ---set;--- }
-public SKRectI Subset { get; set; }
+public SKRectI? Subset { get; set; }
两处破坏点:Subset 的读取类型从结构体 SKRectI 改为可空 SKRectI?(未设置子集时为 null 而不是 default(SKRectI));HasSubset 失去 setter,成为只读属性。配套的新增是构造函数 public SKCodecOptions (SKRectI subset),推荐用法改为:
// 迁移前(1.54.0)
var options = new SKCodecOptions();
options.Subset = new SKRectI (0, 0, 100, 100);
// 迁移后(1.55.0+)
var options = new SKCodecOptions (new SKRectI (0, 0, 100, 100));
// 或者保持不设置子集:options.Subset 为 null,options.HasSubset == false
配套地,SKCodec.GetValidSubset 的签名从 void 变为返回 bool(属于 2.3 节"方法替换"的一部分),以便判断子集信息是否有效。
2.3 遗留方法删除与签名替换
| 类型 | 被移除 | 替代 | 说明 |
|---|---|---|---|
SKCodec |
void GetValidSubset (ref SKRectI) |
bool GetValidSubset (ref SKRectI) |
当前 SKCodec.cs 中该方法保留 bool 返回值的签名,用于查询解码子集是否落在有效范围内 |
SKDocument |
bool Close () |
void Close () |
当前 SKDocument.cs 中 Close() 已为 void,关闭文档不再以返回值报告失败 |
SKMatrix |
static MapRect(...) |
实例方法 MapRect(...) |
矩阵变换改为实例风格:matrix.MapRect(ref other, out dest, ref source) |
SKPictureRecorder |
SKPictureRecorder (IntPtr handle, bool owns) |
无(改用托管构造函数) | 当前 SKPictureRecorder.cs 提供 RecordingCanvas 属性获取录制画布,原生句柄构造函数不再公开 |
此外 SKMatrix.MapXY (float, float) 被标记 [Obsolete] 并指向 MapPoint——注意它只是废弃而非删除,编译会产生警告:
// 迁移前
SKPoint p = matrix.MapXY (10, 20);
// 迁移后
SKPoint p = matrix.MapPoint (10, 20);
当前 SKMatrix.cs 中 MapPoint (SKPoint) 与 MapPoint (float, float) 两个重载均存在,且文档明确提示映射向量(vector)时请改用 MapVector,因为向量映射会忽略平移分量。
3. 逐类型变更详解
3.1 GRContext:无参 Flush() 与可选参数收紧
- 新增无参重载
public void Flush (),并标记<a href="https://link.gitcode.com/i/ebbe05877cc1a2822414a24d2f2b67fd" target="_blank">Obsolete ("Use Flush() instead.")]的Flush (GRContextFlushBits flagsBitfield)作为迁移桥;当前实现 [GRContext.cs 中即为public void Flush () => Flush (true);; - 带参
Flush (GRContextFlushBits flagsBitfield)去掉默认值= 0(见 2.1 节)。
日常绘制代码优先使用无参 Flush(),只有需要精细控制提交粒度(如与后台线程并发渲染时)才使用标志位版本。
3.2 GRContextOptions:5 个新增选项
public bool AllowPathMaskCaching { get; set; }
public static GRContextOptions Default { get; }
public bool DisableDistanceFieldPaths { get; set; }
public bool EnableInstancedRendering { get; set; }
public bool ForceSWPathMasks { get; set; }
Default静态属性返回平台默认配置的上下文选项,创建GRContext时可直接使用而不是new GRContextOptions();- 其余 4 个布尔开关分别控制路径遮罩缓存、距离场路径、实例化渲染和软件路径遮罩,用于针对特定 GPU/驱动问题做调优。实现见 GRContextOptions.cs。
3.3 SKCanvas:裁剪边界查询 + Lattice 绘制 + 新的裁剪/绘制方法
新增只读属性:
public SKRect ClipBounds { get; }
public SKRectI ClipDeviceBounds { get; }
用于在绘制前查询当前生效的裁剪范围(当前版本中这两个属性已进一步演化为 LocalClipBounds / DeviceClipBounds,见 SKCanvas.cs)。
新增方法一览:
public void ClipPath (SKPath path, SKClipOperation operation, bool antialias);
public void ClipRect (SKRect rect, SKClipOperation operation, bool antialias);
public void ClipRegion (SKRegion region, SKClipOperation operation);
public void DrawBitmapLattice (SKBitmap bitmap, SKLattice lattice, SKRect dst, SKPaint paint);
public void DrawImageLattice (SKImage image, SKLattice lattice, SKRect dst, SKPaint paint);
public void DrawColor (SKColor color, SKBlendMode mode);
public void DrawOval (float cx, float cy, float rx, float ry, SKPaint paint);
public void Scale (float s);
要点:
ClipPath/ClipRect的操作参数由SKRegionOperation换为 2 值枚举SKClipOperation { Difference, Intersect }(1.55.0 起裁剪语义收敛为"取差/取交"),旧签名被标记[Obsolete];ClipRegion配合新增的SKRegion类型(见 4.7 节)支持按 1 位区域裁剪;DrawBitmapLattice/DrawImageLattice是九宫格(lattice)纹理贴图的核心入口:用XDivs/YDivs把位图/图像切成网格并分别映射到目标矩形,SKLatticeFlags.Transparent可让格子间的缝隙透明;DrawColor (SKColor, SKBlendMode)与SKPaint.BlendMode(见 3.8 节)共同取代了旧的SKXferMode路径。
3.4 SKColor:Parse / TryParse
public static SKColor Parse (string hexString);
public static bool TryParse (string hexString, out SKColor color);
支持 #RGB、#RRGGBB、#AARRGGBB 等十六进制颜色字符串。当前实现位于 SKColor.cs,并且后续版本又补充了 ReadOnlySpan<char> 重载以避免字符串解析分配——这一演进方向也印证了 1.55.0 引入 Parse 时的"低成本字符串转颜色"定位:
SKColor red = SKColor.Parse ("#FF3030");
if (SKColor.TryParse (input, out SKColor c))
paint.Color = c;
3.5 SKColorFilter:色阶立方体常量重命名
[Obsolete ("Use MaxColorCubeDimension instead.")]
public static const int MaxCubeSize;
[Obsolete ("Use MinColorCubeDimension instead.")]
public static const int MinCubeSize;
新增:
public static const int ColorMatrixSize;
public static const int MaxColorCubeDimension;
public static const int MinColorCubeDimension;
ColorCube 滤镜的维度上下限常量改为更精确的 *Dimension 命名,同时补齐了 4×4 颜色矩阵尺寸常量 ColorMatrixSize(供 CreateColorMatrix 的数组大小使用)。
3.6 SKFontStyleWidth:拼写修正 UltaExpanded → UltraExpanded
UltaExpanded = 9, // Obsolete
UltraExpanded = 9, // 新值
这是一个纯拼写修正,枚举数值保持 9 不变。迁移时只需替换标识符;从源码结构看当前 Definitions.cs 中保留的正是 UltraExpanded = 9,旧拼写已随废弃流程移除。
3.7 SKImageFilter:位移映射改名 + 4 个工厂方法
被废弃的 CreateCompose(实为位移映射效果)更名为语义正确的 CreateDisplacementMapEffect,并新增一批静态工厂:
public static SKImageFilter CreateArithmetic (float k1, float k2, float k3, float k4, bool enforcePMColor, SKImageFilter background, SKImageFilter foreground, SKImageFilter.CropRect cropRect);
public static SKImageFilter CreateBlendMode (SKBlendMode mode, SKImageFilter background, SKImageFilter foreground, SKImageFilter.CropRect cropRect);
public static SKImageFilter CreateDisplacementMapEffect (SKDisplacementMapEffectChannelSelectorType xChannelSelector, SKDisplacementMapEffectChannelSelectorType yChannelSelector, float scale, SKImageFilter displacement, SKImageFilter input, SKImageFilter.CropRect cropRect);
public static SKImageFilter CreateTile (SKRect src, SKRect dst, SKImageFilter input);
对应 Skia C++ 侧的 SkImageFilters::Arithmetic/BlendMode/DisplacementMap/Tile。当前 SKImageFilter.cs 中 CreateDisplacementMapEffect 保留了 3 个渐进式重载(input 与 cropRect 可省略),CreateTile (SKRect src, SKRect dst, SKImageFilter? input) 同样保留(SKImageFilter.cs),API 形态与 1.55.0 引入时一致。
3.8 SKPaint:BlendMode 取代 XferMode,新增克隆与字体度量
[Obsolete ("Use BlendMode instead.")]
public SKXferMode XferMode { get; set; }
新增:
public SKBlendMode BlendMode { get; set; }
public float FontSpacing { get; }
public SKPaint Clone ();
public bool GetFillPath (SKPath src, SKPath dst, float resScale);
public bool GetFillPath (SKPath src, SKPath dst, SKRect cullRect, float resScale);
public float GetFontMetrics (out SKFontMetrics metrics, float scale);
BlendMode与SKPaint.Color配合实现 Porter-Duff 与扩展混合,XferMode进入废弃通道(当前 SKPaint.cs 中BlendMode为主属性);FontSpacing给出按当前字体计算的一行文本间距,GetFontMetrics (out metrics, scale)支持按缩放取字体度量(SKPaint.cs);GetFillPath把源路径按描边宽度"填充化"为新的闭合路径,常用于文本描边转填充、命中区域计算;Clone ()提供值语义的完整拷贝(SKPaint.cs),避免多个绘制器共享同一 paint 造成状态污染。
3.9 SKPath:批量补齐路径构建与变换 API
新增方法覆盖 Skia SkPath 的主要能力面:
// 圆弧/椭圆弧
public void ArcTo (SKPoint point1, SKPoint point2, float radius);
public void ArcTo (SKRect oval, float startAngle, float sweepAngle, bool forceMoveTo);
public void ArcTo (SKPoint r, float xAxisRotate, SKPathArcSize largeArc, SKPathDirection sweep, SKPoint xy);
public void ArcTo (float x1, float y1, float x2, float y2, float radius);
public void RArcTo (SKPoint r, float xAxisRotate, SKPathArcSize largeArc, SKPathDirection sweep, SKPoint xy);
// 相对坐标版本(R 前缀)
public void RLineTo (SKPoint point); public void RMoveTo (SKPoint point);
public void RQuadTo (SKPoint point0, SKPoint point1);
public void RCubicTo (SKPoint point0, SKPoint point1, SKPoint point2);
public void RConicTo (SKPoint point0, SKPoint point1, float w);
// 曲线段
public void ConicTo (SKPoint point0, SKPoint point1, float w);
public void CubicTo (SKPoint point0, SKPoint point1, SKPoint point2);
public void LineTo (SKPoint point); public void MoveTo (SKPoint point);
public void QuadTo (SKPoint point0, SKPoint point1);
// 变换与运算
public void Offset (SKPoint offset);
public SKPath Op (SKPath other, SKPathOp op);
public SKPath Simplify ();
// 圆锥曲线 → 二次曲线转换(SVG 路径解析常用)
public static SKPoint[] ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float w, int pow2);
public static int ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float w, SKPoint[] pts, int pow2);
public static int ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float w, out SKPoint[] pts, int pow2);
其中 Op 是布尔路径运算(union/intersect/difference/reverseDifference/andReversed/xor),Simplify 做共线点简化,ConvertConicToQuads 的 pow2 控制细分精度(2 的幂)。
3.10 其余小类变更
- SKPathEffect:
Create1DPath的样式参数由SkPath1DPathEffectStyle(拼写缺失)改为新枚举SKPath1DPathEffectStyle { Translate, Rotate, Morph }; - SKPoint:新增
Offset (SKPoint p)与Offset (float dx, float dy),与原地的点平移语义对齐SKPath.Offset; - SKRect / SKRectI:新增
MidX、MidY、Standardized属性与AspectFill (SKSize)、AspectFit (SKSize)(整型版对应SKSizeI)。当前实现中MidX为left + (Width / 2f)(MathTypes.cs),AspectFit内部以MidX/MidY为锚点居中(MathTypes.cs)——这对图像缩放的"保持宽高比"场景是标准工具; - SKTypeface:新增只读属性
FontSlant、FontWeight、FontWidth、Style(SKTypefaceStyle),可直接读取字面体自身携带的风格信息,当前 SKTypeface.cs 中FontWeight仍在维护; - SKPictureRecorder:删除原生句柄构造函数,新增
RecordingCanvas属性(SKPictureRecorder.cs)取代手工持有 canvas 句柄的写法。
4. 全新类型详解
4.1 SKBlendMode(29 个值)
1.55.0 引入完整混合模式枚举,数值与 Skia C++ 一一对应(SKBlendMode.generated.cs 中 Saturation = 26、Luminosity = 28 等值至今未变):
[Serializable]
public enum SKBlendMode {
Clear = 0, Src = 1, Dst = 2, SrcOver = 3, DstOver = 4,
SrcIn = 5, DstIn = 6, SrcOut = 7, DstOut = 8, SrcATop = 9, DstATop = 10,
Xor = 11, Plus = 12, Modulate = 13, Screen = 14, Overlay = 15, Darken = 16,
Lighten = 17, ColorDodge = 18, ColorBurn = 19, HardLight = 20, SoftLight = 21,
Difference = 22, Exclusion = 23, Multiply = 24, Hue = 25, Saturation = 26,
Color = 27, Luminosity = 28,
}
典型用法:paint.BlendMode = SKBlendMode.Multiply 实现图片叠加混合;canvas.DrawColor (SKColor.Red, SKBlendMode.SrcOver) 用指定混合模式清屏。
4.2 SKClipOperation
[Serializable]
public enum SKClipOperation {
Difference = 0,
Intersect = 1,
}
仅两个值,取代 SKRegionOperation 在裁剪路径/矩形上的重载参数,语义与 Skia SkClipOp 一致。
4.3 SKLattice 与 SKLatticeFlags
public struct SKLattice {
public SKRectI? Bounds { get; set; }
public SKLatticeFlags[] Flags { get; set; }
public int[] XDivs { get; set; }
public int[] YDivs { get; set; }
}
[Serializable]
public enum SKLatticeFlags {
Default = 0,
Transparent = 1,
}
XDivs/YDivs 数组长度分别决定网格的行数/列数(列数 = XDivs.Length + 1);Flags 数组与"格子"一一对应,Transparent 标记的格子不绘制,常用于九宫格 UI 贴图时让边框缝隙透明。配合 canvas.DrawImageLattice (image, lattice, dst, paint) 使用。
4.4 SKPath1DPathEffectStyle
[Serializable]
public enum SKPath1DPathEffectStyle {
Translate = 0,
Rotate = 1,
Morph = 2,
}
1D 路径效果(沿路径重复绘制小图形)的三种排布方式:平移、旋转、变形。
4.5 SKPathMeasure
沿路径做"距离 → 位置/切线/矩阵"查询的核心类(当前实现 SKPathMeasure.cs 中 Length 属性与 NextContour 均保留):
public class SKPathMeasure : SKObject, IDisposable {
public SKPathMeasure ();
public SKPathMeasure (SKPath path, bool forceClosed, float resScale);
public bool IsClosed { get; }
public float Length { get; }
public bool GetMatrix (float distance, out SKMatrix matrix, MatrixFlags flags);
public bool GetPosition (float distance, out SKPoint position);
public bool GetPositionAndTangent (float distance, out SKPoint position, out SKPoint tangent);
public bool GetSegment (float start, float stop, SKPath dst, bool startWithMoveTo);
public bool GetTangent (float distance, out SKPoint tangent);
public bool NextContour ();
public void SetPath (SKPath path, bool forceClosed);
[Serializable]
[Flags]
public enum MatrixFlags {
GetPosition = 1,
GetTangent = 2,
GetPositionAndTangent = 3,
}
}
典型场景:让文字或粒子沿贝塞尔曲线运动。NextContour() 在多段子路径(contour)间推进,GetSegment 截取路径片段,resScale 控制近似精度。
4.6 SKRegion
1 位(黑白)区域对象,与 SKCanvas.ClipRegion 配合使用:
public class SKRegion : SKObject, IDisposable {
public SKRegion ();
public SKRegion (SKRegion region);
public SKRectI Bounds { get; }
public bool Contains (SKPointI xy);
public bool Contains (SKRegion src);
public bool Contains (int x, int y);
public bool Intersects (SKRectI rect);
public bool Intersects (SKRegion region);
public bool Op (SKRectI rect, SKRegionOperation op);
public bool Op (SKRegion region, SKRegionOperation op);
public bool Op (int left, int top, int right, int bottom, SKRegionOperation op);
public bool SetPath (SKPath path);
public bool SetPath (SKPath path, SKRegion clip);
public bool SetRect (SKRectI rect);
public bool SetRegion (SKRegion region);
}
注意 Op 的运算参数仍是 5 值枚举 SKRegionOperation(与 4.2 节 SKClipOperation 不同——后者是裁剪专用的 2 值收敛版);SetPath 把抗锯齿前的路径轮廓栅格化为区域,clip 参数可限制栅格化范围以提升大路径的性能。
5. 升级迁移检查清单
将 1.54.0 项目升级到 1.55.0 时,按以下清单逐项排查:
| # | 检查项 | 旧写法 | 新写法 |
|---|---|---|---|
| 1 | Flush 默认参数 |
context.Flush () 或省略标志 |
context.Flush ()(新增无参重载);带参版本须显式传 GRContextFlushBits |
| 2 | 裁剪/清屏默认参数 | canvas.ClipRect (rect)、canvas.DrawColor (color) |
显式传 operation/antialias/mode,或改用 SKClipOperation 新重载 |
| 3 | 混合模式 | paint.XferMode = SKXferMode.Multiply |
paint.BlendMode = SKBlendMode.Multiply |
| 4 | 点映射 | matrix.MapXY (x, y) |
matrix.MapPoint (x, y) |
| 5 | MapRect 静态调用 |
SKMatrix.MapRect (ref m, out d, ref s) |
m.MapRect (ref other, out d, ref s) |
| 6 | Codec 子集 | options.Subset = new SKRectI (...) + void GetValidSubset |
new SKCodecOptions (new SKRectI (...)) + bool GetValidSubset (ref ...) |
| 7 | 文档关闭 | bool ok = doc.Close () |
doc.Close ()(返回 void) |
| 8 | 录制器构造 | new SKPictureRecorder (handle, owns) |
托管构造函数 + recorder.RecordingCanvas |
| 9 | 字面体宽度枚举 | SKFontStyleWidth.UltaExpanded |
SKFontStyleWidth.UltraExpanded |
| 10 | 色阶滤镜常量 | SKColorFilter.MaxCubeSize/MinCubeSize |
MaxColorCubeDimension/MinColorCubeDimension |
| 11 | 图像滤镜位移映射 | SKImageFilter.CreateCompose (...) |
SKImageFilter.CreateDisplacementMapEffect (...) |
由于改动集中在签名层面,多数场景下重新编译并跟随编译器错误/警告即可完成迁移;[Obsolete] 标记会保留在 1.55.0 中直到后续版本删除,为过渡期提供缓冲。
6. 配套验证:原生库版本兼容性
SkiaSharp.dll 与原生 libSkiaSharp 必须版本匹配。1.55.0 时代的版本校验逻辑沿用 SkiaSharpVersion:通过 sk_version_get_milestone()/sk_version_get_increment() 读取原生库版本,并要求其落在 <a href="https://link.gitcode.com/i/fd68119076353dfb9549986787aaee87" target="_blank">NativeMinimum, NativeMinimum + 1) 区间内,否则 CheckNativeLibraryCompatible (throwIfIncompatible: true) 抛出 InvalidOperationException([SkiaSharpVersion.cs)。升级 SkiaSharp 包时,NativeAssets 系列 NuGet 包(如 SkiaSharp.NativeAssets.Linux)会随主包一起更新,避免托管/原生版本错位。
7. 小结
1.55.0 的 API diff 可以归纳为三条主线:
- 签名收敛:去掉默认参数、删除
IntPtr句柄构造与遗留静态方法,换取稳定的 ABI 与确定的重载决议; - 语义更名:
XferMode → BlendMode、UltaExpanded → UltraExpanded、CreateCompose → CreateDisplacementMapEffect、CubeSize → ColorCubeDimension,废弃标记为迁移保留缓冲; - 能力补齐:
SKBlendMode、SKLattice、SKPathMeasure、SKRegion四个全新类型与SKColor.Parse、SKRect.AspectFit/AspectFill、SKPath.Op/Simplify等大量方法,把 SVG 路径解析、沿路径动画、九宫格贴图、区域裁剪等常用工作流沉淀为正式 API。
对照 完整 diff、破坏性变更清单 与 1.55.0 发布说明,即可在升级前评估影响面,并在升级后借编译器提示逐条完成迁移。