Chromium Code Reviews| 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/LayoutTableCell.h" | |
| 11 #include "core/layout/LayoutTableCol.h" | |
| 10 #include "core/layout/LayoutView.h" | 12 #include "core/layout/LayoutView.h" |
| 11 #include "core/layout/compositing/CompositedLayerMapping.h" | 13 #include "core/layout/compositing/CompositedLayerMapping.h" |
| 12 #include "core/paint/PaintLayer.h" | 14 #include "core/paint/PaintLayer.h" |
| 13 #include "platform/LayoutUnit.h" | 15 #include "platform/LayoutUnit.h" |
| 14 #include "platform/geometry/LayoutRect.h" | 16 #include "platform/geometry/LayoutRect.h" |
| 15 | 17 |
| 16 namespace blink { | 18 namespace blink { |
| 17 | 19 |
| 18 namespace { | 20 namespace { |
| 19 | 21 |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 206 m_destRect.move(0, std::max(roundedOffset, 0)); | 208 m_destRect.move(0, std::max(roundedOffset, 0)); |
| 207 setPhaseY(LayoutUnit(-std::min(roundedOffset, 0))); | 209 setPhaseY(LayoutUnit(-std::min(roundedOffset, 0))); |
| 208 m_destRect.setHeight(m_tileSize.height() + std::min(roundedOffset, 0)); | 210 m_destRect.setHeight(m_tileSize.height() + std::min(roundedOffset, 0)); |
| 209 setSpaceSize(LayoutSize(spaceSize().width(), LayoutUnit())); | 211 setSpaceSize(LayoutSize(spaceSize().width(), LayoutUnit())); |
| 210 } | 212 } |
| 211 | 213 |
| 212 void BackgroundImageGeometry::setRepeatX(const FillLayer& fillLayer, | 214 void BackgroundImageGeometry::setRepeatX(const FillLayer& fillLayer, |
| 213 LayoutUnit unsnappedTileWidth, | 215 LayoutUnit unsnappedTileWidth, |
| 214 LayoutUnit snappedAvailableWidth, | 216 LayoutUnit snappedAvailableWidth, |
| 215 LayoutUnit unsnappedAvailableWidth, | 217 LayoutUnit unsnappedAvailableWidth, |
| 216 LayoutUnit extraOffset) { | 218 LayoutUnit extraOffset, |
| 219 LayoutUnit offsetForCell) { | |
| 217 // We would like to identify the phase as a fraction of the image size in the | 220 // We would like to identify the phase as a fraction of the image size in the |
| 218 // absence of snapping, then re-apply it to the snapped values. This is to | 221 // absence of snapping, then re-apply it to the snapped values. This is to |
| 219 // handle large positions. | 222 // handle large positions. |
| 220 if (unsnappedTileWidth) { | 223 if (unsnappedTileWidth) { |
| 221 LayoutUnit computedXPosition = roundedMinimumValueForLength( | 224 LayoutUnit computedXPosition = |
| 222 fillLayer.xPosition(), unsnappedAvailableWidth); | 225 roundedMinimumValueForLength(fillLayer.xPosition(), |
| 226 unsnappedAvailableWidth) - | |
| 227 offsetForCell; | |
| 223 if (fillLayer.backgroundXOrigin() == RightEdge) { | 228 if (fillLayer.backgroundXOrigin() == RightEdge) { |
| 224 float numberOfTilesInPosition = | 229 float numberOfTilesInPosition = |
| 225 (snappedAvailableWidth - computedXPosition + extraOffset).toFloat() / | 230 (snappedAvailableWidth - computedXPosition + extraOffset).toFloat() / |
| 226 unsnappedTileWidth.toFloat(); | 231 unsnappedTileWidth.toFloat(); |
| 227 float fractionalPositionWithinTile = | 232 float fractionalPositionWithinTile = |
| 228 numberOfTilesInPosition - truncf(numberOfTilesInPosition); | 233 numberOfTilesInPosition - truncf(numberOfTilesInPosition); |
| 229 setPhaseX(LayoutUnit( | 234 setPhaseX(LayoutUnit( |
| 230 roundf(fractionalPositionWithinTile * tileSize().width()))); | 235 roundf(fractionalPositionWithinTile * tileSize().width()))); |
| 231 } else { | 236 } else { |
| 232 float numberOfTilesInPosition = | 237 float numberOfTilesInPosition = |
| 233 (computedXPosition + extraOffset).toFloat() / | 238 (computedXPosition + extraOffset).toFloat() / |
| 234 unsnappedTileWidth.toFloat(); | 239 unsnappedTileWidth.toFloat(); |
| 235 float fractionalPositionWithinTile = | 240 float fractionalPositionWithinTile = |
| 236 1.0f - (numberOfTilesInPosition - truncf(numberOfTilesInPosition)); | 241 1.0f - (numberOfTilesInPosition - truncf(numberOfTilesInPosition)); |
| 237 setPhaseX(LayoutUnit( | 242 setPhaseX(LayoutUnit( |
| 238 roundf(fractionalPositionWithinTile * tileSize().width()))); | 243 roundf(fractionalPositionWithinTile * tileSize().width()))); |
| 239 } | 244 } |
| 240 } else { | 245 } else { |
| 241 setPhaseX(LayoutUnit()); | 246 setPhaseX(LayoutUnit()); |
| 242 } | 247 } |
| 243 setSpaceSize(LayoutSize(LayoutUnit(), spaceSize().height())); | 248 setSpaceSize(LayoutSize(LayoutUnit(), spaceSize().height())); |
| 244 } | 249 } |
| 245 | 250 |
| 246 void BackgroundImageGeometry::setRepeatY(const FillLayer& fillLayer, | 251 void BackgroundImageGeometry::setRepeatY(const FillLayer& fillLayer, |
| 247 LayoutUnit unsnappedTileHeight, | 252 LayoutUnit unsnappedTileHeight, |
| 248 LayoutUnit snappedAvailableHeight, | 253 LayoutUnit snappedAvailableHeight, |
| 249 LayoutUnit unsnappedAvailableHeight, | 254 LayoutUnit unsnappedAvailableHeight, |
| 250 LayoutUnit extraOffset) { | 255 LayoutUnit extraOffset, |
| 256 LayoutUnit offsetForCell) { | |
| 251 // We would like to identify the phase as a fraction of the image size in the | 257 // We would like to identify the phase as a fraction of the image size in the |
| 252 // absence of snapping, then re-apply it to the snapped values. This is to | 258 // absence of snapping, then re-apply it to the snapped values. This is to |
| 253 // handle large positions. | 259 // handle large positions. |
| 254 if (unsnappedTileHeight) { | 260 if (unsnappedTileHeight) { |
| 255 LayoutUnit computedYPosition = roundedMinimumValueForLength( | 261 LayoutUnit computedYPosition = |
| 256 fillLayer.yPosition(), unsnappedAvailableHeight); | 262 roundedMinimumValueForLength(fillLayer.yPosition(), |
| 263 unsnappedAvailableHeight) - | |
| 264 offsetForCell; | |
| 257 if (fillLayer.backgroundYOrigin() == BottomEdge) { | 265 if (fillLayer.backgroundYOrigin() == BottomEdge) { |
| 258 float numberOfTilesInPosition = | 266 float numberOfTilesInPosition = |
| 259 (snappedAvailableHeight - computedYPosition + extraOffset).toFloat() / | 267 (snappedAvailableHeight - computedYPosition + extraOffset).toFloat() / |
| 260 unsnappedTileHeight.toFloat(); | 268 unsnappedTileHeight.toFloat(); |
| 261 float fractionalPositionWithinTile = | 269 float fractionalPositionWithinTile = |
| 262 numberOfTilesInPosition - truncf(numberOfTilesInPosition); | 270 numberOfTilesInPosition - truncf(numberOfTilesInPosition); |
| 263 setPhaseY(LayoutUnit( | 271 setPhaseY(LayoutUnit( |
| 264 roundf(fractionalPositionWithinTile * tileSize().height()))); | 272 roundf(fractionalPositionWithinTile * tileSize().height()))); |
| 265 } else { | 273 } else { |
| 266 float numberOfTilesInPosition = | 274 float numberOfTilesInPosition = |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 306 } | 314 } |
| 307 | 315 |
| 308 void BackgroundImageGeometry::useFixedAttachment( | 316 void BackgroundImageGeometry::useFixedAttachment( |
| 309 const LayoutPoint& attachmentPoint) { | 317 const LayoutPoint& attachmentPoint) { |
| 310 LayoutPoint alignedPoint = attachmentPoint; | 318 LayoutPoint alignedPoint = attachmentPoint; |
| 311 m_phase.move(std::max(alignedPoint.x() - m_destRect.x(), LayoutUnit()), | 319 m_phase.move(std::max(alignedPoint.x() - m_destRect.x(), LayoutUnit()), |
| 312 std::max(alignedPoint.y() - m_destRect.y(), LayoutUnit())); | 320 std::max(alignedPoint.y() - m_destRect.y(), LayoutUnit())); |
| 313 setPhase(LayoutPoint(roundedIntPoint(m_phase))); | 321 setPhase(LayoutPoint(roundedIntPoint(m_phase))); |
| 314 } | 322 } |
| 315 | 323 |
| 324 enum ColumnGroupDirection { ColumnGroupStart, ColumnGroupEnd }; | |
| 325 | |
| 326 static void expandToTableColumnGroup(const LayoutTableCell& cell, | |
| 327 const LayoutTableCol& columnGroup, | |
| 328 LayoutUnit& value, | |
| 329 ColumnGroupDirection columnDirection) { | |
| 330 auto siblingCell = columnDirection == ColumnGroupStart | |
| 331 ? &LayoutTableCell::previousCell | |
| 332 : &LayoutTableCell::nextCell; | |
| 333 for (const auto* sibling = (cell.*siblingCell)(); sibling; | |
| 334 sibling = (sibling->*siblingCell)()) { | |
| 335 if (cell.table() | |
| 336 ->colElementAtAbsoluteColumn(sibling->absoluteColumnIndex()) | |
| 337 .innermostColOrColGroup() | |
| 338 ->enclosingColumnGroup() != columnGroup) | |
| 339 break; | |
| 340 value += sibling->size().width(); | |
| 341 } | |
| 342 } | |
| 343 | |
| 344 LayoutPoint BackgroundImageGeometry::getOffsetForCell( | |
| 345 const LayoutTableCell& cell, | |
| 346 const LayoutBox& positioningBox) { | |
| 347 LayoutSize borderSpacing = LayoutSize(cell.table()->hBorderSpacing(), | |
| 348 cell.table()->vBorderSpacing()); | |
| 349 if (positioningBox.isTableSection()) | |
| 350 return cell.location() - borderSpacing; | |
| 351 if (positioningBox.isTableRow()) { | |
| 352 return LayoutPoint(cell.location().x(), LayoutUnit()) - | |
| 353 LayoutSize(borderSpacing.width(), LayoutUnit()); | |
| 354 } | |
| 355 | |
| 356 LayoutRect sectionsRect(LayoutPoint(), cell.table()->size()); | |
| 357 cell.table()->subtractCaptionRect(sectionsRect); | |
| 358 LayoutUnit heightOfCaptions = | |
| 359 cell.table()->size().height() - sectionsRect.height(); | |
| 360 LayoutPoint offsetInBackground = LayoutPoint( | |
| 361 LayoutUnit(), (cell.section()->location().y() - | |
| 362 cell.table()->borderBefore() - heightOfCaptions) + | |
| 363 cell.location().y()); | |
| 364 | |
| 365 DCHECK(positioningBox.isLayoutTableCol()); | |
| 366 if (toLayoutTableCol(positioningBox).isTableColumn()) { | |
| 367 return offsetInBackground - | |
| 368 LayoutSize(LayoutUnit(), borderSpacing.height()); | |
| 369 } | |
| 370 | |
| 371 DCHECK(toLayoutTableCol(positioningBox).isTableColumnGroup()); | |
| 372 LayoutUnit offset = offsetInBackground.x(); | |
| 373 expandToTableColumnGroup(cell, toLayoutTableCol(positioningBox), offset, | |
| 374 ColumnGroupStart); | |
| 375 offsetInBackground.move(offset, LayoutUnit()); | |
| 376 return offsetInBackground - LayoutSize(LayoutUnit(), borderSpacing.height()); | |
| 377 } | |
| 378 | |
| 379 LayoutSize BackgroundImageGeometry::getBackgroundObjectDimensions( | |
| 380 const LayoutTableCell& cell, | |
| 381 const LayoutBox& positioningBox) { | |
| 382 LayoutSize borderSpacing = LayoutSize(cell.table()->hBorderSpacing(), | |
| 383 cell.table()->vBorderSpacing()); | |
| 384 if (positioningBox.isTableSection()) | |
| 385 return positioningBox.size() - borderSpacing - borderSpacing; | |
| 386 | |
| 387 if (positioningBox.isTableRow()) { | |
| 388 return positioningBox.size() - | |
| 389 LayoutSize(borderSpacing.width(), LayoutUnit()) - | |
| 390 LayoutSize(borderSpacing.width(), LayoutUnit()); | |
| 391 } | |
| 392 | |
| 393 DCHECK(positioningBox.isLayoutTableCol()); | |
| 394 LayoutRect sectionsRect(LayoutPoint(), cell.table()->size()); | |
| 395 cell.table()->subtractCaptionRect(sectionsRect); | |
| 396 LayoutUnit columnHeight = sectionsRect.height() - | |
| 397 cell.table()->borderBefore() - | |
| 398 borderSpacing.height() - borderSpacing.height(); | |
| 399 if (toLayoutTableCol(positioningBox).isTableColumn()) | |
| 400 return LayoutSize(cell.size().width(), columnHeight); | |
| 401 | |
| 402 DCHECK(toLayoutTableCol(positioningBox).isTableColumnGroup()); | |
| 403 LayoutUnit width = cell.size().width(); | |
| 404 expandToTableColumnGroup(cell, toLayoutTableCol(positioningBox), width, | |
| 405 ColumnGroupStart); | |
| 406 expandToTableColumnGroup(cell, toLayoutTableCol(positioningBox), width, | |
| 407 ColumnGroupEnd); | |
| 408 | |
| 409 return LayoutSize(width, columnHeight); | |
| 410 } | |
| 411 | |
| 316 void BackgroundImageGeometry::calculate( | 412 void BackgroundImageGeometry::calculate( |
| 317 const LayoutBoxModelObject& obj, | 413 const LayoutBoxModelObject& obj, |
| 414 const LayoutObject* backgroundObject, | |
| 318 const LayoutBoxModelObject* paintContainer, | 415 const LayoutBoxModelObject* paintContainer, |
| 319 const GlobalPaintFlags globalPaintFlags, | 416 const GlobalPaintFlags globalPaintFlags, |
| 320 const FillLayer& fillLayer, | 417 const FillLayer& fillLayer, |
| 321 const LayoutRect& paintRect) { | 418 const LayoutRect& paintRect) { |
| 322 LayoutUnit left; | 419 LayoutUnit left; |
| 323 LayoutUnit top; | 420 LayoutUnit top; |
| 324 LayoutSize positioningAreaSize; | 421 LayoutSize positioningAreaSize; |
| 325 bool isLayoutView = obj.isLayoutView(); | 422 bool isLayoutView = obj.isLayoutView(); |
| 326 const LayoutBox* rootBox = nullptr; | 423 const LayoutBox* rootBox = nullptr; |
| 327 if (isLayoutView) { | 424 if (isLayoutView) { |
| 328 // It is only possible reach here when root element has a box. | 425 // It is only possible reach here when root element has a box. |
| 329 Element* documentElement = obj.document().documentElement(); | 426 Element* documentElement = obj.document().documentElement(); |
| 330 DCHECK(documentElement); | 427 DCHECK(documentElement); |
| 331 DCHECK(documentElement->layoutObject()); | 428 DCHECK(documentElement->layoutObject()); |
| 332 DCHECK(documentElement->layoutObject()->isBox()); | 429 DCHECK(documentElement->layoutObject()->isBox()); |
| 333 rootBox = toLayoutBox(documentElement->layoutObject()); | 430 rootBox = toLayoutBox(documentElement->layoutObject()); |
| 334 } | 431 } |
| 432 | |
| 433 bool cellUsingContainerBackground = | |
| 434 obj.isTableCell() && backgroundObject && !backgroundObject->isTableCell(); | |
| 335 const LayoutBoxModelObject& positioningBox = | 435 const LayoutBoxModelObject& positioningBox = |
| 336 isLayoutView ? static_cast<const LayoutBoxModelObject&>(*rootBox) : obj; | 436 isLayoutView |
| 337 | 437 ? static_cast<const LayoutBoxModelObject&>(*rootBox) |
| 438 : cellUsingContainerBackground | |
| 439 ? static_cast<const LayoutBoxModelObject&>(*backgroundObject) | |
| 440 : obj; | |
|
Xianzhu
2017/01/17 18:21:19
I found why toLayoutBoxModelObject for the first o
| |
| 441 LayoutPoint offsetInBackground = | |
| 442 cellUsingContainerBackground | |
| 443 ? getOffsetForCell(toLayoutTableCell(obj), | |
| 444 toLayoutBox(positioningBox)) | |
| 445 : LayoutPoint(); | |
| 338 // Determine the background positioning area and set destRect to the | 446 // Determine the background positioning area and set destRect to the |
| 339 // background painting area. destRect will be adjusted later if the | 447 // background painting area. destRect will be adjusted later if the |
| 340 // background is non-repeating. | 448 // background is non-repeating. |
| 341 // FIXME: transforms spec says that fixed backgrounds behave like scroll | 449 // FIXME: transforms spec says that fixed backgrounds behave like scroll |
| 342 // inside transforms. | 450 // inside transforms. |
| 343 bool fixedAttachment = fillLayer.attachment() == FixedBackgroundAttachment; | 451 bool fixedAttachment = fillLayer.attachment() == FixedBackgroundAttachment; |
| 344 | 452 |
| 345 if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) { | 453 if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) { |
| 346 // As a side effect of an optimization to blit on scroll, we do not honor | 454 // As a side effect of an optimization to blit on scroll, we do not honor |
| 347 // the CSS property "background-attachment: fixed" because it may result in | 455 // the CSS property "background-attachment: fixed" because it may result in |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 368 bottom += positioningBox.paddingBottom(); | 476 bottom += positioningBox.paddingBottom(); |
| 369 } | 477 } |
| 370 } | 478 } |
| 371 | 479 |
| 372 if (isLayoutView) { | 480 if (isLayoutView) { |
| 373 // The background of the box generated by the root element covers the | 481 // The background of the box generated by the root element covers the |
| 374 // entire canvas and will be painted by the view object, but the we should | 482 // entire canvas and will be painted by the view object, but the we should |
| 375 // still use the root element box for positioning. | 483 // still use the root element box for positioning. |
| 376 positioningAreaSize = | 484 positioningAreaSize = |
| 377 rootBox->size() - LayoutSize(left + right, top + bottom), | 485 rootBox->size() - LayoutSize(left + right, top + bottom), |
| 378 rootBox->location(); | 486 rootBox->location(); |
|
Xianzhu
2017/01/17 18:21:19
Not your fault, can you fix the above two lines?
| |
| 379 // The input paint rect is specified in root element local coordinate | 487 // The input paint rect is specified in root element local coordinate |
| 380 // (i.e. a transform is applied on the context for painting), and is | 488 // (i.e. a transform is applied on the context for painting), and is |
| 381 // expanded to cover the whole canvas. Since left/top is relative to the | 489 // expanded to cover the whole canvas. Since left/top is relative to the |
| 382 // paint rect, we need to offset them back. | 490 // paint rect, we need to offset them back. |
| 383 left -= paintRect.x(); | 491 left -= paintRect.x(); |
| 384 top -= paintRect.y(); | 492 top -= paintRect.y(); |
| 385 } else { | 493 } else { |
| 386 positioningAreaSize = | 494 positioningAreaSize = |
| 387 paintRect.size() - LayoutSize(left + right, top + bottom); | 495 (cellUsingContainerBackground |
| 496 ? getBackgroundObjectDimensions(toLayoutTableCell(obj), | |
| 497 toLayoutBox(positioningBox)) | |
| 498 : paintRect.size()) - | |
| 499 LayoutSize(left + right, top + bottom); | |
| 388 } | 500 } |
| 389 } else { | 501 } else { |
| 390 setHasNonLocalGeometry(); | 502 setHasNonLocalGeometry(); |
| 391 | 503 |
| 392 LayoutRect viewportRect = obj.viewRect(); | 504 LayoutRect viewportRect = obj.viewRect(); |
| 393 if (fixedBackgroundPaintsInLocalCoordinates(obj, globalPaintFlags)) { | 505 if (fixedBackgroundPaintsInLocalCoordinates(obj, globalPaintFlags)) { |
| 394 viewportRect.setLocation(LayoutPoint()); | 506 viewportRect.setLocation(LayoutPoint()); |
| 395 } else { | 507 } else { |
| 396 if (FrameView* frameView = obj.view()->frameView()) | 508 if (FrameView* frameView = obj.view()->frameView()) |
| 397 viewportRect.setLocation(IntPoint(frameView->scrollOffsetInt())); | 509 viewportRect.setLocation(IntPoint(frameView->scrollOffsetInt())); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 423 LayoutUnit unsnappedAvailableHeight = | 535 LayoutUnit unsnappedAvailableHeight = |
| 424 positioningAreaSize.height() - fillTileSize.height(); | 536 positioningAreaSize.height() - fillTileSize.height(); |
| 425 positioningAreaSize = | 537 positioningAreaSize = |
| 426 LayoutSize(snapSizeToPixel(positioningAreaSize.width(), m_destRect.x()), | 538 LayoutSize(snapSizeToPixel(positioningAreaSize.width(), m_destRect.x()), |
| 427 snapSizeToPixel(positioningAreaSize.height(), m_destRect.y())); | 539 snapSizeToPixel(positioningAreaSize.height(), m_destRect.y())); |
| 428 LayoutUnit availableWidth = positioningAreaSize.width() - tileSize().width(); | 540 LayoutUnit availableWidth = positioningAreaSize.width() - tileSize().width(); |
| 429 LayoutUnit availableHeight = | 541 LayoutUnit availableHeight = |
| 430 positioningAreaSize.height() - tileSize().height(); | 542 positioningAreaSize.height() - tileSize().height(); |
| 431 | 543 |
| 432 LayoutUnit computedXPosition = | 544 LayoutUnit computedXPosition = |
| 433 roundedMinimumValueForLength(fillLayer.xPosition(), availableWidth); | 545 roundedMinimumValueForLength(fillLayer.xPosition(), availableWidth) - |
| 546 offsetInBackground.x(); | |
| 434 if (backgroundRepeatX == RoundFill && | 547 if (backgroundRepeatX == RoundFill && |
| 435 positioningAreaSize.width() > LayoutUnit() && | 548 positioningAreaSize.width() > LayoutUnit() && |
| 436 fillTileSize.width() > LayoutUnit()) { | 549 fillTileSize.width() > LayoutUnit()) { |
| 437 int nrTiles = std::max( | 550 int nrTiles = std::max( |
| 438 1, roundToInt(positioningAreaSize.width() / fillTileSize.width())); | 551 1, roundToInt(positioningAreaSize.width() / fillTileSize.width())); |
| 439 LayoutUnit roundedWidth = positioningAreaSize.width() / nrTiles; | 552 LayoutUnit roundedWidth = positioningAreaSize.width() / nrTiles; |
| 440 | 553 |
| 441 // Maintain aspect ratio if background-size: auto is set | 554 // Maintain aspect ratio if background-size: auto is set |
| 442 if (fillLayer.size().size.height().isAuto() && | 555 if (fillLayer.size().size.height().isAuto() && |
| 443 backgroundRepeatY != RoundFill) { | 556 backgroundRepeatY != RoundFill) { |
| 444 fillTileSize.setHeight(fillTileSize.height() * roundedWidth / | 557 fillTileSize.setHeight(fillTileSize.height() * roundedWidth / |
| 445 fillTileSize.width()); | 558 fillTileSize.width()); |
| 446 } | 559 } |
| 447 fillTileSize.setWidth(roundedWidth); | 560 fillTileSize.setWidth(roundedWidth); |
| 448 | 561 |
| 449 setTileSize(applySubPixelHeuristicToImageSize(fillTileSize, m_destRect)); | 562 setTileSize(applySubPixelHeuristicToImageSize(fillTileSize, m_destRect)); |
| 450 setPhaseX(tileSize().width() | 563 setPhaseX(tileSize().width() |
| 451 ? LayoutUnit(roundf( | 564 ? LayoutUnit(roundf( |
| 452 tileSize().width() - | 565 tileSize().width() - |
| 453 fmodf((computedXPosition + left), tileSize().width()))) | 566 fmodf((computedXPosition + left), tileSize().width()))) |
| 454 : LayoutUnit()); | 567 : LayoutUnit()); |
| 455 setSpaceSize(LayoutSize()); | 568 setSpaceSize(LayoutSize()); |
| 456 } | 569 } |
| 457 | 570 |
| 458 LayoutUnit computedYPosition = | 571 LayoutUnit computedYPosition = |
| 459 roundedMinimumValueForLength(fillLayer.yPosition(), availableHeight); | 572 roundedMinimumValueForLength(fillLayer.yPosition(), availableHeight) - |
| 573 offsetInBackground.y(); | |
| 460 if (backgroundRepeatY == RoundFill && | 574 if (backgroundRepeatY == RoundFill && |
| 461 positioningAreaSize.height() > LayoutUnit() && | 575 positioningAreaSize.height() > LayoutUnit() && |
| 462 fillTileSize.height() > LayoutUnit()) { | 576 fillTileSize.height() > LayoutUnit()) { |
| 463 int nrTiles = std::max( | 577 int nrTiles = std::max( |
| 464 1, roundToInt(positioningAreaSize.height() / fillTileSize.height())); | 578 1, roundToInt(positioningAreaSize.height() / fillTileSize.height())); |
| 465 LayoutUnit roundedHeight = positioningAreaSize.height() / nrTiles; | 579 LayoutUnit roundedHeight = positioningAreaSize.height() / nrTiles; |
| 466 // Maintain aspect ratio if background-size: auto is set | 580 // Maintain aspect ratio if background-size: auto is set |
| 467 if (fillLayer.size().size.width().isAuto() && | 581 if (fillLayer.size().size.width().isAuto() && |
| 468 backgroundRepeatX != RoundFill) { | 582 backgroundRepeatX != RoundFill) { |
| 469 fillTileSize.setWidth(fillTileSize.width() * roundedHeight / | 583 fillTileSize.setWidth(fillTileSize.width() * roundedHeight / |
| 470 fillTileSize.height()); | 584 fillTileSize.height()); |
| 471 } | 585 } |
| 472 fillTileSize.setHeight(roundedHeight); | 586 fillTileSize.setHeight(roundedHeight); |
| 473 | 587 |
| 474 setTileSize(applySubPixelHeuristicToImageSize(fillTileSize, m_destRect)); | 588 setTileSize(applySubPixelHeuristicToImageSize(fillTileSize, m_destRect)); |
| 475 setPhaseY(tileSize().height() | 589 setPhaseY(tileSize().height() |
| 476 ? LayoutUnit(roundf( | 590 ? LayoutUnit(roundf( |
| 477 tileSize().height() - | 591 tileSize().height() - |
| 478 fmodf((computedYPosition + top), tileSize().height()))) | 592 fmodf((computedYPosition + top), tileSize().height()))) |
| 479 : LayoutUnit()); | 593 : LayoutUnit()); |
| 480 setSpaceSize(LayoutSize()); | 594 setSpaceSize(LayoutSize()); |
| 481 } | 595 } |
| 482 | 596 |
| 483 if (backgroundRepeatX == RepeatFill) { | 597 if (backgroundRepeatX == RepeatFill) { |
| 484 setRepeatX(fillLayer, fillTileSize.width(), availableWidth, | 598 setRepeatX(fillLayer, fillTileSize.width(), availableWidth, |
| 485 unsnappedAvailableWidth, left); | 599 unsnappedAvailableWidth, left, offsetInBackground.x()); |
| 486 } else if (backgroundRepeatX == SpaceFill && | 600 } else if (backgroundRepeatX == SpaceFill && |
| 487 tileSize().width() > LayoutUnit()) { | 601 tileSize().width() > LayoutUnit()) { |
| 488 LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.width(), | 602 LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.width(), |
| 489 tileSize().width()); | 603 tileSize().width()); |
| 490 if (space >= LayoutUnit()) | 604 if (space >= LayoutUnit()) |
| 491 setSpaceX(space, availableWidth, left); | 605 setSpaceX(space, availableWidth, left); |
| 492 else | 606 else |
| 493 backgroundRepeatX = NoRepeatFill; | 607 backgroundRepeatX = NoRepeatFill; |
| 494 } | 608 } |
| 495 if (backgroundRepeatX == NoRepeatFill) { | 609 if (backgroundRepeatX == NoRepeatFill) { |
| 496 LayoutUnit xOffset = fillLayer.backgroundXOrigin() == RightEdge | 610 LayoutUnit xOffset = fillLayer.backgroundXOrigin() == RightEdge |
| 497 ? availableWidth - computedXPosition | 611 ? availableWidth - computedXPosition |
| 498 : computedXPosition; | 612 : computedXPosition; |
| 499 setNoRepeatX(left + xOffset); | 613 setNoRepeatX(left + xOffset); |
| 614 if (offsetInBackground.x() > tileSize().width()) | |
| 615 setDestRect(LayoutRect()); | |
| 500 } | 616 } |
| 501 | 617 |
| 502 if (backgroundRepeatY == RepeatFill) { | 618 if (backgroundRepeatY == RepeatFill) { |
| 503 setRepeatY(fillLayer, fillTileSize.height(), availableHeight, | 619 setRepeatY(fillLayer, fillTileSize.height(), availableHeight, |
| 504 unsnappedAvailableHeight, top); | 620 unsnappedAvailableHeight, top, offsetInBackground.y()); |
| 505 } else if (backgroundRepeatY == SpaceFill && | 621 } else if (backgroundRepeatY == SpaceFill && |
| 506 tileSize().height() > LayoutUnit()) { | 622 tileSize().height() > LayoutUnit()) { |
| 507 LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.height(), | 623 LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.height(), |
| 508 tileSize().height()); | 624 tileSize().height()); |
| 509 if (space >= LayoutUnit()) | 625 if (space >= LayoutUnit()) |
| 510 setSpaceY(space, availableHeight, top); | 626 setSpaceY(space, availableHeight, top); |
| 511 else | 627 else |
| 512 backgroundRepeatY = NoRepeatFill; | 628 backgroundRepeatY = NoRepeatFill; |
| 513 } | 629 } |
| 514 if (backgroundRepeatY == NoRepeatFill) { | 630 if (backgroundRepeatY == NoRepeatFill) { |
| 515 LayoutUnit yOffset = fillLayer.backgroundYOrigin() == BottomEdge | 631 LayoutUnit yOffset = fillLayer.backgroundYOrigin() == BottomEdge |
| 516 ? availableHeight - computedYPosition | 632 ? availableHeight - computedYPosition |
| 517 : computedYPosition; | 633 : computedYPosition; |
| 518 setNoRepeatY(top + yOffset); | 634 setNoRepeatY(top + yOffset); |
| 635 if (offsetInBackground.y() > tileSize().height()) | |
| 636 setDestRect(LayoutRect()); | |
| 519 } | 637 } |
| 520 | 638 |
| 521 if (fixedAttachment) | 639 if (fixedAttachment) |
| 522 useFixedAttachment(paintRect.location()); | 640 useFixedAttachment(paintRect.location()); |
| 523 | 641 |
| 524 // Clip the final output rect to the paint rect | 642 // Clip the final output rect to the paint rect |
| 525 m_destRect.intersect(paintRect); | 643 m_destRect.intersect(paintRect); |
| 526 | 644 |
| 527 // Snap as-yet unsnapped values. | 645 // Snap as-yet unsnapped values. |
| 528 setDestRect(LayoutRect(pixelSnappedIntRect(m_destRect))); | 646 setDestRect(LayoutRect(pixelSnappedIntRect(m_destRect))); |
| 529 } | 647 } |
| 530 | 648 |
| 531 } // namespace blink | 649 } // namespace blink |
| OLD | NEW |