Chromium Code Reviews| 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 |