15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Portions are Copyright (C) 1998 Netscape Communications Corporation. 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Other contributors: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Robert O'Callahan <roc+@cs.cmu.edu> 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * David Baron <dbaron@fas.harvard.edu> 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Christian Biesinger <cbiesinger@web.de> 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Randall Jesup <rjesup@wgate.com> 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de> 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Josh Soref <timeless@mac.com> 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boris Zbarsky <bzbarsky@mit.edu> 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Lesser General Public 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2.1 of the License, or (at your option) any later version. 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Lesser General Public License for more details. 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Lesser General Public 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License along with this library; if not, write to the Free Software 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Alternatively, the contents of this file may be used under the terms 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * of either the Mozilla Public License Version 1.1, found at 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (the "GPL"), in which case the provisions of the MPL or the GPL are 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * applicable instead of those above. If you wish to allow use of your 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version of this file only under the terms of one of those two 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * licenses (the MPL or the GPL) and not to allow others to use your 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version of this file under the LGPL, indicate your decision by 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * deletingthe provisions above and replace them with the notice and 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * other provisions required by the MPL or the GPL, as the case may be. 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * If you do not delete the provisions above, a recipient may use your 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version of this file under any of the LGPL, the MPL or the GPL. 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 4509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/rendering/ScrollAlignment.h" 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 47f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#include "platform/geometry/LayoutRect.h" 48f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 49c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const ScrollAlignment ScrollAlignment::alignCenterIfNeeded = { ScrollAlignmentNoScroll, ScrollAlignmentCenter, ScrollAlignmentClosestEdge }; 5209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const ScrollAlignment ScrollAlignment::alignToEdgeIfNeeded = { ScrollAlignmentNoScroll, ScrollAlignmentClosestEdge, ScrollAlignmentClosestEdge }; 5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const ScrollAlignment ScrollAlignment::alignCenterAlways = { ScrollAlignmentCenter, ScrollAlignmentCenter, ScrollAlignmentCenter }; 5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const ScrollAlignment ScrollAlignment::alignTopAlways = { ScrollAlignmentTop, ScrollAlignmentTop, ScrollAlignmentTop }; 5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const ScrollAlignment ScrollAlignment::alignBottomAlways = { ScrollAlignmentBottom, ScrollAlignmentBottom, ScrollAlignmentBottom }; 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 57f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#define MIN_INTERSECT_FOR_REVEAL 32 58f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 59f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)LayoutRect ScrollAlignment::getRectToExpose(const LayoutRect& visibleRect, const LayoutRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY) 60f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){ 61f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // Determine the appropriate X behavior. 6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ScrollAlignmentBehavior scrollX; 63f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) LayoutRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height()); 64f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) LayoutUnit intersectWidth = intersection(visibleRect, exposeRectX).width(); 65f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL) { 66f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // If the rectangle is fully visible, use the specified visible behavior. 67f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // If the rectangle is partially visible, but over a certain threshold, 68f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // then treat it as fully visible to avoid unnecessary horizontal scrolling 69f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) scrollX = getVisibleBehavior(alignX); 70f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } else if (intersectWidth == visibleRect.width()) { 71f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work. 72f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) scrollX = getVisibleBehavior(alignX); 7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (scrollX == ScrollAlignmentCenter) 7409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) scrollX = ScrollAlignmentNoScroll; 75f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } else if (intersectWidth > 0) { 76f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior 77f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) scrollX = getPartialBehavior(alignX); 78f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } else { 79f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) scrollX = getHiddenBehavior(alignX); 80f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } 81f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 8209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (scrollX == ScrollAlignmentClosestEdge) { 83f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // Closest edge is the right in two cases: 84f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // (1) exposeRect to the right of and smaller than visibleRect 85f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // (2) exposeRect to the left of and larger than visibleRect 86f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if ((exposeRect.maxX() > visibleRect.maxX() && exposeRect.width() < visibleRect.width()) 87f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) || (exposeRect.maxX() < visibleRect.maxX() && exposeRect.width() > visibleRect.width())) { 8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) scrollX = ScrollAlignmentRight; 89f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } 90f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } 91f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 92f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // Given the X behavior, compute the X coordinate. 93f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) LayoutUnit x; 9409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (scrollX == ScrollAlignmentNoScroll) 95f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) x = visibleRect.x(); 9609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) else if (scrollX == ScrollAlignmentRight) 97f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) x = exposeRect.maxX() - visibleRect.width(); 9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) else if (scrollX == ScrollAlignmentCenter) 99f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2; 100f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) else 101f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) x = exposeRect.x(); 102f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 103f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // Determine the appropriate Y behavior. 10409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ScrollAlignmentBehavior scrollY; 105f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) LayoutRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height()); 106f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) LayoutUnit intersectHeight = intersection(visibleRect, exposeRectY).height(); 107f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (intersectHeight == exposeRect.height()) { 108f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // If the rectangle is fully visible, use the specified visible behavior. 109f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) scrollY = getVisibleBehavior(alignY); 110f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } else if (intersectHeight == visibleRect.height()) { 111f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work. 112f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) scrollY = getVisibleBehavior(alignY); 11309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (scrollY == ScrollAlignmentCenter) 11409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) scrollY = ScrollAlignmentNoScroll; 115f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } else if (intersectHeight > 0) { 116f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // If the rectangle is partially visible, use the specified partial behavior 117f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) scrollY = getPartialBehavior(alignY); 118f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } else { 119f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) scrollY = getHiddenBehavior(alignY); 120f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } 121f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 12209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (scrollY == ScrollAlignmentClosestEdge) { 123f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // Closest edge is the bottom in two cases: 124f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // (1) exposeRect below and smaller than visibleRect 125f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // (2) exposeRect above and larger than visibleRect 126f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if ((exposeRect.maxY() > visibleRect.maxY() && exposeRect.height() < visibleRect.height()) 127f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) || (exposeRect.maxY() < visibleRect.maxY() && exposeRect.height() > visibleRect.height())) { 12809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) scrollY = ScrollAlignmentBottom; 129f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } 130f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } 131f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 132f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // Given the Y behavior, compute the Y coordinate. 133f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) LayoutUnit y; 13409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (scrollY == ScrollAlignmentNoScroll) 135f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) y = visibleRect.y(); 13609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) else if (scrollY == ScrollAlignmentBottom) 137f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) y = exposeRect.maxY() - visibleRect.height(); 13809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) else if (scrollY == ScrollAlignmentCenter) 139f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2; 140f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) else 141f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) y = exposeRect.y(); 142f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 143f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) return LayoutRect(LayoutPoint(x, y), visibleRect.size()); 144f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)} 145f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 146c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}; // namespace blink 147