Reland "Use bulk interface for paths"
This is a reland of 5b83d05bf4
In the original, the outline was calculated using the glyph's
position, which included the subpixel adjustment. It should have
been calculated at {0, 0} because all transformations including
subpixel placmenet happen while drawing.
Original change's description:
> Use bulk interface for paths
>
> Change-Id: I3a73f3b181542588470e3ce2c03d147423fef5cd
> Reviewed-on: https://skia-review.googlesource.com/c/192424
> Reviewed-by: Mike Klein <mtklein@google.com>
> Commit-Queue: Herb Derby <herb@google.com>
Change-Id: Id4987a8d0122ce73cae9ade33b853b1a9d080d1f
Reviewed-on: https://skia-review.googlesource.com/c/193021
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
parent
75d4898a27
commit
b27cc444b7
@ -331,28 +331,41 @@ void SkGlyphRunListPainter::processARGBFallback(
|
|||||||
|
|
||||||
// Beware! The following code will end up holding two glyph caches at the same time, but they
|
// 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).
|
// will not be the same cache (which would cause two separate caches to be created).
|
||||||
template <typename PerEmptyT, typename PerPathT>
|
template <typename ProcessPathsT>
|
||||||
void SkGlyphRunListPainter::drawGlyphRunAsPathWithARGBFallback(
|
void SkGlyphRunListPainter::drawGlyphRunAsPathWithARGBFallback(
|
||||||
SkStrikeInterface* pathCache, const SkGlyphRun& glyphRun,
|
SkStrikeInterface* strike, const SkGlyphRun& glyphRun,
|
||||||
SkPoint origin, const SkPaint& runPaint, const SkMatrix& viewMatrix, SkScalar textScale,
|
SkPoint origin, const SkPaint& runPaint, const SkMatrix& viewMatrix, SkScalar textScale,
|
||||||
PerEmptyT&& perEmpty, PerPathT&& perPath, ARGBFallback&& argbFallback) {
|
ProcessPathsT&& processPaths, ARGBFallback&& argbFallback) {
|
||||||
fARGBGlyphsIDs.clear();
|
fARGBGlyphsIDs.clear();
|
||||||
fARGBPositions.clear();
|
fARGBPositions.clear();
|
||||||
|
ScopedBuffers _ = ensureBuffers(glyphRun);
|
||||||
SkScalar maxFallbackDimension{-SK_ScalarInfinity};
|
SkScalar maxFallbackDimension{-SK_ScalarInfinity};
|
||||||
|
|
||||||
|
// Four empty glyphs are expected; one for each horizontal subpixel position.
|
||||||
|
SkSTArray<4, const SkGlyph*> emptyGlyphs;
|
||||||
|
|
||||||
|
int glyphCount = 0;
|
||||||
const SkPoint* positionCursor = glyphRun.positions().data();
|
const SkPoint* positionCursor = glyphRun.positions().data();
|
||||||
for (auto glyphID : glyphRun.glyphsIDs()) {
|
for (auto glyphID : glyphRun.glyphsIDs()) {
|
||||||
SkPoint glyphPos = origin + *positionCursor++;
|
SkPoint glyphPos = origin + *positionCursor++;
|
||||||
const SkGlyph& glyph = pathCache->getGlyphMetrics(glyphID, {0, 0});
|
|
||||||
|
if (std::any_of(emptyGlyphs.begin(), emptyGlyphs.end(),
|
||||||
|
[glyphID](const SkGlyph* g) { return g->getGlyphID() == glyphID; })) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.isEmpty()) {
|
||||||
perEmpty(glyph, glyphPos);
|
emptyGlyphs.push_back(&glyph);
|
||||||
} else if (glyph.fMaskFormat != SkMask::kARGB32_Format) {
|
} else if (glyph.fMaskFormat != SkMask::kARGB32_Format) {
|
||||||
if (pathCache->decideCouldDrawFromPath(glyph)) {
|
if (strike->decideCouldDrawFromPath(glyph)) {
|
||||||
perPath(glyph, glyphPos);
|
fGlyphPos[glyphCount++] = {&glyph, glyphPos};
|
||||||
} else {
|
} else {
|
||||||
// This happens when a bitmap-only font has a very large glyph compared to the
|
// This happens when a bitmap-only font is forced to scale very large. This
|
||||||
// rest of the glyphs. This doesn't happen in practice.
|
// doesn't happen in practice.
|
||||||
perEmpty(glyph, glyphPos);
|
emptyGlyphs.push_back(&glyph);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SkScalar largestDimension = std::max(glyph.fWidth, glyph.fHeight);
|
SkScalar largestDimension = std::max(glyph.fWidth, glyph.fHeight);
|
||||||
@ -362,6 +375,13 @@ void SkGlyphRunListPainter::drawGlyphRunAsPathWithARGBFallback(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (glyphCount > 0) {
|
||||||
|
processPaths(SkSpan<const GlyphAndPos>{fGlyphPos, SkTo<size_t>(glyphCount)},
|
||||||
|
strike,
|
||||||
|
textScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!fARGBGlyphsIDs.empty()) {
|
if (!fARGBGlyphsIDs.empty()) {
|
||||||
this->processARGBFallback(
|
this->processARGBFallback(
|
||||||
maxFallbackDimension, runPaint, glyphRun.font(), viewMatrix, textScale,
|
maxFallbackDimension, runPaint, glyphRun.font(), viewMatrix, textScale,
|
||||||
@ -420,14 +440,14 @@ void SkGlyphRunListPainter::drawGlyphRunAsBMPWithPathFallback(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the glyph is not empty, then it will have a pointer to mask data.
|
// If the glyph is not empty, then it will have a pointer to mask data.
|
||||||
fMasks[glyphCount++] = {&glyph, mappedPt};
|
fGlyphPos[glyphCount++] = {&glyph, mappedPt};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glyphCount > 0) {
|
if (glyphCount > 0) {
|
||||||
mapping.mapPoints(fPositions, glyphCount);
|
mapping.mapPoints(fPositions, glyphCount);
|
||||||
processMasks(SkSpan<const GlyphAndPos>{fMasks, SkTo<size_t>(glyphCount)}, strike.get());
|
processMasks(SkSpan<const GlyphAndPos>{fGlyphPos, SkTo<size_t>(glyphCount)}, strike.get());
|
||||||
}
|
}
|
||||||
if (!fPaths.empty()) {
|
if (!fPaths.empty()) {
|
||||||
processPaths(SkSpan<const GlyphAndPos>{fPaths});
|
processPaths(SkSpan<const GlyphAndPos>{fPaths});
|
||||||
@ -813,14 +833,15 @@ void GrTextBlob::generateFromGlyphRunList(GrStrikeCache* glyphCache,
|
|||||||
pathFont, pathPaint, props,
|
pathFont, pathPaint, props,
|
||||||
scalerContextFlags, SkMatrix::I());
|
scalerContextFlags, SkMatrix::I());
|
||||||
|
|
||||||
auto perEmpty = [](const SkGlyph&, SkPoint) {};
|
|
||||||
|
|
||||||
// Given a glyph that is not ARGB, draw it.
|
// Given a glyph that is not ARGB, draw it.
|
||||||
auto perPath = [textScale, run]
|
auto processPath = [run](
|
||||||
(const SkGlyph& glyph, SkPoint position) {
|
SkSpan<const SkGlyphRunListPainter::GlyphAndPos> paths,
|
||||||
// TODO: path should always be set. Remove when proven.
|
SkStrikeInterface* strike, SkScalar textScale) {
|
||||||
if (const SkPath* glyphPath = glyph.path()) {
|
run->setupFont(strike->strikeSpec());
|
||||||
run->appendPathGlyph(*glyphPath, position, textScale, false);
|
for (const auto& path : paths) {
|
||||||
|
if (const SkPath* glyphPath = path.glyph->path()) {
|
||||||
|
run->appendPathGlyph(*glyphPath, path.position, textScale, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -828,7 +849,7 @@ void GrTextBlob::generateFromGlyphRunList(GrStrikeCache* glyphCache,
|
|||||||
|
|
||||||
glyphPainter->drawGlyphRunAsPathWithARGBFallback(
|
glyphPainter->drawGlyphRunAsPathWithARGBFallback(
|
||||||
pathCache.get(), glyphRun, origin, runPaint, viewMatrix, textScale,
|
pathCache.get(), glyphRun, origin, runPaint, viewMatrix, textScale,
|
||||||
std::move(perEmpty), std::move(perPath), std::move(argbFallback));
|
std::move(processPath), std::move(argbFallback));
|
||||||
} else {
|
} else {
|
||||||
// Ensure the blob is set for bitmaptext
|
// Ensure the blob is set for bitmaptext
|
||||||
this->setHasBitmap();
|
this->setHasBitmap();
|
||||||
@ -1012,20 +1033,16 @@ void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRunForPaths(
|
|||||||
pathPaint, pathFont, this->surfaceProps(), SkMatrix::I(),
|
pathPaint, pathFont, this->surfaceProps(), SkMatrix::I(),
|
||||||
SkScalerContextFlags::kFakeGammaAndBoostContrast, &effects);
|
SkScalerContextFlags::kFakeGammaAndBoostContrast, &effects);
|
||||||
|
|
||||||
auto perEmpty = [glyphCacheState] (const SkGlyph& glyph, SkPoint mappedPt) {
|
// This processor is empty because all changes to the cache are tracked through
|
||||||
glyphCacheState->addGlyph(glyph.getPackedID(), false);
|
// getGlyphMetrics and decideCouldDrawFromPath.
|
||||||
};
|
auto processPaths = [](
|
||||||
|
SkSpan<const SkGlyphRunListPainter::GlyphAndPos>, SkStrikeInterface*, SkScalar) { };
|
||||||
auto perPath = [glyphCacheState](const SkGlyph& glyph, SkPoint position) {
|
|
||||||
const bool asPath = true;
|
|
||||||
glyphCacheState->addGlyph(glyph.getGlyphID(), asPath);
|
|
||||||
};
|
|
||||||
|
|
||||||
ARGBHelper argbFallback{runMatrix, surfaceProps(), fStrikeServer};
|
ARGBHelper argbFallback{runMatrix, surfaceProps(), fStrikeServer};
|
||||||
|
|
||||||
fPainter.drawGlyphRunAsPathWithARGBFallback(
|
fPainter.drawGlyphRunAsPathWithARGBFallback(
|
||||||
glyphCacheState, glyphRun, origin, runPaint, runMatrix, textScale,
|
glyphCacheState, glyphRun, origin, runPaint, runMatrix, textScale,
|
||||||
std::move(perEmpty), std::move(perPath), std::move(argbFallback));
|
std::move(processPaths), std::move(argbFallback));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SK_SUPPORT_GPU
|
#if SK_SUPPORT_GPU
|
||||||
@ -1095,7 +1112,7 @@ SkGlyphRunListPainter::ScopedBuffers::ScopedBuffers(SkGlyphRunListPainter* paint
|
|||||||
fPainter->fMaxRunSize = size;
|
fPainter->fMaxRunSize = size;
|
||||||
|
|
||||||
fPainter->fPositions.reset(size);
|
fPainter->fPositions.reset(size);
|
||||||
fPainter->fMasks.reset(size);
|
fPainter->fGlyphPos.reset(size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1107,7 +1124,7 @@ SkGlyphRunListPainter::ScopedBuffers::~ScopedBuffers() {
|
|||||||
if (fPainter->fMaxRunSize > 200) {
|
if (fPainter->fMaxRunSize > 200) {
|
||||||
fPainter->fMaxRunSize = 0;
|
fPainter->fMaxRunSize = 0;
|
||||||
fPainter->fPositions.reset();
|
fPainter->fPositions.reset();
|
||||||
fPainter->fMasks.reset();
|
fPainter->fGlyphPos.reset();
|
||||||
fPainter->fPaths.shrink_to_fit();
|
fPainter->fPaths.shrink_to_fit();
|
||||||
fPainter->fARGBGlyphsIDs.shrink_to_fit();
|
fPainter->fARGBGlyphsIDs.shrink_to_fit();
|
||||||
fPainter->fARGBPositions.shrink_to_fit();
|
fPainter->fARGBPositions.shrink_to_fit();
|
||||||
|
@ -131,11 +131,11 @@ public:
|
|||||||
// For each glyph that is not ARGB call perPath. If the glyph is ARGB then store the glyphID
|
// 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
|
// and the position in fallback vectors. After all the glyphs are processed, pass the
|
||||||
// fallback glyphIDs and positions to fallbackARGB.
|
// fallback glyphIDs and positions to fallbackARGB.
|
||||||
template <typename PerEmptyT, typename PerPath>
|
template <typename ProcessPathsT>
|
||||||
void drawGlyphRunAsPathWithARGBFallback(
|
void drawGlyphRunAsPathWithARGBFallback(
|
||||||
SkStrikeInterface* cache, const SkGlyphRun& glyphRun,
|
SkStrikeInterface* cache, const SkGlyphRun& glyphRun,
|
||||||
SkPoint origin, const SkPaint& paint, const SkMatrix& viewMatrix, SkScalar textScale,
|
SkPoint origin, const SkPaint& paint, const SkMatrix& viewMatrix, SkScalar textScale,
|
||||||
PerEmptyT&& perEmpty, PerPath&& perPath, ARGBFallback&& fallbackARGB);
|
ProcessPathsT&& processPaths, ARGBFallback&& fallbackARGB);
|
||||||
|
|
||||||
template <typename PerEmptyT, typename PerSDFT, typename PerPathT>
|
template <typename PerEmptyT, typename PerSDFT, typename PerPathT>
|
||||||
void drawGlyphRunAsSDFWithARGBFallback(
|
void drawGlyphRunAsSDFWithARGBFallback(
|
||||||
@ -171,7 +171,7 @@ private:
|
|||||||
|
|
||||||
int fMaxRunSize{0};
|
int fMaxRunSize{0};
|
||||||
SkAutoTMalloc<SkPoint> fPositions;
|
SkAutoTMalloc<SkPoint> fPositions;
|
||||||
SkAutoTMalloc<GlyphAndPos> fMasks;
|
SkAutoTMalloc<GlyphAndPos> fGlyphPos;
|
||||||
|
|
||||||
std::vector<GlyphAndPos> fPaths;
|
std::vector<GlyphAndPos> fPaths;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user