- 桌面应用
- 图形学
【免费下载链接】fontforge
Free (libre) font editor for Windows, Mac OS X and GNU+Linux
本文是一篇聚焦 FontForge 中Element → Tile Path(沿路径平铺)与Tile Pattern(平铺图案)两个命令的实战技术指南。两者均用于在字形轮廓上生成重复性装饰——前者把自定义“瓦片”沿选中曲线逐段铺放并自动弯曲贴合,后者把设计好的图案按指定行列数铺满当前图层。读完本文,你将掌握两种命令的调用方式、四类瓦片与三种缩放/对齐策略的语义,理解其底层样条变换原理,并能在自己的字体设计中用它们制作花边、边框与装饰底纹。
命令入口与启用前提
Tile Path 与 Tile Pattern 并不是 FontForge 默认构建中包含的命令。文档明确说明:
- 该命令默认构建不可用,需要重新以
configure --with-tilepath配置并重新编译 FontForge 才能启用; - 命令在二次曲线(quadratic / TrueType)字体中不可用,仅适用于三次曲线(cubic)轮廓。
从源码层面看,两个命令的完整实现都位于 fontforgeexe/tilepath.c 中,并被#ifdef FONTFORGE_CONFIG_TILEPATH宏整体包裹(见 tilepath.c 与文件末尾的#endif),这正是configure --with-tilepath需要生效的编译开关。菜单入口Element → Tile Path与Element → Tile Pattern...的说明见 doc/sphinx/ui/menus/elementmenu.rst:后者允许把设计好的图案在当前图层上按 m×n 次铺放(m 为水平重复数、n 为垂直重复数)。
两种命令的分工
| 命令 | 作用对象 | 效果 |
|---|---|---|
| Tile Path | 字形中的一条或多条轮廓路径 | 将自绘“瓦片”沿曲线铺放并弯曲贴合,替换选中路径 |
| Tile Pattern | 当前图层(横向 × 纵向) | 将自绘图案按指定行列数重复铺满图层区域 |
Tile Path:把瓦片沿曲线铺放
Tile Path 的使用流程是:先在字形上选中一条(或一组)路径,再执行命令,在弹出的对话框中设计好瓦片,确定后所有选中路径都会被铺上贴合曲线的瓦片。
以一个例子来说明:事先设计好一个简单的矩形“瓦片”(tile),再准备两条待铺放的路径(一条直线、一条闭合曲线),执行命令后瓦片被复制(并发生弯曲变形)以跟随原轮廓的走向——从结果看,原路径已被一排排瓦片完全替代。
下面这段是典型的效果预览对比:
- 瓦片:需要设计的重复单元;
- 待铺放的两条路径:一条开曲线与一条闭合曲线;
- 铺放结果:瓦片沿两条轮廓被复制并弯曲贴合。
从上图可以看出,对话框提供了多个瓦片编辑区。你需要至少指定一个 Medial(中间)瓦片,另外三种(First、Final、Isolated)为可选。四类瓦片的具体语义如下:
- Isolated(孤立):当一条开放轮廓用单个瓦片即可覆盖时,使用它;
- First(起始):对于开放轮廓,铺下的第一个瓦片;
- Final(收尾):对于开放轮廓,铺下的最后一个瓦片;
- Medial(中间):开放轮廓中间的瓦片,以及闭合轮廓的全部瓦片(闭合轮廓没有端点,全部由 Medial 瓦片覆盖)。
这样设计的原因是你可以为轮廓端点做特殊处理。例如在文档示例中,如果希望开放轮廓的两端自动闭合,可以让 First 与 Final 瓦片与 Medial 形状相同、但各自封住对应的一侧边缘;而 Isolated 瓦片则把两侧边缘都封上。
瓦片放置位置:Left / Center / Right
对话框提供三档放置方式,控制瓦片相对路径中心线的横向偏移:
- Left(左侧):瓦片与路径左边缘相切。对顺时针方向的路径而言,左边缘在路径外侧(outside);
- Center(居中):瓦片中心对准路径;
- Right(右侧):瓦片与路径右边缘相切。对顺时针方向的路径而言,右边缘在路径内侧(inside)。
三者的效果示意:
- left(外侧)
- center(居中)
- right(内侧)
缩放模式:Tile / Scale & Tile / Scale
对话框还提供三档缩放策略,决定瓦片如何沿路径长度分布:
| 模式 | 行为 | 边界情况 |
|---|---|---|
| Tile(平铺) | 瓦片不缩放,原样重复铺放 | 路径长度不是瓦片高度的整数倍时,一端会留下半个/残片瓦片 |
| Scale & Tile(缩放并平铺) | 先确定整数铺放次数,再对瓦片做轻微缩放,使其在路径上恰好铺整数次 | 避免残片,铺放次数取整 |
| Scale(缩放) | 只铺一个瓦片,将其缩放至与路径等长 | 用单个瓦片完全覆盖路径 |
三种策略的效果示意:
- tile(纯平铺)
- tile & scale(平铺并缩放)
- scale(仅缩放)
源码中的实现逻辑
这三种模式与放置方式在源码中对应两个枚举(见 tilepath.c):
enum tilepos { tp_left, tp_center, tp_right } tilepos; enum tilescale { ts_tile, ts_tilescale, ts_scale } tilescale;源码注释对三档缩放的内部含义有更精确的描述(tilepath.c):
ts_scale:把单个瓦片缩放至高度等于路径长度;ts_tile:铺下 n 个瓦片使n × 瓦片高 ≈ 路径长,n 不一定是整数,因此可能出现不完整瓦片——对应的样条可能被截断,甚至一条样条被切成两条;ts_tilescale:先求n = floor(路径长 / 瓦片高),再令scale = 路径长 / (n × 瓦片高),把瓦片按该比例缩放后铺下 n 个。
具体的数量判定在TileLine()中完成(tilepath.c):例如ts_tile模式下会先判断路径长度与 Isolated/First/Final 瓦片高度(ibb.maxy、fbb.maxy、lbb.maxy)的关系,决定只铺一个 Isolated、只铺 First、铺 First+Final 还是铺多个瓦片;闭合轮廓(td->path->first->prev != NULL)则一律视为“全是中间瓦片”。对话框中的单选钮在确认时被映射回这两个枚举(tilepath.c)。
弯曲贴合:底层样条变换原理
瓦片沿曲线“弯曲”并非简单旋转复制。源码头部的注释(tilepath.c)描述了核心算法:
- 先求路径的总长度
plength,并求出瓦片高度,得到需要的瓦片数量length/height; - 对瓦片中心轴(x 方向中轴)上的每个点,用它的 y 位置(
y-pos / length)换算成沿路径的进度,再把这个点移到路径上对应的位置; - 对偏离中心轴的点,先做同样的换算,再求路径在该处的法向量,新位置 = 上述路径位置 +
x 偏移 × 法向量; - 对瓦片每条样条上的大量点重复上述计算,再用这些点反拟合出新的样条(
ApproximateSplineFromPoints,见 tilepath.c),完成瓦片的弯曲。
实现上,路径被离散成一组采样点tdsamples(数量为ceil(len)+10,见 tilepath.c),每个采样点记录相对起点的偏移以及路径法线的 cos/sin 值;在样条连接处(非相切连接)则额外记录两条样条各自的法线,以便按两法线夹角求交点(tilepath.c 的AdjustPoint)。由于路径往往不能整除瓦片高度,实现还包含按 y 坐标截断瓦片样条的SplinePointListTruncateAtY(tilepath.c),并在瓦片数量少于路径样条数时主动插入断点以提高拟合精度(TDAddPoints,tilepath.c)。
另外,对话框中每个瓦片编辑区都附带一个“Include Whitespace below Tile”(在瓦片下方包含空白)复选框(tilepath.c)。其提示信息说明:默认瓦片由瓦片的最小包围盒内的全部内容构成,相邻瓦片会紧贴彼此;若希望在瓦片间留出空白,则勾选此项。源码中对应ws_include标志(tilepath.c),并在TileIt()中决定是否保留瓦片底部的空白(tilepath.c)。
操作与校验细节
- 对话框打开时,四个编辑窗格分别名为 First / Medial / Final / Isolated,Tab 键可在窗格间切换(tilepath.c)。
- 确认时校验:Medial 瓦片是必填的;若选择了
ts_scale(Scale)模式,则要求 Medial 或 Isolated 至少提供一个,否则弹出错误“You must specify a medial tile”(tilepath.c)。 - 命令可作用于单个字形(
SCTile)、字符视图(CVTile)或多个选中字形(FVTile,遍历选中编码并对每个字形铺放,见 tilepath.c)。 - 本次使用的瓦片会被记忆,下次打开对话框时自动恢复(
last_tiles[4],见 tilepath.c)。
Tile Pattern:把图案铺满图层
Tile Pattern 对话框(Element → Tile Pattern...)允许你设计一个图案,并将其沿当前图层横向、纵向同时重复铺放:
- 在对话框的编辑窗格中设计图案本体;
- 通过Width(宽)与Height(高)字段指定单个瓦片的尺寸——注意尺寸可以大于图案的包围盒,以便在瓦片四周留出空白(绿色线条表示瓦片的边界);
- 通过X与Y字段指定图案在横向、纵向各重复多少次。
铺放会从原点(origin)开始。图案铺满之后,你还可以:
- 对它施加其他变换(Transform),把矩形排列扭曲成非矩形形状;
- 或用
Element → Overlap → Intersect命令把它裁剪到某条轮廓内。
这样组合使用,就能模拟 Type 3 字体中真正的图案瓦片(pattern tile)的部分能力。
参数默认值与合法性约束(源码级)
从TilePatternAsk()与PTD_OK()的实现可以看到这些细节(tilepath.c):
- 首次打开且无记忆图案时,Width/Height 默认取当前字体的
ascent + descent(tilepath.c); - X/Y 重复数默认均为 10(
patternRepeat = { 10, 10 },见 tilepath.c); - 尺寸与重复数必须为正数:
Width/Height ≤ 0或X/Y ≤ 0会报错;重复数超过2000也会报错(tilepath.c); - 必须提供图案(样条或引用字形至少其一),否则报错 “You must specify a pattern”(tilepath.c);
- 当编辑区中有一个矩形闭合轮廓时,对话框会用定时器自动把其宽/高同步到 Width/Height 字段,方便按图案包围盒精确设定瓦片尺寸(tilepath.c)。
铺放实现:SCTilePattern
铺放逻辑集中在SCTilePattern()(tilepath.c):
- 对
i in [0, cnt->x)、j in [0, cnt->y)双重循环,用平移变换transform[4] = i * size->x; transform[5] = j * size->y逐格复制图案的样条(SplinePointListTransform); - 如果图案中包含引用字形(refs),同样逐格复制引用并重新实例化(
SCReinstanciateRefChar),同时建立依赖关系(SCMakeDependent); - 铺放目标是当前活动图层(
ly_fore/指定 layer,或网格层ly_grid)。
同 Tile Path 一样,Tile Pattern 也支持在字符视图(CVPatternTile)与字体视图多字形批量(FVPatternTile,遍历所有选中字形)中执行,并且上一次的图案、尺寸与重复数都会被记忆以便复用(TPFree,见 tilepath.c)。
实战建议:花边、边框与底纹
把两种命令组合进真实工作流,常见场景包括:
- 开放路径花边:沿一条曲线(如字形内的装饰弧线)铺放开放轮廓瓦片,利用 First/Final/Isolated 瓦片封住两端,做出连续不断裂的花边;
- 闭合区域边框:对字形内部的闭合轮廓直接执行 Tile Path,Medial 瓦片会自动环绕闭合曲线一周,适合做字母描边内的重复纹样;
- 底纹填充:先用 Tile Pattern 铺满图层,再用
Element → Overlap → Intersect与目标轮廓求交,把矩形底纹裁剪成任意字形区域的纹理——这正是 Type 3 图案瓦片的低成本替代方案; - 非矩形扭曲:铺完后使用 Transform 对整块图案做斜切/透视等变换,模拟编织、织物等非规则纹理。
小结
- Tile Path把自绘瓦片沿选中路径复制、弯曲、贴合,四种瓦片(First/Medial/Final/Isolated)对应开放/闭合轮廓与端点特化,Left/Center/Right 控制横向对齐,Tile/Scale & Tile/Scale 控制纵向分布;
- Tile Pattern把自绘图案按 m×n 网格铺满图层,配合 Transform 与 Overlap → Intersect 可实现 Type 3 风格图案填充;
- 两者都需
configure --with-tilepath重新编译启用,且不适用于二次曲线字体; - 更完整的菜单说明见 doc/sphinx/ui/menus/elementmenu.rst,对话框细节见 doc/sphinx/ui/dialogs/tilepath.rst,全部底层实现可对照 fontforgeexe/tilepath.c。
- 桌面应用
- 图形学
【免费下载链接】fontforge
Free (libre) font editor for Windows, Mac OS X and GNU+Linux
相关推荐
Caffe Tile Layer 深度解析:沿指定维度复制 Blob 的平铺机制与实战配置
Caffe Tile Layer 深度解析:沿指定维度复制 Blob 的平铺机制与实战配置 本篇技术指南围绕 Caffe 开源深度学习框架中的 Tile (平铺
深度学习计算机视觉PyPTO 逐元素加法算子 `pypto_pro.language.add` 完全指南:Tile-Tile 与 Tile-Scalar 双模式实战
PyPTO 逐元素加法算子 pypto_pro.language.add 完全指南:Tile Tile 与 Tile Scalar 双模式实战 导读 pypto
人工智能编译器模型编译深度学习高性能计算CANNAscendPyPTO 分块(Tiling)配置实战:Cube Tile Shapes 与 Vector Tile Shapes 完全指南
PyPTO 分块(Tiling)配置实战:Cube Tile Shapes 与 Vector Tile Shapes 完全指南 PyPTO(Parallel T
人工智能编译器模型编译深度学习高性能计算CANNAscend
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考