Introduce mergeGlyphAndImage to SkStrike

This call maintains image invariants while merging in
an image. It replaces much dubious code.

Change-Id: Id57fa1169f8944b2d10063fde983cd9d8256b598
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/223303
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2019-06-24 14:53:59 -04:00 committed by Skia Commit-Bot
parent adf18ce45a
commit 7019060abd
7 changed files with 46 additions and 76 deletions

View File

@ -113,6 +113,21 @@ bool SkGlyph::setImage(SkArenaAlloc* alloc, const void* image) {
return false;
}
bool SkGlyph::setMetricsAndImage(SkArenaAlloc* alloc, const SkGlyph& from) {
if (fImage == nullptr) {
fAdvanceX = from.fAdvanceX;
fAdvanceY = from.fAdvanceY;
fWidth = from.fWidth;
fHeight = from.fHeight;
fTop = from.fTop;
fLeft = from.fLeft;
fForceBW = from.fForceBW;
fMaskFormat = from.fMaskFormat;
return this->setImage(alloc, from.image());
}
return false;
}
size_t SkGlyph::rowBytes() const {
return format_rowbytes(fWidth, (SkMask::Format)fMaskFormat);
}
@ -133,22 +148,6 @@ size_t SkGlyph::imageSize() const {
return size;
}
size_t SkGlyph::copyImageData(const SkGlyph& from, SkArenaAlloc* alloc) {
fMaskFormat = from.fMaskFormat;
fWidth = from.fWidth;
fHeight = from.fHeight;
fLeft = from.fLeft;
fTop = from.fTop;
fForceBW = from.fForceBW;
if (from.image() != nullptr) {
this->setImage(alloc, from.image());
return this->imageSize();
}
return 0u;
}
void SkGlyph::installPath(SkArenaAlloc* alloc, const SkPath* path) {
SkASSERT(fPathData == nullptr);
SkASSERT(!this->setPathHasBeenCalled());

View File

@ -152,6 +152,12 @@ public:
bool setImage(SkArenaAlloc* alloc, SkScalerContext* scalerContext);
bool setImage(SkArenaAlloc* alloc, const void* image);
// Merge the from glyph into this glyph using alloc to allocate image data. Return true if
// image data was allocated. If the image for this glyph has not been initialized, then copy
// the width, height, top, left, format, and image into this glyph making a copy of the image
// using the alloc.
bool setMetricsAndImage(SkArenaAlloc* alloc, const SkGlyph& from);
// Returns true if the image has been set.
bool setImageHasBeenCalled() const {
return fImage != nullptr || this->isEmpty() || this->imageTooLarge();
@ -205,9 +211,6 @@ public:
}
bool imageTooLarge() const { return fWidth >= kMaxGlyphWidth; }
// Returns the size allocated on the arena.
size_t copyImageData(const SkGlyph& from, SkArenaAlloc* alloc);
// Make sure that the intercept information is on the glyph and return it, or return it if it
// already exists.
// * bounds - either end of the gap for the character.

View File

@ -758,38 +758,25 @@ bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySi
if (!deserializer.read<uint64_t>(&glyphImagesCount)) READ_FAILURE
for (size_t j = 0; j < glyphImagesCount; j++) {
SkTLazy<SkGlyph> glyph;
if (!SkStrikeClient::ReadGlyph(glyph, &deserializer)) READ_FAILURE
if (!ReadGlyph(glyph, &deserializer)) READ_FAILURE
SkGlyph* allocatedGlyph = strike->uninitializedGlyph(glyph->getPackedID());
// Update the glyph unless it's already got an image (from fallback),
// preserving any path that might be present.
if (allocatedGlyph->fImage == nullptr) {
auto* glyphPath = allocatedGlyph->fPathData;
*allocatedGlyph = *glyph;
allocatedGlyph->fPathData = glyphPath;
if (!glyph->isEmpty()) {
const volatile void* image =
deserializer.read(glyph->imageSize(), glyph->formatAlignment());
if (!image) READ_FAILURE
glyph->fImage = (void*)image;
}
auto imageSize = glyph->imageSize();
if (imageSize == 0u) continue;
const volatile void* image = deserializer.read(imageSize, glyph->formatAlignment());
if (!image) READ_FAILURE
// Don't overwrite the image if we already have one. We could have used a fallback if
// the glyph was missing earlier.
if (allocatedGlyph->fImage == nullptr) {
strike->initializeImage((void *)image, imageSize, allocatedGlyph);
}
strike->mergeGlyphAndImage(glyph->getPackedID(), *glyph);
}
uint64_t glyphPathsCount = 0u;
if (!deserializer.read<uint64_t>(&glyphPathsCount)) READ_FAILURE
for (size_t j = 0; j < glyphPathsCount; j++) {
SkTLazy<SkGlyph> glyph;
if (!SkStrikeClient::ReadGlyph(glyph, &deserializer)) READ_FAILURE
if (!ReadGlyph(glyph, &deserializer)) READ_FAILURE
SkGlyph* allocatedGlyph = strike->uninitializedGlyph(glyph->getPackedID());
SkGlyph* allocatedGlyph = strike->mergeGlyphAndImage(glyph->getPackedID(), *glyph);
SkPath* pathPtr = nullptr;
SkPath path;

View File

@ -44,14 +44,6 @@ SkGlyph* SkStrike::makeGlyph(SkPackedGlyphID packedGlyphID) {
return glyph;
}
SkGlyph* SkStrike::uninitializedGlyph(SkPackedGlyphID id) {
SkGlyph* glyph = fGlyphMap.findOrNull(id);
if (glyph == nullptr) {
glyph = this->makeGlyph(id);
}
return glyph;
}
SkGlyph* SkStrike::glyph(SkPackedGlyphID packedGlyphID) {
SkGlyph* glyph = fGlyphMap.findOrNull(packedGlyphID);
if (glyph == nullptr) {
@ -128,11 +120,6 @@ SkSpan<const SkGlyph*> SkStrike::metrics(
return {results, glyphCount};
}
bool SkStrike::isGlyphCached(SkGlyphID glyphID, SkFixed x, SkFixed y) const {
SkPackedGlyphID packedGlyphID{glyphID, x, y};
return fGlyphMap.find(packedGlyphID) != nullptr;
}
SkSpan<SkPoint> SkStrike::getAdvances(SkSpan<const SkGlyphID> glyphIDs, SkPoint advances[]) {
auto cursor = advances;
SkAutoSTArray<50, const SkGlyph*> glyphStorage{SkTo<int>(glyphIDs.size())};
@ -151,14 +138,17 @@ const void* SkStrike::findImage(const SkGlyph& glyphRef) {
return glyph->image();
}
void SkStrike::initializeImage(const void* data, size_t size, SkGlyph* glyph) {
SkASSERT(size == glyph->imageSize());
if (glyph->setImage(&fAlloc, data)) {
SkGlyph* SkStrike::mergeGlyphAndImage(SkPackedGlyphID toID, const SkGlyph& from) {
SkGlyph* glyph = fGlyphMap.findOrNull(toID);
if (glyph == nullptr) {
glyph = this->makeGlyph(toID);
}
if (glyph->setMetricsAndImage(&fAlloc, from)) {
fMemoryUsed += glyph->imageSize();
}
return glyph;
}
bool SkStrike::belongsToCache(const SkGlyph* glyph) const {
return glyph && fGlyphMap.findOrNull(glyph->getPackedID()) == glyph;
}
@ -178,10 +168,6 @@ const SkGlyph* SkStrike::getCachedGlyphAnySubPix(SkGlyphID glyphID,
return nullptr;
}
void SkStrike::initializeGlyphFromFallback(SkGlyph* glyph, const SkGlyph& fallback) {
fMemoryUsed += glyph->copyImageData(fallback, &fAlloc);
}
SkVector SkStrike::rounding() const {
return SkStrikeCommon::PixelRounding(fIsSubpixel, fAxisAlignment);
}

View File

@ -39,9 +39,6 @@ public:
std::unique_ptr<SkScalerContext> scaler,
const SkFontMetrics&);
/** Return true if glyph is cached. */
bool isGlyphCached(SkGlyphID glyphID, SkFixed x, SkFixed y) const;
// Return a glyph. Create it if it doesn't exist, and initialize the glyph with metrics and
// advances.
SkGlyph* glyph(SkPackedGlyphID packedID);
@ -52,8 +49,11 @@ public:
// Return a glyph or nullptr if it does not exits in the strike.
SkGlyph* glyphOrNull(SkPackedGlyphID id) const;
// Return a glyph. Create it if it doesn't exist, but zero the data.
SkGlyph* uninitializedGlyph(SkPackedGlyphID id);
// Lookup (or create if needed) the toGlyph using toID. If that glyph is not initialized with
// an image, then use the information in from to initialize the width, height top, left,
// format and image of the toGlyph. This is mainly used preserving the glyph if it was
// created by a search of desperation.
SkGlyph* mergeGlyphAndImage(SkPackedGlyphID toID, const SkGlyph& from);
// If the path has never been set, then use the scaler context to add the glyph.
const SkPath* preparePath(SkGlyph*) override;
@ -75,10 +75,6 @@ public:
*/
const void* findImage(const SkGlyph&);
/** Initializes the image associated with the glyph with |data|.
*/
void initializeImage(const void* data, size_t size, SkGlyph*);
/** If the advance axis intersects the glyph's path, append the positions scaled and offset
to the array (if non-null), and set the count to the updated array length.
*/
@ -93,7 +89,6 @@ public:
*/
const SkGlyph* getCachedGlyphAnySubPix(SkGlyphID,
SkPackedGlyphID vetoID = SkPackedGlyphID()) const;
void initializeGlyphFromFallback(SkGlyph* glyph, const SkGlyph&);
/** Return the vertical metrics for this strike.
*/

View File

@ -312,13 +312,13 @@ bool SkStrikeCache::desperationSearchForImage(const SkDescriptor& desc, SkGlyph*
// This desperate-match node may disappear as soon as we drop fLock, so we
// need to copy the glyph from node into this strike, including a
// deep copy of the mask.
targetCache->initializeGlyphFromFallback(glyph, *fallback);
targetCache->mergeGlyphAndImage(glyph->getPackedID(), *fallback);
return true;
}
// Look for any sub-pixel pos for this glyph, in case there is a pos mismatch.
if (const auto* fallback = node->fStrike.getCachedGlyphAnySubPix(glyphID)) {
targetCache->initializeGlyphFromFallback(glyph, *fallback);
targetCache->mergeGlyphAndImage(glyph->getPackedID(), *fallback);
return true;
}
}

View File

@ -48,9 +48,9 @@ void SkScalerContextProxy::generateMetrics(SkGlyph* glyph) {
// fallback before failing.
if (fCache && fCache->belongsToCache(glyph)) {
// First check the original cache, in case there is a sub-pixel pos mismatch.
if (const auto* fallback =
if (const SkGlyph* from =
fCache->getCachedGlyphAnySubPix(glyph->getGlyphID(), glyph->getPackedID())) {
fCache->initializeGlyphFromFallback(glyph, *fallback);
fCache->mergeGlyphAndImage(glyph->getPackedID(), *from);
fDiscardableManager->notifyCacheMiss(
SkStrikeClient::CacheMissType::kGlyphMetricsFallback);
return;