Поделиться через


Обзор DWriteCore

DWriteCore — это реализация пакета SDK для приложений WindowsDirectWrite (DirectWrite — это API DirectX для высококачественной отрисовки текста, шрифтов структуры независимо от разрешения и полной поддержки текста и макета Юникода). DWriteCore — это форма DirectWrite, которая работает на версиях Windows, начиная с Windows 10, версии 1809 (10.0; Сборка 17763). DWriteCore реализует тот же API, что и DirectWrite, с несколькими дополнениями, как описано в этом разделе.

В этом вводном разделе описывается, что такое DWriteCore, и показано, как установить его в среду разработки и программу с ним.

Для приложения, которое уже использует DirectWrite, переключение на DWriteCore требует минимальных изменений:

  • Добавьте ссылку на пакет пакета SDK для приложений Windows.
  • Включите dwrite_core.h вместо dwrite_3.h.
  • Ссылка DWriteCore.lib вместо DWrite.lib.
  • Используйте DWriteCoreCreateFactory вместо DWriteCreateFactory.

В свою очередь, приложение получает преимущества пакета SDK для приложений Windows, а именно доступ к новейшим API и функциям независимо от того, какая версия Windows запущена.

Совет

Описание и ссылки на компоненты DirectX в активной разработке смотрите в записи блога на посадочной странице DirectX.

Ценность предложения DWriteCore

DirectWrite поддерживает широкий набор функций, благодаря которым он является основным инструментом для рендеринга шрифтов в Windows для большинства приложений, будь то через прямые вызовы или через Direct2D. DirectWrite включает в себя независимую от устройства систему макета текста, высококачественную субпиксельную Microsoft ClearType обработку текста, аппаратное ускорение текста, многоформатный текст, расширенные функции OpenType® типографии, поддержку множества языков и совместимый с GDIмакет и рендеринг. DirectWrite доступен с windows Vista с пакетом обновления 2 (SP2), и он развивался на протяжении многих лет, чтобы включить более сложные функции, такие как переменные шрифты, что позволяет применять стили, весы и другие атрибуты к шрифту только с одним ресурсом шрифта.

Однако из-за длительного существования DirectWrite прогресс в разработке, как правило, оставляет старые версии Windows позади. Кроме того, DirectWrite, как ведущая технология отрисовки текста, ограничена только платформой Windows, оставляя кроссплатформенные приложения либо создавать собственный стек для отрисовки текста, либо полагаться на сторонние решения.

DWriteCore решает основные проблемы, связанные с отсутствием функций версии и кроссплатформенной совместимостью, удалив библиотеку из системы и нацелив все возможные поддерживаемые конечные точки. Для этого мы интегрировали DWriteCore в пакет SDK для приложений Windows.

Основное значение, которое DWriteCore дает вам, как разработчик, в пакете SDK для приложений Windows заключается в том, что он предоставляет доступ ко многим (и в конечном итоге всем) функциям DirectWrite. Все функции DWriteCore будут работать одинаково на всех предыдущих версиях без каких-либо различий, касающихся того, какие функции могут работать на каких версиях.

Демонстрационное приложение DWriteCore — DWriteCoreGallery

DWriteCore представлен на примере приложения DWriteCoreGallery, который можно скачать и изучить.

Начало работы с DWriteCore

DWriteCore является частью пакета SDK для приложений Windows. В этом разделе описывается настройка среды разработки для программирования с помощью DWriteCore.

Установка средств для пакета SDK для приложений Windows

См. средства установки пакета SDK для приложений Windows.

Создание проекта

В Visual Studio создайте новый проект из шаблона проекта Пустое приложение, упакованное (WinUI 3 для настольного компьютера). Этот шаблон проекта можно найти, выбрав язык: C++; платформа: пакет SDK для приложений Windows; тип проекта: Desktop.

Дополнительную информацию см. в разделе 'Шаблоны проектов для WinUI 3'.

Установка пакета NuGet Microsoft.ProjectReunion.DWrite

В Visual Studio щелкните Project>Manage NuGet Packages...>Обзор, введите или вставьте Microsoft.ProjectReunion.DWrite в поле поиска, выберите элемент в результатах поиска, а затем щелкните Установить, чтобы установить пакет для этого проекта.

Кроме того, начните с примера приложения DWriteCoreGallery

Кроме того, вы можете программировать с помощью DWriteCore, начиная с проекта образца приложения DWriteCoreGallery и основываясь на разработке этого проекта. Затем вы можете удалить любой существующий исходный код (или файлы) из этого примера проекта, а также добавить в проект любой новый исходный код (или файлы).

