dwrite: Fix lineGap metric using 'hhea' table values.

This commit is contained in:
Nikolay Sivov 2014-11-28 09:23:51 +03:00 committed by Alexandre Julliard
parent 188bfd6fd4
commit 82e66b4b47
4 changed files with 64 additions and 28 deletions

View File

@ -116,7 +116,7 @@ extern HRESULT opentype_get_font_table(IDWriteFontFileStream*,DWRITE_FONT_FACE_T
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(const void*,const void*,const void*,DWRITE_FONT_METRICS1*) DECLSPEC_HIDDEN;
extern void opentype_get_font_metrics(IDWriteFontFileStream*,DWRITE_FONT_FACE_TYPE,UINT32,DWRITE_FONT_METRICS1*) DECLSPEC_HIDDEN;
extern HRESULT opentype_get_font_strings_from_id(const void*,DWRITE_INFORMATIONAL_STRING_ID,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
/* BiDi helpers */

View File

@ -28,7 +28,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
#define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
#define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
#define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
#define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
#define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
@ -584,29 +583,26 @@ static void get_font_properties_from_stream(IDWriteFontFileStream *stream, DWRIT
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, *tt_post = NULL;
void *os2_context, *head_context, *post_context;
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);
opentype_get_font_table(stream, face_type, face_index, MS_POST_TAG, &tt_post, &post_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(tt_os2, tt_head, tt_post, metrics);
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);
if (tt_post)
IDWriteFontFileStream_ReleaseFileFragment(stream, post_context);
}
HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
@ -1458,8 +1454,8 @@ static HRESULT get_filestream_from_file(IDWriteFontFile *file, IDWriteFontFileSt
static HRESULT init_font_data(IDWriteFactory *factory, IDWriteFontFile *file, UINT32 face_index, DWRITE_FONT_FACE_TYPE face_type, struct dwrite_font_data *data)
{
void *os2_context, *head_context, *post_context;
const void *tt_os2 = NULL, *tt_head = NULL, *tt_post = NULL;
void *os2_context, *head_context;
const void *tt_os2 = NULL, *tt_head = NULL;
IDWriteFontFileStream *stream;
HRESULT hr;
@ -1476,17 +1472,14 @@ static HRESULT init_font_data(IDWriteFactory *factory, IDWriteFontFile *file, UI
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_table(stream, face_type, face_index, MS_POST_TAG, &tt_post, &post_context, NULL, NULL);
opentype_get_font_properties(tt_os2, tt_head, &data->stretch, &data->weight, &data->style);
opentype_get_font_metrics(tt_os2, tt_head, tt_post, &data->metrics);
opentype_get_font_metrics(stream, face_type, face_index, &data->metrics);
if (tt_os2)
IDWriteFontFileStream_ReleaseFileFragment(stream, os2_context);
if (tt_head)
IDWriteFontFileStream_ReleaseFileFragment(stream, head_context);
if (tt_post)
IDWriteFontFileStream_ReleaseFileFragment(stream, post_context);
IDWriteFontFileStream_Release(stream);
return S_OK;

View File

@ -24,8 +24,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
#define MS_TTCF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','t','c','f')
#define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
#define MS_HHEA_TAG DWRITE_MAKE_OPENTYPE_TAG('h','h','e','a')
#define MS_OTTO_TAG DWRITE_MAKE_OPENTYPE_TAG('O','T','T','O')
#define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
#define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
#define MS_TTCF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','t','c','f')
#ifdef WORDS_BIGENDIAN
#define GET_BE_WORD(x) (x)
@ -183,6 +187,24 @@ typedef struct
USHORT usBreakChar;
USHORT usMaxContext;
} TT_OS2_V2;
typedef struct {
ULONG version;
SHORT ascender;
SHORT descender;
SHORT linegap;
USHORT advanceWidthMax;
SHORT minLeftSideBearing;
SHORT minRightSideBearing;
SHORT xMaxExtent;
SHORT caretSlopeRise;
SHORT caretSlopeRun;
SHORT caretOffset;
SHORT reserved[4];
SHORT metricDataFormat;
USHORT numberOfHMetrics;
} TT_HHEA;
#include "poppack.h"
enum OS2_FSSELECTION {
@ -871,14 +893,22 @@ HRESULT opentype_cmap_get_unicode_ranges(void *data, UINT32 max_count, DWRITE_UN
return *count > max_count ? E_NOT_SUFFICIENT_BUFFER : S_OK;
}
void opentype_get_font_metrics(const void *os2, const void *head, const void *post, DWRITE_FONT_METRICS1 *metrics)
void opentype_get_font_metrics(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_TYPE face_type, UINT32 face_index,
DWRITE_FONT_METRICS1 *metrics)
{
TT_OS2_V2 *tt_os2 = (TT_OS2_V2*)os2;
TT_HEAD *tt_head = (TT_HEAD*)head;
TT_POST *tt_post = (TT_POST*)post;
void *os2_context, *head_context, *post_context, *hhea_context;
const TT_OS2_V2 *tt_os2;
const TT_HEAD *tt_head;
const TT_POST *tt_post;
const TT_HHEA *tt_hhea;
memset(metrics, 0, sizeof(*metrics));
opentype_get_font_table(stream, face_type, face_index, MS_OS2_TAG, (const void**)&tt_os2, &os2_context, NULL, NULL);
opentype_get_font_table(stream, face_type, face_index, MS_HEAD_TAG, (const void**)&tt_head, &head_context, NULL, NULL);
opentype_get_font_table(stream, face_type, face_index, MS_POST_TAG, (const void**)&tt_post, &post_context, NULL, NULL);
opentype_get_font_table(stream, face_type, face_index, MS_HHEA_TAG, (const void**)&tt_hhea, &hhea_context, NULL, NULL);
if (tt_head) {
metrics->designUnitsPerEm = GET_BE_WORD(tt_head->unitsPerEm);
metrics->glyphBoxLeft = GET_BE_WORD(tt_head->xMin);
@ -890,11 +920,19 @@ void opentype_get_font_metrics(const void *os2, const void *head, const void *po
if (tt_os2) {
USHORT version = GET_BE_WORD(tt_os2->version);
metrics->ascent = GET_BE_WORD(tt_os2->usWinAscent);
metrics->descent = GET_BE_WORD(tt_os2->usWinDescent);
/* FIXME: sTypoLineGap should only be used when USE_TYPO_METRICS is set,
if not set this value is probably derived from other metrics */
metrics->lineGap = GET_BE_WORD(tt_os2->sTypoLineGap);
metrics->ascent = GET_BE_WORD(tt_os2->usWinAscent);
metrics->descent = GET_BE_WORD(tt_os2->usWinDescent);
/* line gap is estimated using two sets of ascender/descender values and 'hhea' line gap */
if (tt_hhea) {
SHORT descender = (SHORT)GET_BE_WORD(tt_hhea->descender);
INT32 linegap;
linegap = GET_BE_WORD(tt_hhea->ascender) + abs(descender) + GET_BE_WORD(tt_hhea->linegap) -
metrics->ascent - metrics->descent;
metrics->lineGap = linegap > 0 ? linegap : 0;
}
metrics->strikethroughPosition = GET_BE_WORD(tt_os2->yStrikeoutPosition);
metrics->strikethroughThickness = GET_BE_WORD(tt_os2->yStrikeoutSize);
metrics->subscriptPositionX = GET_BE_WORD(tt_os2->ySubscriptXOffset);
@ -935,6 +973,15 @@ void opentype_get_font_metrics(const void *os2, const void *head, const void *po
metrics->xHeight = metrics->designUnitsPerEm / 2;
if (metrics->capHeight == 0)
metrics->capHeight = metrics->designUnitsPerEm * 7 / 10;
if (tt_os2)
IDWriteFontFileStream_ReleaseFileFragment(stream, os2_context);
if (tt_head)
IDWriteFontFileStream_ReleaseFileFragment(stream, head_context);
if (tt_post)
IDWriteFontFileStream_ReleaseFileFragment(stream, post_context);
if (tt_hhea)
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)

View File

@ -1053,7 +1053,6 @@ if (0) /* crashes on native */
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);
todo_wine
ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
@ -1071,7 +1070,6 @@ todo_wine
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);
todo_wine
ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
@ -1091,7 +1089,6 @@ todo_wine
ok(metrics1.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics1.designUnitsPerEm);
ok(metrics1.ascent != 0, "ascent %u\n", metrics1.ascent);
ok(metrics1.descent != 0, "descent %u\n", metrics1.descent);
todo_wine
ok(metrics1.lineGap == 0, "lineGap %d\n", metrics1.lineGap);
ok(metrics1.capHeight, "capHeight %u\n", metrics1.capHeight);
ok(metrics1.xHeight != 0, "xHeight %u\n", metrics1.xHeight);
@ -1120,7 +1117,6 @@ todo_wine
ok(metrics1.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics1.designUnitsPerEm);
ok(metrics1.ascent != 0, "ascent %u\n", metrics1.ascent);
ok(metrics1.descent != 0, "descent %u\n", metrics1.descent);
todo_wine
ok(metrics1.lineGap == 0, "lineGap %d\n", metrics1.lineGap);
ok(metrics1.capHeight, "capHeight %u\n", metrics1.capHeight);
ok(metrics1.xHeight != 0, "xHeight %u\n", metrics1.xHeight);