dwrite: Added support for transform in glyph run analysis.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5da26de7c3
commit
170e31a8b2
|
@ -201,6 +201,7 @@ struct dwrite_glyphbitmap {
|
||||||
RECT bbox;
|
RECT bbox;
|
||||||
BYTE *buf;
|
BYTE *buf;
|
||||||
DWRITE_TEXTURE_TYPE type;
|
DWRITE_TEXTURE_TYPE type;
|
||||||
|
DWRITE_MATRIX *m;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern BOOL init_freetype(void) DECLSPEC_HIDDEN;
|
extern BOOL init_freetype(void) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -4084,6 +4084,8 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
|
||||||
glyph_bitmap.emsize = analysis->run.fontEmSize * analysis->ppdip;
|
glyph_bitmap.emsize = analysis->run.fontEmSize * analysis->ppdip;
|
||||||
glyph_bitmap.nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL ||
|
glyph_bitmap.nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL ||
|
||||||
analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
|
analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
|
||||||
|
if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
|
||||||
|
glyph_bitmap.m = &analysis->m;
|
||||||
|
|
||||||
for (i = 0; i < analysis->run.glyphCount; i++) {
|
for (i = 0; i < analysis->run.glyphCount; i++) {
|
||||||
const D2D_POINT_2F *advanceoffset = analysis->advanceoffsets ? analysis->advanceoffsets + i : NULL;
|
const D2D_POINT_2F *advanceoffset = analysis->advanceoffsets ? analysis->advanceoffsets + i : NULL;
|
||||||
|
@ -4126,6 +4128,8 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
|
||||||
|
|
||||||
/* translate to given run origin */
|
/* translate to given run origin */
|
||||||
OffsetRect(&analysis->bounds, analysis->origin.x, analysis->origin.y);
|
OffsetRect(&analysis->bounds, analysis->origin.x, analysis->origin.y);
|
||||||
|
if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
|
||||||
|
OffsetRect(&analysis->bounds, analysis->m.dx, analysis->m.dy);
|
||||||
|
|
||||||
analysis->flags |= RUNANALYSIS_BOUNDS_READY;
|
analysis->flags |= RUNANALYSIS_BOUNDS_READY;
|
||||||
*bounds = analysis->bounds;
|
*bounds = analysis->bounds;
|
||||||
|
@ -4198,6 +4202,8 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
|
||||||
glyph_bitmap.nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL ||
|
glyph_bitmap.nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL ||
|
||||||
analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
|
analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
|
||||||
glyph_bitmap.type = type;
|
glyph_bitmap.type = type;
|
||||||
|
if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
|
||||||
|
glyph_bitmap.m = &analysis->m;
|
||||||
bbox = &glyph_bitmap.bbox;
|
bbox = &glyph_bitmap.bbox;
|
||||||
|
|
||||||
for (i = 0; i < analysis->run.glyphCount; i++) {
|
for (i = 0; i < analysis->run.glyphCount; i++) {
|
||||||
|
@ -4252,6 +4258,8 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
|
||||||
}
|
}
|
||||||
|
|
||||||
OffsetRect(bbox, analysis->origin.x, analysis->origin.y);
|
OffsetRect(bbox, analysis->origin.x, analysis->origin.y);
|
||||||
|
if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
|
||||||
|
OffsetRect(bbox, analysis->m.dx, analysis->m.dy);
|
||||||
|
|
||||||
/* blit to analysis bitmap */
|
/* blit to analysis bitmap */
|
||||||
dst = get_pixel_ptr(analysis->bitmap, type, bbox, &analysis->bounds);
|
dst = get_pixel_ptr(analysis->bitmap, type, bbox, &analysis->bounds);
|
||||||
|
@ -4437,6 +4445,14 @@ static inline void init_2d_vec(D2D_POINT_2F *vec, FLOAT length, BOOL is_vertical
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void transform_2d_vec(D2D_POINT_2F *vec, const DWRITE_MATRIX *m)
|
||||||
|
{
|
||||||
|
D2D_POINT_2F ret;
|
||||||
|
ret.x = vec->x * m->m11 + vec->y * m->m21;
|
||||||
|
ret.y = vec->x * m->m12 + vec->y * m->m22;
|
||||||
|
*vec = ret;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode, DWRITE_GLYPH_RUN const *run,
|
HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode, DWRITE_GLYPH_RUN const *run,
|
||||||
FLOAT ppdip, const DWRITE_MATRIX *transform, DWRITE_GRID_FIT_MODE gridfit_mode, DWRITE_TEXT_ANTIALIAS_MODE aa_mode,
|
FLOAT ppdip, const DWRITE_MATRIX *transform, DWRITE_GRID_FIT_MODE gridfit_mode, DWRITE_TEXT_ANTIALIAS_MODE aa_mode,
|
||||||
FLOAT originX, FLOAT originY, IDWriteGlyphRunAnalysis **ret)
|
FLOAT originX, FLOAT originY, IDWriteGlyphRunAnalysis **ret)
|
||||||
|
@ -4503,11 +4519,16 @@ HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEA
|
||||||
analysis->run.glyphAdvances = NULL;
|
analysis->run.glyphAdvances = NULL;
|
||||||
analysis->run.glyphOffsets = NULL;
|
analysis->run.glyphOffsets = NULL;
|
||||||
|
|
||||||
|
if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
|
||||||
|
transform_2d_vec(&analysis->origin, &analysis->m);
|
||||||
|
|
||||||
memcpy(analysis->glyphs, run->glyphIndices, run->glyphCount*sizeof(*run->glyphIndices));
|
memcpy(analysis->glyphs, run->glyphIndices, run->glyphCount*sizeof(*run->glyphIndices));
|
||||||
|
|
||||||
if (run->glyphAdvances) {
|
if (run->glyphAdvances) {
|
||||||
for (i = 0; i < run->glyphCount; i++) {
|
for (i = 0; i < run->glyphCount; i++) {
|
||||||
init_2d_vec(analysis->advances + i, run->glyphAdvances[i] * ppdip, run->isSideways);
|
init_2d_vec(analysis->advances + i, run->glyphAdvances[i] * ppdip, run->isSideways);
|
||||||
|
if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
|
||||||
|
transform_2d_vec(analysis->advances + i, &analysis->m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4543,6 +4564,9 @@ HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEA
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
|
||||||
|
transform_2d_vec(analysis->advances + i, &analysis->m);
|
||||||
}
|
}
|
||||||
|
|
||||||
IDWriteFontFace1_Release(fontface1);
|
IDWriteFontFace1_Release(fontface1);
|
||||||
|
@ -4552,6 +4576,10 @@ HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEA
|
||||||
for (i = 0; i < run->glyphCount; i++) {
|
for (i = 0; i < run->glyphCount; i++) {
|
||||||
init_2d_vec(analysis->advanceoffsets + i, run->glyphOffsets[i].advanceOffset * ppdip, run->isSideways);
|
init_2d_vec(analysis->advanceoffsets + i, run->glyphOffsets[i].advanceOffset * ppdip, run->isSideways);
|
||||||
init_2d_vec(analysis->ascenderoffsets + i, run->glyphOffsets[i].ascenderOffset * ppdip, !run->isSideways);
|
init_2d_vec(analysis->ascenderoffsets + i, run->glyphOffsets[i].ascenderOffset * ppdip, !run->isSideways);
|
||||||
|
if (analysis->flags & RUNANALYSIS_USE_TRANSFORM) {
|
||||||
|
transform_2d_vec(analysis->advanceoffsets + i, &analysis->m);
|
||||||
|
transform_2d_vec(analysis->ascenderoffsets + i, &analysis->m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,10 +65,13 @@ typedef struct
|
||||||
|
|
||||||
#define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
|
#define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
|
||||||
MAKE_FUNCPTR(FT_Done_FreeType);
|
MAKE_FUNCPTR(FT_Done_FreeType);
|
||||||
|
MAKE_FUNCPTR(FT_Done_Glyph);
|
||||||
MAKE_FUNCPTR(FT_Get_First_Char);
|
MAKE_FUNCPTR(FT_Get_First_Char);
|
||||||
MAKE_FUNCPTR(FT_Get_Kerning);
|
MAKE_FUNCPTR(FT_Get_Kerning);
|
||||||
MAKE_FUNCPTR(FT_Get_Sfnt_Table);
|
MAKE_FUNCPTR(FT_Get_Sfnt_Table);
|
||||||
|
MAKE_FUNCPTR(FT_Glyph_Copy);
|
||||||
MAKE_FUNCPTR(FT_Glyph_Get_CBox);
|
MAKE_FUNCPTR(FT_Glyph_Get_CBox);
|
||||||
|
MAKE_FUNCPTR(FT_Glyph_Transform);
|
||||||
MAKE_FUNCPTR(FT_Init_FreeType);
|
MAKE_FUNCPTR(FT_Init_FreeType);
|
||||||
MAKE_FUNCPTR(FT_Library_Version);
|
MAKE_FUNCPTR(FT_Library_Version);
|
||||||
MAKE_FUNCPTR(FT_Load_Glyph);
|
MAKE_FUNCPTR(FT_Load_Glyph);
|
||||||
|
@ -148,10 +151,13 @@ BOOL init_freetype(void)
|
||||||
|
|
||||||
#define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(ft_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
|
#define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(ft_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
|
||||||
LOAD_FUNCPTR(FT_Done_FreeType)
|
LOAD_FUNCPTR(FT_Done_FreeType)
|
||||||
|
LOAD_FUNCPTR(FT_Done_Glyph)
|
||||||
LOAD_FUNCPTR(FT_Get_First_Char)
|
LOAD_FUNCPTR(FT_Get_First_Char)
|
||||||
LOAD_FUNCPTR(FT_Get_Kerning)
|
LOAD_FUNCPTR(FT_Get_Kerning)
|
||||||
LOAD_FUNCPTR(FT_Get_Sfnt_Table)
|
LOAD_FUNCPTR(FT_Get_Sfnt_Table)
|
||||||
|
LOAD_FUNCPTR(FT_Glyph_Copy)
|
||||||
LOAD_FUNCPTR(FT_Glyph_Get_CBox)
|
LOAD_FUNCPTR(FT_Glyph_Get_CBox)
|
||||||
|
LOAD_FUNCPTR(FT_Glyph_Transform)
|
||||||
LOAD_FUNCPTR(FT_Init_FreeType)
|
LOAD_FUNCPTR(FT_Init_FreeType)
|
||||||
LOAD_FUNCPTR(FT_Library_Version)
|
LOAD_FUNCPTR(FT_Library_Version)
|
||||||
LOAD_FUNCPTR(FT_Load_Glyph)
|
LOAD_FUNCPTR(FT_Load_Glyph)
|
||||||
|
@ -487,20 +493,61 @@ INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2 *fontface, UINT16 le
|
||||||
return adjustment;
|
return adjustment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ft_matrix_from_dwrite_matrix(const DWRITE_MATRIX *m, FT_Matrix *ft_matrix)
|
||||||
|
{
|
||||||
|
ft_matrix->xx = m->m11 * 0x10000;
|
||||||
|
ft_matrix->xy = -m->m21 * 0x10000;
|
||||||
|
ft_matrix->yx = -m->m12 * 0x10000;
|
||||||
|
ft_matrix->yy = m->m22 * 0x10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should be used only while holding 'freetype_cs' */
|
||||||
|
static BOOL is_face_scalable(IDWriteFontFace2 *fontface)
|
||||||
|
{
|
||||||
|
FT_Face face;
|
||||||
|
if (pFTC_Manager_LookupFace(cache_manager, fontface, &face) == 0)
|
||||||
|
return FT_IS_SCALABLE(face);
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap)
|
void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap)
|
||||||
{
|
{
|
||||||
FTC_ImageTypeRec imagetype;
|
FTC_ImageTypeRec imagetype;
|
||||||
FT_BBox bbox = { 0 };
|
FT_BBox bbox = { 0 };
|
||||||
FT_Glyph glyph;
|
FT_Glyph glyph;
|
||||||
|
|
||||||
|
EnterCriticalSection(&freetype_cs);
|
||||||
|
|
||||||
|
/* Some fonts provide mostly bitmaps and very few outlines, for example for .notdef,
|
||||||
|
disable transform if that's the case. */
|
||||||
|
if (bitmap->m) {
|
||||||
|
if (!is_face_scalable(bitmap->fontface))
|
||||||
|
bitmap->m = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
imagetype.face_id = bitmap->fontface;
|
imagetype.face_id = bitmap->fontface;
|
||||||
imagetype.width = 0;
|
imagetype.width = 0;
|
||||||
imagetype.height = bitmap->emsize;
|
imagetype.height = bitmap->emsize;
|
||||||
imagetype.flags = FT_LOAD_DEFAULT;
|
imagetype.flags = bitmap->m ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT;
|
||||||
|
|
||||||
|
if (pFTC_ImageCache_Lookup(image_cache, &imagetype, bitmap->index, &glyph, NULL) == 0) {
|
||||||
|
if (bitmap->m) {
|
||||||
|
FT_Glyph glyph_copy;
|
||||||
|
|
||||||
|
if (pFT_Glyph_Copy(glyph, &glyph_copy) == 0) {
|
||||||
|
FT_Matrix ft_matrix;
|
||||||
|
|
||||||
|
ft_matrix_from_dwrite_matrix(bitmap->m, &ft_matrix);
|
||||||
|
pFT_Glyph_Transform(glyph_copy, &ft_matrix, NULL);
|
||||||
|
pFT_Glyph_Get_CBox(glyph_copy, FT_GLYPH_BBOX_PIXELS, &bbox);
|
||||||
|
pFT_Done_Glyph(glyph_copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pFT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox);
|
||||||
|
}
|
||||||
|
|
||||||
EnterCriticalSection(&freetype_cs);
|
|
||||||
if (pFTC_ImageCache_Lookup(image_cache, &imagetype, bitmap->index, &glyph, NULL) == 0)
|
|
||||||
pFT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox);
|
|
||||||
LeaveCriticalSection(&freetype_cs);
|
LeaveCriticalSection(&freetype_cs);
|
||||||
|
|
||||||
/* flip Y axis */
|
/* flip Y axis */
|
||||||
|
@ -607,18 +654,42 @@ BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
FT_Glyph glyph;
|
FT_Glyph glyph;
|
||||||
|
|
||||||
|
EnterCriticalSection(&freetype_cs);
|
||||||
|
|
||||||
|
if (bitmap->m) {
|
||||||
|
if (!is_face_scalable(bitmap->fontface))
|
||||||
|
bitmap->m = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
imagetype.face_id = bitmap->fontface;
|
imagetype.face_id = bitmap->fontface;
|
||||||
imagetype.width = 0;
|
imagetype.width = 0;
|
||||||
imagetype.height = bitmap->emsize;
|
imagetype.height = bitmap->emsize;
|
||||||
imagetype.flags = FT_LOAD_DEFAULT;
|
imagetype.flags = bitmap->m ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT;
|
||||||
|
|
||||||
EnterCriticalSection(&freetype_cs);
|
|
||||||
if (pFTC_ImageCache_Lookup(image_cache, &imagetype, bitmap->index, &glyph, NULL) == 0) {
|
if (pFTC_ImageCache_Lookup(image_cache, &imagetype, bitmap->index, &glyph, NULL) == 0) {
|
||||||
|
FT_Glyph glyph_copy;
|
||||||
|
|
||||||
|
if (bitmap->m) {
|
||||||
|
if (pFT_Glyph_Copy(glyph, &glyph_copy) == 0) {
|
||||||
|
FT_Matrix ft_matrix;
|
||||||
|
|
||||||
|
ft_matrix_from_dwrite_matrix(bitmap->m, &ft_matrix);
|
||||||
|
pFT_Glyph_Transform(glyph_copy, &ft_matrix, NULL);
|
||||||
|
glyph = glyph_copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
glyph_copy = NULL;
|
||||||
|
|
||||||
if (bitmap->type == DWRITE_TEXTURE_CLEARTYPE_3x1)
|
if (bitmap->type == DWRITE_TEXTURE_CLEARTYPE_3x1)
|
||||||
ret = freetype_get_aa_glyph_bitmap(bitmap, glyph);
|
ret = freetype_get_aa_glyph_bitmap(bitmap, glyph);
|
||||||
else
|
else
|
||||||
ret = freetype_get_aliased_glyph_bitmap(bitmap, glyph);
|
ret = freetype_get_aliased_glyph_bitmap(bitmap, glyph);
|
||||||
|
|
||||||
|
if (glyph_copy)
|
||||||
|
pFT_Done_Glyph(glyph_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
LeaveCriticalSection(&freetype_cs);
|
LeaveCriticalSection(&freetype_cs);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -3507,6 +3507,7 @@ static void test_CreateGlyphRunAnalysis(void)
|
||||||
DWRITE_GLYPH_OFFSET offsets[2];
|
DWRITE_GLYPH_OFFSET offsets[2];
|
||||||
DWRITE_GLYPH_METRICS metrics;
|
DWRITE_GLYPH_METRICS metrics;
|
||||||
DWRITE_FONT_METRICS fm;
|
DWRITE_FONT_METRICS fm;
|
||||||
|
DWRITE_MATRIX m;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
factory = create_factory();
|
factory = create_factory();
|
||||||
|
@ -3758,6 +3759,32 @@ static void test_CreateGlyphRunAnalysis(void)
|
||||||
ok((rect.right - rect.left) > 2 * advances[0], "got rect width %d for advance %f\n", rect.right - rect.left, advances[0]);
|
ok((rect.right - rect.left) > 2 * advances[0], "got rect width %d for advance %f\n", rect.right - rect.left, advances[0]);
|
||||||
IDWriteGlyphRunAnalysis_Release(analysis);
|
IDWriteGlyphRunAnalysis_Release(analysis);
|
||||||
|
|
||||||
|
/* with scaling transform */
|
||||||
|
hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, NULL,
|
||||||
|
DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_NATURAL,
|
||||||
|
0.0, 0.0, &analysis);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
SetRectEmpty(&rect);
|
||||||
|
hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
ok(!IsRectEmpty(&rect), "got rect width %d\n", rect.right - rect.left);
|
||||||
|
IDWriteGlyphRunAnalysis_Release(analysis);
|
||||||
|
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
|
m.m11 = 2.0;
|
||||||
|
m.m22 = 1.0;
|
||||||
|
hr = IDWriteFactory_CreateGlyphRunAnalysis(factory, &run, 1.0, &m,
|
||||||
|
DWRITE_RENDERING_MODE_ALIASED, DWRITE_MEASURING_MODE_NATURAL,
|
||||||
|
0.0, 0.0, &analysis);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
SetRectEmpty(&rect2);
|
||||||
|
hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect2);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
ok((rect2.right - rect2.left) > (rect.right - rect.left), "got rect width %d\n", rect2.right - rect2.left);
|
||||||
|
IDWriteGlyphRunAnalysis_Release(analysis);
|
||||||
|
|
||||||
IDWriteFontFace_Release(face);
|
IDWriteFontFace_Release(face);
|
||||||
IDWriteFactory_Release(factory);
|
IDWriteFactory_Release(factory);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue