aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Wagner <bungeman@google.com>2019-03-20 15:52:21 -0400
committerBen Wagner <bungeman@google.com>2019-03-22 14:19:03 +0000
commit47d268ce1867b2090a2cd78724768ea52621b9b1 (patch)
treeb276858ec82e559336645464bfd2a44e7f429929
parent80061590f0e2354c4b1e00afe9973f45680a897e (diff)
downloadskia-47d268ce1867b2090a2cd78724768ea52621b9b1.tar.gz
Always draw emoji with GPU.
Remove some illogical code which prevents large font size requests for color fonts from working, and add a large mask fallback when drawing with masks and there are no paths available. Change-Id: I3e8c1dfc124cd315278b42cfcfebb39fc32212b8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/202420 Commit-Queue: Ben Wagner <bungeman@google.com> Reviewed-by: Herb Derby <herb@google.com> (cherry picked from commit 3e685ea1648d3c0f687b2f329658266295f2c2ea) Reviewed-on: https://skia-review.googlesource.com/c/skia/+/202946 Reviewed-by: Ben Wagner <bungeman@google.com>
-rw-r--r--src/core/SkGlyphRunPainter.cpp80
-rw-r--r--src/core/SkGlyphRunPainter.h10
2 files changed, 48 insertions, 42 deletions
diff --git a/src/core/SkGlyphRunPainter.cpp b/src/core/SkGlyphRunPainter.cpp
index d938e0edd5..8a6a5e0499 100644
--- a/src/core/SkGlyphRunPainter.cpp
+++ b/src/core/SkGlyphRunPainter.cpp
@@ -267,19 +267,17 @@ void SkGlyphRunListPainter::drawForBitmapDevice(
// transformations from the view matrix. Calculate a text scale based on that reduction. This
// scale factor is used to increase the size of the destination rectangles. The destination
// rectangles are then scaled, rotated, etc. by the GPU using the view matrix.
-void SkGlyphRunListPainter::processARGBFallback(SkScalar maxGlyphDimension,
+void SkGlyphRunListPainter::processARGBFallback(SkScalar maxSourceGlyphDimension,
const SkPaint& runPaint,
const SkFont& runFont,
const SkMatrix& viewMatrix,
- SkScalar cacheToSourceScale,
SkGlyphRunPainterInterface* process) {
SkASSERT(!fARGBGlyphsIDs.empty());
SkScalar maxScale = viewMatrix.getMaxScale();
- // This is a conservative estimate of the longest dimension among all the glyph widths and
- // heights.
- SkScalar conservativeMaxGlyphDimension = maxGlyphDimension * cacheToSourceScale * maxScale;
+ // This is a linear estimate of the longest dimension among all the glyph widths and heights.
+ SkScalar conservativeMaxGlyphDimension = maxSourceGlyphDimension * maxScale;
// If the situation that the matrix is simple, and all the glyphs are small enough. Go fast!
// N.B. If the matrix has scale, that will be reflected in the strike through the viewMatrix
@@ -328,19 +326,8 @@ void SkGlyphRunListPainter::processARGBFallback(SkScalar maxGlyphDimension,
SkScalar runFontTextSize = runFont.getSize();
// Scale the text size down so the long side of all the glyphs will fit in the atlas.
- SkScalar reducedTextSize =
- (maxAtlasDimension / conservativeMaxGlyphDimension) * runFontTextSize;
-
- // If there's a glyph in the font that's particularly large, it's possible
- // that fScaledFallbackTextSize may end up minimizing too much. We'd rather skip
- // that glyph than make the others blurry, so we set a minimum size of half the
- // maximum text size to avoid this case.
- SkScalar fallbackTextSize =
- SkScalarFloorToScalar(std::max(reducedTextSize, 0.5f * runFontTextSize));
-
- // Don't allow the text size to get too big. This will also improve glyph cache hit rate
- // for larger text sizes.
- fallbackTextSize = std::min(fallbackTextSize, 256.0f);
+ SkScalar fallbackTextSize = SkScalarFloorToScalar(
+ (maxAtlasDimension / maxSourceGlyphDimension) * runFontTextSize);
SkFont fallbackFont{runFont};
fallbackFont.setSize(fallbackTextSize);
@@ -472,10 +459,8 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
{
// fGlyphPos will be reused here.
if (!fARGBGlyphsIDs.empty()) {
- this->processARGBFallback(
- maxFallbackDimension, runPaint, glyphRun.font(), viewMatrix,
- cacheToSourceScale,
- process);
+ this->processARGBFallback(maxFallbackDimension * cacheToSourceScale,
+ runPaint, runFont, viewMatrix, process);
}
}
}
@@ -536,10 +521,8 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
// fGlyphPos will be reused here.
if (!fARGBGlyphsIDs.empty()) {
- this->processARGBFallback(
- maxFallbackDimension, runPaint, glyphRun.font(), viewMatrix,
- strikeToSourceRatio,
- process);
+ this->processARGBFallback(maxFallbackDimension * strikeToSourceRatio,
+ runPaint, runFont, viewMatrix, process);
}
}
} else {
@@ -556,29 +539,40 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
fStrikeCache->findOrCreateScopedStrike(*ad.getDesc(), effects, *typeface);
ScopedBuffers _ = this->ensureBuffers(glyphRun);
+ SkScalar maxFallbackDimension{-SK_ScalarInfinity};
SkMatrix mapping = viewMatrix;
mapping.preTranslate(origin.x(), origin.y());
SkVector rounding = strike->rounding();
mapping.postTranslate(rounding.x(), rounding.y());
- mapping.mapPoints(fPositions, glyphRun.positions().data(), glyphRun.runSize());
-
- int drawableGlyphCount = strike->glyphMetrics(
- glyphRun.glyphsIDs().data(),
- fPositions,
- glyphRun.glyphsIDs().size(),
- fGlyphPos);
+ mapping.mapPoints(fPositions, glyphRun.positions().data(), glyphRun.runSize());
int glyphsWithMaskCount = 0;
- // N.B. this is using the same underlying fGlyphPos array for input and output.
- for (int i = 0; i < drawableGlyphCount; i++) {
- SkGlyphPos glyphPos = fGlyphPos[i];
- if (SkStrikeCommon::GlyphTooBigForAtlas(*glyphPos.glyph)) {
- if (strike->decideCouldDrawFromPath(*glyphPos.glyph)) {
- fPaths.push_back(glyphPos);
+ const SkPoint* positionCursor = glyphRun.positions().data();
+ const SkPoint* devicePositionCursor = fPositions;
+ for (auto glyphID : glyphRun.glyphsIDs()) {
+ SkPoint glyphPos = *positionCursor++;
+ SkPoint deviceGlyphPos = *devicePositionCursor++;
+ if (!SkScalarsAreFinite(deviceGlyphPos.x(), deviceGlyphPos.y())) {
+ continue;
+ }
+
+ const SkGlyph& glyph = strike->getGlyphMetrics(glyphID, deviceGlyphPos);
+ if (glyph.isEmpty()) {
+ continue;
+ }
+
+ if (SkStrikeCommon::GlyphTooBigForAtlas(glyph)) {
+ if (strike->decideCouldDrawFromPath(glyph)) {
+ fPaths.push_back({&glyph, deviceGlyphPos});
+ } else {
+ SkScalar largestDimension = std::max(glyph.fWidth, glyph.fHeight);
+ maxFallbackDimension = std::max(maxFallbackDimension, largestDimension);
+ fARGBGlyphsIDs.push_back(glyph.getGlyphID());
+ fARGBPositions.push_back(origin + glyphPos);
}
} else {
- fGlyphPos[glyphsWithMaskCount++] = glyphPos;
+ fGlyphPos[glyphsWithMaskCount++] = {&glyph, deviceGlyphPos};
}
}
@@ -591,6 +585,12 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
if (!fPaths.empty()) {
process->processDevicePaths(SkSpan<const SkGlyphPos>{fPaths});
}
+
+ // fGlyphPos will be reused here.
+ if (!fARGBGlyphsIDs.empty()) {
+ this->processARGBFallback(maxFallbackDimension / viewMatrix.getMaxScale(),
+ runPaint, runFont, viewMatrix, process);
+ }
}
}
diff --git a/src/core/SkGlyphRunPainter.h b/src/core/SkGlyphRunPainter.h
index 5692c85647..1feff2b223 100644
--- a/src/core/SkGlyphRunPainter.h
+++ b/src/core/SkGlyphRunPainter.h
@@ -95,11 +95,17 @@ private:
// TODO: Remove once I can hoist ensureBuffers above the list for loop in all cases.
ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRun& glyphRun);
- void processARGBFallback(SkScalar maxGlyphDimension,
+ /**
+ * @param fARGBPositions in source space
+ * @param fARGBGlyphsIDs the glyphs to process
+ * @param fGlyphPos used as scratch space
+ * @param maxSourceGlyphDimension the longest dimension of any glyph as if all fARGBGlyphsIDs
+ * were drawn in source space (as if viewMatrix were identity)
+ */
+ void processARGBFallback(SkScalar maxSourceGlyphDimension,
const SkPaint& runPaint,
const SkFont& runFont,
const SkMatrix& viewMatrix,
- SkScalar cacheToSourceScale,
SkGlyphRunPainterInterface* process);
// The props as on the actual device.