193 lines
13 KiB
C
193 lines
13 KiB
C
////////////////////////////////////////////////////////////
|
|
//~ Win32 libs
|
|
|
|
#pragma comment(lib, "dwrite")
|
|
#pragma comment(lib, "gdi32")
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ DirectWrite types
|
|
|
|
/* DirectWrite C API stubs are taken from Mārtiņš Možeiko's c_d2d_dwrite
|
|
* https://github.com/mmozeiko/c_d2d_dwrite/blob/main/cdwrite.h
|
|
*/
|
|
|
|
//- GUIDs
|
|
DEFINE_GUID(IID_IDWriteFactory5, 0x958db99a, 0xbe2a, 0x4f09, 0xaf, 0x7d, 0x65, 0x18, 0x98, 0x03, 0xd1, 0xd3);
|
|
|
|
//- Interfaces
|
|
typedef struct IDWriteFactory { struct { void* tbl[]; }* v; } IDWriteFactory;
|
|
typedef struct IDWriteFactory5 { struct { void* tbl[]; }* v; } IDWriteFactory5;
|
|
typedef struct IDWriteFontFile { struct { void* tbl[]; }* v; } IDWriteFontFile;
|
|
typedef struct IDWriteInMemoryFontFileLoader { struct { void* tbl[]; }* v; } IDWriteInMemoryFontFileLoader;
|
|
typedef struct IDWriteFontFileLoader { struct { void* tbl[]; }* v; } IDWriteFontFileLoader;
|
|
typedef struct IDWriteFontFace { struct { void* tbl[]; }* v; } IDWriteFontFace;
|
|
typedef struct IDWriteRenderingParams { struct { void* tbl[]; }* v; } IDWriteRenderingParams;
|
|
typedef struct IDWriteGdiInterop { struct { void* tbl[]; }* v; } IDWriteGdiInterop;
|
|
typedef struct IDWriteFontSetBuilder { struct { void* tbl[]; }* v; } IDWriteFontSetBuilder;
|
|
typedef struct IDWriteFontSetBuilder1 { struct { void* tbl[]; }* v; } IDWriteFontSetBuilder1;
|
|
typedef struct IDWriteBitmapRenderTarget { struct { void* tbl[]; }* v; } IDWriteBitmapRenderTarget;
|
|
|
|
//- Enums
|
|
typedef enum DWRITE_FACTORY_TYPE {
|
|
DWRITE_FACTORY_TYPE_SHARED = 0,
|
|
DWRITE_FACTORY_TYPE_ISOLATED = 1,
|
|
} DWRITE_FACTORY_TYPE;
|
|
|
|
typedef enum DWRITE_FONT_FACE_TYPE {
|
|
DWRITE_FONT_FACE_TYPE_CFF = 0,
|
|
DWRITE_FONT_FACE_TYPE_TRUETYPE = 1,
|
|
DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION = 2,
|
|
DWRITE_FONT_FACE_TYPE_TYPE1 = 3,
|
|
DWRITE_FONT_FACE_TYPE_VECTOR = 4,
|
|
DWRITE_FONT_FACE_TYPE_BITMAP = 5,
|
|
DWRITE_FONT_FACE_TYPE_UNKNOWN = 6,
|
|
DWRITE_FONT_FACE_TYPE_RAW_CFF = 7,
|
|
DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION = 2,
|
|
} DWRITE_FONT_FACE_TYPE;
|
|
|
|
typedef enum DWRITE_FONT_SIMULATIONS {
|
|
DWRITE_FONT_SIMULATIONS_NONE = 0,
|
|
DWRITE_FONT_SIMULATIONS_BOLD = 1,
|
|
DWRITE_FONT_SIMULATIONS_OBLIQUE = 2,
|
|
} DWRITE_FONT_SIMULATIONS;
|
|
|
|
typedef enum DWRITE_PIXEL_GEOMETRY {
|
|
DWRITE_PIXEL_GEOMETRY_FLAT = 0,
|
|
DWRITE_PIXEL_GEOMETRY_RGB = 1,
|
|
DWRITE_PIXEL_GEOMETRY_BGR = 2,
|
|
} DWRITE_PIXEL_GEOMETRY;
|
|
|
|
typedef enum DWRITE_RENDERING_MODE {
|
|
DWRITE_RENDERING_MODE_DEFAULT = 0,
|
|
DWRITE_RENDERING_MODE_ALIASED = 1,
|
|
DWRITE_RENDERING_MODE_GDI_CLASSIC = 2,
|
|
DWRITE_RENDERING_MODE_GDI_NATURAL = 3,
|
|
DWRITE_RENDERING_MODE_NATURAL = 4,
|
|
DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC = 5,
|
|
DWRITE_RENDERING_MODE_OUTLINE = 6,
|
|
DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC = 2,
|
|
DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL = 3,
|
|
DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL = 4,
|
|
DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC = 5,
|
|
} DWRITE_RENDERING_MODE;
|
|
|
|
//- Structs
|
|
typedef struct DWRITE_FONT_METRICS {
|
|
UINT16 designUnitsPerEm;
|
|
UINT16 ascent;
|
|
UINT16 descent;
|
|
INT16 lineGap;
|
|
UINT16 capHeight;
|
|
UINT16 xHeight;
|
|
INT16 underlinePosition;
|
|
UINT16 underlineThickness;
|
|
INT16 strikethroughPosition;
|
|
UINT16 strikethroughThickness;
|
|
} DWRITE_FONT_METRICS;
|
|
|
|
typedef struct DWRITE_GLYPH_OFFSET {
|
|
FLOAT advanceOffset;
|
|
FLOAT ascenderOffset;
|
|
} DWRITE_GLYPH_OFFSET;
|
|
|
|
typedef struct DWRITE_GLYPH_RUN {
|
|
IDWriteFontFace* fontFace;
|
|
FLOAT fontEmSize;
|
|
UINT32 glyphCount;
|
|
UINT16* glyphIndices;
|
|
FLOAT* glyphAdvances;
|
|
DWRITE_GLYPH_OFFSET* glyphOffsets;
|
|
BOOL isSideways;
|
|
UINT32 bidiLevel;
|
|
} DWRITE_GLYPH_RUN;
|
|
|
|
typedef struct DWRITE_GLYPH_METRICS {
|
|
INT32 leftSideBearing;
|
|
UINT32 advanceWidth;
|
|
INT32 rightSideBearing;
|
|
INT32 topSideBearing;
|
|
UINT32 advanceHeight;
|
|
INT32 bottomSideBearing;
|
|
INT32 verticalOriginY;
|
|
} DWRITE_GLYPH_METRICS;
|
|
|
|
//- Methods
|
|
static inline HRESULT IDWriteFactory5_CreateInMemoryFontFileLoader (IDWriteFactory5* this, IDWriteInMemoryFontFileLoader** newLoader) { return ((HRESULT (WINAPI*)(IDWriteFactory5*, IDWriteInMemoryFontFileLoader**))this->v->tbl[44])(this, newLoader); }
|
|
static inline HRESULT IDWriteFactory5_RegisterFontFileLoader (IDWriteFactory5* this, IDWriteFontFileLoader* fontFileLoader) { return ((HRESULT (WINAPI*)(IDWriteFactory5*, IDWriteFontFileLoader*))this->v->tbl[13])(this, fontFileLoader); }
|
|
static inline HRESULT IDWriteFactory5_CreateFontFace (IDWriteFactory5* this, DWRITE_FONT_FACE_TYPE fontFaceType, UINT32 numberOfFiles, IDWriteFontFile** fontFiles, UINT32 faceIndex, DWRITE_FONT_SIMULATIONS fontFaceSimulationFlags, IDWriteFontFace** fontFace) { return ((HRESULT (WINAPI*)(IDWriteFactory5*, DWRITE_FONT_FACE_TYPE, UINT32, IDWriteFontFile**, UINT32, DWRITE_FONT_SIMULATIONS, IDWriteFontFace**))this->v->tbl[9])(this, fontFaceType, numberOfFiles, fontFiles, faceIndex, fontFaceSimulationFlags, fontFace); }
|
|
static inline HRESULT IDWriteFactory5_CreateRenderingParams (IDWriteFactory5* this, IDWriteRenderingParams** renderingParams) { return ((HRESULT (WINAPI*)(IDWriteFactory5*, IDWriteRenderingParams**))this->v->tbl[10])(this, renderingParams); }
|
|
static inline HRESULT IDWriteFactory5_CreateCustomRenderingParams (IDWriteFactory5* this, FLOAT gamma, FLOAT enhancedContrast, FLOAT clearTypeLevel, DWRITE_PIXEL_GEOMETRY pixelGeometry, DWRITE_RENDERING_MODE renderingMode, IDWriteRenderingParams** renderingParams) { return ((HRESULT (WINAPI*)(IDWriteFactory5*, FLOAT, FLOAT, FLOAT, DWRITE_PIXEL_GEOMETRY, DWRITE_RENDERING_MODE, IDWriteRenderingParams**))this->v->tbl[12])(this, gamma, enhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, renderingParams); }
|
|
static inline HRESULT IDWriteFactory5_GetGdiInterop (IDWriteFactory5* this, IDWriteGdiInterop** gdiInterop) { return ((HRESULT (WINAPI*)(IDWriteFactory5*, IDWriteGdiInterop**))this->v->tbl[17])(this, gdiInterop); }
|
|
static inline UINT32 IDWriteFactory5_Release (IDWriteFactory5* this) { return ((UINT32 (WINAPI*)(IDWriteFactory5*))this->v->tbl[2])(this); }
|
|
static inline HRESULT IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader* this, IDWriteFactory* factory, const void* fontData, UINT32 fontDataSize, IUnknown* ownerObject, IDWriteFontFile** fontFile) { return ((HRESULT (WINAPI*)(IDWriteInMemoryFontFileLoader*, IDWriteFactory*, const void*, UINT32, IUnknown*, IDWriteFontFile**))this->v->tbl[4])(this, factory, fontData, fontDataSize, ownerObject, fontFile); }
|
|
static inline HRESULT IDWriteFontSetBuilder1_AddFontFile (IDWriteFontSetBuilder1* this, IDWriteFontFile* fontFile) { return ((HRESULT (WINAPI*)(IDWriteFontSetBuilder1*, IDWriteFontFile*))this->v->tbl[7])(this, fontFile); }
|
|
static inline UINT32 IDWriteRenderingParams_Release (IDWriteRenderingParams* this) { return ((UINT32 (WINAPI*)(IDWriteRenderingParams*))this->v->tbl[2])(this); }
|
|
static inline FLOAT IDWriteRenderingParams_GetGamma (IDWriteRenderingParams* this) { return ((FLOAT (WINAPI*)(IDWriteRenderingParams*))this->v->tbl[3])(this); }
|
|
static inline HDC IDWriteBitmapRenderTarget_GetMemoryDC (IDWriteBitmapRenderTarget* this) { return ((HDC (WINAPI*)(IDWriteBitmapRenderTarget*))this->v->tbl[4])(this); }
|
|
static inline UINT32 IDWriteFontFile_Release (IDWriteFontFile* this) { return ((UINT32 (WINAPI*)(IDWriteFontFile*))this->v->tbl[2])(this); }
|
|
static inline HRESULT IDWriteFactory5_CreateFontSetBuilder1 (IDWriteFactory5* this, IDWriteFontSetBuilder1** fontSetBuilder) { return ((HRESULT (WINAPI*)(IDWriteFactory5*, IDWriteFontSetBuilder1**))this->v->tbl[43])(this, fontSetBuilder); }static inline FLOAT IDWriteRenderingParams_GetEnhancedContrast (IDWriteRenderingParams* this) { return ((FLOAT (WINAPI*)(IDWriteRenderingParams*))this->v->tbl[4])(this); }
|
|
static inline FLOAT IDWriteRenderingParams_GetClearTypeLevel (IDWriteRenderingParams* this) { return ((FLOAT (WINAPI*)(IDWriteRenderingParams*))this->v->tbl[5])(this); }
|
|
static inline void IDWriteFontFace_GetMetrics (IDWriteFontFace* this, DWRITE_FONT_METRICS* fontFaceMetrics) { ((void (WINAPI*)(IDWriteFontFace*, DWRITE_FONT_METRICS*))this->v->tbl[8])(this, fontFaceMetrics); }
|
|
static inline UINT16 IDWriteFontFace_GetGlyphCount (IDWriteFontFace* this) { return ((UINT16 (WINAPI*)(IDWriteFontFace*))this->v->tbl[9])(this); }
|
|
static inline HRESULT IDWriteGdiInterop_CreateBitmapRenderTarget (IDWriteGdiInterop* this, HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget** renderTarget) { return ((HRESULT (WINAPI*)(IDWriteGdiInterop*, HDC, UINT32, UINT32, IDWriteBitmapRenderTarget**))this->v->tbl[7])(this, hdc, width, height, renderTarget); }
|
|
static inline HRESULT IDWriteBitmapRenderTarget_SetPixelsPerDip (IDWriteBitmapRenderTarget* this, FLOAT pixelsPerDip) { return ((HRESULT (WINAPI*)(IDWriteBitmapRenderTarget*, FLOAT))this->v->tbl[6])(this, pixelsPerDip); }
|
|
static inline HRESULT IDWriteBitmapRenderTarget_DrawGlyphRun (IDWriteBitmapRenderTarget* this, FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE measuringMode, const DWRITE_GLYPH_RUN* glyphRun, IDWriteRenderingParams* renderingParams, COLORREF textColor, RECT* blackBoxRect) { return ((HRESULT (WINAPI*)(IDWriteBitmapRenderTarget*, FLOAT, FLOAT, DWRITE_MEASURING_MODE, const DWRITE_GLYPH_RUN*, IDWriteRenderingParams*, COLORREF, RECT*))this->v->tbl[3])(this, baselineOriginX, baselineOriginY, measuringMode, glyphRun, renderingParams, textColor, blackBoxRect); }
|
|
static inline HRESULT IDWriteFontFace_GetDesignGlyphMetrics (IDWriteFontFace* this, const UINT16* glyphIndices, UINT32 glyphCount, DWRITE_GLYPH_METRICS* glyphMetrics, BOOL isSideways) { return ((HRESULT (WINAPI*)(IDWriteFontFace*, const UINT16*, UINT32, DWRITE_GLYPH_METRICS*, BOOL))this->v->tbl[10])(this, glyphIndices, glyphCount, glyphMetrics, isSideways); }
|
|
static inline HRESULT IDWriteFontFace_GetGlyphIndices (IDWriteFontFace* this, const UINT32* codePoints, UINT32 codePointCount, UINT16* glyphIndices) { return ((HRESULT (WINAPI*)(IDWriteFontFace*, const UINT32*, UINT32, UINT16*))this->v->tbl[11])(this, codePoints, codePointCount, glyphIndices); }
|
|
static inline UINT32 IDWriteGdiInterop_Release (IDWriteGdiInterop* this) { return ((UINT32 (WINAPI*)(IDWriteGdiInterop*))this->v->tbl[2])(this); }
|
|
static inline UINT32 IDWriteBitmapRenderTarget_Release (IDWriteBitmapRenderTarget* this) { return ((UINT32 (WINAPI*)(IDWriteBitmapRenderTarget*))this->v->tbl[2])(this); }
|
|
|
|
//- Functions
|
|
EXTERN_C HRESULT DECLSPEC_IMPORT WINAPI DWriteCreateFactory (DWRITE_FACTORY_TYPE factoryType, const GUID* iid, void** factory) WIN_NOEXCEPT;
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Cache types
|
|
|
|
Struct(TTF_DW_Font)
|
|
{
|
|
TTF_DW_Font *next;
|
|
|
|
u64 hash;
|
|
ResourceKey ttf;
|
|
f32 size;
|
|
|
|
IDWriteFontFile *file;
|
|
IDWriteFontFace *face;
|
|
DWRITE_FONT_METRICS design_metrics;
|
|
|
|
HRESULT hr;
|
|
};
|
|
|
|
Struct(TTF_DW_RenderTarget)
|
|
{
|
|
TTF_DW_RenderTarget *next;
|
|
Vec2I32 dims;
|
|
IDWriteBitmapRenderTarget *dw_rt;
|
|
HDC dc;
|
|
DIBSECTION dib;
|
|
HRESULT hr;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Context types
|
|
|
|
/* TODO: Determine font dpi dynamically */
|
|
#define TTF_DW_Dpi (96.0f)
|
|
|
|
Struct(TTF_DW_Ctx)
|
|
{
|
|
IDWriteFactory5 *factory;
|
|
IDWriteGdiInterop *gdi_interop;
|
|
IDWriteInMemoryFontFileLoader *loader;
|
|
IDWriteFontSetBuilder1 *builder;
|
|
IDWriteRenderingParams *rendering_params;
|
|
|
|
Mutex font_bins_mutex;
|
|
TTF_DW_Font *font_bins[1024];
|
|
|
|
Mutex free_render_targets_mutex;
|
|
TTF_DW_RenderTarget *first_free_render_target;
|
|
};
|
|
|
|
extern TTF_DW_Ctx TTF_DW;
|