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

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

Issue 2733633002: Handle nested position:sticky elements correctly (compositor) (Closed)
Patch Set: Addressed the easier reviewer comments. 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
« no previous file with comments | « cc/trees/property_tree.h ('k') | cc/trees/property_tree_builder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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); 350 LayerStickyPositionConstraint& constraint = sticky_data->constraints;
351 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
375 // In each of the following cases, we measure the limit which is the point 372 // 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 373 // 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 374 // 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 375 // push the element in that direction without being pushed outside of its
379 // containing block. 376 // containing block.
380 // 377 //
381 // Note: The order of applying the sticky constraints is applied such that 378 // Note: The order of applying the sticky constraints is applied such that
382 // left offset takes precedence over right offset, and top takes precedence 379 // left offset takes precedence over right offset, and top takes precedence
383 // over bottom offset. 380 // over bottom offset.
381
382 gfx::Vector2dF ancestor_sticky_box_offset;
383 if (sticky_data->nearest_node_shifting_sticky_box >= 0) {
384 ancestor_sticky_box_offset =
385 tree->StickyPositionData(sticky_data->nearest_node_shifting_sticky_box)
386 ->constraints.total_sticky_box_sticky_offset;
387 }
388
389 gfx::Vector2dF ancestor_containing_block_offset;
390 if (sticky_data->nearest_node_shifting_containing_block >= 0) {
391 ancestor_containing_block_offset =
392 tree->StickyPositionData(
393 sticky_data->nearest_node_shifting_containing_block)
394 ->constraints.total_containing_block_sticky_offset;
395 }
396
397 gfx::Rect sticky_box_rect =
398 constraint.scroll_container_relative_sticky_box_rect;
399 gfx::Rect containing_block_rect =
400 constraint.scroll_container_relative_containing_block_rect;
401 sticky_box_rect += gfx::ToFlooredVector2d(ancestor_sticky_box_offset +
flackr 2017/03/13 19:49:45 This loss of precision seems dangerous, we could e
402 ancestor_containing_block_offset);
403 containing_block_rect +=
404 gfx::ToFlooredVector2d(ancestor_containing_block_offset);
405
406 gfx::Vector2dF sticky_offset(sticky_box_rect.OffsetFromOrigin());
407
384 if (constraint.is_anchored_right) { 408 if (constraint.is_anchored_right) {
385 float right_limit = clip.right() - constraint.right_offset; 409 float right_limit = clip.right() - constraint.right_offset;
386 float right_delta = std::min<float>( 410 float right_delta =
387 0, right_limit - 411 std::min<float>(0, right_limit - sticky_box_rect.right());
388 constraint.scroll_container_relative_sticky_box_rect.right()); 412 float available_space =
389 float available_space = std::min<float>( 413 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) 414 if (right_delta < available_space)
393 right_delta = available_space; 415 right_delta = available_space;
394 sticky_offset.set_x(sticky_offset.x() + right_delta); 416 sticky_offset.set_x(sticky_offset.x() + right_delta);
395 } 417 }
396 if (constraint.is_anchored_left) { 418 if (constraint.is_anchored_left) {
397 float left_limit = clip.x() + constraint.left_offset; 419 float left_limit = clip.x() + constraint.left_offset;
398 float left_delta = std::max<float>( 420 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>( 421 float available_space = std::max<float>(
402 0, constraint.scroll_container_relative_containing_block_rect.right() - 422 0, containing_block_rect.right() - sticky_box_rect.right());
403 constraint.scroll_container_relative_sticky_box_rect.right());
404 if (left_delta > available_space) 423 if (left_delta > available_space)
405 left_delta = available_space; 424 left_delta = available_space;
406 sticky_offset.set_x(sticky_offset.x() + left_delta); 425 sticky_offset.set_x(sticky_offset.x() + left_delta);
407 } 426 }
408 if (constraint.is_anchored_bottom) { 427 if (constraint.is_anchored_bottom) {
409 float bottom_limit = clip.bottom() - constraint.bottom_offset; 428 float bottom_limit = clip.bottom() - constraint.bottom_offset;
410 float bottom_delta = std::min<float>( 429 float bottom_delta =
411 0, bottom_limit - 430 std::min<float>(0, bottom_limit - sticky_box_rect.bottom());
412 constraint.scroll_container_relative_sticky_box_rect.bottom()); 431 float available_space =
413 float available_space = std::min<float>( 432 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) 433 if (bottom_delta < available_space)
417 bottom_delta = available_space; 434 bottom_delta = available_space;
418 sticky_offset.set_y(sticky_offset.y() + bottom_delta); 435 sticky_offset.set_y(sticky_offset.y() + bottom_delta);
419 } 436 }
420 if (constraint.is_anchored_top) { 437 if (constraint.is_anchored_top) {
421 float top_limit = clip.y() + constraint.top_offset; 438 float top_limit = clip.y() + constraint.top_offset;
422 float top_delta = std::max<float>( 439 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>( 440 float available_space = std::max<float>(
426 0, constraint.scroll_container_relative_containing_block_rect.bottom() - 441 0, containing_block_rect.bottom() - sticky_box_rect.bottom());
427 constraint.scroll_container_relative_sticky_box_rect.bottom());
428 if (top_delta > available_space) 442 if (top_delta > available_space)
429 top_delta = available_space; 443 top_delta = available_space;
430 sticky_offset.set_y(sticky_offset.y() + top_delta); 444 sticky_offset.set_y(sticky_offset.y() + top_delta);
431 } 445 }
446
447 constraint.total_sticky_box_sticky_offset =
448 ancestor_sticky_box_offset + sticky_offset -
449 sticky_box_rect.OffsetFromOrigin();
450 constraint.total_containing_block_sticky_offset =
451 ancestor_sticky_box_offset + ancestor_containing_block_offset +
452 sticky_offset - sticky_box_rect.OffsetFromOrigin();
453
432 return sticky_offset - layer_offset - node->source_to_parent - 454 return sticky_offset - layer_offset - node->source_to_parent -
433 constraint.scroll_container_relative_sticky_box_rect 455 sticky_box_rect.OffsetFromOrigin();
434 .OffsetFromOrigin();
435 } 456 }
436 457
437 void TransformTree::UpdateLocalTransform(TransformNode* node) { 458 void TransformTree::UpdateLocalTransform(TransformNode* node) {
438 gfx::Transform transform = node->post_local; 459 gfx::Transform transform = node->post_local;
439 if (NeedsSourceToParentUpdate(node)) { 460 if (NeedsSourceToParentUpdate(node)) {
440 gfx::Transform to_parent; 461 gfx::Transform to_parent;
441 ComputeTranslation(node->source_node_id, node->parent_id, &to_parent); 462 ComputeTranslation(node->source_node_id, node->parent_id, &to_parent);
442 gfx::Vector2dF unsnapping; 463 gfx::Vector2dF unsnapping;
443 TransformNode* current; 464 TransformNode* current;
444 TransformNode* parent_node; 465 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); 2135 const EffectNode* effect_node = effect_tree.Node(effect_id);
2115 2136
2116 if (effect_node->surface_contents_scale.x() != 0.0 && 2137 if (effect_node->surface_contents_scale.x() != 0.0 &&
2117 effect_node->surface_contents_scale.y() != 0.0) 2138 effect_node->surface_contents_scale.y() != 0.0)
2118 screen_space_transform.Scale(1.0 / effect_node->surface_contents_scale.x(), 2139 screen_space_transform.Scale(1.0 / effect_node->surface_contents_scale.x(),
2119 1.0 / effect_node->surface_contents_scale.y()); 2140 1.0 / effect_node->surface_contents_scale.y());
2120 return screen_space_transform; 2141 return screen_space_transform;
2121 } 2142 }
2122 2143
2123 } // namespace cc 2144 } // namespace cc
OLDNEW
« no previous file with comments | « cc/trees/property_tree.h ('k') | cc/trees/property_tree_builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698