C# SixLabors.Fonts字体加载方法 C#在ImageSharp中如何使用自定义字体

来源:这里教程网 时间:2026-02-21 17:41:28 作者:

FontCollection.LoadFonts 无法加载 .ttf 文件?检查路径和流释放

直接用

FontCollection.LoadFonts("font.ttf")
报错“file not found”或空字体列表,大概率是路径没解析对,或者文件被其他进程占用。ImageSharp 本身不负责字体加载,SixLabors.Fonts 才是核心——它要求传入的
Stream
必须可读、未关闭、且位置在开头。

常见错误:用

File.OpenRead()
后没重置位置;或用
Assembly.GetExecutingAssembly().GetManifestResourceStream()
加载嵌入资源时路径写错(注意命名空间前缀)。

本地文件推荐用
new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous)
,确保可异步读取且不被锁死
嵌入资源务必确认完整资源名,可用
Assembly.GetExecutingAssembly().GetManifestResourceNames()
调试输出验证
加载后建议立刻调用
fontCollection.GetFont("FontName", 400, FontStyle.Regular)
测试是否真能解析出字体族,避免“静默失败”

ImageSharp 绘制文字时提示 “No fonts registered”

这说明

FontCollection
实例没传给
TextGraphicsOptions
,或传了但没生效。ImageSharp 2.x+ 不再全局注册字体,必须显式绑定到绘图上下文。

关键点在于:不是把

FontCollection
存起来就行,而是在每次创建
TextGraphicsOptions
时通过
FontCollection
构造参数注入:

var options = new TextGraphicsOptions(true)
{
    Font = fontCollection.CreateFont("Noto Sans CJK SC", 16),
    // 注意:这里 Font 是 FontDescription 类型,不是 FontFamily 或 string
};

如果字体名含空格或中英文混排(如 "Microsoft YaHei"),务必用实际 PostScript 名(可用 FontForge 或

font.FamilyName
输出确认),别依赖显示名。

中文乱码或方块字?优先检查字体是否支持 Unicode 区段

SixLabors.Fonts 默认只加载基本 ASCII 字形,遇到中文会 fallback 到缺失字形(□)。即使加载了 NotoSansCJK.ttc,也得确认你调用的是支持 CJK 的子字体(如

"Noto Sans CJK SC"
,不是
"Noto Sans"
)。

fontCollection.Families
遍历所有已加载家族,打印
family.Name
family.GetRegularFont().Glyphs.Count
,看是否有足够多字形(中文字体通常 >20000)
避免用
CreateFont("SimSun", size)
—— Windows 系统字体名在 Linux/macOS 上不存在,跨平台必须带字体文件
绘制中文前加一句
options.VerticalAlignment = VerticalAlignment.Top;
,防止 baseline 偏移导致截断

性能敏感场景下避免重复加载字体文件

每次

LoadFonts
都会解析整个 TTF/OTF 表结构,开销不小。字体文件应作为单例复用,而不是每次绘图都新建
FontCollection

典型安全做法是静态初始化:

public static class FontProvider
{
    public static readonly FontCollection Collection = new();
    static FontProvider()
    {
        using var stream = typeof(FontProvider).Assembly.GetManifestResourceStream("Assets.NotoSansCJKsc-Regular.otf");
        Collection.LoadFonts(stream);
    }
}

注意:不要在静态构造器里用

await
,SixLabors.Fonts 的
LoadFonts
没有异步重载;若字体来自网络或慢存储,需提前预热并缓存
Font
实例,而非反复查
GetFont

最易忽略的一点:

FontCollection
不是线程安全的,但它的
GetFont
方法是——只要不同时调用
LoadFonts
,多个线程共用同一个实例没问题。

相关推荐