算法生成字体:从TrueType原理到Python实现 1. 项目概述当大语言模型遇上字体设计最近在开源社区里闲逛发现了一个让我这个老码农兼设计爱好者眼前一亮的项目fuglede/llama.ttf。初看这个标题你可能和我一样会心一笑——这名字起得真妙直接把当下AI领域最火的“Llama”大语言模型和字体文件的后缀“.ttf”结合在了一起。这可不是什么简单的玩梗而是一个实实在在的、用代码“生成”的字体文件。简单来说llama.ttf是一个完全由程序生成的 TrueType 字体文件。它的每一个字形Glyph也就是我们看到的字母、数字、符号的形状都不是由设计师在字体设计软件比如 Glyphs, FontForge里一笔一画绘制出来的而是通过算法基于字符的 Unicode 码点code point计算出来的。更具体点你可以把它理解为一个“函数字体”输入一个字符的编码经过一套特定的数学规则运算输出这个字符在画布上的轮廓路径。项目作者fuglede巧妙地将这套生成规则与大语言模型 Llama 的名字关联暗示了其“智能生成”的内涵虽然它本身并不依赖AI模型运行。这个项目解决了一个非常有趣的问题如何用最精简、最确定性的方式创造一套完整、可用且具有独特美学的字符集它跳过了传统字体设计中繁复的手工绘制、调整、Hinting微调等流程直接从“规则”到“成品”。对于开发者、创意编程爱好者、以及任何对字体的生成原理感到好奇的人来说llama.ttf都是一个绝佳的学习样本和创意起点。它用大约500KB的代码字体文件本身和开源仓库向我们生动展示了计算机图形学、字体格式与算法美学交叉地带的无限可能。2. 核心思路与设计哲学拆解2.1 从确定性算法到视觉形态llama.ttf的核心设计哲学是“算法生成”和“确定性”。这与我们熟知的“参数化设计”或“程序化生成”一脉相承。传统字体即便是 Helvetica 或 Times New Roman其每个字形的轮廓数据都是预先定义好的静态点坐标序列存储在字体文件中。而llama.ttf则不同它本质上是一个微型程序嵌入在字体中的函数这个程序定义了如何根据给定的字符编码来“画”出这个字。那么这个“函数”具体是什么呢虽然项目源码是开箱即用的但理解其背后的数学逻辑更有趣。通常这类生成式字体会利用字符编码一个整数作为随机种子或输入参数通过一系列三角函数如sin,cos、噪声函数、分形公式或坐标变换来计算构成字形轮廓的贝塞尔曲线控制点。例如一个非常简化的伪代码思路可能是def generate_glyph(code_point): # 以 Unicode 码点为种子生成确定性但看似随机的序列 seed hash(code_point) random.seed(seed) # 定义轮廓路径 path [] start_point (0, 0) path.append(start_point) # 基于种子生成一系列控制点例如利用正弦波调制 for i in range(num_points): angle 2 * math.pi * i / num_points radius base_radius random_variation * math.sin(frequency * angle seed) x radius * math.cos(angle) center_x y radius * math.sin(angle) center_y # 将 (x, y) 转换为贝塞尔曲线控制点逻辑... path.append(control_point) # 闭合路径形成轮廓 return make_contour(path)llama.ttf的算法可能比这更精巧它需要确保生成的形状1) 对于同一个编码每次生成都完全相同确定性2) 不同字符之间形态有足够区分度3) 整体风格协调统一4) 最终生成的轮廓符合 TrueType 格式规范能被操作系统和渲染引擎正确解析。注意这里的“随机”是伪随机完全由输入决定。这使得llama.ttf在任何设备、任何时间渲染同一个字符其形状都绝对一致这是它作为一款实用字体的基础。2.2 TrueType 格式的嵌入式程序fpgm与glyf要深入理解llama.ttf必须对 TrueType 字体格式有个基本认识。TrueType 字体不仅包含轮廓数据还包含一套简单的指令集用于在渲染时进行网格拟合Grid-fitting和提示Hinting以保证在小字号下的显示清晰度。这些指令存储在fpgm字体程序、prep控制值程序和glyf字形数据等表中。llama.ttf的魔法就藏在glyf表中。通常glyf表直接存放每个字形轮廓的坐标点和指令。但在llama.ttf中许多字形特别是那些非预设的的glyf数据可能非常简略甚至只包含一个“调用生成函数”的指令。真正的轮廓生成逻辑被编译成 TrueType 指令放在了fpgm表中。当渲染引擎需要显示某个字符时它会执行fpgm中对应的函数动态计算出该字形的轮廓。这种设计带来了巨大的灵活性。一个只有几十KB的llama.ttf文件理论上可以“生成”Unicode标准支持的所有十几万个字符只要它的生成算法能覆盖这些码点。而传统的字体文件如果包含全部字符体积可能达到数MB甚至数十MB。实操心得我第一次尝试剖析这类字体时直接用传统的字体查看工具如 FontForge打开发现很多字形显示为空白或极简的占位符一度以为字体损坏了。后来才明白需要在一个真正执行 TrueType 指令的环境比如操作系统自带的字体渲染器或者某些支持完整指令解释的测试工具中查看才能看到动态生成的完整字形。这提醒我们分析工具的选择必须匹配分析对象的特性。2.3 风格统一性与可读性的平衡用算法生成字体最大的挑战之一是风格统一和基础可读性。完全随机的函数容易产生一堆难以辨认的、杂乱无章的图形那只能算“艺术图案”而非“字体”。llama.ttf的成功之处在于它的生成规则必然包含了一系列约束条件使得生成的字符具有相似的视觉权重字符的“粗细”感大致相同不会出现一个字母细如发丝另一个粗如黑体。维持基本的结构例如字母 “o”, “c”, “e” 会保持一个类似的圆形或椭圆形腔体字母 “l”, “i”, “t” 会具有垂直的骨干。拥有共同的细节特征比如笔画末端的处理方式平头、圆头、尖角、转折处的弧度、可能存在的装饰性元素等在整个字符集中保持一致。作者fuglede很可能采用了一种“基于网格或骨架”的生成方法。先为每一类字符如大写字母、小写字母、数字定义一个抽象的“模板骨架”或“特征参数范围”然后让算法在这个框架内进行随机但确定性的变形。例如所有大写字母的高度和宽度被限定在一个固定比例内所有圆形字符的“圆度”参数来自同一个分布。一个可供借鉴的设计思路表字符类别可控参数示例生成规则目的大写字母统一Cap Height大写字母高度控制Width宽度范围固定Stem Width主干笔画宽度确保大写字母整体挺拔、规整易于成词阅读。小写字母定义x-height小写字母主体高度ascender/descender上下延伸部比例笔画末端样式。形成流畅的文本流颜色texture保证小写单词的易读性。数字统一数字宽度确保“0”与“O”有显著区别“1”与“l”和“I”区分开。防止在代码或表格中造成混淆。标点符号基于基础几何图形圆点、线条、弧线生成尺寸与字母笔画宽度关联。保持文本节奏不喧宾夺主。通过这样一套参数化系统llama.ttf在“每个字符独一无二”和“整体看起来是一家人”之间找到了平衡点使其既有趣又实用。3. 技术实现深度解析3.1 核心工具链Python 与 fontTools要创建像llama.ttf这样的字体离不开强大的工具链。从项目源码和常见的生成式字体实践来看Python 语言和fontTools库是绝对的核心。fontTools是一个用于处理字体文件的瑞士军刀式的Python库。它能够解析、创建、编辑各种字体格式TTF, OTF, WOFF等的底层二进制数据让我们能以编程方式操作字体中的每一个表table每一条轮廓contour每一个控制点control point。创建llama.ttf的基本流程可以概括为以下几步这些步骤清晰地揭示了其技术实现路径设计与实现生成算法在Python中编写核心函数如generate_glyph_from_codepoint(codepoint)。这个函数接受一个Unicode码点返回一个表示字形轮廓的数据结构通常是一个由fontTools的PenAPI如TTContourPen所构建的对象。创建空字体骨架使用fontTools.ttLib.TTFont()创建一个新的空TTF对象。然后你需要填充其必需的字体表最基本的有cmap字符编码到字形索引的映射表。告诉系统“字符A对应字形列表中的第几个”。glyf字形轮廓数据表。这里将存放我们生成或计算出的轮廓。locaglyf表中每个字形数据起始位置的索引表。head,hhea,hmtx,maxp,name,OS/2,post等这些表包含了字体的全局元信息如版本、度量标准字间距、行高、字体名称、版权信息等。这些信息需要被正确设置字体才能被系统识别和使用。批量生成与填充遍历你想要支持的Unicode字符范围例如 Basic Latin, Latin-1 Supplement对每个码点调用生成算法将得到的轮廓对象依次添加到字体对象的glyf表中并同步更新cmap和loca表。编译与导出最后调用字体对象的save(llama.ttf)方法fontTools会将所有内存中的数据结构编译成符合标准的、二进制的.ttf文件。一个简化的代码框架示例from fontTools.ttLib import TTFont from fontTools.pens.ttContourPen import TTContourPen from fontTools.fontBuilder import FontBuilder import math def my_glyph_generator(codepoint, width600): 一个极其简单的圆形生成器示例 pen TTContourPen(None) # 在实际中需要传入glyphSet # 以码点影响圆的大小和位置 radius 50 (codepoint % 20) center_x, center_y width // 2, 300 # 用贝塞尔曲线画一个近似圆四个三次贝塞尔曲线段 # 这里省略具体的贝塞尔曲线控制点计算... # pen.moveTo(...), pen.curveTo(...) ... pen.closePath() return pen def build_llama_font(): fb FontBuilder(unitsPerEm1000) # 设置字体坐标系精度 fb.setupGlyphOrder([.notdef, A, B, C]) # 字形顺序.notdef是必需的 # 设置字体度量信息 fb.setupHorizontalMetrics({“A”: (600, 50), “B”: (600, 50), “C”: (600, 50)}) fb.setupHorizontalHeader(ascent800, descent-200) fb.setupNameTable({familyName: Llama Generated}) fb.setupOS2(sTypoAscender800, usWeightClass400) glyphs {} pen_class TTContourPen # 为每个字形调用生成器 for name in [“A”, “B”, “C”]: codepoint ord(name) pen my_glyph_generator(codepoint) # 将pen的轮廓数据转换为glyf表需要的格式 # 这里需要更复杂的转换实际使用fontBuilder的addGlyph方法 # fb.addGlyph(name, glyphObject) # 保存字体 fb.save(llama_demo.ttf)注意以上代码仅为概念演示真实项目如fuglede/llama.ttf的生成逻辑和与fontTools的集成要复杂和严谨得多。重点是理解“算法生成轮廓” - “编程填充字体表” - “导出标准文件”这个核心流水线。3.2 轮廓描述从数学函数到贝塞尔曲线无论算法多么复杂最终输出给字体文件的必须是计算机能够渲染的轮廓描述。在 TrueType 和 PostScript 轮廓用于 OTF中这主要依靠贝塞尔曲线。二次贝塞尔曲线TrueType 格式使用。由三个点定义一个起点、一个控制点、一个终点。控制点决定了曲线的弯曲方向和程度。三次贝塞尔曲线PostScript/OpenType 格式使用。由四个点定义起点、两个控制点、终点。表达能力更强能描述更复杂的曲线。我们的生成算法其最终任务就是计算出一系列有序的、构成字形外轮廓和内轮廓如果有洞比如字母‘O’、‘B’的贝塞尔曲线控制点坐标。例如要生成一个波浪形的边缘算法可能会这样计算控制点# 假设沿着一条水平基线生成波浪 baseline_y 0 points [] for x in range(0, width, step): # 使用正弦波计算y坐标的偏移codepoint影响频率和振幅 frequency 0.1 (codepoint % 100) / 1000.0 amplitude 30 (codepoint // 100 % 20) y baseline_y amplitude * math.sin(frequency * x) points.append((x, y)) # 然后将这些 points 转换为平滑的贝塞尔曲线控制点序列 # 这通常涉及曲线拟合算法如Ramer-Douglas-Peucker算法简化点集再转为贝塞尔曲线。将数学函数输出的坐标点序列通过曲线拟合算法转换成紧凑而平滑的贝塞尔曲线描述是生成式字体技术中的关键一步直接影响到最终字体的文件大小和渲染质量。3.3 性能考量与优化策略动态生成听起来很酷但会带来性能问题吗毕竟每次显示文字都要计算一遍会不会很慢这是一个非常好的问题。实际上llama.ttf的“生成”主要发生在字体安装或首次加载时而不是每次渲染屏幕文字时。现代操作系统和应用程序的字体渲染引擎如 FreeType在加载一个字体时会解析其glyf表并将轮廓数据无论是静态的还是通过fpgm指令动态计算出的缓存在内存中转换成栅格化所需的图形数据。对于llama.ttf这种包含生成指令的字体渲染引擎在首次遇到某个字形时会执行其生成指令计算出轮廓然后将这个轮廓数据缓存起来。之后再次遇到同一个字符就直接使用缓存的结果无需重新计算。因此对于用户而言除了首次打开一个包含大量该字体字符的文档时可能会有极短暂的延迟用于生成和缓存日常使用中几乎感知不到性能差异。优化策略预生成常用字符集为了极致优化字体开发者可以预生成 ASCII 字符集0-127或拉丁字母等最常用字符的静态轮廓直接存储在glyf表中。对于不常用的扩展字符再使用动态生成。llama.ttf可能就采用了这种混合策略。简化生成算法确保fpgm中的生成指令尽可能高效避免复杂的循环或数学运算。用整数运算代替浮点运算利用查表法等。利用prep表prep表在字体加载初期执行可以在这里进行一些全局性的初始化计算将结果存储在字体特定的存储区域Storage Area中供各个字形的生成指令共享使用避免重复计算。4. 应用场景与创意延伸4.1 教育与研究理解字体与算法的窗口llama.ttf首先是一个绝佳的教育工具。对于计算机图形学、字体设计、创意编程的学生和爱好者来说阅读和分析其源码如果开源或理解其概念是一次深度的学习之旅。学习字体格式通过尝试复现一个简单的生成式字体你会被迫去理解cmap,glyf,loca,head等字体表的具体作用和数据结构这比单纯阅读规范文档要生动得多。理解程序化设计它将“参数化设计”和“生成艺术”的概念落到了一个非常具体的产物上。你可以通过调整算法中的几个参数如噪声种子、振幅、频率观察整个字体风格如何系统性变化直观感受算法与视觉输出的关系。跨学科实践这个项目完美结合了编程、数学几何、三角函数、设计排版、字体美学等多个领域是STEAM教育的优秀案例。4.2 设计与创意独一无二的视觉资产对于设计师和艺术家llama.ttf提供了全新的创作思路。品牌定制字体可以为某个品牌或活动快速生成一套独一无二的、算法驱动的字体。只需将品牌名称、核心数字如成立年份或其他特征数据作为算法输入的一部分就能生成具有专属“DNA”的字符集。例如用品牌LOGO的轮廓特征函数来调制字母形状。动态视觉识别在数字媒体或交互装置中字体的形态可以根据环境数据如实时天气、股票指数、社交媒体情绪动态变化。虽然llama.ttf本身是静态的但其原理可以扩展到实时生成领域创造“活”的排版。艺术字体创作摆脱手工绘制的限制探索用物理模拟如粒子系统、引力模型、自然形态如林檎、水流、结晶的算法来生成字体创造出人类手绘难以企及的复杂有机形态。4.3 开发与产品功能性与趣味性的结合在软件开发领域生成式字体也有其用武之地。占位符与测试文本在UI/UX设计和前端开发中经常需要“Lorem Ipsum”这样的占位文本。你可以创建一个生成式字体专门用于生成看似合理但毫无意义的单词形状避免测试时被真实文字内容干扰。llama.ttf的风格如果足够抽象就能很好地服务于这个场景。防机器识别与隐私保护在某些需要展示用户信息但又想防止爬虫轻易OCR识别的场景可以使用生成式字体对数字、字母进行轻微但确定性的扭曲。对于人类来说经过训练的我们很容易适应并识别但对于基于标准字体训练的OCR模型识别率会显著下降。这比简单的验证码更优雅。游戏与沉浸式体验在独立游戏或艺术游戏中使用生成式字体来渲染游戏内的虚构文字、魔法符文或外星语言可以极大地增强世界观的独特性和沉浸感。每个存档、每个玩家看到的“符文”都可以略有不同但又是根据游戏内种子确定生成的。4.4 个人挑战与黑客精神最后对于像我这样的技术爱好者fuglede/llama.ttf项目本身就是一种“黑客精神”的体现——用技术探索一个传统领域的边界并创造出有趣的东西。尝试自己动手实现一个迷你版的“生成式TTF”是巩固相关知识、获得巨大成就感的最佳方式。你可以从一个更简单的目标开始生成一套仅包含26个英文字母的、基于规则的点阵字体。先不用考虑复杂的贝塞尔曲线只用黑白像素。这个过程中你会遇到并解决编码映射、数据存储、文件格式等核心问题。之后再升级到轮廓字体挑战会更大但路径已经清晰。5. 实操从零开始理解与使用llama.ttf5.1 获取与安装假设项目托管在 GitHub 上这是最可能的情况你可以通过以下步骤获取它访问仓库在浏览器中打开https://github.com/fuglede/llama.ttf。下载字体文件在仓库的Release发布页面或根目录下找到llama.ttf或类似名称的字体文件可能是.ttf或.otf格式。点击下载。安装字体Windows右键点击下载的.ttf文件选择“安装”。或将其复制到C:\Windows\Fonts目录。macOS双击.ttf文件会打开“字体册”应用点击窗口右下角的“安装字体”按钮。Linux将文件复制到~/.local/share/fonts/用户级或/usr/share/fonts/系统级需要sudo权限目录然后运行fc-cache -fv更新字体缓存。安装成功后你就可以在文字处理软件如 Word, Pages、设计软件如 Photoshop, Illustrator或代码编辑器中选择并使用“Llama”或项目指定的字体名称了。5.2 在代码中探索与验证仅仅使用还不够我们想“看”到它的生成特性。可以写一个简单的Python脚本来验证。步骤一使用fontTools探查结构from fontTools.ttLib import TTFont font_path path/to/your/llama.ttf font TTFont(font_path) # 1. 查看字体包含哪些表 print(字体包含的表:, list(font.keys())) # 2. 查看 cmap 表了解编码映射 cmap_table font[cmap] for cmap in cmap_table.tables: if cmap.isUnicode(): print(fUnicode 子表格式: {cmap.format}) # 可以打印前几个映射关系示例 items list(cmap.cmap.items())[:5] print(示例映射 (编码 - 字形索引):, items) # 3. 查看 glyf 表关注其结构 glyf_table font[glyf] glyph_order font.getGlyphOrder() print(f\n字体共包含 {len(glyph_order)} 个字形) print(前10个字形名称:, glyph_order[:10]) # 4. 检查特定字形如大写字母A的数据 glyph_name A # 需要根据实际的cmap映射找到正确的字形名 if glyph_name in glyf_table: glyph glyf_table[glyph_name] print(f\n字形 {glyph_name} 的信息:) print(f 轮廓数量: {getattr(glyph, numberOfContours, N/A)}) print(f 是否包含指令: {hasattr(glyph, program) and len(glyph.program) 0}) # 如果 numberOfContours 很简单如0或-1而又有program可能是生成式字形 if glyph.numberOfContours 0 and hasattr(glyph, program): print( - 这可能是一个复合字形或依赖指令生成的简单字形。)这个脚本能帮你判断llama.ttf中是否存在大量轮廓简单但包含程序指令的字形这是生成式字体的一个特征。步骤二视觉化渲染对比为了直观感受我们可以用PIL(Python Imaging Library) 或cairo来渲染字体并与系统默认字体对比。from PIL import Image, ImageDraw, ImageFont import matplotlib.pyplot as plt text_to_render Hello Llama 012345 font_size 40 # 使用 llama.ttf try: llama_font ImageFont.truetype(llama.ttf, font_size) except IOError: print(请确保 llama.ttf 在正确路径。) llama_font ImageFont.load_default() # 使用系统默认无衬线字体如Arial default_font ImageFont.load_default() # 或者指定一个已知字体路径 # 创建画布 img_llama Image.new(RGB, (600, 100), colorwhite) img_default Image.new(RGB, (600, 100), colorwhite) draw_llama ImageDraw.Draw(img_llama) draw_default ImageDraw.Draw(img_default) # 绘制文字 draw_llama.text((10, 30), text_to_render, fontllama_font, fillblack) draw_default.text((10, 30), text_to_render, fontdefault_font, fillblack) # 并排显示 fig, axes plt.subplots(1, 2, figsize(12, 5)) axes[0].imshow(img_llama) axes[0].set_title(Rendered with llama.ttf) axes[0].axis(off) axes[1].imshow(img_default) axes[1].set_title(Rendered with Default Font) axes[1].axis(off) plt.show()通过并排对比你可以清晰地看到llama.ttf独特的、由算法生成的字形风格观察其字母、数字的形态是否协调统一以及其作为一款字体的基本可读性如何。5.3 尝试修改与二次创作如果你胆子大一点甚至可以用fontTools对llama.ttf进行微调。请注意务必尊重原作者的许可证通常是开源许可证如MIT、OFL在允许的范围内进行修改并保留原署名。一个安全的二次创作起点是修改字体的元信息name表from fontTools.ttLib import TTFont font TTFont(llama.ttf) # 获取 name 表 name_table font[name] # 修改字体家族名例如添加你的后缀 for record in name_table.names: if record.nameID 1: # Font Family name original_name record.toUnicode() new_name original_name Modified # 需要根据平台和编码创建新的记录这里简化处理 # 实际中更推荐使用 fontTools 的 setName 方法或更高级的库 print(f将字体名从 {original_name} 修改为 {new_name}) # 此处省略具体的修改代码涉及编码和平台ID # 保存为新文件 font.save(llama_modified.ttf)更高级的修改可能涉及调整OS/2表中的字重usWeightClass、宽度usWidthClass甚至是尝试理解并微调其fpgm表中的生成逻辑这需要对 TrueType 指令集有深入了解。6. 常见问题、挑战与排查思路在探索和使用像llama.ttf这类生成式字体的过程中你可能会遇到一些典型问题。以下是我根据经验总结的排查清单问题现象可能原因排查思路与解决方案字体安装后在某些软件中不显示或显示为空白/方框1. 字体文件损坏。2. 字体缺少关键的表如cmap。3. 软件字体渲染引擎不支持该字体中的某些高级特性如复杂的fpgm指令。4. 字体命名name表不规范导致系统索引失败。1. 重新下载字体文件检查MD5/SHA校验和。2. 用fontTools或在线字体验证器检查字体基本结构。3.在另一款软件如浏览器、系统文本编辑器中尝试。如果浏览器可以显示而专业设计软件不行可能是后者对非标准字体的兼容性问题。4. 使用字体管理工具如 Font Book on macOS查看字体详情确认其“PostScript名称”、“全名”等是否正常。字体渲染异常出现锯齿、破碎或错位1. 字体自身的Hinting微调指令缺失或错误。2. 生成算法在极端情况下如极小字号产生了自相交或无效的轮廓路径。3. 渲染引擎的缓存问题。1. 尝试在不同字号如12pt, 24pt, 72pt下查看如果只有小字号有问题很可能是Hinting问题。生成式字体通常不包含精细的Hinting。2. 在矢量软件如 Illustrator中放大查看轮廓检查路径是否干净。这可能是字体本身的bug。3. 清除系统或应用的字体缓存后重试。想扩展字符集如支持中文但不知如何下手生成算法可能只针对特定编码范围如拉丁字母设计其规则不适用于结构完全不同的文字如汉字。1.分析源码查看生成函数是否根据码点范围使用了不同的规则集。2.分而治之可以为汉字设计另一套完全独立的生成规则例如基于部首、笔画数的组合算法然后在字体中并存两套逻辑。3.务实选择对于象形文字算法生成极具挑战性。更可行的方案是将生成式字体作为西文部分中文字体部分使用传统静态字体或另一套算法做成一个“复合字体”。自己仿写的生成字体文件巨大或渲染极慢1. 为每个字符都生成了极其复杂的轮廓控制点过多。2. 生成算法效率低下每次渲染都进行大量计算。3. 没有利用字体格式的缓存机制。1.简化轮廓在保证识别度的前提下减少每个轮廓的控制点数量。使用曲线拟合算法来优化。2.预计算与缓存考虑在字体创建阶段build time就计算好所有常用字符的轮廓而不是将计算逻辑留在fpgm中运行时执行。3.性能分析用工具如ttxfontTools的一部分将字体反编译成XML查看glyf表数据量优化生成逻辑。生成的字体风格不统一看起来杂乱生成规则中的随机性或可变参数范围设置过大缺乏全局约束。1.引入“母版”参数定义几个全局性的风格变量如“圆度系数”、“笔画宽度”、“倾斜度”所有字符的生成都基于这几个变量进行微调而不是完全独立随机。2.使用一致的噪声源使用一个全局的、基于字体“种子”值的伪随机序列而不是每个字符独立随机能保证不同字符间的随机扰动具有相关性从而形成统一质感。3.分层生成先确定字母的基本骨架如H的竖线、O的椭圆再在这个骨架上添加装饰性细节细节的生成规则保持一致。最后的个人体会折腾像llama.ttf这样的项目最大的收获不是最终得到了一个多酷的字体而是打通了从抽象算法到具体视觉产物之间的认知路径。它让你明白屏幕上每一个看似理所当然的字母形状背后都可以是一段简洁的数学公式或逻辑规则。这种将逻辑、数学与美学连接起来的能力是编程和创造中最令人兴奋的部分。下次当你再选择一款字体时或许你会多想一想它是如何被创造出来的而我是否也可以用代码创造出属于自己独一无二的视觉语言这扇门fuglede/llama.ttf已经为我们推开了一道缝。