[Direct2D/DWrite]설치되지 않은 폰트 설치하지 않고 사용하기 Lu's…〃 Programing。

AddFontMemResourceEx DWrite CreateTextFormat 등에서 적용되지 않는다.

 

DWrite CreateTextFormat 함수는 번째 인자로 fontCollection 받는데, 값이 nullptr이면 시스템 폰트에서 번째 인자로 주는 fontFamilyName 검색한다.

 

DWrite에서 시스템 폰트 이외의 폰트를 사용하는 방법은 폰트 컬렉션을 만드는 방법이다.

 

폰트 컬렉션을 만드는 방법은 크게 가지로 나눌 있는데, 하나는 Windows 10 이상의 환경에서만 사용 가능한 방법과 이전의 버전에서 사용 가능한 방법이다.

 

 

 

  1. Windows 10 이전 버전 호환을 위한 방법

 

Windows 7/8.1에서 사용되는 방법은 Windows 7 Windows SDKSample에 있는데… 지금 찾아보니 페이지가 중국 MS 기술문서 말고는 누가 Github 아카이빙한 말고는 찾겠더라.

 

https://github.com/pauldotknopf/WindowsSDK7-Samples/tree/master/multimedia/DirectWrite/CustomFont

 

예제는 폰트 파일에서 불러오는 아니라 .rc 파일에 있는 폰트를 불러오는 시나리오다. 만약 폰트를 파일에서 불러오고 싶으면 CreateFontFileReference 함수를 써서 reference key 알아낸 이를 사용하여 CreateCustomFontFileReference함수를 호출하여 custom file file reference 만드는 방법이 있다. 만약 rc 파일을 사용한다면 과정은 생략해도 된다.

 

 간단한 스텝에 대해 설명하자면,

 

  1. ResourceFontContext 객체를 선언한다.
     
  2. CreateFontCollection 함수를 호출한다.
    번째 인자는 Font Collection Key이고 번째 인자는 key size이다.

    여기서 알아둘 점은, key 리소스 ID 또는 CustomFontFileReference에서 설정한 ID 값이다.
     
  3. 번째 인자로 넘긴 fontCollection 객체를 활용하여 폰트를 만든다.

 

 

 

방법이 귀찮고 어려운 이유는, CustomFontCollection만들기 위해 필요한 IDWriteFontCollectionLoader 객체를 결국 사용자가 직접 구현을 줘야 한다는 점이다.

 

이러한 문제는 Windows 10 되면서 매우 간단하게 해결이 되었다.

 

 

 

  1. Windows 10 이상의 버전에서 사용하는 방법

 

말도 필요 없을 정도로 간단해졌다.

 

Windows 10부터 추가된 IDWriteFactory3 객체에FontSet 관련 API 들어가서, 더는FontCollectionLoader 객체를 직접 만들어줄 필요가 없어졌다.

 

사실 버전의 폰트 추가 방법에 대해서는 MS 공식문서가 되어 있어서 굳이 포스팅할 필요는 없지만, 간단히 소개해보자 한다.

 

우선 공식 문서 : https://docs.microsoft.com/en-us/windows/desktop/directwrite/custom-font-sets-win10

 

이번에는 리소스에 저장된 폰트는 설명을 생략한다. 공식 문서의 InMemoryFont 참고.

https://docs.microsoft.com/en-us/windows/desktop/directwrite/custom-font-sets-win10#creating-a-custom-font-set-using-font-data-loaded-into-memory

 

 

그리고 포스트에서 설명하는 IDWriteFactory5 객체에 대해서이다. IDWriteFactory3 객체에 대해서는 공식 문서를 참고하기 바란다.

 

가지 필요한 클래스들을 열거해보겠다.


IDWriteFontFile

FontFileReference 얻기 위해 필요한 객체

IDWriteFontSetBuilder1

FontFile 추가하여 FontSet 만드는 Builder 객체

IDWriteFontSet

FontCollection 바꿔먹을

 

최종적으로 FontCollection 만들어지면 개의 객체는 유지되지 않아도 괜찮다. , InMemoryFont 위한 IDWriteInMemoryFontFileLoader 객체의 경우에는 따로 가지고 있다가 객체 소멸 UnregisterFontFileLoader 호출해야한다.

 

 

 

아까 Windows 7/8.1과는 다르게 정말 편해졌다.

 

  ComPtr<IDWriteFontFile> fontFileReference;

 dwFactory->CreateFontFileReference(L"MyFont.ttf", nullptr, &fontFileReference);
 
 ComPtr<IDWriteFontSetBuilder1> fontSetBuilder;
  dwFactory->CreateFontSetBuilder(&fontSetBuilder);
 
  fontSetBuilder->AddFontFile(fontFileReference.Get());
 
 ComPtr<IDWriteFontSet> customFontSet;
  fontSetBuilder->CreateFontSet(&customFontSet);
 
  dwFactory->CreateFontCollectionFromFontSet(

       customFontSet.Get()

    , &m_pdwFontCollection

    );

 

 

 

+) 추가

 

이렇게 추가한 폰트의 이름을 모를 있다. 예를 들어 "TFont"인줄 알았는데 "Test Font"라고 입력해야만 해당 폰트를 찾을 수도 있고. 이럴 때를 위한 폰트 이름을 찾는 방법이다.

 

여기서 폰트이름을 TCHAR[65] 설정했는데, 사실 이건 내가 몰라서 이렇게 지은 것이다. 수도 있다. 적절히 정하자.

 

원리는 단순하다. 아까 만든 FontCollection에서 FontFamily 얻어내 이름들을 얻어올 것이다.

 

  ComPtr<IDWriteFontFamily> fontFamily;
 ComPtr<IDWriteLocalizedStrings> localizedFontName;
 TCHAR c_styleFontName[65];

  m_pdwFontCollection->GetFontFamily(0, &fontFamily);
  fontFamily->GetFamilyNames(&localizedFontName);
  localizedFontName->GetString(0, c_styleFontName, 65);

 

만약 여러 개의 폰트를 FontCollection 추가했다면, FontCollection GetCount 등의 함수가 있으니 적절히 참고하자.

 




덧글

댓글 입력 영역