WebKit Bugzilla
Attachment 368307 Details for
Bug 197308
: [Cairo] Improve ShadowBlur performance using tiling optimization
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
b197308.patch (text/plain), 51.20 KB, created by
Tomoki Imai
on 2019-04-26 00:20:36 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Tomoki Imai
Created:
2019-04-26 00:20:36 PDT
Size:
51.20 KB
patch
obsolete
>diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index d98a0c293b1..bde52183860 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,82 @@ >+2019-04-25 Tomoki Imai <Tomoki.Imai@sony.com> >+ >+ [Cairo] Improve ShadowBlur performance using tiling optimization >+ https://bugs.webkit.org/show_bug.cgi?id=197308 >+ Reviewed by NOBODY (OOPS!). >+ >+ Enable tiling tiling-based optimization for drawRectShadow() and drawInsetShadow(). >+ Since r228776, cairo ports doesn't have tiling-based optimization. >+ >+ For AppleWin, this patch refactors code and it shares almost same code as cairo port. >+ Only the difference is that AppleWin uses ScratchBuffer, but cairo ports doesn't. >+ This should avoid a performance regression for AppleWin. >+ >+ No new tests, covered by existing tests. >+ >+ * platform/graphics/ShadowBlur.cpp: >+ (WebCore::calculateLobes): >+ Fix stylecheck errors >+ >+ (WebCore::ShadowBlur::blurLayerImage): >+ Fix stylecheck errors >+ >+ (WebCore::ShadowBlur::calculateLayerBoundingRect): >+ We don't use position of m_sourceRect, so change the type to FloatSize. >+ >+ (WebCore::ShadowBlur::drawShadowBuffer): >+ Use m_layerSize instead of m_shadowedResultSize to fillRect, as m_layerSize is always smaller than m_shadowedResultSize. >+ It's because in m_layerSize is equal to m_shadowedResultSize if it's not clipped. >+ Clipping doesn't increase size of m_layerSize, so m_layerSize is always smaller than or equal to m_shadowedResultSize. >+ >+ (WebCore::ShadowBlur::templateSize const): >+ Fix stylecheck errors >+ >+ (WebCore::ShadowBlur::drawRectShadow): >+ (WebCore::ShadowBlur::drawInsetShadow): >+ (WebCore::ShadowBlur::drawRectShadowWithoutTiling): >+ (WebCore::ShadowBlur::drawInsetShadowWithoutTiling): >+ (WebCore::ShadowBlur::drawRectShadowWithTiling): >+ (WebCore::ShadowBlur::drawInsetShadowWithTiling): >+ Incorporate tile-based drawing. >+ To accomplish it, this patch abstracts GraphicsContext::drawImageBuffer to ShadowBlur::DrawImageCallback, >+ GraphicsContext::fillRect to ShadowBlur::FillRectCallback, drawing rect with hole to ShadowBlur::FillRectWithHoleCallback. >+ >+ Variants which takes GraphicsContext as parameter now just calls another drawRectShadow. >+ >+ (WebCore::ShadowBlur::drawLayerPieces): >+ Instead of graphicsContext.drawImageBuffer, call corresponding callback. >+ >+ (WebCore::ShadowBlur::drawLayerPiecesAndFillCenter): >+ This function calls drawLayerPieces and fill center for outer shadow. >+ Drawing outer shadow requires another callback for graphicsContext.fillRect. >+ >+ (WebCore::ShadowBlur::drawShadowLayer): >+ Use m_layerSize instead of m_shadowedResultSize to fillRect, >+ as m_layerSize is always smaller than m_shadowedResultSize. >+ >+ * platform/graphics/ShadowBlur.h: >+ Rename m_sourceRect to m_shadowedResultSize, and change it to FloatSize from FloatRect. >+ Remove GraphicsContext usage as much as possible and replace them by corresponding callbacks. >+ >+ * platform/graphics/cairo/CairoOperations.cpp: >+ (WebCore::Cairo::drawShadowImage): >+ This function corresponds to ShadowBlur::DrawImageCallback. >+ >+ (WebCore::Cairo::fillShadowBuffer): >+ Erase sourceRect, as it's always bigger than layerSize. >+ >+ (WebCore::Cairo::drawPathShadow): >+ (WebCore::Cairo::drawGlyphsShadow): >+ Erase unused parameter. >+ >+ (WebCore::Cairo::fillRect): >+ (WebCore::Cairo::fillRoundedRect): >+ (WebCore::Cairo::fillRectWithRoundedHole): >+ For tile-based optimization, add extra arguments to drawRectShadow. >+ >+ (WebCore::Cairo::drawSurface): >+ Erase unused parameter. >+ > 2019-04-02 Chris Dumez <cdumez@apple.com> > > XMLHttpRequestUpload's loadstart event not correct initialized >diff --git a/Source/WebCore/platform/graphics/ShadowBlur.cpp b/Source/WebCore/platform/graphics/ShadowBlur.cpp >index fdc2b78bc65..b01596dded9 100644 >--- a/Source/WebCore/platform/graphics/ShadowBlur.cpp >+++ b/Source/WebCore/platform/graphics/ShadowBlur.cpp >@@ -24,7 +24,7 @@ > * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY > * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > */ > > #include "config.h" >@@ -42,10 +42,11 @@ > namespace WebCore { > > enum { >- leftLobe = 0, >- rightLobe = 1 >+ LeftLobe = 0, >+ RightLobe = 1 > }; > >+#if USE(CG) > static inline int roundUpToMultipleOf32(int d) > { > return (1 + (d >> 5)) << 5; >@@ -65,7 +66,7 @@ public: > #endif > { > } >- >+ > ImageBuffer* getScratchBuffer(const IntSize& size) > { > ASSERT(!m_bufferInUse); >@@ -127,7 +128,7 @@ public: > const Seconds scratchBufferPurgeInterval { 2_s }; > m_purgeTimer.startOneShot(scratchBufferPurgeInterval); > } >- >+ > static ScratchBuffer& singleton(); > > private: >@@ -140,7 +141,7 @@ private: > > std::unique_ptr<ImageBuffer> m_imageBuffer; > Timer m_purgeTimer; >- >+ > FloatRect m_lastInsetBounds; > FloatRect m_lastShadowRect; > FloatRoundedRect::Radii m_lastRadii; >@@ -148,7 +149,7 @@ private: > FloatSize m_lastRadius; > bool m_lastWasInset; > FloatSize m_lastLayerSize; >- >+ > #if !ASSERT_DISABLED > bool m_bufferInUse; > #endif >@@ -160,15 +161,14 @@ ScratchBuffer& ScratchBuffer::singleton() > return scratchBuffer; > } > >-static const int templateSideLength = 1; >- >-#if USE(CG) > static float radiusToLegacyRadius(float radius) > { > return radius > 8 ? 8 + 4 * sqrt((radius - 8) / 2) : radius; > } > #endif > >+static const int templateSideLength = 1; >+ > ShadowBlur::ShadowBlur() = default; > > ShadowBlur::ShadowBlur(const FloatSize& radius, const FloatSize& offset, const Color& color, bool shadowsIgnoreTransforms) >@@ -249,23 +249,23 @@ static void calculateLobes(int lobes[][2], float blurRadius, bool shadowsIgnoreT > if (diameter & 1) { > // if d is odd, use three box-blurs of size 'd', centered on the output pixel. > int lobeSize = (diameter - 1) / 2; >- lobes[0][leftLobe] = lobeSize; >- lobes[0][rightLobe] = lobeSize; >- lobes[1][leftLobe] = lobeSize; >- lobes[1][rightLobe] = lobeSize; >- lobes[2][leftLobe] = lobeSize; >- lobes[2][rightLobe] = lobeSize; >+ lobes[0][LeftLobe] = lobeSize; >+ lobes[0][RightLobe] = lobeSize; >+ lobes[1][LeftLobe] = lobeSize; >+ lobes[1][RightLobe] = lobeSize; >+ lobes[2][LeftLobe] = lobeSize; >+ lobes[2][RightLobe] = lobeSize; > } else { > // if d is even, two box-blurs of size 'd' (the first one centered on the pixel boundary > // between the output pixel and the one to the left, the second one centered on the pixel > // boundary between the output pixel and the one to the right) and one box blur of size 'd+1' centered on the output pixel > int lobeSize = diameter / 2; >- lobes[0][leftLobe] = lobeSize; >- lobes[0][rightLobe] = lobeSize - 1; >- lobes[1][leftLobe] = lobeSize - 1; >- lobes[1][rightLobe] = lobeSize; >- lobes[2][leftLobe] = lobeSize; >- lobes[2][rightLobe] = lobeSize; >+ lobes[0][LeftLobe] = lobeSize; >+ lobes[0][RightLobe] = lobeSize - 1; >+ lobes[1][LeftLobe] = lobeSize - 1; >+ lobes[1][RightLobe] = lobeSize; >+ lobes[2][LeftLobe] = lobeSize; >+ lobes[2][RightLobe] = lobeSize; > } > } > >@@ -293,7 +293,7 @@ void ShadowBlur::blurLayerImage(unsigned char* imageData, const IntSize& size, i > // Two stages: horizontal and vertical > for (int pass = 0; pass < 2; ++pass) { > unsigned char* pixels = imageData; >- >+ > if (!pass && !m_blurRadius.width()) > final = 0; // Do no work if horizonal blur is zero. > >@@ -304,8 +304,8 @@ void ShadowBlur::blurLayerImage(unsigned char* imageData, const IntSize& size, i > // This is much more efficient than computing the sum of each pixels > // covered by the box kernel size for each x. > for (int step = 0; step < 3; ++step) { >- int side1 = lobes[step][leftLobe]; >- int side2 = lobes[step][rightLobe]; >+ int side1 = lobes[step][LeftLobe]; >+ int side2 = lobes[step][RightLobe]; > int pixelCount = side1 + 1 + side2; > int invCount = ((1 << blurSumShift) + pixelCount - 1) / pixelCount; > int ofs = 1 + side2; >@@ -331,13 +331,13 @@ void ShadowBlur::blurLayerImage(unsigned char* imageData, const IntSize& size, i > *ptr = (sum * invCount) >> blurSumShift; > sum += ((ofs < dim) ? *next : alpha2) - alpha1; > } >- >+ > prev = pixels + channels[step]; > for (; ofs < dim; ptr += stride, prev += stride, next += stride, ++i, ++ofs) { > *ptr = (sum * invCount) >> blurSumShift; > sum += (*next) - (*prev); > } >- >+ > for (; i < dim; ptr += stride, prev += stride, ++i) { > *ptr = (sum * invCount) >> blurSumShift; > sum += alpha2 - (*prev); >@@ -422,13 +422,13 @@ IntSize ShadowBlur::calculateLayerBoundingRect(const AffineTransform& transform, > inflatedClip.inflateX(1); > inflatedClip.inflateY(1); > } >- >+ > layerRect.intersect(inflatedClip); > } > > IntSize frameSize = inflation; > frameSize.scale(2); >- m_sourceRect = FloatRect(0, 0, shadowedRect.width() + frameSize.width(), shadowedRect.height() + frameSize.height()); >+ m_shadowedResultSize = FloatSize(shadowedRect.width() + frameSize.width(), shadowedRect.height() + frameSize.height()); > m_layerOrigin = FloatPoint(layerRect.x(), layerRect.y()); > m_layerSize = layerRect.size(); > >@@ -461,7 +461,7 @@ void ShadowBlur::drawShadowBuffer(GraphicsContext& graphicsContext) > graphicsContext.setFillColor(m_color); > > graphicsContext.clearShadow(); >- graphicsContext.fillRect(FloatRect(m_layerOrigin, m_sourceRect.size())); >+ graphicsContext.fillRect(FloatRect(m_layerOrigin, m_layerSize)); > } > > static void computeSliceSizesFromRadii(const IntSize& twiceRadius, const FloatRoundedRect::Radii& radii, int& leftSlice, int& rightSlice, int& topSlice, int& bottomSlice) >@@ -481,87 +481,131 @@ IntSize ShadowBlur::templateSize(const IntSize& radiusPadding, const FloatRounde > int rightSlice; > int topSlice; > int bottomSlice; >- >+ > IntSize blurExpansion = radiusPadding; > blurExpansion.scale(2); > > computeSliceSizesFromRadii(blurExpansion, radii, leftSlice, rightSlice, topSlice, bottomSlice); >- >- return IntSize(templateSideLength + leftSlice + rightSlice, >- templateSideLength + topSlice + bottomSlice); >+ >+ return IntSize(templateSideLength + leftSlice + rightSlice, templateSideLength + topSlice + bottomSlice); > } > > void ShadowBlur::drawRectShadow(GraphicsContext& graphicsContext, const FloatRoundedRect& shadowedRect) > { >- IntSize layerSize = calculateLayerBoundingRect(graphicsContext.getCTM(), shadowedRect.rect(), graphicsContext.clipBounds()); >+ drawRectShadow(graphicsContext.getCTM(), graphicsContext.clipBounds(), shadowedRect, >+ [this, &graphicsContext](ImageBuffer&, const FloatPoint&, const FloatSize&) { >+ // FIXME: Use parameters instead of implicit parameters defined as class variables. >+ drawShadowBuffer(graphicsContext); >+ }, >+ [&graphicsContext](ImageBuffer& image, const FloatRect& destRect, const FloatRect& srcRect) { >+ GraphicsContextStateSaver stateSaver(graphicsContext); >+ graphicsContext.clearShadow(); >+ graphicsContext.drawImageBuffer(image, destRect, srcRect); >+ }, >+ [&graphicsContext](const FloatRect& rect, const Color& color) { >+ GraphicsContextStateSaver stateSaver(graphicsContext); >+ graphicsContext.setFillColor(color); >+ graphicsContext.clearShadow(); >+ graphicsContext.fillRect(rect); >+ }); >+} >+ >+void ShadowBlur::drawInsetShadow(GraphicsContext& graphicsContext, const FloatRect& fullRect, const FloatRoundedRect& holeRect) >+{ >+ drawInsetShadow(graphicsContext.getCTM(), graphicsContext.clipBounds(), fullRect, holeRect, >+ [this, &graphicsContext](ImageBuffer&, const FloatPoint&, const FloatSize&) { >+ // FIXME: Use parameters instead of implicit parameters defined as class variables. >+ drawShadowBuffer(graphicsContext); >+ }, >+ [&graphicsContext](ImageBuffer& image, const FloatRect& destRect, const FloatRect& srcRect) { >+ // Note that drawing the ImageBuffer is faster than creating a Image and drawing that, >+ // because ImageBuffer::draw() knows that it doesn't have to copy the image bits. >+ GraphicsContextStateSaver stateSaver(graphicsContext); >+ graphicsContext.clearShadow(); >+ graphicsContext.drawImageBuffer(image, destRect, srcRect); >+ }, >+ [&graphicsContext](const FloatRect& rect, const FloatRect& holeRect, const Color& color) { >+ Path exteriorPath; >+ exteriorPath.addRect(rect); >+ exteriorPath.addRect(holeRect); >+ >+ GraphicsContextStateSaver fillStateSaver(graphicsContext); >+ graphicsContext.setFillRule(WindRule::EvenOdd); >+ graphicsContext.setFillColor(color); >+ graphicsContext.clearShadow(); >+ graphicsContext.fillPath(exteriorPath); >+ }); >+} >+ >+void ShadowBlur::drawRectShadow(const AffineTransform& transform, const IntRect& clipBounds, const FloatRoundedRect& shadowedRect, const DrawBufferCallback& drawBuffer, const DrawImageCallback& drawImage, const FillRectCallback& fillRect) >+{ >+ IntSize layerSize = calculateLayerBoundingRect(transform, shadowedRect.rect(), clipBounds); > if (layerSize.isEmpty()) > return; > >- adjustBlurRadius(graphicsContext.getCTM()); >+ adjustBlurRadius(transform); >+ >+ bool canUseTilingTechnique = true; > > // drawRectShadowWithTiling does not work with rotations. > // https://bugs.webkit.org/show_bug.cgi?id=45042 >- if (!graphicsContext.getCTM().preservesAxisAlignment() || m_type != BlurShadow) { >- drawRectShadowWithoutTiling(graphicsContext, shadowedRect, layerSize); >- return; >- } >+ if (!transform.preservesAxisAlignment() || m_type != BlurShadow) >+ canUseTilingTechnique = false; > > IntSize edgeSize = blurredEdgeSize(); > IntSize templateSize = this->templateSize(edgeSize, shadowedRect.radii()); > const FloatRect& rect = shadowedRect.rect(); > > if (templateSize.width() > rect.width() || templateSize.height() > rect.height() >- || (templateSize.width() * templateSize.height() > m_sourceRect.width() * m_sourceRect.height())) { >- drawRectShadowWithoutTiling(graphicsContext, shadowedRect, layerSize); >- return; >- } >+ || (templateSize.width() * templateSize.height() > m_shadowedResultSize.width() * m_shadowedResultSize.height())) >+ canUseTilingTechnique = false; > >- drawRectShadowWithTiling(graphicsContext, shadowedRect, templateSize, edgeSize); >+ if (canUseTilingTechnique) >+ drawRectShadowWithTiling(transform, shadowedRect, templateSize, edgeSize, drawImage, fillRect); >+ else >+ drawRectShadowWithoutTiling(transform, shadowedRect, layerSize, drawBuffer); > } > >-void ShadowBlur::drawInsetShadow(GraphicsContext& graphicsContext, const FloatRect& rect, const FloatRoundedRect& holeRect) >+void ShadowBlur::drawInsetShadow(const AffineTransform& transform, const IntRect& clipBounds, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const DrawBufferCallback& drawBuffer, const DrawImageCallback& drawImage, const FillRectWithHoleCallback& fillRectWithHole) > { >- IntSize layerSize = calculateLayerBoundingRect(graphicsContext.getCTM(), rect, graphicsContext.clipBounds()); >+ IntSize layerSize = calculateLayerBoundingRect(transform, fullRect, clipBounds); > if (layerSize.isEmpty()) > return; > >- adjustBlurRadius(graphicsContext.getCTM()); >+ adjustBlurRadius(transform); >+ >+ bool canUseTilingTechnique = true; > >- // drawInsetShadowWithTiling does not work with rotations. >+ // drawRectShadowWithTiling does not work with rotations. > // https://bugs.webkit.org/show_bug.cgi?id=45042 >- if (!graphicsContext.getCTM().preservesAxisAlignment() || m_type != BlurShadow) { >- drawInsetShadowWithoutTiling(graphicsContext, rect, holeRect, layerSize); >- return; >- } >+ if (!transform.preservesAxisAlignment() || m_type != BlurShadow) >+ canUseTilingTechnique = false; > > IntSize edgeSize = blurredEdgeSize(); > IntSize templateSize = this->templateSize(edgeSize, holeRect.radii()); > const FloatRect& hRect = holeRect.rect(); > > if (templateSize.width() > hRect.width() || templateSize.height() > hRect.height() >- || (templateSize.width() * templateSize.height() > hRect.width() * hRect.height())) { >- drawInsetShadowWithoutTiling(graphicsContext, rect, holeRect, layerSize); >- return; >- } >+ || (templateSize.width() * templateSize.height() > hRect.width() * hRect.height())) >+ canUseTilingTechnique = false; > >- drawInsetShadowWithTiling(graphicsContext, rect, holeRect, templateSize, edgeSize); >+ if (canUseTilingTechnique) >+ drawInsetShadowWithTiling(transform, fullRect, holeRect, templateSize, edgeSize, drawImage, fillRectWithHole); >+ else >+ drawInsetShadowWithoutTiling(transform, fullRect, holeRect, layerSize, drawBuffer); > } > >-void ShadowBlur::drawRectShadow(const AffineTransform& transform, const IntRect& clipBounds, const FloatRoundedRect& shadowedRect, const DrawBufferCallback& drawBuffer) >+void ShadowBlur::drawRectShadowWithoutTiling(const AffineTransform&, const FloatRoundedRect& shadowedRect, const IntSize& layerSize, const DrawBufferCallback& drawBuffer) > { >- // FIXME: Try incorporating tile-based rect shadow drawing for the same use case. >- >- IntSize layerSize = calculateLayerBoundingRect(transform, shadowedRect.rect(), clipBounds); >- if (layerSize.isEmpty()) >- return; >- >- adjustBlurRadius(transform); >- > auto layerImage = ImageBuffer::create(layerSize, Unaccelerated, 1); > if (!layerImage) > return; > m_layerImage = layerImage.get(); > >+ GraphicsContext& shadowContext = layerImage->context(); >+ GraphicsContextStateSaver stateSaver(shadowContext); >+ shadowContext.setFillColor(Color::black); >+ > { > GraphicsContext& shadowContext = layerImage->context(); > GraphicsContextStateSaver stateSaver(shadowContext); >@@ -577,20 +621,11 @@ void ShadowBlur::drawRectShadow(const AffineTransform& transform, const IntRect& > > blurShadowBuffer(layerSize); > } >- >- drawBuffer(*layerImage, m_layerOrigin, m_layerSize, m_sourceRect); >+ drawBuffer(*layerImage, m_layerOrigin, m_layerSize); > } > >-void ShadowBlur::drawInsetShadow(const AffineTransform& transform, const IntRect& clipBounds, const FloatRect& rect, const FloatRoundedRect& holeRect, const DrawBufferCallback& drawBuffer) >+void ShadowBlur::drawInsetShadowWithoutTiling(const AffineTransform&, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const IntSize& layerSize, const DrawBufferCallback& drawBuffer) > { >- // FIXME: Try incorporating tile-based inset shadow drawing for the same use case. >- >- IntSize layerSize = calculateLayerBoundingRect(transform, rect, clipBounds); >- if (layerSize.isEmpty()) >- return; >- >- adjustBlurRadius(transform); >- > auto layerImage = ImageBuffer::create(layerSize, Unaccelerated, 1); > if (!layerImage) > return; >@@ -602,7 +637,7 @@ void ShadowBlur::drawInsetShadow(const AffineTransform& transform, const IntRect > shadowContext.translate(m_layerContextTranslation); > > Path path; >- path.addRect(rect); >+ path.addRect(fullRect); > if (holeRect.radii().isZero()) > path.addRect(holeRect.rect()); > else >@@ -615,83 +650,7 @@ void ShadowBlur::drawInsetShadow(const AffineTransform& transform, const IntRect > blurShadowBuffer(layerSize); > } > >- drawBuffer(*layerImage, m_layerOrigin, m_layerSize, m_sourceRect); >-} >- >-void ShadowBlur::drawRectShadowWithoutTiling(GraphicsContext& graphicsContext, const FloatRoundedRect& shadowedRect, const IntSize& layerSize) >-{ >- m_layerImage = ScratchBuffer::singleton().getScratchBuffer(layerSize); >- if (!m_layerImage) >- return; >- >- FloatRect bufferRelativeShadowedRect = shadowedRect.rect(); >- bufferRelativeShadowedRect.move(m_layerContextTranslation); >- >- // Only redraw in the scratch buffer if its cached contents don't match our needs >- bool redrawNeeded = ScratchBuffer::singleton().setCachedShadowValues(m_blurRadius, Color::black, bufferRelativeShadowedRect, shadowedRect.radii(), m_layerSize); >- if (redrawNeeded) { >- GraphicsContext& shadowContext = m_layerImage->context(); >- GraphicsContextStateSaver stateSaver(shadowContext); >- >- // Add a pixel to avoid later edge aliasing when rotated. >- shadowContext.clearRect(FloatRect(0, 0, m_layerSize.width() + 1, m_layerSize.height() + 1)); >- shadowContext.translate(m_layerContextTranslation); >- shadowContext.setFillColor(Color::black); >- if (shadowedRect.radii().isZero()) >- shadowContext.fillRect(shadowedRect.rect()); >- else { >- Path path; >- path.addRoundedRect(shadowedRect); >- shadowContext.fillPath(path); >- } >- >- blurShadowBuffer(layerSize); >- } >- >- drawShadowBuffer(graphicsContext); >- m_layerImage = nullptr; >- ScratchBuffer::singleton().scheduleScratchBufferPurge(); >-} >- >-void ShadowBlur::drawInsetShadowWithoutTiling(GraphicsContext& graphicsContext, const FloatRect& rect, const FloatRoundedRect& holeRect, const IntSize& layerSize) >-{ >- m_layerImage = ScratchBuffer::singleton().getScratchBuffer(layerSize); >- if (!m_layerImage) >- return; >- >- FloatRect bufferRelativeRect = rect; >- bufferRelativeRect.move(m_layerContextTranslation); >- >- FloatRect bufferRelativeHoleRect = holeRect.rect(); >- bufferRelativeHoleRect.move(m_layerContextTranslation); >- >- // Only redraw in the scratch buffer if its cached contents don't match our needs >- bool redrawNeeded = ScratchBuffer::singleton().setCachedInsetShadowValues(m_blurRadius, Color::black, bufferRelativeRect, bufferRelativeHoleRect, holeRect.radii()); >- if (redrawNeeded) { >- GraphicsContext& shadowContext = m_layerImage->context(); >- GraphicsContextStateSaver stateSaver(shadowContext); >- >- // Add a pixel to avoid later edge aliasing when rotated. >- shadowContext.clearRect(FloatRect(0, 0, m_layerSize.width() + 1, m_layerSize.height() + 1)); >- shadowContext.translate(m_layerContextTranslation); >- >- Path path; >- path.addRect(rect); >- if (holeRect.radii().isZero()) >- path.addRect(holeRect.rect()); >- else >- path.addRoundedRect(holeRect); >- >- shadowContext.setFillRule(WindRule::EvenOdd); >- shadowContext.setFillColor(Color::black); >- shadowContext.fillPath(path); >- >- blurShadowBuffer(layerSize); >- } >- >- drawShadowBuffer(graphicsContext); >- m_layerImage = nullptr; >- ScratchBuffer::singleton().scheduleScratchBufferPurge(); >+ drawBuffer(*layerImage, m_layerOrigin, m_layerSize); > } > > /* >@@ -726,9 +685,71 @@ void ShadowBlur::drawInsetShadowWithoutTiling(GraphicsContext& graphicsContext, > the shadow. > */ > >-void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext& graphicsContext, const FloatRect& rect, const FloatRoundedRect& holeRect, const IntSize& templateSize, const IntSize& edgeSize) >+void ShadowBlur::drawRectShadowWithTiling(const AffineTransform& transform, const FloatRoundedRect& shadowedRect, const IntSize& templateSize, const IntSize& edgeSize, const DrawImageCallback& drawImage, const FillRectCallback& fillRect) >+{ >+#if USE(CG) >+ m_layerImage = ScratchBuffer::singleton().getScratchBuffer(templateSize); >+#else >+ auto layerImage = ImageBuffer::create(templateSize, Unaccelerated, 1); >+ m_layerImage = layerImage.get(); >+#endif >+ >+ if (!m_layerImage) >+ return; >+ >+ FloatRect templateShadow = FloatRect(edgeSize.width(), edgeSize.height(), templateSize.width() - 2 * edgeSize.width(), templateSize.height() - 2 * edgeSize.height()); >+ >+ bool redrawNeeded = true; >+#if USE(CG) >+ // Only redraw in the scratch buffer if its cached contents don't match our needs >+ redrawNeeded = ScratchBuffer::singleton().setCachedShadowValues(m_blurRadius, m_color, templateShadow, shadowedRect.radii(), m_layerSize); >+#endif >+ >+ if (redrawNeeded) { >+ // Draw shadow into the ImageBuffer. >+ GraphicsContext& shadowContext = m_layerImage->context(); >+ GraphicsContextStateSaver shadowStateSaver(shadowContext); >+ >+ shadowContext.clearRect(FloatRect(0, 0, templateSize.width(), templateSize.height())); >+ shadowContext.setFillColor(Color::black); >+ >+ if (shadowedRect.radii().isZero()) >+ shadowContext.fillRect(templateShadow); >+ else { >+ Path path; >+ path.addRoundedRect(FloatRoundedRect(templateShadow, shadowedRect.radii())); >+ shadowContext.fillPath(path); >+ } >+ blurAndColorShadowBuffer(templateSize); >+ } >+ >+ FloatSize offset = m_offset; >+ if (shadowsIgnoreTransforms()) >+ offset.scale(1 / transform.xScale(), 1 / transform.yScale()); >+ >+ FloatRect shadowBounds = shadowedRect.rect(); >+ shadowBounds.move(offset); >+ shadowBounds.inflateX(edgeSize.width()); >+ shadowBounds.inflateY(edgeSize.height()); >+ >+ drawLayerPiecesAndFillCenter(shadowBounds, shadowedRect.radii(), edgeSize, templateSize, drawImage, fillRect); >+ >+ m_layerImage = nullptr; >+ >+#if USE(CG) >+ ScratchBuffer::singleton().scheduleScratchBufferPurge(); >+#endif >+} >+ >+void ShadowBlur::drawInsetShadowWithTiling(const AffineTransform& transform, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const IntSize& templateSize, const IntSize& edgeSize, const DrawImageCallback& drawImage, const FillRectWithHoleCallback& fillRectWithHole) > { >+#if USE(CG) > m_layerImage = ScratchBuffer::singleton().getScratchBuffer(templateSize); >+#else >+ auto layerImage = ImageBuffer::create(templateSize, Unaccelerated, 1); >+ m_layerImage = layerImage.get(); >+#endif >+ > if (!m_layerImage) > return; > >@@ -736,8 +757,12 @@ void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext& graphicsContext, con > FloatRect templateBounds(0, 0, templateSize.width(), templateSize.height()); > FloatRect templateHole = FloatRect(edgeSize.width(), edgeSize.height(), templateSize.width() - 2 * edgeSize.width(), templateSize.height() - 2 * edgeSize.height()); > >+ bool redrawNeeded = true; >+#if USE(CG) > // Only redraw in the scratch buffer if its cached contents don't match our needs >- bool redrawNeeded = ScratchBuffer::singleton().setCachedInsetShadowValues(m_blurRadius, m_color, templateBounds, templateHole, holeRect.radii()); >+ redrawNeeded = ScratchBuffer::singleton().setCachedInsetShadowValues(m_blurRadius, m_color, templateBounds, templateHole, holeRect.radii()); >+#endif >+ > if (redrawNeeded) { > // Draw shadow into a new ImageBuffer. > GraphicsContext& shadowContext = m_layerImage->context(); >@@ -758,12 +783,10 @@ void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext& graphicsContext, con > blurAndColorShadowBuffer(templateSize); > } > FloatSize offset = m_offset; >- if (shadowsIgnoreTransforms()) { >- AffineTransform transform = graphicsContext.getCTM(); >+ if (shadowsIgnoreTransforms()) > offset.scale(1 / transform.xScale(), 1 / transform.yScale()); >- } > >- FloatRect boundingRect = rect; >+ FloatRect boundingRect = fullRect; > boundingRect.move(offset); > > FloatRect destHoleRect = holeRect.rect(); >@@ -773,71 +796,18 @@ void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext& graphicsContext, con > destHoleBounds.inflateY(edgeSize.height()); > > // Fill the external part of the shadow (which may be visible because of offset). >- Path exteriorPath; >- exteriorPath.addRect(boundingRect); >- exteriorPath.addRect(destHoleBounds); >+ fillRectWithHole(boundingRect, destHoleBounds, m_color); > >- { >- GraphicsContextStateSaver fillStateSaver(graphicsContext); >- graphicsContext.setFillRule(WindRule::EvenOdd); >- graphicsContext.setFillColor(m_color); >- graphicsContext.clearShadow(); >- graphicsContext.fillPath(exteriorPath); >- } >- >- drawLayerPieces(graphicsContext, destHoleBounds, holeRect.radii(), edgeSize, templateSize, InnerShadow); >+ drawLayerPieces(destHoleBounds, holeRect.radii(), edgeSize, templateSize, drawImage); > > m_layerImage = nullptr; >- ScratchBuffer::singleton().scheduleScratchBufferPurge(); >-} >- >-void ShadowBlur::drawRectShadowWithTiling(GraphicsContext& graphicsContext, const FloatRoundedRect& shadowedRect, const IntSize& templateSize, const IntSize& edgeSize) >-{ >- auto& scratchBuffer = ScratchBuffer::singleton(); >- m_layerImage = scratchBuffer.getScratchBuffer(templateSize); >- if (!m_layerImage) >- return; > >- FloatRect templateShadow = FloatRect(edgeSize.width(), edgeSize.height(), templateSize.width() - 2 * edgeSize.width(), templateSize.height() - 2 * edgeSize.height()); >- >- // Only redraw in the scratch buffer if its cached contents don't match our needs >- bool redrawNeeded = scratchBuffer.setCachedShadowValues(m_blurRadius, m_color, templateShadow, shadowedRect.radii(), m_layerSize); >- if (redrawNeeded) { >- // Draw shadow into the ImageBuffer. >- GraphicsContext& shadowContext = m_layerImage->context(); >- GraphicsContextStateSaver shadowStateSaver(shadowContext); >- >- shadowContext.clearRect(FloatRect(0, 0, templateSize.width(), templateSize.height())); >- shadowContext.setFillColor(Color::black); >- >- if (shadowedRect.radii().isZero()) >- shadowContext.fillRect(templateShadow); >- else { >- Path path; >- path.addRoundedRect(FloatRoundedRect(templateShadow, shadowedRect.radii())); >- shadowContext.fillPath(path); >- } >- >- blurAndColorShadowBuffer(templateSize); >- } >- FloatSize offset = m_offset; >- if (shadowsIgnoreTransforms()) { >- AffineTransform transform = graphicsContext.getCTM(); >- offset.scale(1 / transform.xScale(), 1 / transform.yScale()); >- } >- >- FloatRect shadowBounds = shadowedRect.rect(); >- shadowBounds.move(offset); >- shadowBounds.inflateX(edgeSize.width()); >- shadowBounds.inflateY(edgeSize.height()); >- >- drawLayerPieces(graphicsContext, shadowBounds, shadowedRect.radii(), edgeSize, templateSize, OuterShadow); >- >- m_layerImage = nullptr; >+#if USE(CG) > ScratchBuffer::singleton().scheduleScratchBufferPurge(); >+#endif > } > >-void ShadowBlur::drawLayerPieces(GraphicsContext& graphicsContext, const FloatRect& shadowBounds, const FloatRoundedRect::Radii& radii, const IntSize& bufferPadding, const IntSize& templateSize, ShadowDirection direction) >+void ShadowBlur::drawLayerPieces(const FloatRect& shadowBounds, const FloatRoundedRect::Radii& radii, const IntSize& bufferPadding, const IntSize& templateSize, const DrawImageCallback& drawImage) > { > const IntSize twiceRadius = IntSize(bufferPadding.width() * 2, bufferPadding.height() * 2); > >@@ -849,71 +819,73 @@ void ShadowBlur::drawLayerPieces(GraphicsContext& graphicsContext, const FloatRe > > int centerWidth = shadowBounds.width() - leftSlice - rightSlice; > int centerHeight = shadowBounds.height() - topSlice - bottomSlice; >- >- if (direction == OuterShadow) { >- FloatRect shadowInterior(shadowBounds.x() + leftSlice, shadowBounds.y() + topSlice, centerWidth, centerHeight); >- if (!shadowInterior.isEmpty()) { >- GraphicsContextStateSaver stateSaver(graphicsContext); >- graphicsContext.setFillColor(m_color); >- graphicsContext.clearShadow(); >- graphicsContext.fillRect(shadowInterior); >- } >- } >- >- GraphicsContextStateSaver stateSaver(graphicsContext); >- graphicsContext.setFillColor(m_color); >- graphicsContext.clearShadow(); >- >- // Note that drawing the ImageBuffer is faster than creating a Image and drawing that, >- // because ImageBuffer::draw() knows that it doesn't have to copy the image bits. > FloatRect centerRect(shadowBounds.x() + leftSlice, shadowBounds.y() + topSlice, centerWidth, centerHeight); >- centerRect = graphicsContext.roundToDevicePixels(centerRect); >- >+ > // Top side. > FloatRect tileRect = FloatRect(leftSlice, 0, templateSideLength, topSlice); > FloatRect destRect = FloatRect(centerRect.x(), centerRect.y() - topSlice, centerRect.width(), topSlice); >- graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect); >+ drawImage(*m_layerImage, destRect, tileRect); > > // Draw the bottom side. > tileRect.setY(templateSize.height() - bottomSlice); > tileRect.setHeight(bottomSlice); > destRect.setY(centerRect.maxY()); > destRect.setHeight(bottomSlice); >- graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect); >+ drawImage(*m_layerImage, destRect, tileRect); > > // Left side. > tileRect = FloatRect(0, topSlice, leftSlice, templateSideLength); > destRect = FloatRect(centerRect.x() - leftSlice, centerRect.y(), leftSlice, centerRect.height()); >- graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect); >+ drawImage(*m_layerImage, destRect, tileRect); > > // Right side. > tileRect.setX(templateSize.width() - rightSlice); > tileRect.setWidth(rightSlice); > destRect.setX(centerRect.maxX()); > destRect.setWidth(rightSlice); >- graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect); >+ drawImage(*m_layerImage, destRect, tileRect); > > // Top left corner. > tileRect = FloatRect(0, 0, leftSlice, topSlice); > destRect = FloatRect(centerRect.x() - leftSlice, centerRect.y() - topSlice, leftSlice, topSlice); >- graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect); >+ drawImage(*m_layerImage, destRect, tileRect); > > // Top right corner. > tileRect = FloatRect(templateSize.width() - rightSlice, 0, rightSlice, topSlice); > destRect = FloatRect(centerRect.maxX(), centerRect.y() - topSlice, rightSlice, topSlice); >- graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect); >+ drawImage(*m_layerImage, destRect, tileRect); > > // Bottom right corner. > tileRect = FloatRect(templateSize.width() - rightSlice, templateSize.height() - bottomSlice, rightSlice, bottomSlice); > destRect = FloatRect(centerRect.maxX(), centerRect.maxY(), rightSlice, bottomSlice); >- graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect); >+ drawImage(*m_layerImage, destRect, tileRect); > > // Bottom left corner. > tileRect = FloatRect(0, templateSize.height() - bottomSlice, leftSlice, bottomSlice); > destRect = FloatRect(centerRect.x() - leftSlice, centerRect.maxY(), leftSlice, bottomSlice); >- graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect); >+ drawImage(*m_layerImage, destRect, tileRect); > } > >+void ShadowBlur::drawLayerPiecesAndFillCenter(const FloatRect& shadowBounds, const FloatRoundedRect::Radii& radii, const IntSize& bufferPadding, const IntSize& templateSize, const DrawImageCallback& drawImage, const FillRectCallback& fillRect) >+{ >+ const IntSize twiceRadius = IntSize(bufferPadding.width() * 2, bufferPadding.height() * 2); >+ >+ int leftSlice; >+ int rightSlice; >+ int topSlice; >+ int bottomSlice; >+ computeSliceSizesFromRadii(twiceRadius, radii, leftSlice, rightSlice, topSlice, bottomSlice); >+ >+ int centerWidth = shadowBounds.width() - leftSlice - rightSlice; >+ int centerHeight = shadowBounds.height() - topSlice - bottomSlice; >+ FloatRect centerRect(shadowBounds.x() + leftSlice, shadowBounds.y() + topSlice, centerWidth, centerHeight); >+ >+ // Fill center >+ if (!centerRect.isEmpty()) >+ fillRect(centerRect, m_color); >+ >+ drawLayerPieces(shadowBounds, radii, bufferPadding, templateSize, drawImage); >+} > > void ShadowBlur::blurShadowBuffer(const IntSize& templateSize) > { >@@ -962,7 +934,7 @@ void ShadowBlur::drawShadowLayer(const AffineTransform& transform, const IntRect > } > > blurAndColorShadowBuffer(expandedIntSize(m_layerSize)); >- drawBuffer(*layerImage, m_layerOrigin, m_layerSize, m_sourceRect); >+ drawBuffer(*layerImage, m_layerOrigin, m_layerSize); > } > > } // namespace WebCore >diff --git a/Source/WebCore/platform/graphics/ShadowBlur.h b/Source/WebCore/platform/graphics/ShadowBlur.h >index 9348f1f35ea..d6af402a374 100644 >--- a/Source/WebCore/platform/graphics/ShadowBlur.h >+++ b/Source/WebCore/platform/graphics/ShadowBlur.h >@@ -23,11 +23,10 @@ > * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY > * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > */ > >-#ifndef ShadowBlur_h >-#define ShadowBlur_h >+#pragma once > > #include "Color.h" > #include "FloatRect.h" >@@ -63,12 +62,17 @@ public: > void drawRectShadow(GraphicsContext&, const FloatRoundedRect&); > void drawInsetShadow(GraphicsContext&, const FloatRect&, const FloatRoundedRect& holeRect); > >- using DrawBufferCallback = WTF::Function<void(ImageBuffer&, const FloatPoint&, const FloatSize&, const FloatRect&)>; >- void drawRectShadow(const AffineTransform&, const IntRect&, const FloatRoundedRect&, const DrawBufferCallback&); >- void drawInsetShadow(const AffineTransform&, const IntRect&, const FloatRect&, const FloatRoundedRect&, const DrawBufferCallback&); >- >+ using DrawBufferCallback = WTF::Function<void(ImageBuffer&, const FloatPoint&, const FloatSize&)>; >+ using DrawImageCallback = WTF::Function<void(ImageBuffer&, const FloatRect&, const FloatRect&)>; >+ using FillRectCallback = WTF::Function<void(const FloatRect&, const Color&)>; >+ using FillRectWithHoleCallback = WTF::Function<void(const FloatRect&, const FloatRect&, const Color&)>; > using DrawShadowCallback = WTF::Function<void(GraphicsContext&)>; >- void drawShadowLayer(const AffineTransform&, const IntRect&, const FloatRect&, const DrawShadowCallback&, const DrawBufferCallback&); >+ >+ // DrawBufferCallback is for drawing shadow without tiling. >+ // DrawImageCallback and FillRectCallback is for drawing shadow with tiling. >+ void drawRectShadow(const AffineTransform&, const IntRect& clipBounds, const FloatRoundedRect& shadowedRect, const DrawBufferCallback&, const DrawImageCallback&, const FillRectCallback&); >+ void drawInsetShadow(const AffineTransform&, const IntRect& clipBounds, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const DrawBufferCallback&, const DrawImageCallback&, const FillRectWithHoleCallback&); >+ void drawShadowLayer(const AffineTransform&, const IntRect& clipBounds, const FloatRect& layerArea, const DrawShadowCallback&, const DrawBufferCallback&); > > void blurLayerImage(unsigned char*, const IntSize&, int stride); > >@@ -82,29 +86,29 @@ private: > void drawShadowBuffer(GraphicsContext&); > > void adjustBlurRadius(const AffineTransform&); >- >+ > enum ShadowDirection { > OuterShadow, > InnerShadow > }; >- >+ > IntSize calculateLayerBoundingRect(const AffineTransform&, const FloatRect& layerArea, const IntRect& clipRect); > IntSize templateSize(const IntSize& blurredEdgeSize, const FloatRoundedRect::Radii&) const; > >- void drawRectShadowWithoutTiling(GraphicsContext&, const FloatRoundedRect&, const IntSize& layerSize); >- void drawRectShadowWithTiling(GraphicsContext&, const FloatRoundedRect&, const IntSize& shadowTemplateSize, const IntSize& blurredEdgeSize); >- >- void drawInsetShadowWithoutTiling(GraphicsContext&, const FloatRect&, const FloatRoundedRect& holeRect, const IntSize& layerSize); >- void drawInsetShadowWithTiling(GraphicsContext&, const FloatRect&, const FloatRoundedRect& holeRect, const IntSize& shadowTemplateSize, const IntSize& blurredEdgeSize); >- >- void drawLayerPieces(GraphicsContext&, const FloatRect& shadowBounds, const FloatRoundedRect::Radii&, const IntSize& roundedRadius, const IntSize& templateSize, ShadowDirection); >- > void blurShadowBuffer(const IntSize& templateSize); > void blurAndColorShadowBuffer(const IntSize& templateSize); >- >+ >+ void drawInsetShadowWithoutTiling(const AffineTransform&, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const IntSize& layerSize, const DrawBufferCallback&); >+ void drawInsetShadowWithTiling(const AffineTransform&, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const IntSize& shadowTemplateSize, const IntSize& blurredEdgeSize, const DrawImageCallback&, const FillRectWithHoleCallback&); >+ >+ void drawRectShadowWithoutTiling(const AffineTransform&, const FloatRoundedRect& shadowedRect, const IntSize& layerSize, const DrawBufferCallback&); >+ void drawRectShadowWithTiling(const AffineTransform&, const FloatRoundedRect& shadowedRect, const IntSize& shadowTemplateSize, const IntSize& blurredEdgeSize, const DrawImageCallback&, const FillRectCallback&); >+ >+ void drawLayerPiecesAndFillCenter(const FloatRect& shadowBounds, const FloatRoundedRect::Radii&, const IntSize& roundedRadius, const IntSize& templateSize, const DrawImageCallback&, const FillRectCallback&); >+ void drawLayerPieces(const FloatRect& shadowBounds, const FloatRoundedRect::Radii&, const IntSize& roundedRadius, const IntSize& templateSize, const DrawImageCallback&); >+ > IntSize blurredEdgeSize() const; >- >- >+ > ShadowType m_type { NoShadow }; > > Color m_color; >@@ -113,7 +117,7 @@ private: > > ImageBuffer* m_layerImage { nullptr }; // Buffer to where the temporary shadow will be drawn to. > >- FloatRect m_sourceRect; // Sub-rect of m_layerImage that contains the shadow pixels. >+ FloatSize m_shadowedResultSize; // Size of the result of shadowing which is same as shadowedRect + blurred edges. > FloatPoint m_layerOrigin; // Top-left corner of the (possibly clipped) bounding rect to draw the shadow to. > FloatSize m_layerSize; // Size of m_layerImage pixels that need blurring. > FloatSize m_layerContextTranslation; // Translation to apply to m_layerContext for the shadow to be correctly clipped. >@@ -122,5 +126,3 @@ private: > }; > > } // namespace WebCore >- >-#endif // ShadowBlur_h >diff --git a/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp b/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp >index 3d9c48df358..fba54565a5a 100644 >--- a/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp >+++ b/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp >@@ -184,7 +184,20 @@ static void drawShadowLayerBuffer(PlatformContextCairo& platformContext, ImageBu > } > } > >-static void fillShadowBuffer(PlatformContextCairo& platformContext, ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize, const FloatRect& sourceRect, const ShadowState& shadowState) >+// FIXME: This is mostly same as drawShadowLayerBuffer, so we should merge two. >+static void drawShadowImage(PlatformContextCairo& platformContext, ImageBuffer& layerImage, const FloatRect& destRect, const FloatRect& srcRect, const ShadowState& shadowState) >+{ >+ RefPtr<Image> image = layerImage.copyImage(DontCopyBackingStore); >+ if (!image) >+ return; >+ >+ if (auto surface = image->nativeImageForCurrentFrame()) { >+ drawNativeImage(platformContext, surface.get(), destRect, srcRect, shadowState.globalCompositeOperator, BlendMode::Normal, ImageOrientation(), >+ InterpolationDefault, shadowState.globalAlpha, ShadowState()); >+ } >+} >+ >+static void fillShadowBuffer(PlatformContextCairo& platformContext, ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize, const ShadowState& shadowState) > { > save(platformContext); > >@@ -197,7 +210,7 @@ static void fillShadowBuffer(PlatformContextCairo& platformContext, ImageBuffer& > FillSource fillSource; > fillSource.globalAlpha = shadowState.globalAlpha; > fillSource.color = shadowState.color; >- fillRect(platformContext, FloatRect(layerOrigin, sourceRect.size()), fillSource, ShadowState()); >+ fillRect(platformContext, FloatRect(layerOrigin, expandedIntSize(layerSize)), fillSource, ShadowState()); > > restore(platformContext); > } >@@ -252,7 +265,7 @@ static inline void drawPathShadow(PlatformContextCairo& platformContext, const F > cairo_stroke(cairoShadowContext); > } > }, >- [&platformContext, &shadowState, &cairoContext, &path](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize, const FloatRect&) >+ [&platformContext, &shadowState, &cairoContext, &path](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) > { > // The original path may still be hanging around on the context and endShadowLayer > // will take care of properly creating a path to draw the result shadow. We remove the path >@@ -266,6 +279,7 @@ static inline void drawPathShadow(PlatformContextCairo& platformContext, const F > }); > } > >+ > static inline void fillCurrentCairoPath(PlatformContextCairo& platformContext, const FillSource& fillSource) > { > cairo_t* cr = platformContext.cr(); >@@ -350,7 +364,7 @@ static void drawGlyphsShadow(PlatformContextCairo& platformContext, const Shadow > { > drawGlyphsToContext(shadowContext.platformContext()->cr(), scaledFont, syntheticBoldOffset, glyphs); > }, >- [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize, const FloatRect&) >+ [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) > { > drawShadowLayerBuffer(platformContext, layerImage, layerOrigin, layerSize, shadowState); > }); >@@ -690,9 +704,17 @@ void fillRect(PlatformContextCairo& platformContext, const FloatRect& rect, cons > if (shadowState.isVisible()) { > ShadowBlur shadow({ shadowState.blur, shadowState.blur }, shadowState.offset, shadowState.color, shadowState.ignoreTransforms); > shadow.drawRectShadow(State::getCTM(platformContext), State::getClipBounds(platformContext), FloatRoundedRect(rect), >- [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize, const FloatRect& sourceRect) >+ [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) > { >- fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, sourceRect, shadowState); >+ fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, shadowState); >+ }, >+ [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatRect& destRect, const FloatRect& srcRect) >+ { >+ drawShadowImage(platformContext, layerImage, destRect, srcRect, shadowState); >+ }, >+ [&platformContext](const FloatRect& rect, const Color& color) >+ { >+ fillRectWithColor(platformContext.cr(), rect, color); > }); > } > >@@ -713,9 +735,17 @@ void fillRoundedRect(PlatformContextCairo& platformContext, const FloatRoundedRe > if (shadowState.isVisible()) { > ShadowBlur shadow({ shadowState.blur, shadowState.blur }, shadowState.offset, shadowState.color, shadowState.ignoreTransforms); > shadow.drawRectShadow(State::getCTM(platformContext), State::getClipBounds(platformContext), rect, >- [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize, const FloatRect& sourceRect) >+ [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) > { >- fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, sourceRect, shadowState); >+ fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, shadowState); >+ }, >+ [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatRect& destRect, const FloatRect& srcRect) >+ { >+ drawShadowImage(platformContext, layerImage, destRect, srcRect, shadowState); >+ }, >+ [&platformContext](const FloatRect& rect, const Color& color) >+ { >+ fillRectWithColor(platformContext.cr(), rect, color); > }); > } > >@@ -738,9 +768,25 @@ void fillRectWithRoundedHole(PlatformContextCairo& platformContext, const FloatR > if (shadowState.isVisible()) { > ShadowBlur shadow({ shadowState.blur, shadowState.blur }, shadowState.offset, shadowState.color, shadowState.ignoreTransforms); > shadow.drawInsetShadow(State::getCTM(platformContext), State::getClipBounds(platformContext), rect, roundedHoleRect, >- [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize, const FloatRect& sourceRect) >+ [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) >+ { >+ fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, shadowState); >+ }, >+ [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatRect& destRect, const FloatRect& srcRect) >+ { >+ drawShadowImage(platformContext, layerImage, destRect, srcRect, shadowState); >+ }, >+ [&platformContext](const FloatRect& rect, const FloatRect& holeRect, const Color& color) > { >- fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, sourceRect, shadowState); >+ // FIXME: We should use fillRectWithRoundedHole. >+ cairo_t* cr = platformContext.cr(); >+ cairo_save(cr); >+ setSourceRGBAFromColor(cr, color); >+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD); >+ cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height()); >+ cairo_rectangle(cr, holeRect.x(), holeRect.y(), holeRect.width(), holeRect.height()); >+ cairo_fill(cr); >+ cairo_restore(cr); > }); > } > >@@ -932,7 +978,7 @@ void drawSurface(PlatformContextCairo& platformContext, cairo_surface_t* surface > { > drawPatternToCairoContext(shadowContext.platformContext()->cr(), pattern.get(), destRect, 1); > }, >- [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize, const FloatRect&) >+ [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) > { > drawShadowLayerBuffer(platformContext, layerImage, layerOrigin, layerSize, shadowState); > });
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 197308
:
368306
| 368307 |
368308
|
368309
|
368312