您正在输入cudafont
UTF-8 编码的文本。查看源代码,似乎没有任何东西可以处理 UTF-8 - 甚至,如果我没看错的话,也没有任何东西可以将字体中的自然字形顺序重新编码为常规编码:
char c = str[n];
if( c < FirstGlyph || c > LastGlyph )
continue;
c -= FirstGlyph;
... now c will hold glyph data for a character
(来自函数int4 cudaFont::TextExtents
)
这意味着该库在其字符处理方面严重受损。
在以下上下文中,字形仅表示“可以与现有字符或字符组合相关联的特定图像(即,连字“fi”是表示两个字符“f”和“i”的单个字形). 字体还必须定义一种编码(内置的,通过某种约定,例如 PostScript Type 1 字体,或者,在 TrueType/OpenType 字体的情况下,在它们的cmap
表中定义)以将字符代码与其正确的字形相关联.
CUDA 的默认字体 DejaVu Sans 和 DejaVu Sans Mono 是 TrueType 字体并且确实包含一个cmap
表格,因此它们的字形在物理上可以是任意随机顺序——这取决于字体设计者的判断。一种字体可以首先列出它的所有 A 字形,然后是所有 B 字形,依此类推,或者按字面上的任何顺序列出。如果字体包含 Latin-1 的编码表,则该表将在相应字形的字符代码A
和字体的字形位置之间进行转换。如果相同的字体还包含完全不同的编码,例如 EBCDIC,它自己的代码A
(不是基于 ASCII,因此不是“通常的”0x41,而是 0xC1)仍将指向字体中的相同A
字形。
做什么cudafont
完全是另一回事。它假定至少基本 ASCII的字形完全按照该顺序出现,从字体中的第一个字形开始。这意味着除了字体设计者强加的字形顺序之外,您不能使用任何其他字形顺序。此外,由于cudafont
将字符代码限制为仅 8 位,因此您无法访问 6,107 (DejaVu Sans) 和 3,309 (DejaVu Sans Mono) 字符中的任何字符,ASCII 代码 256 之前范围内的字符除外。
我简要浏览了字形集,在我看来它们是按Unicode 顺序排列的。现在,幸运的是(对于cudafont
s 程序员),这确实意味着前 95 个字符是按 ASCII 顺序排列的。
不幸的是,我的西欧读者(通常对 Latin-1 边界之外的任何东西都不感兴趣)——下一个仍然遵循常见的ISO/IEC 8859-1顺序,但是按照惯例,缺少从 0x7F 到 0x9F 的范围。在基于原始 Latin-1 的 Unicode Latin-1 Supplement 中,这些代码表示控制代码并且没有字形表示。
这仍然意味着您无法将 Python 的默认 UTF-8 编码字符串输入其中,但除了纯 ASCII 之外,您也无法指示 Python 将您的文本编码为 Latin-1。Python可以对其进行编码:
text = 'fængsel'
print (text)
print (text.encode('latin-1'))
fængsel
b'f\xe6ngsel'
但由于缺少范围,显示的字符在列表中仅出现 33 个字形:ć
.
解决方案:中间缺少 33 个字符,因此您可以调整(现在)二进制字符串内容以再次匹配物理字形顺序:
btext = bytes([c if c <= 0x7f else c-33 for c in text.encode('latin-1')])
print (btext)
b'f\xc5ngsel'
并且该字符串应该(理论上)最终呈现您的fængsel
.
任何想要访问超出此修复范围的字形的假设用户都不走运,直到cudafont
更新为 (a) 正确使用字体的编码,以及 (b) 支持完整的 Unicode 范围而不是char
仅支持 s。至少它得到了一个简短的提及stb_truetype.h
:
// Todo:
// 非 MS cmaps