cache direct-write font faces
This commit is contained in:
parent
4ddc2f1666
commit
c140b6271b
@ -39,7 +39,7 @@ void AsyncWorkerEntryPoint(WaveLaneCtx *lane)
|
||||
AsyncWorkerCtx *w = &Base.async.worker_ctx;
|
||||
|
||||
/* FIXME: Remove this */
|
||||
SleepSeconds(0.100);
|
||||
SleepSeconds(0.001);
|
||||
|
||||
//////////////////////////////
|
||||
//- Begin tick
|
||||
|
||||
@ -5,7 +5,7 @@ void WaveSyncEx(WaveLaneCtx *lane, u64 spin_count)
|
||||
{
|
||||
WaveCtx *wave = lane->wave;
|
||||
i32 lanes_count = wave->lanes_count;
|
||||
if (lanes_count > 0)
|
||||
if (lanes_count > 1)
|
||||
{
|
||||
i64 sync_gen = Atomic64Fetch(&wave->sync_gen.v);
|
||||
i32 blocked_count = Atomic32FetchAdd(&wave->sync_count.v, 1) + 1;
|
||||
|
||||
@ -69,8 +69,8 @@
|
||||
|
||||
#define FLOOD_DEBUG 0
|
||||
|
||||
#define GPU_DEBUG 1
|
||||
#define GPU_DEBUG_VALIDATION 1
|
||||
#define GPU_DEBUG 0
|
||||
#define GPU_DEBUG_VALIDATION 0
|
||||
|
||||
#define GPU_SHADER_PRINT 1
|
||||
#define GPU_SHADER_PRINT_BUFFER_SIZE Kibi(64);
|
||||
|
||||
@ -5,8 +5,11 @@ V_WidgetTheme V_GetWidgetTheme(void)
|
||||
{
|
||||
V_WidgetTheme theme = ZI;
|
||||
|
||||
theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
|
||||
theme.font_size = 16;
|
||||
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
|
||||
// theme.font_size = 16;
|
||||
|
||||
theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/roboto-med.ttf")));
|
||||
theme.font_size = 100;
|
||||
|
||||
theme.window_background_color = Rgb32(0xff1a1d1e);
|
||||
theme.window_border_color = Rgb32(0xff343a3b);
|
||||
|
||||
@ -8,152 +8,40 @@ extern TTF_DW_Ctx TTF_DW = ZI;
|
||||
|
||||
void TTF_Bootstrap(void)
|
||||
{
|
||||
/* FIXME: I think IDWriteFactory5 only exists on later updates of windows
|
||||
/* TODO: I think IDWriteFactory5 only exists on later updates of windows
|
||||
* 10? Need to verify. Maybe should just use a custom loader. (We're only
|
||||
* using a factory5 since I think WriteInMemoryFileLoader wasn't
|
||||
* implemented until then) */
|
||||
HRESULT hr = DWriteCreateFactory(
|
||||
DWRITE_FACTORY_TYPE_SHARED,
|
||||
&IID_IDWriteFactory5,
|
||||
(void **)&TTF_DW.factory
|
||||
);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
Panic(Lit("Error creating DWrite factory"));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ @hookimpl Rasterize
|
||||
|
||||
TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, ResourceKey ttf, f32 font_size)
|
||||
{
|
||||
COLORREF bg_color = 0xFF000000;
|
||||
COLORREF fg_color = 0xFFFFFFFF;
|
||||
|
||||
f32 em_size = font_size * (3.0 / 4.0);
|
||||
f32 pixel_per_em = em_size * (TTF_DW_Dpi / 72.0f);
|
||||
|
||||
/* TODO: handle errors */
|
||||
* implemented until then)
|
||||
*/
|
||||
HRESULT hr = 0;
|
||||
|
||||
String encoded = DataFromResource(ttf);
|
||||
|
||||
/* File */
|
||||
IDWriteFontFile *font_file = 0;
|
||||
{
|
||||
/* Create in memory loader */
|
||||
IDWriteInMemoryFontFileLoader *loader = 0;
|
||||
hr = IDWriteFactory5_CreateInMemoryFontFileLoader(TTF_DW.factory, &loader);
|
||||
hr = IDWriteFactory5_RegisterFontFileLoader(TTF_DW.factory, (IDWriteFontFileLoader *)loader);
|
||||
|
||||
IDWriteFontSetBuilder1 *builder = 0;
|
||||
hr = IDWriteFactory5_CreateFontSetBuilder1(TTF_DW.factory, &builder);
|
||||
hr = IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(loader, (IDWriteFactory *)TTF_DW.factory, encoded.text, (u32)encoded.len, 0, &font_file);
|
||||
hr = IDWriteFontSetBuilder1_AddFontFile(builder, font_file);
|
||||
/* Factory */
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory5, (void **)&TTF_DW.factory);
|
||||
}
|
||||
|
||||
/* Face */
|
||||
IDWriteFontFace *font_face = 0;
|
||||
/* GDI interop */
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteFactory5_CreateFontFace(TTF_DW.factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &font_file, 0, DWRITE_FONT_SIMULATIONS_NONE, &font_face);
|
||||
hr = IDWriteFactory5_GetGdiInterop(TTF_DW.factory, &TTF_DW.gdi_interop);
|
||||
}
|
||||
|
||||
/* Glyph idx */
|
||||
u16 glyph_idx = 0;
|
||||
/* Loader */
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteFontFace_GetGlyphIndices(font_face, &codepoint, 1, &glyph_idx);
|
||||
hr = IDWriteFactory5_CreateInMemoryFontFileLoader(TTF_DW.factory, &TTF_DW.loader);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteFactory5_RegisterFontFileLoader(TTF_DW.factory, (IDWriteFontFileLoader *)TTF_DW.loader);
|
||||
}
|
||||
|
||||
/* Font metrics */
|
||||
DWRITE_FONT_METRICS font_metrics = ZI;
|
||||
{
|
||||
IDWriteFontFace_GetMetrics(font_face, &font_metrics);
|
||||
}
|
||||
f32 pixel_per_design_unit = pixel_per_em / ((f32)font_metrics.designUnitsPerEm);
|
||||
f32 font_ascent = font_metrics.ascent * pixel_per_design_unit;
|
||||
f32 font_descent = font_metrics.descent * pixel_per_design_unit;
|
||||
f32 font_cap = font_metrics.capHeight * pixel_per_design_unit;
|
||||
|
||||
/* Glyph metrics */
|
||||
DWRITE_GLYPH_METRICS m = ZI;
|
||||
/* Builder */
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteFontFace_GetDesignGlyphMetrics(font_face, &glyph_idx, 1, &m, 0);
|
||||
hr = IDWriteFactory5_CreateFontSetBuilder1(TTF_DW.factory, &TTF_DW.builder);
|
||||
}
|
||||
f32 advance = (f32)m.advanceWidth * pixel_per_design_unit;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Get interop */
|
||||
IDWriteGdiInterop *dwrite_gdi_interop = 0;
|
||||
/* Rendering params */
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteFactory5_GetGdiInterop(TTF_DW.factory, &dwrite_gdi_interop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* FIXME: Dynamic render target */
|
||||
Vec2I32 rt_dims = VEC2I32(256, 256);
|
||||
|
||||
/* Best-guess a position in the middle of the render target based on metrics */
|
||||
Vec2I32 rt_baseline = ZI;
|
||||
rt_baseline.x = (rt_dims.x / 2) - (advance / 2);
|
||||
rt_baseline.y = (rt_dims.y / 2) + (font_cap / 2);
|
||||
|
||||
/* Create render target */
|
||||
IDWriteBitmapRenderTarget *render_target = 0;
|
||||
{
|
||||
hr = IDWriteGdiInterop_CreateBitmapRenderTarget(dwrite_gdi_interop, 0, (UINT32)rt_dims.x, (UINT32)rt_dims.y, &render_target);
|
||||
hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(render_target, TTF_DW_Dpi / 96.0);
|
||||
}
|
||||
|
||||
/* Get device context */
|
||||
HDC dc = 0;
|
||||
{
|
||||
dc = IDWriteBitmapRenderTarget_GetMemoryDC(render_target);
|
||||
}
|
||||
|
||||
/* Get dib info */
|
||||
DIBSECTION dib = ZI;
|
||||
{
|
||||
HBITMAP bitmap = (HBITMAP)GetCurrentObject(dc, OBJ_BITMAP);
|
||||
GetObject(bitmap, sizeof(dib), &dib);
|
||||
}
|
||||
|
||||
/* Clear render target */
|
||||
{
|
||||
HGDIOBJ original = SelectObject(dc, GetStockObject(DC_PEN));
|
||||
{
|
||||
SetDCPenColor(dc, bg_color);
|
||||
SelectObject(dc, GetStockObject(DC_BRUSH));
|
||||
SetDCBrushColor(dc, bg_color);
|
||||
Rectangle(dc, 0, 0, rt_dims.x, rt_dims.y);
|
||||
}
|
||||
SelectObject(dc, original);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Create rendering params */
|
||||
IDWriteRenderingParams *rendering_params = 0;
|
||||
{
|
||||
/* Get default rendering params */
|
||||
IDWriteRenderingParams *default_rendering_params = 0;
|
||||
{
|
||||
hr = IDWriteFactory5_CreateRenderingParams(TTF_DW.factory, &default_rendering_params);
|
||||
@ -168,17 +56,187 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
||||
clear_type_level,
|
||||
DWRITE_PIXEL_GEOMETRY_FLAT,
|
||||
DWRITE_RENDERING_MODE_DEFAULT,
|
||||
&rendering_params
|
||||
&TTF_DW.rendering_params
|
||||
);
|
||||
IDWriteRenderingParams_Release(default_rendering_params);
|
||||
}
|
||||
}
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
Panic(Lit("Failed to initialize DirectWrite"));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ @hookimpl Rasterize
|
||||
|
||||
TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, ResourceKey ttf, f32 font_size)
|
||||
{
|
||||
/* TODO: handle errors */
|
||||
COLORREF bg_color = 0xFF000000;
|
||||
COLORREF fg_color = 0xFFFFFFFF;
|
||||
|
||||
f32 em_size = font_size * (3.0 / 4.0);
|
||||
f32 pixels_per_em = em_size * (TTF_DW_Dpi / 72.0f);
|
||||
|
||||
/* Load font */
|
||||
HRESULT hr = 0;
|
||||
TTF_DW_Font *font = 0;
|
||||
{
|
||||
u64 hash = RandU64FromSeeds(ttf.v, (u64)(*(u32 *)&font_size));
|
||||
/* Grab font from cache */
|
||||
{
|
||||
Lock lock = LockS(&TTF_DW.font_bins_mutex);
|
||||
{
|
||||
TTF_DW_Font **bin = &TTF_DW.font_bins[hash % countof(TTF_DW.font_bins)];
|
||||
for (font = *bin; font; font = font->next)
|
||||
{
|
||||
if (font->hash == hash && font->ttf.v == ttf.v && font->size == font_size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Unlock(&lock);
|
||||
}
|
||||
/* Create font new font */
|
||||
if (!font)
|
||||
{
|
||||
Lock lock = LockE(&TTF_DW.font_bins_mutex);
|
||||
{
|
||||
TTF_DW_Font **bin = &TTF_DW.font_bins[hash % countof(TTF_DW.font_bins)];
|
||||
for (font = *bin; font; font = font->next)
|
||||
{
|
||||
if (font->hash == hash && font->ttf.v == ttf.v && font->size == font_size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!font)
|
||||
{
|
||||
Arena *perm = PermArena();
|
||||
String encoded = DataFromResource(ttf);
|
||||
font = PushStruct(perm, TTF_DW_Font);
|
||||
font->hash = hash;
|
||||
font->ttf = ttf;
|
||||
font->size = font_size;
|
||||
/* File */
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteInMemoryFontFileLoader_CreateInMemoryFontFileReference(
|
||||
TTF_DW.loader,
|
||||
(IDWriteFactory *)TTF_DW.factory,
|
||||
encoded.text,
|
||||
(u32)encoded.len,
|
||||
0,
|
||||
&font->file
|
||||
);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteFontSetBuilder1_AddFontFile(TTF_DW.builder, font->file);
|
||||
}
|
||||
}
|
||||
/* Face */
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteFactory5_CreateFontFace(
|
||||
TTF_DW.factory,
|
||||
DWRITE_FONT_FACE_TYPE_TRUETYPE,
|
||||
1,
|
||||
&font->file,
|
||||
0,
|
||||
DWRITE_FONT_SIMULATIONS_NONE,
|
||||
&font->face
|
||||
);
|
||||
}
|
||||
/* Metrics */
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IDWriteFontFace_GetMetrics(font->face, &font->design_metrics);
|
||||
}
|
||||
font->hr = hr;
|
||||
SllStackPush(*bin, font);
|
||||
}
|
||||
}
|
||||
Unlock(&lock);
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = font->hr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Render glyph to target */
|
||||
f32 design_units_per_em = font->design_metrics.designUnitsPerEm;
|
||||
f32 pixels_per_design_unit = design_units_per_em > 0 ? (pixels_per_em / design_units_per_em) : 0;
|
||||
f32 font_ascent = font->design_metrics.ascent * pixels_per_design_unit;
|
||||
f32 font_descent = font->design_metrics.descent * pixels_per_design_unit;
|
||||
f32 font_cap = font->design_metrics.capHeight * pixels_per_design_unit;
|
||||
|
||||
/* Render glyph */
|
||||
TTF_GlyphResult result = ZI;
|
||||
{
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
/* Glyph idx */
|
||||
u16 glyph_idx = 0;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteFontFace_GetGlyphIndices(font->face, &codepoint, 1, &glyph_idx);
|
||||
}
|
||||
|
||||
/* Glyph metrics */
|
||||
DWRITE_GLYPH_METRICS m = ZI;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteFontFace_GetDesignGlyphMetrics(font->face, &glyph_idx, 1, &m, 0);
|
||||
}
|
||||
f32 advance = (f32)m.advanceWidth * pixels_per_design_unit;
|
||||
|
||||
/* FIXME: Dynamic render target */
|
||||
Vec2I32 rt_dims = VEC2I32(256, 256);
|
||||
|
||||
/* Best-guess a position in the middle of the render target based on metrics */
|
||||
Vec2I32 rt_baseline = ZI;
|
||||
rt_baseline.x = (rt_dims.x / 2) - (advance / 2);
|
||||
rt_baseline.y = (rt_dims.y / 2) + (font_cap / 2);
|
||||
|
||||
/* Create render target */
|
||||
IDWriteBitmapRenderTarget *render_target = 0;
|
||||
HDC dc = 0;
|
||||
DIBSECTION dib = ZI;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteGdiInterop_CreateBitmapRenderTarget(TTF_DW.gdi_interop, 0, (UINT32)rt_dims.x, (UINT32)rt_dims.y, &render_target);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(render_target, TTF_DW_Dpi / 96.0);
|
||||
dc = IDWriteBitmapRenderTarget_GetMemoryDC(render_target);
|
||||
HBITMAP bitmap = (HBITMAP)GetCurrentObject(dc, OBJ_BITMAP);
|
||||
GetObject(bitmap, sizeof(dib), &dib);
|
||||
}
|
||||
}
|
||||
|
||||
/* Render */
|
||||
Rng2I32 rt_slice = ZI;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
/* Clear target */
|
||||
{
|
||||
HGDIOBJ original = SelectObject(dc, GetStockObject(DC_PEN));
|
||||
{
|
||||
SetDCPenColor(dc, bg_color);
|
||||
SelectObject(dc, GetStockObject(DC_BRUSH));
|
||||
SetDCBrushColor(dc, bg_color);
|
||||
Rectangle(dc, 0, 0, rt_dims.x, rt_dims.y);
|
||||
}
|
||||
SelectObject(dc, original);
|
||||
}
|
||||
/* Draw glyph */
|
||||
{
|
||||
DWRITE_GLYPH_RUN glyph_run = ZI;
|
||||
{
|
||||
glyph_run.fontFace = font_face;
|
||||
glyph_run.fontEmSize = pixel_per_em;
|
||||
glyph_run.fontFace = font->face;
|
||||
glyph_run.fontEmSize = pixels_per_em;
|
||||
glyph_run.glyphCount = 1;
|
||||
glyph_run.glyphIndices = &glyph_idx;
|
||||
}
|
||||
@ -189,7 +247,7 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
||||
rt_baseline.y,
|
||||
DWRITE_MEASURING_MODE_NATURAL,
|
||||
&glyph_run,
|
||||
rendering_params,
|
||||
TTF_DW.rendering_params,
|
||||
fg_color,
|
||||
&bounding_box
|
||||
);
|
||||
@ -202,12 +260,15 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
||||
rt_slice.p0.y = MaxI32(rt_slice.p0.y, 0);
|
||||
rt_slice.p1.x = MinI32(rt_slice.p1.x, rt_dims.x);
|
||||
rt_slice.p1.y = MinI32(rt_slice.p1.y, rt_dims.y);
|
||||
|
||||
Vec2I32 dst_dims = DimsFromRng2I32(rt_slice);
|
||||
u32 *dst_pixels = PushStructsNoZero(arena, u32, dst_dims.x * dst_dims.y);
|
||||
}
|
||||
|
||||
/* Copy from target to result */
|
||||
Vec2I32 dst_dims = ZI;
|
||||
u32 *dst_pixels = 0;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
dst_dims = DimsFromRng2I32(rt_slice);
|
||||
dst_pixels = PushStructsNoZero(arena, u32, dst_dims.x * dst_dims.y);
|
||||
u64 src_pitch = (u64)dib.dsBm.bmWidthBytes / 4;
|
||||
u32 *src_pixels = (u32 *)dib.dsBm.bmBits;
|
||||
for (i32 y = 0; y < dst_dims.y; ++y)
|
||||
@ -225,22 +286,21 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
|
||||
}
|
||||
}
|
||||
|
||||
TTF_GlyphResult result = ZI;
|
||||
{
|
||||
result.ttf = ttf;
|
||||
result.codepoint = codepoint;
|
||||
|
||||
result.advance = advance;
|
||||
result.bounds = RNG2(Vec2FromVec(rt_slice.p0), Vec2FromVec(rt_slice.p1));
|
||||
result.bounds = AddRng2Vec2(result.bounds, NegVec2(Vec2FromVec(rt_baseline)));
|
||||
result.image_dims = dst_dims;
|
||||
result.image_pixels = dst_pixels;
|
||||
|
||||
IDWriteBitmapRenderTarget_Release(render_target);
|
||||
}
|
||||
result.ttf = ttf;
|
||||
result.codepoint = codepoint;
|
||||
result.font_size = font_size;
|
||||
result.font_ascent = font_ascent;
|
||||
result.font_descent = font_descent;
|
||||
result.font_cap = font_cap;
|
||||
|
||||
result.image_dims = dst_dims;
|
||||
result.image_pixels = dst_pixels;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -135,10 +135,29 @@ static inline HRESULT IDWriteBitmapRenderTarget_DrawGl
|
||||
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;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Context types
|
||||
|
||||
@ -148,6 +167,13 @@ EXTERN_C HRESULT DECLSPEC_IMPORT WINAPI DWriteCreateFactory (DWRITE_FACTORY_TYPE
|
||||
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];
|
||||
};
|
||||
|
||||
extern TTF_DW_Ctx TTF_DW;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user