Общие сведения о DWriteCore

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

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

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

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

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

Совет

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

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

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

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

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

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

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

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

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

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

Установка инструментов для Windows App SDK

См. статью Установка инструментов для Windows App SDK.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Как и в случае с DirectWrite, вы программируете с помощью DWriteCore через ИНТЕРФЕЙС 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 важен, так как он направляет все последующие включенные заголовки, чтобы сделать все DirectWrite API доступными для вас. После включения dwrite_core.hв проект можно написать код, выполнить сборку и запуск.

Api, которые являются новыми или отличными для DWriteCore

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

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

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

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

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

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

// 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 с выбранным аппаратно-независимым растровым рисунком (DIB) GDI. IDWriteBitmapRenderTarget::D rawGlyphRun отрисовывает глифы в 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, так как без GDI не существует такого понятия, как HDC.

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