- 开发工具
- 桌面应用
【免费下载链接】DevToys
A Swiss Army knife for developers.
导读
DevToys 是一款面向开发者的多功能工具箱,其界面左侧导航与工具卡片上的图标并非位图,而是由一套自定义图标字体DevToys-Tools-Icons驱动的。本文基于仓库中 assets/font/README.md 的官方工作流,系统讲解如何在任意矢量编辑器中绘制 SVG 字形、如何在 FontForge 中把它并入图标字体、通过校验后导出 TrueType 字体,并最终在应用内以字形码(Glyph)的形式被工具组消费。读完本文,你将掌握向 DevToys 图标字体新增一个工具图标并生成DevToys-Tools-Icons.ttf的完整流程,同时理解字体文件在项目中的嵌入与加载机制。
一、认识 DevToys-Tools-Icons:项目内的图标字体三件套
在仓库的 assets/font 目录下,图标字体由三类文件共同组成:
- SVG 源文件:每个工具一个独立 SVG,例如 JsonFormatter.svg、Base64EncoderDecoder.svg、UuidGenerator.svg 等,它们是字形绘制的原始素材;
- FontForge 工程文件:DevToys-Tools-Icons.sfd,是字体的可编辑母版,全部字形与编码信息都保存在这里;
- 生成产物:DevToys-Tools-Icons.ttf(TrueType 字体,运行时实际加载)与 DevToys-Tools-Icons.afm(字体度量描述文件,记录字形名与包围盒)。
从 DevToys-Tools-Icons.sfd 的文件头可以看到字体的基础元数据:FontName: DevToys-Tools-Icons、Version: 001.000、Ascent: 1024、Descent: 0,这与 AFM 中记录的统一 1000 单位字形宽度(WX 1000)相对应,说明字体采用常规的 1000 em 设计网格,字形绘制时应当把图形控制在 0~1000 的设计坐标系内。
在 DevToys-Tools-Icons.afm 中可以读到完整的字形清单(StartCharMetrics 38,共 38 个字形),例如Base64EncoderDecoder、ColorBlindnessSimulator、JsonFormatter、JwtDecoder、CronParser、Settings、ColorPicker、ListCompare等。每个字形都以有语义的英文名称命名,这一命名习惯也延续到了「给新字形命名」这一步。
二、字体在应用中的角色:从 TTF 到界面图标的调用链
在动手扩展字体之前,先理解字体文件是如何被应用消费的,这有助于确认新字形的 Unicode 值选择是否合理。
- 嵌入资源:在 DevToys.Blazor.csproj 中,
DevToys-Tools-Icons.ttf被声明为嵌入资源(EmbeddedResource),随程序集一起打包; - 注册字体:DevToysBlazorResourceManagerAssemblyIdentifier.cs 通过
FontDefinition将字体流注册到运行时,其中"DevToys-Tools-Icons"就是字体在应用中的逻辑名;同一文件也注册了微软的FluentSystemIcons字体; - 字形消费:各个工具组通过
IconFontName+IconGlyph指定「用哪套字体、渲染哪个字符」。从源码看,绝大多数内置组都使用DevToys-Tools-Icons,具体字形码如下:
| 工具组 | 源码文件 | IconFontName | IconGlyph(Unicode) |
|---|---|---|---|
| Converters | ConvertersGroup.cs | DevToys-Tools-Icons | \u0103 |
| Encoders / Decoders | EncodersDecodersGroup.cs | DevToys-Tools-Icons | \u0105 |
| Formatters | FormattersGroup.cs | DevToys-Tools-Icons | \u0123 |
| Generators | GeneratorsGroup.cs | DevToys-Tools-Icons | \u0126 |
| Graphic | GraphicGroup.cs | DevToys-Tools-Icons | \u0129 |
| Text | TextGroup.cs | DevToys-Tools-Icons | \u0132 |
| Testers | TestersGroup.cs | FluentSystemIcons | \uE33B |
由此可以推断:新增字形时选用的 Unicode 码位应避开这些已被占用的值,并尽量延续「私有区(PUA,如U+E000–U+F8FF)或拉丁扩展区」的既有分配策略。官方教程以U+0100为例,正是为了引导新字形落在尚未被U+0103、U+0123等占用的安全区间。
三、第一步:在矢量编辑器中绘制并导出 SVG 字形
字体中每个字形本质上是「把一段闭合路径映射到一个字符码位」。因此新增字形的起点是绘制图形,官方工作流对此非常灵活——Figma、Inkscape、Adobe Illustrator 或任何你习惯的矢量工具都可以。
绘制时需注意两点,它们直接决定后面导入 FontForge 是否顺利:
- 使用纯路径(Path/Bezier):SVG 导入 FontForge 时主要解析路径数据,应避免使用无法被转换的图层效果(如模糊、渐变纹理),图形以纯色填充路径表达;
- 控制设计尺寸与留白:参考现有字形在 AFM 中的包围盒数据(如
Settings的包围盒B 23 11 957 989、Base64EncoderDecoder的B 70 60 940 930),让新图形在 1000×1000 的设计网格中占满但保留适当边距,保证与既有图标视觉上大小统一。
导出时选择SVG 格式,保存为assets/font目录下的新文件(命名沿用现有规则,如JsonFormatter.svg),完成绘制后进入 FontForge 环节。
四、第二步:在 FontForge 中把 SVG 并入字体
安装 FontForge 后,按照以下步骤把 SVG 字形并入字体母版:
- 打开工程:用 FontForge 打开仓库中的 DevToys-Tools-Icons.sfd。这是唯一可编辑的字体源文件,
DevToys-Tools-Icons.ttf只是它的导出产物; - 新建编码槽位:菜单
Encoding > Add Encoding Slots,为字体新增一个空的字符槽; - 导入 SVG:选中刚创建的槽位,执行
File > Import并选择第 1 步导出的 SVG 文件。关键细节:在Options(选项)中,务必取消勾选Scale to fit (Misc)(缩放到适配)。保留勾选会导致 FontForge 按槽位尺寸自动缩放图形,破坏你已规划好的视觉比例与边距; - 设置字形信息:对导入的字形执行
Element > Glyph Info(字形信息),为其指定两样东西:- 字形名称(Glyph name):沿用仓库既有命名习惯,使用有语义的英文名称,例如新工具叫「Password 生成器」就命名
PasswordGenerator(AFM 中确实已存在PasswordGenerator字形,可作为命名范例参考); - Unicode 值:例如
U+0100。选择码位时避开上表已占用的U+0103、U+0105、U+0123、U+0126、U+0129、U+0132,同时注意与 Windows/Linux 平台上字体的兼容性。
- 字形名称(Glyph name):沿用仓库既有命名习惯,使用有语义的英文名称,例如新工具叫「Password 生成器」就命名
五、第三步:生成前必须通过的字体校验
字体文件对路径质量要求比普通矢量图更严格,任何自相交、非整数坐标或极值点缺失都可能在实际渲染时产生渲染瑕疵甚至导致字体无效。因此官方工作流要求先校验、后生成:
执行Element > Validation > Validate...(元素 > 校验 > 校验...),历史上最常见的三类问题及官方给出的处理方式如下:
| 校验错误 | 现象 | 官方解决方式 | 兜底方案 |
|---|---|---|---|
| Self Intersecting(自相交) | 路径存在交叉,常见于不规则多边形或复杂图形的布尔运算残留 | Element > Overlap > Remove Overlap(去除重叠)自动修复 | 若自动处理导致字形外观劣化,需回到 SVG 手工修正路径 |
| Non-Integral Coordinates(非整数坐标) | 控制点坐标带小数,可能引起不同平台渲染差异 | Element > Round > To Int(取整为整数)自动修复 | —— |
| Missing Points at Extrema(极值点缺失) | 曲线在水平/垂直极值处没有关键点,可能影响 hinting 与平滑度 | Element > Add Extrema(添加极值点)自动修复 | —— |
需要说明的是:Remove Overlap这类自动修复在几何上虽然正确,但可能改变字形观感。官方文档明确指出「如果它把字形弄丑了,你需要手工编辑 SVG 来修复」,即优先保证 SVG 源文件的路径质量,自动修复只是兜底手段。
六、第四步:生成 TrueType 字体
校验通过(无任何 validation issues)后,即可导出最终字体:
- 执行
File > Generate Fonts(文件 > 生成字体); - 在格式下拉框中选择TrueType;
- 勾选
Validate before saving(保存前校验),让 FontForge 在写出文件前再做一次完整性检查; - 点击
Generate(生成),得到新的DevToys-Tools-Icons.ttf。
生成的 TTF 会覆盖 assets/font/DevToys-Tools-Icons.ttf,由于该文件在 DevToys.Blazor.csproj 中被声明为嵌入资源,重新编译后新字形就会随应用发布。若需要同步更新 AFM 度量文件(可选),也可在 FontForge 的字体信息导出功能中生成。
七、第五步:验证新字形
生成 TTF 后,官方建议使用Character Map UWP(Windows 商店中的「字符映射表 UWP」应用)打开字体文件进行验证:确认新字形存在、码位正确、图形渲染无毛刺。这一步骤能提前暴露「编码槽位选错」「SVG 导入比例失真」「路径自相交」等问题,避免把坏字体提交到仓库。
在此基础上,还可以结合应用侧做二次验证:在对应工具组的源码(例如 ConvertersGroup.cs)中把IconGlyph指向新字形的 Unicode 值,重新编译运行 DevToys,在导航界面直接查看图标渲染效果。
八、完整工作流速查表
| 阶段 | 操作 | 关键参数/注意事项 |
|---|---|---|
| 1. 绘制 | Figma / Inkscape / Illustrator 绘制图形 | 纯路径图形,1000×1000 设计网格内控制边距 |
| 2. 导出 | 导出 SVG | 命名沿用工具名.svg规则 |
| 3. 并入 | FontForge 打开DevToys-Tools-Icons.sfd | Encoding > Add Encoding Slots新建槽位 |
| 4. 导入 | File > Import选择 SVG | 取消勾选Scale to fit (Misc) |
| 5. 命名 | Element > Glyph Info | 设置字形名 + Unicode(如U+0100,避开已用码位) |
| 6. 校验 | Element > Validation > Validate... | 修复自相交 / 非整数坐标 / 极值点缺失 |
| 7. 导出 | File > Generate Fonts | 选 TrueType,勾选Validate before saving |
| 8. 验证 | Character Map UWP 打开 TTF | 检查字形存在、码位正确、渲染无瑕疵 |
| 9. 接入 | 更新IconGlyph并重新编译 | 参考 ConvertersGroup.cs 的IconFontName/IconGlyph用法 |
结语
DevToys 的图标体系是一个「SVG 源文件 → FontForge 母版 → TTF 嵌入资源 →IconGlyph渲染」的完整链路。本文基于 assets/font/README.md 的官方教程,补充了字体元数据、字形清单、资源加载与组内字形码映射等源码级细节。按「绘制 SVG → 新建编码槽位导入 → 校验修复 → 生成 TTF → 字符表验证」五步走,即可安全地为 DevToys 贡献一个新工具图标,整个过程不涉及任何位图资源,全部由字体驱动,这也是该项目界面图标保持清晰锐利的关键所在。
- 开发工具
- 桌面应用
【免费下载链接】DevToys
A Swiss Army knife for developers.
相关推荐
DevToys 与开源项目集成:为你的项目添加 DevToys 支持
DevToys 与开源项目集成:为你的项目添加 DevToys 支持 你是否在开发过程中频繁切换各种工具来处理 JSON 格式化、Base64 编码或正则表达式
开发工具桌面应用Omarchy 私有图标字体 omarchy.ttf 指南:为菜单添加与维护品牌字形
Omarchy 私有图标字体 omarchy.ttf 指南:为菜单添加与维护品牌字形 Omarchy 桌面菜单并非为每个应用准备一张位图图标,而是把商标"铸"进
操作系统开发工具AI 应用CLIDevToys图标字体使用:如何在网页和应用中引用工具图标
DevToys图标字体使用:如何在网页和应用中引用工具图标 DevToys提供了一套完整的工具图标字体,包含所有官方工具的矢量图标,可直接在网页和应用中引用。这
开发工具桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考