1

I use IDWriteTextAnalysisSink / AnalyzeScript to display mixed LTR (English) and RTL (Hebrew) text in DirectWrite (C++), and I compute text width from:

textwidth = 0;
for (UINT glyph=0; glyph<actualGlyphCount; glyph++) 
  textwidth += glyphAdvances[glyph];

with glyphAdvances returned from GetGlyphPlacements.

However for Right To Left text, this is often inaccurate, leading to overlapping text, etc. Is this the right method?

Thanks.

BanK
  • 73
  • 8

1 Answers1

2

You may not need to do quite so much work with IDWriteTextAnalysisSink / AnalyzeScript.

    HRESULT hr = S_OK;
    ComPtr<IDWriteTextFormat> textFormat;
    ComPtr<IDWriteTextLayout> textLayout;

    // Error checking omitted for brevity
    hr = textFactory->CreateTextFormat(L"Arial", nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 30.0f, L"", textFormat.GetAddressOf());
    hr = textFormat->SetReadingDirection(DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
    hr = textFactory->CreateTextLayout(L"[HEBREW TEXT HERE]", textsize, textFormat.Get(), 0.0f, 0.0f, textLayout.GetAddressOf());

Render Code:

    renderTarget->Clear(BG_COLOR);
    auto size = renderTarget->GetSize();

    auto margin = 50.0f;
    size.width -= margin * 2.0f;
    size.height -= margin * 2.0f;

    if (S_OK == textLayout->SetMaxWidth(size.width) &&
        S_OK == textLayout->SetMaxHeight(size.height))
    {
        renderTarget->DrawTextLayout(Point2F(margin, margin), textLayout.Get(), brush.Get(), D2D1_DRAW_TEXT_OPTIONS_NONE);
    }

Screenshot from reading hebrew file: enter image description here

(Note: My solution is based on a sample from Kenny Kerr) I realize you are mixing LTR and RTL, however I am not sure that warrants the added complexity of IDWriteTextAnalysisSink / AnalyzeScript.

Jeff
  • 2,495
  • 18
  • 38
  • Great, I have converted part of my code to using IDWriteTextFormat/IDWriteTextLayout, will do the rest later, I hadn't noticed that the GetLineMetrics and GetClusterMetrics functions provide all the necessary measuring information, so in my case there is no need to implement IDWriteTextAnalysisSink after all. Thanks. – BanK Feb 20 '14 at 02:06
  • Yeah, if you are drawing an IDWriteTextLayout, then it is best to measure using one too so the two are consistent, rather than using the much lower level functions which are actually used to create layouts themselves. Otherwise there is a whole slew of things you must duplicate too which the layout transparently does for you, like bidi analysis and font fallback, where lack of font fallback is probably why you are getting incorrect results for Hebrew. – Dwayne Robinson Sep 20 '14 at 10:26