codify SDFT matrix range

Since the introduction of canReuse on a per-run basis, we have
not revisited how SDFT reuse is handled. Abandon the less precise
per GrTextBlob calculation for handling matrix range calculations on
the SubRun.

Change-Id: Ib943b97b2184da1abedbe6851200e6487908bad0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/502696
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2022-02-01 11:51:21 -05:00 committed by SkCQ
parent 53acf74030
commit 1e0b3b7973
8 changed files with 79 additions and 112 deletions

View File

@ -287,7 +287,7 @@ void SkGlyphRunListPainter::processGlyphRun(SkGlyphRunPainterInterface* process,
if (control.isSDFT(approximateDeviceTextSize, runPaint)) { if (control.isSDFT(approximateDeviceTextSize, runPaint)) {
// Process SDFT - This should be the .009% case. // Process SDFT - This should be the .009% case.
const auto& [strikeSpec, strikeToSourceScale, minScale, maxScale] = const auto& [strikeSpec, strikeToSourceScale, matrixRange] =
SkStrikeSpec::MakeSDFT(runFont, runPaint, fDeviceProps, drawMatrix, control); SkStrikeSpec::MakeSDFT(runFont, runPaint, fDeviceProps, drawMatrix, control);
#if defined(SK_TRACE_GLYPH_RUN_PROCESS) #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
@ -311,7 +311,7 @@ void SkGlyphRunListPainter::processGlyphRun(SkGlyphRunPainterInterface* process,
strike->getUnderlyingStrike(), strike->getUnderlyingStrike(),
strikeToSourceScale, strikeToSourceScale,
runFont, runFont,
minScale, maxScale); matrixRange);
} }
} }
} }

View File

@ -23,6 +23,7 @@ namespace skgpu { namespace v1 { class SurfaceDrawContext; }}
class SkGlyphRunPainterInterface; class SkGlyphRunPainterInterface;
class SkStrikeSpec; class SkStrikeSpec;
class GrSDFTMatrixRange;
// round and ignorePositionMask are used to calculate the subpixel position of a glyph. // round and ignorePositionMask are used to calculate the subpixel position of a glyph.
// The per component (x or y) calculation is: // The per component (x or y) calculation is:
@ -149,8 +150,7 @@ public:
sk_sp<SkStrike>&& strike, sk_sp<SkStrike>&& strike,
SkScalar strikeToSourceScale, SkScalar strikeToSourceScale,
const SkFont& runFont, const SkFont& runFont,
SkScalar minScale, const GrSDFTMatrixRange& matrixRange) = 0;
SkScalar maxScale) = 0;
}; };
#endif // SkGlyphRunPainter_DEFINED #endif // SkGlyphRunPainter_DEFINED

View File

@ -171,25 +171,22 @@ SkStrikeSpec SkStrikeSpec::MakePDFVector(const SkTypeface& typeface, int* size)
} }
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
std::tuple<SkStrikeSpec, SkScalar, SkScalar, SkScalar> std::tuple<SkStrikeSpec, SkScalar, GrSDFTMatrixRange>
SkStrikeSpec::MakeSDFT(const SkFont& font, const SkPaint& paint, SkStrikeSpec::MakeSDFT(const SkFont& font, const SkPaint& paint,
const SkSurfaceProps& surfaceProps, const SkMatrix& deviceMatrix, const SkSurfaceProps& surfaceProps, const SkMatrix& deviceMatrix,
const GrSDFTControl& control) { const GrSDFTControl& control) {
// Add filter to the paint which creates the SDFT data for A8 masks.
SkPaint dfPaint{paint}; SkPaint dfPaint{paint};
dfPaint.setMaskFilter(GrSDFMaskFilter::Make()); dfPaint.setMaskFilter(GrSDFMaskFilter::Make());
SkScalar strikeToSourceScale;
SkFont dfFont = control.getSDFFont(font, deviceMatrix, &strikeToSourceScale); auto [dfFont, strikeToSourceScale, matrixRange] = control.getSDFFont(font, deviceMatrix);
// Fake-gamma and subpixel antialiasing are applied in the shader, so we ignore the // Fake-gamma and subpixel antialiasing are applied in the shader, so we ignore the
// passed-in scaler context flags. (It's only used when we fall-back to bitmap text). // passed-in scaler context flags. (It's only used when we fall-back to bitmap text).
SkScalerContextFlags flags = SkScalerContextFlags::kNone; SkScalerContextFlags flags = SkScalerContextFlags::kNone;
SkScalar minScale, maxScale;
std::tie(minScale, maxScale) = control.computeSDFMinMaxScale(font.getSize(), deviceMatrix);
SkStrikeSpec strikeSpec(dfFont, dfPaint, surfaceProps, flags, SkMatrix::I()); SkStrikeSpec strikeSpec(dfFont, dfPaint, surfaceProps, flags, SkMatrix::I());
return std::make_tuple(std::move(strikeSpec), strikeToSourceScale, minScale, maxScale); return std::make_tuple(std::move(strikeSpec), strikeToSourceScale, matrixRange);
} }
sk_sp<GrTextStrike> SkStrikeSpec::findOrCreateGrStrike(GrStrikeCache* cache) const { sk_sp<GrTextStrike> SkStrikeSpec::findOrCreateGrStrike(GrStrikeCache* cache) const {

View File

@ -71,7 +71,7 @@ public:
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
// Create a strike spec for scaled distance field text. // Create a strike spec for scaled distance field text.
static std::tuple<SkStrikeSpec, SkScalar, SkScalar, SkScalar> MakeSDFT( static std::tuple<SkStrikeSpec, SkScalar, GrSDFTMatrixRange> MakeSDFT(
const SkFont& font, const SkFont& font,
const SkPaint& paint, const SkPaint& paint,
const SkSurfaceProps& surfaceProps, const SkSurfaceProps& surfaceProps,

View File

@ -20,19 +20,16 @@
// DF sizes and thresholds for usage of the small and medium sizes. For example, above // DF sizes and thresholds for usage of the small and medium sizes. For example, above
// kSmallDFFontLimit we will use the medium size. The large size is used up until the size at // kSmallDFFontLimit we will use the medium size. The large size is used up until the size at
// which we switch over to drawing as paths as controlled by Control. // which we switch over to drawing as paths as controlled by Control.
static const int kSmallDFFontSize = 32;
static const int kSmallDFFontLimit = 32; static const int kSmallDFFontLimit = 32;
static const int kMediumDFFontSize = 72;
static const int kMediumDFFontLimit = 72; static const int kMediumDFFontLimit = 72;
static const int kLargeDFFontSize = 162;
#ifdef SK_BUILD_FOR_MAC
static const int kLargeDFFontLimit = 162; static const int kLargeDFFontLimit = 162;
static const int kExtraLargeDFFontSize = 256; #ifdef SK_BUILD_FOR_MAC
static const int kExtraLargeDFFontLimit = 256;
#endif #endif
SkScalar GrSDFTControl::MinSDFTRange(bool useSDFTForSmallText, SkScalar min) { SkScalar GrSDFTControl::MinSDFTRange(bool useSDFTForSmallText, SkScalar min) {
if (!useSDFTForSmallText) { if (!useSDFTForSmallText) {
return kLargeDFFontSize; return kLargeDFFontLimit;
} }
return min; return min;
} }
@ -78,51 +75,13 @@ SkScalar scaled_text_size(const SkScalar textSize, const SkMatrix& viewMatrix) {
return scaledTextSize; return scaledTextSize;
} }
SkFont GrSDFTControl::getSDFFont(const SkFont& font, std::tuple<SkFont, SkScalar, GrSDFTMatrixRange>
const SkMatrix& viewMatrix, GrSDFTControl::getSDFFont(const SkFont& font, const SkMatrix& viewMatrix) const {
SkScalar* textRatio) const {
SkScalar textSize = font.getSize(); SkScalar textSize = font.getSize();
SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix); SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix);
SkFont dfFont{font}; SkFont dfFont{font};
if (scaledTextSize <= kSmallDFFontLimit) {
*textRatio = textSize / kSmallDFFontSize;
dfFont.setSize(SkIntToScalar(kSmallDFFontSize));
} else if (scaledTextSize <= kMediumDFFontLimit) {
*textRatio = textSize / kMediumDFFontSize;
dfFont.setSize(SkIntToScalar(kMediumDFFontSize));
#ifdef SK_BUILD_FOR_MAC
} else if (scaledTextSize <= kLargeDFFontLimit) {
*textRatio = textSize / kLargeDFFontSize;
dfFont.setSize(SkIntToScalar(kLargeDFFontSize));
} else {
*textRatio = textSize / kExtraLargeDFFontSize;
dfFont.setSize(SkIntToScalar(kExtraLargeDFFontSize));
}
#else
} else {
*textRatio = textSize / kLargeDFFontSize;
dfFont.setSize(SkIntToScalar(kLargeDFFontSize));
}
#endif
dfFont.setEdging(SkFont::Edging::kAntiAlias);
dfFont.setForceAutoHinting(false);
dfFont.setHinting(SkFontHinting::kNormal);
// The sub-pixel position will always happen when transforming to the screen.
dfFont.setSubpixel(false);
return dfFont;
}
std::pair<SkScalar, SkScalar> GrSDFTControl::computeSDFMinMaxScale(
SkScalar textSize, const SkMatrix& viewMatrix) const {
SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix);
// We have three sizes of distance field text, and within each size 'bucket' there is a floor
// and ceiling. A scale outside of this range would require regenerating the distance fields
SkScalar dfMaskScaleFloor; SkScalar dfMaskScaleFloor;
SkScalar dfMaskScaleCeil; SkScalar dfMaskScaleCeil;
if (scaledTextSize <= kSmallDFFontLimit) { if (scaledTextSize <= kSmallDFFontLimit) {
@ -131,21 +90,35 @@ std::pair<SkScalar, SkScalar> GrSDFTControl::computeSDFMinMaxScale(
} else if (scaledTextSize <= kMediumDFFontLimit) { } else if (scaledTextSize <= kMediumDFFontLimit) {
dfMaskScaleFloor = kSmallDFFontLimit; dfMaskScaleFloor = kSmallDFFontLimit;
dfMaskScaleCeil = kMediumDFFontLimit; dfMaskScaleCeil = kMediumDFFontLimit;
#ifdef SK_BUILD_FOR_MAC
} else if (scaledTextSize <= kLargeDFFontLimit) {
dfMaskScaleFloor = kMediumDFFontLimit;
dfMaskScaleCeil = kLargeDFFontLimit;
} else {
dfMaskScaleFloor = kLargeDFFontLimit;
dfMaskScaleCeil = kExtraLargeDFFontLimit;
}
#else
} else { } else {
dfMaskScaleFloor = kMediumDFFontLimit; dfMaskScaleFloor = kMediumDFFontLimit;
dfMaskScaleCeil = fMaxDistanceFieldFontSize; dfMaskScaleCeil = kLargeDFFontLimit;
}
#endif
dfFont.setSize(SkIntToScalar(dfMaskScaleCeil));
dfFont.setEdging(SkFont::Edging::kAntiAlias);
dfFont.setForceAutoHinting(false);
dfFont.setHinting(SkFontHinting::kNormal);
// The sub-pixel position will always happen when transforming to the screen.
dfFont.setSubpixel(false);
SkScalar minMatrixScale = dfMaskScaleFloor / textSize,
maxMatrixScale = dfMaskScaleCeil / textSize;
return {dfFont, textSize / dfMaskScaleCeil, {minMatrixScale, maxMatrixScale}};
} }
// Because there can be multiple runs in the blob, we want the overall maxMinScale, and bool GrSDFTMatrixRange::matrixInRange(const SkMatrix& matrix) const {
// minMaxScale to make regeneration decisions. Specifically, we want the maximum minimum scale SkScalar maxScale = matrix.getMaxScale();
// we can tolerate before we'd drop to a lower mip size, and the minimum maximum scale we can return fMatrixMin < maxScale && maxScale <= fMatrixMax;
// tolerate before we'd have to move to a large mip size. When we actually test these values
// we look at the delta in scale between the new viewmatrix and the old viewmatrix, and test
// against these values to decide if we can reuse or not(ie, will a given scale change our mip
// level)
SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil);
return std::make_pair(dfMaskScaleFloor / scaledTextSize, dfMaskScaleCeil / scaledTextSize);
} }

