首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用枕头绘制TrueType小帽文本

使用枕头绘制TrueType小帽文本
EN

Stack Overflow用户
提问于 2020-02-12 19:39:48
回答 1查看 616关注 0票数 1

我用枕头在图片上画文字:

代码语言:javascript
复制
from PIL import Image, ImageDraw, ImageFont

im = Image.new("L", (400, 50), color="black")
draw = ImageDraw.Draw(im)
font = ImageFont.truetype("Roboto-Medium.ttf", 28)
draw.text((0, 0), "How To Get Small Caps?", font=font, fill="white")
im.save('small_caps.png')

但我想不出如何用小写字母而不是普通字符来画字符串。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-13 00:00:16

最新版本的Roboto介质确实包含实际绘制到大小的小大写,但它们没有映射到Unicode代码点。这意味着在简单字符串中指定字符的常规方法将无法工作。

OpenType感知软件可以通过OpenType feature c2sc (它用大写字母替换大写字母的等价物)和smcp (做同样的操作,但只用于小写字母)访问字体。这些翻译表驻留在TrueType GSUB表中的字体中--它们是以一种特别狡猾的格式编码的。这可能就是为什么PIL程序员从来不去实现它的原因(以及其他可能有用的OpenType特性,例如每种语言的超级和订阅、克尔宁和本地化信函表单)。

Python模块freetype可以访问原始符号。但是,类似地,FreeType开发人员也曾短暂地考虑过将OpenType特性解析添加到他们的库中,但是决定不这样做,并且FreeType只关注于绘图。尽管如此,您仍然可以使用freetype获取所有字体中的任何字形并对其进行栅格化。唯一的问题是,您将对字形索引进行硬编码。

“字形索引”只不过是‘什么编码值对应于哪个图像’,从0开始,一直持续到最后一个字形。字体的可能编码位于字体数据的其他地方;它可能包含解密的Windows编码(ol的“代码页”(但更大))、完整的Unicode编码、MacRoman和少量的其他编码。您只需选择一个编码,并告诉您在该编码中的字符代码,freetype将为您查找正确的字形。

但是OpenType特性可以推翻这一点。它是一组独立的翻译,由您选择的特性(以及哪个脚本,甚至是哪种语言)驱动。一个完全了解OpenType的界面将看到您的字形,使用所需的特性增加赌注,并返回原始的字形索引。

由于单个字体文件中可能有很多原始的象形文字,所以并不是每个编码都指向字体中的每个字形。例如,想象一下可怜的旧MacRoman,只有256个可能的字符。你不可能用它来处理所有的机器人1294个符号。即使是具有成千上万个定义条目的Unicode也无法解决所有这些问题,因为可以为某些字符(如斜杠大写)创建风格替代方案,就Unicode而言,这些字符与它们的原始字符相同,以及用作连接的字符组合,其中像Zapfino这样的完整序列被绘制成一个单一的复杂字形(字体为"Zapfino";而且非常棒)。

一些字体设计器允许通过‘私有’Unicode代码点访问特殊字符(意思是“每个人都可以自由定义”),但我认为Roboto没有这种功能。

可以向FreeType请求完整的GSUB表,然后解析这个表以找到适合于小型股的翻译,如果这样做,您会很高兴地发现,您的代码随后将与任何字体一起使用真正的小大写(!),但这是一项巨大的工作。

所以我作弊了。有些软件允许对字体进行每张字形检查,我使用AdobeA..Z查找所有A..Z的小盘字形索引。

不过,这确实有缺点。它只适用于Roboto媒体的一个特定版本(可靠),因为设计人员可以为每个新版本添加、删除和移动图形。记住,这对其他软件如何处理字体没有任何影响!对编码表和OpenType表进行了调整以匹配,因此软件不需要了解每种字体的字形索引。

也不能保证中的这些相同的索引能够与Roboto家族中的其他字体一起工作。设计人员可能使用了完全相同的布局,但可能没有。实际上,正如上面所述,他们甚至不应该去关心它。

我已经下载了最新版本2.137;2017年;如果你没有这个版本,请先下载!

下面是一些示例代码,用于打印所有小盘字形的灰度值,它们的水平偏移距字形起始点(左偏移距)和垂直高度(以像素为单位),从基线测量。随意调整以匹配PIL自己的文本绘图例程;它可能需要一些细节才能得到正确的™。

(对相当基本的代码示例表示歉意。我设法破坏了Python2.7和3(某样东西)的PIL安装,因此我无法以图形方式显示一些东西;幸运的是,freetype模块仍然工作。

代码语言:javascript
复制
import freetype
import os.path

smcapGlyphs = [563,562,561,560,552,486,485,484,483,482,481,480,479,
 478,477,476,475,474,473,472,471,470,469,468,467,466]

def dump_bytes(buf,wide,high):
    for y in range(high):
        for x in range(wide):
            print ('%02x ' % buf[y*wide+x], end='')
        print ()

face = freetype.Face(os.path.expanduser('~')+"/Library/Fonts/Roboto-Medium.ttf")
face.set_char_size( 48*64 )

for index,i in enumerate(smcapGlyphs):
    face.load_glyph(i)

    print (chr(65+index))
    bitmap = face.glyph.bitmap
    width  = face.glyph.bitmap.width
    rows   = face.glyph.bitmap.rows
    pitch = face.glyph.bitmap.pitch
    print (face.glyph.bitmap_left)
    print (face.glyph.bitmap_top)

    dump_bytes (bitmap.buffer, pitch,rows)
    print ()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60195738

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档