dwrite: Implement GetAlphaTextureBounds().

This commit is contained in:
Nikolay Sivov 2015-07-29 11:59:02 +03:00 committed by Alexandre Julliard
parent 2c6eca8682
commit b50416aa5f
5 changed files with 103 additions and 18 deletions

View File

@ -124,7 +124,7 @@ extern HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *refer
extern HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface) DECLSPEC_HIDDEN;
extern HRESULT create_fontface(DWRITE_FONT_FACE_TYPE,UINT32,IDWriteFontFile* const*,UINT32,DWRITE_FONT_SIMULATIONS,IDWriteFontFace2**) DECLSPEC_HIDDEN;
extern HRESULT create_font_collection(IDWriteFactory2*,IDWriteFontFileEnumerator*,BOOL,IDWriteFontCollection**) DECLSPEC_HIDDEN;
extern HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE,DWRITE_GLYPH_RUN const*,IDWriteGlyphRunAnalysis**) DECLSPEC_HIDDEN;
extern HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE,DWRITE_GLYPH_RUN const*,FLOAT,IDWriteGlyphRunAnalysis**) DECLSPEC_HIDDEN;
extern BOOL is_system_collection(IDWriteFontCollection*) DECLSPEC_HIDDEN;
extern HRESULT get_local_refkey(const WCHAR*,const FILETIME*,void**,UINT32*) DECLSPEC_HIDDEN;
extern HRESULT get_filestream_from_file(IDWriteFontFile*,IDWriteFontFileStream**) DECLSPEC_HIDDEN;
@ -188,6 +188,7 @@ extern UINT16 freetype_get_glyphcount(IDWriteFontFace2*) DECLSPEC_HIDDEN;
extern UINT16 freetype_get_glyphindex(IDWriteFontFace2*,UINT32) DECLSPEC_HIDDEN;
extern BOOL freetype_has_kerning_pairs(IDWriteFontFace2*) DECLSPEC_HIDDEN;
extern INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2*,UINT16,UINT16) DECLSPEC_HIDDEN;
extern void freetype_get_glyph_bbox(IDWriteFontFace2*,FLOAT,UINT16,BOOL,RECT*) DECLSPEC_HIDDEN;
/* Glyph shaping */
enum SCRIPT_JUSTIFY

View File

