diff --git a/dlls/dwrite/Makefile.in b/dlls/dwrite/Makefile.in index 8b612989386..1c1611f8e16 100644 --- a/dlls/dwrite/Makefile.in +++ b/dlls/dwrite/Makefile.in @@ -1,5 +1,6 @@ MODULE = dwrite.dll IMPORTLIB = dwrite +UNIXLIB = dwrite.so IMPORTS = user32 gdi32 advapi32 EXTRAINCL = $(FREETYPE_CFLAGS) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index f83372acc9e..dd346191662 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -223,8 +223,7 @@ extern HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_cmap *cmap, DWRITE_UNICODE_RANGE *ranges, unsigned int *count) DECLSPEC_HIDDEN; struct dwrite_fontface; -typedef void * font_object_handle; -typedef font_object_handle (*p_dwrite_fontface_get_font_object)(struct dwrite_fontface *fontface); +typedef UINT64 (*p_dwrite_fontface_get_font_object)(struct dwrite_fontface *fontface); struct dwrite_fontface { @@ -238,7 +237,7 @@ struct dwrite_fontface IDWriteFactory7 *factory; struct fontfacecached *cached; - font_object_handle font_object; + UINT64 font_object; void *data_context; p_dwrite_fontface_get_font_object get_font_object; struct @@ -717,22 +716,4 @@ extern HRESULT shape_check_typographic_feature(struct scriptshaping_context *con struct font_data_context; extern HMODULE dwrite_module DECLSPEC_HIDDEN; -struct font_backend_funcs -{ - font_object_handle (CDECL *create_font_object)(const void *data_ptr, UINT64 data_size, unsigned int index); - void (CDECL *release_font_object)(font_object_handle object); - int (CDECL *get_glyph_outline)(font_object_handle object, float emsize, unsigned int simulations, UINT16 glyph, - struct dwrite_outline *outline); - UINT16 (CDECL *get_glyph_count)(font_object_handle object); - INT32 (CDECL *get_glyph_advance)(font_object_handle object, float em_size, UINT16 glyph, - DWRITE_MEASURING_MODE measuring_mode, BOOL *has_contours); - void (CDECL *get_glyph_bbox)(font_object_handle object, struct dwrite_glyphbitmap *bitmap_desc); - BOOL (CDECL *get_glyph_bitmap)(font_object_handle object, struct dwrite_glyphbitmap *bitmap_desc); - void (CDECL *get_design_glyph_metrics)(font_object_handle object, UINT16 upem, UINT16 ascent, unsigned int simulations, - UINT16 glyph, DWRITE_GLYPH_METRICS *metrics); -}; - -extern void init_font_backend(void) DECLSPEC_HIDDEN; -extern void release_font_backend(void) DECLSPEC_HIDDEN; - extern void dwrite_fontface_get_glyph_bbox(IDWriteFontFace *fontface, struct dwrite_glyphbitmap *bitmap) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index cb4f856524c..22fb3369bc7 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -26,6 +26,7 @@ #define COBJMACROS #include "dwrite_private.h" +#include "unixlib.h" WINE_DEFAULT_DEBUG_CHANNEL(dwrite); WINE_DECLARE_DEBUG_CHANNEL(dwrite_file); @@ -45,8 +46,6 @@ static const FLOAT RECOMMENDED_OUTLINE_AA_THRESHOLD = 100.0f; static const FLOAT RECOMMENDED_OUTLINE_A_THRESHOLD = 350.0f; static const FLOAT RECOMMENDED_NATURAL_PPEM = 20.0f; -static const struct font_backend_funcs *font_funcs; - struct cache_key { float size; @@ -59,7 +58,7 @@ struct cache_entry struct wine_rb_entry entry; struct list mru; struct cache_key key; - float advance; + int advance; RECT bbox; BYTE *bitmap; unsigned int bitmap_size; @@ -117,19 +116,28 @@ static struct cache_entry * fontface_get_cache_entry(struct dwrite_fontface *fon return entry; } -static float fontface_get_glyph_advance(struct dwrite_fontface *fontface, float fontsize, unsigned short glyph, +static int fontface_get_glyph_advance(struct dwrite_fontface *fontface, float fontsize, unsigned short glyph, unsigned short mode, BOOL *has_contours) { struct cache_key key = { .size = fontsize, .glyph = glyph, .mode = mode }; + struct get_glyph_advance_params params; struct cache_entry *entry; - BOOL value; + unsigned int value; if (!(entry = fontface_get_cache_entry(fontface, 0, &key))) - return 0.0f; + return 0; if (!entry->has_advance) { - entry->advance = font_funcs->get_glyph_advance(fontface->get_font_object(fontface), fontsize, glyph, mode, &value); + params.object = fontface->get_font_object(fontface); + params.glyph = glyph; + params.mode = mode; + params.emsize = fontsize; + params.advance = &entry->advance; + params.has_contours = &value; + + UNIX_CALL(get_glyph_advance, ¶ms); + entry->has_contours = !!value; entry->has_advance = 1; } @@ -142,24 +150,31 @@ void dwrite_fontface_get_glyph_bbox(IDWriteFontFace *iface, struct dwrite_glyphb { struct cache_key key = { .size = bitmap->emsize, .glyph = bitmap->glyph, .mode = DWRITE_MEASURING_MODE_NATURAL }; struct dwrite_fontface *fontface = unsafe_impl_from_IDWriteFontFace(iface); + struct get_glyph_bbox_params params; struct cache_entry *entry; + params.object = fontface->get_font_object(fontface); + params.simulations = bitmap->simulations; + params.glyph = bitmap->glyph; + params.emsize = bitmap->emsize; + params.m = bitmap->m ? *bitmap->m : identity; + EnterCriticalSection(&fontface->cs); /* For now bypass cache for transformed cases. */ if (bitmap->m && memcmp(bitmap->m, &identity, sizeof(*bitmap->m))) { - font_funcs->get_glyph_bbox(fontface->get_font_object(fontface), bitmap); + params.bbox = &bitmap->bbox; + UNIX_CALL(get_glyph_bbox, ¶ms); } else if ((entry = fontface_get_cache_entry(fontface, 0, &key))) { - if (entry->has_bbox) - bitmap->bbox = entry->bbox; - else + if (!entry->has_bbox) { - font_funcs->get_glyph_bbox(fontface->get_font_object(fontface), bitmap); - entry->bbox = bitmap->bbox; + params.bbox = &entry->bbox; + UNIX_CALL(get_glyph_bbox, ¶ms); entry->has_bbox = 1; } + bitmap->bbox = entry->bbox; } LeaveCriticalSection(&fontface->cs); } @@ -170,22 +185,34 @@ static unsigned int get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode } static HRESULT dwrite_fontface_get_glyph_bitmap(struct dwrite_fontface *fontface, DWRITE_RENDERING_MODE rendering_mode, - BOOL *is_1bpp, struct dwrite_glyphbitmap *bitmap) + unsigned int *is_1bpp, struct dwrite_glyphbitmap *bitmap) { struct cache_key key = { .size = bitmap->emsize, .glyph = bitmap->glyph, .mode = DWRITE_MEASURING_MODE_NATURAL }; + struct get_glyph_bitmap_params params; const RECT *bbox = &bitmap->bbox; + unsigned int bitmap_size, _1bpp; struct cache_entry *entry; - unsigned int bitmap_size; HRESULT hr = S_OK; bitmap_size = get_glyph_bitmap_pitch(rendering_mode, bbox->right - bbox->left) * (bbox->bottom - bbox->top); + params.object = fontface->get_font_object(fontface); + params.simulations = fontface->simulations; + params.glyph = bitmap->glyph; + params.mode = rendering_mode; + params.emsize = bitmap->emsize; + params.m = bitmap->m ? *bitmap->m : identity; + params.bbox = bitmap->bbox; + params.pitch = bitmap->pitch; + params.bitmap = bitmap->buf; + params.is_1bpp = is_1bpp; + EnterCriticalSection(&fontface->cs); /* For now bypass cache for transformed cases. */ - if (bitmap->m && memcmp(bitmap->m, &identity, sizeof(*bitmap->m))) + if (memcmp(¶ms.m, &identity, sizeof(params.m))) { - *is_1bpp = font_funcs->get_glyph_bitmap(fontface->get_font_object(fontface), bitmap); + UNIX_CALL(get_glyph_bitmap, ¶ms); } else if ((entry = fontface_get_cache_entry(fontface, bitmap_size, &key))) { @@ -195,10 +222,13 @@ static HRESULT dwrite_fontface_get_glyph_bitmap(struct dwrite_fontface *fontface } else { - entry->is_1bpp = font_funcs->get_glyph_bitmap(fontface->get_font_object(fontface), bitmap); + params.is_1bpp = &_1bpp; + UNIX_CALL(get_glyph_bitmap, ¶ms); + entry->bitmap_size = bitmap_size; if ((entry->bitmap = malloc(entry->bitmap_size))) memcpy(entry->bitmap, bitmap->buf, entry->bitmap_size); + entry->is_1bpp = !!_1bpp; entry->has_bitmap = 1; } *is_1bpp = entry->is_1bpp; @@ -797,6 +827,7 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace5 *iface) { struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface); ULONG refcount = InterlockedDecrement(&fontface->refcount); + struct release_font_object_params params = { fontface->font_object }; TRACE("%p, refcount %u.\n", iface, refcount); @@ -837,7 +868,7 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace5 *iface) for (i = 0; i < ARRAY_SIZE(fontface->glyphs); i++) free(fontface->glyphs[i]); - font_funcs->release_font_object(fontface->font_object); + UNIX_CALL(release_font_object, ¶ms); if (fontface->stream) { IDWriteFontFileStream_ReleaseFileFragment(fontface->stream, fontface->data_context); @@ -924,16 +955,24 @@ static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace5 *iface, DWRITE_FON static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace5 *iface) { struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface); + struct get_glyph_count_params params; + unsigned int count; TRACE("%p.\n", iface); - return font_funcs->get_glyph_count(fontface->get_font_object(fontface)); + params.object = fontface->get_font_object(fontface); + params.count = &count; + UNIX_CALL(get_glyph_count, ¶ms); + + return count; } static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5 *iface, UINT16 const *glyphs, UINT32 glyph_count, DWRITE_GLYPH_METRICS *ret, BOOL is_sideways) { struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface); + struct get_design_glyph_metrics_params params; + DWRITE_GLYPH_METRICS metrics; HRESULT hr = S_OK; unsigned int i; @@ -945,16 +984,20 @@ static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5 *ifa if (is_sideways) FIXME("sideways metrics are not supported.\n"); + params.object = fontface->get_font_object(fontface); + params.simulations = fontface->simulations; + params.upem = fontface->metrics.designUnitsPerEm; + params.ascent = fontface->typo_metrics.ascent; + params.metrics = &metrics; + EnterCriticalSection(&fontface->cs); for (i = 0; i < glyph_count; ++i) { - DWRITE_GLYPH_METRICS metrics; if (get_cached_glyph_metrics(fontface, glyphs[i], &metrics) != S_OK) { - font_funcs->get_design_glyph_metrics(fontface->get_font_object(fontface), - fontface->metrics.designUnitsPerEm, fontface->typo_metrics.ascent, - fontface->simulations, glyphs[i], &metrics); + params.glyph = glyphs[i]; + UNIX_CALL(get_design_glyph_metrics, ¶ms); if (FAILED(hr = set_cached_glyph_metrics(fontface, glyphs[i], &metrics))) break; } ret[i] = metrics; @@ -1024,12 +1067,13 @@ static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace5 *iface, struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface); D2D1_POINT_2F *origins, baseline_origin = { 0 }; struct dwrite_outline outline, outline_size; + struct get_glyph_outline_params params; D2D1_BEZIER_SEGMENT segment; D2D1_POINT_2F point; DWRITE_GLYPH_RUN run; unsigned int i, j, p; + NTSTATUS status; HRESULT hr; - int ret; TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface, emSize, glyphs, advances, offsets, count, is_sideways, is_rtl, sink); @@ -1063,28 +1107,35 @@ static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace5 *iface, memset(&outline_size, 0, sizeof(outline_size)); memset(&outline, 0, sizeof(outline)); + params.object = fontface->get_font_object(fontface); + params.simulations = fontface->simulations; + params.emsize = emSize; + for (i = 0; i < count; ++i) { outline.tags.count = outline.points.count = 0; EnterCriticalSection(&fontface->cs); - if (!(ret = font_funcs->get_glyph_outline(fontface->get_font_object(fontface), emSize, fontface->simulations, - glyphs[i], &outline_size))) + + params.glyph = glyphs[i]; + params.outline = &outline_size; + + if (!(status = UNIX_CALL(get_glyph_outline, ¶ms))) { dwrite_array_reserve((void **)&outline.tags.values, &outline.tags.size, outline_size.tags.count, sizeof(*outline.tags.values)); dwrite_array_reserve((void **)&outline.points.values, &outline.points.size, outline_size.points.count, sizeof(*outline.points.values)); - if ((ret = font_funcs->get_glyph_outline(fontface->get_font_object(fontface), emSize, fontface->simulations, - glyphs[i], &outline))) + params.outline = &outline; + if ((status = UNIX_CALL(get_glyph_outline, ¶ms))) { WARN("Failed to get glyph outline for glyph %u.\n", glyphs[i]); } } LeaveCriticalSection(&fontface->cs); - if (ret) + if (status) continue; for (j = 0, p = 0; j < outline.tags.count; ++j) @@ -5239,26 +5290,37 @@ HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_ke return S_OK; } -static font_object_handle dwrite_fontface_get_font_object(struct dwrite_fontface *fontface) +static UINT64 dwrite_fontface_get_font_object(struct dwrite_fontface *fontface) { - font_object_handle font_object; + struct create_font_object_params create_params; + struct release_font_object_params release_params; + UINT64 font_object, size; const void *data_ptr; void *data_context; - UINT64 size; if (!fontface->font_object && SUCCEEDED(IDWriteFontFileStream_GetFileSize(fontface->stream, &size))) { if (SUCCEEDED(IDWriteFontFileStream_ReadFileFragment(fontface->stream, &data_ptr, 0, size, &data_context))) { - if (!(font_object = font_funcs->create_font_object(data_ptr, size, fontface->index))) + create_params.data = data_ptr; + create_params.size = size; + create_params.index = fontface->index; + create_params.object = &font_object; + + UNIX_CALL(create_font_object, &create_params); + + if (!font_object) { WARN("Backend failed to create font object.\n"); IDWriteFontFileStream_ReleaseFileFragment(fontface->stream, data_context); - return NULL; + return 0; } - if (InterlockedCompareExchangePointer((void **)&fontface->font_object, font_object, NULL)) - font_funcs->release_font_object(font_object); + if (InterlockedCompareExchange64((LONGLONG *)&fontface->font_object, font_object, 0)) + { + release_params.object = font_object; + UNIX_CALL(release_font_object, &release_params); + } } } @@ -5997,7 +6059,7 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis) { BYTE *src = glyph_bitmap.buf, *dst; int x, y, width, height; - BOOL is_1bpp; + unsigned int is_1bpp; glyph_bitmap.glyph = analysis->run.glyphIndices[i]; dwrite_fontface_get_glyph_bbox(analysis->run.fontFace, &glyph_bitmap); @@ -6010,6 +6072,7 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis) glyph_bitmap.pitch = get_glyph_bitmap_pitch(analysis->rendering_mode, width); memset(src, 0, height * glyph_bitmap.pitch); + if (FAILED(dwrite_fontface_get_glyph_bitmap(fontface, analysis->rendering_mode, &is_1bpp, &glyph_bitmap))) { WARN("Failed to render glyph[%u] = %#x.\n", i, glyph_bitmap.glyph); @@ -8140,13 +8203,3 @@ HRESULT create_fontset_builder(IDWriteFactory7 *factory, IDWriteFontSetBuilder2 return S_OK; } - -void init_font_backend(void) -{ - __wine_init_unix_lib(dwrite_module, DLL_PROCESS_ATTACH, NULL, &font_funcs); -} - -void release_font_backend(void) -{ - __wine_init_unix_lib(dwrite_module, DLL_PROCESS_DETACH, NULL, NULL); -} diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c index daaff6a3f8c..02f496f181b 100644 --- a/dlls/dwrite/freetype.c +++ b/dlls/dwrite/freetype.c @@ -40,6 +40,7 @@ #define WIN32_NO_STATUS #include "windef.h" #include "wine/debug.h" +#include "unixlib.h" #include "dwrite_private.h" @@ -88,6 +89,8 @@ MAKE_FUNCPTR(FT_Set_Pixel_Sizes); #undef MAKE_FUNCPTR static FT_Error (*pFT_Outline_EmboldenXY)(FT_Outline *, FT_Pos, FT_Pos); +#define FaceFromObject(o) ((FT_Face)(ULONG_PTR)(o)) + static FT_Size freetype_set_face_size(FT_Face face, FT_UInt emsize) { FT_Size size; @@ -110,7 +113,7 @@ static BOOL freetype_glyph_has_contours(FT_Face face) return face->glyph->format == FT_GLYPH_FORMAT_OUTLINE && face->glyph->outline.n_contours; } -static BOOL init_freetype(void) +static NTSTATUS process_attach(void *args) { FT_Version_t FT_Version; @@ -118,7 +121,7 @@ static BOOL init_freetype(void) if (!ft_handle) { WINE_MESSAGE("Wine cannot find the FreeType font library.\n"); - return FALSE; + return STATUS_DLL_NOT_FOUND; } #define LOAD_FUNCPTR(f) if((p##f = dlsym(ft_handle, #f)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;} @@ -153,72 +156,89 @@ static BOOL init_freetype(void) #undef LOAD_FUNCPTR pFT_Outline_EmboldenXY = dlsym(ft_handle, "FT_Outline_EmboldenXY"); - if (pFT_Init_FreeType(&library) != 0) { + if (pFT_Init_FreeType(&library) != 0) + { ERR("Can't init FreeType library\n"); - dlclose(ft_handle); + dlclose(ft_handle); ft_handle = NULL; - return FALSE; + return STATUS_UNSUCCESSFUL; } 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; + return STATUS_SUCCESS; sym_not_found: WINE_MESSAGE("Wine cannot find certain functions that it needs from FreeType library.\n"); dlclose(ft_handle); ft_handle = NULL; - return FALSE; + return STATUS_UNSUCCESSFUL; } -static font_object_handle CDECL freetype_create_font_object(const void *data_ptr, UINT64 data_size, unsigned int index) +static NTSTATUS process_detach(void *args) { + pFT_Done_FreeType(library); + return STATUS_SUCCESS; +} + +static NTSTATUS create_font_object(void *args) +{ + struct create_font_object_params *params = args; FT_Face face = NULL; FT_Error fterror; - fterror = pFT_New_Memory_Face(library, data_ptr, data_size, index, &face); + fterror = pFT_New_Memory_Face(library, params->data, params->size, params->index, &face); if (fterror != FT_Err_Ok) + { WARN("Failed to create a face object, error %d.\n", fterror); + return STATUS_UNSUCCESSFUL; + } - return face; + *params->object = (ULONG_PTR)face; + + return STATUS_SUCCESS; } -static void CDECL freetype_release_font_object(font_object_handle object) +static NTSTATUS release_font_object(void *args) { - pFT_Done_Face(object); + struct release_font_object_params *params = args; + pFT_Done_Face(FaceFromObject(params->object)); + return STATUS_SUCCESS; } -static void CDECL freetype_get_design_glyph_metrics(font_object_handle object, UINT16 upem, UINT16 ascent, - unsigned int simulations, UINT16 glyph, DWRITE_GLYPH_METRICS *ret) +static NTSTATUS get_design_glyph_metrics(void *args) { - FT_Face face = object; + struct get_design_glyph_metrics_params *params = args; + FT_Face face = FaceFromObject(params->object); FT_Size size; - if (!(size = freetype_set_face_size(face, upem))) - return; + if (!(size = freetype_set_face_size(face, params->upem))) + return STATUS_UNSUCCESSFUL; - if (!pFT_Load_Glyph(face, glyph, FT_LOAD_NO_SCALE)) + if (!pFT_Load_Glyph(face, params->glyph, FT_LOAD_NO_SCALE)) { FT_Glyph_Metrics *metrics = &face->glyph->metrics; - ret->leftSideBearing = metrics->horiBearingX; - ret->advanceWidth = metrics->horiAdvance; - ret->rightSideBearing = metrics->horiAdvance - metrics->horiBearingX - metrics->width; + params->metrics->leftSideBearing = metrics->horiBearingX; + params->metrics->advanceWidth = metrics->horiAdvance; + params->metrics->rightSideBearing = metrics->horiAdvance - metrics->horiBearingX - metrics->width; - ret->advanceHeight = metrics->vertAdvance; - ret->verticalOriginY = ascent; - ret->topSideBearing = ascent - metrics->horiBearingY; - ret->bottomSideBearing = metrics->vertAdvance - metrics->height - ret->topSideBearing; + params->metrics->advanceHeight = metrics->vertAdvance; + params->metrics->verticalOriginY = params->ascent; + params->metrics->topSideBearing = params->ascent - metrics->horiBearingY; + params->metrics->bottomSideBearing = metrics->vertAdvance - metrics->height - params->metrics->topSideBearing; /* Adjust in case of bold simulation, glyphs without contours are ignored. */ - if (simulations & DWRITE_FONT_SIMULATIONS_BOLD && freetype_glyph_has_contours(face)) + if (params->simulations & DWRITE_FONT_SIMULATIONS_BOLD && freetype_glyph_has_contours(face)) { - if (ret->advanceWidth) - ret->advanceWidth += (upem + 49) / 50; + if (params->metrics->advanceWidth) + params->metrics->advanceWidth += (params->upem + 49) / 50; } } pFT_Done_Size(size); + + return STATUS_SUCCESS; } struct decompose_context @@ -425,52 +445,55 @@ static void embolden_glyph(FT_Glyph glyph, FLOAT emsize) embolden_glyph_outline(&outline_glyph->outline, emsize); } -static int CDECL freetype_get_glyph_outline(font_object_handle object, float emsize, unsigned int simulations, - UINT16 glyph, struct dwrite_outline *outline) +static NTSTATUS get_glyph_outline(void *args) { - FT_Face face = object; + struct get_glyph_outline_params *params = args; + FT_Face face = FaceFromObject(params->object); FT_Size size; - int ret = 0; - if (!(size = freetype_set_face_size(face, emsize))) - return 0; + if (!(size = freetype_set_face_size(face, params->emsize))) + return STATUS_UNSUCCESSFUL; - if (!pFT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP)) + if (!pFT_Load_Glyph(face, params->glyph, FT_LOAD_NO_BITMAP)) { FT_Outline *ft_outline = &face->glyph->outline; FT_Matrix m; - if (outline->points.values) + if (params->outline->points.values) { - if (simulations & DWRITE_FONT_SIMULATIONS_BOLD) - embolden_glyph_outline(ft_outline, emsize); + if (params->simulations & DWRITE_FONT_SIMULATIONS_BOLD) + embolden_glyph_outline(ft_outline, params->emsize); m.xx = 1 << 16; - m.xy = simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE ? (1 << 16) / 3 : 0; + m.xy = params->simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE ? (1 << 16) / 3 : 0; m.yx = 0; m.yy = -(1 << 16); /* flip Y axis */ pFT_Outline_Transform(ft_outline, &m); - ret = decompose_outline(ft_outline, outline); + decompose_outline(ft_outline, params->outline); } else { /* Intentionally overestimate numbers to keep it simple. */ - outline->points.count = ft_outline->n_points * 3; - outline->tags.count = ft_outline->n_points + ft_outline->n_contours * 2; + params->outline->points.count = ft_outline->n_points * 3; + params->outline->tags.count = ft_outline->n_points + ft_outline->n_contours * 2; } } pFT_Done_Size(size); - return ret; + return STATUS_SUCCESS; } -static UINT16 CDECL freetype_get_glyph_count(font_object_handle object) +static NTSTATUS get_glyph_count(void *args) { - FT_Face face = object; - return face ? face->num_glyphs : 0; + struct get_glyph_count_params *params = args; + FT_Face face = FaceFromObject(params->object); + + *params->count = face ? face->num_glyphs : 0; + + return STATUS_SUCCESS; } static inline void ft_matrix_from_dwrite_matrix(const DWRITE_MATRIX *m, FT_Matrix *ft_matrix) @@ -481,9 +504,9 @@ static inline void ft_matrix_from_dwrite_matrix(const DWRITE_MATRIX *m, FT_Matri ft_matrix->yy = m->m22 * 0x10000; } -static BOOL get_glyph_transform(struct dwrite_glyphbitmap *bitmap, FT_Matrix *ret) +static BOOL get_glyph_transform(unsigned int simulations, const DWRITE_MATRIX *m, FT_Matrix *ret) { - FT_Matrix m; + FT_Matrix ftm; ret->xx = 1 << 16; ret->xy = 0; @@ -492,53 +515,53 @@ static BOOL get_glyph_transform(struct dwrite_glyphbitmap *bitmap, FT_Matrix *re /* Some fonts provide mostly bitmaps and very few outlines, for example for .notdef. Disable transform if that's the case. */ - if (!bitmap->m && !bitmap->simulations) + if (!memcmp(m, &identity, sizeof(*m)) && !simulations) return FALSE; - if (bitmap->simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) { - m.xx = 1 << 16; - m.xy = (1 << 16) / 3; - m.yx = 0; - m.yy = 1 << 16; - pFT_Matrix_Multiply(&m, ret); + if (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) + { + ftm.xx = 1 << 16; + ftm.xy = (1 << 16) / 3; + ftm.yx = 0; + ftm.yy = 1 << 16; + pFT_Matrix_Multiply(&ftm, ret); } - if (bitmap->m) { - ft_matrix_from_dwrite_matrix(bitmap->m, &m); - pFT_Matrix_Multiply(&m, ret); - } + ft_matrix_from_dwrite_matrix(m, &ftm); + pFT_Matrix_Multiply(&ftm, ret); return TRUE; } -static void CDECL freetype_get_glyph_bbox(font_object_handle object, struct dwrite_glyphbitmap *bitmap) +static NTSTATUS get_glyph_bbox(void *args) { - FT_Face face = object; + struct get_glyph_bbox_params *params = args; + FT_Face face = FaceFromObject(params->object); FT_Glyph glyph = NULL; FT_BBox bbox = { 0 }; BOOL needs_transform; FT_Matrix m; FT_Size size; - SetRectEmpty(&bitmap->bbox); + SetRectEmpty(params->bbox); - if (!(size = freetype_set_face_size(face, bitmap->emsize))) - return; + if (!(size = freetype_set_face_size(face, params->emsize))) + return STATUS_UNSUCCESSFUL; - needs_transform = FT_IS_SCALABLE(face) && get_glyph_transform(bitmap, &m); + needs_transform = FT_IS_SCALABLE(face) && get_glyph_transform(params->simulations, ¶ms->m, &m); - if (pFT_Load_Glyph(face, bitmap->glyph, needs_transform ? FT_LOAD_NO_BITMAP : 0)) + if (pFT_Load_Glyph(face, params->glyph, needs_transform ? FT_LOAD_NO_BITMAP : 0)) { - WARN("Failed to load glyph %u.\n", bitmap->glyph); + WARN("Failed to load glyph %u.\n", params->glyph); pFT_Done_Size(size); - return; + return STATUS_UNSUCCESSFUL; } pFT_Get_Glyph(face->glyph, &glyph); if (needs_transform) { - if (bitmap->simulations & DWRITE_FONT_SIMULATIONS_BOLD) - embolden_glyph(glyph, bitmap->emsize); + if (params->simulations & DWRITE_FONT_SIMULATIONS_BOLD) + embolden_glyph(glyph, params->emsize); /* Includes oblique and user transform. */ pFT_Glyph_Transform(glyph, &m, NULL); @@ -549,15 +572,19 @@ static void CDECL freetype_get_glyph_bbox(font_object_handle object, struct dwri pFT_Done_Size(size); /* flip Y axis */ - SetRect(&bitmap->bbox, bbox.xMin, -bbox.yMax, bbox.xMax, -bbox.yMin); + SetRect(params->bbox, bbox.xMin, -bbox.yMax, bbox.xMax, -bbox.yMin); + + return STATUS_SUCCESS; } -static BOOL freetype_get_aliased_glyph_bitmap(struct dwrite_glyphbitmap *bitmap, FT_Glyph glyph) +static NTSTATUS freetype_get_aliased_glyph_bitmap(struct get_glyph_bitmap_params *params, FT_Glyph glyph) { - const RECT *bbox = &bitmap->bbox; + const RECT *bbox = ¶ms->bbox; int width = bbox->right - bbox->left; int height = bbox->bottom - bbox->top; + *params->is_1bpp = 1; + if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph; const FT_Outline *src = &outline->outline; @@ -566,9 +593,9 @@ static BOOL freetype_get_aliased_glyph_bitmap(struct dwrite_glyphbitmap *bitmap, ft_bitmap.width = width; ft_bitmap.rows = height; - ft_bitmap.pitch = bitmap->pitch; + ft_bitmap.pitch = params->pitch; ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO; - ft_bitmap.buffer = bitmap->buf; + ft_bitmap.buffer = params->bitmap; /* Note: FreeType will only set 'black' bits for us. */ if (pFT_Outline_New(library, src->n_points, src->n_contours, ©) == 0) { @@ -580,28 +607,29 @@ static BOOL freetype_get_aliased_glyph_bitmap(struct dwrite_glyphbitmap *bitmap, } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap; - BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf; - int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3); + BYTE *src = ft_bitmap->buffer, *dst = params->bitmap; + int w = min(params->pitch, (ft_bitmap->width + 7) >> 3); int h = min(height, ft_bitmap->rows); while (h--) { memcpy(dst, src, w); src += ft_bitmap->pitch; - dst += bitmap->pitch; + dst += params->pitch; } } else FIXME("format %x not handled\n", glyph->format); - return TRUE; + return STATUS_SUCCESS; } -static BOOL freetype_get_aa_glyph_bitmap(struct dwrite_glyphbitmap *bitmap, FT_Glyph glyph) +static NTSTATUS freetype_get_aa_glyph_bitmap(struct get_glyph_bitmap_params *params, FT_Glyph glyph) { - const RECT *bbox = &bitmap->bbox; + const RECT *bbox = ¶ms->bbox; int width = bbox->right - bbox->left; int height = bbox->bottom - bbox->top; - BOOL ret = FALSE; + + *params->is_1bpp = 0; if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph; @@ -611,9 +639,9 @@ static BOOL freetype_get_aa_glyph_bitmap(struct dwrite_glyphbitmap *bitmap, FT_G ft_bitmap.width = width; ft_bitmap.rows = height; - ft_bitmap.pitch = bitmap->pitch; + ft_bitmap.pitch = params->pitch; ft_bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; - ft_bitmap.buffer = bitmap->buf; + ft_bitmap.buffer = params->bitmap; /* Note: FreeType will only set 'black' bits for us. */ if (pFT_Outline_New(library, src->n_points, src->n_contours, ©) == 0) { @@ -625,55 +653,61 @@ static BOOL freetype_get_aa_glyph_bitmap(struct dwrite_glyphbitmap *bitmap, FT_G } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap; - BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf; - int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3); + BYTE *src = ft_bitmap->buffer, *dst = params->bitmap; + int w = min(params->pitch, (ft_bitmap->width + 7) >> 3); int h = min(height, ft_bitmap->rows); while (h--) { memcpy(dst, src, w); src += ft_bitmap->pitch; - dst += bitmap->pitch; + dst += params->pitch; } - ret = TRUE; + *params->is_1bpp = 1; } else + { FIXME("format %x not handled\n", glyph->format); + return STATUS_NOT_IMPLEMENTED; + } - return ret; + return STATUS_SUCCESS; } -static BOOL CDECL freetype_get_glyph_bitmap(font_object_handle object, struct dwrite_glyphbitmap *bitmap) +static NTSTATUS get_glyph_bitmap(void *args) { - FT_Face face = object; + struct get_glyph_bitmap_params *params = args; + FT_Face face = FaceFromObject(params->object); BOOL needs_transform; BOOL ret = FALSE; FT_Glyph glyph; FT_Size size; FT_Matrix m; - if (!(size = freetype_set_face_size(face, bitmap->emsize))) - return FALSE; + *params->is_1bpp = 0; - needs_transform = FT_IS_SCALABLE(face) && get_glyph_transform(bitmap, &m); + if (!(size = freetype_set_face_size(face, params->emsize))) + return STATUS_UNSUCCESSFUL; - if (!pFT_Load_Glyph(face, bitmap->glyph, needs_transform ? FT_LOAD_NO_BITMAP : 0)) + needs_transform = FT_IS_SCALABLE(face) && get_glyph_transform(params->simulations, ¶ms->m, &m); + + if (!pFT_Load_Glyph(face, params->glyph, needs_transform ? FT_LOAD_NO_BITMAP : 0)) { pFT_Get_Glyph(face->glyph, &glyph); if (needs_transform) { - if (bitmap->simulations & DWRITE_FONT_SIMULATIONS_BOLD) - embolden_glyph(glyph, bitmap->emsize); + if (params->simulations & DWRITE_FONT_SIMULATIONS_BOLD) + embolden_glyph(glyph, params->emsize); /* Includes oblique and user transform. */ pFT_Glyph_Transform(glyph, &m, NULL); } - if (bitmap->aliased) - ret = freetype_get_aliased_glyph_bitmap(bitmap, glyph); + if (params->mode == DWRITE_RENDERING_MODE1_ALIASED) + ret = freetype_get_aliased_glyph_bitmap(params, glyph); else - ret = freetype_get_aa_glyph_bitmap(bitmap, glyph); + ret = freetype_get_aa_glyph_bitmap(params, glyph); pFT_Done_Glyph(glyph); } @@ -683,128 +717,100 @@ static BOOL CDECL freetype_get_glyph_bitmap(font_object_handle object, struct dw return ret; } -static INT32 CDECL freetype_get_glyph_advance(font_object_handle object, float emsize, UINT16 glyph, - DWRITE_MEASURING_MODE mode, BOOL *has_contours) +static NTSTATUS get_glyph_advance(void *args) { - FT_Face face = object; - INT32 advance = 0; + struct get_glyph_advance_params *params = args; + FT_Face face = FaceFromObject(params->object); FT_Size size; - *has_contours = FALSE; + *params->advance = 0; + *params->has_contours = FALSE; - if (!(size = freetype_set_face_size(face, emsize))) - return 0; + if (!(size = freetype_set_face_size(face, params->emsize))) + return STATUS_UNSUCCESSFUL; - if (!pFT_Load_Glyph(face, glyph, mode == DWRITE_MEASURING_MODE_NATURAL ? FT_LOAD_NO_HINTING : 0)) + if (!pFT_Load_Glyph(face, params->glyph, params->mode == DWRITE_MEASURING_MODE_NATURAL ? FT_LOAD_NO_HINTING : 0)) { - advance = face->glyph->advance.x >> 6; - *has_contours = freetype_glyph_has_contours(face); + *params->advance = face->glyph->advance.x >> 6; + *params->has_contours = freetype_glyph_has_contours(face); } pFT_Done_Size(size); - return advance; -} - -const static struct font_backend_funcs freetype_funcs = -{ - freetype_create_font_object, - freetype_release_font_object, - freetype_get_glyph_outline, - freetype_get_glyph_count, - freetype_get_glyph_advance, - freetype_get_glyph_bbox, - freetype_get_glyph_bitmap, - freetype_get_design_glyph_metrics, -}; - -static NTSTATUS init_freetype_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out) -{ - if (!init_freetype()) return STATUS_DLL_NOT_FOUND; - *(const struct font_backend_funcs **)ptr_out = &freetype_funcs; - return STATUS_SUCCESS; -} - -static NTSTATUS release_freetype_lib(void) -{ - pFT_Done_FreeType(library); return STATUS_SUCCESS; } #else /* HAVE_FREETYPE */ -static font_object_handle CDECL null_create_font_object(const void *data_ptr, UINT64 data_size, unsigned int index) +static NTSTATUS process_attach(void *args) { - return NULL; + return STATUS_NOT_IMPLEMENTED; } -static void CDECL null_release_font_object(font_object_handle object) +static NTSTATUS process_detach(void *args) { + return STATUS_NOT_IMPLEMENTED; } -static int CDECL null_get_glyph_outline(font_object_handle object, float emSize, unsigned int simulations, - UINT16 glyph, struct dwrite_outline *outline) +static NTSTATUS create_font_object(void *args) { - return 1; + return STATUS_NOT_IMPLEMENTED; } -static UINT16 CDECL null_get_glyph_count(font_object_handle object) +static NTSTATUS release_font_object(void *args) { - return 0; + return STATUS_NOT_IMPLEMENTED; } -static INT32 CDECL null_get_glyph_advance(font_object_handle object, float emsize, UINT16 glyph, - DWRITE_MEASURING_MODE mode, BOOL *has_contours) +static NTSTATUS get_glyph_outline(void *args) { - *has_contours = FALSE; - return 0; + return STATUS_NOT_IMPLEMENTED; } -static void CDECL null_get_glyph_bbox(font_object_handle object, struct dwrite_glyphbitmap *bitmap) +static NTSTATUS get_glyph_count(void *args) { - SetRectEmpty(&bitmap->bbox); + return STATUS_NOT_IMPLEMENTED; } -static BOOL CDECL null_get_glyph_bitmap(font_object_handle object, struct dwrite_glyphbitmap *bitmap) +static NTSTATUS get_glyph_advance(void *args) { - return FALSE; + struct get_glyph_advance_params *params = args; + + *params->has_contours = 0; + *params->advance = 0; + + return STATUS_NOT_IMPLEMENTED; } -static void CDECL null_get_design_glyph_metrics(font_object_handle object, UINT16 upem, UINT16 ascent, unsigned int simulations, - UINT16 glyph, DWRITE_GLYPH_METRICS *metrics) +static NTSTATUS get_glyph_bbox(void *args) { + struct get_glyph_bbox_params *params = args; + SetRectEmpty(params->bbox); + return STATUS_NOT_IMPLEMENTED; } -const static struct font_backend_funcs null_funcs = +static NTSTATUS get_glyph_bitmap(void *args) { - null_create_font_object, - null_release_font_object, - null_get_glyph_outline, - null_get_glyph_count, - null_get_glyph_advance, - null_get_glyph_bbox, - null_get_glyph_bitmap, - null_get_design_glyph_metrics, -}; - -static NTSTATUS init_freetype_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out) -{ - *(const struct font_backend_funcs **)ptr_out = &null_funcs; - return STATUS_DLL_NOT_FOUND; + return STATUS_NOT_IMPLEMENTED; } -static NTSTATUS release_freetype_lib(void) +static NTSTATUS get_design_glyph_metrics(void *args) { - return STATUS_DLL_NOT_FOUND; + return STATUS_NOT_IMPLEMENTED; } #endif /* HAVE_FREETYPE */ -NTSTATUS CDECL __wine_init_unix_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out) +const unixlib_entry_t __wine_unix_call_funcs[] = { - if (reason == DLL_PROCESS_ATTACH) - return init_freetype_lib(module, reason, ptr_in, ptr_out); - else if (reason == DLL_PROCESS_DETACH) - return release_freetype_lib(); - return STATUS_SUCCESS; -} + process_attach, + process_detach, + create_font_object, + release_font_object, + get_glyph_outline, + get_glyph_count, + get_glyph_advance, + get_glyph_bbox, + get_glyph_bitmap, + get_design_glyph_metrics, +}; diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index d0dd4dd99e9..b21eba0c50a 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -30,11 +30,13 @@ #include "initguid.h" #include "dwrite_private.h" +#include "unixlib.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(dwrite); HMODULE dwrite_module = 0; +unixlib_handle_t unixlib_handle = 0; static IDWriteFactory7 *shared_factory; static void release_shared_factory(IDWriteFactory7 *factory); @@ -45,13 +47,15 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved) case DLL_PROCESS_ATTACH: dwrite_module = hinstDLL; DisableThreadLibraryCalls( hinstDLL ); - init_font_backend(); + if (!NtQueryVirtualMemory(GetCurrentProcess(), hinstDLL, MemoryWineUnixFuncs, + &unixlib_handle, sizeof(unixlib_handle), NULL)) + UNIX_CALL(process_attach, NULL); init_local_fontfile_loader(); break; case DLL_PROCESS_DETACH: if (reserved) break; release_shared_factory(shared_factory); - release_font_backend(); + if (unixlib_handle) UNIX_CALL(process_detach, NULL); } return TRUE; } diff --git a/dlls/dwrite/unixlib.h b/dlls/dwrite/unixlib.h new file mode 100644 index 00000000000..533c3168b99 --- /dev/null +++ b/dlls/dwrite/unixlib.h @@ -0,0 +1,113 @@ +/* + * Copyright 2021 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 +#include "windef.h" +#include "winternl.h" +#include "dwrite.h" +#include "wine/unixlib.h" + +struct create_font_object_params +{ + const void *data; + UINT64 size; + unsigned int index; + UINT64 *object; +}; + +struct release_font_object_params +{ + UINT64 object; +}; + +struct get_glyph_outline_params +{ + UINT64 object; + unsigned int simulations; + unsigned int glyph; + float emsize; + struct dwrite_outline *outline; +}; + +struct get_glyph_count_params +{ + UINT64 object; + unsigned int *count; +}; + +struct get_glyph_advance_params +{ + UINT64 object; + unsigned int glyph; + unsigned int mode; + float emsize; + int *advance; + unsigned int *has_contours; +}; + +struct get_glyph_bbox_params +{ + UINT64 object; + unsigned int simulations; + unsigned int glyph; + float emsize; + DWRITE_MATRIX m; + RECT *bbox; +}; + +struct get_glyph_bitmap_params +{ + UINT64 object; + unsigned int simulations; + unsigned int glyph; + unsigned int mode; + float emsize; + DWRITE_MATRIX m; + RECT bbox; + int pitch; + BYTE *bitmap; + unsigned int *is_1bpp; +}; + +struct get_design_glyph_metrics_params +{ + UINT64 object; + unsigned int simulations; + unsigned int glyph; + unsigned int upem; + unsigned int ascent; + DWRITE_GLYPH_METRICS *metrics; +}; + +enum font_backend_funcs +{ + unix_process_attach, + unix_process_detach, + unix_create_font_object, + unix_release_font_object, + unix_get_glyph_outline, + unix_get_glyph_count, + unix_get_glyph_advance, + unix_get_glyph_bbox, + unix_get_glyph_bitmap, + unix_get_design_glyph_metrics, +}; + +extern unixlib_handle_t unixlib_handle DECLSPEC_HIDDEN; + +#define UNIX_CALL( func, params ) __wine_unix_call( unixlib_handle, unix_ ## func, params )