3420
3420
IntDivCeil(aDirtyEnd - aTileOffset, aTileSize) * aTileSize;
3424
PixelSnapRectangle(gfxContext* aContext, nsIDeviceContext *aDC, nsRect& aRect)
3427
tmpRect.pos.x = aDC->AppUnitsToGfxUnits(aRect.x);
3428
tmpRect.pos.y = aDC->AppUnitsToGfxUnits(aRect.y);
3429
tmpRect.size.width = aDC->AppUnitsToGfxUnits(aRect.width);
3430
tmpRect.size.height = aDC->AppUnitsToGfxUnits(aRect.height);
3431
if (aContext->UserToDevicePixelSnapped(tmpRect)) {
3432
tmpRect = aContext->DeviceToUser(tmpRect);
3433
aRect.x = aDC->GfxUnitsToAppUnits(tmpRect.pos.x);
3434
aRect.y = aDC->GfxUnitsToAppUnits(tmpRect.pos.y);
3435
aRect.width = aDC->GfxUnitsToAppUnits(tmpRect.XMost()) - aRect.x;
3436
aRect.height = aDC->GfxUnitsToAppUnits(tmpRect.YMost()) - aRect.y;
3441
PixelSnapPoint(gfxContext* aContext, nsIDeviceContext *aDC, nsPoint& aPoint)
3444
tmpRect.pos.x = aDC->AppUnitsToGfxUnits(aPoint.x);
3445
tmpRect.pos.y = aDC->AppUnitsToGfxUnits(aPoint.y);
3446
tmpRect.size.width = 0;
3447
tmpRect.size.height = 0;
3448
if (aContext->UserToDevicePixelSnapped(tmpRect)) {
3449
tmpRect = aContext->DeviceToUser(tmpRect);
3450
aPoint.x = aDC->GfxUnitsToAppUnits(tmpRect.pos.x);
3451
aPoint.y = aDC->GfxUnitsToAppUnits(tmpRect.pos.y);
3424
3456
nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
3425
3457
nsIRenderingContext& aRenderingContext,
3512
nsIDeviceContext *dc = aPresContext->DeviceContext();
3513
nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext();
3515
// Snap bgClipArea to device pixel boundaries. (We have to snap
3516
// bgOriginArea below; if we don't do this as well then we could make
3517
// incorrect decisions about various optimizations.)
3518
PixelSnapRectangle(ctx, dc, bgClipArea);
3480
3520
// The actual dirty rect is the intersection of the 'background-clip'
3481
3521
// area and the dirty rect we were given
3482
3522
nsRect dirtyRect;
3604
// Snap bgOriginArea to device pixel boundaries to avoid variations in
3605
// tiling when the subpixel position of the element changes.
3606
PixelSnapRectangle(ctx, dc, bgOriginArea);
3564
3608
// Based on the repeat setting, compute how many tiles we should
3565
3609
// lay down for each axis. The value computed is the maximum based
3566
3610
// on the dirty rect before accounting for the background-position.
3670
nsPoint borderAreaOriginSnapped = aBorderArea.TopLeft();
3671
PixelSnapPoint(ctx, dc, borderAreaOriginSnapped);
3626
3673
// Compute the anchor point.
3628
3675
// When tiling, the anchor coordinate values will be negative offsets
3703
3750
// For scrolling attachment, the anchor is within the 'background-clip'
3704
anchor.x += bgClipArea.x - aBorderArea.x;
3705
anchor.y += bgClipArea.y - aBorderArea.y;
3751
anchor.x += bgClipArea.x - borderAreaOriginSnapped.x;
3752
anchor.y += bgClipArea.y - borderAreaOriginSnapped.y;
3708
nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext();
3755
// Pixel-snap the anchor point so that we don't end up with blurry
3756
// images due to subpixel positions. But round 0.5 down rather than
3757
// up, since that's what we've always done. (And do that by just
3758
// snapping the negative of the point.)
3759
anchor.x = -anchor.x; anchor.y = -anchor.y;
3760
PixelSnapPoint(ctx, dc, anchor);
3761
anchor.x = -anchor.x; anchor.y = -anchor.y;
3711
3765
nscoord appUnitsPerPixel = aPresContext->DevPixelsToAppUnits(1);
3861
3915
// relative to aBorderArea.TopLeft()
3916
// ... but pixel-snapped, so that it comes out correctly relative to
3917
// all the other pixel-snapped things
3862
3918
nsRect tileRect(anchor, nsSize(tileWidth, tileHeight));
3863
3919
if (repeat & NS_STYLE_BG_REPEAT_X) {
3864
3920
// When tiling in the x direction, adjust the starting position of the
3865
3921
// tile to account for dirtyRect.x. When tiling in x, the anchor.x value
3866
3922
// will be a negative value used to adjust the starting coordinate.
3867
nscoord x0 = FindTileStart(dirtyRect.x - aBorderArea.x, anchor.x, tileWidth);
3868
nscoord x1 = FindTileEnd(dirtyRect.XMost() - aBorderArea.x, anchor.x, tileWidth);
3923
nscoord x0 = FindTileStart(dirtyRect.x - borderAreaOriginSnapped.x, anchor.x, tileWidth);
3924
nscoord x1 = FindTileEnd(dirtyRect.XMost() - borderAreaOriginSnapped.x, anchor.x, tileWidth);
3869
3925
tileRect.x = x0;
3870
3926
tileRect.width = x1 - x0;
3873
3929
// When tiling in the y direction, adjust the starting position of the
3874
3930
// tile to account for dirtyRect.y. When tiling in y, the anchor.y value
3875
3931
// will be a negative value used to adjust the starting coordinate.
3876
nscoord y0 = FindTileStart(dirtyRect.y - aBorderArea.y, anchor.y, tileHeight);
3877
nscoord y1 = FindTileEnd(dirtyRect.YMost() - aBorderArea.y, anchor.y, tileHeight);
3932
nscoord y0 = FindTileStart(dirtyRect.y - borderAreaOriginSnapped.y, anchor.y, tileHeight);
3933
nscoord y1 = FindTileEnd(dirtyRect.YMost() - borderAreaOriginSnapped.y, anchor.y, tileHeight);
3878
3934
tileRect.y = y0;
3879
3935
tileRect.height = y1 - y0;
3882
3938
// Take the intersection again to paint only the required area.
3883
nsRect absTileRect = tileRect + aBorderArea.TopLeft();
3939
nsRect absTileRect = tileRect + borderAreaOriginSnapped;
3885
3941
nsRect drawRect;
3886
3942
if (drawRect.IntersectRect(absTileRect, dirtyRect)) {
3899
3955
// passed in relative to the image top-left.
3900
3956
nsRect destRect; // The rectangle we would draw ignoring dirty-rect
3901
3957
destRect.IntersectRect(absTileRect, bgClipArea);
3902
nsRect subimageRect = destRect - aBorderArea.TopLeft() - tileRect.TopLeft();
3958
nsRect subimageRect = destRect - borderAreaOriginSnapped - tileRect.TopLeft();
3903
3959
if (sourceRect.XMost() <= tileWidth && sourceRect.YMost() <= tileHeight) {
3904
3960
// The entire drawRect is contained inside a single tile; just
3905
3961
// draw the corresponding part of the image once.