dwrite: Switch to unixlib syscall interface.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2021-12-08 14:10:42 +03:00 committed by Alexandre Julliard
parent 0b3d65f822
commit 275a2d71d6
6 changed files with 406 additions and 248 deletions

View File

@ -1,5 +1,6 @@
MODULE = dwrite.dll MODULE = dwrite.dll
IMPORTLIB = dwrite IMPORTLIB = dwrite
UNIXLIB = dwrite.so
IMPORTS = user32 gdi32 advapi32 IMPORTS = user32 gdi32 advapi32
EXTRAINCL = $(FREETYPE_CFLAGS) EXTRAINCL = $(FREETYPE_CFLAGS)

View File

@ -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; DWRITE_UNICODE_RANGE *ranges, unsigned int *count) DECLSPEC_HIDDEN;
struct dwrite_fontface; struct dwrite_fontface;
typedef void * font_object_handle; typedef UINT64 (*p_dwrite_fontface_get_font_object)(struct dwrite_fontface *fontface);
typedef font_object_handle (*p_dwrite_fontface_get_font_object)(struct dwrite_fontface *fontface);
struct dwrite_fontface struct dwrite_fontface
{ {
@ -238,7 +237,7 @@ struct dwrite_fontface
IDWriteFactory7 *factory; IDWriteFactory7 *factory;
struct fontfacecached *cached; struct fontfacecached *cached;
font_object_handle font_object; UINT64 font_object;
void *data_context; void *data_context;
p_dwrite_fontface_get_font_object get_font_object; p_dwrite_fontface_get_font_object get_font_object;
struct struct
@ -717,22 +716,4 @@ extern HRESULT shape_check_typographic_feature(struct scriptshaping_context *con
struct font_data_context; struct font_data_context;
extern HMODULE dwrite_module DECLSPEC_HIDDEN; 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; extern void dwrite_fontface_get_glyph_bbox(IDWriteFontFace *fontface, struct dwrite_glyphbitmap *bitmap) DECLSPEC_HIDDEN;

View File

@ -26,6 +26,7 @@
#define COBJMACROS #define COBJMACROS
#include "dwrite_private.h" #include "dwrite_private.h"
#include "unixlib.h"
WINE_DEFAULT_DEBUG_CHANNEL(dwrite); WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
WINE_DECLARE_DEBUG_CHANNEL(dwrite_file); 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_OUTLINE_A_THRESHOLD = 350.0f;
static const FLOAT RECOMMENDED_NATURAL_PPEM = 20.0f; static const FLOAT RECOMMENDED_NATURAL_PPEM = 20.0f;
static const struct font_backend_funcs *font_funcs;
struct cache_key struct cache_key
{ {
float size; float size;
@ -59,7 +58,7 @@ struct cache_entry
struct wine_rb_entry entry; struct wine_rb_entry entry;
struct list mru; struct list mru;
struct cache_key key; struct cache_key key;
float advance; int advance;
RECT bbox; RECT bbox;
BYTE *bitmap; BYTE *bitmap;
unsigned int bitmap_size; unsigned int bitmap_size;
@ -117,19 +116,28 @@ static struct cache_entry * fontface_get_cache_entry(struct dwrite_fontface *fon
return entry; 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) unsigned short mode, BOOL *has_contours)
{ {
struct cache_key key = { .size = fontsize, .glyph = glyph, .mode = mode }; struct cache_key key = { .size = fontsize, .glyph = glyph, .mode = mode };
struct get_glyph_advance_params params;
struct cache_entry *entry; struct cache_entry *entry;
BOOL value; unsigned int value;
if (!(entry = fontface_get_cache_entry(fontface, 0, &key))) if (!(entry = fontface_get_cache_entry(fontface, 0, &key)))
return 0.0f; return 0;
if (!entry->has_advance) 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, &params);
entry->has_contours = !!value; entry->has_contours = !!value;
entry->has_advance = 1; 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 cache_key key = { .size = bitmap->emsize, .glyph = bitmap->glyph, .mode = DWRITE_MEASURING_MODE_NATURAL };
struct dwrite_fontface *fontface = unsafe_impl_from_IDWriteFontFace(iface); struct dwrite_fontface *fontface = unsafe_impl_from_IDWriteFontFace(iface);
struct get_glyph_bbox_params params;
struct cache_entry *entry; 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); EnterCriticalSection(&fontface->cs);
/* For now bypass cache for transformed cases. */ /* For now bypass cache for transformed cases. */
if (bitmap->m && memcmp(bitmap->m, &identity, sizeof(*bitmap->m))) 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, &params);
} }
else if ((entry = fontface_get_cache_entry(fontface, 0, &key))) else if ((entry = fontface_get_cache_entry(fontface, 0, &key)))
{ {
if (entry->has_bbox) if (!entry->has_bbox)
bitmap->bbox = entry->bbox;
else
{ {
font_funcs->get_glyph_bbox(fontface->get_font_object(fontface), bitmap); params.bbox = &entry->bbox;
entry->bbox = bitmap->bbox; UNIX_CALL(get_glyph_bbox, &params);
entry->has_bbox = 1; entry->has_bbox = 1;
} }
bitmap->bbox = entry->bbox;
} }
LeaveCriticalSection(&fontface->cs); 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, 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 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; const RECT *bbox = &bitmap->bbox;
unsigned int bitmap_size, _1bpp;
struct cache_entry *entry; struct cache_entry *entry;
unsigned int bitmap_size;
HRESULT hr = S_OK; HRESULT hr = S_OK;
bitmap_size = get_glyph_bitmap_pitch(rendering_mode, bbox->right - bbox->left) * bitmap_size = get_glyph_bitmap_pitch(rendering_mode, bbox->right - bbox->left) *
(bbox->bottom - bbox->top); (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); EnterCriticalSection(&fontface->cs);
/* For now bypass cache for transformed cases. */ /* For now bypass cache for transformed cases. */
if (bitmap->m && memcmp(bitmap->m, &identity, sizeof(*bitmap->m))) if (memcmp(&params.m, &identity, sizeof(params.m)))
{ {
*is_1bpp = font_funcs->get_glyph_bitmap(fontface->get_font_object(fontface), bitmap); UNIX_CALL(get_glyph_bitmap, &params);
} }
else if ((entry = fontface_get_cache_entry(fontface, bitmap_size, &key))) 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 else
{ {
entry->is_1bpp = font_funcs->get_glyph_bitmap(fontface->get_font_object(fontface), bitmap); params.is_1bpp = &_1bpp;
UNIX_CALL(get_glyph_bitmap, &params);
entry->bitmap_size = bitmap_size; entry->bitmap_size = bitmap_size;
if ((entry->bitmap = malloc(entry->bitmap_size))) if ((entry->bitmap = malloc(entry->bitmap_size)))
memcpy(entry->bitmap, bitmap->buf, entry->bitmap_size); memcpy(entry->bitmap, bitmap->buf, entry->bitmap_size);
entry->is_1bpp = !!_1bpp;
entry->has_bitmap = 1; entry->has_bitmap = 1;
} }
*is_1bpp = entry->is_1bpp; *is_1bpp = entry->is_1bpp;
@ -797,6 +827,7 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace5 *iface)
{ {
struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface); struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface);
ULONG refcount = InterlockedDecrement(&fontface->refcount); ULONG refcount = InterlockedDecrement(&fontface->refcount);
struct release_font_object_params params = { fontface->font_object };
TRACE("%p, refcount %u.\n", iface, refcount); 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++) for (i = 0; i < ARRAY_SIZE(fontface->glyphs); i++)
free(fontface->glyphs[i]); free(fontface->glyphs[i]);
font_funcs->release_font_object(fontface->font_object); UNIX_CALL(release_font_object, &params);
if (fontface->stream) if (fontface->stream)
{ {
IDWriteFontFileStream_ReleaseFileFragment(fontface->stream, fontface->data_context); 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) static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace5 *iface)
{ {
struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface); struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface);
struct get_glyph_count_params params;
unsigned int count;
TRACE("%p.\n", iface); 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, &params);
return count;
} }
static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5 *iface, static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5 *iface,
UINT16 const *glyphs, UINT32 glyph_count, DWRITE_GLYPH_METRICS *ret, BOOL is_sideways) UINT16 const *glyphs, UINT32 glyph_count, DWRITE_GLYPH_METRICS *ret, BOOL is_sideways)
{ {
struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface); struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface);
struct get_design_glyph_metrics_params params;
DWRITE_GLYPH_METRICS metrics;
HRESULT hr = S_OK; HRESULT hr = S_OK;
unsigned int i; unsigned int i;
@ -945,16 +984,20 @@ static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5 *ifa
if (is_sideways) if (is_sideways)
FIXME("sideways metrics are not supported.\n"); 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); EnterCriticalSection(&fontface->cs);
for (i = 0; i < glyph_count; ++i) for (i = 0; i < glyph_count; ++i)
{ {
DWRITE_GLYPH_METRICS metrics;
if (get_cached_glyph_metrics(fontface, glyphs[i], &metrics) != S_OK) if (get_cached_glyph_metrics(fontface, glyphs[i], &metrics) != S_OK)
{ {
font_funcs->get_design_glyph_metrics(fontface->get_font_object(fontface), params.glyph = glyphs[i];
fontface->metrics.designUnitsPerEm, fontface->typo_metrics.ascent, UNIX_CALL(get_design_glyph_metrics, &params);
fontface->simulations, glyphs[i], &metrics);
if (FAILED(hr = set_cached_glyph_metrics(fontface, glyphs[i], &metrics))) break; if (FAILED(hr = set_cached_glyph_metrics(fontface, glyphs[i], &metrics))) break;
} }
ret[i] = metrics; ret[i] = metrics;
@ -1024,12 +1067,13 @@ static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace5 *iface,
struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface); struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface);
D2D1_POINT_2F *origins, baseline_origin = { 0 }; D2D1_POINT_2F *origins, baseline_origin = { 0 };
struct dwrite_outline outline, outline_size; struct dwrite_outline outline, outline_size;
struct get_glyph_outline_params params;
D2D1_BEZIER_SEGMENT segment; D2D1_BEZIER_SEGMENT segment;
D2D1_POINT_2F point; D2D1_POINT_2F point;
DWRITE_GLYPH_RUN run; DWRITE_GLYPH_RUN run;
unsigned int i, j, p; unsigned int i, j, p;
NTSTATUS status;
HRESULT hr; HRESULT hr;
int ret;
TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface, emSize, glyphs, advances, offsets, TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface, emSize, glyphs, advances, offsets,
count, is_sideways, is_rtl, sink); 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_size, 0, sizeof(outline_size));
memset(&outline, 0, sizeof(outline)); 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) for (i = 0; i < count; ++i)
{ {
outline.tags.count = outline.points.count = 0; outline.tags.count = outline.points.count = 0;
EnterCriticalSection(&fontface->cs); 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, &params)))
{ {
dwrite_array_reserve((void **)&outline.tags.values, &outline.tags.size, outline_size.tags.count, dwrite_array_reserve((void **)&outline.tags.values, &outline.tags.size, outline_size.tags.count,
sizeof(*outline.tags.values)); sizeof(*outline.tags.values));
dwrite_array_reserve((void **)&outline.points.values, &outline.points.size, outline_size.points.count, dwrite_array_reserve((void **)&outline.points.values, &outline.points.size, outline_size.points.count,
sizeof(*outline.points.values)); sizeof(*outline.points.values));
if ((ret = font_funcs->get_glyph_outline(fontface->get_font_object(fontface), emSize, fontface->simulations, params.outline = &outline;
glyphs[i], &outline))) if ((status = UNIX_CALL(get_glyph_outline, &params)))
{ {
WARN("Failed to get glyph outline for glyph %u.\n", glyphs[i]); WARN("Failed to get glyph outline for glyph %u.\n", glyphs[i]);
} }
} }
LeaveCriticalSection(&fontface->cs); LeaveCriticalSection(&fontface->cs);
if (ret) if (status)
continue; continue;
for (j = 0, p = 0; j < outline.tags.count; ++j) 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; 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; const void *data_ptr;
void *data_context; void *data_context;
UINT64 size;
if (!fontface->font_object && SUCCEEDED(IDWriteFontFileStream_GetFileSize(fontface->stream, &size))) if (!fontface->font_object && SUCCEEDED(IDWriteFontFileStream_GetFileSize(fontface->stream, &size)))
{ {
if (SUCCEEDED(IDWriteFontFileStream_ReadFileFragment(fontface->stream, &data_ptr, 0, size, &data_context))) 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"); WARN("Backend failed to create font object.\n");
IDWriteFontFileStream_ReleaseFileFragment(fontface->stream, data_context); IDWriteFontFileStream_ReleaseFileFragment(fontface->stream, data_context);
return NULL; return 0;
} }
if (InterlockedCompareExchangePointer((void **)&fontface->font_object, font_object, NULL)) if (InterlockedCompareExchange64((LONGLONG *)&fontface->font_object, font_object, 0))
font_funcs->release_font_object(font_object); {
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; BYTE *src = glyph_bitmap.buf, *dst;
int x, y, width, height; int x, y, width, height;
BOOL is_1bpp; unsigned int is_1bpp;
glyph_bitmap.glyph = analysis->run.glyphIndices[i]; glyph_bitmap.glyph = analysis->run.glyphIndices[i];
dwrite_fontface_get_glyph_bbox(analysis->run.fontFace, &glyph_bitmap); 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); glyph_bitmap.pitch = get_glyph_bitmap_pitch(analysis->rendering_mode, width);
memset(src, 0, height * glyph_bitmap.pitch); memset(src, 0, height * glyph_bitmap.pitch);
if (FAILED(dwrite_fontface_get_glyph_bitmap(fontface, analysis->rendering_mode, &is_1bpp, &glyph_bitmap))) 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); 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; 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);
}

