From 26977d4a4b3e6159072ae75e77a3e3b007bd3127 Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Sat, 16 Aug 2014 20:40:48 -0500 Subject: [PATCH] dwrite: Initial implementation of CreateFontFace. --- dlls/dwrite/dwrite_private.h | 1 + dlls/dwrite/font.c | 196 ++++++++++++++++++++++++++++------- dlls/dwrite/main.c | 4 +- dlls/dwrite/tests/font.c | 4 + 4 files changed, 167 insertions(+), 38 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 64f55e2789e..f56b6f01419 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -90,6 +90,7 @@ extern HRESULT get_system_fontcollection(IDWriteFontCollection**) DECLSPEC_HIDDE extern void release_system_fontcollection(void) DECLSPEC_HIDDEN; extern HRESULT get_textanalyzer(IDWriteTextAnalyzer**) DECLSPEC_HIDDEN; extern HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file) DECLSPEC_HIDDEN; +extern HRESULT font_create_fontface(IDWriteFactory *iface, DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDWriteFontFile* const* font_files, UINT32 index, DWRITE_FONT_SIMULATIONS sim_flags, IDWriteFontFace **font_face) DECLSPEC_HIDDEN; /* Opentype font table functions */ extern HRESULT analyze_opentype_font(const void* font_data, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 0c75271b085..8c82d0884f2 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -146,6 +146,7 @@ struct dwrite_font { IDWriteFont IDWriteFont_iface; LONG ref; + BOOL is_system; IDWriteFontFamily *family; IDWriteFontFace *face; DWRITE_FONT_STYLE style; @@ -159,6 +160,13 @@ struct dwrite_fontface { IDWriteFontFace IDWriteFontFace_iface; LONG ref; + DWRITE_FONT_FACE_TYPE type; + UINT32 file_count; + IDWriteFontFile ** files; + DWRITE_FONT_SIMULATIONS simulations; + UINT32 index; + + BOOL is_system; LOGFONTW logfont; }; @@ -169,6 +177,7 @@ struct dwrite_fontfile { IDWriteFontFileLoader *loader; void *reference_key; UINT32 key_size; + IDWriteFontFileStream *stream; }; static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family); @@ -198,6 +207,25 @@ static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWr return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface); } +static HRESULT WINAPI _dwritefontfile_GetFontFileStream(IDWriteFontFile *iface, IDWriteFontFileStream **stream) +{ + HRESULT hr; + struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface); + if (!This->stream) + { + hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &This->stream); + if (FAILED(hr)) + return hr; + } + if (This->stream) + { + IDWriteFontFileStream_AddRef(This->stream); + *stream = This->stream; + return S_OK; + } + return E_FAIL; +} + static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj) { struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); @@ -231,7 +259,13 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface) TRACE("(%p)->(%d)\n", This, ref); if (!ref) + { + int i; + for (i = 0; i < This->file_count; i++) + IDWriteFontFile_Release(This->files[i]); + heap_free(This->files); heap_free(This); + } return ref; } @@ -239,30 +273,45 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface) 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; + TRACE("(%p)\n", This); + return This->type; } static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files, IDWriteFontFile **fontfiles) { + int i; struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); - FIXME("(%p)->(%p %p): stub\n", This, number_of_files, fontfiles); - return E_NOTIMPL; + TRACE("(%p)->(%p %p)\n", This, number_of_files, fontfiles); + if (fontfiles == NULL) + { + *number_of_files = This->file_count; + return S_OK; + } + if (*number_of_files < This->file_count) + return E_INVALIDARG; + + for (i = 0; i < This->file_count; i++) + { + IDWriteFontFile_AddRef(This->files[i]); + fontfiles[i] = This->files[i]; + } + + return S_OK; } static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface) { struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); - FIXME("(%p): stub\n", This); - return 0; + TRACE("(%p)\n", This); + return This->index; } 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; + TRACE("(%p)\n", This); + return This->simulations; } static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface) @@ -297,30 +346,38 @@ static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UIN UINT32 count, UINT16 *glyph_indices) { struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); - HFONT hfont; - WCHAR *str; - HDC hdc; - unsigned int i; + if (This->is_system) + { + HFONT hfont; + WCHAR *str; + HDC hdc; + unsigned int i; - TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices); + TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices); - str = heap_alloc(count*sizeof(WCHAR)); - if (!str) return E_OUTOFMEMORY; + str = heap_alloc(count*sizeof(WCHAR)); + if (!str) return E_OUTOFMEMORY; - for (i = 0; i < count; i++) - str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?'; + for (i = 0; i < count; i++) + str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?'; - hdc = CreateCompatibleDC(0); - hfont = CreateFontIndirectW(&This->logfont); - SelectObject(hdc, hfont); + hdc = CreateCompatibleDC(0); + hfont = CreateFontIndirectW(&This->logfont); + SelectObject(hdc, hfont); - GetGlyphIndicesW(hdc, str, count, glyph_indices, 0); - heap_free(str); + GetGlyphIndicesW(hdc, str, count, glyph_indices, 0); + heap_free(str); - DeleteDC(hdc); - DeleteObject(hfont); + DeleteDC(hdc); + DeleteObject(hfont); - return S_OK; + return S_OK; + } + else + { + 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, @@ -394,7 +451,7 @@ static const IDWriteFontFaceVtbl dwritefontfacevtbl = { dwritefontface_GetGdiCompatibleGlyphMetrics }; -static HRESULT create_fontface(struct dwrite_font *font, IDWriteFontFace **face) +static HRESULT create_system_fontface(struct dwrite_font *font, IDWriteFontFace **face) { struct dwrite_fontface *This; @@ -405,7 +462,13 @@ static HRESULT create_fontface(struct dwrite_font *font, IDWriteFontFace **face) This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl; This->ref = 1; + This->type = DWRITE_FONT_FACE_TYPE_UNKNOWN; + This->file_count = 0; + This->files = NULL; + This->index = 0; + This->simulations = DWRITE_FONT_SIMULATIONS_NONE; + This->is_system = TRUE; memset(&This->logfont, 0, sizeof(This->logfont)); This->logfont.lfItalic = font->style == DWRITE_FONT_STYLE_ITALIC; /* weight values from DWRITE_FONT_WEIGHT match values used for LOGFONT */ @@ -548,18 +611,31 @@ static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontF { struct dwrite_font *This = impl_from_IDWriteFont(iface); - TRACE("(%p)->(%p)\n", This, face); - - if (!This->face) + if (This->is_system) { - HRESULT hr = create_fontface(This, &This->face); - if (FAILED(hr)) return hr; + TRACE("(%p)->(%p)\n", This, face); + + if (!This->face) + { + HRESULT hr = create_system_fontface(This, &This->face); + if (FAILED(hr)) return hr; + } + + *face = This->face; + IDWriteFontFace_AddRef(*face); + + return S_OK; + } + else + { + TRACE("(%p)->(%p)\n", This, face); + if (This->face) + { + *face = This->face; + IDWriteFontFace_AddRef(*face); + } + return S_OK; } - - *face = This->face; - IDWriteFontFace_AddRef(*face); - - return S_OK; } static const IDWriteFontVtbl dwritefontvtbl = { @@ -984,6 +1060,7 @@ HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font) This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl; This->ref = 1; This->face = NULL; + This->is_system = TRUE; This->family = family; This->style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; This->facename = heap_strdupW(logfont->lfFaceName); @@ -1028,6 +1105,7 @@ static ULONG WINAPI dwritefontfile_Release(IDWriteFontFile *iface) if (!ref) { IDWriteFontFileLoader_Release(This->loader); + if (This->stream) IDWriteFontFileStream_Release(This->stream); heap_free(This->reference_key); heap_free(This); } @@ -1105,6 +1183,7 @@ HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_ke This->ref = 1; IDWriteFontFileLoader_AddRef(loader); This->loader = loader; + This->stream = NULL; This->reference_key = heap_alloc(key_size); memcpy(This->reference_key, reference_key, key_size); This->key_size = key_size; @@ -1113,3 +1192,48 @@ HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_ke return S_OK; } + +HRESULT font_create_fontface(IDWriteFactory *iface, DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDWriteFontFile* const* font_files, UINT32 index, DWRITE_FONT_SIMULATIONS sim_flags, IDWriteFontFace **font_face) +{ + int i; + struct dwrite_fontface *This; + HRESULT hr = S_OK; + + *font_face = NULL; + + This = heap_alloc(sizeof(struct dwrite_fontface)); + if (!This) return E_OUTOFMEMORY; + + This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl; + This->ref = 1; + This->type = facetype; + This->file_count = files_number; + This->files = heap_alloc(sizeof(*This->files) * files_number); + /* Verify font file streams */ + for (i = 0; i < This->file_count && SUCCEEDED(hr); i++) + { + IDWriteFontFileStream *stream; + hr = _dwritefontfile_GetFontFileStream(font_files[i], &stream); + if (SUCCEEDED(hr)) + IDWriteFontFileStream_Release(stream); + } + if (FAILED(hr)) + { + heap_free(This->files); + heap_free(This); + return hr; + } + for (i = 0; i < This->file_count; i++) + { + This->files[i] = font_files[i]; + IDWriteFontFile_AddRef(font_files[i]); + } + + This->index = index; + This->simulations = sim_flags; + This->is_system = FALSE; + + *font_face = &This->IDWriteFontFace_iface; + + return S_OK; +} diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index f736301d411..abe61643238 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -531,8 +531,8 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory *iface, UINT32 index, DWRITE_FONT_SIMULATIONS sim_flags, IDWriteFontFace **font_face) { struct dwritefactory *This = impl_from_IDWriteFactory(iface); - FIXME("(%p)->(%d %u %p %u 0x%x %p): stub\n", This, facetype, files_number, font_files, index, sim_flags, font_face); - return E_NOTIMPL; + TRACE("(%p)->(%d %u %p %u 0x%x %p)\n", This, facetype, files_number, font_files, index, sim_flags, font_face); + return font_create_fontface(iface, facetype, files_number, font_files, index, sim_flags, font_face); } static HRESULT WINAPI dwritefactory_CreateRenderingParams(IDWriteFactory *iface, IDWriteRenderingParams **params) diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 44e7ee69b5f..04dff59517b 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -767,6 +767,7 @@ static void test_FontLoader(void) DWRITE_FONT_FILE_TYPE type = 1; DWRITE_FONT_FACE_TYPE face = 1; UINT32 count = 1; + IDWriteFontFace *fface = NULL; HRESULT hr; hr = IDWriteFactory_RegisterFontFileLoader(factory, NULL); @@ -801,6 +802,9 @@ static void test_FontLoader(void) ok(type == DWRITE_FONT_FILE_TYPE_UNKNOWN, "got %i\n", type); ok(face == DWRITE_FONT_FACE_TYPE_UNKNOWN, "got %i\n", face); ok(count == 0, "got %i\n", count); + + hr = IDWriteFactory_CreateFontFace(factory, type, 1, &ffile, 0, 0, &fface); + ok(hr == 0x8faecafe, "got 0x%08x\n", hr); IDWriteFontFile_Release(ffile); hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);