Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(452)

Side by Side Diff: third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp

Issue 1456813002: Calculate Background Image Geometries using sub-pixel values (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Unit fix and moar ref test corrections. Still no expected results. Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698