mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
chore: cherry-pick 872b8c13d7 from skia (#28739)
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
cherry-pick-6763a713f957.patch
|
||||
cherry-pick-b0d3d3e85fa6.patch
|
||||
skscalercontext_getimage_less_brittle.patch
|
||||
|
||||
199
patches/skia/skscalercontext_getimage_less_brittle.patch
Normal file
199
patches/skia/skscalercontext_getimage_less_brittle.patch
Normal file
@@ -0,0 +1,199 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Wagner <bungeman@google.com>
|
||||
Date: Thu, 1 Apr 2021 15:02:21 -0400
|
||||
Subject: SkScalerContext::getImage less brittle.
|
||||
|
||||
Properly handle edge cases like
|
||||
* the temporary glyph being a different size than expected
|
||||
* filters which reduce in size
|
||||
* filters which return false to indicate no filtering has been done
|
||||
|
||||
Bug: chromium:1190525
|
||||
Change-Id: Ibc53eb1d7014210019e96cd6bae3e256d967be54
|
||||
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/392156
|
||||
Commit-Queue: Ben Wagner <bungeman@google.com>
|
||||
Reviewed-by: Herb Derby <herb@google.com>
|
||||
(cherry picked from commit 348ee387a96d7d94733d46ad9e82b19cb890dd16)
|
||||
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/392437
|
||||
|
||||
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
|
||||
index a2df87c3ef62790353b8fac8169d83bc657db3d4..d1cb80a631814e995c756dc23764a21b00e97270 100644
|
||||
--- a/src/core/SkScalerContext.cpp
|
||||
+++ b/src/core/SkScalerContext.cpp
|
||||
@@ -534,41 +534,39 @@ static void generateMask(const SkMask& mask, const SkPath& path,
|
||||
}
|
||||
|
||||
void SkScalerContext::getImage(const SkGlyph& origGlyph) {
|
||||
- const SkGlyph* glyph = &origGlyph;
|
||||
+ const SkGlyph* unfilteredGlyph = &origGlyph;
|
||||
SkGlyph tmpGlyph{origGlyph.getPackedID()};
|
||||
|
||||
// in case we need to call generateImage on a mask-format that is different
|
||||
// (i.e. larger) than what our caller allocated by looking at origGlyph.
|
||||
SkAutoMalloc tmpGlyphImageStorage;
|
||||
|
||||
- if (fMaskFilter) { // restore the prefilter bounds
|
||||
-
|
||||
+ if (fMaskFilter) {
|
||||
// need the original bounds, sans our maskfilter
|
||||
sk_sp<SkMaskFilter> mf = std::move(fMaskFilter);
|
||||
this->getMetrics(&tmpGlyph);
|
||||
fMaskFilter = std::move(mf);
|
||||
|
||||
- // we need the prefilter bounds to be <= filter bounds
|
||||
- SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
|
||||
- SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
|
||||
-
|
||||
- if (tmpGlyph.fMaskFormat == origGlyph.fMaskFormat) {
|
||||
+ // Use the origGlyph storage for the temporary unfiltered mask if it will fit.
|
||||
+ if (tmpGlyph.fMaskFormat == origGlyph.fMaskFormat &&
|
||||
+ tmpGlyph.imageSize() <= origGlyph.imageSize())
|
||||
+ {
|
||||
tmpGlyph.fImage = origGlyph.fImage;
|
||||
} else {
|
||||
tmpGlyphImageStorage.reset(tmpGlyph.imageSize());
|
||||
tmpGlyph.fImage = tmpGlyphImageStorage.get();
|
||||
}
|
||||
- glyph = &tmpGlyph;
|
||||
+ unfilteredGlyph = &tmpGlyph;
|
||||
}
|
||||
|
||||
if (!fGenerateImageFromPath) {
|
||||
- generateImage(*glyph);
|
||||
+ generateImage(*unfilteredGlyph);
|
||||
} else {
|
||||
SkPath devPath;
|
||||
- SkMask mask = glyph->mask();
|
||||
+ SkMask mask = unfilteredGlyph->mask();
|
||||
|
||||
- if (!this->internalGetPath(glyph->getPackedID(), &devPath)) {
|
||||
- generateImage(*glyph);
|
||||
+ if (!this->internalGetPath(unfilteredGlyph->getPackedID(), &devPath)) {
|
||||
+ generateImage(*unfilteredGlyph);
|
||||
} else {
|
||||
SkASSERT(SkMask::kARGB32_Format != origGlyph.fMaskFormat);
|
||||
SkASSERT(SkMask::kARGB32_Format != mask.fFormat);
|
||||
@@ -579,39 +577,98 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) {
|
||||
}
|
||||
|
||||
if (fMaskFilter) {
|
||||
- // the src glyph image shouldn't be 3D
|
||||
- SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
|
||||
+ // k3D_Format should not be mask filtered.
|
||||
+ SkASSERT(SkMask::k3D_Format != unfilteredGlyph->fMaskFormat);
|
||||
+
|
||||
+ SkMask filteredMask;
|
||||
+ SkMask srcMask;
|
||||
+ SkMatrix m;
|
||||
+ fRec.getMatrixFrom2x2(&m);
|
||||
+
|
||||
+ if (as_MFB(fMaskFilter)->filterMask(&filteredMask, unfilteredGlyph->mask(), m, nullptr)) {
|
||||
+ // Filter succeeded; filteredMask.fImage was allocated.
|
||||
+ srcMask = filteredMask;
|
||||
+ } else if (unfilteredGlyph->fImage == tmpGlyphImageStorage.get()) {
|
||||
+ // Filter did nothing; unfiltered mask is independent of origGlyph.fImage.
|
||||
+ srcMask = unfilteredGlyph->mask();
|
||||
+ } else if (origGlyph.iRect() == unfilteredGlyph->iRect()) {
|
||||
+ // Filter did nothing; the unfiltered mask is in origGlyph.fImage and matches.
|
||||
+ return;
|
||||
+ } else {
|
||||
+ // Filter did nothing; the unfiltered mask is in origGlyph.fImage and conflicts.
|
||||
+ srcMask = unfilteredGlyph->mask();
|
||||
+ size_t imageSize = unfilteredGlyph->imageSize();
|
||||
+ tmpGlyphImageStorage.reset(imageSize);
|
||||
+ srcMask.fImage = static_cast<uint8_t*>(tmpGlyphImageStorage.get());
|
||||
+ memcpy(srcMask.fImage, unfilteredGlyph->fImage, imageSize);
|
||||
+ }
|
||||
|
||||
- SkMask srcM = glyph->mask(),
|
||||
- dstM;
|
||||
- SkMatrix matrix;
|
||||
+ SkASSERT_RELEASE(srcMask.fFormat == origGlyph.fMaskFormat);
|
||||
+ SkMask dstMask = origGlyph.mask();
|
||||
+ SkIRect origBounds = dstMask.fBounds;
|
||||
|
||||
- fRec.getMatrixFrom2x2(&matrix);
|
||||
+ // Find the intersection of src and dst while updating the fImages.
|
||||
+ if (srcMask.fBounds.fTop < dstMask.fBounds.fTop) {
|
||||
+ int32_t topDiff = dstMask.fBounds.fTop - srcMask.fBounds.fTop;
|
||||
+ srcMask.fImage += srcMask.fRowBytes * topDiff;
|
||||
+ srcMask.fBounds.fTop = dstMask.fBounds.fTop;
|
||||
+ }
|
||||
+ if (dstMask.fBounds.fTop < srcMask.fBounds.fTop) {
|
||||
+ int32_t topDiff = srcMask.fBounds.fTop - dstMask.fBounds.fTop;
|
||||
+ dstMask.fImage += dstMask.fRowBytes * topDiff;
|
||||
+ dstMask.fBounds.fTop = srcMask.fBounds.fTop;
|
||||
+ }
|
||||
|
||||
- if (as_MFB(fMaskFilter)->filterMask(&dstM, srcM, matrix, nullptr)) {
|
||||
- int width = std::min<int>(origGlyph.fWidth, dstM.fBounds.width());
|
||||
- int height = std::min<int>(origGlyph.fHeight, dstM.fBounds.height());
|
||||
- int dstRB = origGlyph.rowBytes();
|
||||
- int srcRB = dstM.fRowBytes;
|
||||
+ if (srcMask.fBounds.fLeft < dstMask.fBounds.fLeft) {
|
||||
+ int32_t leftDiff = dstMask.fBounds.fLeft - srcMask.fBounds.fLeft;
|
||||
+ srcMask.fImage += leftDiff;
|
||||
+ srcMask.fBounds.fLeft = dstMask.fBounds.fLeft;
|
||||
+ }
|
||||
+ if (dstMask.fBounds.fLeft < srcMask.fBounds.fLeft) {
|
||||
+ int32_t leftDiff = srcMask.fBounds.fLeft - dstMask.fBounds.fLeft;
|
||||
+ dstMask.fImage += leftDiff;
|
||||
+ dstMask.fBounds.fLeft = srcMask.fBounds.fLeft;
|
||||
+ }
|
||||
|
||||
- const uint8_t* src = (const uint8_t*)dstM.fImage;
|
||||
- uint8_t* dst = (uint8_t*)origGlyph.fImage;
|
||||
+ if (srcMask.fBounds.fBottom < dstMask.fBounds.fBottom) {
|
||||
+ dstMask.fBounds.fBottom = srcMask.fBounds.fBottom;
|
||||
+ }
|
||||
+ if (dstMask.fBounds.fBottom < srcMask.fBounds.fBottom) {
|
||||
+ srcMask.fBounds.fBottom = dstMask.fBounds.fBottom;
|
||||
+ }
|
||||
|
||||
- if (SkMask::k3D_Format == dstM.fFormat) {
|
||||
- // we have to copy 3 times as much
|
||||
- height *= 3;
|
||||
- }
|
||||
+ if (srcMask.fBounds.fRight < dstMask.fBounds.fRight) {
|
||||
+ dstMask.fBounds.fRight = srcMask.fBounds.fRight;
|
||||
+ }
|
||||
+ if (dstMask.fBounds.fRight < srcMask.fBounds.fRight) {
|
||||
+ srcMask.fBounds.fRight = dstMask.fBounds.fRight;
|
||||
+ }
|
||||
|
||||
- // clean out our glyph, since it may be larger than dstM
|
||||
- //sk_bzero(dst, height * dstRB);
|
||||
+ SkASSERT(srcMask.fBounds == dstMask.fBounds);
|
||||
+ int width = srcMask.fBounds.width();
|
||||
+ int height = srcMask.fBounds.height();
|
||||
+ int dstRB = dstMask.fRowBytes;
|
||||
+ int srcRB = srcMask.fRowBytes;
|
||||
|
||||
- while (--height >= 0) {
|
||||
- memcpy(dst, src, width);
|
||||
- src += srcRB;
|
||||
- dst += dstRB;
|
||||
- }
|
||||
- SkMask::FreeImage(dstM.fImage);
|
||||
+ const uint8_t* src = srcMask.fImage;
|
||||
+ uint8_t* dst = dstMask.fImage;
|
||||
+
|
||||
+ if (SkMask::k3D_Format == filteredMask.fFormat) {
|
||||
+ // we have to copy 3 times as much
|
||||
+ height *= 3;
|
||||
+ }
|
||||
+
|
||||
+ // If not filling the full original glyph, clear it out first.
|
||||
+ if (dstMask.fBounds != origBounds) {
|
||||
+ sk_bzero(origGlyph.fImage, origGlyph.fHeight * origGlyph.rowBytes());
|
||||
+ }
|
||||
+
|
||||
+ while (--height >= 0) {
|
||||
+ memcpy(dst, src, width);
|
||||
+ src += srcRB;
|
||||
+ dst += dstRB;
|
||||
}
|
||||
+ SkMask::FreeImage(filteredMask.fImage);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user