[client] windows: compile DirectWrite font support as C++

This commit is contained in:
Geoffrey McRae
2026-10-03 09:41:53 +10:00
parent faa078f069
commit 1ff31304cd
3 changed files with 93 additions and 72 deletions

View File

@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(client_platform_Windows LANGUAGES C) project(client_platform_Windows LANGUAGES C CXX)
add_library(client_platform_Windows STATIC add_library(client_platform_Windows STATIC
clipboard_files.c clipboard_files.c
config.c config.c
font.c font.cpp
input.c input.c
process.c process.c
) )

View File

@@ -18,20 +18,23 @@
* Temple Place, Suite 330, Boston, MA 02111-1307 USA * Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#define COBJMACROS
#include <windows.h> #include <windows.h>
#include <initguid.h>
#include <dwrite.h> #include <dwrite.h>
#include "font_platform.h" #include "font_platform.h"
#include "common/debug.h" #include <inttypes.h>
#include "common/win32.h"
#include <limits.h> #include <limits.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
extern "C"
{
#include "common/debug.h"
#include "common/win32.h"
}
struct FontPlatform struct FontPlatform
{ {
IDWriteFactory * factory; IDWriteFactory * factory;
@@ -48,64 +51,68 @@ static bool font_platformGetFacePath(
*index = 0; *index = 0;
UINT32 fileCount = 0; UINT32 fileCount = 0;
HRESULT result = IDWriteFontFace_GetFiles(face, &fileCount, NULL); HRESULT result = face->GetFiles(&fileCount, NULL);
if (FAILED(result) || fileCount != 1) if (FAILED(result) || fileCount != 1)
return false; return false;
IDWriteFontFile * file = NULL; IDWriteFontFile * file = NULL;
result = IDWriteFontFace_GetFiles(face, &fileCount, &file); result = face->GetFiles(&fileCount, &file);
if (FAILED(result) || !file) if (FAILED(result) || !file)
return false; return false;
IDWriteFontFileLoader * loader = NULL; IDWriteFontFileLoader * loader = NULL;
result = IDWriteFontFile_GetLoader(file, &loader); result = file->GetLoader(&loader);
if (FAILED(result) || !loader) if (FAILED(result) || !loader)
{ {
IDWriteFontFile_Release(file); file->Release();
return false; return false;
} }
IDWriteLocalFontFileLoader * local = NULL; IDWriteLocalFontFileLoader * local = NULL;
result = IDWriteFontFileLoader_QueryInterface(loader, result = loader->QueryInterface(__uuidof(IDWriteLocalFontFileLoader),
&IID_IDWriteLocalFontFileLoader, (void **)&local); reinterpret_cast<void **>(&local));
if (FAILED(result) || !local) if (FAILED(result) || !local)
{ {
IDWriteFontFileLoader_Release(loader); loader->Release();
IDWriteFontFile_Release(file); file->Release();
return false; return false;
} }
const void * key; const void * key = NULL;
UINT32 keySize; UINT32 keySize = 0;
result = IDWriteFontFile_GetReferenceKey(file, &key, &keySize); UINT32 pathLength = 0;
UINT32 pathCapacity = 0;
size_t pathSize = 0;
wchar_t * widePath = NULL;
UINT32 faceIndex = 0;
result = file->GetReferenceKey(&key, &keySize);
if (FAILED(result)) if (FAILED(result))
goto done; goto done;
UINT32 pathLength; result = local->GetFilePathLengthFromKey(key, keySize, &pathLength);
result = IDWriteLocalFontFileLoader_GetFilePathLengthFromKey(
local, key, keySize, &pathLength);
if (FAILED(result)) if (FAILED(result))
goto done; goto done;
const UINT32 pathCapacity = pathLength + 1; pathCapacity = pathLength + 1;
if (!pathCapacity) if (!pathCapacity)
goto done; goto done;
const size_t pathSize = (size_t)pathCapacity * sizeof(wchar_t); pathSize = static_cast<size_t>(pathCapacity) * sizeof(wchar_t);
if (pathSize / sizeof(wchar_t) != pathCapacity) if (pathSize / sizeof(wchar_t) != pathCapacity)
goto done; goto done;
wchar_t * widePath = malloc(pathSize); widePath = static_cast<wchar_t *>(malloc(pathSize));
if (!widePath) if (!widePath)
goto done; goto done;
result = IDWriteLocalFontFileLoader_GetFilePathFromKey( result = local->GetFilePathFromKey(
local, key, keySize, widePath, pathCapacity); key, keySize, widePath, pathCapacity);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
*path = lgWideToUtf8(widePath); *path = lgWideToUtf8(widePath);
free(widePath); free(widePath);
const UINT32 faceIndex = IDWriteFontFace_GetIndex(face); faceIndex = face->GetIndex();
if (!*path || faceIndex > INT_MAX) if (!*path || faceIndex > INT_MAX)
{ {
free(*path); free(*path);
@@ -113,12 +120,12 @@ static bool font_platformGetFacePath(
goto done; goto done;
} }
*index = (int)faceIndex; *index = static_cast<int>(faceIndex);
done: done:
IDWriteLocalFontFileLoader_Release(local); local->Release();
IDWriteFontFileLoader_Release(loader); loader->Release();
IDWriteFontFile_Release(file); file->Release();
return *path != NULL; return *path != NULL;
} }
@@ -126,12 +133,12 @@ static bool font_platformGetFontPath(
IDWriteFont * font, char ** path, int * index) IDWriteFont * font, char ** path, int * index)
{ {
IDWriteFontFace * face = NULL; IDWriteFontFace * face = NULL;
const HRESULT result = IDWriteFont_CreateFontFace(font, &face); const HRESULT result = font->CreateFontFace(&face);
if (FAILED(result) || !face) if (FAILED(result) || !face)
return false; return false;
const bool success = font_platformGetFacePath(face, path, index); const bool success = font_platformGetFacePath(face, path, index);
IDWriteFontFace_Release(face); face->Release();
return success; return success;
} }
@@ -141,24 +148,24 @@ static bool font_platformGetFamilyFont(FontPlatform * platform,
*font = NULL; *font = NULL;
IDWriteFontFamily * family = NULL; IDWriteFontFamily * family = NULL;
HRESULT result = IDWriteFontCollection_GetFontFamily( HRESULT result = platform->collection->GetFontFamily(
platform->collection, familyIndex, &family); familyIndex, &family);
if (FAILED(result) || !family) if (FAILED(result) || !family)
return false; return false;
result = IDWriteFontFamily_GetFirstMatchingFont(family, result = family->GetFirstMatchingFont(
DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STRETCH_NORMAL,
DWRITE_FONT_STYLE_NORMAL, font); DWRITE_FONT_STYLE_NORMAL, font);
IDWriteFontFamily_Release(family); family->Release();
return SUCCEEDED(result) && *font; return SUCCEEDED(result) && *font;
} }
static bool font_platformFindFamily(FontPlatform * platform, static bool font_platformFindFamily(FontPlatform * platform,
const wchar_t * name, UINT32 * familyIndex) const wchar_t * name, UINT32 * familyIndex)
{ {
BOOL exists = FALSE; BOOL exists = FALSE;
const HRESULT result = IDWriteFontCollection_FindFamilyName( const HRESULT result = platform->collection->FindFamilyName(
platform->collection, name, familyIndex, &exists); name, familyIndex, &exists);
return SUCCEEDED(result) && exists; return SUCCEEDED(result) && exists;
} }
@@ -175,27 +182,29 @@ static bool font_platformAddFont(IDWriteFont * font,
return false; return false;
IDWriteFontFace * face = NULL; IDWriteFontFace * face = NULL;
HRESULT result = IDWriteFont_CreateFontFace(font, &face); HRESULT result = font->CreateFontFace(&face);
if (FAILED(result) || !face) if (FAILED(result) || !face)
return true; return true;
uint16_t * indices = malloc(*remainingCount * sizeof(*indices)); uint16_t * indices = static_cast<uint16_t *>(
uint32_t * covered = malloc(*remainingCount * sizeof(*covered)); malloc(*remainingCount * sizeof(*indices)));
uint32_t * covered = static_cast<uint32_t *>(
malloc(*remainingCount * sizeof(*covered)));
if (!indices || !covered) if (!indices || !covered)
{ {
free(indices); free(indices);
free(covered); free(covered);
IDWriteFontFace_Release(face); face->Release();
return false; return false;
} }
result = IDWriteFontFace_GetGlyphIndices(face, remaining, result = face->GetGlyphIndices(
(UINT32)*remainingCount, indices); remaining, static_cast<UINT32>(*remainingCount), indices);
if (FAILED(result)) if (FAILED(result))
{ {
free(indices); free(indices);
free(covered); free(covered);
IDWriteFontFace_Release(face); face->Release();
return true; return true;
} }
@@ -208,7 +217,7 @@ static bool font_platformAddFont(IDWriteFont * font,
if (!coveredCount) if (!coveredCount)
{ {
free(covered); free(covered);
IDWriteFontFace_Release(face); face->Release();
return true; return true;
} }
@@ -217,11 +226,11 @@ static bool font_platformAddFont(IDWriteFont * font,
if (!font_platformGetFacePath(face, &path, &index)) if (!font_platformGetFacePath(face, &path, &index))
{ {
free(covered); free(covered);
IDWriteFontFace_Release(face); face->Release();
return true; return true;
} }
IDWriteFontFace_Release(face); face->Release();
const FontPlatformFaceResult faceResult = addFace( const FontPlatformFaceResult faceResult = addFace(
opaque, path, index, covered, coveredCount); opaque, path, index, covered, coveredCount);
free(path); free(path);
@@ -264,7 +273,8 @@ bool font_platformInit(FontPlatform ** platform)
*platform = NULL; *platform = NULL;
FontPlatform * state = calloc(1, sizeof(*state)); FontPlatform * state = static_cast<FontPlatform *>(
calloc(1, sizeof(*state)));
if (!state) if (!state)
return false; return false;
@@ -273,30 +283,32 @@ bool font_platformInit(FontPlatform ** platform)
state->comInitialized = true; state->comInitialized = true;
else if (result != RPC_E_CHANGED_MODE) else if (result != RPC_E_CHANGED_MODE)
{ {
DEBUG_ERROR("CoInitializeEx failed: 0x%08lx", (unsigned long)result); DEBUG_ERROR("CoInitializeEx failed: 0x%08lx",
static_cast<unsigned long>(result));
free(state); free(state);
return false; return false;
} }
result = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, result = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
&IID_IDWriteFactory, (IUnknown **)&state->factory); __uuidof(IDWriteFactory),
reinterpret_cast<IUnknown **>(&state->factory));
if (FAILED(result) || !state->factory) if (FAILED(result) || !state->factory)
{ {
DEBUG_ERROR("DWriteCreateFactory failed: 0x%08lx", DEBUG_ERROR("DWriteCreateFactory failed: 0x%08lx",
(unsigned long)result); static_cast<unsigned long>(result));
if (state->comInitialized) if (state->comInitialized)
CoUninitialize(); CoUninitialize();
free(state); free(state);
return false; return false;
} }
result = IDWriteFactory_GetSystemFontCollection( result = state->factory->GetSystemFontCollection(
state->factory, &state->collection, FALSE); &state->collection, FALSE);
if (FAILED(result) || !state->collection) if (FAILED(result) || !state->collection)
{ {
DEBUG_ERROR("GetSystemFontCollection failed: 0x%08lx", DEBUG_ERROR("GetSystemFontCollection failed: 0x%08lx",
(unsigned long)result); static_cast<unsigned long>(result));
IDWriteFactory_Release(state->factory); state->factory->Release();
if (state->comInitialized) if (state->comInitialized)
CoUninitialize(); CoUninitialize();
free(state); free(state);
@@ -313,11 +325,11 @@ void font_platformFree(FontPlatform * platform)
return; return;
if (platform->primary) if (platform->primary)
IDWriteFont_Release(platform->primary); platform->primary->Release();
if (platform->collection) if (platform->collection)
IDWriteFontCollection_Release(platform->collection); platform->collection->Release();
if (platform->factory) if (platform->factory)
IDWriteFactory_Release(platform->factory); platform->factory->Release();
if (platform->comInitialized) if (platform->comInitialized)
CoUninitialize(); CoUninitialize();
@@ -333,7 +345,7 @@ char * font_platformSelect(FontPlatform * platform, const char * fontName)
if (!familyLength || familyLength == SIZE_MAX) if (!familyLength || familyLength == SIZE_MAX)
return NULL; return NULL;
char * familyName = malloc(familyLength + 1); char * familyName = static_cast<char *>(malloc(familyLength + 1));
if (!familyName) if (!familyName)
return NULL; return NULL;
memcpy(familyName, fontName, familyLength); memcpy(familyName, fontName, familyLength);
@@ -364,7 +376,7 @@ char * font_platformSelect(FontPlatform * platform, const char * fontName)
{ {
if (selected) if (selected)
{ {
IDWriteFont_Release(selected); selected->Release();
selected = NULL; selected = NULL;
} }
@@ -378,7 +390,7 @@ char * font_platformSelect(FontPlatform * platform, const char * fontName)
{ {
if (selected) if (selected)
{ {
IDWriteFont_Release(selected); selected->Release();
selected = NULL; selected = NULL;
} }
continue; continue;
@@ -389,7 +401,7 @@ char * font_platformSelect(FontPlatform * platform, const char * fontName)
} }
if (!selected && if (!selected &&
IDWriteFontCollection_GetFontFamilyCount(platform->collection) && platform->collection->GetFontFamilyCount() &&
font_platformGetFamilyFont(platform, 0, &selected) && font_platformGetFamilyFont(platform, 0, &selected) &&
font_platformGetFontPath(selected, &selectedPath, &selectedIndex)) font_platformGetFontPath(selected, &selectedPath, &selectedIndex))
selectedFamily = 0; selectedFamily = 0;
@@ -399,13 +411,13 @@ char * font_platformSelect(FontPlatform * platform, const char * fontName)
if (!selected || !selectedPath) if (!selected || !selectedPath)
{ {
if (selected) if (selected)
IDWriteFont_Release(selected); selected->Release();
DEBUG_ERROR("Failed to locate the requested font: %s", fontName); DEBUG_ERROR("Failed to locate the requested font: %s", fontName);
return NULL; return NULL;
} }
if (platform->primary) if (platform->primary)
IDWriteFont_Release(platform->primary); platform->primary->Release();
platform->primary = selected; platform->primary = selected;
platform->primaryFamily = selectedFamily; platform->primaryFamily = selectedFamily;
return selectedPath; return selectedPath;
@@ -420,19 +432,19 @@ bool font_platformResolve(FontPlatform * platform,
glyphCount > SIZE_MAX / sizeof(*glyphs)) glyphCount > SIZE_MAX / sizeof(*glyphs))
return false; return false;
uint32_t * remaining = malloc(glyphCount * sizeof(*remaining)); uint32_t * remaining = static_cast<uint32_t *>(
malloc(glyphCount * sizeof(*remaining)));
if (!remaining && glyphCount) if (!remaining && glyphCount)
return false; return false;
if (glyphCount) if (glyphCount)
memcpy(remaining, glyphs, glyphCount * sizeof(*remaining)); memcpy(remaining, glyphs, glyphCount * sizeof(*remaining));
size_t remainingCount = glyphCount; const UINT32 familyCount = platform->collection->GetFontFamilyCount();
size_t remainingCount = glyphCount;
if (!font_platformAddFont(platform->primary, remaining, if (!font_platformAddFont(platform->primary, remaining,
&remainingCount, addFace, opaque)) &remainingCount, addFace, opaque))
goto fail; goto fail;
const UINT32 familyCount = IDWriteFontCollection_GetFontFamilyCount(
platform->collection);
for (UINT32 i = 0; i < familyCount && remainingCount; ++i) for (UINT32 i = 0; i < familyCount && remainingCount; ++i)
{ {
if (i == platform->primaryFamily) if (i == platform->primaryFamily)
@@ -444,7 +456,7 @@ bool font_platformResolve(FontPlatform * platform,
const bool success = font_platformAddFont( const bool success = font_platformAddFont(
font, remaining, &remainingCount, addFace, opaque); font, remaining, &remainingCount, addFace, opaque);
IDWriteFont_Release(font); font->Release();
if (!success) if (!success)
goto fail; goto fail;
} }

View File

@@ -25,6 +25,11 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct FontPlatform FontPlatform; typedef struct FontPlatform FontPlatform;
typedef enum FontPlatformFaceResult typedef enum FontPlatformFaceResult
@@ -48,4 +53,8 @@ bool font_platformResolve(FontPlatform * platform,
const uint32_t * glyphs, size_t glyphCount, const uint32_t * glyphs, size_t glyphCount,
FontPlatformAddFaceFn addFace, void * opaque, size_t * unresolved); FontPlatformAddFaceFn addFace, void * opaque, size_t * unresolved);
#ifdef __cplusplus
}
#endif
#endif #endif