如何为 IDWriteTextLayout 指定不明确字符的方向性?

How do I specify directionality of ambiguous characters to IDWriteTextLayout?

有些字符的方向性不明确,例如空格和标点符号。这可能会导致文本布局情况,即在没有访问附加数据来解决歧义的情况下似乎没有单一正确的布局。考虑这段文字:

\u05e9\u05e0\u05d1\u05d2abcd!

这是四个希伯来字符(明确从右到左)、四个英文字符(明确从左到右)和一个标点符号(明确)。如果我将该字符串布局为 IDWriteTextLayoutDWRITE_READING_DIRECTION_RIGHT_TO_LEFT,我将得到以下内容:

标点符号似乎被视为从右到左的字符,它在英语的左侧开始一个新的从右到左的块,这似乎非常合理,尤其是考虑到从右到- left 是指定的阅读方向。但是,期望标点符号被视为与嵌入的从左到右的英文文本相关联的从左到右的字符也是完全合理的,这意味着它应该出现在 'd' 的右侧.

我的应用程序确切地知道它希望如何对待这个角色。如何将该数据传递给 IDWriteTextLayout 以解决这种歧义?

我找到了SetLocaleName这个方法,我想这一定是答案,但我似乎根本无法得到它来影响结果。我还在创建 IDWriteTextFormat 时找到了 localeName 参数(然后用于创建 IDWriteTextLayout)。

如果我的目标是通常将其作为带有一串嵌入式美国英语的希伯来语文本,我想我会想在 IDWriteTextFormat 上使用区域设置 he,然后使用 SetLocaleName 在字符范围 [4-9] 上用语言环境 en-US 覆盖它。但是,这样做没有任何效果。事实上,无论是将它们限制在子范围内还是将它们应用于整个字符串,我都无法获得在这些地方使用的任何语言环境组合对布局产生任何影响。

我认为这些 API 应该用于此目的的想法是错误的吗?如果是这样,我应该使用哪些 API?或者真的没有办法告诉 IDWriteTextLayout 以不同的方式解决这种歧义吗?我可能使用了错误的 API 吗?这是我用来创建这个 IDWriteTextLayout:

的测试代码
TestTextRenderer::TestTextRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources) : 
    m_deviceResources(deviceResources),
    m_text(L"\u05e9\u05e0\u05d1\u05d2abcd!"),
    m_readingDirection(DWRITE_READING_DIRECTION_RIGHT_TO_LEFT),
    m_formatLocale(L"en-US"),
    m_layoutLocale(L"en-US")
{
    ComPtr<IDWriteTextFormat> textFormat;
    DX::ThrowIfFailed(
        m_deviceResources->GetDWriteFactory()->CreateTextFormat(
            L"Segoe UI",
            nullptr,
            DWRITE_FONT_WEIGHT_MEDIUM,
            DWRITE_FONT_STYLE_NORMAL,
            DWRITE_FONT_STRETCH_NORMAL,
            24.0f,
            m_formatLocale.c_str(),
            &textFormat
        )
    );
    DX::ThrowIfFailed(textFormat->SetReadingDirection(m_readingDirection));

    DX::ThrowIfFailed(
        m_deviceResources->GetDWriteFactory()->CreateTextLayout(
            m_text.c_str(),
            (uint32) m_text.length(),
            textFormat.Get(),
            250.0f,
            100.0f,
            &m_textLayout
        )
    );

    DWRITE_TEXT_RANGE all{0u, m_text.size()};
    DX::ThrowIfFailed(m_textLayout->SetLocaleName(m_layoutLocale.c_str(), all));

    DX::ThrowIfFailed(m_deviceResources->GetD2DFactory()->CreateDrawingStateBlock(&m_stateBlock));
    CreateDeviceDependentResources();
}

我认为从 Unicode BiDi 算法的角度来看没有任何歧义。初始方向设置为 IDWriteTextFormatIDWriteTextLayout 是至关重要的,但在那之后 运行 方向将严格来自代码点。

设置语言环境不会改变方向,但它可能会影响形状,最终结果取决于特定的特性运行字体有。

我认为您可以使用围绕这部分文本的 LRE/PDF 控件完成 abcd!... 输出。