问题描述
我目前正在调试我编写的一些 DirectWrite 代码,因为我在使用非英语字符进行测试时遇到了问题。主要是让多个 Unicode 字符返回正确的索引。
编辑:经过进一步研究,我认为问题是变音符号,应该以某种方式组合额外的字符。 DWRITE_SHAPING_GLYPH_PROPERTIES
字段 isDiacritic
确实为最后一个 Unicode 代码点返回 1。然而,塑造过程似乎根本没有考虑到这些。 GetGlyPHPlacements
为变音符号字形的前进和偏移返回 0。 LSB 大约为 -5,但这不足以偏移到正确的位置。有谁知道 DirectWrite 在塑造过程中应该在哪里考虑变音符号以及如何考虑?
考虑这个字符:œ̃
它显示为一个字符(通过大多数文本编辑器),但有两个代码点:U+0153 U+0303
我如何在 GetGlyphs()
中说明这一点,因为它们是单独的代码点?在我的代码中,它返回两个不同的索引 (177,1123)
和一个集群 (0,0)
。
这就是最终呈现的内容:
这与单独呈现的两个代码点一致,但与实际字符不一致。 GetGlyphs()
返回的实际索引计数为 2。
我的问题如下:
我很抱歉,因为我对字体/Unicode 以及整个塑造过程的内部运作不是很了解。
text_length = len(text.encode('utf-16-le')) // 2
text_buffer = create_unicode_buffer(text,text_length)
self._text_analysis.GenerateResults(self._analyzer,text_buffer,len(text_buffer))
# Formula for text buffer size from Microsoft.
max_glyph_size = int(3 * text_length / 2 + 16)
length = text_length
clusters = (UINT16 * length)()
text_props = (DWRITE_SHAPING_TEXT_PROPERTIES * length)()
indices = (UINT16 * max_glyph_size)()
glyph_props = (DWRITE_SHAPING_GLYPH_PROPERTIES * max_glyph_size)()
actual_count = UINT32()
self._analyzer.GetGlyphs(text_buffer,len(text_buffer),self.font.font_face,False,# sideways
False,# rtl
self._text_analysis.script,# scriptAnalysis
None,# localName
None,# numberSub
None,# typo features
None,# feature range length
0,# feature range
max_glyph_size,# max glyph size
clusters,# cluster map
text_props,# text props
indices,# glyph indices
glyph_props,# glyph pops
byref(actual_count) # glyph count
)
advances = (FLOAT * length)()
offsets = (DWRITE_GLYPH_OFFSET * length)()
self._analyzer.GetGlyPHPlacements(text_buffer,clusters,text_props,text_length,indices,glyph_props,actual_count,self.font.font_metrics.designUnitsPerEm,self._text_analysis.script,self.font.locale,None,advances,offsets)
编辑:这是渲染代码:
def render_single_glyph(self,font_face,indice,advance,offset,metrics):
"""Renders a single glyph using D2D DrawGlyphRun"""
glyph_width,glyph_height,lsb,font_advance = metrics
# Slicing an array turns it into a python object. Maybe a better way to keep it a ctypes value?
new_indice = (UINT16 * 1)(indice)
new_advance = (FLOAT * 1)(advance)
run = self._get_single_glyph_run(font_face,self.font._real_size,new_indice,# indice,new_advance,# advance,pointer(offset),# offset,False)
offset_x = 0
if lsb < 0:
# Negative LSB: we shift the layout rect to the right
# Otherwise we will cut the left part of the glyph
offset_x = math.ceil(abs(lsb))
font_height = (self.font.font_metrics.ascent + self.font.font_metrics.descent) * self.font.font_scale_ratio
# Create new bitmap.
self._create_bitmap(int(math.ceil(glyph_width)),int(math.ceil(font_height)))
# This offsets the characters if needed.
point = D2D_POINT_2F(offset_x,int(math.ceil(font_height)))
self._render_target.BeginDraw()
self._render_target.Clear(transparent)
self._render_target.DrawGlyphRun(point,run,self.brush,DWRITE_MEASURING_MODE_NATURAL)
self._render_target.EndDraw(None,None)
image = wic_decoder.get_image(self._bitmap)
glyph = self.font.create_glyph(image)
glyph.set_bearings(self.font.descent,offset_x,round(advance * self.font.font_scale_ratio)) # baseline,advance
return glyph
解决方法
塑造过程由您的输入控制,即(文本、字体、语言环境、脚本、用户功能)。所有这些都会影响你得到的结果。具体回答您的问题:
这应该从 GetGlyphs() 返回一个索引吗?
这主要由您的字体定义。
我是否应该得到一个指数,或者是否涉及一些魔法 有两个不同的指数,在这个过程的某个阶段,他们 在字形运行中组合?
GetGlyphs() 单次运行。根据每个脚本定义的整形规则和字体中定义的转换,字形可以自由地形成一个簇。
如果我应该得到一个指标,这些是什么过程/功能 指数组合在?也许是我的 ScriptAnalysis 中的错误?尝试去 缩小问题所在。
基本上,如果你的输入参数是正确的,你就会得到你所得到的输出,你无法真正控制它的核心。您可以做的是在 Uniscribe、CoreText (macos) 和 Chromium/Firefox (harfbuzz) 上测试相同文本和字体的输出,看看它们是否不同。
我应该使用字符的长度而不是包含 代码点?
我没有得到这个。