hide paint's getFontBounds

Bug: skia:
Change-Id: I26b693e32d0dadfe47710a29296eceb8ec90ee0c
Reviewed-on: https://skia-review.googlesource.com/c/174308
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Herb Derby <herb@google.com>
This commit is contained in:
Mike Reed 2018-12-04 17:35:56 -05:00 committed by Skia Commit-Bot
parent 5138990abe
commit 7d1eb33aec
8 changed files with 73 additions and 60 deletions

View File

@ -98,6 +98,8 @@ private:
DEF_GM( return new DrawAtlasGM; ) DEF_GM( return new DrawAtlasGM; )
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
#include "SkFont.h"
#include "SkFontPriv.h"
#include "SkPath.h" #include "SkPath.h"
#include "SkPathMeasure.h" #include "SkPathMeasure.h"
@ -106,16 +108,18 @@ static void draw_text_on_path(SkCanvas* canvas, const void* text, size_t length,
float baseline_offset) { float baseline_offset) {
SkPathMeasure meas(path, false); SkPathMeasure meas(path, false);
int count = paint.countText(text, length); SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);
int count = font.countText(text, length, kUTF8_SkTextEncoding);
size_t size = count * (sizeof(SkRSXform) + sizeof(SkScalar)); size_t size = count * (sizeof(SkRSXform) + sizeof(SkScalar));
SkAutoSMalloc<512> storage(size); SkAutoSMalloc<512> storage(size);
SkRSXform* xform = (SkRSXform*)storage.get(); SkRSXform* xform = (SkRSXform*)storage.get();
SkScalar* widths = (SkScalar*)(xform + count); SkScalar* widths = (SkScalar*)(xform + count);
// Compute a conservative bounds so we can cull the draw // Compute a conservative bounds so we can cull the draw
const SkRect font = paint.getFontBounds(); const SkRect fontb = SkFontPriv::GetFontBounds(font);
const SkScalar max = SkTMax(SkTMax(SkScalarAbs(font.fLeft), SkScalarAbs(font.fRight)), const SkScalar max = SkTMax(SkTMax(SkScalarAbs(fontb.fLeft), SkScalarAbs(fontb.fRight)),
SkTMax(SkScalarAbs(font.fTop), SkScalarAbs(font.fBottom))); SkTMax(SkScalarAbs(fontb.fTop), SkScalarAbs(fontb.fBottom)));
const SkRect bounds = path.getBounds().makeOutset(max, max); const SkRect bounds = path.getBounds().makeOutset(max, max);
paint.getTextWidths(text, length, widths); paint.getTextWidths(text, length, widths);

View File

