代码之家  ›  专栏  ›  技术社区  ›  Jayonas

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

  •  1
  • Jayonas  · 技术社区  · 9 年前

    有些字符具有模糊的方向性,如空格和标点符号。这可能导致文本布局的情况,在这种情况下,如果不访问额外的数据来解决歧义,似乎就没有一个正确的布局。考虑以下文本:

    \u05e9\u05e0\u05d1\u05d2abcd!
    

    这是四个希伯来语字符(从右到左)、四个英语字符(从左到右)和一个标点符号(模棱两可)。如果我在 IDWriteTextLayout 具有 DWRITE_READING_DIRECTION_RIGHT_TO_LEFT ,我得到以下结果:

    Rendered screen shot showing punctuation on far left.

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

    我的应用程序确切地知道它希望如何对待这个角色。如何将数据传递给 ID写入文本布局 要解决这种歧义?

    我找到了 SetLocaleName 方法,并认为这一定是答案,但我似乎根本无法让它影响结果。我还发现 localeName 创建时的参数 IDWriteTextFormat (然后用于创建 ID写入文本布局 ).

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

    我认为这些API应该达到这个目的,这是错误的吗?如果是,我应该使用什么API?还是真的无从得知 ID写入文本布局 以不同的方式解决这种歧义?我可能用错API了吗?这是我用来创建这个的测试代码 ID写入文本布局 :

    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();
    }
    
    1 回复  |  直到 9 年前
        1
  •  3
  •   bunglehead    9 年前

    我不认为从Unicode BiDi算法的角度来看有任何歧义。初始方向设置为 IDWriteTextFormat IDWriteTextLayout 这是至关重要的,但在此之后,将严格从代码点导出运行方向。

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

    我想你可以完成 abcd!。。。 使用LRE/PDF控件围绕这部分文本进行输出。