One routine to rule them all!
Change-Id: I6c448f325fca21c4919c0a0854d9d5cb9d54beb0 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/198661 Commit-Queue: Herb Derby <herb@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
ca9b2082d1
commit
4eff3f934d
@ -380,215 +380,235 @@ void SkGlyphRunListPainter::processARGBFallback(SkScalar maxGlyphDimension,
|
||||
}
|
||||
}
|
||||
|
||||
// Beware! The following code will end up holding two glyph caches at the same time, but they
|
||||
// will not be the same cache (which would cause two separate caches to be created).
|
||||
void SkGlyphRunListPainter::drawGlyphRunAsPathWithARGBFallback(
|
||||
const SkPaint& runPaint, const SkFont& runFont,
|
||||
const SkGlyphRun& glyphRun, SkPoint origin, const SkMatrix& viewMatrix,
|
||||
SkGlyphRunPainterInterface* process) {
|
||||
fARGBGlyphsIDs.clear();
|
||||
fARGBPositions.clear();
|
||||
ScopedBuffers _ = this->ensureBuffers(glyphRun);
|
||||
SkScalar maxFallbackDimension{-SK_ScalarInfinity};
|
||||
|
||||
// setup our std runPaint, in hopes of getting hits in the cache
|
||||
SkPaint pathPaint{runPaint};
|
||||
SkFont pathFont{runFont};
|
||||
|
||||
// The factor to get from the size stored in the strike to the size needed for the source.
|
||||
SkScalar strikeToSourceRatio = pathFont.setupForAsPaths(&pathPaint);
|
||||
|
||||
SkAutoDescriptor ad;
|
||||
SkScalerContextEffects effects;
|
||||
SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
|
||||
pathFont, pathPaint, fDeviceProps, fScalerContextFlags, SkMatrix::I(), &ad, &effects);
|
||||
|
||||
SkScopedStrike strike =
|
||||
fStrikeCache->findOrCreateScopedStrike(
|
||||
*ad.getDesc(), effects,*pathFont.getTypefaceOrDefault());
|
||||
|
||||
int glyphCount = 0;
|
||||
const SkPoint* positionCursor = glyphRun.positions().data();
|
||||
for (auto glyphID : glyphRun.glyphsIDs()) {
|
||||
SkPoint glyphPos = origin + *positionCursor++;
|
||||
|
||||
// Use outline from {0, 0} because all transforms including subpixel translation happen
|
||||
// during drawing.
|
||||
const SkGlyph& glyph = strike->getGlyphMetrics(glyphID, {0, 0});
|
||||
if (!glyph.isEmpty()) {
|
||||
if (glyph.fMaskFormat != SkMask::kARGB32_Format) {
|
||||
if (strike->decideCouldDrawFromPath(glyph)) {
|
||||
fGlyphPos[glyphCount++] = {&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 (process) {
|
||||
if (glyphCount > 0) {
|
||||
process->processSourcePaths(SkSpan<const GlyphAndPos>{fGlyphPos, SkTo<size_t>
|
||||
(glyphCount)},
|
||||
strike.get(),
|
||||
strikeToSourceRatio);
|
||||
}
|
||||
|
||||
// fGlyphPos will be reused here.
|
||||
if (!fARGBGlyphsIDs.empty()) {
|
||||
this->processARGBFallback(
|
||||
maxFallbackDimension, runPaint, glyphRun.font(), viewMatrix,
|
||||
strikeToSourceRatio,
|
||||
process);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkGlyphRunListPainter::drawGlyphRunAsBMPWithPathFallback(
|
||||
const SkPaint& paint, const SkFont& font,
|
||||
const SkGlyphRun& glyphRun, SkPoint origin, const SkMatrix& deviceMatrix,
|
||||
SkGlyphRunPainterInterface* process) {
|
||||
|
||||
SkAutoDescriptor ad;
|
||||
SkScalerContextEffects effects;
|
||||
|
||||
SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
|
||||
font, paint, fDeviceProps, fScalerContextFlags, deviceMatrix, &ad, &effects);
|
||||
|
||||
SkTypeface* typeface = font.getTypefaceOrDefault();
|
||||
SkScopedStrike strike =
|
||||
fStrikeCache->findOrCreateScopedStrike(*ad.getDesc(), effects, *typeface);
|
||||
|
||||
ScopedBuffers _ = this->ensureBuffers(glyphRun);
|
||||
|
||||
SkMatrix mapping = deviceMatrix;
|
||||
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 glyphCount = 0;
|
||||
const SkPoint* posCursor = fPositions;
|
||||
for (auto glyphID : glyphRun.glyphsIDs()) {
|
||||
SkPoint mappedPt = *posCursor++;
|
||||
|
||||
if (SkScalarsAreFinite(mappedPt.x(), mappedPt.y())) {
|
||||
const SkGlyph& glyph = strike->getGlyphMetrics(glyphID, mappedPt);
|
||||
if (!glyph.isEmpty()) {
|
||||
if (SkStrikeCommon::GlyphTooBigForAtlas(glyph)) {
|
||||
if (strike->decideCouldDrawFromPath(glyph)) {
|
||||
fPaths.push_back({&glyph, mappedPt});
|
||||
}
|
||||
} else {
|
||||
// If the glyph is not empty, then it will have a pointer to mask data.
|
||||
fGlyphPos[glyphCount++] = {&glyph, mappedPt};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (process) {
|
||||
if (glyphCount > 0) {
|
||||
mapping.mapPoints(fPositions, glyphCount);
|
||||
process->processDeviceMasks(
|
||||
SkSpan<const GlyphAndPos>{fGlyphPos, SkTo<size_t>(glyphCount)}, strike.get());
|
||||
}
|
||||
if (!fPaths.empty()) {
|
||||
process->processDevicePaths(SkSpan<const GlyphAndPos>{fPaths});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
void SkGlyphRunListPainter::drawGlyphRunAsSDFWithARGBFallback(
|
||||
const SkPaint& runPaint, const SkFont& runFont,
|
||||
const SkGlyphRun& glyphRun, SkPoint origin, const SkMatrix& viewMatrix,
|
||||
const GrTextContext::Options& options,
|
||||
SkGlyphRunPainterInterface* process) {
|
||||
fARGBGlyphsIDs.clear();
|
||||
fARGBPositions.clear();
|
||||
ScopedBuffers _ = this->ensureBuffers(glyphRun);
|
||||
SkScalar maxFallbackDimension{-SK_ScalarInfinity};
|
||||
void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunList,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkSurfaceProps& props,
|
||||
bool contextSupportsDistanceFieldText,
|
||||
const GrTextContext::Options& options,
|
||||
SkGlyphRunPainterInterface* process) {
|
||||
|
||||
// Setup distance field runPaint and text ratio
|
||||
SkPaint dfPaint = GrTextContext::InitDistanceFieldPaint(runPaint);
|
||||
SkScalar textScale;
|
||||
SkFont dfFont = GrTextContext::InitDistanceFieldFont(
|
||||
runFont, viewMatrix, options, &textScale);
|
||||
// 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).
|
||||
SkScalerContextFlags flags = SkScalerContextFlags::kNone;
|
||||
SkPoint origin = glyphRunList.origin();
|
||||
const SkPaint& runPaint = glyphRunList.paint();
|
||||
|
||||
SkScalar minScale, maxScale;
|
||||
std::tie(minScale, maxScale) = GrTextContext::InitDistanceFieldMinMaxScale(
|
||||
runFont.getSize(), viewMatrix, options);
|
||||
for (const auto& glyphRun : glyphRunList) {
|
||||
const SkFont& runFont = glyphRun.font();
|
||||
|
||||
SkAutoDescriptor ad;
|
||||
SkScalerContextEffects effects;
|
||||
SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
|
||||
dfFont, dfPaint, fDeviceProps, flags, SkMatrix::I(), &ad, &effects);
|
||||
SkScopedStrike strike =
|
||||
fStrikeCache->findOrCreateScopedStrike(
|
||||
*ad.getDesc(), effects, *dfFont.getTypefaceOrDefault());
|
||||
bool useSDFT = GrTextContext::CanDrawAsDistanceFields(
|
||||
runPaint, runFont, viewMatrix, props, contextSupportsDistanceFieldText, options);
|
||||
if (process) {
|
||||
process->startRun(glyphRun, useSDFT);
|
||||
}
|
||||
|
||||
std::vector<GlyphAndPos> paths;
|
||||
if (useSDFT) {
|
||||
fARGBGlyphsIDs.clear();
|
||||
fARGBPositions.clear();
|
||||
ScopedBuffers _ = this->ensureBuffers(glyphRun);
|
||||
SkScalar maxFallbackDimension{-SK_ScalarInfinity};
|
||||
|
||||
int glyphCount = 0;
|
||||
const SkPoint* positionCursor = glyphRun.positions().data();
|
||||
for (auto glyphID : glyphRun.glyphsIDs()) {
|
||||
const SkGlyph& glyph = strike->getGlyphMetrics(glyphID, {0, 0});
|
||||
SkPoint glyphPos = origin + *positionCursor++;
|
||||
if (!glyph.isEmpty()) {
|
||||
if (glyph.fMaskFormat == SkMask::kSDF_Format) {
|
||||
if (!SkStrikeCommon::GlyphTooBigForAtlas(glyph)) {
|
||||
// If the glyph is not empty, then it will have a pointer to SDF data.
|
||||
fGlyphPos[glyphCount++] = {&glyph, glyphPos};
|
||||
} else {
|
||||
if (strike->decideCouldDrawFromPath(glyph)) {
|
||||
paths.push_back({&glyph, glyphPos});
|
||||
// Setup distance field runPaint and text ratio
|
||||
SkPaint dfPaint = GrTextContext::InitDistanceFieldPaint(runPaint);
|
||||
SkScalar cacheToSourceScale;
|
||||
SkFont dfFont = GrTextContext::InitDistanceFieldFont(
|
||||
runFont, viewMatrix, options, &cacheToSourceScale);
|
||||
// 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).
|
||||
SkScalerContextFlags flags = SkScalerContextFlags::kNone;
|
||||
|
||||
SkScalar minScale, maxScale;
|
||||
std::tie(minScale, maxScale) = GrTextContext::InitDistanceFieldMinMaxScale(
|
||||
runFont.getSize(), viewMatrix, options);
|
||||
|
||||
SkAutoDescriptor ad;
|
||||
SkScalerContextEffects effects;
|
||||
SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
|
||||
dfFont, dfPaint, fDeviceProps, flags, SkMatrix::I(), &ad, &effects);
|
||||
SkScopedStrike strike =
|
||||
fStrikeCache->findOrCreateScopedStrike(
|
||||
*ad.getDesc(), effects, *dfFont.getTypefaceOrDefault());
|
||||
|
||||
std::vector<GlyphAndPos> paths;
|
||||
|
||||
int glyphCount = 0;
|
||||
const SkPoint* positionCursor = glyphRun.positions().data();
|
||||
for (auto glyphID : glyphRun.glyphsIDs()) {
|
||||
const SkGlyph& glyph = strike->getGlyphMetrics(glyphID, {0, 0});
|
||||
SkPoint glyphPos = origin + *positionCursor++;
|
||||
if (!glyph.isEmpty()) {
|
||||
if (glyph.fMaskFormat == SkMask::kSDF_Format) {
|
||||
if (!SkStrikeCommon::GlyphTooBigForAtlas(glyph)) {
|
||||
// If the glyph is not empty, then it will have a pointer to SDF data.
|
||||
fGlyphPos[glyphCount++] = {&glyph, glyphPos};
|
||||
} else {
|
||||
if (strike->decideCouldDrawFromPath(glyph)) {
|
||||
paths.push_back({&glyph, glyphPos});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SkASSERT(glyph.fMaskFormat == SkMask::kARGB32_Format);
|
||||
SkScalar largestDimension = std::max(glyph.fWidth, glyph.fHeight);
|
||||
maxFallbackDimension = std::max(maxFallbackDimension, largestDimension);
|
||||
fARGBGlyphsIDs.push_back(glyphID);
|
||||
fARGBPositions.push_back(glyphPos);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SkASSERT(glyph.fMaskFormat == SkMask::kARGB32_Format);
|
||||
SkScalar largestDimension = std::max(glyph.fWidth, glyph.fHeight);
|
||||
maxFallbackDimension = std::max(maxFallbackDimension, largestDimension);
|
||||
fARGBGlyphsIDs.push_back(glyphID);
|
||||
fARGBPositions.push_back(glyphPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (process) {
|
||||
if (glyphCount > 0) {
|
||||
bool hasWCoord = viewMatrix.hasPerspective()
|
||||
|| options.fDistanceFieldVerticesAlwaysHaveW;
|
||||
process->processSourceSDFT(
|
||||
SkSpan<const GlyphAndPos>{fGlyphPos, SkTo<size_t>(glyphCount)},
|
||||
strike.get(), runFont, textScale, minScale, maxScale, hasWCoord);
|
||||
}
|
||||
if (process) {
|
||||
if (glyphCount > 0) {
|
||||
bool hasWCoord = viewMatrix.hasPerspective()
|
||||
|| options.fDistanceFieldVerticesAlwaysHaveW;
|
||||
process->processSourceSDFT(
|
||||
SkSpan<const GlyphAndPos>{fGlyphPos, SkTo<size_t>(glyphCount)},
|
||||
strike.get(),
|
||||
runFont,
|
||||
cacheToSourceScale,
|
||||
minScale,
|
||||
maxScale,
|
||||
hasWCoord);
|
||||
}
|
||||
|
||||
if (!paths.empty()) {
|
||||
process->processSourcePaths(
|
||||
SkSpan<const GlyphAndPos>{paths}, strike.get(), textScale);
|
||||
}
|
||||
if (!paths.empty()) {
|
||||
process->processSourcePaths(
|
||||
SkSpan<const GlyphAndPos>{paths}, strike.get(), cacheToSourceScale);
|
||||
}
|
||||
|
||||
{
|
||||
// fGlyphPos will be reused here.
|
||||
if (!fARGBGlyphsIDs.empty()) {
|
||||
this->processARGBFallback(
|
||||
maxFallbackDimension, runPaint, glyphRun.font(), viewMatrix, textScale,
|
||||
process);
|
||||
{
|
||||
// fGlyphPos will be reused here.
|
||||
if (!fARGBGlyphsIDs.empty()) {
|
||||
this->processARGBFallback(
|
||||
maxFallbackDimension, runPaint, glyphRun.font(), viewMatrix,
|
||||
cacheToSourceScale,
|
||||
process);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (SkGlyphRunListPainter::ShouldDrawAsPath(runPaint, runFont, viewMatrix)) {
|
||||
|
||||
fARGBGlyphsIDs.clear();
|
||||
fARGBPositions.clear();
|
||||
ScopedBuffers _ = this->ensureBuffers(glyphRun);
|
||||
SkScalar maxFallbackDimension{-SK_ScalarInfinity};
|
||||
|
||||
// setup our std runPaint, in hopes of getting hits in the cache
|
||||
SkPaint pathPaint{runPaint};
|
||||
SkFont pathFont{runFont};
|
||||
|
||||
// The factor to get from the size stored in the strike to the size needed for
|
||||
// the source.
|
||||
SkScalar strikeToSourceRatio = pathFont.setupForAsPaths(&pathPaint);
|
||||
|
||||
SkAutoDescriptor ad;
|
||||
SkScalerContextEffects effects;
|
||||
SkScalerContext::CreateDescriptorAndEffectsUsingPaint(pathFont,
|
||||
pathPaint,
|
||||
fDeviceProps,
|
||||
fScalerContextFlags,
|
||||
SkMatrix::I(),
|
||||
&ad,
|
||||
&effects);
|
||||
SkScopedStrike strike =
|
||||
fStrikeCache->findOrCreateScopedStrike(
|
||||
*ad.getDesc(), effects,*pathFont.getTypefaceOrDefault());
|
||||
|
||||
int glyphCount = 0;
|
||||
const SkPoint* positionCursor = glyphRun.positions().data();
|
||||
for (auto glyphID : glyphRun.glyphsIDs()) {
|
||||
SkPoint glyphPos = origin + *positionCursor++;
|
||||
|
||||
// Use outline from {0, 0} because all transforms including subpixel translation
|
||||
// happen during drawing.
|
||||
const SkGlyph& glyph = strike->getGlyphMetrics(glyphID, {0, 0});
|
||||
if (!glyph.isEmpty()) {
|
||||
if (glyph.fMaskFormat != SkMask::kARGB32_Format) {
|
||||
if (strike->decideCouldDrawFromPath(glyph)) {
|
||||
fGlyphPos[glyphCount++] = {&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 (process) {
|
||||
if (glyphCount > 0) {
|
||||
process->processSourcePaths(
|
||||
SkSpan<const GlyphAndPos>{fGlyphPos, SkTo<size_t>(glyphCount)},
|
||||
strike.get(),
|
||||
strikeToSourceRatio);
|
||||
}
|
||||
|
||||
// fGlyphPos will be reused here.
|
||||
if (!fARGBGlyphsIDs.empty()) {
|
||||
this->processARGBFallback(
|
||||
maxFallbackDimension, runPaint, glyphRun.font(), viewMatrix,
|
||||
strikeToSourceRatio,
|
||||
process);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
SkAutoDescriptor ad;
|
||||
SkScalerContextEffects effects;
|
||||
|
||||
SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
|
||||
runFont, runPaint, fDeviceProps, fScalerContextFlags, viewMatrix, &ad,
|
||||
&effects);
|
||||
|
||||
SkTypeface* typeface = runFont.getTypefaceOrDefault();
|
||||
SkScopedStrike strike =
|
||||
fStrikeCache->findOrCreateScopedStrike(*ad.getDesc(), effects, *typeface);
|
||||
|
||||
ScopedBuffers _ = this->ensureBuffers(glyphRun);
|
||||
|
||||
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 glyphCount = 0;
|
||||
const SkPoint* posCursor = fPositions;
|
||||
for (auto glyphID : glyphRun.glyphsIDs()) {
|
||||
SkPoint mappedPt = *posCursor++;
|
||||
|
||||
if (SkScalarsAreFinite(mappedPt.x(), mappedPt.y())) {
|
||||
const SkGlyph& glyph = strike->getGlyphMetrics(glyphID, mappedPt);
|
||||
if (!glyph.isEmpty()) {
|
||||
if (SkStrikeCommon::GlyphTooBigForAtlas(glyph)) {
|
||||
if (strike->decideCouldDrawFromPath(glyph)) {
|
||||
fPaths.push_back({&glyph, mappedPt});
|
||||
}
|
||||
} else {
|
||||
// If the glyph is not empty, then it will have a pointer to mask data.
|
||||
fGlyphPos[glyphCount++] = {&glyph, mappedPt};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (process) {
|
||||
if (glyphCount > 0) {
|
||||
mapping.mapPoints(fPositions, glyphCount);
|
||||
process->processDeviceMasks(
|
||||
SkSpan<const GlyphAndPos>{fGlyphPos, SkTo<size_t>(glyphCount)},
|
||||
strike.get());
|
||||
}
|
||||
if (!fPaths.empty()) {
|
||||
process->processDevicePaths(SkSpan<const GlyphAndPos>{fPaths});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
||||
SkGlyphRunListPainter::ScopedBuffers
|
||||
SkGlyphRunListPainter::ensureBuffers(const SkGlyphRunList& glyphRunList) {
|
||||
auto SkGlyphRunListPainter::ensureBuffers(const SkGlyphRunList& glyphRunList) -> ScopedBuffers {
|
||||
size_t size = 0;
|
||||
for (const SkGlyphRun& run : glyphRunList) {
|
||||
size = std::max(run.runSize(), size);
|
||||
@ -811,38 +831,12 @@ void GrTextBlob::generateFromGlyphRunList(const GrShaderCaps& shaderCaps,
|
||||
this->initReusableBlob(SkPaintPriv::ComputeLuminanceColor(runPaint), viewMatrix,
|
||||
origin.x(), origin.y());
|
||||
|
||||
for (const auto& glyphRun : glyphRunList) {
|
||||
const SkFont& runFont = glyphRun.font();
|
||||
|
||||
bool useSDFT = GrTextContext::CanDrawAsDistanceFields(
|
||||
runPaint, runFont, viewMatrix, props, shaderCaps.supportsDistanceFieldText(),
|
||||
options);
|
||||
|
||||
this->startRun(glyphRun, useSDFT);
|
||||
|
||||
if (useSDFT) {
|
||||
|
||||
glyphPainter->drawGlyphRunAsSDFWithARGBFallback(
|
||||
runPaint, glyphRun.font(),
|
||||
glyphRun, origin, viewMatrix,
|
||||
options,
|
||||
this);
|
||||
|
||||
} else if (SkGlyphRunListPainter::ShouldDrawAsPath(runPaint, runFont, viewMatrix)) {
|
||||
// The glyphs are big, so use paths to draw them.
|
||||
|
||||
glyphPainter->drawGlyphRunAsPathWithARGBFallback(
|
||||
runPaint, runFont,
|
||||
glyphRun, origin, viewMatrix,
|
||||
this);
|
||||
} else {
|
||||
|
||||
glyphPainter->drawGlyphRunAsBMPWithPathFallback(
|
||||
runPaint, runFont,
|
||||
glyphRun, origin, viewMatrix,
|
||||
this);
|
||||
}
|
||||
}
|
||||
glyphPainter->processGlyphRunList(glyphRunList,
|
||||
viewMatrix,
|
||||
props,
|
||||
shaderCaps.supportsDistanceFieldText(),
|
||||
options,
|
||||
this);
|
||||
}
|
||||
|
||||
GrTextBlob::Run* GrTextBlob::currentRun() {
|
||||
@ -1002,75 +996,6 @@ std::unique_ptr<GrDrawOp> GrTextContext::createOp_TestingOnly(GrRecordingContext
|
||||
#endif // GR_TEST_UTILS
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
||||
// -- SkTextBlobCacheDiffCanvas::TrackLayerDevice --------------------------------------------------
|
||||
|
||||
void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRun(
|
||||
const SkPoint& origin, const SkGlyphRun& glyphRun, const SkPaint& runPaint) {
|
||||
TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRun");
|
||||
|
||||
const SkMatrix& runMatrix = this->ctm();
|
||||
|
||||
// If the matrix has perspective, we fall back to using distance field text or paths.
|
||||
#if SK_SUPPORT_GPU
|
||||
if (this->maybeProcessGlyphRunForDFT(glyphRun, runMatrix, origin, runPaint)) {
|
||||
return;
|
||||
} else
|
||||
#endif
|
||||
if (SkGlyphRunListPainter::ShouldDrawAsPath(runPaint, glyphRun.font(), runMatrix)) {
|
||||
this->processGlyphRunForPaths(glyphRun, runMatrix, origin, runPaint);
|
||||
} else {
|
||||
this->processGlyphRunForMask(glyphRun, runMatrix, origin, runPaint);
|
||||
}
|
||||
}
|
||||
|
||||
void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRunForMask(
|
||||
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix,
|
||||
SkPoint origin, const SkPaint& runPaint) {
|
||||
TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRunForMask");
|
||||
|
||||
fPainter.drawGlyphRunAsBMPWithPathFallback(
|
||||
runPaint, glyphRun.font(), glyphRun, origin, runMatrix, nullptr);
|
||||
}
|
||||
|
||||
SkScalar SkTextBlobCacheDiffCanvas::SetupForPath(SkPaint* paint, SkFont* font) {
|
||||
return font->setupForAsPaths(paint);
|
||||
}
|
||||
|
||||
void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRunForPaths(
|
||||
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix,
|
||||
SkPoint origin, const SkPaint& runPaint) {
|
||||
TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRunForPaths");
|
||||
|
||||
fPainter.drawGlyphRunAsPathWithARGBFallback(
|
||||
runPaint, glyphRun.font(), glyphRun, origin, runMatrix, nullptr);
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
bool SkTextBlobCacheDiffCanvas::TrackLayerDevice::maybeProcessGlyphRunForDFT(
|
||||
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix,
|
||||
SkPoint origin, const SkPaint& runPaint) {
|
||||
TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::maybeProcessGlyphRunForDFT");
|
||||
|
||||
const SkFont& runFont = glyphRun.font();
|
||||
|
||||
GrTextContext::Options options;
|
||||
options.fMinDistanceFieldFontSize = fSettings.fMinDistanceFieldFontSize;
|
||||
options.fMaxDistanceFieldFontSize = fSettings.fMaxDistanceFieldFontSize;
|
||||
GrTextContext::SanitizeOptions(&options);
|
||||
if (!GrTextContext::CanDrawAsDistanceFields(runPaint, runFont,
|
||||
runMatrix, this->surfaceProps(),
|
||||
fSettings.fContextSupportsDistanceFieldText,
|
||||
options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fPainter.drawGlyphRunAsSDFWithARGBFallback(
|
||||
runPaint, glyphRun.font(), glyphRun, origin, runMatrix, options, nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
SkGlyphRunListPainter::ScopedBuffers::ScopedBuffers(SkGlyphRunListPainter* painter, int size)
|
||||
: fPainter{painter} {
|
||||
SkASSERT(size >= 0);
|
||||
|
@ -76,31 +76,16 @@ public:
|
||||
const SkGlyphRunList& glyphRunList, const SkMatrix& deviceMatrix,
|
||||
const BitmapDevicePainter* bitmapDevice);
|
||||
|
||||
// In the drawGlyphRunAs... routines a nullptr for process means that the calls to the cache
|
||||
// will be performed, but none of the callbacks will be called.
|
||||
void drawGlyphRunAsBMPWithPathFallback(
|
||||
const SkPaint& paint, const SkFont& font,
|
||||
const SkGlyphRun& glyphRun, SkPoint origin, const SkMatrix& deviceMatrix,
|
||||
SkGlyphRunPainterInterface* process);
|
||||
|
||||
// Draw glyphs as paths with fallback to scaled ARGB glyphs if color is needed.
|
||||
// PerPath - perPath(const SkGlyph&, SkPoint position)
|
||||
// FallbackARGB - fallbackARGB(SkSpan<const SkGlyphID>, SkSpan<const SkPoint>)
|
||||
// For each glyph that is not ARGB call perPath. If the glyph is ARGB then store the glyphID
|
||||
// and the position in fallback vectors. After all the glyphs are processed, pass the
|
||||
// fallback glyphIDs and positions to fallbackARGB.
|
||||
void drawGlyphRunAsPathWithARGBFallback(
|
||||
const SkPaint& runPaint, const SkFont& runFont,
|
||||
const SkGlyphRun& glyphRun, SkPoint origin, const SkMatrix& viewMatrix,
|
||||
SkGlyphRunPainterInterface* process);
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
void drawGlyphRunAsSDFWithARGBFallback(
|
||||
const SkPaint& runPaint, const SkFont& runFont,
|
||||
const SkGlyphRun& glyphRun, SkPoint origin, const SkMatrix& viewMatrix,
|
||||
const GrTextContext::Options& options,
|
||||
SkGlyphRunPainterInterface* process);
|
||||
#endif
|
||||
// A nullptr for process means that the calls to the cache will be performed, but none of the
|
||||
// callbacks will be called.
|
||||
void processGlyphRunList(const SkGlyphRunList& glyphRunList,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkSurfaceProps& props,
|
||||
bool contextSupportsDistanceFieldText,
|
||||
const GrTextContext::Options& options,
|
||||
SkGlyphRunPainterInterface* process);
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
||||
// TODO: Make this the canonical check for Skia.
|
||||
static bool ShouldDrawAsPath(const SkPaint& paint, const SkFont& font, const SkMatrix& matrix);
|
||||
|
@ -210,9 +210,21 @@ SkBaseDevice* SkTextBlobCacheDiffCanvas::TrackLayerDevice::onCreateDevice(
|
||||
|
||||
void SkTextBlobCacheDiffCanvas::TrackLayerDevice::drawGlyphRunList(
|
||||
const SkGlyphRunList& glyphRunList) {
|
||||
for (auto& glyphRun : glyphRunList) {
|
||||
this->processGlyphRun(glyphRunList.origin(), glyphRun, glyphRunList.paint());
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
GrTextContext::Options options;
|
||||
options.fMinDistanceFieldFontSize = fSettings.fMinDistanceFieldFontSize;
|
||||
options.fMaxDistanceFieldFontSize = fSettings.fMaxDistanceFieldFontSize;
|
||||
GrTextContext::SanitizeOptions(&options);
|
||||
|
||||
fPainter.processGlyphRunList(glyphRunList,
|
||||
this->ctm(),
|
||||
this->surfaceProps(),
|
||||
fSettings.fContextSupportsDistanceFieldText,
|
||||
options,
|
||||
nullptr);
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
||||
}
|
||||
|
||||
// -- SkTextBlobCacheDiffCanvas -------------------------------------------------------------------
|
||||
|
@ -110,23 +110,6 @@ protected:
|
||||
void drawGlyphRunList(const SkGlyphRunList& glyphRunList) override;
|
||||
|
||||
private:
|
||||
void processGlyphRun(
|
||||
const SkPoint& origin, const SkGlyphRun& glyphRun, const SkPaint& runPaint);
|
||||
|
||||
void processGlyphRunForMask(
|
||||
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix,
|
||||
SkPoint origin, const SkPaint& paint);
|
||||
|
||||
void processGlyphRunForPaths(
|
||||
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix,
|
||||
SkPoint origin, const SkPaint& paint);
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
bool maybeProcessGlyphRunForDFT(
|
||||
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix,
|
||||
SkPoint origin, const SkPaint& paint);
|
||||
#endif
|
||||
|
||||
SkStrikeServer* const fStrikeServer;
|
||||
const SkTextBlobCacheDiffCanvas::Settings fSettings;
|
||||
SkGlyphRunListPainter fPainter;
|
||||
|
Loading…
Reference in New Issue
Block a user