OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2012 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 20 matching lines...) Expand all Loading... | |
31 #include "core/paint/PaintLayer.h" | 31 #include "core/paint/PaintLayer.h" |
32 #include "platform/geometry/TransformState.h" | 32 #include "platform/geometry/TransformState.h" |
33 #include "wtf/TemporaryChange.h" | 33 #include "wtf/TemporaryChange.h" |
34 | 34 |
35 namespace blink { | 35 namespace blink { |
36 | 36 |
37 LayoutGeometryMap::LayoutGeometryMap(MapCoordinatesFlags flags) | 37 LayoutGeometryMap::LayoutGeometryMap(MapCoordinatesFlags flags) |
38 : m_insertionPosition(kNotFound) | 38 : m_insertionPosition(kNotFound) |
39 , m_nonUniformStepsCount(0) | 39 , m_nonUniformStepsCount(0) |
40 , m_transformedStepsCount(0) | 40 , m_transformedStepsCount(0) |
41 , m_fixedStepsCount(0) | 41 , m_viewportConstrainedStepsCount(0) |
42 , m_mapCoordinatesFlags(flags) | 42 , m_mapCoordinatesFlags(flags) |
43 { | 43 { |
44 } | 44 } |
45 | 45 |
46 LayoutGeometryMap::~LayoutGeometryMap() | 46 LayoutGeometryMap::~LayoutGeometryMap() |
47 { | 47 { |
48 } | 48 } |
49 | 49 |
50 void LayoutGeometryMap::mapToContainer(TransformState& transformState, const Lay outBoxModelObject* container) const | 50 void LayoutGeometryMap::mapToContainer(TransformState& transformState, const Lay outBoxModelObject* container) const |
51 { | 51 { |
52 // If the mapping includes something like columns, we have to go via layoutO bjects. | 52 // If the mapping includes something like columns, we have to go via layoutO bjects. |
53 if (hasNonUniformStep()) { | 53 if (hasNonUniformStep()) { |
54 m_mapping.last().m_layoutObject->mapLocalToContainer(container, transfor mState, ApplyContainerFlip | m_mapCoordinatesFlags); | 54 m_mapping.last().m_layoutObject->mapLocalToContainer(container, transfor mState, ApplyContainerFlip | m_mapCoordinatesFlags); |
55 transformState.flatten(); | 55 transformState.flatten(); |
56 return; | 56 return; |
57 } | 57 } |
58 | 58 |
59 bool inFixed = false; | 59 bool inFixed = false; |
60 #if ENABLE(ASSERT) | 60 #if ENABLE(ASSERT) |
61 bool foundContainer = !container || (m_mapping.size() && m_mapping[0].m_layo utObject == container); | 61 bool foundContainer = !container || (m_mapping.size() && m_mapping[0].m_layo utObject == container); |
62 #endif | 62 #endif |
63 | 63 |
64 for (int i = m_mapping.size() - 1; i >= 0; --i) { | 64 for (int i = m_mapping.size() - 1; i >= 0; --i) { |
65 const LayoutGeometryMapStep& currentStep = m_mapping[i]; | 65 const LayoutGeometryMapStep& currentStep = m_mapping[i]; |
66 | 66 |
67 // If container is the root LayoutView (step 0) we want to apply its fix ed position offset. | 67 // If container is the root LayoutView (step 0) we want to apply its vie wport constrained position offset. |
chrishtr
2015/11/04 01:55:18
Sticky elements are not quite viewport constrained
flackr
2015/11/25 20:47:52
Yes, I rethought this and it seems we can get by w
| |
68 if (i > 0 && currentStep.m_layoutObject == container) { | 68 if (i > 0 && currentStep.m_layoutObject == container) { |
69 #if ENABLE(ASSERT) | 69 #if ENABLE(ASSERT) |
70 foundContainer = true; | 70 foundContainer = true; |
71 #endif | 71 #endif |
72 break; | 72 break; |
73 } | 73 } |
74 | 74 |
75 // If this box has a transform, it acts as a fixed position container | 75 // If this box has a transform, it acts as a viewport constrained positi on container |
76 // for fixed descendants, which prevents the propagation of 'fixed' | 76 // for viewport constrained descendants, which prevents the propagation of viewport constrained |
77 // unless the layer itself is also fixed position. | 77 // unless the layer itself is also a viewport constrained position. |
78 if (i && currentStep.m_hasTransform && !currentStep.m_isFixedPosition) | 78 // TODO(flackr): Verify how fixed and sticky elements should interact wi th each other. |
chrishtr
2015/11/04 01:55:18
Meaning: what should happen with a sticky element
flackr
2015/11/25 20:47:52
Correct. FWIW I have now tested both of these and
| |
79 if (i && currentStep.m_hasTransform && !currentStep.m_isViewportConstrai ned) | |
79 inFixed = false; | 80 inFixed = false; |
80 else if (currentStep.m_isFixedPosition) | 81 else if (currentStep.m_isViewportConstrained) |
81 inFixed = true; | 82 inFixed = true; |
82 | 83 |
83 ASSERT(!i == isTopmostLayoutView(currentStep.m_layoutObject)); | 84 ASSERT(!i == isTopmostLayoutView(currentStep.m_layoutObject)); |
84 | 85 |
85 if (!i) { | 86 if (!i) { |
86 // A null container indicates mapping through the root LayoutView, s o including its transform (the page scale). | 87 // A null container indicates mapping through the root LayoutView, s o including its transform (the page scale). |
87 if (!container && currentStep.m_transform) | 88 if (!container && currentStep.m_transform) |
88 transformState.applyTransform(*currentStep.m_transform.get()); | 89 transformState.applyTransform(*currentStep.m_transform.get()); |
89 } else { | 90 } else { |
90 TransformState::TransformAccumulation accumulate = currentStep.m_acc umulatingTransform ? TransformState::AccumulateTransform : TransformState::Flatt enTransform; | 91 TransformState::TransformAccumulation accumulate = currentStep.m_acc umulatingTransform ? TransformState::AccumulateTransform : TransformState::Flatt enTransform; |
91 if (currentStep.m_transform) | 92 if (currentStep.m_transform) |
92 transformState.applyTransform(*currentStep.m_transform.get(), ac cumulate); | 93 transformState.applyTransform(*currentStep.m_transform.get(), ac cumulate); |
93 else | 94 else |
94 transformState.move(currentStep.m_offset.width(), currentStep.m_ offset.height(), accumulate); | 95 transformState.move(currentStep.m_offset.width(), currentStep.m_ offset.height(), accumulate); |
95 } | 96 } |
96 | 97 |
97 if (inFixed && !currentStep.m_offsetForFixedPosition.isZero()) { | 98 if (inFixed && !currentStep.m_offsetForViewportConstrained.isZero()) { |
98 ASSERT(currentStep.m_layoutObject->isLayoutView()); | 99 ASSERT(currentStep.m_layoutObject->isLayoutView()); |
99 transformState.move(currentStep.m_offsetForFixedPosition); | 100 transformState.move(currentStep.m_offsetForViewportConstrained); |
100 } | 101 } |
101 } | 102 } |
102 | 103 |
103 ASSERT(foundContainer); | 104 ASSERT(foundContainer); |
104 transformState.flatten(); | 105 transformState.flatten(); |
105 } | 106 } |
106 | 107 |
107 FloatPoint LayoutGeometryMap::mapToContainer(const FloatPoint& p, const LayoutBo xModelObject* container) const | 108 FloatPoint LayoutGeometryMap::mapToContainer(const FloatPoint& p, const LayoutBo xModelObject* container) const |
108 { | 109 { |
109 FloatPoint result; | 110 FloatPoint result; |
110 | 111 |
111 if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep() & & (!container || (m_mapping.size() && container == m_mapping[0].m_layoutObject)) ) { | 112 if (!hasViewportConstrainedStep() && !hasTransformStep() && !hasNonUniformSt ep() && (!container || (m_mapping.size() && container == m_mapping[0].m_layoutOb ject))) { |
112 result = p + m_accumulatedOffset; | 113 result = p + m_accumulatedOffset; |
113 } else { | 114 } else { |
114 TransformState transformState(TransformState::ApplyTransformDirection, p ); | 115 TransformState transformState(TransformState::ApplyTransformDirection, p ); |
115 mapToContainer(transformState, container); | 116 mapToContainer(transformState, container); |
116 result = transformState.lastPlanarPoint(); | 117 result = transformState.lastPlanarPoint(); |
117 } | 118 } |
118 | 119 |
119 #if ENABLE(ASSERT) | 120 #if ENABLE(ASSERT) |
120 if (m_mapping.size() > 0) { | 121 if (m_mapping.size() > 0) { |
121 const LayoutObject* lastLayoutObject = m_mapping.last().m_layoutObject; | 122 const LayoutObject* lastLayoutObject = m_mapping.last().m_layoutObject; |
(...skipping 27 matching lines...) Expand all Loading... | |
149 fprintf(stderr, " hasTransform"); | 150 fprintf(stderr, " hasTransform"); |
150 fprintf(stderr, "\n"); | 151 fprintf(stderr, "\n"); |
151 } | 152 } |
152 } | 153 } |
153 #endif | 154 #endif |
154 | 155 |
155 FloatQuad LayoutGeometryMap::mapToContainer(const FloatRect& rect, const LayoutB oxModelObject* container) const | 156 FloatQuad LayoutGeometryMap::mapToContainer(const FloatRect& rect, const LayoutB oxModelObject* container) const |
156 { | 157 { |
157 FloatQuad result; | 158 FloatQuad result; |
158 | 159 |
159 if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep() & & (!container || (m_mapping.size() && container == m_mapping[0].m_layoutObject)) ) { | 160 if (!hasViewportConstrainedStep() && !hasTransformStep() && !hasNonUniformSt ep() && (!container || (m_mapping.size() && container == m_mapping[0].m_layoutOb ject))) { |
160 result = rect; | 161 result = rect; |
161 result.move(m_accumulatedOffset); | 162 result.move(m_accumulatedOffset); |
162 } else { | 163 } else { |
163 TransformState transformState(TransformState::ApplyTransformDirection, r ect.center(), rect); | 164 TransformState transformState(TransformState::ApplyTransformDirection, r ect.center(), rect); |
164 mapToContainer(transformState, container); | 165 mapToContainer(transformState, container); |
165 result = transformState.lastPlanarQuad(); | 166 result = transformState.lastPlanarQuad(); |
166 } | 167 } |
167 | 168 |
168 #if ENABLE(ASSERT) | 169 #if ENABLE(ASSERT) |
169 if (m_mapping.size() > 0) { | 170 if (m_mapping.size() > 0) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 layer->convertToLayerCoords(ancestorLayer, layerOffset); | 235 layer->convertToLayerCoords(ancestorLayer, layerOffset); |
235 | 236 |
236 // The LayoutView must be pushed first. | 237 // The LayoutView must be pushed first. |
237 if (!m_mapping.size()) { | 238 if (!m_mapping.size()) { |
238 ASSERT(ancestorLayer->layoutObject()->isLayoutView()); | 239 ASSERT(ancestorLayer->layoutObject()->isLayoutView()); |
239 pushMappingsToAncestor(ancestorLayer->layoutObject(), 0); | 240 pushMappingsToAncestor(ancestorLayer->layoutObject(), 0); |
240 } | 241 } |
241 | 242 |
242 TemporaryChange<size_t> positionChange(m_insertionPosition, m_mapping.si ze()); | 243 TemporaryChange<size_t> positionChange(m_insertionPosition, m_mapping.si ze()); |
243 bool accumulatingTransform = layer->layoutObject()->style()->preserves3D () || ancestorLayer->layoutObject()->style()->preserves3D(); | 244 bool accumulatingTransform = layer->layoutObject()->style()->preserves3D () || ancestorLayer->layoutObject()->style()->preserves3D(); |
244 push(layoutObject, toLayoutSize(layerOffset), accumulatingTransform, /*i sNonUniform*/ false, /*isFixedPosition*/ false, /*hasTransform*/ false); | 245 push(layoutObject, toLayoutSize(layerOffset), accumulatingTransform, /*i sNonUniform*/ false, /*isViewportConstrained*/ false, /*hasTransform*/ false); |
245 return; | 246 return; |
246 } | 247 } |
247 const LayoutBoxModelObject* ancestorLayoutObject = ancestorLayer ? ancestorL ayer->layoutObject() : 0; | 248 const LayoutBoxModelObject* ancestorLayoutObject = ancestorLayer ? ancestorL ayer->layoutObject() : 0; |
248 pushMappingsToAncestor(layoutObject, ancestorLayoutObject); | 249 pushMappingsToAncestor(layoutObject, ancestorLayoutObject); |
249 } | 250 } |
250 | 251 |
251 void LayoutGeometryMap::push(const LayoutObject* layoutObject, const LayoutSize& offsetFromContainer, bool accumulatingTransform, bool isNonUniform, bool isFixe dPosition, bool hasTransform, LayoutSize offsetForFixedPosition) | 252 void LayoutGeometryMap::push(const LayoutObject* layoutObject, const LayoutSize& offsetFromContainer, bool accumulatingTransform, bool isNonUniform, bool isView portConstrained, bool hasTransform, LayoutSize offsetForViewportConstrained) |
252 { | 253 { |
253 // fprintf(stderr, "LayoutGeometryMap::push %p %d,%d isNonUniform=%d\n", layo utObject, offsetFromContainer.width().toInt(), offsetFromContainer.height().toIn t(), isNonUniform); | 254 // fprintf(stderr, "LayoutGeometryMap::push %p %d,%d isNonUniform=%d\n", layo utObject, offsetFromContainer.width().toInt(), offsetFromContainer.height().toIn t(), isNonUniform); |
254 | 255 |
255 ASSERT(m_insertionPosition != kNotFound); | 256 ASSERT(m_insertionPosition != kNotFound); |
256 ASSERT(!layoutObject->isLayoutView() || !m_insertionPosition || m_mapCoordin atesFlags & TraverseDocumentBoundaries); | 257 ASSERT(!layoutObject->isLayoutView() || !m_insertionPosition || m_mapCoordin atesFlags & TraverseDocumentBoundaries); |
257 ASSERT(offsetForFixedPosition.isZero() || layoutObject->isLayoutView()); | 258 ASSERT(offsetForViewportConstrained.isZero() || layoutObject->isLayoutView() ); |
258 | 259 |
259 m_mapping.insert(m_insertionPosition, LayoutGeometryMapStep(layoutObject, ac cumulatingTransform, isNonUniform, isFixedPosition, hasTransform)); | 260 m_mapping.insert(m_insertionPosition, LayoutGeometryMapStep(layoutObject, ac cumulatingTransform, isNonUniform, isViewportConstrained, hasTransform)); |
260 | 261 |
261 LayoutGeometryMapStep& step = m_mapping[m_insertionPosition]; | 262 LayoutGeometryMapStep& step = m_mapping[m_insertionPosition]; |
262 step.m_offset = offsetFromContainer; | 263 step.m_offset = offsetFromContainer; |
263 step.m_offsetForFixedPosition = offsetForFixedPosition; | 264 step.m_offsetForViewportConstrained = offsetForViewportConstrained; |
264 | 265 |
265 stepInserted(step); | 266 stepInserted(step); |
266 } | 267 } |
267 | 268 |
268 void LayoutGeometryMap::push(const LayoutObject* layoutObject, const Transformat ionMatrix& t, bool accumulatingTransform, bool isNonUniform, bool isFixedPositio n, bool hasTransform, LayoutSize offsetForFixedPosition) | 269 void LayoutGeometryMap::push(const LayoutObject* layoutObject, const Transformat ionMatrix& t, bool accumulatingTransform, bool isNonUniform, bool isViewportCons trained, bool hasTransform, LayoutSize offsetForViewportConstrained) |
269 { | 270 { |
270 ASSERT(m_insertionPosition != kNotFound); | 271 ASSERT(m_insertionPosition != kNotFound); |
271 ASSERT(!layoutObject->isLayoutView() || !m_insertionPosition || m_mapCoordin atesFlags & TraverseDocumentBoundaries); | 272 ASSERT(!layoutObject->isLayoutView() || !m_insertionPosition || m_mapCoordin atesFlags & TraverseDocumentBoundaries); |
272 ASSERT(offsetForFixedPosition.isZero() || layoutObject->isLayoutView()); | 273 ASSERT(offsetForViewportConstrained.isZero() || layoutObject->isLayoutView() ); |
273 | 274 |
274 m_mapping.insert(m_insertionPosition, LayoutGeometryMapStep(layoutObject, ac cumulatingTransform, isNonUniform, isFixedPosition, hasTransform)); | 275 m_mapping.insert(m_insertionPosition, LayoutGeometryMapStep(layoutObject, ac cumulatingTransform, isNonUniform, isViewportConstrained, hasTransform)); |
275 | 276 |
276 LayoutGeometryMapStep& step = m_mapping[m_insertionPosition]; | 277 LayoutGeometryMapStep& step = m_mapping[m_insertionPosition]; |
277 step.m_offsetForFixedPosition = offsetForFixedPosition; | 278 step.m_offsetForViewportConstrained = offsetForViewportConstrained; |
278 | 279 |
279 if (!t.isIntegerTranslation()) | 280 if (!t.isIntegerTranslation()) |
280 step.m_transform = adoptPtr(new TransformationMatrix(t)); | 281 step.m_transform = adoptPtr(new TransformationMatrix(t)); |
281 else | 282 else |
282 step.m_offset = LayoutSize(t.e(), t.f()); | 283 step.m_offset = LayoutSize(t.e(), t.f()); |
283 | 284 |
284 stepInserted(step); | 285 stepInserted(step); |
285 } | 286 } |
286 | 287 |
287 void LayoutGeometryMap::popMappingsToAncestor(const LayoutBoxModelObject* ancest orLayoutObject) | 288 void LayoutGeometryMap::popMappingsToAncestor(const LayoutBoxModelObject* ancest orLayoutObject) |
(...skipping 15 matching lines...) Expand all Loading... | |
303 void LayoutGeometryMap::stepInserted(const LayoutGeometryMapStep& step) | 304 void LayoutGeometryMap::stepInserted(const LayoutGeometryMapStep& step) |
304 { | 305 { |
305 m_accumulatedOffset += step.m_offset; | 306 m_accumulatedOffset += step.m_offset; |
306 | 307 |
307 if (step.m_isNonUniform) | 308 if (step.m_isNonUniform) |
308 ++m_nonUniformStepsCount; | 309 ++m_nonUniformStepsCount; |
309 | 310 |
310 if (step.m_transform) | 311 if (step.m_transform) |
311 ++m_transformedStepsCount; | 312 ++m_transformedStepsCount; |
312 | 313 |
313 if (step.m_isFixedPosition) | 314 if (step.m_isViewportConstrained) |
314 ++m_fixedStepsCount; | 315 ++m_viewportConstrainedStepsCount; |
315 } | 316 } |
316 | 317 |
317 void LayoutGeometryMap::stepRemoved(const LayoutGeometryMapStep& step) | 318 void LayoutGeometryMap::stepRemoved(const LayoutGeometryMapStep& step) |
318 { | 319 { |
319 m_accumulatedOffset -= step.m_offset; | 320 m_accumulatedOffset -= step.m_offset; |
320 | 321 |
321 if (step.m_isNonUniform) { | 322 if (step.m_isNonUniform) { |
322 ASSERT(m_nonUniformStepsCount); | 323 ASSERT(m_nonUniformStepsCount); |
323 --m_nonUniformStepsCount; | 324 --m_nonUniformStepsCount; |
324 } | 325 } |
325 | 326 |
326 if (step.m_transform) { | 327 if (step.m_transform) { |
327 ASSERT(m_transformedStepsCount); | 328 ASSERT(m_transformedStepsCount); |
328 --m_transformedStepsCount; | 329 --m_transformedStepsCount; |
329 } | 330 } |
330 | 331 |
331 if (step.m_isFixedPosition) { | 332 if (step.m_isViewportConstrained) { |
332 ASSERT(m_fixedStepsCount); | 333 ASSERT(m_viewportConstrainedStepsCount); |
333 --m_fixedStepsCount; | 334 --m_viewportConstrainedStepsCount; |
334 } | 335 } |
335 } | 336 } |
336 | 337 |
337 #if ENABLE(ASSERT) | 338 #if ENABLE(ASSERT) |
338 bool LayoutGeometryMap::isTopmostLayoutView(const LayoutObject* layoutObject) co nst | 339 bool LayoutGeometryMap::isTopmostLayoutView(const LayoutObject* layoutObject) co nst |
339 { | 340 { |
340 if (!layoutObject->isLayoutView()) | 341 if (!layoutObject->isLayoutView()) |
341 return false; | 342 return false; |
342 | 343 |
343 // If we're not working with multiple LayoutViews, then any view is consider ed | 344 // If we're not working with multiple LayoutViews, then any view is consider ed |
344 // "topmost" (to preserve original behavior). | 345 // "topmost" (to preserve original behavior). |
345 if (!(m_mapCoordinatesFlags & TraverseDocumentBoundaries)) | 346 if (!(m_mapCoordinatesFlags & TraverseDocumentBoundaries)) |
346 return true; | 347 return true; |
347 | 348 |
348 return layoutObject->frame()->isMainFrame(); | 349 return layoutObject->frame()->isMainFrame(); |
349 } | 350 } |
350 #endif | 351 #endif |
351 | 352 |
352 } // namespace blink | 353 } // namespace blink |
OLD | NEW |