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; )
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "SkFont.h"
#include "SkFontPriv.h"
#include "SkPath.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) {
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));
SkAutoSMalloc<512> storage(size);
SkRSXform* xform = (SkRSXform*)storage.get();
SkScalar* widths = (SkScalar*)(xform + count);
// Compute a conservative bounds so we can cull the draw
const SkRect font = paint.getFontBounds();
const SkScalar max = SkTMax(SkTMax(SkScalarAbs(font.fLeft), SkScalarAbs(font.fRight)),
SkTMax(SkScalarAbs(font.fTop), SkScalarAbs(font.fBottom)));
const SkRect fontb = SkFontPriv::GetFontBounds(font);
const SkScalar max = SkTMax(SkTMax(SkScalarAbs(fontb.fLeft), SkScalarAbs(fontb.fRight)),
SkTMax(SkScalarAbs(fontb.fTop), SkScalarAbs(fontb.fBottom)));
const SkRect bounds = path.getBounds().makeOutset(max, max);
paint.getTextWidths(text, length, widths);

View File

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

View File

@ -975,18 +975,6 @@ public:
*/
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.
Returns the number of glyph indices represented by text.
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
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) {
TRACE_EVENT0("skia", TRACE_FUNC);
if (byteLength) {
sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
SkPaint tmp(paint);
font.LEGACY_applyToPaint(&tmp);
tmp.setTextEncoding(encoding);
this->onDrawText(text, byteLength, x, y, tmp);
}
}

View File

@ -527,3 +527,18 @@ void SkFont::LEGACY_applyPaintFlags(uint32_t paintFlags) {
}
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*);
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 {

View File

@ -541,18 +541,6 @@ int SkPaint::getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds
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
// a shader, then we can't compute a const luminance for it :(
static bool just_a_color(const SkPaint& paint, SkColor* color) {

View File

@ -6,7 +6,7 @@
*/
#include "SkTextBlob.h"
#include "SkFontPriv.h"
#include "SkGlyphRun.h"
#include "SkPaintPriv.h"
#include "SkReadBuffer.h"
@ -328,7 +328,8 @@ SkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run
SkPaint 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()) {
// Empty font bounds are likely a font bug. TightBounds has a better chance of
// producing useful results in this case.