DWriteCore 개요

DWriteCore는 DirectWriteWindows 앱 SDK 구현입니다(DirectWrite는 고품질 텍스트 렌더링, 해상도 독립 윤곽선 글꼴 및 전체 유니코드 텍스트 및 레이아웃 지원을 위한 DirectX API임). DWriteCore는 windows 버전에서 DirectWrite Windows 10, 버전 1809(10.0; 빌드 17763). DWriteCore는 이 항목에 설명된 대로 몇 가지 추가를 사용하여 DirectWrite 동일한 API를 구현합니다.

이 소개 항목에서는 DWriteCore가 무엇인지 설명하고 이를 사용하여 개발 환경 및 프로그램에 설치하는 방법을 보여 줍니다.

이미 DirectWrite 사용하는 앱의 경우 DWriteCore로 전환하려면 최소한의 변경이 필요합니다.

그 대가로 앱은 고객이 실행 중인 Windows 버전에 관계없이 최신 API 및 기능에 대한 액세스와 같은 Windows 앱 SDK 이점을 얻습니다.

현재 개발 중인 DirectX 구성 요소에 대한 설명 및 링크는 블로그 게시물 DirectX 방문 페이지를 참조하세요.

DWriteCore의 가치 제안

DirectWrite 자체는 직접 호출을 통해서든 Direct2D를 통해서든 대부분의 앱에서 Windows에서 선택할 수 있는 글꼴 렌더링 도구가 되는 다양한 기능을 지원합니다. DirectWrite 디바이스 독립적 텍스트 레이아웃 시스템, 고품질 하위 픽셀 Microsoft ClearType 텍스트 렌더링, 하드웨어 가속 텍스트, 다중 형식 텍스트, 고급 OpenType® 입력 체계 기능, 와이드 언어 지원 및 GDI 호환 레이아웃 및 렌더링을 포함합니다. DirectWrite Windows Vista SP2부터 사용할 수 있으며, 가변 글꼴과 같은 고급 기능을 포함하도록 수년에 걸쳐 발전해 왔으며, 이를 통해 하나의 글꼴 리소스만 있는 글꼴에 스타일, 가중치 및 기타 특성을 적용할 수 있습니다.

그러나 DirectWrite 수명이 길기 때문에 개발의 발전으로 인해 이전 버전의 Windows가 뒤처진 경향이 있습니다. 또한 DirectWrite 프리미어 텍스트 렌더링 기술로서의 상태 Windows로만 제한되므로 플랫폼 간 애플리케이션은 자체 텍스트 렌더링 스택을 작성하거나 타사 솔루션에 의존하게 됩니다.

DWriteCore는 시스템에서 라이브러리를 제거하고 지원되는 모든 엔드포인트를 대상으로 하여 버전 기능 분리 및 플랫폼 간 호환성의 근본적인 문제를 해결합니다. 이를 위해 DWriteCore를 Windows 앱 SDK 통합했습니다.

DWriteCore가 개발자로서 Windows 앱 SDK 제공하는 기본 값은 많은(그리고 결국 모든) DirectWrite 기능에 대한 액세스를 제공한다는 것입니다. DWriteCore의 모든 기능은 어떤 버전에서 작동할 수 있는지에 대한 차이 없이 모든 하위 수준 버전에서 동일하게 작동합니다.

DWriteCore 데모 앱- DWriteCoreGallery

DWriteCore는 지금 다운로드하고 공부할 수 있는 DWriteCoreGallery 샘플 앱을 통해 시연됩니다.

DWriteCore 시작

DWriteCore는 Windows 앱 SDK 일부입니다. 이 섹션에서는 DWriteCore를 사용하여 프로그래밍을 위한 개발 환경을 설정하는 방법을 설명합니다.

Windows 앱 SDK용 도구 설치

Windows 앱 SDK용 도구 설치를 참조하세요.

새 프로젝트 만들기

Visual Studio의 빈 앱 패키지(데스크톱의 WinUI 3) 프로젝트 템플릿에서 새 프로젝트를 만듭니다. C++; 언어를 선택하여 프로젝트 템플릿을 찾을 수 있습니다. platform: Windows 앱 SDK; 프로젝트 유형: 데스크톱.

자세한 내용은 WinUI 3용 프로젝트 템플릿을 참조하세요.

Microsoft.ProjectReunion.DWrite NuGet 패키지 설치

Visual Studio에서 프로젝트>NuGet 패키지 관리...를 클릭합니다.>검색 상자에 Microsoft.ProjectReunion.DWrite를 찾아보거나 입력하거나 붙여넣고 검색 결과에서 항목을 선택한 다음 설치를 클릭하여 해당 프로젝트에 대한 패키지를 설치합니다.

또는 DWriteCoreGallery 샘플 앱으로 시작합니다.

또는 DWriteCoreGallery 샘플 앱 프로젝트로 시작하여 DWriteCore 로 프로그래밍하고 해당 프로젝트에 대한 개발을 기반으로 할 수 있습니다. 그런 다음, 해당 샘플 프로젝트에서 기존 소스 코드(또는 파일)를 제거하고 프로젝트에 새 소스 코드(또는 파일)를 추가할 수 있습니다.

프로젝트에서 DWriteCore 사용

DWriteCore를 사용한 프로그래밍에 대한 자세한 내용은 이 항목의 뒷부분에 있는 DWriteCore를 사용한 프로그래밍 섹션을 참조하세요.

DWriteCore의 릴리스 단계

DirectWrite DWriteCore로 포팅하는 것은 여러 Windows 릴리스 주기에 걸쳐 있을 만큼 충분히 큰 프로젝트입니다. 해당 프로젝트는 각각 릴리스에서 제공되는 기능 청크에 해당하는 단계로 나뉩니다.

