and*_*abs 9 directx winapi opentype uniscribe directwrite
完全披露:我正在研究我的libui GUI框架的文本API.这包括Windows上的DirectWrite,OS X上的Core Text和其他Unix上的Pango(它使用HarfBuzz进行OpenType整形).我想要指定的文本格式化属性之一是要使用的OpenType功能的集合,这三者都提供了这些功能.DirectWrite是IDWriteTypography.
现在,当您使用这些库绘制一些文本时,默认情况下您将启用一些有用的OpenType功能,例如标准连字(liga),如f + i连字.我认为这是特定于字体的,但事实证明这是特定于正在形成的文本的脚本.Microsoft为OpenType支持的所有脚本提供了指南(在"特定于脚本的开发"下),我可以看到相当复杂的逻辑,可以在HarfBuzz中完成所有这些以确认它.
在Core Text和Pango上,如果我启用其他属性,它们将被添加到这些默认值之上.但是使用DirectWrite,IDWriteTextLayout::SetTypography()这样做会删除默认值:

可以在此处找到生成此输出的程序.
显然我的第一个选择是询问如何获取DirectWrite的默认功能.但是,有人已经在这个网站上这样做了,答案似乎是"不".
我猜测DirectWrite允许我完全控制要应用于某些文本的功能列表.这很好,除了我不能用其他API做到这一点,除非我以某种方式明确禁用默认功能!当然,我不知道这个列表是否会改变,所以硬编码可能不是最好的主意.
即使硬编码是一种选择,我也可以为每个脚本获取HarfBuzz的列表,但是a)它相当复杂 b)脚本有多种可能的整形器,这取决于(我认为)版本兼容性(例如,缅甸).
那么为什么不使用HarfBuzz的列表来重新创建DirectWrite的默认功能列表呢?它似乎想要对其他塑造者准确,所以这应该工作,对吧?好吧,我需要做两件事:找出要使用的脚本,并找出哪些属性用于脚本中字符的位置重要的脚本.
DirectWrite提供了一个接口IDWriteTextAnalyzer,提供执行整形的工具.我可以使用它,但似乎脚本数据在DWRITE_SCRIPT_ANALYSIS结构中返回,并且脚本ID的描述显示"写入系统脚本的从零开始的索引表示.".
这没有用,所以我编写了一个程序来转储我输入的文本的脚本编号.在输入字符串上运行它
????????????????????????? abcd ???? ??? ??????? ????????? ???????? ?????
Run Code Online (Sandbox Code Playgroud)
产生输出
0 - 26 script 3 shapes 0
26 - 5 script 49 shapes 0
31 - 14 script 3 shapes 0
45 - 2 script 1 shapes 1
47 - 25 script 22 shapes 0
Run Code Online (Sandbox Code Playgroud)
我无法将这些脚本编号与任何Windows标题中的任何内容匹配:如果在任何API中有阿拉伯语,拉丁语或西里尔语的已定义数字,则它们与这些不匹配.即使我确实得到了脚本和脚本编号之间的映射,仍然没有给我应用单词内功能的数据.
Uniscribe怎么样?那么,等效SCRIPT_ANALYSIS类型的文档说它的脚本ID是一个"[opaque]值",其"该成员的值未定义,应用程序不应该依赖于从一个版本到下一个版本的值相同".虽然我可以通过语言代码来识别脚本,但除了LANG_ENGLISH"西方"(拉丁文?)脚本之外,还没有定义的值.DirectWrite值是否与Uniscribe相同?似乎我至少可以通过查看fLinkBefore和fLinkAfter字段来计算单词的初始和最终状态,但这足以正确应用每个脚本的属性吗?
HarfBuzz确实有一个实验性的DirectWrite后端,不适合真正的程序使用 ; 我还不确定它是否具有我在上面指定的相同特征 - 破坏.如果我发现,我会在这里更新这部分.
最后,如果我在kaxaml之类的内容中输入以下第一个等效测试用例:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<FlowDocumentPageViewer>
<FlowDocument FontFamily="Constantia" FontSize="48">
<Paragraph>
afford afire aflight 1/4<LineBreak/>
<Run Typography.Fraction="1">afford afire aflight 1/4</Run>
</Paragraph>
</FlowDocument>
</FlowDocumentPageViewer>
</Grid>
</Page>
Run Code Online (Sandbox Code Playgroud)
即使在后一种情况下,我也看到正确应用了连字:

(在最后的分数只是为了证明该被应用的属性.)如果我想XAML使用DirectWrite的,那么就证明我的第一个选项(简单地覆盖我的自定义上的默认设置的顶部属性)应该是可能的...(我根据XAML为Direct2D提供了一个与绘制2D图形非常相似的API的想法做了这个假设,并且填充了很多漏洞,我不得不手动编写大量的胶水代码来与vanilla Direct2D做同样的事情,所以我假设在XAML中可能的任何东西都可以使用Direct2D,并且扩展为DirectWrite,因为它们在技术上一起引入......)
在这一点上,我完全迷失了.我希望至少可以跨平台进行预测,而且我不确定程序是否应该直接使用OpenType功能,或者无论如何都不应该使用OpenType功能.我对文本布局API的期望不高吗?如果我想要这个,我是否必须丢弃IDWriteTextLayout并自行完成所有文本整形和布局?
或者我是否必须删除vanilla Windows 7支持并升级到Platform Update DirectWrite功能集?甚至完全是Windows 7?
在与 Peter Sikking 和 Ebrahim Byagowi 进行一些讨论后,我去调试了一个我快速构建的更通用的程序来测试东西,并且我弄清楚了内部发生了什么。
不过,首先我要说的是,这同样适用于 Uniscribe 和 DirectWrite。
事实证明,无论我使用什么功能集,DirectWrite 始终提供一组默认的 OpenType 功能!情况是,提供的默认功能列表会有所不同,具体取决于我是否加载自己的功能以及整形引擎。对于latn水平书写模式下的脚本和英语,这是通过“通用引擎”完成的。
如果我不提供任何功能,通用引擎将加载特定于脚本的功能。对于水平方向latn,这个列表是
locl
ccmp
rlig
rclt
calt
liga
clig
Run Code Online (Sandbox Code Playgroud)
如果我确实提供功能,通用引擎将为所有脚本使用相同的默认列表:
locl
ccmp
rclt
rlig
mark
mkmk
dist
Run Code Online (Sandbox Code Playgroud)
所以我不知道该怎么办。我可能可以liga在 libui 代码中自己提供一些其他内容(标记为“HACK当然”),但这仍然很奇怪。我也不确定动机是什么。不管怎样,这解释了我所看到的行为。
| 归档时间: |
|
| 查看次数: |
339 次 |
| 最近记录: |