From 05c08d197313ebad457bbdf367b9b63645b07458 Mon Sep 17 00:00:00 2001 From: Geektree0101 Date: Sat, 31 Oct 2020 13:17:56 +0900 Subject: [PATCH 1/7] add ASEdgeLayoutSpec.h --- AsyncDisplayKit.xcodeproj/project.pbxproj | 4 ++ Source/AsyncDisplayKit.h | 1 + Source/Layout/ASEdgeLayoutSpec.h | 68 +++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 Source/Layout/ASEdgeLayoutSpec.h diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 4f8b9a3c9..07cfe75c7 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -455,6 +455,7 @@ CCF1FF5E20C4785000AAD8FC /* ASLocking.h in Headers */ = {isa = PBXBuildFile; fileRef = CCF1FF5D20C4785000AAD8FC /* ASLocking.h */; settings = {ATTRIBUTES = (Public, ); }; }; D933F041224AD17F00FF495E /* ASTransactionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = D933F040224AD17F00FF495E /* ASTransactionTests.mm */; }; D99F9158232990F30083CC8E /* ASImageNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D99F9157232990F30083CC8E /* ASImageNodeTests.m */; }; + DA316FC8254D13CD008942BE /* ASEdgeLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = DA316FC7254D128C008942BE /* ASEdgeLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; }; DB78412E1C6BCE1600A9E2B4 /* _ASTransitionContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.mm */; }; DBABFAFC1C6A8D2F0039EA4A /* _ASTransitionContext.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -999,6 +1000,7 @@ D785F6611A74327E00291744 /* ASScrollNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASScrollNode.mm; sourceTree = ""; }; D933F040224AD17F00FF495E /* ASTransactionTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTransactionTests.mm; sourceTree = ""; }; D99F9157232990F30083CC8E /* ASImageNodeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASImageNodeTests.m; sourceTree = ""; }; + DA316FC7254D128C008942BE /* ASEdgeLayoutSpec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASEdgeLayoutSpec.h; sourceTree = ""; }; DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = _ASTransitionContext.h; path = ../_ASTransitionContext.h; sourceTree = ""; }; DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = _ASTransitionContext.mm; path = ../_ASTransitionContext.mm; sourceTree = ""; }; DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASContextTransitioning.h; sourceTree = ""; }; @@ -1696,6 +1698,7 @@ ACF6ED081B17843500DA7C62 /* ASDimension.mm */, 690C35631E055C7B00069B91 /* ASDimensionInternal.h */, 690C35601E055C5D00069B91 /* ASDimensionInternal.mm */, + DA316FC7254D128C008942BE /* ASEdgeLayoutSpec.h */, ACF6ED091B17843500DA7C62 /* ASInsetLayoutSpec.h */, ACF6ED0A1B17843500DA7C62 /* ASInsetLayoutSpec.mm */, ACF6ED0B1B17843500DA7C62 /* ASLayout.h */, @@ -2069,6 +2072,7 @@ CC2F65EE1E5FFB1600DA57C9 /* ASMutableElementMap.h in Headers */, 34EFC76A1B701CE600AD841F /* ASLayoutSpec.h in Headers */, CCA282D01E9EBF6C0037E8B7 /* ASTipsWindow.h in Headers */, + DA316FC8254D13CD008942BE /* ASEdgeLayoutSpec.h in Headers */, B350625C1B010F070018CF92 /* ASLog.h in Headers */, CC3B208A1C3F7A5400798563 /* ASWeakSet.h in Headers */, B35062041B010EFD0018CF92 /* ASMultiplexImageNode.h in Headers */, diff --git a/Source/AsyncDisplayKit.h b/Source/AsyncDisplayKit.h index 59e9aeeca..b11af6c66 100644 --- a/Source/AsyncDisplayKit.h +++ b/Source/AsyncDisplayKit.h @@ -79,6 +79,7 @@ #import #import #import +#import #import #import #import diff --git a/Source/Layout/ASEdgeLayoutSpec.h b/Source/Layout/ASEdgeLayoutSpec.h new file mode 100644 index 000000000..e9b512127 --- /dev/null +++ b/Source/Layout/ASEdgeLayoutSpec.h @@ -0,0 +1,68 @@ +// +// ASEdgeLayoutSpec.h +// AsyncDisplayKit +// +// Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import + +/** + The edge location for positioning edge element. + */ +typedef NS_ENUM(NSInteger, ASEdgeLayoutLocation) { + ASEdgeLayoutLocationTop, + ASEdgeLayoutLocationLeft, + ASEdgeLayoutLocationBottom, + ASEdgeLayoutLocationRight, +}; + +NS_ASSUME_NONNULL_BEGIN + +/** + A layout spec that positions a edge element which relatives to the child element. + + @warning Both child element and edge element must have valid preferredSize for layout calculation. + */ +@interface ASEdgeLayoutSpec : ASLayoutSpec + +/** + A layout spec that positions a edge element which relatives to the child element. + + @param child A child that is laid out to determine the size of this spec. + @param edge A layoutElement object that is laid out to a edge on the child. + @param location The edge position option. + @return An ASEdgeLayoutSpec object with a given child and an layoutElement that act as edge. + */ +- (instancetype)initWithChild:(id )child edge:(id )edge location:(ASEdgeLayoutLocation)location AS_WARN_UNUSED_RESULT; + +/** + A layout spec that positions a edge element which relatives to the child element. + + @param child A child that is laid out to determine the size of this spec. + @param edge A layoutElement object that is laid out to a edge on the child. + @param location The edge position option. + @return An ASEdgeLayoutSpec object with a given child and an layoutElement that act as edge. + */ ++ (instancetype)edgeLayoutSpecWithChild:(id )child edge:(id )edge location:(ASEdgeLayoutLocation)location NS_RETURNS_RETAINED AS_WARN_UNUSED_RESULT; + +/** + A layoutElement object that is laid out to a edge on the child. + */ +@property (nonatomic) id edge; + +/** + The edge position option. + */ +@property (nonatomic) ASEdgeLayoutLocation edgeLocation; + +/** + The point which offsets from the edge location. Use this property to make delta + distance from the default edge location. Default is 0.0. + */ +@property (nonatomic) CGFloat offset; + +@end + +NS_ASSUME_NONNULL_END From 57f69f81e679181b4646d050fdfd93c48cf456fb Mon Sep 17 00:00:00 2001 From: Geektree0101 Date: Sat, 31 Oct 2020 13:26:13 +0900 Subject: [PATCH 2/7] add ASEdgeLayoutSpecSnapshotTests.mm --- AsyncDisplayKit.xcodeproj/project.pbxproj | 4 + Tests/ASEdgeLayoutSpecSnapshotTests.mm | 154 ++++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 Tests/ASEdgeLayoutSpecSnapshotTests.mm diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 07cfe75c7..d59cea8fb 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -456,6 +456,7 @@ D933F041224AD17F00FF495E /* ASTransactionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = D933F040224AD17F00FF495E /* ASTransactionTests.mm */; }; D99F9158232990F30083CC8E /* ASImageNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D99F9157232990F30083CC8E /* ASImageNodeTests.m */; }; DA316FC8254D13CD008942BE /* ASEdgeLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = DA316FC7254D128C008942BE /* ASEdgeLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA316FCD254D19C0008942BE /* ASEdgeLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA316FCC254D19C0008942BE /* ASEdgeLayoutSpecSnapshotTests.mm */; }; DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; }; DB78412E1C6BCE1600A9E2B4 /* _ASTransitionContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.mm */; }; DBABFAFC1C6A8D2F0039EA4A /* _ASTransitionContext.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -1001,6 +1002,7 @@ D933F040224AD17F00FF495E /* ASTransactionTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTransactionTests.mm; sourceTree = ""; }; D99F9157232990F30083CC8E /* ASImageNodeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASImageNodeTests.m; sourceTree = ""; }; DA316FC7254D128C008942BE /* ASEdgeLayoutSpec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASEdgeLayoutSpec.h; sourceTree = ""; }; + DA316FCC254D19C0008942BE /* ASEdgeLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASEdgeLayoutSpecSnapshotTests.mm; sourceTree = ""; }; DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = _ASTransitionContext.h; path = ../_ASTransitionContext.h; sourceTree = ""; }; DB55C2601C6408D6004EDCF5 /* _ASTransitionContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = _ASTransitionContext.mm; path = ../_ASTransitionContext.mm; sourceTree = ""; }; DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASContextTransitioning.h; sourceTree = ""; }; @@ -1328,6 +1330,7 @@ CC54A81D1D7008B300296A24 /* ASDispatchTests.mm */, 058D0A2D195D057000B7D73C /* ASDisplayLayerTests.mm */, 058D0A2E195D057000B7D73C /* ASDisplayNodeAppearanceTests.mm */, + DA316FCC254D19C0008942BE /* ASEdgeLayoutSpecSnapshotTests.mm */, F711994D1D20C21100568860 /* ASDisplayNodeExtrasTests.mm */, DBC453211C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.mm */, 69B225661D72535E00B25B22 /* ASDisplayNodeLayoutTests.mm */, @@ -2390,6 +2393,7 @@ AEEC47E41C21D3D200EC1693 /* ASVideoNodeTests.mm in Sources */, 254C6B521BF8FE6D003EC431 /* ASTextKitTruncationTests.mm in Sources */, F325E490217460B100AC93A4 /* ASTextNode2Tests.mm in Sources */, + DA316FCD254D19C0008942BE /* ASEdgeLayoutSpecSnapshotTests.mm in Sources */, 058D0A3D195D057000B7D73C /* ASTextKitCoreTextAdditionsTests.mm in Sources */, CC3B20901C3F892D00798563 /* ASBridgedPropertiesTests.mm in Sources */, CCE4F9BE1F0ECE5200062E4E /* ASTLayoutFixture.mm in Sources */, diff --git a/Tests/ASEdgeLayoutSpecSnapshotTests.mm b/Tests/ASEdgeLayoutSpecSnapshotTests.mm new file mode 100644 index 000000000..8ff05d322 --- /dev/null +++ b/Tests/ASEdgeLayoutSpecSnapshotTests.mm @@ -0,0 +1,154 @@ +// +// ASEdgeLayoutSpecSnapshotTests.mm +// AsyncDisplayKitTests +// +// Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import "ASLayoutSpecSnapshotTestsHelper.h" +#import +#import +#import + +@interface ASEdgeLayoutSpecSnapshotTests : ASLayoutSpecSnapshotTestCase + +@property (nonatomic, copy) UIColor *boxColor; +@property (nonatomic, copy) UIColor *baseColor; +@property (nonatomic, copy) UIColor *edgeColor; +@property (nonatomic, copy) UIColor *contextColor; + +@property (nonatomic) CGSize baseSize; +@property (nonatomic) CGSize edgeSize; +@property (nonatomic) CGSize contextSize; + +@property (nonatomic) ASSizeRange contextSizeRange; + +@end + +@implementation ASEdgeLayoutSpecSnapshotTests + +- (void)setUp +{ + [super setUp]; + + self.recordMode = NO; + + _boxColor = [UIColor greenColor]; + _baseColor = [UIColor blueColor]; + _edgeColor = [UIColor orangeColor]; + _contextColor = [UIColor lightGrayColor]; + + _baseSize = CGSizeMake(60, 60); + _edgeSize = CGSizeMake(20, 20); + _contextSize = CGSizeMake(200, 200); + + _contextSizeRange = ASSizeRangeMake(CGSizeZero, _contextSize); +} + +- (void)testEdgeSpecForAllLocations +{ + CGFloat offset = 0.0; + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationTop offset:offset]; + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationLeft offset:offset]; + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationBottom offset:offset]; + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationRight offset:offset]; +} + +- (void)testEdgeSpecForAllLocationsWithInnerOffset +{ + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationTop offset:-_edgeSize.height]; + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationLeft offset:-_edgeSize.width]; + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationBottom offset:-_edgeSize.height]; + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationRight offset:-_edgeSize.width]; +} + +- (void)testEdgeSpecForAllLocationsWithOuterOffset +{ + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationTop offset:_edgeSize.height]; + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationLeft offset:_edgeSize.width]; + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationBottom offset:_edgeSize.height]; + [self testEdgeSpecWithLocation:ASEdgeLayoutLocationRight offset:_edgeSize.width]; +} + + +- (void)testEdgeSpecWithLocation:(ASEdgeLayoutLocation)location + offset:(CGFloat)offset +{ + ASDisplayNode *baseNode = ASDisplayNodeWithBackgroundColor(_baseColor, _baseSize); + ASDisplayNode *edgeNode = ASDisplayNodeWithBackgroundColor(_edgeColor, _edgeSize); + ASDisplayNode *debugBoxNode = ASDisplayNodeWithBackgroundColor(_boxColor); + + ASEdgeLayoutSpec *edgeSpec = [ASEdgeLayoutSpec edgeLayoutSpecWithChild:baseNode + edge:edgeNode + location:location]; + edgeSpec.offset = offset; + + ASCenterLayoutSpec *centerSpec = [ASCenterLayoutSpec centerLayoutSpecWithCenteringOptions:ASCenterLayoutSpecCenteringXY sizingOptions:ASCenterLayoutSpecSizingOptionDefault child:edgeSpec]; + + ASBackgroundLayoutSpec *backgroundSpec = [ASBackgroundLayoutSpec backgroundLayoutSpecWithChild:centerSpec + background:debugBoxNode]; + + [self testLayoutSpec:backgroundSpec + sizeRange:_contextSizeRange + subnodes:@[debugBoxNode, baseNode, edgeNode] + identifier:[self suffixWithLocation:location offset:offset]]; +} + +- (NSString *)suffixWithLocation:(ASEdgeLayoutLocation)location + offset:(CGFloat)offset +{ + NSMutableString *desc = [NSMutableString string]; + + switch (location) { + case ASEdgeLayoutLocationTop: + [desc appendString:@"top"]; + break; + case ASEdgeLayoutLocationLeft: + [desc appendString:@"left"]; + break; + case ASEdgeLayoutLocationBottom: + [desc appendString:@"bottom"]; + break; + case ASEdgeLayoutLocationRight: + [desc appendString:@"right"]; + break; + } + + [desc appendString:@"_"]; + + switch (location) { + case ASEdgeLayoutLocationTop: + if (offset >= 0.0) { + [desc appendString:@"outer"]; + } else { + [desc appendString:@"inner"]; + } + break; + case ASEdgeLayoutLocationLeft: + if (offset >= 0.0) { + [desc appendString:@"inner"]; + } else { + [desc appendString:@"outer"]; + } + break; + case ASEdgeLayoutLocationBottom: + if (offset >= 0.0) { + [desc appendString:@"inner"]; + } else { + [desc appendString:@"outer"]; + } + break; + case ASEdgeLayoutLocationRight: + if (offset >= 0.0) { + [desc appendString:@"outer"]; + } else { + [desc appendString:@"inner"]; + } + break; + } + + return desc.copy; +} + +@end From 7a68503c08cc72ba8a29df5a847be0a356644ea5 Mon Sep 17 00:00:00 2001 From: Geektree0101 Date: Sat, 31 Oct 2020 13:57:10 +0900 Subject: [PATCH 3/7] add ASEdgeLayoutSpec.mm --- AsyncDisplayKit.xcodeproj/project.pbxproj | 4 + Source/Layout/ASEdgeLayoutSpec.mm | 143 ++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 Source/Layout/ASEdgeLayoutSpec.mm diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index d59cea8fb..89634147e 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -455,6 +455,7 @@ CCF1FF5E20C4785000AAD8FC /* ASLocking.h in Headers */ = {isa = PBXBuildFile; fileRef = CCF1FF5D20C4785000AAD8FC /* ASLocking.h */; settings = {ATTRIBUTES = (Public, ); }; }; D933F041224AD17F00FF495E /* ASTransactionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = D933F040224AD17F00FF495E /* ASTransactionTests.mm */; }; D99F9158232990F30083CC8E /* ASImageNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D99F9157232990F30083CC8E /* ASImageNodeTests.m */; }; + DA316FC6254D1282008942BE /* ASEdgeLayoutSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA316FC5254D1282008942BE /* ASEdgeLayoutSpec.mm */; }; DA316FC8254D13CD008942BE /* ASEdgeLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = DA316FC7254D128C008942BE /* ASEdgeLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA316FCD254D19C0008942BE /* ASEdgeLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA316FCC254D19C0008942BE /* ASEdgeLayoutSpecSnapshotTests.mm */; }; DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1001,6 +1002,7 @@ D785F6611A74327E00291744 /* ASScrollNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASScrollNode.mm; sourceTree = ""; }; D933F040224AD17F00FF495E /* ASTransactionTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTransactionTests.mm; sourceTree = ""; }; D99F9157232990F30083CC8E /* ASImageNodeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASImageNodeTests.m; sourceTree = ""; }; + DA316FC5254D1282008942BE /* ASEdgeLayoutSpec.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASEdgeLayoutSpec.mm; sourceTree = ""; }; DA316FC7254D128C008942BE /* ASEdgeLayoutSpec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASEdgeLayoutSpec.h; sourceTree = ""; }; DA316FCC254D19C0008942BE /* ASEdgeLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASEdgeLayoutSpecSnapshotTests.mm; sourceTree = ""; }; DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = _ASTransitionContext.h; path = ../_ASTransitionContext.h; sourceTree = ""; }; @@ -1702,6 +1704,7 @@ 690C35631E055C7B00069B91 /* ASDimensionInternal.h */, 690C35601E055C5D00069B91 /* ASDimensionInternal.mm */, DA316FC7254D128C008942BE /* ASEdgeLayoutSpec.h */, + DA316FC5254D1282008942BE /* ASEdgeLayoutSpec.mm */, ACF6ED091B17843500DA7C62 /* ASInsetLayoutSpec.h */, ACF6ED0A1B17843500DA7C62 /* ASInsetLayoutSpec.mm */, ACF6ED0B1B17843500DA7C62 /* ASLayout.h */, @@ -2522,6 +2525,7 @@ 254C6B8C1BF94F8A003EC431 /* ASTextKitTailTruncater.mm in Sources */, 6907C25A1DC4ECFE00374C66 /* ASObjectDescriptionHelpers.mm in Sources */, B35062051B010EFD0018CF92 /* ASMultiplexImageNode.mm in Sources */, + DA316FC6254D1282008942BE /* ASEdgeLayoutSpec.mm in Sources */, B35062251B010EFD0018CF92 /* ASMutableAttributedStringBuilder.mm in Sources */, B35062071B010EFD0018CF92 /* ASNetworkImageNode.mm in Sources */, 34EFC76D1B701CF100AD841F /* ASOverlayLayoutSpec.mm in Sources */, diff --git a/Source/Layout/ASEdgeLayoutSpec.mm b/Source/Layout/ASEdgeLayoutSpec.mm new file mode 100644 index 000000000..8b8a915cc --- /dev/null +++ b/Source/Layout/ASEdgeLayoutSpec.mm @@ -0,0 +1,143 @@ +// +// ASEdgeLayoutSpec.m +// AsyncDisplayKit +// +// Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import +#import +#import + +static NSUInteger const kBaseChildIndex = 0; +static NSUInteger const kEdgeChildIndex = 1; + +@interface ASEdgeLayoutSpec() +@end + +@implementation ASEdgeLayoutSpec + +- (instancetype)initWithChild:(id )child edge:(id )edge location:(ASEdgeLayoutLocation)location +{ + self = [super init]; + if (self) { + self.child = child; + self.edge = edge; + self.edgeLocation = location; + } + return self; +} + ++ (instancetype)edgeLayoutSpecWithChild:(id )child edge:(id )edge location:(ASEdgeLayoutLocation)location NS_RETURNS_RETAINED +{ + return [[self alloc] initWithChild:child edge:edge location:location]; +} + +#pragma mark - Children + +- (void)setChild:(id)child +{ + ASDisplayNodeAssertNotNil(child, @"Child shouldn't be nil."); + [super setChild:child atIndex:kBaseChildIndex]; +} + +- (id)child +{ + return [super childAtIndex:kBaseChildIndex]; +} + +- (void)setEdge:(id)edge +{ + ASDisplayNodeAssertNotNil(edge, @"Edge element cannot be nil."); + [super setChild:edge atIndex:kEdgeChildIndex]; +} + +- (id)edge +{ + return [super childAtIndex:kEdgeChildIndex]; +} + +#pragma mark - Calculation + +- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize +{ + CGSize size = { + ASPointsValidForSize(constrainedSize.max.width) == NO ? ASLayoutElementParentDimensionUndefined : constrainedSize.max.width, + ASPointsValidForSize(constrainedSize.max.height) == NO ? ASLayoutElementParentDimensionUndefined : constrainedSize.max.height + }; + + id child = self.child; + id edge = self.edge; + + // Element validation + [self _validateElement:child]; + [self _validateElement:edge]; + + CGRect childFrame = CGRectZero; + CGRect edgeFrame = CGRectZero; + + // Layout child + ASLayout *childLayout = [child layoutThatFits:constrainedSize parentSize:size]; + childFrame.size = childLayout.size; + + // Layout edge + ASLayout *edgeLayout = [edge layoutThatFits:constrainedSize parentSize:size]; + edgeFrame.size = edgeLayout.size; + + // Update edge's position + switch (_edgeLocation) { + case ASEdgeLayoutLocationTop: + edgeFrame.origin.x = childFrame.origin.x + (childFrame.size.width - edgeFrame.size.width) * 0.5; + edgeFrame.origin.y = childFrame.origin.y - edgeFrame.size.height - _offset; + break; + case ASEdgeLayoutLocationLeft: + edgeFrame.origin.x = childFrame.origin.x - edgeFrame.size.width - _offset; + edgeFrame.origin.y = childFrame.origin.y + (childFrame.size.height - edgeFrame.size.height) * 0.5; + break; + case ASEdgeLayoutLocationBottom: + edgeFrame.origin.x = childFrame.origin.x + (childFrame.size.width - edgeFrame.size.width) * 0.5; + edgeFrame.origin.y = childFrame.origin.y + childFrame.size.height + _offset; + break; + case ASEdgeLayoutLocationRight: + edgeFrame.origin.x = childFrame.origin.x + childFrame.size.width + _offset; + edgeFrame.origin.y = childFrame.origin.y + (childFrame.size.height - edgeFrame.size.height) * 0.5; + break; + } + + // Calculate size + CGRect frame = childFrame; + + // Shift sublayouts' positions if they are off the bounds. + if (frame.origin.x != 0.0) { + CGFloat deltaX = frame.origin.x; + childFrame.origin.x -= deltaX; + edgeFrame.origin.x -= deltaX; + } + + if (frame.origin.y != 0.0) { + CGFloat deltaY = frame.origin.y; + childFrame.origin.y -= deltaY; + edgeFrame.origin.y -= deltaY; + } + + childLayout.position = childFrame.origin; + edgeLayout.position = edgeFrame.origin; + + return [ASLayout layoutWithLayoutElement:self size:frame.size sublayouts:@[childLayout, edgeLayout]]; +} + +- (void)_validateElement:(id )element +{ + // Validate non-nil element + if (element == nil) { + ASDisplayNodeAssertNotNil(element, @"[%@]: Must have a non-nil child/edge for layout calculation.", self.class); + } + // Validate preferredSize if needed + CGSize size = element.style.preferredSize; + if (!CGSizeEqualToSize(size, CGSizeZero) && !ASIsCGSizeValidForSize(size) && (size.width < 0 || (size.height < 0))) { + ASDisplayNodeFailAssert(@"[%@]: Should give a valid preferredSize value for %@ before edge's position calculation.", self.class, element); + } +} + +@end From 651d7afc2c4339dbe98e46cc05f2617cf7d378ee Mon Sep 17 00:00:00 2001 From: Geektree0101 Date: Sat, 31 Oct 2020 13:57:46 +0900 Subject: [PATCH 4/7] add ASEdgeLayoutSpec snapshot referrence images --- ...lLocationsWithInnerOffset_bottom_outer@3x.png | Bin 0 -> 9780 bytes ...AllLocationsWithInnerOffset_left_outer@3x.png | Bin 0 -> 9354 bytes ...llLocationsWithInnerOffset_right_inner@3x.png | Bin 0 -> 9223 bytes ...rAllLocationsWithInnerOffset_top_inner@3x.png | Bin 0 -> 9907 bytes ...lLocationsWithOuterOffset_bottom_inner@3x.png | Bin 0 -> 9291 bytes ...AllLocationsWithOuterOffset_left_inner@3x.png | Bin 0 -> 9453 bytes ...llLocationsWithOuterOffset_right_outer@3x.png | Bin 0 -> 9585 bytes ...rAllLocationsWithOuterOffset_top_outer@3x.png | Bin 0 -> 9483 bytes ...stEdgeSpecForAllLocations_bottom_inner@3x.png | Bin 0 -> 9292 bytes ...testEdgeSpecForAllLocations_left_inner@3x.png | Bin 0 -> 9333 bytes ...estEdgeSpecForAllLocations_right_outer@3x.png | Bin 0 -> 9171 bytes .../testEdgeSpecForAllLocations_top_outer@3x.png | Bin 0 -> 9370 bytes 12 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_bottom_outer@3x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_left_outer@3x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_right_inner@3x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_top_inner@3x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_bottom_inner@3x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_left_inner@3x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_right_outer@3x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_top_outer@3x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_bottom_inner@3x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_left_inner@3x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_right_outer@3x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_top_outer@3x.png diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_bottom_outer@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_bottom_outer@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..32423a39b3eda5232c91ccd7d038d2216e4c4b6c GIT binary patch literal 9780 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_right_inner@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_right_inner@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..0b797f05ee3ea5504957e0071d1a05c862f5758d GIT binary patch literal 9223 zcmeHNe^3-v9N*pcVh=`J4m=x!T99MT;lQj^Qp*L8k>fx~95@K&u+YRGfTmz5-eQah zGiD4P#%U3yPI18@5ugaG;5drlWI^U3Tp8w%&OL68ZWaP<-d!F2E-o(6ZCR_^NtCv@YIg`r4ghu3w` zkfw*nZ$uEEV0fTm#u<8W(`&VQ@ltTczyUs}3VbQ~GrT7Mn5#K351h|x)FDf=(BHa3 ziehGvl8_e;n6hoIH!huB^$ z-W5#N{*?;;njlFXH0N5?^t?sYGQo-Bk#K0syKyXcy1^5A;KK&yP;a~ZJ|Ff zfoX`q)w`7ON1qz(T!Eq3iBu-sz+Tv}NnU*|%!5jw3~NptD_0k*E;A#kGZ=)?*V2Bp zes#l~LfzeRDOv9Zd5fWM_(m9SvD<3*(FWR*K*=b}*NF$hRPTL@6WtP6`7j2hyF#03 zYf6ZuXi67IN=aQpWrwf)_&XSW3j-A?L(|3iMF;1mCk6VG6ls>{ftS z6V|3QMMbF3T=1^1l6wH(W8KskZZuZZ@qmFB#|$BL!1_ITK=bOiClPQ@OZR}cFzwfQKGf*7Z1sqr%wnoY3 zPQGo8`)vDs5HLH{Fs3ZHkv%%y&x24&@rsmPE%8L7lu$7WOHa@4D#Gl_hd5~CT{lYK z4Z_lZP;41VPIA}DNFAot2OfWCm5);_KwD}a34MuSi+~asgZJmLCIc(eVK?pe`vvTm zLXg67UsY;;_3ifu5?1%Zy-AD$<$mHq;b!^6a2H+s?`BPYA4QO{vD;xc_aTU^67Fi) zFNPF&Ye@Bp*N3|sXI>hb(-%#y&u6-q=A10Jk#+9;`Ks+WFzFe7$KY6- z_psxWW|!+$|$JkO{UnJYg>K!~s=hx`u@PQc}rf2#%+t-XN!NX-2|vD7I3*3d3DF@rQg= zZFeEaa4v&{(4fietvK}&!kmQZj^k!qFWBi=0+T~D*k=Jl`cgCe=`t>pap57l03-45 z&BCTRmYlAhv>+*1iyp8VefFKNh1rVOOV})jy{z%>y3#y0j?4VH23x(i*BZxQMcyx& z(nOikY}9(K^y&Avd}CT{}3^89Hzb50ZMuwkamokXatOH`%Mly^GV5n8S~V!P}a&Cjm8P z19AX~TkKx%C-^XZn+bTd7s^)|MFp>SIels5L8{NtGOPq*lkJ46X%5ui>6v)8u8NJp ziO(OiZCCshX<$usa&6-S%V8o>Ciqa&6jejsj}W-$Rk!0U`-7a?J)=R47GT@3t3?GS zuS;&(lIGH9jk8UA#8ck(YEe2U=Ar;sdvY$u0FZ(Y+TKI)#8w3?@{|Oz+j^qQ z0+50a7wT5au_TapK;UAzS2m}ckM~x|i+UC58h|Y*V;{&P0(G{IxXuH`AeWaO+9t|6 zaIgYkiLK9M7XXmF4_mHVUvXoqa9D#%&=VPRgS&bhac*ZEvU)#&tt9wds4YsMPSZBY z#~@7#Lc-gM^yR58()VAXFTV}M9HEDfuAL2Zl54YvpmGR1=}NcaDyw;EjEAt#&Sfc~ zvsiNWhm>QlI=g0Z%;ld!$Cquryz*dasq-}h6i;D0zf2X~6l87xNN8KQz!x5W7VEn? zE1>gx;avfrc7+!TDa^p8AJ>C0mS6OcBeJaer+2X9P3Sbrj8xc=6d>w8jDdsiO&7q^=Cr=l%&tPewoh literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_top_inner@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_top_inner@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..0d3a90efd7ed82e9a78c698d0751261dd66710a3 GIT binary patch literal 9907 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 TbcEc9{_PW{H|Pq+nbQ9QbPs&h literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_left_inner@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_left_inner@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..0111583dfcffd1b1f270973d5fe8784b35c4a294 GIT binary patch literal 9453 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 D)(Z(T literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_right_outer@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_right_outer@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..bd2073e56b9a393a60bb71b70e088725810b830a GIT binary patch literal 9585 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_left_inner@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_left_inner@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..00563d5e0941e93204a9769005c6e584a7d6d4f5 GIT binary patch literal 9333 zcmeHNe^3+I9p5Y)+<!D6DB$f{ z?*P+NPCc+j2V{DjQxJjX)PQmseoFdwvpLgFr^6p@XF9W) zd3n40-uu4y{l4$_^FH}*isE87dAKchgCNKwQl;1mL9m)Bs4IBV`rhdtPzkcOZi;|v zI+qNB8&SGyM-~M6hB8HkeFeu<7kbw}_T%l}k{+*SW~Poq0vJItoWK{U3W`GP z*Ca%lmQhNQYs1{zpS-n_>qnBbAHlU03Lj@2{lX!E&@RNemUj3>==CVac-+8Dz}_WO zIcJjt9OE%HJ2lf%N4y|);X4edl%kV z@vdXM;2+iS;?>}H1EP4RVk3=@4U|VJ7B_joCHQlLJxuvioF^k3+xmB$ioi$5rl+4Q z`|YZ1I@O=h%CPE^N!t+-(ke5g)U7K}&E(FT*+kNbbb*2-aD4NTo0aQ>lU4;{I9Bal zh@g9R)^z%L=YNNww}lL=qsX9z0eTCaSAUuy3ByiYj2k{QuG6W1RC?mU5{4=waE0R3 zo<^6ku4GsMUrnV{BwcA9k|uvAi2*Y)o{OP{;`mF03vMUqL|{Ob&`$vCOR6pxDwEz4 zz*!6%1dEAM@QdLs!~4wtB$_A*+-7^#_NDFo#~YmES6))}dt~;@hN;|lDQgFz-Ejdy z&%#?t+Fd{egenFKMrfn|4A`V|w9cFwD4?wU=ElK*Z+2KT-Xq;bNel6GHiYrOd+NYuSB?;@Lo=FShS` zX2?mBo*K=x4rPrGUB3Bz@41OZ0{AP^3m=Ujv?8foy{y$`;Kb-!0h|r9N+R6_rNfn_ zKJOcIKWo~x{E(8QSKval8N<|YhkN(GQgoZ^$3S$X9n}jxWxho1$G+cYCYu23~2}_c+1H=7wf%{=|Z_ z(O;Vov`5seu6a+4sh4SL^qSxH^q^sm zifZyLn*23JZvU|f7YMT14xlS?WKxIfqx?rNW?0iyvuBb+yn4-T zCenste-`GcfS2VBT5r)WGp)m}`!%b?D3%jn^9zxW`d2qnqDk>AaA)pv1`OOusKAG7rUQkJl99<3LL%PL^w;lW*++W zz@e_m6FP8caH9wzc5nq?9$+g1RVk+Ze8%_kl>x< zELFpm=|_2hjy;840UZ+xl=+g7(wI`#DdH|Ll+8!1f9LC#-tlL;K*o1KRxbz*8fv;= z+|&59%a4MnhsXT|Ah z<1LdFA`k`hLBh`sJ~|~!mFZ;%>Qy*V9=8e;VZr`u3XbG9jobkYkC15r!;8b>?q|nm zegDzTDkWfnpD-+t^sNi?@A)A=t@Q&CYXTP?L>(q8T6JeSDx+EN58CdofRXt{cYOOF zS#rk!qbzp!0gRG28E-P)%lt% zdrJ`He(K4~>&q!Fjc;Is-AU$f?!8IJYXBBixQ=n&K{w30EdUBwsoLEP$T`XE9#;-3D%cJ19FDJMTp#cZXK9fcIKv&(x!j4spuck=4oA{07>0g5N+Vr{E)y zk3c)Sa)LV^LOBTk=ktn(P#!{g660VyJc;@5vd|2w&6f!F$xXeP$NVoSQW>kLiO?SY EJ5kc1od5s; literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_right_outer@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_right_outer@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..03ce239858106c5fa66d3c9b0b723c4ec9899ccd GIT binary patch literal 9171 zcmeHNdr%Wc7|)#-dVy+>glD1c8H_?332H%0wO%n1L>~2p5h+PyOI1R_Mh9@B*3CD=zwDg~j)49xC_AdMF z?r*=x?l1dY)_YN*lO11nWU*M2mxPIzvsj>%x?l(Lm+}NdGg$zt<)I-gW4(6=`M^mD zTccvJrp}`-K%$=|Cx7(bAdX&1mLPeNA3#Wc`PxhB-ub}#J)HSunXp9s?#eXak872? zyi2%P!{BCXdebe>(_O`!`b!^pq+Q{s1)s<(zWcy3xRV8d5R9N0>Ke8)E6{$gVc|WY za%U9N*lMf5-gy_p?e_?ZnkaGGlLAl6QwT<-5JYP0h^je-&5t_8rQ5^8v2La4tH-1q zx;^AJI=BWCBH1gBkF^JNW3b$`=lo*m_5d!SVIWRbzq`Cax7QGS8itmAd(*D{bbD<4 zG^&|tFxJ3O#;K?nW@3X`sYaJ#X2C_6eZ#hyGP^iKM(jN7Z#fkLtIJ!mGdz_glVW@T zP=(8j>a5WQto0ta)~!ILt*S^R7D8|xTO9_$5O`K>P?k=5a8&^UVC6+J#3{A~qfXy-ZjCX!I`?*G&zj*ytBj3@;=yAYf-BW^YluQm4g^+eRZRn55J@1}Nq&yU$CeRa zHCul%j9g6?H~$oVFo*C%P1{eOXJ7gSyt`p8{?QyR3}rgsDeQH^Z$OZqh~4}GG+y4c zzT}uOQqb3zxN$2EI8s~}l3FTd@ zBIufb&{1bm$NMKEqle5BopAISt-)ekJ!^t^3L5iM&7=YP|D^${CyHmB0ouU|fW@*} zkJh(}$rG1b)QQVI^1MY5`XZ~+ve|06RugLZRr#C5QEztn>~Q8*-;P6vWL6j%Sce~K zX?e}+DNLVKkuj{=yU1!C=ugh(4lD#-(y?$%enH`y6=G?bo8o62F&AV&-@x-dJ4?95 z(@~S!9NXtW>V3n!0RxM)>pIh0R&b*GbFBn4{|rXeuo(_XkKr1gM? z_>+tPudxV7+FvTd{m7sh%xrVg(@|NX%tLH&E1wNlZpmceKF8XPOm4m2)3}Xu#&)I$ zQADgvTkT$369G0tnO8sEQ@4#10W9N(2bpop*@Fmrf0doXk#ww^?^fZ@&4|_zE^th( zcjxCs;HYF`g{)t2KjcYCnb2zvCyqx72F~sm1hB}3!&a{y3g z=ZF;d^jGwD@q7CrID%rX-$uc48=D-JtS+4O6%j}Z#`&mZ;0kP? z_RGj*d3nkV2v)n=Ii+1iCv{aVB+q1LUY)%&cxp2F- jfk~+SUlMBT*&`174+nUdbIQ(8Z`~}BM2U?d^31;gd>Hat literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_top_outer@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_top_outer@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..096da11826c0d27c5ee4f0dbcea186b0dd0cde22 GIT binary patch literal 9370 zcmeHNYfuwc6yCjDWCO)4frd_{vSa|U2Ek5Me8Hm004n&FfC#C5SfMCrZBeQ07As(8 ztcq3YlcCNqBUHjDK9OuKjI~Zh>43JNMgdy-RwPk&fRm* z`Mz`SreJnll)LM@t^`52$3$!95(LtT2Q>t))O=Rd0u8xpZq!ub&;_4+@I#gnov?}^ z{KCY8)b1Fghl@VTG_&SIi{O9{sfMp0TPvO`vfK~+RR*mlMiV(di~P4~%;whUx3s^6 z_gt%Xxs|SRe?RZK$|-m3!6RDcr-1fetFBY?)%(?F!=1^RhOy;I6^ zfTgmOS$%xGJBjW);~nEifQT!9^Kp;%Odi26V)a)8Yy4PF@XN^FG7qG?8OB&W0XS?n z<+U@SIyIJI^}9LY?TAx1v-O#>_@(?E-{{c@H@P`Tbs09uNpy@8 zPR3?WgF#F)cQd7+(-O(**Q|o7qL>aEos-qL3r0GQ`D*DnCu`` zk>a0C(Z`)}Q~J$eFbE%X)@1_J1H2re^ScY7s`!r0eD-Tu6Gr%`j4Dsh$-EQ5niI^= zT(%hqzRN*sO|R<4G)@R+jLSW*i!()sh5t4ZbY?>tb8QdIKoH(^-Z!}_kYQQ~fmLyD-dpk(o_m=r0yqx4$@9y3RgUA!wBjcd3G3Ro^5v1>a!di z%M*M$LTSw@Eo)@9cxY9z`qK_l$)@OTaJL&(-dsB#1`&og%U5m!oxa#1X!7EJmSO4( zPg>X9ck{vwPB<)d$o;*g(0Wrs%d!GRm`o9UABVOL?><&4Q~+R@#G095LO-pXm=|qb zC-08p*c2gG!?7$|L>0z7Wpk>EAQtsitUs%7Sh-qRdAA^tEd~goXo|{L%=zHn@VgaC zNNK8EnUATNiH9zzlv6HYs?%9q43Oj;)%3utPQ8sw073Xhw3Xmv&Nn91mWD*z1B2t2 zdKmV7j&Kix8inV$Adi5;hkRe^7|0nRm5=6x18x7Pmt69Ug{Kmi4Kz&$lzh@KwbClgq1kvBWpvdJmL3o@M_mdtpMW)uWG>+`;|1-_H@%I^W zzP;+=5XIi>PdlPGL2c<>zdvV4MYYpIAc0dtw(d!kku}!{qw*Rb(FOgFxCn&5B7GIW z5L~E7V905w=gTUAb}~dRury?LEvhXE0lru~5N#suJZ_j|+^=*4E+`cNI^?~0lUCgW zAbw?lc6gBsBsG$6q_`1tN=gO^C|-9Eg@rBb!LVw&{z2VRe(+^L#sDJ>?)ulF_Li<| zomQLVAX_-}C1)$`dzzOASmLG1#gAg^XAQn1urbKXKFOT8|M{w;C1*l}NTCATdz6%S xgReg&RFNQBA|Rk Date: Sat, 31 Oct 2020 14:29:24 +0900 Subject: [PATCH 5/7] fix offset annotation --- Source/Layout/ASEdgeLayoutSpec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Layout/ASEdgeLayoutSpec.h b/Source/Layout/ASEdgeLayoutSpec.h index e9b512127..3b479f752 100644 --- a/Source/Layout/ASEdgeLayoutSpec.h +++ b/Source/Layout/ASEdgeLayoutSpec.h @@ -58,7 +58,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) ASEdgeLayoutLocation edgeLocation; /** - The point which offsets from the edge location. Use this property to make delta + The offset from the edge location. Use this property to make delta distance from the default edge location. Default is 0.0. */ @property (nonatomic) CGFloat offset; From d8d142c21bee3baa1cfe171d9a6f6d603d7c8dd5 Mon Sep 17 00:00:00 2001 From: Geektree0101 Date: Sat, 31 Oct 2020 14:34:30 +0900 Subject: [PATCH 6/7] add convenience constructor --- Source/Layout/ASEdgeLayoutSpec.h | 14 +++++++++++++- Source/Layout/ASEdgeLayoutSpec.mm | 10 ++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Source/Layout/ASEdgeLayoutSpec.h b/Source/Layout/ASEdgeLayoutSpec.h index 3b479f752..c9bab7145 100644 --- a/Source/Layout/ASEdgeLayoutSpec.h +++ b/Source/Layout/ASEdgeLayoutSpec.h @@ -33,9 +33,21 @@ NS_ASSUME_NONNULL_BEGIN @param child A child that is laid out to determine the size of this spec. @param edge A layoutElement object that is laid out to a edge on the child. @param location The edge position option. + @param offset offset from the edge location @return An ASEdgeLayoutSpec object with a given child and an layoutElement that act as edge. */ -- (instancetype)initWithChild:(id )child edge:(id )edge location:(ASEdgeLayoutLocation)location AS_WARN_UNUSED_RESULT; +- (instancetype)initWithChild:(id )child edge:(id )edge location:(ASEdgeLayoutLocation)location offset:(CGFloat)offset AS_WARN_UNUSED_RESULT; + +/** + A layout spec that positions a edge element which relatives to the child element. + + @param child A child that is laid out to determine the size of this spec. + @param edge A layoutElement object that is laid out to a edge on the child. + @param location The edge position option. + @param offset offset from the edge location + @return An ASEdgeLayoutSpec object with a given child and an layoutElement that act as edge. + */ ++ (instancetype)edgeLayoutSpecWithChild:(id )child edge:(id )edge location:(ASEdgeLayoutLocation)location offset:(CGFloat)offset NS_RETURNS_RETAINED AS_WARN_UNUSED_RESULT; /** A layout spec that positions a edge element which relatives to the child element. diff --git a/Source/Layout/ASEdgeLayoutSpec.mm b/Source/Layout/ASEdgeLayoutSpec.mm index 8b8a915cc..0063a31e8 100644 --- a/Source/Layout/ASEdgeLayoutSpec.mm +++ b/Source/Layout/ASEdgeLayoutSpec.mm @@ -18,20 +18,26 @@ @interface ASEdgeLayoutSpec() @implementation ASEdgeLayoutSpec -- (instancetype)initWithChild:(id )child edge:(id )edge location:(ASEdgeLayoutLocation)location +- (instancetype)initWithChild:(id )child edge:(id )edge location:(ASEdgeLayoutLocation)location offset:(CGFloat)offset { self = [super init]; if (self) { self.child = child; self.edge = edge; self.edgeLocation = location; + self.offset = offset; } return self; } + (instancetype)edgeLayoutSpecWithChild:(id )child edge:(id )edge location:(ASEdgeLayoutLocation)location NS_RETURNS_RETAINED { - return [[self alloc] initWithChild:child edge:edge location:location]; + return [[self alloc] initWithChild:child edge:edge location:location offset:0.0]; +} + ++ (instancetype)edgeLayoutSpecWithChild:(id )child edge:(id )edge location:(ASEdgeLayoutLocation)location offset:(CGFloat)offset NS_RETURNS_RETAINED; +{ + return [[self alloc] initWithChild:child edge:edge location:location offset:offset]; } #pragma mark - Children From a241edca5c5a9c88923af7eedd237ce87f879e34 Mon Sep 17 00:00:00 2001 From: Geektree0101 Date: Mon, 2 Nov 2020 09:39:20 +0900 Subject: [PATCH 7/7] fix ci test fail --- ...lLocationsWithInnerOffset_bottom_outer@2x.png | Bin 0 -> 4925 bytes ...AllLocationsWithInnerOffset_left_outer@2x.png | Bin 0 -> 5130 bytes ...llLocationsWithInnerOffset_right_inner@2x.png | Bin 0 -> 4842 bytes ...rAllLocationsWithInnerOffset_top_inner@2x.png | Bin 0 -> 4967 bytes ...lLocationsWithOuterOffset_bottom_inner@2x.png | Bin 0 -> 5075 bytes ...AllLocationsWithOuterOffset_left_inner@2x.png | Bin 0 -> 5040 bytes ...llLocationsWithOuterOffset_right_outer@2x.png | Bin 0 -> 4991 bytes ...rAllLocationsWithOuterOffset_top_outer@2x.png | Bin 0 -> 5197 bytes ...stEdgeSpecForAllLocations_bottom_inner@2x.png | Bin 0 -> 5058 bytes ...testEdgeSpecForAllLocations_left_inner@2x.png | Bin 0 -> 5192 bytes ...estEdgeSpecForAllLocations_right_outer@2x.png | Bin 0 -> 4839 bytes .../testEdgeSpecForAllLocations_top_outer@2x.png | Bin 0 -> 5138 bytes 12 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_bottom_outer@2x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_left_outer@2x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_right_inner@2x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_top_inner@2x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_bottom_inner@2x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_left_inner@2x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_right_outer@2x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_top_outer@2x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_bottom_inner@2x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_left_inner@2x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_right_outer@2x.png create mode 100644 Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_top_outer@2x.png diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_bottom_outer@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_bottom_outer@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9b8d68af38d64a9f285824c6176f412ae923920e GIT binary patch literal 4925 zcmeHL`%@EF6y6PsE+A!z4ls$ONeV@+Ag!&@O6?*GgqDY+PEnDP87<(01Rpg?1x>8- z7@(l-z*rte?X*@pGNL7DBCl}-2TH-I6&gZRg2kyo36+paOwSFZ?O)LT(Cp0JbF(>j z&$r*6@8q5oZb*#v_T+eC80H-(Vm4wJUWNua53VSiS9O8G4{VHGk6r3s{1`sSKim?R zo{)eogE@&2I0th_E-=>N+`r~A_!7*`ah-)>`MWS;&L{w{`cjz<6YfwjRJRzhE@*xQ#)-!NtY9n54~MA)w>vfb$X<$ig6RRDbDf z0$UizL~fSjPwqxah}RalwOZ|83p;$6z{hO@;T|k`!BdNEhNO73lICwH7QKM82$Gu4 zWvy3YFkPnFEmC-(Z-bRQ1UT+nCVc;V$_KD|pH;n5&teI9`V|AC zY#irP9%O+s$m>>rmMT-RcT=Mwnx+YpIk8F+MbjjMT&3T}XmljgIb@E^XmE#64QY+~ zV5p5eHbvoae#KYxtX^~9SJ~PkrIPFzu3kNv2j$j*YH&-5MB!Ud-ah|qzziAu5K&FjO_ylsIMK5tzKg;4djHba;%MX^o- zMp3=E%HRj6R-MqNBJ#qy8=W1F;Cgj2sb%&9H&8C{^?@?B^pnNxRlg`)W z2*N*(s98KB97lRkSiCJCEd;rQBO#uS2tV>nqUs%*ka(t9Ams?t?YAc?9jS?uzC&0O zlV)Yazsn=m^hgJhD9mHrv0q;S&4`g2Uss4{rVOm}?L&q|O=FOEWXETR9}0~qKVL@a zD2*s-G8ZC<`_)DrQijPO9JrU@gt*h(GCitwk11`}F3m9jFyFEe%S~w$szNbHqDDC< zcX%O!Xrh}H8Wce*ZLF(A>Ty6csV4L?uj0T`*{131A!td`SfMcom7-#ze7?zY=BWSn z8JW$V^ql)cP2EfiLMye!Rv$>F>F3F6;%3q0GF5VJmm$O2{Ro!JB((`p?`9wH&XLcn zj>ZB31J>o04M_LfWS!S6PWYz5l^H|j@OYV_4+hqv;I7q>7B1ExTiB?F6;i4<>5#;+iw4y_oWv>n{q3b7yU-SNW*f zxav+Eck~_%t9OHTcXtTtQEZT~j`l^M%FI0KpCv*c;0J;4=t)k}Z~S=ai%Hauh?|{l xjfltj*%-}r!E~|d%1xJqP?`E47bLdoog3Nt{Iv07QRu&=xadUY(t7c+KLHdB`EmdN literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_left_outer@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_left_outer@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..db97b4b3d74ac2d33696ac7f8210357185c8ac48 GIT binary patch literal 5130 zcmeHLjZ+gx6u&z!cnMODuZSR!P*7CxqmCkqdO*}LNT7-e%_y{5&{hHplK`UR1O@y+ z)DdI=p_b8hw2IOiAOaDpKvn$cI6@(O2mz58BU%(8q`ML7Ur?vchtbZ;fljH|C zl}0zl*ckKX{hTsRhL5*UP%he}n(#68qEbty3-(};ze24Rpf8*4kLmRyogc?S8$s|e z%$d`;f0tNB{pu}VU#{d)6uxaxP*C9q7BvGZxwu+ZK=5vF9rTG3n-UpP^}a4qE+NSxW!#+^WyZTwLvz|X1{3>PnyGjJXyu8EZefW@400o)VrwowvO z&?nCWt${c|XT115Z`lO8yZ*cQ+nFFBGo0chWl|~8pqZ)>XG*1H2IQV#bgM<6PwI2A za-bv{dJ31srB9%m(4!(R3lNZ=)Fw5XB+(XKt#Ymf_#hkyT>jOF0;LD&lhRt`36yBw zb*m^1{9Hh^!QsLKkC`AKr<3pJDdEt_!^>M;G0c}^3Aq03BV}^NS=E*N+UGMMdQ$S_ zj>806v2{_UiU$I6(tK%|5Dw!TQ;8gm=YKiKyiQ$TxX-?qMY#%{d#vQ*a+$Ylw!3*0 zbF?>MRIkK)bPH40AHFHkkcK402J0BQR=s(D)^B||=kXJ&E_X1Lq~3;1z|S}dY#JpS zVTLtN!yW0q^he*{^9X`@Qjio-T}DORuqk^I zezvyFYvk3d0du-i@gikqji+8WoU%N{d`b^WJJ3n-OZ+=EgKy_7R_zLQOi=-v13GUC zK=Snie)RO5bgU&)5T(b(wRK?_tAtw;GuE;5o8yWsDc_~^^J2=np=soax*I#TvR#n7 zR7eJMSiDFw6dMTOdKb6?JR=;XT}!LoNQ{9p&QjYzz*i%*YLF0iTsY8%?|T5dxQ~lyxY%d<8A2tI^a&VF>!JMSIY#U z5@NpZyh~yhkM6%QlRl)_m=H2IzBhWDHZ;^a&|k^0CTI_oyVvodr@eUck&$+GGwYaa zmiK1xcG|Mm#EK2=XcUo*vCKN9!f{%aZYZfzgfe_1 z0w{h_`s=#~m1uXhjB%~DJDL@=$)enAR4v{jIwes|!-}LBx73wWa?kHwWZgX5WXqq3 zod?#ae52aguFf0(*-)6dwJ^ReDG@w@n0q2UGk0C F{|^PUV_N_K literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_right_inner@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_right_inner@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2a633fa354002a974078a975847498ecc90eab48 GIT binary patch literal 4842 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_bottom_inner@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_bottom_inner@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0566b109b9b17330d96b4693ed0b54c3bde39011 GIT binary patch literal 5075 zcmeHLX;2hL6rLGolK}*V1%U#^1(tx69Ek@M5Hgwt7A+P9;t{T`U=&4GL;`HWv1`I5 zAV(}I4-5sKAQA)tfpBRM3M6h6E4;w{l545eQ)}0 z{7#Oel7hAZf*?vxY?dp6pee8sAAu)=sx3{RLyx;UZbNQ1uNekE!oJ<>bimmeF#%%& z!BK6521P)#Lv`Mb9Z+LLPVyW>kk~^Az9ho|J-mPp$(*;nTqe3C4c5uTq|#_grrh!v zPHU)m8UQ-^K=!`l2%=#K8|viBoB$8k9Ade+gB~c9T=n2?3>xe~BYw-cq&filcqi6Y z_b_y{Wh)Q=bd_AqjQFZ$y$VZrxK`iNAKA0&_4L9#K{6--rMEMYt&CzgLB5H=wh0h0 zG!Y(V^X1`NfdJkS;r2}JKfRy~gTa7zDwBRKCO91m69gfdeGSji>oNqwD7IpmP}wrT zUozjw;s$U^Mh2Kd{vR^L;gvn(FH8KnhIBTbHJBRS+UAT-wkF*di=QM@`n@$|9FDW7 zG+O^?F;!$+yuR~=K7)Y;@r{}*^gxo+M^V)j%iY-?-eC5znaqtH7^ctYFz+0rqo^J! zPs9nBigj%PLO=cyx6&?qioyq`I2ZU|QWU|0qDOBylvEI`#{Q|T2a9PyRk2TLhat#~ z3_3}oP8x}Y9hhjU^-5rQf8Z2<`3( z0Y>INi)Nl8tI_v-?U)&anI8JANk@u`@4LBd(4O(NZn}zfp(#*xYoWHwOqC?DRDh9v zi+iC<1EAUx-QfkDXEuKCtfdsyRNdj=#suI>vvt7-JbC#3}>V1_{}!bki6x)$$BuJ+GNYI zdw7lqL*s=_=kPLr)lXFGPJq#5WI=r92wdO5*VKNu}hURf?{_c)m2J z99p&O^`cVcX!-Y{rZj zRk#@BnxtSb5Q?s>4ft+56nSH~RAO+M7VWQc+1&=P09h+7DjcwEXPfrtr(qQ`u>*V| zq_Bqfq*ge>>I2eWQkW#-4(CIPTGqo7q&IyftbBcbG874s7BA3(F~3|lI)r7u5|)qs zlrFSDLQkj^TF@@qeU%Ae`K*Lhb#mZyXhADHKS+E5EGWv(<2XTBRV!gdu5S1Niu?*Q zhSY-h>)40PiSei?apio^{;>`CB1!tu-vrq%&hZurcX{`T_ZI7 zo|!YJ-Uii*9*!kPnT{Roe>_(oM8niYm<*3?FfHc$JAT z=Pvv4_b58aQY$qMoOB(D)ft(l;R6xAdl(aht$AW7M#HdY@t*|l>V0-up-wF?Uy-PP z8l~5hzdiH01^u?n-1oD)62`*w72paY1T1%RHTH)b%XC{2%-0JqbL?T<%Oqu9`Y#c} a>J|4j#p>;|92kZFcsbc~SU0zEPy7p8oN9Fd literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_left_inner@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_left_inner@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5e42ccd861166fa338736a2cb78f1909c94fc30a GIT binary patch literal 5040 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_top_outer@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_top_outer@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..24ed66e1266d658ef6d308600c605be6afe64dfc GIT binary patch literal 5197 zcmeHL`BM{D9N%3wbpt8^RH!Hfx;|> zF@fOdOoRbbKwFNQPQ;$*TttT+#}FiO8-jnx;ej4r;2rcc?|U6F`XL+Oh%rqznkLry z7{kZ@s%YVZjv49w!(IfLVGSF~U1y~LgR{1A)@%Shcp-h&f%{z0U=Nz^WTV%LSnzBs zm*ciUh`wy9&hJ^m@~9qttsGi>XLH59jId3Ghw{4Ya`(*hxi_R5Q+kOI6vJm=C+$wJ zq{H!e%$*Jbu#3KbucAZz2uvah@PLe{bUGvmIKT>I7C86X(;a@2ygl%?zg+1h_7T5u45{y9;5SWuJH^s!uizDJfmIG{ zcE4#1MtOBAYlOCbY&QFG1U88=b$Nc6Ys08SB#Ip~9vsWZ^QX>P+oDGtUwlsLMjcL- z#Ft))4<*URi{Ic_s&puEfF~wNvZ4W>syi!oL$xq_cpr)?M;&@p{>%-tJ+ljqS*%@7 z)M0Fr`M$Bp@UcpfsAAVkCT>PO)9=nCDUnE+!<;p3$=eHu1~`3v7&bT@S~qgh@WRq$ zPB0+(fz^xAuG-N!6g|+XNMk>}ax|5n)7YrlOa zNs^EWRu6}3QifFkx$=rFONeK!NRGxB81^K^Cep97Ge@`9=+b39qOK*uqT@0wmf^nZ zA6fM!n)ZzVWS zFH!;kiMpPwz`cnYWVuNS?|Xye$8PoLT(ZoGYw z!i?2Qe3NzRZoMSNpLCVicB|FR=2VJE|CrPVsBz1Xv@|9tY*^TqSJZwI3gLG26CM;o zAQQ+j$~C1p)*x`1nZt_b_xMnOve433&Ok+B)p1SNl zzY-Wl0Tk%cEYF}yqQERQ-8|}9F$90*(6-+cxPB3|hJRcg<&S3o@RE5uN1%WQ2Qy0> zp@0LRjm%z?V;71Cq~5x%FWC#7qvwsWpgcuGZKs(@^e#OBE}K>yV*ua|D0ywY;Oh)q z0C}D|-|)KwcJWsC(@E`Rb^v^jO0T5dQ$x*JKe@bw0l@jXvg^=zDq?NrQBdJ$0Z;E+ zjS;tvsiy9M!Nc-4XaHqnM`eOJ8fqDnYTIQH-1+FM5IED2N~7qdIDUk#X>Rwnt4~i# zUknJ9ZqWj8&JneZ-{6-3j_;}6)#;Y=0r>8W8~YvLOdUFsT%cjnHGMGP^k~ontVqQ> zu}cXwE3&e=~Ecrl!5ZnS7-sSdozU`wdE0MH-%OTTBo4@ fNBX={n2sgX1|?dE)cM)q*oAOCc$`A_utWa=0DhN+ literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_bottom_inner@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_bottom_inner@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..41df46287828617a388f87990a49073d6cbe62e6 GIT binary patch literal 5058 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 V{?dB{0&v4yVU>y literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_top_outer@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_top_outer@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7bd6640c372eba0dfa7b39a3ca3ca21f3f616b4b GIT binary patch literal 5138 zcmeHLYfuwc6y9AnWdj8kP@sYk5CpXdom!xRx?p%jhldJ^GLWFQ#cB`{B*<%5rGSFq zbkvzT(2O|BAfk30o)LmLh=W2AdDQSyuojT;Dnf`My&DPmvwxiFbh0yd&)s{^{qC1@ z?m2rlSwR85dO9m~APCaq__23F5S&Lh>@zSz*19|a0zSUe*9$6bwip5rg6~2(-~0PR zYe64_PtlD@zmsx=>^mJnXh1~@`Qtqtc1 zwU+wyvd5xMJ`l_pzrDvH$i$9rFlVRjI2g1z#10Gw5^Sit8o}KGG+KhjY!z4QbpV;q zVS5G(;J58{#e;6Rcir6IvMJXm`$f$nUS#R1>n|Oz#je@bJSA7id`SpKP=w;08^l=z z2~oAbk{>#LtQXfrCznjfl2R5enh8Q zLq}ts|Jm8uzWcpK+56;EYM1PDQ7i&{~A9gF1PI>FWHco>$=IStA~n87Q3u9lkO z_|Xm2X++y9UJ-LZQA3iVqi>n0CH2N&AfKQ}Qc%dWSmricbZUY>y=rj<3iD=b1=_lTrQW(`VKo+YIWeV!24JU`moT| zQmH7LH|)YHoYCC~V#B%uAK;gZe-y;+a_eCe1bQ$wu%vRUN*iSpQnQ?ZZw*8Bavy8& zYjb3=kY_3N`O&MuJ3zBoV=($iX%5N14h*k;E~wR%%DstSh(MvXpDxr!+da=7{OWUd zU7B+Ho;Fi__xg*TU#|;eoR!U{^tD(~>EaoA%6!i^D zd>A&&lW;3WT|g1Wvjb86TOzOfzT=&f9?`qHq}~8-@U{D~8;eePM0929JKjBp(O!^2tHYXZQ_*BqI#0dSL(`4w%}>Ljr;u+WilKUV{lcHpMX&fj(sf&Q8-=nsuCR3_?U}EyLwA%!LS1Qsa zALTFYh8_tG?vg$lK_BIa8smhGD0)U^(`y5V?!7)I9-a`$JQJe9>y+%Cf50yX96wNd zsx=_x1Mp*49-MHZbE#8bmitPzO`lC{crob>JR*88bT4NB@aVLcWfC>D#y_cJGi3n0 z!auUwl>Vic#~$YEt8F?YSizUs0FOkZ{+=(P!OLr7Bz!eBjl2It?pA-t6cyeovjs&u z#aa4l()0I@^`RB$bD>exn1}w9)*K2=C}=W;>R+W#7z)dgwCPJ3)^d~Cc~Evi9Pa>j IsTc3mKiw2fa{vGU literal 0 HcmV?d00001