init project
This commit is contained in:
@@ -1,3 +1,146 @@
|
||||
# timi-icon-font
|
||||
|
||||
SVG 字体图标
|
||||
纯 Java SVG 图标字体工具库,支持 SVG 构建 TTF,也支持从 TrueType `glyf` 字体导出 SVG 字形。
|
||||
|
||||
## 构建 TTF
|
||||
|
||||
```java
|
||||
List<IconGlyph> glyphs = List.of(
|
||||
IconGlyph.of("home", "e001", "M128 512L512 128L896 512L768 512L768 896L256 896L256 512Z")
|
||||
);
|
||||
|
||||
byte[] ttf = IconFontBuilder.build("TimiIcon", glyphs);
|
||||
```
|
||||
|
||||
也可以直接用 `name -> pathData` 映射并指定起始 Unicode:
|
||||
|
||||
```java
|
||||
Map<String, String> paths = new LinkedHashMap<>();
|
||||
paths.put("home", "M128 512L512 128L896 512L768 512L768 896L256 896L256 512Z");
|
||||
|
||||
byte[] ttf = IconFontBuilder.build("TimiIcon", paths, 0xE001);
|
||||
```
|
||||
|
||||
从目录或 JSON 文件构建:
|
||||
|
||||
```java
|
||||
IconFontOptions options = IconFontOptions.defaults("TimiIcon");
|
||||
IconFontIO.writeTtfFromSvgDirectory(Path.of("icons.ttf"), options, Path.of("icons"), 0xE001);
|
||||
IconFontIO.writeTtfFromSvgJson(Path.of("icons.ttf"), options, Path.of("icons.json"), 0xE001);
|
||||
```
|
||||
|
||||
如果源图标基于固定画布绘制,例如 `16 x 16`,但图形没有占满整个画布,应显式指定源画布,避免构建 TTF 时按字形外接框被二次放大:
|
||||
|
||||
```java
|
||||
IconFontOptions options = IconFontOptions.defaults("TimiIcon")
|
||||
.withSourceBounds(0, 0, 16, 16);
|
||||
```
|
||||
|
||||
默认会保留源画布中的原始留白与落点,这对通用图标库更稳妥。如果希望某个方向按实际字形外接框居中,可单独开启:
|
||||
|
||||
```java
|
||||
IconFontOptions options = IconFontOptions.defaults("TimiIcon")
|
||||
.withSourceBounds(0, 0, 16, 16)
|
||||
.withAlignment(GlyphAlignment.SOURCE, GlyphAlignment.GLYPH_CENTER);
|
||||
```
|
||||
|
||||
像素风图标如果希望尽量贴齐源网格,可额外启用偏移吸附。它会牺牲部分“数学居中”,换取更稳定的像素边缘:
|
||||
|
||||
```java
|
||||
IconFontOptions options = IconFontOptions.defaults("TimiIcon")
|
||||
.withSourceBounds(0, 0, 16, 16)
|
||||
.withAlignment(GlyphAlignment.SOURCE, GlyphAlignment.GLYPH_CENTER)
|
||||
.withSnapOffsetToGrid(true);
|
||||
```
|
||||
|
||||
## 写入字体元数据
|
||||
|
||||
```java
|
||||
FontMetadata metadata = FontMetadata.defaults("TimiIcon");
|
||||
metadata.setDesigner("Codex");
|
||||
metadata.setCopyright("Copyright 2026 Timi");
|
||||
metadata.setVersion("Version 1.000");
|
||||
metadata.setLicense("Preview and print embedding only");
|
||||
metadata.setLicenseUrl("https://example.com/license");
|
||||
metadata.setEmbeddingRestrictions(FontEmbeddingRestrictions.of(
|
||||
FontEmbeddingRestrictions.PREVIEW_AND_PRINT
|
||||
| FontEmbeddingRestrictions.NO_SUBSETTING
|
||||
));
|
||||
|
||||
IconFontOptions options = IconFontOptions.defaults("TimiIcon").withMetadata(metadata);
|
||||
IconFont font = IconFontBuilder.buildFont(options, glyphs);
|
||||
```
|
||||
|
||||
## TTF 导出 SVG
|
||||
|
||||
```java
|
||||
List<SvgGlyph> glyphs = TtfIconFontReader.readSvgGlyphs(ttfBytes);
|
||||
String svg = glyphs.getFirst().getSvg();
|
||||
```
|
||||
|
||||
导出为目录或 JSON:
|
||||
|
||||
```java
|
||||
IconFontIO.writeSvgDirectory(Path.of("icons.ttf"), Path.of("icons-out"));
|
||||
IconFontIO.writeSvgJson(Path.of("icons.ttf"), Path.of("icons.json"));
|
||||
```
|
||||
|
||||
## CLI
|
||||
|
||||
打包后可通过可执行 jar 调用:
|
||||
|
||||
```shell
|
||||
java -jar target/timi-icon-font-0.0.1.jar build \
|
||||
-i icons \
|
||||
-o icons.ttf \
|
||||
--family TimiIcon \
|
||||
--start-unicode e001 \
|
||||
--designer Codex \
|
||||
--fs-type 0x104
|
||||
|
||||
java -jar target/timi-icon-font-0.0.1.jar build \
|
||||
-i icons.json \
|
||||
-o icons.ttf \
|
||||
--input-format json \
|
||||
--horizontal-alignment source \
|
||||
--vertical-alignment glyph_center \
|
||||
--snap-offset-to-grid true \
|
||||
--source-width 16 \
|
||||
--source-height 16 \
|
||||
--metadata-json metadata.json
|
||||
|
||||
java -jar target/timi-icon-font-0.0.1.jar export \
|
||||
-i icons.ttf \
|
||||
-o icons-out
|
||||
|
||||
java -jar target/timi-icon-font-0.0.1.jar export \
|
||||
-i icons.ttf \
|
||||
-o icons.json \
|
||||
--output-format json
|
||||
```
|
||||
|
||||
输入目录格式:`*.svg` 文件名作为图标名称,文件内容为 SVG path 或完整 SVG。
|
||||
|
||||
输入 JSON 格式:
|
||||
|
||||
```json
|
||||
{
|
||||
"home": "M128 512L512 128L896 512L768 512L768 896L256 896L256 512Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 读取字体信息
|
||||
|
||||
```java
|
||||
FontInfo info = TtfIconFontReader.readFontInfo(ttfBytes);
|
||||
FontMetadata metadata = info.metadata();
|
||||
FontMetrics metrics = info.metrics();
|
||||
List<CharacterMapping> characters = info.characters();
|
||||
```
|
||||
|
||||
## 兼容范围
|
||||
|
||||
- SVG path 支持 `M/L/H/V/C/S/Q/T/A/Z` 与相对命令,支持外层 XML、完整 SVG 和多个 `path`,曲线会按配置采样为 TrueType 简单轮廓。
|
||||
- TTF 导出支持 `cmap format 4/12`、`glyf` 简单轮廓和常见复合字形。
|
||||
- 元数据支持 `name` 表常用字段、`OS/2 fsType` 使用限制、weight/width/vendor、字符映射和基础指标信息。
|
||||
- CFF/OpenType PS 轮廓不是 TrueType `glyf` 数据,当前会抛出明确异常。
|
||||
|
||||
Reference in New Issue
Block a user