@ -10,6 +10,7 @@
#include "SkCanvas.h" #include "SkCanvas.h"
#include "SkCommonFlags.h" #include "SkCommonFlags.h"
#include "SkFontMgr.h" #include "SkFontMgr.h"
#include "SkFontPriv.h"
#include "SkPath.h" #include "SkPath.h"
#include "SkGraphics.h" #include "SkGraphics.h"
#include "SkTypeface.h" #include "SkTypeface.h"
@ -218,19 +219,19 @@ public:
fFM = SkFontMgr::RefDefault(); fFM = SkFontMgr::RefDefault();
} }
static void show_bounds(SkCanvas* canvas, const SkPaint& paint, SkScalar x, SkScalar y, static void show_bounds(SkCanvas* canvas, const SkFont& font, SkScalar x, SkScalar y,
SkColor boundsColor) SkColor boundsColor)
{ {
SkPaint glyphPaint(paint); SkRect fontBounds = SkFontPriv::GetFontBounds(font).makeOffset(x, y);
SkRect fontBounds = glyphPaint.getFontBounds();
fontBounds.offset(x, y); SkPaint boundsPaint;
SkPaint boundsPaint(glyphPaint); boundsPaint.setAntiAlias(true);
boundsPaint.setColor(boundsColor); boundsPaint.setColor(boundsColor);
boundsPaint.setStyle(SkPaint::kStroke_Style); boundsPaint.setStyle(SkPaint::kStroke_Style);
canvas->drawRect(fontBounds, boundsPaint); canvas->drawRect(fontBounds, boundsPaint);
SkFontMetrics fm; SkFontMetrics fm;
glyphPaint.getFontMetrics(&fm); font.getMetrics(&fm);
SkPaint metricsPaint(boundsPaint); SkPaint metricsPaint(boundsPaint);
metricsPaint.setStyle(SkPaint::kFill_Style); metricsPaint.setStyle(SkPaint::kFill_Style);
metricsPaint.setAlpha(0x40); metricsPaint.setAlpha(0x40);
@ -252,13 +253,12 @@ public:
SkGlyphID left = 0, right = 0, top = 0, bottom = 0; SkGlyphID left = 0, right = 0, top = 0, bottom = 0;
{ {
int numGlyphs = glyphPaint.getTypeface()->countGlyphs(); int numGlyphs = font.getTypeface()->countGlyphs();
SkRect min = {0, 0, 0, 0}; SkRect min = {0, 0, 0, 0};
glyphPaint.setTextEncoding(kGlyphID_SkTextEncoding);
for (int i = 0; i < numGlyphs; ++i) { for (int i = 0; i < numGlyphs; ++i) {
SkGlyphID glyphId = i; SkGlyphID glyphId = i;
SkRect cur; SkRect cur;
glyphPaint.measureText(&glyphId, sizeof(glyphId), &cur); font.getBounds(&glyphId, 1, &cur, nullptr);
if (cur.fLeft < min.fLeft ) { min.fLeft = cur.fLeft; left = i; } if (cur.fLeft < min.fLeft ) { min.fLeft = cur.fLeft; left = i; }
if (cur.fTop < min.fTop ) { min.fTop = cur.fTop ; top = i; } if (cur.fTop < min.fTop ) { min.fTop = cur.fTop ; top = i; }
if (min.fRight < cur.fRight ) { min.fRight = cur.fRight; right = i; } if (min.fRight < cur.fRight ) { min.fRight = cur.fRight; right = i; }
@ -273,27 +273,30 @@ public:
{fontBounds.centerX(), fontBounds.bottom()} {fontBounds.centerX(), fontBounds.bottom()}
}; };
SkPaint labelPaint; SkFont labelFont;
labelPaint.setAntiAlias(true); labelFont.setEdging(SkFont::Edging::kAntiAlias);
sk_tool_utils::set_portable_typeface(&labelPaint); labelFont.setTypeface(sk_tool_utils::create_portable_typeface());
if (FLAGS_veryVerbose) { if (FLAGS_veryVerbose) {
SkString name; SkString name;
paint.getTypeface()->getFamilyName(&name); font.getTypeface()->getFamilyName(&name);
canvas->drawText(name.c_str(), name.size(), canvas->drawSimpleText(name.c_str(), name.size(), kUTF8_SkTextEncoding,
fontBounds.fLeft, fontBounds.fBottom, labelPaint); fontBounds.fLeft, fontBounds.fBottom, labelFont, SkPaint());
} }
for (size_t i = 0; i < SK_ARRAY_COUNT(str); ++i) { for (size_t i = 0; i < SK_ARRAY_COUNT(str); ++i) {
SkPath path; SkPath path;
glyphPaint.getTextPath(&str[i], sizeof(str[0]), x, y, &path); font.getPath(str[i], &path);
path.offset(x, y);
SkPaint::Style style = path.isEmpty() ? SkPaint::kFill_Style : SkPaint::kStroke_Style; SkPaint::Style style = path.isEmpty() ? SkPaint::kFill_Style : SkPaint::kStroke_Style;
SkPaint glyphPaint;
glyphPaint.setStyle(style); glyphPaint.setStyle(style);
canvas->drawText(&str[i], sizeof(str[0]), x, y, glyphPaint); canvas->drawSimpleText(&str[i], sizeof(str[0]), kGlyphID_SkTextEncoding, x, y, font, glyphPaint);
if (FLAGS_veryVerbose) { if (FLAGS_veryVerbose) {
SkString glyphStr; SkString glyphStr;
glyphStr.appendS32(str[i]); glyphStr.appendS32(str[i]);
canvas->drawText(glyphStr.c_str(), glyphStr.size(), canvas->drawSimpleText(glyphStr.c_str(), glyphStr.size(), kUTF8_SkTextEncoding,
location[i].fX, location[i].fY, labelPaint); location[i].fX, location[i].fY, labelFont, SkPaint());
} }
} }
@ -310,12 +313,12 @@ protected:
} }
void onDraw(SkCanvas* canvas) override { void onDraw(SkCanvas* canvas) override {
SkPaint paint; SkFont font;
paint.setAntiAlias(true); font.setEdging(SkFont::Edging::kAntiAlias);
paint.setSubpixelText(true); font.setSubpixel(true);
paint.setTextSize(100); font.setSize(100);
paint.setTextScaleX(fScaleX); font.setScaleX(fScaleX);
paint.setTextSkewX(fSkewX); font.setSkewX(fSkewX);
const SkColor boundsColors[2] = { SK_ColorRED, SK_ColorBLUE }; const SkColor boundsColors[2] = { SK_ColorRED, SK_ColorBLUE };
@ -330,13 +333,13 @@ protected:
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
sk_sp<SkFontStyleSet> set(fm->createStyleSet(i)); sk_sp<SkFontStyleSet> set(fm->createStyleSet(i));
for (int j = 0; j < set->count() && j < 3; ++j) { for (int j = 0; j < set->count() && j < 3; ++j) {
paint.setTypeface(sk_sp<SkTypeface>(set->createTypeface(j))); font.setTypeface(sk_sp<SkTypeface>(set->createTypeface(j)));
// Fonts with lots of glyphs are interesting, but can take a long time to find // Fonts with lots of glyphs are interesting, but can take a long time to find
// the glyphs which make up the maximum extent. // the glyphs which make up the maximum extent.
if (paint.getTypeface() && paint.getTypeface()->countGlyphs() < 1000) { if (font.getTypeface() && font.getTypeface()->countGlyphs() < 1000) {
SkRect fontBounds = paint.getFontBounds(); SkRect fontBounds = SkFontPriv::GetFontBounds(font);
x -= fontBounds.fLeft; x -= fontBounds.fLeft;
show_bounds(canvas, paint, x, y, boundsColors[index & 1]); show_bounds(canvas, font, x, y, boundsColors[index & 1]);
x += fontBounds.fRight + 20; x += fontBounds.fRight + 20;
index += 1; index += 1;
if (x > 900) { if (x > 900) {

View File

@ -975,18 +975,6 @@ public:
*/ */
SkScalar getFontSpacing() const { return this->getFontMetrics(nullptr); } SkScalar getFontSpacing() const { return this->getFontMetrics(nullptr); }
/** Returns the union of bounds of all glyphs.
Returned dimensions are computed by font manager from font data,
ignoring SkPaint::Hinting. Includes font metrics, but not fake bold or SkPathEffect.
If text size is large, text scale is one, and text skew is zero,
returns the bounds as:
{ SkFontMetrics::fXMin, SkFontMetrics::fTop, SkFontMetrics::fXMax, SkFontMetrics::fBottom }.
@return union of bounds of all glyphs
*/
SkRect getFontBounds() const;
/** Converts text into glyph indices. /** Converts text into glyph indices.
Returns the number of glyph indices represented by text. Returns the number of glyph indices represented by text.
SkTextEncoding specifies how text represents characters or glyphs. SkTextEncoding specifies how text represents characters or glyphs.

View File

@ -2530,13 +2530,14 @@ void SkCanvas::drawString(const SkString& string, SkScalar x, SkScalar y, const
} }
// These call the (virtual) onDraw... method // These call the (virtual) onDraw... method
void SkCanvas::drawSimpleText(const void* text, size_t byteLength, SkTextEncoding, void SkCanvas::drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint) { SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint) {
TRACE_EVENT0("skia", TRACE_FUNC); TRACE_EVENT0("skia", TRACE_FUNC);
if (byteLength) { if (byteLength) {
sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength)); sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
SkPaint tmp(paint); SkPaint tmp(paint);
font.LEGACY_applyToPaint(&tmp); font.LEGACY_applyToPaint(&tmp);
tmp.setTextEncoding(encoding);
this->onDrawText(text, byteLength, x, y, tmp); this->onDrawText(text, byteLength, x, y, tmp);
} }
} }

View File

@ -527,3 +527,18 @@ void SkFont::LEGACY_applyPaintFlags(uint32_t paintFlags) {
} }
this->setEdging(edging); this->setEdging(edging);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////
SkRect SkFontPriv::GetFontBounds(const SkFont& font) {
SkMatrix m;
m.setScale(font.getSize() * font.getScaleX(), font.getSize());
m.postSkew(font.getSkewX(), 0);
SkTypeface* typeface = SkFontPriv::GetTypefaceOrDefault(font);
SkRect bounds;
m.mapRect(&bounds, typeface->getBounds());
return bounds;
}

View File

@ -45,6 +45,19 @@ public:
typedef const SkGlyph& (*GlyphCacheProc)(SkGlyphCache*, const char**, const char*); typedef const SkGlyph& (*GlyphCacheProc)(SkGlyphCache*, const char**, const char*);
static GlyphCacheProc GetGlyphCacheProc(SkTextEncoding encoding, bool needFullMetrics); static GlyphCacheProc GetGlyphCacheProc(SkTextEncoding encoding, bool needFullMetrics);
/**
Returns the union of bounds of all glyphs.
Returned dimensions are computed by font manager from font data,
ignoring SkPaint::Hinting. Includes font metrics, but not fake bold or SkPathEffect.
If text size is large, text scale is one, and text skew is zero,
returns the bounds as:
{ SkFontMetrics::fXMin, SkFontMetrics::fTop, SkFontMetrics::fXMax, SkFontMetrics::fBottom }.
@return union of bounds of all glyphs
*/
static SkRect GetFontBounds(const SkFont&);
}; };
class SkAutoToGlyphs { class SkAutoToGlyphs {

View File

@ -541,18 +541,6 @@ int SkPaint::getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds
return count; return count;
} }
SkRect SkPaint::getFontBounds() const {
SkMatrix m;
m.setScale(fTextSize * fTextScaleX, fTextSize);
m.postSkew(fTextSkewX, 0);
SkTypeface* typeface = SkPaintPriv::GetTypefaceOrDefault(*this);
SkRect bounds;
m.mapRect(&bounds, typeface->getBounds());
return bounds;
}
// return true if the paint is just a single color (i.e. not a shader). If its // return true if the paint is just a single color (i.e. not a shader). If its
// a shader, then we can't compute a const luminance for it :( // a shader, then we can't compute a const luminance for it :(
static bool just_a_color(const SkPaint& paint, SkColor* color) { static bool just_a_color(const SkPaint& paint, SkColor* color) {

View File

@ -6,7 +6,7 @@
*/ */
#include "SkTextBlob.h" #include "SkTextBlob.h"
#include "SkFontPriv.h"
#include "SkGlyphRun.h" #include "SkGlyphRun.h"
#include "SkPaintPriv.h" #include "SkPaintPriv.h"
#include "SkReadBuffer.h" #include "SkReadBuffer.h"
@ -328,7 +328,8 @@ SkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run
SkPaint paint; SkPaint paint;
run.font().applyToPaint(&paint); run.font().applyToPaint(&paint);
const SkRect fontBounds = paint.getFontBounds(); SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);
const SkRect fontBounds = SkFontPriv::GetFontBounds(font);
if (fontBounds.isEmpty()) { if (fontBounds.isEmpty()) {
// Empty font bounds are likely a font bug. TightBounds has a better chance of // Empty font bounds are likely a font bug. TightBounds has a better chance of
// producing useful results in this case. // producing useful results in this case.