Вызовы ID2D1RenderTarget :: DrawTextLayout () не работают

В основном, учитывая следующий тестовый код:

CComPtr<IDWriteTextLayout> layout;
wstring text2 = L"Here is some text.";
this->currentLevelText->Formatting->TextFactory->CreateTextLayout(text2.c_str(), text2.length(), this->matrixHeaderTextInfo->TextFormat, FLT_MAX, FLT_MAX, &layout);
target->DrawTextLayout(D2D1::Point2F(30, 30), layout, this->textBrush);

Метод target-> DrawTextLayout ничего не рисует. Однако следующий вызов DrawTextW работает:

target->DrawTextW(this->currentLevelText->Text.c_str(), this->currentLevelText->Text.length(), 
    this->currentLevelText->Formatting->TextFormat, this->currentLevelText->ActualRectangle.DrawingRectangle,
    this->textBrush);

Вот краткое изложение того, что я знаю:

  • TextFactory - это указатель на объект IDWriteFactory, TextFormat - это объект IDWriteTextFormat, а target - действительный ID2D1HwndRenderTarget.
  • TextFormat является допустимым объектом IDWriteTextFormat, так как я могу правильно рисовать с ним текст с помощью метода DrawTextW.
  • Вызов CreateTextLayout не возвращает код ошибки, он возвращает код успеха S_OK.
  • TextFormat и объект макета текста были созданы с использованием одной и той же фабрики DirectWrite, которая также является единственной фабрикой DirectWrite, существующей в моем приложении.
  • ID2D1SolidColorBrush textBrush - это допустимая кисть с непрозрачностью 1.0 и установленным на черный цвет. Я знаю, что проблема не в этом, потому что DrawTextW использует эту кисть для успешного рисования в окне.
  • Вызов метода GetMetrics объекта ID2D1TextLayout возвращает допустимые метрики; другими словами, ширина и высота текста, хранящегося в объекте, не равны 0 или отрицательны.
  • Вызов ID2D1RenderTarget :: EndDraw () не возвращает код ошибки, он возвращает код успеха S_OK.
  • Что больше всего озадачивает, в другом разделе моего кода (который находится в другом файле dll) вызовы DrawTextLayout действительно работают. Несмотря на то, что этот код находится в файле dll, он использует ту же фабрику DirectWrite. Я действительно не думаю, что использование другого файла DLL должно иметь значение.

Оба образца кода, которые я предоставил, выполняются один за другим, и оба должны успешно рисовать текст. Однако только DrawTextW рисует текст. Я не делаю ничего сложного с рисованием, например, использую Direct 2D Effects. Код не сложнее представленных мною примеров. На данный момент я могу просто использовать метод DrawTextW, но я бы предпочел этого не делать, поскольку я где-то читал, что просто создает объект IDWriteTextLayout, рисует его, а затем уничтожает объект. Это много ненужной работы, которую можно облегчить, используя сам объект макета текста.

Кто-нибудь знает, почему это может происходить? Я совершенно не понимаю, почему это происходит, хотя я продолжаю пытаться где-нибудь найти связь.


person Nkosi Dean    schedule 15.11.2016    source источник


Ответы (1)


Я считаю, что нашел решение. Объект TextFormat был создан с выравниванием абзаца DWRITE_PARAGRAPH_ALIGNMENT_CENTER, выравниванием текста DWRITE_TEXT_ALIGNMENT_CENTER, а макет имеет размер ограничивающей рамки FLT_MAX (имитация без границ, поэтому текст никогда не будет принудительно переноситься).

Я не осознавал этого, но DWRITE_PARAGRAPH_ALIGNMENT относится к вертикальному выравниванию текста. DWRITE_PARAGRAPH_ALIGNMENT_NEAR означает выравнивание по верхнему краю, DWRITE_PARAGRAPH_ALIGNMENT_FAR означает выравнивание по низу, а DWRITE_PARAGRAPH_ALIGNMENT_CENTER означает выравнивание по центру по вертикали.

Поскольку контейнер макета был FLT_MAX * FLT_MAX, текст не будет виден нигде на экране, независимо от того, какую исходную позицию я укажу, потому что он всегда будет примерно FLT_MAX / 2 пикселя как по оси x, так и по оси y.

Изменение выравнивания абзацев текстового формата с DWRITE_PARAGRAPH_ALIGNMENT_CENTER на DWRITE_PARAGRAPH_ALIGNMENT_NEAR было первым шагом к решению проблемы. Однако я заметил, что текст по-прежнему не отображается. Я понял, что DWRITE_TEXT_ALIGNMENT_CENTER не будет работать с шириной FLT_MAX по той же причине, по которой выравнивание абзацев не работает, как я ожидал. При центрировании текста при ширине FLT_MAX для рисования текст снова смещается за пределы экрана вправо.

Итак, хотя использование FLT_MAX не доставляло мне проблем до сих пор (до сих пор у меня, должно быть, не было необходимости использовать выравнивание по центру), моя проблема была решена с помощью конкретных ограничений размера для макета и использования выравнивания «ближнего» абзаца.

person Nkosi Dean    schedule 25.12.2016