From 0bc406df48ac6f358ab8dcff08f71fe9c32b79de Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Sat, 1 Mar 2014 20:12:26 +0000 Subject: [PATCH] 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 --- AUTHORS | 1 + include/core/SkPaint.h | 47 +++++++++++++++++++++++++++++++++++++-- src/core/SkPaint.cpp | 2 ++ src/ports/SkFontHost_FreeType.cpp | 27 ++++++++++++++++++++++ src/ports/SkFontHost_mac.cpp | 5 +++++ src/ports/SkFontHost_win.cpp | 10 +++++++++ src/ports/SkFontHost_win_dw.cpp | 10 +++++++++ 7 files changed, 100 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index a51e7c6..4bef933 100644 --- a/AUTHORS +++ b/AUTHORS @@ -17,5 +17,6 @@ George Wright Google Inc. <*@google.com> Intel <*@intel.com> NVIDIA <*@nvidia.com> +Samsung <*@samsung.com> The Chromium Authors <*@chromium.org> Thiago Fransosi Farina 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 @@ public: 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 @@ SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const { 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 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, // 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 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, 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 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, 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 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, 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 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, 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 @@ void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx, 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 @@ void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint: 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 @@ void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint: 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 @@ void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx, 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 @@ void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx, 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; } } -- 2.7.4