summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/scroll/scroll_alignment.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/scroll/scroll_alignment.cc')
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scroll_alignment.cc193
1 files changed, 193 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scroll_alignment.cc b/chromium/third_party/blink/renderer/platform/scroll/scroll_alignment.cc
new file mode 100644
index 00000000000..c8544902612
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scroll/scroll_alignment.cc
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ * Robert O'Callahan <roc+@cs.cmu.edu>
+ * David Baron <dbaron@fas.harvard.edu>
+ * Christian Biesinger <cbiesinger@web.de>
+ * Randall Jesup <rjesup@wgate.com>
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ * Josh Soref <timeless@mac.com>
+ * Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "third_party/blink/renderer/platform/scroll/scroll_alignment.h"
+
+#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
+
+namespace blink {
+
+const ScrollAlignment ScrollAlignment::kAlignCenterIfNeeded = {
+ kScrollAlignmentNoScroll, kScrollAlignmentCenter,
+ kScrollAlignmentClosestEdge};
+const ScrollAlignment ScrollAlignment::kAlignToEdgeIfNeeded = {
+ kScrollAlignmentNoScroll, kScrollAlignmentClosestEdge,
+ kScrollAlignmentClosestEdge};
+const ScrollAlignment ScrollAlignment::kAlignCenterAlways = {
+ kScrollAlignmentCenter, kScrollAlignmentCenter, kScrollAlignmentCenter};
+const ScrollAlignment ScrollAlignment::kAlignTopAlways = {
+ kScrollAlignmentTop, kScrollAlignmentTop, kScrollAlignmentTop};
+const ScrollAlignment ScrollAlignment::kAlignBottomAlways = {
+ kScrollAlignmentBottom, kScrollAlignmentBottom, kScrollAlignmentBottom};
+const ScrollAlignment ScrollAlignment::kAlignLeftAlways = {
+ kScrollAlignmentLeft, kScrollAlignmentLeft, kScrollAlignmentLeft};
+const ScrollAlignment ScrollAlignment::kAlignRightAlways = {
+ kScrollAlignmentRight, kScrollAlignmentRight, kScrollAlignmentRight};
+
+#define MIN_INTERSECT_FOR_REVEAL 32
+
+ScrollOffset ScrollAlignment::GetScrollOffsetToExpose(
+ const LayoutRect& scroll_snapport_rect,
+ const LayoutRect& expose_rect,
+ const ScrollAlignment& align_x,
+ const ScrollAlignment& align_y,
+ const ScrollOffset& current_scroll_offset) {
+ // Prevent degenerate cases by giving the visible rect a minimum non-0 size.
+ LayoutRect non_zero_visible_rect(scroll_snapport_rect);
+ LayoutUnit minimum_layout_unit;
+ minimum_layout_unit.SetRawValue(1);
+ if (non_zero_visible_rect.Width() == LayoutUnit())
+ non_zero_visible_rect.SetWidth(minimum_layout_unit);
+ if (non_zero_visible_rect.Height() == LayoutUnit())
+ non_zero_visible_rect.SetHeight(minimum_layout_unit);
+
+ // Determine the appropriate X behavior.
+ ScrollAlignmentBehavior scroll_x;
+ LayoutRect expose_rect_x(expose_rect.X(), non_zero_visible_rect.Y(),
+ expose_rect.Width(), non_zero_visible_rect.Height());
+ LayoutUnit intersect_width =
+ Intersection(non_zero_visible_rect, expose_rect_x).Width();
+ if (intersect_width == expose_rect.Width() ||
+ intersect_width >= MIN_INTERSECT_FOR_REVEAL) {
+ // If the rectangle is fully visible, use the specified visible behavior.
+ // If the rectangle is partially visible, but over a certain threshold,
+ // then treat it as fully visible to avoid unnecessary horizontal scrolling
+ scroll_x = GetVisibleBehavior(align_x);
+ } else if (intersect_width == non_zero_visible_rect.Width()) {
+ // If the rect is bigger than the visible area, don't bother trying to
+ // center. Other alignments will work.
+ scroll_x = GetVisibleBehavior(align_x);
+ if (scroll_x == kScrollAlignmentCenter)
+ scroll_x = kScrollAlignmentNoScroll;
+ } else if (intersect_width > 0) {
+ // If the rectangle is partially visible, but not above the minimum
+ // threshold, use the specified partial behavior
+ scroll_x = GetPartialBehavior(align_x);
+ } else {
+ scroll_x = GetHiddenBehavior(align_x);
+ }
+
+ if (scroll_x == kScrollAlignmentClosestEdge) {
+ // Closest edge is the right in two cases:
+ // (1) exposeRect to the right of and smaller than nonZeroVisibleRect
+ // (2) exposeRect to the left of and larger than nonZeroVisibleRect
+ if ((expose_rect.MaxX() > non_zero_visible_rect.MaxX() &&
+ expose_rect.Width() < non_zero_visible_rect.Width()) ||
+ (expose_rect.MaxX() < non_zero_visible_rect.MaxX() &&
+ expose_rect.Width() > non_zero_visible_rect.Width())) {
+ scroll_x = kScrollAlignmentRight;
+ }
+ }
+
+ // Determine the appropriate Y behavior.
+ ScrollAlignmentBehavior scroll_y;
+ LayoutRect expose_rect_y(non_zero_visible_rect.X(), expose_rect.Y(),
+ non_zero_visible_rect.Width(), expose_rect.Height());
+ LayoutUnit intersect_height =
+ Intersection(non_zero_visible_rect, expose_rect_y).Height();
+ if (intersect_height == expose_rect.Height()) {
+ // If the rectangle is fully visible, use the specified visible behavior.
+ scroll_y = GetVisibleBehavior(align_y);
+ } else if (intersect_height == non_zero_visible_rect.Height()) {
+ // If the rect is bigger than the visible area, don't bother trying to
+ // center. Other alignments will work.
+ scroll_y = GetVisibleBehavior(align_y);
+ if (scroll_y == kScrollAlignmentCenter)
+ scroll_y = kScrollAlignmentNoScroll;
+ } else if (intersect_height > 0) {
+ // If the rectangle is partially visible, use the specified partial behavior
+ scroll_y = GetPartialBehavior(align_y);
+ } else {
+ scroll_y = GetHiddenBehavior(align_y);
+ }
+
+ if (scroll_y == kScrollAlignmentClosestEdge) {
+ // Closest edge is the bottom in two cases:
+ // (1) exposeRect below and smaller than nonZeroVisibleRect
+ // (2) exposeRect above and larger than nonZeroVisibleRect
+ if ((expose_rect.MaxY() > non_zero_visible_rect.MaxY() &&
+ expose_rect.Height() < non_zero_visible_rect.Height()) ||
+ (expose_rect.MaxY() < non_zero_visible_rect.MaxY() &&
+ expose_rect.Height() > non_zero_visible_rect.Height())) {
+ scroll_y = kScrollAlignmentBottom;
+ }
+ }
+
+ // We would like calculate the ScrollPosition to move |expose_rect| inside
+ // the scroll_snapport, which is based on the scroll_origin of the scroller.
+ non_zero_visible_rect.Move(LayoutSize(-current_scroll_offset));
+
+ // Given the X behavior, compute the X coordinate.
+ float x;
+ if (scroll_x == kScrollAlignmentNoScroll) {
+ x = current_scroll_offset.Width();
+ } else if (scroll_x == kScrollAlignmentRight) {
+ x = (expose_rect.MaxX() - non_zero_visible_rect.MaxX()).ToFloat();
+ } else if (scroll_x == kScrollAlignmentCenter) {
+ x = ((expose_rect.X() + expose_rect.MaxX() -
+ (non_zero_visible_rect.X() + non_zero_visible_rect.MaxX())) /
+ 2)
+ .ToFloat();
+ } else {
+ x = (expose_rect.X() - non_zero_visible_rect.X()).ToFloat();
+ }
+
+ // Given the Y behavior, compute the Y coordinate.
+ float y;
+ if (scroll_y == kScrollAlignmentNoScroll) {
+ y = current_scroll_offset.Height();
+ } else if (scroll_y == kScrollAlignmentBottom) {
+ y = (expose_rect.MaxY() - non_zero_visible_rect.MaxY()).ToFloat();
+ } else if (scroll_y == kScrollAlignmentCenter) {
+ y = ((expose_rect.Y() + expose_rect.MaxY() -
+ (non_zero_visible_rect.Y() + non_zero_visible_rect.MaxY())) /
+ 2)
+ .ToFloat();
+ } else {
+ y = (expose_rect.Y() - non_zero_visible_rect.Y()).ToFloat();
+ }
+
+ return ScrollOffset(x, y);
+}
+
+} // namespace blink