시작하기

VSTSDK 3.7.9, 윈도우 10, VS2022 community를 사용했다.
단일 파일(.dll = .vst3) 파일로 빌드하기 -> https://kiriki-liszt.github.io/yg331/production/Windows-VSTSDK-dll-build/

폰트의 호출

uidescrtion -> uinode -> cfont -> win32factory -> D2Dfont

폰트가 사용될 때 다음과 같은 경로로 호출된다.
그리고 기존 customfont가 추가되는 것은 win32factory의 “Win32Factory::createFont”가 “makeOwned < D2DFont > “를 통해 D2DDont가 construst될 때이다.

기존의 customfont

VSTGUI 4.9 이상부터는 Resources/Fonts 폴더에 존재하는 폰트들을 모두 읽어 fontcollection으로 등록하는 구현이 추가되어 있다.
이러한 방식은 macOS에서도 사용할 수 있는 cross-platfrom 기능이지만, 나는 windows 특정 dll 단일 파일로 빌드하기 때문에 사용할 수 없다.

참고 - microsoft/Windows-classic-samples/Samples/DirectWriteCustomFontSets

https://learn.microsoft.com/en-us/windows/win32/directwrite/custom-font-sets-win10
https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/DirectWriteCustomFontSets

두 페이지를 잘 읽어보고 적용해보자.

구현 @ D2Dfont.cpp

namespace VSTGUI {
namespace D2DFontPrivate {

//-----------------------------------------------------------------------------
struct CustomFonts
{
#if VSTGUI_WIN32_CUSTOMFONT_SUPPORT
  struct MemoryFontInfo
  {
    HGLOBAL fontData;
    uint32_t fontDataSize;
  };

  void AddFontResourceToVector (wchar_t const* resourceName)
  {
    HRSRC hFontResource = FindResource (GetInstance (), resourceName, MAKEINTRESOURCE(RT_RCDATA));

    if (hFontResource == nullptr)
      return;

    uint32_t binaryFontDataSize = SizeofResource (GetInstance (), hFontResource);
    HGLOBAL hFontResource_Loaded = LoadResource (GetInstance (), hFontResource);
    if (hFontResource_Loaded == nullptr)
      return;

    void* binaryFontData = LockResource (hFontResource_Loaded);
    if (binaryFontData != nullptr)
    {
      MemoryFontInfo fontInfo = {binaryFontData, binaryFontDataSize};
      m_appFontResources.push_back (fontInfo);
    }
  };

  ~CustomFonts ()
  {
    if (m_inMemoryFontFileLoader.get () != nullptr)
      m_dwriteFactory5->UnregisterFontFileLoader (m_inMemoryFontFileLoader.get ());
  } 

  CustomFonts ()
  {
    auto factory = getDWriteFactory ();

    if (!factory ||
      FAILED (factory->QueryInterface<IDWriteFactory5> (m_dwriteFactory5.adoptPtr ())))
      return;

    m_dwriteFactory5->CreateInMemoryFontFileLoader (m_inMemoryFontFileLoader.adoptPtr ());
    m_dwriteFactory5->RegisterFontFileLoader (m_inMemoryFontFileLoader.get ());

    COM::Ptr<IDWriteFontSetBuilder1> fontSetBuilder;
    m_dwriteFactory5->CreateFontSetBuilder (fontSetBuilder.adoptPtr ());

    // your font  
    AddFontResourceToVector (L"PretendardRegular");

    for (uint32_t fontIndex = 0; fontIndex < m_appFontResources.size (); fontIndex++)
    {
      MemoryFontInfo fontInfo = m_appFontResources[fontIndex];

      COM::Ptr<IDWriteFontFile> fontFileReference;

      m_inMemoryFontFileLoader->CreateInMemoryFontFileReference (
        m_dwriteFactory5.get (),
        fontInfo.fontData,
        fontInfo.fontDataSize,
        m_inMemoryFontFileLoader.get (),
        fontFileReference.adoptPtr());


      fontSetBuilder->AddFontFile (fontFileReference.get ());
    }

    fontSetBuilder->CreateFontSet (fontSet.adoptPtr ());
    m_dwriteFactory5->CreateFontCollectionFromFontSet (fontSet.get (),
    fontCollection.adoptPtr ());
    return;
  }

private:
  COM::Ptr<IDWriteInMemoryFontFileLoader> m_inMemoryFontFileLoader; 
  COM::Ptr<IDWriteFactory5> m_dwriteFactory5;
  COM::Ptr<IDWriteFontSet> fontSet;
  COM::Ptr<IDWriteFontCollection1> fontCollection;

  std::vector<MemoryFontInfo> m_appFontResources;

#else
//~
#endif
};
}
}

구현 @ win32resource

#include <windows.h>
#include "../source/version.h"

#define APSTUDIO_READONLY_SYMBOLS

your_editor.uidesc DATA "your_editor.uidesc"

PretendardRegular RCDATA "Pretendard-Regular.ttf"

//~~~

사용

.rc파일에 RCDATA로 등록해주고, 이름을 지정해준 다음 D2DFont.cpp에서 AddFontResourceToVector 해주면 된다.
물론 다른 폰트, 더 많은 폰트를 사용한다면 다 AddFontResourceToVector 해준다.