印刷复制和显示技术的发展已经并将继续影响人类文化。15世纪德国约翰内斯·古腾堡(Johannes Gutenberg)利用铅铸字母开发的早期印刷技术为提高识字率和科学革命提供了催化剂。自动排版机,如19世纪发明的列印机,改变了信息的生产、分发和消费方式。在数字时代,自从上世纪80年代个人电脑的普及和90年代互联网的快速发展以来,我们的文本消费方式已经发生了巨大的变化。电子邮件、网站和即时消息中的文本充斥着电脑屏幕,尽管过去的许多排版规则都适用,屏幕上的字体需要额外考虑,以增强沟通和易读性。
屏幕上的字母是通过设置像素的颜色创建的。排版的质量受到屏幕分辨率的限制。因为在历史上,屏幕的分辨率比纸低,所以人们开发了一些技术来增强屏幕上字体的外观。最早的苹果Macintosh电脑上的字体由10、12和24点等特定大小的小位图图像组成。利用这项技术,每种字体的变体都是为特定字体的每种大小而设计的。例如,旧金山字体中的字符A使用不同的图像来显示大小为12和18的字符。1985年激光打印机问世时,Postscript技术定义了字体,并对每个字符的轮廓进行了数学描述。这使得屏幕上的字体可以缩放到大尺寸,并且看起来仍然很平滑。苹果和微软后来开发了TrueType,另一种大纲字体格式。最近,这些技术被合并到OpenType格式中。同时介绍了在屏幕上平滑文本的方法。这些消除混叠技术使用字符边缘的灰色像素来补偿低屏幕分辨率。
20世纪80年代中期个人电脑的激增催生了一个快速排版实验的时期。数字字体是软件,旧的金属和照片字体规则不再适用。被称为莱特罗的荷兰印刷师解释说:“工业上生产印刷术的方法意味着所有的字母都必须是相同的……印刷术现在是用先进的设备来生产的,而这些设备并没有强加这样的规则。唯一的限制是在我们的期望中。”1莱特罗用他们的字体Beowolf扩展了排版的可能性(第131页)。它以不同的方式打印每一个字母,例如,每次打印A时,它将具有不同的形状。在这段时间里,Zuzana Licko和Barry Deck等印刷师借助新的软件工具创造出了创新的字体。软件的灵活性使得大量的字体恢复和历史性的敬意,如罗伯特斯利姆巴赫的Adobe Garamond和Jonathan Hoefler的Proteus项目。通过软件字体工具,诸如fi和æ等字母对之间的连字连接之类的印刷细微差别——由于现代机械化印刷术而变得不切实际——再次繁荣起来。
函数的作用是:在屏幕上绘制字母、单词和段落。在最简单的用法中,第一个参数可以是字符串、char、int或float。第二个和第三个参数设置文本的位置。默认情况下,第二个参数定义从窗口左边缘到窗口顶部的距离;第三个参数定义从文本基线到窗口顶部的距离。函数的作用是:以像素为单位定义字母的大小。用于定义文本大小的数字不是每个字母的精确高度,其差异取决于每个字体的设计。例如,语句textSize(30);不一定要在30像素高处画一个大写的H。函数的作用是:控制文本的颜色和透明度。此函数影响文本的方式与影响矩形()和椭圆()等形状的方式相同,但文本不受stroke()的影响。
fill(0); text("LAX", 0, 40); // 显示 "LAX" 在坐标 (0,40) text("AMS", 0, 70); // 显示 "AMS" 在坐标 (0,70) text("FRA", 0, 100); // 显示 "FRA" 在坐标 (0,100) |
textSize(32); // 文本大小 32 fill(0); text("LAX", 0, 40); text("ORD", 0, 70); text("DAY", 0, 100); |
textSize(32); fill(0); // 填充色为黑色 text("LAX", 0, 40); fill(126); // 填充色为灰色 text("HKG", 0, 70); fill(255); // 填充色为白色 text("PVG", 0, 100); |
textSize(64); fill(0, 140); // 用低不透明度填充黑色 text("8", 0, 60); text("8", 15, 65); text("8", 30, 70); text("8", 45, 75); text("8", 60, 80); |
另一个版本的text()在矩形内绘制字符。在这种情况下,第二个和第三个参数定义框的左上角的位置,第四个和第五个参数定义框的宽度和高度。如果文本长度超过定义框的尺寸,则不会显示文本。
String s = "Five hexing wizard bots jump quickly."; fill(0); text(s, 10, 10, 60, 80); |
String s = "Five hexing wizard bots jump quickly."; fill(0); text(s, 10, 10, 60, 55); // Box too small |
本章中的示例是第一个将外部媒体加载到草图中的示例。到目前为止,所有示例都只使用了在处理过程中通过绘图函数(如line()和elliple())生成的图形。处理能够加载和显示其他媒体,包括字体、图像、矢量文件、格式化数据和声音。本章着重于加载字体,其他章节讨论有关其他媒体类型的特定信息,但有关加载适用于所有类别的媒体的一些内容。这里讨论这些相似之处。
在处理草图中使用外部媒体之前,需要在每次运行程序时加载它。媒体可以直接从草图的文件夹、计算机上的另一个位置或通过Internet加载。通常,媒体直接从草图的文件夹加载。介质通常放在称为数据的文件夹中;有三种方法可以将介质放入此文件夹:
要确认文件已正确添加,请从“草图”菜单中选择“显示草图文件夹”。文件将在数据文件夹中。图像文件放在正确的位置,就可以加载了。请确保将文件格式扩展名作为名称的一部分,并将整个名称用引号括起来(例如,“pup.gif”、“kat.jpg”、“ignatz.png”)。加载文件时,请注意在写入文件名时使用正确的大写字母。如果文件是arch.jpg,尝试加载arch.jpg或arch.jpg将创建错误。另外,避免在文件名中使用空格,这可能会导致问题。
为了使媒体文件可以从程序中的任何位置访问,它们通常被声明为setup()和draw()之外的全局可用变量。文件通常在setup()中加载,因为它们只需要加载一次,而且加载它们需要时间。在draw()中加载文件会降低程序的帧速率,因为这会导致文件重新加载每个帧。在setup()中加载文件后,可以在程序中的任何位置使用该文件。在大多数处理程序中,所有文件都是在程序启动时加载的。
要使用不同于默认字体的字体,需要更多的函数来准备要用于处理的字体。createFont()函数用于转换TrueType字体(.ttf)或OpenType字体(.otf),以便它可以通过text()显示。函数的作用是定义要显示的当前字体。可以使用安装在运行处理的计算机上或存储在草图数据文件夹中的任何兼容字体。以下短程序用于将可用的已安装字体列表打印到控制台:
String[] fontList = PFont.list(); printArray(fontList);
printArray()函数(第420页)用于在新行上写入每个字体。打印到控制台的前几个选项是一般的印刷分类,例如Serif、SansSerif和Monospaced。使用这些选项定义样式,但不定义特定字体。当这个列表是在用来写这本书的计算机上生成的,573个字体选项的列表会打印到控制台上。根据安装的操作系统和自定义字体,计算机将产生不同的结果。该列表以跨平台工作的常规字体类别开始,然后以特定的字体名称继续。以下是我们名单中的一小部分:
[0] "Serif"
[1] "SansSerif"
[2] "Monospaced"
[3] "Dialog"
[4] "DialogInput"
[5] "ACaslonPro-Bold"
…
[567] "ZXX-Sans"
[568] "ZXX-Xed"
[569] "ZapfDingbatsITC"
[570] "Zapfino"
[571] "Ziggurat-Black"
[572] "Ziggurat-BlackItalic"
在程序中使用字体之前,必须将其转换并设置为当前字体。处理有一个称为PFont的唯一数据类型来存储字体数据。创建一个PFont类型的新变量,并使用createFont()函数转换字体。createFont()的第一个参数是要转换的字体的名称,第二个参数定义字体的基本大小。(可选的第三和第四个参数在引用中定义。)然后必须使用textFont()函数设置当前字体。在我们的开发计算机上,要使用上述列表选项571的Ziggurat Black,运行以下代码:
要使此程序在您的计算机上运行,您可能需要修改第5行以使用计算机上的字体。此程序类似于代码12-01,但请注意Ziggurat字体中的字母与默认字体之间的差异。
要确保字体将加载到所有计算机上,无论字体是否已安装,请将文件添加到草图的数据文件夹中。(数据文件夹中的字体不会在控制台列表中打印,如代码12-07所示。)按照第10页的说明将字体添加到数据文件夹中。使用数据文件夹中的字体时,需要将完整的文件名(包括数据类型扩展名)作为参数写入createFont()。下面的示例与前面的示例类似,但它在数据文件夹中使用OpenType字体。它使用源代码Pro,一种可以在线找到并通过web浏览器下载的开源字体。
要在一个程序中使用两种字体,请创建两个PFont变量并使用textFont()函数更改当前字体。基于前面的两个示例,Ziggurat黑色字体从其在本地计算机上的位置加载,源代码Pro从数据文件夹加载。
处理还可以处理字体,将其转换为小图像纹理。这些字体不像为使用createFont()进行处理而转换并与默认渲染器一起使用的字体那样灵活和清晰,但它们更适合与P2D和P3D渲染器一起使用。第547页讨论了渲染器之间的区别。处理使用的像素字体格式是1990年代中期在麻省理工学院媒体实验室视觉语言工作室(VLW)开发的。VLW格式将每个字母数字字符存储为像素网格。这是一种快速呈现文本的方法,可以在不包含矢量数据的情况下在草图中包含字体。
要将字体转换为VLW格式,请从“工具”菜单中选择“创建字体”选项。将打开一个窗口,显示计算机上安装的兼容字体的名称。从列表中选择一种字体,然后单击“确定”。该字体将生成并复制到当前草图的数据文件夹中。若要确保字体存在,请单击“草图”菜单并选择“显示草图文件夹”。创建字体工具提供设置字体大小和选择是否具有平滑、抗锯齿边缘的选项。此工具还提供导出“所有字符”的选项,这意味着字体中的每个字符都将包含在内,因此将增加文件大小。
下面的示例使用与前面的createFont()示例相同的字体。唯一的区别是用loadFont()替换该函数。要运行这些示例,首先使用“创建字体”工具将字体转换为VLW文件。将参数的名称更改为loadFont()以匹配创建的VLW文件的名称。
当字体以与创建时不同的大小绘制时,它会被缩放,因此看起来并不总是那么清晰和平滑。例如,如果字体以12像素创建并以96像素显示,则它将显示为模糊。
为了获得最佳效果,请按照创建字体的大小绘制一个字体。如果同一字体需要以多种大小使用,请考虑以这些精确的大小进行渲染和加载。当在3D中使用VLW字体时,具有不同z坐标的字母有时会遮挡其他字母。这可以用提示来纠正,见第547页。
文本属性
处理包括控制前导(文本行之间的间距)和对齐的函数。处理还可以计算任何字符或字符组的宽度,这是排列形状和排版元素的有用技术。函数的作用是:设置文本行之间的间距。它有一个以像素为单位定义这个空间的参数。
String lines = "L1 L2 L3"; textSize(12); fill(0); textLeading(10); text(lines, 10, 15, 30, 100); textLeading(20); text(lines, 40, 15, 30, 100); textLeading(30); text(lines, 70, 15, 30, 100); |
字母和单词可以从它们的中心、左边缘和右边缘绘制。函数的作用是:通过参数设置绘制文本的对齐方式,参数可以是左对齐、居中对齐或右对齐。它设置字母相对于text()函数中指定的x坐标的显示特征。
fill(0); textSize(12); line(50, 0, 50, 100); textAlign(LEFT); text("Left", 50, 20); textAlign(RIGHT); text("Right", 50, 40); textAlign(CENTER); text("Center", 50, 80); |
textSize()、textLeading()和textAlign()的设置将用于对text()函数的所有后续调用。但是,请注意,text size()函数将重置文本行距,textFont()函数将重置大小和行距。
函数的作用是:计算并返回任何字符或文本字符串的像素宽度。此数字是根据textFont()和textSize()函数定义的当前字体和大小计算的。由于每个字体的字母大小不同,并且许多字体中的字母宽度也不同,因此此函数是了解字符串或字符在屏幕上显示时宽度的唯一方法。因此,请始终使用textWidth()相对于文本定位元素,而不是将它们硬编码到程序中。
String s = "AEIOU"; float tw; // Text width fill(0); textSize(14); tw = textWidth(s); text(s, 4, 40); rect(4, 42, tw, 5); textSize(28); tw = textWidth(s); text(s, 4, 76); rect(4, 78, tw, 5); |
当与键盘结合使用时,将字母画到屏幕上会变得更加引人入胜。第97页中介绍的keyPressed()事件函数可用于记录键入的每个字母。下面的两个例子使用这个函数通过文本章节(第143页)中介绍的字符串方法从键盘读取和分析输入。在这两种情况下,字符串变量字母都以空开头。键入的每个键都添加到字符串的末尾。第一个例子显示了当按下键时字符串的增长,并在按下backspace时从末尾删除字母。第二个例子建立在第一个例子的基础上,当按下回车键或回车键时,程序会检查是否键入了“gray”或“black”。如果输入了其中一个单词,则背景将更改为该值。
许多人每天花几个小时在电脑上输入信件,但这一行动受到很大限制。什么功能可以添加到文本编辑器,使其对打字员更具响应性?例如,打字的速度可以减小字母的大小,或者长时间的停顿可以增加许多空格,模仿一个人说话时的停顿。如果键盘可以记录一个人打字的难易程度(就像钢琴在轻按键时弹奏软音符的方式),并且可以自动分配属性,例如斜体表示软按,粗体表示强按,会怎么样?这些类比说明了当前软件如何保守地对待排版和打字。
许多艺术家和设计师对字体很感兴趣,他们用鼠标、键盘和更奇特的输入设备创造了独特的字体探索方式。一个最小但引人入胜的例子是John Maeda的Type,Tap,Write软件,创建于1998年,是为了向手动打字机致敬。该软件使用键盘作为键盘黑白屏幕表示的输入。按数字键使软件在不同的模式中循环,每个模式都显示了对键盘数据的有趣解释。在Jeffrey Shaw和Dirk Groeneveld的《易读的城市》(1989-91)中,建筑物被三维字母取代,创造出一个符合真实街道的排版城市。例如,在曼哈顿版本中,市长、出租车司机和弗兰克·劳埃德·赖特的短信构成了这座城市。图像显示在投影屏幕上,用户通过踩下并驾驶位于投影图像前面的固定自行车进行导航。像这样的项目表明,软件提供了一个非凡的机会来扩展我们的读写方式。
排版元素可以被指定为定义与鼠标或键盘相关的个性的行为。一个词可以通过向老鼠快速移动来表达攻击,或者慢慢移动可以表达胆怯。下面的例子演示了这个领域的基本应用。在第一种情况下,单词avoid远离鼠标,因为它的位置设置为光标位置的倒数。在第二种情况下,当光标悬停在其位置上时,“挠痒痒”这个词就会抖动。
void setup() { size(100, 100); textSize(24); textAlign(CENTER); } void draw() { background(204); text("avoid", width-mouseX, height-mouseY); } |
一。Ellen Lupton,《用类型思考:设计师、作家、编辑和学生的批判指南》(普林斯顿建筑出版社,2004年),第29页。