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 "config.h" | 5 #include "config.h" |
| 6 #include "core/paint/BackgroundImageGeometry.h" | 6 #include "core/paint/BackgroundImageGeometry.h" |
| 7 | 7 |
| 8 #include "core/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
| 9 #include "core/layout/LayoutBox.h" | 9 #include "core/layout/LayoutBox.h" |
| 10 #include "core/layout/LayoutBoxModelObject.h" | 10 #include "core/layout/LayoutBoxModelObject.h" |
| 11 #include "core/layout/LayoutView.h" | 11 #include "core/layout/LayoutView.h" |
| 12 #include "core/layout/compositing/CompositedLayerMapping.h" | 12 #include "core/layout/compositing/CompositedLayerMapping.h" |
| 13 #include "core/paint/PaintLayer.h" | 13 #include "core/paint/PaintLayer.h" |
| 14 #include "platform/LayoutUnit.h" | 14 #include "platform/LayoutUnit.h" |
| 15 #include "platform/geometry/LayoutRect.h" | 15 #include "platform/geometry/LayoutRect.h" |
| 16 | 16 |
| 17 namespace blink { | 17 namespace blink { |
| 18 | 18 |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 inline void applySubPixelHeuristicForTileSize(LayoutSize& tileSize, const IntSiz e& positioningAreaSize) | |
| 22 { | |
| 23 tileSize.setWidth(positioningAreaSize.width() - tileSize.width() <= 1 ? tile Size.width().ceil() : tileSize.width().floor()); | |
| 24 tileSize.setHeight(positioningAreaSize.height() - tileSize.height() <= 1 ? t ileSize.height().ceil() : tileSize.height().floor()); | |
| 25 } | |
| 26 | |
| 27 // Return the amount of space to leave between image tiles for the background-re peat: space property. | 21 // Return the amount of space to leave between image tiles for the background-re peat: space property. |
| 28 inline int getSpaceBetweenImageTiles(int areaSize, int tileSize) | 22 inline LayoutUnit getSpaceBetweenImageTiles(LayoutUnit areaSize, LayoutUnit tile Size) |
| 29 { | 23 { |
| 30 int numberOfTiles = areaSize / tileSize; | 24 int numberOfTiles = areaSize / tileSize; |
| 31 int space = -1; | 25 LayoutUnit space = -1; |
| 32 | 26 |
| 33 if (numberOfTiles > 1) { | 27 if (numberOfTiles > 1) { |
| 34 // Spec doesn't specify rounding, so use the same method as for backgrou nd-repeat: round. | 28 // Spec doesn't specify rounding, so use the same method as for backgrou nd-repeat: round. |
| 35 space = lroundf((areaSize - numberOfTiles * tileSize) / (float)(numberOf Tiles - 1)); | 29 space = (areaSize - numberOfTiles * tileSize) / (numberOfTiles - 1); |
| 36 } | 30 } |
| 37 | 31 |
| 38 return space; | 32 return space; |
| 39 } | 33 } |
| 40 | 34 |
| 41 bool fixedBackgroundPaintsInLocalCoordinates(const LayoutObject& obj, const Glob alPaintFlags globalPaintFlags) | 35 bool fixedBackgroundPaintsInLocalCoordinates(const LayoutObject& obj, const Glob alPaintFlags globalPaintFlags) |
| 42 { | 36 { |
| 43 if (!obj.isLayoutView()) | 37 if (!obj.isLayoutView()) |
| 44 return false; | 38 return false; |
| 45 | 39 |
| 46 const LayoutView& view = toLayoutView(obj); | 40 const LayoutView& view = toLayoutView(obj); |
| 47 | 41 |
| 48 if (globalPaintFlags & GlobalPaintFlattenCompositingLayers) | 42 if (globalPaintFlags & GlobalPaintFlattenCompositingLayers) |
| 49 return false; | 43 return false; |
| 50 | 44 |
| 51 PaintLayer* rootLayer = view.layer(); | 45 PaintLayer* rootLayer = view.layer(); |
| 52 if (!rootLayer || rootLayer->compositingState() == NotComposited) | 46 if (!rootLayer || rootLayer->compositingState() == NotComposited) |
| 53 return false; | 47 return false; |
| 54 | 48 |
| 55 return rootLayer->compositedLayerMapping()->backgroundLayerPaintsFixedRootBa ckground(); | 49 return rootLayer->compositedLayerMapping()->backgroundLayerPaintsFixedRootBa ckground(); |
| 56 } | 50 } |
| 57 | 51 |
| 58 IntSize calculateFillTileSize(const LayoutBoxModelObject& obj, const FillLayer& fillLayer, const IntSize& positioningAreaSize) | 52 LayoutSize calculateFillTileSize(const LayoutBoxModelObject& obj, const FillLaye r& fillLayer, const LayoutSize& positioningAreaSize) |
| 59 { | 53 { |
| 60 StyleImage* image = fillLayer.image(); | 54 StyleImage* image = fillLayer.image(); |
| 61 EFillSizeType type = fillLayer.size().type; | 55 EFillSizeType type = fillLayer.size().type; |
| 62 | 56 |
| 63 IntSize imageIntrinsicSize = obj.calculateImageIntrinsicDimensions(image, po sitioningAreaSize, LayoutBoxModelObject::ScaleByEffectiveZoom); | 57 LayoutSize imageIntrinsicSize = obj.calculateImageIntrinsicDimensions(image, positioningAreaSize, LayoutBoxModelObject::ScaleByEffectiveZoom); |
| 64 imageIntrinsicSize.scale(1 / image->imageScaleFactor(), 1 / image->imageScal eFactor()); | 58 imageIntrinsicSize.scale(1 / image->imageScaleFactor(), 1 / image->imageScal eFactor()); |
| 65 switch (type) { | 59 switch (type) { |
| 66 case SizeLength: { | 60 case SizeLength: { |
| 67 LayoutSize tileSize(positioningAreaSize); | 61 LayoutSize tileSize(positioningAreaSize); |
| 68 | 62 |
| 69 Length layerWidth = fillLayer.size().size.width(); | 63 Length layerWidth = fillLayer.size().size.width(); |
| 70 Length layerHeight = fillLayer.size().size.height(); | 64 Length layerHeight = fillLayer.size().size.height(); |
| 71 | 65 |
| 72 if (layerWidth.isFixed()) | 66 if (layerWidth.isFixed()) |
| 73 tileSize.setWidth(layerWidth.value()); | 67 tileSize.setWidth(layerWidth.value()); |
| 74 else if (layerWidth.hasPercent()) | 68 else if (layerWidth.hasPercent()) |
| 75 tileSize.setWidth(valueForLength(layerWidth, positioningAreaSize.wid th())); | 69 tileSize.setWidth(valueForLength(layerWidth, positioningAreaSize.wid th())); |
| 76 | 70 |
| 77 if (layerHeight.isFixed()) | 71 if (layerHeight.isFixed()) |
| 78 tileSize.setHeight(layerHeight.value()); | 72 tileSize.setHeight(layerHeight.value()); |
| 79 else if (layerHeight.hasPercent()) | 73 else if (layerHeight.hasPercent()) |
| 80 tileSize.setHeight(valueForLength(layerHeight, positioningAreaSize.h eight())); | 74 tileSize.setHeight(valueForLength(layerHeight, positioningAreaSize.h eight())); |
| 81 | 75 |
| 82 applySubPixelHeuristicForTileSize(tileSize, positioningAreaSize); | |
| 83 | |
| 84 // If one of the values is auto we have to use the appropriate | 76 // If one of the values is auto we have to use the appropriate |
| 85 // scale to maintain our aspect ratio. | 77 // scale to maintain our aspect ratio. |
| 86 if (layerWidth.isAuto() && !layerHeight.isAuto()) { | 78 if (layerWidth.isAuto() && !layerHeight.isAuto()) { |
| 87 if (imageIntrinsicSize.height()) { | 79 if (imageIntrinsicSize.height()) { |
| 88 LayoutUnit adjustedWidth = imageIntrinsicSize.width() * tileSize .height() / imageIntrinsicSize.height(); | 80 LayoutUnit adjustedWidth = imageIntrinsicSize.width() * tileSize .height() / imageIntrinsicSize.height(); |
| 89 if (imageIntrinsicSize.width() >= 1 && adjustedWidth < 1) | 81 if (imageIntrinsicSize.width() >= 1 && adjustedWidth < 1) |
| 90 adjustedWidth = 1; | 82 adjustedWidth = 1; |
| 91 tileSize.setWidth(adjustedWidth); | 83 tileSize.setWidth(adjustedWidth); |
| 92 } | 84 } |
| 93 } else if (!layerWidth.isAuto() && layerHeight.isAuto()) { | 85 } else if (!layerWidth.isAuto() && layerHeight.isAuto()) { |
| 94 if (imageIntrinsicSize.width()) { | 86 if (imageIntrinsicSize.width()) { |
| 95 LayoutUnit adjustedHeight = imageIntrinsicSize.height() * tileSi ze.width() / imageIntrinsicSize.width(); | 87 LayoutUnit adjustedHeight = imageIntrinsicSize.height() * tileSi ze.width() / imageIntrinsicSize.width(); |
| 96 if (imageIntrinsicSize.height() >= 1 && adjustedHeight < 1) | 88 if (imageIntrinsicSize.height() >= 1 && adjustedHeight < 1) |
| 97 adjustedHeight = 1; | 89 adjustedHeight = 1; |
| 98 tileSize.setHeight(adjustedHeight); | 90 tileSize.setHeight(adjustedHeight); |
| 99 } | 91 } |
| 100 } else if (layerWidth.isAuto() && layerHeight.isAuto()) { | 92 } else if (layerWidth.isAuto() && layerHeight.isAuto()) { |
| 101 // If both width and height are auto, use the image's intrinsic size . | 93 // If both width and height are auto, use the image's intrinsic size . |
| 102 tileSize = LayoutSize(imageIntrinsicSize); | 94 tileSize = imageIntrinsicSize; |
| 103 } | 95 } |
| 104 | 96 |
| 105 tileSize.clampNegativeToZero(); | 97 tileSize.clampNegativeToZero(); |
| 106 return flooredIntSize(tileSize); | 98 return tileSize; |
| 107 } | 99 } |
| 108 case SizeNone: { | 100 case SizeNone: { |
| 109 // If both values are 'auto' then the intrinsic width and/or height of t he image should be used, if any. | 101 // If both values are 'auto' then the intrinsic width and/or height of t he image should be used, if any. |
| 110 if (!imageIntrinsicSize.isEmpty()) | 102 if (!imageIntrinsicSize.isEmpty()) |
| 111 return imageIntrinsicSize; | 103 return imageIntrinsicSize; |
| 112 | 104 |
| 113 // If the image has neither an intrinsic width nor an intrinsic height, its size is determined as for 'contain'. | 105 // If the image has neither an intrinsic width nor an intrinsic height, its size is determined as for 'contain'. |
| 114 type = Contain; | 106 type = Contain; |
| 115 } | 107 } |
| 116 case Contain: | 108 case Contain: |
| 117 case Cover: { | 109 case Cover: { |
| 118 float horizontalScaleFactor = imageIntrinsicSize.width() | 110 float horizontalScaleFactor = imageIntrinsicSize.width() |
| 119 ? static_cast<float>(positioningAreaSize.width()) / imageIntrinsicSi ze.width() : 1; | 111 ? positioningAreaSize.width().toFloat() / imageIntrinsicSize.width() : 1; |
| 120 float verticalScaleFactor = imageIntrinsicSize.height() | 112 float verticalScaleFactor = imageIntrinsicSize.height() |
| 121 ? static_cast<float>(positioningAreaSize.height()) / imageIntrinsicS ize.height() : 1; | 113 ? positioningAreaSize.height().toFloat() / imageIntrinsicSize.height () : 1; |
| 122 float scaleFactor = type == Contain ? std::min(horizontalScaleFactor, ve rticalScaleFactor) : std::max(horizontalScaleFactor, verticalScaleFactor); | 114 float scaleFactor = type == Contain ? std::min(horizontalScaleFactor, ve rticalScaleFactor) : std::max(horizontalScaleFactor, verticalScaleFactor); |
| 123 return IntSize(std::max(1l, lround(imageIntrinsicSize.width() * scaleFac tor)), std::max(1l, lround(imageIntrinsicSize.height() * scaleFactor))); | 115 return LayoutSize(std::max<LayoutUnit>(1, imageIntrinsicSize.width() * s caleFactor), std::max<LayoutUnit>(1, imageIntrinsicSize.height() * scaleFactor)) ; |
| 124 } | 116 } |
| 125 } | 117 } |
| 126 | 118 |
| 127 ASSERT_NOT_REACHED(); | 119 ASSERT_NOT_REACHED(); |
| 128 return IntSize(); | 120 return LayoutSize(); |
| 129 } | 121 } |
| 130 | 122 |
| 131 IntPoint accumulatedScrollOffset(const LayoutBoxModelObject& object, const Layou tBoxModelObject* container) | 123 IntPoint accumulatedScrollOffset(const LayoutBoxModelObject& object, const Layou tBoxModelObject* container) |
| 132 { | 124 { |
| 133 const LayoutBlock* block = object.isLayoutBlock() ? toLayoutBlock(&object) : object.containingBlock(); | 125 const LayoutBlock* block = object.isLayoutBlock() ? toLayoutBlock(&object) : object.containingBlock(); |
| 134 IntPoint result; | 126 IntPoint result; |
| 135 while (block) { | 127 while (block) { |
| 136 if (block->hasOverflowClip()) | 128 if (block->hasOverflowClip()) |
| 137 result += block->scrolledContentOffset(); | 129 result += block->scrolledContentOffset(); |
| 138 if (block == container) | 130 if (block == container) |
| 139 break; | 131 break; |
| 140 block = block->containingBlock(); | 132 block = block->containingBlock(); |
| 141 } | 133 } |
| 142 return result; | 134 return result; |
| 143 } | 135 } |
| 144 | 136 |
| 145 } // anonymous namespace | 137 } // anonymous namespace |
| 146 | 138 |
| 147 void BackgroundImageGeometry::setNoRepeatX(int xOffset) | 139 void BackgroundImageGeometry::setNoRepeatX(LayoutUnit xOffset) |
| 148 { | 140 { |
| 149 m_destRect.move(std::max(xOffset, 0), 0); | 141 m_destRect.move(std::max(xOffset, LayoutUnit()), LayoutUnit()); |
| 150 m_phase.setX(-std::min(xOffset, 0)); | 142 m_phase.setX(-std::min(xOffset, LayoutUnit())); |
| 151 m_destRect.setWidth(m_tileSize.width() + std::min(xOffset, 0)); | 143 m_destRect.setWidth(m_tileSize.width() + std::min(xOffset, LayoutUnit())); |
| 152 } | 144 } |
| 153 | 145 |
| 154 void BackgroundImageGeometry::setNoRepeatY(int yOffset) | 146 void BackgroundImageGeometry::setNoRepeatY(LayoutUnit yOffset) |
| 155 { | 147 { |
| 156 m_destRect.move(0, std::max(yOffset, 0)); | 148 m_destRect.move(LayoutUnit(), std::max(yOffset, LayoutUnit())); |
| 157 m_phase.setY(-std::min(yOffset, 0)); | 149 m_phase.setY(-std::min(yOffset, LayoutUnit())); |
| 158 m_destRect.setHeight(m_tileSize.height() + std::min(yOffset, 0)); | 150 m_destRect.setHeight(m_tileSize.height() + std::min(yOffset, LayoutUnit())); |
| 159 } | 151 } |
| 160 | 152 |
| 161 void BackgroundImageGeometry::useFixedAttachment(const IntPoint& attachmentPoint ) | 153 void BackgroundImageGeometry::useFixedAttachment(const LayoutPoint& attachmentPo int) |
| 162 { | 154 { |
| 163 IntPoint alignedPoint = attachmentPoint; | 155 LayoutPoint alignedPoint = attachmentPoint; |
| 164 m_phase.move(std::max(alignedPoint.x() - m_destRect.x(), 0), std::max(aligne dPoint.y() - m_destRect.y(), 0)); | 156 m_phase.move(std::max(alignedPoint.x() - m_destRect.x(), LayoutUnit()), std: :max(alignedPoint.y() - m_destRect.y(), LayoutUnit())); |
| 165 } | 157 } |
| 166 | 158 |
| 167 void BackgroundImageGeometry::clip(const IntRect& clipRect) | 159 void BackgroundImageGeometry::clip(const LayoutRect& clipRect) |
| 168 { | 160 { |
| 169 m_destRect.intersect(clipRect); | 161 m_destRect.intersect(clipRect); |
| 170 } | 162 } |
| 171 | 163 |
| 164 // When we match the destination rect in a dimension, we snap the same way. Othe rwise | |
| 165 // we floor. | |
|
eae
2015/11/25 00:21:05
Could you expand on why we're flooring in the othe
leviw_travelin_and_unemployed
2015/11/25 00:31:56
Sure. We're following the same heuristic as before
| |
| 166 static LayoutSize applySubPixelHeuristicToImageSize(const LayoutSize& size, cons t LayoutRect& destination) | |
| 167 { | |
| 168 LayoutSize snappedSize = LayoutSize( | |
| 169 size.width() == destination.width() ? destination.pixelSnappedWidth() : size.width().floor(), | |
| 170 size.height() == destination.height() ? destination.pixelSnappedHeight() : size.height().floor()); | |
| 171 return snappedSize; | |
| 172 } | |
| 173 | |
| 174 void BackgroundImageGeometry::pixelSnapGeometry() | |
| 175 { | |
| 176 setTileSize(applySubPixelHeuristicToImageSize(m_tileSize, m_destRect)); | |
| 177 setImageContainerSize(applySubPixelHeuristicToImageSize(m_imageContainerSize , m_destRect)); | |
| 178 setSpaceSize(LayoutSize(roundedIntSize(m_repeatSpacing))); | |
| 179 setDestRect(LayoutRect(pixelSnappedIntRect(m_destRect))); | |
| 180 setPhase(LayoutPoint(flooredIntPoint(m_phase))); | |
| 181 } | |
| 182 | |
| 172 void BackgroundImageGeometry::calculate(const LayoutBoxModelObject& obj, const L ayoutBoxModelObject* paintContainer, | 183 void BackgroundImageGeometry::calculate(const LayoutBoxModelObject& obj, const L ayoutBoxModelObject* paintContainer, |
| 173 const GlobalPaintFlags globalPaintFlags, const FillLayer& fillLayer, const L ayoutRect& paintRect) | 184 const GlobalPaintFlags globalPaintFlags, const FillLayer& fillLayer, const L ayoutRect& paintRect) |
| 174 { | 185 { |
| 175 LayoutUnit left = 0; | 186 LayoutUnit left; |
| 176 LayoutUnit top = 0; | 187 LayoutUnit top; |
| 177 IntSize positioningAreaSize; | 188 LayoutSize positioningAreaSize; |
| 178 IntRect snappedPaintRect = pixelSnappedIntRect(paintRect); | |
| 179 bool isLayoutView = obj.isLayoutView(); | 189 bool isLayoutView = obj.isLayoutView(); |
| 180 const LayoutBox* rootBox = nullptr; | 190 const LayoutBox* rootBox = nullptr; |
| 181 if (isLayoutView) { | 191 if (isLayoutView) { |
| 182 // It is only possible reach here when root element has a box. | 192 // It is only possible reach here when root element has a box. |
| 183 Element* documentElement = obj.document().documentElement(); | 193 Element* documentElement = obj.document().documentElement(); |
| 184 ASSERT(documentElement); | 194 ASSERT(documentElement); |
| 185 ASSERT(documentElement->layoutObject()); | 195 ASSERT(documentElement->layoutObject()); |
| 186 ASSERT(documentElement->layoutObject()->isBox()); | 196 ASSERT(documentElement->layoutObject()->isBox()); |
| 187 rootBox = toLayoutBox(documentElement->layoutObject()); | 197 rootBox = toLayoutBox(documentElement->layoutObject()); |
| 188 } | 198 } |
| 189 const LayoutBoxModelObject& positioningBox = isLayoutView ? static_cast<cons t LayoutBoxModelObject&>(*rootBox) : obj; | 199 const LayoutBoxModelObject& positioningBox = isLayoutView ? static_cast<cons t LayoutBoxModelObject&>(*rootBox) : obj; |
| 190 | 200 |
| 191 // Determine the background positioning area and set destRect to the backgro und painting area. | 201 // Determine the background positioning area and set destRect to the backgro und painting area. |
| 192 // destRect will be adjusted later if the background is non-repeating. | 202 // destRect will be adjusted later if the background is non-repeating. |
| 193 // FIXME: transforms spec says that fixed backgrounds behave like scroll ins ide transforms. | 203 // FIXME: transforms spec says that fixed backgrounds behave like scroll ins ide transforms. |
| 194 bool fixedAttachment = fillLayer.attachment() == FixedBackgroundAttachment; | 204 bool fixedAttachment = fillLayer.attachment() == FixedBackgroundAttachment; |
| 195 | 205 |
| 196 if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) { | 206 if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) { |
| 197 // As a side effect of an optimization to blit on scroll, we do not hono r the CSS | 207 // As a side effect of an optimization to blit on scroll, we do not hono r the CSS |
| 198 // property "background-attachment: fixed" because it may result in rend ering | 208 // property "background-attachment: fixed" because it may result in rend ering |
| 199 // artifacts. Note, these artifacts only appear if we are blitting on sc roll of | 209 // artifacts. Note, these artifacts only appear if we are blitting on sc roll of |
| 200 // a page that has fixed background images. | 210 // a page that has fixed background images. |
| 201 fixedAttachment = false; | 211 fixedAttachment = false; |
| 202 } | 212 } |
| 203 | 213 |
| 204 if (!fixedAttachment) { | 214 if (!fixedAttachment) { |
| 205 setDestRect(snappedPaintRect); | 215 setDestRect(paintRect); |
| 206 | 216 |
| 207 LayoutUnit right = 0; | 217 LayoutUnit right; |
| 208 LayoutUnit bottom = 0; | 218 LayoutUnit bottom; |
| 209 // Scroll and Local. | 219 // Scroll and Local. |
| 210 if (fillLayer.origin() != BorderFillBox) { | 220 if (fillLayer.origin() != BorderFillBox) { |
| 211 left = positioningBox.borderLeft(); | 221 left = positioningBox.borderLeft(); |
| 212 right = positioningBox.borderRight(); | 222 right = positioningBox.borderRight(); |
| 213 top = positioningBox.borderTop(); | 223 top = positioningBox.borderTop(); |
| 214 bottom = positioningBox.borderBottom(); | 224 bottom = positioningBox.borderBottom(); |
| 215 if (fillLayer.origin() == ContentFillBox) { | 225 if (fillLayer.origin() == ContentFillBox) { |
| 216 left += positioningBox.paddingLeft(); | 226 left += positioningBox.paddingLeft(); |
| 217 right += positioningBox.paddingRight(); | 227 right += positioningBox.paddingRight(); |
| 218 top += positioningBox.paddingTop(); | 228 top += positioningBox.paddingTop(); |
| 219 bottom += positioningBox.paddingBottom(); | 229 bottom += positioningBox.paddingBottom(); |
| 220 } | 230 } |
| 221 } | 231 } |
| 222 | 232 |
| 223 if (isLayoutView) { | 233 if (isLayoutView) { |
| 224 // The background of the box generated by the root element covers th e entire canvas and will | 234 // The background of the box generated by the root element covers th e entire canvas and will |
| 225 // be painted by the view object, but the we should still use the ro ot element box for | 235 // be painted by the view object, but the we should still use the ro ot element box for |
| 226 // positioning. | 236 // positioning. |
| 227 positioningAreaSize = pixelSnappedIntSize(rootBox->size() - LayoutSi ze(left + right, top + bottom), rootBox->location()); | 237 positioningAreaSize = rootBox->size() - LayoutSize(left + right, top + bottom), rootBox->location(); |
| 228 // The input paint rect is specified in root element local coordinat e (i.e. a transform | 238 // The input paint rect is specified in root element local coordinat e (i.e. a transform |
| 229 // is applied on the context for painting), and is expanded to cover the whole canvas. | 239 // is applied on the context for painting), and is expanded to cover the whole canvas. |
| 230 // Since left/top is relative to the paint rect, we need to offset t hem back. | 240 // Since left/top is relative to the paint rect, we need to offset t hem back. |
| 231 left -= paintRect.x(); | 241 left -= paintRect.x(); |
| 232 top -= paintRect.y(); | 242 top -= paintRect.y(); |
| 233 } else { | 243 } else { |
| 234 positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutS ize(left + right, top + bottom), paintRect.location()); | 244 positioningAreaSize = paintRect.size() - LayoutSize(left + right, to p + bottom); |
| 235 } | 245 } |
| 236 } else { | 246 } else { |
| 237 setHasNonLocalGeometry(); | 247 setHasNonLocalGeometry(); |
| 238 | 248 |
| 239 IntRect viewportRect = pixelSnappedIntRect(obj.viewRect()); | 249 LayoutRect viewportRect = obj.viewRect(); |
| 240 if (fixedBackgroundPaintsInLocalCoordinates(obj, globalPaintFlags)) { | 250 if (fixedBackgroundPaintsInLocalCoordinates(obj, globalPaintFlags)) { |
| 241 viewportRect.setLocation(IntPoint()); | 251 viewportRect.setLocation(LayoutPoint()); |
| 242 } else { | 252 } else { |
| 243 if (FrameView* frameView = obj.view()->frameView()) | 253 if (FrameView* frameView = obj.view()->frameView()) |
| 244 viewportRect.setLocation(frameView->scrollPosition()); | 254 viewportRect.setLocation(frameView->scrollPosition()); |
| 245 // Compensate the translations created by ScrollRecorders. | 255 // Compensate the translations created by ScrollRecorders. |
| 246 // TODO(trchen): Fix this for SP phase 2. crbug.com/529963. | 256 // TODO(trchen): Fix this for SP phase 2. crbug.com/529963. |
| 247 viewportRect.moveBy(accumulatedScrollOffset(obj, paintContainer)); | 257 viewportRect.moveBy(accumulatedScrollOffset(obj, paintContainer)); |
| 248 } | 258 } |
| 249 | 259 |
| 250 if (paintContainer) { | 260 if (paintContainer) |
| 251 IntPoint absoluteContainerOffset = roundedIntPoint(paintContainer->l ocalToAbsolute(FloatPoint())); | 261 viewportRect.moveBy(LayoutPoint(-paintContainer->localToAbsolute(Flo atPoint()))); |
| 252 viewportRect.moveBy(-absoluteContainerOffset); | |
| 253 } | |
| 254 | 262 |
| 255 setDestRect(viewportRect); | 263 setDestRect(viewportRect); |
| 256 positioningAreaSize = destRect().size(); | 264 positioningAreaSize = destRect().size(); |
| 257 } | 265 } |
| 258 | 266 |
| 259 IntSize fillTileSize = calculateFillTileSize(positioningBox, fillLayer, posi tioningAreaSize); | 267 LayoutSize fillTileSize = calculateFillTileSize(positioningBox, fillLayer, p ositioningAreaSize); |
| 260 setTileSize(fillTileSize); | 268 setTileSize(fillTileSize); |
| 261 setImageContainerSize(fillTileSize); | 269 setImageContainerSize(fillTileSize); |
| 262 | 270 |
| 263 EFillRepeat backgroundRepeatX = fillLayer.repeatX(); | 271 EFillRepeat backgroundRepeatX = fillLayer.repeatX(); |
| 264 EFillRepeat backgroundRepeatY = fillLayer.repeatY(); | 272 EFillRepeat backgroundRepeatY = fillLayer.repeatY(); |
| 265 int availableWidth = positioningAreaSize.width() - tileSize().width(); | 273 LayoutUnit availableWidth = positioningAreaSize.width() - tileSize().width() ; |
| 266 int availableHeight = positioningAreaSize.height() - tileSize().height(); | 274 LayoutUnit availableHeight = positioningAreaSize.height() - tileSize().heigh t(); |
| 267 | 275 |
| 268 LayoutUnit computedXPosition = roundedMinimumValueForLength(fillLayer.xPosit ion(), availableWidth); | 276 LayoutUnit computedXPosition = roundedMinimumValueForLength(fillLayer.xPosit ion(), availableWidth); |
| 269 if (backgroundRepeatX == RoundFill && positioningAreaSize.width() > 0 && fil lTileSize.width() > 0) { | 277 if (backgroundRepeatX == RoundFill && positioningAreaSize.width() > LayoutUn it() && fillTileSize.width() > LayoutUnit()) { |
| 270 long nrTiles = std::max(1l, lroundf((float)positioningAreaSize.width() / fillTileSize.width())); | 278 int nrTiles = std::max(1, roundToInt(positioningAreaSize.width() / fillT ileSize.width())); |
| 271 | 279 |
| 272 // Round tile size per css3-background spec. | 280 fillTileSize.setWidth(positioningAreaSize.width() / nrTiles); |
| 273 fillTileSize.setWidth(lroundf(positioningAreaSize.width() / (float)nrTil es)); | |
| 274 | 281 |
| 275 // Maintain aspect ratio if background-size: auto is set | 282 // Maintain aspect ratio if background-size: auto is set |
| 276 if (fillLayer.size().size.height().isAuto() && backgroundRepeatY != Roun dFill) { | 283 if (fillLayer.size().size.height().isAuto() && backgroundRepeatY != Roun dFill) { |
| 277 fillTileSize.setHeight(fillTileSize.height() * positioningAreaSize.w idth() / (nrTiles * fillTileSize.width())); | 284 fillTileSize.setHeight(fillTileSize.height() * positioningAreaSize.w idth() / (nrTiles * fillTileSize.width())); |
| 278 } | 285 } |
| 279 | 286 |
| 280 setTileSize(fillTileSize); | 287 setTileSize(fillTileSize); |
| 281 setPhaseX(tileSize().width() ? tileSize().width() - roundToInt(computedX Position + left) % tileSize().width() : 0); | 288 setImageContainerSize(fillTileSize); |
| 282 setSpaceSize(IntSize()); | 289 setPhaseX(tileSize().width() ? tileSize().width() - fmodf((computedXPosi tion + left), tileSize().width()) : 0.0f); |
| 290 setSpaceSize(LayoutSize()); | |
| 283 } | 291 } |
| 284 | 292 |
| 285 LayoutUnit computedYPosition = roundedMinimumValueForLength(fillLayer.yPosit ion(), availableHeight); | 293 LayoutUnit computedYPosition = roundedMinimumValueForLength(fillLayer.yPosit ion(), availableHeight); |
| 286 if (backgroundRepeatY == RoundFill && positioningAreaSize.height() > 0 && fi llTileSize.height() > 0) { | 294 if (backgroundRepeatY == RoundFill && positioningAreaSize.height() > LayoutU nit() && fillTileSize.height() > LayoutUnit()) { |
| 287 long nrTiles = std::max(1l, lroundf((float)positioningAreaSize.height() / fillTileSize.height())); | 295 int nrTiles = std::max(1, roundToInt(positioningAreaSize.height() / fill TileSize.height())); |
| 288 | 296 |
| 289 // Round tile size per css3-background spec. | 297 fillTileSize.setHeight(positioningAreaSize.height() / nrTiles); |
| 290 fillTileSize.setHeight(lroundf(positioningAreaSize.height() / (float)nrT iles)); | |
| 291 | 298 |
| 292 // Maintain aspect ratio if background-size: auto is set | 299 // Maintain aspect ratio if background-size: auto is set |
| 293 if (fillLayer.size().size.width().isAuto() && backgroundRepeatX != Round Fill) { | 300 if (fillLayer.size().size.width().isAuto() && backgroundRepeatX != Round Fill) { |
| 294 fillTileSize.setWidth(fillTileSize.width() * positioningAreaSize.hei ght() / (nrTiles * fillTileSize.height())); | 301 fillTileSize.setWidth(fillTileSize.width() * positioningAreaSize.hei ght() / (nrTiles * fillTileSize.height())); |
| 295 } | 302 } |
| 296 | 303 |
| 297 setTileSize(fillTileSize); | 304 setTileSize(fillTileSize); |
| 298 setPhaseY(tileSize().height() ? tileSize().height() - roundToInt(compute dYPosition + top) % tileSize().height() : 0); | 305 setImageContainerSize(fillTileSize); |
| 299 setSpaceSize(IntSize()); | 306 setPhaseY(tileSize().height() ? tileSize().height() - fmodf((computedYPo sition + top), tileSize().height()) : 0.0f); |
| 307 setSpaceSize(LayoutSize()); | |
| 300 } | 308 } |
| 301 | 309 |
| 302 if (backgroundRepeatX == RepeatFill) { | 310 if (backgroundRepeatX == RepeatFill) { |
| 303 LayoutUnit xOffset = fillLayer.backgroundXOrigin() == RightEdge ? availa bleWidth - computedXPosition : computedXPosition; | 311 LayoutUnit xOffset = fillLayer.backgroundXOrigin() == RightEdge ? availa bleWidth - computedXPosition : computedXPosition; |
| 304 setPhaseX(tileSize().width() ? tileSize().width() - roundToInt(xOffset + left) % tileSize().width() : 0); | 312 setPhaseX(tileSize().width() ? tileSize().width() - fmodf((xOffset + lef t), tileSize().width()) : 0.0f); |
| 305 setSpaceSize(IntSize()); | 313 setSpaceSize(LayoutSize()); |
| 306 } else if (backgroundRepeatX == SpaceFill && fillTileSize.width() > 0) { | 314 } else if (backgroundRepeatX == SpaceFill && fillTileSize.width() > LayoutUn it()) { |
| 307 int space = getSpaceBetweenImageTiles(positioningAreaSize.width(), tileS ize().width()); | 315 LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.width() , tileSize().width()); |
| 308 int actualWidth = tileSize().width() + space; | 316 LayoutUnit actualWidth = tileSize().width() + space; |
| 309 | 317 |
| 310 if (space >= 0) { | 318 if (space >= LayoutUnit()) { |
| 311 computedXPosition = roundedMinimumValueForLength(Length(), available Width); | 319 computedXPosition = roundedMinimumValueForLength(Length(), available Width); |
| 312 setSpaceSize(IntSize(space, 0)); | 320 setSpaceSize(LayoutSize(space, LayoutUnit())); |
| 313 setPhaseX(actualWidth ? actualWidth - roundToInt(computedXPosition + left) % actualWidth : 0); | 321 setPhaseX(actualWidth ? actualWidth - fmodf((computedXPosition + lef t), actualWidth) : 0.0f); |
| 314 } else { | 322 } else { |
| 315 backgroundRepeatX = NoRepeatFill; | 323 backgroundRepeatX = NoRepeatFill; |
| 316 } | 324 } |
| 317 } | 325 } |
| 318 if (backgroundRepeatX == NoRepeatFill) { | 326 if (backgroundRepeatX == NoRepeatFill) { |
| 319 LayoutUnit xOffset = fillLayer.backgroundXOrigin() == RightEdge ? availa bleWidth - computedXPosition : computedXPosition; | 327 LayoutUnit xOffset = fillLayer.backgroundXOrigin() == RightEdge ? availa bleWidth - computedXPosition : computedXPosition; |
| 320 setNoRepeatX(left + xOffset); | 328 setNoRepeatX(left + xOffset); |
| 321 setSpaceSize(IntSize(0, spaceSize().height())); | 329 setSpaceSize(LayoutSize(LayoutUnit(), spaceSize().height())); |
| 322 } | 330 } |
| 323 | 331 |
| 324 if (backgroundRepeatY == RepeatFill) { | 332 if (backgroundRepeatY == RepeatFill) { |
| 325 LayoutUnit yOffset = fillLayer.backgroundYOrigin() == BottomEdge ? avail ableHeight - computedYPosition : computedYPosition; | 333 LayoutUnit yOffset = fillLayer.backgroundYOrigin() == BottomEdge ? avail ableHeight - computedYPosition : computedYPosition; |
| 326 setPhaseY(tileSize().height() ? tileSize().height() - roundToInt(yOffset + top) % tileSize().height() : 0); | 334 setPhaseY(tileSize().height() ? tileSize().height() - fmodf((yOffset + t op), tileSize().height()) : 0.0f); |
| 327 setSpaceSize(IntSize(spaceSize().width(), 0)); | 335 setSpaceSize(LayoutSize(spaceSize().width(), LayoutUnit())); |
| 328 } else if (backgroundRepeatY == SpaceFill && fillTileSize.height() > 0) { | 336 } else if (backgroundRepeatY == SpaceFill && fillTileSize.height() > LayoutU nit()) { |
| 329 int space = getSpaceBetweenImageTiles(positioningAreaSize.height(), tile Size().height()); | 337 LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.height( ), tileSize().height()); |
| 330 int actualHeight = tileSize().height() + space; | 338 LayoutUnit actualHeight = tileSize().height() + space; |
| 331 | 339 |
| 332 if (space >= 0) { | 340 if (space >= LayoutUnit()) { |
| 333 computedYPosition = roundedMinimumValueForLength(Length(), available Height); | 341 computedYPosition = roundedMinimumValueForLength(Length(), available Height); |
| 334 setSpaceSize(IntSize(spaceSize().width(), space)); | 342 setSpaceSize(LayoutSize(spaceSize().width(), space)); |
| 335 setPhaseY(actualHeight ? actualHeight - roundToInt(computedYPosition + top) % actualHeight : 0); | 343 setPhaseY(actualHeight ? actualHeight - fmodf((computedYPosition + t op), actualHeight) : 0.0f); |
| 336 } else { | 344 } else { |
| 337 backgroundRepeatY = NoRepeatFill; | 345 backgroundRepeatY = NoRepeatFill; |
| 338 } | 346 } |
| 339 } | 347 } |
| 340 if (backgroundRepeatY == NoRepeatFill) { | 348 if (backgroundRepeatY == NoRepeatFill) { |
| 341 LayoutUnit yOffset = fillLayer.backgroundYOrigin() == BottomEdge ? avail ableHeight - computedYPosition : computedYPosition; | 349 LayoutUnit yOffset = fillLayer.backgroundYOrigin() == BottomEdge ? avail ableHeight - computedYPosition : computedYPosition; |
| 342 setNoRepeatY(top + yOffset); | 350 setNoRepeatY(top + yOffset); |
| 343 setSpaceSize(IntSize(spaceSize().width(), 0)); | 351 setSpaceSize(LayoutSize(spaceSize().width(), LayoutUnit())); |
| 344 } | 352 } |
| 345 | 353 |
| 346 if (fixedAttachment) | 354 if (fixedAttachment) |
| 347 useFixedAttachment(snappedPaintRect.location()); | 355 useFixedAttachment(paintRect.location()); |
| 348 | 356 |
| 349 clip(snappedPaintRect); | 357 clip(paintRect); |
| 358 pixelSnapGeometry(); | |
| 350 } | 359 } |
| 351 | 360 |
| 352 } // namespace blink | 361 } // namespace blink |
| OLD | NEW |