[ASLayout] Cache constrained size range

This commit is contained in:
Levi McCallum
2016-05-20 12:31:10 -07:00
parent 4804f429b9
commit c469ad273b
13 changed files with 82 additions and 18 deletions

View File

@@ -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. // Make sure layoutableObject of the root layout is `self`, so that the flattened layout will be structurally correct.
if (layout.layoutableObject != self) { if (layout.layoutableObject != self) {
layout.position = CGPointZero; 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) { return [layout flattenedLayoutUsingPredicateBlock:^BOOL(ASLayout *evaluatedLayout) {
if (self.usesImplicitHierarchyManagement) { 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, // If neither -layoutSpecThatFits: nor -calculateSizeThatFits: is overridden by subclassses, preferredFrameSize should be used,
// assume that the default implementation of -calculateSizeThatFits: returns it. // assume that the default implementation of -calculateSizeThatFits: returns it.
CGSize size = [self calculateSizeThatFits:constrainedSize.max]; CGSize size = [self calculateSizeThatFits:constrainedSize.max];
return [ASLayout layoutWithLayoutableObject:self size:ASSizeRangeClamp(constrainedSize, size)]; return [ASLayout layoutWithLayoutableObject:self
constrainedSizeRange:constrainedSize
size:ASSizeRangeClamp(constrainedSize, size)];
} }
} }

View File

@@ -55,7 +55,10 @@ static NSString * const kBackgroundChildKey = @"kBackgroundChildKey";
contentsLayout.position = CGPointZero; contentsLayout.position = CGPointZero;
[sublayouts addObject:contentsLayout]; [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<ASLayoutable>)background - (void)setBackground:(id<ASLayoutable>)background

View File

@@ -91,7 +91,9 @@ static CGFloat centerInset(CGFloat outer, CGFloat inner)
if (self.child == nil) { if (self.child == nil) {
ASDisplayNodeAssert(NO, @"Inset spec measured without a child. The spec will do nothing."); 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]; ASLayout *sublayout = [self.child measureWithSizeRange:insetConstrainedSize];
@@ -112,7 +114,10 @@ static CGFloat centerInset(CGFloat outer, CGFloat inner)
sublayout.position = CGPointMake(x, y); sublayout.position = CGPointMake(x, y);
return [ASLayout layoutWithLayoutableObject:self size:computedSize sublayouts:@[sublayout]]; return [ASLayout layoutWithLayoutableObject:self
constrainedSizeRange:constrainedSize
size:computedSize
sublayouts:@[sublayout]];
} }
@end @end

View File

