From b3c27c4792a64e7b8665b4b53fb658afb2e21988 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 1 Dec 2020 15:15:03 +0300 Subject: [PATCH] dwrite: Use font data access helpers when reading metrics tables. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/dwrite/opentype.c | 200 ++++++++++++++++++++++++------------------------- 1 file changed, 97 insertions(+), 103 deletions(-) diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index d7a0aaf8e51..68da6e4ecfb 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -126,7 +126,7 @@ enum opentype_cmap_table_encoding /* PANOSE is 10 bytes in size, need to pack the structure properly */ #include "pshpack2.h" -typedef struct +struct tt_head { USHORT majorVersion; USHORT minorVersion; @@ -146,9 +146,9 @@ typedef struct SHORT direction_hint; SHORT index_format; SHORT glyphdata_format; -} TT_HEAD; +}; -enum TT_HEAD_MACSTYLE +enum tt_head_macstyle { TT_HEAD_MACSTYLE_BOLD = 1 << 0, TT_HEAD_MACSTYLE_ITALIC = 1 << 1, @@ -159,7 +159,7 @@ enum TT_HEAD_MACSTYLE TT_HEAD_MACSTYLE_EXTENDED = 1 << 6, }; -typedef struct +struct tt_post { ULONG Version; ULONG italicAngle; @@ -170,9 +170,9 @@ typedef struct ULONG maxmemType42; ULONG minmemType1; ULONG maxmemType1; -} TT_POST; +}; -typedef struct +struct tt_os2 { USHORT version; SHORT xAvgCharWidth; @@ -217,9 +217,10 @@ typedef struct USHORT usDefaultChar; USHORT usBreakChar; USHORT usMaxContext; -} TT_OS2_V2; +}; -typedef struct { +struct tt_hhea +{ USHORT majorVersion; USHORT minorVersion; SHORT ascender; @@ -235,7 +236,7 @@ typedef struct { SHORT reserved[4]; SHORT metricDataFormat; USHORT numberOfHMetrics; -} TT_HHEA; +}; struct sbix_header { @@ -1878,31 +1879,25 @@ HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_cmap *cmap, unsigne void opentype_get_font_typo_metrics(struct file_stream_desc *stream_desc, unsigned int *ascent, unsigned int *descent) { struct dwrite_fonttable os2; - const TT_OS2_V2 *data; opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2); - data = (const TT_OS2_V2 *)os2.data; *ascent = *descent = 0; - if (os2.size >= FIELD_OFFSET(TT_OS2_V2, sTypoLineGap)) + if (os2.size >= FIELD_OFFSET(struct tt_os2, sTypoLineGap)) { - SHORT value = GET_BE_WORD(data->sTypoDescender); - *ascent = GET_BE_WORD(data->sTypoAscender); + SHORT value = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoDescender)); + *ascent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoAscender)); *descent = value < 0 ? -value : 0; } - if (data) + if (os2.data) IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, os2.context); } void opentype_get_font_metrics(struct file_stream_desc *stream_desc, DWRITE_FONT_METRICS1 *metrics, DWRITE_CARET_METRICS *caret) { struct dwrite_fonttable os2, head, post, hhea; - 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)); @@ -1911,88 +1906,89 @@ void opentype_get_font_metrics(struct file_stream_desc *stream_desc, DWRITE_FONT opentype_get_font_table(stream_desc, MS_POST_TAG, &post); opentype_get_font_table(stream_desc, MS_HHEA_TAG, &hhea); - tt_head = (const TT_HEAD *)head.data; - tt_os2 = (const TT_OS2_V2 *)os2.data; - tt_post = (const TT_POST *)post.data; - tt_hhea = (const TT_HHEA *)hhea.data; - - if (tt_head) { - metrics->designUnitsPerEm = GET_BE_WORD(tt_head->unitsPerEm); - metrics->glyphBoxLeft = GET_BE_WORD(tt_head->xMin); - metrics->glyphBoxTop = GET_BE_WORD(tt_head->yMax); - metrics->glyphBoxRight = GET_BE_WORD(tt_head->xMax); - metrics->glyphBoxBottom = GET_BE_WORD(tt_head->yMin); + if (head.data) + { + metrics->designUnitsPerEm = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, unitsPerEm)); + metrics->glyphBoxLeft = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, xMin)); + metrics->glyphBoxTop = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, yMax)); + metrics->glyphBoxRight = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, xMax)); + metrics->glyphBoxBottom = table_read_be_word(&head, FIELD_OFFSET(struct 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 (hhea.data) + { + caret->slopeRise = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, caretSlopeRise)); + caret->slopeRun = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, caretSlopeRun)); + caret->offset = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, caretOffset)); } + else + memset(caret, 0, sizeof(*caret)); } - if (tt_os2) { - USHORT version = GET_BE_WORD(tt_os2->version); + if (os2.data) + { + USHORT version = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, version)); - metrics->ascent = GET_BE_WORD(tt_os2->usWinAscent); + metrics->ascent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, usWinAscent)); /* Some fonts have usWinDescent value stored as signed short, which could be wrongly interpreted as large unsigned value. */ - metrics->descent = abs((SHORT)GET_BE_WORD(tt_os2->usWinDescent)); + metrics->descent = abs((SHORT)table_read_be_word(&os2, FIELD_OFFSET(struct 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); + /* Line gap is estimated using two sets of ascender/descender values and 'hhea' line gap. */ + if (hhea.data) + { + SHORT descender = (SHORT)table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, descender)); INT32 linegap; - linegap = GET_BE_WORD(tt_hhea->ascender) + abs(descender) + GET_BE_WORD(tt_hhea->linegap) - - metrics->ascent - metrics->descent; + linegap = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, ascender)) + abs(descender) + + table_read_be_word(&hhea, FIELD_OFFSET(struct 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); + metrics->strikethroughPosition = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, yStrikeoutPosition)); + metrics->strikethroughThickness = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, yStrikeoutSize)); + metrics->subscriptPositionX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptXOffset)); /* Y offset is stored as positive offset below baseline */ - metrics->subscriptPositionY = -GET_BE_WORD(tt_os2->ySubscriptYOffset); - metrics->subscriptSizeX = GET_BE_WORD(tt_os2->ySubscriptXSize); - metrics->subscriptSizeY = GET_BE_WORD(tt_os2->ySubscriptYSize); - metrics->superscriptPositionX = GET_BE_WORD(tt_os2->ySuperscriptXOffset); - metrics->superscriptPositionY = GET_BE_WORD(tt_os2->ySuperscriptYOffset); - metrics->superscriptSizeX = GET_BE_WORD(tt_os2->ySuperscriptXSize); - metrics->superscriptSizeY = GET_BE_WORD(tt_os2->ySuperscriptYSize); + metrics->subscriptPositionY = -table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptYOffset)); + metrics->subscriptSizeX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptXSize)); + metrics->subscriptSizeY = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptYSize)); + metrics->superscriptPositionX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptXOffset)); + metrics->superscriptPositionY = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptYOffset)); + metrics->superscriptSizeX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptXSize)); + metrics->superscriptSizeY = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptYSize)); /* version 2 fields */ - if (version >= 2) { - metrics->capHeight = GET_BE_WORD(tt_os2->sCapHeight); - metrics->xHeight = GET_BE_WORD(tt_os2->sxHeight); + if (version >= 2) + { + metrics->capHeight = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sCapHeight)); + metrics->xHeight = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sxHeight)); } - if (GET_BE_WORD(tt_os2->fsSelection) & OS2_FSSELECTION_USE_TYPO_METRICS) { - SHORT descent = GET_BE_WORD(tt_os2->sTypoDescender); - metrics->ascent = GET_BE_WORD(tt_os2->sTypoAscender); + if (table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, fsSelection)) & OS2_FSSELECTION_USE_TYPO_METRICS) + { + SHORT descent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoDescender)); + metrics->ascent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoAscender)); metrics->descent = descent < 0 ? -descent : 0; - metrics->lineGap = GET_BE_WORD(tt_os2->sTypoLineGap); + metrics->lineGap = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoLineGap)); metrics->hasTypographicMetrics = TRUE; } } - else { + else + { metrics->strikethroughPosition = metrics->designUnitsPerEm / 3; - if (tt_hhea) { - metrics->ascent = GET_BE_WORD(tt_hhea->ascender); - metrics->descent = abs((SHORT)GET_BE_WORD(tt_hhea->descender)); + if (hhea.data) + { + metrics->ascent = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, ascender)); + metrics->descent = abs((SHORT)table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, descender))); } } - if (tt_post) { - metrics->underlinePosition = GET_BE_WORD(tt_post->underlinePosition); - metrics->underlineThickness = GET_BE_WORD(tt_post->underlineThickness); + if (post.data) + { + metrics->underlinePosition = table_read_be_word(&post, FIELD_OFFSET(struct tt_post, underlinePosition)); + metrics->underlineThickness = table_read_be_word(&post, FIELD_OFFSET(struct tt_post, underlineThickness)); } if (metrics->underlineThickness == 0) @@ -2006,13 +2002,13 @@ void opentype_get_font_metrics(struct file_stream_desc *stream_desc, DWRITE_FONT if (metrics->capHeight == 0) metrics->capHeight = metrics->designUnitsPerEm * 7 / 10; - if (tt_os2) + if (os2.data) IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, os2.context); - if (tt_head) + if (head.data) IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, head.context); - if (tt_post) + if (post.data) IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, post.context); - if (tt_hhea) + if (hhea.data) IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, hhea.context); } @@ -2020,15 +2016,10 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d { struct dwrite_fonttable os2, head, colr, cpal; BOOL is_symbol, is_monospaced; - const TT_OS2_V2 *tt_os2; - const TT_HEAD *tt_head; opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2); opentype_get_font_table(stream_desc, MS_HEAD_TAG, &head); - tt_os2 = (const TT_OS2_V2 *)os2.data; - tt_head = (const TT_HEAD *)head.data; - /* default stretch, weight and style to normal */ props->stretch = DWRITE_FONT_STRETCH_NORMAL; props->weight = DWRITE_FONT_WEIGHT_NORMAL; @@ -2039,12 +2030,13 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d props->flags = 0; /* DWRITE_FONT_STRETCH enumeration values directly match font data values */ - if (tt_os2) + if (os2.data) { - USHORT version = GET_BE_WORD(tt_os2->version); - USHORT fsSelection = GET_BE_WORD(tt_os2->fsSelection); - USHORT usWeightClass = GET_BE_WORD(tt_os2->usWeightClass); - USHORT usWidthClass = GET_BE_WORD(tt_os2->usWidthClass); + USHORT version = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, version)); + USHORT fsSelection = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, fsSelection)); + USHORT usWeightClass = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, usWeightClass)); + USHORT usWidthClass = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, usWidthClass)); + const void *panose; if (usWidthClass > DWRITE_FONT_STRETCH_UNDEFINED && usWidthClass <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED) props->stretch = usWidthClass; @@ -2063,22 +2055,24 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d props->style = DWRITE_FONT_STYLE_ITALIC; props->lf.lfItalic = !!(fsSelection & OS2_FSSELECTION_ITALIC); - memcpy(&props->panose, &tt_os2->panose, sizeof(props->panose)); + if ((panose = table_read_ensure(&os2, FIELD_OFFSET(struct tt_os2, panose), sizeof(props->panose)))) + memcpy(&props->panose, panose, sizeof(props->panose)); /* FONTSIGNATURE */ - props->fontsig.fsUsb[0] = GET_BE_DWORD(tt_os2->ulUnicodeRange1); - props->fontsig.fsUsb[1] = GET_BE_DWORD(tt_os2->ulUnicodeRange2); - props->fontsig.fsUsb[2] = GET_BE_DWORD(tt_os2->ulUnicodeRange3); - props->fontsig.fsUsb[3] = GET_BE_DWORD(tt_os2->ulUnicodeRange4); + props->fontsig.fsUsb[0] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange1)); + props->fontsig.fsUsb[1] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange2)); + props->fontsig.fsUsb[2] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange3)); + props->fontsig.fsUsb[3] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange4)); if (version) { - props->fontsig.fsCsb[0] = GET_BE_DWORD(tt_os2->ulCodePageRange1); - props->fontsig.fsCsb[1] = GET_BE_DWORD(tt_os2->ulCodePageRange2); + props->fontsig.fsCsb[0] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulCodePageRange1)); + props->fontsig.fsCsb[1] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulCodePageRange2)); } } - else if (tt_head) { - USHORT macStyle = GET_BE_WORD(tt_head->macStyle); + else if (head.data) + { + USHORT macStyle = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, macStyle)); if (macStyle & TT_HEAD_MACSTYLE_CONDENSED) props->stretch = DWRITE_FONT_STRETCH_CONDENSED; @@ -2137,7 +2131,7 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d if (post.data) { - is_monospaced = !!table_read_dword(&post, FIELD_OFFSET(TT_POST, fixed_pitch)); + is_monospaced = !!table_read_dword(&post, FIELD_OFFSET(struct tt_post, fixed_pitch)); IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, post.context); } @@ -2544,20 +2538,20 @@ HRESULT opentype_get_font_info_strings(const struct file_stream_desc *stream_des HRESULT opentype_get_font_familyname(struct file_stream_desc *stream_desc, IDWriteLocalizedStrings **names) { struct dwrite_fonttable os2, name; - const TT_OS2_V2 *tt_os2; const void *name_table; + UINT16 fsselection; HRESULT hr; opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2); opentype_get_font_table(stream_desc, MS_NAME_TAG, &name); - tt_os2 = (const TT_OS2_V2 *)os2.data; name_table = (const void *)name.data; *names = NULL; - /* if Preferred Family doesn't conform to WWS model try WWS name */ - if (tt_os2 && !(GET_BE_WORD(tt_os2->fsSelection) & OS2_FSSELECTION_WWS)) + /* If Preferred Family doesn't conform to WWS model try WWS name. */ + fsselection = os2.data ? table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, fsSelection)) : 0; + if (os2.data && !(fsselection & OS2_FSSELECTION_WWS)) hr = opentype_get_font_strings_from_id(name_table, OPENTYPE_STRING_WWS_FAMILY_NAME, names); else hr = E_FAIL; @@ -2581,20 +2575,20 @@ HRESULT opentype_get_font_facename(struct file_stream_desc *stream_desc, WCHAR * { struct dwrite_fonttable os2, name; IDWriteLocalizedStrings *lfnames; - const TT_OS2_V2 *tt_os2; const void *name_table; + UINT16 fsselection; HRESULT hr; opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2); opentype_get_font_table(stream_desc, MS_NAME_TAG, &name); - tt_os2 = (const TT_OS2_V2 *)os2.data; name_table = name.data; *names = NULL; /* if Preferred Family doesn't conform to WWS model try WWS name */ - if (tt_os2 && !(GET_BE_WORD(tt_os2->fsSelection) & OS2_FSSELECTION_WWS)) + fsselection = os2.data ? table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, fsSelection)) : 0; + if (os2.data && !(fsselection & OS2_FSSELECTION_WWS)) hr = opentype_get_font_strings_from_id(name_table, OPENTYPE_STRING_WWS_SUBFAMILY_NAME, names); else hr = E_FAIL; -- 2.11.4.GIT