Internationalization 如何将不明确字符的方向性指定给IDWriteTextLayout?

Internationalization 如何将不明确字符的方向性指定给IDWriteTextLayout?,internationalization,globalization,directwrite,Internationalization,Globalization,Directwrite,有些字符具有模糊的方向性,如空格和标点符号。这可能会导致文本布局的情况,即在没有访问其他数据以解决歧义的情况下,似乎没有单个正确的布局。考虑这篇课文: \u05e9\u05e0\u05d1\u05d2abcd! 这是四个希伯来语字符(明确地从右到左)、四个英语字符(明确地从左到右)和一个标点符号(模棱两可)。如果我在IDWriteTextLayout中用DWRITE\u READING\u DIRECTION\u RIGHT\u TO\u LEFT布局该字符串,我会得到以下结果: 标点符号似

有些字符具有模糊的方向性,如空格和标点符号。这可能会导致文本布局的情况,即在没有访问其他数据以解决歧义的情况下,似乎没有单个正确的布局。考虑这篇课文:

\u05e9\u05e0\u05d1\u05d2abcd!
这是四个希伯来语字符(明确地从右到左)、四个英语字符(明确地从左到右)和一个标点符号(模棱两可)。如果我在
IDWriteTextLayout
中用
DWRITE\u READING\u DIRECTION\u RIGHT\u TO\u LEFT
布局该字符串,我会得到以下结果:

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

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

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

如果我的目标是让它通常是希伯来语文本,带有一个嵌入的美国英语字符串,我想我应该在
IDWriteTextFormat
上使用locale
he
,然后在字符范围[4-9]上使用
SetLocaleName
覆盖locale
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();
}
TestTextRenderer::TestTextRenderer(const std::shared_ptr&deviceResources):
m_设备源(设备源),
m_文本(L“\u05e9\u05e0\u05d1\u05d2abcd!”),
m_读取方向(数据写入读取方向从右到左),
m_formatLocale(L“en US”),
m_layoutLocale(L“en US”)
{
ComPtr文本格式;
DX::ThrowIfFailed(
m_deviceResources->GetDWriteFactory()->CreateTextFormat(
L“Segoe UI”,
nullptr,
DWRITE_FONT_WEIGHT_MEDIUM,
DWRITE\u FONT\u STYLE\u NORMAL,
DWRITE\u FONT\u STRETCH\u NORMAL,
24.0f,
m_formatLocale.c_str(),
&文本格式
)
);
DX::ThrowIfFailed(textFormat->SetReadingDirection(m_readingDirection));
DX::ThrowIfFailed(
m_deviceResources->GetDWriteFactory()->CreateTextLayout(
m_text.c_str(),
(uint32)m_text.length(),
textFormat.Get(),
250.0华氏度,
100.0f,
&m_文本布局
)
);
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算法的角度来看,我不认为有任何歧义。将初始方向设置为
IDWriteTextFormat
IDWriteTextLayout
是至关重要的,但之后运行方向将严格从代码点派生

设置区域设置不会改变方向,但它可能会影响形状,最终结果取决于字体所具有的特定功能


我认为你能做到使用LRE/PDF控件围绕文本的这一部分进行输出。

已确认,使用控件字符LRE和PDF具有预期效果,似乎是处理此问题的正确方法。