Move remote glyph cache DFT handling to painter
Change-Id: I68178e0675a45d77355b76a50eff06238ee1c54c Reviewed-on: https://skia-review.googlesource.com/158380 Commit-Queue: Herb Derby <herb@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
8ef78eae93
commit
7d8e1f7ca3
@ -335,40 +335,6 @@ void SkGlyphRunListPainter::processARGBFallback(
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
template <typename PerSDFT, typename PerPathT>
|
||||
void SkGlyphRunListPainter::drawGlyphRunAsSDFWithARGBFallback(
|
||||
SkGlyphCacheInterface* cache, const SkGlyphRun& glyphRun,
|
||||
SkPoint origin, const SkMatrix& viewMatrix, SkScalar textScale,
|
||||
PerSDFT perSDF, PerPathT perPath, ARGBFallback argbFallback) {
|
||||
fARGBGlyphsIDs.clear();
|
||||
fARGBPositions.clear();
|
||||
SkScalar maxFallbackDimension{-SK_ScalarInfinity};
|
||||
|
||||
const SkPoint* positionCursor = glyphRun.positions().data();
|
||||
for (auto glyphID : glyphRun.shuntGlyphsIDs()) {
|
||||
const SkGlyph& glyph = cache->getGlyphMetrics(glyphID, {0, 0});
|
||||
SkPoint glyphPos = origin + *positionCursor++;
|
||||
if (glyph.fMaskFormat == SkMask::kSDF_Format || glyph.isEmpty()) {
|
||||
if (!SkGlyphCacheCommon::GlyphTooBigForAtlas(glyph)) {
|
||||
perSDF(glyph, glyphPos);
|
||||
} else {
|
||||
perPath(glyph, glyphPos);
|
||||
}
|
||||
} else {
|
||||
SkScalar largestDimension = std::max(glyph.fWidth, glyph.fHeight);
|
||||
maxFallbackDimension = std::max(maxFallbackDimension, largestDimension);
|
||||
fARGBGlyphsIDs.push_back(glyphID);
|
||||
fARGBPositions.push_back(glyphPos);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fARGBGlyphsIDs.empty()) {
|
||||
this->processARGBFallback(
|
||||
maxFallbackDimension, glyphRun.paint(), origin, viewMatrix, textScale, argbFallback);
|
||||
}
|
||||
}
|
||||
|
||||
// -- GrTextContext --------------------------------------------------------------------------------
|
||||
GrColor generate_filtered_color(const SkPaint& paint, const GrColorSpaceInfo& colorSpaceInfo) {
|
||||
GrColor4f filteredColor = SkColor4fToUnpremulGrColor4f(paint.getColor4f(), colorSpaceInfo);
|
||||
|
@ -224,4 +224,37 @@ void SkGlyphRunListPainter::drawGlyphRunAsBMPWithPathFallback(
|
||||
this->forEachMappedDrawableGlyph(glyphRun, origin, deviceMatrix, cache, eachGlyph);
|
||||
}
|
||||
|
||||
template <typename PerSDFT, typename PerPathT>
|
||||
void SkGlyphRunListPainter::drawGlyphRunAsSDFWithARGBFallback(
|
||||
SkGlyphCacheInterface* cache, const SkGlyphRun& glyphRun,
|
||||
SkPoint origin, const SkMatrix& viewMatrix, SkScalar textScale,
|
||||
PerSDFT perSDF, PerPathT perPath, ARGBFallback argbFallback) {
|
||||
fARGBGlyphsIDs.clear();
|
||||
fARGBPositions.clear();
|
||||
SkScalar maxFallbackDimension{-SK_ScalarInfinity};
|
||||
|
||||
const SkPoint* positionCursor = glyphRun.positions().data();
|
||||
for (auto glyphID : glyphRun.shuntGlyphsIDs()) {
|
||||
const SkGlyph& glyph = cache->getGlyphMetrics(glyphID, {0, 0});
|
||||
SkPoint glyphPos = origin + *positionCursor++;
|
||||
if (glyph.fMaskFormat == SkMask::kSDF_Format || glyph.isEmpty()) {
|
||||
if (!SkGlyphCacheCommon::GlyphTooBigForAtlas(glyph)) {
|
||||
perSDF(glyph, glyphPos);
|
||||
} else {
|
||||
perPath(glyph, glyphPos);
|
||||
}
|
||||
} else {
|
||||
SkScalar largestDimension = std::max(glyph.fWidth, glyph.fHeight);
|
||||
maxFallbackDimension = std::max(maxFallbackDimension, largestDimension);
|
||||
fARGBGlyphsIDs.push_back(glyphID);
|
||||
fARGBPositions.push_back(glyphPos);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fARGBGlyphsIDs.empty()) {
|
||||
this->processARGBFallback(
|
||||
maxFallbackDimension, glyphRun.paint(), origin, viewMatrix, textScale, argbFallback);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SkGlyphRunPainter_DEFINED
|
||||
|
@ -182,40 +182,6 @@ bool read_path(Deserializer* deserializer, SkGlyph* glyph, SkGlyphCache* cache)
|
||||
return cache->initializePath(glyph, path, pathSize);
|
||||
}
|
||||
|
||||
void add_glyph_to_cache(SkStrikeServer::SkGlyphCacheState* cache, SkTypeface* tf,
|
||||
const SkScalerContextEffects& effects, SkGlyphID glyphID) {
|
||||
SkASSERT(cache != nullptr);
|
||||
|
||||
cache->addGlyph(SkPackedGlyphID(glyphID, 0, 0), false);
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
void add_fallback_text_to_cache(const GrTextContext::FallbackGlyphRunHelper& helper,
|
||||
const SkSurfaceProps& props,
|
||||
const SkMatrix& matrix,
|
||||
const SkPaint& origPaint,
|
||||
SkStrikeServer* server) {
|
||||
if (helper.fallbackText().empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE_EVENT0("skia", "add_fallback_text_to_cache");
|
||||
SkPaint fallbackPaint{origPaint};
|
||||
SkScalar textRatio;
|
||||
SkMatrix fallbackMatrix = matrix;
|
||||
helper.initializeForDraw(&fallbackPaint, &textRatio, &fallbackMatrix);
|
||||
|
||||
SkScalerContextEffects effects;
|
||||
auto* glyphCacheState =
|
||||
server->getOrCreateCache(fallbackPaint, props, fallbackMatrix,
|
||||
SkScalerContextFlags::kFakeGammaAndBoostContrast, &effects);
|
||||
|
||||
for (auto glyphID : helper.fallbackText()) {
|
||||
add_glyph_to_cache(glyphCacheState, fallbackPaint.getTypeface(), effects, glyphID);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const {
|
||||
return key->getChecksum();
|
||||
}
|
||||
@ -267,7 +233,7 @@ void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRun(
|
||||
|
||||
// If the matrix has perspective, we fall back to using distance field text or paths.
|
||||
#if SK_SUPPORT_GPU
|
||||
if (this->maybeProcessGlyphRunForDFT(glyphRun, runMatrix)) {
|
||||
if (this->maybeProcessGlyphRunForDFT(glyphRun, runMatrix, origin)) {
|
||||
return;
|
||||
} else
|
||||
#endif
|
||||
@ -305,6 +271,29 @@ void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRunForMask(
|
||||
glyphCacheState, glyphRun, origin, runMatrix, perGlyph, perPath);
|
||||
}
|
||||
|
||||
struct ARGBHelper {
|
||||
void operator () (const SkPaint& fallbackPaint, SkSpan<const SkGlyphID> glyphIDs,
|
||||
SkSpan<const SkPoint> positions, SkScalar textScale,
|
||||
const SkMatrix& glyphCacheMatrix,
|
||||
SkGlyphRunListPainter::NeedsTransform needsTransform) {
|
||||
TRACE_EVENT0("skia", "argbFallback");
|
||||
|
||||
SkScalerContextEffects effects;
|
||||
auto* fallbackCache =
|
||||
fStrikeServer->getOrCreateCache(
|
||||
fallbackPaint, fSurfaceProps, fFallbackMatrix,
|
||||
SkScalerContextFlags::kFakeGammaAndBoostContrast, &effects);
|
||||
|
||||
for (auto glyphID : glyphIDs) {
|
||||
fallbackCache->addGlyph(SkPackedGlyphID(glyphID, 0, 0), false);
|
||||
}
|
||||
}
|
||||
|
||||
const SkMatrix& fFallbackMatrix;
|
||||
const SkSurfaceProps& fSurfaceProps;
|
||||
SkStrikeServer* const fStrikeServer;
|
||||
};
|
||||
|
||||
void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRunForPaths(
|
||||
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix, SkPoint origin) {
|
||||
TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRunForPaths");
|
||||
@ -323,24 +312,7 @@ void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRunForPaths(
|
||||
glyphCacheState->addGlyph(glyph.getGlyphID(), asPath);
|
||||
};
|
||||
|
||||
auto argbFallback = [this, &runMatrix]
|
||||
(const SkPaint& fallbackPaint, SkSpan<const SkGlyphID> glyphIDs,
|
||||
SkSpan<const SkPoint> positions, SkScalar textScale,
|
||||
const SkMatrix& glyphCacheMatrix,
|
||||
SkGlyphRunListPainter::NeedsTransform needsTransform) {
|
||||
TRACE_EVENT0("skia", "argbFallback_path");
|
||||
SkMatrix fallbackMatrix = runMatrix;
|
||||
|
||||
SkScalerContextEffects effects;
|
||||
auto* glyphCacheState =
|
||||
fStrikeServer->getOrCreateCache(
|
||||
fallbackPaint, surfaceProps(), fallbackMatrix,
|
||||
SkScalerContextFlags::kFakeGammaAndBoostContrast, &effects);
|
||||
|
||||
for (auto glyphID : glyphIDs) {
|
||||
add_glyph_to_cache(glyphCacheState, fallbackPaint.getTypeface(), effects, glyphID);
|
||||
}
|
||||
};
|
||||
ARGBHelper argbFallback{runMatrix, surfaceProps(), fStrikeServer};
|
||||
|
||||
fPainter.drawGlyphRunAsPathWithARGBFallback(
|
||||
glyphCacheState, glyphRun, origin, runMatrix, textScale, perPath, argbFallback);
|
||||
@ -348,7 +320,7 @@ void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRunForPaths(
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
bool SkTextBlobCacheDiffCanvas::TrackLayerDevice::maybeProcessGlyphRunForDFT(
|
||||
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix) {
|
||||
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix, SkPoint origin) {
|
||||
TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::maybeProcessGlyphRunForDFT");
|
||||
|
||||
const SkPaint& runPaint = glyphRun.paint();
|
||||
@ -369,33 +341,29 @@ bool SkTextBlobCacheDiffCanvas::TrackLayerDevice::maybeProcessGlyphRunForDFT(
|
||||
GrTextContext::InitDistanceFieldPaint(nullptr, &dfPaint, runMatrix, options, &textRatio,
|
||||
&flags);
|
||||
SkScalerContextEffects effects;
|
||||
auto* glyphCacheState = fStrikeServer->getOrCreateCache(dfPaint, this->surfaceProps(),
|
||||
auto* sdfCache = fStrikeServer->getOrCreateCache(dfPaint, this->surfaceProps(),
|
||||
SkMatrix::I(), flags, &effects);
|
||||
|
||||
GrTextContext::FallbackGlyphRunHelper fallbackTextHelper(runMatrix, runPaint, textRatio);
|
||||
const bool asPath = false;
|
||||
const SkPoint emptyPosition{0, 0};
|
||||
auto glyphs = glyphRun.shuntGlyphsIDs();
|
||||
for (uint32_t index = 0; index < glyphRun.runSize(); index++) {
|
||||
auto glyphID = glyphs[index];
|
||||
const auto& glyph =
|
||||
glyphCacheState->findGlyph(glyphID);
|
||||
if (glyph.fMaskFormat != SkMask::kSDF_Format && !glyph.isEmpty()) {
|
||||
// Note that we send data for the original glyph even in the case of fallback
|
||||
// since its glyph metrics will still be used on the client.
|
||||
fallbackTextHelper.appendGlyph(glyph, glyphID, emptyPosition);
|
||||
}
|
||||
ARGBHelper argbFallback{runMatrix, surfaceProps(), fStrikeServer};
|
||||
|
||||
glyphCacheState->addGlyph(SkPackedGlyphID(glyphs[index]), asPath);
|
||||
}
|
||||
auto perSDF = [sdfCache] (const SkGlyph& glyph, SkPoint position) {
|
||||
const bool asPath = false;
|
||||
sdfCache->addGlyph(glyph.getGlyphID(), asPath);
|
||||
};
|
||||
|
||||
auto perPath = [sdfCache] (const SkGlyph& glyph, SkPoint position) {
|
||||
const bool asPath = true;
|
||||
sdfCache->addGlyph(glyph.getGlyphID(), asPath);
|
||||
};
|
||||
|
||||
fPainter.drawGlyphRunAsSDFWithARGBFallback(
|
||||
sdfCache, glyphRun, origin, runMatrix, textRatio,
|
||||
perSDF, perPath, argbFallback);
|
||||
|
||||
add_fallback_text_to_cache(fallbackTextHelper, this->surfaceProps(), runMatrix, runPaint,
|
||||
fStrikeServer);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// -- SkTextBlobCacheDiffCanvas -------------------------------------------------------------------
|
||||
SkTextBlobCacheDiffCanvas::Settings::Settings() = default;
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "SkDescriptor.h"
|
||||
#include "SkGlyphRun.h"
|
||||
#include "SkGlyphRunPainter.h"
|
||||
#include "SkRemoteGlyphCache.h"
|
||||
|
||||
class SkStrikeServer::SkGlyphCacheState : public SkGlyphCacheInterface {
|
||||
@ -104,7 +105,8 @@ private:
|
||||
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix, SkPoint origin);
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
bool maybeProcessGlyphRunForDFT(const SkGlyphRun& glyphRun, const SkMatrix& runMatrix);
|
||||
bool maybeProcessGlyphRunForDFT(
|
||||
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix, SkPoint origin);
|
||||
#endif
|
||||
|
||||
SkStrikeServer* const fStrikeServer;
|
||||
|
@ -200,94 +200,6 @@ void GrTextContext::InitDistanceFieldPaint(GrTextBlob* blob,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Fallback uses a fast strategy and a general strategy. If the viewMatrix is only scale and
|
||||
// translate, and all the glyphs in the run are small enough, then the font uses the runPaint for
|
||||
// the size of the colored glyph, and the positions are all transformed. In the general case,
|
||||
// a suitable font size is found, and the view transformation happens during rendering. The font
|
||||
// in the general case is oriented with x and y, and all rotations, scaling, etc. happen during
|
||||
// rendering.
|
||||
|
||||
GrTextContext::FallbackGlyphRunHelper::FallbackGlyphRunHelper(
|
||||
const SkMatrix& viewMatrix, const SkPaint& runPaint, SkScalar textRatio)
|
||||
: fViewMatrix(viewMatrix)
|
||||
, fTextSize(runPaint.getTextSize())
|
||||
, fMaxTextSize(SkGlyphCacheCommon::kSkSideTooBigForAtlas)
|
||||
, fTextRatio(textRatio)
|
||||
, fTransformedFallbackTextSize(fMaxTextSize)
|
||||
, fMaxScale(viewMatrix.getMaxScale())
|
||||
, fUseTransformedFallback(false) { }
|
||||
|
||||
void GrTextContext::FallbackGlyphRunHelper::appendGlyph(
|
||||
const SkGlyph& glyph, SkGlyphID glyphID, SkPoint glyphPos) {
|
||||
SkScalar maxDim = SkTMax(glyph.fWidth, glyph.fHeight)*fTextRatio;
|
||||
if (SkScalarNearlyZero(maxDim)) return;
|
||||
|
||||
if (!fUseTransformedFallback) {
|
||||
if (!fViewMatrix.isScaleTranslate() || maxDim*fMaxScale > fMaxTextSize) {
|
||||
fUseTransformedFallback = true;
|
||||
fMaxTextSize -= 2; // Subtract 2 to account for the bilerp pad around the glyph
|
||||
}
|
||||
}
|
||||
|
||||
if (fUseTransformedFallback) {
|
||||
// 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 glyphTextSize =
|
||||
SkTMax(SkScalarFloorToScalar(fTextSize * fMaxTextSize/maxDim), 0.5f*fMaxTextSize);
|
||||
fTransformedFallbackTextSize = SkTMin(glyphTextSize, fTransformedFallbackTextSize);
|
||||
}
|
||||
fFallbackTxt.push_back(glyphID);
|
||||
fFallbackPos.push_back(glyphPos);
|
||||
}
|
||||
|
||||
void GrTextContext::FallbackGlyphRunHelper::drawGlyphs(
|
||||
GrTextBlob* blob, int runIndex, GrGlyphCache* glyphCache, const SkSurfaceProps& props,
|
||||
const SkPaint& paint, GrColor filteredColor, SkScalerContextFlags scalerContextFlags) {
|
||||
if (!fFallbackTxt.empty()) {
|
||||
blob->initOverride(runIndex);
|
||||
blob->setHasBitmap();
|
||||
blob->setSubRunHasW(runIndex, fViewMatrix.hasPerspective());
|
||||
const SkPaint& skPaint = paint;
|
||||
SkColor textColor = filteredColor;
|
||||
|
||||
SkScalar textRatio = SK_Scalar1;
|
||||
SkPaint fallbackPaint(skPaint);
|
||||
SkMatrix matrix = fViewMatrix;
|
||||
this->initializeForDraw(&fallbackPaint, &textRatio, &matrix);
|
||||
SkExclusiveStrikePtr cache =
|
||||
blob->setupCache(runIndex, props, scalerContextFlags, fallbackPaint, &matrix);
|
||||
|
||||
sk_sp<GrTextStrike> currStrike = glyphCache->getStrike(cache.get());
|
||||
auto glyphPos = fFallbackPos.begin();
|
||||
for (auto glyphID : fFallbackTxt) {
|
||||
const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphID);
|
||||
if (!fUseTransformedFallback) {
|
||||
fViewMatrix.mapPoints(&*glyphPos, 1);
|
||||
glyphPos->fX = SkScalarFloorToScalar(glyphPos->fX);
|
||||
glyphPos->fY = SkScalarFloorToScalar(glyphPos->fY);
|
||||
}
|
||||
GrTextContext::AppendGlyph(blob, runIndex, currStrike,
|
||||
glyph, GrGlyph::kCoverage_MaskStyle,
|
||||
glyphPos->fX, glyphPos->fY, textColor,
|
||||
cache.get(), textRatio, fUseTransformedFallback);
|
||||
glyphPos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrTextContext::FallbackGlyphRunHelper::initializeForDraw(
|
||||
SkPaint* paint, SkScalar* textRatio, SkMatrix* matrix) const {
|
||||
if (!fUseTransformedFallback) return;
|
||||
|
||||
paint->setTextSize(fTransformedFallbackTextSize);
|
||||
*textRatio = fTextSize / fTransformedFallbackTextSize;
|
||||
*matrix = SkMatrix::I();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#if GR_TEST_UTILS
|
||||
|
||||
|
@ -68,33 +68,6 @@ public:
|
||||
SkScalar* textRatio,
|
||||
SkScalerContextFlags* flags);
|
||||
|
||||
class FallbackGlyphRunHelper {
|
||||
public:
|
||||
FallbackGlyphRunHelper(
|
||||
const SkMatrix& viewMatrix, const SkPaint& runPaint, SkScalar textRatio);
|
||||
|
||||
void appendGlyph(const SkGlyph& glyph, SkGlyphID glyphID, SkPoint glyphPos);
|
||||
void drawGlyphs(
|
||||
GrTextBlob* blob, int runIndex, GrGlyphCache* cache,
|
||||
const SkSurfaceProps& props, const SkPaint& runPaint, GrColor filteredColor,
|
||||
SkScalerContextFlags scalerContextFlags);
|
||||
|
||||
void initializeForDraw(SkPaint* paint, SkScalar* textRatio, SkMatrix* matrix) const;
|
||||
const std::vector<SkGlyphID>& fallbackText() const { return fFallbackTxt; }
|
||||
|
||||
private:
|
||||
std::vector<SkGlyphID> fFallbackTxt;
|
||||
std::vector<SkPoint> fFallbackPos;
|
||||
|
||||
const SkMatrix& fViewMatrix;
|
||||
SkScalar fTextSize;
|
||||
SkScalar fMaxTextSize{SkGlyphCacheCommon::kSkSideTooBigForAtlas};
|
||||
SkScalar fTextRatio;
|
||||
SkScalar fTransformedFallbackTextSize;
|
||||
SkScalar fMaxScale;
|
||||
bool fUseTransformedFallback;
|
||||
};
|
||||
|
||||
private:
|
||||
GrTextContext(const Options& options);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user