@@ -40,6 +40,11 @@ extern BOOL CGPointIsNull(CGPoint point);
*/ */
@property (nonatomic, readwrite) CGPoint position; @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. * 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. * @param sublayouts Sublayouts belong to the new layout.
*/ */
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject + (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
constrainedSizeRange:(ASSizeRange)sizeRange
size:(CGSize)size size:(CGSize)size
position:(CGPoint)position position:(CGPoint)position
sublayouts:(nullable NSArray<ASLayout *> *)sublayouts sublayouts:(nullable NSArray<ASLayout *> *)sublayouts
@@ -85,6 +91,7 @@ extern BOOL CGPointIsNull(CGPoint point);
* @param sublayouts Sublayouts belong to the new layout. * @param sublayouts Sublayouts belong to the new layout.
*/ */
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject + (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
constrainedSizeRange:(ASSizeRange)sizeRange
size:(CGSize)size size:(CGSize)size
sublayouts:(nullable NSArray<ASLayout *> *)sublayouts; sublayouts:(nullable NSArray<ASLayout *> *)sublayouts;
@@ -97,7 +104,9 @@ extern BOOL CGPointIsNull(CGPoint point);
* *
* @param size The size of this layout. * @param size The size of this layout.
*/ */
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject size:(CGSize)size; + (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
constrainedSizeRange:(ASSizeRange)sizeRange
size:(CGSize)size;
/** /**
* Convenience initializer that is flattened and has CGPointNull position. * 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. * @param sublayouts Sublayouts belong to the new layout.
*/ */
+ (instancetype)flattenedLayoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject + (instancetype)flattenedLayoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
constrainedSizeRange:(ASSizeRange)sizeRange
size:(CGSize)size size:(CGSize)size
sublayouts:(nullable NSArray<ASLayout *> *)sublayouts; sublayouts:(nullable NSArray<ASLayout *> *)sublayouts;

View File

@@ -24,6 +24,7 @@ extern BOOL CGPointIsNull(CGPoint point)
@implementation ASLayout @implementation ASLayout
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject + (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
constrainedSizeRange:(ASSizeRange)sizeRange
size:(CGSize)size size:(CGSize)size
position:(CGPoint)position position:(CGPoint)position
sublayouts:(NSArray *)sublayouts sublayouts:(NSArray *)sublayouts
@@ -46,6 +47,7 @@ extern BOOL CGPointIsNull(CGPoint point)
} else { } else {
size = CGSizeMake(ASCeilPixelValue(size.width), ASCeilPixelValue(size.height)); size = CGSizeMake(ASCeilPixelValue(size.width), ASCeilPixelValue(size.height));
} }
l->_constrainedSizeRange = sizeRange;
l->_size = size; l->_size = size;
if (CGPointIsNull(position) == NO) { if (CGPointIsNull(position) == NO) {
@@ -68,22 +70,39 @@ extern BOOL CGPointIsNull(CGPoint point)
} }
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject + (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
constrainedSizeRange:(ASSizeRange)sizeRange
size:(CGSize)size size:(CGSize)size
sublayouts:(NSArray *)sublayouts 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<ASLayoutable>)layoutableObject size:(CGSize)size + (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)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<ASLayoutable>)layoutableObject + (instancetype)flattenedLayoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
constrainedSizeRange:(ASSizeRange)sizeRange
size:(CGSize)size size:(CGSize)size
sublayouts:(nullable NSArray<ASLayout *> *)sublayouts sublayouts:(nullable NSArray<ASLayout *> *)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 - (ASLayout *)flattenedLayoutUsingPredicateBlock:(BOOL (^)(ASLayout *))predicateBlock
@@ -110,6 +129,7 @@ extern BOOL CGPointIsNull(CGPoint point)
if (predicateBlock(context.layout)) { if (predicateBlock(context.layout)) {
[flattenedSublayouts addObject:[ASLayout layoutWithLayoutableObject:context.layout.layoutableObject [flattenedSublayouts addObject:[ASLayout layoutWithLayoutableObject:context.layout.layoutableObject
constrainedSizeRange:context.layout.constrainedSizeRange
size:context.layout.size size:context.layout.size
position:context.absolutePosition position:context.absolutePosition
sublayouts:nil 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 - (CGRect)frame

View File

@@ -52,7 +52,9 @@
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
{ {
return [ASLayout layoutWithLayoutableObject:self size:constrainedSize.min]; return [ASLayout layoutWithLayoutableObject:self
constrainedSizeRange:constrainedSize
size:constrainedSize.min];
} }
- (id<ASLayoutable>)finalLayoutable - (id<ASLayoutable>)finalLayoutable

View File

@@ -58,7 +58,10 @@ static NSString * const kOverlayChildKey = @"kOverlayChildKey";
[sublayouts addObject:overlayLayout]; [sublayouts addObject:overlayLayout];
} }
return [ASLayout layoutWithLayoutableObject:self size:contentsLayout.size sublayouts:sublayouts]; return [ASLayout layoutWithLayoutableObject:self
constrainedSizeRange:constrainedSize
size:contentsLayout.size
sublayouts:sublayouts];
} }
@end @end

View File

@@ -72,7 +72,10 @@
const ASSizeRange childRange = (bestSize == sizeOptions.end()) ? constrainedSize : ASSizeRangeMake(*bestSize, *bestSize); const ASSizeRange childRange = (bestSize == sizeOptions.end()) ? constrainedSize : ASSizeRangeMake(*bestSize, *bestSize);
ASLayout *sublayout = [self.child measureWithSizeRange:childRange]; ASLayout *sublayout = [self.child measureWithSizeRange:childRange];
sublayout.position = CGPointZero; sublayout.position = CGPointZero;
return [ASLayout layoutWithLayoutableObject:self size:sublayout.size sublayouts:@[sublayout]]; return [ASLayout layoutWithLayoutableObject:self
constrainedSizeRange:constrainedSize
size:sublayout.size
sublayouts:@[sublayout]];
} }
@end @end

View File

@@ -89,7 +89,10 @@
ASRoundPixelValue((size.height - sublayout.size.height) * yPosition) 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 - (CGFloat)proportionOfAxisForAxisPosition:(ASRelativeLayoutSpecPosition)position

View File

@@ -124,7 +124,9 @@
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
{ {
if (self.children.count == 0) { 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}; ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems, .baselineRelativeArrangement = _baselineRelativeArrangement};
@@ -163,6 +165,7 @@
} }
return [ASLayout layoutWithLayoutableObject:self return [ASLayout layoutWithLayoutableObject:self
constrainedSizeRange:constrainedSize
size:ASSizeRangeClamp(constrainedSize, finalSize) size:ASSizeRangeClamp(constrainedSize, finalSize)
sublayouts:sublayouts]; sublayouts:sublayouts];
} }

View File

@@ -68,6 +68,7 @@
} }
return [ASLayout layoutWithLayoutableObject:self return [ASLayout layoutWithLayoutableObject:self
constrainedSizeRange:constrainedSize
size:ASSizeRangeClamp(constrainedSize, size) size:ASSizeRangeClamp(constrainedSize, size)
sublayouts:sublayouts]; sublayouts:sublayouts];
} }

View File

@@ -303,7 +303,7 @@ static std::vector<ASStackUnpositionedItem> layoutChildrenAlongUnconstrainedStac
const CGFloat exactStackDimension = ASRelativeDimensionResolve(flexBasis, stackDimension(style.direction, size)); const CGFloat exactStackDimension = ASRelativeDimensionResolve(flexBasis, stackDimension(style.direction, size));
if (useOptimizedFlexing && isFlexibleInBothDirections(child)) { if (useOptimizedFlexing && isFlexibleInBothDirections(child)) {
return { child, [ASLayout layoutWithLayoutableObject:child size:{0, 0}] }; return { child, [ASLayout layoutWithLayoutableObject:child constrainedSizeRange:sizeRange size:{0, 0}] };
} else { } else {
return { return {
child, child,

View File

@@ -55,7 +55,10 @@
{ {
ASLayout *layout = [layoutSpecUnderTest measureWithSizeRange:sizeRange]; ASLayout *layout = [layoutSpecUnderTest measureWithSizeRange:sizeRange];
layout.position = CGPointZero; 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) { _layoutUnderTest = [layout flattenedLayoutUsingPredicateBlock:^BOOL(ASLayout *evaluatedLayout) {
return [self.subnodes containsObject:(ASDisplayNode *)evaluatedLayout.layoutableObject]; return [self.subnodes containsObject:(ASDisplayNode *)evaluatedLayout.layoutableObject];
}]; }];