dwrite: Implement GetMetrics() for IDWriteFont
Nikolay Sivov
nsivov at codeweavers.com
Tue Oct 16 03:13:31 CDT 2012
Implement GetMetrics() for IDWriteFont
-------------- next part --------------
>From 5b9bc3dda98ae657926365905387d06a496bb3cb Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Tue, 16 Oct 2012 09:37:20 -0400
Subject: [PATCH 3/3] Implement GetMetrics() for IDWriteFont
---
dlls/dwrite/font.c | 69 ++++++++++++++++++++++++++++++++++++++++++++--
dlls/dwrite/tests/font.c | 60 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 127 insertions(+), 2 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index d145df0..90131b8 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -31,6 +31,40 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
#include "pshpack2.h"
typedef struct
{
+ ULONG version;
+ ULONG revision;
+ ULONG checksumadj;
+ ULONG magic;
+ USHORT flags;
+ USHORT unitsPerEm;
+ ULONGLONG created;
+ ULONGLONG modified;
+ SHORT xMin;
+ SHORT yMin;
+ SHORT xMax;
+ SHORT yMax;
+ USHORT macStyle;
+ USHORT lowestRecPPEM;
+ SHORT direction_hint;
+ SHORT index_format;
+ SHORT glyphdata_format;
+} TT_HEAD;
+
+typedef struct
+{
+ ULONG Version;
+ ULONG italicAngle;
+ SHORT underlinePosition;
+ SHORT underlineThickness;
+ ULONG fixed_pitch;
+ ULONG minmemType42;
+ ULONG maxmemType42;
+ ULONG minmemType1;
+ ULONG maxmemType1;
+} TT_POST;
+
+typedef struct
+{
USHORT version;
SHORT xAvgCharWidth;
USHORT usWeightClass;
@@ -88,7 +122,10 @@ typedef struct
#define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
-#define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
+
+#define MS_HEAD_TAG MS_MAKE_TAG('h','e','a','d')
+#define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
+#define MS_POST_TAG MS_MAKE_TAG('p','o','s','t')
struct dwrite_fontfamily {
IDWriteFontFamily IDWriteFontFamily_iface;
@@ -106,6 +143,7 @@ struct dwrite_font {
DWRITE_FONT_STYLE style;
DWRITE_FONT_STRETCH stretch;
DWRITE_FONT_WEIGHT weight;
+ DWRITE_FONT_METRICS metrics;
};
struct dwrite_fontface {
@@ -423,7 +461,9 @@ static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *ifa
static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
{
struct dwrite_font *This = impl_from_IDWriteFont(iface);
- FIXME("(%p)->(%p): stub\n", This, metrics);
+
+ TRACE("(%p)->(%p)\n", This, metrics);
+ *metrics = This->metrics;
}
static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
@@ -595,12 +635,16 @@ static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **fa
static void get_font_properties(struct dwrite_font *font, HDC hdc)
{
TT_OS2_V2 tt_os2;
+ TT_HEAD tt_head;
+ TT_POST tt_post;
LONG size;
/* default stretch and weight to normal */
font->stretch = DWRITE_FONT_STRETCH_NORMAL;
font->weight = DWRITE_FONT_WEIGHT_NORMAL;
+ memset(&font->metrics, 0, sizeof(font->metrics));
+
size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
if (size != GDI_ERROR)
{
@@ -615,6 +659,27 @@ static void get_font_properties(struct dwrite_font *font, HDC hdc)
font->weight = GET_BE_WORD(tt_os2.usWeightClass);
TRACE("stretch=%d, weight=%d\n", font->stretch, font->weight);
+
+ font->metrics.ascent = GET_BE_WORD(tt_os2.sTypoAscender);
+ font->metrics.descent = GET_BE_WORD(tt_os2.sTypoDescender);
+ font->metrics.lineGap = GET_BE_WORD(tt_os2.sTypoLineGap);
+ font->metrics.capHeight = GET_BE_WORD(tt_os2.sCapHeight);
+ font->metrics.xHeight = GET_BE_WORD(tt_os2.sxHeight);
+ font->metrics.strikethroughPosition = GET_BE_WORD(tt_os2.yStrikeoutPosition);
+ font->metrics.strikethroughThickness = GET_BE_WORD(tt_os2.yStrikeoutSize);
+ }
+
+ memset(&tt_head, 0, sizeof(tt_head));
+ if (GetFontData(hdc, MS_HEAD_TAG, 0, &tt_head, sizeof(tt_head)) != GDI_ERROR)
+ {
+ font->metrics.designUnitsPerEm = GET_BE_WORD(tt_head.unitsPerEm);
+ }
+
+ memset(&tt_post, 0, sizeof(tt_post));
+ if (GetFontData(hdc, MS_POST_TAG, 0, &tt_post, sizeof(tt_post)) != GDI_ERROR)
+ {
+ font->metrics.underlinePosition = GET_BE_WORD(tt_post.underlinePosition);
+ font->metrics.underlineThickness = GET_BE_WORD(tt_post.underlineThickness);
}
}
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 83c19da..74d82be 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -452,6 +452,65 @@ if (0) /* crashes on native */
IDWriteGdiInterop_Release(interop);
}
+static void test_GetMetrics(void)
+{
+ static const WCHAR arialW[] = {'A','r','i','a','l',0};
+ IDWriteGdiInterop *interop;
+ DWRITE_FONT_METRICS metrics;
+ OUTLINETEXTMETRICW otm;
+ IDWriteFont *font;
+ LOGFONTW logfont;
+ HRESULT hr;
+ HDC hdc;
+ HFONT hfont;
+ int ret;
+
+ hr = IDWriteFactory_GetGdiInterop(factory, &interop);
+ EXPECT_HR(hr, S_OK);
+
+ memset(&logfont, 0, sizeof(logfont));
+ logfont.lfHeight = 12;
+ logfont.lfWidth = 12;
+ logfont.lfWeight = FW_NORMAL;
+ logfont.lfItalic = 1;
+ lstrcpyW(logfont.lfFaceName, arialW);
+
+ hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hfont = CreateFontIndirectW(&logfont);
+ hdc = CreateCompatibleDC(0);
+ SelectObject(hdc, hfont);
+
+ otm.otmSize = sizeof(otm);
+ ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
+ ok(ret, "got %d\n", ret);
+ DeleteDC(hdc);
+ DeleteObject(hfont);
+
+if (0) /* crashes on native */
+ IDWriteFont_GetMetrics(font, NULL);
+
+ memset(&metrics, 0, sizeof(metrics));
+ IDWriteFont_GetMetrics(font, &metrics);
+
+ ok(metrics.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics.designUnitsPerEm);
+ ok(metrics.ascent != 0, "ascent %u\n", metrics.ascent);
+ ok(metrics.descent != 0, "descent %u\n", metrics.descent);
+ ok(metrics.lineGap > 0, "lineGap %d\n", metrics.lineGap);
+ if (otm.otmsCapEmHeight)
+ ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
+ if (otm.otmsXHeight)
+ ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
+ ok(metrics.underlinePosition < 0, "underlinePosition %d\n", metrics.underlinePosition);
+ ok(metrics.underlineThickness != 0, "underlineThickness %u\n", metrics.underlineThickness);
+ ok(metrics.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics.strikethroughPosition);
+ ok(metrics.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics.strikethroughThickness);
+
+ IDWriteFont_Release(font);
+ IDWriteGdiInterop_Release(interop);
+}
+
START_TEST(font)
{
HRESULT hr;
@@ -469,6 +528,7 @@ START_TEST(font)
test_GetFontFamily();
test_GetFamilyNames();
test_CreateFontFace();
+ test_GetMetrics();
IDWriteFactory_Release(factory);
}
--
1.7.10.4
More information about the wine-patches
mailing list