#direct2d #directwrite
Вопрос:
Я оцениваю Direct2D в исследовательских целях, и пока я занимался этим, я решил отобразить свой обычный текст справки с помощью пользовательского средства визуализации текста DirectWrite, которое преобразует текст в геометрию пути, чтобы добавить контур (как показано в примере DWriteHelloWorld на MSDN).
Однако на некоторых буквах есть странные «волоски» или «рожки» (рисунок: ширина штриха 3 и 5).
Также пробовал использовать другие шрифты (например, Consolas), эффект тот же.
Исходный код (ПО сравнению с 2015 годом): https://www.dropbox.com/s/v3204h0ww2cp0yk/FOR_STACKOVERFLOW_12.zip?dl=0
Ответ №1:
Я бы заподозрил, что причина этого в том, что допуск сглаживания по умолчанию в D2D плохо работает для визуализации контуров глифа при достаточно малых размерах. Обычно вы используете растровый рендеринг для небольших размеров и контуры для больших, согласно GetRecommendedRenderingMode(). Есть ли у вас такие же артефакты, если вы увеличите размер шрифта, скажем, в 10 раз?
Комментарии:
1. если я увеличу размер шрифта, то он будет выглядеть нормально, но цель будет заключаться в том, чтобы он хорошо выглядел с этим размером шрифта. Интересно, что GDI может это сделать. Как бы вы отрисовали контуры растровым шрифтом?
2. Вы имеете в виду, если вы передадите геометрию D2D методам GDI ? Я думаю, что тогда GDI работает по-другому. Что вы подразумеваете под растровым шрифтом? Если для данного глифа нет контура, я думаю, что GetGlyphRunOutline пропустит его и перейдет к следующему.
3. Я имел в виду, что GDI может идеально отображать выделенный текст с таким размером шрифта (используя GraphicsPath::AddString, Graphics::drawPath и Graphics::FillPath). Хотел написать «растризатор» (не растровый шрифт, это совершенно другое), например, если этот метод геометрии пути не подходит для небольших размеров шрифта, то как я могу отрисовывать очерченный текст другими способами?
4. Я сам не пробовал, если это действительно касается допуска, вы можете попробовать ID2D1DeviceContext1::CreateFilledGeometryRealization() и поиграть со значением допуска, чтобы посмотреть, поможет ли это вообще. Если это так, вы можете затем составить некоторую оценку допуска, основанную на размере шрифта. Другой вариант-использовать ID2D1Geometry::Simplify(), который также принимает аргумент допуска. Средство визуализации по умолчанию в D2D использует рекомендуемый режим, который переключается на контур с размером ~100,0 ems. Может быть, вы нашли причину, по которой она не ниже.
5. Я поиграл с Simplify() и параметром допуска, но «волоски» все еще там.
Ответ №2:
Решение так просто, как я и надеялся. «Волоски» на самом деле вызваны соединениями линий, которые генерирует D2D. Поэтому решение состоит в том, чтобы создать объект ID2D1StrokeStyle следующим образом:
ID2D1StrokeStyle* strokestyle = nullptr;
D2D1_STROKE_STYLE_PROPERTIES strokeprops = D2D1::StrokeStyleProperties();
strokeprops.lineJoin = D2D1_LINE_JOIN_ROUND;
d2dfactory->CreateStrokeStyle(strokeprops, NULL, 0, amp;strokestyle);
// draw
rendertarget->DrawGeometry(transformedgeometry, blackbrush, 3.0f, strokestyle);
С помощью этого решения текст отображается так, как ожидалось (возможно, немного более округлый в местах соединения).