| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/paint/BackgroundImageGeometry.h" | 5 #include "core/paint/BackgroundImageGeometry.h" |
| 6 | 6 |
| 7 #include "core/frame/FrameView.h" | 7 #include "core/frame/FrameView.h" |
| 8 #include "core/layout/LayoutBox.h" | 8 #include "core/layout/LayoutBox.h" |
| 9 #include "core/layout/LayoutBoxModelObject.h" | 9 #include "core/layout/LayoutBoxModelObject.h" |
| 10 #include "core/layout/LayoutView.h" | 10 #include "core/layout/LayoutView.h" |
| 11 #include "core/layout/compositing/CompositedLayerMapping.h" | 11 #include "core/layout/compositing/CompositedLayerMapping.h" |
| 12 #include "core/paint/PaintLayer.h" | 12 #include "core/paint/PaintLayer.h" |
| 13 #include "platform/LayoutUnit.h" | 13 #include "platform/LayoutUnit.h" |
| 14 #include "platform/geometry/LayoutRect.h" | 14 #include "platform/geometry/LayoutRect.h" |
| 15 | 15 |
| 16 namespace blink { | 16 namespace blink { |
| 17 | 17 |
| 18 namespace { | 18 namespace { |
| 19 | 19 |
| 20 // Return the amount of space to leave between image tiles for the background-re
peat: space property. | 20 // Return the amount of space to leave between image tiles for the background-re
peat: space property. |
| 21 inline LayoutUnit getSpaceBetweenImageTiles(LayoutUnit areaSize, LayoutUnit tile
Size) | 21 inline LayoutUnit getSpaceBetweenImageTiles(LayoutUnit areaSize, LayoutUnit tile
Size) |
| 22 { | 22 { |
| 23 int numberOfTiles = areaSize / tileSize; | 23 int numberOfTiles = areaSize / tileSize; |
| 24 LayoutUnit space = -1; | 24 LayoutUnit space(-1); |
| 25 | 25 |
| 26 if (numberOfTiles > 1) { | 26 if (numberOfTiles > 1) { |
| 27 // Spec doesn't specify rounding, so use the same method as for backgrou
nd-repeat: round. | 27 // Spec doesn't specify rounding, so use the same method as for backgrou
nd-repeat: round. |
| 28 space = (areaSize - numberOfTiles * tileSize) / (numberOfTiles - 1); | 28 space = (areaSize - numberOfTiles * tileSize) / (numberOfTiles - 1); |
| 29 } | 29 } |
| 30 | 30 |
| 31 return space; | 31 return space; |
| 32 } | 32 } |
| 33 | 33 |
| 34 bool fixedBackgroundPaintsInLocalCoordinates(const LayoutObject& obj, const Glob
alPaintFlags globalPaintFlags) | 34 bool fixedBackgroundPaintsInLocalCoordinates(const LayoutObject& obj, const Glob
alPaintFlags globalPaintFlags) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 56 LayoutSize imageIntrinsicSize = obj.calculateImageIntrinsicDimensions(image,
positioningAreaSize, LayoutBoxModelObject::ScaleByEffectiveZoom); | 56 LayoutSize imageIntrinsicSize = obj.calculateImageIntrinsicDimensions(image,
positioningAreaSize, LayoutBoxModelObject::ScaleByEffectiveZoom); |
| 57 imageIntrinsicSize.scale(1 / image->imageScaleFactor(), 1 / image->imageScal
eFactor()); | 57 imageIntrinsicSize.scale(1 / image->imageScaleFactor(), 1 / image->imageScal
eFactor()); |
| 58 switch (type) { | 58 switch (type) { |
| 59 case SizeLength: { | 59 case SizeLength: { |
| 60 LayoutSize tileSize(positioningAreaSize); | 60 LayoutSize tileSize(positioningAreaSize); |
| 61 | 61 |
| 62 Length layerWidth = fillLayer.size().size.width(); | 62 Length layerWidth = fillLayer.size().size.width(); |
| 63 Length layerHeight = fillLayer.size().size.height(); | 63 Length layerHeight = fillLayer.size().size.height(); |
| 64 | 64 |
| 65 if (layerWidth.isFixed()) | 65 if (layerWidth.isFixed()) |
| 66 tileSize.setWidth(layerWidth.value()); | 66 tileSize.setWidth(LayoutUnit(layerWidth.value())); |
| 67 else if (layerWidth.hasPercent()) | 67 else if (layerWidth.hasPercent()) |
| 68 tileSize.setWidth(valueForLength(layerWidth, positioningAreaSize.wid
th())); | 68 tileSize.setWidth(valueForLength(layerWidth, positioningAreaSize.wid
th())); |
| 69 | 69 |
| 70 if (layerHeight.isFixed()) | 70 if (layerHeight.isFixed()) |
| 71 tileSize.setHeight(layerHeight.value()); | 71 tileSize.setHeight(LayoutUnit(layerHeight.value())); |
| 72 else if (layerHeight.hasPercent()) | 72 else if (layerHeight.hasPercent()) |
| 73 tileSize.setHeight(valueForLength(layerHeight, positioningAreaSize.h
eight())); | 73 tileSize.setHeight(valueForLength(layerHeight, positioningAreaSize.h
eight())); |
| 74 | 74 |
| 75 // If one of the values is auto we have to use the appropriate | 75 // If one of the values is auto we have to use the appropriate |
| 76 // scale to maintain our aspect ratio. | 76 // scale to maintain our aspect ratio. |
| 77 if (layerWidth.isAuto() && !layerHeight.isAuto()) { | 77 if (layerWidth.isAuto() && !layerHeight.isAuto()) { |
| 78 if (imageIntrinsicSize.height()) { | 78 if (imageIntrinsicSize.height()) { |
| 79 LayoutUnit adjustedWidth = imageIntrinsicSize.width() * tileSize
.height() / imageIntrinsicSize.height(); | 79 LayoutUnit adjustedWidth = imageIntrinsicSize.width() * tileSize
.height() / imageIntrinsicSize.height(); |
| 80 if (imageIntrinsicSize.width() >= 1 && adjustedWidth < 1) | 80 if (imageIntrinsicSize.width() >= 1 && adjustedWidth < 1) |
| 81 adjustedWidth = 1; | 81 adjustedWidth = LayoutUnit(1); |
| 82 tileSize.setWidth(adjustedWidth); | 82 tileSize.setWidth(adjustedWidth); |
| 83 } | 83 } |
| 84 } else if (!layerWidth.isAuto() && layerHeight.isAuto()) { | 84 } else if (!layerWidth.isAuto() && layerHeight.isAuto()) { |
| 85 if (imageIntrinsicSize.width()) { | 85 if (imageIntrinsicSize.width()) { |
| 86 LayoutUnit adjustedHeight = imageIntrinsicSize.height() * tileSi
ze.width() / imageIntrinsicSize.width(); | 86 LayoutUnit adjustedHeight = imageIntrinsicSize.height() * tileSi
ze.width() / imageIntrinsicSize.width(); |
| 87 if (imageIntrinsicSize.height() >= 1 && adjustedHeight < 1) | 87 if (imageIntrinsicSize.height() >= 1 && adjustedHeight < 1) |
| 88 adjustedHeight = 1; | 88 adjustedHeight = LayoutUnit(1); |
| 89 tileSize.setHeight(adjustedHeight); | 89 tileSize.setHeight(adjustedHeight); |
| 90 } | 90 } |
| 91 } else if (layerWidth.isAuto() && layerHeight.isAuto()) { | 91 } else if (layerWidth.isAuto() && layerHeight.isAuto()) { |
| 92 // If both width and height are auto, use the image's intrinsic size
. | 92 // If both width and height are auto, use the image's intrinsic size
. |
| 93 tileSize = imageIntrinsicSize; | 93 tileSize = imageIntrinsicSize; |
| 94 } | 94 } |
| 95 | 95 |
| 96 tileSize.clampNegativeToZero(); | 96 tileSize.clampNegativeToZero(); |
| 97 return tileSize; | 97 return tileSize; |
| 98 } | 98 } |
| 99 case SizeNone: { | 99 case SizeNone: { |
| 100 // If both values are 'auto' then the intrinsic width and/or height of t
he image should be used, if any. | 100 // If both values are 'auto' then the intrinsic width and/or height of t
he image should be used, if any. |
| 101 if (!imageIntrinsicSize.isEmpty()) | 101 if (!imageIntrinsicSize.isEmpty()) |
| 102 return imageIntrinsicSize; | 102 return imageIntrinsicSize; |
| 103 | 103 |
| 104 // If the image has neither an intrinsic width nor an intrinsic height,
its size is determined as for 'contain'. | 104 // If the image has neither an intrinsic width nor an intrinsic height,
its size is determined as for 'contain'. |
| 105 type = Contain; | 105 type = Contain; |
| 106 } | 106 } |
| 107 case Contain: | 107 case Contain: |
| 108 case Cover: { | 108 case Cover: { |
| 109 float horizontalScaleFactor = imageIntrinsicSize.width() | 109 float horizontalScaleFactor = imageIntrinsicSize.width() |
| 110 ? positioningAreaSize.width().toFloat() / imageIntrinsicSize.width()
: 1; | 110 ? positioningAreaSize.width().toFloat() / imageIntrinsicSize.width()
: 1.0f; |
| 111 float verticalScaleFactor = imageIntrinsicSize.height() | 111 float verticalScaleFactor = imageIntrinsicSize.height() |
| 112 ? positioningAreaSize.height().toFloat() / imageIntrinsicSize.height
() : 1; | 112 ? positioningAreaSize.height().toFloat() / imageIntrinsicSize.height
() : 1.0f; |
| 113 float scaleFactor = type == Contain ? std::min(horizontalScaleFactor, ve
rticalScaleFactor) : std::max(horizontalScaleFactor, verticalScaleFactor); | 113 float scaleFactor = type == Contain ? std::min(horizontalScaleFactor, ve
rticalScaleFactor) : std::max(horizontalScaleFactor, verticalScaleFactor); |
| 114 return LayoutSize(std::max<LayoutUnit>(1, imageIntrinsicSize.width() * s
caleFactor), std::max<LayoutUnit>(1, imageIntrinsicSize.height() * scaleFactor))
; | 114 return LayoutSize(std::max(1.0f, imageIntrinsicSize.width() * scaleFacto
r), |
| 115 std::max(1.0f, imageIntrinsicSize.height() * scaleFactor)); |
| 115 } | 116 } |
| 116 } | 117 } |
| 117 | 118 |
| 118 ASSERT_NOT_REACHED(); | 119 ASSERT_NOT_REACHED(); |
| 119 return LayoutSize(); | 120 return LayoutSize(); |
| 120 } | 121 } |
| 121 | 122 |
| 122 IntPoint accumulatedScrollOffsetForFixedBackground(const LayoutBoxModelObject& o
bject, const LayoutBoxModelObject* container) | 123 IntPoint accumulatedScrollOffsetForFixedBackground(const LayoutBoxModelObject& o
bject, const LayoutBoxModelObject* container) |
| 123 { | 124 { |
| 124 IntPoint result; | 125 IntPoint result; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 fixedAttachment = false; | 215 fixedAttachment = false; |
| 215 } | 216 } |
| 216 | 217 |
| 217 if (!fixedAttachment) { | 218 if (!fixedAttachment) { |
| 218 setDestRect(paintRect); | 219 setDestRect(paintRect); |
| 219 | 220 |
| 220 LayoutUnit right; | 221 LayoutUnit right; |
| 221 LayoutUnit bottom; | 222 LayoutUnit bottom; |
| 222 // Scroll and Local. | 223 // Scroll and Local. |
| 223 if (fillLayer.origin() != BorderFillBox) { | 224 if (fillLayer.origin() != BorderFillBox) { |
| 224 left = positioningBox.borderLeft(); | 225 left = LayoutUnit(positioningBox.borderLeft()); |
| 225 right = positioningBox.borderRight(); | 226 right = LayoutUnit(positioningBox.borderRight()); |
| 226 top = positioningBox.borderTop(); | 227 top = LayoutUnit(positioningBox.borderTop()); |
| 227 bottom = positioningBox.borderBottom(); | 228 bottom = LayoutUnit(positioningBox.borderBottom()); |
| 228 if (fillLayer.origin() == ContentFillBox) { | 229 if (fillLayer.origin() == ContentFillBox) { |
| 229 left += positioningBox.paddingLeft(); | 230 left += positioningBox.paddingLeft(); |
| 230 right += positioningBox.paddingRight(); | 231 right += positioningBox.paddingRight(); |
| 231 top += positioningBox.paddingTop(); | 232 top += positioningBox.paddingTop(); |
| 232 bottom += positioningBox.paddingBottom(); | 233 bottom += positioningBox.paddingBottom(); |
| 233 } | 234 } |
| 234 } | 235 } |
| 235 | 236 |
| 236 if (isLayoutView) { | 237 if (isLayoutView) { |
| 237 // The background of the box generated by the root element covers th
e entire canvas and will | 238 // The background of the box generated by the root element covers th
e entire canvas and will |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 | 287 |
| 287 fillTileSize.setWidth(positioningAreaSize.width() / nrTiles); | 288 fillTileSize.setWidth(positioningAreaSize.width() / nrTiles); |
| 288 | 289 |
| 289 // Maintain aspect ratio if background-size: auto is set | 290 // Maintain aspect ratio if background-size: auto is set |
| 290 if (fillLayer.size().size.height().isAuto() && backgroundRepeatY != Roun
dFill) { | 291 if (fillLayer.size().size.height().isAuto() && backgroundRepeatY != Roun
dFill) { |
| 291 fillTileSize.setHeight(fillTileSize.height() * positioningAreaSize.w
idth() / (nrTiles * fillTileSize.width())); | 292 fillTileSize.setHeight(fillTileSize.height() * positioningAreaSize.w
idth() / (nrTiles * fillTileSize.width())); |
| 292 } | 293 } |
| 293 | 294 |
| 294 setTileSize(fillTileSize); | 295 setTileSize(fillTileSize); |
| 295 setImageContainerSize(fillTileSize); | 296 setImageContainerSize(fillTileSize); |
| 296 setPhaseX(tileSize().width() ? tileSize().width() - fmodf((computedXPosi
tion + left), tileSize().width()) : 0.0f); | 297 setPhaseX(tileSize().width() ? LayoutUnit(tileSize().width() - fmodf((co
mputedXPosition + left), tileSize().width())) |
| 298 : LayoutUnit()); |
| 297 setSpaceSize(LayoutSize()); | 299 setSpaceSize(LayoutSize()); |
| 298 } | 300 } |
| 299 | 301 |
| 300 LayoutUnit computedYPosition = roundedMinimumValueForLength(fillLayer.yPosit
ion(), availableHeight); | 302 LayoutUnit computedYPosition = roundedMinimumValueForLength(fillLayer.yPosit
ion(), availableHeight); |
| 301 if (backgroundRepeatY == RoundFill && positioningAreaSize.height() > LayoutU
nit() && fillTileSize.height() > LayoutUnit()) { | 303 if (backgroundRepeatY == RoundFill && positioningAreaSize.height() > LayoutU
nit() && fillTileSize.height() > LayoutUnit()) { |
| 302 int nrTiles = std::max(1, roundToInt(positioningAreaSize.height() / fill
TileSize.height())); | 304 int nrTiles = std::max(1, roundToInt(positioningAreaSize.height() / fill
TileSize.height())); |
| 303 | 305 |
| 304 fillTileSize.setHeight(positioningAreaSize.height() / nrTiles); | 306 fillTileSize.setHeight(positioningAreaSize.height() / nrTiles); |
| 305 | 307 |
| 306 // Maintain aspect ratio if background-size: auto is set | 308 // Maintain aspect ratio if background-size: auto is set |
| 307 if (fillLayer.size().size.width().isAuto() && backgroundRepeatX != Round
Fill) { | 309 if (fillLayer.size().size.width().isAuto() && backgroundRepeatX != Round
Fill) { |
| 308 fillTileSize.setWidth(fillTileSize.width() * positioningAreaSize.hei
ght() / (nrTiles * fillTileSize.height())); | 310 fillTileSize.setWidth(fillTileSize.width() * positioningAreaSize.hei
ght() / (nrTiles * fillTileSize.height())); |
| 309 } | 311 } |
| 310 | 312 |
| 311 setTileSize(fillTileSize); | 313 setTileSize(fillTileSize); |
| 312 setImageContainerSize(fillTileSize); | 314 setImageContainerSize(fillTileSize); |
| 313 setPhaseY(tileSize().height() ? tileSize().height() - fmodf((computedYPo
sition + top), tileSize().height()) : 0.0f); | 315 setPhaseY(tileSize().height() ? LayoutUnit(tileSize().height() - fmodf((
computedYPosition + top), tileSize().height())) |
| 316 : LayoutUnit()); |
| 314 setSpaceSize(LayoutSize()); | 317 setSpaceSize(LayoutSize()); |
| 315 } | 318 } |
| 316 | 319 |
| 317 if (backgroundRepeatX == RepeatFill) { | 320 if (backgroundRepeatX == RepeatFill) { |
| 318 LayoutUnit xOffset = fillLayer.backgroundXOrigin() == RightEdge ? availa
bleWidth - computedXPosition : computedXPosition; | 321 LayoutUnit xOffset = fillLayer.backgroundXOrigin() == RightEdge ? availa
bleWidth - computedXPosition : computedXPosition; |
| 319 setPhaseX(tileSize().width() ? tileSize().width() - fmodf((xOffset + lef
t), tileSize().width()) : 0.0f); | 322 setPhaseX(tileSize().width() ? LayoutUnit(tileSize().width() - fmodf((xO
ffset + left), tileSize().width())) |
| 323 : LayoutUnit()); |
| 320 setSpaceSize(LayoutSize()); | 324 setSpaceSize(LayoutSize()); |
| 321 } else if (backgroundRepeatX == SpaceFill && fillTileSize.width() > LayoutUn
it()) { | 325 } else if (backgroundRepeatX == SpaceFill && fillTileSize.width() > LayoutUn
it()) { |
| 322 LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.width()
, tileSize().width()); | 326 LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.width()
, tileSize().width()); |
| 323 LayoutUnit actualWidth = tileSize().width() + space; | 327 LayoutUnit actualWidth = tileSize().width() + space; |
| 324 | 328 |
| 325 if (space >= LayoutUnit()) { | 329 if (space >= LayoutUnit()) { |
| 326 computedXPosition = roundedMinimumValueForLength(Length(), available
Width); | 330 computedXPosition = roundedMinimumValueForLength(Length(), available
Width); |
| 327 setSpaceSize(LayoutSize(space, LayoutUnit())); | 331 setSpaceSize(LayoutSize(space, LayoutUnit())); |
| 328 setPhaseX(actualWidth ? actualWidth - fmodf((computedXPosition + lef
t), actualWidth) : 0.0f); | 332 setPhaseX(actualWidth ? LayoutUnit(actualWidth - fmodf((computedXPos
ition + left), actualWidth)) : LayoutUnit()); |
| 329 } else { | 333 } else { |
| 330 backgroundRepeatX = NoRepeatFill; | 334 backgroundRepeatX = NoRepeatFill; |
| 331 } | 335 } |
| 332 } | 336 } |
| 333 if (backgroundRepeatX == NoRepeatFill) { | 337 if (backgroundRepeatX == NoRepeatFill) { |
| 334 LayoutUnit xOffset = fillLayer.backgroundXOrigin() == RightEdge ? availa
bleWidth - computedXPosition : computedXPosition; | 338 LayoutUnit xOffset = fillLayer.backgroundXOrigin() == RightEdge ? availa
bleWidth - computedXPosition : computedXPosition; |
| 335 setNoRepeatX(left + xOffset); | 339 setNoRepeatX(left + xOffset); |
| 336 setSpaceSize(LayoutSize(LayoutUnit(), spaceSize().height())); | 340 setSpaceSize(LayoutSize(LayoutUnit(), spaceSize().height())); |
| 337 } | 341 } |
| 338 | 342 |
| 339 if (backgroundRepeatY == RepeatFill) { | 343 if (backgroundRepeatY == RepeatFill) { |
| 340 LayoutUnit yOffset = fillLayer.backgroundYOrigin() == BottomEdge ? avail
ableHeight - computedYPosition : computedYPosition; | 344 LayoutUnit yOffset = fillLayer.backgroundYOrigin() == BottomEdge ? avail
ableHeight - computedYPosition : computedYPosition; |
| 341 setPhaseY(tileSize().height() ? tileSize().height() - fmodf((yOffset + t
op), tileSize().height()) : 0.0f); | 345 setPhaseY(tileSize().height() ? LayoutUnit(tileSize().height() - fmodf((
yOffset + top), tileSize().height())) |
| 346 : LayoutUnit()); |
| 342 setSpaceSize(LayoutSize(spaceSize().width(), LayoutUnit())); | 347 setSpaceSize(LayoutSize(spaceSize().width(), LayoutUnit())); |
| 343 } else if (backgroundRepeatY == SpaceFill && fillTileSize.height() > LayoutU
nit()) { | 348 } else if (backgroundRepeatY == SpaceFill && fillTileSize.height() > LayoutU
nit()) { |
| 344 LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.height(
), tileSize().height()); | 349 LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.height(
), tileSize().height()); |
| 345 LayoutUnit actualHeight = tileSize().height() + space; | 350 LayoutUnit actualHeight = tileSize().height() + space; |
| 346 | 351 |
| 347 if (space >= LayoutUnit()) { | 352 if (space >= LayoutUnit()) { |
| 348 computedYPosition = roundedMinimumValueForLength(Length(), available
Height); | 353 computedYPosition = roundedMinimumValueForLength(Length(), available
Height); |
| 349 setSpaceSize(LayoutSize(spaceSize().width(), space)); | 354 setSpaceSize(LayoutSize(spaceSize().width(), space)); |
| 350 setPhaseY(actualHeight ? actualHeight - fmodf((computedYPosition + t
op), actualHeight) : 0.0f); | 355 setPhaseY(actualHeight ? LayoutUnit(actualHeight - fmodf((computedYP
osition + top), actualHeight)) : LayoutUnit()); |
| 351 } else { | 356 } else { |
| 352 backgroundRepeatY = NoRepeatFill; | 357 backgroundRepeatY = NoRepeatFill; |
| 353 } | 358 } |
| 354 } | 359 } |
| 355 if (backgroundRepeatY == NoRepeatFill) { | 360 if (backgroundRepeatY == NoRepeatFill) { |
| 356 LayoutUnit yOffset = fillLayer.backgroundYOrigin() == BottomEdge ? avail
ableHeight - computedYPosition : computedYPosition; | 361 LayoutUnit yOffset = fillLayer.backgroundYOrigin() == BottomEdge ? avail
ableHeight - computedYPosition : computedYPosition; |
| 357 setNoRepeatY(top + yOffset); | 362 setNoRepeatY(top + yOffset); |
| 358 setSpaceSize(LayoutSize(spaceSize().width(), LayoutUnit())); | 363 setSpaceSize(LayoutSize(spaceSize().width(), LayoutUnit())); |
| 359 } | 364 } |
| 360 | 365 |
| 361 if (fixedAttachment) | 366 if (fixedAttachment) |
| 362 useFixedAttachment(paintRect.location()); | 367 useFixedAttachment(paintRect.location()); |
| 363 | 368 |
| 364 clip(paintRect); | 369 clip(paintRect); |
| 365 pixelSnapGeometry(); | 370 pixelSnapGeometry(); |
| 366 } | 371 } |
| 367 | 372 |
| 368 } // namespace blink | 373 } // namespace blink |
| OLD | NEW |