View File

@ -11,18 +11,31 @@
#include "include/core/SkFont.h" #include "include/core/SkFont.h"
#include "include/core/SkScalar.h" #include "include/core/SkScalar.h"
#include <tuple>
class SkMatrix; class SkMatrix;
class SkSurfaceProps; class SkSurfaceProps;
// Two numbers fMatrixMin and fMatrixMax such that if viewMatrix.getMaxScale() is between them then
// this SDFT size can be reused.
class GrSDFTMatrixRange {
public:
GrSDFTMatrixRange(SkScalar min, SkScalar max) : fMatrixMin{min}, fMatrixMax{max} {}
bool matrixInRange(const SkMatrix& matrix) const;
private:
const SkScalar fMatrixMin,
fMatrixMax;
};
class GrSDFTControl { class GrSDFTControl {
public: public:
GrSDFTControl(bool ableToUseSDFT, bool useSDFTForSmallText, SkScalar min, SkScalar max); GrSDFTControl(bool ableToUseSDFT, bool useSDFTForSmallText, SkScalar min, SkScalar max);
SkFont getSDFFont(const SkFont& font, // Produce a font, a scale factor from the nominal size to the source space size, and matrix
const SkMatrix& viewMatrix, // range where this font can be reused.
SkScalar* textRatio) const; std::tuple<SkFont, SkScalar, GrSDFTMatrixRange>
std::pair<SkScalar, SkScalar> computeSDFMinMaxScale( getSDFFont(const SkFont& font, const SkMatrix& viewMatrix) const;
SkScalar textSize, const SkMatrix& viewMatrix) const;
bool isDirect(SkScalar approximateDeviceTextSize, const SkPaint& paint) const; bool isDirect(SkScalar approximateDeviceTextSize, const SkPaint& paint) const;
bool isSDFT(SkScalar approximateDeviceTextSize, const SkPaint& paint) const; bool isSDFT(SkScalar approximateDeviceTextSize, const SkPaint& paint) const;

View File

@ -1277,12 +1277,14 @@ public:
SkSpan<const VertexData> vertexData, SkSpan<const VertexData> vertexData,
GlyphVector&& glyphs, GlyphVector&& glyphs,
bool useLCDText, bool useLCDText,
bool antiAliased); bool antiAliased,
const GrSDFTMatrixRange& matrixRange);
static GrSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables, static GrSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
const SkFont& runFont, const SkFont& runFont,
sk_sp<SkStrike>&& strike, sk_sp<SkStrike>&& strike,
SkScalar strikeToSourceScale, SkScalar strikeToSourceScale,
const GrSDFTMatrixRange& matrixRange,
GrTextBlob* blob, GrTextBlob* blob,
GrSubRunAllocator* alloc); GrSubRunAllocator* alloc);
@ -1339,6 +1341,7 @@ private:
const bool fUseLCDText; const bool fUseLCDText;
const bool fAntiAliased; const bool fAntiAliased;
const GrSDFTMatrixRange fMatrixRange;
}; };
SDFTSubRun::SDFTSubRun(GrMaskFormat format, SDFTSubRun::SDFTSubRun(GrMaskFormat format,
@ -1348,7 +1351,8 @@ SDFTSubRun::SDFTSubRun(GrMaskFormat format,
SkSpan<const VertexData> vertexData, SkSpan<const VertexData> vertexData,
GlyphVector&& glyphs, GlyphVector&& glyphs,
bool useLCDText, bool useLCDText,
bool antiAliased) bool antiAliased,
const GrSDFTMatrixRange& matrixRange)
: fMaskFormat{format} : fMaskFormat{format}
, fBlob{textBlob} , fBlob{textBlob}
, fStrikeToSourceScale{strikeToSource} , fStrikeToSourceScale{strikeToSource}
@ -1356,7 +1360,8 @@ SDFTSubRun::SDFTSubRun(GrMaskFormat format,
, fVertexData{vertexData} , fVertexData{vertexData}
, fGlyphs{std::move(glyphs)} , fGlyphs{std::move(glyphs)}
, fUseLCDText{useLCDText} , fUseLCDText{useLCDText}
, fAntiAliased{antiAliased} {} , fAntiAliased{antiAliased}
, fMatrixRange{matrixRange} {}
bool has_some_antialiasing(const SkFont& font ) { bool has_some_antialiasing(const SkFont& font ) {
SkFont::Edging edging = font.getEdging(); SkFont::Edging edging = font.getEdging();
@ -1368,6 +1373,7 @@ GrSubRunOwner SDFTSubRun::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
const SkFont& runFont, const SkFont& runFont,
sk_sp<SkStrike>&& strike, sk_sp<SkStrike>&& strike,
SkScalar strikeToSourceScale, SkScalar strikeToSourceScale,
const GrSDFTMatrixRange& matrixRange,
GrTextBlob* blob, GrTextBlob* blob,
GrSubRunAllocator* alloc) { GrSubRunAllocator* alloc) {
SkRect bounds = SkRectPriv::MakeLargestInverted(); SkRect bounds = SkRectPriv::MakeLargestInverted();
@ -1395,7 +1401,8 @@ GrSubRunOwner SDFTSubRun::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
vertexData, vertexData,
GlyphVector::Make(std::move(strike), drawables.get<0>(), alloc), GlyphVector::Make(std::move(strike), drawables.get<0>(), alloc),
runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias, runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias,
has_some_antialiasing(runFont)); has_some_antialiasing(runFont),
matrixRange);
} }
void SDFTSubRun::draw(SkCanvas*, void SDFTSubRun::draw(SkCanvas*,
@ -1481,18 +1488,7 @@ SDFTSubRun::makeAtlasTextOp(const GrClip* clip,
} }
bool SDFTSubRun::canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const { bool SDFTSubRun::canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const {
const SkMatrix& initialPositionMatrix = fBlob->initialPositionMatrix(); return fMatrixRange.matrixInRange(positionMatrix);
// A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would result in a different
// distance field being generated, so we have to regenerate in those cases
SkScalar newMaxScale = positionMatrix.getMaxScale();
SkScalar oldMaxScale = initialPositionMatrix.getMaxScale();
SkScalar scaleAdjust = newMaxScale / oldMaxScale;
auto [maxMinScale, minMaxScale] = fBlob->scaleBounds();
if (scaleAdjust < maxMinScale || scaleAdjust > minMaxScale) {
return false;
}
return true;
} }
void SDFTSubRun::testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) const { void SDFTSubRun::testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) const {
@ -1848,13 +1844,10 @@ void GrTextBlob::processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawabl
sk_sp<SkStrike>&& strike, sk_sp<SkStrike>&& strike,
SkScalar strikeToSourceScale, SkScalar strikeToSourceScale,
const SkFont& runFont, const SkFont& runFont,
SkScalar minScale, const GrSDFTMatrixRange& matrixRange) {
SkScalar maxScale) {
fMaxMinScale = std::max(minScale, fMaxMinScale);
fMinMaxScale = std::min(maxScale, fMinMaxScale);
fSubRunList.append( fSubRunList.append(
SDFTSubRun::Make(drawables, runFont, std::move(strike), strikeToSourceScale,this, &fAlloc)); SDFTSubRun::Make(
drawables, runFont, std::move(strike), strikeToSourceScale, matrixRange, this,&fAlloc));
} }
void GrTextBlob::processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables, void GrTextBlob::processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
@ -2560,7 +2553,7 @@ void GrSubRunNoCachePainter::processSourceSDFT(const SkZip<SkGlyphVariant, SkPoi
sk_sp<SkStrike>&& strike, sk_sp<SkStrike>&& strike,
SkScalar strikeToSourceScale, SkScalar strikeToSourceScale,
const SkFont& runFont, const SkFont& runFont,
SkScalar minScale, SkScalar maxScale) { const GrSDFTMatrixRange&) {
if (drawables.empty()) { if (drawables.empty()) {
return; return;
} }
@ -2615,8 +2608,8 @@ public:
SkScalar strikeToSourceScale) override; SkScalar strikeToSourceScale) override;
void processSourceSDFT( void processSourceSDFT(
const SkZip<SkGlyphVariant, SkPoint>& drawables, sk_sp<SkStrike>&& strike, const SkZip<SkGlyphVariant, SkPoint>& drawables, sk_sp<SkStrike>&& strike,
SkScalar strikeToSourceScale, const SkFont& runFont, SkScalar minScale, SkScalar strikeToSourceScale, const SkFont& runFont,
SkScalar maxScale) override; const GrSDFTMatrixRange& matrixRange) override;
const SkMatrix& initialPositionMatrix() const override { return fInitialPositionMatrix; } const SkMatrix& initialPositionMatrix() const override { return fInitialPositionMatrix; }
SkPoint origin() const { return fOrigin; } SkPoint origin() const { return fOrigin; }
@ -3321,8 +3314,7 @@ void Slug::processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
sk_sp<SkStrike>&& strike, sk_sp<SkStrike>&& strike,
SkScalar strikeToSourceScale, SkScalar strikeToSourceScale,
const SkFont& runFont, const SkFont& runFont,
SkScalar minScale, const GrSDFTMatrixRange&) {
SkScalar maxScale) {
fSubRuns.append(SDFTSubRunSlug::Make( fSubRuns.append(SDFTSubRunSlug::Make(
this, drawables, runFont, std::move(strike), strikeToSourceScale, &fAlloc)); this, drawables, runFont, std::move(strike), strikeToSourceScale, &fAlloc));

View File

@ -224,7 +224,6 @@ public:
const SkMatrix& initialPositionMatrix() const override { return fInitialPositionMatrix; } const SkMatrix& initialPositionMatrix() const override { return fInitialPositionMatrix; }
bool supportBilerpAtlas() const { return fSupportBilerpAtlas; } bool supportBilerpAtlas() const { return fSupportBilerpAtlas; }
std::tuple<SkScalar, SkScalar> scaleBounds() const { return {fMaxMinScale, fMinMaxScale}; }
bool canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const; bool canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const;
const Key& key() const; const Key& key() const;
@ -254,8 +253,7 @@ private:
sk_sp<SkStrike>&& strike, sk_sp<SkStrike>&& strike,
SkScalar strikeToSourceScale, SkScalar strikeToSourceScale,
const SkFont& runFont, const SkFont& runFont,
SkScalar minScale, const GrSDFTMatrixRange& matrixRange) override;
SkScalar maxScale) override;
void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables, void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
sk_sp<SkStrike>&& strike, sk_sp<SkStrike>&& strike,
SkScalar strikeToSourceScale) override; SkScalar strikeToSourceScale) override;
@ -281,12 +279,6 @@ private:
Key fKey; Key fKey;
// We can reuse distance field text, but only if the new view matrix would not result in
// a mip change. Because there can be multiple runs in a blob, we track the overall
// maximum minimum scale, and minimum maximum scale, we can support before we need to regen
SkScalar fMaxMinScale{-SK_ScalarMax};
SkScalar fMinMaxScale{SK_ScalarMax};
bool fSomeGlyphsExcluded{false}; bool fSomeGlyphsExcluded{false};
}; };
@ -311,7 +303,7 @@ public:
sk_sp<SkStrike>&& strike, sk_sp<SkStrike>&& strike,
SkScalar strikeToSourceScale, SkScalar strikeToSourceScale,
const SkFont& runFont, const SkFont& runFont,
SkScalar minScale, SkScalar maxScale) override; const GrSDFTMatrixRange& matrixRange) override;
private: private: