Changeset 244913 in webkit
- Timestamp:
- May 3, 2019 11:31:06 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r244912 r244913 1 2019-05-03 Tomoki Imai <Tomoki.Imai@sony.com> 2 3 [Cairo] Improve ShadowBlur performance using tiling optimization 4 https://bugs.webkit.org/show_bug.cgi?id=197308 5 Reviewed by Žan Doberšek. 6 7 Enable tiling tiling-based optimization for drawRectShadow() and drawInsetShadow(). 8 Since r228776, cairo ports doesn't have tiling-based optimization. 9 10 For AppleWin, this patch refactors code and it shares almost same code as cairo port. 11 Only the difference is that AppleWin uses ScratchBuffer, but cairo ports doesn't. 12 This should avoid a performance regression for AppleWin. 13 14 No new tests, covered by existing tests. 15 16 * platform/graphics/ShadowBlur.cpp: 17 (WebCore::calculateLobes): 18 Fix stylecheck errors 19 20 (WebCore::ShadowBlur::blurLayerImage): 21 Fix stylecheck errors 22 23 (WebCore::ShadowBlur::calculateLayerBoundingRect): 24 We don't use position of m_sourceRect, so change the type to FloatSize. 25 26 (WebCore::ShadowBlur::drawShadowBuffer): 27 Use m_layerSize instead of m_shadowedResultSize to fillRect, as m_layerSize is always smaller than m_shadowedResultSize. 28 It's because in m_layerSize is equal to m_shadowedResultSize if it's not clipped. 29 Clipping doesn't increase size of m_layerSize, so m_layerSize is always smaller than or equal to m_shadowedResultSize. 30 31 (WebCore::ShadowBlur::templateSize const): 32 Fix stylecheck errors 33 34 (WebCore::ShadowBlur::drawRectShadow): 35 (WebCore::ShadowBlur::drawInsetShadow): 36 (WebCore::ShadowBlur::drawRectShadowWithoutTiling): 37 (WebCore::ShadowBlur::drawInsetShadowWithoutTiling): 38 (WebCore::ShadowBlur::drawRectShadowWithTiling): 39 (WebCore::ShadowBlur::drawInsetShadowWithTiling): 40 Incorporate tile-based drawing. 41 To accomplish it, this patch abstracts GraphicsContext::drawImageBuffer to ShadowBlur::DrawImageCallback, 42 GraphicsContext::fillRect to ShadowBlur::FillRectCallback, drawing rect with hole to ShadowBlur::FillRectWithHoleCallback. 43 44 Variants which takes GraphicsContext as parameter now just calls another drawRectShadow. 45 46 (WebCore::ShadowBlur::drawLayerPieces): 47 Instead of graphicsContext.drawImageBuffer, call corresponding callback. 48 49 (WebCore::ShadowBlur::drawLayerPiecesAndFillCenter): 50 This function calls drawLayerPieces and fill center for outer shadow. 51 Drawing outer shadow requires another callback for graphicsContext.fillRect. 52 53 (WebCore::ShadowBlur::drawShadowLayer): 54 Use m_layerSize instead of m_shadowedResultSize to fillRect, 55 as m_layerSize is always smaller than m_shadowedResultSize. 56 57 * platform/graphics/ShadowBlur.h: 58 Rename m_sourceRect to m_shadowedResultSize, and change it to FloatSize from FloatRect. 59 Remove GraphicsContext usage as much as possible and replace them by corresponding callbacks. 60 61 * platform/graphics/cairo/CairoOperations.cpp: 62 (WebCore::Cairo::drawShadowImage): 63 This function corresponds to ShadowBlur::DrawImageCallback. 64 65 (WebCore::Cairo::fillShadowBuffer): 66 Erase sourceRect, as it's always bigger than layerSize. 67 68 (WebCore::Cairo::drawPathShadow): 69 (WebCore::Cairo::drawGlyphsShadow): 70 Erase unused parameter. 71 72 (WebCore::Cairo::fillRect): 73 (WebCore::Cairo::fillRoundedRect): 74 (WebCore::Cairo::fillRectWithRoundedHole): 75 For tile-based optimization, add extra arguments to drawRectShadow. 76 77 (WebCore::Cairo::drawSurface): 78 Erase unused parameter. 79 1 80 2019-05-03 Antti Koivisto <antti@apple.com> 2 81 -
trunk/Source/WebCore/platform/graphics/ShadowBlur.cpp
r239461 r244913 25 25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 28 */ 29 29 … … 43 43 44 44 enum { 45 leftLobe = 0,46 rightLobe = 145 LeftLobe = 0, 46 RightLobe = 1 47 47 }; 48 48 49 #if USE(CG) 49 50 static inline int roundUpToMultipleOf32(int d) 50 51 { … … 66 67 { 67 68 } 68 69 69 70 ImageBuffer* getScratchBuffer(const IntSize& size) 70 71 { … … 128 129 m_purgeTimer.startOneShot(scratchBufferPurgeInterval); 129 130 } 130 131 131 132 static ScratchBuffer& singleton(); 132 133 … … 141 142 std::unique_ptr<ImageBuffer> m_imageBuffer; 142 143 Timer m_purgeTimer; 143 144 144 145 FloatRect m_lastInsetBounds; 145 146 FloatRect m_lastShadowRect; … … 149 150 bool m_lastWasInset; 150 151 FloatSize m_lastLayerSize; 151 152 152 153 #if !ASSERT_DISABLED 153 154 bool m_bufferInUse; … … 161 162 } 162 163 164 static float radiusToLegacyRadius(float radius) 165 { 166 return radius > 8 ? 8 + 4 * sqrt((radius - 8) / 2) : radius; 167 } 168 #endif 169 163 170 static const int templateSideLength = 1; 164 165 #if USE(CG)166 static float radiusToLegacyRadius(float radius)167 {168 return radius > 8 ? 8 + 4 * sqrt((radius - 8) / 2) : radius;169 }170 #endif171 171 172 172 ShadowBlur::ShadowBlur() = default; … … 250 250 // if d is odd, use three box-blurs of size 'd', centered on the output pixel. 251 251 int lobeSize = (diameter - 1) / 2; 252 lobes[0][ leftLobe] = lobeSize;253 lobes[0][ rightLobe] = lobeSize;254 lobes[1][ leftLobe] = lobeSize;255 lobes[1][ rightLobe] = lobeSize;256 lobes[2][ leftLobe] = lobeSize;257 lobes[2][ rightLobe] = lobeSize;252 lobes[0][LeftLobe] = lobeSize; 253 lobes[0][RightLobe] = lobeSize; 254 lobes[1][LeftLobe] = lobeSize; 255 lobes[1][RightLobe] = lobeSize; 256 lobes[2][LeftLobe] = lobeSize; 257 lobes[2][RightLobe] = lobeSize; 258 258 } else { 259 259 // if d is even, two box-blurs of size 'd' (the first one centered on the pixel boundary … … 261 261 // boundary between the output pixel and the one to the right) and one box blur of size 'd+1' centered on the output pixel 262 262 int lobeSize = diameter / 2; 263 lobes[0][ leftLobe] = lobeSize;264 lobes[0][ rightLobe] = lobeSize - 1;265 lobes[1][ leftLobe] = lobeSize - 1;266 lobes[1][ rightLobe] = lobeSize;267 lobes[2][ leftLobe] = lobeSize;268 lobes[2][ rightLobe] = lobeSize;263 lobes[0][LeftLobe] = lobeSize; 264 lobes[0][RightLobe] = lobeSize - 1; 265 lobes[1][LeftLobe] = lobeSize - 1; 266 lobes[1][RightLobe] = lobeSize; 267 lobes[2][LeftLobe] = lobeSize; 268 lobes[2][RightLobe] = lobeSize; 269 269 } 270 270 } … … 294 294 for (int pass = 0; pass < 2; ++pass) { 295 295 unsigned char* pixels = imageData; 296 296 297 297 if (!pass && !m_blurRadius.width()) 298 298 final = 0; // Do no work if horizonal blur is zero. … … 305 305 // covered by the box kernel size for each x. 306 306 for (int step = 0; step < 3; ++step) { 307 int side1 = lobes[step][ leftLobe];308 int side2 = lobes[step][ rightLobe];307 int side1 = lobes[step][LeftLobe]; 308 int side2 = lobes[step][RightLobe]; 309 309 int pixelCount = side1 + 1 + side2; 310 310 int invCount = ((1 << blurSumShift) + pixelCount - 1) / pixelCount; … … 332 332 sum += ((ofs < dim) ? *next : alpha2) - alpha1; 333 333 } 334 334 335 335 prev = pixels + channels[step]; 336 336 for (; ofs < dim; ptr += stride, prev += stride, next += stride, ++i, ++ofs) { … … 338 338 sum += (*next) - (*prev); 339 339 } 340 340 341 341 for (; i < dim; ptr += stride, prev += stride, ++i) { 342 342 *ptr = (sum * invCount) >> blurSumShift; … … 423 423 inflatedClip.inflateY(1); 424 424 } 425 425 426 426 layerRect.intersect(inflatedClip); 427 427 } … … 429 429 IntSize frameSize = inflation; 430 430 frameSize.scale(2); 431 m_s ourceRect = FloatRect(0, 0,shadowedRect.width() + frameSize.width(), shadowedRect.height() + frameSize.height());431 m_shadowedResultSize = FloatSize(shadowedRect.width() + frameSize.width(), shadowedRect.height() + frameSize.height()); 432 432 m_layerOrigin = FloatPoint(layerRect.x(), layerRect.y()); 433 433 m_layerSize = layerRect.size(); … … 462 462 463 463 graphicsContext.clearShadow(); 464 graphicsContext.fillRect(FloatRect(m_layerOrigin, m_ sourceRect.size()));464 graphicsContext.fillRect(FloatRect(m_layerOrigin, m_layerSize)); 465 465 } 466 466 … … 482 482 int topSlice; 483 483 int bottomSlice; 484 484 485 485 IntSize blurExpansion = radiusPadding; 486 486 blurExpansion.scale(2); 487 487 488 488 computeSliceSizesFromRadii(blurExpansion, radii, leftSlice, rightSlice, topSlice, bottomSlice); 489 490 return IntSize(templateSideLength + leftSlice + rightSlice, 491 templateSideLength + topSlice + bottomSlice); 489 490 return IntSize(templateSideLength + leftSlice + rightSlice, templateSideLength + topSlice + bottomSlice); 492 491 } 493 492 494 493 void ShadowBlur::drawRectShadow(GraphicsContext& graphicsContext, const FloatRoundedRect& shadowedRect) 495 494 { 496 IntSize layerSize = calculateLayerBoundingRect(graphicsContext.getCTM(), shadowedRect.rect(), graphicsContext.clipBounds()); 495 drawRectShadow(graphicsContext.getCTM(), graphicsContext.clipBounds(), shadowedRect, 496 [this, &graphicsContext](ImageBuffer&, const FloatPoint&, const FloatSize&) { 497 // FIXME: Use parameters instead of implicit parameters defined as class variables. 498 drawShadowBuffer(graphicsContext); 499 }, 500 [&graphicsContext](ImageBuffer& image, const FloatRect& destRect, const FloatRect& srcRect) { 501 GraphicsContextStateSaver stateSaver(graphicsContext); 502 graphicsContext.clearShadow(); 503 graphicsContext.drawImageBuffer(image, destRect, srcRect); 504 }, 505 [&graphicsContext](const FloatRect& rect, const Color& color) { 506 GraphicsContextStateSaver stateSaver(graphicsContext); 507 graphicsContext.setFillColor(color); 508 graphicsContext.clearShadow(); 509 graphicsContext.fillRect(rect); 510 }); 511 } 512 513 void ShadowBlur::drawInsetShadow(GraphicsContext& graphicsContext, const FloatRect& fullRect, const FloatRoundedRect& holeRect) 514 { 515 drawInsetShadow(graphicsContext.getCTM(), graphicsContext.clipBounds(), fullRect, holeRect, 516 [this, &graphicsContext](ImageBuffer&, const FloatPoint&, const FloatSize&) { 517 // FIXME: Use parameters instead of implicit parameters defined as class variables. 518 drawShadowBuffer(graphicsContext); 519 }, 520 [&graphicsContext](ImageBuffer& image, const FloatRect& destRect, const FloatRect& srcRect) { 521 // Note that drawing the ImageBuffer is faster than creating a Image and drawing that, 522 // because ImageBuffer::draw() knows that it doesn't have to copy the image bits. 523 GraphicsContextStateSaver stateSaver(graphicsContext); 524 graphicsContext.clearShadow(); 525 graphicsContext.drawImageBuffer(image, destRect, srcRect); 526 }, 527 [&graphicsContext](const FloatRect& rect, const FloatRect& holeRect, const Color& color) { 528 Path exteriorPath; 529 exteriorPath.addRect(rect); 530 exteriorPath.addRect(holeRect); 531 532 GraphicsContextStateSaver fillStateSaver(graphicsContext); 533 graphicsContext.setFillRule(WindRule::EvenOdd); 534 graphicsContext.setFillColor(color); 535 graphicsContext.clearShadow(); 536 graphicsContext.fillPath(exteriorPath); 537 }); 538 } 539 540 void ShadowBlur::drawRectShadow(const AffineTransform& transform, const IntRect& clipBounds, const FloatRoundedRect& shadowedRect, const DrawBufferCallback& drawBuffer, const DrawImageCallback& drawImage, const FillRectCallback& fillRect) 541 { 542 IntSize layerSize = calculateLayerBoundingRect(transform, shadowedRect.rect(), clipBounds); 497 543 if (layerSize.isEmpty()) 498 544 return; 499 545 500 adjustBlurRadius(graphicsContext.getCTM()); 546 adjustBlurRadius(transform); 547 548 bool canUseTilingTechnique = true; 501 549 502 550 // drawRectShadowWithTiling does not work with rotations. 503 551 // https://bugs.webkit.org/show_bug.cgi?id=45042 504 if (!graphicsContext.getCTM().preservesAxisAlignment() || m_type != BlurShadow) { 505 drawRectShadowWithoutTiling(graphicsContext, shadowedRect, layerSize); 506 return; 507 } 552 if (!transform.preservesAxisAlignment() || m_type != BlurShadow) 553 canUseTilingTechnique = false; 508 554 509 555 IntSize edgeSize = blurredEdgeSize(); … … 512 558 513 559 if (templateSize.width() > rect.width() || templateSize.height() > rect.height() 514 || (templateSize.width() * templateSize.height() > m_sourceRect.width() * m_sourceRect.height())) { 515 drawRectShadowWithoutTiling(graphicsContext, shadowedRect, layerSize); 516 return; 517 } 518 519 drawRectShadowWithTiling(graphicsContext, shadowedRect, templateSize, edgeSize); 520 } 521 522 void ShadowBlur::drawInsetShadow(GraphicsContext& graphicsContext, const FloatRect& rect, const FloatRoundedRect& holeRect) 523 { 524 IntSize layerSize = calculateLayerBoundingRect(graphicsContext.getCTM(), rect, graphicsContext.clipBounds()); 560 || (templateSize.width() * templateSize.height() > m_shadowedResultSize.width() * m_shadowedResultSize.height())) 561 canUseTilingTechnique = false; 562 563 if (canUseTilingTechnique) 564 drawRectShadowWithTiling(transform, shadowedRect, templateSize, edgeSize, drawImage, fillRect); 565 else 566 drawRectShadowWithoutTiling(transform, shadowedRect, layerSize, drawBuffer); 567 } 568 569 void ShadowBlur::drawInsetShadow(const AffineTransform& transform, const IntRect& clipBounds, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const DrawBufferCallback& drawBuffer, const DrawImageCallback& drawImage, const FillRectWithHoleCallback& fillRectWithHole) 570 { 571 IntSize layerSize = calculateLayerBoundingRect(transform, fullRect, clipBounds); 525 572 if (layerSize.isEmpty()) 526 573 return; 527 574 528 adjustBlurRadius(graphicsContext.getCTM()); 529 530 // drawInsetShadowWithTiling does not work with rotations. 575 adjustBlurRadius(transform); 576 577 bool canUseTilingTechnique = true; 578 579 // drawRectShadowWithTiling does not work with rotations. 531 580 // https://bugs.webkit.org/show_bug.cgi?id=45042 532 if (!graphicsContext.getCTM().preservesAxisAlignment() || m_type != BlurShadow) { 533 drawInsetShadowWithoutTiling(graphicsContext, rect, holeRect, layerSize); 534 return; 535 } 581 if (!transform.preservesAxisAlignment() || m_type != BlurShadow) 582 canUseTilingTechnique = false; 536 583 537 584 IntSize edgeSize = blurredEdgeSize(); … … 540 587 541 588 if (templateSize.width() > hRect.width() || templateSize.height() > hRect.height() 542 || (templateSize.width() * templateSize.height() > hRect.width() * hRect.height())) { 543 drawInsetShadowWithoutTiling(graphicsContext, rect, holeRect, layerSize); 544 return; 545 } 546 547 drawInsetShadowWithTiling(graphicsContext, rect, holeRect, templateSize, edgeSize); 548 } 549 550 void ShadowBlur::drawRectShadow(const AffineTransform& transform, const IntRect& clipBounds, const FloatRoundedRect& shadowedRect, const DrawBufferCallback& drawBuffer) 551 { 552 // FIXME: Try incorporating tile-based rect shadow drawing for the same use case. 553 554 IntSize layerSize = calculateLayerBoundingRect(transform, shadowedRect.rect(), clipBounds); 555 if (layerSize.isEmpty()) 556 return; 557 558 adjustBlurRadius(transform); 559 589 || (templateSize.width() * templateSize.height() > hRect.width() * hRect.height())) 590 canUseTilingTechnique = false; 591 592 if (canUseTilingTechnique) 593 drawInsetShadowWithTiling(transform, fullRect, holeRect, templateSize, edgeSize, drawImage, fillRectWithHole); 594 else 595 drawInsetShadowWithoutTiling(transform, fullRect, holeRect, layerSize, drawBuffer); 596 } 597 598 void ShadowBlur::drawRectShadowWithoutTiling(const AffineTransform&, const FloatRoundedRect& shadowedRect, const IntSize& layerSize, const DrawBufferCallback& drawBuffer) 599 { 560 600 auto layerImage = ImageBuffer::create(layerSize, Unaccelerated, 1); 561 601 if (!layerImage) 562 602 return; 563 603 m_layerImage = layerImage.get(); 604 605 GraphicsContext& shadowContext = layerImage->context(); 606 GraphicsContextStateSaver stateSaver(shadowContext); 607 shadowContext.setFillColor(Color::black); 564 608 565 609 { … … 578 622 blurShadowBuffer(layerSize); 579 623 } 580 581 drawBuffer(*layerImage, m_layerOrigin, m_layerSize, m_sourceRect); 582 } 583 584 void ShadowBlur::drawInsetShadow(const AffineTransform& transform, const IntRect& clipBounds, const FloatRect& rect, const FloatRoundedRect& holeRect, const DrawBufferCallback& drawBuffer) 585 { 586 // FIXME: Try incorporating tile-based inset shadow drawing for the same use case. 587 588 IntSize layerSize = calculateLayerBoundingRect(transform, rect, clipBounds); 589 if (layerSize.isEmpty()) 590 return; 591 592 adjustBlurRadius(transform); 593 624 drawBuffer(*layerImage, m_layerOrigin, m_layerSize); 625 } 626 627 void ShadowBlur::drawInsetShadowWithoutTiling(const AffineTransform&, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const IntSize& layerSize, const DrawBufferCallback& drawBuffer) 628 { 594 629 auto layerImage = ImageBuffer::create(layerSize, Unaccelerated, 1); 595 630 if (!layerImage) … … 603 638 604 639 Path path; 605 path.addRect( rect);640 path.addRect(fullRect); 606 641 if (holeRect.radii().isZero()) 607 642 path.addRect(holeRect.rect()); … … 616 651 } 617 652 618 drawBuffer(*layerImage, m_layerOrigin, m_layerSize, m_sourceRect); 619 } 620 621 void ShadowBlur::drawRectShadowWithoutTiling(GraphicsContext& graphicsContext, const FloatRoundedRect& shadowedRect, const IntSize& layerSize) 622 { 623 m_layerImage = ScratchBuffer::singleton().getScratchBuffer(layerSize); 624 if (!m_layerImage) 625 return; 626 627 FloatRect bufferRelativeShadowedRect = shadowedRect.rect(); 628 bufferRelativeShadowedRect.move(m_layerContextTranslation); 629 630 // Only redraw in the scratch buffer if its cached contents don't match our needs 631 bool redrawNeeded = ScratchBuffer::singleton().setCachedShadowValues(m_blurRadius, Color::black, bufferRelativeShadowedRect, shadowedRect.radii(), m_layerSize); 632 if (redrawNeeded) { 633 GraphicsContext& shadowContext = m_layerImage->context(); 634 GraphicsContextStateSaver stateSaver(shadowContext); 635 636 // Add a pixel to avoid later edge aliasing when rotated. 637 shadowContext.clearRect(FloatRect(0, 0, m_layerSize.width() + 1, m_layerSize.height() + 1)); 638 shadowContext.translate(m_layerContextTranslation); 639 shadowContext.setFillColor(Color::black); 640 if (shadowedRect.radii().isZero()) 641 shadowContext.fillRect(shadowedRect.rect()); 642 else { 643 Path path; 644 path.addRoundedRect(shadowedRect); 645 shadowContext.fillPath(path); 646 } 647 648 blurShadowBuffer(layerSize); 649 } 650 651 drawShadowBuffer(graphicsContext); 652 m_layerImage = nullptr; 653 ScratchBuffer::singleton().scheduleScratchBufferPurge(); 654 } 655 656 void ShadowBlur::drawInsetShadowWithoutTiling(GraphicsContext& graphicsContext, const FloatRect& rect, const FloatRoundedRect& holeRect, const IntSize& layerSize) 657 { 658 m_layerImage = ScratchBuffer::singleton().getScratchBuffer(layerSize); 659 if (!m_layerImage) 660 return; 661 662 FloatRect bufferRelativeRect = rect; 663 bufferRelativeRect.move(m_layerContextTranslation); 664 665 FloatRect bufferRelativeHoleRect = holeRect.rect(); 666 bufferRelativeHoleRect.move(m_layerContextTranslation); 667 668 // Only redraw in the scratch buffer if its cached contents don't match our needs 669 bool redrawNeeded = ScratchBuffer::singleton().setCachedInsetShadowValues(m_blurRadius, Color::black, bufferRelativeRect, bufferRelativeHoleRect, holeRect.radii()); 670 if (redrawNeeded) { 671 GraphicsContext& shadowContext = m_layerImage->context(); 672 GraphicsContextStateSaver stateSaver(shadowContext); 673 674 // Add a pixel to avoid later edge aliasing when rotated. 675 shadowContext.clearRect(FloatRect(0, 0, m_layerSize.width() + 1, m_layerSize.height() + 1)); 676 shadowContext.translate(m_layerContextTranslation); 677 678 Path path; 679 path.addRect(rect); 680 if (holeRect.radii().isZero()) 681 path.addRect(holeRect.rect()); 682 else 683 path.addRoundedRect(holeRect); 684 685 shadowContext.setFillRule(WindRule::EvenOdd); 686 shadowContext.setFillColor(Color::black); 687 shadowContext.fillPath(path); 688 689 blurShadowBuffer(layerSize); 690 } 691 692 drawShadowBuffer(graphicsContext); 693 m_layerImage = nullptr; 694 ScratchBuffer::singleton().scheduleScratchBufferPurge(); 653 drawBuffer(*layerImage, m_layerOrigin, m_layerSize); 695 654 } 696 655 … … 727 686 */ 728 687 729 void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext& graphicsContext, const FloatRect& rect, const FloatRoundedRect& holeRect, const IntSize& templateSize, const IntSize& edgeSize) 730 { 688 void ShadowBlur::drawRectShadowWithTiling(const AffineTransform& transform, const FloatRoundedRect& shadowedRect, const IntSize& templateSize, const IntSize& edgeSize, const DrawImageCallback& drawImage, const FillRectCallback& fillRect) 689 { 690 #if USE(CG) 731 691 m_layerImage = ScratchBuffer::singleton().getScratchBuffer(templateSize); 692 #else 693 auto layerImage = ImageBuffer::create(templateSize, Unaccelerated, 1); 694 m_layerImage = layerImage.get(); 695 #endif 696 697 if (!m_layerImage) 698 return; 699 700 FloatRect templateShadow = FloatRect(edgeSize.width(), edgeSize.height(), templateSize.width() - 2 * edgeSize.width(), templateSize.height() - 2 * edgeSize.height()); 701 702 bool redrawNeeded = true; 703 #if USE(CG) 704 // Only redraw in the scratch buffer if its cached contents don't match our needs 705 redrawNeeded = ScratchBuffer::singleton().setCachedShadowValues(m_blurRadius, m_color, templateShadow, shadowedRect.radii(), m_layerSize); 706 #endif 707 708 if (redrawNeeded) { 709 // Draw shadow into the ImageBuffer. 710 GraphicsContext& shadowContext = m_layerImage->context(); 711 GraphicsContextStateSaver shadowStateSaver(shadowContext); 712 713 shadowContext.clearRect(FloatRect(0, 0, templateSize.width(), templateSize.height())); 714 shadowContext.setFillColor(Color::black); 715 716 if (shadowedRect.radii().isZero()) 717 shadowContext.fillRect(templateShadow); 718 else { 719 Path path; 720 path.addRoundedRect(FloatRoundedRect(templateShadow, shadowedRect.radii())); 721 shadowContext.fillPath(path); 722 } 723 blurAndColorShadowBuffer(templateSize); 724 } 725 726 FloatSize offset = m_offset; 727 if (shadowsIgnoreTransforms()) 728 offset.scale(1 / transform.xScale(), 1 / transform.yScale()); 729 730 FloatRect shadowBounds = shadowedRect.rect(); 731 shadowBounds.move(offset); 732 shadowBounds.inflateX(edgeSize.width()); 733 shadowBounds.inflateY(edgeSize.height()); 734 735 drawLayerPiecesAndFillCenter(shadowBounds, shadowedRect.radii(), edgeSize, templateSize, drawImage, fillRect); 736 737 m_layerImage = nullptr; 738 739 #if USE(CG) 740 ScratchBuffer::singleton().scheduleScratchBufferPurge(); 741 #endif 742 } 743 744 void ShadowBlur::drawInsetShadowWithTiling(const AffineTransform& transform, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const IntSize& templateSize, const IntSize& edgeSize, const DrawImageCallback& drawImage, const FillRectWithHoleCallback& fillRectWithHole) 745 { 746 #if USE(CG) 747 m_layerImage = ScratchBuffer::singleton().getScratchBuffer(templateSize); 748 #else 749 auto layerImage = ImageBuffer::create(templateSize, Unaccelerated, 1); 750 m_layerImage = layerImage.get(); 751 #endif 752 732 753 if (!m_layerImage) 733 754 return; … … 737 758 FloatRect templateHole = FloatRect(edgeSize.width(), edgeSize.height(), templateSize.width() - 2 * edgeSize.width(), templateSize.height() - 2 * edgeSize.height()); 738 759 760 bool redrawNeeded = true; 761 #if USE(CG) 739 762 // Only redraw in the scratch buffer if its cached contents don't match our needs 740 bool redrawNeeded = ScratchBuffer::singleton().setCachedInsetShadowValues(m_blurRadius, m_color, templateBounds, templateHole, holeRect.radii()); 763 redrawNeeded = ScratchBuffer::singleton().setCachedInsetShadowValues(m_blurRadius, m_color, templateBounds, templateHole, holeRect.radii()); 764 #endif 765 741 766 if (redrawNeeded) { 742 767 // Draw shadow into a new ImageBuffer. … … 759 784 } 760 785 FloatSize offset = m_offset; 761 if (shadowsIgnoreTransforms()) { 762 AffineTransform transform = graphicsContext.getCTM(); 786 if (shadowsIgnoreTransforms()) 763 787 offset.scale(1 / transform.xScale(), 1 / transform.yScale()); 764 } 765 766 FloatRect boundingRect = rect; 788 789 FloatRect boundingRect = fullRect; 767 790 boundingRect.move(offset); 768 791 … … 774 797 775 798 // Fill the external part of the shadow (which may be visible because of offset). 776 Path exteriorPath; 777 exteriorPath.addRect(boundingRect); 778 exteriorPath.addRect(destHoleBounds); 779 780 { 781 GraphicsContextStateSaver fillStateSaver(graphicsContext); 782 graphicsContext.setFillRule(WindRule::EvenOdd); 783 graphicsContext.setFillColor(m_color); 784 graphicsContext.clearShadow(); 785 graphicsContext.fillPath(exteriorPath); 786 } 787 788 drawLayerPieces(graphicsContext, destHoleBounds, holeRect.radii(), edgeSize, templateSize, InnerShadow); 799 fillRectWithHole(boundingRect, destHoleBounds, m_color); 800 801 drawLayerPieces(destHoleBounds, holeRect.radii(), edgeSize, templateSize, drawImage); 789 802 790 803 m_layerImage = nullptr; 804 805 #if USE(CG) 791 806 ScratchBuffer::singleton().scheduleScratchBufferPurge(); 792 } 793 794 void ShadowBlur::drawRectShadowWithTiling(GraphicsContext& graphicsContext, const FloatRoundedRect& shadowedRect, const IntSize& templateSize, const IntSize& edgeSize) 795 { 796 auto& scratchBuffer = ScratchBuffer::singleton(); 797 m_layerImage = scratchBuffer.getScratchBuffer(templateSize); 798 if (!m_layerImage) 799 return; 800 801 FloatRect templateShadow = FloatRect(edgeSize.width(), edgeSize.height(), templateSize.width() - 2 * edgeSize.width(), templateSize.height() - 2 * edgeSize.height()); 802 803 // Only redraw in the scratch buffer if its cached contents don't match our needs 804 bool redrawNeeded = scratchBuffer.setCachedShadowValues(m_blurRadius, m_color, templateShadow, shadowedRect.radii(), m_layerSize); 805 if (redrawNeeded) { 806 // Draw shadow into the ImageBuffer. 807 GraphicsContext& shadowContext = m_layerImage->context(); 808 GraphicsContextStateSaver shadowStateSaver(shadowContext); 809 810 shadowContext.clearRect(FloatRect(0, 0, templateSize.width(), templateSize.height())); 811 shadowContext.setFillColor(Color::black); 812 813 if (shadowedRect.radii().isZero()) 814 shadowContext.fillRect(templateShadow); 815 else { 816 Path path; 817 path.addRoundedRect(FloatRoundedRect(templateShadow, shadowedRect.radii())); 818 shadowContext.fillPath(path); 819 } 820 821 blurAndColorShadowBuffer(templateSize); 822 } 823 FloatSize offset = m_offset; 824 if (shadowsIgnoreTransforms()) { 825 AffineTransform transform = graphicsContext.getCTM(); 826 offset.scale(1 / transform.xScale(), 1 / transform.yScale()); 827 } 828 829 FloatRect shadowBounds = shadowedRect.rect(); 830 shadowBounds.move(offset); 831 shadowBounds.inflateX(edgeSize.width()); 832 shadowBounds.inflateY(edgeSize.height()); 833 834 drawLayerPieces(graphicsContext, shadowBounds, shadowedRect.radii(), edgeSize, templateSize, OuterShadow); 835 836 m_layerImage = nullptr; 837 ScratchBuffer::singleton().scheduleScratchBufferPurge(); 838 } 839 840 void ShadowBlur::drawLayerPieces(GraphicsContext& graphicsContext, const FloatRect& shadowBounds, const FloatRoundedRect::Radii& radii, const IntSize& bufferPadding, const IntSize& templateSize, ShadowDirection direction) 807 #endif 808 } 809 810 void ShadowBlur::drawLayerPieces(const FloatRect& shadowBounds, const FloatRoundedRect::Radii& radii, const IntSize& bufferPadding, const IntSize& templateSize, const DrawImageCallback& drawImage) 841 811 { 842 812 const IntSize twiceRadius = IntSize(bufferPadding.width() * 2, bufferPadding.height() * 2); … … 850 820 int centerWidth = shadowBounds.width() - leftSlice - rightSlice; 851 821 int centerHeight = shadowBounds.height() - topSlice - bottomSlice; 852 853 if (direction == OuterShadow) {854 FloatRect shadowInterior(shadowBounds.x() + leftSlice, shadowBounds.y() + topSlice, centerWidth, centerHeight);855 if (!shadowInterior.isEmpty()) {856 GraphicsContextStateSaver stateSaver(graphicsContext);857 graphicsContext.setFillColor(m_color);858 graphicsContext.clearShadow();859 graphicsContext.fillRect(shadowInterior);860 }861 }862 863 GraphicsContextStateSaver stateSaver(graphicsContext);864 graphicsContext.setFillColor(m_color);865 graphicsContext.clearShadow();866 867 // Note that drawing the ImageBuffer is faster than creating a Image and drawing that,868 // because ImageBuffer::draw() knows that it doesn't have to copy the image bits.869 822 FloatRect centerRect(shadowBounds.x() + leftSlice, shadowBounds.y() + topSlice, centerWidth, centerHeight); 870 centerRect = graphicsContext.roundToDevicePixels(centerRect); 871 823 872 824 // Top side. 873 825 FloatRect tileRect = FloatRect(leftSlice, 0, templateSideLength, topSlice); 874 826 FloatRect destRect = FloatRect(centerRect.x(), centerRect.y() - topSlice, centerRect.width(), topSlice); 875 graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect);827 drawImage(*m_layerImage, destRect, tileRect); 876 828 877 829 // Draw the bottom side. … … 880 832 destRect.setY(centerRect.maxY()); 881 833 destRect.setHeight(bottomSlice); 882 graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect);834 drawImage(*m_layerImage, destRect, tileRect); 883 835 884 836 // Left side. 885 837 tileRect = FloatRect(0, topSlice, leftSlice, templateSideLength); 886 838 destRect = FloatRect(centerRect.x() - leftSlice, centerRect.y(), leftSlice, centerRect.height()); 887 graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect);839 drawImage(*m_layerImage, destRect, tileRect); 888 840 889 841 // Right side. … … 892 844 destRect.setX(centerRect.maxX()); 893 845 destRect.setWidth(rightSlice); 894 graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect);846 drawImage(*m_layerImage, destRect, tileRect); 895 847 896 848 // Top left corner. 897 849 tileRect = FloatRect(0, 0, leftSlice, topSlice); 898 850 destRect = FloatRect(centerRect.x() - leftSlice, centerRect.y() - topSlice, leftSlice, topSlice); 899 graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect);851 drawImage(*m_layerImage, destRect, tileRect); 900 852 901 853 // Top right corner. 902 854 tileRect = FloatRect(templateSize.width() - rightSlice, 0, rightSlice, topSlice); 903 855 destRect = FloatRect(centerRect.maxX(), centerRect.y() - topSlice, rightSlice, topSlice); 904 graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect);856 drawImage(*m_layerImage, destRect, tileRect); 905 857 906 858 // Bottom right corner. 907 859 tileRect = FloatRect(templateSize.width() - rightSlice, templateSize.height() - bottomSlice, rightSlice, bottomSlice); 908 860 destRect = FloatRect(centerRect.maxX(), centerRect.maxY(), rightSlice, bottomSlice); 909 graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect);861 drawImage(*m_layerImage, destRect, tileRect); 910 862 911 863 // Bottom left corner. 912 864 tileRect = FloatRect(0, templateSize.height() - bottomSlice, leftSlice, bottomSlice); 913 865 destRect = FloatRect(centerRect.x() - leftSlice, centerRect.maxY(), leftSlice, bottomSlice); 914 graphicsContext.drawImageBuffer(*m_layerImage, destRect, tileRect); 915 } 916 866 drawImage(*m_layerImage, destRect, tileRect); 867 } 868 869 void ShadowBlur::drawLayerPiecesAndFillCenter(const FloatRect& shadowBounds, const FloatRoundedRect::Radii& radii, const IntSize& bufferPadding, const IntSize& templateSize, const DrawImageCallback& drawImage, const FillRectCallback& fillRect) 870 { 871 const IntSize twiceRadius = IntSize(bufferPadding.width() * 2, bufferPadding.height() * 2); 872 873 int leftSlice; 874 int rightSlice; 875 int topSlice; 876 int bottomSlice; 877 computeSliceSizesFromRadii(twiceRadius, radii, leftSlice, rightSlice, topSlice, bottomSlice); 878 879 int centerWidth = shadowBounds.width() - leftSlice - rightSlice; 880 int centerHeight = shadowBounds.height() - topSlice - bottomSlice; 881 FloatRect centerRect(shadowBounds.x() + leftSlice, shadowBounds.y() + topSlice, centerWidth, centerHeight); 882 883 // Fill center 884 if (!centerRect.isEmpty()) 885 fillRect(centerRect, m_color); 886 887 drawLayerPieces(shadowBounds, radii, bufferPadding, templateSize, drawImage); 888 } 917 889 918 890 void ShadowBlur::blurShadowBuffer(const IntSize& templateSize) … … 963 935 964 936 blurAndColorShadowBuffer(expandedIntSize(m_layerSize)); 965 drawBuffer(*layerImage, m_layerOrigin, m_layerSize , m_sourceRect);937 drawBuffer(*layerImage, m_layerOrigin, m_layerSize); 966 938 } 967 939 -
trunk/Source/WebCore/platform/graphics/ShadowBlur.h
r228776 r244913 24 24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 28 29 #ifndef ShadowBlur_h 30 #define ShadowBlur_h 29 #pragma once 31 30 32 31 #include "Color.h" … … 64 63 void drawInsetShadow(GraphicsContext&, const FloatRect&, const FloatRoundedRect& holeRect); 65 64 66 using DrawBufferCallback = WTF::Function<void(ImageBuffer&, const FloatPoint&, const FloatSize&, const FloatRect&)>; 67 void drawRectShadow(const AffineTransform&, const IntRect&, const FloatRoundedRect&, const DrawBufferCallback&); 68 void drawInsetShadow(const AffineTransform&, const IntRect&, const FloatRect&, const FloatRoundedRect&, const DrawBufferCallback&); 65 using DrawBufferCallback = WTF::Function<void(ImageBuffer&, const FloatPoint&, const FloatSize&)>; 66 using DrawImageCallback = WTF::Function<void(ImageBuffer&, const FloatRect&, const FloatRect&)>; 67 using FillRectCallback = WTF::Function<void(const FloatRect&, const Color&)>; 68 using FillRectWithHoleCallback = WTF::Function<void(const FloatRect&, const FloatRect&, const Color&)>; 69 using DrawShadowCallback = WTF::Function<void(GraphicsContext&)>; 69 70 70 using DrawShadowCallback = WTF::Function<void(GraphicsContext&)>; 71 void drawShadowLayer(const AffineTransform&, const IntRect&, const FloatRect&, const DrawShadowCallback&, const DrawBufferCallback&); 71 // DrawBufferCallback is for drawing shadow without tiling. 72 // DrawImageCallback and FillRectCallback is for drawing shadow with tiling. 73 void drawRectShadow(const AffineTransform&, const IntRect& clipBounds, const FloatRoundedRect& shadowedRect, const DrawBufferCallback&, const DrawImageCallback&, const FillRectCallback&); 74 void drawInsetShadow(const AffineTransform&, const IntRect& clipBounds, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const DrawBufferCallback&, const DrawImageCallback&, const FillRectWithHoleCallback&); 75 void drawShadowLayer(const AffineTransform&, const IntRect& clipBounds, const FloatRect& layerArea, const DrawShadowCallback&, const DrawBufferCallback&); 72 76 73 77 void blurLayerImage(unsigned char*, const IntSize&, int stride); … … 83 87 84 88 void adjustBlurRadius(const AffineTransform&); 85 89 86 90 enum ShadowDirection { 87 91 OuterShadow, 88 92 InnerShadow 89 93 }; 90 94 91 95 IntSize calculateLayerBoundingRect(const AffineTransform&, const FloatRect& layerArea, const IntRect& clipRect); 92 96 IntSize templateSize(const IntSize& blurredEdgeSize, const FloatRoundedRect::Radii&) const; 93 97 94 void drawRectShadowWithoutTiling(GraphicsContext&, const FloatRoundedRect&, const IntSize& layerSize);95 void drawRectShadowWithTiling(GraphicsContext&, const FloatRoundedRect&, const IntSize& shadowTemplateSize, const IntSize& blurredEdgeSize);96 97 void drawInsetShadowWithoutTiling(GraphicsContext&, const FloatRect&, const FloatRoundedRect& holeRect, const IntSize& layerSize);98 void drawInsetShadowWithTiling(GraphicsContext&, const FloatRect&, const FloatRoundedRect& holeRect, const IntSize& shadowTemplateSize, const IntSize& blurredEdgeSize);99 100 void drawLayerPieces(GraphicsContext&, const FloatRect& shadowBounds, const FloatRoundedRect::Radii&, const IntSize& roundedRadius, const IntSize& templateSize, ShadowDirection);101 102 98 void blurShadowBuffer(const IntSize& templateSize); 103 99 void blurAndColorShadowBuffer(const IntSize& templateSize); 104 100 101 void drawInsetShadowWithoutTiling(const AffineTransform&, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const IntSize& layerSize, const DrawBufferCallback&); 102 void drawInsetShadowWithTiling(const AffineTransform&, const FloatRect& fullRect, const FloatRoundedRect& holeRect, const IntSize& shadowTemplateSize, const IntSize& blurredEdgeSize, const DrawImageCallback&, const FillRectWithHoleCallback&); 103 104 void drawRectShadowWithoutTiling(const AffineTransform&, const FloatRoundedRect& shadowedRect, const IntSize& layerSize, const DrawBufferCallback&); 105 void drawRectShadowWithTiling(const AffineTransform&, const FloatRoundedRect& shadowedRect, const IntSize& shadowTemplateSize, const IntSize& blurredEdgeSize, const DrawImageCallback&, const FillRectCallback&); 106 107 void drawLayerPiecesAndFillCenter(const FloatRect& shadowBounds, const FloatRoundedRect::Radii&, const IntSize& roundedRadius, const IntSize& templateSize, const DrawImageCallback&, const FillRectCallback&); 108 void drawLayerPieces(const FloatRect& shadowBounds, const FloatRoundedRect::Radii&, const IntSize& roundedRadius, const IntSize& templateSize, const DrawImageCallback&); 109 105 110 IntSize blurredEdgeSize() const; 106 107 111 108 112 ShadowType m_type { NoShadow }; 109 113 … … 114 118 ImageBuffer* m_layerImage { nullptr }; // Buffer to where the temporary shadow will be drawn to. 115 119 116 Float Rect m_sourceRect; // Sub-rect of m_layerImage that contains the shadow pixels.120 FloatSize m_shadowedResultSize; // Size of the result of shadowing which is same as shadowedRect + blurred edges. 117 121 FloatPoint m_layerOrigin; // Top-left corner of the (possibly clipped) bounding rect to draw the shadow to. 118 122 FloatSize m_layerSize; // Size of m_layerImage pixels that need blurring. … … 123 127 124 128 } // namespace WebCore 125 126 #endif // ShadowBlur_h -
trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp
r237844 r244913 185 185 } 186 186 187 static void fillShadowBuffer(PlatformContextCairo& platformContext, ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize, const FloatRect& sourceRect, const ShadowState& shadowState) 187 // FIXME: This is mostly same as drawShadowLayerBuffer, so we should merge two. 188 static void drawShadowImage(PlatformContextCairo& platformContext, ImageBuffer& layerImage, const FloatRect& destRect, const FloatRect& srcRect, const ShadowState& shadowState) 189 { 190 RefPtr<Image> image = layerImage.copyImage(DontCopyBackingStore); 191 if (!image) 192 return; 193 194 if (auto surface = image->nativeImageForCurrentFrame()) { 195 drawNativeImage(platformContext, surface.get(), destRect, srcRect, shadowState.globalCompositeOperator, BlendMode::Normal, ImageOrientation(), 196 InterpolationDefault, shadowState.globalAlpha, ShadowState()); 197 } 198 } 199 200 static void fillShadowBuffer(PlatformContextCairo& platformContext, ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize, const ShadowState& shadowState) 188 201 { 189 202 save(platformContext); … … 198 211 fillSource.globalAlpha = shadowState.globalAlpha; 199 212 fillSource.color = shadowState.color; 200 fillRect(platformContext, FloatRect(layerOrigin, sourceRect.size()), fillSource, ShadowState());213 fillRect(platformContext, FloatRect(layerOrigin, expandedIntSize(layerSize)), fillSource, ShadowState()); 201 214 202 215 restore(platformContext); … … 253 266 } 254 267 }, 255 [&platformContext, &shadowState, &cairoContext, &path](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize , const FloatRect&)268 [&platformContext, &shadowState, &cairoContext, &path](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) 256 269 { 257 270 // The original path may still be hanging around on the context and endShadowLayer … … 267 280 } 268 281 282 269 283 static inline void fillCurrentCairoPath(PlatformContextCairo& platformContext, const FillSource& fillSource) 270 284 { … … 351 365 drawGlyphsToContext(shadowContext.platformContext()->cr(), scaledFont, syntheticBoldOffset, glyphs); 352 366 }, 353 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize , const FloatRect&)367 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) 354 368 { 355 369 drawShadowLayerBuffer(platformContext, layerImage, layerOrigin, layerSize, shadowState); … … 691 705 ShadowBlur shadow({ shadowState.blur, shadowState.blur }, shadowState.offset, shadowState.color, shadowState.ignoreTransforms); 692 706 shadow.drawRectShadow(State::getCTM(platformContext), State::getClipBounds(platformContext), FloatRoundedRect(rect), 693 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize , const FloatRect& sourceRect)707 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) 694 708 { 695 fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, sourceRect, shadowState); 709 fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, shadowState); 710 }, 711 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatRect& destRect, const FloatRect& srcRect) 712 { 713 drawShadowImage(platformContext, layerImage, destRect, srcRect, shadowState); 714 }, 715 [&platformContext](const FloatRect& rect, const Color& color) 716 { 717 fillRectWithColor(platformContext.cr(), rect, color); 696 718 }); 697 719 } … … 714 736 ShadowBlur shadow({ shadowState.blur, shadowState.blur }, shadowState.offset, shadowState.color, shadowState.ignoreTransforms); 715 737 shadow.drawRectShadow(State::getCTM(platformContext), State::getClipBounds(platformContext), rect, 716 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize , const FloatRect& sourceRect)738 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) 717 739 { 718 fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, sourceRect, shadowState); 740 fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, shadowState); 741 }, 742 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatRect& destRect, const FloatRect& srcRect) 743 { 744 drawShadowImage(platformContext, layerImage, destRect, srcRect, shadowState); 745 }, 746 [&platformContext](const FloatRect& rect, const Color& color) 747 { 748 fillRectWithColor(platformContext.cr(), rect, color); 719 749 }); 720 750 } … … 739 769 ShadowBlur shadow({ shadowState.blur, shadowState.blur }, shadowState.offset, shadowState.color, shadowState.ignoreTransforms); 740 770 shadow.drawInsetShadow(State::getCTM(platformContext), State::getClipBounds(platformContext), rect, roundedHoleRect, 741 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize , const FloatRect& sourceRect)771 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) 742 772 { 743 fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, sourceRect, shadowState); 773 fillShadowBuffer(platformContext, layerImage, layerOrigin, layerSize, shadowState); 774 }, 775 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatRect& destRect, const FloatRect& srcRect) 776 { 777 drawShadowImage(platformContext, layerImage, destRect, srcRect, shadowState); 778 }, 779 [&platformContext](const FloatRect& rect, const FloatRect& holeRect, const Color& color) 780 { 781 // FIXME: We should use fillRectWithRoundedHole. 782 cairo_t* cr = platformContext.cr(); 783 cairo_save(cr); 784 setSourceRGBAFromColor(cr, color); 785 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD); 786 cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height()); 787 cairo_rectangle(cr, holeRect.x(), holeRect.y(), holeRect.width(), holeRect.height()); 788 cairo_fill(cr); 789 cairo_restore(cr); 744 790 }); 745 791 } … … 933 979 drawPatternToCairoContext(shadowContext.platformContext()->cr(), pattern.get(), destRect, 1); 934 980 }, 935 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize , const FloatRect&)981 [&platformContext, &shadowState](ImageBuffer& layerImage, const FloatPoint& layerOrigin, const FloatSize& layerSize) 936 982 { 937 983 drawShadowLayerBuffer(platformContext, layerImage, layerOrigin, layerSize, shadowState);
Note: See TracChangeset
for help on using the changeset viewer.