From c469ad273bb1df9a09eb6a987f65c08055c4361d Mon Sep 17 00:00:00 2001 From: Levi McCallum Date: Fri, 20 May 2016 12:31:10 -0700 Subject: [PATCH] [ASLayout] Cache constrained size range --- AsyncDisplayKit/ASDisplayNode.mm | 9 +++-- .../Layout/ASBackgroundLayoutSpec.mm | 5 ++- AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm | 9 +++-- AsyncDisplayKit/Layout/ASLayout.h | 12 ++++++- AsyncDisplayKit/Layout/ASLayout.mm | 33 ++++++++++++++++--- AsyncDisplayKit/Layout/ASLayoutSpec.mm | 4 ++- AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm | 5 ++- AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm | 5 ++- .../Layout/ASRelativeLayoutSpec.mm | 5 ++- AsyncDisplayKit/Layout/ASStackLayoutSpec.mm | 5 ++- AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm | 1 + .../Private/ASStackUnpositionedLayout.mm | 2 +- .../ASLayoutSpecSnapshotTestsHelper.m | 5 ++- 13 files changed, 82 insertions(+), 18 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 3b3e6327a1..79e1ece249 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1956,7 +1956,10 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) // Make sure layoutableObject of the root layout is `self`, so that the flattened layout will be structurally correct. if (layout.layoutableObject != self) { layout.position = CGPointZero; - layout = [ASLayout layoutWithLayoutableObject:self size:layout.size sublayouts:@[layout]]; + layout = [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize + size:layout.size + sublayouts:@[layout]]; } return [layout flattenedLayoutUsingPredicateBlock:^BOOL(ASLayout *evaluatedLayout) { if (self.usesImplicitHierarchyManagement) { @@ -1969,7 +1972,9 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) // If neither -layoutSpecThatFits: nor -calculateSizeThatFits: is overridden by subclassses, preferredFrameSize should be used, // assume that the default implementation of -calculateSizeThatFits: returns it. CGSize size = [self calculateSizeThatFits:constrainedSize.max]; - return [ASLayout layoutWithLayoutableObject:self size:ASSizeRangeClamp(constrainedSize, size)]; + return [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize + size:ASSizeRangeClamp(constrainedSize, size)]; } } diff --git a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm index ea18aca990..7b127c0ddf 100644 --- a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm @@ -55,7 +55,10 @@ static NSString * const kBackgroundChildKey = @"kBackgroundChildKey"; contentsLayout.position = CGPointZero; [sublayouts addObject:contentsLayout]; - return [ASLayout layoutWithLayoutableObject:self size:contentsLayout.size sublayouts:sublayouts]; + return [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize + size:contentsLayout.size + sublayouts:sublayouts]; } - (void)setBackground:(id)background diff --git a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm index 5c03393be7..b2e778b4f0 100644 --- a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm @@ -91,7 +91,9 @@ static CGFloat centerInset(CGFloat outer, CGFloat inner) if (self.child == nil) { ASDisplayNodeAssert(NO, @"Inset spec measured without a child. The spec will do nothing."); - return [ASLayout layoutWithLayoutableObject:self size:CGSizeZero]; + return [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize + size:CGSizeZero]; } ASLayout *sublayout = [self.child measureWithSizeRange:insetConstrainedSize]; @@ -112,7 +114,10 @@ static CGFloat centerInset(CGFloat outer, CGFloat inner) sublayout.position = CGPointMake(x, y); - return [ASLayout layoutWithLayoutableObject:self size:computedSize sublayouts:@[sublayout]]; + return [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize + size:computedSize + sublayouts:@[sublayout]]; } @end diff --git a/AsyncDisplayKit/Layout/ASLayout.h b/AsyncDisplayKit/Layout/ASLayout.h index af7b99ad23..f38cb3e621 100644 --- a/AsyncDisplayKit/Layout/ASLayout.h +++ b/AsyncDisplayKit/Layout/ASLayout.h @@ -40,6 +40,11 @@ extern BOOL CGPointIsNull(CGPoint point); */ @property (nonatomic, readwrite) CGPoint position; +/** + * The size range that was use to determine the size of the layout. + */ +@property (nonatomic, readonly) ASSizeRange constrainedSizeRange; + /** * Array of ASLayouts. Each must have a valid non-null position. */ @@ -67,6 +72,7 @@ extern BOOL CGPointIsNull(CGPoint point); * @param sublayouts Sublayouts belong to the new layout. */ + (instancetype)layoutWithLayoutableObject:(id)layoutableObject + constrainedSizeRange:(ASSizeRange)sizeRange size:(CGSize)size position:(CGPoint)position sublayouts:(nullable NSArray *)sublayouts @@ -85,6 +91,7 @@ extern BOOL CGPointIsNull(CGPoint point); * @param sublayouts Sublayouts belong to the new layout. */ + (instancetype)layoutWithLayoutableObject:(id)layoutableObject + constrainedSizeRange:(ASSizeRange)sizeRange size:(CGSize)size sublayouts:(nullable NSArray *)sublayouts; @@ -97,7 +104,9 @@ extern BOOL CGPointIsNull(CGPoint point); * * @param size The size of this layout. */ -+ (instancetype)layoutWithLayoutableObject:(id)layoutableObject size:(CGSize)size; ++ (instancetype)layoutWithLayoutableObject:(id)layoutableObject + constrainedSizeRange:(ASSizeRange)sizeRange + size:(CGSize)size; /** * Convenience initializer that is flattened and has CGPointNull position. @@ -109,6 +118,7 @@ extern BOOL CGPointIsNull(CGPoint point); * @param sublayouts Sublayouts belong to the new layout. */ + (instancetype)flattenedLayoutWithLayoutableObject:(id)layoutableObject + constrainedSizeRange:(ASSizeRange)sizeRange size:(CGSize)size sublayouts:(nullable NSArray *)sublayouts; diff --git a/AsyncDisplayKit/Layout/ASLayout.mm b/AsyncDisplayKit/Layout/ASLayout.mm index 3d710316ca..624773915a 100644 --- a/AsyncDisplayKit/Layout/ASLayout.mm +++ b/AsyncDisplayKit/Layout/ASLayout.mm @@ -24,6 +24,7 @@ extern BOOL CGPointIsNull(CGPoint point) @implementation ASLayout + (instancetype)layoutWithLayoutableObject:(id)layoutableObject + constrainedSizeRange:(ASSizeRange)sizeRange size:(CGSize)size position:(CGPoint)position sublayouts:(NSArray *)sublayouts @@ -46,6 +47,7 @@ extern BOOL CGPointIsNull(CGPoint point) } else { size = CGSizeMake(ASCeilPixelValue(size.width), ASCeilPixelValue(size.height)); } + l->_constrainedSizeRange = sizeRange; l->_size = size; if (CGPointIsNull(position) == NO) { @@ -68,22 +70,39 @@ extern BOOL CGPointIsNull(CGPoint point) } + (instancetype)layoutWithLayoutableObject:(id)layoutableObject + constrainedSizeRange:(ASSizeRange)sizeRange size:(CGSize)size sublayouts:(NSArray *)sublayouts { - return [self layoutWithLayoutableObject:layoutableObject size:size position:CGPointNull sublayouts:sublayouts flattened:NO]; + return [self layoutWithLayoutableObject:layoutableObject + constrainedSizeRange:sizeRange + size:size + position:CGPointNull + sublayouts:sublayouts + flattened:NO]; } -+ (instancetype)layoutWithLayoutableObject:(id)layoutableObject size:(CGSize)size ++ (instancetype)layoutWithLayoutableObject:(id)layoutableObject + constrainedSizeRange:(ASSizeRange)sizeRange + size:(CGSize)size { - return [self layoutWithLayoutableObject:layoutableObject size:size sublayouts:nil]; + return [self layoutWithLayoutableObject:layoutableObject + constrainedSizeRange:sizeRange + size:size + sublayouts:nil]; } + (instancetype)flattenedLayoutWithLayoutableObject:(id)layoutableObject + constrainedSizeRange:(ASSizeRange)sizeRange size:(CGSize)size sublayouts:(nullable NSArray *)sublayouts { - return [self layoutWithLayoutableObject:layoutableObject size:size position:CGPointNull sublayouts:sublayouts flattened:YES]; + return [self layoutWithLayoutableObject:layoutableObject + constrainedSizeRange:sizeRange + size:size + position:CGPointNull + sublayouts:sublayouts + flattened:YES]; } - (ASLayout *)flattenedLayoutUsingPredicateBlock:(BOOL (^)(ASLayout *))predicateBlock @@ -110,6 +129,7 @@ extern BOOL CGPointIsNull(CGPoint point) if (predicateBlock(context.layout)) { [flattenedSublayouts addObject:[ASLayout layoutWithLayoutableObject:context.layout.layoutableObject + constrainedSizeRange:context.layout.constrainedSizeRange size:context.layout.size position:context.absolutePosition sublayouts:nil @@ -124,7 +144,10 @@ extern BOOL CGPointIsNull(CGPoint point) } } - return [ASLayout flattenedLayoutWithLayoutableObject:_layoutableObject size:_size sublayouts:flattenedSublayouts]; + return [ASLayout flattenedLayoutWithLayoutableObject:_layoutableObject + constrainedSizeRange:_constrainedSizeRange + size:_size + sublayouts:flattenedSublayouts]; } - (CGRect)frame diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index af46b53842..97fbe6958b 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -52,7 +52,9 @@ - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize { - return [ASLayout layoutWithLayoutableObject:self size:constrainedSize.min]; + return [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize + size:constrainedSize.min]; } - (id)finalLayoutable diff --git a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm index 892872179e..bcf284d439 100644 --- a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm @@ -58,7 +58,10 @@ static NSString * const kOverlayChildKey = @"kOverlayChildKey"; [sublayouts addObject:overlayLayout]; } - return [ASLayout layoutWithLayoutableObject:self size:contentsLayout.size sublayouts:sublayouts]; + return [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize + size:contentsLayout.size + sublayouts:sublayouts]; } @end diff --git a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm index 4e9c66ed98..0dd36049af 100644 --- a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm @@ -72,7 +72,10 @@ const ASSizeRange childRange = (bestSize == sizeOptions.end()) ? constrainedSize : ASSizeRangeMake(*bestSize, *bestSize); ASLayout *sublayout = [self.child measureWithSizeRange:childRange]; sublayout.position = CGPointZero; - return [ASLayout layoutWithLayoutableObject:self size:sublayout.size sublayouts:@[sublayout]]; + return [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize + size:sublayout.size + sublayouts:@[sublayout]]; } @end diff --git a/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm b/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm index 4206171b5e..d95344e6d6 100644 --- a/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm @@ -89,7 +89,10 @@ ASRoundPixelValue((size.height - sublayout.size.height) * yPosition) }; - return [ASLayout layoutWithLayoutableObject:self size:size sublayouts:@[sublayout]]; + return [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize + size:size + sublayouts:@[sublayout]]; } - (CGFloat)proportionOfAxisForAxisPosition:(ASRelativeLayoutSpecPosition)position diff --git a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm index cb99f38288..2e9439f900 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm @@ -124,7 +124,9 @@ - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize { if (self.children.count == 0) { - return [ASLayout layoutWithLayoutableObject:self size:constrainedSize.min]; + return [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize + size:constrainedSize.min]; } ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems, .baselineRelativeArrangement = _baselineRelativeArrangement}; @@ -163,6 +165,7 @@ } return [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize size:ASSizeRangeClamp(constrainedSize, finalSize) sublayouts:sublayouts]; } diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm index 68db47ff14..ca3ba66b6c 100644 --- a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm @@ -68,6 +68,7 @@ } return [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:constrainedSize size:ASSizeRangeClamp(constrainedSize, size) sublayouts:sublayouts]; } diff --git a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm index 57902a6b4e..aef235e118 100644 --- a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm @@ -303,7 +303,7 @@ static std::vector layoutChildrenAlongUnconstrainedStac const CGFloat exactStackDimension = ASRelativeDimensionResolve(flexBasis, stackDimension(style.direction, size)); if (useOptimizedFlexing && isFlexibleInBothDirections(child)) { - return { child, [ASLayout layoutWithLayoutableObject:child size:{0, 0}] }; + return { child, [ASLayout layoutWithLayoutableObject:child constrainedSizeRange:sizeRange size:{0, 0}] }; } else { return { child, diff --git a/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m b/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m index 92895d5a9a..e485e12cb9 100644 --- a/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m +++ b/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m @@ -55,7 +55,10 @@ { ASLayout *layout = [layoutSpecUnderTest measureWithSizeRange:sizeRange]; layout.position = CGPointZero; - layout = [ASLayout layoutWithLayoutableObject:self size:layout.size sublayouts:@[layout]]; + layout = [ASLayout layoutWithLayoutableObject:self + constrainedSizeRange:sizeRange + size:layout.size + sublayouts:@[layout]]; _layoutUnderTest = [layout flattenedLayoutUsingPredicateBlock:^BOOL(ASLayout *evaluatedLayout) { return [self.subnodes containsObject:(ASDisplayNode *)evaluatedLayout.layoutableObject]; }];