View File

@ -40,6 +40,7 @@
#define WIN32_NO_STATUS #define WIN32_NO_STATUS
#include "windef.h" #include "windef.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "unixlib.h"
#include "dwrite_private.h" #include "dwrite_private.h"
@ -88,6 +89,8 @@ MAKE_FUNCPTR(FT_Set_Pixel_Sizes);
#undef MAKE_FUNCPTR #undef MAKE_FUNCPTR
static FT_Error (*pFT_Outline_EmboldenXY)(FT_Outline *, FT_Pos, FT_Pos); 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) static FT_Size freetype_set_face_size(FT_Face face, FT_UInt emsize)
{ {
FT_Size size; 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; 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; FT_Version_t FT_Version;
@ -118,7 +121,7 @@ static BOOL init_freetype(void)
if (!ft_handle) if (!ft_handle)
{ {
WINE_MESSAGE("Wine cannot find the FreeType font library.\n"); 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;} #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 #undef LOAD_FUNCPTR
pFT_Outline_EmboldenXY = dlsym(ft_handle, "FT_Outline_EmboldenXY"); 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"); ERR("Can't init FreeType library\n");
dlclose(ft_handle); dlclose(ft_handle);
ft_handle = NULL; ft_handle = NULL;
return FALSE; return STATUS_UNSUCCESSFUL;
} }
pFT_Library_Version(library, &FT_Version.major, &FT_Version.minor, &FT_Version.patch); 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); 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: sym_not_found:
WINE_MESSAGE("Wine cannot find certain functions that it needs from FreeType library.\n"); WINE_MESSAGE("Wine cannot find certain functions that it needs from FreeType library.\n");
dlclose(ft_handle); dlclose(ft_handle);
ft_handle = NULL; 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_Face face = NULL;
FT_Error fterror; 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) if (fterror != FT_Err_Ok)
{
WARN("Failed to create a face object, error %d.\n", fterror); 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, static NTSTATUS get_design_glyph_metrics(void *args)
unsigned int simulations, UINT16 glyph, DWRITE_GLYPH_METRICS *ret)
{ {
FT_Face face = object; struct get_design_glyph_metrics_params *params = args;
FT_Face face = FaceFromObject(params->object);
FT_Size size; FT_Size size;
if (!(size = freetype_set_face_size(face, upem))) if (!(size = freetype_set_face_size(face, params->upem)))
return; 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; FT_Glyph_Metrics *metrics = &face->glyph->metrics;
ret->leftSideBearing = metrics->horiBearingX; params->metrics->leftSideBearing = metrics->horiBearingX;
ret->advanceWidth = metrics->horiAdvance; params->metrics->advanceWidth = metrics->horiAdvance;
ret->rightSideBearing = metrics->horiAdvance - metrics->horiBearingX - metrics->width; params->metrics->rightSideBearing = metrics->horiAdvance - metrics->horiBearingX - metrics->width;
ret->advanceHeight = metrics->vertAdvance; params->metrics->advanceHeight = metrics->vertAdvance;
ret->verticalOriginY = ascent; params->metrics->verticalOriginY = params->ascent;
ret->topSideBearing = ascent - metrics->horiBearingY; params->metrics->topSideBearing = params->ascent - metrics->horiBearingY;
ret->bottomSideBearing = metrics->vertAdvance - metrics->height - ret->topSideBearing; params->metrics->bottomSideBearing = metrics->vertAdvance - metrics->height - params->metrics->topSideBearing;
/* Adjust in case of bold simulation, glyphs without contours are ignored. */ /* 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) if (params->metrics->advanceWidth)
ret->advanceWidth += (upem + 49) / 50; params->metrics->advanceWidth += (params->upem + 49) / 50;
} }
} }
pFT_Done_Size(size); pFT_Done_Size(size);
return STATUS_SUCCESS;
} }
struct decompose_context struct decompose_context
@ -425,52 +445,55 @@ static void embolden_glyph(FT_Glyph glyph, FLOAT emsize)
embolden_glyph_outline(&outline_glyph->outline, emsize); embolden_glyph_outline(&outline_glyph->outline, emsize);
} }
static int CDECL freetype_get_glyph_outline(font_object_handle object, float emsize, unsigned int simulations, static NTSTATUS get_glyph_outline(void *args)
UINT16 glyph, struct dwrite_outline *outline)
{ {
FT_Face face = object; struct get_glyph_outline_params *params = args;
FT_Face face = FaceFromObject(params->object);
FT_Size size; FT_Size size;
int ret = 0;
if (!(size = freetype_set_face_size(face, emsize))) if (!(size = freetype_set_face_size(face, params->emsize)))
return 0; 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_Outline *ft_outline = &face->glyph->outline;
FT_Matrix m; FT_Matrix m;
if (outline->points.values) if (params->outline->points.values)
{ {
if (simulations & DWRITE_FONT_SIMULATIONS_BOLD) if (params->simulations & DWRITE_FONT_SIMULATIONS_BOLD)
embolden_glyph_outline(ft_outline, emsize); embolden_glyph_outline(ft_outline, params->emsize);
m.xx = 1 << 16; 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.yx = 0;
m.yy = -(1 << 16); /* flip Y axis */ m.yy = -(1 << 16); /* flip Y axis */
pFT_Outline_Transform(ft_outline, &m); pFT_Outline_Transform(ft_outline, &m);
ret = decompose_outline(ft_outline, outline); decompose_outline(ft_outline, params->outline);
} }
else else
{ {
/* Intentionally overestimate numbers to keep it simple. */ /* Intentionally overestimate numbers to keep it simple. */
outline->points.count = ft_outline->n_points * 3; params->outline->points.count = ft_outline->n_points * 3;
outline->tags.count = ft_outline->n_points + ft_outline->n_contours * 2; params->outline->tags.count = ft_outline->n_points + ft_outline->n_contours * 2;
} }
} }
pFT_Done_Size(size); 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; struct get_glyph_count_params *params = args;
return face ? face->num_glyphs : 0; 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) 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; 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->xx = 1 << 16;
ret->xy = 0; 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. /* Some fonts provide mostly bitmaps and very few outlines, for example for .notdef.
Disable transform if that's the case. */ Disable transform if that's the case. */
if (!bitmap->m && !bitmap->simulations) if (!memcmp(m, &identity, sizeof(*m)) && !simulations)
return FALSE; return FALSE;
if (bitmap->simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) { if (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE)
m.xx = 1 << 16; {
m.xy = (1 << 16) / 3; ftm.xx = 1 << 16;
m.yx = 0; ftm.xy = (1 << 16) / 3;
m.yy = 1 << 16; ftm.yx = 0;
pFT_Matrix_Multiply(&m, ret); ftm.yy = 1 << 16;
pFT_Matrix_Multiply(&ftm, ret);
} }
if (bitmap->m) { ft_matrix_from_dwrite_matrix(m, &ftm);
ft_matrix_from_dwrite_matrix(bitmap->m, &m); pFT_Matrix_Multiply(&ftm, ret);
pFT_Matrix_Multiply(&m, ret);
}
return TRUE; 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_Glyph glyph = NULL;
FT_BBox bbox = { 0 }; FT_BBox bbox = { 0 };
BOOL needs_transform; BOOL needs_transform;
FT_Matrix m; FT_Matrix m;
FT_Size size; FT_Size size;
SetRectEmpty(&bitmap->bbox); SetRectEmpty(params->bbox);
if (!(size = freetype_set_face_size(face, bitmap->emsize))) if (!(size = freetype_set_face_size(face, params->emsize)))
return; 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, &params->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); pFT_Done_Size(size);
return; return STATUS_UNSUCCESSFUL;
} }
pFT_Get_Glyph(face->glyph, &glyph); pFT_Get_Glyph(face->glyph, &glyph);
if (needs_transform) if (needs_transform)
{ {
if (bitmap->simulations & DWRITE_FONT_SIMULATIONS_BOLD) if (params->simulations & DWRITE_FONT_SIMULATIONS_BOLD)
embolden_glyph(glyph, bitmap->emsize); embolden_glyph(glyph, params->emsize);
/* Includes oblique and user transform. */ /* Includes oblique and user transform. */
pFT_Glyph_Transform(glyph, &m, NULL); 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); pFT_Done_Size(size);
/* flip Y axis */ /* 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 = &params->bbox;
int width = bbox->right - bbox->left; int width = bbox->right - bbox->left;
int height = bbox->bottom - bbox->top; int height = bbox->bottom - bbox->top;
*params->is_1bpp = 1;
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph; FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph;
const FT_Outline *src = &outline->outline; 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.width = width;
ft_bitmap.rows = height; ft_bitmap.rows = height;
ft_bitmap.pitch = bitmap->pitch; ft_bitmap.pitch = params->pitch;
ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO; 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. */ /* Note: FreeType will only set 'black' bits for us. */
if (pFT_Outline_New(library, src->n_points, src->n_contours, &copy) == 0) { if (pFT_Outline_New(library, src->n_points, src->n_contours, &copy) == 0) {
@ -580,28 +607,29 @@ static BOOL freetype_get_aliased_glyph_bitmap(struct dwrite_glyphbitmap *bitmap,
} }
else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap; FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap;
BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf; BYTE *src = ft_bitmap->buffer, *dst = params->bitmap;
int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3); int w = min(params->pitch, (ft_bitmap->width + 7) >> 3);
int h = min(height, ft_bitmap->rows); int h = min(height, ft_bitmap->rows);
while (h--) { while (h--) {
memcpy(dst, src, w); memcpy(dst, src, w);
src += ft_bitmap->pitch; src += ft_bitmap->pitch;
dst += bitmap->pitch; dst += params->pitch;
} }
} }
else else
FIXME("format %x not handled\n", glyph->format); 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 = &params->bbox;
int width = bbox->right - bbox->left; int width = bbox->right - bbox->left;
int height = bbox->bottom - bbox->top; int height = bbox->bottom - bbox->top;
BOOL ret = FALSE;
*params->is_1bpp = 0;
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph; 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.width = width;
ft_bitmap.rows = height; ft_bitmap.rows = height;
ft_bitmap.pitch = bitmap->pitch; ft_bitmap.pitch = params->pitch;
ft_bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; 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. */ /* Note: FreeType will only set 'black' bits for us. */
if (pFT_Outline_New(library, src->n_points, src->n_contours, &copy) == 0) { if (pFT_Outline_New(library, src->n_points, src->n_contours, &copy) == 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) { else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap; FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap;
BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf; BYTE *src = ft_bitmap->buffer, *dst = params->bitmap;
int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3); int w = min(params->pitch, (ft_bitmap->width + 7) >> 3);
int h = min(height, ft_bitmap->rows); int h = min(height, ft_bitmap->rows);
while (h--) { while (h--) {
memcpy(dst, src, w); memcpy(dst, src, w);
src += ft_bitmap->pitch; src += ft_bitmap->pitch;
dst += bitmap->pitch; dst += params->pitch;
} }
ret = TRUE; *params->is_1bpp = 1;
} }
else else
{
FIXME("format %x not handled\n", glyph->format); 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 needs_transform;
BOOL ret = FALSE; BOOL ret = FALSE;
FT_Glyph glyph; FT_Glyph glyph;
FT_Size size; FT_Size size;
FT_Matrix m; FT_Matrix m;
if (!(size = freetype_set_face_size(face, bitmap->emsize))) *params->is_1bpp = 0;
return FALSE;
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, &params->m, &m);
if (!pFT_Load_Glyph(face, params->glyph, needs_transform ? FT_LOAD_NO_BITMAP : 0))
{ {
pFT_Get_Glyph(face->glyph, &glyph); pFT_Get_Glyph(face->glyph, &glyph);
if (needs_transform) if (needs_transform)
{ {
if (bitmap->simulations & DWRITE_FONT_SIMULATIONS_BOLD) if (params->simulations & DWRITE_FONT_SIMULATIONS_BOLD)
embolden_glyph(glyph, bitmap->emsize); embolden_glyph(glyph, params->emsize);
/* Includes oblique and user transform. */ /* Includes oblique and user transform. */
pFT_Glyph_Transform(glyph, &m, NULL); pFT_Glyph_Transform(glyph, &m, NULL);
} }
if (bitmap->aliased) if (params->mode == DWRITE_RENDERING_MODE1_ALIASED)
ret = freetype_get_aliased_glyph_bitmap(bitmap, glyph); ret = freetype_get_aliased_glyph_bitmap(params, glyph);
else else
ret = freetype_get_aa_glyph_bitmap(bitmap, glyph); ret = freetype_get_aa_glyph_bitmap(params, glyph);
pFT_Done_Glyph(glyph); pFT_Done_Glyph(glyph);
} }
@ -683,128 +717,100 @@ static BOOL CDECL freetype_get_glyph_bitmap(font_object_handle object, struct dw
return ret; return ret;
} }
static INT32 CDECL freetype_get_glyph_advance(font_object_handle object, float emsize, UINT16 glyph, static NTSTATUS get_glyph_advance(void *args)
DWRITE_MEASURING_MODE mode, BOOL *has_contours)
{ {
FT_Face face = object; struct get_glyph_advance_params *params = args;
INT32 advance = 0; FT_Face face = FaceFromObject(params->object);
FT_Size size; FT_Size size;
*has_contours = FALSE; *params->advance = 0;
*params->has_contours = FALSE;
if (!(size = freetype_set_face_size(face, emsize))) if (!(size = freetype_set_face_size(face, params->emsize)))
return 0; 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; *params->advance = face->glyph->advance.x >> 6;
*has_contours = freetype_glyph_has_contours(face); *params->has_contours = freetype_glyph_has_contours(face);
} }
pFT_Done_Size(size); 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; return STATUS_SUCCESS;
} }
#else /* HAVE_FREETYPE */ #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, static NTSTATUS create_font_object(void *args)
UINT16 glyph, struct dwrite_outline *outline)
{ {
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, static NTSTATUS get_glyph_outline(void *args)
DWRITE_MEASURING_MODE mode, BOOL *has_contours)
{ {
*has_contours = FALSE; return STATUS_NOT_IMPLEMENTED;
return 0;
} }
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, static NTSTATUS get_glyph_bbox(void *args)
UINT16 glyph, DWRITE_GLYPH_METRICS *metrics)
{ {
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, return STATUS_NOT_IMPLEMENTED;
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;
} }
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 */ #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) process_attach,
return init_freetype_lib(module, reason, ptr_in, ptr_out); process_detach,
else if (reason == DLL_PROCESS_DETACH) create_font_object,
return release_freetype_lib(); release_font_object,
return STATUS_SUCCESS; get_glyph_outline,
} get_glyph_count,
get_glyph_advance,
get_glyph_bbox,
get_glyph_bitmap,
get_design_glyph_metrics,
};

View File

@ -30,11 +30,13 @@
#include "initguid.h" #include "initguid.h"
#include "dwrite_private.h" #include "dwrite_private.h"
#include "unixlib.h"
#include "wine/debug.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dwrite); WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
HMODULE dwrite_module = 0; HMODULE dwrite_module = 0;
unixlib_handle_t unixlib_handle = 0;
static IDWriteFactory7 *shared_factory; static IDWriteFactory7 *shared_factory;
static void release_shared_factory(IDWriteFactory7 *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: case DLL_PROCESS_ATTACH:
dwrite_module = hinstDLL; dwrite_module = hinstDLL;
DisableThreadLibraryCalls( 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(); init_local_fontfile_loader();
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
if (reserved) break; if (reserved) break;
release_shared_factory(shared_factory); release_shared_factory(shared_factory);
release_font_backend(); if (unixlib_handle) UNIX_CALL(process_detach, NULL);
} }
return TRUE; return TRUE;
} }

113
dlls/dwrite/unixlib.h Normal file
View File

@ -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 <stdarg.h>
#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 )