SkScalerContext::getMetrics to not request metrics it will ignore.

Before this change SkScalerContext::getMetrics always calls
generateMetrics to force the subclass to create full metrics. However,
if the SkScalerContext is going to draw from outlines then there is no
reason to do so since it is immediately going to overwrite those metrics
by computing its own from the path. This also puts off other decisions
being made based on the glyph metrics until after the metrics are fully
computed.

The logic in SkScalerContext::getImage is updated to be similar to the
logic in the new SkScalerContext::getMetrics.

Change-Id: I1798c9244277fab85595fb39fc3a85ef7eb33620
Reviewed-on: https://skia-review.googlesource.com/117085
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
This commit is contained in:
Ben Wagner 2018-03-29 15:02:28 -04:00 committed by Skia Commit-Bot
parent 97be6f99f6
commit 2de1eda3d2
3 changed files with 40 additions and 79 deletions

View File

@ -71,38 +71,20 @@ void SkScalerContext::getAdvance(SkGlyph* glyph) {
}
void SkScalerContext::getMetrics(SkGlyph* glyph) {
generateMetrics(glyph);
// for now we have separate cache entries for devkerning on and off
// in the future we might share caches, but make our measure/draw
// code make the distinction. Thus we zap the values if the caller
// has not asked for them.
if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
// no devkern, so zap the fields
glyph->fLsbDelta = glyph->fRsbDelta = 0;
}
// if either dimension is empty, zap the image bounds of the glyph
if (0 == glyph->fWidth || 0 == glyph->fHeight) {
glyph->fWidth = 0;
glyph->fHeight = 0;
glyph->fTop = 0;
glyph->fLeft = 0;
glyph->fMaskFormat = 0;
return;
}
bool generatingImageFromPath = fGenerateImageFromPath;
if (fGenerateImageFromPath) {
if (!generatingImageFromPath) {
generateMetrics(glyph);
} else {
SkPath devPath, fillPath;
SkMatrix fillToDevMatrix;
if (!this->internalGetPath(glyph->getPackedID(), &fillPath, &devPath, &fillToDevMatrix)) {
generatingImageFromPath = false;
generatingImageFromPath = this->internalGetPath(glyph->getPackedID(), &fillPath, &devPath,
&fillToDevMatrix);
if (!generatingImageFromPath) {
generateMetrics(glyph);
} else {
// just use devPath
const SkIRect ir = devPath.getBounds().roundOut();
generateAdvance(glyph);
const SkIRect ir = devPath.getBounds().roundOut();
if (ir.isEmpty() || !ir.is16Bit()) {
goto SK_ERROR;
}
@ -124,6 +106,25 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) {
}
}
// for now we have separate cache entries for devkerning on and off
// in the future we might share caches, but make our measure/draw
// code make the distinction. Thus we zap the values if the caller
// has not asked for them.
if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
// no devkern, so zap the fields
glyph->fLsbDelta = glyph->fRsbDelta = 0;
}
// if either dimension is empty, zap the image bounds of the glyph
if (0 == glyph->fWidth || 0 == glyph->fHeight) {
glyph->fWidth = 0;
glyph->fHeight = 0;
glyph->fTop = 0;
glyph->fLeft = 0;
glyph->fMaskFormat = 0;
return;
}
if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
glyph->fMaskFormat = fRec.fMaskFormat;
}
@ -428,7 +429,9 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) {
glyph = &tmpGlyph;
}
if (fGenerateImageFromPath) {
if (!fGenerateImageFromPath) {
generateImage(*glyph);
} else {
SkPath devPath, fillPath;
SkMatrix fillToDevMatrix;
SkMask mask;
@ -441,8 +444,6 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) {
SkASSERT(SkMask::kARGB32_Format != mask.fFormat);
generateMask(mask, devPath, fPreBlend);
}
} else {
generateImage(*glyph);
}
if (fMaskFilter) {

View File

@ -98,16 +98,6 @@ SkTestTypeface::SkTestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& st
}
void SkTestTypeface::getAdvance(SkGlyph* glyph) {
// TODO(benjaminwagner): Update users to use floats.
glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyph->getGlyphID()]);
glyph->fAdvanceY = 0;
}
void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
*metrics = fTestFont->fMetrics;
}
void SkTestTypeface::getMetrics(SkGlyph* glyph) {
SkGlyphID glyphID = glyph->getGlyphID();
glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
@ -116,6 +106,10 @@ void SkTestTypeface::getMetrics(SkGlyph* glyph) {
glyph->fAdvanceY = 0;
}
void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
*metrics = fTestFont->fMetrics;
}
void SkTestTypeface::getPath(SkGlyphID glyphID, SkPath* path) {
glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
*path = *fTestFont->fPaths[glyphID];
@ -211,46 +205,13 @@ protected:
}
void generateMetrics(SkGlyph* glyph) override {
this->getTestTypeface()->getMetrics(glyph);
const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
SkFloatToScalar(glyph->fAdvanceY));
glyph->fAdvanceX = SkScalarToFloat(advance.fX);
glyph->fAdvanceY = SkScalarToFloat(advance.fY);
SkPath path;
this->getTestTypeface()->getPath(glyph->getGlyphID(), &path);
path.transform(fMatrix);
SkRect storage;
const SkPaint paint;
const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
&storage,
SkPaint::kFill_Style);
SkIRect ibounds;
newBounds.roundOut(&ibounds);
glyph->fLeft = ibounds.fLeft;
glyph->fTop = ibounds.fTop;
glyph->fWidth = ibounds.width();
glyph->fHeight = ibounds.height();
glyph->zeroMetrics();
this->generateAdvance(glyph);
// Always generates from paths, so SkScalerContext::getMetrics will figure the bounds.
}
void generateImage(const SkGlyph& glyph) override {
SkPath path;
this->getTestTypeface()->getPath(glyph.getGlyphID(), &path);
SkBitmap bm;
bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
glyph.fImage, glyph.rowBytes());
bm.eraseColor(0);
SkCanvas canvas(bm);
canvas.translate(-SkIntToScalar(glyph.fLeft),
-SkIntToScalar(glyph.fTop));
canvas.concat(fMatrix);
SkPaint paint;
paint.setAntiAlias(true);
canvas.drawPath(path, paint);
void generateImage(const SkGlyph&) override {
SK_ABORT("Should have generated from path.");
}
void generatePath(SkGlyphID glyph, SkPath* path) override {

View File

@ -66,7 +66,6 @@ public:
SkTestTypeface(sk_sp<SkTestFont>, const SkFontStyle& style);
void getAdvance(SkGlyph* glyph);
void getFontMetrics(SkPaint::FontMetrics* metrics);
void getMetrics(SkGlyph* glyph);
void getPath(SkGlyphID glyph, SkPath* path);
protected:
SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,