@ -106,15 +106,22 @@ struct dwrite_fonttable {
BOOL exists;
};
enum runanalysis_readystate {
RUNANALYSIS_BOUNDS = 1 << 0,
};
struct dwrite_glyphrunanalysis {
IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface;
LONG ref;
DWRITE_RENDERING_MODE rendering_mode;
DWRITE_GLYPH_RUN run;
FLOAT ppdip;
UINT16 *glyphs;
FLOAT *advances;
DWRITE_GLYPH_OFFSET *offsets;
RECT bounds;
UINT8 ready;
};
#define GLYPH_BLOCK_SHIFT 8
@ -2904,11 +2911,16 @@ static ULONG WINAPI glyphrunanalysis_Release(IDWriteGlyphRunAnalysis *iface)
return ref;
}
static HRESULT WINAPI glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis *iface, DWRITE_TEXTURE_TYPE type, RECT* bounds)
static HRESULT WINAPI glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis *iface, DWRITE_TEXTURE_TYPE type, RECT *bounds)
{
struct dwrite_glyphrunanalysis *This = impl_from_IDWriteGlyphRunAnalysis(iface);
IDWriteFontFace2 *fontface2;
BOOL nohint, is_rtl;
FLOAT origin_x;
HRESULT hr;
UINT32 i;
FIXME("(%p)->(%d %p): stub\n", This, type, bounds);
TRACE("(%p)->(%d %p)\n", This, type, bounds);
if ((UINT32)type > DWRITE_TEXTURE_CLEARTYPE_3x1) {
memset(bounds, 0, sizeof(*bounds));
@ -2921,7 +2933,46 @@ static HRESULT WINAPI glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnal
return S_OK;
}
return E_NOTIMPL;
if (This->ready & RUNANALYSIS_BOUNDS) {
*bounds = This->bounds;
return S_OK;
}
if (This->run.isSideways)
FIXME("sideways runs are not supported.\n");
hr = IDWriteFontFace_QueryInterface(This->run.fontFace, &IID_IDWriteFontFace2, (void**)&fontface2);
if (FAILED(hr))
WARN("failed to get IDWriteFontFace2, 0x%08x\n", hr);
nohint = This->rendering_mode == DWRITE_RENDERING_MODE_NATURAL || This->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
/* Start with empty bounds at (0,0) origin, returned bounds are not translated back to (0,0), e.g. for
RTL run negative left bound is returned, same goes for vertical direction - top bound will be negative
for any non-zero glyph ascender */
origin_x = 0.0;
is_rtl = This->run.bidiLevel & 1;
for (i = 0; i < This->run.glyphCount; i++) {
const DWRITE_GLYPH_OFFSET *offset = &This->offsets[i];
FLOAT advance = This->advances[i];
RECT bbox;
freetype_get_glyph_bbox(fontface2, This->run.fontEmSize * This->ppdip, This->run.glyphIndices[i], nohint, &bbox);
if (is_rtl)
OffsetRect(&bbox, origin_x - offset->advanceOffset - advance, -offset->ascenderOffset);
else
OffsetRect(&bbox, origin_x + offset->advanceOffset, offset->ascenderOffset);
UnionRect(&This->bounds, &This->bounds, &bbox);
origin_x += is_rtl ? -advance : advance;
}
IDWriteFontFace2_Release(fontface2);
This->ready |= RUNANALYSIS_BOUNDS;
*bounds = This->bounds;
return S_OK;
}
static HRESULT WINAPI glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis *iface, DWRITE_TEXTURE_TYPE type,
@ -2977,7 +3028,7 @@ static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl = {
glyphrunanalysis_GetAlphaBlendParams
};
HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_GLYPH_RUN const *run, IDWriteGlyphRunAnalysis **ret)
HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_GLYPH_RUN const *run, FLOAT ppdip, IDWriteGlyphRunAnalysis **ret)
{
struct dwrite_glyphrunanalysis *analysis;
@ -2994,6 +3045,9 @@ HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_GLY
analysis->IDWriteGlyphRunAnalysis_iface.lpVtbl = &glyphrunanalysisvtbl;
analysis->ref = 1;
analysis->rendering_mode = rendering_mode;
analysis->ready = 0;
analysis->ppdip = ppdip;
SetRectEmpty(&analysis->bounds);
analysis->run = *run;
IDWriteFontFace_AddRef(analysis->run.fontFace);
analysis->glyphs = heap_alloc(run->glyphCount*sizeof(*run->glyphIndices));

View File

@ -1,7 +1,7 @@
/*
* FreeType integration
*
* Copyright 2014 Nikolay Sivov for CodeWeavers
* Copyright 2014-2015 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
@ -54,6 +54,7 @@ static void *ft_handle = NULL;
static FT_Library library = 0;
static FTC_Manager cache_manager = 0;
static FTC_CMapCache cmap_cache = 0;
static FTC_ImageCache image_cache = 0;
typedef struct
{
FT_Int major;
@ -64,6 +65,7 @@ typedef struct
#define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
MAKE_FUNCPTR(FT_Done_FreeType);
MAKE_FUNCPTR(FT_Get_Kerning);
MAKE_FUNCPTR(FT_Glyph_Get_CBox);
MAKE_FUNCPTR(FT_Init_FreeType);
MAKE_FUNCPTR(FT_Library_Version);
MAKE_FUNCPTR(FT_Load_Glyph);
@ -71,6 +73,8 @@ MAKE_FUNCPTR(FT_New_Memory_Face);
MAKE_FUNCPTR(FT_Outline_Transform);
MAKE_FUNCPTR(FTC_CMapCache_Lookup);
MAKE_FUNCPTR(FTC_CMapCache_New);
MAKE_FUNCPTR(FTC_ImageCache_Lookup);
MAKE_FUNCPTR(FTC_ImageCache_New);
MAKE_FUNCPTR(FTC_Manager_New);
MAKE_FUNCPTR(FTC_Manager_Done);
MAKE_FUNCPTR(FTC_Manager_LookupFace);
@ -137,6 +141,7 @@ BOOL init_freetype(void)
#define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(ft_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;}
LOAD_FUNCPTR(FT_Done_FreeType)
LOAD_FUNCPTR(FT_Get_Kerning)
LOAD_FUNCPTR(FT_Glyph_Get_CBox)
LOAD_FUNCPTR(FT_Init_FreeType)
LOAD_FUNCPTR(FT_Library_Version)
LOAD_FUNCPTR(FT_Load_Glyph)
@ -144,6 +149,8 @@ BOOL init_freetype(void)
LOAD_FUNCPTR(FT_Outline_Transform)
LOAD_FUNCPTR(FTC_CMapCache_Lookup)
LOAD_FUNCPTR(FTC_CMapCache_New)
LOAD_FUNCPTR(FTC_ImageCache_Lookup)
LOAD_FUNCPTR(FTC_ImageCache_New)
LOAD_FUNCPTR(FTC_Manager_New)
LOAD_FUNCPTR(FTC_Manager_Done)
LOAD_FUNCPTR(FTC_Manager_LookupFace)
@ -161,7 +168,8 @@ BOOL init_freetype(void)
/* init cache manager */
if (pFTC_Manager_New(library, 0, 0, 0, &face_requester, NULL, &cache_manager) != 0 ||
pFTC_CMapCache_New(cache_manager, &cmap_cache) != 0) {
pFTC_CMapCache_New(cache_manager, &cmap_cache) != 0 ||
pFTC_ImageCache_New(cache_manager, &image_cache) != 0) {
ERR("Failed to init FreeType cache\n");
pFTC_Manager_Done(cache_manager);
@ -456,6 +464,29 @@ INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2 *fontface, UINT16 le
return adjustment;
}
void freetype_get_glyph_bbox(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, BOOL nohint, RECT *ret)
{
FTC_ImageTypeRec imagetype;
FT_BBox bbox = { 0 };
FT_Glyph glyph;
imagetype.face_id = fontface;
imagetype.width = 0;
imagetype.height = emSize;
imagetype.flags = nohint ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
EnterCriticalSection(&freetype_cs);
if (pFTC_ImageCache_Lookup(image_cache, &imagetype, index, &glyph, NULL) == 0)
pFT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox);
LeaveCriticalSection(&freetype_cs);
/* flip Y axis */
ret->left = bbox.xMin;
ret->right = bbox.xMax;
ret->top = -bbox.yMax;
ret->bottom = -bbox.yMin;
}
#else /* HAVE_FREETYPE */
BOOL init_freetype(void)
@ -507,4 +538,9 @@ INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2 *fontface, UINT16 le
return 0;
}
void freetype_get_glyph_bbox(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, BOOL nohint, RECT *ret)
{
ret->left = ret->right = ret->top = ret->bottom = 0;
}
#endif /* HAVE_FREETYPE */

View File

@ -1076,10 +1076,10 @@ static HRESULT WINAPI dwritefactory_CreateGlyphRunAnalysis(IDWriteFactory2 *ifac
{
struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
TRACE("(%p)->(%p %f %p %d %d %f %f %p)\n", This, run, ppdip, transform, rendering_mode,
TRACE("(%p)->(%p %.2f %p %d %d %f %f %p)\n", This, run, ppdip, transform, rendering_mode,
measuring_mode, baseline_x, baseline_y, analysis);
return create_glyphrunanalysis(rendering_mode, run, analysis);
return create_glyphrunanalysis(rendering_mode, run, ppdip, analysis);
}
static HRESULT WINAPI dwritefactory1_GetEudcFontCollection(IDWriteFactory2 *iface, IDWriteFontCollection **collection,

View File

@ -3500,10 +3500,9 @@ static void test_CreateGlyphRunAnalysis(void)
if (rendermodes[i] == DWRITE_RENDERING_MODE_ALIASED) {
memset(&rect, 0, sizeof(rect));
hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
todo_wine {
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(!IsRectEmpty(&rect), "got empty rect\n");
}
rect.left = rect.top = 0;
rect.bottom = rect.right = 1;
hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
@ -3519,11 +3518,9 @@ static void test_CreateGlyphRunAnalysis(void)
memset(&rect, 0, sizeof(rect));
hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
todo_wine {
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(!IsRectEmpty(&rect), "got empty rect\n");
}
}
IDWriteGlyphRunAnalysis_Release(analysis);
}
@ -3542,10 +3539,7 @@ static void test_CreateGlyphRunAnalysis(void)
memset(&rect, 0, sizeof(rect));
hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, DWRITE_TEXTURE_ALIASED_1x1, &rect);
todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr != S_OK)
break;
hr = IDWriteFontFace_GetGdiCompatibleGlyphMetrics(run.fontFace, run.fontEmSize, 1.0, NULL,
DWRITE_MEASURING_MODE_GDI_CLASSIC, run.glyphIndices, 1, &gm, run.isSideways);
@ -3557,8 +3551,8 @@ static void test_CreateGlyphRunAnalysis(void)
rect.right -= rect.left;
rect.bottom -= rect.top;
ok(abs(bboxX - rect.right) <= 1, "%.0f: bbox width %d, from metrics %d\n", run.fontEmSize, rect.right, bboxX);
ok(abs(bboxY - rect.bottom) <= 1, "%.0f: bbox height %d, from metrics %d\n", run.fontEmSize, rect.bottom, bboxY);
ok(abs(bboxX - rect.right) <= 2, "%.0f: bbox width %d, from metrics %d\n", run.fontEmSize, rect.right, bboxX);
ok(abs(bboxY - rect.bottom) <= 2, "%.0f: bbox height %d, from metrics %d\n", run.fontEmSize, rect.bottom, bboxY);
IDWriteGlyphRunAnalysis_Release(analysis);
}