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:
parent
adf18ce45a
commit
7019060abd
@ -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());
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user