diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 7a3ec6bc338..3890f892ae1 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -39,9 +39,20 @@ struct dwrite_font { LONG ref; IDWriteFontFamily *family; + IDWriteFontFace *face; DWRITE_FONT_STYLE style; }; +struct dwrite_fontface { + IDWriteFontFace IDWriteFontFace_iface; + LONG ref; +}; + +static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface) +{ + return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace_iface); +} + static inline struct dwrite_font *impl_from_IDWriteFont(IDWriteFont *iface) { return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont_iface); @@ -52,6 +63,196 @@ static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontF return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface); } +static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFace)) + { + *obj = iface; + IDWriteFontFace_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace *iface) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p)->(%d)\n", This, ref); + return ref; +} + +static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(%d)\n", This, ref); + + if (!ref) + heap_free(This); + + return S_OK; +} + +static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace *iface) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p): stub\n", This); + return DWRITE_FONT_FACE_TYPE_UNKNOWN; +} + +static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files, + IDWriteFontFile **fontfiles) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p)->(%p %p): stub\n", This, number_of_files, fontfiles); + return E_NOTIMPL; +} + +static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p): stub\n", This); + return 0; +} + +static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace *iface) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p): stub\n", This); + return DWRITE_FONT_SIMULATIONS_NONE; +} + +static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p): stub\n", This); + return FALSE; +} + +static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace *iface, DWRITE_FONT_METRICS *metrics) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p)->(%p): stub\n", This, metrics); +} + +static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace *iface) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p): stub\n", This); + return 0; +} + +static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace *iface, + UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways); + return E_NOTIMPL; +} + +static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UINT32 const *codepoints, + UINT32 count, UINT16 *glyph_indices) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p)->(%p %u %p): stub\n", This, codepoints, count, glyph_indices); + return E_NOTIMPL; +} + +static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UINT32 table_tag, + const void **table_data, UINT32 *table_size, void **context, BOOL *exists) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists); + return E_NOTIMPL; +} + +static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p)->(%p): stub\n", This, table_context); +} + +static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize, + UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets, + UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets, + glyph_count, is_sideways, is_rtl, geometrysink); + return E_NOTIMPL; +} + +static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace *iface, FLOAT emSize, + FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode); + return E_NOTIMPL; +} + +static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip, + DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics); + return E_NOTIMPL; +} + +static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip, + DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count, + DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways) +{ + struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); + FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices, + glyph_count, metrics, is_sideways); + return E_NOTIMPL; +} + +static const IDWriteFontFaceVtbl dwritefontfacevtbl = { + dwritefontface_QueryInterface, + dwritefontface_AddRef, + dwritefontface_Release, + dwritefontface_GetType, + dwritefontface_GetFiles, + dwritefontface_GetIndex, + dwritefontface_GetSimulations, + dwritefontface_IsSymbolFont, + dwritefontface_GetMetrics, + dwritefontface_GetGlyphCount, + dwritefontface_GetDesignGlyphMetrics, + dwritefontface_GetGlyphIndices, + dwritefontface_TryGetFontTable, + dwritefontface_ReleaseFontTable, + dwritefontface_GetGlyphRunOutline, + dwritefontface_GetRecommendedRenderingMode, + dwritefontface_GetGdiCompatibleMetrics, + dwritefontface_GetGdiCompatibleGlyphMetrics +}; + +static HRESULT create_fontface(IDWriteFontFace **face) +{ + struct dwrite_fontface *This; + + *face = NULL; + + This = heap_alloc(sizeof(struct dwrite_fontface)); + if (!This) return E_OUTOFMEMORY; + + This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl; + This->ref = 1; + *face = &This->IDWriteFontFace_iface; + + return S_OK; +} + static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont *iface, REFIID riid, void **obj) { struct dwrite_font *This = impl_from_IDWriteFont(iface); @@ -169,8 +370,21 @@ static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontFace **face) { struct dwrite_font *This = impl_from_IDWriteFont(iface); - FIXME("(%p)->(%p): stub\n", This, face); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, face); + + if (!This->face) + { + HRESULT hr = create_fontface(&This->face); + if (FAILED(hr)) return hr; + *face = This->face; + return hr; + } + + *face = This->face; + IDWriteFontFace_AddRef(*face); + + return S_OK; } static const IDWriteFontVtbl dwritefontvtbl = { @@ -190,6 +404,7 @@ static const IDWriteFontVtbl dwritefontvtbl = { dwritefont_CreateFontFace }; + static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj) { struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface); @@ -351,6 +566,7 @@ HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font) This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl; This->ref = 1; + This->face = NULL; This->family = family; This->style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 34d123c441c..3bba1ca88fb 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -358,6 +358,56 @@ if (0) /* crashes on native */ IDWriteGdiInterop_Release(interop); } +static void test_CreateFontFace(void) +{ + static const WCHAR arialW[] = {'A','r','i','a','l',0}; + IDWriteFontFace *fontface, *fontface2; + IDWriteGdiInterop *interop; + IDWriteFont *font; + LOGFONTW logfont; + HRESULT hr; + + hr = IDWriteFactory_GetGdiInterop(factory, &interop); + EXPECT_HR(hr, S_OK); + + memset(&logfont, 0, sizeof(logfont)); + logfont.lfHeight = 12; + logfont.lfWidth = 12; + logfont.lfWeight = FW_NORMAL; + logfont.lfItalic = 1; + lstrcpyW(logfont.lfFaceName, arialW); + + hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFontFace, (void**)&fontface); + ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); + +if (0) /* crashes on native */ + hr = IDWriteFont_CreateFontFace(font, NULL); + + hr = IDWriteFont_CreateFontFace(font, &fontface); + ok(hr == S_OK, "got 0x%08x\n", hr); + EXPECT_REF(font, 1); + EXPECT_REF(fontface, 1); + + hr = IDWriteFont_CreateFontFace(font, &fontface2); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface); + EXPECT_REF(fontface, 2); + EXPECT_REF(font, 1); + + IDWriteFontFace_AddRef(fontface); + EXPECT_REF(font, 1); + EXPECT_REF(fontface, 3); + IDWriteFontFace_Release(fontface); + IDWriteFontFace_Release(fontface); + + IDWriteFontFace_Release(fontface); + IDWriteFont_Release(font); + IDWriteGdiInterop_Release(interop); +} + START_TEST(font) { HRESULT hr; @@ -374,6 +424,7 @@ START_TEST(font) test_CreateBitmapRenderTarget(); test_GetFontFamily(); test_GetFamilyNames(); + test_CreateFontFace(); IDWriteFactory_Release(factory); } diff --git a/include/dwrite.idl b/include/dwrite.idl index 60a2bae9cd5..98d55c321ac 100644 --- a/include/dwrite.idl +++ b/include/dwrite.idl @@ -658,7 +658,7 @@ interface IDWriteFontFace : IUnknown void ReleaseFontTable(void *table_context); - HRESULT GettGlyphRunOutline( + HRESULT GetGlyphRunOutline( FLOAT emSize, UINT16 const *glyph_indices, FLOAT const* glyph_advances,