Bug 1293210 - add cap height support to nsFontMetrics. r=jfkthame
authorJeremy Chen <jeremychen@mozilla.com>
Thu, 18 Aug 2016 17:43:54 +0800
changeset 310004 449a9db6d0820baa50561d904827b2ebf517880b
parent 310003 b70e0aba06afc6e44b8c31a3c98eee67f692d14f
child 310005 985039d0c6b49ffa99fe8e4e4b3058086a6dbdc5
push id30575
push userryanvm@gmail.com
push dateFri, 19 Aug 2016 13:46:06 +0000
treeherdermozilla-central@3da4d64410c0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1293210
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1293210 - add cap height support to nsFontMetrics. r=jfkthame MozReview-Commit-ID: 8EXWUtbuN3s
gfx/src/nsFontMetrics.cpp
gfx/src/nsFontMetrics.h
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
--- a/gfx/src/nsFontMetrics.cpp
+++ b/gfx/src/nsFontMetrics.cpp
@@ -168,16 +168,22 @@ nsFontMetrics::GetMetrics(gfxFont::Orien
 
 nscoord
 nsFontMetrics::XHeight()
 {
     return ROUND_TO_TWIPS(GetMetrics().xHeight);
 }
 
 nscoord
+nsFontMetrics::CapHeight()
+{
+    return ROUND_TO_TWIPS(GetMetrics().capHeight);
+}
+
+nscoord
 nsFontMetrics::SuperscriptOffset()
 {
     return ROUND_TO_TWIPS(GetMetrics().emHeight *
                           NS_FONT_SUPERSCRIPT_OFFSET_RATIO);
 }
 
 nscoord
 nsFontMetrics::SubscriptOffset()
--- a/gfx/src/nsFontMetrics.h
+++ b/gfx/src/nsFontMetrics.h
@@ -70,16 +70,21 @@ public:
     void Destroy();
 
     /**
      * Return the font's x-height.
      */
     nscoord XHeight();
 
     /**
+     * Return the font's cap-height.
+     */
+    nscoord CapHeight();
+
+    /**
      * Return the font's superscript offset (the distance from the
      * baseline to where a superscript's baseline should be placed).
      * The value returned will be positive.
      */
     nscoord SuperscriptOffset();
 
     /**
      * Return the font's subscript offset (the distance from the
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -3454,22 +3454,28 @@ gfxFont::InitMetricsFromSfntTables(Metri
     SET_UNSIGNED(underlineSize, post->underlineThickness);
 
     // 'OS/2' table is optional, if not found we'll estimate xHeight
     // and aveCharWidth by measuring glyphs
     gfxFontEntry::AutoTable os2Table(mFontEntry, kOS_2TableTag);
     if (os2Table) {
         const OS2Table *os2 =
             reinterpret_cast<const OS2Table*>(hb_blob_get_data(os2Table, &len));
-        // although sxHeight is a signed field, we consider negative values to
-        // be erroneous and just ignore them
-        if (len >= offsetof(OS2Table, sxHeight) + sizeof(int16_t) &&
-            uint16_t(os2->version) >= 2 && int16_t(os2->sxHeight) > 0) {
-            // version 2 and later includes the x-height field
-            SET_SIGNED(xHeight, os2->sxHeight);
+        // although sxHeight and sCapHeight are signed fields, we consider
+        // negative values to be erroneous and just ignore them
+        if (uint16_t(os2->version) >= 2) {
+            // version 2 and later includes the x-height and cap-height fields
+            if (len >= offsetof(OS2Table, sxHeight) + sizeof(int16_t) &&
+                int16_t(os2->sxHeight) > 0) {
+                SET_SIGNED(xHeight, os2->sxHeight);
+            }
+            if (len >= offsetof(OS2Table, sCapHeight) + sizeof(int16_t) &&
+                int16_t(os2->sCapHeight) > 0) {
+                SET_SIGNED(capHeight, os2->sCapHeight);
+            }
         }
         // this should always be present in any valid OS/2 of any version
         if (len >= offsetof(OS2Table, sTypoLineGap) + sizeof(int16_t)) {
             SET_SIGNED(aveCharWidth, os2->xAvgCharWidth);
             SET_SIGNED(strikeoutSize, os2->yStrikeoutSize);
             SET_SIGNED(strikeoutOffset, os2->yStrikeoutPosition);
 
             // for fonts with USE_TYPO_METRICS set in the fsSelection field,
@@ -3507,16 +3513,22 @@ void gfxFont::CalculateDerivedMetrics(Me
 
     if (aMetrics.xHeight <= 0) {
         // only happens if we couldn't find either font metrics
         // or a char to measure;
         // pick an arbitrary value that's better than zero
         aMetrics.xHeight = aMetrics.maxAscent * DEFAULT_XHEIGHT_FACTOR;
     }
 
+    // If we have a font that doesn't provide a capHeight value, use maxAscent
+    // as a reasonable fallback.
+    if (aMetrics.capHeight <= 0) {
+        aMetrics.capHeight = aMetrics.maxAscent;
+    }
+
     aMetrics.maxHeight = aMetrics.maxAscent + aMetrics.maxDescent;
 
     if (aMetrics.maxHeight - aMetrics.emHeight > 0.0) {
         aMetrics.internalLeading = aMetrics.maxHeight - aMetrics.emHeight;
     } else {
         aMetrics.internalLeading = 0.0;
     }
 
@@ -3769,16 +3781,17 @@ gfxFont::CreateVerticalMetrics()
     metrics->strikeoutSize = std::max(1.0, metrics->strikeoutSize);
     metrics->strikeoutOffset = - 0.5 * metrics->strikeoutSize;
 
     // Somewhat arbitrary values for now, subject to future refinement...
     metrics->spaceWidth = metrics->aveCharWidth;
     metrics->zeroOrAveCharWidth = metrics->aveCharWidth;
     metrics->maxHeight = metrics->maxAscent + metrics->maxDescent;
     metrics->xHeight = metrics->emHeight / 2;
+    metrics->capHeight = metrics->maxAscent;
 
     return metrics;
 }
 
 gfxFloat
 gfxFont::SynthesizeSpaceWidth(uint32_t aCh)
 {
     // return an appropriate width for various Unicode space characters
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -1507,16 +1507,17 @@ public:
     virtual already_AddRefed<mozilla::gfx::GlyphRenderingOptions>
       GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams = nullptr)
     { return nullptr; }
 
     gfxFloat SynthesizeSpaceWidth(uint32_t aCh);
 
     // Font metrics
     struct Metrics {
+        gfxFloat capHeight;
         gfxFloat xHeight;
         gfxFloat strikeoutSize;
         gfxFloat strikeoutOffset;
         gfxFloat underlineSize;
         gfxFloat underlineOffset;
 
         gfxFloat internalLeading;
         gfxFloat externalLeading;