microsoft / WindowsAppSDK

The Windows App SDK empowers all Windows desktop apps with modern Windows UI, APIs, and platform features, including back-compat support, shipped via NuGet.
https://docs.microsoft.com/windows/apps/windows-app-sdk/
MIT License
3.8k stars 320 forks source link

DWriteCore empty vertical text layout crash #4070

Open timeester3648 opened 9 months ago

timeester3648 commented 9 months ago

Describe the bug

DWriteCore crashes when the text layout is empty and the text layout layouts the text vertically.

Steps to reproduce the bug

  1. open the WindowSdkApp samples and open DWriteCoreGallery
  2. In MarkdownWindow.cpp, in the function CreateTextLayoutsFromPseudoMarkdown add this:
result.push_back(CreateTextLayout(bodyFormat.get(), L"A"));

THROW_IF_FAILED(result.back()->SetFlowDirection(DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT));
THROW_IF_FAILED(result.back()->SetReadingDirection(DWRITE_READING_DIRECTION_TOP_TO_BOTTOM));
return result;

under std::vector<DWRITE_TEXT_RANGE> codeRanges; so the function essentially becomes this:

std::vector<wil::com_ptr<IDWriteTextLayout4>> CreateTextLayoutsFromPseudoMarkdown(std::span<char const> inputText, MarkdownStyle style)
{
    std::vector<wil::com_ptr<IDWriteTextLayout4>> result;

    auto headingFormat = CreateTextFormat(style.headingFamilyName, style.headingFontSize, style.headingAxisValues);
    auto bodyFormat = CreateTextFormat(style.bodyFamilyName, style.bodyFontSize, style.bodyAxisValues);
    auto codeFormat = CreateTextFormat(style.codeFamilyName, style.codeFontSize, style.bodyAxisValues);

    THROW_IF_FAILED(codeFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP));

    auto GetTextFormat = [&](MarkdownBlockType blockType)
    {
        switch (blockType)
        {
        case MarkdownBlockType::Body:     return bodyFormat.get();
        case MarkdownBlockType::Heading:  return headingFormat.get();
        case MarkdownBlockType::Code:     return codeFormat.get();
        default: THROW_HR(E_INVALIDARG);
        }
    };

    std::wstring text;
    std::vector<DWRITE_TEXT_RANGE> boldRanges;
    std::vector<DWRITE_TEXT_RANGE> italicRanges;
    std::vector<DWRITE_TEXT_RANGE> codeRanges;

    result.push_back(CreateTextLayout(bodyFormat.get(), L"A"));

    THROW_IF_FAILED(result.back()->SetFlowDirection(DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT));
    THROW_IF_FAILED(result.back()->SetReadingDirection(DWRITE_READING_DIRECTION_TOP_TO_BOTTOM));
    return result;
}

if you run this, it works like normal, but if you change result.push_back(CreateTextLayout(bodyFormat.get(), L"A")); to result.push_back(CreateTextLayout(bodyFormat.get(), L"")); (an empty string) it crashes.

if you comment out:

THROW_IF_FAILED(result.back()->SetFlowDirection(DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT));
THROW_IF_FAILED(result.back()->SetReadingDirection(DWRITE_READING_DIRECTION_TOP_TO_BOTTOM));

Then an empty string does not crash.

In my application, this is the error message I get:

thread '<unnamed>' panicked at 'index out of bounds: the len is 0 but the index is 0', rust\layout\src\run_list.rs:325:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I tried a multitude of functions, but all of them then reported this exact message, the first point I got this error was at text_layout->Draw but if I ignore the error, and continue, I get the same error with the functions: text_layout->GetMetrics, text_layout->GetLineMetrics and text_layout->HitTestTextPosition. I have not tested other functions.

Expected behavior

Just like when using a horizontal layout, the code does not crash/report an error.

Screenshots

No response

NuGet package version

None

Packaging type

No response

Windows version

No response

IDE

No response

Additional context

No response

codendone commented 7 months ago

internal bug