dwrite: Implement GetCaretMetrics().

This commit is contained in:
Nikolay Sivov 2015-02-03 13:27:24 +03:00 committed by Alexandre Julliard
parent fbeb829584
commit 8f9bca9103
4 changed files with 139 additions and 56 deletions

View File

@ -127,8 +127,9 @@ extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,UINT32*,DWRITE_FONT_
extern HRESULT opentype_get_font_table(IDWriteFontFileStream*,DWRITE_FONT_FACE_TYPE,UINT32,UINT32,const void**,void**,UINT32*,BOOL*) DECLSPEC_HIDDEN;
extern void opentype_cmap_get_glyphindex(void*,UINT32,UINT16*) DECLSPEC_HIDDEN;
extern HRESULT opentype_cmap_get_unicode_ranges(void*,UINT32,DWRITE_UNICODE_RANGE*,UINT32*) DECLSPEC_HIDDEN;
extern void opentype_get_font_properties(const void*,const void*,DWRITE_FONT_STRETCH*,DWRITE_FONT_WEIGHT*,DWRITE_FONT_STYLE*) DECLSPEC_HIDDEN;
extern void opentype_get_font_metrics(IDWriteFontFileStream*,DWRITE_FONT_FACE_TYPE,UINT32,DWRITE_FONT_METRICS1*) DECLSPEC_HIDDEN;
extern void opentype_get_font_properties(IDWriteFontFileStream*,DWRITE_FONT_FACE_TYPE,UINT32,DWRITE_FONT_STRETCH*,
DWRITE_FONT_WEIGHT*,DWRITE_FONT_STYLE*) DECLSPEC_HIDDEN;
extern void opentype_get_font_metrics(IDWriteFontFileStream*,DWRITE_FONT_FACE_TYPE,UINT32,DWRITE_FONT_METRICS1*,DWRITE_CARET_METRICS*) DECLSPEC_HIDDEN;
extern HRESULT opentype_get_font_strings_from_id(const void*,DWRITE_INFORMATIONAL_STRING_ID,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
extern HRESULT opentype_get_typographic_features(IDWriteFontFace*,UINT32,UINT32,UINT32,UINT32*,DWRITE_FONT_FEATURE_TAG*) DECLSPEC_HIDDEN;

View File

@ -114,6 +114,7 @@ struct dwrite_fontface {
USHORT simulations;
DWRITE_FONT_FACE_TYPE type;
DWRITE_FONT_METRICS1 metrics;
DWRITE_CARET_METRICS caret;
struct dwrite_fonttable cmap;
DWRITE_GLYPH_METRICS *glyphs[GLYPH_MAX/GLYPH_BLOCK_SIZE];
@ -597,7 +598,8 @@ static HRESULT WINAPI dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace2 *
static void WINAPI dwritefontface1_GetCaretMetrics(IDWriteFontFace2 *iface, DWRITE_CARET_METRICS *metrics)
{
struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
FIXME("(%p)->(%p): stub\n", This, metrics);
TRACE("(%p)->(%p)\n", This, metrics);
*metrics = This->caret;
}
static HRESULT WINAPI dwritefontface1_GetUnicodeRanges(IDWriteFontFace2 *iface, UINT32 max_count,
@ -771,38 +773,11 @@ static const IDWriteFontFace2Vtbl dwritefontfacevtbl = {
dwritefontface2_GetRecommendedRenderingMode
};
static void get_font_properties_from_stream(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_TYPE face_type,
UINT32 face_index, DWRITE_FONT_METRICS1 *metrics, DWRITE_FONT_STRETCH *stretch, DWRITE_FONT_WEIGHT *weight,
DWRITE_FONT_STYLE *style)
{
const void *tt_os2 = NULL, *tt_head = NULL;
void *os2_context, *head_context;
DWRITE_FONT_STRETCH fontstretch;
DWRITE_FONT_WEIGHT fontweight;
DWRITE_FONT_STYLE fontstyle;
opentype_get_font_table(stream, face_type, face_index, MS_OS2_TAG, &tt_os2, &os2_context, NULL, NULL);
opentype_get_font_table(stream, face_type, face_index, MS_HEAD_TAG, &tt_head, &head_context, NULL, NULL);
if (!stretch) stretch = &fontstretch;
if (!weight) weight = &fontweight;
if (!style) style = &fontstyle;
opentype_get_font_properties(tt_os2, tt_head, stretch, weight, style);
opentype_get_font_metrics(stream, face_type, face_index, metrics);
if (tt_os2)
IDWriteFontFileStream_ReleaseFileFragment(stream, os2_context);
if (tt_head)
IDWriteFontFileStream_ReleaseFileFragment(stream, head_context);
}
HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
{
DWRITE_FONT_SIMULATIONS simulations;
DWRITE_FONT_FACE_TYPE face_type;
IDWriteFontFileStream *stream;
DWRITE_FONT_METRICS1 metrics;
DWRITE_FONT_STRETCH stretch;
DWRITE_FONT_STYLE style;
DWRITE_FONT_WEIGHT weight;
@ -825,7 +800,7 @@ HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
index = IDWriteFontFace_GetIndex(face);
face_type = IDWriteFontFace_GetType(face);
get_font_properties_from_stream(stream, face_type, index, &metrics, &stretch, &weight, &style);
opentype_get_font_properties(stream, face_type, index, &stretch, &weight, &style);
IDWriteFontFileStream_Release(stream);
simulations = IDWriteFontFace_GetSimulations(face);
@ -1670,8 +1645,8 @@ static HRESULT init_font_data(IDWriteFactory2 *factory, IDWriteFontFile *file, U
opentype_get_font_table(stream, face_type, face_index, MS_OS2_TAG, &tt_os2, &os2_context, NULL, NULL);
opentype_get_font_table(stream, face_type, face_index, MS_HEAD_TAG, &tt_head, &head_context, NULL, NULL);
opentype_get_font_properties(tt_os2, tt_head, &data->stretch, &data->weight, &data->style);
opentype_get_font_metrics(stream, face_type, face_index, &data->metrics);
opentype_get_font_properties(stream, face_type, face_index, &data->stretch, &data->weight, &data->style);
opentype_get_font_metrics(stream, face_type, face_index, &data->metrics, NULL);
if (tt_os2)
IDWriteFontFileStream_ReleaseFileFragment(stream, os2_context);
@ -2216,7 +2191,14 @@ HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDW
IDWriteFontFile_AddRef(font_files[i]);
}
get_font_properties_from_stream(fontface->streams[0], facetype, index, &fontface->metrics, NULL, NULL, NULL);
opentype_get_font_metrics(fontface->streams[0], facetype, index, &fontface->metrics, &fontface->caret);
if (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) {
/* TODO: test what happens if caret is already slanted */
if (fontface->caret.slopeRise == 1) {
fontface->caret.slopeRise = fontface->metrics.designUnitsPerEm;
fontface->caret.slopeRun = fontface->caret.slopeRise / 3;
}
}
*ret = &fontface->IDWriteFontFace2_iface;
return S_OK;

View File

@ -950,7 +950,7 @@ HRESULT opentype_cmap_get_unicode_ranges(void *data, UINT32 max_count, DWRITE_UN
}
void opentype_get_font_metrics(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_TYPE face_type, UINT32 face_index,
DWRITE_FONT_METRICS1 *metrics)
DWRITE_FONT_METRICS1 *metrics, DWRITE_CARET_METRICS *caret)
{
void *os2_context, *head_context, *post_context, *hhea_context;
const TT_OS2_V2 *tt_os2;
@ -973,6 +973,19 @@ void opentype_get_font_metrics(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_T
metrics->glyphBoxBottom = GET_BE_WORD(tt_head->yMin);
}
if (caret) {
if (tt_hhea) {
caret->slopeRise = GET_BE_WORD(tt_hhea->caretSlopeRise);
caret->slopeRun = GET_BE_WORD(tt_hhea->caretSlopeRun);
caret->offset = GET_BE_WORD(tt_hhea->caretOffset);
}
else {
caret->slopeRise = 0;
caret->slopeRun = 0;
caret->offset = 0;
}
}
if (tt_os2) {
USHORT version = GET_BE_WORD(tt_os2->version);
@ -1040,10 +1053,15 @@ void opentype_get_font_metrics(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_T
IDWriteFontFileStream_ReleaseFileFragment(stream, hhea_context);
}
void opentype_get_font_properties(const void *os2, const void *head, DWRITE_FONT_STRETCH *stretch, DWRITE_FONT_WEIGHT *weight, DWRITE_FONT_STYLE *style)
void opentype_get_font_properties(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_TYPE type, UINT32 index,
DWRITE_FONT_STRETCH *stretch, DWRITE_FONT_WEIGHT *weight, DWRITE_FONT_STYLE *style)
{
TT_OS2_V2 *tt_os2 = (TT_OS2_V2*)os2;
TT_HEAD *tt_head = (TT_HEAD*)head;
void *os2_context, *head_context;
const TT_OS2_V2 *tt_os2;
const TT_HEAD *tt_head;
opentype_get_font_table(stream, type, index, MS_OS2_TAG, (const void**)&tt_os2, &os2_context, NULL, NULL);
opentype_get_font_table(stream, type, index, MS_HEAD_TAG, (const void**)&tt_head, &head_context, NULL, NULL);
/* default stretch, weight and style to normal */
*stretch = DWRITE_FONT_STRETCH_NORMAL;
@ -1064,6 +1082,11 @@ void opentype_get_font_properties(const void *os2, const void *head, DWRITE_FONT
if (macStyle & 0x0002)
*style = DWRITE_FONT_STYLE_ITALIC;
}
if (tt_os2)
IDWriteFontFileStream_ReleaseFileFragment(stream, os2_context);
if (tt_head)
IDWriteFontFileStream_ReleaseFileFragment(stream, head_context);
}
static UINT get_name_record_codepage(enum OPENTYPE_PLATFORM_ID platform, USHORT encoding)

View File

@ -2074,19 +2074,15 @@ static void test_GetFontFromFontFace(void)
IDWriteFactory_Release(factory);
}
static void test_GetFirstMatchingFont(void)
static IDWriteFont *get_tahoma_instance(IDWriteFactory *factory, DWRITE_FONT_STYLE style)
{
DWRITE_FONT_SIMULATIONS simulations;
IDWriteFontCollection *collection;
IDWriteFont *font, *font2;
IDWriteFontFamily *family;
IDWriteFactory *factory;
IDWriteFont *font;
UINT32 index;
BOOL exists;
HRESULT hr;
factory = create_factory();
hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
ok(hr == S_OK, "got 0x%08x\n", hr);
@ -2100,26 +2096,31 @@ static void test_GetFirstMatchingFont(void)
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
DWRITE_FONT_STRETCH_NORMAL, style, &font);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font2);
ok(hr == S_OK, "got 0x%08x\n", hr);
return font;
}
static void test_GetFirstMatchingFont(void)
{
DWRITE_FONT_SIMULATIONS simulations;
IDWriteFont *font, *font2;
IDWriteFactory *factory;
factory = create_factory();
font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
font2 = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
ok(font != font2, "got %p, %p\n", font, font2);
IDWriteFont_Release(font);
IDWriteFont_Release(font2);
hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_ITALIC, &font);
ok(hr == S_OK, "got 0x%08x\n", hr);
font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_ITALIC);
simulations = IDWriteFont_GetSimulations(font);
ok(simulations == DWRITE_FONT_SIMULATIONS_OBLIQUE, "%d\n", simulations);
IDWriteFont_Release(font);
IDWriteFont_Release(font2);
IDWriteFontFamily_Release(family);
IDWriteFontCollection_Release(collection);
IDWriteFactory_Release(factory);
}
@ -2955,6 +2956,81 @@ static void test_GetEudcFontCollection(void)
IDWriteFactory1_Release(factory1);
}
static void test_GetCaretMetrics(void)
{
DWRITE_FONT_METRICS1 metrics;
IDWriteFontFace1 *fontface1;
DWRITE_CARET_METRICS caret;
IDWriteFontFace *fontface;
IDWriteFactory *factory;
IDWriteFontFile *file;
IDWriteFont *font;
HRESULT hr;
create_testfontfile(test_fontfile);
factory = create_factory();
hr = IDWriteFactory_CreateFontFileReference(factory, test_fontfile, NULL, &file);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
ok(hr == S_OK, "got 0x%08x\n", hr);
IDWriteFontFile_Release(file);
hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
IDWriteFontFace_Release(fontface);
if (hr != S_OK) {
win_skip("GetCaretMetrics() is not supported.\n");
IDWriteFactory_Release(factory);
DeleteFileW(test_fontfile);
return;
}
memset(&caret, 0xcc, sizeof(caret));
IDWriteFontFace1_GetCaretMetrics(fontface1, &caret);
ok(caret.slopeRise == 1, "got %d\n", caret.slopeRise);
ok(caret.slopeRun == 0, "got %d\n", caret.slopeRun);
ok(caret.offset == 0, "got %d\n", caret.offset);
IDWriteFontFace1_Release(fontface1);
/* now with Tahoma Normal */
font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
hr = IDWriteFont_CreateFontFace(font, &fontface);
ok(hr == S_OK, "got 0x%08x\n", hr);
IDWriteFont_Release(font);
hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
ok(hr == S_OK, "got 0x%08x\n", hr);
IDWriteFontFace_Release(fontface);
memset(&caret, 0xcc, sizeof(caret));
IDWriteFontFace1_GetCaretMetrics(fontface1, &caret);
ok(caret.slopeRise == 1, "got %d\n", caret.slopeRise);
ok(caret.slopeRun == 0, "got %d\n", caret.slopeRun);
ok(caret.offset == 0, "got %d\n", caret.offset);
IDWriteFontFace1_Release(fontface1);
/* simulated italic */
font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_ITALIC);
hr = IDWriteFont_CreateFontFace(font, &fontface);
ok(hr == S_OK, "got 0x%08x\n", hr);
IDWriteFont_Release(font);
hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
ok(hr == S_OK, "got 0x%08x\n", hr);
IDWriteFontFace_Release(fontface);
IDWriteFontFace1_GetMetrics(fontface1, &metrics);
memset(&caret, 0xcc, sizeof(caret));
IDWriteFontFace1_GetCaretMetrics(fontface1, &caret);
ok(caret.slopeRise == metrics.designUnitsPerEm, "got %d\n", caret.slopeRise);
ok(caret.slopeRun > 0, "got %d\n", caret.slopeRun);
ok(caret.offset == 0, "got %d\n", caret.offset);
IDWriteFontFace1_Release(fontface1);
IDWriteFactory_Release(factory);
DeleteFileW(test_fontfile);
}
START_TEST(font)
{
IDWriteFactory *factory;
@ -2993,6 +3069,7 @@ START_TEST(font)
test_IsMonospacedFont();
test_GetGlyphRunOutline();
test_GetEudcFontCollection();
test_GetCaretMetrics();
IDWriteFactory_Release(factory);
}