dwrite: Implement GetRecommendedRenderingMode().
This commit is contained in:
parent
aac3a069e4
commit
e877cfbcfa
|
@ -148,6 +148,15 @@ extern HRESULT opentype_get_font_strings_from_id(const void*,DWRITE_INFORMATIONA
|
|||
extern HRESULT opentype_get_typographic_features(IDWriteFontFace*,UINT32,UINT32,UINT32,UINT32*,DWRITE_FONT_FEATURE_TAG*) DECLSPEC_HIDDEN;
|
||||
extern BOOL opentype_get_vdmx_size(const void*,INT,UINT16*,UINT16*) DECLSPEC_HIDDEN;
|
||||
|
||||
enum gasp_flags {
|
||||
GASP_GRIDFIT = 0x0001,
|
||||
GASP_DOGRAY = 0x0002,
|
||||
GASP_SYMMETRIC_GRIDFIT = 0x0004,
|
||||
GASP_SYMMETRIC_SMOOTHING = 0x0008,
|
||||
};
|
||||
|
||||
extern WORD opentype_get_gasp_flags(const WORD*,UINT32,INT) DECLSPEC_HIDDEN;
|
||||
|
||||
/* BiDi helpers */
|
||||
extern HRESULT bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*) DECLSPEC_HIDDEN;
|
||||
extern WCHAR bidi_get_mirrored_char(WCHAR) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -32,9 +32,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
|
|||
#define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
|
||||
#define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
|
||||
#define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
|
||||
#define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
|
||||
|
||||
static const IID IID_issystemcollection = {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
|
||||
|
||||
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;
|
||||
|
||||
struct dwrite_font_data {
|
||||
LONG ref;
|
||||
|
||||
|
@ -129,6 +134,7 @@ struct dwrite_fontface {
|
|||
|
||||
struct dwrite_fonttable cmap;
|
||||
struct dwrite_fonttable vdmx;
|
||||
struct dwrite_fonttable gasp;
|
||||
DWRITE_GLYPH_METRICS *glyphs[GLYPH_MAX/GLYPH_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
|
@ -230,6 +236,13 @@ static inline void* get_fontface_vdmx(struct dwrite_fontface *fontface)
|
|||
return get_fontface_table(fontface, MS_VDMX_TAG, &fontface->vdmx);
|
||||
}
|
||||
|
||||
static inline void* get_fontface_gasp(struct dwrite_fontface *fontface, UINT32 *size)
|
||||
{
|
||||
void *ptr = get_fontface_table(fontface, MS_GASP_TAG, &fontface->gasp);
|
||||
*size = fontface->gasp.size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void release_font_data(struct dwrite_font_data *data)
|
||||
{
|
||||
int i;
|
||||
|
@ -304,6 +317,8 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace2 *iface)
|
|||
IDWriteFontFace2_ReleaseFontTable(iface, This->cmap.context);
|
||||
if (This->vdmx.context)
|
||||
IDWriteFontFace2_ReleaseFontTable(iface, This->vdmx.context);
|
||||
if (This->gasp.context)
|
||||
IDWriteFontFace2_ReleaseFontTable(iface, This->gasp.context);
|
||||
for (i = 0; i < This->file_count; i++) {
|
||||
if (This->streams[i])
|
||||
IDWriteFontFileStream_Release(This->streams[i]);
|
||||
|
@ -585,12 +600,64 @@ static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace2 *iface,
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static DWRITE_RENDERING_MODE fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring,
|
||||
FLOAT ppem, WORD gasp)
|
||||
{
|
||||
DWRITE_RENDERING_MODE mode = DWRITE_RENDERING_MODE_DEFAULT;
|
||||
|
||||
switch (measuring)
|
||||
{
|
||||
case DWRITE_MEASURING_MODE_NATURAL:
|
||||
{
|
||||
if (!(gasp & GASP_SYMMETRIC_SMOOTHING) && (ppem <= RECOMMENDED_NATURAL_PPEM))
|
||||
mode = DWRITE_RENDERING_MODE_NATURAL;
|
||||
else
|
||||
mode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
|
||||
break;
|
||||
}
|
||||
case DWRITE_MEASURING_MODE_GDI_CLASSIC:
|
||||
mode = DWRITE_RENDERING_MODE_GDI_CLASSIC;
|
||||
break;
|
||||
case DWRITE_MEASURING_MODE_GDI_NATURAL:
|
||||
mode = DWRITE_RENDERING_MODE_GDI_NATURAL;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT emSize,
|
||||
FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
|
||||
FLOAT ppdip, DWRITE_MEASURING_MODE measuring, IDWriteRenderingParams *params, DWRITE_RENDERING_MODE *mode)
|
||||
{
|
||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
|
||||
FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
|
||||
return E_NOTIMPL;
|
||||
WORD gasp, *ptr;
|
||||
UINT32 size;
|
||||
FLOAT ppem;
|
||||
|
||||
TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This, emSize, ppdip, measuring, params, mode);
|
||||
|
||||
if (!params) {
|
||||
*mode = DWRITE_RENDERING_MODE_DEFAULT;
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*mode = IDWriteRenderingParams_GetRenderingMode(params);
|
||||
if (*mode != DWRITE_RENDERING_MODE_DEFAULT)
|
||||
return S_OK;
|
||||
|
||||
ppem = emSize * ppdip;
|
||||
|
||||
if (ppem >= RECOMMENDED_OUTLINE_AA_THRESHOLD) {
|
||||
*mode = DWRITE_RENDERING_MODE_OUTLINE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ptr = get_fontface_gasp(This, &size);
|
||||
gasp = opentype_get_gasp_flags(ptr, size, ppem);
|
||||
*mode = fontface_renderingmode_from_measuringmode(measuring, ppem, gasp);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace2 *iface, FLOAT emSize, FLOAT pixels_per_dip,
|
||||
|
@ -832,10 +899,7 @@ static HRESULT WINAPI dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFac
|
|||
FLOAT font_emsize, FLOAT dpiX, FLOAT dpiY, const DWRITE_MATRIX *transform, BOOL is_sideways,
|
||||
DWRITE_OUTLINE_THRESHOLD threshold, DWRITE_MEASURING_MODE measuring_mode, DWRITE_RENDERING_MODE *rendering_mode)
|
||||
{
|
||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
|
||||
DWRITE_GRID_FIT_MODE gridfitmode;
|
||||
TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p)\n", This, font_emsize, dpiX, dpiY, transform, is_sideways,
|
||||
threshold, measuring_mode, rendering_mode);
|
||||
return IDWriteFontFace2_GetRecommendedRenderingMode(iface, font_emsize, dpiX, dpiY, transform, is_sideways,
|
||||
threshold, measuring_mode, NULL, rendering_mode, &gridfitmode);
|
||||
}
|
||||
|
@ -884,15 +948,63 @@ static HRESULT WINAPI dwritefontface2_GetPaletteEntries(IDWriteFontFace2 *iface,
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT fontEmSize,
|
||||
FLOAT dpiX, FLOAT dpiY, DWRITE_MATRIX const *transform, BOOL is_sideways, DWRITE_OUTLINE_THRESHOLD threshold,
|
||||
static HRESULT WINAPI dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT emSize,
|
||||
FLOAT dpiX, FLOAT dpiY, DWRITE_MATRIX const *m, BOOL is_sideways, DWRITE_OUTLINE_THRESHOLD threshold,
|
||||
DWRITE_MEASURING_MODE measuringmode, IDWriteRenderingParams *params, DWRITE_RENDERING_MODE *renderingmode,
|
||||
DWRITE_GRID_FIT_MODE *gridfitmode)
|
||||
{
|
||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
|
||||
FIXME("(%p)->(%f %f %f %p %d %d %d %p %p %p): stub\n", This, fontEmSize, dpiX, dpiY, transform, is_sideways, threshold,
|
||||
FLOAT emthreshold;
|
||||
WORD gasp, *ptr;
|
||||
UINT32 size;
|
||||
|
||||
TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This, emSize, dpiX, dpiY, m, is_sideways, threshold,
|
||||
measuringmode, params, renderingmode, gridfitmode);
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (m)
|
||||
FIXME("transform not supported %s\n", debugstr_matrix(m));
|
||||
|
||||
if (is_sideways)
|
||||
FIXME("sideways mode not supported\n");
|
||||
|
||||
*renderingmode = DWRITE_RENDERING_MODE_DEFAULT;
|
||||
*gridfitmode = DWRITE_GRID_FIT_MODE_DEFAULT;
|
||||
if (params) {
|
||||
IDWriteRenderingParams2 *params2;
|
||||
HRESULT hr;
|
||||
|
||||
hr = IDWriteRenderingParams_QueryInterface(params, &IID_IDWriteRenderingParams2, (void**)¶ms2);
|
||||
if (hr == S_OK) {
|
||||
*renderingmode = IDWriteRenderingParams2_GetRenderingMode(params2);
|
||||
*gridfitmode = IDWriteRenderingParams2_GetGridFitMode(params2);
|
||||
IDWriteRenderingParams2_Release(params2);
|
||||
}
|
||||
else
|
||||
*renderingmode = IDWriteRenderingParams_GetRenderingMode(params);
|
||||
}
|
||||
|
||||
emthreshold = threshold == DWRITE_OUTLINE_THRESHOLD_ANTIALIASED ? RECOMMENDED_OUTLINE_AA_THRESHOLD : RECOMMENDED_OUTLINE_A_THRESHOLD;
|
||||
|
||||
ptr = get_fontface_gasp(This, &size);
|
||||
gasp = opentype_get_gasp_flags(ptr, size, emSize);
|
||||
|
||||
if (*renderingmode == DWRITE_RENDERING_MODE_DEFAULT) {
|
||||
if (emSize >= emthreshold)
|
||||
*renderingmode = DWRITE_RENDERING_MODE_OUTLINE;
|
||||
else
|
||||
*renderingmode = fontface_renderingmode_from_measuringmode(measuringmode, emSize, gasp);
|
||||
}
|
||||
|
||||
if (*gridfitmode == DWRITE_GRID_FIT_MODE_DEFAULT) {
|
||||
if (emSize >= emthreshold)
|
||||
*gridfitmode = DWRITE_GRID_FIT_MODE_DISABLED;
|
||||
else if (measuringmode == DWRITE_MEASURING_MODE_GDI_CLASSIC || measuringmode == DWRITE_MEASURING_MODE_GDI_NATURAL)
|
||||
*gridfitmode = DWRITE_GRID_FIT_MODE_ENABLED;
|
||||
else
|
||||
*gridfitmode = (gasp & (GASP_GRIDFIT|GASP_SYMMETRIC_GRIDFIT)) ? DWRITE_GRID_FIT_MODE_ENABLED : DWRITE_GRID_FIT_MODE_DISABLED;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const IDWriteFontFace2Vtbl dwritefontfacevtbl = {
|
||||
|
@ -2344,8 +2456,10 @@ HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDW
|
|||
fontface->file_count = files_number;
|
||||
memset(&fontface->cmap, 0, sizeof(fontface->cmap));
|
||||
memset(&fontface->vdmx, 0, sizeof(fontface->vdmx));
|
||||
memset(&fontface->gasp, 0, sizeof(fontface->gasp));
|
||||
fontface->cmap.exists = TRUE;
|
||||
fontface->vdmx.exists = TRUE;
|
||||
fontface->gasp.exists = TRUE;
|
||||
fontface->index = index;
|
||||
fontface->simulations = simulations;
|
||||
memset(fontface->glyphs, 0, sizeof(fontface->glyphs));
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define COBJMACROS
|
||||
|
||||
#include "dwrite_private.h"
|
||||
#include "winternl.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
|
||||
|
||||
|
@ -37,8 +38,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
|
|||
#define GET_BE_WORD(x) (x)
|
||||
#define GET_BE_DWORD(x) (x)
|
||||
#else
|
||||
#define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
|
||||
#define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)))
|
||||
#define GET_BE_WORD(x) RtlUshortByteSwap(x)
|
||||
#define GET_BE_DWORD(x) RtlUlongByteSwap(x)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
|
@ -1377,3 +1378,28 @@ BOOL opentype_get_vdmx_size(const void *data, INT emsize, UINT16 *ascent, UINT16
|
|||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WORD opentype_get_gasp_flags(const WORD *ptr, UINT32 size, INT emsize)
|
||||
{
|
||||
WORD num_recs, version;
|
||||
WORD flags = 0;
|
||||
|
||||
if (!ptr)
|
||||
return 0;
|
||||
|
||||
version = GET_BE_WORD( *ptr++ );
|
||||
num_recs = GET_BE_WORD( *ptr++ );
|
||||
if (version > 1 || size < (num_recs * 2 + 2) * sizeof(WORD)) {
|
||||
ERR("unsupported gasp table: ver %d size %d recs %d\n", version, size, num_recs);
|
||||
goto done;
|
||||
}
|
||||
|
||||
while (num_recs--) {
|
||||
flags = GET_BE_WORD( *(ptr + 1) );
|
||||
if (emsize <= GET_BE_WORD( *ptr )) break;
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
done:
|
||||
return flags;
|
||||
}
|
||||
|
|
|
@ -4238,10 +4238,9 @@ if (0) /* crashes on native */
|
|||
mode = 10;
|
||||
hr = IDWriteFontFace_GetRecommendedRenderingMode(fontface, 3.0, 1.0,
|
||||
DWRITE_MEASURING_MODE_GDI_CLASSIC, NULL, &mode);
|
||||
todo_wine {
|
||||
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
|
||||
ok(mode == DWRITE_RENDERING_MODE_DEFAULT, "got %d\n", mode);
|
||||
}
|
||||
|
||||
hr = IDWriteFactory_CreateRenderingParams(factory, ¶ms);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
|
@ -4251,24 +4250,16 @@ todo_wine {
|
|||
for (emsize = 1.0; emsize < 500.0; emsize += 1.0) {
|
||||
WORD gasp = get_gasp_flags(fontface, emsize);
|
||||
DWRITE_RENDERING_MODE expected;
|
||||
int i, skiptest = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(recmode_tests)/sizeof(recmode_tests[0]); i++) {
|
||||
mode = 10;
|
||||
expected = get_expected_rendering_mode(emsize, gasp, recmode_tests[i].measuring, recmode_tests[i].threshold);
|
||||
hr = IDWriteFontFace_GetRecommendedRenderingMode(fontface, emsize, 1.0, recmode_tests[i].measuring, params, &mode);
|
||||
todo_wine
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
if (hr != S_OK) {
|
||||
skiptest = 1;
|
||||
break;
|
||||
}
|
||||
ok(mode == expected, "%.2f/%d: got %d, flags 0x%04x, expected %d\n", emsize, i, mode, gasp, expected);
|
||||
}
|
||||
|
||||
if (skiptest)
|
||||
break;
|
||||
|
||||
/* IDWriteFontFace1 offers another variant of this method */
|
||||
if (fontface1) {
|
||||
for (i = 0; i < sizeof(recmode_tests1)/sizeof(recmode_tests1[0]); i++) {
|
||||
|
@ -4308,10 +4299,9 @@ todo_wine {
|
|||
|
||||
mode = 10;
|
||||
hr = IDWriteFontFace_GetRecommendedRenderingMode(fontface, 500.0, 1.0, DWRITE_MEASURING_MODE_NATURAL, params, &mode);
|
||||
todo_wine {
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(mode == DWRITE_RENDERING_MODE_GDI_CLASSIC, "got %d\n", mode);
|
||||
}
|
||||
|
||||
IDWriteRenderingParams_Release(params);
|
||||
|
||||
if (fontface2) {
|
||||
|
@ -4326,16 +4316,24 @@ todo_wine {
|
|||
DWRITE_RENDERING_MODE_OUTLINE, DWRITE_GRID_FIT_MODE_ENABLED, ¶ms2);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
mode = 10;
|
||||
gridfit = 10;
|
||||
hr = IDWriteFontFace2_GetRecommendedRenderingMode(fontface2, 5.0, 96.0, 96.0,
|
||||
NULL, FALSE, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED, DWRITE_MEASURING_MODE_GDI_CLASSIC,
|
||||
NULL, &mode, &gridfit);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(mode == DWRITE_RENDERING_MODE_GDI_CLASSIC, "got %d\n", mode);
|
||||
ok(gridfit == DWRITE_GRID_FIT_MODE_ENABLED, "got %d\n", gridfit);
|
||||
|
||||
mode = 10;
|
||||
gridfit = 10;
|
||||
hr = IDWriteFontFace2_GetRecommendedRenderingMode(fontface2, 5.0, 96.0, 96.0,
|
||||
NULL, FALSE, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED, DWRITE_MEASURING_MODE_GDI_CLASSIC,
|
||||
(IDWriteRenderingParams*)params2, &mode, &gridfit);
|
||||
todo_wine {
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(mode == DWRITE_RENDERING_MODE_OUTLINE, "got %d\n", mode);
|
||||
ok(gridfit == DWRITE_GRID_FIT_MODE_ENABLED, "got %d\n", gridfit);
|
||||
}
|
||||
|
||||
IDWriteRenderingParams2_Release(params2);
|
||||
IDWriteFactory2_Release(factory2);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue