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 |