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
IMPORTLIB = dwrite
UNIXLIB = dwrite.so
IMPORTS = user32 gdi32 advapi32
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;
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;

View File

@ -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, &params);
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, &params);
}
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, &params);
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(&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)))
{
@ -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, &params);
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, &params);
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, &params);
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, &params);
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, &params)))
{
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, &params)))
{
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);
}

View File

@ -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, &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);
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 = &params->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, &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) {
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 = &params->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, &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) {
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, &params->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,
};

View File

@ -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;
}

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 )