Inline fallback code

Change-Id: I49adc018dc4b486edb7be8aa55f86f248bb39c83
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/251212
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2019-10-28 12:21:17 -04:00 committed by Skia Commit-Bot
parent aacbd44cad
commit 9e1909f03d

View File

@ -122,94 +122,6 @@ void SkGlyphRunListPainter::drawForBitmapDevice(
}
}
// Getting glyphs to the screen in a fallback situation can be complex. Here is the set of
// transformations that have to happen. Normally, they would all be accommodated by the font
// scaler, but the atlas has an upper limit to the glyphs it can handle. So the GPU is used to
// make up the difference from the smaller atlas size to the larger size needed by the final
// transform. Here are the transformations that are applied.
//
// final transform = [view matrix] * [text scale] * [text size]
//
// There are three cases:
// * Go Fast - view matrix is scale and translate, and all the glyphs are small enough
// Just scale the positions, and have the glyph cache handle the view matrix transformation.
// The text scale is 1.
// * It's complicated - view matrix is not scale and translate, and the glyphs are small enough
// The glyph cache does not handle the view matrix, but stores the glyphs at the text size
// specified by the run paint. The GPU handles the rotation, etc. specified by the view matrix.
// The text scale is 1.
// * Too big - The glyphs are too big to fit in the atlas
// Reduce the text size so the glyphs will fit in the atlas, but don't apply any
// 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 maxSourceGlyphDimension,
const SkPaint& runPaint,
const SkFont& runFont,
SkPoint origin,
const SkMatrix& viewMatrix,
SkGlyphRunPainterInterface* process) {
// if maxSourceGlyphDimension then no pixels will change.
if (maxSourceGlyphDimension == 0) { return; }
SkScalar maxScale = viewMatrix.getMaxScale();
// 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
// in the useFastPath case.
bool useDeviceCache =
viewMatrix.isScaleTranslate()
&& conservativeMaxGlyphDimension <= SkStrikeCommon::kSkSideTooBigForAtlas;
// A scaled and translated transform is the common case, and is handled directly in fallback.
// Even if the transform is scale and translate, fallback must be careful to use glyphs that
// fit in the atlas. If a glyph will not fit in the atlas, then the general transform case is
// used to render the glyphs.
if (useDeviceCache) {
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeMask(
runFont, runPaint, fDeviceProps, fScalerContextFlags, viewMatrix);
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
fDrawable.startDevice(fRejects.source(), origin, viewMatrix, strike->roundingSpec());
strike->prepareForMaskDrawing(&fDrawable, &fRejects);
// There better not be any rejects.
fRejects.flipRejectsToSource();
SkASSERT(fRejects.source().empty());
if (process) {
process->processDeviceFallback(fDrawable.drawable(), strikeSpec);
}
} else {
// If the matrix is complicated or if scaling is used to fit the glyphs in the cache,
// then this case is used.
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeSourceFallback(
runFont, runPaint, fDeviceProps, fScalerContextFlags, maxSourceGlyphDimension);
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
fDrawable.startSource(fRejects.source(), origin);
strike->prepareForMaskDrawing(&fDrawable, &fRejects);
// There better not be any rejects.
fRejects.flipRejectsToSource();
SkASSERT(fRejects.source().empty());
if (process) {
process->processSourceFallback(
fDrawable.drawable(),
strikeSpec,
viewMatrix.hasPerspective());
}
}
}
#if SK_SUPPORT_GPU
void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunList,
const SkMatrix& viewMatrix,
@ -302,10 +214,88 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
}
}
// Handle fallback for all cases.
if (!fRejects.source().empty()) {
this->processARGBFallback(
maxDimensionInSourceSpace, runPaint, runFont, origin, viewMatrix, process);
// Getting glyphs to the screen in a fallback situation can be complex. Here is the set of
// transformations that have to happen. Normally, they would all be accommodated by the font
// scaler, but the atlas has an upper limit to the glyphs it can handle. So the GPU is used
// to make up the difference from the smaller atlas size to the larger size needed by the
// final transform. Here are the transformations that are applied.
//
// final transform = [view matrix] * [text scale] * [text size]
//
// There are three cases:
// * Go Fast - view matrix is scale and translate, and all the glyphs are small enough
// Just scale the positions, and have the glyph cache handle the view matrix
// transformation.
// The text scale is 1.
// * It's complicated - view matrix is not scale and translate, and the glyphs are small
// enough The glyph cache does not handle the view matrix, but stores the glyphs at the
// text size specified by the run paint. The GPU handles the rotation, etc. specified
// by the view matrix.
// The text scale is 1.
// * Too big - The glyphs are too big to fit in the atlas
// Reduce the text size so the glyphs will fit in the atlas, but don't apply any
// 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.
if (!fRejects.source().empty() && maxDimensionInSourceSpace != 0) {
SkScalar maxScale = viewMatrix.getMaxScale();
// This is a linear estimate of the longest dimension among all the glyph widths and
// heights.
SkScalar conservativeMaxGlyphDimension = maxDimensionInSourceSpace * 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 in the useFastPath case.
bool useDeviceCache =
viewMatrix.isScaleTranslate()
&& conservativeMaxGlyphDimension <= SkStrikeCommon::kSkSideTooBigForAtlas;
// A scaled and translated transform is the common case, and is handled directly in
// fallback. Even if the transform is scale and translate, fallback must be careful
// to use glyphs that fit in the atlas. If a glyph will not fit in the atlas, then
// the general transform case is used to render the glyphs.
if (useDeviceCache) {
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeMask(
runFont, runPaint, fDeviceProps, fScalerContextFlags, viewMatrix);
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
fDrawable.startDevice(
fRejects.source(), origin, viewMatrix, strike->roundingSpec());
strike->prepareForMaskDrawing(&fDrawable, &fRejects);
fRejects.flipRejectsToSource();
SkASSERT(fRejects.source().empty());
if (process) {
process->processDeviceFallback(fDrawable.drawable(), strikeSpec);
}
} else {
// If the matrix is complicated or if scaling is used to fit the glyphs in the
// atlas, then this case is used.
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeSourceFallback(
runFont, runPaint, fDeviceProps,
fScalerContextFlags, maxDimensionInSourceSpace);
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
fDrawable.startSource(fRejects.source(), origin);
strike->prepareForMaskDrawing(&fDrawable, &fRejects);
fRejects.flipRejectsToSource();
SkASSERT(fRejects.source().empty());
if (process) {
process->processSourceFallback(
fDrawable.drawable(),
strikeSpec,
viewMatrix.hasPerspective());
}
}
}
} // For all glyph runs
}