[PATCH 6/6] dwrite: Improve returned design glyph metrics.

Nikolay Sivov nsivov at codeweavers.com
Mon May 13 06:21:47 CDT 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/dwrite_private.h | 71 +++++++++++++++++++++++++++++++-----
 dlls/dwrite/font.c           | 51 ++++----------------------
 dlls/dwrite/freetype.c       | 25 +++++++------
 dlls/dwrite/opentype.c       | 21 +++++++++++
 4 files changed, 103 insertions(+), 65 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index e2aa2131a1..32ccd63c3e 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -164,12 +164,69 @@ struct fontface_desc
     struct dwrite_font_data *font_data; /* could be NULL when face is created directly with IDWriteFactory::CreateFontFace() */
 };
 
+struct dwrite_fonttable
+{
+    const BYTE *data;
+    void *context;
+    UINT32 size;
+    BOOL exists;
+};
+
 struct fontfacecached
 {
     struct list entry;
     IDWriteFontFace4 *fontface;
 };
 
+#define GLYPH_BLOCK_SHIFT 8
+#define GLYPH_BLOCK_SIZE  (1UL << GLYPH_BLOCK_SHIFT)
+#define GLYPH_BLOCK_MASK  (GLYPH_BLOCK_SIZE - 1)
+#define GLYPH_MAX         65536
+
+struct dwrite_fontface
+{
+    IDWriteFontFace4 IDWriteFontFace4_iface;
+    LONG ref;
+
+    IDWriteFontFileStream *stream;
+    IDWriteFontFile **files;
+    UINT32 file_count;
+    UINT32 index;
+
+    IDWriteFactory5 *factory;
+    struct fontfacecached *cached;
+
+    USHORT simulations;
+    DWRITE_FONT_FACE_TYPE type;
+    DWRITE_FONT_METRICS1 metrics;
+    DWRITE_CARET_METRICS caret;
+    struct
+    {
+        unsigned int ascent;
+        unsigned int descent;
+    } typo_metrics;
+    INT charmap;
+    UINT16 flags;
+
+    struct dwrite_fonttable cmap;
+    struct dwrite_fonttable vdmx;
+    struct dwrite_fonttable gasp;
+    struct dwrite_fonttable cpal;
+    struct dwrite_fonttable colr;
+    DWRITE_GLYPH_METRICS *glyphs[GLYPH_MAX/GLYPH_BLOCK_SIZE];
+
+    DWRITE_FONT_STYLE style;
+    DWRITE_FONT_STRETCH stretch;
+    DWRITE_FONT_WEIGHT weight;
+    DWRITE_PANOSE panose;
+    FONTSIGNATURE fontsig;
+    UINT32 glyph_image_formats;
+
+    struct scriptshaping_cache *shaping_cache;
+
+    LOGFONTW lf;
+};
+
 extern HRESULT create_numbersubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD,const WCHAR *locale,BOOL,IDWriteNumberSubstitution**) DECLSPEC_HIDDEN;
 extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH,
                                  FLOAT,const WCHAR*,IDWriteTextFormat**) DECLSPEC_HIDDEN;
@@ -241,14 +298,6 @@ struct file_stream_desc {
     UINT32 face_index;
 };
 
-struct dwrite_fonttable
-{
-    const BYTE *data;
-    void *context;
-    UINT32 size;
-    BOOL exists;
-};
-
 extern const void* get_fontface_table(IDWriteFontFace4 *fontface, UINT32 tag,
         struct dwrite_fonttable *table) DECLSPEC_HIDDEN;
 
@@ -258,6 +307,8 @@ extern HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *t
         DWRITE_UNICODE_RANGE *ranges, unsigned int *count) DECLSPEC_HIDDEN;
 extern void opentype_get_font_properties(struct file_stream_desc*,struct dwrite_font_props*) DECLSPEC_HIDDEN;
 extern void opentype_get_font_metrics(struct file_stream_desc*,DWRITE_FONT_METRICS1*,DWRITE_CARET_METRICS*) DECLSPEC_HIDDEN;
+extern void opentype_get_font_typo_metrics(struct file_stream_desc *stream_desc, unsigned int *ascent,
+        unsigned int *descent) DECLSPEC_HIDDEN;
 extern HRESULT opentype_get_font_info_strings(const void*,DWRITE_INFORMATIONAL_STRING_ID,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
 extern HRESULT opentype_get_font_familyname(struct file_stream_desc*,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
 extern HRESULT opentype_get_font_facename(struct file_stream_desc*,WCHAR*,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
@@ -317,7 +368,9 @@ struct dwrite_glyphbitmap
 
 extern BOOL init_freetype(void) DECLSPEC_HIDDEN;
 extern void release_freetype(void) DECLSPEC_HIDDEN;
-extern HRESULT freetype_get_design_glyph_metrics(IDWriteFontFace4*,UINT16,UINT16,DWRITE_GLYPH_METRICS*) DECLSPEC_HIDDEN;
+
+extern HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph,
+        DWRITE_GLYPH_METRICS *metrics) DECLSPEC_HIDDEN;
 extern void freetype_notify_cacheremove(IDWriteFontFace4*) DECLSPEC_HIDDEN;
 extern BOOL freetype_is_monospaced(IDWriteFontFace4*) DECLSPEC_HIDDEN;
 extern HRESULT freetype_get_glyphrun_outline(IDWriteFontFace4 *fontface, float emsize, UINT16 const *glyphs,
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 732ca371f2..5a3afefb27 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -207,44 +207,6 @@ enum fontface_flags {
     FONTFACE_HAS_VERTICAL_VARIANTS = 1 << 3
 };
 
-struct dwrite_fontface {
-    IDWriteFontFace4 IDWriteFontFace4_iface;
-    LONG ref;
-
-    IDWriteFontFileStream *stream;
-    IDWriteFontFile **files;
-    UINT32 file_count;
-    UINT32 index;
-
-    IDWriteFactory5 *factory;
-    struct fontfacecached *cached;
-
-    USHORT simulations;
-    DWRITE_FONT_FACE_TYPE type;
-    DWRITE_FONT_METRICS1 metrics;
-    DWRITE_CARET_METRICS caret;
-    INT charmap;
-    UINT16 flags;
-
-    struct dwrite_fonttable cmap;
-    struct dwrite_fonttable vdmx;
-    struct dwrite_fonttable gasp;
-    struct dwrite_fonttable cpal;
-    struct dwrite_fonttable colr;
-    DWRITE_GLYPH_METRICS *glyphs[GLYPH_MAX/GLYPH_BLOCK_SIZE];
-
-    DWRITE_FONT_STYLE style;
-    DWRITE_FONT_STRETCH stretch;
-    DWRITE_FONT_WEIGHT weight;
-    DWRITE_PANOSE panose;
-    FONTSIGNATURE fontsig;
-    UINT32 glyph_image_formats;
-
-    struct scriptshaping_cache *shaping_cache;
-
-    LOGFONTW lf;
-};
-
 struct dwrite_fontfile {
     IDWriteFontFile IDWriteFontFile_iface;
     LONG ref;
@@ -636,11 +598,11 @@ static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace4 *iface)
 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace4 *iface,
     UINT16 const *glyphs, UINT32 glyph_count, DWRITE_GLYPH_METRICS *ret, BOOL is_sideways)
 {
-    struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface);
+    struct dwrite_fontface *fontface = impl_from_IDWriteFontFace4(iface);
+    unsigned int i;
     HRESULT hr;
-    UINT32 i;
 
-    TRACE("(%p)->(%p %u %p %d)\n", This, glyphs, glyph_count, ret, is_sideways);
+    TRACE("%p, %p, %u, %p, %d.\n", iface, glyphs, glyph_count, ret, is_sideways);
 
     if (!glyphs)
         return E_INVALIDARG;
@@ -651,10 +613,10 @@ static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace4 *ifa
     for (i = 0; i < glyph_count; i++) {
         DWRITE_GLYPH_METRICS metrics;
 
-        hr = get_cached_glyph_metrics(This, glyphs[i], &metrics);
+        hr = get_cached_glyph_metrics(fontface, glyphs[i], &metrics);
         if (hr != S_OK) {
-            freetype_get_design_glyph_metrics(iface, This->metrics.designUnitsPerEm, glyphs[i], &metrics);
-            hr = set_cached_glyph_metrics(This, glyphs[i], &metrics);
+            freetype_get_design_glyph_metrics(fontface, glyphs[i], &metrics);
+            hr = set_cached_glyph_metrics(fontface, glyphs[i], &metrics);
             if (FAILED(hr))
                 return hr;
         }
@@ -4505,6 +4467,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
     stream_desc.face_type = desc->face_type;
     stream_desc.face_index = desc->index;
     opentype_get_font_metrics(&stream_desc, &fontface->metrics, &fontface->caret);
+    opentype_get_font_typo_metrics(&stream_desc, &fontface->typo_metrics.ascent, &fontface->typo_metrics.descent);
     if (desc->simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) {
         /* TODO: test what happens if caret is already slanted */
         if (fontface->caret.slopeRise == 1) {
diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c
index fd94829e68..16317036e3 100644
--- a/dlls/dwrite/freetype.c
+++ b/dlls/dwrite/freetype.c
@@ -263,14 +263,14 @@ void freetype_notify_cacheremove(IDWriteFontFace4 *fontface)
     LeaveCriticalSection(&freetype_cs);
 }
 
-HRESULT freetype_get_design_glyph_metrics(IDWriteFontFace4 *fontface, UINT16 unitsperEm, UINT16 glyph, DWRITE_GLYPH_METRICS *ret)
+HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *ret)
 {
     FTC_ScalerRec scaler;
     FT_Size size;
 
-    scaler.face_id = fontface;
-    scaler.width  = unitsperEm;
-    scaler.height = unitsperEm;
+    scaler.face_id = &fontface->IDWriteFontFace4_iface;
+    scaler.width = fontface->metrics.designUnitsPerEm;
+    scaler.height = fontface->metrics.designUnitsPerEm;
     scaler.pixel = 1;
     scaler.x_res = 0;
     scaler.y_res = 0;
@@ -278,22 +278,23 @@ HRESULT freetype_get_design_glyph_metrics(IDWriteFontFace4 *fontface, UINT16 uni
     EnterCriticalSection(&freetype_cs);
     if (pFTC_Manager_LookupSize(cache_manager, &scaler, &size) == 0) {
          if (pFT_Load_Glyph(size->face, glyph, FT_LOAD_NO_SCALE) == 0) {
-             USHORT simulations = IDWriteFontFace4_GetSimulations(fontface);
              FT_Glyph_Metrics *metrics = &size->face->glyph->metrics;
 
              ret->leftSideBearing = metrics->horiBearingX;
              ret->advanceWidth = metrics->horiAdvance;
              ret->rightSideBearing = metrics->horiAdvance - metrics->horiBearingX - metrics->width;
-             ret->topSideBearing = metrics->vertBearingY;
+
              ret->advanceHeight = metrics->vertAdvance;
-             ret->bottomSideBearing = metrics->vertAdvance - metrics->vertBearingY - metrics->height;
-             ret->verticalOriginY = metrics->height + metrics->vertBearingY;
+             ret->verticalOriginY = fontface->typo_metrics.ascent;
+             ret->topSideBearing = fontface->typo_metrics.ascent - metrics->horiBearingY;
+             ret->bottomSideBearing = metrics->vertAdvance - metrics->height - ret->topSideBearing;
 
              /* Adjust in case of bold simulation, glyphs without contours are ignored. */
-             if (simulations & DWRITE_FONT_SIMULATIONS_BOLD && size->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE &&
-                     size->face->glyph->outline.n_contours != 0) {
+             if (fontface->simulations & DWRITE_FONT_SIMULATIONS_BOLD &&
+                     size->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE && size->face->glyph->outline.n_contours)
+             {
                  if (ret->advanceWidth)
-                     ret->advanceWidth += (unitsperEm + 49) / 50;
+                     ret->advanceWidth += (fontface->metrics.designUnitsPerEm + 49) / 50;
              }
          }
     }
@@ -929,7 +930,7 @@ void freetype_notify_cacheremove(IDWriteFontFace4 *fontface)
 {
 }
 
-HRESULT freetype_get_design_glyph_metrics(IDWriteFontFace4 *fontface, UINT16 unitsperEm, UINT16 glyph, DWRITE_GLYPH_METRICS *ret)
+HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *ret)
 {
     return E_NOTIMPL;
 }
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 4772236770..e8efa1d196 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -1553,6 +1553,27 @@ HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *cmap, un
     return *count > max_count ? E_NOT_SUFFICIENT_BUFFER : S_OK;
 }
 
+void opentype_get_font_typo_metrics(struct file_stream_desc *stream_desc, unsigned int *ascent, unsigned int *descent)
+{
+    const TT_OS2_V2 *data;
+    unsigned int size;
+    void *context;
+
+    opentype_get_font_table(stream_desc, MS_OS2_TAG, (const void **)&data, &context, &size, NULL);
+
+    *ascent = *descent = 0;
+
+    if (size >= FIELD_OFFSET(TT_OS2_V2, sTypoLineGap))
+    {
+        SHORT value = GET_BE_WORD(data->sTypoDescender);
+        *ascent = GET_BE_WORD(data->sTypoAscender);
+        *descent = value < 0 ? -value : 0;
+    }
+
+    if (data)
+        IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, context);
+}
+
 void opentype_get_font_metrics(struct file_stream_desc *stream_desc, DWRITE_FONT_METRICS1 *metrics, DWRITE_CARET_METRICS *caret)
 {
     void *os2_context, *head_context, *post_context, *hhea_context;
-- 
2.20.1




More information about the wine-devel mailing list