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

Side by Side Diff: cc/trees/property_tree.cc

Issue 2733633002: Handle nested position:sticky elements correctly (compositor) (Closed)
Patch Set: More layer id fixes Created 3 years, 9 months 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 <stddef.h> 5 #include <stddef.h>
6 6
7 #include <set> 7 #include <set>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 CombineTransformsBetween(dest_id, source_id, &dest_to_source); 339 CombineTransformsBetween(dest_id, source_id, &dest_to_source);
340 gfx::Transform source_to_dest; 340 gfx::Transform source_to_dest;
341 bool all_are_invertible = dest_to_source.GetInverse(&source_to_dest); 341 bool all_are_invertible = dest_to_source.GetInverse(&source_to_dest);
342 transform->PreconcatTransform(source_to_dest); 342 transform->PreconcatTransform(source_to_dest);
343 return all_are_invertible; 343 return all_are_invertible;
344 } 344 }
345 345
346 gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) { 346 gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) {
347 if (node->sticky_position_constraint_id == -1) 347 if (node->sticky_position_constraint_id == -1)
348 return gfx::Vector2dF(); 348 return gfx::Vector2dF();
349 const StickyPositionNodeData* sticky_data = 349 StickyPositionNodeData* sticky_data = tree->StickyPositionData(node->id);
350 tree->StickyPositionData(node->id);
351 const LayerStickyPositionConstraint& constraint = sticky_data->constraints; 350 const LayerStickyPositionConstraint& constraint = sticky_data->constraints;
352 ScrollNode* scroll_node = 351 ScrollNode* scroll_node =
353 tree->property_trees()->scroll_tree.Node(sticky_data->scroll_ancestor); 352 tree->property_trees()->scroll_tree.Node(sticky_data->scroll_ancestor);
354 gfx::ScrollOffset scroll_offset = 353 gfx::ScrollOffset scroll_offset =
355 tree->property_trees()->scroll_tree.current_scroll_offset( 354 tree->property_trees()->scroll_tree.current_scroll_offset(
356 scroll_node->owning_layer_id); 355 scroll_node->owning_layer_id);
357 gfx::PointF scroll_position(scroll_offset.x(), scroll_offset.y()); 356 gfx::PointF scroll_position(scroll_offset.x(), scroll_offset.y());
358 TransformNode* scroll_ancestor_transform_node = 357 TransformNode* scroll_ancestor_transform_node =
359 tree->Node(scroll_node->transform_id); 358 tree->Node(scroll_node->transform_id);
360 if (scroll_ancestor_transform_node->scrolls) { 359 if (scroll_ancestor_transform_node->scrolls) {
361 // The scroll position does not include snapping which shifts the scroll 360 // The scroll position does not include snapping which shifts the scroll
362 // offset to align to a pixel boundary, we need to manually include it here. 361 // offset to align to a pixel boundary, we need to manually include it here.
363 // In this case, snapping is caused by a scroll. 362 // In this case, snapping is caused by a scroll.
364 scroll_position -= scroll_ancestor_transform_node->snap_amount; 363 scroll_position -= scroll_ancestor_transform_node->snap_amount;
365 } 364 }
366 365
367 gfx::RectF clip( 366 gfx::RectF clip(
368 scroll_position, 367 scroll_position,
369 gfx::SizeF(tree->property_trees()->scroll_tree.scroll_clip_layer_bounds( 368 gfx::SizeF(tree->property_trees()->scroll_tree.scroll_clip_layer_bounds(
370 scroll_node->id))); 369 scroll_node->id)));
371 gfx::Vector2dF sticky_offset(
372 constraint.scroll_container_relative_sticky_box_rect.OffsetFromOrigin());
373 gfx::Vector2dF layer_offset(sticky_data->main_thread_offset); 370 gfx::Vector2dF layer_offset(sticky_data->main_thread_offset);
374 371
372 gfx::Vector2dF ancestor_sticky_box_offset;
373 if (sticky_data->nearest_node_shifting_sticky_box !=
374 TransformTree::kInvalidNodeId) {
375 ancestor_sticky_box_offset =
376 tree->StickyPositionData(sticky_data->nearest_node_shifting_sticky_box)
377 ->total_sticky_box_sticky_offset;
378 }
379
380 gfx::Vector2dF ancestor_containing_block_offset;
381 if (sticky_data->nearest_node_shifting_containing_block !=
382 TransformTree::kInvalidNodeId) {
383 ancestor_containing_block_offset =
384 tree->StickyPositionData(
385 sticky_data->nearest_node_shifting_containing_block)
386 ->total_containing_block_sticky_offset;
387 }
388
389 // Compute the current position of the constraint rects based on the original
390 // positions and the offsets from ancestor sticky elements.
391 gfx::RectF sticky_box_rect =
392 constraint.scroll_container_relative_sticky_box_rect +
393 ancestor_sticky_box_offset + ancestor_containing_block_offset;
394 gfx::RectF containing_block_rect =
395 constraint.scroll_container_relative_containing_block_rect +
396 ancestor_containing_block_offset;
397
398 gfx::Vector2dF sticky_offset(sticky_box_rect.OffsetFromOrigin());
399
375 // In each of the following cases, we measure the limit which is the point 400 // In each of the following cases, we measure the limit which is the point
376 // that the element should stick to, clamping on one side to 0 (because sticky 401 // that the element should stick to, clamping on one side to 0 (because sticky
377 // only pushes elements in one direction). Then we clamp to how far we can 402 // only pushes elements in one direction). Then we clamp to how far we can
378 // push the element in that direction without being pushed outside of its 403 // push the element in that direction without being pushed outside of its
379 // containing block. 404 // containing block.
380 // 405 //
381 // Note: The order of applying the sticky constraints is applied such that 406 // Note: The order of applying the sticky constraints is applied such that
382 // left offset takes precedence over right offset, and top takes precedence 407 // left offset takes precedence over right offset, and top takes precedence
383 // over bottom offset. 408 // over bottom offset.
384 if (constraint.is_anchored_right) { 409 if (constraint.is_anchored_right) {
385 float right_limit = clip.right() - constraint.right_offset; 410 float right_limit = clip.right() - constraint.right_offset;
386 float right_delta = std::min<float>( 411 float right_delta =
387 0, right_limit - 412 std::min<float>(0, right_limit - sticky_box_rect.right());
388 constraint.scroll_container_relative_sticky_box_rect.right()); 413 float available_space =
389 float available_space = std::min<float>( 414 std::min<float>(0, containing_block_rect.x() - sticky_box_rect.x());
390 0, constraint.scroll_container_relative_containing_block_rect.x() -
391 constraint.scroll_container_relative_sticky_box_rect.x());
392 if (right_delta < available_space) 415 if (right_delta < available_space)
393 right_delta = available_space; 416 right_delta = available_space;
394 sticky_offset.set_x(sticky_offset.x() + right_delta); 417 sticky_offset.set_x(sticky_offset.x() + right_delta);
395 } 418 }
396 if (constraint.is_anchored_left) { 419 if (constraint.is_anchored_left) {
397 float left_limit = clip.x() + constraint.left_offset; 420 float left_limit = clip.x() + constraint.left_offset;
398 float left_delta = std::max<float>( 421 float left_delta = std::max<float>(0, left_limit - sticky_box_rect.x());
399 0,
400 left_limit - constraint.scroll_container_relative_sticky_box_rect.x());
401 float available_space = std::max<float>( 422 float available_space = std::max<float>(
402 0, constraint.scroll_container_relative_containing_block_rect.right() - 423 0, containing_block_rect.right() - sticky_box_rect.right());
403 constraint.scroll_container_relative_sticky_box_rect.right());
404 if (left_delta > available_space) 424 if (left_delta > available_space)
405 left_delta = available_space; 425 left_delta = available_space;
406 sticky_offset.set_x(sticky_offset.x() + left_delta); 426 sticky_offset.set_x(sticky_offset.x() + left_delta);
407 } 427 }
408 if (constraint.is_anchored_bottom) { 428 if (constraint.is_anchored_bottom) {
409 float bottom_limit = clip.bottom() - constraint.bottom_offset; 429 float bottom_limit = clip.bottom() - constraint.bottom_offset;
410 float bottom_delta = std::min<float>( 430 float bottom_delta =
411 0, bottom_limit - 431 std::min<float>(0, bottom_limit - sticky_box_rect.bottom());
412 constraint.scroll_container_relative_sticky_box_rect.bottom()); 432 float available_space =
413 float available_space = std::min<float>( 433 std::min<float>(0, containing_block_rect.y() - sticky_box_rect.y());
414 0, constraint.scroll_container_relative_containing_block_rect.y() -
415 constraint.scroll_container_relative_sticky_box_rect.y());
416 if (bottom_delta < available_space) 434 if (bottom_delta < available_space)
417 bottom_delta = available_space; 435 bottom_delta = available_space;
418 sticky_offset.set_y(sticky_offset.y() + bottom_delta); 436 sticky_offset.set_y(sticky_offset.y() + bottom_delta);
419 } 437 }
420 if (constraint.is_anchored_top) { 438 if (constraint.is_anchored_top) {
421 float top_limit = clip.y() + constraint.top_offset; 439 float top_limit = clip.y() + constraint.top_offset;
422 float top_delta = std::max<float>( 440 float top_delta = std::max<float>(0, top_limit - sticky_box_rect.y());
423 0,
424 top_limit - constraint.scroll_container_relative_sticky_box_rect.y());
425 float available_space = std::max<float>( 441 float available_space = std::max<float>(
426 0, constraint.scroll_container_relative_containing_block_rect.bottom() - 442 0, containing_block_rect.bottom() - sticky_box_rect.bottom());
427 constraint.scroll_container_relative_sticky_box_rect.bottom());
428 if (top_delta > available_space) 443 if (top_delta > available_space)
429 top_delta = available_space; 444 top_delta = available_space;
430 sticky_offset.set_y(sticky_offset.y() + top_delta); 445 sticky_offset.set_y(sticky_offset.y() + top_delta);
431 } 446 }
447
448 sticky_data->total_sticky_box_sticky_offset =
449 ancestor_sticky_box_offset + sticky_offset -
450 sticky_box_rect.OffsetFromOrigin();
451 sticky_data->total_containing_block_sticky_offset =
452 ancestor_sticky_box_offset + ancestor_containing_block_offset +
453 sticky_offset - sticky_box_rect.OffsetFromOrigin();
454
432 return sticky_offset - layer_offset - node->source_to_parent - 455 return sticky_offset - layer_offset - node->source_to_parent -
433 constraint.scroll_container_relative_sticky_box_rect 456 sticky_box_rect.OffsetFromOrigin();
434 .OffsetFromOrigin();
435 } 457 }
436 458
437 void TransformTree::UpdateLocalTransform(TransformNode* node) { 459 void TransformTree::UpdateLocalTransform(TransformNode* node) {
438 gfx::Transform transform = node->post_local; 460 gfx::Transform transform = node->post_local;
439 if (NeedsSourceToParentUpdate(node)) { 461 if (NeedsSourceToParentUpdate(node)) {
440 gfx::Transform to_parent; 462 gfx::Transform to_parent;
441 ComputeTranslation(node->source_node_id, node->parent_id, &to_parent); 463 ComputeTranslation(node->source_node_id, node->parent_id, &to_parent);
442 gfx::Vector2dF unsnapping; 464 gfx::Vector2dF unsnapping;
443 TransformNode* current; 465 TransformNode* current;
444 TransformNode* parent_node; 466 TransformNode* parent_node;
(...skipping 1669 matching lines...) Expand 10 before | Expand all | Expand 10 after
2114 const EffectNode* effect_node = effect_tree.Node(effect_id); 2136 const EffectNode* effect_node = effect_tree.Node(effect_id);
2115 2137
2116 if (effect_node->surface_contents_scale.x() != 0.0 && 2138 if (effect_node->surface_contents_scale.x() != 0.0 &&
2117 effect_node->surface_contents_scale.y() != 0.0) 2139 effect_node->surface_contents_scale.y() != 0.0)
2118 screen_space_transform.Scale(1.0 / effect_node->surface_contents_scale.x(), 2140 screen_space_transform.Scale(1.0 / effect_node->surface_contents_scale.x(),
2119 1.0 / effect_node->surface_contents_scale.y()); 2141 1.0 / effect_node->surface_contents_scale.y());
2120 return screen_space_transform; 2142 return screen_space_transform;
2121 } 2143 }
2122 2144
2123 } // namespace cc 2145 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698