如何检测OTF字体中同一字符的多语言字形并在Jupyter中渲染?
检查并渲染OTF字体中同一Unicode字符的语言专属字形
Unicode字符\u76F4(对应汉字「直」)在中文里的样式为带竖钩的写法,在日语里则是不带竖钩的横排样式。以下是如何用fonttools检查字体是否包含该字符的日文字形,以及在Jupyter Notebook中渲染它的方法:
一、检查字体是否包含「直」的日文字形
你的字体包含GSUB表,这类语言专属字形通常通过GSUB的**语言系统(Language System)和特性(Feature)**实现(比如日语的JP语言标签)。可以用fonttools解析GSUB表验证:
from fontTools.ttLib import TTFont font_path = "SiYuanHeavyFont.otf" font = TTFont(font_path) # 检查是否支持日语语言系统 gsub = font["GSUB"] lang_systems = gsub.table.LanguageSystemList.LanguageSystemRecord has_japanese = any(ls.LanguageSystemTag == "JP " for ls in lang_systems) print(f"字体是否支持日语语言系统: {has_japanese}") # 检查字符\u76F4是否有日语专属替换规则 char_code = 0x76F4 cmap = font.getBestCmap() base_glyph = cmap.get(char_code) if not base_glyph: print("字体中无该字符基础字形") else: # 遍历GSUB规则查找日语替换字形 for lookup in gsub.table.LookupList.Lookup: for subtable in lookup.SubTable: if hasattr(subtable, 'LangSys') and subtable.LangSys == "JP ": if hasattr(subtable, 'mapping') and base_glyph in subtable.mapping: print(f"找到日语专属字形: {subtable.mapping[base_glyph]}") break
如果上述代码未找到日语字形,说明该字体仅包含「直」的中文字形,没有提供日语地域变体。
二、在Jupyter Notebook中渲染日文字形
PIL的ImageFont默认不会触发GSUB的语言特性,需要用支持OpenType特性的库指定语言标签:
方法1:使用freetype-py指定日语语言特性
import freetype import numpy as np from PIL import Image font_path = "SiYuanHeavyFont.otf" face = freetype.Face(font_path) face.set_char_size(64 * 64) # 设置字号为64(单位:1/64像素) # 指定日语语言标签加载字符 char_code = 0x76F4 face.select_charmap(freetype.FT_ENCODING_UNICODE) face.set_script("han") face.set_language("JP") face.load_char(chr(char_code), freetype.FT_LOAD_RENDER) # 将渲染结果转为PIL图像 glyph_bitmap = face.glyph.bitmap data = np.array(glyph_bitmap.buffer, dtype=np.uint8).reshape(glyph_bitmap.rows, glyph_bitmap.width) image = Image.fromarray(255 - data, mode='L') # 填充到128x128画布 image = image.crop((0, 0, 128, 128)) if image.size >= (128,128) else image.pad((0, 128 - image.height, 128 - image.width, 0), fill=224) image
方法2:使用fonttools生成指定语言的字形
from fontTools.ttLib import TTFont import matplotlib.pyplot as plt from fontTools.pens.cocoaPen import CocoaPen font_path = "SiYuanHeavyFont.otf" font = TTFont(font_path) gsub = font["GSUB"] char_code = 0x76F4 base_glyph = font.getBestCmap()[char_code] japanese_glyph = base_glyph # 应用GSUB日语特性获取替换字形 lookup_index = gsub.getLookupIndexForLangSys("JP ") if lookup_index is not None: for lookup in gsub.table.LookupList.Lookup[:lookup_index+1]: for subtable in lookup.SubTable: if hasattr(subtable, 'mapping') and base_glyph in subtable.mapping: japanese_glyph = subtable.mapping[base_glyph] break # 渲染字形 glyph_set = font.getGlyphSet() glyph = glyph_set[japanese_glyph] pen = CocoaPen(glyph_set) glyph.draw(pen) # 用matplotlib展示 fig, ax = plt.subplots(figsize=(2,2), dpi=64) ax.add_patch(plt.PathPatch(pen.path, facecolor='black')) ax.set_xlim(0, font['hhea'].advanceWidthMax) ax.set_ylim(0, font['head'].unitsPerEm) ax.invert_yaxis() ax.axis('off') plt.show()
内容的提问来源于stack exchange,提问作者martin li
相关产品推荐
相关产品推荐