Использование DWriteCore в проекте

Дополнительные сведения о программировании с помощью DWriteCore см. в разделе Программирование с помощью DWriteCore далее в этом разделе.

Этапы выпуска DWriteCore

Перенос DirectWrite в DWriteCore является достаточно большим проектом для охвата нескольких циклов выпуска Windows. Этот проект разделен на этапы, каждый из которых соответствует фрагменту функциональных возможностей, предоставляемых в выпуске.

Функции в текущем выпуске DWriteCore

DWriteCore является частью пакета SDK для приложений Windows. Он содержит основные инструменты, которые вы, как разработчик, должны использовать DWriteCore, включая следующие функции.

Функция баннера — цветовые шрифты. Цветовые шрифты позволяют отображать шрифты с более сложной функциональностью цвета, помимо простых отдельных цветов. Например, цветовые шрифты — это возможность отрисовки шрифтов эмодзи и значков панели инструментов (последний из которых используется Office, например). Цветовые шрифты впервые появились в Windows 8.1, но эта функция была сильно расширена в Windows 10 версии 1607 (юбилейное обновление).

Работа по очистке кэша шрифтов и загрузчика шрифтов в памяти позволяет ускорить загрузку шрифтов и улучшения памяти.

С помощью этих функций можно сразу же начать использовать некоторые современные функциональные возможности DirectWrite, такие как шрифты переменных. Шрифты переменных — это одна из наиболее важных функций для клиентов DirectWrite.

Наше приглашение для вас в качестве разработчика DirectWrite

DWriteCore, а также другие компоненты Windows App SDK, будут разработаны с открытостью к отзывам разработчиков. Мы приглашаем вас начать изучение DWriteCore, а также предоставить аналитические сведения или запросы на разработку функций в репозитории GitHub пакета SDK для Windows.

Программирование с помощью DWriteCore

Как и DirectWrite, вы программируете с DWriteCore через интерфейс API COM-light IDWriteFactory.

Чтобы использовать DWriteCore, необходимо включить файл заголовка dwrite_core.h.

// pch.h
...
// DWriteCore header file.
#include <dwrite_core.h>

Файл заголовка dwrite_core.h сначала определяет токен DWRITE_CORE, а затем включает файл заголовка dwrite_3.h. Маркер DWRITE_CORE важен, так как он направляет все последующие включенные заголовки, чтобы сделать все API DirectWrite доступными для вас. После включения dwrite_core.hв проект можно приступить к написанию кода, сборке и запуску проекта.

API, которые являются новыми или разными для DWriteCore

Область API DWriteCore является в значительной степени той же, что и для DirectWrite. Но есть небольшое количество новых API, которые находятся только в DWriteCore в настоящее время.

Создание объекта фабрики

Бесплатная функция DWriteCoreCreateFactory создает объект фабрики, используемый для последующего создания отдельных объектов DWriteCore.

DWriteCoreCreateFactory функционально совпадает с функцией DWriteCreateFactory, экспортируемой системной версией DirectWrite. Функция DWriteCore имеет другое имя, чтобы избежать неоднозначности.

Создание объекта ограниченной фабрики

Перечисление DWRITE_FACTORY_TYPE имеет новую константу —DWRITE_FACTORY_TYPE_ISOLATED2, указывающую изолированную фабрику. Ограниченная фабрика более заблокирована, чем изолированная фабрика. Он не взаимодействует с межпроцессным и постоянным кэшем шрифтов каким-либо образом. Кроме того, коллекция системных шрифтов, возвращенная из этой фабрики, включает только известные шрифты. Вот как можно использовать DWRITE_FACTORY_TYPE_ISOLATED2 для создания ограниченного фабричного объекта при вызове свободной функции DWriteCoreCreateFactory.

// Create a factory that doesn't interact with any cross-process nor
// persistent cache state.
winrt::com_ptr<::IDWriteFactory7> spFactory;
winrt::check_hresult(
  ::DWriteCoreCreateFactory(
    DWRITE_FACTORY_TYPE_ISOLATED2,
    __uuidof(spFactory),
    reinterpret_cast<IUnknown**>(spFactory.put())
  )
);

Если вы передаете DWRITE_FACTORY_TYPE_ISOLATED2 более старой версии DirectWrite, которая не поддерживает ее, то DWriteCreateFactory возвращает E_INVALIDARG.

Рисование глифов в растровую карту системной памяти

