Adding code to calculate Underline Thickness from Font Metrics, this will be useful when Skia is used with Blink/Chrome. Blink changes are uploaded with code change in patch https://codereview.chromium.org/147703002/

BUG=skia:
R=reed@android.com, edisonn@google.com, reed@google.com, mtklein@google.com, mtklein@chromium.org, bungeman@google.com

Author: h.joshi@samsung.com

Review URL: https://codereview.chromium.org/152073003

git-svn-id: http://skia.googlecode.com/svn/trunk@13635 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/AUTHORS b/AUTHORS
index a51e7c6..4bef933 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -17,5 +17,6 @@
 Google Inc. <*@google.com>
 Intel <*@intel.com>
 NVIDIA <*@nvidia.com>
+Samsung <*@samsung.com>
 The Chromium Authors <*@chromium.org>
 Thiago Fransosi Farina <thiago.farina@gmail.com>
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 48cd573..7d553ec 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -731,17 +731,60 @@
     void setTextEncoding(TextEncoding encoding);
 
     struct FontMetrics {
+        /** Flags which indicate the confidence level of various metrics.
+            A set flag indicates that the metric may be trusted.
+        */
+        enum FontMetricsFlags {
+            kUnderlineThinknessIsValid_Flag = 1 << 0,
+            kUnderlinePositionIsValid_Flag = 1 << 1,
+        };
+
+        uint32_t    fFlags;       //!< Bit field to identify which values are unknown
         SkScalar    fTop;       //!< The greatest distance above the baseline for any glyph (will be <= 0)
         SkScalar    fAscent;    //!< The recommended distance above the baseline (will be <= 0)
         SkScalar    fDescent;   //!< The recommended distance below the baseline (will be >= 0)
         SkScalar    fBottom;    //!< The greatest distance below the baseline for any glyph (will be >= 0)
         SkScalar    fLeading;   //!< The recommended distance to add between lines of text (will be >= 0)
-        SkScalar    fAvgCharWidth;  //!< the average charactor width (>= 0)
-        SkScalar    fMaxCharWidth;  //!< the max charactor width (>= 0)
+        SkScalar    fAvgCharWidth;  //!< the average character width (>= 0)
+        SkScalar    fMaxCharWidth;  //!< the max character width (>= 0)
         SkScalar    fXMin;      //!< The minimum bounding box x value for all glyphs
         SkScalar    fXMax;      //!< The maximum bounding box x value for all glyphs
         SkScalar    fXHeight;   //!< The height of an 'x' in px, or 0 if no 'x' in face
         SkScalar    fCapHeight;  //!< The cap height (> 0), or 0 if cannot be determined.
+        SkScalar    fUnderlineThickness; //!< underline thickness, or 0 if cannot be determined
+
+        /**  Underline Position - position of the top of the Underline stroke
+                relative to the baseline, this can have following values
+                - Negative - means underline should be drawn above baseline.
+                - Positive - means below baseline.
+                - Zero     - mean underline should be drawn on baseline.
+         */
+        SkScalar    fUnderlinePosition; //!< underline position, or 0 if cannot be determined
+
+        /**  If the fontmetrics has a valid underlinethickness, return true, and set the
+                thickness param to that value. If it doesn't return false and ignore the
+                thickness param.
+        */
+        bool hasUnderlineThickness(SkScalar* thickness) const {
+            if (SkToBool(fFlags & kUnderlineThinknessIsValid_Flag)) {
+                *thickness = fUnderlineThickness;
+                return true;
+            }
+            return false;
+        }
+
+        /**  If the fontmetrics has a valid underlineposition, return true, and set the
+                thickness param to that value. If it doesn't return false and ignore the
+                thickness param.
+        */
+        bool hasUnderlinePosition(SkScalar* position) const {
+            if (SkToBool(fFlags & kUnderlinePositionIsValid_Flag)) {
+                *position = fUnderlinePosition;
+                return true;
+            }
+            return false;
+        }
+
     };
 
     /** Return the recommend spacing between lines (which will be
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 263ba10..76fa734 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1305,6 +1305,8 @@
         metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
         metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
         metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
+        metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale);
+        metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale);
     }
     return metrics->fDescent - metrics->fAscent + metrics->fLeading;
 }
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index cb7ce80..fce8259 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -1390,6 +1390,7 @@
 
     // pull from format-specific metrics as needed
     SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax;
+    SkScalar underlineThickness, underlinePosition;
     if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font
         ascent = -SkIntToScalar(face->ascender) / upem;
         descent = -SkIntToScalar(face->descender) / upem;
@@ -1398,6 +1399,17 @@
         xmax = SkIntToScalar(face->bbox.xMax) / upem;
         ymin = -SkIntToScalar(face->bbox.yMin) / upem;
         ymax = -SkIntToScalar(face->bbox.yMax) / upem;
+        underlineThickness = SkIntToScalar(face->underline_thickness) / upem;
+        underlinePosition = -SkIntToScalar(face->underline_position) / upem;
+
+        if(mx) {
+            mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+            mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
+        }
+        if(my){
+            my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+            my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
+        }
         // we may be able to synthesize x_height and cap_height from outline
         if (!x_height) {
             FT_BBox bbox;
@@ -1422,6 +1434,17 @@
         xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem;
         ymin = descent + leading;
         ymax = ascent - descent;
+        underlineThickness = 0;
+        underlinePosition = 0;
+
+        if(mx) {
+            mx->fFlags &= ~SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+            mx->fFlags &= ~SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
+        }
+        if(my){
+            my->fFlags &= ~SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+            my->fFlags &= ~SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
+        }
     } else {
         goto ERROR;
     }
@@ -1453,6 +1476,8 @@
         mx->fXMax = xmax;
         mx->fXHeight = x_height;
         mx->fCapHeight = cap_height;
+        mx->fUnderlineThickness = underlineThickness;
+        mx->fUnderlinePosition = underlinePosition;
     }
     if (my) {
         my->fTop = ymax * myy;
@@ -1465,6 +1490,8 @@
         my->fXMax = xmax;
         my->fXHeight = x_height;
         my->fCapHeight = cap_height;
+        my->fUnderlineThickness = underlineThickness;
+        my->fUnderlinePosition = underlinePosition;
     }
 }
 
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index ac0e365..26d30d7 100755
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -1379,6 +1379,11 @@
     theMetrics.fXMin         = CGToScalar( CGRectGetMinX_inline(theBounds));
     theMetrics.fXMax         = CGToScalar( CGRectGetMaxX_inline(theBounds));
     theMetrics.fXHeight      = CGToScalar( CTFontGetXHeight(fCTFont));
+    theMetrics.fUnderlineThickness = CGToScalar( CTFontGetUnderlineThickness(fCTFont));
+    theMetrics.fUnderlinePosition = -CGToScalar( CTFontGetUnderlinePosition(fCTFont));
+
+    theMetrics.fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+    theMetrics.fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
 
     if (mx != NULL) {
         *mx = theMetrics;
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index 4ca0fb9..9dc720a 100755
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -1061,6 +1061,11 @@
         mx->fDescent = SkIntToScalar(-otm.otmDescent);
         mx->fBottom = SkIntToScalar(otm.otmrcFontBox.right);
         mx->fLeading = SkIntToScalar(otm.otmLineGap);
+        mx->fUnderlineThickness = SkIntToScalar(otm.otmsUnderscoreSize);
+        mx->fUnderlinePosition = -SkIntToScalar(otm.otmsUnderscorePosition);
+
+        mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+        mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
     }
 
     if (my) {
@@ -1074,6 +1079,11 @@
         my->fMaxCharWidth = SkIntToScalar(otm.otmTextMetrics.tmMaxCharWidth);
         my->fXMin = SkIntToScalar(otm.otmrcFontBox.left);
         my->fXMax = SkIntToScalar(otm.otmrcFontBox.right);
+        my->fUnderlineThickness = SkIntToScalar(otm.otmsUnderscoreSize);
+        my->fUnderlinePosition = -SkIntToScalar(otm.otmsUnderscorePosition);
+
+        my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+        my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
 #endif
         my->fXHeight = SkIntToScalar(otm.otmsXHeight);
 
diff --git a/src/ports/SkFontHost_win_dw.cpp b/src/ports/SkFontHost_win_dw.cpp
index ce5e49b..b80154a 100644
--- a/src/ports/SkFontHost_win_dw.cpp
+++ b/src/ports/SkFontHost_win_dw.cpp
@@ -874,6 +874,11 @@
         mx->fBottom = mx->fDescent;
         mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
         mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
+        mx->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
+        mx->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
+
+        mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+        mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
     }
 
     if (my) {
@@ -883,6 +888,11 @@
         my->fBottom = my->fDescent;
         my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
         my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
+        my->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
+        my->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
+
+        my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+        my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
     }
 }