如何在Skia中加载TrueType/OpenType集合并使用其中的指定字体样式?
解决方案
前置检查
- 先确认你的SkiaSharp版本 ≥ 2.80.0,低于该版本存在
ttcIndex参数不生效的已知bug,升级到稳定版即可修复 - 加载用的流必须支持定位(
Stream.CanSeek == true),如果是不可定位的网络流/非内存流,先拷贝到MemoryStream中再操作
具体实现步骤
1. 预处理流(仅不可定位流需要)
// 替换为你实际的字体集合流 Stream rawCollectionStream = GetFontCollectionStream(); MemoryStream seekableStream = new MemoryStream(); rawCollectionStream.CopyTo(seekableStream); seekableStream.Position = 0;
2. 获取集合内字体总数量
调用带out int count参数的SKTypeface.FromStream重载,即可读取TTC/OTC文件内包含的字体总数:
int fontCount = 0; // 临时Typeface用完即可释放 using (var _ = SKTypeface.FromStream(seekableStream, ttcIndex: 0, out fontCount)) { // 无操作,仅用于获取总数量 } seekableStream.Position = 0; // 必须重置流位置到起始点
3. 循环加载所有字体
按索引遍历加载所有Typeface,注意每次加载完成后都要重置流位置:
List<SKTypeface> collectionTypefaces = new List<SKTypeface>(); for (int i = 0; i < fontCount; i++) { var typeface = SKTypeface.FromStream(seekableStream, ttcIndex: i); if (typeface != null) { collectionTypefaces.Add(typeface); } // 重置流位置,避免下一次读取失败 seekableStream.Position = 0; }
常见问题说明
非零ttcIndex返回null的90%以上场景都是未重置流位置导致的,每次调用FromStream方法后,流的读取指针会移动到末尾,后续调用如果不重置位置就会读取不到有效数据,直接返回null。
加载完成后你可以通过SKTypeface.FamilyName、SKTypeface.FontWeight、SKTypeface.FontSlant等属性筛选所需的字体样式,正常用于Skia文本渲染即可。
内容的提问来源于stack exchange,提问作者John Carruthers
相关产品推荐
相关产品推荐