DirectWrite имеет целевой интерфейс отрисовки растрового изображения, поддерживающий отрисовку глифов в растровую карту в системной памяти. Однако в настоящее время единственный способ получить доступ к базовым данным пикселей заключается в том, чтобы пройти через GDI, и поэтому API не является пригодным для использования кроссплатформенным. Это легко устраняется путем добавления метода для получения данных пикселей.

И поэтому DWriteCore представляет интерфейс IDWriteBitmapRenderTarget2 и его метод IDWriteBitmapRenderTarget2::GetBitmapData. Этот метод принимает параметр типа (указателя на) DWRITE_BITMAP_DATA_BGRA32, который является новой структурой.

Приложение создает целевой объект отрисовки растрового изображения путем вызова IDWriteGdiInterop::CreateBitmapRenderTarget. В Windows целевой объект отрисовки растрового изображения инкапсулирует контроллер памяти GDI с выбранным в него точечным изображением, независимым от устройства GDI. IDWriteBitmapRenderTarget::DrawGlyphRun отображает глифы в DIB. DirectWrite рендерит глифы, не используя GDI. Затем ваше приложение может получить HDC из целевого объекта отрисовки растрового изображения и использовать BitBlt для копирования пикселей в окно HDC.

На платформах, кроме Windows, ваше приложение по-прежнему может создать целевой объект для отрисовки растрового изображения, но он просто инкапсулирует массив системной памяти без HDC и без DIB. Без HDCнеобходимо найти другой способ, чтобы ваше приложение могло получать пиксели растрового изображения для их копирования или иного использования. Даже в Windows иногда полезно получить фактические данные пикселей, и мы показываем текущий способ сделать это в приведенном ниже примере кода.

// pch.h
#pragma once

#include <windows.h>
#include <Unknwn.h>
#include <winrt/Windows.Foundation.h>

// WinMain.cpp
#include "pch.h"
#include <dwrite_core.h>
#pragma comment(lib, "Gdi32")

class TextRenderer
{
    DWRITE_BITMAP_DATA_BGRA32 m_targetBitmapData;

public:
    void InitializeBitmapData(winrt::com_ptr<IDWriteBitmapRenderTarget> const& renderTarget)
    {
        // Query the bitmap render target for the new interface. 
        winrt::com_ptr<IDWriteBitmapRenderTarget2> renderTarget2;
        renderTarget2 = renderTarget.try_as<IDWriteBitmapRenderTarget2>();

        if (renderTarget2)
        {
            // IDWriteBitmapRenderTarget2 exists, so we can get the bitmap the easy way. 
            winrt::check_hresult(renderTarget2->GetBitmapData(OUT & m_targetBitmapData));
        }
        else
        {
            // We're using an older version that doesn't implement IDWriteBitmapRenderTarget2, 
            // so we have to get the bitmap by going through GDI. First get the bitmap handle. 
            HDC hdc = renderTarget->GetMemoryDC();
            winrt::handle dibHandle{ GetCurrentObject(hdc, OBJ_BITMAP) };
            winrt::check_bool(bool{ dibHandle });

            // Call a GDI function to fill in the DIBSECTION structure for the bitmap. 
            DIBSECTION dib;
            winrt::check_bool(GetObject(dibHandle.get(), sizeof(dib), &dib));

            m_targetBitmapData.width = dib.dsBm.bmWidth;
            m_targetBitmapData.height = dib.dsBm.bmHeight;
            m_targetBitmapData.pixels = static_cast<uint32_t*>(dib.dsBm.bmBits);
        }
    }
};

int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
{
    TextRenderer textRenderer;
    winrt::com_ptr<IDWriteBitmapRenderTarget> renderTarget{ /* ... */ };
    textRenderer.InitializeBitmapData(renderTarget);
}

Другие различия API между DWriteCore и DirectWrite

Существует некоторые API, которые являются только заглушками, либо ведут себя несколько иначе на платформах, отличных от Windows. Например, IDWriteGdiInterop::CreateFontFaceFromHdc возвращает E_NOTIMPL на платформах, отличных от Windows, так как нет такой вещи, как HDC без GDI.

И, наконец, существуют некоторые другие API Windows, которые обычно используются вместе с DirectWrite (Direct2D является заметным примером). Однако в настоящее время Direct2D и DWriteCore не взаимодействуют. Например, если вы создаете IDWriteTextLayout с помощью DWriteCore и передаете его в D2D1RenderTarget::DrawTextLayout, то этот вызов завершится ошибкой.