From a77b9ed0c733fcb71fe3189f533f80166efc577e Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 21 Nov 2014 11:48:23 +0300 Subject: [PATCH] dwrite: Load freetype on module attach, create one FT_Face per fontface. --- dlls/dwrite/Makefile.in | 2 + dlls/dwrite/dwrite_private.h | 7 ++ dlls/dwrite/font.c | 25 +++++++ dlls/dwrite/freetype.c | 138 +++++++++++++++++++++++++++++++++++ dlls/dwrite/main.c | 1 + 5 files changed, 173 insertions(+) create mode 100644 dlls/dwrite/freetype.c diff --git a/dlls/dwrite/Makefile.in b/dlls/dwrite/Makefile.in index 20908830b65..ded14db4578 100644 --- a/dlls/dwrite/Makefile.in +++ b/dlls/dwrite/Makefile.in @@ -1,12 +1,14 @@ MODULE = dwrite.dll IMPORTLIB = dwrite IMPORTS = user32 gdi32 +EXTRAINCL = $(FREETYPE_CFLAGS) C_SRCS = \ analyzer.c \ bidi.c \ bracket.c \ font.c \ + freetype.c \ gdiinterop.c \ layout.c \ linebreak.c \ diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 3b1d2833d29..c600f3ec9fd 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -119,9 +119,16 @@ extern void opentype_get_font_properties(const void*,const void*,DWRITE_FONT_STR extern void opentype_get_font_metrics(const void*,const void*,const void*,DWRITE_FONT_METRICS1*) DECLSPEC_HIDDEN; extern HRESULT opentype_get_font_strings_from_id(const void*,DWRITE_INFORMATIONAL_STRING_ID,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN; +/* BiDi helpers */ extern HRESULT bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*) DECLSPEC_HIDDEN; extern WCHAR bidi_get_mirrored_char(WCHAR) DECLSPEC_HIDDEN; +/* FreeType integration */ +struct ft_fontface; +extern BOOL init_freetype(void) DECLSPEC_HIDDEN; +extern HRESULT alloc_ft_fontface(const void*,UINT32,UINT32,struct ft_fontface**) DECLSPEC_HIDDEN; +extern void release_ft_fontface(struct ft_fontface*) DECLSPEC_HIDDEN; + /* Glyph shaping */ enum SCRIPT_JUSTIFY { diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index ed38a6fe2b9..eb7a27436bb 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -119,6 +119,7 @@ struct dwrite_fontface { DWRITE_FONT_METRICS1 metrics; struct dwrite_fonttable cmap; + struct ft_fontface *ft; }; struct dwrite_fontfile { @@ -254,6 +255,7 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace2 *iface) if (This->files[i]) IDWriteFontFile_Release(This->files[i]); } + release_ft_fontface(This->ft); heap_free(This); } @@ -1928,9 +1930,14 @@ HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDW DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace2 **ret) { struct dwrite_fontface *fontface; + const void *data_ptr; HRESULT hr = S_OK; + void *context; + UINT64 size; int i; + *ret = NULL; + fontface = heap_alloc(sizeof(struct dwrite_fontface)); if (!fontface) return E_OUTOFMEMORY; @@ -1954,6 +1961,7 @@ HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDW fontface->cmap.size = 0; fontface->index = index; fontface->simulations = simulations; + fontface->ft = NULL; for (i = 0; i < fontface->file_count; i++) { hr = get_stream_from_file(font_files[i], &fontface->streams[i]); @@ -1968,8 +1976,25 @@ HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDW get_font_properties_from_stream(fontface->streams[0], facetype, index, &fontface->metrics, NULL, NULL, NULL); + hr = IDWriteFontFileStream_GetFileSize(fontface->streams[0], &size); + if (FAILED(hr)) + goto fail; + + hr = IDWriteFontFileStream_ReadFileFragment(fontface->streams[0], &data_ptr, 0, size, &context); + if (FAILED(hr)) + goto fail; + + hr = alloc_ft_fontface(data_ptr, size, fontface->index, &fontface->ft); + IDWriteFontFileStream_ReleaseFileFragment(fontface->streams[0], context); + if (FAILED(hr)) + goto fail; + *ret = &fontface->IDWriteFontFace2_iface; return S_OK; + +fail: + IDWriteFontFace2_Release(&fontface->IDWriteFontFace2_iface); + return hr; } /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */ diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c new file mode 100644 index 00000000000..86d85b34739 --- /dev/null +++ b/dlls/dwrite/freetype.c @@ -0,0 +1,138 @@ +/* + * FreeType integration + * + * Copyright 2014 Nikolay Sivov for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#ifdef HAVE_FT2BUILD_H +#include +#include FT_FREETYPE_H +#endif /* HAVE_FT2BUILD_H */ + +#include "windef.h" +#include "wine/library.h" +#include "wine/debug.h" + +#include "dwrite_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dwrite); + +#ifdef HAVE_FREETYPE + +static void *ft_handle = NULL; +static FT_Library library = 0; +typedef struct +{ + FT_Int major; + FT_Int minor; + FT_Int patch; +} FT_Version_t; + +#define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL +MAKE_FUNCPTR(FT_Done_Face); +MAKE_FUNCPTR(FT_Init_FreeType); +MAKE_FUNCPTR(FT_Library_Version); +MAKE_FUNCPTR(FT_New_Memory_Face); +#undef MAKE_FUNCPTR + +struct ft_fontface +{ + FT_Face face; +}; + +BOOL init_freetype(void) +{ + FT_Version_t FT_Version; + + ft_handle = wine_dlopen(SONAME_LIBFREETYPE, RTLD_NOW, NULL, 0); + if (!ft_handle) { + WINE_MESSAGE("Wine cannot find the FreeType font library.\n"); + return FALSE; + } + +#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_Face) + LOAD_FUNCPTR(FT_Init_FreeType) + LOAD_FUNCPTR(FT_Library_Version) + LOAD_FUNCPTR(FT_New_Memory_Face) +#undef LOAD_FUNCPTR + + if (pFT_Init_FreeType(&library) != 0) { + ERR("Can't init FreeType library\n"); + wine_dlclose(ft_handle, NULL, 0); + ft_handle = NULL; + return FALSE; + } + pFT_Library_Version(library, &FT_Version.major, &FT_Version.minor, &FT_Version.patch); + + TRACE("FreeType version is %d.%d.%d\n", FT_Version.major, FT_Version.minor, FT_Version.patch); + return TRUE; + +sym_not_found: + WINE_MESSAGE("Wine cannot find certain functions that it needs from FreeType library.\n"); + wine_dlclose(ft_handle, NULL, 0); + ft_handle = NULL; + return FALSE; +} + +HRESULT alloc_ft_fontface(const void *data_ptr, UINT32 data_size, UINT32 index, struct ft_fontface **ftface) +{ + FT_Face face; + FT_Error err; + + *ftface = heap_alloc_zero(sizeof(struct ft_fontface)); + if (!*ftface) + return E_OUTOFMEMORY; + + err = pFT_New_Memory_Face(library, data_ptr, data_size, index, &face); + if (err) { + ERR("FT_New_Memory_Face rets %d\n", err); + return E_FAIL; + } + (*ftface)->face = face; + + return S_OK; +} + +void release_ft_fontface(struct ft_fontface *ftface) +{ + if (!ftface) return; + pFT_Done_Face(ftface->face); + heap_free(ftface); +} + +#else /* HAVE_FREETYPE */ + +BOOL init_freetype(void) +{ + return FALSE; +} + +HRESULT alloc_ft_fontface(const void *data_ptr, UINT32 data_size, UINT32 index, struct ft_fontface **face) +{ + *face = NULL; + return S_FALSE; +} + +void release_ft_fontface(struct ft_fontface *face) +{ +} + +#endif /* HAVE_FREETYPE */ diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 1292086b122..79aa7d00d10 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -45,6 +45,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved) return FALSE; /* prefer native version */ case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls( hinstDLL ); + init_freetype(); break; case DLL_PROCESS_DETACH: if (reserved) break;