diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 4f8b9a3c9..89634147e 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -455,6 +455,9 @@ 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, ); }; }; 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 +1002,9 @@ 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 = ""; }; 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 = ""; }; @@ -1326,6 +1332,7 @@ CC54A81D1D7008B300296A24 /* ASDispatchTests.mm */, 058D0A2D195D057000B7D73C /* ASDisplayLayerTests.mm */, 058D0A2E195D057000B7D73C /* ASDisplayNodeAppearanceTests.mm */, + DA316FCC254D19C0008942BE /* ASEdgeLayoutSpecSnapshotTests.mm */, F711994D1D20C21100568860 /* ASDisplayNodeExtrasTests.mm */, DBC453211C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.mm */, 69B225661D72535E00B25B22 /* ASDisplayNodeLayoutTests.mm */, @@ -1696,6 +1703,8 @@ ACF6ED081B17843500DA7C62 /* ASDimension.mm */, 690C35631E055C7B00069B91 /* ASDimensionInternal.h */, 690C35601E055C5D00069B91 /* ASDimensionInternal.mm */, + DA316FC7254D128C008942BE /* ASEdgeLayoutSpec.h */, + DA316FC5254D1282008942BE /* ASEdgeLayoutSpec.mm */, ACF6ED091B17843500DA7C62 /* ASInsetLayoutSpec.h */, ACF6ED0A1B17843500DA7C62 /* ASInsetLayoutSpec.mm */, ACF6ED0B1B17843500DA7C62 /* ASLayout.h */, @@ -2069,6 +2078,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 */, @@ -2386,6 +2396,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 */, @@ -2514,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/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..c9bab7145 --- /dev/null +++ b/Source/Layout/ASEdgeLayoutSpec.h @@ -0,0 +1,80 @@ +// +// 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. + @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 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. + + @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 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; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Source/Layout/ASEdgeLayoutSpec.mm b/Source/Layout/ASEdgeLayoutSpec.mm new file mode 100644 index 000000000..0063a31e8 --- /dev/null +++ b/Source/Layout/ASEdgeLayoutSpec.mm @@ -0,0 +1,149 @@ +// +// 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 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 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 + +- (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 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 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 000000000..9b8d68af3 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_bottom_outer@2x.png differ 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 000000000..32423a39b Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_bottom_outer@3x.png differ 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 000000000..db97b4b3d Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_left_outer@2x.png differ diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_left_outer@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_left_outer@3x.png new file mode 100644 index 000000000..cb8de14bd Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_left_outer@3x.png differ 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 000000000..2a633fa35 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_right_inner@2x.png differ 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 000000000..0b797f05e Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_right_inner@3x.png differ diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_top_inner@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_top_inner@2x.png new file mode 100644 index 000000000..65675b618 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_top_inner@2x.png differ 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 000000000..0d3a90efd Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithInnerOffset_top_inner@3x.png differ 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 000000000..0566b109b Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_bottom_inner@2x.png differ diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_bottom_inner@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_bottom_inner@3x.png new file mode 100644 index 000000000..f5d895479 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_bottom_inner@3x.png differ 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 000000000..5e42ccd86 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_left_inner@2x.png differ 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 000000000..0111583df Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_left_inner@3x.png differ diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_right_outer@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_right_outer@2x.png new file mode 100644 index 000000000..94e5ee6b7 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_right_outer@2x.png differ 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 000000000..bd2073e56 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_right_outer@3x.png differ 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 000000000..24ed66e12 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_top_outer@2x.png differ diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_top_outer@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_top_outer@3x.png new file mode 100644 index 000000000..4e39b4bfa Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocationsWithOuterOffset_top_outer@3x.png differ 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 000000000..41df46287 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_bottom_inner@2x.png differ diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_bottom_inner@3x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_bottom_inner@3x.png new file mode 100644 index 000000000..1024be97e Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_bottom_inner@3x.png differ diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_left_inner@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_left_inner@2x.png new file mode 100644 index 000000000..8a64f7563 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_left_inner@2x.png differ 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 000000000..00563d5e0 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_left_inner@3x.png differ diff --git a/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_right_outer@2x.png b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_right_outer@2x.png new file mode 100644 index 000000000..8246dbe5b Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_right_outer@2x.png differ 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 000000000..03ce23985 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_right_outer@3x.png differ 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 000000000..7bd6640c3 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_top_outer@2x.png differ 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 000000000..096da1182 Binary files /dev/null and b/Tests/ReferenceImages_64/ASEdgeLayoutSpecSnapshotTests/testEdgeSpecForAllLocations_top_outer@3x.png differ