diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 0353a2d1e6..ce7aad50e6 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -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; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index c949687dac..ca586ea01d 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -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; diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index 7b3fb1f0d7..aabc0491eb 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -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) diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index c3cad684c6..6bea28880e 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -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); }