DWriteCore의 현재 릴리스 기능

DWriteCore는 Windows 앱 SDK 일부입니다. 여기에는 개발자가 다음 기능을 포함하여 DWriteCore를 사용해야 하는 기본 도구가 포함되어 있습니다.

배너 기능은 색 글꼴입니다. 색 글꼴을 사용하면 단순한 단일 색을 넘어 보다 정교한 색 기능으로 글꼴을 렌더링할 수 있습니다. 예를 들어 색 글꼴은 이모지 및 도구 모음 아이콘 글꼴을 렌더링하는 기능을 지원합니다(예: Office에서 사용되는 후자). 색 글꼴은 Windows 8.1 처음 도입되었지만 이 기능은 Windows 10 버전 1607(1주년 업데이트)에서 크게 확장되었습니다.

글꼴 캐시 및 메모리 내 글꼴 로더 정리 작업을 통해 글꼴을 더 빠르게 로드하고 메모리를 개선할 수 있습니다.

이러한 기능을 사용하면 변수 글꼴과 같은 DirectWrite 최신 핵심 기능 중 일부를 즉시 활용할 수 있습니다. 가변 글꼴은 DirectWrite 고객에게 가장 중요한 기능 중 하나입니다.

DirectWrite 개발자로 초대

DWriteCore는 다른 Windows 앱 SDK 구성 요소와 함께 개발자 피드백에 대한 개방성을 사용하여 개발될 예정입니다. DWriteCore 탐색을 시작하고 Windows 앱 SDK GitHub 리포지토리의 기능 개발에 대한 인사이트 또는 요청을 제공하도록 초대합니다.

DWriteCore를 사용한 프로그래밍

DirectWrite 마찬가지로 IDWriteFactory 인터페이스를 통해 COM 조명 API를 통해 DWriteCore로 프로그래밍합니다.

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되면 계속 진행하여 코드를 작성하고, 빌드하고, 실행할 수 있습니다.

DWriteCore에 대해 새로운 API 또는 다른 API

DWriteCore API 표면은 DirectWrite 경우와 거의 동일합니다. 그러나 현재 DWriteCore에만 있는 소수의 새 API가 있습니다.

팩터리 개체 만들기

DWriteCoreCreateFactory free 함수는 개별 DWriteCore 개체의 후속 생성에 사용되는 센터 개체를 만듭니다.

DWriteCoreCreateFactory는 시스템 버전의 DirectWrite에서 내보낸 DWriteCreateFactory 함수와 기능적으로 동일합니다. DWriteCore 함수의 이름은 모호성을 방지하기 위해 다릅니다.

제한된 팩터리 개체 만들기

DWRITE_FACTORY_TYPE 열거형에는 제한된 팩터리를 나타내는 새 상수(DWRITE_FACTORY_TYPE_ISOLATED2)가 있습니다. 제한된 팩터리는 격리된 팩터리보다 더 잠겨 있습니다. 어떤 방식으로든 프로세스 간 또는 영구 글꼴 캐시와 상호 작용하지 않습니다. 또한 이 팩터리에서 반환된 시스템 글꼴 컬렉션에는 잘 알려진 글꼴만 포함됩니다. DWriteCoreCreateFactory free 함수를 호출할 때 DWRITE_FACTORY_TYPE_ISOLATED2 사용하여 제한된 팩터리 개체를 만드는 방법은 다음과 같습니다.

// 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 전달하면 DWriteCreateFactoryE_INVALIDARG 반환합니다.

시스템 메모리 비트맵에 문자 모양 그리기

DirectWrite 시스템 메모리의 비트맵에 문자 모양 렌더링을 지원하는 비트맵 렌더링 대상 인터페이스가 있습니다. 그러나 현재 기본 픽셀 데이터에 액세스할 수 있는 유일한 방법은 GDI를 통과하는 것이므로 API는 플랫폼 간에서 사용할 수 없습니다. 이는 픽셀 데이터를 검색하는 메서드를 추가하여 쉽게 해결할 수 있습니다.

따라서 DWriteCore는 IDWriteBitmapRenderTarget2 인터페이스와 해당 메서드 IDWriteBitmapRenderTarget2::GetBitmapData를 소개합니다. 해당 메서드는 새 구조체인 DWRITE_BITMAP_DATA_BGRA32 형식의 매개 변수를 사용합니다.

애플리케이션은 IDWriteGdiInterop::CreateBitmapRenderTarget을 호출하여 비트맵 렌더링 대상을 만듭니다. Windows에서 비트맵 렌더링 대상은 GDI 디바이스 독립적 비트맵(DIB)이 선택된 GDI 메모리 DC를 캡슐화합니다. 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);
}

DWriteCore와 DirectWrite 간의 다른 API 차이점

스텁만 있는 몇 가지 API가 있거나 Windows가 아닌 플랫폼에서는 다소 다르게 동작합니다. 예를 들어 IDWriteGdiInterop::CreateFontFaceFromHdcGDI가 없는 HDC와 같은 항목이 없으므로 비 Windows 플랫폼에서 E_NOTIMPL 반환합니다.

마지막으로, 일반적으로 DirectWrite 함께 사용되는 특정 다른 Windows API가 있습니다(Direct2D가 주목할 만한 예임). 그러나 현재 Direct2D 및 DWriteCore는 상호 운용되지 않습니다. 예를 들어 DWriteCore를 사용하여 IDWriteTextLayout 을 만들고 D2D1RenderTarget::D rawTextLayout에 전달하면 해당 호출이 실패합니다.