/* Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ #import "CGRect+ASConvenience.h" #import "ASScrollDirection.h" #import "ASLayoutController.h" struct ASDirectionalScreenfulBuffer { CGFloat positiveDirection; // Positive relative to iOS Core Animation layer coordinate space. CGFloat negativeDirection; }; typedef struct ASDirectionalScreenfulBuffer ASDirectionalScreenfulBuffer; ASDirectionalScreenfulBuffer ASDirectionalScreenfulBufferHorizontal(ASScrollDirection scrollDirection, ASRangeTuningParameters rangeTuningParameters) { ASDirectionalScreenfulBuffer horizontalBuffer = {0, 0}; BOOL movingRight = ASScrollDirectionContainsRight(scrollDirection); horizontalBuffer.positiveDirection = movingRight ? rangeTuningParameters.leadingBufferScreenfuls : rangeTuningParameters.trailingBufferScreenfuls; horizontalBuffer.negativeDirection = movingRight ? rangeTuningParameters.trailingBufferScreenfuls : rangeTuningParameters.leadingBufferScreenfuls; return horizontalBuffer; } ASDirectionalScreenfulBuffer ASDirectionalScreenfulBufferVertical(ASScrollDirection scrollDirection, ASRangeTuningParameters rangeTuningParameters) { ASDirectionalScreenfulBuffer verticalBuffer = {0, 0}; BOOL movingDown = ASScrollDirectionContainsDown(scrollDirection); verticalBuffer.positiveDirection = movingDown ? rangeTuningParameters.leadingBufferScreenfuls : rangeTuningParameters.trailingBufferScreenfuls; verticalBuffer.negativeDirection = movingDown ? rangeTuningParameters.trailingBufferScreenfuls : rangeTuningParameters.leadingBufferScreenfuls; return verticalBuffer; } CGRect CGRectExpandHorizontally(CGRect rect, ASDirectionalScreenfulBuffer buffer) { CGFloat negativeDirectionWidth = buffer.negativeDirection * rect.size.width; CGFloat positiveDirectionWidth = buffer.positiveDirection * rect.size.width; rect.size.width = negativeDirectionWidth + rect.size.width + positiveDirectionWidth; rect.origin.x -= negativeDirectionWidth; return rect; } CGRect CGRectExpandVertically(CGRect rect, ASDirectionalScreenfulBuffer buffer) { CGFloat negativeDirectionHeight = buffer.negativeDirection * rect.size.height; CGFloat positiveDirectionHeight = buffer.positiveDirection * rect.size.height; rect.size.height = negativeDirectionHeight + rect.size.height + positiveDirectionHeight; rect.origin.y -= negativeDirectionHeight; return rect; } CGRect CGRectExpandToRangeWithScrollableDirections(CGRect rect, ASRangeTuningParameters tuningParameters, ASScrollDirection scrollableDirections, ASScrollDirection scrollDirection) { // Can scroll horizontally - expand the range appropriately if (ASScrollDirectionContainsHorizontalDirection(scrollableDirections)) { ASDirectionalScreenfulBuffer horizontalBuffer = ASDirectionalScreenfulBufferHorizontal(scrollDirection, tuningParameters); rect = CGRectExpandHorizontally(rect, horizontalBuffer); } // Can scroll vertically - expand the range appropriately if (ASScrollDirectionContainsVerticalDirection(scrollableDirections)) { ASDirectionalScreenfulBuffer verticalBuffer = ASDirectionalScreenfulBufferVertical(scrollDirection, tuningParameters); rect = CGRectExpandVertically(rect, verticalBuffer); } return rect; }