Change getMetrics to the final API prepareForDrawing
Change the name, and add the atlas limit parameter.
Change-Id: Ic718d06d483667d7a341b74c280bc3fd016289ff
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/207314
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/core/SkGlyphRunPainter.cpp b/src/core/SkGlyphRunPainter.cpp
index 5a6da46..a0dd674 100644
--- a/src/core/SkGlyphRunPainter.cpp
+++ b/src/core/SkGlyphRunPainter.cpp
@@ -306,10 +306,13 @@
fStrikeCache->findOrCreateScopedStrike(
*ad.getDesc(), effects, *runFont.getTypefaceOrDefault());
- SkSpan<const SkGlyphPos> glyphPosSpan = strike->glyphMetrics(fARGBGlyphsIDs.data(),
- fARGBPositions.data(),
- fARGBGlyphsIDs.size(),
- fGlyphPos);
+ SkSpan<const SkGlyphPos> glyphPosSpan = strike->prepareForDrawing(
+ fARGBGlyphsIDs.data(),
+ fARGBPositions.data(),
+ fARGBGlyphsIDs.size(),
+ SkStrikeCommon::kSkSideTooBigForAtlas,
+ fGlyphPos);
+
if (process) {
process->processDeviceFallback(glyphPosSpan, strike.get());
}
@@ -552,13 +555,21 @@
mapping.postTranslate(rounding.x(), rounding.y());
mapping.mapPoints(fPositions, glyphRun.positions().data(), glyphRun.runSize());
- SkSpan<const SkGlyphPos> glyphPosSpan = strike->glyphMetrics(
- glyphRun.glyphsIDs().data(), fPositions, glyphRun.runSize(), fGlyphPos);
+ // Lookup all the glyphs from the cache.
+ SkSpan<const SkGlyphPos> glyphPosSpan = strike->prepareForDrawing(
+ glyphRun.glyphsIDs().data(),
+ fPositions,
+ glyphRun.runSize(),
+ SkStrikeCommon::kSkSideTooBigForAtlas,
+ fGlyphPos);
+ // Sort glyphs into the three bins: mask (fGlyphPos), path (fPaths), and fallback.
size_t glyphsWithMaskCount = 0;
for (const SkGlyphPos& glyphPos : glyphPosSpan) {
const SkGlyph& glyph = *glyphPos.glyph;
const SkPoint position = glyphPos.position;
+
+ // Able to position glyph?
if (!SkScalarsAreFinite(position.x(), position.y())) {
continue;
}
diff --git a/src/core/SkRemoteGlyphCache.cpp b/src/core/SkRemoteGlyphCache.cpp
index 5abb37c..8b4cdac 100644
--- a/src/core/SkRemoteGlyphCache.cpp
+++ b/src/core/SkRemoteGlyphCache.cpp
@@ -609,10 +609,14 @@
// This version of glyphMetrics only adds entries to result if their data need to be sent to the
-// GPU process.
-SkSpan<const SkGlyphPos> SkStrikeServer::SkGlyphCacheState::glyphMetrics(
- const SkGlyphID glyphIDs[], const SkPoint positions[], size_t n, SkGlyphPos result[]) {
-
+// GPU process. As a result, empty glyphs will be sent so that the GPU code can lookup the glyph
+// and detect that it is empty.
+SkSpan<const SkGlyphPos> SkStrikeServer::SkGlyphCacheState::prepareForDrawing(
+ const SkGlyphID glyphIDs[],
+ const SkPoint positions[],
+ size_t n,
+ int maxDimension,
+ SkGlyphPos results[]) {
size_t glyphsToSendCount = 0;
for (size_t i = 0; i < n; i++) {
SkPoint glyphPos = positions[i];
@@ -633,15 +637,40 @@
this->ensureScalerContext();
fContext->getMetrics(glyphPtr);
- result[glyphsToSendCount++] = {i, glyphPtr, glyphPos};
+ if (glyphPtr->maxDimension() <= maxDimension) {
+
+ // The mask/SDF will fit in the cache.
+ // TODO: no need to do this once code base converted over to bulk.
+ results[glyphsToSendCount++] = {i, glyphPtr, glyphPos};
+ } else if (glyphPtr->fMaskFormat != SkMask::kARGB32_Format) {
+
+ // The glyph is too big for the atlas, but it is not color, so it is handled with a
+ // path.
+ if (glyphPtr->fPathData == nullptr) {
+
+ // Never checked for a path before. Add the path now.
+ auto path = const_cast<SkGlyph&>(*glyphPtr).addPath(fContext.get(), &fAlloc);
+ if (path != nullptr) {
+
+ // A path was added make sure to send it to the GPU.
+ fCachedGlyphPaths.add(glyphPtr->getPackedID());
+ fPendingGlyphPaths.push_back(glyphPtr->getPackedID());
+ }
+ }
+ } else {
+
+ // This will be handled by the fallback strike.
+ SkASSERT(glyphPtr->maxDimension() > maxDimension
+ && glyphPtr->fMaskFormat == SkMask::kARGB32_Format);
+ }
// Make sure to send the glyph to the GPU because we always send the image for a glyph.
fCachedGlyphImages.add(packedGlyphID);
fPendingGlyphImages.push_back(packedGlyphID);
}
- }
- return SkSpan<const SkGlyphPos>{result, glyphsToSendCount};
+ }
+ return SkSpan<const SkGlyphPos>(results, glyphsToSendCount);
}
// SkStrikeClient -----------------------------------------
diff --git a/src/core/SkRemoteGlyphCacheImpl.h b/src/core/SkRemoteGlyphCacheImpl.h
index c7f5acf..1d7c9ba 100644
--- a/src/core/SkRemoteGlyphCacheImpl.h
+++ b/src/core/SkRemoteGlyphCacheImpl.h
@@ -43,8 +43,11 @@
const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) override;
- SkSpan<const SkGlyphPos> glyphMetrics(
- const SkGlyphID[], const SkPoint[], size_t n, SkGlyphPos result[]) override;
+ SkSpan<const SkGlyphPos> prepareForDrawing(const SkGlyphID glyphIDs[],
+ const SkPoint positions[],
+ size_t n,
+ int maxDimension,
+ SkGlyphPos results[]) override;
bool decideCouldDrawFromPath(const SkGlyph& glyph) override;
diff --git a/src/core/SkStrike.cpp b/src/core/SkStrike.cpp
index 236d721..20bb221 100644
--- a/src/core/SkStrike.cpp
+++ b/src/core/SkStrike.cpp
@@ -233,17 +233,34 @@
// N.B. This glyphMetrics call culls all the glyphs which will not display based on a non-finite
// position or that there are no mask pixels.
-SkSpan<const SkGlyphPos> SkStrike::glyphMetrics(const SkGlyphID glyphIDs[],
- const SkPoint positions[],
- size_t n,
- SkGlyphPos result[]) {
+SkSpan<const SkGlyphPos> SkStrike::prepareForDrawing(const SkGlyphID glyphIDs[],
+ const SkPoint positions[],
+ size_t n,
+ int maxDimension,
+ SkGlyphPos result[]) {
size_t drawableGlyphCount = 0;
for (size_t i = 0; i < n; i++) {
- SkPoint glyphPos = positions[i];
- if (SkScalarsAreFinite(glyphPos.x(), glyphPos.y())) {
- const SkGlyph& glyph = this->getGlyphMetrics(glyphIDs[i], glyphPos);
+ SkPoint position = positions[i];
+ if (SkScalarsAreFinite(position.x(), position.y())) {
+ // This assumes that the strike has no sub-pixel positioning for glyphs that are
+ // transformed from source space to device space.
+ const SkGlyph& glyph = this->getGlyphMetrics(glyphIDs[i], position);
if (!glyph.isEmpty()) {
- result[drawableGlyphCount++] = {i, &glyph, glyphPos};
+ result[drawableGlyphCount++] = {i, &glyph, position};
+ if (glyph.maxDimension() <= maxDimension) {
+
+ // Glyph fits in the atlas, good to go.
+ this->findImage(glyph);
+ } else if (glyph.fMaskFormat != SkMask::kARGB32_Format) {
+
+ // The out of atlas glyph is not color so we can draw it using paths.
+ this->findPath(glyph);
+ } else {
+
+ // This will be handled by the fallback strike.
+ SkASSERT(glyph.maxDimension() > maxDimension
+ && glyph.fMaskFormat == SkMask::kARGB32_Format);
+ }
}
}
}
diff --git a/src/core/SkStrike.h b/src/core/SkStrike.h
index 1f17b14..76b2fae 100644
--- a/src/core/SkStrike.h
+++ b/src/core/SkStrike.h
@@ -136,8 +136,11 @@
this->getScalerContext()->getEffects()};
}
- SkSpan<const SkGlyphPos> glyphMetrics(
- const SkGlyphID[], const SkPoint[], size_t n, SkGlyphPos result[]) override;
+ SkSpan<const SkGlyphPos> prepareForDrawing(const SkGlyphID glyphIDs[],
+ const SkPoint positions[],
+ size_t n,
+ int maxDimension,
+ SkGlyphPos results[]) override;
void onAboutToExitScope() override;
diff --git a/src/core/SkStrikeCache.cpp b/src/core/SkStrikeCache.cpp
index f5da322..02ff8af 100644
--- a/src/core/SkStrikeCache.cpp
+++ b/src/core/SkStrikeCache.cpp
@@ -36,12 +36,14 @@
return fStrike.getGlyphMetrics(glyphID, position);
}
- SkSpan<const SkGlyphPos> glyphMetrics(
- const SkGlyphID id[], const SkPoint point[], size_t n, SkGlyphPos result[]) override {
- return fStrike.glyphMetrics(id, point, n, result);
+ SkSpan<const SkGlyphPos> prepareForDrawing(const SkGlyphID glyphIDs[],
+ const SkPoint positions[],
+ size_t n,
+ int maxDimension,
+ SkGlyphPos results[]) override {
+ return fStrike.prepareForDrawing(glyphIDs, positions, n, maxDimension, results);
}
-
bool decideCouldDrawFromPath(const SkGlyph& glyph) override {
return fStrike.decideCouldDrawFromPath(glyph);
}
diff --git a/src/core/SkStrikeInterface.h b/src/core/SkStrikeInterface.h
index 0353b0a..9c52c36 100644
--- a/src/core/SkStrikeInterface.h
+++ b/src/core/SkStrikeInterface.h
@@ -70,9 +70,17 @@
virtual const SkDescriptor& getDescriptor() const = 0;
virtual SkStrikeSpec strikeSpec() const = 0;
- // glyphMetrics writes its results to result, but only returns a subspan of result.
- virtual SkSpan<const SkGlyphPos> glyphMetrics(
- const SkGlyphID[], const SkPoint[], size_t n, SkGlyphPos result[]) = 0;
+ // prepareForDrawing takes glyphIDs, and position, and returns a list of SkGlyphs and
+ // positions where all the data to draw the glyph has been created. The maxDimension
+ // parameter determines if the mask/SDF version will be created, or an alternate drawing
+ // format should be used. For path-only drawing set maxDimension to 0, and for bitmap-device
+ // drawing (where there is no upper limit to the glyph in the cache) use INT_MAX.
+ virtual SkSpan<const SkGlyphPos> prepareForDrawing(const SkGlyphID glyphIDs[],
+ const SkPoint positions[],
+ size_t n,
+ int maxDimension,
+ SkGlyphPos results[]) = 0;
+
virtual const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) = 0;
virtual bool decideCouldDrawFromPath(const SkGlyph& glyph) = 0;
virtual void onAboutToExitScope() = 0;