diff --git a/.bazelrc b/.bazelrc index 66f15a8b85..f5c694f926 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,3 +1,5 @@ build --strategy=Genrule=local build --apple_platform_type=ios build --cxxopt='-std=c++14' +build --copt='-w' +build --swiftcopt='-Xcc' --swiftcopt='-w' diff --git a/Wallet/BUILD b/Wallet/BUILD index 7f2f822515..b3b5c2150f 100644 --- a/Wallet/BUILD +++ b/Wallet/BUILD @@ -50,7 +50,7 @@ swift_library( "//submodules/WalletCore:WalletCore", "//submodules/BuildConfig:BuildConfig", "//submodules/AppBundle:AppBundle", - #"//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode", + "//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode", #"//submodules/WalletUI:WalletUI", ], ) diff --git a/submodules/AsyncDisplayKit/BUILD b/submodules/AsyncDisplayKit/BUILD index cfed6ac319..1a152cde4a 100644 --- a/submodules/AsyncDisplayKit/BUILD +++ b/submodules/AsyncDisplayKit/BUILD @@ -1,10 +1,14 @@ +load( + "@rules_apple_extras//apple:objc_library.bzl", + "objc_library", +) public_headers = glob([ - "Source/Public/AsyncDisplayKit/*.h", + "Source/PublicHeaders/AsyncDisplayKit/*.h", ]) private_headers = glob([ - "Source/Implementation/AsyncDisplayKit/*.h", + "Source/*.h", ]) objc_library( @@ -19,14 +23,6 @@ objc_library( defines = [ "MINIMAL_ASDK", ], - copts = [ - "-w", - "-isystem", - "submodules/AsyncDisplayKit/Source/Implementation", - ], - includes = [ - "Source/Public", - ], sdk_frameworks = [ "Foundation", "UIKit", diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASAbstractLayoutController+FrameworkPrivate.h b/submodules/AsyncDisplayKit/Source/ASAbstractLayoutController+FrameworkPrivate.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASAbstractLayoutController+FrameworkPrivate.h rename to submodules/AsyncDisplayKit/Source/ASAbstractLayoutController+FrameworkPrivate.h diff --git a/submodules/AsyncDisplayKit/Source/ASAsciiArtBoxCreator.mm b/submodules/AsyncDisplayKit/Source/ASAsciiArtBoxCreator.mm new file mode 100644 index 0000000000..78eb572ead --- /dev/null +++ b/submodules/AsyncDisplayKit/Source/ASAsciiArtBoxCreator.mm @@ -0,0 +1,186 @@ +// +// ASAsciiArtBoxCreator.mm +// Texture +// +// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import + +#import +#import + +static const NSUInteger kDebugBoxPadding = 2; + +typedef NS_ENUM(NSUInteger, PIDebugBoxPaddingLocation) +{ + PIDebugBoxPaddingLocationFront, + PIDebugBoxPaddingLocationEnd, + PIDebugBoxPaddingLocationBoth +}; + +@interface NSString(PIDebugBox) + +@end + +@implementation NSString(PIDebugBox) + ++ (instancetype)debugbox_stringWithString:(NSString *)stringToRepeat repeatedCount:(NSUInteger)repeatCount NS_RETURNS_RETAINED +{ + NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[stringToRepeat length] * repeatCount]; + for (NSUInteger index = 0; index < repeatCount; index++) { + [string appendString:stringToRepeat]; + } + return [string copy]; +} + +- (NSString *)debugbox_stringByAddingPadding:(NSString *)padding count:(NSUInteger)count location:(PIDebugBoxPaddingLocation)location +{ + NSString *paddingString = [NSString debugbox_stringWithString:padding repeatedCount:count]; + switch (location) { + case PIDebugBoxPaddingLocationFront: + return [NSString stringWithFormat:@"%@%@", paddingString, self]; + case PIDebugBoxPaddingLocationEnd: + return [NSString stringWithFormat:@"%@%@", self, paddingString]; + case PIDebugBoxPaddingLocationBoth: + return [NSString stringWithFormat:@"%@%@%@", paddingString, self, paddingString]; + } + return [self copy]; +} + +@end + +@implementation ASAsciiArtBoxCreator + ++ (NSString *)horizontalBoxStringForChildren:(NSArray *)children parent:(NSString *)parent +{ + if ([children count] == 0) { + return parent; + } + + NSMutableArray *childrenLines = [NSMutableArray array]; + + // split the children into lines + NSUInteger lineCountPerChild = 0; + for (NSString *child in children) { + NSArray *lines = [child componentsSeparatedByString:@"\n"]; + lineCountPerChild = MAX(lineCountPerChild, [lines count]); + } + + for (NSString *child in children) { + NSMutableArray *lines = [[child componentsSeparatedByString:@"\n"] mutableCopy]; + NSUInteger topPadding = ceil((CGFloat)(lineCountPerChild - [lines count])/2.0); + NSUInteger bottomPadding = (lineCountPerChild - [lines count])/2.0; + NSUInteger lineLength = [lines[0] length]; + + for (NSUInteger index = 0; index < topPadding; index++) { + [lines insertObject:[NSString debugbox_stringWithString:@" " repeatedCount:lineLength] atIndex:0]; + } + for (NSUInteger index = 0; index < bottomPadding; index++) { + [lines addObject:[NSString debugbox_stringWithString:@" " repeatedCount:lineLength]]; + } + [childrenLines addObject:lines]; + } + + NSMutableArray *concatenatedLines = [NSMutableArray array]; + NSString *padding = [NSString debugbox_stringWithString:@" " repeatedCount:kDebugBoxPadding]; + for (NSUInteger index = 0; index < lineCountPerChild; index++) { + NSMutableString *line = [[NSMutableString alloc] init]; + [line appendFormat:@"|%@",padding]; + for (NSArray *childLines in childrenLines) { + [line appendFormat:@"%@%@", childLines[index], padding]; + } + [line appendString:@"|"]; + [concatenatedLines addObject:line]; + } + + // surround the lines in a box + NSUInteger totalLineLength = [concatenatedLines[0] length]; + if (totalLineLength < [parent length]) { + NSUInteger difference = [parent length] + (2 * kDebugBoxPadding) - totalLineLength; + NSUInteger leftPadding = ceil((CGFloat)difference/2.0); + NSUInteger rightPadding = difference/2; + + NSString *leftString = [@"|" debugbox_stringByAddingPadding:@" " count:leftPadding location:PIDebugBoxPaddingLocationEnd]; + NSString *rightString = [@"|" debugbox_stringByAddingPadding:@" " count:rightPadding location:PIDebugBoxPaddingLocationFront]; + + NSMutableArray *paddedLines = [NSMutableArray array]; + for (NSString *line in concatenatedLines) { + NSString *paddedLine = [line stringByReplacingOccurrencesOfString:@"|" withString:leftString options:NSCaseInsensitiveSearch range:NSMakeRange(0, 1)]; + paddedLine = [paddedLine stringByReplacingOccurrencesOfString:@"|" withString:rightString options:NSCaseInsensitiveSearch range:NSMakeRange([paddedLine length] - 1, 1)]; + [paddedLines addObject:paddedLine]; + } + concatenatedLines = paddedLines; + // totalLineLength += difference; + } + concatenatedLines = [self appendTopAndBottomToBoxString:concatenatedLines parent:parent]; + return [concatenatedLines componentsJoinedByString:@"\n"]; + +} + ++ (NSString *)verticalBoxStringForChildren:(NSArray *)children parent:(NSString *)parent +{ + if ([children count] == 0) { + return parent; + } + + NSMutableArray *childrenLines = [NSMutableArray array]; + + NSUInteger maxChildLength = 0; + for (NSString *child in children) { + NSArray *lines = [child componentsSeparatedByString:@"\n"]; + maxChildLength = MAX(maxChildLength, [lines[0] length]); + } + + NSUInteger rightPadding = 0; + NSUInteger leftPadding = 0; + + if (maxChildLength < [parent length]) { + NSUInteger difference = [parent length] + (2 * kDebugBoxPadding) - maxChildLength; + leftPadding = ceil((CGFloat)difference/2.0); + rightPadding = difference/2; + } + + NSString *rightPaddingString = [NSString debugbox_stringWithString:@" " repeatedCount:rightPadding + kDebugBoxPadding]; + NSString *leftPaddingString = [NSString debugbox_stringWithString:@" " repeatedCount:leftPadding + kDebugBoxPadding]; + + for (NSString *child in children) { + NSMutableArray *lines = [[child componentsSeparatedByString:@"\n"] mutableCopy]; + + NSUInteger leftLinePadding = ceil((CGFloat)(maxChildLength - [lines[0] length])/2.0); + NSUInteger rightLinePadding = (maxChildLength - [lines[0] length])/2.0; + + for (NSString *line in lines) { + NSString *rightLinePaddingString = [NSString debugbox_stringWithString:@" " repeatedCount:rightLinePadding]; + rightLinePaddingString = [NSString stringWithFormat:@"%@%@|", rightLinePaddingString, rightPaddingString]; + + NSString *leftLinePaddingString = [NSString debugbox_stringWithString:@" " repeatedCount:leftLinePadding]; + leftLinePaddingString = [NSString stringWithFormat:@"|%@%@", leftLinePaddingString, leftPaddingString]; + + NSString *paddingLine = [NSString stringWithFormat:@"%@%@%@", leftLinePaddingString, line, rightLinePaddingString]; + [childrenLines addObject:paddingLine]; + } + } + + childrenLines = [self appendTopAndBottomToBoxString:childrenLines parent:parent]; + return [childrenLines componentsJoinedByString:@"\n"]; +} + ++ (NSMutableArray *)appendTopAndBottomToBoxString:(NSMutableArray *)boxStrings parent:(NSString *)parent +{ + NSUInteger totalLineLength = [boxStrings[0] length]; + [boxStrings addObject:[NSString debugbox_stringWithString:@"-" repeatedCount:totalLineLength]]; + + NSUInteger leftPadding = ceil(((CGFloat)(totalLineLength - [parent length]))/2.0); + NSUInteger rightPadding = (totalLineLength - [parent length])/2; + + NSString *topLine = [parent debugbox_stringByAddingPadding:@"-" count:leftPadding location:PIDebugBoxPaddingLocationFront]; + topLine = [topLine debugbox_stringByAddingPadding:@"-" count:rightPadding location:PIDebugBoxPaddingLocationEnd]; + [boxStrings insertObject:topLine atIndex:0]; + + return boxStrings; +} + +@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASAssert.mm b/submodules/AsyncDisplayKit/Source/ASAssert.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASAssert.mm rename to submodules/AsyncDisplayKit/Source/ASAssert.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASCGImageBuffer.h b/submodules/AsyncDisplayKit/Source/ASCGImageBuffer.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASCGImageBuffer.h rename to submodules/AsyncDisplayKit/Source/ASCGImageBuffer.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASCGImageBuffer.mm b/submodules/AsyncDisplayKit/Source/ASCGImageBuffer.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASCGImageBuffer.mm rename to submodules/AsyncDisplayKit/Source/ASCGImageBuffer.mm index de397471e0..6f05300e23 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASCGImageBuffer.mm +++ b/submodules/AsyncDisplayKit/Source/ASCGImageBuffer.mm @@ -6,7 +6,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASCGImageBuffer.h" #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASCollections.mm b/submodules/AsyncDisplayKit/Source/ASCollections.mm old mode 100755 new mode 100644 similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASCollections.mm rename to submodules/AsyncDisplayKit/Source/ASCollections.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfiguration.mm b/submodules/AsyncDisplayKit/Source/ASConfiguration.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfiguration.mm rename to submodules/AsyncDisplayKit/Source/ASConfiguration.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfigurationInternal.mm b/submodules/AsyncDisplayKit/Source/ASConfigurationInternal.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfigurationInternal.mm rename to submodules/AsyncDisplayKit/Source/ASConfigurationInternal.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitTailTruncater.h b/submodules/AsyncDisplayKit/Source/ASControlNode+Private.h similarity index 55% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitTailTruncater.h rename to submodules/AsyncDisplayKit/Source/ASControlNode+Private.h index 70734d9e2c..02f54a20ec 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitTailTruncater.h +++ b/submodules/AsyncDisplayKit/Source/ASControlNode+Private.h @@ -1,5 +1,5 @@ // -// ASTextKitTailTruncater.h +// ASControlNode+Private.h // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -7,15 +7,12 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import -#import +@interface ASControlNode (Private) -#if AS_ENABLE_TEXTNODE - -AS_SUBCLASSING_RESTRICTED -@interface ASTextKitTailTruncater : NSObject +#if TARGET_OS_TV +- (void)_pressDown; +#endif @end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASControlNode.mm b/submodules/AsyncDisplayKit/Source/ASControlNode.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASControlNode.mm rename to submodules/AsyncDisplayKit/Source/ASControlNode.mm index e401c47071..7a44591394 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASControlNode.mm +++ b/submodules/AsyncDisplayKit/Source/ASControlNode.mm @@ -8,9 +8,11 @@ // #import +#import "ASControlNode+Private.h" #import #import -#import +#import +#import "ASInternalHelpers.h" #import #import #import @@ -70,6 +72,7 @@ CGRect _ASControlNodeGetExpandedBounds(ASControlNode *controlNode); @implementation ASControlNode { + ASImageNode *_debugHighlightOverlay; } #pragma mark - Lifecycle @@ -490,4 +493,9 @@ CGRect _ASControlNodeGetExpandedBounds(ASControlNode *controlNode) { // Subclass hook } +#pragma mark - Debug +- (ASImageNode *)debugHighlightOverlay +{ + return _debugHighlightOverlay; +} @end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASControlTargetAction.mm b/submodules/AsyncDisplayKit/Source/ASControlTargetAction.mm similarity index 96% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASControlTargetAction.mm rename to submodules/AsyncDisplayKit/Source/ASControlTargetAction.mm index 41cc113314..49c2314fcc 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASControlTargetAction.mm +++ b/submodules/AsyncDisplayKit/Source/ASControlTargetAction.mm @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASControlTargetAction.h" @implementation ASControlTargetAction { diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDimension.mm b/submodules/AsyncDisplayKit/Source/ASDimension.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDimension.mm rename to submodules/AsyncDisplayKit/Source/ASDimension.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDimensionInternal.mm b/submodules/AsyncDisplayKit/Source/ASDimensionInternal.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDimensionInternal.mm rename to submodules/AsyncDisplayKit/Source/ASDimensionInternal.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDispatch.h b/submodules/AsyncDisplayKit/Source/ASDispatch.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDispatch.h rename to submodules/AsyncDisplayKit/Source/ASDispatch.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDispatch.mm b/submodules/AsyncDisplayKit/Source/ASDispatch.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDispatch.mm rename to submodules/AsyncDisplayKit/Source/ASDispatch.mm index 769a9185d4..edc2feba46 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDispatch.mm +++ b/submodules/AsyncDisplayKit/Source/ASDispatch.mm @@ -6,7 +6,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASDispatch.h" #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Ancestry.mm b/submodules/AsyncDisplayKit/Source/ASDisplayNode+Ancestry.mm similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Ancestry.mm rename to submodules/AsyncDisplayKit/Source/ASDisplayNode+Ancestry.mm index ea1376ed54..7003064c70 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Ancestry.mm +++ b/submodules/AsyncDisplayKit/Source/ASDisplayNode+Ancestry.mm @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASDisplayNode+Ancestry.h" #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+AsyncDisplay.mm b/submodules/AsyncDisplayKit/Source/ASDisplayNode+AsyncDisplay.mm similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+AsyncDisplay.mm rename to submodules/AsyncDisplayKit/Source/ASDisplayNode+AsyncDisplay.mm index 4efd2b0a79..7b17b06f82 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+AsyncDisplay.mm +++ b/submodules/AsyncDisplayKit/Source/ASDisplayNode+AsyncDisplay.mm @@ -7,15 +7,15 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "_ASCoreAnimationExtras.h" #import #import #import -#import +#import "ASDisplayNodeInternal.h" #import #import #import -#import +#import "ASSignpost.h" #import using AS::MutexLocker; diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Convenience.mm b/submodules/AsyncDisplayKit/Source/ASDisplayNode+Convenience.mm similarity index 89% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Convenience.mm rename to submodules/AsyncDisplayKit/Source/ASDisplayNode+Convenience.mm index 9673f93678..a7b7519bab 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Convenience.mm +++ b/submodules/AsyncDisplayKit/Source/ASDisplayNode+Convenience.mm @@ -7,12 +7,12 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASDisplayNode+Convenience.h" #import #import -#import +#import "ASResponderChainEnumerator.h" @implementation ASDisplayNode (Convenience) diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Deprecated.h b/submodules/AsyncDisplayKit/Source/ASDisplayNode+Deprecated.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Deprecated.h rename to submodules/AsyncDisplayKit/Source/ASDisplayNode+Deprecated.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Layout.mm b/submodules/AsyncDisplayKit/Source/ASDisplayNode+Layout.mm similarity index 94% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Layout.mm rename to submodules/AsyncDisplayKit/Source/ASDisplayNode+Layout.mm index 6145457a42..32934a599c 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Layout.mm +++ b/submodules/AsyncDisplayKit/Source/ASDisplayNode+Layout.mm @@ -8,17 +8,15 @@ // #import +#import #import -#import +#import "ASDisplayNodeInternal.h" #import #import #import #import -#import -#import -#import +#import "ASLayoutElementStylePrivate.h" #import -#import using AS::MutexLocker; @@ -74,7 +72,7 @@ using AS::MutexLocker; - (ASLayout *)layoutThatFits:(ASSizeRange)constrainedSize parentSize:(CGSize)parentSize { - ASLockScopeSelf(); + ASScopedLockSelfOrToRoot(); // If one or multiple layout transitions are in flight it still can happen that layout information is requested // on other threads. As the pending and calculated layout to be updated in the layout transition in here just a @@ -96,7 +94,6 @@ using AS::MutexLocker; layout = [self calculateLayoutThatFits:constrainedSize restrictedToSize:self.style.size relativeToParentSize:parentSize]; - as_log_verbose(ASLayoutLog(), "Established pending layout for %@ in %s", self, sel_getName(_cmd)); _pendingDisplayNodeLayout = ASDisplayNodeLayout(layout, constrainedSize, parentSize,version); ASDisplayNodeAssertNotNil(layout, @"-[ASDisplayNode layoutThatFits:parentSize:] newly calculated layout should not be nil! %@", self); } @@ -229,8 +226,6 @@ ASLayoutElementStyleExtensibilityForwarding ASDisplayNodeAssertThreadAffinity(self); ASAssertUnlocked(__instanceLock__); - as_activity_create_for_scope("Set needs layout from above"); - // Mark the node for layout in the next layout pass [self setNeedsLayout]; @@ -315,7 +310,7 @@ ASLayoutElementStyleExtensibilityForwarding - (void)_u_measureNodeWithBoundsIfNecessary:(CGRect)bounds { // ASAssertUnlocked(__instanceLock__); - ASLockScopeSelf(); + ASScopedLockSelfOrToRoot(); // Check if we are a subnode in a layout transition. // In this case no measurement is needed as it's part of the layout transition @@ -345,13 +340,6 @@ ASLayoutElementStyleExtensibilityForwarding if (!pendingLayoutIsPreferred && calculatedLayoutIsReusable) { return; } - - as_activity_create_for_scope("Update node layout for current bounds"); - as_log_verbose(ASLayoutLog(), "Node %@, bounds size %@, calculatedSize %@, calculatedIsDirty %d", - self, - NSStringFromCGSize(boundsSizeForLayout), - NSStringFromCGSize(_calculatedDisplayNodeLayout.layout.size), - _calculatedDisplayNodeLayout.version < _layoutVersion); // _calculatedDisplayNodeLayout is not reusable we need to transition to a new one [self cancelLayoutTransition]; @@ -371,18 +359,13 @@ ASLayoutElementStyleExtensibilityForwarding // If our bounds size is different than it, or invalid, recalculate. Use #define to avoid nullptr-> BOOL pendingLayoutApplicable = NO; if (nextLayout.layout == nil) { - as_log_verbose(ASLayoutLog(), "No pending layout."); } else if (!nextLayout.isValid(_layoutVersion)) { - as_log_verbose(ASLayoutLog(), "Pending layout is stale."); } else if (layoutSizeDifferentFromBounds) { - as_log_verbose(ASLayoutLog(), "Pending layout size %@ doesn't match bounds size.", NSStringFromCGSize(nextLayout.layout.size)); } else { - as_log_verbose(ASLayoutLog(), "Using pending layout %@.", nextLayout.layout); pendingLayoutApplicable = YES; } if (!pendingLayoutApplicable) { - as_log_verbose(ASLayoutLog(), "Measuring with previous constrained size."); // Use the last known constrainedSize passed from a parent during layout (if never, use bounds). NSUInteger version = _layoutVersion; ASSizeRange constrainedSize = [self _locked_constrainedSizeForLayoutPass]; @@ -403,7 +386,6 @@ ASLayoutElementStyleExtensibilityForwarding // This can occur for either pre-calculated or newly-calculated layouts. if (nextLayout.requestedLayoutFromAbove == NO && CGSizeEqualToSize(boundsSizeForLayout, nextLayout.layout.size) == NO) { - as_log_verbose(ASLayoutLog(), "Layout size doesn't match bounds size. Requesting layout from above."); // The layout that we have specifies that this node (self) would like to be a different size // than it currently is. Because that size has been computed within the constrainedSize, we // expect that calling setNeedsLayoutFromAbove will result in our parent resizing us to this. @@ -578,13 +560,10 @@ ASLayoutElementStyleExtensibilityForwarding measurementCompletion:(void(^)())completion { ASDisplayNodeAssertMainThread(); - as_activity_create_for_scope("Transition node layout"); - as_log_debug(ASLayoutLog(), "Transition layout for %@ sizeRange %@ anim %d asyncMeasure %d", self, NSStringFromASSizeRange(constrainedSize), animated, shouldMeasureAsync); if (constrainedSize.max.width <= 0.0 || constrainedSize.max.height <= 0.0) { // Using CGSizeZero for the sizeRange can cause negative values in client layout code. // Most likely called transitionLayout: without providing a size, before first layout pass. - as_log_verbose(ASLayoutLog(), "Ignoring transition due to bad size range."); return; } @@ -612,12 +591,10 @@ ASLayoutElementStyleExtensibilityForwarding // Every new layout transition has a transition id associated to check in subsequent transitions for cancelling int32_t transitionID = [self _startNewTransition]; - as_log_verbose(ASLayoutLog(), "Transition ID is %d", transitionID); // NOTE: This block captures self. It's cheaper than hitting the weak table. asdisplaynode_iscancelled_block_t isCancelled = ^{ BOOL result = (_transitionID != transitionID); if (result) { - as_log_verbose(ASLayoutLog(), "Transition %d canceled, superseded by %d", transitionID, _transitionID.load()); } return result; }; @@ -639,7 +616,7 @@ ASLayoutElementStyleExtensibilityForwarding NSUInteger newLayoutVersion = _layoutVersion; ASLayout *newLayout; { - ASLockScopeSelf(); + ASScopedLockSelfOrToRoot(); ASLayoutElementContext *ctx = [[ASLayoutElementContext alloc] init]; ctx.transitionID = transitionID; @@ -665,7 +642,6 @@ ASLayoutElementStyleExtensibilityForwarding if (isCancelled()) { return; } - as_activity_create_for_scope("Commit layout transition"); ASLayoutTransition *pendingLayoutTransition; _ASTransitionContext *pendingLayoutTransitionContext; { @@ -693,7 +669,6 @@ ASLayoutElementStyleExtensibilityForwarding // Apply complete layout transitions for all subnodes { - as_activity_create_for_scope("Complete pending layout transitions for subtree"); ASDisplayNodePerformBlockOnEverySubnode(self, NO, ^(ASDisplayNode * _Nonnull node) { [node _completePendingLayoutTransition]; node.hierarchyState &= (~ASHierarchyStateLayoutPending); @@ -712,7 +687,6 @@ ASLayoutElementStyleExtensibilityForwarding // Kick off animating the layout transition { - as_activity_create_for_scope("Animate layout transition"); [self animateLayoutTransition:pendingLayoutTransitionContext]; } diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+LayoutSpec.mm b/submodules/AsyncDisplayKit/Source/ASDisplayNode+LayoutSpec.mm similarity index 95% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+LayoutSpec.mm rename to submodules/AsyncDisplayKit/Source/ASDisplayNode+LayoutSpec.mm index d79073ffdd..132bc666f8 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+LayoutSpec.mm +++ b/submodules/AsyncDisplayKit/Source/ASDisplayNode+LayoutSpec.mm @@ -9,13 +9,12 @@ #import #import -#import -#import +#import "_ASScopeTimer.h" +#import "ASDisplayNodeInternal.h" #import #import -#import -#import -#import +#import "ASLayoutSpec+Subclasses.h" +#import "ASLayoutSpecPrivate.h" #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+UIViewBridge.mm b/submodules/AsyncDisplayKit/Source/ASDisplayNode+UIViewBridge.mm similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+UIViewBridge.mm rename to submodules/AsyncDisplayKit/Source/ASDisplayNode+UIViewBridge.mm index a6d60a7748..a1ace00a62 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+UIViewBridge.mm +++ b/submodules/AsyncDisplayKit/Source/ASDisplayNode+UIViewBridge.mm @@ -7,13 +7,13 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import -#import +#import "_ASCoreAnimationExtras.h" +#import "_ASPendingState.h" #import -#import +#import "ASDisplayNodeInternal.h" #import #import -#import +#import "ASPendingStateController.h" /** * The following macros are conveniences to help in the common tasks related to the bridging that ASDisplayNode does to UIView and CALayer. diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode.mm b/submodules/AsyncDisplayKit/Source/ASDisplayNode.mm similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode.mm rename to submodules/AsyncDisplayKit/Source/ASDisplayNode.mm index a767a77a0d..358a007f2a 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode.mm +++ b/submodules/AsyncDisplayKit/Source/ASDisplayNode.mm @@ -7,43 +7,40 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASDisplayNodeInternal.h" #import #import #import -#import +#import "ASLayoutSpec+Subclasses.h" #import #include #import -#import -#import +#import "_ASAsyncTransactionContainer+Private.h" +#import "_ASCoreAnimationExtras.h" #import #import -#import -#import +#import "_ASPendingState.h" +#import "_ASScopeTimer.h" #import #import -#import #import #import #import #import #import #import -#import +#import "ASLayoutElementStylePrivate.h" #import -#import -#import +#import "ASLayoutSpecPrivate.h" #import -#import #import -#import +#import "ASSignpost.h" #import -#import -#import +#import "ASWeakProxy.h" +#import "ASResponderChainEnumerator.h" // Conditionally time these scopes to our debug ivars (only exist in debug/profile builds) #if TIME_DISPLAYNODE_OPS @@ -209,7 +206,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) // Subclasses should never override these. Use unused to prevent warnings __unused NSString *classString = NSStringFromClass(self); - ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(calculatedSize)), @"Subclass %@ must not override calculatedSize method.", classString); + //ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(calculatedSize)), @"Subclass %@ must not override calculatedSize method.", classString); ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(calculatedLayout)), @"Subclass %@ must not override calculatedLayout method.", classString); ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(layoutThatFits:)), @"Subclass %@ must not override layoutThatFits: method. Instead override calculateLayoutThatFits:.", classString); ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(layoutThatFits:parentSize:)), @"Subclass %@ must not override layoutThatFits:parentSize method. Instead override calculateLayoutThatFits:.", classString); @@ -589,7 +586,6 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); ASDisplayNodeAssertMainThread(); ASAssertUnlocked(__instanceLock__); ASDisplayNodeLogEvent(self, @"didLoad"); - as_log_verbose(ASNodeLog(), "didLoad %@", self); TIME_SCOPED(_debugTimeForDidLoad); [self didLoad]; @@ -893,18 +889,6 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); _automaticallyRelayoutOnLayoutMarginsChanges = flag; } -- (void)__setNodeController:(ASNodeController *)controller -{ - // See docs for why we don't lock. - if (controller.shouldInvertStrongReference) { - _strongNodeController = controller; - _weakNodeController = nil; - } else { - _weakNodeController = controller; - _strongNodeController = nil; - } -} - #pragma mark - UIResponder #define HANDLE_NODE_RESPONDER_METHOD(__sel) \ @@ -1056,7 +1040,6 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); // Performing layout on a zero-bounds view often results in frame calculations // with negative sizes after applying margins, which will cause // layoutThatFits: on subnodes to assert. - as_log_debug(OS_LOG_DISABLED, "Warning: No size given for node before node was trying to layout itself: %@. Please provide a frame for the node.", self); return; } @@ -1066,8 +1049,6 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); return; } - as_activity_create_for_scope("-[ASDisplayNode __layout]"); - // This method will confirm that the layout is up to date (and update if needed). // Importantly, it will also APPLY the layout to all of our subnodes if (unless parent is transitioning). l.unlock(); @@ -1105,9 +1086,6 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); restrictedToSize:(ASLayoutElementSize)size relativeToParentSize:(CGSize)parentSize { - as_activity_scope_verbose(as_activity_create("Calculate node layout", AS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT)); - as_log_verbose(ASLayoutLog(), "Calculating layout for %@ sizeRange %@", self, NSStringFromASSizeRange(constrainedSize)); - #if AS_KDEBUG_ENABLE // We only want one calculateLayout signpost interval per thread. // Currently there is no fallback for profiling i386, since it's not useful. @@ -1120,7 +1098,6 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__); ASSizeRange styleAndParentSize = ASLayoutElementSizeResolve(self.style.size, parentSize); const ASSizeRange resolvedRange = ASSizeRangeIntersect(constrainedSize, styleAndParentSize); ASLayout *result = [self calculateLayoutThatFits:resolvedRange]; - as_log_verbose(ASLayoutLog(), "Calculated layout %@", result); #if AS_KDEBUG_ENABLE if (--tls_callDepth == 0) { @@ -1351,7 +1328,6 @@ NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"AS }]; }); - as_log_verbose(ASDisplayLog(), "%s %@", sel_getName(_cmd), node); [renderQueue enqueue:node]; } @@ -1574,33 +1550,8 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) }); } -- (void)_setClipCornerLayersVisible:(BOOL)__unused visible +- (void)_setClipCornerLayersVisible:(BOOL)visible { - /* - ASPerformBlockOnMainThread(^{ - ASDisplayNodeAssertMainThread(); - if (visible) { - for (int idx = 0; idx < NUM_CLIP_CORNER_LAYERS; idx++) { - if (_clipCornerLayers[idx] == nil) { - static ASDisplayNodeCornerLayerDelegate *clipCornerLayers; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - clipCornerLayers = [[ASDisplayNodeCornerLayerDelegate alloc] init]; - }); - _clipCornerLayers[idx] = [[CALayer alloc] init]; - _clipCornerLayers[idx].zPosition = 99999; - _clipCornerLayers[idx].delegate = clipCornerLayers; - } - } - [self _updateClipCornerLayerContentsWithRadius:_cornerRadius backgroundColor:self.backgroundColor]; - } else { - for (int idx = 0; idx < NUM_CLIP_CORNER_LAYERS; idx++) { - [_clipCornerLayers[idx] removeFromSuperlayer]; - _clipCornerLayers[idx] = nil; - } - } - }); - */ } - (void)updateCornerRoundingWithType:(ASCornerRoundingType)newRoundingType cornerRadius:(CGFloat)newCornerRadius @@ -2110,8 +2061,6 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { // TODO: Disabled due to PR: https://github.com/TextureGroup/Texture/pull/1204 // ASAssertUnlocked(__instanceLock__); - as_log_verbose(ASNodeLog(), "Insert subnode %@ at index %zd of %@ and remove subnode %@", subnode, subnodeIndex, self, oldSubnode); - if (subnode == nil || subnode == self) { ASDisplayNodeFailAssert(@"Cannot insert a nil subnode or self as subnode"); return; @@ -2548,7 +2497,6 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { // Note: we continue even if supernode is nil to ensure view/layer are removed from hierarchy. if (supernode != nil) { - as_log_verbose(ASNodeLog(), "Remove %@ from supernode %@", self, supernode); } // Clear supernode's reference to us before removing the view from the hierarchy, as _ASDisplayView @@ -2828,7 +2776,6 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { } ASDisplayNodeLogEvent(self, @"setHierarchyState: %@", NSStringFromASHierarchyStateChange(oldState, newState)); - as_log_verbose(ASNodeLog(), "%s%@ %@", sel_getName(_cmd), NSStringFromASHierarchyStateChange(oldState, newState), self); } - (void)willEnterHierarchy @@ -2943,8 +2890,6 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { - (void)recursivelySetInterfaceState:(ASInterfaceState)newInterfaceState { - as_activity_create_for_scope("Recursively set interface state"); - // Instead of each node in the recursion assuming it needs to schedule itself for display, // setInterfaceState: skips this when handling range-managed nodes (our whole subtree has this set). // If our range manager intends for us to be displayed right now, and didn't before, get started! @@ -3105,7 +3050,6 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) { // for all cell nodes and it isn't currently meaningful. BOOL measureChangeOnly = ((oldState | newState) == ASInterfaceStateMeasureLayout); if (!measureChangeOnly) { - as_log_verbose(ASNodeLog(), "%s %@ %@", sel_getName(_cmd), NSStringFromASInterfaceStateChange(oldState, newState), self); } ASDisplayNodeLogEvent(self, @"interfaceStateDidChange: %@", NSStringFromASInterfaceStateChange(oldState, newState)); diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNodeExtras.mm b/submodules/AsyncDisplayKit/Source/ASDisplayNodeExtras.mm similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNodeExtras.mm rename to submodules/AsyncDisplayKit/Source/ASDisplayNodeExtras.mm index d1be1576e3..de08b03c43 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNodeExtras.mm +++ b/submodules/AsyncDisplayKit/Source/ASDisplayNodeExtras.mm @@ -8,8 +8,8 @@ // #import -#import -#import +#import "ASDisplayNodeInternal.h" +#import "ASDisplayNode+FrameworkPrivate.h" #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNodeInternal.h b/submodules/AsyncDisplayKit/Source/ASDisplayNodeInternal.h similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNodeInternal.h rename to submodules/AsyncDisplayKit/Source/ASDisplayNodeInternal.h index 8cc49441e1..88b268c696 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNodeInternal.h +++ b/submodules/AsyncDisplayKit/Source/ASDisplayNodeInternal.h @@ -16,7 +16,7 @@ #import #import #import -#import +#import "ASLayoutTransition.h" #import #import #import @@ -287,16 +287,6 @@ AS_EXTERN NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimest */ - (void)__setNeedsDisplay; -/** - * Setup the node -> controller reference. Strong or weak is based on - * the "shouldInvertStrongReference" property of the controller. - * - * Note: To prevent lock-ordering deadlocks, this method does not take the node's lock. - * In practice, changing the node controller of a node multiple times is not - * supported behavior. - */ -- (void)__setNodeController:(ASNodeController *)controller; - /** * Called whenever the node needs to layout its subnodes and, if it's already loaded, its subviews. Executes the layout pass for the node * diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNodeLayout.h b/submodules/AsyncDisplayKit/Source/ASDisplayNodeLayout.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNodeLayout.h rename to submodules/AsyncDisplayKit/Source/ASDisplayNodeLayout.h index ba8d9c273e..af905a813a 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNodeLayout.h +++ b/submodules/AsyncDisplayKit/Source/ASDisplayNodeLayout.h @@ -9,6 +9,7 @@ #pragma once +#import #import @class ASLayout; diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASEditableTextNode.mm b/submodules/AsyncDisplayKit/Source/ASEditableTextNode.mm similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASEditableTextNode.mm rename to submodules/AsyncDisplayKit/Source/ASEditableTextNode.mm index 21f94b4493..87baeb09ac 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASEditableTextNode.mm +++ b/submodules/AsyncDisplayKit/Source/ASEditableTextNode.mm @@ -15,7 +15,7 @@ #import #import #import -#import +#import "ASTextNodeWordKerner.h" #import @implementation ASEditableTextNodeTargetForAction diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASExperimentalFeatures.mm b/submodules/AsyncDisplayKit/Source/ASExperimentalFeatures.mm similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASExperimentalFeatures.mm rename to submodules/AsyncDisplayKit/Source/ASExperimentalFeatures.mm index d03248462f..653db2c370 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASExperimentalFeatures.mm +++ b/submodules/AsyncDisplayKit/Source/ASExperimentalFeatures.mm @@ -7,6 +7,7 @@ // #import + #import NSArray *ASExperimentalFeaturesGetNames(ASExperimentalFeatures flags) diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASGraphicsContext.mm b/submodules/AsyncDisplayKit/Source/ASGraphicsContext.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASGraphicsContext.mm rename to submodules/AsyncDisplayKit/Source/ASGraphicsContext.mm index b950613d0d..82f7c4730c 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASGraphicsContext.mm +++ b/submodules/AsyncDisplayKit/Source/ASGraphicsContext.mm @@ -7,10 +7,10 @@ // #import -#import +#import "ASCGImageBuffer.h" #import #import -#import +#import "ASInternalHelpers.h" #import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASHashing.mm b/submodules/AsyncDisplayKit/Source/ASHashing.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASHashing.mm rename to submodules/AsyncDisplayKit/Source/ASHashing.mm diff --git a/submodules/AsyncDisplayKit/Source/ASImageNode+CGExtras.h b/submodules/AsyncDisplayKit/Source/ASImageNode+CGExtras.h new file mode 100644 index 0000000000..01b546443b --- /dev/null +++ b/submodules/AsyncDisplayKit/Source/ASImageNode+CGExtras.h @@ -0,0 +1,31 @@ +// +// ASImageNode+CGExtras.h +// Texture +// +// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import +#import + +/** + @abstract Decides how to scale and crop an image to fit in the provided size, while not wasting memory by upscaling images + @param sourceImageSize The size of the encoded image. + @param boundsSize The bounds in which the image will be displayed. + @param contentMode The mode that defines how image will be scaled and cropped to fit. Supported values are UIViewContentModeScaleToAspectFill and UIViewContentModeScaleToAspectFit. + @param cropRect A rectangle that is to be featured by the cropped image. The rectangle is specified as a "unit rectangle," using fractions of the source image's width and height, e.g. CGRectMake(0.5, 0, 0.5, 1.0) will feature the full right half a photo. If the cropRect is empty, the contentMode will be used to determine the drawRect's size, and only the cropRect's origin will be used for positioning. + @param forceUpscaling A boolean that indicates you would *not* like the backing size to be downscaled if the image is smaller than the destination size. Setting this to YES will result in higher memory usage when images are smaller than their destination. + @param forcedSize A CGSize, that if non-CGSizeZero, indicates that the backing size should be forcedSize and not calculated based on boundsSize. + @discussion If the image is smaller than the size and UIViewContentModeScaleToAspectFill is specified, we suggest the input size so it will be efficiently upscaled on the GPU by the displaying layer at composite time. + */ +AS_EXTERN void ASCroppedImageBackingSizeAndDrawRectInBounds(CGSize sourceImageSize, + CGSize boundsSize, + UIViewContentMode contentMode, + CGRect cropRect, + BOOL forceUpscaling, + CGSize forcedSize, + CGSize *outBackingSize, + CGRect *outDrawRect + ); diff --git a/submodules/AsyncDisplayKit/Source/ASImageNode+CGExtras.mm b/submodules/AsyncDisplayKit/Source/ASImageNode+CGExtras.mm new file mode 100644 index 0000000000..40b331fb32 --- /dev/null +++ b/submodules/AsyncDisplayKit/Source/ASImageNode+CGExtras.mm @@ -0,0 +1,123 @@ +// +// ASImageNode+CGExtras.mm +// Texture +// +// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import "ASImageNode+CGExtras.h" + +#import + +// TODO rewrite these to be closer to the intended use -- take UIViewContentMode as param, CGRect destinationBounds, CGSize sourceSize. +static CGSize _ASSizeFillWithAspectRatio(CGFloat aspectRatio, CGSize constraints); +static CGSize _ASSizeFitWithAspectRatio(CGFloat aspectRatio, CGSize constraints); + +static CGSize _ASSizeFillWithAspectRatio(CGFloat sizeToScaleAspectRatio, CGSize destinationSize) +{ + CGFloat destinationAspectRatio = destinationSize.width / destinationSize.height; + if (sizeToScaleAspectRatio > destinationAspectRatio) { + return CGSizeMake(destinationSize.height * sizeToScaleAspectRatio, destinationSize.height); + } else { + return CGSizeMake(destinationSize.width, round(destinationSize.width / sizeToScaleAspectRatio)); + } +} + +static CGSize _ASSizeFitWithAspectRatio(CGFloat aspectRatio, CGSize constraints) +{ + CGFloat constraintAspectRatio = constraints.width / constraints.height; + if (aspectRatio > constraintAspectRatio) { + return CGSizeMake(constraints.width, constraints.width / aspectRatio); + } else { + return CGSizeMake(constraints.height * aspectRatio, constraints.height); + } +} + +void ASCroppedImageBackingSizeAndDrawRectInBounds(CGSize sourceImageSize, + CGSize boundsSize, + UIViewContentMode contentMode, + CGRect cropRect, + BOOL forceUpscaling, + CGSize forcedSize, + CGSize *outBackingSize, + CGRect *outDrawRect + ) +{ + + size_t destinationWidth = boundsSize.width; + size_t destinationHeight = boundsSize.height; + + // Often, an image is too low resolution to completely fill the width and height provided. + // Per the API contract as commented in the header, we will adjust input parameters (destinationWidth, destinationHeight) to ensure that the image is not upscaled on the CPU. + CGFloat boundsAspectRatio = (CGFloat)destinationWidth / (CGFloat)destinationHeight; + + CGSize scaledSizeForImage = sourceImageSize; + BOOL cropToRectDimensions = !CGRectIsEmpty(cropRect); + + if (cropToRectDimensions) { + scaledSizeForImage = CGSizeMake(boundsSize.width / cropRect.size.width, boundsSize.height / cropRect.size.height); + } else { + if (contentMode == UIViewContentModeScaleAspectFill) + scaledSizeForImage = _ASSizeFillWithAspectRatio(boundsAspectRatio, sourceImageSize); + else if (contentMode == UIViewContentModeScaleAspectFit) + scaledSizeForImage = _ASSizeFitWithAspectRatio(boundsAspectRatio, sourceImageSize); + } + + // If fitting the desired aspect ratio to the image size actually results in a larger buffer, use the input values. + // However, if there is a pixel savings (e.g. we would have to upscale the image), override the function arguments. + if (CGSizeEqualToSize(CGSizeZero, forcedSize) == NO) { + destinationWidth = (size_t)round(forcedSize.width); + destinationHeight = (size_t)round(forcedSize.height); + } else if (forceUpscaling == NO && (scaledSizeForImage.width * scaledSizeForImage.height) < (destinationWidth * destinationHeight)) { + destinationWidth = (size_t)round(scaledSizeForImage.width); + destinationHeight = (size_t)round(scaledSizeForImage.height); + if (destinationWidth == 0 || destinationHeight == 0) { + *outBackingSize = CGSizeZero; + *outDrawRect = CGRectZero; + return; + } + } + + // Figure out the scaled size within the destination bounds. + CGFloat sourceImageAspectRatio = sourceImageSize.width / sourceImageSize.height; + CGSize scaledSizeForDestination = CGSizeMake(destinationWidth, destinationHeight); + + if (cropToRectDimensions) { + scaledSizeForDestination = CGSizeMake(boundsSize.width / cropRect.size.width, boundsSize.height / cropRect.size.height); + } else { + if (contentMode == UIViewContentModeScaleAspectFill) + scaledSizeForDestination = _ASSizeFillWithAspectRatio(sourceImageAspectRatio, scaledSizeForDestination); + else if (contentMode == UIViewContentModeScaleAspectFit) + scaledSizeForDestination = _ASSizeFitWithAspectRatio(sourceImageAspectRatio, scaledSizeForDestination); + } + + // Figure out the rectangle into which to draw the image. + CGRect drawRect = CGRectZero; + if (cropToRectDimensions) { + drawRect = CGRectMake(-cropRect.origin.x * scaledSizeForDestination.width, + -cropRect.origin.y * scaledSizeForDestination.height, + scaledSizeForDestination.width, + scaledSizeForDestination.height); + } else { + // We want to obey the origin of cropRect in aspect-fill mode. + if (contentMode == UIViewContentModeScaleAspectFill) { + drawRect = CGRectMake(((destinationWidth - scaledSizeForDestination.width) * cropRect.origin.x), + ((destinationHeight - scaledSizeForDestination.height) * cropRect.origin.y), + scaledSizeForDestination.width, + scaledSizeForDestination.height); + + } + // And otherwise just center it. + else { + drawRect = CGRectMake(((destinationWidth - scaledSizeForDestination.width) / 2.0), + ((destinationHeight - scaledSizeForDestination.height) / 2.0), + scaledSizeForDestination.width, + scaledSizeForDestination.height); + } + } + + *outDrawRect = drawRect; + *outBackingSize = CGSizeMake(destinationWidth, destinationHeight); +} diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASImageContainerProtocolCategories.h b/submodules/AsyncDisplayKit/Source/ASImageNode+Private.h similarity index 50% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASImageContainerProtocolCategories.h rename to submodules/AsyncDisplayKit/Source/ASImageNode+Private.h index 44ddc354fd..8de78c8784 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASImageContainerProtocolCategories.h +++ b/submodules/AsyncDisplayKit/Source/ASImageNode+Private.h @@ -1,5 +1,5 @@ // -// ASImageContainerProtocolCategories.h +// ASImageNode+Private.h // Texture // // Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. @@ -7,13 +7,11 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import -#import +#pragma once -@interface UIImage (ASImageContainerProtocol) - -@end - -@interface NSData (ASImageContainerProtocol) +@interface ASImageNode (Private) + +- (void)_locked_setImage:(UIImage *)image; +- (UIImage *)_locked_Image; @end diff --git a/submodules/AsyncDisplayKit/Source/ASImageNode.mm b/submodules/AsyncDisplayKit/Source/ASImageNode.mm new file mode 100644 index 0000000000..ddd9fe68c7 --- /dev/null +++ b/submodules/AsyncDisplayKit/Source/ASImageNode.mm @@ -0,0 +1,744 @@ +// +// ASImageNode.mm +// Texture +// +// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import + +#import + +#import +#import +#import +#import "ASDisplayNode+FrameworkPrivate.h" +#import +#import +#import +#import +#import "ASImageNode+CGExtras.h" +#import +#import +#import +#import "ASWeakMap.h" +#import +#import "_ASCoreAnimationExtras.h" + +// TODO: It would be nice to remove this dependency; it's the only subclass using more than +FrameworkSubclasses.h +#import "ASDisplayNodeInternal.h" + +static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0}; + +typedef void (^ASImageNodeDrawParametersBlock)(ASWeakMapEntry *entry); + +@interface ASImageNodeDrawParameters : NSObject { +@package + UIImage *_image; + BOOL _opaque; + CGRect _bounds; + CGFloat _contentsScale; + UIColor *_backgroundColor; + UIViewContentMode _contentMode; + BOOL _cropEnabled; + BOOL _forceUpscaling; + CGSize _forcedSize; + CGRect _cropRect; + CGRect _cropDisplayBounds; + asimagenode_modification_block_t _imageModificationBlock; + ASDisplayNodeContextModifier _willDisplayNodeContentWithRenderingContext; + ASDisplayNodeContextModifier _didDisplayNodeContentWithRenderingContext; + ASImageNodeDrawParametersBlock _didDrawBlock; +} + +@end + +@implementation ASImageNodeDrawParameters + +@end + +/** + * Contains all data that is needed to generate the content bitmap. + */ +@interface ASImageNodeContentsKey : NSObject + +@property (nonatomic) UIImage *image; +@property CGSize backingSize; +@property CGRect imageDrawRect; +@property BOOL isOpaque; +@property (nonatomic, copy) UIColor *backgroundColor; +@property (nonatomic) ASDisplayNodeContextModifier willDisplayNodeContentWithRenderingContext; +@property (nonatomic) ASDisplayNodeContextModifier didDisplayNodeContentWithRenderingContext; +@property (nonatomic) asimagenode_modification_block_t imageModificationBlock; + +@end + +@implementation ASImageNodeContentsKey + +- (BOOL)isEqual:(id)object +{ + if (self == object) { + return YES; + } + + // Optimization opportunity: The `isKindOfClass` call here could be avoided by not using the NSObject `isEqual:` + // convention and instead using a custom comparison function that assumes all items are heterogeneous. + // However, profiling shows that our entire `isKindOfClass` expression is only ~1/40th of the total + // overheard of our caching, so it's likely not high-impact. + if ([object isKindOfClass:[ASImageNodeContentsKey class]]) { + ASImageNodeContentsKey *other = (ASImageNodeContentsKey *)object; + return [_image isEqual:other.image] + && CGSizeEqualToSize(_backingSize, other.backingSize) + && CGRectEqualToRect(_imageDrawRect, other.imageDrawRect) + && _isOpaque == other.isOpaque + && [_backgroundColor isEqual:other.backgroundColor] + && _willDisplayNodeContentWithRenderingContext == other.willDisplayNodeContentWithRenderingContext + && _didDisplayNodeContentWithRenderingContext == other.didDisplayNodeContentWithRenderingContext + && _imageModificationBlock == other.imageModificationBlock; + } else { + return NO; + } +} + +- (NSUInteger)hash +{ +#pragma clang diagnostic push +#pragma clang diagnostic warning "-Wpadded" + struct { + NSUInteger imageHash; + CGSize backingSize; + CGRect imageDrawRect; + NSInteger isOpaque; + NSUInteger backgroundColorHash; + void *willDisplayNodeContentWithRenderingContext; + void *didDisplayNodeContentWithRenderingContext; + void *imageModificationBlock; +#pragma clang diagnostic pop + } data = { + _image.hash, + _backingSize, + _imageDrawRect, + _isOpaque, + _backgroundColor.hash, + (void *)_willDisplayNodeContentWithRenderingContext, + (void *)_didDisplayNodeContentWithRenderingContext, + (void *)_imageModificationBlock + }; + return ASHashBytes(&data, sizeof(data)); +} + +@end + + +@implementation ASImageNode +{ +@private + UIImage *_image; + ASWeakMapEntry *_weakCacheEntry; // Holds a reference that keeps our contents in cache. + UIColor *_placeholderColor; + + void (^_displayCompletionBlock)(BOOL canceled); + + // Cropping. + BOOL _cropEnabled; // Defaults to YES. + BOOL _forceUpscaling; //Defaults to NO. + CGSize _forcedSize; //Defaults to CGSizeZero, indicating no forced size. + CGRect _cropRect; // Defaults to CGRectMake(0.5, 0.5, 0, 0) + CGRect _cropDisplayBounds; // Defaults to CGRectNull +} + +@synthesize image = _image; +@synthesize imageModificationBlock = _imageModificationBlock; + +#pragma mark - Lifecycle + +- (instancetype)init +{ + if (!(self = [super init])) + return nil; + + // TODO can this be removed? + self.contentsScale = ASScreenScale(); + self.contentMode = UIViewContentModeScaleAspectFill; + self.opaque = NO; + self.clipsToBounds = YES; + + // If no backgroundColor is set to the image node and it's a subview of UITableViewCell, UITableView is setting + // the opaque value of all subviews to YES if highlighting / selection is happening and does not set it back to the + // initial value. With setting a explicit backgroundColor we can prevent that change. + self.backgroundColor = [UIColor clearColor]; + + _cropEnabled = YES; + _forceUpscaling = NO; + _cropRect = CGRectMake(0.5, 0.5, 0, 0); + _cropDisplayBounds = CGRectNull; + _placeholderColor = ASDisplayNodeDefaultPlaceholderColor(); +#ifndef MINIMAL_ASDK + _animatedImageRunLoopMode = ASAnimatedImageDefaultRunLoopMode; +#endif + + return self; +} + +- (void)dealloc +{ + // Invalidate all components around animated images +#ifndef MINIMAL_ASDK + [self invalidateAnimatedImage]; +#endif +} + +#pragma mark - Placeholder + +- (UIImage *)placeholderImage +{ + // FIXME: Replace this implementation with reusable CALayers that have .backgroundColor set. + // This would completely eliminate the memory and performance cost of the backing store. + CGSize size = self.calculatedSize; + if ((size.width * size.height) < CGFLOAT_EPSILON) { + return nil; + } + + AS::MutexLocker l(__instanceLock__); + + ASGraphicsBeginImageContextWithOptions(size, NO, 1); + [self.placeholderColor setFill]; + UIRectFill(CGRectMake(0, 0, size.width, size.height)); + UIImage *image = ASGraphicsGetImageAndEndCurrentContext(); + + return image; +} + +#pragma mark - Layout and Sizing + +- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize +{ + const auto image = ASLockedSelf(_image); + + if (image == nil) { + return [super calculateSizeThatFits:constrainedSize]; + } + + return image.size; +} + +#pragma mark - Setter / Getter + +- (void)setImage:(UIImage *)image +{ + AS::MutexLocker l(__instanceLock__); + [self _locked_setImage:image]; +} + +- (void)_locked_setImage:(UIImage *)image +{ + ASAssertLocked(__instanceLock__); + if (ASObjectIsEqual(_image, image)) { + return; + } + + UIImage *oldImage = _image; + _image = image; + + if (image != nil) { + // We explicitly call setNeedsDisplay in this case, although we know setNeedsDisplay will be called with lock held. + // Therefore we have to be careful in methods that are involved with setNeedsDisplay to not run into a deadlock + [self setNeedsDisplay]; + + if (_displayWithoutProcessing && ASDisplayNodeThreadIsMain()) { + BOOL stretchable = !UIEdgeInsetsEqualToEdgeInsets(image.capInsets, UIEdgeInsetsZero); + if (stretchable) { + ASDisplayNodeSetResizableContents(self, image); + } else { + self.contents = (id)image.CGImage; + } + return; + } + } else { + self.contents = nil; + } + + // Destruction of bigger images on the main thread can be expensive + // and can take some time, so we dispatch onto a bg queue to + // actually dealloc. + CGSize oldImageSize = oldImage.size; + BOOL shouldReleaseImageOnBackgroundThread = oldImageSize.width > kMinReleaseImageOnBackgroundSize.width + || oldImageSize.height > kMinReleaseImageOnBackgroundSize.height; + if (shouldReleaseImageOnBackgroundThread) { + ASPerformBackgroundDeallocation(&oldImage); + } +} + +- (UIImage *)image +{ + return ASLockedSelf(_image); +} + +- (UIColor *)placeholderColor +{ + return ASLockedSelf(_placeholderColor); +} + +- (void)setPlaceholderColor:(UIColor *)placeholderColor +{ + ASLockScopeSelf(); + if (ASCompareAssignCopy(_placeholderColor, placeholderColor)) { + _placeholderEnabled = (placeholderColor != nil); + } +} + +#pragma mark - Drawing + +- (NSObject *)drawParametersForAsyncLayer:(_ASDisplayLayer *)layer +{ + ASLockScopeSelf(); + + ASImageNodeDrawParameters *drawParameters = [[ASImageNodeDrawParameters alloc] init]; + drawParameters->_image = _image; + drawParameters->_bounds = [self threadSafeBounds]; + drawParameters->_opaque = self.opaque; + drawParameters->_contentsScale = _contentsScaleForDisplay; + drawParameters->_backgroundColor = self.backgroundColor; + drawParameters->_contentMode = self.contentMode; + drawParameters->_cropEnabled = _cropEnabled; + drawParameters->_forceUpscaling = _forceUpscaling; + drawParameters->_forcedSize = _forcedSize; + drawParameters->_cropRect = _cropRect; + drawParameters->_cropDisplayBounds = _cropDisplayBounds; + drawParameters->_imageModificationBlock = _imageModificationBlock; + drawParameters->_willDisplayNodeContentWithRenderingContext = _willDisplayNodeContentWithRenderingContext; + drawParameters->_didDisplayNodeContentWithRenderingContext = _didDisplayNodeContentWithRenderingContext; + + // Hack for now to retain the weak entry that was created while this drawing happened + drawParameters->_didDrawBlock = ^(ASWeakMapEntry *entry){ + ASLockScopeSelf(); + _weakCacheEntry = entry; + }; + + return drawParameters; +} + ++ (UIImage *)displayWithParameters:(id)parameter isCancelled:(NS_NOESCAPE asdisplaynode_iscancelled_block_t)isCancelled +{ + ASImageNodeDrawParameters *drawParameter = (ASImageNodeDrawParameters *)parameter; + + UIImage *image = drawParameter->_image; + if (image == nil) { + return nil; + } + + if (true) { + return image; + } + + CGRect drawParameterBounds = drawParameter->_bounds; + BOOL forceUpscaling = drawParameter->_forceUpscaling; + CGSize forcedSize = drawParameter->_forcedSize; + BOOL cropEnabled = drawParameter->_cropEnabled; + BOOL isOpaque = drawParameter->_opaque; + UIColor *backgroundColor = drawParameter->_backgroundColor; + UIViewContentMode contentMode = drawParameter->_contentMode; + CGFloat contentsScale = drawParameter->_contentsScale; + CGRect cropDisplayBounds = drawParameter->_cropDisplayBounds; + CGRect cropRect = drawParameter->_cropRect; + asimagenode_modification_block_t imageModificationBlock = drawParameter->_imageModificationBlock; + ASDisplayNodeContextModifier willDisplayNodeContentWithRenderingContext = drawParameter->_willDisplayNodeContentWithRenderingContext; + ASDisplayNodeContextModifier didDisplayNodeContentWithRenderingContext = drawParameter->_didDisplayNodeContentWithRenderingContext; + + BOOL hasValidCropBounds = cropEnabled && !CGRectIsEmpty(cropDisplayBounds); + CGRect bounds = (hasValidCropBounds ? cropDisplayBounds : drawParameterBounds); + + + ASDisplayNodeAssert(contentsScale > 0, @"invalid contentsScale at display time"); + + // if the image is resizable, bail early since the image has likely already been configured + BOOL stretchable = !UIEdgeInsetsEqualToEdgeInsets(image.capInsets, UIEdgeInsetsZero); + if (stretchable) { + if (imageModificationBlock != NULL) { + image = imageModificationBlock(image); + } + return image; + } + + CGSize imageSize = image.size; + CGSize imageSizeInPixels = CGSizeMake(imageSize.width * image.scale, imageSize.height * image.scale); + CGSize boundsSizeInPixels = CGSizeMake(std::floor(bounds.size.width * contentsScale), std::floor(bounds.size.height * contentsScale)); + + BOOL contentModeSupported = contentMode == UIViewContentModeScaleAspectFill || + contentMode == UIViewContentModeScaleAspectFit || + contentMode == UIViewContentModeCenter; + + CGSize backingSize = CGSizeZero; + CGRect imageDrawRect = CGRectZero; + + if (boundsSizeInPixels.width * contentsScale < 1.0f || boundsSizeInPixels.height * contentsScale < 1.0f || + imageSizeInPixels.width < 1.0f || imageSizeInPixels.height < 1.0f) { + return nil; + } + + + // If we're not supposed to do any cropping, just decode image at original size + if (!cropEnabled || !contentModeSupported || stretchable) { + backingSize = imageSizeInPixels; + imageDrawRect = (CGRect){.size = backingSize}; + } else { + if (CGSizeEqualToSize(CGSizeZero, forcedSize) == NO) { + //scale forced size + forcedSize.width *= contentsScale; + forcedSize.height *= contentsScale; + } + ASCroppedImageBackingSizeAndDrawRectInBounds(imageSizeInPixels, + boundsSizeInPixels, + contentMode, + cropRect, + forceUpscaling, + forcedSize, + &backingSize, + &imageDrawRect); + } + + if (backingSize.width <= 0.0f || backingSize.height <= 0.0f || + imageDrawRect.size.width <= 0.0f || imageDrawRect.size.height <= 0.0f) { + return nil; + } + + ASImageNodeContentsKey *contentsKey = [[ASImageNodeContentsKey alloc] init]; + contentsKey.image = image; + contentsKey.backingSize = backingSize; + contentsKey.imageDrawRect = imageDrawRect; + contentsKey.isOpaque = isOpaque; + contentsKey.backgroundColor = backgroundColor; + contentsKey.willDisplayNodeContentWithRenderingContext = willDisplayNodeContentWithRenderingContext; + contentsKey.didDisplayNodeContentWithRenderingContext = didDisplayNodeContentWithRenderingContext; + contentsKey.imageModificationBlock = imageModificationBlock; + + if (isCancelled()) { + return nil; + } + + ASWeakMapEntry *entry = [self.class contentsForkey:contentsKey + drawParameters:parameter + isCancelled:isCancelled]; + // If nil, we were cancelled. + if (entry == nil) { + return nil; + } + + if (drawParameter->_didDrawBlock) { + drawParameter->_didDrawBlock(entry); + } + + return entry.value; +} + +static ASWeakMap *cache = nil; + ++ (ASWeakMapEntry *)contentsForkey:(ASImageNodeContentsKey *)key drawParameters:(id)drawParameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelled +{ + static dispatch_once_t onceToken; + static AS::Mutex *cacheLock = nil; + dispatch_once(&onceToken, ^{ + cacheLock = new AS::Mutex(); + }); + + { + AS::MutexLocker l(*cacheLock); + if (!cache) { + cache = [[ASWeakMap alloc] init]; + } + ASWeakMapEntry *entry = [cache entryForKey:key]; + if (entry != nil) { + return entry; + } + } + + // cache miss + UIImage *contents = [self createContentsForkey:key drawParameters:drawParameters isCancelled:isCancelled]; + if (contents == nil) { // If nil, we were cancelled + return nil; + } + + { + AS::MutexLocker l(*cacheLock); + return [cache setObject:contents forKey:key]; + } +} + ++ (UIImage *)createContentsForkey:(ASImageNodeContentsKey *)key drawParameters:(id)drawParameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelled +{ + // The following `ASGraphicsBeginImageContextWithOptions` call will sometimes take take longer than 5ms on an + // A5 processor for a 400x800 backingSize. + // Check for cancellation before we call it. + if (isCancelled()) { + return nil; + } + + // Use contentsScale of 1.0 and do the contentsScale handling in boundsSizeInPixels so ASCroppedImageBackingSizeAndDrawRectInBounds + // will do its rounding on pixel instead of point boundaries + ASGraphicsBeginImageContextWithOptions(key.backingSize, key.isOpaque, 1.0); + + BOOL contextIsClean = YES; + + CGContextRef context = UIGraphicsGetCurrentContext(); + if (context && key.willDisplayNodeContentWithRenderingContext) { + key.willDisplayNodeContentWithRenderingContext(context, drawParameters); + contextIsClean = NO; + } + + // if view is opaque, fill the context with background color + if (key.isOpaque && key.backgroundColor) { + [key.backgroundColor setFill]; + UIRectFill({ .size = key.backingSize }); + contextIsClean = NO; + } + + // iOS 9 appears to contain a thread safety regression when drawing the same CGImageRef on + // multiple threads concurrently. In fact, instead of crashing, it appears to deadlock. + // The issue is present in Mac OS X El Capitan and has been seen hanging Pro apps like Adobe Premiere, + // as well as iOS games, and a small number of ASDK apps that provide the same image reference + // to many separate ASImageNodes. A workaround is to set .displaysAsynchronously = NO for the nodes + // that may get the same pointer for a given UI asset image, etc. + // FIXME: We should replace @synchronized here, probably using a global, locked NSMutableSet, and + // only if the object already exists in the set we should create a semaphore to signal waiting threads + // upon removal of the object from the set when the operation completes. + // Another option is to have ASDisplayNode+AsyncDisplay coordinate these cases, and share the decoded buffer. + // Details tracked in https://github.com/facebook/AsyncDisplayKit/issues/1068 + + UIImage *image = key.image; + BOOL canUseCopy = (contextIsClean || ASImageAlphaInfoIsOpaque(CGImageGetAlphaInfo(image.CGImage))); + CGBlendMode blendMode = canUseCopy ? kCGBlendModeCopy : kCGBlendModeNormal; + + @synchronized(image) { + [image drawInRect:key.imageDrawRect blendMode:blendMode alpha:1]; + } + + if (context && key.didDisplayNodeContentWithRenderingContext) { + key.didDisplayNodeContentWithRenderingContext(context, drawParameters); + } + + // Check cancellation one last time before forming image. + if (isCancelled()) { + ASGraphicsEndImageContext(); + return nil; + } + + UIImage *result = ASGraphicsGetImageAndEndCurrentContext(); + + if (key.imageModificationBlock) { + result = key.imageModificationBlock(result); + } + + return result; +} + +- (void)displayDidFinish +{ + [super displayDidFinish]; + + __instanceLock__.lock(); + UIImage *image = _image; + void (^displayCompletionBlock)(BOOL canceled) = _displayCompletionBlock; + BOOL shouldPerformDisplayCompletionBlock = (image && displayCompletionBlock); + + // Clear the ivar now. The block is retained and will be executed shortly. + if (shouldPerformDisplayCompletionBlock) { + _displayCompletionBlock = nil; + } + + __instanceLock__.unlock(); + + // If we've got a block to perform after displaying, do it. + if (shouldPerformDisplayCompletionBlock) { + displayCompletionBlock(NO); + } +} + +- (void)setNeedsDisplayWithCompletion:(void (^ _Nullable)(BOOL canceled))displayCompletionBlock +{ + if (self.displaySuspended) { + if (displayCompletionBlock) + displayCompletionBlock(YES); + return; + } + + // Stash the block and call-site queue. We'll invoke it in -displayDidFinish. + { + AS::MutexLocker l(__instanceLock__); + if (_displayCompletionBlock != displayCompletionBlock) { + _displayCompletionBlock = displayCompletionBlock; + } + } + + [self setNeedsDisplay]; +} + +#pragma mark Interface State + +- (void)clearContents +{ + [super clearContents]; + + AS::MutexLocker l(__instanceLock__); + _weakCacheEntry = nil; // release contents from the cache. +} + +#pragma mark - Cropping + +- (BOOL)isCropEnabled +{ + AS::MutexLocker l(__instanceLock__); + return _cropEnabled; +} + +- (void)setCropEnabled:(BOOL)cropEnabled +{ + [self setCropEnabled:cropEnabled recropImmediately:NO inBounds:self.bounds]; +} + +- (void)setCropEnabled:(BOOL)cropEnabled recropImmediately:(BOOL)recropImmediately inBounds:(CGRect)cropBounds +{ + __instanceLock__.lock(); + if (_cropEnabled == cropEnabled) { + __instanceLock__.unlock(); + return; + } + + _cropEnabled = cropEnabled; + _cropDisplayBounds = cropBounds; + + UIImage *image = _image; + __instanceLock__.unlock(); + + // If we have an image to display, display it, respecting our recrop flag. + if (image != nil) { + ASPerformBlockOnMainThread(^{ + if (recropImmediately) + [self displayImmediately]; + else + [self setNeedsDisplay]; + }); + } +} + +- (CGRect)cropRect +{ + AS::MutexLocker l(__instanceLock__); + return _cropRect; +} + +- (void)setCropRect:(CGRect)cropRect +{ + { + AS::MutexLocker l(__instanceLock__); + if (CGRectEqualToRect(_cropRect, cropRect)) { + return; + } + + _cropRect = cropRect; + } + + // TODO: this logic needs to be updated to respect cropRect. + CGSize boundsSize = self.bounds.size; + CGSize imageSize = self.image.size; + + BOOL isCroppingImage = ((boundsSize.width < imageSize.width) || (boundsSize.height < imageSize.height)); + + // Re-display if we need to. + ASPerformBlockOnMainThread(^{ + if (self.nodeLoaded && self.contentMode == UIViewContentModeScaleAspectFill && isCroppingImage) + [self setNeedsDisplay]; + }); +} + +- (BOOL)forceUpscaling +{ + AS::MutexLocker l(__instanceLock__); + return _forceUpscaling; +} + +- (void)setForceUpscaling:(BOOL)forceUpscaling +{ + AS::MutexLocker l(__instanceLock__); + _forceUpscaling = forceUpscaling; +} + +- (CGSize)forcedSize +{ + AS::MutexLocker l(__instanceLock__); + return _forcedSize; +} + +- (void)setForcedSize:(CGSize)forcedSize +{ + AS::MutexLocker l(__instanceLock__); + _forcedSize = forcedSize; +} + +- (asimagenode_modification_block_t)imageModificationBlock +{ + AS::MutexLocker l(__instanceLock__); + return _imageModificationBlock; +} + +- (void)setImageModificationBlock:(asimagenode_modification_block_t)imageModificationBlock +{ + AS::MutexLocker l(__instanceLock__); + _imageModificationBlock = imageModificationBlock; +} + +#pragma mark - Debug + +- (void)layout +{ + [super layout]; +} + +@end + +#pragma mark - Extras + +asimagenode_modification_block_t ASImageNodeRoundBorderModificationBlock(CGFloat borderWidth, UIColor *borderColor) +{ + return ^(UIImage *originalImage) { + ASGraphicsBeginImageContextWithOptions(originalImage.size, NO, originalImage.scale); + UIBezierPath *roundOutline = [UIBezierPath bezierPathWithOvalInRect:(CGRect){CGPointZero, originalImage.size}]; + + // Make the image round + [roundOutline addClip]; + + // Draw the original image + [originalImage drawAtPoint:CGPointZero blendMode:kCGBlendModeCopy alpha:1]; + + // Draw a border on top. + if (borderWidth > 0.0) { + [borderColor setStroke]; + [roundOutline setLineWidth:borderWidth]; + [roundOutline stroke]; + } + + return ASGraphicsGetImageAndEndCurrentContext(); + }; +} + +asimagenode_modification_block_t ASImageNodeTintColorModificationBlock(UIColor *color) +{ + return ^(UIImage *originalImage) { + ASGraphicsBeginImageContextWithOptions(originalImage.size, NO, originalImage.scale); + + // Set color and render template + [color setFill]; + UIImage *templateImage = [originalImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + [templateImage drawAtPoint:CGPointZero blendMode:kCGBlendModeCopy alpha:1]; + + UIImage *modifiedImage = ASGraphicsGetImageAndEndCurrentContext(); + + // if the original image was stretchy, keep it stretchy + if (!UIEdgeInsetsEqualToEdgeInsets(originalImage.capInsets, UIEdgeInsetsZero)) { + modifiedImage = [modifiedImage resizableImageWithCapInsets:originalImage.capInsets resizingMode:originalImage.resizingMode]; + } + + return modifiedImage; + }; +} diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASInternalHelpers.mm b/submodules/AsyncDisplayKit/Source/ASInternalHelpers.mm similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASInternalHelpers.mm rename to submodules/AsyncDisplayKit/Source/ASInternalHelpers.mm index a9926ccca4..d3dd743b7c 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASInternalHelpers.mm +++ b/submodules/AsyncDisplayKit/Source/ASInternalHelpers.mm @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASInternalHelpers.h" #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayout.mm b/submodules/AsyncDisplayKit/Source/ASLayout.mm similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayout.mm rename to submodules/AsyncDisplayKit/Source/ASLayout.mm index bc2c46de57..6a6a96f24c 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayout.mm +++ b/submodules/AsyncDisplayKit/Source/ASLayout.mm @@ -12,14 +12,14 @@ #import #import +#import #import -#import -#import +#import "ASLayoutSpecUtilities.h" +#import "ASLayoutSpec+Subclasses.h" #import #import #import -#import NSString *const ASThreadDictMaxConstraintSizeKey = @"kASThreadDictMaxConstraintSizeKey"; @@ -94,7 +94,7 @@ static std::atomic_bool static_retainsSublayoutLayoutElements = ATOMIC_VAR_INIT( _layoutElementType = layoutElement.layoutElementType; if (!ASIsCGSizeValidForSize(size)) { - ASDisplayNodeFailAssert(@"layoutSize is invalid and unsafe to provide to Core Animation! Release configurations will force to 0, 0. Size = %@, node = %@", NSStringFromCGSize(size), layoutElement); + //ASDisplayNodeFailAssert(@"layoutSize is invalid and unsafe to provide to Core Animation! Release configurations will force to 0, 0. Size = %@, node = %@", NSStringFromCGSize(size), layoutElement); size = CGSizeZero; } else { size = CGSizeMake(ASCeilPixelValue(size.width), ASCeilPixelValue(size.height)); diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutElement.mm b/submodules/AsyncDisplayKit/Source/ASLayoutElement.mm similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutElement.mm rename to submodules/AsyncDisplayKit/Source/ASLayoutElement.mm index 887f609e99..61f61e7514 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutElement.mm +++ b/submodules/AsyncDisplayKit/Source/ASLayoutElement.mm @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASDisplayNode+FrameworkPrivate.h" #import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutElementStylePrivate.h b/submodules/AsyncDisplayKit/Source/ASLayoutElementStylePrivate.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutElementStylePrivate.h rename to submodules/AsyncDisplayKit/Source/ASLayoutElementStylePrivate.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutManager.h b/submodules/AsyncDisplayKit/Source/ASLayoutManager.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutManager.h rename to submodules/AsyncDisplayKit/Source/ASLayoutManager.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutManager.mm b/submodules/AsyncDisplayKit/Source/ASLayoutManager.mm similarity index 96% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutManager.mm rename to submodules/AsyncDisplayKit/Source/ASLayoutManager.mm index fbb3b49ea4..9eca28e489 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutManager.mm +++ b/submodules/AsyncDisplayKit/Source/ASLayoutManager.mm @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASLayoutManager.h" @implementation ASLayoutManager diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpec+Subclasses.h b/submodules/AsyncDisplayKit/Source/ASLayoutSpec+Subclasses.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpec+Subclasses.h rename to submodules/AsyncDisplayKit/Source/ASLayoutSpec+Subclasses.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpec+Subclasses.mm b/submodules/AsyncDisplayKit/Source/ASLayoutSpec+Subclasses.mm similarity index 95% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpec+Subclasses.mm rename to submodules/AsyncDisplayKit/Source/ASLayoutSpec+Subclasses.mm index 17ff53e6c5..c1e4e2496a 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpec+Subclasses.mm +++ b/submodules/AsyncDisplayKit/Source/ASLayoutSpec+Subclasses.mm @@ -7,10 +7,10 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASLayoutSpec+Subclasses.h" #import -#import +#import "ASLayoutSpecPrivate.h" #pragma mark - ASNullLayoutSpec diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpec.mm b/submodules/AsyncDisplayKit/Source/ASLayoutSpec.mm similarity index 93% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpec.mm rename to submodules/AsyncDisplayKit/Source/ASLayoutSpec.mm index 7cf5e198ba..6123e4d734 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpec.mm +++ b/submodules/AsyncDisplayKit/Source/ASLayoutSpec.mm @@ -8,12 +8,12 @@ // #import -#import +#import "ASLayoutSpecPrivate.h" -#import +#import "ASLayoutSpec+Subclasses.h" #import -#import +#import "ASLayoutElementStylePrivate.h" #import #import #import @@ -317,7 +317,17 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__) + (NSString *)asciiArtStringForChildren:(NSArray *)children parentName:(NSString *)parentName direction:(ASStackLayoutDirection)direction { - return @""; + NSMutableArray *childStrings = [NSMutableArray array]; + for (id layoutChild in children) { + NSString *childString = [layoutChild asciiArtString]; + if (childString) { + [childStrings addObject:childString]; + } + } + if (direction == ASStackLayoutDirectionHorizontal) { + return [ASAsciiArtBoxCreator horizontalBoxStringForChildren:childStrings parent:parentName]; + } + return [ASAsciiArtBoxCreator verticalBoxStringForChildren:childStrings parent:parentName]; } + (NSString *)asciiArtStringForChildren:(NSArray *)children parentName:(NSString *)parentName diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpecPrivate.h b/submodules/AsyncDisplayKit/Source/ASLayoutSpecPrivate.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpecPrivate.h rename to submodules/AsyncDisplayKit/Source/ASLayoutSpecPrivate.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpecUtilities.h b/submodules/AsyncDisplayKit/Source/ASLayoutSpecUtilities.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpecUtilities.h rename to submodules/AsyncDisplayKit/Source/ASLayoutSpecUtilities.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutTransition.h b/submodules/AsyncDisplayKit/Source/ASLayoutTransition.h similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutTransition.h rename to submodules/AsyncDisplayKit/Source/ASLayoutTransition.h index f2bcf9b253..d11eb65fb1 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutTransition.h +++ b/submodules/AsyncDisplayKit/Source/ASLayoutTransition.h @@ -7,9 +7,10 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import #import -#import +#import "ASDisplayNodeLayout.h" #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutTransition.mm b/submodules/AsyncDisplayKit/Source/ASLayoutTransition.mm similarity index 96% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutTransition.mm rename to submodules/AsyncDisplayKit/Source/ASLayoutTransition.mm index 2fea2b8ad0..0956943cc0 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutTransition.mm +++ b/submodules/AsyncDisplayKit/Source/ASLayoutTransition.mm @@ -7,13 +7,12 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASLayoutTransition.h" #import #import -#import // Required for _insertSubnode... / _removeFromSupernode. -#import +#import "ASDisplayNodeInternal.h" // Required for _insertSubnode... / _removeFromSupernode. #import @@ -98,7 +97,6 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) { [self calculateSubnodeOperationsIfNeeded]; // Create an activity even if no subnodes affected. - as_activity_create_for_scope("Apply subnode insertions and moves"); if (_insertedSubnodePositions.size() == 0 && _subnodeMoves.size() == 0) { return; } @@ -131,7 +129,6 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) { - (void)applySubnodeRemovals { - as_activity_scope(as_activity_create("Apply subnode removals", AS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT)); MutexLocker l(*__instanceLock__); [self calculateSubnodeOperationsIfNeeded]; @@ -158,7 +155,6 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) { } // Create an activity even if no subnodes affected. - as_activity_create_for_scope("Calculate subnode operations"); ASLayout *previousLayout = _previousLayout.layout; ASLayout *pendingLayout = _pendingLayout.layout; diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMainSerialQueue.h b/submodules/AsyncDisplayKit/Source/ASMainSerialQueue.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMainSerialQueue.h rename to submodules/AsyncDisplayKit/Source/ASMainSerialQueue.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMainSerialQueue.mm b/submodules/AsyncDisplayKit/Source/ASMainSerialQueue.mm similarity index 93% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMainSerialQueue.mm rename to submodules/AsyncDisplayKit/Source/ASMainSerialQueue.mm index 06cb7c3b9b..81a3116c81 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMainSerialQueue.mm +++ b/submodules/AsyncDisplayKit/Source/ASMainSerialQueue.mm @@ -7,10 +7,10 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASMainSerialQueue.h" #import -#import +#import "ASInternalHelpers.h" @interface ASMainSerialQueue () { diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMainThreadDeallocation.mm b/submodules/AsyncDisplayKit/Source/ASMainThreadDeallocation.mm similarity index 86% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMainThreadDeallocation.mm rename to submodules/AsyncDisplayKit/Source/ASMainThreadDeallocation.mm index 1cf90ada05..cb6dee7641 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMainThreadDeallocation.mm +++ b/submodules/AsyncDisplayKit/Source/ASMainThreadDeallocation.mm @@ -10,8 +10,7 @@ #import #import -#import -#import +#import "ASInternalHelpers.h" #import #import @@ -42,15 +41,12 @@ } if ([object_getClass(value) needsMainThreadDeallocation]) { - as_log_debug(ASMainThreadDeallocationLog(), "%@: Trampolining ivar '%s' value %@ for main deallocation.", self, ivar_getName(ivar), value); - // Release the ivar's reference before handing the object to the queue so we // don't risk holding onto it longer than the queue does. object_setIvar(self, ivar, nil); ASPerformMainThreadDeallocation(&value); } else { - as_log_debug(ASMainThreadDeallocationLog(), "%@: Not trampolining ivar '%s' value %@.", self, ivar_getName(ivar), value); } } } @@ -112,16 +108,13 @@ // If it's `id` we have to include it just in case. resultIvars[resultCount] = ivar; resultCount += 1; - as_log_verbose(ASMainThreadDeallocationLog(), "%@: Marking ivar '%s' for possible main deallocation due to type id", self, ivar_getName(ivar)); } else { // If it's an ivar with a static type, check the type. Class c = ASGetClassFromType(type); if ([c needsMainThreadDeallocation]) { resultIvars[resultCount] = ivar; resultCount += 1; - as_log_verbose(ASMainThreadDeallocationLog(), "%@: Marking ivar '%s' for main deallocation due to class %@", self, ivar_getName(ivar), c); } else { - as_log_verbose(ASMainThreadDeallocationLog(), "%@: Skipping ivar '%s' for main deallocation.", self, ivar_getName(ivar)); } } } diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASObjectDescriptionHelpers.mm b/submodules/AsyncDisplayKit/Source/ASObjectDescriptionHelpers.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASObjectDescriptionHelpers.mm rename to submodules/AsyncDisplayKit/Source/ASObjectDescriptionHelpers.mm index cbd6be0963..2b5d94492c 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASObjectDescriptionHelpers.mm +++ b/submodules/AsyncDisplayKit/Source/ASObjectDescriptionHelpers.mm @@ -11,7 +11,7 @@ #import -#import +#import "NSIndexSet+ASHelpers.h" NSString *ASGetDescriptionValueString(id object) { diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASPendingStateController.h b/submodules/AsyncDisplayKit/Source/ASPendingStateController.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASPendingStateController.h rename to submodules/AsyncDisplayKit/Source/ASPendingStateController.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASPendingStateController.mm b/submodules/AsyncDisplayKit/Source/ASPendingStateController.mm similarity index 91% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASPendingStateController.mm rename to submodules/AsyncDisplayKit/Source/ASPendingStateController.mm index 269b37e948..e7ca4a71de 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASPendingStateController.mm +++ b/submodules/AsyncDisplayKit/Source/ASPendingStateController.mm @@ -7,10 +7,10 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASPendingStateController.h" #import #import -#import // Required for -applyPendingViewState; consider moving this to +FrameworkPrivate +#import "ASDisplayNodeInternal.h" // Required for -applyPendingViewState; consider moving this to +FrameworkPrivate @interface ASPendingStateController() { diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRecursiveUnfairLock.mm b/submodules/AsyncDisplayKit/Source/ASRecursiveUnfairLock.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRecursiveUnfairLock.mm rename to submodules/AsyncDisplayKit/Source/ASRecursiveUnfairLock.mm index e44eec76d1..9e4a29d47a 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRecursiveUnfairLock.mm +++ b/submodules/AsyncDisplayKit/Source/ASRecursiveUnfairLock.mm @@ -6,7 +6,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASRecursiveUnfairLock.h" #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASResponderChainEnumerator.h b/submodules/AsyncDisplayKit/Source/ASResponderChainEnumerator.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASResponderChainEnumerator.h rename to submodules/AsyncDisplayKit/Source/ASResponderChainEnumerator.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASResponderChainEnumerator.mm b/submodules/AsyncDisplayKit/Source/ASResponderChainEnumerator.mm similarity index 94% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASResponderChainEnumerator.mm rename to submodules/AsyncDisplayKit/Source/ASResponderChainEnumerator.mm index bb16e0fc57..2d94c99945 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASResponderChainEnumerator.mm +++ b/submodules/AsyncDisplayKit/Source/ASResponderChainEnumerator.mm @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASResponderChainEnumerator.h" #import @implementation ASResponderChainEnumerator { diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRunLoopQueue.mm b/submodules/AsyncDisplayKit/Source/ASRunLoopQueue.mm similarity index 88% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRunLoopQueue.mm rename to submodules/AsyncDisplayKit/Source/ASRunLoopQueue.mm index 4aefeeb89d..2d2415e2b1 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRunLoopQueue.mm +++ b/submodules/AsyncDisplayKit/Source/ASRunLoopQueue.mm @@ -9,11 +9,10 @@ #import #import -#import #import #import #import -#import +#import "ASSignpost.h" #import #import #import @@ -115,9 +114,6 @@ static void runLoopSourceCallback(void *info) { NSPointerArray *_internalQueue; // Use NSPointerArray so we can decide __strong or __weak per-instance. AS::RecursiveMutex _internalQueueLock; - // In order to not pollute the top-level activities, each queue has 1 root activity. - os_activity_t _rootActivity; - #if ASRunLoopQueueLoggingEnabled NSTimer *_runloopQueueLoggingTimer; #endif @@ -138,15 +134,6 @@ static void runLoopSourceCallback(void *info) { _queueConsumer = handlerBlock; _batchSize = 1; _ensureExclusiveMembership = YES; - - // We don't want to pollute the top-level app activities with run loop batches, so we create one top-level - // activity per queue, and each batch activity joins that one instead. - _rootActivity = as_activity_create("Process run loop queue items", OS_ACTIVITY_NONE, OS_ACTIVITY_FLAG_DEFAULT); - { - // Log a message identifying this queue into the queue's root activity. - as_activity_scope_verbose(_rootActivity); - as_log_verbose(ASDisplayLog(), "Created run loop queue: %@", self); - } // Self is guaranteed to outlive the observer. Without the high cost of a weak pointer, // __unsafe_unretained allows us to avoid flagging the memory cycle detector. @@ -260,15 +247,10 @@ static void runLoopSourceCallback(void *info) { // itemsToProcess will be empty if _queueConsumer == nil so no need to check again. const auto count = itemsToProcess.size(); if (count > 0) { - as_activity_scope_verbose(as_activity_create("Process run loop queue batch", _rootActivity, OS_ACTIVITY_FLAG_DEFAULT)); const auto itemsEnd = itemsToProcess.cend(); for (auto iterator = itemsToProcess.begin(); iterator < itemsEnd; iterator++) { __unsafe_unretained id value = *iterator; _queueConsumer(value, isQueueDrained && iterator == itemsEnd - 1); - as_log_verbose(ASDisplayLog(), "processed %@", value); - } - if (count > 1) { - as_log_verbose(ASDisplayLog(), "processed %lu items", (unsigned long)count); } } @@ -339,7 +321,6 @@ ASSynthesizeLockingMethodsWithMutex(_internalQueueLock) AS::Mutex _internalQueueLock; // In order to not pollute the top-level activities, each queue has 1 root activity. - os_activity_t _rootActivity; #if ASRunLoopQueueLoggingEnabled NSTimer *_runloopQueueLoggingTimer; @@ -368,15 +349,6 @@ dispatch_once_t _ASSharedCATransactionQueueOnceToken; _internalQueue.reserve(kInternalQueueInitialCapacity); _batchBuffer.reserve(kInternalQueueInitialCapacity); - // We don't want to pollute the top-level app activities with run loop batches, so we create one top-level - // activity per queue, and each batch activity joins that one instead. - _rootActivity = as_activity_create("Process run loop queue items", OS_ACTIVITY_NONE, OS_ACTIVITY_FLAG_DEFAULT); - { - // Log a message identifying this queue into the queue's root activity. - as_activity_scope_verbose(_rootActivity); - as_log_verbose(ASDisplayLog(), "Created run loop queue: %@", self); - } - // Self is guaranteed to outlive the observer. Without the high cost of a weak pointer, // __unsafe_unretained allows us to avoid flagging the memory cycle detector. __unsafe_unretained __typeof__(self) weakSelf = self; @@ -439,7 +411,6 @@ dispatch_once_t _ASSharedCATransactionQueueOnceToken; if (count == 0) { return; } - as_activity_scope_verbose(as_activity_create("Process run loop queue batch", _rootActivity, OS_ACTIVITY_FLAG_DEFAULT)); ASSignpostStart(ASSignpostRunLoopQueueBatch); // Swap buffers, clear our hash table. @@ -451,10 +422,8 @@ dispatch_once_t _ASSharedCATransactionQueueOnceToken; for (const id &value : _batchBuffer) { [value prepareForCATransactionCommit]; - as_log_verbose(ASDisplayLog(), "processed %@", value); } _batchBuffer.clear(); - as_log_verbose(ASDisplayLog(), "processed %lu items", (unsigned long)count); ASSignpostEnd(ASSignpostRunLoopQueueBatch); } diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASScrollDirection.mm b/submodules/AsyncDisplayKit/Source/ASScrollDirection.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASScrollDirection.mm rename to submodules/AsyncDisplayKit/Source/ASScrollDirection.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASScrollNode.mm b/submodules/AsyncDisplayKit/Source/ASScrollNode.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASScrollNode.mm rename to submodules/AsyncDisplayKit/Source/ASScrollNode.mm index c686b5f8ac..9a6af0725c 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASScrollNode.mm +++ b/submodules/AsyncDisplayKit/Source/ASScrollNode.mm @@ -9,7 +9,7 @@ #import #import -#import +#import "ASDisplayNode+FrameworkPrivate.h" #import #import #import @@ -87,7 +87,7 @@ restrictedToSize:(ASLayoutElementSize)size relativeToParentSize:(CGSize)parentSize { - ASLockScopeSelf(); + ASScopedLockSelfOrToRoot(); ASSizeRange contentConstrainedSize = constrainedSize; if (ASScrollDirectionContainsVerticalDirection(_scrollableDirections)) { diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASSignpost.h b/submodules/AsyncDisplayKit/Source/ASSignpost.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASSignpost.h rename to submodules/AsyncDisplayKit/Source/ASSignpost.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitComponents.mm b/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitComponents.mm rename to submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitContext.h b/submodules/AsyncDisplayKit/Source/ASTextKitContext.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitContext.h rename to submodules/AsyncDisplayKit/Source/ASTextKitContext.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitContext.mm b/submodules/AsyncDisplayKit/Source/ASTextKitContext.mm similarity index 96% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitContext.mm rename to submodules/AsyncDisplayKit/Source/ASTextKitContext.mm index 8883f3175f..42f4a1a45c 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitContext.mm +++ b/submodules/AsyncDisplayKit/Source/ASTextKitContext.mm @@ -7,11 +7,11 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASTextKitContext.h" #if AS_ENABLE_TEXTNODE -#import +#import "ASLayoutManager.h" #import #include diff --git a/submodules/AsyncDisplayKit/Source/ASTextNodeCommon.h b/submodules/AsyncDisplayKit/Source/ASTextNodeCommon.h new file mode 100644 index 0000000000..765f401c2a --- /dev/null +++ b/submodules/AsyncDisplayKit/Source/ASTextNodeCommon.h @@ -0,0 +1,34 @@ +// +// ASTextNodeCommon.h +// Texture +// +// Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import + +#import + +#define AS_TEXT_ALERT_UNIMPLEMENTED_FEATURE() { \ + static dispatch_once_t onceToken; \ + dispatch_once(&onceToken, ^{ \ + NSLog(@"[Texture] Warning: Feature %@ is unimplemented in %@.", NSStringFromSelector(_cmd), NSStringFromClass(self.class)); \ + });\ +} + +/** + * Highlight styles. + */ +typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { + /** + * Highlight style for text on a light background. + */ + ASTextNodeHighlightStyleLight, + + /** + * Highlight style for text on a dark background. + */ + ASTextNodeHighlightStyleDark +}; + diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextNodeWordKerner.h b/submodules/AsyncDisplayKit/Source/ASTextNodeWordKerner.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextNodeWordKerner.h rename to submodules/AsyncDisplayKit/Source/ASTextNodeWordKerner.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextNodeWordKerner.mm b/submodules/AsyncDisplayKit/Source/ASTextNodeWordKerner.mm similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextNodeWordKerner.mm rename to submodules/AsyncDisplayKit/Source/ASTextNodeWordKerner.mm index 67e640557c..e1d0c73c0e 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextNodeWordKerner.mm +++ b/submodules/AsyncDisplayKit/Source/ASTextNodeWordKerner.mm @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASTextNodeWordKerner.h" #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTraitCollection.mm b/submodules/AsyncDisplayKit/Source/ASTraitCollection.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTraitCollection.mm rename to submodules/AsyncDisplayKit/Source/ASTraitCollection.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakMap.h b/submodules/AsyncDisplayKit/Source/ASWeakMap.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakMap.h rename to submodules/AsyncDisplayKit/Source/ASWeakMap.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakMap.mm b/submodules/AsyncDisplayKit/Source/ASWeakMap.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakMap.mm rename to submodules/AsyncDisplayKit/Source/ASWeakMap.mm index 3110b13d37..1267d8ff69 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakMap.mm +++ b/submodules/AsyncDisplayKit/Source/ASWeakMap.mm @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASWeakMap.h" @interface ASWeakMapEntry () @property (nonatomic, readonly) id key; diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakProxy.h b/submodules/AsyncDisplayKit/Source/ASWeakProxy.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakProxy.h rename to submodules/AsyncDisplayKit/Source/ASWeakProxy.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakProxy.mm b/submodules/AsyncDisplayKit/Source/ASWeakProxy.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakProxy.mm rename to submodules/AsyncDisplayKit/Source/ASWeakProxy.mm index 4a73408dd5..4a3b5c8a2a 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakProxy.mm +++ b/submodules/AsyncDisplayKit/Source/ASWeakProxy.mm @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "ASWeakProxy.h" #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakSet.mm b/submodules/AsyncDisplayKit/Source/ASWeakSet.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakSet.mm rename to submodules/AsyncDisplayKit/Source/ASWeakSet.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASAbstractLayoutController.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASAbstractLayoutController.h deleted file mode 100644 index 6de7801fb6..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASAbstractLayoutController.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// ASAbstractLayoutController.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -AS_EXTERN ASDirectionalScreenfulBuffer ASDirectionalScreenfulBufferHorizontal(ASScrollDirection scrollDirection, ASRangeTuningParameters rangeTuningParameters); - -AS_EXTERN ASDirectionalScreenfulBuffer ASDirectionalScreenfulBufferVertical(ASScrollDirection scrollDirection, ASRangeTuningParameters rangeTuningParameters); - -AS_EXTERN CGRect CGRectExpandToRangeWithScrollableDirections(CGRect rect, ASRangeTuningParameters tuningParameters, ASScrollDirection scrollableDirections, ASScrollDirection scrollDirection); - -@interface ASAbstractLayoutController : NSObject - -@end - -@interface ASAbstractLayoutController (Unavailable) - -- (NSHashTable *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType __unavailable; - -- (void)allIndexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode displaySet:(NSHashTable * _Nullable * _Nullable)displaySet preloadSet:(NSHashTable * _Nullable * _Nullable)preloadSet __unavailable; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASAbstractLayoutController.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASAbstractLayoutController.mm deleted file mode 100644 index 9d6b61f689..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASAbstractLayoutController.mm +++ /dev/null @@ -1,185 +0,0 @@ -// -// ASAbstractLayoutController.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import - -ASRangeTuningParameters const ASRangeTuningParametersZero = {}; - -BOOL ASRangeTuningParametersEqualToRangeTuningParameters(ASRangeTuningParameters lhs, ASRangeTuningParameters rhs) -{ - return lhs.leadingBufferScreenfuls == rhs.leadingBufferScreenfuls && lhs.trailingBufferScreenfuls == rhs.trailingBufferScreenfuls; -} - -ASDirectionalScreenfulBuffer ASDirectionalScreenfulBufferHorizontal(ASScrollDirection scrollDirection, - ASRangeTuningParameters rangeTuningParameters) -{ - ASDirectionalScreenfulBuffer horizontalBuffer = {0, 0}; - BOOL movingRight = ASScrollDirectionContainsRight(scrollDirection); - - horizontalBuffer.positiveDirection = movingRight ? rangeTuningParameters.leadingBufferScreenfuls - : rangeTuningParameters.trailingBufferScreenfuls; - horizontalBuffer.negativeDirection = movingRight ? rangeTuningParameters.trailingBufferScreenfuls - : rangeTuningParameters.leadingBufferScreenfuls; - return horizontalBuffer; -} - -ASDirectionalScreenfulBuffer ASDirectionalScreenfulBufferVertical(ASScrollDirection scrollDirection, - ASRangeTuningParameters rangeTuningParameters) -{ - ASDirectionalScreenfulBuffer verticalBuffer = {0, 0}; - BOOL movingDown = ASScrollDirectionContainsDown(scrollDirection); - - verticalBuffer.positiveDirection = movingDown ? rangeTuningParameters.leadingBufferScreenfuls - : rangeTuningParameters.trailingBufferScreenfuls; - verticalBuffer.negativeDirection = movingDown ? rangeTuningParameters.trailingBufferScreenfuls - : rangeTuningParameters.leadingBufferScreenfuls; - return verticalBuffer; -} - -CGRect CGRectExpandHorizontally(CGRect rect, ASDirectionalScreenfulBuffer buffer) -{ - CGFloat negativeDirectionWidth = buffer.negativeDirection * rect.size.width; - CGFloat positiveDirectionWidth = buffer.positiveDirection * rect.size.width; - rect.size.width = negativeDirectionWidth + rect.size.width + positiveDirectionWidth; - rect.origin.x -= negativeDirectionWidth; - return rect; -} - -CGRect CGRectExpandVertically(CGRect rect, ASDirectionalScreenfulBuffer buffer) -{ - CGFloat negativeDirectionHeight = buffer.negativeDirection * rect.size.height; - CGFloat positiveDirectionHeight = buffer.positiveDirection * rect.size.height; - rect.size.height = negativeDirectionHeight + rect.size.height + positiveDirectionHeight; - rect.origin.y -= negativeDirectionHeight; - return rect; -} - -CGRect CGRectExpandToRangeWithScrollableDirections(CGRect rect, ASRangeTuningParameters tuningParameters, - ASScrollDirection scrollableDirections, ASScrollDirection scrollDirection) -{ - // Can scroll horizontally - expand the range appropriately - if (ASScrollDirectionContainsHorizontalDirection(scrollableDirections)) { - ASDirectionalScreenfulBuffer horizontalBuffer = ASDirectionalScreenfulBufferHorizontal(scrollDirection, tuningParameters); - rect = CGRectExpandHorizontally(rect, horizontalBuffer); - } - - // Can scroll vertically - expand the range appropriately - if (ASScrollDirectionContainsVerticalDirection(scrollableDirections)) { - ASDirectionalScreenfulBuffer verticalBuffer = ASDirectionalScreenfulBufferVertical(scrollDirection, tuningParameters); - rect = CGRectExpandVertically(rect, verticalBuffer); - } - - return rect; -} - -@interface ASAbstractLayoutController () { - std::vector> _tuningParameters; -} -@end - -@implementation ASAbstractLayoutController - -+ (std::vector>)defaultTuningParameters -{ - auto tuningParameters = std::vector> (ASLayoutRangeModeCount, std::vector (ASLayoutRangeTypeCount)); - - tuningParameters[ASLayoutRangeModeFull][ASLayoutRangeTypeDisplay] = { - .leadingBufferScreenfuls = 1.0, - .trailingBufferScreenfuls = 0.5 - }; - - tuningParameters[ASLayoutRangeModeFull][ASLayoutRangeTypePreload] = { - .leadingBufferScreenfuls = 2.5, - .trailingBufferScreenfuls = 1.5 - }; - - tuningParameters[ASLayoutRangeModeMinimum][ASLayoutRangeTypeDisplay] = { - .leadingBufferScreenfuls = 0.25, - .trailingBufferScreenfuls = 0.25 - }; - tuningParameters[ASLayoutRangeModeMinimum][ASLayoutRangeTypePreload] = { - .leadingBufferScreenfuls = 0.5, - .trailingBufferScreenfuls = 0.25 - }; - - tuningParameters[ASLayoutRangeModeVisibleOnly][ASLayoutRangeTypeDisplay] = { - .leadingBufferScreenfuls = 0, - .trailingBufferScreenfuls = 0 - }; - tuningParameters[ASLayoutRangeModeVisibleOnly][ASLayoutRangeTypePreload] = { - .leadingBufferScreenfuls = 0, - .trailingBufferScreenfuls = 0 - }; - - // The Low Memory range mode has special handling. Because a zero range still includes the visible area / bounds, - // in order to implement the behavior of releasing all graphics memory (backing stores), ASRangeController must check - // for this range mode and use an empty set for displayIndexPaths rather than querying the ASLayoutController for the indexPaths. - tuningParameters[ASLayoutRangeModeLowMemory][ASLayoutRangeTypeDisplay] = { - .leadingBufferScreenfuls = 0, - .trailingBufferScreenfuls = 0 - }; - tuningParameters[ASLayoutRangeModeLowMemory][ASLayoutRangeTypePreload] = { - .leadingBufferScreenfuls = 0, - .trailingBufferScreenfuls = 0 - }; - return tuningParameters; -} - -- (instancetype)init -{ - if (!(self = [super init])) { - return nil; - } - ASDisplayNodeAssert(self.class != [ASAbstractLayoutController class], @"Should never create instances of abstract class ASAbstractLayoutController."); - - _tuningParameters = [[self class] defaultTuningParameters]; - - return self; -} - -#pragma mark - Tuning Parameters - -- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType -{ - return [self tuningParametersForRangeMode:ASLayoutRangeModeFull rangeType:rangeType]; -} - -- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType -{ - return [self setTuningParameters:tuningParameters forRangeMode:ASLayoutRangeModeFull rangeType:rangeType]; -} - -- (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType -{ - ASDisplayNodeAssert(rangeMode < _tuningParameters.size() && rangeType < _tuningParameters[rangeMode].size(), @"Requesting a range that is OOB for the configured tuning parameters"); - return _tuningParameters[rangeMode][rangeType]; -} - -- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType -{ - ASDisplayNodeAssert(rangeMode < _tuningParameters.size() && rangeType < _tuningParameters[rangeMode].size(), @"Setting a range that is OOB for the configured tuning parameters"); - _tuningParameters[rangeMode][rangeType] = tuningParameters; -} - -#pragma mark - Abstract Index Path Range Support - -- (NSHashTable *)elementsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType map:(ASElementMap *)map -{ - ASDisplayNodeAssertNotSupported(); - return nil; -} - -- (void)allElementsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode displaySet:(NSHashTable *__autoreleasing _Nullable *)displaySet preloadSet:(NSHashTable *__autoreleasing _Nullable *)preloadSet map:(ASElementMap *)map -{ - ASDisplayNodeAssertNotSupported(); -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDelegateProxy.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDelegateProxy.h deleted file mode 100644 index 7ed406b6db..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDelegateProxy.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// ASDelegateProxy.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -@class ASDelegateProxy; -@protocol ASDelegateProxyInterceptor -@required -// Called if the target object is discovered to be nil if it had been non-nil at init time. -// This happens if the object is deallocated, because the proxy must maintain a weak reference to avoid cycles. -// Though the target object may become nil, the interceptor must not; it is assumed the interceptor owns the proxy. -- (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy; -@end - -/** - * Stand-in for delegates like UITableView or UICollectionView's delegate / dataSource. - * Any selectors flagged by "interceptsSelector" are routed to the interceptor object and are not delivered to the target. - * Everything else leaves AsyncDisplayKit safely and arrives at the original target object. - */ - -@interface ASDelegateProxy : NSProxy - -- (instancetype)initWithTarget:(id)target interceptor:(id )interceptor; - -// This method must be overridden by a subclass. -- (BOOL)interceptsSelector:(SEL)selector; - -@end - -/** - * ASTableView intercepts and/or overrides a few of UITableView's critical data source and delegate methods. - * - * Any selector included in this function *MUST* be implemented by ASTableView. - */ - -@interface ASTableViewProxy : ASDelegateProxy -@end - -/** - * ASCollectionView intercepts and/or overrides a few of UICollectionView's critical data source and delegate methods. - * - * Any selector included in this function *MUST* be implemented by ASCollectionView. - */ - -@interface ASCollectionViewProxy : ASDelegateProxy -@end - -@interface ASPagerNodeProxy : ASDelegateProxy -@end - diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDelegateProxy.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDelegateProxy.mm deleted file mode 100644 index a5368024d1..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDelegateProxy.mm +++ /dev/null @@ -1,273 +0,0 @@ -// -// ASDelegateProxy.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#ifndef MINIMAL_ASDK - -#import -#import -#import -#import - -// UIKit performs a class check for UIDataSourceModelAssociation protocol conformance rather than an instance check, so -// the implementation of conformsToProtocol: below never gets called. We need to declare the two as conforming to the protocol here, then -// we need to implement dummy methods to get rid of a compiler warning about not conforming to the protocol. -@interface ASTableViewProxy () -@end - -@interface ASCollectionViewProxy () -@end - -@interface ASDelegateProxy (UIDataSourceModelAssociationPrivate) -- (nullable NSString *)_modelIdentifierForElementAtIndexPath:(NSIndexPath *)indexPath inView:(UIView *)view; -- (nullable NSIndexPath *)_indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view; -@end - -@implementation ASTableViewProxy - -- (BOOL)interceptsSelector:(SEL)selector -{ - return ( - // handled by ASTableView node<->cell machinery - selector == @selector(tableView:cellForRowAtIndexPath:) || - selector == @selector(tableView:heightForRowAtIndexPath:) || - - // Selection, highlighting, menu - selector == @selector(tableView:willSelectRowAtIndexPath:) || - selector == @selector(tableView:didSelectRowAtIndexPath:) || - selector == @selector(tableView:willDeselectRowAtIndexPath:) || - selector == @selector(tableView:didDeselectRowAtIndexPath:) || - selector == @selector(tableView:shouldHighlightRowAtIndexPath:) || - selector == @selector(tableView:didHighlightRowAtIndexPath:) || - selector == @selector(tableView:didUnhighlightRowAtIndexPath:) || - selector == @selector(tableView:shouldShowMenuForRowAtIndexPath:) || - selector == @selector(tableView:canPerformAction:forRowAtIndexPath:withSender:) || - selector == @selector(tableView:performAction:forRowAtIndexPath:withSender:) || - - // handled by ASRangeController - selector == @selector(numberOfSectionsInTableView:) || - selector == @selector(tableView:numberOfRowsInSection:) || - - // reordering support - selector == @selector(tableView:canMoveRowAtIndexPath:) || - selector == @selector(tableView:moveRowAtIndexPath:toIndexPath:) || - - // used for ASCellNode visibility - selector == @selector(scrollViewDidScroll:) || - - // used for ASCellNode user interaction - selector == @selector(scrollViewWillBeginDragging:) || - selector == @selector(scrollViewDidEndDragging:willDecelerate:) || - - // used for ASRangeController visibility updates - selector == @selector(tableView:willDisplayCell:forRowAtIndexPath:) || - selector == @selector(tableView:didEndDisplayingCell:forRowAtIndexPath:) || - - // used for batch fetching API - selector == @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:) || - selector == @selector(scrollViewDidEndDecelerating:) || - - // UIDataSourceModelAssociation - selector == @selector(modelIdentifierForElementAtIndexPath:inView:) || - selector == @selector(indexPathForElementWithModelIdentifier:inView:) - ); -} - -- (nullable NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)indexPath inView:(UIView *)view { - return [self _modelIdentifierForElementAtIndexPath:indexPath inView:view]; -} - -- (nullable NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view { - return [self _indexPathForElementWithModelIdentifier:identifier inView:view]; -} - -@end - -@implementation ASCollectionViewProxy - -- (BOOL)interceptsSelector:(SEL)selector -{ - return ( - // handled by ASCollectionView node<->cell machinery - selector == @selector(collectionView:cellForItemAtIndexPath:) || - selector == @selector(collectionView:layout:sizeForItemAtIndexPath:) || - selector == @selector(collectionView:layout:insetForSectionAtIndex:) || - selector == @selector(collectionView:layout:minimumLineSpacingForSectionAtIndex:) || - selector == @selector(collectionView:layout:minimumInteritemSpacingForSectionAtIndex:) || - selector == @selector(collectionView:layout:referenceSizeForHeaderInSection:) || - selector == @selector(collectionView:layout:referenceSizeForFooterInSection:) || - selector == @selector(collectionView:viewForSupplementaryElementOfKind:atIndexPath:) || - - // Selection, highlighting, menu - selector == @selector(collectionView:shouldSelectItemAtIndexPath:) || - selector == @selector(collectionView:didSelectItemAtIndexPath:) || - selector == @selector(collectionView:shouldDeselectItemAtIndexPath:) || - selector == @selector(collectionView:didDeselectItemAtIndexPath:) || - selector == @selector(collectionView:shouldHighlightItemAtIndexPath:) || - selector == @selector(collectionView:didHighlightItemAtIndexPath:) || - selector == @selector(collectionView:didUnhighlightItemAtIndexPath:) || - selector == @selector(collectionView:shouldShowMenuForItemAtIndexPath:) || - selector == @selector(collectionView:canPerformAction:forItemAtIndexPath:withSender:) || - selector == @selector(collectionView:performAction:forItemAtIndexPath:withSender:) || - - // Item counts - selector == @selector(numberOfSectionsInCollectionView:) || - selector == @selector(collectionView:numberOfItemsInSection:) || - - // Element appearance callbacks - selector == @selector(collectionView:willDisplayCell:forItemAtIndexPath:) || - selector == @selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:) || - selector == @selector(collectionView:willDisplaySupplementaryView:forElementKind:atIndexPath:) || - selector == @selector(collectionView:didEndDisplayingSupplementaryView:forElementOfKind:atIndexPath:) || - - // used for batch fetching API - selector == @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:) || - selector == @selector(scrollViewDidEndDecelerating:) || - - // used for ASCellNode visibility - selector == @selector(scrollViewDidScroll:) || - - // used for ASCellNode user interaction - selector == @selector(scrollViewWillBeginDragging:) || - selector == @selector(scrollViewDidEndDragging:willDecelerate:) || - - // intercepted due to not being supported by ASCollectionView (prevent bugs caused by usage) - selector == @selector(collectionView:canMoveItemAtIndexPath:) || - selector == @selector(collectionView:moveItemAtIndexPath:toIndexPath:) || - - // UIDataSourceModelAssociation - selector == @selector(modelIdentifierForElementAtIndexPath:inView:) || - selector == @selector(indexPathForElementWithModelIdentifier:inView:) - ); -} - -- (nullable NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)indexPath inView:(UIView *)view { - return [self _modelIdentifierForElementAtIndexPath:indexPath inView:view]; -} - -- (nullable NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view { - return [self _indexPathForElementWithModelIdentifier:identifier inView:view]; -} - -@end - -@implementation ASPagerNodeProxy - -- (BOOL)interceptsSelector:(SEL)selector -{ - return ( - // handled by ASPagerDataSource node<->cell machinery - selector == @selector(collectionNode:nodeForItemAtIndexPath:) || - selector == @selector(collectionNode:nodeBlockForItemAtIndexPath:) || - selector == @selector(collectionNode:numberOfItemsInSection:) || - selector == @selector(collectionNode:constrainedSizeForItemAtIndexPath:) - ); -} - -@end - -@implementation ASDelegateProxy { - id __weak _interceptor; - id __weak _target; -} - -- (instancetype)initWithTarget:(id)target interceptor:(id )interceptor -{ - ASDisplayNodeAssert(interceptor, @"interceptor must not be nil"); - - _target = target ? : [NSNull null]; - _interceptor = interceptor; - - return self; -} - -- (BOOL)conformsToProtocol:(Protocol *)aProtocol -{ - id target = _target; - if (target) { - return [target conformsToProtocol:aProtocol]; - } else { - return [super conformsToProtocol:aProtocol]; - } -} - -- (BOOL)respondsToSelector:(SEL)aSelector -{ - if ([self interceptsSelector:aSelector]) { - return [_interceptor respondsToSelector:aSelector]; - } else { - // Also return NO if _target has become nil due to zeroing weak reference (or placeholder initialization). - return [_target respondsToSelector:aSelector]; - } -} - -- (id)forwardingTargetForSelector:(SEL)aSelector -{ - if ([self interceptsSelector:aSelector]) { - return _interceptor; - } else { - id target = _target; - if (target) { - return [target respondsToSelector:aSelector] ? target : nil; - } else { - // The _interceptor needs to be nilled out in this scenario. For that a strong reference needs to be created - // to be able to nil out the _interceptor but still let it know that the proxy target has deallocated - // We have to hold a strong reference to the interceptor as we have to nil it out and call the proxyTargetHasDeallocated - // The reason that the interceptor needs to be nilled out is that there maybe a change of a infinite loop, for example - // if a method will be called in the proxyTargetHasDeallocated: that again would trigger a whole new forwarding cycle - id interceptor = _interceptor; - _interceptor = nil; - [interceptor proxyTargetHasDeallocated:self]; - - return nil; - } - } -} - -- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector -{ - // Check for a compiled definition for the selector - NSMethodSignature *methodSignature = nil; - if ([self interceptsSelector:aSelector]) { - methodSignature = [[_interceptor class] instanceMethodSignatureForSelector:aSelector]; - } else { - methodSignature = [[_target class] instanceMethodSignatureForSelector:aSelector]; - } - - // Unfortunately, in order to get this object to work properly, the use of a method which creates an NSMethodSignature - // from a C string. -methodSignatureForSelector is called when a compiled definition for the selector cannot be found. - // This is the place where we have to create our own dud NSMethodSignature. This is necessary because if this method - // returns nil, a selector not found exception is raised. The string argument to -signatureWithObjCTypes: outlines - // the return type and arguments to the message. To return a dud NSMethodSignature, pretty much any signature will - // suffice. Since the -forwardInvocation call will do nothing if the delegate does not respond to the selector, - // the dud NSMethodSignature simply gets us around the exception. - return methodSignature ?: [NSMethodSignature signatureWithObjCTypes:"@^v^c"]; -} - -- (void)forwardInvocation:(NSInvocation *)invocation -{ - // If we are down here this means _interceptor and _target where nil. Just don't do anything to prevent a crash -} - -- (BOOL)interceptsSelector:(SEL)selector -{ - ASDisplayNodeAssert(NO, @"This method must be overridden by subclasses."); - return NO; -} - -- (nullable NSString *)_modelIdentifierForElementAtIndexPath:(NSIndexPath *)indexPath inView:(UIView *)view { - return [(id)_interceptor modelIdentifierForElementAtIndexPath:indexPath inView:view]; -} - -- (nullable NSIndexPath *)_indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view { - return [(id)_interceptor indexPathForElementWithModelIdentifier:identifier inView:view]; -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+DebugTiming.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+DebugTiming.h deleted file mode 100644 index f6935224a9..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+DebugTiming.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// ASDisplayNode+DebugTiming.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -@interface ASDisplayNode (DebugTiming) - -@property (nonatomic, readonly) NSTimeInterval debugTimeToCreateView; -@property (nonatomic, readonly) NSTimeInterval debugTimeToApplyPendingState; -@property (nonatomic, readonly) NSTimeInterval debugTimeToAddSubnodeViews; -@property (nonatomic, readonly) NSTimeInterval debugTimeForDidLoad; - -- (NSTimeInterval)debugAllCreationTime; - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+DebugTiming.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+DebugTiming.mm deleted file mode 100644 index d9311a10d9..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+DebugTiming.mm +++ /dev/null @@ -1,85 +0,0 @@ -// -// ASDisplayNode+DebugTiming.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -@implementation ASDisplayNode (DebugTiming) - -#if TIME_DISPLAYNODE_OPS -- (NSTimeInterval)debugTimeToCreateView -{ - return _debugTimeToCreateView; -} - -- (NSTimeInterval)debugTimeToApplyPendingState -{ - return _debugTimeToApplyPendingState; -} - -- (NSTimeInterval)debugTimeToAddSubnodeViews -{ - return _debugTimeToAddSubnodeViews; -} - -- (NSTimeInterval)debugTimeForDidLoad -{ - return _debugTimeForDidLoad; -} - -- (NSTimeInterval)debugAllCreationTime -{ - return self.debugTimeToCreateView + self.debugTimeToApplyPendingState + self.debugTimeToAddSubnodeViews + self.debugTimeForDidLoad; -} - -// This would over-count views that are created in the parent's didload or addsubnodesubviews, so we need to take a more basic approach -//- (NSTimeInterval)debugRecursiveAllCreationTime -//{ -// __block NSTimeInterval total = 0; -// ASDisplayNodeFindAllSubnodes(self, ^(ASDisplayNode *n){ -// total += self.debugTimeToCreateView; -// total += self.debugTimeToApplyPendingState; -// total += self.debugTimeToAddSubnodeViews; -// total += self.debugTimeForDidLoad; -// return NO; -// }); -// return total; -//} - -#else - -// These ivars are compiled out so we don't have the info available -- (NSTimeInterval)debugTimeToCreateView -{ - return -1; -} - -- (NSTimeInterval)debugTimeToApplyPendingState -{ - return -1; -} - -- (NSTimeInterval)debugTimeToAddSubnodeViews -{ - return -1; -} - -- (NSTimeInterval)debugTimeForDidLoad -{ - return -1; -} - -- (NSTimeInterval)debugAllCreationTime -{ - return -1; -} - -#endif - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASElementMap.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASElementMap.h deleted file mode 100644 index 1ea0ef58d4..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASElementMap.h +++ /dev/null @@ -1,137 +0,0 @@ -// -// ASElementMap.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#ifndef MINIMAL_ASDK - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@class ASCollectionElement, ASSection, UICollectionViewLayoutAttributes; -@protocol ASSectionContext; - -/** - * An immutable representation of the state of a collection view's data. - * All items and supplementary elements are represented by ASCollectionElement. - * Fast enumeration is in terms of ASCollectionElement. - */ -AS_SUBCLASSING_RESTRICTED -@interface ASElementMap : NSObject - -/** - * The total number of elements in this map. - */ -@property (readonly) NSUInteger count; - -/** - * The number of sections (of items) in this map. - */ -@property (readonly) NSInteger numberOfSections; - -/** - * The kinds of supplementary elements present in this map. O(1) - */ -@property (copy, readonly) NSArray *supplementaryElementKinds; - -/** - * Returns number of items in the given section. O(1) - */ -- (NSInteger)numberOfItemsInSection:(NSInteger)section; - -/** - * Returns the context object for the given section, if any. O(1) - */ -- (nullable id)contextForSection:(NSInteger)section; - -/** - * All the index paths for all the items in this map. O(N) - * - * This property may be removed in the future, since it doesn't account for supplementary nodes. - */ -@property (copy, readonly) NSArray *itemIndexPaths; - -/** - * All the item elements in this map, in ascending order. O(N) - */ -@property (copy, readonly) NSArray *itemElements; - -/** - * Returns the index path that corresponds to the same element in @c map at the given @c indexPath. - * O(1) for items, fast O(N) for sections. - * - * Note you can pass "section index paths" of length 1 and get a corresponding section index path. - */ -- (nullable NSIndexPath *)convertIndexPath:(NSIndexPath *)indexPath fromMap:(ASElementMap *)map; - -/** - * Returns the section index into the receiver that corresponds to the same element in @c map at @c sectionIndex. Fast O(N). - * - * Returns @c NSNotFound if the section does not exist in the receiver. - */ -- (NSInteger)convertSection:(NSInteger)sectionIndex fromMap:(ASElementMap *)map; - -/** - * Returns the index path for the given element. O(1) - */ -- (nullable NSIndexPath *)indexPathForElement:(ASCollectionElement *)element; - -/** - * Returns the index path for the given element, if it represents a cell. O(1) - */ -- (nullable NSIndexPath *)indexPathForElementIfCell:(ASCollectionElement *)element; - -/** - * Returns the item-element at the given index path. O(1) - */ -- (nullable ASCollectionElement *)elementForItemAtIndexPath:(NSIndexPath *)indexPath; - -/** - * Returns the element for the supplementary element of the given kind at the given index path. O(1) - */ -- (nullable ASCollectionElement *)supplementaryElementOfKind:(NSString *)supplementaryElementKind atIndexPath:(NSIndexPath *)indexPath; - -/** - * Returns the element that corresponds to the given layout attributes, if any. - * - * NOTE: This method only regards the category, kind, and index path of the attributes object. Elements do not - * have any concept of size/position. - */ -- (nullable ASCollectionElement *)elementForLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes; - -/** - * A very terse description e.g. { itemCounts = [ ] } - */ -@property (readonly) NSString *smallDescription; - -#pragma mark - Initialization -- Only Useful to ASDataController - - -// SectionIndex -> ItemIndex -> Element -typedef NSArray *> ASCollectionElementTwoDimensionalArray; - -// ElementKind -> IndexPath -> Element -typedef NSDictionary *> ASSupplementaryElementDictionary; - -/** - * Create a new element map for this dataset. You probably don't need to use this – ASDataController is the only one who creates these. - * - * @param sections The array of ASSection objects. - * @param items A 2D array of ASCollectionElements, for each item. - * @param supplementaryElements A dictionary of gathered supplementary elements. - */ -- (instancetype)initWithSections:(NSArray *)sections - items:(ASCollectionElementTwoDimensionalArray *)items - supplementaryElements:(ASSupplementaryElementDictionary *)supplementaryElements; - -@end - -NS_ASSUME_NONNULL_END - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASElementMap.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASElementMap.mm deleted file mode 100644 index 6df89ff6cd..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASElementMap.mm +++ /dev/null @@ -1,280 +0,0 @@ -// -// ASElementMap.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#ifndef MINIMAL_ASDK - -#import -#import -#import -#import -#import -#import -#import -#import - -@interface ASElementMap () - -@property (nonatomic, readonly) NSArray *sections; - -// Element -> IndexPath -@property (nonatomic, readonly) NSMapTable *elementToIndexPathMap; - -// The items, in a 2D array -@property (nonatomic, readonly) ASCollectionElementTwoDimensionalArray *sectionsOfItems; - -@property (nonatomic, readonly) ASSupplementaryElementDictionary *supplementaryElements; - -@end - -@implementation ASElementMap - -- (instancetype)init -{ - return [self initWithSections:@[] items:@[] supplementaryElements:@{}]; -} - -- (instancetype)initWithSections:(NSArray *)sections items:(ASCollectionElementTwoDimensionalArray *)items supplementaryElements:(ASSupplementaryElementDictionary *)supplementaryElements -{ - NSCParameterAssert(items.count == sections.count); - - if (self = [super init]) { - _sections = [sections copy]; - _sectionsOfItems = [[NSArray alloc] initWithArray:items copyItems:YES]; - _supplementaryElements = [[NSDictionary alloc] initWithDictionary:supplementaryElements copyItems:YES]; - - // Setup our index path map - _elementToIndexPathMap = [NSMapTable mapTableWithKeyOptions:(NSMapTableStrongMemory | NSMapTableObjectPointerPersonality) valueOptions:NSMapTableCopyIn]; - NSInteger s = 0; - for (NSArray *section in _sectionsOfItems) { - NSInteger i = 0; - for (ASCollectionElement *element in section) { - NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:s]; - [_elementToIndexPathMap setObject:indexPath forKey:element]; - i++; - } - s++; - } - for (NSDictionary *supplementariesForKind in [_supplementaryElements objectEnumerator]) { - [supplementariesForKind enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *_Nonnull indexPath, ASCollectionElement * _Nonnull element, BOOL * _Nonnull stop) { - [_elementToIndexPathMap setObject:indexPath forKey:element]; - }]; - } - } - return self; -} - -- (NSUInteger)count -{ - return _elementToIndexPathMap.count; -} - -- (NSArray *)itemIndexPaths -{ - return ASIndexPathsForTwoDimensionalArray(_sectionsOfItems); -} - -- (NSArray *)itemElements -{ - return ASElementsInTwoDimensionalArray(_sectionsOfItems); -} - -- (NSInteger)numberOfSections -{ - return _sectionsOfItems.count; -} - -- (NSArray *)supplementaryElementKinds -{ - return _supplementaryElements.allKeys; -} - -- (NSInteger)numberOfItemsInSection:(NSInteger)section -{ - if (![self sectionIndexIsValid:section assert:YES]) { - return 0; - } - - return _sectionsOfItems[section].count; -} - -- (id)contextForSection:(NSInteger)section -{ - if (![self sectionIndexIsValid:section assert:NO]) { - return nil; - } - - return _sections[section].context; -} - -- (nullable NSIndexPath *)indexPathForElement:(ASCollectionElement *)element -{ - return element ? [_elementToIndexPathMap objectForKey:element] : nil; -} - -- (nullable NSIndexPath *)indexPathForElementIfCell:(ASCollectionElement *)element -{ - if (element.supplementaryElementKind == nil) { - return [self indexPathForElement:element]; - } else { - return nil; - } -} - -- (nullable ASCollectionElement *)elementForItemAtIndexPath:(NSIndexPath *)indexPath -{ - NSInteger section, item; - if (![self itemIndexPathIsValid:indexPath assert:NO item:&item section:§ion]) { - return nil; - } - - return _sectionsOfItems[section][item]; -} - -- (nullable ASCollectionElement *)supplementaryElementOfKind:(NSString *)supplementaryElementKind atIndexPath:(NSIndexPath *)indexPath -{ - return _supplementaryElements[supplementaryElementKind][indexPath]; -} - -- (ASCollectionElement *)elementForLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes -{ - switch (layoutAttributes.representedElementCategory) { - case UICollectionElementCategoryCell: - // Cell - return [self elementForItemAtIndexPath:layoutAttributes.indexPath]; - case UICollectionElementCategorySupplementaryView: - // Supplementary element. - return [self supplementaryElementOfKind:layoutAttributes.representedElementKind atIndexPath:layoutAttributes.indexPath]; - case UICollectionElementCategoryDecorationView: - // No support for decoration views. - return nil; - } -} - -- (NSIndexPath *)convertIndexPath:(NSIndexPath *)indexPath fromMap:(ASElementMap *)map -{ - if (indexPath.item == NSNotFound) { - // Section index path - NSInteger result = [self convertSection:indexPath.section fromMap:map]; - return (result != NSNotFound ? [NSIndexPath indexPathWithIndex:result] : nil); - } else { - // Item index path - ASCollectionElement *element = [map elementForItemAtIndexPath:indexPath]; - return [self indexPathForElement:element]; - } -} - -- (NSInteger)convertSection:(NSInteger)sectionIndex fromMap:(ASElementMap *)map -{ - if (![map sectionIndexIsValid:sectionIndex assert:YES]) { - return NSNotFound; - } - - ASSection *section = map.sections[sectionIndex]; - return [_sections indexOfObjectIdenticalTo:section]; -} - -#pragma mark - NSCopying - -- (id)copyWithZone:(NSZone *)zone -{ - return self; -} - -// NSMutableCopying conformance is declared in ASMutableElementMap.h, so that most consumers of ASElementMap don't bother with it. -#pragma mark - NSMutableCopying - -- (id)mutableCopyWithZone:(NSZone *)zone -{ - return [[ASMutableElementMap alloc] initWithSections:_sections items:_sectionsOfItems supplementaryElements:_supplementaryElements]; -} - -#pragma mark - NSFastEnumeration - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id _Nullable __unsafe_unretained [])buffer count:(NSUInteger)len -{ - return [_elementToIndexPathMap countByEnumeratingWithState:state objects:buffer count:len]; -} - -- (NSString *)smallDescription -{ - NSMutableArray *sectionDescriptions = [NSMutableArray array]; - - NSUInteger i = 0; - for (NSArray *section in _sectionsOfItems) { - [sectionDescriptions addObject:[NSString stringWithFormat:@"", i, section.count]]; - i++; - } - return ASObjectDescriptionMakeWithoutObject(@[ @{ @"itemCounts": sectionDescriptions }]); -} - -#pragma mark - ASDescriptionProvider - -- (NSString *)description -{ - return ASObjectDescriptionMake(self, [self propertiesForDescription]); -} - -- (NSMutableArray *)propertiesForDescription -{ - NSMutableArray *result = [NSMutableArray array]; - [result addObject:@{ @"items" : _sectionsOfItems }]; - [result addObject:@{ @"supplementaryElements" : _supplementaryElements }]; - return result; -} - -#pragma mark - Internal - -/** - * Fails assert + return NO if section is out of bounds. - */ -- (BOOL)sectionIndexIsValid:(NSInteger)section assert:(BOOL)assert -{ - NSInteger sectionCount = _sectionsOfItems.count; - if (section >= sectionCount || section < 0) { - if (assert) { - ASDisplayNodeFailAssert(@"Invalid section index %ld when there are only %ld sections!", (long)section, (long)sectionCount); - } - return NO; - } else { - return YES; - } -} - -/** - * If indexPath is nil, just returns NO. - * If indexPath is invalid, fails assertion and returns NO. - * Otherwise returns YES and sets the item & section. - */ -- (BOOL)itemIndexPathIsValid:(NSIndexPath *)indexPath assert:(BOOL)assert item:(out NSInteger *)outItem section:(out NSInteger *)outSection -{ - if (indexPath == nil) { - return NO; - } - - NSInteger section = indexPath.section; - if (![self sectionIndexIsValid:section assert:assert]) { - return NO; - } - - NSInteger itemCount = _sectionsOfItems[section].count; - NSInteger item = indexPath.item; - if (item >= itemCount || item < 0) { - if (assert) { - ASDisplayNodeFailAssert(@"Invalid item index %ld in section %ld which only has %ld items!", (long)item, (long)section, (long)itemCount); - } - return NO; - } - *outItem = item; - *outSection = section; - return YES; -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASEventLog.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASEventLog.mm deleted file mode 100644 index 25ecc29968..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASEventLog.mm +++ /dev/null @@ -1,121 +0,0 @@ -// -// ASEventLog.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import -#import - -@implementation ASEventLog { - AS::RecursiveMutex __instanceLock__; - - // The index of the most recent log entry. -1 until first entry. - NSInteger _eventLogHead; - - // A description of the object we're logging for. This is immutable. - NSString *_objectDescription; -} - -/** - * Even just when debugging, all these events can take up considerable memory. - * Store them in a shared NSCache to limit the total consumption. - */ -+ (NSCache *> *)contentsCache -{ - static NSCache *cache; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - cache = [[NSCache alloc] init]; - }); - return cache; -} - -- (instancetype)initWithObject:(id)anObject -{ - if ((self = [super init])) { - _objectDescription = ASObjectDescriptionMakeTiny(anObject); - _eventLogHead = -1; - } - return self; -} - -- (instancetype)init -{ - // This method is marked unavailable so the compiler won't let them call it. - ASDisplayNodeFailAssert(@"Failed to call initWithObject:"); - return nil; -} - -- (void)logEventWithBacktrace:(NSArray *)backtrace format:(NSString *)format, ... -{ - va_list args; - va_start(args, format); - ASTraceEvent *event = [[ASTraceEvent alloc] initWithBacktrace:backtrace - format:format - arguments:args]; - va_end(args); - - AS::MutexLocker l(__instanceLock__); - NSCache *cache = [ASEventLog contentsCache]; - NSMutableArray *events = [cache objectForKey:self]; - if (events == nil) { - events = [NSMutableArray arrayWithObject:event]; - [cache setObject:events forKey:self]; - _eventLogHead = 0; - return; - } - - // Increment the head index. - _eventLogHead = (_eventLogHead + 1) % ASEVENTLOG_CAPACITY; - if (_eventLogHead < events.count) { - [events replaceObjectAtIndex:_eventLogHead withObject:event]; - } else { - [events insertObject:event atIndex:_eventLogHead]; - } -} - -- (NSArray *)events -{ - NSMutableArray *events = [[ASEventLog contentsCache] objectForKey:self]; - if (events == nil) { - return nil; - } - - AS::MutexLocker l(__instanceLock__); - NSUInteger tail = (_eventLogHead + 1); - NSUInteger count = events.count; - - NSMutableArray *result = [NSMutableArray array]; - - // Start from `tail` and go through array, wrapping around when we exceed end index. - for (NSUInteger actualIndex = 0; actualIndex < ASEVENTLOG_CAPACITY; actualIndex++) { - NSInteger ringIndex = (tail + actualIndex) % ASEVENTLOG_CAPACITY; - if (ringIndex < count) { - [result addObject:events[ringIndex]]; - } - } - return result; -} - -- (NSString *)description -{ - /** - * This description intentionally doesn't follow the standard description format. - * Since this is a log, it's important for the description to look a certain way, and - * the formal description style doesn't allow for newlines and has a ton of punctuation. - */ - NSArray *events = [self events]; - if (events == nil) { - return [NSString stringWithFormat:@"Event log for %@ was purged to conserve memory.", _objectDescription]; - } else { - return [NSString stringWithFormat:@"Event log for %@. Events: %@", _objectDescription, events]; - } -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASHighlightOverlayLayer.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASHighlightOverlayLayer.h deleted file mode 100644 index aff6694bf1..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASHighlightOverlayLayer.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// ASHighlightOverlayLayer.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -AS_SUBCLASSING_RESTRICTED -@interface ASHighlightOverlayLayer : CALayer - -/** - @summary Initializes with CGRects for the highlighting, in the targetLayer's coordinate space. - - @desc This is the designated initializer. - - @param rects Array containing CGRects wrapped in NSValue. - @param targetLayer The layer that the rects are relative to. The rects will be translated to the receiver's coordinate space when rendering. - */ -- (instancetype)initWithRects:(NSArray *)rects targetLayer:(nullable CALayer *)targetLayer; - -/** - @summary Initializes with CGRects for the highlighting, in the receiver's coordinate space. - - @param rects Array containing CGRects wrapped in NSValue. - */ -- (instancetype)initWithRects:(NSArray *)rects; - -@property (nullable, nonatomic) __attribute__((NSObject)) CGColorRef highlightColor; -@property (nonatomic, weak) CALayer *targetLayer; - -@end - -@interface CALayer (ASHighlightOverlayLayerSupport) - -/** - @summary Set to YES to indicate to a sublayer that this is where highlight overlay layers (for pressed states) should - be added so that the highlight won't be clipped by a neighboring layer. - */ -@property (nonatomic, setter=as_setAllowsHighlightDrawing:) BOOL as_allowsHighlightDrawing; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASHighlightOverlayLayer.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASHighlightOverlayLayer.mm deleted file mode 100644 index 03cf468165..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASHighlightOverlayLayer.mm +++ /dev/null @@ -1,134 +0,0 @@ -// -// ASHighlightOverlayLayer.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#import -#import - -#import - -static const CGFloat kCornerRadius = 2.5; -static const UIEdgeInsets padding = {2, 4, 1.5, 4}; - -@implementation ASHighlightOverlayLayer -{ - NSArray *_rects; -} - -+ (id)defaultValueForKey:(NSString *)key -{ - if ([key isEqualToString:@"contentsScale"]) { - return @(ASScreenScale()); - } else if ([key isEqualToString:@"highlightColor"]) { - CGFloat components[] = {0, 0, 0, 0.25}; - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGColorRef color = CGColorCreate(colorSpace, components); - CGColorSpaceRelease(colorSpace); - return CFBridgingRelease(color); - } else { - return [super defaultValueForKey:key]; - } -} - -+ (BOOL)needsDisplayForKey:(NSString *)key -{ - if ([key isEqualToString:@"bounds"]) { - return YES; - } else { - return [super needsDisplayForKey:key]; - } -} - -+ (id)defaultActionForKey:(NSString *)event -{ - return (id)[NSNull null]; -} - -- (instancetype)initWithRects:(NSArray *)rects -{ - return [self initWithRects:rects targetLayer:nil]; -} - -- (instancetype)initWithRects:(NSArray *)rects targetLayer:(id)targetLayer -{ - if (self = [super init]) { - _rects = [rects copy]; - _targetLayer = targetLayer; - } - return self; -} - -@dynamic highlightColor; - -- (void)drawInContext:(CGContextRef)ctx -{ - [super drawInContext:ctx]; - - CGAffineTransform affine = CGAffineTransformIdentity; - CGMutablePathRef highlightPath = CGPathCreateMutable(); - CALayer *targetLayer = self.targetLayer; - - for (NSValue *value in _rects) { - CGRect rect = [value CGRectValue]; - - // Don't highlight empty rects. - if (CGRectIsEmpty(rect)) { - continue; - } - - if (targetLayer != nil) { - rect = [self convertRect:rect fromLayer:targetLayer]; - } - rect = CGRectMake(std::round(rect.origin.x), std::round(rect.origin.y), std::round(rect.size.width), std::round(rect.size.height)); - - CGFloat minX = rect.origin.x - padding.left; - CGFloat maxX = CGRectGetMaxX(rect) + padding.right; - CGFloat midX = (maxX - minX) / 2 + minX; - CGFloat minY = rect.origin.y - padding.top; - CGFloat maxY = CGRectGetMaxY(rect) + padding.bottom; - CGFloat midY = (maxY - minY) / 2 + minY; - - CGPathMoveToPoint(highlightPath, &affine, minX, midY); - CGPathAddArcToPoint(highlightPath, &affine, minX, maxY, midX, maxY, kCornerRadius); - CGPathAddArcToPoint(highlightPath, &affine, maxX, maxY, maxX, midY, kCornerRadius); - CGPathAddArcToPoint(highlightPath, &affine, maxX, minY, midX, minY, kCornerRadius); - CGPathAddArcToPoint(highlightPath, &affine, minX, minY, minX, midY, kCornerRadius); - CGPathCloseSubpath(highlightPath); - } - - CGContextAddPath(ctx, highlightPath); - CGContextSetFillColorWithColor(ctx, self.highlightColor); - CGContextDrawPath(ctx, kCGPathFill); - CGPathRelease(highlightPath); -} - -- (CALayer *)hitTest:(CGPoint)p -{ - // Don't handle taps - return nil; -} - -@end - -@implementation CALayer (ASHighlightOverlayLayerSupport) - -static NSString *kAllowsHighlightDrawingKey = @"allows_highlight_drawing"; - -- (BOOL)as_allowsHighlightDrawing -{ - return [[self valueForKey:kAllowsHighlightDrawingKey] boolValue]; -} - -- (void)as_setAllowsHighlightDrawing:(BOOL)allowsHighlightDrawing -{ - [self setValue:@(allowsHighlightDrawing) forKey:kAllowsHighlightDrawingKey]; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASImageContainerProtocolCategories.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASImageContainerProtocolCategories.mm deleted file mode 100644 index c9316c32ab..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASImageContainerProtocolCategories.mm +++ /dev/null @@ -1,38 +0,0 @@ -// -// ASImageContainerProtocolCategories.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -@implementation UIImage (ASImageContainerProtocol) - -- (UIImage *)asdk_image -{ - return self; -} - -- (NSData *)asdk_animatedImageData -{ - return nil; -} - -@end - -@implementation NSData (ASImageContainerProtocol) - -- (UIImage *)asdk_image -{ - return nil; -} - -- (NSData *)asdk_animatedImageData -{ - return self; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASImageProtocols.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASImageProtocols.h deleted file mode 100644 index fae3b9f5b4..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASImageProtocols.h +++ /dev/null @@ -1,240 +0,0 @@ -// -// ASImageProtocols.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol ASAnimatedImageProtocol; - -@protocol ASImageContainerProtocol - -- (nullable UIImage *)asdk_image; -- (nullable NSData *)asdk_animatedImageData; - -@end - -typedef void(^ASImageCacherCompletion)(id _Nullable imageFromCache); - -@protocol ASImageCacheProtocol - -/** - @abstract Attempts to fetch an image with the given URL from the cache. - @param URL The URL of the image to retrieve from the cache. - @param callbackQueue The queue to call `completion` on. - @param completion The block to be called when the cache has either hit or missed. - @discussion If `URL` is nil, `completion` will be invoked immediately with a nil image. This method should not block - the calling thread as it is likely to be called from the main thread. - */ -- (void)cachedImageWithURL:(NSURL *)URL - callbackQueue:(dispatch_queue_t)callbackQueue - completion:(ASImageCacherCompletion)completion; - -@optional - -/** - @abstract Attempts to fetch an image with the given URL from a memory cache. - @param URL The URL of the image to retrieve from the cache. - @discussion This method exists to support synchronous rendering of nodes. Before the layer is drawn, this method - is called to attempt to get the image out of the cache synchronously. This allows drawing to occur on the main thread - if displaysAsynchronously is set to NO or recursivelyEnsureDisplaySynchronously: has been called. - - This method *should* block the calling thread to fetch the image from a fast memory cache. It is OK to return nil from - this method and instead support only cachedImageWithURL:callbackQueue:completion: however, synchronous rendering will - not be possible. - */ -- (nullable id )synchronouslyFetchedCachedImageWithURL:(NSURL *)URL; - -/** - @abstract Called during clearPreloadedData. Allows the cache to optionally trim items. - @note Depending on your caches implementation you may *not* wish to respond to this method. It is however useful - if you have a memory and disk cache in which case you'll likely want to clear out the memory cache. - */ -- (void)clearFetchedImageFromCacheWithURL:(NSURL *)URL; - -@end - -/** - @param image The image that was downloaded, if the image could be successfully downloaded; nil otherwise. - @param error An error describing why the download of `URL` failed, if the download failed; nil otherwise. - @param downloadIdentifier The identifier for the download task that completed. - @param userInfo Any additional info that your downloader would like to communicate through Texture. - */ -typedef void(^ASImageDownloaderCompletion)(id _Nullable image, NSError * _Nullable error, id _Nullable downloadIdentifier, id _Nullable userInfo); - -/** - @param progress The progress of the download, in the range of (0.0, 1.0), inclusive. - */ -typedef void(^ASImageDownloaderProgress)(CGFloat progress); -typedef void(^ASImageDownloaderProgressImage)(UIImage *progressImage, CGFloat progress, id _Nullable downloadIdentifier); - -typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) { - ASImageDownloaderPriorityPreload = 0, - ASImageDownloaderPriorityImminent, - ASImageDownloaderPriorityVisible -}; - -@protocol ASImageDownloaderProtocol - -@required - -/** - @abstract Downloads an image with the given URL. - @param URL The URL of the image to download. - @param callbackQueue The queue to call `downloadProgressBlock` and `completion` on. - @param downloadProgress The block to be invoked when the download of `URL` progresses. - @param completion The block to be invoked when the download has completed, or has failed. - @discussion This method is likely to be called on the main thread, so any custom implementations should make sure to background any expensive download operations. - @result An opaque identifier to be used in canceling the download, via `cancelImageDownloadForIdentifier:`. You must - retain the identifier if you wish to use it later. - */ -- (nullable id)downloadImageWithURL:(NSURL *)URL - callbackQueue:(dispatch_queue_t)callbackQueue - downloadProgress:(nullable ASImageDownloaderProgress)downloadProgress - completion:(ASImageDownloaderCompletion)completion; - -/** - @abstract Cancels an image download. - @param downloadIdentifier The opaque download identifier object returned from - `downloadImageWithURL:callbackQueue:downloadProgress:completion:`. - @discussion This method has no effect if `downloadIdentifier` is nil. - */ -- (void)cancelImageDownloadForIdentifier:(id)downloadIdentifier; - -@optional - -/** - @abstract Downloads an image with the given URL. - @param URL The URL of the image to download. - @param priority The priority at which the image should be downloaded. - @param callbackQueue The queue to call `downloadProgressBlock` and `completion` on. - @param downloadProgress The block to be invoked when the download of `URL` progresses. - @param completion The block to be invoked when the download has completed, or has failed. - @discussion This method is likely to be called on the main thread, so any custom implementations should make sure to background any expensive download operations. - @note If this method is implemented, it will be called instead of the required method (`downloadImageWithURL:callbackQueue:downloadProgress:completion:`). - @result An opaque identifier to be used in canceling the download, via `cancelImageDownloadForIdentifier:`. You must - retain the identifier if you wish to use it later. - */ -- (nullable id)downloadImageWithURL:(NSURL *)URL - priority:(ASImageDownloaderPriority)priority - callbackQueue:(dispatch_queue_t)callbackQueue - downloadProgress:(nullable ASImageDownloaderProgress)downloadProgress - completion:(ASImageDownloaderCompletion)completion; - -/** - @abstract Cancels an image download, however indicating resume data should be stored in case of redownload. - @param downloadIdentifier The opaque download identifier object returned from - `downloadImageWithURL:callbackQueue:downloadProgress:completion:`. - @discussion This method has no effect if `downloadIdentifier` is nil. If implemented, this method - may be called instead of `cancelImageDownloadForIdentifier:` in cases where ASDK believes there's a chance - the image download will be resumed (currently when an image exits preload range). You can use this to store - any data that has already been downloaded for use in resuming the download later. - */ -- (void)cancelImageDownloadWithResumePossibilityForIdentifier:(id)downloadIdentifier; - -/** - @abstract Return an object that conforms to ASAnimatedImageProtocol - @param animatedImageData Data that represents an animated image. - */ -- (nullable id )animatedImageWithData:(NSData *)animatedImageData; - - -/** - @abstract Sets block to be called when a progress image is available. - @param progressBlock The block to be invoked when the download has a progressive render of an image available. - @param callbackQueue The queue to call `progressImageBlock` on. - @param downloadIdentifier The opaque download identifier object returned from - `downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:`. - */ -- (void)setProgressImageBlock:(nullable ASImageDownloaderProgressImage)progressBlock - callbackQueue:(dispatch_queue_t)callbackQueue - withDownloadIdentifier:(id)downloadIdentifier; - -/** - @abstract Called to indicate what priority an image should be downloaded at. - @param priority The priority at which the image should be downloaded. - @param downloadIdentifier The opaque download identifier object returned from - `downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:`. - */ -- (void)setPriority:(ASImageDownloaderPriority)priority -withDownloadIdentifier:(id)downloadIdentifier; - -@end - -@protocol ASAnimatedImageProtocol - -@optional - -/** - @abstract A block which receives the cover image. Should be called when the objects cover image is ready. - */ -@property (nonatomic) void (^coverImageReadyCallback)(UIImage *coverImage); - -/** - @abstract Returns whether the supplied data contains a supported animated image format. - @param data the data to check if contains a supported animated image. - */ -- (BOOL)isDataSupported:(NSData *)data; - - -@required - -/** - @abstract Return the objects's cover image. - */ -@property (nonatomic, readonly) UIImage *coverImage; -/** - @abstract Return a boolean to indicate that the cover image is ready. - */ -@property (nonatomic, readonly) BOOL coverImageReady; -/** - @abstract Return the total duration of the animated image's playback. - */ -@property (nonatomic, readonly) CFTimeInterval totalDuration; -/** - @abstract Return the interval at which playback should occur. Will be set to a CADisplayLink's frame interval. - */ -@property (nonatomic, readonly) NSUInteger frameInterval; -/** - @abstract Return the total number of loops the animated image should play or 0 to loop infinitely. - */ -@property (nonatomic, readonly) size_t loopCount; -/** - @abstract Return the total number of frames in the animated image. - */ -@property (nonatomic, readonly) size_t frameCount; -/** - @abstract Return YES when playback is ready to occur. - */ -@property (nonatomic, readonly) BOOL playbackReady; -/** - @abstract Return any error that has occured. Playback will be paused if this returns non-nil. - */ -@property (nonatomic, readonly) NSError *error; -/** - @abstract Should be called when playback is ready. - */ -@property (nonatomic) dispatch_block_t playbackReadyCallback; - -/** - @abstract Return the image at a given index. - */ -- (CGImageRef)imageAtIndex:(NSUInteger)index; -/** - @abstract Return the duration at a given index. - */ -- (CFTimeInterval)durationAtIndex:(NSUInteger)index; -/** - @abstract Clear any cached data. Called when playback is paused. - */ -- (void)clearAnimatedImageCache; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASInsetLayoutSpec.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASInsetLayoutSpec.h deleted file mode 100644 index 8e22fe9bd2..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASInsetLayoutSpec.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// ASInsetLayoutSpec.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - A layout spec that wraps another layoutElement child, applying insets around it. - - If the child has a size specified as a fraction, the fraction is resolved against this spec's parent - size **after** applying insets. - - @example ASOuterLayoutSpec contains an ASInsetLayoutSpec with an ASInnerLayoutSpec. Suppose that: - - ASOuterLayoutSpec is 200pt wide. - - ASInnerLayoutSpec specifies its width as 100%. - - The ASInsetLayoutSpec has insets of 10pt on every side. - ASInnerLayoutSpec will have size 180pt, not 200pt, because it receives a parent size that has been adjusted for insets. - - If you're familiar with CSS: ASInsetLayoutSpec's child behaves similarly to "box-sizing: border-box". - - An infinite inset is resolved as an inset equal to all remaining space after applying the other insets and child size. - @example An ASInsetLayoutSpec with an infinite left inset and 10px for all other edges will position it's child 10px from the right edge. - */ -@interface ASInsetLayoutSpec : ASLayoutSpec - -@property (nonatomic) UIEdgeInsets insets; - -/** - @param insets The amount of space to inset on each side. - @param child The wrapped child to inset. - */ -+ (instancetype)insetLayoutSpecWithInsets:(UIEdgeInsets)insets child:(id)child NS_RETURNS_RETAINED AS_WARN_UNUSED_RESULT; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASInsetLayoutSpec.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASInsetLayoutSpec.mm deleted file mode 100644 index 450480f1c4..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASInsetLayoutSpec.mm +++ /dev/null @@ -1,123 +0,0 @@ -// -// ASInsetLayoutSpec.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#import - -#import -#import - -@interface ASInsetLayoutSpec () -{ - UIEdgeInsets _insets; -} -@end - -/* Returns f if f is finite, substitute otherwise */ -static CGFloat finite(CGFloat f, CGFloat substitute) -{ - return isinf(f) ? substitute : f; -} - -/* Returns f if f is finite, 0 otherwise */ -static CGFloat finiteOrZero(CGFloat f) -{ - return finite(f, 0); -} - -/* Returns the inset required to center 'inner' in 'outer' */ -static CGFloat centerInset(CGFloat outer, CGFloat inner) -{ - return ASRoundPixelValue((outer - inner) / 2); -} - -@implementation ASInsetLayoutSpec - -- (instancetype)initWithInsets:(UIEdgeInsets)insets child:(id)child; -{ - if (!(self = [super init])) { - return nil; - } - ASDisplayNodeAssertNotNil(child, @"Child cannot be nil"); - _insets = insets; - [self setChild:child]; - return self; -} - -+ (instancetype)insetLayoutSpecWithInsets:(UIEdgeInsets)insets child:(id)child NS_RETURNS_RETAINED -{ - return [[self alloc] initWithInsets:insets child:child]; -} - -- (void)setInsets:(UIEdgeInsets)insets -{ - ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); - _insets = insets; -} - -/** - Inset will compute a new constrained size for it's child after applying insets and re-positioning - the child to respect the inset. - */ -- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize - restrictedToSize:(ASLayoutElementSize)size - relativeToParentSize:(CGSize)parentSize -{ - if (self.child == nil) { - ASDisplayNodeAssert(NO, @"Inset spec measured without a child. The spec will do nothing."); - return [ASLayout layoutWithLayoutElement:self size:CGSizeZero]; - } - - const CGFloat insetsX = (finiteOrZero(_insets.left) + finiteOrZero(_insets.right)); - const CGFloat insetsY = (finiteOrZero(_insets.top) + finiteOrZero(_insets.bottom)); - - // if either x-axis inset is infinite, let child be intrinsic width - const CGFloat minWidth = (isinf(_insets.left) || isinf(_insets.right)) ? 0 : constrainedSize.min.width; - // if either y-axis inset is infinite, let child be intrinsic height - const CGFloat minHeight = (isinf(_insets.top) || isinf(_insets.bottom)) ? 0 : constrainedSize.min.height; - - const ASSizeRange insetConstrainedSize = { - { - MAX(0, minWidth - insetsX), - MAX(0, minHeight - insetsY), - }, - { - MAX(0, constrainedSize.max.width - insetsX), - MAX(0, constrainedSize.max.height - insetsY), - } - }; - - const CGSize insetParentSize = { - MAX(0, parentSize.width - insetsX), - MAX(0, parentSize.height - insetsY) - }; - - ASLayout *sublayout = [self.child layoutThatFits:insetConstrainedSize parentSize:insetParentSize]; - - const CGSize computedSize = ASSizeRangeClamp(constrainedSize, { - finite(sublayout.size.width + _insets.left + _insets.right, constrainedSize.max.width), - finite(sublayout.size.height + _insets.top + _insets.bottom, constrainedSize.max.height), - }); - - const CGFloat x = finite(_insets.left, constrainedSize.max.width - - (finite(_insets.right, - centerInset(constrainedSize.max.width, sublayout.size.width)) + sublayout.size.width)); - - const CGFloat y = finite(_insets.top, - constrainedSize.max.height - - (finite(_insets.bottom, - centerInset(constrainedSize.max.height, sublayout.size.height)) + sublayout.size.height)); - - sublayout.position = CGPointMake(x, y); - - return [ASLayout layoutWithLayoutElement:self size:computedSize sublayouts:@[sublayout]]; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASIntegerMap.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASIntegerMap.h deleted file mode 100644 index ece6f5a8bf..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASIntegerMap.h +++ /dev/null @@ -1,68 +0,0 @@ -// -// ASIntegerMap.h -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - * An objective-C wrapper for unordered_map. - */ -AS_SUBCLASSING_RESTRICTED -@interface ASIntegerMap : NSObject - -/** - * Creates a map based on the specified update to an array. - * - * If oldCount is 0, returns the empty map. - * If deleted and inserted are empty, returns the identity map. - */ -+ (ASIntegerMap *)mapForUpdateWithOldCount:(NSInteger)oldCount - deleted:(nullable NSIndexSet *)deleted - inserted:(nullable NSIndexSet *)inserted NS_RETURNS_RETAINED; - -/** - * A singleton that maps each integer to itself. Its inverse is itself. - * - * Note: You cannot mutate this. - */ -@property (class, readonly) ASIntegerMap *identityMap; -+ (ASIntegerMap *)identityMap NS_RETURNS_RETAINED; - -/** - * A singleton that returns NSNotFound for all keys. Its inverse is itself. - * - * Note: You cannot mutate this. - */ -@property (class, readonly) ASIntegerMap *emptyMap; -+ (ASIntegerMap *)emptyMap NS_RETURNS_RETAINED; - -/** - * Retrieves the integer for a given key, or NSNotFound if the key is not found. - * - * @param key A key to lookup the value for. - */ -- (NSInteger)integerForKey:(NSInteger)key; - -/** - * Sets the value for a given key. - * - * @param value The new value. - * @param key The key to store the value for. - */ -- (void)setInteger:(NSInteger)value forKey:(NSInteger)key; - -/** - * Create and return a map with the inverse mapping. - */ -- (ASIntegerMap *)inverseMap; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASIntegerMap.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASIntegerMap.mm deleted file mode 100644 index 2c3e03e413..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASIntegerMap.mm +++ /dev/null @@ -1,185 +0,0 @@ -// -// ASIntegerMap.mm -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import -#import -#import - -/** - * This is just a friendly Objective-C interface to unordered_map - */ -@interface ASIntegerMap () -@end - -@implementation ASIntegerMap { - std::unordered_map _map; - BOOL _isIdentity; - BOOL _isEmpty; - BOOL _immutable; // identity map and empty mape are immutable. -} - -#pragma mark - Singleton - -+ (ASIntegerMap *)identityMap NS_RETURNS_RETAINED -{ - static ASIntegerMap *identityMap; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - identityMap = [[ASIntegerMap alloc] init]; - identityMap->_isIdentity = YES; - identityMap->_immutable = YES; - }); - return identityMap; -} - -+ (ASIntegerMap *)emptyMap NS_RETURNS_RETAINED -{ - static ASIntegerMap *emptyMap; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - emptyMap = [[ASIntegerMap alloc] init]; - emptyMap->_isEmpty = YES; - emptyMap->_immutable = YES; - }); - return emptyMap; -} - -+ (ASIntegerMap *)mapForUpdateWithOldCount:(NSInteger)oldCount deleted:(NSIndexSet *)deletions inserted:(NSIndexSet *)insertions NS_RETURNS_RETAINED -{ - if (oldCount == 0) { - return ASIntegerMap.emptyMap; - } - - if (deletions.count == 0 && insertions.count == 0) { - return ASIntegerMap.identityMap; - } - - ASIntegerMap *result = [[ASIntegerMap alloc] init]; - // Start with the old indexes - NSMutableIndexSet *indexes = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, oldCount)]; - - // Descending order, shift deleted ranges left - [deletions enumerateRangesWithOptions:NSEnumerationReverse usingBlock:^(NSRange range, BOOL * _Nonnull stop) { - [indexes shiftIndexesStartingAtIndex:NSMaxRange(range) by:-range.length]; - }]; - - // Ascending order, shift inserted ranges right - [insertions enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) { - [indexes shiftIndexesStartingAtIndex:range.location by:range.length]; - }]; - - __block NSInteger oldIndex = 0; - [indexes enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) { - // Note we advance oldIndex unconditionally, not newIndex - for (NSInteger newIndex = range.location; newIndex < NSMaxRange(range); oldIndex++) { - if ([deletions containsIndex:oldIndex]) { - // index was deleted, do nothing, just let oldIndex advance. - } else { - // assign the next index for this item. - result->_map[oldIndex] = newIndex++; - } - } - }]; - return result; -} - -- (NSInteger)integerForKey:(NSInteger)key -{ - if (_isIdentity) { - return key; - } else if (_isEmpty) { - return NSNotFound; - } - - const auto result = _map.find(key); - return result != _map.end() ? result->second : NSNotFound; -} - -- (void)setInteger:(NSInteger)value forKey:(NSInteger)key -{ - if (_immutable) { - ASDisplayNodeFailAssert(@"Cannot mutate special integer map: %@", self); - return; - } - - _map[key] = value; -} - -- (ASIntegerMap *)inverseMap -{ - if (_isIdentity || _isEmpty) { - return self; - } - - const auto result = [[ASIntegerMap alloc] init]; - - for (const auto &e : _map) { - result->_map[e.second] = e.first; - } - return result; -} - -#pragma mark - NSCopying - -- (id)copyWithZone:(NSZone *)zone -{ - if (_immutable) { - return self; - } - - const auto newMap = [[ASIntegerMap allocWithZone:zone] init]; - newMap->_map = _map; - return newMap; -} - -#pragma mark - Description - -- (NSMutableArray *)propertiesForDescription -{ - NSMutableArray *result = [NSMutableArray array]; - - if (_isIdentity) { - [result addObject:@{ @"map": @"" }]; - } else if (_isEmpty) { - [result addObject:@{ @"map": @"" }]; - } else { - // { 1->2 3->4 5->6 } - NSMutableString *str = [NSMutableString string]; - for (const auto &e : _map) { - [str appendFormat:@" %ld->%ld", (long)e.first, (long)e.second]; - } - // Remove leading space - if (str.length > 0) { - [str deleteCharactersInRange:NSMakeRange(0, 1)]; - } - [result addObject:@{ @"map": str }]; - } - - return result; -} - -- (NSString *)description -{ - return ASObjectDescriptionMakeWithoutObject([self propertiesForDescription]); -} - -- (BOOL)isEqual:(id)object -{ - if ([super isEqual:object]) { - return YES; - } - - if (ASIntegerMap *otherMap = ASDynamicCast(object, ASIntegerMap)) { - return otherMap->_map == _map; - } - return NO; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutController.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutController.h deleted file mode 100644 index d0e2f60907..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutController.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// ASLayoutController.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@class ASCollectionElement, ASElementMap; - -struct ASDirectionalScreenfulBuffer { - CGFloat positiveDirection; // Positive relative to iOS Core Animation layer coordinate space. - CGFloat negativeDirection; -}; -typedef struct ASDirectionalScreenfulBuffer ASDirectionalScreenfulBuffer; - -@protocol ASLayoutController - -- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType; - -- (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType; - -- (NSHashTable *)elementsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType map:(ASElementMap *)map; - -- (void)allElementsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode displaySet:(NSHashTable * _Nullable * _Nullable)displaySet preloadSet:(NSHashTable * _Nullable * _Nullable)preloadSet map:(ASElementMap *)map; - -@optional - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLog.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLog.h deleted file mode 100644 index ccab4b8e58..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLog.h +++ /dev/null @@ -1,163 +0,0 @@ -// -// ASLog.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import -#import -#import - -#ifndef ASEnableVerboseLogging - #define ASEnableVerboseLogging 0 -#endif - -/** - * Disable all logging. - * - * You should only use this function if the default log level is - * annoying during development. By default, logging is run at - * the appropriate system log level (see the os_log_* functions), - * so you do not need to worry generally about the performance - * implications of log messages. - * - * For example, virtually all log messages generated by Texture - * are at the `debug` log level, which the system - * disables in production. - */ -AS_EXTERN void ASDisableLogging(void); - -/** - * Restore logging that has been runtime-disabled via ASDisableLogging(). - * - * Logging can be disabled at runtime using the ASDisableLogging() function. - * This command restores logging to the level provided in the build - * configuration. This can be used in conjunction with ASDisableLogging() - * to allow logging to be toggled off and back on at runtime. - */ -AS_EXTERN void ASEnableLogging(void); - -/// Log for general node events e.g. interfaceState, didLoad. -#define ASNodeLogEnabled 1 -AS_EXTERN os_log_t ASNodeLog(void); - -/// Log for layout-specific events e.g. calculateLayout. -#define ASLayoutLogEnabled 1 -AS_EXTERN os_log_t ASLayoutLog(void); - -/// Log for display-specific events e.g. display queue batches. -#define ASDisplayLogEnabled 1 -AS_EXTERN os_log_t ASDisplayLog(void); - -/// Log for collection events e.g. reloadData, performBatchUpdates. -#define ASCollectionLogEnabled 1 -AS_EXTERN os_log_t ASCollectionLog(void); - -/// Log for ASNetworkImageNode and ASMultiplexImageNode events. -#define ASImageLoadingLogEnabled 1 -AS_EXTERN os_log_t ASImageLoadingLog(void); - -/// Specialized log for our main thread deallocation trampoline. -#define ASMainThreadDeallocationLogEnabled 0 -AS_EXTERN os_log_t ASMainThreadDeallocationLog(void); - -/** - * The activity tracing system changed a lot between iOS 9 and 10. - * In iOS 10, the system was merged with logging and became much more powerful - * and adopted a new API. - * - * The legacy API is visible, but its functionality is extremely limited and the API is so different - * that we don't bother with it. For example, activities described by os_activity_start/end are not - * reflected in the log whereas activities described by the newer - * os_activity_scope are. So unfortunately we must use these iOS 10 - * APIs to get meaningful logging data. - */ -#if OS_LOG_TARGET_HAS_10_12_FEATURES - -#define OS_ACTIVITY_NULLABLE nullable -#define AS_ACTIVITY_CURRENT OS_ACTIVITY_CURRENT -#define as_activity_scope(activity) os_activity_scope(activity) -#define as_activity_apply(activity, block) os_activity_apply(activity, block) -#define as_activity_create(description, parent_activity, flags) os_activity_create(description, parent_activity, flags) -#define as_activity_scope_enter(activity, statePtr) os_activity_scope_enter(activity, statePtr) -#define as_activity_scope_leave(statePtr) os_activity_scope_leave(statePtr) -#define as_activity_get_identifier(activity, outParentID) os_activity_get_identifier(activity, outParentID) - -#else - -#define OS_ACTIVITY_NULLABLE -#define AS_ACTIVITY_CURRENT OS_ACTIVITY_NULL -#define as_activity_scope(activity) -#define as_activity_apply(activity, block) -#define as_activity_create(description, parent_activity, flags) OS_ACTIVITY_NULL -#define as_activity_scope_enter(activity, statePtr) -#define as_activity_scope_leave(statePtr) -#define as_activity_get_identifier(activity, outParentID) (os_activity_id_t)0 - -#endif // OS_LOG_TARGET_HAS_10_12_FEATURES - -// Create activities only when verbose enabled. Doesn't materially impact performance, but good if we're cluttering up -// activity scopes and reducing readability. -#if ASEnableVerboseLogging - #define as_activity_scope_verbose(activity) as_activity_scope(activity) -#else - #define as_activity_scope_verbose(activity) -#endif - -// Convenience for: as_activity_scope(as_activity_create(description, AS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT)) -#define as_activity_create_for_scope(description) \ - as_activity_scope(as_activity_create(description, AS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT)) - -/** - * The logging macros are not guarded by deployment-target checks like the activity macros are, but they are - * only available on iOS >= 9 at runtime, so just make them conditional. - */ - -#define as_log_create(subsystem, category) ({ \ -os_log_t __val; \ -if (AS_AVAILABLE_IOS_TVOS(9, 9)) { \ - __val = os_log_create(subsystem, category); \ -} else { \ - __val = (os_log_t)0; \ -} \ -__val; \ -}) - -#define as_log_debug(log, format, ...) \ -if (AS_AVAILABLE_IOS_TVOS(9, 9)) { \ - os_log_debug(log, format, ##__VA_ARGS__); \ -} else { \ - (void)0; \ -} \ - -#define as_log_info(log, format, ...) \ -if (AS_AVAILABLE_IOS_TVOS(9, 9)) { \ - os_log_info(log, format, ##__VA_ARGS__); \ -} else { \ - (void)0; \ -} \ - -#define as_log_error(log, format, ...) \ -if (AS_AVAILABLE_IOS_TVOS(9, 9)) { \ - os_log_error(log, format, ##__VA_ARGS__); \ -} else { \ - (void)0; \ -} \ - -#define as_log_fault(log, format, ...) \ -if (AS_AVAILABLE_IOS_TVOS(9, 9)) { \ - os_log_fault(log, format, ##__VA_ARGS__); \ -} else { \ - (void)0; \ -} \ - -#if ASEnableVerboseLogging - #define as_log_verbose(log, format, ...) as_log_debug(log, format, ##__VA_ARGS__) -#else - #define as_log_verbose(log, format, ...) -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLog.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLog.mm deleted file mode 100644 index 270246454b..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLog.mm +++ /dev/null @@ -1,48 +0,0 @@ -// -// ASLog.mm -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -static atomic_bool __ASLogEnabled = ATOMIC_VAR_INIT(YES); - -void ASDisableLogging() { - atomic_store(&__ASLogEnabled, NO); -} - -void ASEnableLogging() { - atomic_store(&__ASLogEnabled, YES); -} - -ASDISPLAYNODE_INLINE BOOL ASLoggingIsEnabled() { - return atomic_load(&__ASLogEnabled); -} - -os_log_t ASNodeLog() { - return (ASNodeLogEnabled && ASLoggingIsEnabled()) ? ASCreateOnce(as_log_create("org.TextureGroup.Texture", "Node")) : OS_LOG_DISABLED; -} - -os_log_t ASLayoutLog() { - return (ASLayoutLogEnabled && ASLoggingIsEnabled()) ? ASCreateOnce(as_log_create("org.TextureGroup.Texture", "Layout")) : OS_LOG_DISABLED; -} - -os_log_t ASCollectionLog() { - return (ASCollectionLogEnabled && ASLoggingIsEnabled()) ?ASCreateOnce(as_log_create("org.TextureGroup.Texture", "Collection")) : OS_LOG_DISABLED; -} - -os_log_t ASDisplayLog() { - return (ASDisplayLogEnabled && ASLoggingIsEnabled()) ?ASCreateOnce(as_log_create("org.TextureGroup.Texture", "Display")) : OS_LOG_DISABLED; -} - -os_log_t ASImageLoadingLog() { - return (ASImageLoadingLogEnabled && ASLoggingIsEnabled()) ? ASCreateOnce(as_log_create("org.TextureGroup.Texture", "ImageLoading")) : OS_LOG_DISABLED; -} - -os_log_t ASMainThreadDeallocationLog() { - return (ASMainThreadDeallocationLogEnabled && ASLoggingIsEnabled()) ? ASCreateOnce(as_log_create("org.TextureGroup.Texture", "MainDealloc")) : OS_LOG_DISABLED; -} diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableAttributedStringBuilder.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableAttributedStringBuilder.h deleted file mode 100644 index d531549a0e..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableAttributedStringBuilder.h +++ /dev/null @@ -1,65 +0,0 @@ -// -// ASMutableAttributedStringBuilder.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -/* - * Use this class to compose new attributed strings. You may use the normal - * attributed string calls on this the same way you would on a normal mutable - * attributed string, but it coalesces your changes into transactions on the - * actual string allowing improvements in performance. - * - * @discussion This is a use-once and throw away class for each string you make. - * Since this class is designed for increasing performance, we actually hand - * back the internally managed mutable attributed string in the - * `composedAttributedString` call. So once you make that call, any more - * changes will actually modify the string that was handed back to you in that - * method. - * - * Combination of multiple calls into single attribution is managed through - * merging of attribute dictionaries over ranges. For best performance, call - * collections of attributions over a single range together. So for instance, - * don't call addAttributes for range1, then range2, then range1 again. Group - * them together so you call addAttributes for both range1 together, and then - * range2. - * - * Also please note that switching between addAttribute and setAttributes in the - * middle of composition is a bad idea for performance because they have - * semantically different meanings, and trigger a commit of the pending - * attributes. - * - * Please note that ALL of the standard NSString methods are left unimplemented. - */ -AS_SUBCLASSING_RESTRICTED -@interface ASMutableAttributedStringBuilder : NSMutableAttributedString - -- (instancetype)initWithString:(NSString *)str attributes:(nullable NSDictionary *)attrs; -- (instancetype)initWithAttributedString:(NSAttributedString *)attrStr; - -- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str; -- (void)setAttributes:(nullable NSDictionary *)attrs range:(NSRange)range; - -- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range; -- (void)addAttributes:(NSDictionary *)attrs range:(NSRange)range; -- (void)removeAttribute:(NSString *)name range:(NSRange)range; - -- (void)replaceCharactersInRange:(NSRange)range withAttributedString:(NSAttributedString *)attrString; -- (void)insertAttributedString:(NSAttributedString *)attrString atIndex:(NSUInteger)loc; -- (void)appendAttributedString:(NSAttributedString *)attrString; -- (void)deleteCharactersInRange:(NSRange)range; -- (void)setAttributedString:(NSAttributedString *)attrString; - -- (NSMutableAttributedString *)composedAttributedString; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableAttributedStringBuilder.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableAttributedStringBuilder.mm deleted file mode 100644 index b393fe1118..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableAttributedStringBuilder.mm +++ /dev/null @@ -1,254 +0,0 @@ -// -// ASMutableAttributedStringBuilder.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -@implementation ASMutableAttributedStringBuilder { - // Flag for the type of the current transaction (set or add) - BOOL _setRange; - // The range over which the currently pending transaction will occur - NSRange _pendingRange; - // The actual attribute dictionary that is being composed - NSMutableDictionary *_pendingRangeAttributes; - NSMutableAttributedString *_attrStr; - - // We delay initialization of the _attrStr until we need to - NSString *_initString; -} - -- (instancetype)init -{ - if (self = [super init]) { - _attrStr = [[NSMutableAttributedString alloc] init]; - _pendingRange.location = NSNotFound; - } - return self; -} - -- (instancetype)initWithString:(NSString *)str -{ - return [self initWithString:str attributes:@{}]; -} - -- (instancetype)initWithString:(NSString *)str attributes:(NSDictionary *)attrs -{ - if (self = [super init]) { - // We cache this in an ivar that we can lazily construct the attributed - // string with when we get to a forced commit point. - _initString = str; - // Triggers a creation of the _pendingRangeAttributes dictionary which then - // is filled with entries from the given attrs dict. - [[self _pendingRangeAttributes] addEntriesFromDictionary:attrs]; - _setRange = NO; - _pendingRange = NSMakeRange(0, _initString.length); - } - return self; -} - -- (instancetype)initWithAttributedString:(NSAttributedString *)attrStr -{ - if (self = [super init]) { - _attrStr = [[NSMutableAttributedString alloc] initWithAttributedString:attrStr]; - _pendingRange.location = NSNotFound; - } - return self; -} - -- (NSMutableAttributedString *)_attributedString -{ - if (_attrStr == nil && _initString != nil) { - // We can lazily construct the attributed string if it hasn't already been - // created with the existing pending attributes. This is significantly - // faster if more attributes are added after initializing this instance - // and the new attributions are for the entire string anyway. - _attrStr = [[NSMutableAttributedString alloc] initWithString:_initString attributes:_pendingRangeAttributes]; - _pendingRangeAttributes = nil; - _pendingRange.location = NSNotFound; - _initString = nil; - } - - return _attrStr; -} - -#pragma mark - Pending attribution - -- (NSMutableDictionary *)_pendingRangeAttributes -{ - // Lazy dictionary creation. Call this if you want to force initialization, - // otherwise just use the ivar. - if (_pendingRangeAttributes == nil) { - _pendingRangeAttributes = [[NSMutableDictionary alloc] init]; - } - return _pendingRangeAttributes; -} - -- (void)_applyPendingRangeAttributions -{ - if (_attrStr == nil) { - // Trigger its creation if it doesn't exist. - [self _attributedString]; - } - - if (_pendingRangeAttributes.count == 0) { - return; - } - - if (_pendingRange.location == NSNotFound) { - return; - } - - if (_setRange) { - [[self _attributedString] setAttributes:_pendingRangeAttributes range:_pendingRange]; - } else { - [[self _attributedString] addAttributes:_pendingRangeAttributes range:_pendingRange]; - } - _pendingRangeAttributes = nil; - _pendingRange.location = NSNotFound; -} - -#pragma mark - Editing - -- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str -{ - [self _applyPendingRangeAttributions]; - [[self _attributedString] replaceCharactersInRange:range withString:str]; -} - -- (void)replaceCharactersInRange:(NSRange)range withAttributedString:(NSAttributedString *)attrString -{ - [self _applyPendingRangeAttributions]; - [[self _attributedString] replaceCharactersInRange:range withAttributedString:attrString]; -} - -- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range -{ - if (_setRange) { - [self _applyPendingRangeAttributions]; - _setRange = NO; - } - - if (!NSEqualRanges(_pendingRange, range)) { - [self _applyPendingRangeAttributions]; - _pendingRange = range; - } - - NSMutableDictionary *pendingAttributes = [self _pendingRangeAttributes]; - pendingAttributes[name] = value; -} - -- (void)addAttributes:(NSDictionary *)attrs range:(NSRange)range -{ - if (_setRange) { - [self _applyPendingRangeAttributions]; - _setRange = NO; - } - - if (!NSEqualRanges(_pendingRange, range)) { - [self _applyPendingRangeAttributions]; - _pendingRange = range; - } - - NSMutableDictionary *pendingAttributes = [self _pendingRangeAttributes]; - [pendingAttributes addEntriesFromDictionary:attrs]; -} - -- (void)insertAttributedString:(NSAttributedString *)attrString atIndex:(NSUInteger)loc -{ - [self _applyPendingRangeAttributions]; - [[self _attributedString] insertAttributedString:attrString atIndex:loc]; -} - -- (void)appendAttributedString:(NSAttributedString *)attrString -{ - [self _applyPendingRangeAttributions]; - [[self _attributedString] appendAttributedString:attrString]; -} - -- (void)deleteCharactersInRange:(NSRange)range -{ - [self _applyPendingRangeAttributions]; - [[self _attributedString] deleteCharactersInRange:range]; -} - -- (void)setAttributedString:(NSAttributedString *)attrString -{ - [self _applyPendingRangeAttributions]; - [[self _attributedString] setAttributedString:attrString]; -} - -- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range -{ - if (!_setRange) { - [self _applyPendingRangeAttributions]; - _setRange = YES; - } - - if (!NSEqualRanges(_pendingRange, range)) { - [self _applyPendingRangeAttributions]; - _pendingRange = range; - } - - NSMutableDictionary *pendingAttributes = [self _pendingRangeAttributes]; - [pendingAttributes addEntriesFromDictionary:attrs]; -} - -- (void)removeAttribute:(NSString *)name range:(NSRange)range -{ - // This call looks like the other set/add functions, but in order for this - // function to perform as advertised we MUST first add the attributes we - // currently have pending. - [self _applyPendingRangeAttributions]; - - [[self _attributedString] removeAttribute:name range:range]; -} - -#pragma mark - Output - -- (NSMutableAttributedString *)composedAttributedString -{ - if (_pendingRangeAttributes.count > 0) { - [self _applyPendingRangeAttributions]; - } - return [self _attributedString]; -} - -#pragma mark - Forwarding - -- (NSUInteger)length -{ - // If we just want a length call, no need to lazily construct the attributed string - return _attrStr ? _attrStr.length : _initString.length; -} - -- (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range -{ - return [[self _attributedString] attributesAtIndex:location effectiveRange:range]; -} - -- (NSString *)string -{ - return _attrStr ? _attrStr.string : _initString; -} - -- (NSMutableString *)mutableString -{ - return [[self _attributedString] mutableString]; -} - -- (void)beginEditing -{ - [[self _attributedString] beginEditing]; -} - -- (void)endEditing -{ - [[self _attributedString] endEditing]; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableElementMap.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableElementMap.h deleted file mode 100644 index ed4f0b5ff4..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableElementMap.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// ASMutableElementMap.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#ifndef MINIMAL_ASDK - -#import -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@class ASSection, ASCollectionElement, _ASHierarchyChangeSet; - -/** - * This mutable version will be removed in the future. It's only here now to keep the diff small - * as we port data controller to use ASElementMap. - */ -AS_SUBCLASSING_RESTRICTED -@interface ASMutableElementMap : NSObject - -- (instancetype)init __unavailable; - -- (instancetype)initWithSections:(NSArray *)sections items:(ASCollectionElementTwoDimensionalArray *)items supplementaryElements:(ASSupplementaryElementDictionary *)supplementaryElements; - -- (void)insertSection:(ASSection *)section atIndex:(NSInteger)index; - -- (void)removeAllSections; - -/// Only modifies the array of ASSection * objects -- (void)removeSectionsAtIndexes:(NSIndexSet *)indexes; - -- (void)removeAllElements; - -- (void)removeItemsAtIndexPaths:(NSArray *)indexPaths; - -- (void)removeSectionsOfItems:(NSIndexSet *)itemSections; - -- (void)removeSupplementaryElementsAtIndexPaths:(NSArray *)indexPaths kind:(NSString *)kind; - -- (void)insertEmptySectionsOfItemsAtIndexes:(NSIndexSet *)sections; - -- (void)insertElement:(ASCollectionElement *)element atIndexPath:(NSIndexPath *)indexPath; - -/** - * Update the index paths for all supplementary elements to account for section-level - * deletes, moves, inserts. This must be called before adding new supplementary elements. - * - * This also deletes any supplementary elements in deleted sections. - */ -- (void)migrateSupplementaryElementsWithSectionMapping:(ASIntegerMap *)mapping; - -@end - -@interface ASElementMap (MutableCopying) -@end - -NS_ASSUME_NONNULL_END - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableElementMap.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableElementMap.mm deleted file mode 100644 index 73798be119..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMutableElementMap.mm +++ /dev/null @@ -1,149 +0,0 @@ -// -// ASMutableElementMap.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#ifndef MINIMAL_ASDK - -#import - -#import -#import -#import -#import -#import - -typedef NSMutableArray *> ASMutableCollectionElementTwoDimensionalArray; - -typedef NSMutableDictionary *> ASMutableSupplementaryElementDictionary; - -@implementation ASMutableElementMap { - ASMutableSupplementaryElementDictionary *_supplementaryElements; - NSMutableArray *_sections; - ASMutableCollectionElementTwoDimensionalArray *_sectionsOfItems; -} - -- (instancetype)initWithSections:(NSArray *)sections items:(ASCollectionElementTwoDimensionalArray *)items supplementaryElements:(ASSupplementaryElementDictionary *)supplementaryElements -{ - if (self = [super init]) { - _sections = [sections mutableCopy]; - _sectionsOfItems = (ASMutableCollectionElementTwoDimensionalArray *)ASTwoDimensionalArrayDeepMutableCopy(items); - _supplementaryElements = [ASMutableElementMap deepMutableCopyOfElementsDictionary:supplementaryElements]; - } - return self; -} - -- (id)copyWithZone:(NSZone *)zone -{ - return [[ASElementMap alloc] initWithSections:_sections items:_sectionsOfItems supplementaryElements:_supplementaryElements]; -} - -- (void)removeAllSections -{ - [_sections removeAllObjects]; -} - -- (void)insertSection:(ASSection *)section atIndex:(NSInteger)index -{ - [_sections insertObject:section atIndex:index]; -} - -- (void)removeItemsAtIndexPaths:(NSArray *)indexPaths -{ - ASDeleteElementsInTwoDimensionalArrayAtIndexPaths(_sectionsOfItems, indexPaths); -} - -- (void)removeSectionsAtIndexes:(NSIndexSet *)indexes -{ - [_sections removeObjectsAtIndexes:indexes]; -} - -- (void)removeSupplementaryElementsAtIndexPaths:(NSArray *)indexPaths kind:(NSString *)kind -{ - [_supplementaryElements[kind] removeObjectsForKeys:indexPaths]; -} - -- (void)removeAllElements -{ - [_sectionsOfItems removeAllObjects]; - [_supplementaryElements removeAllObjects]; -} - -- (void)removeSectionsOfItems:(NSIndexSet *)itemSections -{ - [_sectionsOfItems removeObjectsAtIndexes:itemSections]; -} - -- (void)insertEmptySectionsOfItemsAtIndexes:(NSIndexSet *)sections -{ - [sections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { - [_sectionsOfItems insertObject:[[NSMutableArray alloc] init] atIndex:idx]; - }]; -} - -- (void)insertElement:(ASCollectionElement *)element atIndexPath:(NSIndexPath *)indexPath -{ - NSString *kind = element.supplementaryElementKind; - if (kind == nil) { - [_sectionsOfItems[indexPath.section] insertObject:element atIndex:indexPath.item]; - } else { - NSMutableDictionary *supplementariesForKind = _supplementaryElements[kind]; - if (supplementariesForKind == nil) { - supplementariesForKind = [[NSMutableDictionary alloc] init]; - _supplementaryElements[kind] = supplementariesForKind; - } - supplementariesForKind[indexPath] = element; - } -} - -- (void)migrateSupplementaryElementsWithSectionMapping:(ASIntegerMap *)mapping -{ - // Fast-path, no section changes. - if (mapping == ASIntegerMap.identityMap) { - return; - } - - // For each element kind, - [_supplementaryElements enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSMutableDictionary * _Nonnull supps, BOOL * _Nonnull stop) { - - // For each index path of that kind, move entries into a new dictionary. - // Note: it's tempting to update the dictionary in-place but because of the likely collision between old and new index paths, - // subtle bugs are possible. Note that this process is rare (only on section-level updates), - // that this work is done off-main, and that the typical supplementary element use case is just 1-per-section (header). - NSMutableDictionary *newSupps = [[NSMutableDictionary alloc] init]; - [supps enumerateKeysAndObjectsUsingBlock:^(NSIndexPath * _Nonnull oldIndexPath, ASCollectionElement * _Nonnull obj, BOOL * _Nonnull stop) { - NSInteger oldSection = oldIndexPath.section; - NSInteger newSection = [mapping integerForKey:oldSection]; - - if (oldSection == newSection) { - // Index path stayed the same, just copy it over. - newSupps[oldIndexPath] = obj; - } else if (newSection != NSNotFound) { - // Section index changed, move it. - NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:oldIndexPath.item inSection:newSection]; - newSupps[newIndexPath] = obj; - } - }]; - [supps setDictionary:newSupps]; - }]; -} - -#pragma mark - Helpers - -+ (ASMutableSupplementaryElementDictionary *)deepMutableCopyOfElementsDictionary:(ASSupplementaryElementDictionary *)originalDict -{ - NSMutableDictionary *deepCopy = [[NSMutableDictionary alloc] initWithCapacity:originalDict.count]; - [originalDict enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSDictionary * _Nonnull obj, BOOL * _Nonnull stop) { - deepCopy[key] = [obj mutableCopy]; - }]; - - return deepCopy; -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASNodeController+Beta.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASNodeController+Beta.h deleted file mode 100644 index e9028f1986..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASNodeController+Beta.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// ASNodeController+Beta.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import // for ASInterfaceState protocol - -/* ASNodeController is currently beta and open to change in the future */ -@interface ASNodeController<__covariant DisplayNodeType : ASDisplayNode *> - : NSObject - -@property (nonatomic, strong /* may be weak! */) DisplayNodeType node; - -// Until an ASNodeController can be provided in place of an ASCellNode, some apps may prefer to have -// nodes keep their controllers alive (and a weak reference from controller to node) - -@property (nonatomic) BOOL shouldInvertStrongReference; - -- (void)loadNode; - -// for descriptions see definition -- (void)nodeDidLoad ASDISPLAYNODE_REQUIRES_SUPER; -- (void)nodeDidLayout ASDISPLAYNODE_REQUIRES_SUPER; - -// This is only called during Yoga-driven layouts. -- (void)nodeWillCalculateLayout:(ASSizeRange)constrainedSize ASDISPLAYNODE_REQUIRES_SUPER; - -- (void)didEnterVisibleState ASDISPLAYNODE_REQUIRES_SUPER; -- (void)didExitVisibleState ASDISPLAYNODE_REQUIRES_SUPER; - -- (void)didEnterDisplayState ASDISPLAYNODE_REQUIRES_SUPER; -- (void)didExitDisplayState ASDISPLAYNODE_REQUIRES_SUPER; - -- (void)didEnterPreloadState ASDISPLAYNODE_REQUIRES_SUPER; -- (void)didExitPreloadState ASDISPLAYNODE_REQUIRES_SUPER; - -- (void)interfaceStateDidChange:(ASInterfaceState)newState - fromState:(ASInterfaceState)oldState ASDISPLAYNODE_REQUIRES_SUPER; - -- (void)hierarchyDisplayDidFinish ASDISPLAYNODE_REQUIRES_SUPER; - -/** - * @discussion Attempts (via ASLockSequence, a backing-off spinlock similar to - * std::lock()) to lock both the node and its ASNodeController, if one exists. - */ -- (ASLockSet)lockPair; - -@end - -@interface ASDisplayNode (ASNodeController) - -@property(nonatomic, readonly) ASNodeController *nodeController; - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASNodeController+Beta.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASNodeController+Beta.mm deleted file mode 100644 index 14aae33633..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASNodeController+Beta.mm +++ /dev/null @@ -1,135 +0,0 @@ -// -// ASNodeController+Beta.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import -#import - -#define _node (_shouldInvertStrongReference ? _weakNode : _strongNode) - -@implementation ASNodeController -{ - ASDisplayNode *_strongNode; - __weak ASDisplayNode *_weakNode; - AS::RecursiveMutex __instanceLock__; -} - -- (void)loadNode -{ - ASLockScopeSelf(); - self.node = [[ASDisplayNode alloc] init]; -} - -- (ASDisplayNode *)node -{ - ASLockScopeSelf(); - if (_node == nil) { - [self loadNode]; - } - return _node; -} - -- (void)setupReferencesWithNode:(ASDisplayNode *)node -{ - ASLockScopeSelf(); - if (_shouldInvertStrongReference) { - // The node should own the controller; weak reference from controller to node. - _weakNode = node; - _strongNode = nil; - } else { - // The controller should own the node; weak reference from node to controller. - _strongNode = node; - _weakNode = nil; - } - - [node __setNodeController:self]; -} - -- (void)setNode:(ASDisplayNode *)node -{ - ASLockScopeSelf(); - if (node == _node) { - return; - } - [self setupReferencesWithNode:node]; - [node addInterfaceStateDelegate:self]; -} - -- (void)setShouldInvertStrongReference:(BOOL)shouldInvertStrongReference -{ - ASLockScopeSelf(); - if (_shouldInvertStrongReference != shouldInvertStrongReference) { - // Because the BOOL controls which ivar we access, get the node before toggling. - ASDisplayNode *node = _node; - _shouldInvertStrongReference = shouldInvertStrongReference; - [self setupReferencesWithNode:node]; - } -} - -// subclass overrides -- (void)nodeDidLoad {} -- (void)nodeDidLayout {} -- (void)nodeWillCalculateLayout:(ASSizeRange)constrainedSize {} - -- (void)didEnterVisibleState {} -- (void)didExitVisibleState {} - -- (void)didEnterDisplayState {} -- (void)didExitDisplayState {} - -- (void)didEnterPreloadState {} -- (void)didExitPreloadState {} - -- (void)interfaceStateDidChange:(ASInterfaceState)newState - fromState:(ASInterfaceState)oldState {} - -- (void)hierarchyDisplayDidFinish {} - -- (ASLockSet)lockPair { - ASLockSet lockSet = ASLockSequence(^BOOL(ASAddLockBlock addLock) { - if (!addLock(_node)) { - return NO; - } - if (!addLock(self)) { - return NO; - } - return YES; - }); - - return lockSet; -} - -#pragma mark NSLocking - -- (void)lock -{ - __instanceLock__.lock(); -} - -- (void)unlock -{ - __instanceLock__.unlock(); -} - -- (BOOL)tryLock -{ - return __instanceLock__.try_lock(); -} - -@end - -@implementation ASDisplayNode (ASNodeController) - -- (ASNodeController *)nodeController -{ - return _weakNodeController ?: _strongNodeController; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASOverlayLayoutSpec.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASOverlayLayoutSpec.h deleted file mode 100644 index a29a72b750..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASOverlayLayoutSpec.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// ASOverlayLayoutSpec.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - This layout spec lays out a single layoutElement child and then overlays a layoutElement object on top of it streched to its size - */ -@interface ASOverlayLayoutSpec : ASLayoutSpec - -/** - * Overlay layoutElement of this layout spec - */ -@property (nonatomic) id overlay; - -/** - * Creates and returns an ASOverlayLayoutSpec object with a given child and an layoutElement that act as overlay. - * - * @param child A child that is laid out to determine the size of this spec. - * @param overlay A layoutElement object that is laid out over the child. - */ -+ (instancetype)overlayLayoutSpecWithChild:(id)child overlay:(id)overlay NS_RETURNS_RETAINED AS_WARN_UNUSED_RESULT; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASOverlayLayoutSpec.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASOverlayLayoutSpec.mm deleted file mode 100644 index 27ffbeb8c7..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASOverlayLayoutSpec.mm +++ /dev/null @@ -1,88 +0,0 @@ -// -// ASOverlayLayoutSpec.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import -#import - -static NSUInteger const kUnderlayChildIndex = 0; -static NSUInteger const kOverlayChildIndex = 1; - -@implementation ASOverlayLayoutSpec - -#pragma mark - Class - -+ (instancetype)overlayLayoutSpecWithChild:(id)child overlay:(id)overlay NS_RETURNS_RETAINED -{ - return [[self alloc] initWithChild:child overlay:overlay]; -} - -#pragma mark - Lifecycle - -- (instancetype)initWithChild:(id)child overlay:(id)overlay -{ - if (!(self = [super init])) { - return nil; - } - self.child = child; - self.overlay = overlay; - return self; -} - -#pragma mark - Setter / Getter - -- (void)setChild:(id)child -{ - ASDisplayNodeAssertNotNil(child, @"Child that will be overlayed on shouldn't be nil"); - [super setChild:child atIndex:kUnderlayChildIndex]; -} - -- (id)child -{ - return [super childAtIndex:kUnderlayChildIndex]; -} - -- (void)setOverlay:(id)overlay -{ - ASDisplayNodeAssertNotNil(overlay, @"Overlay cannot be nil"); - [super setChild:overlay atIndex:kOverlayChildIndex]; -} - -- (id)overlay -{ - return [super childAtIndex:kOverlayChildIndex]; -} - -#pragma mark - ASLayoutSpec - -/** - First layout the contents, then fit the overlay on top of it. - */ -- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize - restrictedToSize:(ASLayoutElementSize)size - relativeToParentSize:(CGSize)parentSize -{ - ASLayout *contentsLayout = [self.child layoutThatFits:constrainedSize parentSize:parentSize]; - contentsLayout.position = CGPointZero; - ASLayout *rawSublayouts[2]; - int i = 0; - rawSublayouts[i++] = contentsLayout; - if (self.overlay) { - ASLayout *overlayLayout = [self.overlay layoutThatFits:ASSizeRangeMake(contentsLayout.size) - parentSize:contentsLayout.size]; - overlayLayout.position = CGPointZero; - rawSublayouts[i++] = overlayLayout; - } - - const auto sublayouts = [NSArray arrayByTransferring:rawSublayouts count:i]; - return [ASLayout layoutWithLayoutElement:self size:contentsLayout.size sublayouts:sublayouts]; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASSupplementaryNodeSource.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASSupplementaryNodeSource.h deleted file mode 100644 index bc361dc736..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASSupplementaryNodeSource.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// ASSupplementaryNodeSource.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#ifndef MINIMAL_ASDK - -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol ASSupplementaryNodeSource - -@optional - -/** - * A method to provide the node-block for the supplementary element. - * - * @param elementKind The kind of supplementary element. - * @param index The index of the item. - * @return A node block for the supplementary element. - * @see collectionNode:nodeForSupplementaryElementOfKind:atIndexPath: - */ -- (ASCellNodeBlock)nodeBlockForSupplementaryElementOfKind:(NSString *)elementKind atIndex:(NSInteger)index; - -/** - * Asks the controller to provide a node to display for the given supplementary element. - * - * @param kind The kind of supplementary element. - * @param index The index of the item. - */ -- (ASCellNode *)nodeForSupplementaryElementOfKind:(NSString *)kind atIndex:(NSInteger)index; - -/** - * A method to provide the size range used for measuring the supplementary - * element of the given kind at the given index. - * - * @param elementKind The kind of supplementary element. - * @param index The index of the item. - * @return A size range used for asynchronously measuring the node. - * @see collectionNode:constrainedSizeForSupplementaryElementOfKind:atIndexPath: - */ -- (ASSizeRange)sizeRangeForSupplementaryElementOfKind:(NSString *)elementKind atIndex:(NSInteger)index; - -@end - -NS_ASSUME_NONNULL_END - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextAttribute.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextAttribute.h deleted file mode 100644 index 2d9e3771a0..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextAttribute.h +++ /dev/null @@ -1,346 +0,0 @@ -// -// ASTextAttribute.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - Enum Define - -/// The attribute type -typedef NS_OPTIONS(NSInteger, ASTextAttributeType) { - ASTextAttributeTypeNone = 0, - ASTextAttributeTypeUIKit = 1 << 0, ///< UIKit attributes, such as UILabel/UITextField/drawInRect. - ASTextAttributeTypeCoreText = 1 << 1, ///< CoreText attributes, used by CoreText. - ASTextAttributeTypeASText = 1 << 2, ///< ASText attributes, used by ASText. -}; - -/// Get the attribute type from an attribute name. -AS_EXTERN ASTextAttributeType ASTextAttributeGetType(NSString *attributeName); - -/** - Line style in ASText (similar to NSUnderlineStyle). - */ -typedef NS_OPTIONS (NSInteger, ASTextLineStyle) { - // basic style (bitmask:0xFF) - ASTextLineStyleNone = 0x00, ///< ( ) Do not draw a line (Default). - ASTextLineStyleSingle = 0x01, ///< (──────) Draw a single line. - ASTextLineStyleThick = 0x02, ///< (━━━━━━━) Draw a thick line. - ASTextLineStyleDouble = 0x09, ///< (══════) Draw a double line. - - // style pattern (bitmask:0xF00) - ASTextLineStylePatternSolid = 0x000, ///< (────────) Draw a solid line (Default). - ASTextLineStylePatternDot = 0x100, ///< (‑ ‑ ‑ ‑ ‑ ‑) Draw a line of dots. - ASTextLineStylePatternDash = 0x200, ///< (— — — —) Draw a line of dashes. - ASTextLineStylePatternDashDot = 0x300, ///< (— ‑ — ‑ — ‑) Draw a line of alternating dashes and dots. - ASTextLineStylePatternDashDotDot = 0x400, ///< (— ‑ ‑ — ‑ ‑) Draw a line of alternating dashes and two dots. - ASTextLineStylePatternCircleDot = 0x900, ///< (••••••••••••) Draw a line of small circle dots. -}; - -/** - Text vertical alignment. - */ -typedef NS_ENUM(NSInteger, ASTextVerticalAlignment) { - ASTextVerticalAlignmentTop = 0, ///< Top alignment. - ASTextVerticalAlignmentCenter = 1, ///< Center alignment. - ASTextVerticalAlignmentBottom = 2, ///< Bottom alignment. -}; - -/** - The direction define in ASText. - */ -typedef NS_OPTIONS(NSUInteger, ASTextDirection) { - ASTextDirectionNone = 0, - ASTextDirectionTop = 1 << 0, - ASTextDirectionRight = 1 << 1, - ASTextDirectionBottom = 1 << 2, - ASTextDirectionLeft = 1 << 3, -}; - -/** - The trunction type, tells the truncation engine which type of truncation is being requested. - */ -typedef NS_ENUM (NSUInteger, ASTextTruncationType) { - /// No truncate. - ASTextTruncationTypeNone = 0, - - /// Truncate at the beginning of the line, leaving the end portion visible. - ASTextTruncationTypeStart = 1, - - /// Truncate at the end of the line, leaving the start portion visible. - ASTextTruncationTypeEnd = 2, - - /// Truncate in the middle of the line, leaving both the start and the end portions visible. - ASTextTruncationTypeMiddle = 3, -}; - - - -#pragma mark - Attribute Name Defined in ASText - -/// The value of this attribute is a `ASTextBackedString` object. -/// Use this attribute to store the original plain text if it is replaced by something else (such as attachment). -UIKIT_EXTERN NSString *const ASTextBackedStringAttributeName; - -/// The value of this attribute is a `ASTextBinding` object. -/// Use this attribute to bind a range of text together, as if it was a single charactor. -UIKIT_EXTERN NSString *const ASTextBindingAttributeName; - -/// The value of this attribute is a `ASTextShadow` object. -/// Use this attribute to add shadow to a range of text. -/// Shadow will be drawn below text glyphs. Use ASTextShadow.subShadow to add multi-shadow. -UIKIT_EXTERN NSString *const ASTextShadowAttributeName; - -/// The value of this attribute is a `ASTextShadow` object. -/// Use this attribute to add inner shadow to a range of text. -/// Inner shadow will be drawn above text glyphs. Use ASTextShadow.subShadow to add multi-shadow. -UIKIT_EXTERN NSString *const ASTextInnerShadowAttributeName; - -/// The value of this attribute is a `ASTextDecoration` object. -/// Use this attribute to add underline to a range of text. -/// The underline will be drawn below text glyphs. -UIKIT_EXTERN NSString *const ASTextUnderlineAttributeName; - -/// The value of this attribute is a `ASTextDecoration` object. -/// Use this attribute to add strikethrough (delete line) to a range of text. -/// The strikethrough will be drawn above text glyphs. -UIKIT_EXTERN NSString *const ASTextStrikethroughAttributeName; - -/// The value of this attribute is a `ASTextBorder` object. -/// Use this attribute to add cover border or cover color to a range of text. -/// The border will be drawn above the text glyphs. -UIKIT_EXTERN NSString *const ASTextBorderAttributeName; - -/// The value of this attribute is a `ASTextBorder` object. -/// Use this attribute to add background border or background color to a range of text. -/// The border will be drawn below the text glyphs. -UIKIT_EXTERN NSString *const ASTextBackgroundBorderAttributeName; - -/// The value of this attribute is a `ASTextBorder` object. -/// Use this attribute to add a code block border to one or more line of text. -/// The border will be drawn below the text glyphs. -UIKIT_EXTERN NSString *const ASTextBlockBorderAttributeName; - -/// The value of this attribute is a `ASTextAttachment` object. -/// Use this attribute to add attachment to text. -/// It should be used in conjunction with a CTRunDelegate. -UIKIT_EXTERN NSString *const ASTextAttachmentAttributeName; - -/// The value of this attribute is a `ASTextHighlight` object. -/// Use this attribute to add a touchable highlight state to a range of text. -UIKIT_EXTERN NSString *const ASTextHighlightAttributeName; - -/// The value of this attribute is a `NSValue` object stores CGAffineTransform. -/// Use this attribute to add transform to each glyph in a range of text. -UIKIT_EXTERN NSString *const ASTextGlyphTransformAttributeName; - - - -#pragma mark - String Token Define - -UIKIT_EXTERN NSString *const ASTextAttachmentToken; ///< Object replacement character (U+FFFC), used for text attachment. -UIKIT_EXTERN NSString *const ASTextTruncationToken; ///< Horizontal ellipsis (U+2026), used for text truncation "…". - - - -#pragma mark - Attribute Value Define - -/** - The tap/long press action callback defined in ASText. - - @param containerView The text container view (such as ASLabel/ASTextView). - @param text The whole text. - @param range The text range in `text` (if no range, the range.location is NSNotFound). - @param rect The text frame in `containerView` (if no data, the rect is CGRectNull). - */ -typedef void(^ASTextAction)(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect); - - -/** - ASTextBackedString objects are used by the NSAttributedString class cluster - as the values for text backed string attributes (stored in the attributed - string under the key named ASTextBackedStringAttributeName). - - It may used for copy/paste plain text from attributed string. - Example: If :) is replace by a custom emoji (such as😊), the backed string can be set to @":)". - */ -@interface ASTextBackedString : NSObject -+ (instancetype)stringWithString:(nullable NSString *)string NS_RETURNS_RETAINED; -@property (nullable, nonatomic, copy) NSString *string; ///< backed string -@end - - -/** - ASTextBinding objects are used by the NSAttributedString class cluster - as the values for shadow attributes (stored in the attributed string under - the key named ASTextBindingAttributeName). - - Add this to a range of text will make the specified characters 'binding together'. - ASTextView will treat the range of text as a single character during text - selection and edit. - */ -@interface ASTextBinding : NSObject -+ (instancetype)bindingWithDeleteConfirm:(BOOL)deleteConfirm NS_RETURNS_RETAINED; -@property (nonatomic) BOOL deleteConfirm; ///< confirm the range when delete in ASTextView -@end - - -/** - ASTextShadow objects are used by the NSAttributedString class cluster - as the values for shadow attributes (stored in the attributed string under - the key named ASTextShadowAttributeName or ASTextInnerShadowAttributeName). - - It's similar to `NSShadow`, but offers more options. - */ -@interface ASTextShadow : NSObject -+ (instancetype)shadowWithColor:(nullable UIColor *)color offset:(CGSize)offset radius:(CGFloat)radius NS_RETURNS_RETAINED; - -@property (nullable, nonatomic) UIColor *color; ///< shadow color -@property (nonatomic) CGSize offset; ///< shadow offset -@property (nonatomic) CGFloat radius; ///< shadow blur radius -@property (nonatomic) CGBlendMode blendMode; ///< shadow blend mode -@property (nullable, nonatomic) ASTextShadow *subShadow; ///< a sub shadow which will be added above the parent shadow - -+ (instancetype)shadowWithNSShadow:(NSShadow *)nsShadow NS_RETURNS_RETAINED; ///< convert NSShadow to ASTextShadow -- (NSShadow *)nsShadow; ///< convert ASTextShadow to NSShadow -@end - - -/** - ASTextDecorationLine objects are used by the NSAttributedString class cluster - as the values for decoration line attributes (stored in the attributed string under - the key named ASTextUnderlineAttributeName or ASTextStrikethroughAttributeName). - - When it's used as underline, the line is drawn below text glyphs; - when it's used as strikethrough, the line is drawn above text glyphs. - */ -@interface ASTextDecoration : NSObject -+ (instancetype)decorationWithStyle:(ASTextLineStyle)style NS_RETURNS_RETAINED; -+ (instancetype)decorationWithStyle:(ASTextLineStyle)style width:(nullable NSNumber *)width color:(nullable UIColor *)color NS_RETURNS_RETAINED; -@property (nonatomic) ASTextLineStyle style; ///< line style -@property (nullable, nonatomic) NSNumber *width; ///< line width (nil means automatic width) -@property (nullable, nonatomic) UIColor *color; ///< line color (nil means automatic color) -@property (nullable, nonatomic) ASTextShadow *shadow; ///< line shadow -@end - - -/** - ASTextBorder objects are used by the NSAttributedString class cluster - as the values for border attributes (stored in the attributed string under - the key named ASTextBorderAttributeName or ASTextBackgroundBorderAttributeName). - - It can be used to draw a border around a range of text, or draw a background - to a range of text. - - Example: - ╭──────╮ - │ Text │ - ╰──────╯ - */ -@interface ASTextBorder : NSObject -+ (instancetype)borderWithLineStyle:(ASTextLineStyle)lineStyle lineWidth:(CGFloat)width strokeColor:(nullable UIColor *)color NS_RETURNS_RETAINED; -+ (instancetype)borderWithFillColor:(nullable UIColor *)color cornerRadius:(CGFloat)cornerRadius NS_RETURNS_RETAINED; -@property (nonatomic) ASTextLineStyle lineStyle; ///< border line style -@property (nonatomic) CGFloat strokeWidth; ///< border line width -@property (nullable, nonatomic) UIColor *strokeColor; ///< border line color -@property (nonatomic) CGLineJoin lineJoin; ///< border line join -@property (nonatomic) UIEdgeInsets insets; ///< border insets for text bounds -@property (nonatomic) CGFloat cornerRadius; ///< border corder radius -@property (nullable, nonatomic) ASTextShadow *shadow; ///< border shadow -@property (nullable, nonatomic) UIColor *fillColor; ///< inner fill color -@end - - -/** - ASTextAttachment objects are used by the NSAttributedString class cluster - as the values for attachment attributes (stored in the attributed string under - the key named ASTextAttachmentAttributeName). - - When display an attributed string which contains `ASTextAttachment` object, - the content will be placed in text metric. If the content is `UIImage`, - then it will be drawn to CGContext; if the content is `UIView` or `CALayer`, - then it will be added to the text container's view or layer. - */ -@interface ASTextAttachment : NSObject -+ (instancetype)attachmentWithContent:(nullable id)content NS_RETURNS_RETAINED; -@property (nullable, nonatomic) id content; ///< Supported type: UIImage, UIView, CALayer -@property (nonatomic) UIViewContentMode contentMode; ///< Content display mode. -@property (nonatomic) UIEdgeInsets contentInsets; ///< The insets when drawing content. -@property (nullable, nonatomic) NSDictionary *userInfo; ///< The user information dictionary. -@end - - -/** - ASTextHighlight objects are used by the NSAttributedString class cluster - as the values for touchable highlight attributes (stored in the attributed string - under the key named ASTextHighlightAttributeName). - - When display an attributed string in `ASLabel` or `ASTextView`, the range of - highlight text can be toucheds down by users. If a range of text is turned into - highlighted state, the `attributes` in `ASTextHighlight` will be used to modify - (set or remove) the original attributes in the range for display. - */ -@interface ASTextHighlight : NSObject - -/** - Attributes that you can apply to text in an attributed string when highlight. - Key: Same as CoreText/ASText Attribute Name. - Value: Modify attribute value when highlight (NSNull for remove attribute). - */ -@property (nullable, nonatomic, copy) NSDictionary *attributes; - -/** - Creates a highlight object with specified attributes. - - @param attributes The attributes which will replace original attributes when highlight, - If the value is NSNull, it will removed when highlight. - */ -+ (instancetype)highlightWithAttributes:(nullable NSDictionary *)attributes NS_RETURNS_RETAINED; - -/** - Convenience methods to create a default highlight with the specifeid background color. - - @param color The background border color. - */ -+ (instancetype)highlightWithBackgroundColor:(nullable UIColor *)color NS_RETURNS_RETAINED; - -// Convenience methods below to set the `attributes`. -- (void)setFont:(nullable UIFont *)font; -- (void)setColor:(nullable UIColor *)color; -- (void)setStrokeWidth:(nullable NSNumber *)width; -- (void)setStrokeColor:(nullable UIColor *)color; -- (void)setShadow:(nullable ASTextShadow *)shadow; -- (void)setInnerShadow:(nullable ASTextShadow *)shadow; -- (void)setUnderline:(nullable ASTextDecoration *)underline; -- (void)setStrikethrough:(nullable ASTextDecoration *)strikethrough; -- (void)setBackgroundBorder:(nullable ASTextBorder *)border; -- (void)setBorder:(nullable ASTextBorder *)border; -- (void)setAttachment:(nullable ASTextAttachment *)attachment; - -/** - The user information dictionary, default is nil. - */ -@property (nullable, nonatomic, copy) NSDictionary *userInfo; - -/** - Tap action when user tap the highlight, default is nil. - If the value is nil, ASTextView or ASLabel will ask it's delegate to handle the tap action. - */ -@property (nullable, nonatomic) ASTextAction tapAction; - -/** - Long press action when user long press the highlight, default is nil. - If the value is nil, ASTextView or ASLabel will ask it's delegate to handle the long press action. - */ -@property (nullable, nonatomic) ASTextAction longPressAction; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextAttribute.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextAttribute.mm deleted file mode 100644 index abbcc8ddf1..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextAttribute.mm +++ /dev/null @@ -1,488 +0,0 @@ -// -// ASTextAttribute.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import -#import - -NSString *const ASTextBackedStringAttributeName = @"ASTextBackedString"; -NSString *const ASTextBindingAttributeName = @"ASTextBinding"; -NSString *const ASTextShadowAttributeName = @"ASTextShadow"; -NSString *const ASTextInnerShadowAttributeName = @"ASTextInnerShadow"; -NSString *const ASTextUnderlineAttributeName = @"ASTextUnderline"; -NSString *const ASTextStrikethroughAttributeName = @"ASTextStrikethrough"; -NSString *const ASTextBorderAttributeName = @"ASTextBorder"; -NSString *const ASTextBackgroundBorderAttributeName = @"ASTextBackgroundBorder"; -NSString *const ASTextBlockBorderAttributeName = @"ASTextBlockBorder"; -NSString *const ASTextAttachmentAttributeName = @"ASTextAttachment"; -NSString *const ASTextHighlightAttributeName = @"ASTextHighlight"; -NSString *const ASTextGlyphTransformAttributeName = @"ASTextGlyphTransform"; - -NSString *const ASTextAttachmentToken = @"\uFFFC"; -NSString *const ASTextTruncationToken = @"\u2026"; - - -ASTextAttributeType ASTextAttributeGetType(NSString *name){ - if (name.length == 0) return ASTextAttributeTypeNone; - - static NSMutableDictionary *dic; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - dic = [NSMutableDictionary new]; - NSNumber *All = @(ASTextAttributeTypeUIKit | ASTextAttributeTypeCoreText | ASTextAttributeTypeASText); - NSNumber *CoreText_ASText = @(ASTextAttributeTypeCoreText | ASTextAttributeTypeASText); - NSNumber *UIKit_ASText = @(ASTextAttributeTypeUIKit | ASTextAttributeTypeASText); - NSNumber *UIKit_CoreText = @(ASTextAttributeTypeUIKit | ASTextAttributeTypeCoreText); - NSNumber *UIKit = @(ASTextAttributeTypeUIKit); - NSNumber *CoreText = @(ASTextAttributeTypeCoreText); - NSNumber *ASText = @(ASTextAttributeTypeASText); - - dic[NSFontAttributeName] = All; - dic[NSKernAttributeName] = All; - dic[NSForegroundColorAttributeName] = UIKit; - dic[(id)kCTForegroundColorAttributeName] = CoreText; - dic[(id)kCTForegroundColorFromContextAttributeName] = CoreText; - dic[NSBackgroundColorAttributeName] = UIKit; - dic[NSStrokeWidthAttributeName] = All; - dic[NSStrokeColorAttributeName] = UIKit; - dic[(id)kCTStrokeColorAttributeName] = CoreText_ASText; - dic[NSShadowAttributeName] = UIKit_ASText; - dic[NSStrikethroughStyleAttributeName] = UIKit; - dic[NSUnderlineStyleAttributeName] = UIKit_CoreText; - dic[(id)kCTUnderlineColorAttributeName] = CoreText; - dic[NSLigatureAttributeName] = All; - dic[(id)kCTSuperscriptAttributeName] = UIKit; //it's a CoreText attrubite, but only supported by UIKit... - dic[NSVerticalGlyphFormAttributeName] = All; - dic[(id)kCTGlyphInfoAttributeName] = CoreText_ASText; -#if TARGET_OS_IOS -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - dic[(id)kCTCharacterShapeAttributeName] = CoreText_ASText; -#pragma clang diagnostic pop -#endif - dic[(id)kCTRunDelegateAttributeName] = CoreText_ASText; - dic[(id)kCTBaselineClassAttributeName] = CoreText_ASText; - dic[(id)kCTBaselineInfoAttributeName] = CoreText_ASText; - dic[(id)kCTBaselineReferenceInfoAttributeName] = CoreText_ASText; - dic[(id)kCTWritingDirectionAttributeName] = CoreText_ASText; - dic[NSParagraphStyleAttributeName] = All; - - dic[NSStrikethroughColorAttributeName] = UIKit; - dic[NSUnderlineColorAttributeName] = UIKit; - dic[NSTextEffectAttributeName] = UIKit; - dic[NSObliquenessAttributeName] = UIKit; - dic[NSExpansionAttributeName] = UIKit; - dic[(id)kCTLanguageAttributeName] = CoreText_ASText; - dic[NSBaselineOffsetAttributeName] = UIKit; - dic[NSWritingDirectionAttributeName] = All; - dic[NSAttachmentAttributeName] = UIKit; - dic[NSLinkAttributeName] = UIKit; - dic[(id)kCTRubyAnnotationAttributeName] = CoreText; - - dic[ASTextBackedStringAttributeName] = ASText; - dic[ASTextBindingAttributeName] = ASText; - dic[ASTextShadowAttributeName] = ASText; - dic[ASTextInnerShadowAttributeName] = ASText; - dic[ASTextUnderlineAttributeName] = ASText; - dic[ASTextStrikethroughAttributeName] = ASText; - dic[ASTextBorderAttributeName] = ASText; - dic[ASTextBackgroundBorderAttributeName] = ASText; - dic[ASTextBlockBorderAttributeName] = ASText; - dic[ASTextAttachmentAttributeName] = ASText; - dic[ASTextHighlightAttributeName] = ASText; - dic[ASTextGlyphTransformAttributeName] = ASText; - }); - NSNumber *num = dic[name]; - if (num) return num.integerValue; - return ASTextAttributeTypeNone; -} - - -@implementation ASTextBackedString - -+ (instancetype)stringWithString:(NSString *)string NS_RETURNS_RETAINED { - ASTextBackedString *one = [self new]; - one.string = string; - return one; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder { - [aCoder encodeObject:self.string forKey:@"string"]; -} - -- (id)initWithCoder:(NSCoder *)aDecoder { - self = [super init]; - _string = [aDecoder decodeObjectForKey:@"string"]; - return self; -} - -- (id)copyWithZone:(NSZone *)zone { - __typeof__(self) one = [self.class new]; - one.string = self.string; - return one; -} - -@end - - -@implementation ASTextBinding - -+ (instancetype)bindingWithDeleteConfirm:(BOOL)deleteConfirm NS_RETURNS_RETAINED { - ASTextBinding *one = [self new]; - one.deleteConfirm = deleteConfirm; - return one; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder { - [aCoder encodeObject:@(self.deleteConfirm) forKey:@"deleteConfirm"]; -} - -- (id)initWithCoder:(NSCoder *)aDecoder { - self = [super init]; - _deleteConfirm = ((NSNumber *)[aDecoder decodeObjectForKey:@"deleteConfirm"]).boolValue; - return self; -} - -- (id)copyWithZone:(NSZone *)zone { - __typeof__(self) one = [self.class new]; - one.deleteConfirm = self.deleteConfirm; - return one; -} - -@end - - -@implementation ASTextShadow - -+ (instancetype)shadowWithColor:(UIColor *)color offset:(CGSize)offset radius:(CGFloat)radius NS_RETURNS_RETAINED { - ASTextShadow *one = [self new]; - one.color = color; - one.offset = offset; - one.radius = radius; - return one; -} - -+ (instancetype)shadowWithNSShadow:(NSShadow *)nsShadow NS_RETURNS_RETAINED { - if (!nsShadow) return nil; - ASTextShadow *shadow = [self new]; - shadow.offset = nsShadow.shadowOffset; - shadow.radius = nsShadow.shadowBlurRadius; - id color = nsShadow.shadowColor; - if (color) { - if (CGColorGetTypeID() == CFGetTypeID((__bridge CFTypeRef)(color))) { - color = [UIColor colorWithCGColor:(__bridge CGColorRef)(color)]; - } - if ([color isKindOfClass:[UIColor class]]) { - shadow.color = color; - } - } - return shadow; -} - -- (NSShadow *)nsShadow { - NSShadow *shadow = [NSShadow new]; - shadow.shadowOffset = self.offset; - shadow.shadowBlurRadius = self.radius; - shadow.shadowColor = self.color; - return shadow; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder { - [aCoder encodeObject:self.color forKey:@"color"]; - [aCoder encodeObject:@(self.radius) forKey:@"radius"]; - [aCoder encodeObject:[NSValue valueWithCGSize:self.offset] forKey:@"offset"]; - [aCoder encodeObject:self.subShadow forKey:@"subShadow"]; -} - -- (id)initWithCoder:(NSCoder *)aDecoder { - self = [super init]; - _color = [aDecoder decodeObjectForKey:@"color"]; - _radius = ((NSNumber *)[aDecoder decodeObjectForKey:@"radius"]).floatValue; - _offset = ((NSValue *)[aDecoder decodeObjectForKey:@"offset"]).CGSizeValue; - _subShadow = [aDecoder decodeObjectForKey:@"subShadow"]; - return self; -} - -- (id)copyWithZone:(NSZone *)zone { - __typeof__(self) one = [self.class new]; - one.color = self.color; - one.radius = self.radius; - one.offset = self.offset; - one.subShadow = self.subShadow.copy; - return one; -} - -@end - - -@implementation ASTextDecoration - -- (instancetype)init { - self = [super init]; - _style = ASTextLineStyleSingle; - return self; -} - -+ (instancetype)decorationWithStyle:(ASTextLineStyle)style NS_RETURNS_RETAINED { - ASTextDecoration *one = [self new]; - one.style = style; - return one; -} -+ (instancetype)decorationWithStyle:(ASTextLineStyle)style width:(NSNumber *)width color:(UIColor *)color NS_RETURNS_RETAINED { - ASTextDecoration *one = [self new]; - one.style = style; - one.width = width; - one.color = color; - return one; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder { - [aCoder encodeObject:@(self.style) forKey:@"style"]; - [aCoder encodeObject:self.width forKey:@"width"]; - [aCoder encodeObject:self.color forKey:@"color"]; -} - -- (id)initWithCoder:(NSCoder *)aDecoder { - self = [super init]; - self.style = ((NSNumber *)[aDecoder decodeObjectForKey:@"style"]).unsignedIntegerValue; - self.width = [aDecoder decodeObjectForKey:@"width"]; - self.color = [aDecoder decodeObjectForKey:@"color"]; - return self; -} - -- (id)copyWithZone:(NSZone *)zone { - __typeof__(self) one = [self.class new]; - one.style = self.style; - one.width = self.width; - one.color = self.color; - return one; -} - -@end - - -@implementation ASTextBorder - -+ (instancetype)borderWithLineStyle:(ASTextLineStyle)lineStyle lineWidth:(CGFloat)width strokeColor:(UIColor *)color NS_RETURNS_RETAINED { - ASTextBorder *one = [self new]; - one.lineStyle = lineStyle; - one.strokeWidth = width; - one.strokeColor = color; - return one; -} - -+ (instancetype)borderWithFillColor:(UIColor *)color cornerRadius:(CGFloat)cornerRadius NS_RETURNS_RETAINED { - ASTextBorder *one = [self new]; - one.fillColor = color; - one.cornerRadius = cornerRadius; - one.insets = UIEdgeInsetsMake(-2, 0, 0, -2); - return one; -} - -- (instancetype)init { - self = [super init]; - self.lineStyle = ASTextLineStyleSingle; - return self; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder { - [aCoder encodeObject:@(self.lineStyle) forKey:@"lineStyle"]; - [aCoder encodeObject:@(self.strokeWidth) forKey:@"strokeWidth"]; - [aCoder encodeObject:self.strokeColor forKey:@"strokeColor"]; - [aCoder encodeObject:@(self.lineJoin) forKey:@"lineJoin"]; - [aCoder encodeObject:[NSValue valueWithUIEdgeInsets:self.insets] forKey:@"insets"]; - [aCoder encodeObject:@(self.cornerRadius) forKey:@"cornerRadius"]; - [aCoder encodeObject:self.shadow forKey:@"shadow"]; - [aCoder encodeObject:self.fillColor forKey:@"fillColor"]; -} - -- (id)initWithCoder:(NSCoder *)aDecoder { - self = [super init]; - _lineStyle = ((NSNumber *)[aDecoder decodeObjectForKey:@"lineStyle"]).unsignedIntegerValue; - _strokeWidth = ((NSNumber *)[aDecoder decodeObjectForKey:@"strokeWidth"]).doubleValue; - _strokeColor = [aDecoder decodeObjectForKey:@"strokeColor"]; - _lineJoin = (CGLineJoin)((NSNumber *)[aDecoder decodeObjectForKey:@"join"]).unsignedIntegerValue; - _insets = ((NSValue *)[aDecoder decodeObjectForKey:@"insets"]).UIEdgeInsetsValue; - _cornerRadius = ((NSNumber *)[aDecoder decodeObjectForKey:@"cornerRadius"]).doubleValue; - _shadow = [aDecoder decodeObjectForKey:@"shadow"]; - _fillColor = [aDecoder decodeObjectForKey:@"fillColor"]; - return self; -} - -- (id)copyWithZone:(NSZone *)zone { - __typeof__(self) one = [self.class new]; - one.lineStyle = self.lineStyle; - one.strokeWidth = self.strokeWidth; - one.strokeColor = self.strokeColor; - one.lineJoin = self.lineJoin; - one.insets = self.insets; - one.cornerRadius = self.cornerRadius; - one.shadow = self.shadow.copy; - one.fillColor = self.fillColor; - return one; -} - -@end - - -@implementation ASTextAttachment - -+ (instancetype)attachmentWithContent:(id)content NS_RETURNS_RETAINED { - ASTextAttachment *one = [self new]; - one.content = content; - return one; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder { - [aCoder encodeObject:self.content forKey:@"content"]; - [aCoder encodeObject:[NSValue valueWithUIEdgeInsets:self.contentInsets] forKey:@"contentInsets"]; - [aCoder encodeObject:self.userInfo forKey:@"userInfo"]; -} - -- (id)initWithCoder:(NSCoder *)aDecoder { - self = [super init]; - _content = [aDecoder decodeObjectForKey:@"content"]; - _contentInsets = ((NSValue *)[aDecoder decodeObjectForKey:@"contentInsets"]).UIEdgeInsetsValue; - _userInfo = [aDecoder decodeObjectForKey:@"userInfo"]; - return self; -} - -- (id)copyWithZone:(NSZone *)zone { - __typeof__(self) one = [self.class new]; - if ([self.content respondsToSelector:@selector(copy)]) { - one.content = [self.content copy]; - } else { - one.content = self.content; - } - one.contentInsets = self.contentInsets; - one.userInfo = self.userInfo.copy; - return one; -} - -@end - - -@implementation ASTextHighlight - -+ (instancetype)highlightWithAttributes:(NSDictionary *)attributes NS_RETURNS_RETAINED { - ASTextHighlight *one = [self new]; - one.attributes = attributes; - return one; -} - -+ (instancetype)highlightWithBackgroundColor:(UIColor *)color NS_RETURNS_RETAINED { - ASTextBorder *highlightBorder = [ASTextBorder new]; - highlightBorder.insets = UIEdgeInsetsMake(-2, -1, -2, -1); - highlightBorder.cornerRadius = 3; - highlightBorder.fillColor = color; - - ASTextHighlight *one = [self new]; - [one setBackgroundBorder:highlightBorder]; - return one; -} - -- (void)setAttributes:(NSDictionary *)attributes { - _attributes = attributes.mutableCopy; -} - -- (id)copyWithZone:(NSZone *)zone { - __typeof__(self) one = [self.class new]; - one.attributes = self.attributes.mutableCopy; - return one; -} - -- (void)_makeMutableAttributes { - if (!_attributes) { - _attributes = [NSMutableDictionary new]; - } else if (![_attributes isKindOfClass:[NSMutableDictionary class]]) { - _attributes = _attributes.mutableCopy; - } -} - -- (void)setFont:(UIFont *)font { - [self _makeMutableAttributes]; - if (font == (id)[NSNull null] || font == nil) { - ((NSMutableDictionary *)_attributes)[(id)kCTFontAttributeName] = [NSNull null]; - } else { - CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef)font.fontName, font.pointSize, NULL); - if (ctFont) { - ((NSMutableDictionary *)_attributes)[(id)kCTFontAttributeName] = (__bridge id)(ctFont); - CFRelease(ctFont); - } - } -} - -- (void)setColor:(UIColor *)color { - [self _makeMutableAttributes]; - if (color == (id)[NSNull null] || color == nil) { - ((NSMutableDictionary *)_attributes)[(id)kCTForegroundColorAttributeName] = [NSNull null]; - ((NSMutableDictionary *)_attributes)[NSForegroundColorAttributeName] = [NSNull null]; - } else { - ((NSMutableDictionary *)_attributes)[(id)kCTForegroundColorAttributeName] = (__bridge id)(color.CGColor); - ((NSMutableDictionary *)_attributes)[NSForegroundColorAttributeName] = color; - } -} - -- (void)setStrokeWidth:(NSNumber *)width { - [self _makeMutableAttributes]; - if (width == (id)[NSNull null] || width == nil) { - ((NSMutableDictionary *)_attributes)[(id)kCTStrokeWidthAttributeName] = [NSNull null]; - } else { - ((NSMutableDictionary *)_attributes)[(id)kCTStrokeWidthAttributeName] = width; - } -} - -- (void)setStrokeColor:(UIColor *)color { - [self _makeMutableAttributes]; - if (color == (id)[NSNull null] || color == nil) { - ((NSMutableDictionary *)_attributes)[(id)kCTStrokeColorAttributeName] = [NSNull null]; - ((NSMutableDictionary *)_attributes)[NSStrokeColorAttributeName] = [NSNull null]; - } else { - ((NSMutableDictionary *)_attributes)[(id)kCTStrokeColorAttributeName] = (__bridge id)(color.CGColor); - ((NSMutableDictionary *)_attributes)[NSStrokeColorAttributeName] = color; - } -} - -- (void)setTextAttribute:(NSString *)attribute value:(id)value { - [self _makeMutableAttributes]; - if (value == nil) value = [NSNull null]; - ((NSMutableDictionary *)_attributes)[attribute] = value; -} - -- (void)setShadow:(ASTextShadow *)shadow { - [self setTextAttribute:ASTextShadowAttributeName value:shadow]; -} - -- (void)setInnerShadow:(ASTextShadow *)shadow { - [self setTextAttribute:ASTextInnerShadowAttributeName value:shadow]; -} - -- (void)setUnderline:(ASTextDecoration *)underline { - [self setTextAttribute:ASTextUnderlineAttributeName value:underline]; -} - -- (void)setStrikethrough:(ASTextDecoration *)strikethrough { - [self setTextAttribute:ASTextStrikethroughAttributeName value:strikethrough]; -} - -- (void)setBackgroundBorder:(ASTextBorder *)border { - [self setTextAttribute:ASTextBackgroundBorderAttributeName value:border]; -} - -- (void)setBorder:(ASTextBorder *)border { - [self setTextAttribute:ASTextBorderAttributeName value:border]; -} - -- (void)setAttachment:(ASTextAttachment *)attachment { - [self setTextAttribute:ASTextAttachmentAttributeName value:attachment]; -} - -@end - diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextDebugOption.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextDebugOption.h deleted file mode 100644 index efa7808c87..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextDebugOption.h +++ /dev/null @@ -1,92 +0,0 @@ -// -// ASTextDebugOption.h -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -@class ASTextDebugOption; - -NS_ASSUME_NONNULL_BEGIN - -/** - The ASTextDebugTarget protocol defines the method a debug target should implement. - A debug target can be add to the global container to receive the shared debug - option changed notification. - */ -@protocol ASTextDebugTarget - -@required -/** - When the shared debug option changed, this method would be called on main thread. - It should return as quickly as possible. The option's property should not be changed - in this method. - - @param option The shared debug option. - */ -- (void)setDebugOption:(nullable ASTextDebugOption *)option; -@end - - - -/** - The debug option for ASText. - */ -@interface ASTextDebugOption : NSObject -@property (nullable, nonatomic) UIColor *baselineColor; ///< baseline color -@property (nullable, nonatomic) UIColor *CTFrameBorderColor; ///< CTFrame path border color -@property (nullable, nonatomic) UIColor *CTFrameFillColor; ///< CTFrame path fill color -@property (nullable, nonatomic) UIColor *CTLineBorderColor; ///< CTLine bounds border color -@property (nullable, nonatomic) UIColor *CTLineFillColor; ///< CTLine bounds fill color -@property (nullable, nonatomic) UIColor *CTLineNumberColor; ///< CTLine line number color -@property (nullable, nonatomic) UIColor *CTRunBorderColor; ///< CTRun bounds border color -@property (nullable, nonatomic) UIColor *CTRunFillColor; ///< CTRun bounds fill color -@property (nullable, nonatomic) UIColor *CTRunNumberColor; ///< CTRun number color -@property (nullable, nonatomic) UIColor *CGGlyphBorderColor; ///< CGGlyph bounds border color -@property (nullable, nonatomic) UIColor *CGGlyphFillColor; ///< CGGlyph bounds fill color - -- (BOOL)needDrawDebug; ///< `YES`: at least one debug color is visible. `NO`: all debug color is invisible/nil. -- (void)clear; ///< Set all debug color to nil. - -/** - Add a debug target. - - @discussion When `setSharedDebugOption:` is called, all added debug target will - receive `setDebugOption:` in main thread. It maintains an unsafe_unretained - reference to this target. The target must to removed before dealloc. - - @param target A debug target. - */ -+ (void)addDebugTarget:(id)target; - -/** - Remove a debug target which is added by `addDebugTarget:`. - - @param target A debug target. - */ -+ (void)removeDebugTarget:(id)target; - -/** - Returns the shared debug option. - - @return The shared debug option, default is nil. - */ -+ (nullable ASTextDebugOption *)sharedDebugOption; - -/** - Set a debug option as shared debug option. - This method must be called on main thread. - - @discussion When call this method, the new option will set to all debug target - which is added by `addDebugTarget:`. - - @param option A new debug option (nil is valid). - */ -+ (void)setSharedDebugOption:(nullable ASTextDebugOption *)option; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextDebugOption.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextDebugOption.mm deleted file mode 100644 index 9887e1ad74..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextDebugOption.mm +++ /dev/null @@ -1,135 +0,0 @@ -// -// ASTextDebugOption.mm -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -static pthread_mutex_t _sharedDebugLock; -static CFMutableSetRef _sharedDebugTargets = nil; -static ASTextDebugOption *_sharedDebugOption = nil; - -static const void* _as_sharedDebugSetRetain(CFAllocatorRef allocator, const void *value) { - return value; -} - -static void _as_sharedDebugSetRelease(CFAllocatorRef allocator, const void *value) { -} - -void _as_sharedDebugSetFunction(const void *value, void *context) { - id target = (__bridge id)(value); - [target setDebugOption:_sharedDebugOption]; -} - -static void _initSharedDebug() { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - pthread_mutex_init(&_sharedDebugLock, NULL); - CFSetCallBacks callbacks = kCFTypeSetCallBacks; - callbacks.retain = _as_sharedDebugSetRetain; - callbacks.release = _as_sharedDebugSetRelease; - _sharedDebugTargets = CFSetCreateMutable(CFAllocatorGetDefault(), 0, &callbacks); - }); -} - -static void _setSharedDebugOption(ASTextDebugOption *option) { - _initSharedDebug(); - pthread_mutex_lock(&_sharedDebugLock); - _sharedDebugOption = option.copy; - CFSetApplyFunction(_sharedDebugTargets, _as_sharedDebugSetFunction, NULL); - pthread_mutex_unlock(&_sharedDebugLock); -} - -static ASTextDebugOption *_getSharedDebugOption() { - _initSharedDebug(); - pthread_mutex_lock(&_sharedDebugLock); - ASTextDebugOption *op = _sharedDebugOption; - pthread_mutex_unlock(&_sharedDebugLock); - return op; -} - -static void _addDebugTarget(id target) { - _initSharedDebug(); - pthread_mutex_lock(&_sharedDebugLock); - CFSetAddValue(_sharedDebugTargets, (__bridge const void *)(target)); - pthread_mutex_unlock(&_sharedDebugLock); -} - -static void _removeDebugTarget(id target) { - _initSharedDebug(); - pthread_mutex_lock(&_sharedDebugLock); - CFSetRemoveValue(_sharedDebugTargets, (__bridge const void *)(target)); - pthread_mutex_unlock(&_sharedDebugLock); -} - - -@implementation ASTextDebugOption - -- (id)copyWithZone:(NSZone *)zone { - ASTextDebugOption *op = [self.class new]; - op.baselineColor = self.baselineColor; - op.CTFrameBorderColor = self.CTFrameBorderColor; - op.CTFrameFillColor = self.CTFrameFillColor; - op.CTLineBorderColor = self.CTLineBorderColor; - op.CTLineFillColor = self.CTLineFillColor; - op.CTLineNumberColor = self.CTLineNumberColor; - op.CTRunBorderColor = self.CTRunBorderColor; - op.CTRunFillColor = self.CTRunFillColor; - op.CTRunNumberColor = self.CTRunNumberColor; - op.CGGlyphBorderColor = self.CGGlyphBorderColor; - op.CGGlyphFillColor = self.CGGlyphFillColor; - return op; -} - -- (BOOL)needDrawDebug { - if (self.baselineColor || - self.CTFrameBorderColor || - self.CTFrameFillColor || - self.CTLineBorderColor || - self.CTLineFillColor || - self.CTLineNumberColor || - self.CTRunBorderColor || - self.CTRunFillColor || - self.CTRunNumberColor || - self.CGGlyphBorderColor || - self.CGGlyphFillColor) return YES; - return NO; -} - -- (void)clear { - self.baselineColor = nil; - self.CTFrameBorderColor = nil; - self.CTFrameFillColor = nil; - self.CTLineBorderColor = nil; - self.CTLineFillColor = nil; - self.CTLineNumberColor = nil; - self.CTRunBorderColor = nil; - self.CTRunFillColor = nil; - self.CTRunNumberColor = nil; - self.CGGlyphBorderColor = nil; - self.CGGlyphFillColor = nil; -} - -+ (void)addDebugTarget:(id)target { - if (target) _addDebugTarget(target); -} - -+ (void)removeDebugTarget:(id)target { - if (target) _removeDebugTarget(target); -} - -+ (ASTextDebugOption *)sharedDebugOption { - return _getSharedDebugOption(); -} - -+ (void)setSharedDebugOption:(ASTextDebugOption *)option { - NSAssert([NSThread isMainThread], @"This method must be called on the main thread"); - _setSharedDebugOption(option); -} - -@end - diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextInput.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextInput.h deleted file mode 100644 index 9a6cbd13d1..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextInput.h +++ /dev/null @@ -1,85 +0,0 @@ -// -// ASTextInput.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - Text position affinity. For example, the offset appears after the last - character on a line is backward affinity, before the first character on - the following line is forward affinity. - */ -typedef NS_ENUM(NSInteger, ASTextAffinity) { - ASTextAffinityForward = 0, ///< offset appears before the character - ASTextAffinityBackward = 1, ///< offset appears after the character -}; - - -/** - A ASTextPosition object represents a position in a text container; in other words, - it is an index into the backing string in a text-displaying view. - - ASTextPosition has the same API as Apple's implementation in UITextView/UITextField, - so you can alse use it to interact with UITextView/UITextField. - */ -@interface ASTextPosition : UITextPosition - -@property (nonatomic, readonly) NSInteger offset; -@property (nonatomic, readonly) ASTextAffinity affinity; - -+ (instancetype)positionWithOffset:(NSInteger)offset NS_RETURNS_RETAINED; -+ (instancetype)positionWithOffset:(NSInteger)offset affinity:(ASTextAffinity) affinity NS_RETURNS_RETAINED; - -- (NSComparisonResult)compare:(id)otherPosition; - -@end - - -/** - A ASTextRange object represents a range of characters in a text container; in other words, - it identifies a starting index and an ending index in string backing a text-displaying view. - - ASTextRange has the same API as Apple's implementation in UITextView/UITextField, - so you can alse use it to interact with UITextView/UITextField. - */ -@interface ASTextRange : UITextRange - -@property (nonatomic, readonly) ASTextPosition *start; -@property (nonatomic, readonly) ASTextPosition *end; -@property (nonatomic, readonly, getter=isEmpty) BOOL empty; - -+ (instancetype)rangeWithRange:(NSRange)range NS_RETURNS_RETAINED; -+ (instancetype)rangeWithRange:(NSRange)range affinity:(ASTextAffinity) affinity NS_RETURNS_RETAINED; -+ (instancetype)rangeWithStart:(ASTextPosition *)start end:(ASTextPosition *)end NS_RETURNS_RETAINED; -+ (instancetype)defaultRange NS_RETURNS_RETAINED; ///< <{0,0} Forward> - -- (NSRange)asRange; - -@end - - -/** - A ASTextSelectionRect object encapsulates information about a selected range of - text in a text-displaying view. - - ASTextSelectionRect has the same API as Apple's implementation in UITextView/UITextField, - so you can alse use it to interact with UITextView/UITextField. - */ -@interface ASTextSelectionRect : UITextSelectionRect - -@property (nonatomic) CGRect rect; -@property (nonatomic) UITextWritingDirection writingDirection; -@property (nonatomic) BOOL containsStart; -@property (nonatomic) BOOL containsEnd; -@property (nonatomic) BOOL isVertical; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextInput.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextInput.mm deleted file mode 100644 index 1cdfe73858..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextInput.mm +++ /dev/null @@ -1,150 +0,0 @@ -// -// ASTextInput.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - - -@implementation ASTextPosition - -+ (instancetype)positionWithOffset:(NSInteger)offset NS_RETURNS_RETAINED { - return [self positionWithOffset:offset affinity:ASTextAffinityForward]; -} - -+ (instancetype)positionWithOffset:(NSInteger)offset affinity:(ASTextAffinity)affinity NS_RETURNS_RETAINED { - ASTextPosition *p = [self new]; - p->_offset = offset; - p->_affinity = affinity; - return p; -} - -- (instancetype)copyWithZone:(NSZone *)zone { - return [self.class positionWithOffset:_offset affinity:_affinity]; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p> (%@%@)", self.class, self, @(_offset), _affinity == ASTextAffinityForward ? @"F":@"B"]; -} - -- (NSUInteger)hash { - return _offset * 2 + (_affinity == ASTextAffinityForward ? 1 : 0); -} - -- (BOOL)isEqual:(ASTextPosition *)object { - if (!object) return NO; - return _offset == object.offset && _affinity == object.affinity; -} - -- (NSComparisonResult)compare:(ASTextPosition *)otherPosition { - if (!otherPosition) return NSOrderedAscending; - if (_offset < otherPosition.offset) return NSOrderedAscending; - if (_offset > otherPosition.offset) return NSOrderedDescending; - if (_affinity == ASTextAffinityBackward && otherPosition.affinity == ASTextAffinityForward) return NSOrderedAscending; - if (_affinity == ASTextAffinityForward && otherPosition.affinity == ASTextAffinityBackward) return NSOrderedDescending; - return NSOrderedSame; -} - -@end - - - -@implementation ASTextRange { - ASTextPosition *_start; - ASTextPosition *_end; -} - -- (instancetype)init { - self = [super init]; - if (!self) return nil; - _start = [ASTextPosition positionWithOffset:0]; - _end = [ASTextPosition positionWithOffset:0]; - return self; -} - -- (ASTextPosition *)start { - return _start; -} - -- (ASTextPosition *)end { - return _end; -} - -- (BOOL)isEmpty { - return _start.offset == _end.offset; -} - -- (NSRange)asRange { - return NSMakeRange(_start.offset, _end.offset - _start.offset); -} - -+ (instancetype)rangeWithRange:(NSRange)range NS_RETURNS_RETAINED { - return [self rangeWithRange:range affinity:ASTextAffinityForward]; -} - -+ (instancetype)rangeWithRange:(NSRange)range affinity:(ASTextAffinity)affinity NS_RETURNS_RETAINED { - ASTextPosition *start = [ASTextPosition positionWithOffset:range.location affinity:affinity]; - ASTextPosition *end = [ASTextPosition positionWithOffset:range.location + range.length affinity:affinity]; - return [self rangeWithStart:start end:end]; -} - -+ (instancetype)rangeWithStart:(ASTextPosition *)start end:(ASTextPosition *)end NS_RETURNS_RETAINED { - if (!start || !end) return nil; - if ([start compare:end] == NSOrderedDescending) { - ASTEXT_SWAP(start, end); - } - ASTextRange *range = [ASTextRange new]; - range->_start = start; - range->_end = end; - return range; -} - -+ (instancetype)defaultRange NS_RETURNS_RETAINED { - return [self new]; -} - -- (instancetype)copyWithZone:(NSZone *)zone { - return [self.class rangeWithStart:_start end:_end]; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p> (%@, %@)%@", self.class, self, @(_start.offset), @(_end.offset - _start.offset), _end.affinity == ASTextAffinityForward ? @"F":@"B"]; -} - -- (NSUInteger)hash { - return (sizeof(NSUInteger) == 8 ? OSSwapInt64(_start.hash) : OSSwapInt32(_start.hash)) + _end.hash; -} - -- (BOOL)isEqual:(ASTextRange *)object { - if (!object) return NO; - return [_start isEqual:object.start] && [_end isEqual:object.end]; -} - -@end - - - -@implementation ASTextSelectionRect - -@synthesize rect = _rect; -@synthesize writingDirection = _writingDirection; -@synthesize containsStart = _containsStart; -@synthesize containsEnd = _containsEnd; -@synthesize isVertical = _isVertical; - -- (id)copyWithZone:(NSZone *)zone { - ASTextSelectionRect *one = [self.class new]; - one.rect = _rect; - one.writingDirection = _writingDirection; - one.containsStart = _containsStart; - one.containsEnd = _containsEnd; - one.isVertical = _isVertical; - return one; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitAttributes.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitAttributes.h deleted file mode 100644 index d8c21dbc23..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitAttributes.h +++ /dev/null @@ -1,128 +0,0 @@ -// -// ASTextKitAttributes.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#pragma once - -#import - -#import - -#if AS_ENABLE_TEXTNODE - -#import - -AS_EXTERN NSString *const ASTextKitTruncationAttributeName; -/** - Use ASTextKitEntityAttribute as the value of this attribute to embed a link or other interactable content inside the - text. - */ -AS_EXTERN NSString *const ASTextKitEntityAttributeName; - -/** - All NSObject values in this struct should be copied when passed into the TextComponent. - */ -struct ASTextKitAttributes { - /** - The string to be drawn. ASTextKit will not augment this string with default colors, etc. so this must be complete. - */ - NSAttributedString *attributedString; - /** - The string to use as the truncation string, usually just "...". If you have a range of text you would like to - restrict highlighting to (for instance if you have "... Continue Reading", use the ASTextKitTruncationAttributeName - to mark the specific range of the string that should be highlightable. - */ - NSAttributedString *truncationAttributedString; - /** - This is the character set that ASTextKit should attempt to avoid leaving as a trailing character before your - truncation token. By default this set includes "\s\t\n\r.,!?:;" so you don't end up with ugly looking truncation - text like "Hey, this is some fancy Truncation!\n\n...". Instead it would be truncated as "Hey, this is some fancy - truncation...". This is not always possible. - - Set this to the empty charset if you want to just use the "dumb" truncation behavior. A nil value will be - substituted with the default described above. - */ - NSCharacterSet *avoidTailTruncationSet; - /** - The line-break mode to apply to the text. Since this also impacts how TextKit will attempt to truncate the text - in your string, we only support NSLineBreakByWordWrapping and NSLineBreakByCharWrapping. - */ - NSLineBreakMode lineBreakMode; - /** - The maximum number of lines to draw in the drawable region. Leave blank or set to 0 to define no maximum. - This is required to apply scale factors to shrink text to fit within a number of lines - */ - NSUInteger maximumNumberOfLines; - /** - An array of UIBezierPath objects representing the exclusion paths inside the receiver's bounding rectangle. Default value: nil. - */ - NSArray *exclusionPaths; - /** - The shadow offset for any shadows applied to the text. The coordinate space for this is the same as UIKit, so a - positive width means towards the right, and a positive height means towards the bottom. - */ - CGSize shadowOffset; - /** - The color to use in drawing the text's shadow. - */ - UIColor *shadowColor; - /** - The opacity of the shadow from 0 to 1. - */ - CGFloat shadowOpacity; - /** - The radius that should be applied to the shadow blur. Larger values mean a larger, more blurred shadow. - */ - CGFloat shadowRadius; - /** - An array of scale factors in descending order to apply to the text to try to make it fit into a constrained size. - */ - NSArray *pointSizeScaleFactors; - - /** - We provide an explicit copy function so we can use aggregate initializer syntax while providing copy semantics for - the NSObjects inside. - */ - const ASTextKitAttributes copy() const - { - return { - [attributedString copy], - [truncationAttributedString copy], - [avoidTailTruncationSet copy], - lineBreakMode, - maximumNumberOfLines, - [exclusionPaths copy], - shadowOffset, - [shadowColor copy], - shadowOpacity, - shadowRadius, - pointSizeScaleFactors, - }; - }; - - bool operator==(const ASTextKitAttributes &other) const - { - // These comparisons are in a specific order to reduce the overall cost of this function. - return lineBreakMode == other.lineBreakMode - && maximumNumberOfLines == other.maximumNumberOfLines - && shadowOpacity == other.shadowOpacity - && shadowRadius == other.shadowRadius - && (pointSizeScaleFactors == other.pointSizeScaleFactors - || [pointSizeScaleFactors isEqualToArray:other.pointSizeScaleFactors]) - && CGSizeEqualToSize(shadowOffset, other.shadowOffset) - && ASObjectIsEqual(exclusionPaths, other.exclusionPaths) - && ASObjectIsEqual(avoidTailTruncationSet, other.avoidTailTruncationSet) - && ASObjectIsEqual(shadowColor, other.shadowColor) - && ASObjectIsEqual(attributedString, other.attributedString) - && ASObjectIsEqual(truncationAttributedString, other.truncationAttributedString); - } - - size_t hash() const; -}; - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitAttributes.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitAttributes.mm deleted file mode 100644 index 400ef437bb..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitAttributes.mm +++ /dev/null @@ -1,50 +0,0 @@ -// -// ASTextKitAttributes.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#if AS_ENABLE_TEXTNODE - -#import - -NSString *const ASTextKitTruncationAttributeName = @"ck_truncation"; -NSString *const ASTextKitEntityAttributeName = @"ck_entity"; - -size_t ASTextKitAttributes::hash() const -{ -#pragma clang diagnostic push -#pragma clang diagnostic warning "-Wpadded" - struct { - NSUInteger attrStringHash; - NSUInteger truncationStringHash; - NSUInteger avoidTrunactionSetHash; - NSLineBreakMode lineBreakMode; - NSUInteger maximumNumberOfLines; - NSUInteger exclusionPathsHash; - CGSize shadowOffset; - NSUInteger shadowColorHash; - CGFloat shadowOpacity; - CGFloat shadowRadius; -#pragma clang diagnostic pop - } data = { - [attributedString hash], - [truncationAttributedString hash], - [avoidTailTruncationSet hash], - lineBreakMode, - maximumNumberOfLines, - [exclusionPaths hash], - shadowOffset, - [shadowColor hash], - shadowOpacity, - shadowRadius, - }; - return ASHashBytes(&data, sizeof(data)); -} - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitCoreTextAdditions.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitCoreTextAdditions.h deleted file mode 100644 index 9a8f48050a..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitCoreTextAdditions.h +++ /dev/null @@ -1,89 +0,0 @@ -// -// ASTextKitCoreTextAdditions.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#import - -#if AS_ENABLE_TEXTNODE - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - @abstract Returns whether a given attribute is an unsupported Core Text attribute. - @param attributeName The name of the attribute - @discussion The following Core Text attributes are not supported on NSAttributedString, and thus will not be preserved during the conversion: - - kCTForegroundColorFromContextAttributeName - - kCTSuperscriptAttributeName - - kCTGlyphInfoAttributeName - - kCTCharacterShapeAttributeName - - kCTLanguageAttributeName - - kCTRunDelegateAttributeName - - kCTBaselineClassAttributeName - - kCTBaselineInfoAttributeName - - kCTBaselineReferenceInfoAttributeName - - kCTWritingDirectionAttributeName - - kCTUnderlineColorAttributeName - @result Whether attributeName is an unsupported Core Text attribute. - */ -AS_EXTERN BOOL ASAttributeWithNameIsUnsupportedCoreTextAttribute(NSString *attributeName); - - -/** - @abstract Returns an attributes dictionary for use by NSAttributedString, given a dictionary of Core Text attributes. - @param coreTextAttributes An NSDictionary whose keys are CFAttributedStringRef attributes. - @discussion The following Core Text attributes are not supported on NSAttributedString, and thus will not be preserved during the conversion: - - kCTForegroundColorFromContextAttributeName - - kCTSuperscriptAttributeName - - kCTGlyphInfoAttributeName - - kCTCharacterShapeAttributeName - - kCTLanguageAttributeName - - kCTRunDelegateAttributeName - - kCTBaselineClassAttributeName - - kCTBaselineInfoAttributeName - - kCTBaselineReferenceInfoAttributeName - - kCTWritingDirectionAttributeName - - kCTUnderlineColorAttributeName - @result An NSDictionary of attributes for use by NSAttributedString. - */ -AS_EXTERN NSDictionary *NSAttributedStringAttributesForCoreTextAttributes(NSDictionary *coreTextAttributes); - -/** - @abstract Returns an NSAttributedString whose Core Text attributes have been converted, where possible, to NSAttributedString attributes. - @param dirtyAttributedString An NSAttributedString that may contain Core Text attributes. - @result An NSAttributedString that's preserved as many CFAttributedString attributes as possible. - */ -AS_EXTERN NSAttributedString *ASCleanseAttributedStringOfCoreTextAttributes(NSAttributedString *dirtyAttributedString); - -#pragma mark - -#pragma mark - -@interface NSParagraphStyle (ASTextKitCoreTextAdditions) - -/** - @abstract Returns an NSParagraphStyle initialized with the paragraph specifiers from the given CTParagraphStyleRef. - @param coreTextParagraphStyle A Core Text paragraph style. - @discussion It is important to note that not all CTParagraphStyle specifiers are supported by NSParagraphStyle, and consequently, this is a lossy conversion. Notably, the following specifiers will not preserved: - - kCTParagraphStyleSpecifierTabStops - - kCTParagraphStyleSpecifierDefaultTabInterval - - kCTParagraphStyleSpecifierMaximumLineSpacing - - kCTParagraphStyleSpecifierMinimumLineSpacing - - kCTParagraphStyleSpecifierLineSpacingAdjustment - - kCTParagraphStyleSpecifierLineBoundsOptions - @result An NSParagraphStyle initialized with as many of the paragraph specifiers from `coreTextParagraphStyle` as possible. - - */ -+ (NSParagraphStyle *)paragraphStyleWithCTParagraphStyle:(CTParagraphStyleRef)coreTextParagraphStyle NS_RETURNS_RETAINED; - -@end - -NS_ASSUME_NONNULL_END - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitCoreTextAdditions.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitCoreTextAdditions.mm deleted file mode 100644 index 8ae370de14..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitCoreTextAdditions.mm +++ /dev/null @@ -1,331 +0,0 @@ -// -// ASTextKitCoreTextAdditions.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#if AS_ENABLE_TEXTNODE - -#import -#import - -#import - -#pragma mark - Public -BOOL ASAttributeWithNameIsUnsupportedCoreTextAttribute(NSString *attributeName) -{ - static NSSet *coreTextAttributes; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - coreTextAttributes = [NSSet setWithObjects:(__bridge id)kCTForegroundColorAttributeName, - kCTForegroundColorFromContextAttributeName, - kCTForegroundColorAttributeName, - kCTStrokeColorAttributeName, - kCTUnderlineStyleAttributeName, - kCTVerticalFormsAttributeName, - kCTRunDelegateAttributeName, - kCTBaselineClassAttributeName, - kCTBaselineInfoAttributeName, - kCTBaselineReferenceInfoAttributeName, - kCTUnderlineColorAttributeName, - kCTParagraphStyleAttributeName, - nil]; - }); - return [coreTextAttributes containsObject:attributeName]; -} - -NSDictionary *NSAttributedStringAttributesForCoreTextAttributes(NSDictionary *coreTextAttributes) -{ - NSMutableDictionary *cleanAttributes = [[NSMutableDictionary alloc] initWithCapacity:coreTextAttributes.count]; - - [coreTextAttributes enumerateKeysAndObjectsUsingBlock:^(NSString *coreTextKey, id coreTextValue, BOOL *stop) { - // The following attributes are not supported on NSAttributedString. Should they become available, we should add them. - /* - kCTForegroundColorFromContextAttributeName - kCTSuperscriptAttributeName - kCTGlyphInfoAttributeName - kCTCharacterShapeAttributeName - kCTLanguageAttributeName - kCTRunDelegateAttributeName - kCTBaselineClassAttributeName - kCTBaselineInfoAttributeName - kCTBaselineReferenceInfoAttributeName - kCTWritingDirectionAttributeName - kCTUnderlineColorAttributeName - */ - - // Conversely, the following attributes are not supported on CFAttributedString. Should they become available, we should add them. - /* - NSStrikethroughStyleAttributeName - NSShadowAttributeName - NSBackgroundColorAttributeName - */ - - // kCTFontAttributeName -> NSFontAttributeName - if ([coreTextKey isEqualToString:(NSString *)kCTFontAttributeName]) { - CTFontRef coreTextFont = (__bridge CTFontRef)coreTextValue; - cleanAttributes[NSFontAttributeName] = (__bridge UIFont *)coreTextFont; - } - // kCTKernAttributeName -> NSKernAttributeName - else if ([coreTextKey isEqualToString:(NSString *)kCTKernAttributeName]) { - cleanAttributes[NSKernAttributeName] = (NSNumber *)coreTextValue; - } - // kCTLigatureAttributeName -> NSLigatureAttributeName - else if ([coreTextKey isEqualToString:(NSString *)kCTLigatureAttributeName]) { - cleanAttributes[NSLigatureAttributeName] = (NSNumber *)coreTextValue; - } - // kCTForegroundColorAttributeName -> NSForegroundColorAttributeName - else if ([coreTextKey isEqualToString:(NSString *)kCTForegroundColorAttributeName]) { - cleanAttributes[NSForegroundColorAttributeName] = [UIColor colorWithCGColor:(CGColorRef)coreTextValue]; - } - // kCTParagraphStyleAttributeName -> NSParagraphStyleAttributeName - else if ([coreTextKey isEqualToString:(NSString *)kCTParagraphStyleAttributeName]) { - if ([coreTextValue isKindOfClass:[NSParagraphStyle class]]) { - cleanAttributes[NSParagraphStyleAttributeName] = (NSParagraphStyle *)coreTextValue; - } - else { - cleanAttributes[NSParagraphStyleAttributeName] = [NSParagraphStyle paragraphStyleWithCTParagraphStyle:(CTParagraphStyleRef)coreTextValue]; - } - } - // kCTStrokeWidthAttributeName -> NSStrokeWidthAttributeName - else if ([coreTextKey isEqualToString:(NSString *)kCTStrokeWidthAttributeName]) { - cleanAttributes[NSStrokeWidthAttributeName] = (NSNumber *)coreTextValue; - } - // kCTStrokeColorAttributeName -> NSStrokeColorAttributeName - else if ([coreTextKey isEqualToString:(NSString *)kCTStrokeColorAttributeName]) { - cleanAttributes[NSStrokeColorAttributeName] = [UIColor colorWithCGColor:(CGColorRef)coreTextValue]; - } - // kCTUnderlineStyleAttributeName -> NSUnderlineStyleAttributeName - else if ([coreTextKey isEqualToString:(NSString *)kCTUnderlineStyleAttributeName]) { - cleanAttributes[NSUnderlineStyleAttributeName] = (NSNumber *)coreTextValue; - } - // kCTVerticalFormsAttributeName -> NSVerticalGlyphFormAttributeName - else if ([coreTextKey isEqualToString:(NSString *)kCTVerticalFormsAttributeName]) { - BOOL flag = (BOOL)CFBooleanGetValue((CFBooleanRef)coreTextValue); - cleanAttributes[NSVerticalGlyphFormAttributeName] = @((int)flag); // NSVerticalGlyphFormAttributeName is documented to be an NSNumber with an integer that's either 0 or 1. - } - // Don't filter out any internal text attributes - else if (!ASAttributeWithNameIsUnsupportedCoreTextAttribute(coreTextKey)){ - cleanAttributes[coreTextKey] = coreTextValue; - } - }]; - - return cleanAttributes; -} - -NSAttributedString *ASCleanseAttributedStringOfCoreTextAttributes(NSAttributedString *dirtyAttributedString) -{ - if (!dirtyAttributedString) - return nil; - - // First see if there are any core text attributes on the string - __block BOOL containsCoreTextAttributes = NO; - [dirtyAttributedString enumerateAttributesInRange:NSMakeRange(0, dirtyAttributedString.length) - options:0 - usingBlock:^(NSDictionary *dirtyAttributes, NSRange range, BOOL *stop) { - [dirtyAttributes enumerateKeysAndObjectsUsingBlock:^(NSString *coreTextKey, id coreTextValue, BOOL *innerStop) { - if (ASAttributeWithNameIsUnsupportedCoreTextAttribute(coreTextKey)) { - containsCoreTextAttributes = YES; - *innerStop = YES; - } - }]; - *stop = containsCoreTextAttributes; - }]; - if (containsCoreTextAttributes) { - - NSString *plainString = dirtyAttributedString.string; - NSMutableAttributedString *cleanAttributedString = [[NSMutableAttributedString alloc] initWithString:plainString]; - - // Iterate over all of the attributes, cleaning them as appropriate and applying them as we go. - [dirtyAttributedString enumerateAttributesInRange:NSMakeRange(0, plainString.length) - options:0 - usingBlock:^(NSDictionary *dirtyAttributes, NSRange range, BOOL *stop) { - [cleanAttributedString addAttributes:NSAttributedStringAttributesForCoreTextAttributes(dirtyAttributes) range:range]; - }]; - - return cleanAttributedString; - } else { - return [dirtyAttributedString copy]; - } -} - -#pragma mark - -#pragma mark - -@implementation NSParagraphStyle (ASTextKitCoreTextAdditions) - -+ (NSParagraphStyle *)paragraphStyleWithCTParagraphStyle:(CTParagraphStyleRef)coreTextParagraphStyle NS_RETURNS_RETAINED -{ - NSMutableParagraphStyle *newParagraphStyle = [[NSMutableParagraphStyle alloc] init]; - - if (!coreTextParagraphStyle) { - return newParagraphStyle; - } - - // The following paragraph style specifiers are not supported on NSParagraphStyle. Should they become available, we should add them. - /* - kCTParagraphStyleSpecifierTabStops - kCTParagraphStyleSpecifierDefaultTabInterval - kCTParagraphStyleSpecifierMaximumLineSpacing - kCTParagraphStyleSpecifierMinimumLineSpacing - kCTParagraphStyleSpecifierLineSpacingAdjustment - kCTParagraphStyleSpecifierLineBoundsOptions - */ - - // Conversely, the following paragraph styles are not supported on CTParagraphStyle. Should they become available, we should add them. - /* - hyphenationFactor - */ - - // kCTParagraphStyleSpecifierAlignment -> alignment - CTTextAlignment coreTextAlignment; - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierAlignment, - sizeof(coreTextAlignment), - &coreTextAlignment)) { - newParagraphStyle.alignment = NSTextAlignmentFromCTTextAlignment(coreTextAlignment); - } - - // kCTParagraphStyleSpecifierFirstLineHeadIndent -> firstLineHeadIndent - CGFloat firstLineHeadIndent; - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierFirstLineHeadIndent, - sizeof(firstLineHeadIndent), - &firstLineHeadIndent)) { - newParagraphStyle.firstLineHeadIndent = firstLineHeadIndent; - } - - // kCTParagraphStyleSpecifierHeadIndent -> headIndent - CGFloat headIndent; - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierHeadIndent, - sizeof(headIndent), - &headIndent)) { - newParagraphStyle.headIndent = headIndent; - } - - // kCTParagraphStyleSpecifierTailIndent -> tailIndent - CGFloat tailIndent; - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierTailIndent, - sizeof(tailIndent), - &tailIndent)) { - newParagraphStyle.tailIndent = tailIndent; - } - - // kCTParagraphStyleSpecifierLineBreakMode -> lineBreakMode - CTLineBreakMode coreTextLineBreakMode; - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierLineBreakMode, - sizeof(coreTextLineBreakMode), - &coreTextLineBreakMode)) { - newParagraphStyle.lineBreakMode = (NSLineBreakMode)coreTextLineBreakMode; // They're the same enum. - } - - // kCTParagraphStyleSpecifierLineHeightMultiple -> lineHeightMultiple - CGFloat lineHeightMultiple; - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierLineHeightMultiple, - sizeof(lineHeightMultiple), - &lineHeightMultiple)) { - newParagraphStyle.lineHeightMultiple = lineHeightMultiple; - } - - // kCTParagraphStyleSpecifierMaximumLineHeight -> maximumLineHeight - CGFloat maximumLineHeight; - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierMaximumLineHeight, - sizeof(maximumLineHeight), - &maximumLineHeight)) { - newParagraphStyle.maximumLineHeight = maximumLineHeight; - } - - // kCTParagraphStyleSpecifierMinimumLineHeight -> minimumLineHeight - CGFloat minimumLineHeight; - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierMinimumLineHeight, - sizeof(minimumLineHeight), - &minimumLineHeight)) { - newParagraphStyle.minimumLineHeight = minimumLineHeight; - } - - CGFloat lineSpacing = 0; -#if TARGET_OS_IOS -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - // kCTParagraphStyleSpecifierLineSpacing -> lineSpacing - // Note that kCTParagraphStyleSpecifierLineSpacing is deprecated and will die soon. We should not be using it. - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierLineSpacing, - sizeof(lineSpacing), - &lineSpacing)) { - newParagraphStyle.lineSpacing = lineSpacing; - } -#pragma clang diagnostic pop -#endif - - // Attempt to weakly map the following onto -[NSParagraphStyle lineSpacing]: - // - kCTParagraphStyleSpecifierMinimumLineSpacing - // - kCTParagraphStyleSpecifierMaximumLineSpacing - // - kCTParagraphStyleSpecifierLineSpacingAdjustment - if (fabs(lineSpacing) <= FLT_EPSILON && - CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierMinimumLineSpacing, - sizeof(lineSpacing), - &lineSpacing)) { - newParagraphStyle.lineSpacing = lineSpacing; - } - - if (fabs(lineSpacing) <= FLT_EPSILON && - CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierMaximumLineSpacing, - sizeof(lineSpacing), - &lineSpacing)) { - newParagraphStyle.lineSpacing = lineSpacing; - } - - if (fabs(lineSpacing) <= FLT_EPSILON && - CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierLineSpacingAdjustment, - sizeof(lineSpacing), - &lineSpacing)) { - newParagraphStyle.lineSpacing = lineSpacing; - } - - // kCTParagraphStyleSpecifierParagraphSpacing -> paragraphSpacing - CGFloat paragraphSpacing; - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierParagraphSpacing, - sizeof(paragraphSpacing), - ¶graphSpacing)) { - newParagraphStyle.paragraphSpacing = paragraphSpacing; - } - - // kCTParagraphStyleSpecifierParagraphSpacingBefore -> paragraphSpacingBefore - CGFloat paragraphSpacingBefore; - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierParagraphSpacingBefore, - sizeof(paragraphSpacingBefore), - ¶graphSpacingBefore)) { - newParagraphStyle.paragraphSpacingBefore = paragraphSpacingBefore; - } - - // kCTParagraphStyleSpecifierBaseWritingDirection -> baseWritingDirection - CTWritingDirection coreTextBaseWritingDirection; - if (CTParagraphStyleGetValueForSpecifier(coreTextParagraphStyle, - kCTParagraphStyleSpecifierBaseWritingDirection, - sizeof(coreTextBaseWritingDirection), - &coreTextBaseWritingDirection)) { - newParagraphStyle.baseWritingDirection = (NSWritingDirection)coreTextBaseWritingDirection; // They're the same enum. - } - - return newParagraphStyle; -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitEntityAttribute.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitEntityAttribute.h deleted file mode 100644 index 3655138be7..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitEntityAttribute.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// ASTextKitEntityAttribute.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#import - -#if AS_ENABLE_TEXTNODE - -#import - -/** - The object that should be embedded with ASTextKitEntityAttributeName. Please note that the entity you provide MUST - implement a proper hash and isEqual function or your application performance will grind to a halt due to - NSMutableAttributedString's usage of a global hash table of all attributes. This means the entity should NOT be a - Foundation Collection (NSArray, NSDictionary, NSSet, etc.) since their hash function is a simple count of the values - in the collection, which causes pathological performance problems deep inside NSAttributedString's implementation. - - rdar://19352367 - */ -AS_SUBCLASSING_RESTRICTED -@interface ASTextKitEntityAttribute : NSObject - -@property (nonatomic, readonly) id entity; - -- (instancetype)initWithEntity:(id)entity; - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitEntityAttribute.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitEntityAttribute.mm deleted file mode 100644 index fb87e9bd3a..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitEntityAttribute.mm +++ /dev/null @@ -1,43 +0,0 @@ -// -// ASTextKitEntityAttribute.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#if AS_ENABLE_TEXTNODE - -@implementation ASTextKitEntityAttribute - -- (instancetype)initWithEntity:(id)entity -{ - if (self = [super init]) { - _entity = entity; - } - return self; -} - -- (NSUInteger)hash -{ - return [_entity hash]; -} - -- (BOOL)isEqual:(id)object -{ - if (self == object) { - return YES; - } - if (![object isKindOfClass:[self class]]) { - return NO; - } - ASTextKitEntityAttribute *other = (ASTextKitEntityAttribute *)object; - return _entity == other.entity || [_entity isEqual:other.entity]; -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitFontSizeAdjuster.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitFontSizeAdjuster.h deleted file mode 100644 index 1b7b10ff5f..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitFontSizeAdjuster.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// ASTextKitFontSizeAdjuster.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#import - -#if AS_ENABLE_TEXTNODE - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class ASTextKitContext; - -AS_SUBCLASSING_RESTRICTED -@interface ASTextKitFontSizeAdjuster : NSObject - -@property (nonatomic) CGSize constrainedSize; - -/** - * Creates a class that will return a scale factor the will make a string fit inside the constrained size. - * - * "Fitting" means that both the longest word in the string will fit without breaking in the constrained - * size's width AND that the entire string will try to fit within attribute's maximumLineCount. The amount - * that the string will scale is based upon the attribute's pointSizeScaleFactors. If the string cannot fit - * in the given width/number of lines, the smallest scale factor will be returned. - * - * @param context The text kit context - * @param constrainedSize The constrained size to render into - * @param textComponentAttributes The renderer's text attributes - */ -- (instancetype)initWithContext:(ASTextKitContext *)context - constrainedSize:(CGSize)constrainedSize - textKitAttributes:(const ASTextKitAttributes &)textComponentAttributes; - -/** - * Returns the best fit scale factor for the text - */ -- (CGFloat)scaleFactor; - -/** - * Takes all of the attributed string attributes dealing with size (font size, line spacing, kerning, etc) and - * scales them by the scaleFactor. I wouldn't be surprised if I missed some in here. - */ -+ (void)adjustFontSizeForAttributeString:(NSMutableAttributedString *)attrString withScaleFactor:(CGFloat)scaleFactor; - -@end - -NS_ASSUME_NONNULL_END - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitFontSizeAdjuster.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitFontSizeAdjuster.mm deleted file mode 100644 index aeea44d7cc..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitFontSizeAdjuster.mm +++ /dev/null @@ -1,241 +0,0 @@ -// -// ASTextKitFontSizeAdjuster.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - - -#import - -#if AS_ENABLE_TEXTNODE - -#import -#import - -#import -#import -#import - -//#define LOG(...) NSLog(__VA_ARGS__) -#define LOG(...) - -@interface ASTextKitFontSizeAdjuster() -@property (nonatomic, readonly) NSLayoutManager *sizingLayoutManager; -@property (nonatomic, readonly) NSTextContainer *sizingTextContainer; -@end - -@implementation ASTextKitFontSizeAdjuster -{ - __weak ASTextKitContext *_context; - ASTextKitAttributes _attributes; - BOOL _measured; - CGFloat _scaleFactor; - AS::Mutex __instanceLock__; -} - -@synthesize sizingLayoutManager = _sizingLayoutManager; -@synthesize sizingTextContainer = _sizingTextContainer; - -- (instancetype)initWithContext:(ASTextKitContext *)context - constrainedSize:(CGSize)constrainedSize - textKitAttributes:(const ASTextKitAttributes &)textComponentAttributes; -{ - if (self = [super init]) { - _context = context; - _constrainedSize = constrainedSize; - _attributes = textComponentAttributes; - } - return self; -} - -+ (void)adjustFontSizeForAttributeString:(NSMutableAttributedString *)attrString withScaleFactor:(CGFloat)scaleFactor -{ - if (scaleFactor == 1.0) return; - - [attrString beginEditing]; - - // scale all the attributes that will change the bounding box - [attrString enumerateAttributesInRange:NSMakeRange(0, attrString.length) options:0 usingBlock:^(NSDictionary * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) { - if (attrs[NSFontAttributeName] != nil) { - UIFont *font = attrs[NSFontAttributeName]; - font = [font fontWithSize:std::round(font.pointSize * scaleFactor)]; - [attrString removeAttribute:NSFontAttributeName range:range]; - [attrString addAttribute:NSFontAttributeName value:font range:range]; - } - - if (attrs[NSKernAttributeName] != nil) { - NSNumber *kerning = attrs[NSKernAttributeName]; - [attrString removeAttribute:NSKernAttributeName range:range]; - [attrString addAttribute:NSKernAttributeName value:@([kerning floatValue] * scaleFactor) range:range]; - } - - if (attrs[NSParagraphStyleAttributeName] != nil) { - NSMutableParagraphStyle *paragraphStyle = [attrs[NSParagraphStyleAttributeName] mutableCopy]; - paragraphStyle.lineSpacing = (paragraphStyle.lineSpacing * scaleFactor); - paragraphStyle.paragraphSpacing = (paragraphStyle.paragraphSpacing * scaleFactor); - paragraphStyle.firstLineHeadIndent = (paragraphStyle.firstLineHeadIndent * scaleFactor); - paragraphStyle.headIndent = (paragraphStyle.headIndent * scaleFactor); - paragraphStyle.tailIndent = (paragraphStyle.tailIndent * scaleFactor); - paragraphStyle.minimumLineHeight = (paragraphStyle.minimumLineHeight * scaleFactor); - paragraphStyle.maximumLineHeight = (paragraphStyle.maximumLineHeight * scaleFactor); - - [attrString removeAttribute:NSParagraphStyleAttributeName range:range]; - [attrString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range]; - } - - }]; - - [attrString endEditing]; -} - -- (NSUInteger)lineCountForString:(NSAttributedString *)attributedString -{ - NSUInteger lineCount = 0; - - NSLayoutManager *sizingLayoutManager = [self sizingLayoutManager]; - NSTextContainer *sizingTextContainer = [self sizingTextContainer]; - - NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString]; - [textStorage addLayoutManager:sizingLayoutManager]; - - [sizingLayoutManager ensureLayoutForTextContainer:sizingTextContainer]; - for (NSRange lineRange = { 0, 0 }; NSMaxRange(lineRange) < [sizingLayoutManager numberOfGlyphs] && lineCount <= _attributes.maximumNumberOfLines; lineCount++) { - [sizingLayoutManager lineFragmentRectForGlyphAtIndex:NSMaxRange(lineRange) effectiveRange:&lineRange]; - } - - [textStorage removeLayoutManager:sizingLayoutManager]; - return lineCount; -} - -- (CGSize)boundingBoxForString:(NSAttributedString *)attributedString -{ - NSLayoutManager *sizingLayoutManager = [self sizingLayoutManager]; - NSTextContainer *sizingTextContainer = [self sizingTextContainer]; - - NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString]; - [textStorage addLayoutManager:sizingLayoutManager]; - - [sizingLayoutManager ensureLayoutForTextContainer:sizingTextContainer]; - CGRect textRect = [sizingLayoutManager boundingRectForGlyphRange:NSMakeRange(0, [textStorage length]) - inTextContainer:sizingTextContainer]; - [textStorage removeLayoutManager:sizingLayoutManager]; - return textRect.size; -} - -- (NSLayoutManager *)sizingLayoutManager -{ - AS::MutexLocker l(__instanceLock__); - if (_sizingLayoutManager == nil) { - _sizingLayoutManager = [[ASLayoutManager alloc] init]; - _sizingLayoutManager.usesFontLeading = NO; - - if (_sizingTextContainer == nil) { - // make this text container unbounded in height so that the layout manager will compute the total - // number of lines and not stop counting when height runs out. - _sizingTextContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(_constrainedSize.width, CGFLOAT_MAX)]; - _sizingTextContainer.lineFragmentPadding = 0; - - // use 0 regardless of what is in the attributes so that we get an accurate line count - _sizingTextContainer.maximumNumberOfLines = 0; - - _sizingTextContainer.lineBreakMode = _attributes.lineBreakMode; - _sizingTextContainer.exclusionPaths = _attributes.exclusionPaths; - } - [_sizingLayoutManager addTextContainer:_sizingTextContainer]; - } - - return _sizingLayoutManager; -} - -- (CGFloat)scaleFactor -{ - if (_measured) { - return _scaleFactor; - } - - if ([_attributes.pointSizeScaleFactors count] == 0 || isinf(_constrainedSize.width)) { - _measured = YES; - _scaleFactor = 1.0; - return _scaleFactor; - } - - __block CGFloat adjustedScale = 1.0; - - // We add the scale factor of 1 to our scaleFactors array so that in the first iteration of the loop below, we are - // actually determining if we need to scale at all. If something doesn't fit, we will continue to iterate our scale factors. - NSArray *scaleFactors = [@[@(1)] arrayByAddingObjectsFromArray:_attributes.pointSizeScaleFactors]; - - [_context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - - // Check for two different situations (and correct for both) - // 1. The longest word in the string fits without being wrapped - // 2. The entire text fits in the given constrained size. - - NSString *str = textStorage.string; - NSArray *words = [str componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; - NSString *longestWordNeedingResize = @""; - for (NSString *word in words) { - if ([word length] > [longestWordNeedingResize length]) { - longestWordNeedingResize = word; - } - } - - // check to see if we may need to shrink for any of these things - BOOL longestWordFits = [longestWordNeedingResize length] ? NO : YES; - BOOL maxLinesFits = self->_attributes.maximumNumberOfLines > 0 ? NO : YES; - BOOL heightFits = isinf(self->_constrainedSize.height) ? YES : NO; - - CGSize longestWordSize = CGSizeZero; - if (longestWordFits == NO) { - NSRange longestWordRange = [str rangeOfString:longestWordNeedingResize]; - NSAttributedString *attrString = [textStorage attributedSubstringFromRange:longestWordRange]; - longestWordSize = [attrString boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size; - } - - // we may need to shrink for some reason, so let's iterate through our scale factors to see if we actually need to shrink - // Note: the first scale factor in the array is 1.0 so will make sure that things don't fit without shrinking - for (NSNumber *adjustedScaleObj in scaleFactors) { - if (longestWordFits && maxLinesFits && heightFits) { - break; - } - - adjustedScale = [adjustedScaleObj floatValue]; - - if (longestWordFits == NO) { - // we need to check the longest word to make sure it fits - longestWordFits = std::ceil((longestWordSize.width * adjustedScale) <= self->_constrainedSize.width); - } - - // if the longest word fits, go ahead and check max line and height. If it didn't fit continue to the next scale factor - if (longestWordFits == YES) { - - // scale our string by the current scale factor - NSMutableAttributedString *scaledString = [[NSMutableAttributedString alloc] initWithAttributedString:textStorage]; - [[self class] adjustFontSizeForAttributeString:scaledString withScaleFactor:adjustedScale]; - - // check to see if this scaled string fit in the max lines - if (maxLinesFits == NO) { - maxLinesFits = ([self lineCountForString:scaledString] <= self->_attributes.maximumNumberOfLines); - } - - // if max lines still doesn't fit, continue without checking that we fit in the constrained height - if (maxLinesFits == YES && heightFits == NO) { - // max lines fit so make sure that we fit in the constrained height. - CGSize stringSize = [self boundingBoxForString:scaledString]; - heightFits = (stringSize.height <= self->_constrainedSize.height); - } - } - } - - }]; - _measured = YES; - _scaleFactor = adjustedScale; - return _scaleFactor; -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+Positioning.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+Positioning.h deleted file mode 100644 index c887282568..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+Positioning.h +++ /dev/null @@ -1,106 +0,0 @@ -// -// ASTextKitRenderer+Positioning.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#if AS_ENABLE_TEXTNODE - -typedef void (^as_text_component_index_block_t)(NSUInteger characterIndex, - CGRect glyphBoundingRect, - BOOL *stop); - -/** - Measure options are used to specify which type of line height measurement to use. - - ASTextNodeRendererMeasureOptionLineHeight is faster and will give the height from the baseline to the next line. - - ASTextNodeRendererMeasureOptionCapHeight is a more nuanced measure of the glyphs in the given range that attempts to - produce a visually balanced rectangle above and below the glyphs to produce nice looking text highlights. - - ASTextNodeRendererMeasureOptionBlock uses the cap height option to generate each glyph index, but combines all but the - first and last line rect into a single block. Looks nice for multiline selection. - */ -typedef NS_ENUM(NSUInteger, ASTextKitRendererMeasureOption) { - ASTextKitRendererMeasureOptionLineHeight, - ASTextKitRendererMeasureOptionCapHeight, - ASTextKitRendererMeasureOptionBlock -}; - -@interface ASTextKitRenderer (Positioning) - -/** - Returns the bounding rect for the given character range. - - @param textRange The character range for which the bounding rect will be computed. Should be within the range of the - attributedString of this renderer. - - @discussion In the external, shadowed coordinate space. - */ -- (CGRect)frameForTextRange:(NSRange)textRange; - -/** - Returns an array of rects representing the lines in the given character range - - @param textRange The character range for which the rects will be computed. Should be within the range of the - attributedString of this renderer. - @param measureOption The measure option to use for construction of the rects. See ASTextKitRendererMeasureOption - docs for usage. - - @discussion This method is useful for providing highlighting text. Returned rects are in the coordinate space of the - renderer. - - Triggers initialization of textkit components, truncation, and sizing. - */ -- (NSArray *)rectsForTextRange:(NSRange)textRange - measureOption:(ASTextKitRendererMeasureOption)measureOption; - -/** - Enumerate the text character indexes at a position within the coordinate space of the renderer. - - @param position The point in the shadowed coordinate space at which text indexes will be enumerated. - @param block The block that will be executed for each index identified that may correspond to the given position. The - block is given the character index that corresponds to the glyph at each index in question, as well as the bounding - rect for that glyph. - - @discussion Glyph location based on a touch point is not an exact science because user touches are not well-represented - by a simple point, especially in the context of link-heavy text. So we have this method to make it a bit easier. This - method checks a grid of candidate positions around the touch point you give it, and computes the bounding rect of the - glyph corresponding to the character index given. - - The bounding rect of the glyph can be used to identify the best glyph index that corresponds to your touch. For - instance, comparing centroidal distance from the glyph bounding rect to the touch center is useful for identifying - which link a user actually intended to select. - - Triggers initialization of textkit components, truncation, and sizing. - */ -- (void)enumerateTextIndexesAtPosition:(CGPoint)position - usingBlock:(as_text_component_index_block_t)block; - -/** - Returns the single text index whose glyph's centroid is closest to the given position. - - @param position The point in the shadowed coordinate space that should be checked. - - @discussion This will use the grid enumeration function above, `enumerateTextIndexesAtPosition...`, in order to find - the closest glyph, so it is possible that a glyph could be missed, but ultimately unlikely. - */ -- (NSUInteger)nearestTextIndexAtPosition:(CGPoint)position; - -/** - Returns the trailing rect unused by the renderer in the last rendered line. - - @discussion In the external shadowed coordinate space. - - Triggers initialization of textkit components, truncation, and sizing. - */ -- (CGRect)trailingRect; - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+Positioning.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+Positioning.mm deleted file mode 100644 index 9dc770e1d9..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+Positioning.mm +++ /dev/null @@ -1,386 +0,0 @@ -// -// ASTextKitRenderer+Positioning.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#if AS_ENABLE_TEXTNODE - -#import -#import - -#import - -#import -#import - -static const CGFloat ASTextKitRendererGlyphTouchHitSlop = 5.0; -static const CGFloat ASTextKitRendererTextCapHeightPadding = 1.3; - -@implementation ASTextKitRenderer (Tracking) - -- (NSArray *)rectsForTextRange:(NSRange)textRange measureOption:(ASTextKitRendererMeasureOption)measureOption -{ - __block NSArray *textRects = nil; - [self.context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - textRects = [self unlockedRectsForTextRange:textRange measureOptions:measureOption layoutManager:layoutManager textStorage:textStorage textContainer:textContainer]; - }]; - return textRects; -} - -/** - Helper function that should be called within performBlockWithLockedTextKitComponents: in an already locked state to - prevent a deadlock - */ -- (NSArray *)unlockedRectsForTextRange:(NSRange)textRange measureOptions:(ASTextKitRendererMeasureOption)measureOption layoutManager:(NSLayoutManager *)layoutManager textStorage:(NSTextStorage *)textStorage textContainer:(NSTextContainer *)textContainer -{ - NSRange clampedRange = NSIntersectionRange(textRange, NSMakeRange(0, [textStorage length])); - if (clampedRange.location == NSNotFound || clampedRange.length == 0) { - return @[]; - } - - // Used for block measure option - __block CGRect firstRect = CGRectNull; - __block CGRect lastRect = CGRectNull; - __block CGRect blockRect = CGRectNull; - NSMutableArray *mutableTextRects = [NSMutableArray array]; - - NSString *string = textStorage.string; - - NSRange totalGlyphRange = [layoutManager glyphRangeForCharacterRange:clampedRange actualCharacterRange:NULL]; - - [layoutManager enumerateLineFragmentsForGlyphRange:totalGlyphRange usingBlock:^(CGRect rect, - CGRect usedRect, - NSTextContainer *innerTextContainer, - NSRange glyphRange, - BOOL *stop) { - - CGRect lineRect = CGRectNull; - // If we're empty, don't bother looping through glyphs, use the default. - if (CGRectIsEmpty(usedRect)) { - lineRect = usedRect; - } else { - // TextKit's bounding rect computations are just a touch off, so we actually - // compose the rects by hand from the center of the given TextKit bounds and - // imposing the font attributes returned by the glyph's font. - NSRange lineGlyphRange = NSIntersectionRange(totalGlyphRange, glyphRange); - for (NSUInteger i = lineGlyphRange.location; i < NSMaxRange(lineGlyphRange) && i < string.length; i++) { - // We grab the properly sized rect for the glyph - CGRect properGlyphRect = [self _internalRectForGlyphAtIndex:i - measureOption:measureOption - layoutManager:layoutManager - textContainer:textContainer - textStorage:textStorage]; - - // Don't count empty glyphs towards our line rect. - if (!CGRectIsEmpty(properGlyphRect)) { - lineRect = CGRectIsNull(lineRect) ? properGlyphRect - : CGRectUnion(lineRect, properGlyphRect); - } - } - } - - if (!CGRectIsNull(lineRect)) { - if (measureOption == ASTextKitRendererMeasureOptionBlock) { - // For the block measurement option we store the first & last rect as - // special cases, then merge everything else into a single block rect - if (CGRectIsNull(firstRect)) { - // We don't have a firstRect, so we must be on the first line. - firstRect = lineRect; - } else if(CGRectIsNull(lastRect)) { - // We don't have a lastRect, but we do have a firstRect, so we must - // be on the second line. No need to merge in the blockRect just yet - lastRect = lineRect; - } else if(CGRectIsNull(blockRect)) { - // We have both a first and last rect, so we must be on the third line - // we don't have any blockRect to merge it into, so we just set it - // directly. - blockRect = lastRect; - lastRect = lineRect; - } else { - // Everything is already set, so we just merge this line into the - // block. - blockRect = CGRectUnion(blockRect, lastRect); - lastRect = lineRect; - } - } else { - // If the block option isn't being used then each line is being treated - // individually. - [mutableTextRects addObject:[NSValue valueWithCGRect:[self.shadower offsetRectWithInternalRect:lineRect]]]; - } - } - }]; - - if (measureOption == ASTextKitRendererMeasureOptionBlock) { - // Block measure option is handled differently with just 3 vars for the entire range. - if (!CGRectIsNull(firstRect)) { - if (!CGRectIsNull(blockRect)) { - CGFloat rightEdge = MAX(CGRectGetMaxX(blockRect), CGRectGetMaxX(lastRect)); - if (rightEdge > CGRectGetMaxX(firstRect)) { - // Force the right side of the first rect to properly align with the - // right side of the rightmost of the block and last rect - firstRect.size.width += rightEdge - CGRectGetMaxX(firstRect); - } - - // Force the left side of the block rect to properly align with the - // left side of the leftmost of the first and last rect - blockRect.origin.x = MIN(CGRectGetMinX(firstRect), CGRectGetMinX(lastRect)); - // Force the right side of the block rect to properly align with the - // right side of the rightmost of the first and last rect - blockRect.size.width += MAX(CGRectGetMaxX(firstRect), CGRectGetMaxX(lastRect)) - CGRectGetMaxX(blockRect); - } - if (!CGRectIsNull(lastRect)) { - // Force the left edge of the last rect to properly align with the - // left side of the leftmost of the first and block rect, if necessary. - CGFloat leftEdge = MIN(CGRectGetMinX(blockRect), CGRectGetMinX(firstRect)); - CGFloat lastRectNudgeAmount = MAX(CGRectGetMinX(lastRect) - leftEdge, 0); - lastRect.origin.x = MIN(leftEdge, CGRectGetMinX(lastRect)); - lastRect.size.width += lastRectNudgeAmount; - } - - [mutableTextRects addObject:[NSValue valueWithCGRect:[self.shadower offsetRectWithInternalRect:firstRect]]]; - } - if (!CGRectIsNull(blockRect)) { - [mutableTextRects addObject:[NSValue valueWithCGRect:[self.shadower offsetRectWithInternalRect:blockRect]]]; - } - if (!CGRectIsNull(lastRect)) { - [mutableTextRects addObject:[NSValue valueWithCGRect:[self.shadower offsetRectWithInternalRect:lastRect]]]; - } - } - - return [mutableTextRects copy]; -} - -- (NSUInteger)nearestTextIndexAtPosition:(CGPoint)position -{ - // Check in a 9-point region around the actual touch point so we make sure - // we get the best attribute for the touch. - __block CGFloat minimumGlyphDistance = CGFLOAT_MAX; - __block NSUInteger minimumGlyphCharacterIndex = NSNotFound; - - [self enumerateTextIndexesAtPosition:position usingBlock:^(NSUInteger characterIndex, CGRect glyphBoundingRect, BOOL *stop) { - CGPoint glyphLocation = CGPointMake(CGRectGetMidX(glyphBoundingRect), CGRectGetMidY(glyphBoundingRect)); - CGFloat currentDistance = std::sqrt(std::pow(position.x - glyphLocation.x, 2.f) + std::pow(position.y - glyphLocation.y, 2.f)); - if (currentDistance < minimumGlyphDistance) { - minimumGlyphDistance = currentDistance; - minimumGlyphCharacterIndex = characterIndex; - } - }]; - return minimumGlyphCharacterIndex; -} - -/** - Measured from the internal coordinate space of the context, not accounting for shadow offsets. Actually uses CoreText - as an approximation to work around problems in TextKit's glyph sizing. - */ -- (CGRect)_internalRectForGlyphAtIndex:(NSUInteger)glyphIndex - measureOption:(ASTextKitRendererMeasureOption)measureOption - layoutManager:(NSLayoutManager *)layoutManager - textContainer:(NSTextContainer *)textContainer - textStorage:(NSTextStorage *)textStorage -{ - NSUInteger charIndex = [layoutManager characterIndexForGlyphAtIndex:glyphIndex]; - CGGlyph glyph = [layoutManager glyphAtIndex:glyphIndex]; - CTFontRef font = (__bridge_retained CTFontRef)[textStorage attribute:NSFontAttributeName - atIndex:charIndex - effectiveRange:NULL]; - if (font == nil) { - font = (__bridge_retained CTFontRef)[UIFont systemFontOfSize:12.0]; - } - - // Glyph Advance - // +-------------------------+ - // | | - // | | - // +------------------------+--|-------------------------|--+-----------+-----+ What TextKit returns sometimes - // | | | XXXXXXXXXXX + | | | (approx. correct height, but - // | ---------|--+---------+ XXX XXXX +|-----------|-----| sometimes inaccurate bounding - // | | | XXX XXXXX| | | widths) - // | | | XX XX | | | - // | | | XX | | | - // | | | XXX | | | - // | | | XX | | | - // | | | XXXXXXXXXXX | | | - // | Cap Height->| | XX | | | - // | | | XX | Ascent-->| | - // | | | XX | | | - // | | | XX | | | - // | | | X | | | - // | | | X | | | - // | | | X | | | - // | | | XX | | | - // | | | X | | | - // | ---------|-------+ X +-------------------------------------| - // | | XX | | - // | | X | | - // | | XX Descent------>| | - // | | XXXXXX | | - // | | XXX | | - // +------------------------+-------------------------------------------------+ - // | - // +--+Actual bounding box - - CGRect glyphRect = [layoutManager boundingRectForGlyphRange:NSMakeRange(glyphIndex, 1) - inTextContainer:textContainer]; - - // If it is a NSTextAttachment, we don't have the matched glyph and use width of glyphRect instead of advance. - CGFloat advance = (glyph == kCGFontIndexInvalid) ? glyphRect.size.width : CTFontGetAdvancesForGlyphs(font, kCTFontOrientationHorizontal, &glyph, NULL, 1); - - // We treat the center of the glyph's bounding box as the center of our new rect - CGPoint glyphCenter = CGPointMake(CGRectGetMidX(glyphRect), CGRectGetMidY(glyphRect)); - - CGRect properGlyphRect; - if (measureOption == ASTextKitRendererMeasureOptionCapHeight - || measureOption == ASTextKitRendererMeasureOptionBlock) { - CGFloat ascent = CTFontGetAscent(font); - CGFloat descent = CTFontGetDescent(font); - CGFloat capHeight = CTFontGetCapHeight(font); - CGFloat leading = CTFontGetLeading(font); - CGFloat glyphHeight = ascent + descent; - - // For visual balance, we add the cap height padding above the cap, and - // below the baseline, we scale by the descent so it grows with the size of - // the text. - CGFloat topPadding = ASTextKitRendererTextCapHeightPadding * descent; - CGFloat bottomPadding = topPadding; - - properGlyphRect = CGRectMake(glyphCenter.x - advance * 0.5, - glyphCenter.y - glyphHeight * 0.5 + (ascent - capHeight) - topPadding + leading, - advance, - capHeight + topPadding + bottomPadding); - } else { - // We are just measuring the line heights here, so we can use the - // heights used by TextKit, which tend to be pretty good. - properGlyphRect = CGRectMake(glyphCenter.x - advance * 0.5, - glyphRect.origin.y, - advance, - glyphRect.size.height); - } - - CFRelease(font); - - return properGlyphRect; -} - -- (void)enumerateTextIndexesAtPosition:(CGPoint)externalPosition usingBlock:(as_text_component_index_block_t)block -{ - // This method is a little complex because it has to call out to client code from inside an enumeration that needs - // to achieve a lock on the textkit components. It cannot call out to client code from within that lock so we just - // perform the textkit-locked ops inside the locked context. - ASTextKitContext *lockingContext = self.context; - CGPoint internalPosition = [self.shadower offsetPointWithExternalPoint:externalPosition]; - __block BOOL invalidPosition = NO; - [lockingContext performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - invalidPosition = internalPosition.x > textContainer.size.width - || internalPosition.y > textContainer.size.height - || block == NULL; - }]; - if (invalidPosition) { - // Short circuit if the position is outside the size of this renderer, or if the block is null. - return; - } - - // We break it up into a 44pt box for the touch, and find the closest link attribute-containing glyph to the center of - // the touch. - CGFloat squareSide = 44.f; - // Should be odd if you want to test the center of the touch. - NSInteger pointsOnASide = 3; - - // The distance between any 2 of the adjacent points - CGFloat pointSeparation = squareSide / pointsOnASide; - // These are for tracking which point we're on. We start with -pointsOnASide/2 and go to pointsOnASide/2. So if - // pointsOnASide=3, we go from -1 to 1. - NSInteger endIndex = pointsOnASide / 2; - NSInteger startIndex = -endIndex; - - BOOL stop = NO; - for (NSInteger i = startIndex; i <= endIndex && !stop; i++) { - for (NSInteger j = startIndex; j <= endIndex && !stop; j++) { - CGPoint currentPoint = CGPointMake(internalPosition.x + i * pointSeparation, - internalPosition.y + j * pointSeparation); - - __block NSUInteger characterIndex = NSNotFound; - __block BOOL isValidGlyph = NO; - __block CGRect glyphRect = CGRectNull; - - [lockingContext performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - // We ask the layout manager for the proper glyph at the touch point - NSUInteger glyphIndex = [layoutManager glyphIndexForPoint:currentPoint - inTextContainer:textContainer]; - - // If it's an invalid glyph, quit. - - [layoutManager glyphAtIndex:glyphIndex isValidIndex:&isValidGlyph]; - if (!isValidGlyph) { - return; - } - - characterIndex = [layoutManager characterIndexForGlyphAtIndex:glyphIndex]; - - glyphRect = [self _internalRectForGlyphAtIndex:glyphIndex - measureOption:ASTextKitRendererMeasureOptionLineHeight - layoutManager:layoutManager - textContainer:textContainer - textStorage:textStorage]; - }]; - - // Sometimes TextKit plays jokes on us and returns glyphs that really aren't close to the point in question. - // Silly TextKit... - if (!isValidGlyph || !CGRectContainsPoint(CGRectInset(glyphRect, -ASTextKitRendererGlyphTouchHitSlop, -ASTextKitRendererGlyphTouchHitSlop), currentPoint)) { - continue; - } - - block(characterIndex, [self.shadower offsetRectWithInternalRect:glyphRect], &stop); - } - } -} - -- (CGRect)trailingRect -{ - __block CGRect trailingRect = CGRectNull; - [self.context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - CGSize calculatedSize = textContainer.size; - // If have an empty string, then our whole bounds constitute trailing space. - if ([textStorage length] == 0) { - trailingRect = CGRectMake(0, 0, calculatedSize.width, calculatedSize.height); - return; - } - - // Take everything after our final character as trailing space. - NSRange textRange = NSMakeRange([textStorage length] - 1, 1); - NSArray *finalRects = [self unlockedRectsForTextRange:textRange measureOptions:ASTextKitRendererMeasureOptionLineHeight layoutManager:layoutManager textStorage:textStorage textContainer:textContainer]; - CGRect finalGlyphRect = [[finalRects lastObject] CGRectValue]; - CGPoint origin = CGPointMake(CGRectGetMaxX(finalGlyphRect), CGRectGetMinY(finalGlyphRect)); - CGSize size = CGSizeMake(calculatedSize.width - origin.x, calculatedSize.height - origin.y); - trailingRect = (CGRect){origin, size}; - }]; - return trailingRect; -} - -- (CGRect)frameForTextRange:(NSRange)textRange -{ - __block CGRect textRect = CGRectNull; - [self.context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - // Bail on invalid range. - if (NSMaxRange(textRange) > [textStorage length]) { - ASDisplayNodeCFailAssert(@"Invalid range"); - return; - } - - // Force glyph generation and layout. - [layoutManager ensureLayoutForTextContainer:textContainer]; - - NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:textRange actualCharacterRange:NULL]; - textRect = [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer]; - }]; - return textRect; -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+TextChecking.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+TextChecking.h deleted file mode 100644 index d4ba74fd32..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+TextChecking.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// ASTextKitRenderer+TextChecking.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#if AS_ENABLE_TEXTNODE - -/** - Application extensions to NSTextCheckingType. We're allowed to do this (see NSTextCheckingAllCustomTypes). - */ -static uint64_t const ASTextKitTextCheckingTypeEntity = 1ULL << 33; -static uint64_t const ASTextKitTextCheckingTypeTruncation = 1ULL << 34; - -@class ASTextKitEntityAttribute; - -@interface ASTextKitTextCheckingResult : NSTextCheckingResult -@property (nonatomic, readonly) ASTextKitEntityAttribute *entityAttribute; -@end - -@interface ASTextKitRenderer (TextChecking) - -- (NSTextCheckingResult *)textCheckingResultAtPoint:(CGPoint)point; - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+TextChecking.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+TextChecking.mm deleted file mode 100644 index e556393572..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer+TextChecking.mm +++ /dev/null @@ -1,104 +0,0 @@ -// -// ASTextKitRenderer+TextChecking.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#if AS_ENABLE_TEXTNODE - -#import -#import -#import - -@implementation ASTextKitTextCheckingResult - -{ - // Be explicit about the fact that we are overriding the super class' implementation of -range and -resultType - // and substituting our own custom values. (We could use @synthesize to make these ivars, but our linter correctly - // complains; it's weird to use @synthesize for properties that are redeclared on top of an original declaration in - // the superclass. We only do it here because NSTextCheckingResult doesn't expose an initializer, which is silly.) - NSRange _rangeOverride; - NSTextCheckingType _resultTypeOverride; -} - -- (instancetype)initWithType:(NSTextCheckingType)type - entityAttribute:(ASTextKitEntityAttribute *)entityAttribute - range:(NSRange)range -{ - if ((self = [super init])) { - _resultTypeOverride = type; - _rangeOverride = range; - _entityAttribute = entityAttribute; - } - return self; -} - -- (NSTextCheckingType)resultType -{ - return _resultTypeOverride; -} - -- (NSRange)range -{ - return _rangeOverride; -} - -@end - -@implementation ASTextKitRenderer (TextChecking) - -- (NSTextCheckingResult *)textCheckingResultAtPoint:(CGPoint)point -{ - __block NSTextCheckingResult *result = nil; - NSAttributedString *attributedString = self.attributes.attributedString; - NSAttributedString *truncationAttributedString = self.attributes.truncationAttributedString; - - // get the index of the last character, so we can handle text in the truncation token - __block NSRange truncationTokenRange = { NSNotFound, 0 }; - - [truncationAttributedString enumerateAttribute:ASTextKitTruncationAttributeName inRange:NSMakeRange(0, truncationAttributedString.length) - options:0 - usingBlock:^(id value, NSRange range, BOOL *stop) { - if (value != nil && range.length > 0) { - truncationTokenRange = range; - } - }]; - - if (truncationTokenRange.location == NSNotFound) { - // The truncation string didn't specify a substring which should be highlighted, so we just highlight it all - truncationTokenRange = { 0, truncationAttributedString.length }; - } - - NSRange visibleRange = self.truncater.firstVisibleRange; - truncationTokenRange.location += NSMaxRange(visibleRange); - - __block CGFloat minDistance = CGFLOAT_MAX; - [self enumerateTextIndexesAtPosition:point usingBlock:^(NSUInteger index, CGRect glyphBoundingRect, BOOL *stop){ - if (index >= truncationTokenRange.location) { - result = [[ASTextKitTextCheckingResult alloc] initWithType:ASTextKitTextCheckingTypeTruncation - entityAttribute:nil - range:truncationTokenRange]; - } else { - NSRange range; - NSDictionary *attributes = [attributedString attributesAtIndex:index effectiveRange:&range]; - ASTextKitEntityAttribute *entityAttribute = attributes[ASTextKitEntityAttributeName]; - CGFloat distance = hypot(CGRectGetMidX(glyphBoundingRect) - point.x, CGRectGetMidY(glyphBoundingRect) - point.y); - if (entityAttribute && distance < minDistance) { - result = [[ASTextKitTextCheckingResult alloc] initWithType:ASTextKitTextCheckingTypeEntity - entityAttribute:entityAttribute - range:range]; - minDistance = distance; - } - } - }]; - return result; -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer.h deleted file mode 100644 index 0f0cc00e0a..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer.h +++ /dev/null @@ -1,108 +0,0 @@ -// -// ASTextKitRenderer.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#import - -#if AS_ENABLE_TEXTNODE - -#import - -#import - -@class ASTextKitContext; -@class ASTextKitShadower; -@class ASTextKitFontSizeAdjuster; -@protocol ASTextKitTruncating; - -/** - ASTextKitRenderer is a modular object that is responsible for laying out and drawing text. - - A renderer will hold onto the TextKit layouts for the given attributes after initialization. This may constitute a - large amount of memory for large enough applications, so care must be taken when keeping many of these around in-memory - at once. - - This object is designed to be modular and simple. All complex maintenance of state should occur in sub-objects or be - derived via pure functions or categories. No touch-related handling belongs in this class. - - ALL sizing and layout information from this class is in the external coordinate space of the TextKit components. This - is an important distinction because all internal sizing and layout operations are carried out within the shadowed - coordinate space. Padding will be added for you in order to ensure clipping does not occur, and additional information - on this transform is available via the shadower should you need it. - */ -@interface ASTextKitRenderer : NSObject - -/** - Designated Initializer - @discussion Sizing will occur as a result of initialization, so be careful when/where you use this. - */ -- (instancetype)initWithTextKitAttributes:(const ASTextKitAttributes &)textComponentAttributes - constrainedSize:(const CGSize)constrainedSize; - -@property (nonatomic, readonly) ASTextKitContext *context; - -@property (nonatomic, readonly) id truncater; - -@property (nonatomic, readonly) ASTextKitFontSizeAdjuster *fontSizeAdjuster; - -@property (nonatomic, readonly) ASTextKitShadower *shadower; - -@property (nonatomic, readonly) ASTextKitAttributes attributes; - -@property (nonatomic, readonly) CGSize constrainedSize; - -@property (nonatomic, readonly) CGFloat currentScaleFactor; - -#pragma mark - Drawing -/** - Draw the renderer's text content into the bounds provided. - - @param bounds The rect in which to draw the contents of the renderer. - */ -- (void)drawInContext:(CGContextRef)context bounds:(CGRect)bounds; - -#pragma mark - Layout - -/** - Returns the computed size of the renderer given the constrained size and other parameters in the initializer. - */ -- (CGSize)size; - -#pragma mark - Text Ranges - -/** - The character range from the original attributedString that is displayed by the renderer given the parameters in the - initializer. - */ -@property (nonatomic, readonly) std::vector visibleRanges; - -/** - The number of lines shown in the string. - */ -- (NSUInteger)lineCount; - -/** - Whether or not the text is truncated. - */ -- (BOOL)isTruncated; - -@end - -@interface ASTextKitRenderer (ASTextKitRendererConvenience) - -/** - Returns the first visible range or an NSRange with location of NSNotFound and size of 0 if no first visible - range exists - */ -@property (nonatomic, readonly) NSRange firstVisibleRange; - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer.mm deleted file mode 100644 index b724d70747..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitRenderer.mm +++ /dev/null @@ -1,295 +0,0 @@ -// -// ASTextKitRenderer.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#if AS_ENABLE_TEXTNODE - -#import - -#import -#import -#import -#import -#import -#import - -//#define LOG(...) NSLog(__VA_ARGS__) -#define LOG(...) - -static NSCharacterSet *_defaultAvoidTruncationCharacterSet() -{ - static NSCharacterSet *truncationCharacterSet; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSMutableCharacterSet *mutableCharacterSet = [[NSMutableCharacterSet alloc] init]; - [mutableCharacterSet formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - [mutableCharacterSet addCharactersInString:@".,!?:;"]; - truncationCharacterSet = mutableCharacterSet; - }); - return truncationCharacterSet; -} - -@implementation ASTextKitRenderer { - CGSize _calculatedSize; -} -@synthesize attributes = _attributes, context = _context, shadower = _shadower, truncater = _truncater, fontSizeAdjuster = _fontSizeAdjuster; - -#pragma mark - Initialization - -- (instancetype)initWithTextKitAttributes:(const ASTextKitAttributes &)attributes - constrainedSize:(const CGSize)constrainedSize -{ - if (self = [super init]) { - _constrainedSize = constrainedSize; - _attributes = attributes; - _currentScaleFactor = 1; - - // As the renderer should be thread safe, create all subcomponents in the initialization method - _shadower = [ASTextKitShadower shadowerWithShadowOffset:attributes.shadowOffset - shadowColor:attributes.shadowColor - shadowOpacity:attributes.shadowOpacity - shadowRadius:attributes.shadowRadius]; - - // We must inset the constrained size by the size of the shadower. - CGSize shadowConstrainedSize = [[self shadower] insetSizeWithConstrainedSize:_constrainedSize]; - - _context = [[ASTextKitContext alloc] initWithAttributedString:attributes.attributedString - lineBreakMode:attributes.lineBreakMode - maximumNumberOfLines:attributes.maximumNumberOfLines - exclusionPaths:attributes.exclusionPaths - constrainedSize:shadowConstrainedSize]; - - NSCharacterSet *avoidTailTruncationSet = attributes.avoidTailTruncationSet ?: _defaultAvoidTruncationCharacterSet(); - _truncater = [[ASTextKitTailTruncater alloc] initWithContext:[self context] - truncationAttributedString:attributes.truncationAttributedString - avoidTailTruncationSet:avoidTailTruncationSet]; - - ASTextKitAttributes attributes = _attributes; - // We must inset the constrained size by the size of the shadower. - _fontSizeAdjuster = [[ASTextKitFontSizeAdjuster alloc] initWithContext:[self context] - constrainedSize:shadowConstrainedSize - textKitAttributes:attributes]; - - // Calcualate size immediately - [self _calculateSize]; - } - return self; -} - -- (NSStringDrawingContext *)stringDrawingContext -{ - // String drawing contexts are not safe to use from more than one thread. - // i.e. if they are created on one thread, it is unsafe to use them on another. - // Therefore we always need to create a new one. - // - // http://web.archive.org/web/20140703122636/https://developer.apple.com/library/ios/documentation/uikit/reference/NSAttributedString_UIKit_Additions/Reference/Reference.html - NSStringDrawingContext *stringDrawingContext = [[NSStringDrawingContext alloc] init]; - - if (isinf(_constrainedSize.width) == NO && _attributes.maximumNumberOfLines > 0) { - ASDisplayNodeAssert(_attributes.maximumNumberOfLines != 1, @"Max line count 1 is not supported in fast-path."); - [stringDrawingContext setValue:@(_attributes.maximumNumberOfLines) forKey:@"maximumNumberOfLines"]; - } - return stringDrawingContext; -} - -#pragma mark - Sizing - -- (CGSize)size -{ - return _calculatedSize; -} - -- (void)_calculateSize -{ - // if we have no scale factors or an unconstrained width, there is no reason to try to adjust the font size - if (isinf(_constrainedSize.width) == NO && [_attributes.pointSizeScaleFactors count] > 0) { - _currentScaleFactor = [[self fontSizeAdjuster] scaleFactor]; - } - - const CGRect constrainedRect = {CGPointZero, _constrainedSize}; - - // If we do not scale, do exclusion, or do custom truncation, we should just use NSAttributedString drawing for a fast-path. - if (self.canUseFastPath) { - CGRect rect = [_attributes.attributedString boundingRectWithSize:_constrainedSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine context:self.stringDrawingContext]; - // Intersect with constrained rect, in case text kit goes out-of-bounds. - rect = CGRectIntersection(rect, constrainedRect); - _calculatedSize = [self.shadower outsetSizeWithInsetSize:rect.size]; - return; - } - - BOOL isScaled = [self isScaled]; - __block NSTextStorage *scaledTextStorage = nil; - if (isScaled) { - // apply the string scale before truncating or else we may truncate the string after we've done the work to shrink it. - [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - NSMutableAttributedString *scaledString = [[NSMutableAttributedString alloc] initWithAttributedString:textStorage]; - [ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:self->_currentScaleFactor]; - scaledTextStorage = [[NSTextStorage alloc] initWithAttributedString:scaledString]; - - [textStorage removeLayoutManager:layoutManager]; - [scaledTextStorage addLayoutManager:layoutManager]; - }]; - } - - [[self truncater] truncate]; - - __block CGRect boundingRect; - - // Force glyph generation and layout, which may not have happened yet (and isn't triggered by - // -usedRectForTextContainer:). - [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - [layoutManager ensureLayoutForTextContainer:textContainer]; - boundingRect = [layoutManager usedRectForTextContainer:textContainer]; - if (isScaled) { - // put the non-scaled version back - [scaledTextStorage removeLayoutManager:layoutManager]; - [textStorage addLayoutManager:layoutManager]; - } - }]; - - // TextKit often returns incorrect glyph bounding rects in the horizontal direction, so we clip to our bounding rect - // to make sure our width calculations aren't being offset by glyphs going beyond the constrained rect. - boundingRect = CGRectIntersection(boundingRect, constrainedRect); - _calculatedSize = [_shadower outsetSizeWithInsetSize:boundingRect.size]; -} - -- (BOOL)isScaled -{ - return (_currentScaleFactor > 0 && _currentScaleFactor < 1.0); -} - -- (BOOL)usesCustomTruncation -{ - // NOTE: This code does not correctly handle if they set `…` with different attributes. - return _attributes.avoidTailTruncationSet != nil || [_attributes.truncationAttributedString.string isEqualToString:@"\u2026"] == NO; -} - -- (BOOL)usesExclusionPaths -{ - return _attributes.exclusionPaths.count > 0; -} - -- (BOOL)canUseFastPath -{ - return NO; -// Fast path is temporarily disabled, because it's crashing in production. -// NOTE: Remember to re-enable testFastPathTruncation when we re-enable this. -// return self.isScaled == NO -// && self.usesCustomTruncation == NO -// && self.usesExclusionPaths == NO -// // NSAttributedString drawing methods ignore usesLineFragmentOrigin if max line count 1, -// // rendering them useless: -// && (_attributes.maximumNumberOfLines != 1 || isinf(_constrainedSize.width)); -} - -#pragma mark - Drawing - -- (void)drawInContext:(CGContextRef)context bounds:(CGRect)bounds; -{ - // We add an assertion so we can track the rare conditions where a graphics context is not present - ASDisplayNodeAssertNotNil(context, @"This is no good without a context."); - - bounds = CGRectIntersection(bounds, { .size = _constrainedSize }); - CGRect shadowInsetBounds = [[self shadower] insetRectWithConstrainedRect:bounds]; - - CGContextSaveGState(context); - [[self shadower] setShadowInContext:context]; - UIGraphicsPushContext(context); - - LOG(@"%@, shadowInsetBounds = %@",self, NSStringFromCGRect(shadowInsetBounds)); - - // If we use default options, we can use NSAttributedString for a - // fast path. - if (self.canUseFastPath) { - CGRect drawingBounds = shadowInsetBounds; - [_attributes.attributedString drawWithRect:drawingBounds options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine context:self.stringDrawingContext]; - } else { - BOOL isScaled = [self isScaled]; - [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - - NSTextStorage *scaledTextStorage = nil; - - if (isScaled) { - // if we are going to scale the text, swap out the non-scaled text for the scaled version. - NSMutableAttributedString *scaledString = [[NSMutableAttributedString alloc] initWithAttributedString:textStorage]; - [ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:self->_currentScaleFactor]; - scaledTextStorage = [[NSTextStorage alloc] initWithAttributedString:scaledString]; - - [textStorage removeLayoutManager:layoutManager]; - [scaledTextStorage addLayoutManager:layoutManager]; - } - - LOG(@"usedRect: %@", NSStringFromCGRect([layoutManager usedRectForTextContainer:textContainer])); - - NSRange glyphRange = [layoutManager glyphRangeForBoundingRect:(CGRect){ .size = textContainer.size } inTextContainer:textContainer]; - LOG(@"boundingRect: %@", NSStringFromCGRect([layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer])); - - [layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:shadowInsetBounds.origin]; - [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:shadowInsetBounds.origin]; - - if (isScaled) { - // put the non-scaled version back - [scaledTextStorage removeLayoutManager:layoutManager]; - [textStorage addLayoutManager:layoutManager]; - } - }]; - } - - UIGraphicsPopContext(); - CGContextRestoreGState(context); -} - -#pragma mark - String Ranges - -- (NSUInteger)lineCount -{ - __block NSUInteger lineCount = 0; - [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - for (NSRange lineRange = { 0, 0 }; NSMaxRange(lineRange) < [layoutManager numberOfGlyphs]; lineCount++) { - [layoutManager lineFragmentRectForGlyphAtIndex:NSMaxRange(lineRange) effectiveRange:&lineRange]; - } - }]; - return lineCount; -} - -- (BOOL)isTruncated -{ - if (self.canUseFastPath) { - CGRect boundedRect = [_attributes.attributedString boundingRectWithSize:CGSizeMake(_constrainedSize.width, CGFLOAT_MAX) - options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine - context:nil]; - return boundedRect.size.height > _constrainedSize.height; - } else { - return self.firstVisibleRange.length < _attributes.attributedString.length; - } -} - -- (std::vector)visibleRanges -{ - return _truncater.visibleRanges; -} - -@end - -@implementation ASTextKitRenderer (ASTextKitRendererConvenience) - -- (NSRange)firstVisibleRange -{ - std::vector visibleRanges = self.visibleRanges; - if (visibleRanges.size() > 0) { - return visibleRanges[0]; - } - - return NSMakeRange(0, 0); -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitShadower.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitShadower.h deleted file mode 100644 index 2f9c604fbc..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitShadower.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// ASTextKitShadower.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#import - -#if AS_ENABLE_TEXTNODE - -#import - -/** - * @abstract an immutable class for calculating shadow padding drawing a shadowed background for text - */ -AS_SUBCLASSING_RESTRICTED -@interface ASTextKitShadower : NSObject - -+ (ASTextKitShadower *)shadowerWithShadowOffset:(CGSize)shadowOffset - shadowColor:(UIColor *)shadowColor - shadowOpacity:(CGFloat)shadowOpacity - shadowRadius:(CGFloat)shadowRadius; - -/** - * @abstract The offset from the top-left corner at which the shadow starts. - * @discussion A positive width will move the shadow to the right. - * A positive height will move the shadow downwards. - */ -@property (nonatomic, readonly) CGSize shadowOffset; - -//! CGColor in which the shadow is drawn -@property (nonatomic, copy, readonly) UIColor *shadowColor; - -//! Alpha of the shadow -@property (nonatomic, readonly) CGFloat shadowOpacity; - -//! Radius, in pixels -@property (nonatomic, readonly) CGFloat shadowRadius; - -/** - * @abstract The edge insets which represent shadow padding - * @discussion Each edge inset is less than or equal to zero. - * - * Example: - * CGRect boundsWithoutShadowPadding; // Large enough to fit text, not large enough to fit the shadow as well - * UIEdgeInsets shadowPadding = [shadower shadowPadding]; - * CGRect boundsWithShadowPadding = UIEdgeInsetsRect(boundsWithoutShadowPadding, shadowPadding); - */ -- (UIEdgeInsets)shadowPadding; - -- (CGSize)insetSizeWithConstrainedSize:(CGSize)constrainedSize; - -- (CGRect)insetRectWithConstrainedRect:(CGRect)constrainedRect; - -- (CGSize)outsetSizeWithInsetSize:(CGSize)insetSize; - -- (CGRect)outsetRectWithInsetRect:(CGRect)insetRect; - -- (CGRect)offsetRectWithInternalRect:(CGRect)internalRect; - -- (CGPoint)offsetPointWithInternalPoint:(CGPoint)internalPoint; - -- (CGPoint)offsetPointWithExternalPoint:(CGPoint)externalPoint; - -/** - * @abstract draws the shadow for text in the provided CGContext - * @discussion Call within the text node's +drawRect method - */ -- (void)setShadowInContext:(CGContextRef)context; - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitShadower.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitShadower.mm deleted file mode 100644 index a2f37f7e06..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitShadower.mm +++ /dev/null @@ -1,177 +0,0 @@ -// -// ASTextKitShadower.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#if AS_ENABLE_TEXTNODE - -#import - -static inline CGSize _insetSize(CGSize size, UIEdgeInsets insets) -{ - size.width -= (insets.left + insets.right); - size.height -= (insets.top + insets.bottom); - return size; -} - -static inline UIEdgeInsets _invertInsets(UIEdgeInsets insets) -{ - return { - .top = -insets.top, - .left = -insets.left, - .bottom = -insets.bottom, - .right = -insets.right - }; -} - -@implementation ASTextKitShadower { - UIEdgeInsets _calculatedShadowPadding; -} - -+ (ASTextKitShadower *)shadowerWithShadowOffset:(CGSize)shadowOffset - shadowColor:(UIColor *)shadowColor - shadowOpacity:(CGFloat)shadowOpacity - shadowRadius:(CGFloat)shadowRadius -{ - /** - * For all cases where no shadow is drawn, we share this singleton shadower to save resources. - */ - static dispatch_once_t onceToken; - static ASTextKitShadower *sharedNonShadower; - dispatch_once(&onceToken, ^{ - sharedNonShadower = [[ASTextKitShadower alloc] initWithShadowOffset:CGSizeZero shadowColor:nil shadowOpacity:0 shadowRadius:0]; - }); - - BOOL hasShadow = shadowOpacity > 0 && (shadowRadius > 0 || CGSizeEqualToSize(shadowOffset, CGSizeZero) == NO) && CGColorGetAlpha(shadowColor.CGColor) > 0; - if (hasShadow == NO) { - return sharedNonShadower; - } else { - return [[ASTextKitShadower alloc] initWithShadowOffset:shadowOffset shadowColor:shadowColor shadowOpacity:shadowOpacity shadowRadius:shadowRadius]; - } -} - -- (instancetype)initWithShadowOffset:(CGSize)shadowOffset - shadowColor:(UIColor *)shadowColor - shadowOpacity:(CGFloat)shadowOpacity - shadowRadius:(CGFloat)shadowRadius -{ - if (self = [super init]) { - _shadowOffset = shadowOffset; - _shadowColor = shadowColor; - _shadowOpacity = shadowOpacity; - _shadowRadius = shadowRadius; - _calculatedShadowPadding = UIEdgeInsetsMake(-INFINITY, -INFINITY, INFINITY, INFINITY); - } - return self; -} - -/* - * This method is duplicated here because it gets called frequently, and we were - * wasting valuable time constructing a state object to ask it. - */ -- (BOOL)_shouldDrawShadow -{ - return _shadowOpacity != 0.0 && (_shadowRadius != 0 || !CGSizeEqualToSize(_shadowOffset, CGSizeZero)) && CGColorGetAlpha(_shadowColor.CGColor) > 0; -} - -- (void)setShadowInContext:(CGContextRef)context -{ - if ([self _shouldDrawShadow]) { - CGColorRef textShadowColor = CGColorRetain(_shadowColor.CGColor); - CGSize textShadowOffset = _shadowOffset; - CGFloat textShadowOpacity = _shadowOpacity; - CGFloat textShadowRadius = _shadowRadius; - - if (textShadowOpacity != 1.0) { - CGFloat inherentAlpha = CGColorGetAlpha(textShadowColor); - - CGColorRef oldTextShadowColor = textShadowColor; - textShadowColor = CGColorCreateCopyWithAlpha(textShadowColor, inherentAlpha * textShadowOpacity); - CGColorRelease(oldTextShadowColor); - } - - CGContextSetShadowWithColor(context, textShadowOffset, textShadowRadius, textShadowColor); - - CGColorRelease(textShadowColor); - } -} - - -- (UIEdgeInsets)shadowPadding -{ - if (_calculatedShadowPadding.top == -INFINITY) { - if (![self _shouldDrawShadow]) { - return UIEdgeInsetsZero; - } - - UIEdgeInsets shadowPadding = UIEdgeInsetsZero; - - // min values are expected to be negative for most typical shadowOffset and - // blurRadius settings: - shadowPadding.top = std::fmin(0.0f, _shadowOffset.height - _shadowRadius); - shadowPadding.left = std::fmin(0.0f, _shadowOffset.width - _shadowRadius); - - shadowPadding.bottom = std::fmin(0.0f, -_shadowOffset.height - _shadowRadius); - shadowPadding.right = std::fmin(0.0f, -_shadowOffset.width - _shadowRadius); - - _calculatedShadowPadding = shadowPadding; - } - - return _calculatedShadowPadding; -} - -- (CGSize)insetSizeWithConstrainedSize:(CGSize)constrainedSize -{ - return _insetSize(constrainedSize, _invertInsets([self shadowPadding])); -} - -- (CGRect)insetRectWithConstrainedRect:(CGRect)constrainedRect -{ - return UIEdgeInsetsInsetRect(constrainedRect, _invertInsets([self shadowPadding])); -} - -- (CGSize)outsetSizeWithInsetSize:(CGSize)insetSize -{ - return _insetSize(insetSize, [self shadowPadding]); -} - -- (CGRect)outsetRectWithInsetRect:(CGRect)insetRect -{ - return UIEdgeInsetsInsetRect(insetRect, [self shadowPadding]); -} - -- (CGRect)offsetRectWithInternalRect:(CGRect)internalRect -{ - return (CGRect){ - .origin = [self offsetPointWithInternalPoint:internalRect.origin], - .size = internalRect.size - }; -} - -- (CGPoint)offsetPointWithInternalPoint:(CGPoint)internalPoint -{ - UIEdgeInsets shadowPadding = [self shadowPadding]; - return (CGPoint){ - internalPoint.x + shadowPadding.left, - internalPoint.y + shadowPadding.top - }; -} - -- (CGPoint)offsetPointWithExternalPoint:(CGPoint)externalPoint -{ - UIEdgeInsets shadowPadding = [self shadowPadding]; - return (CGPoint){ - externalPoint.x - shadowPadding.left, - externalPoint.y - shadowPadding.top - }; -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitTailTruncater.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitTailTruncater.mm deleted file mode 100644 index b81e27be05..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitTailTruncater.mm +++ /dev/null @@ -1,196 +0,0 @@ -// -// ASTextKitTailTruncater.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#if AS_ENABLE_TEXTNODE - -#import - -@implementation ASTextKitTailTruncater -{ - __weak ASTextKitContext *_context; - NSAttributedString *_truncationAttributedString; - NSCharacterSet *_avoidTailTruncationSet; -} -@synthesize visibleRanges = _visibleRanges; - -- (instancetype)initWithContext:(ASTextKitContext *)context - truncationAttributedString:(NSAttributedString *)truncationAttributedString - avoidTailTruncationSet:(NSCharacterSet *)avoidTailTruncationSet -{ - if (self = [super init]) { - _context = context; - _truncationAttributedString = truncationAttributedString; - _avoidTailTruncationSet = avoidTailTruncationSet; - } - return self; -} - -/** - Calculates the intersection of the truncation message within the end of the last line. - */ -- (NSUInteger)_calculateCharacterIndexBeforeTruncationMessage:(NSLayoutManager *)layoutManager - textStorage:(NSTextStorage *)textStorage - textContainer:(NSTextContainer *)textContainer -{ - CGRect constrainedRect = (CGRect){ .size = textContainer.size }; - - NSRange visibleGlyphRange = [layoutManager glyphRangeForBoundingRect:constrainedRect - inTextContainer:textContainer]; - NSInteger lastVisibleGlyphIndex = (NSMaxRange(visibleGlyphRange) - 1); - - if (lastVisibleGlyphIndex < 0) { - return NSNotFound; - } - - CGRect lastLineRect = [layoutManager lineFragmentRectForGlyphAtIndex:lastVisibleGlyphIndex - effectiveRange:NULL]; - CGRect lastLineUsedRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:lastVisibleGlyphIndex - effectiveRange:NULL]; - NSParagraphStyle *paragraphStyle = [textStorage attributesAtIndex:[layoutManager characterIndexForGlyphAtIndex:lastVisibleGlyphIndex] - effectiveRange:NULL][NSParagraphStyleAttributeName]; - - // We assume LTR so long as the writing direction is not - BOOL rtlWritingDirection = paragraphStyle ? paragraphStyle.baseWritingDirection == NSWritingDirectionRightToLeft : NO; - // We only want to treat the truncation rect as left-aligned in the case that we are right-aligned and our writing - // direction is RTL. - BOOL leftAligned = CGRectGetMinX(lastLineRect) == CGRectGetMinX(lastLineUsedRect) || !rtlWritingDirection; - - // Calculate the bounding rectangle for the truncation message - ASTextKitContext *truncationContext = [[ASTextKitContext alloc] initWithAttributedString:_truncationAttributedString - lineBreakMode:NSLineBreakByWordWrapping - maximumNumberOfLines:1 - exclusionPaths:nil - constrainedSize:constrainedRect.size]; - __block CGRect truncationUsedRect; - - [truncationContext performBlockWithLockedTextKitComponents:^(NSLayoutManager *truncationLayoutManager, NSTextStorage *truncationTextStorage, NSTextContainer *truncationTextContainer) { - // Size the truncation message - [truncationLayoutManager ensureLayoutForTextContainer:truncationTextContainer]; - NSRange truncationGlyphRange = [truncationLayoutManager glyphRangeForTextContainer:truncationTextContainer]; - truncationUsedRect = [truncationLayoutManager boundingRectForGlyphRange:truncationGlyphRange - inTextContainer:truncationTextContainer]; - }]; - CGFloat truncationOriginX = (leftAligned ? - CGRectGetMaxX(constrainedRect) - truncationUsedRect.size.width : - CGRectGetMinX(constrainedRect)); - CGRect translatedTruncationRect = CGRectMake(truncationOriginX, - CGRectGetMinY(lastLineRect), - truncationUsedRect.size.width, - truncationUsedRect.size.height); - - // Determine which glyph is the first to be clipped / overlaps the truncation message. - CGFloat truncationMessageX = (leftAligned ? - CGRectGetMinX(translatedTruncationRect) : - CGRectGetMaxX(translatedTruncationRect)); - CGPoint beginningOfTruncationMessage = CGPointMake(truncationMessageX, - CGRectGetMidY(translatedTruncationRect)); - NSUInteger firstClippedGlyphIndex = [layoutManager glyphIndexForPoint:beginningOfTruncationMessage - inTextContainer:textContainer - fractionOfDistanceThroughGlyph:NULL]; - // If it didn't intersect with any text then it should just return the last visible character index, since the - // truncation rect can fully fit on the line without clipping any other text. - if (firstClippedGlyphIndex == NSNotFound) { - return [layoutManager characterIndexForGlyphAtIndex:lastVisibleGlyphIndex]; - } - NSUInteger firstCharacterIndexToReplace = [layoutManager characterIndexForGlyphAtIndex:firstClippedGlyphIndex]; - - // Break on word boundaries - return [self _findTruncationInsertionPointAtOrBeforeCharacterIndex:firstCharacterIndexToReplace - layoutManager:layoutManager - textStorage:textStorage]; -} - -/** - Finds the first whitespace at or before the character index do we don't truncate in the middle of words - If there are multiple whitespaces together (say a space and a newline), this will backtrack to the first one - */ -- (NSUInteger)_findTruncationInsertionPointAtOrBeforeCharacterIndex:(NSUInteger)firstCharacterIndexToReplace - layoutManager:(NSLayoutManager *)layoutManager - textStorage:(NSTextStorage *)textStorage -{ - // Don't attempt to truncate beyond the end of the string - if (firstCharacterIndexToReplace >= textStorage.length) { - return 0; - } - - // Find the glyph range of the line fragment containing the first character to replace. - NSRange lineGlyphRange; - [layoutManager lineFragmentRectForGlyphAtIndex:[layoutManager glyphIndexForCharacterAtIndex:firstCharacterIndexToReplace] - effectiveRange:&lineGlyphRange]; - - // Look for the first whitespace from the end of the line, starting from the truncation point - NSUInteger startingSearchIndex = [layoutManager characterIndexForGlyphAtIndex:lineGlyphRange.location]; - NSUInteger endingSearchIndex = firstCharacterIndexToReplace; - NSRange rangeToSearch = NSMakeRange(startingSearchIndex, (endingSearchIndex - startingSearchIndex)); - - NSRange rangeOfLastVisibleAvoidedChars = { .location = NSNotFound }; - if (_avoidTailTruncationSet) { - rangeOfLastVisibleAvoidedChars = [textStorage.string rangeOfCharacterFromSet:_avoidTailTruncationSet - options:NSBackwardsSearch - range:rangeToSearch]; - } - - // Couldn't find a good place to truncate. Might be because there is no whitespace in the text, or we're dealing - // with a foreign language encoding. Settle for truncating at the original place, which may be mid-word. - if (rangeOfLastVisibleAvoidedChars.location == NSNotFound) { - return firstCharacterIndexToReplace; - } else { - return rangeOfLastVisibleAvoidedChars.location; - } -} - -- (void)truncate -{ - [_context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - NSUInteger originalStringLength = textStorage.length; - - [layoutManager ensureLayoutForTextContainer:textContainer]; - - NSRange visibleGlyphRange = [layoutManager glyphRangeForBoundingRect:{ .size = textContainer.size } - inTextContainer:textContainer]; - NSRange visibleCharacterRange = [layoutManager characterRangeForGlyphRange:visibleGlyphRange - actualGlyphRange:NULL]; - - // Check if text is truncated, and if so apply our truncation string - if (visibleCharacterRange.length < originalStringLength && self->_truncationAttributedString.length > 0) { - NSInteger firstCharacterIndexToReplace = [self _calculateCharacterIndexBeforeTruncationMessage:layoutManager - textStorage:textStorage - textContainer:textContainer]; - if (firstCharacterIndexToReplace == 0 || firstCharacterIndexToReplace == NSNotFound) { - return; - } - - // Update/truncate the visible range of text - visibleCharacterRange = NSMakeRange(0, firstCharacterIndexToReplace); - NSRange truncationReplacementRange = NSMakeRange(firstCharacterIndexToReplace, - textStorage.length - firstCharacterIndexToReplace); - // Replace the end of the visible message with the truncation string - [textStorage replaceCharactersInRange:truncationReplacementRange - withAttributedString:self->_truncationAttributedString]; - } - - self->_visibleRanges = { visibleCharacterRange }; - }]; -} - -- (NSRange)firstVisibleRange -{ - std::vector visibleRanges = _visibleRanges; - if (visibleRanges.size() > 0) { - return visibleRanges[0]; - } - - return NSMakeRange(NSNotFound, 0); -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitTruncating.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitTruncating.h deleted file mode 100644 index 35392fd6b3..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitTruncating.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// ASTextKitTruncating.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#import - -#if AS_ENABLE_TEXTNODE - -#import - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class ASTextKitContext; - -@protocol ASTextKitTruncating - -/** - The character range from the original attributedString that is displayed by the renderer given the parameters in the - initializer. - */ -@property (nonatomic, readonly) std::vector visibleRanges; - -/** - Returns the first visible range or an NSRange with location of NSNotFound and size of 0 if no first visible - range exists - */ -@property (nonatomic, readonly) NSRange firstVisibleRange; - -/** - A truncater object is initialized with the full state of the text. It is a Single Responsibility Object that is - mutative. It configures the state of the TextKit components (layout manager, text container, text storage) to achieve - the intended truncation, then it stores the resulting state for later fetching. - - The truncater may mutate the state of the text storage such that only the drawn string is actually present in the - text storage itself. - - The truncater should not store a strong reference to the context to prevent retain cycles. - */ -- (instancetype)initWithContext:(ASTextKitContext *)context - truncationAttributedString:(NSAttributedString * _Nullable)truncationAttributedString - avoidTailTruncationSet:(NSCharacterSet * _Nullable)avoidTailTruncationSet; - -/** - Actually do the truncation. - */ -- (void)truncate; - -@end - -NS_ASSUME_NONNULL_END - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextRunDelegate.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextRunDelegate.h deleted file mode 100644 index 3d3bf11c2c..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextRunDelegate.h +++ /dev/null @@ -1,65 +0,0 @@ -// -// ASTextRunDelegate.h -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - Wrapper for CTRunDelegateRef. - - Example: - - ASTextRunDelegate *delegate = [ASTextRunDelegate new]; - delegate.ascent = 20; - delegate.descent = 4; - delegate.width = 20; - CTRunDelegateRef ctRunDelegate = delegate.CTRunDelegate; - if (ctRunDelegate) { - /// add to attributed string - CFRelease(ctRunDelegate); - } - - */ -@interface ASTextRunDelegate : NSObject - -/** - Creates and returns the CTRunDelegate. - - @discussion You need call CFRelease() after used. - The CTRunDelegateRef has a strong reference to this ASTextRunDelegate object. - In CoreText, use CTRunDelegateGetRefCon() to get this ASTextRunDelegate object. - - @return The CTRunDelegate object. - */ -- (nullable CTRunDelegateRef)CTRunDelegate CF_RETURNS_RETAINED; - -/** - Additional information about the the run delegate. - */ -@property (nullable, nonatomic) NSDictionary *userInfo; - -/** - The typographic ascent of glyphs in the run. - */ -@property (nonatomic) CGFloat ascent; - -/** - The typographic descent of glyphs in the run. - */ -@property (nonatomic) CGFloat descent; - -/** - The typographic width of glyphs in the run. - */ -@property (nonatomic) CGFloat width; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextRunDelegate.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextRunDelegate.mm deleted file mode 100644 index 1c179b1fea..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextRunDelegate.mm +++ /dev/null @@ -1,68 +0,0 @@ -// -// ASTextRunDelegate.mm -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -static void DeallocCallback(void *ref) { - ASTextRunDelegate *self = (__bridge_transfer ASTextRunDelegate *)(ref); - self = nil; // release -} - -static CGFloat GetAscentCallback(void *ref) { - ASTextRunDelegate *self = (__bridge ASTextRunDelegate *)(ref); - return self.ascent; -} - -static CGFloat GetDecentCallback(void *ref) { - ASTextRunDelegate *self = (__bridge ASTextRunDelegate *)(ref); - return self.descent; -} - -static CGFloat GetWidthCallback(void *ref) { - ASTextRunDelegate *self = (__bridge ASTextRunDelegate *)(ref); - return self.width; -} - -@implementation ASTextRunDelegate - -- (CTRunDelegateRef)CTRunDelegate CF_RETURNS_RETAINED { - CTRunDelegateCallbacks callbacks; - callbacks.version = kCTRunDelegateCurrentVersion; - callbacks.dealloc = DeallocCallback; - callbacks.getAscent = GetAscentCallback; - callbacks.getDescent = GetDecentCallback; - callbacks.getWidth = GetWidthCallback; - return CTRunDelegateCreate(&callbacks, (__bridge_retained void *)(self.copy)); -} - -- (void)encodeWithCoder:(NSCoder *)aCoder { - [aCoder encodeObject:@(_ascent) forKey:@"ascent"]; - [aCoder encodeObject:@(_descent) forKey:@"descent"]; - [aCoder encodeObject:@(_width) forKey:@"width"]; - [aCoder encodeObject:_userInfo forKey:@"userInfo"]; -} - -- (id)initWithCoder:(NSCoder *)aDecoder { - self = [super init]; - _ascent = ((NSNumber *)[aDecoder decodeObjectForKey:@"ascent"]).floatValue; - _descent = ((NSNumber *)[aDecoder decodeObjectForKey:@"descent"]).floatValue; - _width = ((NSNumber *)[aDecoder decodeObjectForKey:@"width"]).floatValue; - _userInfo = [aDecoder decodeObjectForKey:@"userInfo"]; - return self; -} - -- (id)copyWithZone:(NSZone *)zone { - __typeof__(self) one = [self.class new]; - one.ascent = self.ascent; - one.descent = self.descent; - one.width = self.width; - one.userInfo = self.userInfo; - return one; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextUtilities.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextUtilities.h deleted file mode 100644 index f21a931ba8..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextUtilities.h +++ /dev/null @@ -1,316 +0,0 @@ -// -// ASTextUtilities.h -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import -#import -#import - - -#ifndef ASTEXT_CLAMP // return the clamped value -#define ASTEXT_CLAMP(_x_, _low_, _high_) (((_x_) > (_high_)) ? (_high_) : (((_x_) < (_low_)) ? (_low_) : (_x_))) -#endif - -#ifndef ASTEXT_SWAP // swap two value -#define ASTEXT_SWAP(_a_, _b_) do { __typeof__(_a_) _tmp_ = (_a_); (_a_) = (_b_); (_b_) = _tmp_; } while (0) -#endif - -NS_ASSUME_NONNULL_BEGIN - -/** - Whether the character is 'line break char': - U+000D (\\r or CR) - U+2028 (Unicode line separator) - U+000A (\\n or LF) - U+2029 (Unicode paragraph separator) - - @param c A character - @return YES or NO. - */ -static inline BOOL ASTextIsLinebreakChar(unichar c) { - switch (c) { - case 0x000D: - case 0x2028: - case 0x000A: - case 0x2029: - return YES; - default: - return NO; - } -} - -/** - Whether the string is a 'line break': - U+000D (\\r or CR) - U+2028 (Unicode line separator) - U+000A (\\n or LF) - U+2029 (Unicode paragraph separator) - \\r\\n, in that order (also known as CRLF) - - @param str A string - @return YES or NO. - */ -static inline BOOL ASTextIsLinebreakString(NSString * _Nullable str) { - if (str.length > 2 || str.length == 0) return NO; - if (str.length == 1) { - unichar c = [str characterAtIndex:0]; - return ASTextIsLinebreakChar(c); - } else { - return ([str characterAtIndex:0] == '\r') && ([str characterAtIndex:1] == '\n'); - } -} - -/** - If the string has a 'line break' suffix, return the 'line break' length. - - @param str A string. - @return The length of the tail line break: 0, 1 or 2. - */ -static inline NSUInteger ASTextLinebreakTailLength(NSString * _Nullable str) { - if (str.length >= 2) { - unichar c2 = [str characterAtIndex:str.length - 1]; - if (ASTextIsLinebreakChar(c2)) { - unichar c1 = [str characterAtIndex:str.length - 2]; - if (c1 == '\r' && c2 == '\n') return 2; - else return 1; - } else { - return 0; - } - } else if (str.length == 1) { - return ASTextIsLinebreakChar([str characterAtIndex:0]) ? 1 : 0; - } else { - return 0; - } -} - -/** - Whether the font contains color bitmap glyphs. - - @discussion Only `AppleColorEmoji` contains color bitmap glyphs in iOS system fonts. - @param font A font. - @return YES: the font contains color bitmap glyphs, NO: the font has no color bitmap glyph. - */ -static inline BOOL ASTextCTFontContainsColorBitmapGlyphs(CTFontRef font) { - return (CTFontGetSymbolicTraits(font) & kCTFontTraitColorGlyphs) != 0; -} - -/** - Get the `AppleColorEmoji` font's ascent with a specified font size. - It may used to create custom emoji. - - @param fontSize The specified font size. - @return The font ascent. - */ -static inline CGFloat ASTextEmojiGetAscentWithFontSize(CGFloat fontSize) { - if (fontSize < 16) { - return 1.25 * fontSize; - } else if (16 <= fontSize && fontSize <= 24) { - return 0.5 * fontSize + 12; - } else { - return fontSize; - } -} - -/** - Get the `AppleColorEmoji` font's descent with a specified font size. - It may used to create custom emoji. - - @param fontSize The specified font size. - @return The font descent. - */ -static inline CGFloat ASTextEmojiGetDescentWithFontSize(CGFloat fontSize) { - if (fontSize < 16) { - return 0.390625 * fontSize; - } else if (16 <= fontSize && fontSize <= 24) { - return 0.15625 * fontSize + 3.75; - } else { - return 0.3125 * fontSize; - } - return 0; -} - -/** - Get the `AppleColorEmoji` font's glyph bounding rect with a specified font size. - It may used to create custom emoji. - - @param fontSize The specified font size. - @return The font glyph bounding rect. - */ -static inline CGRect ASTextEmojiGetGlyphBoundingRectWithFontSize(CGFloat fontSize) { - CGRect rect; - rect.origin.x = 0.75; - rect.size.width = rect.size.height = ASTextEmojiGetAscentWithFontSize(fontSize); - if (fontSize < 16) { - rect.origin.y = -0.2525 * fontSize; - } else if (16 <= fontSize && fontSize <= 24) { - rect.origin.y = 0.1225 * fontSize -6; - } else { - rect.origin.y = -0.1275 * fontSize; - } - return rect; -} - - -/** - Get the character set which should rotate in vertical form. - @return The shared character set. - */ -NSCharacterSet *ASTextVerticalFormRotateCharacterSet(void); - -/** - Get the character set which should rotate and move in vertical form. - @return The shared character set. - */ -NSCharacterSet *ASTextVerticalFormRotateAndMoveCharacterSet(void); - - -/// Get the transform rotation. -/// @return the rotation in radians [-PI,PI] ([-180°,180°]) -static inline CGFloat ASTextCGAffineTransformGetRotation(CGAffineTransform transform) { - return atan2(transform.b, transform.a); -} - -/// Negates/inverts a UIEdgeInsets. -static inline UIEdgeInsets ASTextUIEdgeInsetsInvert(UIEdgeInsets insets) { - return UIEdgeInsetsMake(-insets.top, -insets.left, -insets.bottom, -insets.right); -} - -/** - Returns a rectangle to fit `rect` with specified content mode. - - @param rect The constraint rect - @param size The content size - @param mode The content mode - @return A rectangle for the given content mode. - @discussion UIViewContentModeRedraw is same as UIViewContentModeScaleToFill. - */ -CGRect ASTextCGRectFitWithContentMode(CGRect rect, CGSize size, UIViewContentMode mode); - -/// Returns the center for the rectangle. -static inline CGPoint ASTextCGRectGetCenter(CGRect rect) { - return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); -} - -/// Returns the area of the rectangle. -static inline CGFloat ASTextCGRectGetArea(CGRect rect) { - if (CGRectIsNull(rect)) return 0; - rect = CGRectStandardize(rect); - return rect.size.width * rect.size.height; -} - -/// Returns the minmium distance between a point to a rectangle. -static inline CGFloat ASTextCGPointGetDistanceToRect(CGPoint p, CGRect r) { - r = CGRectStandardize(r); - if (CGRectContainsPoint(r, p)) return 0; - CGFloat distV, distH; - if (CGRectGetMinY(r) <= p.y && p.y <= CGRectGetMaxY(r)) { - distV = 0; - } else { - distV = p.y < CGRectGetMinY(r) ? CGRectGetMinY(r) - p.y : p.y - CGRectGetMaxY(r); - } - if (CGRectGetMinX(r) <= p.x && p.x <= CGRectGetMaxX(r)) { - distH = 0; - } else { - distH = p.x < CGRectGetMinX(r) ? CGRectGetMinX(r) - p.x : p.x - CGRectGetMaxX(r); - } - return MAX(distV, distH); -} - -/// Convert point to pixel. -static inline CGFloat ASTextCGFloatToPixel(CGFloat value) { - return value * ASScreenScale(); -} - -/// Convert pixel to point. -static inline CGFloat ASTextCGFloatFromPixel(CGFloat value) { - return value / ASScreenScale(); -} - -/// round point value to .5 pixel for path stroke (odd pixel line width pixel-aligned) -static inline CGFloat ASTextCGFloatPixelHalf(CGFloat value) { - CGFloat scale = ASScreenScale(); - return (floor(value * scale) + 0.5) / scale; -} - -/// floor point value for pixel-aligned -static inline CGPoint ASTextCGPointPixelFloor(CGPoint point) { - CGFloat scale = ASScreenScale(); - return CGPointMake(floor(point.x * scale) / scale, - floor(point.y * scale) / scale); -} - -/// round point value for pixel-aligned -static inline CGPoint ASTextCGPointPixelRound(CGPoint point) { - CGFloat scale = ASScreenScale(); - return CGPointMake(round(point.x * scale) / scale, - round(point.y * scale) / scale); -} - -/// ceil point value for pixel-aligned -static inline CGPoint ASTextCGPointPixelCeil(CGPoint point) { - CGFloat scale = ASScreenScale(); - return CGPointMake(ceil(point.x * scale) / scale, - ceil(point.y * scale) / scale); -} - -/// round point value to .5 pixel for path stroke (odd pixel line width pixel-aligned) -static inline CGPoint ASTextCGPointPixelHalf(CGPoint point) { - CGFloat scale = ASScreenScale(); - return CGPointMake((floor(point.x * scale) + 0.5) / scale, - (floor(point.y * scale) + 0.5) / scale); -} - -/// round point value for pixel-aligned -static inline CGRect ASTextCGRectPixelRound(CGRect rect) { - CGPoint origin = ASTextCGPointPixelRound(rect.origin); - CGPoint corner = ASTextCGPointPixelRound(CGPointMake(rect.origin.x + rect.size.width, - rect.origin.y + rect.size.height)); - return CGRectMake(origin.x, origin.y, corner.x - origin.x, corner.y - origin.y); -} - -/// round point value to .5 pixel for path stroke (odd pixel line width pixel-aligned) -static inline CGRect ASTextCGRectPixelHalf(CGRect rect) { - CGPoint origin = ASTextCGPointPixelHalf(rect.origin); - CGPoint corner = ASTextCGPointPixelHalf(CGPointMake(rect.origin.x + rect.size.width, - rect.origin.y + rect.size.height)); - return CGRectMake(origin.x, origin.y, corner.x - origin.x, corner.y - origin.y); -} - - -static inline UIFont * _Nullable ASTextFontWithBold(UIFont *font) { - return [UIFont fontWithDescriptor:[font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold] size:font.pointSize]; -} - -static inline UIFont * _Nullable ASTextFontWithItalic(UIFont *font) { - return [UIFont fontWithDescriptor:[font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitItalic] size:font.pointSize]; -} - -static inline UIFont * _Nullable ASTextFontWithBoldItalic(UIFont *font) { - return [UIFont fontWithDescriptor:[font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold | UIFontDescriptorTraitItalic] size:font.pointSize]; -} - - - -/** - Convert CFRange to NSRange - @param range CFRange @return NSRange - */ -static inline NSRange ASTextNSRangeFromCFRange(CFRange range) { - return NSMakeRange(range.location, range.length); -} - -/** - Convert NSRange to CFRange - @param range NSRange @return CFRange - */ -static inline CFRange ASTextCFRangeFromNSRange(NSRange range) { - return CFRangeMake(range.location, range.length); -} - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextUtilities.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextUtilities.mm deleted file mode 100644 index e1b8c6d71c..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextUtilities.mm +++ /dev/null @@ -1,143 +0,0 @@ -// -// ASTextUtilities.mm -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -NSCharacterSet *ASTextVerticalFormRotateCharacterSet() { - static NSMutableCharacterSet *set; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - set = [NSMutableCharacterSet new]; - [set addCharactersInRange:NSMakeRange(0x1100, 256)]; // Hangul Jamo - [set addCharactersInRange:NSMakeRange(0x2460, 160)]; // Enclosed Alphanumerics - [set addCharactersInRange:NSMakeRange(0x2600, 256)]; // Miscellaneous Symbols - [set addCharactersInRange:NSMakeRange(0x2700, 192)]; // Dingbats - [set addCharactersInRange:NSMakeRange(0x2E80, 128)]; // CJK Radicals Supplement - [set addCharactersInRange:NSMakeRange(0x2F00, 224)]; // Kangxi Radicals - [set addCharactersInRange:NSMakeRange(0x2FF0, 16)]; // Ideographic Description Characters - [set addCharactersInRange:NSMakeRange(0x3000, 64)]; // CJK Symbols and Punctuation - [set removeCharactersInRange:NSMakeRange(0x3008, 10)]; - [set removeCharactersInRange:NSMakeRange(0x3014, 12)]; - [set addCharactersInRange:NSMakeRange(0x3040, 96)]; // Hiragana - [set addCharactersInRange:NSMakeRange(0x30A0, 96)]; // Katakana - [set addCharactersInRange:NSMakeRange(0x3100, 48)]; // Bopomofo - [set addCharactersInRange:NSMakeRange(0x3130, 96)]; // Hangul Compatibility Jamo - [set addCharactersInRange:NSMakeRange(0x3190, 16)]; // Kanbun - [set addCharactersInRange:NSMakeRange(0x31A0, 32)]; // Bopomofo Extended - [set addCharactersInRange:NSMakeRange(0x31C0, 48)]; // CJK Strokes - [set addCharactersInRange:NSMakeRange(0x31F0, 16)]; // Katakana Phonetic Extensions - [set addCharactersInRange:NSMakeRange(0x3200, 256)]; // Enclosed CJK Letters and Months - [set addCharactersInRange:NSMakeRange(0x3300, 256)]; // CJK Compatibility - [set addCharactersInRange:NSMakeRange(0x3400, 2582)]; // CJK Unified Ideographs Extension A - [set addCharactersInRange:NSMakeRange(0x4E00, 20941)]; // CJK Unified Ideographs - [set addCharactersInRange:NSMakeRange(0xAC00, 11172)]; // Hangul Syllables - [set addCharactersInRange:NSMakeRange(0xD7B0, 80)]; // Hangul Jamo Extended-B - [set addCharactersInString:@""]; // U+F8FF (Private Use Area) - [set addCharactersInRange:NSMakeRange(0xF900, 512)]; // CJK Compatibility Ideographs - [set addCharactersInRange:NSMakeRange(0xFE10, 16)]; // Vertical Forms - [set addCharactersInRange:NSMakeRange(0xFF00, 240)]; // Halfwidth and Fullwidth Forms - [set addCharactersInRange:NSMakeRange(0x1F200, 256)]; // Enclosed Ideographic Supplement - [set addCharactersInRange:NSMakeRange(0x1F300, 768)]; // Enclosed Ideographic Supplement - [set addCharactersInRange:NSMakeRange(0x1F600, 80)]; // Emoticons (Emoji) - [set addCharactersInRange:NSMakeRange(0x1F680, 128)]; // Transport and Map Symbols - - // See http://unicode-table.com/ for more information. - }); - return set; -} - -NSCharacterSet *ASTextVerticalFormRotateAndMoveCharacterSet() { - static NSMutableCharacterSet *set; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - set = [NSMutableCharacterSet new]; - [set addCharactersInString:@",。、."]; - }); - return set; -} - -CGRect ASTextCGRectFitWithContentMode(CGRect rect, CGSize size, UIViewContentMode mode) { - rect = CGRectStandardize(rect); - size.width = size.width < 0 ? -size.width : size.width; - size.height = size.height < 0 ? -size.height : size.height; - CGPoint center = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); - switch (mode) { - case UIViewContentModeScaleAspectFit: - case UIViewContentModeScaleAspectFill: { - if (rect.size.width < 0.01 || rect.size.height < 0.01 || - size.width < 0.01 || size.height < 0.01) { - rect.origin = center; - rect.size = CGSizeZero; - } else { - CGFloat scale; - if (mode == UIViewContentModeScaleAspectFit) { - if (size.width / size.height < rect.size.width / rect.size.height) { - scale = rect.size.height / size.height; - } else { - scale = rect.size.width / size.width; - } - } else { - if (size.width / size.height < rect.size.width / rect.size.height) { - scale = rect.size.width / size.width; - } else { - scale = rect.size.height / size.height; - } - } - size.width *= scale; - size.height *= scale; - rect.size = size; - rect.origin = CGPointMake(center.x - size.width * 0.5, center.y - size.height * 0.5); - } - } break; - case UIViewContentModeCenter: { - rect.size = size; - rect.origin = CGPointMake(center.x - size.width * 0.5, center.y - size.height * 0.5); - } break; - case UIViewContentModeTop: { - rect.origin.x = center.x - size.width * 0.5; - rect.size = size; - } break; - case UIViewContentModeBottom: { - rect.origin.x = center.x - size.width * 0.5; - rect.origin.y += rect.size.height - size.height; - rect.size = size; - } break; - case UIViewContentModeLeft: { - rect.origin.y = center.y - size.height * 0.5; - rect.size = size; - } break; - case UIViewContentModeRight: { - rect.origin.y = center.y - size.height * 0.5; - rect.origin.x += rect.size.width - size.width; - rect.size = size; - } break; - case UIViewContentModeTopLeft: { - rect.size = size; - } break; - case UIViewContentModeTopRight: { - rect.origin.x += rect.size.width - size.width; - rect.size = size; - } break; - case UIViewContentModeBottomLeft: { - rect.origin.y += rect.size.height - size.height; - rect.size = size; - } break; - case UIViewContentModeBottomRight: { - rect.origin.x += rect.size.width - size.width; - rect.origin.y += rect.size.height - size.height; - rect.size = size; - } break; - case UIViewContentModeScaleToFill: - case UIViewContentModeRedraw: - default: { - rect = rect; - } - } - return rect; -} diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTraceEvent.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTraceEvent.h deleted file mode 100644 index 72249faea9..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTraceEvent.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// ASTraceEvent.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -AS_SUBCLASSING_RESTRICTED -@interface ASTraceEvent : NSObject - -/** - * This method is dealloc safe. - */ -- (instancetype)initWithBacktrace:(nullable NSArray *)backtrace - format:(NSString *)format - arguments:(va_list)arguments NS_FORMAT_FUNCTION(2,0); - -// Will be nil unless AS_SAVE_EVENT_BACKTRACES=1 (default=0) -@property (nonatomic, nullable, readonly) NSArray *backtrace; -@property (nonatomic, readonly) NSString *message; -@property (nonatomic, readonly) NSTimeInterval timestamp; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTraceEvent.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTraceEvent.mm deleted file mode 100644 index c809865591..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTraceEvent.mm +++ /dev/null @@ -1,67 +0,0 @@ -// -// ASTraceEvent.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -static NSString *const ASTraceEventThreadDescriptionKey = @"ASThreadTraceEventDescription"; - -@interface ASTraceEvent () -@property (nonatomic, readonly) NSString *objectDescription; -@property (nonatomic, readonly) NSString *threadDescription; -@end - -@implementation ASTraceEvent - -- (instancetype)initWithBacktrace:(NSArray *)backtrace format:(NSString *)format arguments:(va_list)args -{ - self = [super init]; - if (self != nil) { - static NSTimeInterval refTime; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - refTime = CACurrentMediaTime(); - }); - - // Create the format string passed to us. - _message = [[NSString alloc] initWithFormat:format arguments:args]; - - NSThread *thread = [NSThread currentThread]; - NSString *threadDescription = thread.name; - if (threadDescription.length == 0) { - if ([thread isMainThread]) { - threadDescription = @"Main"; - } else { - // If the bg thread has no name, we cache a 4-character ptr string to identify it by - // inside the thread dictionary. - NSMutableDictionary *threadDict = thread.threadDictionary; - threadDescription = threadDict[ASTraceEventThreadDescriptionKey]; - if (threadDescription == nil) { - // Want these to be 4-chars to line up with "Main". It's possible that a collision could happen - // here but it's so unbelievably likely to impact development, the risk is acceptable. - NSString *ptrString = [NSString stringWithFormat:@"%p", thread]; - threadDescription = [ptrString substringFromIndex:MAX(0, ptrString.length - 4)]; - threadDict[ASTraceEventThreadDescriptionKey] = threadDescription; - } - } - } - _threadDescription = threadDescription; - - _backtrace = backtrace; - _timestamp = CACurrentMediaTime() - refTime; - } - return self; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"<(%@) t=%7.3f: %@>", _threadDescription, _timestamp, _message]; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTwoDimensionalArrayUtils.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTwoDimensionalArrayUtils.h deleted file mode 100644 index 6a3c9bb5ce..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTwoDimensionalArrayUtils.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// ASTwoDimensionalArrayUtils.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - * Helper functions for two-dimensional array, where the objects of the root array are each arrays. - */ - -/** - * Deep mutable copy of an array that contains arrays, which contain objects. It will go one level deep into the array to copy. - * This method is substantially faster than the generalized version, e.g. about 10x faster, so use it whenever it fits the need. - */ -AS_EXTERN NSMutableArray *ASTwoDimensionalArrayDeepMutableCopy(NSArray *array) AS_WARN_UNUSED_RESULT; - -/** - * Delete the elements of the mutable two-dimensional array at given index paths – sorted in descending order! - */ -AS_EXTERN void ASDeleteElementsInTwoDimensionalArrayAtIndexPaths(NSMutableArray *mutableArray, NSArray *indexPaths); - -/** - * Return all the index paths of a two-dimensional array, in ascending order. - */ -AS_EXTERN NSArray *ASIndexPathsForTwoDimensionalArray(NSArray* twoDimensionalArray) AS_WARN_UNUSED_RESULT; - -/** - * Return all the elements of a two-dimensional array, in ascending order. - */ -AS_EXTERN NSArray *ASElementsInTwoDimensionalArray(NSArray* twoDimensionalArray) AS_WARN_UNUSED_RESULT; - -/** - * Attempt to get the object at the given index path. Returns @c nil if the index path is out of bounds. - */ -AS_EXTERN id _Nullable ASGetElementInTwoDimensionalArray(NSArray *array, NSIndexPath *indexPath) AS_WARN_UNUSED_RESULT; - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTwoDimensionalArrayUtils.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTwoDimensionalArrayUtils.mm deleted file mode 100644 index 0527580df1..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTwoDimensionalArrayUtils.mm +++ /dev/null @@ -1,122 +0,0 @@ -// -// ASTwoDimensionalArrayUtils.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import -#import - -#import - -// Import UIKit to get [NSIndexPath indexPathForItem:inSection:] which uses -// tagged pointers. -#import - -#pragma mark - Public Methods - -NSMutableArray *ASTwoDimensionalArrayDeepMutableCopy(NSArray *array) -{ - NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:array.count]; - NSInteger i = 0; - for (NSArray *subarray in array) { - ASDisplayNodeCAssert([subarray isKindOfClass:[NSArray class]], @"This function expects NSArray *"); - newArray[i++] = [subarray mutableCopy]; - } - return newArray; -} - -void ASDeleteElementsInTwoDimensionalArrayAtIndexPaths(NSMutableArray *mutableArray, NSArray *indexPaths) -{ - if (indexPaths.count == 0) { - return; - } - -#if ASDISPLAYNODE_ASSERTIONS_ENABLED - NSArray *sortedIndexPaths = [indexPaths sortedArrayUsingSelector:@selector(asdk_inverseCompare:)]; - ASDisplayNodeCAssert([sortedIndexPaths isEqualToArray:indexPaths], @"Expected array of index paths to be sorted in descending order."); -#endif - - /** - * It is tempting to do something clever here and collect indexes into ranges or NSIndexSets - * but deep down, __NSArrayM only implements removeObjectAtIndex: and so doing all that extra - * work ends up running the same code. - */ - for (NSIndexPath *indexPath in indexPaths) { - NSInteger section = indexPath.section; - if (section >= mutableArray.count) { - ASDisplayNodeCFailAssert(@"Invalid section index %ld – only %ld sections", (long)section, (long)mutableArray.count); - continue; - } - - NSMutableArray *subarray = mutableArray[section]; - NSInteger item = indexPath.item; - if (item >= subarray.count) { - ASDisplayNodeCFailAssert(@"Invalid item index %ld – only %ld items in section %ld", (long)item, (long)subarray.count, (long)section); - continue; - } - [subarray removeObjectAtIndex:item]; - } -} - -NSArray *ASIndexPathsForTwoDimensionalArray(NSArray * twoDimensionalArray) -{ - NSInteger sectionCount = twoDimensionalArray.count; - NSInteger counts[sectionCount]; - NSInteger totalCount = 0; - NSInteger i = 0; - for (NSArray *subarray in twoDimensionalArray) { - NSInteger count = subarray.count; - counts[i++] = count; - totalCount += count; - } - - // Count could be huge. Use a reserved vector rather than VLA (stack.) - std::vector indexPaths; - indexPaths.reserve(totalCount); - for (NSInteger i = 0; i < sectionCount; i++) { - for (NSInteger j = 0; j < counts[i]; j++) { - indexPaths.push_back([NSIndexPath indexPathForItem:j inSection:i]); - } - } - return [NSArray arrayByTransferring:indexPaths.data() count:totalCount]; -} - -NSArray *ASElementsInTwoDimensionalArray(NSArray * twoDimensionalArray) -{ - NSInteger totalCount = 0; - for (NSArray *subarray in twoDimensionalArray) { - totalCount += subarray.count; - } - - std::vector elements; - elements.reserve(totalCount); - for (NSArray *subarray in twoDimensionalArray) { - for (id object in subarray) { - elements.push_back(object); - } - } - return [NSArray arrayByTransferring:elements.data() count:totalCount]; -} - -id ASGetElementInTwoDimensionalArray(NSArray *array, NSIndexPath *indexPath) -{ - ASDisplayNodeCAssertNotNil(indexPath, @"Expected non-nil index path"); - ASDisplayNodeCAssert(indexPath.length == 2, @"Expected index path of length 2. Index path: %@", indexPath); - NSInteger section = indexPath.section; - if (array.count <= section) { - return nil; - } - - NSArray *innerArray = array[section]; - NSInteger item = indexPath.item; - if (innerArray.count <= item) { - return nil; - } - return innerArray[item]; -} diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASVisibilityProtocols.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASVisibilityProtocols.h deleted file mode 100644 index 837e848269..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASVisibilityProtocols.h +++ /dev/null @@ -1,145 +0,0 @@ -// -// ASVisibilityProtocols.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@class UIViewController; - -AS_EXTERN ASLayoutRangeMode ASLayoutRangeModeForVisibilityDepth(NSUInteger visibilityDepth); - -/** - * ASVisibilityDepth - * - * @discussion "Visibility Depth" represents the number of user actions required to make an ASDisplayNode or - * ASViewController visibile. AsyncDisplayKit uses this information to intelligently manage memory and focus - * resources where they are most visible to the user. - * - * The ASVisibilityDepth protocol describes how custom view controllers can integrate with this system. - * - * Parent view controllers should also implement @c ASManagesChildVisibilityDepth - * - * @see ASManagesChildVisibilityDepth - */ - -@protocol ASVisibilityDepth - -/** - * Visibility depth - * - * @discussion Represents the number of user actions necessary to reach the view controller. An increased visibility - * depth indicates a higher number of user interactions for the view controller to be visible again. For example, - * an onscreen navigation controller's top view controller should have a visibility depth of 0. The view controller - * one from the top should have a visibility deptch of 1 as should the root view controller in the stack (because - * the user can hold the back button to pop to the root view controller). - * - * Visibility depth is used to automatically adjust ranges on range controllers (and thus free up memory) and can - * be used to reduce memory usage of other items as well. - */ -- (NSInteger)visibilityDepth; - -/** - * Called when visibility depth changes - * - * @discussion @c visibilityDepthDidChange is called whenever the visibility depth of the represented view controller - * has changed. - * - * If implemented by a view controller container, use this method to notify child view controllers that their view - * depth has changed @see ASNavigationController.m - * - * If implemented on an ASViewController, use this method to reduce or increase the resources that your - * view controller uses. A higher visibility depth view controller should decrease it's resource usage, a lower - * visibility depth controller should pre-warm resources in preperation for a display at 0 depth. - * - * ASViewController implements this method and reduces / increases range mode of supporting nodes (such as ASCollectionNode - * and ASTableNode). - * - * @see visibilityDepth - */ -- (void)visibilityDepthDidChange; - -@end - -/** - * ASManagesChildVisibilityDepth - * - * @discussion A protocol which should be implemented by container view controllers to allow proper - * propagation of visibility depth - * - * @see ASVisibilityDepth - */ -@protocol ASManagesChildVisibilityDepth - -/** - * @abstract Container view controllers should adopt this protocol to indicate that they will manage their child's - * visibilityDepth. For example, ASNavigationController adopts this protocol and manages its childrens visibility - * depth. - * - * If you adopt this protocol, you *must* also emit visibilityDepthDidChange messages to child view controllers. - * - * @param childViewController Expected to return the visibility depth of the child view controller. - */ -- (NSInteger)visibilityDepthOfChildViewController:(UIViewController *)childViewController; - -@end - -#define ASVisibilitySetVisibilityDepth \ -- (void)setVisibilityDepth:(NSUInteger)visibilityDepth \ -{ \ - if (_visibilityDepth == visibilityDepth) { \ - return; \ - } \ - _visibilityDepth = visibilityDepth; \ - [self visibilityDepthDidChange]; \ -} - -#define ASVisibilityDepthImplementation \ -- (NSInteger)visibilityDepth \ -{ \ - if (self.parentViewController && _parentManagesVisibilityDepth == NO) { \ - _parentManagesVisibilityDepth = [self.parentViewController conformsToProtocol:@protocol(ASManagesChildVisibilityDepth)]; \ - } \ - \ - if (_parentManagesVisibilityDepth) { \ - return [(id )self.parentViewController visibilityDepthOfChildViewController:self]; \ - } \ - return _visibilityDepth; \ -} - -#define ASVisibilityViewDidDisappearImplementation \ -- (void)viewDidDisappear:(BOOL)animated \ -{ \ - [super viewDidDisappear:animated]; \ - \ - if (_parentManagesVisibilityDepth == NO) { \ - [self setVisibilityDepth:1]; \ - } \ -} - -#define ASVisibilityViewWillAppear \ -- (void)viewWillAppear:(BOOL)animated \ -{ \ - [super viewWillAppear:animated]; \ - \ - if (_parentManagesVisibilityDepth == NO) { \ - [self setVisibilityDepth:0]; \ - } \ -} - -#define ASVisibilityDidMoveToParentViewController \ -- (void)didMoveToParentViewController:(UIViewController *)parent \ -{ \ - [super didMoveToParentViewController:parent]; \ - _parentManagesVisibilityDepth = NO; \ - [self visibilityDepthDidChange]; \ -} - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASVisibilityProtocols.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASVisibilityProtocols.mm deleted file mode 100644 index b13a683bea..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASVisibilityProtocols.mm +++ /dev/null @@ -1,22 +0,0 @@ -// -// ASVisibilityProtocols.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -ASLayoutRangeMode ASLayoutRangeModeForVisibilityDepth(NSUInteger visibilityDepth) -{ - if (visibilityDepth == 0) { - return ASLayoutRangeModeFull; - } else if (visibilityDepth == 1) { - return ASLayoutRangeModeMinimum; - } else if (visibilityDepth == 2) { - return ASLayoutRangeModeVisibleOnly; - } - return ASLayoutRangeModeLowMemory; -} diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSAttributedString+ASText.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSAttributedString+ASText.h deleted file mode 100644 index ef44fb4f35..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSAttributedString+ASText.h +++ /dev/null @@ -1,1375 +0,0 @@ -// -// NSAttributedString+ASText.h -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - Get pre-defined attributes from attributed string. - All properties defined in UIKit, CoreText and ASText are included. - */ -@interface NSAttributedString (ASText) - -#pragma mark - Retrieving character attribute information -///============================================================================= -/// @name Retrieving character attribute information -///============================================================================= - -/** - Returns the attributes at first charactor. - */ -@property (nullable, nonatomic, copy, readonly) NSDictionary *as_attributes; - -/** - Returns the attributes for the character at a given index. - - @discussion Raises an `NSRangeException` if index lies beyond the end of the - receiver's characters. - - @param index The index for which to return attributes. - This value must lie within the bounds of the receiver. - - @return The attributes for the character at index. - */ -- (nullable NSDictionary *)as_attributesAtIndex:(NSUInteger)index; - -/** - Returns the value for an attribute with a given name of the character at a given index. - - @discussion Raises an `NSRangeException` if index lies beyond the end of the - receiver's characters. - - @param attributeName The name of an attribute. - @param index The index for which to return attributes. - This value must not exceed the bounds of the receiver. - - @return The value for the attribute named `attributeName` of the character at - index `index`, or nil if there is no such attribute. - */ -- (nullable id)as_attribute:(NSString *)attributeName atIndex:(NSUInteger)index; - - -#pragma mark - Get character attribute as property -///============================================================================= -/// @name Get character attribute as property -///============================================================================= - -/** - The font of the text. (read-only) - - @discussion Default is Helvetica (Neue) 12. - @discussion Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic, readonly) UIFont *as_font; -- (nullable UIFont *)as_fontAtIndex:(NSUInteger)index; - -/** - A kerning adjustment. (read-only) - - @discussion Default is standard kerning. The kerning attribute indicate how many - points the following character should be shifted from its default offset as - defined by the current character's font in points; a positive kern indicates a - shift farther along and a negative kern indicates a shift closer to the current - character. If this attribute is not present, standard kerning will be used. - If this attribute is set to 0.0, no kerning will be done at all. - @discussion Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic, readonly) NSNumber *as_kern; -- (nullable NSNumber *)as_kernAtIndex:(NSUInteger)index; - -/** - The foreground color. (read-only) - - @discussion Default is Black. - @discussion Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic, readonly) UIColor *as_color; -- (nullable UIColor *)as_colorAtIndex:(NSUInteger)index; - -/** - The background color. (read-only) - - @discussion Default is nil (or no background). - @discussion Get this property returns the first character's attribute. - @since UIKit:6.0 - */ -@property (nullable, nonatomic, readonly) UIColor *as_backgroundColor; -- (nullable UIColor *)as_backgroundColorAtIndex:(NSUInteger)index; - -/** - The stroke width. (read-only) - - @discussion Default value is 0.0 (no stroke). This attribute, interpreted as - a percentage of font point size, controls the text drawing mode: positive - values effect drawing with stroke only; negative values are for stroke and fill. - A typical value for outlined text is 3.0. - @discussion Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 - */ -@property (nullable, nonatomic, readonly) NSNumber *as_strokeWidth; -- (nullable NSNumber *)as_strokeWidthAtIndex:(NSUInteger)index; - -/** - The stroke color. (read-only) - - @discussion Default value is nil (same as foreground color). - @discussion Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 - */ -@property (nullable, nonatomic, readonly) UIColor *as_strokeColor; -- (nullable UIColor *)as_strokeColorAtIndex:(NSUInteger)index; - -/** - The text shadow. (read-only) - - @discussion Default value is nil (no shadow). - @discussion Get this property returns the first character's attribute. - @since UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic, readonly) NSShadow *as_shadow; -- (nullable NSShadow *)as_shadowAtIndex:(NSUInteger)index; - -/** - The strikethrough style. (read-only) - - @discussion Default value is NSUnderlineStyleNone (no strikethrough). - @discussion Get this property returns the first character's attribute. - @since UIKit:6.0 - */ -@property (nonatomic, readonly) NSUnderlineStyle as_strikethroughStyle; -- (NSUnderlineStyle)as_strikethroughStyleAtIndex:(NSUInteger)index; - -/** - The strikethrough color. (read-only) - - @discussion Default value is nil (same as foreground color). - @discussion Get this property returns the first character's attribute. - @since UIKit:7.0 - */ -@property (nullable, nonatomic, readonly) UIColor *as_strikethroughColor; -- (nullable UIColor *)as_strikethroughColorAtIndex:(NSUInteger)index; - -/** - The underline style. (read-only) - - @discussion Default value is NSUnderlineStyleNone (no underline). - @discussion Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 - */ -@property (nonatomic, readonly) NSUnderlineStyle as_underlineStyle; -- (NSUnderlineStyle)as_underlineStyleAtIndex:(NSUInteger)index; - -/** - The underline color. (read-only) - - @discussion Default value is nil (same as foreground color). - @discussion Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:7.0 - */ -@property (nullable, nonatomic, readonly) UIColor *as_underlineColor; -- (nullable UIColor *)as_underlineColorAtIndex:(NSUInteger)index; - -/** - Ligature formation control. (read-only) - - @discussion Default is int value 1. The ligature attribute determines what kinds - of ligatures should be used when displaying the string. A value of 0 indicates - that only ligatures essential for proper rendering of text should be used, - 1 indicates that standard ligatures should be used, and 2 indicates that all - available ligatures should be used. Which ligatures are standard depends on the - script and possibly the font. - @discussion Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic, readonly) NSNumber *as_ligature; -- (nullable NSNumber *)as_ligatureAtIndex:(NSUInteger)index; - -/** - The text effect. (read-only) - - @discussion Default is nil (no effect). The only currently supported value - is NSTextEffectLetterpressStyle. - @discussion Get this property returns the first character's attribute. - @since UIKit:7.0 - */ -@property (nullable, nonatomic, readonly) NSString *as_textEffect; -- (nullable NSString *)as_textEffectAtIndex:(NSUInteger)index; - -/** - The skew to be applied to glyphs. (read-only) - - @discussion Default is 0 (no skew). - @discussion Get this property returns the first character's attribute. - @since UIKit:7.0 - */ -@property (nullable, nonatomic, readonly) NSNumber *as_obliqueness; -- (nullable NSNumber *)as_obliquenessAtIndex:(NSUInteger)index; - -/** - The log of the expansion factor to be applied to glyphs. (read-only) - - @discussion Default is 0 (no expansion). - @discussion Get this property returns the first character's attribute. - @since UIKit:7.0 - */ -@property (nullable, nonatomic, readonly) NSNumber *as_expansion; -- (nullable NSNumber *)as_expansionAtIndex:(NSUInteger)index; - -/** - The character's offset from the baseline, in points. (read-only) - - @discussion Default is 0. - @discussion Get this property returns the first character's attribute. - @since UIKit:7.0 - */ -@property (nullable, nonatomic, readonly) NSNumber *as_baselineOffset; -- (nullable NSNumber *)as_baselineOffsetAtIndex:(NSUInteger)index; - -/** - Glyph orientation control. (read-only) - - @discussion Default is NO. A value of NO indicates that horizontal glyph forms - are to be used, YES indicates that vertical glyph forms are to be used. - @discussion Get this property returns the first character's attribute. - @since CoreText:4.3 ASText:6.0 - */ -@property (nonatomic, readonly) BOOL as_verticalGlyphForm; -- (BOOL)as_verticalGlyphFormAtIndex:(NSUInteger)index; - -/** - Specifies text language. (read-only) - - @discussion Value must be a NSString containing a locale identifier. Default is - unset. When this attribute is set to a valid identifier, it will be used to select - localized glyphs (if supported by the font) and locale-specific line breaking rules. - @discussion Get this property returns the first character's attribute. - @since CoreText:7.0 ASText:7.0 - */ -@property (nullable, nonatomic, readonly) NSString *as_language; -- (nullable NSString *)as_languageAtIndex:(NSUInteger)index; - -/** - Specifies a bidirectional override or embedding. (read-only) - - @discussion See alse NSWritingDirection and NSWritingDirectionAttributeName. - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:7.0 ASText:6.0 - */ -@property (nullable, nonatomic, readonly) NSArray *as_writingDirection; -- (nullable NSArray *)as_writingDirectionAtIndex:(NSUInteger)index; - -/** - An NSParagraphStyle object which is used to specify things like - line alignment, tab rulers, writing direction, etc. (read-only) - - @discussion Default is nil ([NSParagraphStyle defaultParagraphStyle]). - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic, readonly) NSParagraphStyle *as_paragraphStyle; -- (nullable NSParagraphStyle *)as_paragraphStyleAtIndex:(NSUInteger)index; - -#pragma mark - Get paragraph attribute as property -///============================================================================= -/// @name Get paragraph attribute as property -///============================================================================= - -/** - The text alignment (A wrapper for NSParagraphStyle). (read-only) - - @discussion Natural text alignment is realized as left or right alignment - depending on the line sweep direction of the first script contained in the paragraph. - @discussion Default is NSTextAlignmentNatural. - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) NSTextAlignment as_alignment; -- (NSTextAlignment)as_alignmentAtIndex:(NSUInteger)index; - -/** - The mode that should be used to break lines (A wrapper for NSParagraphStyle). (read-only) - - @discussion This property contains the line break mode to be used laying out the paragraph's text. - @discussion Default is NSLineBreakByWordWrapping. - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) NSLineBreakMode as_lineBreakMode; -- (NSLineBreakMode)as_lineBreakModeAtIndex:(NSUInteger)index; - -/** - The distance in points between the bottom of one line fragment and the top of the next. - (A wrapper for NSParagraphStyle) (read-only) - - @discussion This value is always nonnegative. This value is included in the line - fragment heights in the layout manager. - @discussion Default is 0. - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) CGFloat as_lineSpacing; -- (CGFloat)as_lineSpacingAtIndex:(NSUInteger)index; - -/** - The space after the end of the paragraph (A wrapper for NSParagraphStyle). (read-only) - - @discussion This property contains the space (measured in points) added at the - end of the paragraph to separate it from the following paragraph. This value must - be nonnegative. The space between paragraphs is determined by adding the previous - paragraph's paragraphSpacing and the current paragraph's paragraphSpacingBefore. - @discussion Default is 0. - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) CGFloat as_paragraphSpacing; -- (CGFloat)as_paragraphSpacingAtIndex:(NSUInteger)index; - -/** - The distance between the paragraph's top and the beginning of its text content. - (A wrapper for NSParagraphStyle). (read-only) - - @discussion This property contains the space (measured in points) between the - paragraph's top and the beginning of its text content. - @discussion Default is 0. - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) CGFloat as_paragraphSpacingBefore; -- (CGFloat)as_paragraphSpacingBeforeAtIndex:(NSUInteger)index; - -/** - The indentation of the first line (A wrapper for NSParagraphStyle). (read-only) - - @discussion This property contains the distance (in points) from the leading margin - of a text container to the beginning of the paragraph's first line. This value - is always nonnegative. - @discussion Default is 0. - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) CGFloat as_firstLineHeadIndent; -- (CGFloat)as_firstLineHeadIndentAtIndex:(NSUInteger)index; - -/** - The indentation of the receiver's lines other than the first. (A wrapper for NSParagraphStyle). (read-only) - - @discussion This property contains the distance (in points) from the leading margin - of a text container to the beginning of lines other than the first. This value is - always nonnegative. - @discussion Default is 0. - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) CGFloat as_headIndent; -- (CGFloat)as_headIndentAtIndex:(NSUInteger)index; - -/** - The trailing indentation (A wrapper for NSParagraphStyle). (read-only) - - @discussion If positive, this value is the distance from the leading margin - (for example, the left margin in left-to-right text). If 0 or negative, it's the - distance from the trailing margin. - @discussion Default is 0. - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) CGFloat as_tailIndent; -- (CGFloat)as_tailIndentAtIndex:(NSUInteger)index; - -/** - The receiver's minimum height (A wrapper for NSParagraphStyle). (read-only) - - @discussion This property contains the minimum height in points that any line in - the receiver will occupy, regardless of the font size or size of any attached graphic. - This value must be nonnegative. - @discussion Default is 0. - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) CGFloat as_minimumLineHeight; -- (CGFloat)as_minimumLineHeightAtIndex:(NSUInteger)index; - -/** - The receiver's maximum line height (A wrapper for NSParagraphStyle). (read-only) - - @discussion This property contains the maximum height in points that any line in - the receiver will occupy, regardless of the font size or size of any attached graphic. - This value is always nonnegative. Glyphs and graphics exceeding this height will - overlap neighboring lines; however, a maximum height of 0 implies no line height limit. - Although this limit applies to the line itself, line spacing adds extra space between adjacent lines. - @discussion Default is 0 (no limit). - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) CGFloat as_maximumLineHeight; -- (CGFloat)as_maximumLineHeightAtIndex:(NSUInteger)index; - -/** - The line height multiple (A wrapper for NSParagraphStyle). (read-only) - - @discussion This property contains the line break mode to be used laying out the paragraph's text. - @discussion Default is 0 (no multiple). - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) CGFloat as_lineHeightMultiple; -- (CGFloat)as_lineHeightMultipleAtIndex:(NSUInteger)index; - -/** - The base writing direction (A wrapper for NSParagraphStyle). (read-only) - - @discussion If you specify NSWritingDirectionNaturalDirection, the receiver resolves - the writing direction to either NSWritingDirectionLeftToRight or NSWritingDirectionRightToLeft, - depending on the direction for the user's `language` preference setting. - @discussion Default is NSWritingDirectionNatural. - @discussion Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic, readonly) NSWritingDirection as_baseWritingDirection; -- (NSWritingDirection)as_baseWritingDirectionAtIndex:(NSUInteger)index; - -/** - The paragraph's threshold for hyphenation. (A wrapper for NSParagraphStyle). (read-only) - - @discussion Valid values lie between 0.0 and 1.0 inclusive. Hyphenation is attempted - when the ratio of the text width (as broken without hyphenation) to the width of the - line fragment is less than the hyphenation factor. When the paragraph's hyphenation - factor is 0.0, the layout manager's hyphenation factor is used instead. When both - are 0.0, hyphenation is disabled. - @discussion Default is 0. - @discussion Get this property returns the first character's attribute. - @since UIKit:6.0 - */ -@property (nonatomic, readonly) float as_hyphenationFactor; -- (float)as_hyphenationFactorAtIndex:(NSUInteger)index; - -/** - The document-wide default tab interval (A wrapper for NSParagraphStyle). (read-only) - - @discussion This property represents the default tab interval in points. Tabs after the - last specified in tabStops are placed at integer multiples of this distance (if positive). - @discussion Default is 0. - @discussion Get this property returns the first character's attribute. - @since CoreText:7.0 UIKit:7.0 ASText:7.0 - */ -@property (nonatomic, readonly) CGFloat as_defaultTabInterval; -- (CGFloat)as_defaultTabIntervalAtIndex:(NSUInteger)index; - -/** - An array of NSTextTab objects representing the receiver's tab stops. - (A wrapper for NSParagraphStyle). (read-only) - - @discussion The NSTextTab objects, sorted by location, define the tab stops for - the paragraph style. - @discussion Default is 12 TabStops with 28.0 tab interval. - @discussion Get this property returns the first character's attribute. - @since CoreText:7.0 UIKit:7.0 ASText:7.0 - */ -@property (nullable, nonatomic, copy, readonly) NSArray *as_tabStops; -- (nullable NSArray *)as_tabStopsAtIndex:(NSUInteger)index; - -#pragma mark - Get ASText attribute as property -///============================================================================= -/// @name Get ASText attribute as property -///============================================================================= - -/** - The text shadow. (read-only) - - @discussion Default value is nil (no shadow). - @discussion Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic, readonly) ASTextShadow *as_textShadow; -- (nullable ASTextShadow *)as_textShadowAtIndex:(NSUInteger)index; - -/** - The text inner shadow. (read-only) - - @discussion Default value is nil (no shadow). - @discussion Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic, readonly) ASTextShadow *as_textInnerShadow; -- (nullable ASTextShadow *)as_textInnerShadowAtIndex:(NSUInteger)index; - -/** - The text underline. (read-only) - - @discussion Default value is nil (no underline). - @discussion Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic, readonly) ASTextDecoration *as_textUnderline; -- (nullable ASTextDecoration *)as_textUnderlineAtIndex:(NSUInteger)index; - -/** - The text strikethrough. (read-only) - - @discussion Default value is nil (no strikethrough). - @discussion Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic, readonly) ASTextDecoration *as_textStrikethrough; -- (nullable ASTextDecoration *)as_textStrikethroughAtIndex:(NSUInteger)index; - -/** - The text border. (read-only) - - @discussion Default value is nil (no border). - @discussion Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic, readonly) ASTextBorder *as_textBorder; -- (nullable ASTextBorder *)as_textBorderAtIndex:(NSUInteger)index; - -/** - The text background border. (read-only) - - @discussion Default value is nil (no background border). - @discussion Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic, readonly) ASTextBorder *as_textBackgroundBorder; -- (nullable ASTextBorder *)as_textBackgroundBorderAtIndex:(NSUInteger)index; - -/** - The glyph transform. (read-only) - - @discussion Default value is CGAffineTransformIdentity (no transform). - @discussion Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nonatomic, readonly) CGAffineTransform as_textGlyphTransform; -- (CGAffineTransform)as_textGlyphTransformAtIndex:(NSUInteger)index; - - -#pragma mark - Query for ASText -///============================================================================= -/// @name Query for ASText -///============================================================================= - -/** - Returns the plain text from a range. - If there's `ASTextBackedStringAttributeName` attribute, the backed string will - replace the attributed string range. - - @param range A range in receiver. - @return The plain text. - */ -- (nullable NSString *)as_plainTextForRange:(NSRange)range; - - -#pragma mark - Create attachment string for ASText -///============================================================================= -/// @name Create attachment string for ASText -///============================================================================= - -/** - Creates and returns an attachment. - - @param content The attachment (UIImage/UIView/CALayer). - @param contentMode The attachment's content mode. - @param width The attachment's container width in layout. - @param ascent The attachment's container ascent in layout. - @param descent The attachment's container descent in layout. - - @return An attributed string, or nil if an error occurs. - @since ASText:6.0 - */ -+ (NSMutableAttributedString *)as_attachmentStringWithContent:(nullable id)content - contentMode:(UIViewContentMode)contentMode - width:(CGFloat)width - ascent:(CGFloat)ascent - descent:(CGFloat)descent; - -/** - Creates and returns an attachment. - - - Example: ContentMode:bottom Alignment:Top. - - The text The attachment holder - ↓ ↓ - ─────────┌──────────────────────┐─────── - / \ │ │ / ___| - / _ \ │ │| | - / ___ \ │ │| |___ ←── The text line - /_/ \_\│ ██████████████ │ \____| - ─────────│ ██████████████ │─────── - │ ██████████████ │ - │ ██████████████ ←───────────────── The attachment content - │ ██████████████ │ - └──────────────────────┘ - - @param content The attachment (UIImage/UIView/CALayer). - @param contentMode The attachment's content mode in attachment holder - @param attachmentSize The attachment holder's size in text layout. - @param font The attachment will align to this font. - @param alignment The attachment holder's alignment to text line. - - @return An attributed string, or nil if an error occurs. - @since ASText:6.0 - */ -+ (NSMutableAttributedString *)as_attachmentStringWithContent:(nullable id)content - contentMode:(UIViewContentMode)contentMode - attachmentSize:(CGSize)attachmentSize - alignToFont:(UIFont *)font - alignment:(ASTextVerticalAlignment)alignment; - -/** - Creates and returns an attahment from a fourquare image as if it was an emoji. - - @param image A fourquare image. - @param fontSize The font size. - - @return An attributed string, or nil if an error occurs. - @since ASText:6.0 - */ -+ (nullable NSMutableAttributedString *)as_attachmentStringWithEmojiImage:(UIImage *)image - fontSize:(CGFloat)fontSize; - -#pragma mark - Utility -///============================================================================= -/// @name Utility -///============================================================================= - -/** - Returns NSMakeRange(0, self.length). - */ -- (NSRange)as_rangeOfAll; - -/** - If YES, it share the same attribute in entire text range. - */ -- (BOOL)as_isSharedAttributesInAllRange; - -/** - If YES, it can be drawn with the [drawWithRect:options:context:] method or displayed with UIKit. - If NO, it should be drawn with CoreText or ASText. - - @discussion If the method returns NO, it means that there's at least one attribute - which is not supported by UIKit (such as CTParagraphStyleRef). If display this string - in UIKit, it may lose some attribute, or even crash the app. - */ -- (BOOL)as_canDrawWithUIKit; - -@end - - - - -/** - Set pre-defined attributes to attributed string. - All properties defined in UIKit, CoreText and ASText are included. - */ -@interface NSMutableAttributedString (ASText) - -#pragma mark - Set character attribute -///============================================================================= -/// @name Set character attribute -///============================================================================= - -/** - Sets the attributes to the entire text string. - - @discussion The old attributes will be removed. - - @param attributes A dictionary containing the attributes to set, or nil to remove all attributes. - */ -- (void)as_setAttributes:(nullable NSDictionary *)attributes; -- (void)setAs_attributes:(nullable NSDictionary *)attributes; - -/** - Sets an attribute with the given name and value to the entire text string. - - @param name A string specifying the attribute name. - @param value The attribute value associated with name. Pass `nil` or `NSNull` to - remove the attribute. - */ -- (void)as_setAttribute:(NSString *)name value:(nullable id)value; - -/** - Sets an attribute with the given name and value to the characters in the specified range. - - @param name A string specifying the attribute name. - @param value The attribute value associated with name. Pass `nil` or `NSNull` to - remove the attribute. - @param range The range of characters to which the specified attribute/value pair applies. - */ -- (void)as_setAttribute:(NSString *)name value:(nullable id)value range:(NSRange)range; - -/** - Removes all attributes in the specified range. - - @param range The range of characters. - */ -- (void)as_removeAttributesInRange:(NSRange)range; - - -#pragma mark - Set character attribute as property -///============================================================================= -/// @name Set character attribute as property -///============================================================================= - -/** - The font of the text. - - @discussion Default is Helvetica (Neue) 12. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic) UIFont *as_font; -- (void)as_setFont:(nullable UIFont *)font range:(NSRange)range; - -/** - A kerning adjustment. - - @discussion Default is standard kerning. The kerning attribute indicate how many - points the following character should be shifted from its default offset as - defined by the current character's font in points; a positive kern indicates a - shift farther along and a negative kern indicates a shift closer to the current - character. If this attribute is not present, standard kerning will be used. - If this attribute is set to 0.0, no kerning will be done at all. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic) NSNumber *as_kern; -- (void)as_setKern:(nullable NSNumber *)kern range:(NSRange)range; - -/** - The foreground color. - - @discussion Default is Black. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic) UIColor *as_color; -- (void)as_setColor:(nullable UIColor *)color range:(NSRange)range; - -/** - The background color. - - @discussion Default is nil (or no background). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since UIKit:6.0 - */ -@property (nullable, nonatomic) UIColor *as_backgroundColor; -- (void)as_setBackgroundColor:(nullable UIColor *)backgroundColor range:(NSRange)range; - -/** - The stroke width. - - @discussion Default value is 0.0 (no stroke). This attribute, interpreted as - a percentage of font point size, controls the text drawing mode: positive - values effect drawing with stroke only; negative values are for stroke and fill. - A typical value for outlined text is 3.0. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic) NSNumber *as_strokeWidth; -- (void)as_setStrokeWidth:(nullable NSNumber *)strokeWidth range:(NSRange)range; - -/** - The stroke color. - - @discussion Default value is nil (same as foreground color). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic) UIColor *as_strokeColor; -- (void)as_setStrokeColor:(nullable UIColor *)strokeColor range:(NSRange)range; - -/** - The text shadow. - - @discussion Default value is nil (no shadow). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic) NSShadow *as_shadow; -- (void)as_setShadow:(nullable NSShadow *)shadow range:(NSRange)range; - -/** - The strikethrough style. - - @discussion Default value is NSUnderlineStyleNone (no strikethrough). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since UIKit:6.0 - */ -@property (nonatomic) NSUnderlineStyle as_strikethroughStyle; -- (void)as_setStrikethroughStyle:(NSUnderlineStyle)strikethroughStyle range:(NSRange)range; - -/** - The strikethrough color. - - @discussion Default value is nil (same as foreground color). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since UIKit:7.0 - */ -@property (nullable, nonatomic) UIColor *as_strikethroughColor; -- (void)as_setStrikethroughColor:(nullable UIColor *)strikethroughColor range:(NSRange)range NS_AVAILABLE_IOS(7_0); - -/** - The underline style. - - @discussion Default value is NSUnderlineStyleNone (no underline). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 - */ -@property (nonatomic) NSUnderlineStyle as_underlineStyle; -- (void)as_setUnderlineStyle:(NSUnderlineStyle)underlineStyle range:(NSRange)range; - -/** - The underline color. - - @discussion Default value is nil (same as foreground color). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:7.0 - */ -@property (nullable, nonatomic) UIColor *as_underlineColor; -- (void)as_setUnderlineColor:(nullable UIColor *)underlineColor range:(NSRange)range; - -/** - Ligature formation control. - - @discussion Default is int value 1. The ligature attribute determines what kinds - of ligatures should be used when displaying the string. A value of 0 indicates - that only ligatures essential for proper rendering of text should be used, - 1 indicates that standard ligatures should be used, and 2 indicates that all - available ligatures should be used. Which ligatures are standard depends on the - script and possibly the font. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:3.2 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic) NSNumber *as_ligature; -- (void)as_setLigature:(nullable NSNumber *)ligature range:(NSRange)range; - -/** - The text effect. - - @discussion Default is nil (no effect). The only currently supported value - is NSTextEffectLetterpressStyle. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since UIKit:7.0 - */ -@property (nullable, nonatomic) NSString *as_textEffect; -- (void)as_setTextEffect:(nullable NSString *)textEffect range:(NSRange)range NS_AVAILABLE_IOS(7_0); - -/** - The skew to be applied to glyphs. - - @discussion Default is 0 (no skew). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since UIKit:7.0 - */ -@property (nullable, nonatomic) NSNumber *as_obliqueness; -- (void)as_setObliqueness:(nullable NSNumber *)obliqueness range:(NSRange)range NS_AVAILABLE_IOS(7_0); - -/** - The log of the expansion factor to be applied to glyphs. - - @discussion Default is 0 (no expansion). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since UIKit:7.0 - */ -@property (nullable, nonatomic) NSNumber *as_expansion; -- (void)as_setExpansion:(nullable NSNumber *)expansion range:(NSRange)range NS_AVAILABLE_IOS(7_0); - -/** - The character's offset from the baseline, in points. - - @discussion Default is 0. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since UIKit:7.0 - */ -@property (nullable, nonatomic) NSNumber *as_baselineOffset; -- (void)as_setBaselineOffset:(nullable NSNumber *)baselineOffset range:(NSRange)range NS_AVAILABLE_IOS(7_0); - -/** - Glyph orientation control. - - @discussion Default is NO. A value of NO indicates that horizontal glyph forms - are to be used, YES indicates that vertical glyph forms are to be used. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:4.3 ASText:6.0 - */ -@property (nonatomic) BOOL as_verticalGlyphForm; -- (void)as_setVerticalGlyphForm:(BOOL)verticalGlyphForm range:(NSRange)range; - -/** - Specifies text language. - - @discussion Value must be a NSString containing a locale identifier. Default is - unset. When this attribute is set to a valid identifier, it will be used to select - localized glyphs (if supported by the font) and locale-specific line breaking rules. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:7.0 ASText:7.0 - */ -@property (nullable, nonatomic) NSString *as_language; -- (void)as_setLanguage:(nullable NSString *)language range:(NSRange)range NS_AVAILABLE_IOS(7_0); - -/** - Specifies a bidirectional override or embedding. - - @discussion See alse NSWritingDirection and NSWritingDirectionAttributeName. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:7.0 ASText:6.0 - */ -@property (nullable, nonatomic) NSArray *as_writingDirection; -- (void)as_setWritingDirection:(nullable NSArray *)writingDirection range:(NSRange)range; - -/** - An NSParagraphStyle object which is used to specify things like - line alignment, tab rulers, writing direction, etc. - - @discussion Default is nil ([NSParagraphStyle defaultParagraphStyle]). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nullable, nonatomic) NSParagraphStyle *as_paragraphStyle; -- (void)as_setParagraphStyle:(nullable NSParagraphStyle *)paragraphStyle range:(NSRange)range; - - -#pragma mark - Set paragraph attribute as property -///============================================================================= -/// @name Set paragraph attribute as property -///============================================================================= - -/** - The text alignment (A wrapper for NSParagraphStyle). - - @discussion Natural text alignment is realized as left or right alignment - depending on the line sweep direction of the first script contained in the paragraph. - @discussion Default is NSTextAlignmentNatural. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) NSTextAlignment as_alignment; -- (void)as_setAlignment:(NSTextAlignment)alignment range:(NSRange)range; - -/** - The mode that should be used to break lines (A wrapper for NSParagraphStyle). - - @discussion This property contains the line break mode to be used laying out the paragraph's text. - @discussion Default is NSLineBreakByWordWrapping. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) NSLineBreakMode as_lineBreakMode; -- (void)as_setLineBreakMode:(NSLineBreakMode)lineBreakMode range:(NSRange)range; - -/** - The distance in points between the bottom of one line fragment and the top of the next. - (A wrapper for NSParagraphStyle) - - @discussion This value is always nonnegative. This value is included in the line - fragment heights in the layout manager. - @discussion Default is 0. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) CGFloat as_lineSpacing; -- (void)as_setLineSpacing:(CGFloat)lineSpacing range:(NSRange)range; - -/** - The space after the end of the paragraph (A wrapper for NSParagraphStyle). - - @discussion This property contains the space (measured in points) added at the - end of the paragraph to separate it from the following paragraph. This value must - be nonnegative. The space between paragraphs is determined by adding the previous - paragraph's paragraphSpacing and the current paragraph's paragraphSpacingBefore. - @discussion Default is 0. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) CGFloat as_paragraphSpacing; -- (void)as_setParagraphSpacing:(CGFloat)paragraphSpacing range:(NSRange)range; - -/** - The distance between the paragraph's top and the beginning of its text content. - (A wrapper for NSParagraphStyle). - - @discussion This property contains the space (measured in points) between the - paragraph's top and the beginning of its text content. - @discussion Default is 0. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) CGFloat as_paragraphSpacingBefore; -- (void)as_setParagraphSpacingBefore:(CGFloat)paragraphSpacingBefore range:(NSRange)range; - -/** - The indentation of the first line (A wrapper for NSParagraphStyle). - - @discussion This property contains the distance (in points) from the leading margin - of a text container to the beginning of the paragraph's first line. This value - is always nonnegative. - @discussion Default is 0. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) CGFloat as_firstLineHeadIndent; -- (void)as_setFirstLineHeadIndent:(CGFloat)firstLineHeadIndent range:(NSRange)range; - -/** - The indentation of the receiver's lines other than the first. (A wrapper for NSParagraphStyle). - - @discussion This property contains the distance (in points) from the leading margin - of a text container to the beginning of lines other than the first. This value is - always nonnegative. - @discussion Default is 0. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) CGFloat as_headIndent; -- (void)as_setHeadIndent:(CGFloat)headIndent range:(NSRange)range; - -/** - The trailing indentation (A wrapper for NSParagraphStyle). - - @discussion If positive, this value is the distance from the leading margin - (for example, the left margin in left-to-right text). If 0 or negative, it's the - distance from the trailing margin. - @discussion Default is 0. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) CGFloat as_tailIndent; -- (void)as_setTailIndent:(CGFloat)tailIndent range:(NSRange)range; - -/** - The receiver's minimum height (A wrapper for NSParagraphStyle). - - @discussion This property contains the minimum height in points that any line in - the receiver will occupy, regardless of the font size or size of any attached graphic. - This value must be nonnegative. - @discussion Default is 0. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) CGFloat as_minimumLineHeight; -- (void)as_setMinimumLineHeight:(CGFloat)minimumLineHeight range:(NSRange)range; - -/** - The receiver's maximum line height (A wrapper for NSParagraphStyle). - - @discussion This property contains the maximum height in points that any line in - the receiver will occupy, regardless of the font size or size of any attached graphic. - This value is always nonnegative. Glyphs and graphics exceeding this height will - overlap neighboring lines; however, a maximum height of 0 implies no line height limit. - Although this limit applies to the line itself, line spacing adds extra space between adjacent lines. - @discussion Default is 0 (no limit). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) CGFloat as_maximumLineHeight; -- (void)as_setMaximumLineHeight:(CGFloat)maximumLineHeight range:(NSRange)range; - -/** - The line height multiple (A wrapper for NSParagraphStyle). - - @discussion This property contains the line break mode to be used laying out the paragraph's text. - @discussion Default is 0 (no multiple). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) CGFloat as_lineHeightMultiple; -- (void)as_setLineHeightMultiple:(CGFloat)lineHeightMultiple range:(NSRange)range; - -/** - The base writing direction (A wrapper for NSParagraphStyle). - - @discussion If you specify NSWritingDirectionNaturalDirection, the receiver resolves - the writing direction to either NSWritingDirectionLeftToRight or NSWritingDirectionRightToLeft, - depending on the direction for the user's `language` preference setting. - @discussion Default is NSWritingDirectionNatural. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:6.0 UIKit:6.0 ASText:6.0 - */ -@property (nonatomic) NSWritingDirection as_baseWritingDirection; -- (void)as_setBaseWritingDirection:(NSWritingDirection)baseWritingDirection range:(NSRange)range; - -/** - The paragraph's threshold for hyphenation. (A wrapper for NSParagraphStyle). - - @discussion Valid values lie between 0.0 and 1.0 inclusive. Hyphenation is attempted - when the ratio of the text width (as broken without hyphenation) to the width of the - line fragment is less than the hyphenation factor. When the paragraph's hyphenation - factor is 0.0, the layout manager's hyphenation factor is used instead. When both - are 0.0, hyphenation is disabled. - @discussion Default is 0. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since UIKit:6.0 - */ -@property (nonatomic) float as_hyphenationFactor; -- (void)as_setHyphenationFactor:(float)hyphenationFactor range:(NSRange)range; - -/** - The document-wide default tab interval (A wrapper for NSParagraphStyle). - - @discussion This property represents the default tab interval in points. Tabs after the - last specified in tabStops are placed at integer multiples of this distance (if positive). - @discussion Default is 0. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:7.0 UIKit:7.0 ASText:7.0 - */ -@property (nonatomic) CGFloat as_defaultTabInterval; -- (void)as_setDefaultTabInterval:(CGFloat)defaultTabInterval range:(NSRange)range NS_AVAILABLE_IOS(7_0); - -/** - An array of NSTextTab objects representing the receiver's tab stops. - (A wrapper for NSParagraphStyle). - - @discussion The NSTextTab objects, sorted by location, define the tab stops for - the paragraph style. - @discussion Default is 12 TabStops with 28.0 tab interval. - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since CoreText:7.0 UIKit:7.0 ASText:7.0 - */ -@property (nullable, nonatomic, copy) NSArray *as_tabStops; -- (void)as_setTabStops:(nullable NSArray *)tabStops range:(NSRange)range NS_AVAILABLE_IOS(7_0); - -#pragma mark - Set ASText attribute as property -///============================================================================= -/// @name Set ASText attribute as property -///============================================================================= - -/** - The text shadow. - - @discussion Default value is nil (no shadow). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic) ASTextShadow *as_textShadow; -- (void)as_setTextShadow:(nullable ASTextShadow *)textShadow range:(NSRange)range; - -/** - The text inner shadow. - - @discussion Default value is nil (no shadow). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic) ASTextShadow *as_textInnerShadow; -- (void)as_setTextInnerShadow:(nullable ASTextShadow *)textInnerShadow range:(NSRange)range; - -/** - The text underline. - - @discussion Default value is nil (no underline). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic) ASTextDecoration *as_textUnderline; -- (void)as_setTextUnderline:(nullable ASTextDecoration *)textUnderline range:(NSRange)range; - -/** - The text strikethrough. - - @discussion Default value is nil (no strikethrough). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic) ASTextDecoration *as_textStrikethrough; -- (void)as_setTextStrikethrough:(nullable ASTextDecoration *)textStrikethrough range:(NSRange)range; - -/** - The text border. - - @discussion Default value is nil (no border). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic) ASTextBorder *as_textBorder; -- (void)as_setTextBorder:(nullable ASTextBorder *)textBorder range:(NSRange)range; - -/** - The text background border. - - @discussion Default value is nil (no background border). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nullable, nonatomic) ASTextBorder *as_textBackgroundBorder; -- (void)as_setTextBackgroundBorder:(nullable ASTextBorder *)textBackgroundBorder range:(NSRange)range; - -/** - The glyph transform. - - @discussion Default value is CGAffineTransformIdentity (no transform). - @discussion Set this property applies to the entire text string. - Get this property returns the first character's attribute. - @since ASText:6.0 - */ -@property (nonatomic) CGAffineTransform as_textGlyphTransform; -- (void)as_setTextGlyphTransform:(CGAffineTransform)textGlyphTransform range:(NSRange)range; - - -#pragma mark - Set discontinuous attribute for range -///============================================================================= -/// @name Set discontinuous attribute for range -///============================================================================= - -- (void)as_setSuperscript:(nullable NSNumber *)superscript range:(NSRange)range; -- (void)as_setGlyphInfo:(nullable CTGlyphInfoRef)glyphInfo range:(NSRange)range; -- (void)as_setCharacterShape:(nullable NSNumber *)characterShape range:(NSRange)range __TVOS_PROHIBITED; -- (void)as_setRunDelegate:(nullable CTRunDelegateRef)runDelegate range:(NSRange)range; -- (void)as_setBaselineClass:(nullable CFStringRef)baselineClass range:(NSRange)range; -- (void)as_setBaselineInfo:(nullable CFDictionaryRef)baselineInfo range:(NSRange)range; -- (void)as_setBaselineReferenceInfo:(nullable CFDictionaryRef)referenceInfo range:(NSRange)range; -- (void)as_setRubyAnnotation:(nullable CTRubyAnnotationRef)ruby range:(NSRange)range NS_AVAILABLE_IOS(8_0); -- (void)as_setAttachment:(nullable NSTextAttachment *)attachment range:(NSRange)range NS_AVAILABLE_IOS(7_0); -- (void)as_setLink:(nullable id)link range:(NSRange)range NS_AVAILABLE_IOS(7_0); -- (void)as_setTextBackedString:(nullable ASTextBackedString *)textBackedString range:(NSRange)range; -- (void)as_setTextBinding:(nullable ASTextBinding *)textBinding range:(NSRange)range; -- (void)as_setTextAttachment:(nullable ASTextAttachment *)textAttachment range:(NSRange)range; -- (void)as_setTextHighlight:(nullable ASTextHighlight *)textHighlight range:(NSRange)range; -- (void)as_setTextBlockBorder:(nullable ASTextBorder *)textBlockBorder range:(NSRange)range; - - -#pragma mark - Convenience methods for text highlight -///============================================================================= -/// @name Convenience methods for text highlight -///============================================================================= - -/** - Convenience method to set text highlight - - @param range text range - @param color text color (pass nil to ignore) - @param backgroundColor text background color when highlight - @param userInfo user information dictionary (pass nil to ignore) - @param tapAction tap action when user tap the highlight (pass nil to ignore) - @param longPressAction long press action when user long press the highlight (pass nil to ignore) - */ -- (void)as_setTextHighlightRange:(NSRange)range - color:(nullable UIColor *)color - backgroundColor:(nullable UIColor *)backgroundColor - userInfo:(nullable NSDictionary *)userInfo - tapAction:(nullable ASTextAction)tapAction - longPressAction:(nullable ASTextAction)longPressAction; - -/** - Convenience method to set text highlight - - @param range text range - @param color text color (pass nil to ignore) - @param backgroundColor text background color when highlight - @param tapAction tap action when user tap the highlight (pass nil to ignore) - */ -- (void)as_setTextHighlightRange:(NSRange)range - color:(nullable UIColor *)color - backgroundColor:(nullable UIColor *)backgroundColor - tapAction:(nullable ASTextAction)tapAction; - -/** - Convenience method to set text highlight - - @param range text range - @param color text color (pass nil to ignore) - @param backgroundColor text background color when highlight - @param userInfo tap action when user tap the highlight (pass nil to ignore) - */ -- (void)as_setTextHighlightRange:(NSRange)range - color:(nullable UIColor *)color - backgroundColor:(nullable UIColor *)backgroundColor - userInfo:(nullable NSDictionary *)userInfo; - -#pragma mark - Utilities -///============================================================================= -/// @name Utilities -///============================================================================= - -/** - Inserts into the receiver the characters of a given string at a given location. - The new string inherit the attributes of the first replaced character from location. - - @param string The string to insert into the receiver, must not be nil. - @param location The location at which string is inserted. The location must not - exceed the bounds of the receiver. - @throw Raises an NSRangeException if the location out of bounds. - */ -- (void)as_insertString:(NSString *)string atIndex:(NSUInteger)location; - -/** - Adds to the end of the receiver the characters of a given string. - The new string inherit the attributes of the receiver's tail. - - @param string The string to append to the receiver, must not be nil. - */ -- (void)as_appendString:(NSString *)string; - -/** - Removes all discontinuous attributes in a specified range. - See `allDiscontinuousAttributeKeys`. - - @param range A text range. - */ -- (void)as_removeDiscontinuousAttributesInRange:(NSRange)range; - -/** - Returns all discontinuous attribute keys, such as RunDelegate/Attachment/Ruby. - - @discussion These attributes can only set to a specified range of text, and - should not extend to other range when editing text. - */ -+ (NSArray *)as_allDiscontinuousAttributeKeys; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSAttributedString+ASText.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSAttributedString+ASText.mm deleted file mode 100644 index 39f628151c..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSAttributedString+ASText.mm +++ /dev/null @@ -1,1208 +0,0 @@ -// -// NSAttributedString+ASText.mm -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import -#import -#import - - -// Dummy class for category -@interface NSAttributedString_ASText : NSObject @end -@implementation NSAttributedString_ASText @end - - -@implementation NSAttributedString (ASText) - -- (NSDictionary *)as_attributesAtIndex:(NSUInteger)index { - if (index > self.length || self.length == 0) return nil; - if (self.length > 0 && index == self.length) index--; - return [self attributesAtIndex:index effectiveRange:NULL]; -} - -- (id)as_attribute:(NSString *)attributeName atIndex:(NSUInteger)index { - if (!attributeName) return nil; - if (index > self.length || self.length == 0) return nil; - if (self.length > 0 && index == self.length) index--; - return [self attribute:attributeName atIndex:index effectiveRange:NULL]; -} - -- (NSDictionary *)as_attributes { - return [self as_attributesAtIndex:0]; -} - -- (UIFont *)as_font { - return [self as_fontAtIndex:0]; -} - -- (UIFont *)as_fontAtIndex:(NSUInteger)index { - return [self as_attribute:NSFontAttributeName atIndex:index]; -} - -- (NSNumber *)as_kern { - return [self as_kernAtIndex:0]; -} - -- (NSNumber *)as_kernAtIndex:(NSUInteger)index { - return [self as_attribute:NSKernAttributeName atIndex:index]; -} - -- (UIColor *)as_color { - return [self as_colorAtIndex:0]; -} - -- (UIColor *)as_colorAtIndex:(NSUInteger)index { - UIColor *color = [self as_attribute:NSForegroundColorAttributeName atIndex:index]; - if (!color) { - CGColorRef ref = (__bridge CGColorRef)([self as_attribute:(NSString *)kCTForegroundColorAttributeName atIndex:index]); - color = [UIColor colorWithCGColor:ref]; - } - if (color && ![color isKindOfClass:[UIColor class]]) { - if (CFGetTypeID((__bridge CFTypeRef)(color)) == CGColorGetTypeID()) { - color = [UIColor colorWithCGColor:(__bridge CGColorRef)(color)]; - } else { - color = nil; - } - } - return color; -} - -- (UIColor *)as_backgroundColor { - return [self as_backgroundColorAtIndex:0]; -} - -- (UIColor *)as_backgroundColorAtIndex:(NSUInteger)index { - return [self as_attribute:NSBackgroundColorAttributeName atIndex:index]; -} - -- (NSNumber *)as_strokeWidth { - return [self as_strokeWidthAtIndex:0]; -} - -- (NSNumber *)as_strokeWidthAtIndex:(NSUInteger)index { - return [self as_attribute:NSStrokeWidthAttributeName atIndex:index]; -} - -- (UIColor *)as_strokeColor { - return [self as_strokeColorAtIndex:0]; -} - -- (UIColor *)as_strokeColorAtIndex:(NSUInteger)index { - UIColor *color = [self as_attribute:NSStrokeColorAttributeName atIndex:index]; - if (!color) { - CGColorRef ref = (__bridge CGColorRef)([self as_attribute:(NSString *)kCTStrokeColorAttributeName atIndex:index]); - color = [UIColor colorWithCGColor:ref]; - } - return color; -} - -- (NSShadow *)as_shadow { - return [self as_shadowAtIndex:0]; -} - -- (NSShadow *)as_shadowAtIndex:(NSUInteger)index { - return [self as_attribute:NSShadowAttributeName atIndex:index]; -} - -- (NSUnderlineStyle)as_strikethroughStyle { - return [self as_strikethroughStyleAtIndex:0]; -} - -- (NSUnderlineStyle)as_strikethroughStyleAtIndex:(NSUInteger)index { - NSNumber *style = [self as_attribute:NSStrikethroughStyleAttributeName atIndex:index]; - return (NSUnderlineStyle)style.integerValue; -} - -- (UIColor *)as_strikethroughColor { - return [self as_strikethroughColorAtIndex:0]; -} - -- (UIColor *)as_strikethroughColorAtIndex:(NSUInteger)index { - return [self as_attribute:NSStrikethroughColorAttributeName atIndex:index]; -} - -- (NSUnderlineStyle)as_underlineStyle { - return [self as_underlineStyleAtIndex:0]; -} - -- (NSUnderlineStyle)as_underlineStyleAtIndex:(NSUInteger)index { - NSNumber *style = [self as_attribute:NSUnderlineStyleAttributeName atIndex:index]; - return (NSUnderlineStyle)style.integerValue; -} - -- (UIColor *)as_underlineColor { - return [self as_underlineColorAtIndex:0]; -} - -- (UIColor *)as_underlineColorAtIndex:(NSUInteger)index { - UIColor *color = [self as_attribute:NSUnderlineColorAttributeName atIndex:index]; - if (!color) { - CGColorRef ref = (__bridge CGColorRef)([self as_attribute:(NSString *)kCTUnderlineColorAttributeName atIndex:index]); - color = [UIColor colorWithCGColor:ref]; - } - return color; -} - -- (NSNumber *)as_ligature { - return [self as_ligatureAtIndex:0]; -} - -- (NSNumber *)as_ligatureAtIndex:(NSUInteger)index { - return [self as_attribute:NSLigatureAttributeName atIndex:index]; -} - -- (NSString *)as_textEffect { - return [self as_textEffectAtIndex:0]; -} - -- (NSString *)as_textEffectAtIndex:(NSUInteger)index { - return [self as_attribute:NSTextEffectAttributeName atIndex:index]; -} - -- (NSNumber *)as_obliqueness { - return [self as_obliquenessAtIndex:0]; -} - -- (NSNumber *)as_obliquenessAtIndex:(NSUInteger)index { - return [self as_attribute:NSObliquenessAttributeName atIndex:index]; -} - -- (NSNumber *)as_expansion { - return [self as_expansionAtIndex:0]; -} - -- (NSNumber *)as_expansionAtIndex:(NSUInteger)index { - return [self as_attribute:NSExpansionAttributeName atIndex:index]; -} - -- (NSNumber *)as_baselineOffset { - return [self as_baselineOffsetAtIndex:0]; -} - -- (NSNumber *)as_baselineOffsetAtIndex:(NSUInteger)index { - return [self as_attribute:NSBaselineOffsetAttributeName atIndex:index]; -} - -- (BOOL)as_verticalGlyphForm { - return [self as_verticalGlyphFormAtIndex:0]; -} - -- (BOOL)as_verticalGlyphFormAtIndex:(NSUInteger)index { - NSNumber *num = [self as_attribute:NSVerticalGlyphFormAttributeName atIndex:index]; - return num.boolValue; -} - -- (NSString *)as_language { - return [self as_languageAtIndex:0]; -} - -- (NSString *)as_languageAtIndex:(NSUInteger)index { - return [self as_attribute:(id)kCTLanguageAttributeName atIndex:index]; -} - -- (NSArray *)as_writingDirection { - return [self as_writingDirectionAtIndex:0]; -} - -- (NSArray *)as_writingDirectionAtIndex:(NSUInteger)index { - return [self as_attribute:(id)kCTWritingDirectionAttributeName atIndex:index]; -} - -- (NSParagraphStyle *)as_paragraphStyle { - return [self as_paragraphStyleAtIndex:0]; -} - -- (NSParagraphStyle *)as_paragraphStyleAtIndex:(NSUInteger)index { - /* - NSParagraphStyle is NOT toll-free bridged to CTParagraphStyleRef. - - CoreText can use both NSParagraphStyle and CTParagraphStyleRef, - but UILabel/UITextView can only use NSParagraphStyle. - - We use NSParagraphStyle in both CoreText and UIKit. - */ - NSParagraphStyle *style = [self as_attribute:NSParagraphStyleAttributeName atIndex:index]; - if (style) { - if (CFGetTypeID((__bridge CFTypeRef)(style)) == CTParagraphStyleGetTypeID()) { \ - style = [NSParagraphStyle as_styleWithCTStyle:(__bridge CTParagraphStyleRef)(style)]; - } - } - return style; -} - -#define ParagraphAttribute(_attr_) \ -NSParagraphStyle *style = self.as_paragraphStyle; \ -if (!style) style = [NSParagraphStyle defaultParagraphStyle]; \ -return style. _attr_; - -#define ParagraphAttributeAtIndex(_attr_) \ -NSParagraphStyle *style = [self as_paragraphStyleAtIndex:index]; \ -if (!style) style = [NSParagraphStyle defaultParagraphStyle]; \ -return style. _attr_; - -- (NSTextAlignment)as_alignment { - ParagraphAttribute(alignment); -} - -- (NSLineBreakMode)as_lineBreakMode { - ParagraphAttribute(lineBreakMode); -} - -- (CGFloat)as_lineSpacing { - ParagraphAttribute(lineSpacing); -} - -- (CGFloat)as_paragraphSpacing { - ParagraphAttribute(paragraphSpacing); -} - -- (CGFloat)as_paragraphSpacingBefore { - ParagraphAttribute(paragraphSpacingBefore); -} - -- (CGFloat)as_firstLineHeadIndent { - ParagraphAttribute(firstLineHeadIndent); -} - -- (CGFloat)as_headIndent { - ParagraphAttribute(headIndent); -} - -- (CGFloat)as_tailIndent { - ParagraphAttribute(tailIndent); -} - -- (CGFloat)as_minimumLineHeight { - ParagraphAttribute(minimumLineHeight); -} - -- (CGFloat)as_maximumLineHeight { - ParagraphAttribute(maximumLineHeight); -} - -- (CGFloat)as_lineHeightMultiple { - ParagraphAttribute(lineHeightMultiple); -} - -- (NSWritingDirection)as_baseWritingDirection { - ParagraphAttribute(baseWritingDirection); -} - -- (float)as_hyphenationFactor { - ParagraphAttribute(hyphenationFactor); -} - -- (CGFloat)as_defaultTabInterval { - ParagraphAttribute(defaultTabInterval); -} - -- (NSArray *)as_tabStops { - ParagraphAttribute(tabStops); -} - -- (NSTextAlignment)as_alignmentAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(alignment); -} - -- (NSLineBreakMode)as_lineBreakModeAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(lineBreakMode); -} - -- (CGFloat)as_lineSpacingAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(lineSpacing); -} - -- (CGFloat)as_paragraphSpacingAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(paragraphSpacing); -} - -- (CGFloat)as_paragraphSpacingBeforeAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(paragraphSpacingBefore); -} - -- (CGFloat)as_firstLineHeadIndentAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(firstLineHeadIndent); -} - -- (CGFloat)as_headIndentAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(headIndent); -} - -- (CGFloat)as_tailIndentAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(tailIndent); -} - -- (CGFloat)as_minimumLineHeightAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(minimumLineHeight); -} - -- (CGFloat)as_maximumLineHeightAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(maximumLineHeight); -} - -- (CGFloat)as_lineHeightMultipleAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(lineHeightMultiple); -} - -- (NSWritingDirection)as_baseWritingDirectionAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(baseWritingDirection); -} - -- (float)as_hyphenationFactorAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(hyphenationFactor); -} - -- (CGFloat)as_defaultTabIntervalAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(defaultTabInterval); -} - -- (NSArray *)as_tabStopsAtIndex:(NSUInteger)index { - ParagraphAttributeAtIndex(tabStops); -} - -#undef ParagraphAttribute -#undef ParagraphAttributeAtIndex - -- (ASTextShadow *)as_textShadow { - return [self as_textShadowAtIndex:0]; -} - -- (ASTextShadow *)as_textShadowAtIndex:(NSUInteger)index { - return [self as_attribute:ASTextShadowAttributeName atIndex:index]; -} - -- (ASTextShadow *)as_textInnerShadow { - return [self as_textInnerShadowAtIndex:0]; -} - -- (ASTextShadow *)as_textInnerShadowAtIndex:(NSUInteger)index { - return [self as_attribute:ASTextInnerShadowAttributeName atIndex:index]; -} - -- (ASTextDecoration *)as_textUnderline { - return [self as_textUnderlineAtIndex:0]; -} - -- (ASTextDecoration *)as_textUnderlineAtIndex:(NSUInteger)index { - return [self as_attribute:ASTextUnderlineAttributeName atIndex:index]; -} - -- (ASTextDecoration *)as_textStrikethrough { - return [self as_textStrikethroughAtIndex:0]; -} - -- (ASTextDecoration *)as_textStrikethroughAtIndex:(NSUInteger)index { - return [self as_attribute:ASTextStrikethroughAttributeName atIndex:index]; -} - -- (ASTextBorder *)as_textBorder { - return [self as_textBorderAtIndex:0]; -} - -- (ASTextBorder *)as_textBorderAtIndex:(NSUInteger)index { - return [self as_attribute:ASTextBorderAttributeName atIndex:index]; -} - -- (ASTextBorder *)as_textBackgroundBorder { - return [self as_textBackgroundBorderAtIndex:0]; -} - -- (ASTextBorder *)as_textBackgroundBorderAtIndex:(NSUInteger)index { - return [self as_attribute:ASTextBackedStringAttributeName atIndex:index]; -} - -- (CGAffineTransform)as_textGlyphTransform { - return [self as_textGlyphTransformAtIndex:0]; -} - -- (CGAffineTransform)as_textGlyphTransformAtIndex:(NSUInteger)index { - NSValue *value = [self as_attribute:ASTextGlyphTransformAttributeName atIndex:index]; - if (!value) return CGAffineTransformIdentity; - return [value CGAffineTransformValue]; -} - -- (NSString *)as_plainTextForRange:(NSRange)range { - if (range.location == NSNotFound ||range.length == NSNotFound) return nil; - NSMutableString *result = [NSMutableString string]; - if (range.length == 0) return result; - NSString *string = self.string; - [self enumerateAttribute:ASTextBackedStringAttributeName inRange:range options:kNilOptions usingBlock:^(id value, NSRange range, BOOL *stop) { - ASTextBackedString *backed = value; - if (backed && backed.string) { - [result appendString:backed.string]; - } else { - [result appendString:[string substringWithRange:range]]; - } - }]; - return result; -} - -+ (NSMutableAttributedString *)as_attachmentStringWithContent:(id)content - contentMode:(UIViewContentMode)contentMode - width:(CGFloat)width - ascent:(CGFloat)ascent - descent:(CGFloat)descent { - NSMutableAttributedString *atr = [[NSMutableAttributedString alloc] initWithString:ASTextAttachmentToken]; - - ASTextAttachment *attach = [ASTextAttachment new]; - attach.content = content; - attach.contentMode = contentMode; - [atr as_setTextAttachment:attach range:NSMakeRange(0, atr.length)]; - - ASTextRunDelegate *delegate = [ASTextRunDelegate new]; - delegate.width = width; - delegate.ascent = ascent; - delegate.descent = descent; - CTRunDelegateRef delegateRef = delegate.CTRunDelegate; - [atr as_setRunDelegate:delegateRef range:NSMakeRange(0, atr.length)]; - if (delegate) CFRelease(delegateRef); - - return atr; -} - -+ (NSMutableAttributedString *)as_attachmentStringWithContent:(id)content - contentMode:(UIViewContentMode)contentMode - attachmentSize:(CGSize)attachmentSize - alignToFont:(UIFont *)font - alignment:(ASTextVerticalAlignment)alignment { - NSMutableAttributedString *atr = [[NSMutableAttributedString alloc] initWithString:ASTextAttachmentToken]; - - ASTextAttachment *attach = [ASTextAttachment new]; - attach.content = content; - attach.contentMode = contentMode; - [atr as_setTextAttachment:attach range:NSMakeRange(0, atr.length)]; - - ASTextRunDelegate *delegate = [ASTextRunDelegate new]; - delegate.width = attachmentSize.width; - switch (alignment) { - case ASTextVerticalAlignmentTop: { - delegate.ascent = font.ascender; - delegate.descent = attachmentSize.height - font.ascender; - if (delegate.descent < 0) { - delegate.descent = 0; - delegate.ascent = attachmentSize.height; - } - } break; - case ASTextVerticalAlignmentCenter: { - CGFloat fontHeight = font.ascender - font.descender; - CGFloat yOffset = font.ascender - fontHeight * 0.5; - delegate.ascent = attachmentSize.height * 0.5 + yOffset; - delegate.descent = attachmentSize.height - delegate.ascent; - if (delegate.descent < 0) { - delegate.descent = 0; - delegate.ascent = attachmentSize.height; - } - } break; - case ASTextVerticalAlignmentBottom: { - delegate.ascent = attachmentSize.height + font.descender; - delegate.descent = -font.descender; - if (delegate.ascent < 0) { - delegate.ascent = 0; - delegate.descent = attachmentSize.height; - } - } break; - default: { - delegate.ascent = attachmentSize.height; - delegate.descent = 0; - } break; - } - - CTRunDelegateRef delegateRef = delegate.CTRunDelegate; - [atr as_setRunDelegate:delegateRef range:NSMakeRange(0, atr.length)]; - if (delegate) CFRelease(delegateRef); - - return atr; -} - -+ (NSMutableAttributedString *)as_attachmentStringWithEmojiImage:(UIImage *)image - fontSize:(CGFloat)fontSize { - if (!image || fontSize <= 0) return nil; - - BOOL hasAnim = NO; - if (image.images.count > 1) { - hasAnim = YES; - } else if (NSProtocolFromString(@"ASAnimatedImage") && - [image conformsToProtocol:NSProtocolFromString(@"ASAnimatedImage")]) { - NSNumber *frameCount = [image valueForKey:@"animatedImageFrameCount"]; - if (frameCount.intValue > 1) hasAnim = YES; - } - - CGFloat ascent = ASTextEmojiGetAscentWithFontSize(fontSize); - CGFloat descent = ASTextEmojiGetDescentWithFontSize(fontSize); - CGRect bounding = ASTextEmojiGetGlyphBoundingRectWithFontSize(fontSize); - - ASTextRunDelegate *delegate = [ASTextRunDelegate new]; - delegate.ascent = ascent; - delegate.descent = descent; - delegate.width = bounding.size.width + 2 * bounding.origin.x; - - ASTextAttachment *attachment = [ASTextAttachment new]; - attachment.contentMode = UIViewContentModeScaleAspectFit; - attachment.contentInsets = UIEdgeInsetsMake(ascent - (bounding.size.height + bounding.origin.y), bounding.origin.x, descent + bounding.origin.y, bounding.origin.x); - if (hasAnim) { - Class imageClass = NSClassFromString(@"ASAnimatedImageView"); - if (!imageClass) imageClass = [UIImageView class]; - UIImageView *view = (id)[imageClass new]; - view.frame = bounding; - view.image = image; - view.contentMode = UIViewContentModeScaleAspectFit; - attachment.content = view; - } else { - attachment.content = image; - } - - NSMutableAttributedString *atr = [[NSMutableAttributedString alloc] initWithString:ASTextAttachmentToken]; - [atr as_setTextAttachment:attachment range:NSMakeRange(0, atr.length)]; - CTRunDelegateRef ctDelegate = delegate.CTRunDelegate; - [atr as_setRunDelegate:ctDelegate range:NSMakeRange(0, atr.length)]; - if (ctDelegate) CFRelease(ctDelegate); - - return atr; -} - -- (NSRange)as_rangeOfAll { - return NSMakeRange(0, self.length); -} - -- (BOOL)as_isSharedAttributesInAllRange { - __block BOOL shared = YES; - __block NSDictionary *firstAttrs = nil; - [self enumerateAttributesInRange:self.as_rangeOfAll options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) { - if (range.location == 0) { - firstAttrs = attrs; - } else { - if (firstAttrs.count != attrs.count) { - shared = NO; - *stop = YES; - } else if (firstAttrs) { - if (![firstAttrs isEqualToDictionary:attrs]) { - shared = NO; - *stop = YES; - } - } - } - }]; - return shared; -} - -- (BOOL)as_canDrawWithUIKit { - static NSMutableSet *failSet; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - failSet = [NSMutableSet new]; - [failSet addObject:(id)kCTGlyphInfoAttributeName]; -#if TARGET_OS_IOS -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [failSet addObject:(id)kCTCharacterShapeAttributeName]; -#pragma clang diagnostic pop -#endif - [failSet addObject:(id)kCTLanguageAttributeName]; - [failSet addObject:(id)kCTRunDelegateAttributeName]; - [failSet addObject:(id)kCTBaselineClassAttributeName]; - [failSet addObject:(id)kCTBaselineInfoAttributeName]; - [failSet addObject:(id)kCTBaselineReferenceInfoAttributeName]; - [failSet addObject:(id)kCTRubyAnnotationAttributeName]; - [failSet addObject:ASTextShadowAttributeName]; - [failSet addObject:ASTextInnerShadowAttributeName]; - [failSet addObject:ASTextUnderlineAttributeName]; - [failSet addObject:ASTextStrikethroughAttributeName]; - [failSet addObject:ASTextBorderAttributeName]; - [failSet addObject:ASTextBackgroundBorderAttributeName]; - [failSet addObject:ASTextBlockBorderAttributeName]; - [failSet addObject:ASTextAttachmentAttributeName]; - [failSet addObject:ASTextHighlightAttributeName]; - [failSet addObject:ASTextGlyphTransformAttributeName]; - }); - -#define Fail { result = NO; *stop = YES; return; } - __block BOOL result = YES; - [self enumerateAttributesInRange:self.as_rangeOfAll options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) { - if (attrs.count == 0) return; - for (NSString *str in attrs.allKeys) { - if ([failSet containsObject:str]) Fail; - } - if (attrs[(id)kCTForegroundColorAttributeName] && !attrs[NSForegroundColorAttributeName]) Fail; - if (attrs[(id)kCTStrokeColorAttributeName] && !attrs[NSStrokeColorAttributeName]) Fail; - if (attrs[(id)kCTUnderlineColorAttributeName]) { - if (!attrs[NSUnderlineColorAttributeName]) Fail; - } - NSParagraphStyle *style = attrs[NSParagraphStyleAttributeName]; - if (style && CFGetTypeID((__bridge CFTypeRef)(style)) == CTParagraphStyleGetTypeID()) Fail; - }]; - return result; -#undef Fail -} - -@end - -@implementation NSMutableAttributedString (ASText) - -- (void)as_setAttributes:(NSDictionary *)attributes { - [self setAs_attributes:attributes]; -} - -- (void)setAs_attributes:(NSDictionary *)attributes { - if (attributes == (id)[NSNull null]) attributes = nil; - [self setAttributes:@{} range:NSMakeRange(0, self.length)]; - [attributes enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { - [self as_setAttribute:key value:obj]; - }]; -} - -- (void)as_setAttribute:(NSString *)name value:(id)value { - [self as_setAttribute:name value:value range:NSMakeRange(0, self.length)]; -} - -- (void)as_setAttribute:(NSString *)name value:(id)value range:(NSRange)range { - if (!name || [NSNull isEqual:name]) return; - if (value && ![NSNull isEqual:value]) [self addAttribute:name value:value range:range]; - else [self removeAttribute:name range:range]; -} - -- (void)as_removeAttributesInRange:(NSRange)range { - [self setAttributes:nil range:range]; -} - -#pragma mark - Property Setter - -- (void)setAs_font:(UIFont *)font { - /* - In iOS7 and later, UIFont is toll-free bridged to CTFontRef, - although Apple does not mention it in documentation. - - In iOS6, UIFont is a wrapper for CTFontRef, so CoreText can alse use UIfont, - but UILabel/UITextView cannot use CTFontRef. - - We use UIFont for both CoreText and UIKit. - */ - [self as_setFont:font range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_kern:(NSNumber *)kern { - [self as_setKern:kern range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_color:(UIColor *)color { - [self as_setColor:color range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_backgroundColor:(UIColor *)backgroundColor { - [self as_setBackgroundColor:backgroundColor range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_strokeWidth:(NSNumber *)strokeWidth { - [self as_setStrokeWidth:strokeWidth range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_strokeColor:(UIColor *)strokeColor { - [self as_setStrokeColor:strokeColor range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_shadow:(NSShadow *)shadow { - [self as_setShadow:shadow range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_strikethroughStyle:(NSUnderlineStyle)strikethroughStyle { - [self as_setStrikethroughStyle:strikethroughStyle range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_strikethroughColor:(UIColor *)strikethroughColor { - [self as_setStrikethroughColor:strikethroughColor range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_underlineStyle:(NSUnderlineStyle)underlineStyle { - [self as_setUnderlineStyle:underlineStyle range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_underlineColor:(UIColor *)underlineColor { - [self as_setUnderlineColor:underlineColor range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_ligature:(NSNumber *)ligature { - [self as_setLigature:ligature range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_textEffect:(NSString *)textEffect { - [self as_setTextEffect:textEffect range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_obliqueness:(NSNumber *)obliqueness { - [self as_setObliqueness:obliqueness range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_expansion:(NSNumber *)expansion { - [self as_setExpansion:expansion range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_baselineOffset:(NSNumber *)baselineOffset { - [self as_setBaselineOffset:baselineOffset range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_verticalGlyphForm:(BOOL)verticalGlyphForm { - [self as_setVerticalGlyphForm:verticalGlyphForm range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_language:(NSString *)language { - [self as_setLanguage:language range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_writingDirection:(NSArray *)writingDirection { - [self as_setWritingDirection:writingDirection range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_paragraphStyle:(NSParagraphStyle *)paragraphStyle { - /* - NSParagraphStyle is NOT toll-free bridged to CTParagraphStyleRef. - - CoreText can use both NSParagraphStyle and CTParagraphStyleRef, - but UILabel/UITextView can only use NSParagraphStyle. - - We use NSParagraphStyle in both CoreText and UIKit. - */ - [self as_setParagraphStyle:paragraphStyle range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_alignment:(NSTextAlignment)alignment { - [self as_setAlignment:alignment range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_baseWritingDirection:(NSWritingDirection)baseWritingDirection { - [self as_setBaseWritingDirection:baseWritingDirection range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_lineSpacing:(CGFloat)lineSpacing { - [self as_setLineSpacing:lineSpacing range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_paragraphSpacing:(CGFloat)paragraphSpacing { - [self as_setParagraphSpacing:paragraphSpacing range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_paragraphSpacingBefore:(CGFloat)paragraphSpacingBefore { - [self as_setParagraphSpacing:paragraphSpacingBefore range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_firstLineHeadIndent:(CGFloat)firstLineHeadIndent { - [self as_setFirstLineHeadIndent:firstLineHeadIndent range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_headIndent:(CGFloat)headIndent { - [self as_setHeadIndent:headIndent range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_tailIndent:(CGFloat)tailIndent { - [self as_setTailIndent:tailIndent range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_lineBreakMode:(NSLineBreakMode)lineBreakMode { - [self as_setLineBreakMode:lineBreakMode range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_minimumLineHeight:(CGFloat)minimumLineHeight { - [self as_setMinimumLineHeight:minimumLineHeight range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_maximumLineHeight:(CGFloat)maximumLineHeight { - [self as_setMaximumLineHeight:maximumLineHeight range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_lineHeightMultiple:(CGFloat)lineHeightMultiple { - [self as_setLineHeightMultiple:lineHeightMultiple range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_hyphenationFactor:(float)hyphenationFactor { - [self as_setHyphenationFactor:hyphenationFactor range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_defaultTabInterval:(CGFloat)defaultTabInterval { - [self as_setDefaultTabInterval:defaultTabInterval range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_tabStops:(NSArray *)tabStops { - [self as_setTabStops:tabStops range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_textShadow:(ASTextShadow *)textShadow { - [self as_setTextShadow:textShadow range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_textInnerShadow:(ASTextShadow *)textInnerShadow { - [self as_setTextInnerShadow:textInnerShadow range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_textUnderline:(ASTextDecoration *)textUnderline { - [self as_setTextUnderline:textUnderline range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_textStrikethrough:(ASTextDecoration *)textStrikethrough { - [self as_setTextStrikethrough:textStrikethrough range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_textBorder:(ASTextBorder *)textBorder { - [self as_setTextBorder:textBorder range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_textBackgroundBorder:(ASTextBorder *)textBackgroundBorder { - [self as_setTextBackgroundBorder:textBackgroundBorder range:NSMakeRange(0, self.length)]; -} - -- (void)setAs_textGlyphTransform:(CGAffineTransform)textGlyphTransform { - [self as_setTextGlyphTransform:textGlyphTransform range:NSMakeRange(0, self.length)]; -} - -#pragma mark - Range Setter - -- (void)as_setFont:(UIFont *)font range:(NSRange)range { - [self as_setAttribute:NSFontAttributeName value:font range:range]; -} - -- (void)as_setKern:(NSNumber *)kern range:(NSRange)range { - [self as_setAttribute:NSKernAttributeName value:kern range:range]; -} - -- (void)as_setColor:(UIColor *)color range:(NSRange)range { - [self as_setAttribute:(id)kCTForegroundColorAttributeName value:(id)color.CGColor range:range]; - [self as_setAttribute:NSForegroundColorAttributeName value:color range:range]; -} - -- (void)as_setBackgroundColor:(UIColor *)backgroundColor range:(NSRange)range { - [self as_setAttribute:NSBackgroundColorAttributeName value:backgroundColor range:range]; -} - -- (void)as_setStrokeWidth:(NSNumber *)strokeWidth range:(NSRange)range { - [self as_setAttribute:NSStrokeWidthAttributeName value:strokeWidth range:range]; -} - -- (void)as_setStrokeColor:(UIColor *)strokeColor range:(NSRange)range { - [self as_setAttribute:(id)kCTStrokeColorAttributeName value:(id)strokeColor.CGColor range:range]; - [self as_setAttribute:NSStrokeColorAttributeName value:strokeColor range:range]; -} - -- (void)as_setShadow:(NSShadow *)shadow range:(NSRange)range { - [self as_setAttribute:NSShadowAttributeName value:shadow range:range]; -} - -- (void)as_setStrikethroughStyle:(NSUnderlineStyle)strikethroughStyle range:(NSRange)range { - NSNumber *style = strikethroughStyle == 0 ? nil : @(strikethroughStyle); - [self as_setAttribute:NSStrikethroughStyleAttributeName value:style range:range]; -} - -- (void)as_setStrikethroughColor:(UIColor *)strikethroughColor range:(NSRange)range { - [self as_setAttribute:NSStrikethroughColorAttributeName value:strikethroughColor range:range]; -} - -- (void)as_setUnderlineStyle:(NSUnderlineStyle)underlineStyle range:(NSRange)range { - NSNumber *style = underlineStyle == 0 ? nil : @(underlineStyle); - [self as_setAttribute:NSUnderlineStyleAttributeName value:style range:range]; -} - -- (void)as_setUnderlineColor:(UIColor *)underlineColor range:(NSRange)range { - [self as_setAttribute:(id)kCTUnderlineColorAttributeName value:(id)underlineColor.CGColor range:range]; - [self as_setAttribute:NSUnderlineColorAttributeName value:underlineColor range:range]; -} - -- (void)as_setLigature:(NSNumber *)ligature range:(NSRange)range { - [self as_setAttribute:NSLigatureAttributeName value:ligature range:range]; -} - -- (void)as_setTextEffect:(NSString *)textEffect range:(NSRange)range { - [self as_setAttribute:NSTextEffectAttributeName value:textEffect range:range]; -} - -- (void)as_setObliqueness:(NSNumber *)obliqueness range:(NSRange)range { - [self as_setAttribute:NSObliquenessAttributeName value:obliqueness range:range]; -} - -- (void)as_setExpansion:(NSNumber *)expansion range:(NSRange)range { - [self as_setAttribute:NSExpansionAttributeName value:expansion range:range]; -} - -- (void)as_setBaselineOffset:(NSNumber *)baselineOffset range:(NSRange)range { - [self as_setAttribute:NSBaselineOffsetAttributeName value:baselineOffset range:range]; -} - -- (void)as_setVerticalGlyphForm:(BOOL)verticalGlyphForm range:(NSRange)range { - NSNumber *v = verticalGlyphForm ? @(YES) : nil; - [self as_setAttribute:NSVerticalGlyphFormAttributeName value:v range:range]; -} - -- (void)as_setLanguage:(NSString *)language range:(NSRange)range { - [self as_setAttribute:(id)kCTLanguageAttributeName value:language range:range]; -} - -- (void)as_setWritingDirection:(NSArray *)writingDirection range:(NSRange)range { - [self as_setAttribute:(id)kCTWritingDirectionAttributeName value:writingDirection range:range]; -} - -- (void)as_setParagraphStyle:(NSParagraphStyle *)paragraphStyle range:(NSRange)range { - /* - NSParagraphStyle is NOT toll-free bridged to CTParagraphStyleRef. - - CoreText can use both NSParagraphStyle and CTParagraphStyleRef, - but UILabel/UITextView can only use NSParagraphStyle. - - We use NSParagraphStyle in both CoreText and UIKit. - */ - [self as_setAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range]; -} - -#define ParagraphStyleSet(_attr_) \ -[self enumerateAttribute:NSParagraphStyleAttributeName \ -inRange:range \ -options:kNilOptions \ -usingBlock: ^(NSParagraphStyle *value, NSRange subRange, BOOL *stop) { \ -NSMutableParagraphStyle *style = nil; \ -if (value) { \ -if (CFGetTypeID((__bridge CFTypeRef)(value)) == CTParagraphStyleGetTypeID()) { \ -value = [NSParagraphStyle as_styleWithCTStyle:(__bridge CTParagraphStyleRef)(value)]; \ -} \ -if (value. _attr_ == _attr_) return; \ -if ([value isKindOfClass:[NSMutableParagraphStyle class]]) { \ -style = (id)value; \ -} else { \ -style = value.mutableCopy; \ -} \ -} else { \ -if ([NSParagraphStyle defaultParagraphStyle]. _attr_ == _attr_) return; \ -style = [NSParagraphStyle defaultParagraphStyle].mutableCopy; \ -} \ -style. _attr_ = _attr_; \ -[self as_setParagraphStyle:style range:subRange]; \ -}]; - -- (void)as_setAlignment:(NSTextAlignment)alignment range:(NSRange)range { - ParagraphStyleSet(alignment); -} - -- (void)as_setBaseWritingDirection:(NSWritingDirection)baseWritingDirection range:(NSRange)range { - ParagraphStyleSet(baseWritingDirection); -} - -- (void)as_setLineSpacing:(CGFloat)lineSpacing range:(NSRange)range { - ParagraphStyleSet(lineSpacing); -} - -- (void)as_setParagraphSpacing:(CGFloat)paragraphSpacing range:(NSRange)range { - ParagraphStyleSet(paragraphSpacing); -} - -- (void)as_setParagraphSpacingBefore:(CGFloat)paragraphSpacingBefore range:(NSRange)range { - ParagraphStyleSet(paragraphSpacingBefore); -} - -- (void)as_setFirstLineHeadIndent:(CGFloat)firstLineHeadIndent range:(NSRange)range { - ParagraphStyleSet(firstLineHeadIndent); -} - -- (void)as_setHeadIndent:(CGFloat)headIndent range:(NSRange)range { - ParagraphStyleSet(headIndent); -} - -- (void)as_setTailIndent:(CGFloat)tailIndent range:(NSRange)range { - ParagraphStyleSet(tailIndent); -} - -- (void)as_setLineBreakMode:(NSLineBreakMode)lineBreakMode range:(NSRange)range { - ParagraphStyleSet(lineBreakMode); -} - -- (void)as_setMinimumLineHeight:(CGFloat)minimumLineHeight range:(NSRange)range { - ParagraphStyleSet(minimumLineHeight); -} - -- (void)as_setMaximumLineHeight:(CGFloat)maximumLineHeight range:(NSRange)range { - ParagraphStyleSet(maximumLineHeight); -} - -- (void)as_setLineHeightMultiple:(CGFloat)lineHeightMultiple range:(NSRange)range { - ParagraphStyleSet(lineHeightMultiple); -} - -- (void)as_setHyphenationFactor:(float)hyphenationFactor range:(NSRange)range { - ParagraphStyleSet(hyphenationFactor); -} - -- (void)as_setDefaultTabInterval:(CGFloat)defaultTabInterval range:(NSRange)range { - ParagraphStyleSet(defaultTabInterval); -} - -- (void)as_setTabStops:(NSArray *)tabStops range:(NSRange)range { - ParagraphStyleSet(tabStops); -} - -#undef ParagraphStyleSet - -- (void)as_setSuperscript:(NSNumber *)superscript range:(NSRange)range { - if ([superscript isEqualToNumber:@(0)]) { - superscript = nil; - } - [self as_setAttribute:(id)kCTSuperscriptAttributeName value:superscript range:range]; -} - -- (void)as_setGlyphInfo:(CTGlyphInfoRef)glyphInfo range:(NSRange)range { - [self as_setAttribute:(id)kCTGlyphInfoAttributeName value:(__bridge id)glyphInfo range:range]; -} - -- (void)as_setCharacterShape:(NSNumber *)characterShape range:(NSRange)range { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [self as_setAttribute:(id)kCTCharacterShapeAttributeName value:characterShape range:range]; -#pragma clang diagnostic pop -} - -- (void)as_setRunDelegate:(CTRunDelegateRef)runDelegate range:(NSRange)range { - [self as_setAttribute:(id)kCTRunDelegateAttributeName value:(__bridge id)runDelegate range:range]; -} - -- (void)as_setBaselineClass:(CFStringRef)baselineClass range:(NSRange)range { - [self as_setAttribute:(id)kCTBaselineClassAttributeName value:(__bridge id)baselineClass range:range]; -} - -- (void)as_setBaselineInfo:(CFDictionaryRef)baselineInfo range:(NSRange)range { - [self as_setAttribute:(id)kCTBaselineInfoAttributeName value:(__bridge id)baselineInfo range:range]; -} - -- (void)as_setBaselineReferenceInfo:(CFDictionaryRef)referenceInfo range:(NSRange)range { - [self as_setAttribute:(id)kCTBaselineReferenceInfoAttributeName value:(__bridge id)referenceInfo range:range]; -} - -- (void)as_setRubyAnnotation:(CTRubyAnnotationRef)ruby range:(NSRange)range { - [self as_setAttribute:(id)kCTRubyAnnotationAttributeName value:(__bridge id)ruby range:range]; -} - -- (void)as_setAttachment:(NSTextAttachment *)attachment range:(NSRange)range { - [self as_setAttribute:NSAttachmentAttributeName value:attachment range:range]; -} - -- (void)as_setLink:(id)link range:(NSRange)range { - [self as_setAttribute:NSLinkAttributeName value:link range:range]; -} - -- (void)as_setTextBackedString:(ASTextBackedString *)textBackedString range:(NSRange)range { - [self as_setAttribute:ASTextBackedStringAttributeName value:textBackedString range:range]; -} - -- (void)as_setTextBinding:(ASTextBinding *)textBinding range:(NSRange)range { - [self as_setAttribute:ASTextBindingAttributeName value:textBinding range:range]; -} - -- (void)as_setTextShadow:(ASTextShadow *)textShadow range:(NSRange)range { - [self as_setAttribute:ASTextShadowAttributeName value:textShadow range:range]; -} - -- (void)as_setTextInnerShadow:(ASTextShadow *)textInnerShadow range:(NSRange)range { - [self as_setAttribute:ASTextInnerShadowAttributeName value:textInnerShadow range:range]; -} - -- (void)as_setTextUnderline:(ASTextDecoration *)textUnderline range:(NSRange)range { - [self as_setAttribute:ASTextUnderlineAttributeName value:textUnderline range:range]; -} - -- (void)as_setTextStrikethrough:(ASTextDecoration *)textStrikethrough range:(NSRange)range { - [self as_setAttribute:ASTextStrikethroughAttributeName value:textStrikethrough range:range]; -} - -- (void)as_setTextBorder:(ASTextBorder *)textBorder range:(NSRange)range { - [self as_setAttribute:ASTextBorderAttributeName value:textBorder range:range]; -} - -- (void)as_setTextBackgroundBorder:(ASTextBorder *)textBackgroundBorder range:(NSRange)range { - [self as_setAttribute:ASTextBackgroundBorderAttributeName value:textBackgroundBorder range:range]; -} - -- (void)as_setTextAttachment:(ASTextAttachment *)textAttachment range:(NSRange)range { - [self as_setAttribute:ASTextAttachmentAttributeName value:textAttachment range:range]; -} - -- (void)as_setTextHighlight:(ASTextHighlight *)textHighlight range:(NSRange)range { - [self as_setAttribute:ASTextHighlightAttributeName value:textHighlight range:range]; -} - -- (void)as_setTextBlockBorder:(ASTextBorder *)textBlockBorder range:(NSRange)range { - [self as_setAttribute:ASTextBlockBorderAttributeName value:textBlockBorder range:range]; -} - -- (void)as_setTextGlyphTransform:(CGAffineTransform)textGlyphTransform range:(NSRange)range { - NSValue *value = CGAffineTransformIsIdentity(textGlyphTransform) ? nil : [NSValue valueWithCGAffineTransform:textGlyphTransform]; - [self as_setAttribute:ASTextGlyphTransformAttributeName value:value range:range]; -} - -- (void)as_setTextHighlightRange:(NSRange)range - color:(UIColor *)color - backgroundColor:(UIColor *)backgroundColor - userInfo:(NSDictionary *)userInfo - tapAction:(ASTextAction)tapAction - longPressAction:(ASTextAction)longPressAction { - ASTextHighlight *highlight = [ASTextHighlight highlightWithBackgroundColor:backgroundColor]; - highlight.userInfo = userInfo; - highlight.tapAction = tapAction; - highlight.longPressAction = longPressAction; - if (color) [self as_setColor:color range:range]; - [self as_setTextHighlight:highlight range:range]; -} - -- (void)as_setTextHighlightRange:(NSRange)range - color:(UIColor *)color - backgroundColor:(UIColor *)backgroundColor - tapAction:(ASTextAction)tapAction { - [self as_setTextHighlightRange:range - color:color - backgroundColor:backgroundColor - userInfo:nil - tapAction:tapAction - longPressAction:nil]; -} - -- (void)as_setTextHighlightRange:(NSRange)range - color:(UIColor *)color - backgroundColor:(UIColor *)backgroundColor - userInfo:(NSDictionary *)userInfo { - [self as_setTextHighlightRange:range - color:color - backgroundColor:backgroundColor - userInfo:userInfo - tapAction:nil - longPressAction:nil]; -} - -- (void)as_insertString:(NSString *)string atIndex:(NSUInteger)location { - [self replaceCharactersInRange:NSMakeRange(location, 0) withString:string]; - [self as_removeDiscontinuousAttributesInRange:NSMakeRange(location, string.length)]; -} - -- (void)as_appendString:(NSString *)string { - NSUInteger length = self.length; - [self replaceCharactersInRange:NSMakeRange(length, 0) withString:string]; - [self as_removeDiscontinuousAttributesInRange:NSMakeRange(length, string.length)]; -} - -- (void)as_removeDiscontinuousAttributesInRange:(NSRange)range { - NSArray *keys = [NSMutableAttributedString as_allDiscontinuousAttributeKeys]; - for (NSString *key in keys) { - [self removeAttribute:key range:range]; - } -} - -+ (NSArray *)as_allDiscontinuousAttributeKeys { - static NSArray *keys; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - keys = @[(id)kCTSuperscriptAttributeName, - (id)kCTRunDelegateAttributeName, - ASTextBackedStringAttributeName, - ASTextBindingAttributeName, - ASTextAttachmentAttributeName, - (id)kCTRubyAnnotationAttributeName, - NSAttachmentAttributeName]; - }); - return keys; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSMutableAttributedString+TextKitAdditions.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSMutableAttributedString+TextKitAdditions.h deleted file mode 100644 index afb96722c6..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSMutableAttributedString+TextKitAdditions.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// NSMutableAttributedString+TextKitAdditions.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface NSMutableAttributedString (TextKitAdditions) - -- (void)attributeTextInRange:(NSRange)range withTextKitMinimumLineHeight:(CGFloat)minimumLineHeight; - -- (void)attributeTextInRange:(NSRange)range withTextKitMinimumLineHeight:(CGFloat)minimumLineHeight maximumLineHeight:(CGFloat)maximumLineHeight; - -- (void)attributeTextInRange:(NSRange)range withTextKitLineHeight:(CGFloat)lineHeight; - -- (void)attributeTextInRange:(NSRange)range withTextKitParagraphStyle:(NSParagraphStyle *)paragraphStyle; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSMutableAttributedString+TextKitAdditions.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSMutableAttributedString+TextKitAdditions.mm deleted file mode 100644 index 3f2ed9d35c..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSMutableAttributedString+TextKitAdditions.mm +++ /dev/null @@ -1,49 +0,0 @@ -// -// NSMutableAttributedString+TextKitAdditions.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -@implementation NSMutableAttributedString (TextKitAdditions) - -#pragma mark - Convenience Methods - -- (void)attributeTextInRange:(NSRange)range withTextKitMinimumLineHeight:(CGFloat)minimumLineHeight -{ - if (range.length) { - - NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; - [style setMinimumLineHeight:minimumLineHeight]; - [self attributeTextInRange:range withTextKitParagraphStyle:style]; - } -} - -- (void)attributeTextInRange:(NSRange)range withTextKitMinimumLineHeight:(CGFloat)minimumLineHeight maximumLineHeight:(CGFloat)maximumLineHeight -{ - if (range.length) { - - NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; - [style setMinimumLineHeight:minimumLineHeight]; - [style setMaximumLineHeight:maximumLineHeight]; - [self attributeTextInRange:range withTextKitParagraphStyle:style]; - } -} - -- (void)attributeTextInRange:(NSRange)range withTextKitLineHeight:(CGFloat)lineHeight -{ - [self attributeTextInRange:range withTextKitMinimumLineHeight:lineHeight maximumLineHeight:lineHeight]; -} - -- (void)attributeTextInRange:(NSRange)range withTextKitParagraphStyle:(NSParagraphStyle *)paragraphStyle -{ - if (range.length) { - [self addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range]; - } -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSParagraphStyle+ASText.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSParagraphStyle+ASText.h deleted file mode 100644 index a7c0aec5ff..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSParagraphStyle+ASText.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// NSParagraphStyle+ASText.h -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - Provides extensions for `NSParagraphStyle` to work with CoreText. - */ -@interface NSParagraphStyle (ASText) - -/** - Creates a new NSParagraphStyle object from the CoreText Style. - - @param CTStyle CoreText Paragraph Style. - - @return a new NSParagraphStyle - */ -+ (nullable NSParagraphStyle *)as_styleWithCTStyle:(CTParagraphStyleRef)CTStyle; - -/** - Creates and returns a CoreText Paragraph Style. (need call CFRelease() after used) - */ -- (nullable CTParagraphStyleRef)as_CTStyle CF_RETURNS_RETAINED; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSParagraphStyle+ASText.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSParagraphStyle+ASText.mm deleted file mode 100644 index bc19fd234c..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSParagraphStyle+ASText.mm +++ /dev/null @@ -1,219 +0,0 @@ -// -// NSParagraphStyle+ASText.mm -// Texture -// -// Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import -#import - -// Dummy class for category -@interface NSParagraphStyle_ASText : NSObject @end -@implementation NSParagraphStyle_ASText @end - - -@implementation NSParagraphStyle (ASText) - -+ (NSParagraphStyle *)as_styleWithCTStyle:(CTParagraphStyleRef)CTStyle { - if (CTStyle == NULL) return nil; - - NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; - -#if TARGET_OS_IOS -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - CGFloat lineSpacing; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierLineSpacing, sizeof(CGFloat), &lineSpacing)) { - style.lineSpacing = lineSpacing; - } -#pragma clang diagnostic pop -#endif - - CGFloat paragraphSpacing; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierParagraphSpacing, sizeof(CGFloat), ¶graphSpacing)) { - style.paragraphSpacing = paragraphSpacing; - } - - CTTextAlignment alignment; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &alignment)) { - style.alignment = NSTextAlignmentFromCTTextAlignment(alignment); - } - - CGFloat firstLineHeadIndent; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierFirstLineHeadIndent, sizeof(CGFloat), &firstLineHeadIndent)) { - style.firstLineHeadIndent = firstLineHeadIndent; - } - - CGFloat headIndent; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierHeadIndent, sizeof(CGFloat), &headIndent)) { - style.headIndent = headIndent; - } - - CGFloat tailIndent; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierTailIndent, sizeof(CGFloat), &tailIndent)) { - style.tailIndent = tailIndent; - } - - CTLineBreakMode lineBreakMode; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierLineBreakMode, sizeof(CTLineBreakMode), &lineBreakMode)) { - style.lineBreakMode = (NSLineBreakMode)lineBreakMode; - } - - CGFloat minimumLineHeight; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierMinimumLineHeight, sizeof(CGFloat), &minimumLineHeight)) { - style.minimumLineHeight = minimumLineHeight; - } - - CGFloat maximumLineHeight; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierMaximumLineHeight, sizeof(CGFloat), &maximumLineHeight)) { - style.maximumLineHeight = maximumLineHeight; - } - - CTWritingDirection baseWritingDirection; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierBaseWritingDirection, sizeof(CTWritingDirection), &baseWritingDirection)) { - style.baseWritingDirection = (NSWritingDirection)baseWritingDirection; - } - - CGFloat lineHeightMultiple; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierLineHeightMultiple, sizeof(CGFloat), &lineHeightMultiple)) { - style.lineHeightMultiple = lineHeightMultiple; - } - - CGFloat paragraphSpacingBefore; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierParagraphSpacingBefore, sizeof(CGFloat), ¶graphSpacingBefore)) { - style.paragraphSpacingBefore = paragraphSpacingBefore; - } - - CFArrayRef tabStops; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierTabStops, sizeof(CFArrayRef), &tabStops)) { - NSMutableArray *tabs = [NSMutableArray new]; - [((__bridge NSArray *)(tabStops))enumerateObjectsUsingBlock : ^(id obj, NSUInteger idx, BOOL *stop) { - CTTextTabRef ctTab = (__bridge CTTextTabRef)obj; - - NSTextTab *tab = [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentFromCTTextAlignment(CTTextTabGetAlignment(ctTab)) location:CTTextTabGetLocation(ctTab) options:(__bridge id)CTTextTabGetOptions(ctTab)]; - [tabs addObject:tab]; - }]; - if (tabs.count) { - style.tabStops = tabs; - } - } - - CGFloat defaultTabInterval; - if (CTParagraphStyleGetValueForSpecifier(CTStyle, kCTParagraphStyleSpecifierDefaultTabInterval, sizeof(CGFloat), &defaultTabInterval)) { - style.defaultTabInterval = defaultTabInterval; - } - - return style; -} - -- (CTParagraphStyleRef)as_CTStyle CF_RETURNS_RETAINED { - CTParagraphStyleSetting set[kCTParagraphStyleSpecifierCount] = { }; - int count = 0; - -#if TARGET_OS_IOS -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - CGFloat lineSpacing = self.lineSpacing; - set[count].spec = kCTParagraphStyleSpecifierLineSpacing; - set[count].valueSize = sizeof(CGFloat); - set[count].value = &lineSpacing; - count++; -#pragma clang diagnostic pop -#endif - - CGFloat paragraphSpacing = self.paragraphSpacing; - set[count].spec = kCTParagraphStyleSpecifierParagraphSpacing; - set[count].valueSize = sizeof(CGFloat); - set[count].value = ¶graphSpacing; - count++; - - CTTextAlignment alignment = NSTextAlignmentToCTTextAlignment(self.alignment); - set[count].spec = kCTParagraphStyleSpecifierAlignment; - set[count].valueSize = sizeof(CTTextAlignment); - set[count].value = &alignment; - count++; - - CGFloat firstLineHeadIndent = self.firstLineHeadIndent; - set[count].spec = kCTParagraphStyleSpecifierFirstLineHeadIndent; - set[count].valueSize = sizeof(CGFloat); - set[count].value = &firstLineHeadIndent; - count++; - - CGFloat headIndent = self.headIndent; - set[count].spec = kCTParagraphStyleSpecifierHeadIndent; - set[count].valueSize = sizeof(CGFloat); - set[count].value = &headIndent; - count++; - - CGFloat tailIndent = self.tailIndent; - set[count].spec = kCTParagraphStyleSpecifierTailIndent; - set[count].valueSize = sizeof(CGFloat); - set[count].value = &tailIndent; - count++; - - CTLineBreakMode paraLineBreak = (CTLineBreakMode)self.lineBreakMode; - set[count].spec = kCTParagraphStyleSpecifierLineBreakMode; - set[count].valueSize = sizeof(CTLineBreakMode); - set[count].value = ¶LineBreak; - count++; - - CGFloat minimumLineHeight = self.minimumLineHeight; - set[count].spec = kCTParagraphStyleSpecifierMinimumLineHeight; - set[count].valueSize = sizeof(CGFloat); - set[count].value = &minimumLineHeight; - count++; - - CGFloat maximumLineHeight = self.maximumLineHeight; - set[count].spec = kCTParagraphStyleSpecifierMaximumLineHeight; - set[count].valueSize = sizeof(CGFloat); - set[count].value = &maximumLineHeight; - count++; - - CTWritingDirection paraWritingDirection = (CTWritingDirection)self.baseWritingDirection; - set[count].spec = kCTParagraphStyleSpecifierBaseWritingDirection; - set[count].valueSize = sizeof(CTWritingDirection); - set[count].value = ¶WritingDirection; - count++; - - CGFloat lineHeightMultiple = self.lineHeightMultiple; - set[count].spec = kCTParagraphStyleSpecifierLineHeightMultiple; - set[count].valueSize = sizeof(CGFloat); - set[count].value = &lineHeightMultiple; - count++; - - CGFloat paragraphSpacingBefore = self.paragraphSpacingBefore; - set[count].spec = kCTParagraphStyleSpecifierParagraphSpacingBefore; - set[count].valueSize = sizeof(CGFloat); - set[count].value = ¶graphSpacingBefore; - count++; - - NSMutableArray *tabs = [NSMutableArray array]; - NSInteger numTabs = self.tabStops.count; - if (numTabs) { - [self.tabStops enumerateObjectsUsingBlock: ^(NSTextTab *tab, NSUInteger idx, BOOL *stop) { - CTTextTabRef ctTab = CTTextTabCreate(NSTextAlignmentToCTTextAlignment(tab.alignment), tab.location, (__bridge CFDictionaryRef)tab.options); - [tabs addObject:(__bridge id)ctTab]; - CFRelease(ctTab); - }]; - - CFArrayRef tabStops = (__bridge CFArrayRef)(tabs); - set[count].spec = kCTParagraphStyleSpecifierTabStops; - set[count].valueSize = sizeof(CFArrayRef); - set[count].value = &tabStops; - count++; - } - - CGFloat defaultTabInterval = self.defaultTabInterval; - set[count].spec = kCTParagraphStyleSpecifierDefaultTabInterval; - set[count].valueSize = sizeof(CGFloat); - set[count].value = &defaultTabInterval; - count++; - - CTParagraphStyleRef style = CTParagraphStyleCreate(set, count); - return style; -} - -@end diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UICollectionViewLayout+ASConvenience.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UICollectionViewLayout+ASConvenience.h deleted file mode 100644 index 78e55a17bd..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UICollectionViewLayout+ASConvenience.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// UICollectionViewLayout+ASConvenience.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import - -@protocol ASCollectionViewLayoutInspecting; - -NS_ASSUME_NONNULL_BEGIN - -@interface UICollectionViewLayout (ASLayoutInspectorProviding) - -/** - * You can override this method on your @c UICollectionViewLayout subclass to - * return a layout inspector tailored to your layout. - * - * It's fine to return @c self. You must not return @c nil. - */ -- (id)asdk_layoutInspector; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UICollectionViewLayout+ASConvenience.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UICollectionViewLayout+ASConvenience.mm deleted file mode 100644 index d63b51a157..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UICollectionViewLayout+ASConvenience.mm +++ /dev/null @@ -1,32 +0,0 @@ -// -// UICollectionViewLayout+ASConvenience.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#ifndef MINIMAL_ASDK - -#import - -#import - -#import - -@implementation UICollectionViewLayout (ASLayoutInspectorProviding) - -- (id)asdk_layoutInspector -{ - UICollectionViewFlowLayout *flow = ASDynamicCast(self, UICollectionViewFlowLayout); - if (flow != nil) { - return [[ASCollectionViewFlowLayoutInspector alloc] initWithFlowLayout:flow]; - } else { - return [[ASCollectionViewLayoutInspector alloc] init]; - } -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASHierarchyChangeSet.h b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASHierarchyChangeSet.h deleted file mode 100644 index 800be37517..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASHierarchyChangeSet.h +++ /dev/null @@ -1,218 +0,0 @@ -// -// _ASHierarchyChangeSet.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#ifndef MINIMAL_ASDK - -#import -#import -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef NSUInteger ASDataControllerAnimationOptions; - -typedef NS_ENUM(NSInteger, _ASHierarchyChangeType) { - /** - * A reload change, as submitted by the user. When a change set is - * completed, these changes are decomposed into delete-insert pairs - * and combined with the original deletes and inserts of the change. - */ - _ASHierarchyChangeTypeReload, - - /** - * A change that was either an original delete, or the first - * part of a decomposed reload. - */ - _ASHierarchyChangeTypeDelete, - - /** - * A change that was submitted by the user as a delete. - */ - _ASHierarchyChangeTypeOriginalDelete, - - /** - * A change that was either an original insert, or the second - * part of a decomposed reload. - */ - _ASHierarchyChangeTypeInsert, - - /** - * A change that was submitted by the user as an insert. - */ - _ASHierarchyChangeTypeOriginalInsert -}; - -/** - * Returns YES if the given change type is either .Insert or .Delete, NO otherwise. - * Other change types – .Reload, .OriginalInsert, .OriginalDelete – are - * intermediary types used while building the change set. All changes will - * be reduced to either .Insert or .Delete when the change is marked completed. - */ -BOOL ASHierarchyChangeTypeIsFinal(_ASHierarchyChangeType changeType); - -NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType); - -@interface _ASHierarchySectionChange : NSObject - -// FIXME: Generalize this to `changeMetadata` dict? -@property (nonatomic, readonly) ASDataControllerAnimationOptions animationOptions; - -@property (nonatomic, readonly) NSIndexSet *indexSet; - -@property (nonatomic, readonly) _ASHierarchyChangeType changeType; - -/** - * If this is a .OriginalInsert or .OriginalDelete change, this returns a copied change - * with type .Insert or .Delete. Calling this on changes of other types is an error. - */ -- (_ASHierarchySectionChange *)changeByFinalizingType; - -@end - -@interface _ASHierarchyItemChange : NSObject - -@property (nonatomic, readonly) ASDataControllerAnimationOptions animationOptions; - -/// Index paths are sorted descending for changeType .Delete, ascending otherwise -@property (nonatomic, readonly) NSArray *indexPaths; - -@property (nonatomic, readonly) _ASHierarchyChangeType changeType; - -+ (NSDictionary *)sectionToIndexSetMapFromChanges:(NSArray<_ASHierarchyItemChange *> *)changes; - -/** - * If this is a .OriginalInsert or .OriginalDelete change, this returns a copied change - * with type .Insert or .Delete. Calling this on changes of other types is an error. - */ -- (_ASHierarchyItemChange *)changeByFinalizingType; - -@end - -@interface _ASHierarchyChangeSet : NSObject - -/// @precondition The change set must be completed. -@property (nonatomic, readonly) NSIndexSet *deletedSections; - -/// @precondition The change set must be completed. -@property (nonatomic, readonly) NSIndexSet *insertedSections; - -@property (nonatomic, readonly) BOOL completed; - -/// Whether or not changes should be animated. -// TODO: if any update in this chagne set is non-animated, the whole update should be non-animated. -@property (nonatomic) BOOL animated; - -@property (nonatomic, readonly) BOOL includesReloadData; - -/// Indicates whether the change set is empty, that is it includes neither reload data nor per item or section changes. -@property (nonatomic, readonly) BOOL isEmpty; - -/// The count of new ASCellNodes that can undergo async layout calculation. May be zero if all UIKit passthrough cells. -@property (nonatomic, assign) NSUInteger countForAsyncLayout; - -/// The top-level activity for this update. -@property (nonatomic, OS_ACTIVITY_NULLABLE) os_activity_t rootActivity; - -/// The activity for submitting this update i.e. between -beginUpdates and -endUpdates. -@property (nonatomic, OS_ACTIVITY_NULLABLE) os_activity_t submitActivity; - -- (instancetype)initWithOldData:(std::vector)oldItemCounts NS_DESIGNATED_INITIALIZER; - -/** - * Append the given completion handler to the combined @c completionHandler. - * - * @discussion Since batch updates can be nested, we have to support multiple - * completion handlers per update. - * - * @precondition The change set must not be completed. - */ -- (void)addCompletionHandler:(nullable void(^)(BOOL finished))completion; - -/** - * Execute the combined completion handler. - * - * @warning The completion block is discarded after reading because it may have captured - * significant resources that we would like to reclaim as soon as possible. - */ -- (void)executeCompletionHandlerWithFinished:(BOOL)finished; - -/** - * Get the section index after the update for the given section before the update. - * - * @precondition The change set must be completed. - * @return The new section index, or NSNotFound if the given section was deleted. - */ -- (NSUInteger)newSectionForOldSection:(NSUInteger)oldSection; - -/** - * A table that maps old section indexes to new section indexes. - */ -@property (nonatomic, readonly) ASIntegerMap *sectionMapping; - -/** - * A table that maps new section indexes to old section indexes. - */ -@property (nonatomic, readonly) ASIntegerMap *reverseSectionMapping; - -/** - * A table that provides the item mapping for the old section. If the section was deleted - * or is out of bounds, returns the empty table. - */ -- (ASIntegerMap *)itemMappingInSection:(NSInteger)oldSection; - -/** - * A table that provides the reverse item mapping for the new section. If the section was inserted - * or is out of bounds, returns the empty table. - */ -- (ASIntegerMap *)reverseItemMappingInSection:(NSInteger)newSection; - -/** - * Get the old item index path for the given new index path. - * - * @precondition The change set must be completed. - * @return The old index path, or nil if the given item was inserted. - */ -- (nullable NSIndexPath *)oldIndexPathForNewIndexPath:(NSIndexPath *)indexPath; - -/** - * Get the new item index path for the given old index path. - * - * @precondition The change set must be completed. - * @return The new index path, or nil if the given item was deleted. - */ -- (nullable NSIndexPath *)newIndexPathForOldIndexPath:(NSIndexPath *)indexPath; - -/// Call this once the change set has been constructed to prevent future modifications to the changeset. Calling this more than once is a programmer error. -/// NOTE: Calling this method will cause the changeset to convert all reloads into delete/insert pairs. -- (void)markCompletedWithNewItemCounts:(std::vector)newItemCounts; - -- (nullable NSArray <_ASHierarchySectionChange *> *)sectionChangesOfType:(_ASHierarchyChangeType)changeType; - -- (nullable NSArray <_ASHierarchyItemChange *> *)itemChangesOfType:(_ASHierarchyChangeType)changeType; - -/// Returns all item indexes affected by changes of the given type in the given section. -- (NSIndexSet *)indexesForItemChangesOfType:(_ASHierarchyChangeType)changeType inSection:(NSUInteger)section; - -- (void)reloadData; -- (void)deleteSections:(NSIndexSet *)sections animationOptions:(ASDataControllerAnimationOptions)options; -- (void)insertSections:(NSIndexSet *)sections animationOptions:(ASDataControllerAnimationOptions)options; -- (void)reloadSections:(NSIndexSet *)sections animationOptions:(ASDataControllerAnimationOptions)options; -- (void)insertItems:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options; -- (void)deleteItems:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options; -- (void)reloadItems:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options; -- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection animationOptions:(ASDataControllerAnimationOptions)options; -- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath animationOptions:(ASDataControllerAnimationOptions)options; - -@end - -NS_ASSUME_NONNULL_END - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASHierarchyChangeSet.mm b/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASHierarchyChangeSet.mm deleted file mode 100644 index 77d4d1af3f..0000000000 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASHierarchyChangeSet.mm +++ /dev/null @@ -1,1016 +0,0 @@ -// -// _ASHierarchyChangeSet.mm -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#ifndef MINIMAL_ASDK - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -// If assertions are enabled and they haven't forced us to suppress the exception, -// then throw, otherwise log. -#if ASDISPLAYNODE_ASSERTIONS_ENABLED - #define ASFailUpdateValidation(...)\ - _Pragma("clang diagnostic push")\ - _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")\ - if ([ASDisplayNode suppressesInvalidCollectionUpdateExceptions]) {\ - NSLog(__VA_ARGS__);\ - } else {\ - NSLog(__VA_ARGS__);\ - [NSException raise:ASCollectionInvalidUpdateException format:__VA_ARGS__];\ - }\ - _Pragma("clang diagnostic pop") -#else - #define ASFailUpdateValidation(...) NSLog(__VA_ARGS__); -#endif - -BOOL ASHierarchyChangeTypeIsFinal(_ASHierarchyChangeType changeType) { - switch (changeType) { - case _ASHierarchyChangeTypeInsert: - case _ASHierarchyChangeTypeDelete: - return YES; - default: - return NO; - } -} - -NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType) -{ - switch (changeType) { - case _ASHierarchyChangeTypeInsert: - return @"Insert"; - case _ASHierarchyChangeTypeOriginalInsert: - return @"OriginalInsert"; - case _ASHierarchyChangeTypeDelete: - return @"Delete"; - case _ASHierarchyChangeTypeOriginalDelete: - return @"OriginalDelete"; - case _ASHierarchyChangeTypeReload: - return @"Reload"; - default: - return @"(invalid)"; - } -} - -@interface _ASHierarchySectionChange () -- (instancetype)initWithChangeType:(_ASHierarchyChangeType)changeType indexSet:(NSIndexSet *)indexSet animationOptions:(ASDataControllerAnimationOptions)animationOptions; - -/** - On return `changes` is sorted according to the change type with changes coalesced by animationOptions - Assumes: `changes` all have the same changeType - */ -+ (void)sortAndCoalesceSectionChanges:(NSMutableArray<_ASHierarchySectionChange *> *)changes; - -/// Returns all the indexes from all the `indexSet`s of the given `_ASHierarchySectionChange` objects. -+ (NSMutableIndexSet *)allIndexesInSectionChanges:(NSArray *)changes; - -+ (NSString *)smallDescriptionForSectionChanges:(NSArray<_ASHierarchySectionChange *> *)changes; -@end - -@interface _ASHierarchyItemChange () -- (instancetype)initWithChangeType:(_ASHierarchyChangeType)changeType indexPaths:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)animationOptions presorted:(BOOL)presorted; - -/** - On return `changes` is sorted according to the change type with changes coalesced by animationOptions - Assumes: `changes` all have the same changeType - */ -+ (void)sortAndCoalesceItemChanges:(NSMutableArray<_ASHierarchyItemChange *> *)changes ignoringChangesInSections:(NSIndexSet *)sections; - -+ (NSString *)smallDescriptionForItemChanges:(NSArray<_ASHierarchyItemChange *> *)changes; - -+ (void)ensureItemChanges:(NSArray<_ASHierarchyItemChange *> *)changes ofSameType:(_ASHierarchyChangeType)changeType; -@end - -@interface _ASHierarchyChangeSet () - -// array index is old section index, map goes oldItem -> newItem -@property (nonatomic, readonly) NSMutableArray *itemMappings; - -// array index is new section index, map goes newItem -> oldItem -@property (nonatomic, readonly) NSMutableArray *reverseItemMappings; - -@property (nonatomic, readonly) NSMutableArray<_ASHierarchyItemChange *> *insertItemChanges; -@property (nonatomic, readonly) NSMutableArray<_ASHierarchyItemChange *> *originalInsertItemChanges; - -@property (nonatomic, readonly) NSMutableArray<_ASHierarchyItemChange *> *deleteItemChanges; -@property (nonatomic, readonly) NSMutableArray<_ASHierarchyItemChange *> *originalDeleteItemChanges; - -@property (nonatomic, readonly) NSMutableArray<_ASHierarchyItemChange *> *reloadItemChanges; - -@property (nonatomic, readonly) NSMutableArray<_ASHierarchySectionChange *> *insertSectionChanges; -@property (nonatomic, readonly) NSMutableArray<_ASHierarchySectionChange *> *originalInsertSectionChanges; - -@property (nonatomic, readonly) NSMutableArray<_ASHierarchySectionChange *> *deleteSectionChanges; -@property (nonatomic, readonly) NSMutableArray<_ASHierarchySectionChange *> *originalDeleteSectionChanges; - -@property (nonatomic, readonly) NSMutableArray<_ASHierarchySectionChange *> *reloadSectionChanges; - -@end - -@implementation _ASHierarchyChangeSet { - NSUInteger _countForAsyncLayout; - std::vector _oldItemCounts; - std::vector _newItemCounts; - void (^_completionHandler)(BOOL finished); -} -@synthesize sectionMapping = _sectionMapping; -@synthesize reverseSectionMapping = _reverseSectionMapping; -@synthesize itemMappings = _itemMappings; -@synthesize reverseItemMappings = _reverseItemMappings; -@synthesize countForAsyncLayout = _countForAsyncLayout; - -- (instancetype)init -{ - ASFailUpdateValidation(@"_ASHierarchyChangeSet: -init is not supported. Call -initWithOldData:"); - return [self initWithOldData:std::vector()]; -} - -- (instancetype)initWithOldData:(std::vector)oldItemCounts -{ - self = [super init]; - if (self) { - _oldItemCounts = oldItemCounts; - - _originalInsertItemChanges = [[NSMutableArray alloc] init]; - _insertItemChanges = [[NSMutableArray alloc] init]; - _originalDeleteItemChanges = [[NSMutableArray alloc] init]; - _deleteItemChanges = [[NSMutableArray alloc] init]; - _reloadItemChanges = [[NSMutableArray alloc] init]; - - _originalInsertSectionChanges = [[NSMutableArray alloc] init]; - _insertSectionChanges = [[NSMutableArray alloc] init]; - _originalDeleteSectionChanges = [[NSMutableArray alloc] init]; - _deleteSectionChanges = [[NSMutableArray alloc] init]; - _reloadSectionChanges = [[NSMutableArray alloc] init]; - } - return self; -} - -#pragma mark External API - -- (BOOL)isEmpty -{ - return (! _includesReloadData) && (! [self _includesPerItemOrSectionChanges]); -} - -- (void)addCompletionHandler:(void (^)(BOOL))completion -{ - [self _ensureNotCompleted]; - if (completion == nil) { - return; - } - - void (^oldCompletionHandler)(BOOL finished) = _completionHandler; - _completionHandler = ^(BOOL finished) { - if (oldCompletionHandler != nil) { - oldCompletionHandler(finished); - } - completion(finished); - }; -} - -- (void)executeCompletionHandlerWithFinished:(BOOL)finished -{ - if (_completionHandler != nil) { - _completionHandler(finished); - _completionHandler = nil; - } -} - -- (void)markCompletedWithNewItemCounts:(std::vector)newItemCounts -{ - NSAssert(!_completed, @"Attempt to mark already-completed changeset as completed."); - _completed = YES; - _newItemCounts = newItemCounts; - [self _sortAndCoalesceChangeArrays]; - [self _validateUpdate]; -} - -- (NSArray *)sectionChangesOfType:(_ASHierarchyChangeType)changeType -{ - [self _ensureCompleted]; - switch (changeType) { - case _ASHierarchyChangeTypeInsert: - return _insertSectionChanges; - case _ASHierarchyChangeTypeReload: - return _reloadSectionChanges; - case _ASHierarchyChangeTypeDelete: - return _deleteSectionChanges; - case _ASHierarchyChangeTypeOriginalDelete: - return _originalDeleteSectionChanges; - case _ASHierarchyChangeTypeOriginalInsert: - return _originalInsertSectionChanges; - default: - NSAssert(NO, @"Request for section changes with invalid type: %lu", (long)changeType); - return nil; - } -} - -- (NSArray *)itemChangesOfType:(_ASHierarchyChangeType)changeType -{ - [self _ensureCompleted]; - switch (changeType) { - case _ASHierarchyChangeTypeInsert: - return _insertItemChanges; - case _ASHierarchyChangeTypeReload: - return _reloadItemChanges; - case _ASHierarchyChangeTypeDelete: - return _deleteItemChanges; - case _ASHierarchyChangeTypeOriginalInsert: - return _originalInsertItemChanges; - case _ASHierarchyChangeTypeOriginalDelete: - return _originalDeleteItemChanges; - default: - NSAssert(NO, @"Request for item changes with invalid type: %lu", (long)changeType); - return nil; - } -} - -- (NSIndexSet *)indexesForItemChangesOfType:(_ASHierarchyChangeType)changeType inSection:(NSUInteger)section -{ - [self _ensureCompleted]; - const auto result = [[NSMutableIndexSet alloc] init]; - for (_ASHierarchyItemChange *change in [self itemChangesOfType:changeType]) { - [result addIndexes:[NSIndexSet as_indexSetFromIndexPaths:change.indexPaths inSection:section]]; - } - return result; -} - -- (NSUInteger)newSectionForOldSection:(NSUInteger)oldSection -{ - return [self.sectionMapping integerForKey:oldSection]; -} - -- (NSUInteger)oldSectionForNewSection:(NSUInteger)newSection -{ - return [self.reverseSectionMapping integerForKey:newSection]; -} - -- (ASIntegerMap *)sectionMapping -{ - ASDisplayNodeAssertNotNil(_deletedSections, @"Cannot call %s before `markCompleted` returns.", sel_getName(_cmd)); - ASDisplayNodeAssertNotNil(_insertedSections, @"Cannot call %s before `markCompleted` returns.", sel_getName(_cmd)); - [self _ensureCompleted]; - if (_sectionMapping == nil) { - _sectionMapping = [ASIntegerMap mapForUpdateWithOldCount:_oldItemCounts.size() deleted:_deletedSections inserted:_insertedSections]; - } - return _sectionMapping; -} - -- (ASIntegerMap *)reverseSectionMapping -{ - if (_reverseSectionMapping == nil) { - _reverseSectionMapping = [self.sectionMapping inverseMap]; - } - return _reverseSectionMapping; -} - -- (NSMutableArray *)itemMappings -{ - [self _ensureCompleted]; - - if (_itemMappings == nil) { - _itemMappings = [[NSMutableArray alloc] init]; - const auto insertMap = [_ASHierarchyItemChange sectionToIndexSetMapFromChanges:_originalInsertItemChanges]; - const auto deleteMap = [_ASHierarchyItemChange sectionToIndexSetMapFromChanges:_originalDeleteItemChanges]; - NSInteger oldSection = 0; - for (NSInteger oldCount : _oldItemCounts) { - NSInteger newSection = [self newSectionForOldSection:oldSection]; - ASIntegerMap *table; - if (newSection == NSNotFound) { - table = ASIntegerMap.emptyMap; - } else { - table = [ASIntegerMap mapForUpdateWithOldCount:oldCount deleted:deleteMap[@(oldSection)] inserted:insertMap[@(newSection)]]; - } - _itemMappings[oldSection] = table; - oldSection++; - } - } - return _itemMappings; -} - -- (NSMutableArray *)reverseItemMappings -{ - [self _ensureCompleted]; - - if (_reverseItemMappings == nil) { - _reverseItemMappings = [[NSMutableArray alloc] init]; - for (NSInteger newSection = 0; newSection < _newItemCounts.size(); newSection++) { - NSInteger oldSection = [self oldSectionForNewSection:newSection]; - ASIntegerMap *table; - if (oldSection == NSNotFound) { - table = ASIntegerMap.emptyMap; - } else { - table = [[self itemMappingInSection:oldSection] inverseMap]; - } - _reverseItemMappings[newSection] = table; - } - } - return _reverseItemMappings; -} - -- (ASIntegerMap *)itemMappingInSection:(NSInteger)oldSection -{ - if (self.includesReloadData || oldSection >= _oldItemCounts.size()) { - return ASIntegerMap.emptyMap; - } - return self.itemMappings[oldSection]; -} - -- (ASIntegerMap *)reverseItemMappingInSection:(NSInteger)newSection -{ - if (self.includesReloadData || newSection >= _newItemCounts.size()) { - return ASIntegerMap.emptyMap; - } - return self.reverseItemMappings[newSection]; -} - -- (NSIndexPath *)oldIndexPathForNewIndexPath:(NSIndexPath *)indexPath -{ - [self _ensureCompleted]; - NSInteger newSection = indexPath.section; - NSInteger oldSection = [self oldSectionForNewSection:newSection]; - if (oldSection == NSNotFound) { - return nil; - } - NSInteger oldItem = [[self reverseItemMappingInSection:newSection] integerForKey:indexPath.item]; - if (oldItem == NSNotFound) { - return nil; - } - return [NSIndexPath indexPathForItem:oldItem inSection:oldSection]; -} - -- (NSIndexPath *)newIndexPathForOldIndexPath:(NSIndexPath *)indexPath -{ - [self _ensureCompleted]; - NSInteger oldSection = indexPath.section; - NSInteger newSection = [self newSectionForOldSection:oldSection]; - if (newSection == NSNotFound) { - return nil; - } - NSInteger newItem = [[self itemMappingInSection:oldSection] integerForKey:indexPath.item]; - if (newItem == NSNotFound) { - return nil; - } - return [NSIndexPath indexPathForItem:newItem inSection:newSection]; -} - -- (void)reloadData -{ - [self _ensureNotCompleted]; - NSAssert(_includesReloadData == NO, @"Attempt to reload data multiple times %@", self); - _includesReloadData = YES; -} - -- (void)deleteItems:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options -{ - [self _ensureNotCompleted]; - _ASHierarchyItemChange *change = [[_ASHierarchyItemChange alloc] initWithChangeType:_ASHierarchyChangeTypeOriginalDelete indexPaths:indexPaths animationOptions:options presorted:NO]; - [_originalDeleteItemChanges addObject:change]; -} - -- (void)deleteSections:(NSIndexSet *)sections animationOptions:(ASDataControllerAnimationOptions)options -{ - [self _ensureNotCompleted]; - _ASHierarchySectionChange *change = [[_ASHierarchySectionChange alloc] initWithChangeType:_ASHierarchyChangeTypeOriginalDelete indexSet:sections animationOptions:options]; - [_originalDeleteSectionChanges addObject:change]; -} - -- (void)insertItems:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options -{ - [self _ensureNotCompleted]; - _ASHierarchyItemChange *change = [[_ASHierarchyItemChange alloc] initWithChangeType:_ASHierarchyChangeTypeOriginalInsert indexPaths:indexPaths animationOptions:options presorted:NO]; - [_originalInsertItemChanges addObject:change]; -} - -- (void)insertSections:(NSIndexSet *)sections animationOptions:(ASDataControllerAnimationOptions)options -{ - [self _ensureNotCompleted]; - _ASHierarchySectionChange *change = [[_ASHierarchySectionChange alloc] initWithChangeType:_ASHierarchyChangeTypeOriginalInsert indexSet:sections animationOptions:options]; - [_originalInsertSectionChanges addObject:change]; -} - -- (void)reloadItems:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options -{ - [self _ensureNotCompleted]; - _ASHierarchyItemChange *change = [[_ASHierarchyItemChange alloc] initWithChangeType:_ASHierarchyChangeTypeReload indexPaths:indexPaths animationOptions:options presorted:NO]; - [_reloadItemChanges addObject:change]; -} - -- (void)reloadSections:(NSIndexSet *)sections animationOptions:(ASDataControllerAnimationOptions)options -{ - [self _ensureNotCompleted]; - _ASHierarchySectionChange *change = [[_ASHierarchySectionChange alloc] initWithChangeType:_ASHierarchyChangeTypeReload indexSet:sections animationOptions:options]; - [_reloadSectionChanges addObject:change]; -} - -- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath animationOptions:(ASDataControllerAnimationOptions)options -{ - /** - * TODO: Proper move implementation. - */ - [self deleteItems:@[ indexPath ] animationOptions:options]; - [self insertItems:@[ newIndexPath ] animationOptions:options]; -} - -- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection animationOptions:(ASDataControllerAnimationOptions)options -{ - /** - * TODO: Proper move implementation. - */ - [self deleteSections:[NSIndexSet indexSetWithIndex:section] animationOptions:options]; - [self insertSections:[NSIndexSet indexSetWithIndex:newSection] animationOptions:options]; -} - -#pragma mark Private - -- (BOOL)_ensureNotCompleted -{ - NSAssert(!_completed, @"Attempt to modify completed changeset %@", self); - return !_completed; -} - -- (BOOL)_ensureCompleted -{ - NSAssert(_completed, @"Attempt to process incomplete changeset %@", self); - return _completed; -} - -- (void)_sortAndCoalesceChangeArrays -{ - if (_includesReloadData) { - return; - } - - @autoreleasepool { - - // Split reloaded sections into [delete(oldIndex), insert(newIndex)] - - // Give these their "pre-reloads" values. Once we add in the reloads we'll re-process them. - _deletedSections = [_ASHierarchySectionChange allIndexesInSectionChanges:_originalDeleteSectionChanges]; - _insertedSections = [_ASHierarchySectionChange allIndexesInSectionChanges:_originalInsertSectionChanges]; - for (_ASHierarchySectionChange *originalDeleteSectionChange in _originalDeleteSectionChanges) { - [_deleteSectionChanges addObject:[originalDeleteSectionChange changeByFinalizingType]]; - } - for (_ASHierarchySectionChange *originalInsertSectionChange in _originalInsertSectionChanges) { - [_insertSectionChanges addObject:[originalInsertSectionChange changeByFinalizingType]]; - } - - for (_ASHierarchySectionChange *change in _reloadSectionChanges) { - NSIndexSet *newSections = [change.indexSet as_indexesByMapping:^(NSUInteger idx) { - NSUInteger newSec = [self newSectionForOldSection:idx]; - ASDisplayNodeAssert(newSec != NSNotFound, @"Request to reload and delete same section %tu", idx); - return newSec; - }]; - - _ASHierarchySectionChange *deleteChange = [[_ASHierarchySectionChange alloc] initWithChangeType:_ASHierarchyChangeTypeDelete indexSet:change.indexSet animationOptions:change.animationOptions]; - [_deleteSectionChanges addObject:deleteChange]; - - _ASHierarchySectionChange *insertChange = [[_ASHierarchySectionChange alloc] initWithChangeType:_ASHierarchyChangeTypeInsert indexSet:newSections animationOptions:change.animationOptions]; - [_insertSectionChanges addObject:insertChange]; - } - - [_ASHierarchySectionChange sortAndCoalesceSectionChanges:_deleteSectionChanges]; - [_ASHierarchySectionChange sortAndCoalesceSectionChanges:_insertSectionChanges]; - _deletedSections = [_ASHierarchySectionChange allIndexesInSectionChanges:_deleteSectionChanges]; - _insertedSections = [_ASHierarchySectionChange allIndexesInSectionChanges:_insertSectionChanges]; - - // Split reloaded items into [delete(oldIndexPath), insert(newIndexPath)] - for (_ASHierarchyItemChange *originalDeleteItemChange in _originalDeleteItemChanges) { - [_deleteItemChanges addObject:[originalDeleteItemChange changeByFinalizingType]]; - } - for (_ASHierarchyItemChange *originalInsertItemChange in _originalInsertItemChanges) { - [_insertItemChanges addObject:[originalInsertItemChange changeByFinalizingType]]; - } - - [_ASHierarchyItemChange ensureItemChanges:_insertItemChanges ofSameType:_ASHierarchyChangeTypeInsert]; - [_ASHierarchyItemChange ensureItemChanges:_deleteItemChanges ofSameType:_ASHierarchyChangeTypeDelete]; - - for (_ASHierarchyItemChange *change in _reloadItemChanges) { - NSAssert(change.changeType == _ASHierarchyChangeTypeReload, @"It must be a reload change to be in here"); - - const auto newIndexPaths = ASArrayByFlatMapping(change.indexPaths, NSIndexPath *indexPath, [self newIndexPathForOldIndexPath:indexPath]); - - // All reload changes are translated into deletes and inserts - // We delete the items that needs reload together with other deleted items, at their original index - _ASHierarchyItemChange *deleteItemChangeFromReloadChange = [[_ASHierarchyItemChange alloc] initWithChangeType:_ASHierarchyChangeTypeDelete indexPaths:change.indexPaths animationOptions:change.animationOptions presorted:NO]; - [_deleteItemChanges addObject:deleteItemChangeFromReloadChange]; - // We insert the items that needs reload together with other inserted items, at their future index - _ASHierarchyItemChange *insertItemChangeFromReloadChange = [[_ASHierarchyItemChange alloc] initWithChangeType:_ASHierarchyChangeTypeInsert indexPaths:newIndexPaths animationOptions:change.animationOptions presorted:NO]; - [_insertItemChanges addObject:insertItemChangeFromReloadChange]; - } - - // Ignore item deletes in reloaded/deleted sections. - [_ASHierarchyItemChange sortAndCoalesceItemChanges:_deleteItemChanges ignoringChangesInSections:_deletedSections]; - - // Ignore item inserts in reloaded(new)/inserted sections. - [_ASHierarchyItemChange sortAndCoalesceItemChanges:_insertItemChanges ignoringChangesInSections:_insertedSections]; - } -} - -- (void)_validateUpdate -{ - // If reloadData exists, ignore other changes - if (_includesReloadData) { - if ([self _includesPerItemOrSectionChanges]) { - NSLog(@"Warning: A reload data shouldn't be used in conjuntion with other updates."); - } - return; - } - - NSIndexSet *allReloadedSections = [_ASHierarchySectionChange allIndexesInSectionChanges:_reloadSectionChanges]; - - NSInteger newSectionCount = _newItemCounts.size(); - NSInteger oldSectionCount = _oldItemCounts.size(); - - NSInteger insertedSectionCount = _insertedSections.count; - NSInteger deletedSectionCount = _deletedSections.count; - // Assert that the new section count is correct. - if (newSectionCount != oldSectionCount + insertedSectionCount - deletedSectionCount) { - ASFailUpdateValidation(@"Invalid number of sections. The number of sections after the update (%ld) must be equal to the number of sections before the update (%ld) plus or minus the number of sections inserted or deleted (%ld inserted, %ld deleted)", (long)newSectionCount, (long)oldSectionCount, (long)insertedSectionCount, (long)deletedSectionCount); - return; - } - - // Assert that no invalid deletes/reloads happened. - NSInteger invalidSectionDelete = NSNotFound; - if (oldSectionCount == 0) { - invalidSectionDelete = _deletedSections.firstIndex; - } else { - invalidSectionDelete = [_deletedSections indexGreaterThanIndex:oldSectionCount - 1]; - } - if (invalidSectionDelete != NSNotFound) { - ASFailUpdateValidation(@"Attempt to delete section %ld but there are only %ld sections before the update.", (long)invalidSectionDelete, (long)oldSectionCount); - return; - } - - for (_ASHierarchyItemChange *change in _deleteItemChanges) { - for (NSIndexPath *indexPath in change.indexPaths) { - // Assert that item delete happened in a valid section. - NSInteger section = indexPath.section; - NSInteger item = indexPath.item; - if (section >= oldSectionCount) { - ASFailUpdateValidation(@"Attempt to delete item %ld from section %ld, but there are only %ld sections before the update.", (long)item, (long)section, (long)oldSectionCount); - return; - } - - // Assert that item delete happened to a valid item. - NSInteger oldItemCount = _oldItemCounts[section]; - if (item >= oldItemCount) { - ASFailUpdateValidation(@"Attempt to delete item %ld from section %ld, which only contains %ld items before the update.", (long)item, (long)section, (long)oldItemCount); - return; - } - } - } - - for (_ASHierarchyItemChange *change in _insertItemChanges) { - for (NSIndexPath *indexPath in change.indexPaths) { - NSInteger section = indexPath.section; - NSInteger item = indexPath.item; - // Assert that item insert happened in a valid section. - if (section >= newSectionCount) { - ASFailUpdateValidation(@"Attempt to insert item %ld into section %ld, but there are only %ld sections after the update.", (long)item, (long)section, (long)newSectionCount); - return; - } - - // Assert that item delete happened to a valid item. - NSInteger newItemCount = _newItemCounts[section]; - if (item >= newItemCount) { - ASFailUpdateValidation(@"Attempt to insert item %ld into section %ld, which only contains %ld items after the update.", (long)item, (long)section, (long)newItemCount); - return; - } - } - } - - // Assert that no sections were inserted out of bounds. - NSInteger invalidSectionInsert = NSNotFound; - if (newSectionCount == 0) { - invalidSectionInsert = _insertedSections.firstIndex; - } else { - invalidSectionInsert = [_insertedSections indexGreaterThanIndex:newSectionCount - 1]; - } - if (invalidSectionInsert != NSNotFound) { - ASFailUpdateValidation(@"Attempt to insert section %ld but there are only %ld sections after the update.", (long)invalidSectionInsert, (long)newSectionCount); - return; - } - - for (NSUInteger oldSection = 0; oldSection < oldSectionCount; oldSection++) { - NSInteger oldItemCount = _oldItemCounts[oldSection]; - // If section was reloaded, ignore. - if ([allReloadedSections containsIndex:oldSection]) { - continue; - } - - // If section was deleted, ignore. - NSUInteger newSection = [self newSectionForOldSection:oldSection]; - if (newSection == NSNotFound) { - continue; - } - - NSIndexSet *originalInsertedItems = [self indexesForItemChangesOfType:_ASHierarchyChangeTypeOriginalInsert inSection:newSection]; - NSIndexSet *originalDeletedItems = [self indexesForItemChangesOfType:_ASHierarchyChangeTypeOriginalDelete inSection:oldSection]; - NSIndexSet *reloadedItems = [self indexesForItemChangesOfType:_ASHierarchyChangeTypeReload inSection:oldSection]; - - // Assert that no reloaded items were deleted. - NSInteger deletedReloadedItem = [originalDeletedItems as_intersectionWithIndexes:reloadedItems].firstIndex; - if (deletedReloadedItem != NSNotFound) { - ASFailUpdateValidation(@"Attempt to delete and reload the same item at index path %@", [NSIndexPath indexPathForItem:deletedReloadedItem inSection:oldSection]); - return; - } - - // Assert that the new item count is correct. - NSInteger newItemCount = _newItemCounts[newSection]; - NSInteger insertedItemCount = originalInsertedItems.count; - NSInteger deletedItemCount = originalDeletedItems.count; - if (newItemCount != oldItemCount + insertedItemCount - deletedItemCount) { - ASFailUpdateValidation(@"Invalid number of items in section %ld. The number of items after the update (%ld) must be equal to the number of items before the update (%ld) plus or minus the number of items inserted or deleted (%ld inserted, %ld deleted).", (long)oldSection, (long)newItemCount, (long)oldItemCount, (long)insertedItemCount, (long)deletedItemCount); - return; - } - } -} - -- (BOOL)_includesPerItemOrSectionChanges -{ - return 0 < (_originalDeleteSectionChanges.count + _originalDeleteItemChanges.count - +_originalInsertSectionChanges.count + _originalInsertItemChanges.count - + _reloadSectionChanges.count + _reloadItemChanges.count); -} - -#pragma mark - Debugging (Private) - -- (NSString *)description -{ - return ASObjectDescriptionMakeWithoutObject([self propertiesForDescription]); -} - -- (NSString *)debugDescription -{ - return ASObjectDescriptionMake(self, [self propertiesForDebugDescription]); -} - -- (NSMutableArray *)propertiesForDescription -{ - NSMutableArray *result = [NSMutableArray array]; - if (_includesReloadData) { - [result addObject:@{ @"reloadData" : @"YES" }]; - } - if (_reloadSectionChanges.count > 0) { - [result addObject:@{ @"reloadSections" : [_ASHierarchySectionChange smallDescriptionForSectionChanges:_reloadSectionChanges] }]; - } - if (_reloadItemChanges.count > 0) { - [result addObject:@{ @"reloadItems" : [_ASHierarchyItemChange smallDescriptionForItemChanges:_reloadItemChanges] }]; - } - if (_originalDeleteSectionChanges.count > 0) { - [result addObject:@{ @"deleteSections" : [_ASHierarchySectionChange smallDescriptionForSectionChanges:_originalDeleteSectionChanges] }]; - } - if (_originalDeleteItemChanges.count > 0) { - [result addObject:@{ @"deleteItems" : [_ASHierarchyItemChange smallDescriptionForItemChanges:_originalDeleteItemChanges] }]; - } - if (_originalInsertSectionChanges.count > 0) { - [result addObject:@{ @"insertSections" : [_ASHierarchySectionChange smallDescriptionForSectionChanges:_originalInsertSectionChanges] }]; - } - if (_originalInsertItemChanges.count > 0) { - [result addObject:@{ @"insertItems" : [_ASHierarchyItemChange smallDescriptionForItemChanges:_originalInsertItemChanges] }]; - } - return result; -} - -- (NSMutableArray *)propertiesForDebugDescription -{ - return [self propertiesForDescription]; -} - -@end - -@implementation _ASHierarchySectionChange - -- (instancetype)initWithChangeType:(_ASHierarchyChangeType)changeType indexSet:(NSIndexSet *)indexSet animationOptions:(ASDataControllerAnimationOptions)animationOptions -{ - self = [super init]; - if (self) { - ASDisplayNodeAssert(indexSet.count > 0, @"Request to create _ASHierarchySectionChange with no sections!"); - _changeType = changeType; - _indexSet = indexSet; - _animationOptions = animationOptions; - } - return self; -} - -- (_ASHierarchySectionChange *)changeByFinalizingType -{ - _ASHierarchyChangeType newType; - switch (_changeType) { - case _ASHierarchyChangeTypeOriginalInsert: - newType = _ASHierarchyChangeTypeInsert; - break; - case _ASHierarchyChangeTypeOriginalDelete: - newType = _ASHierarchyChangeTypeDelete; - break; - default: - ASFailUpdateValidation(@"Attempt to finalize section change of invalid type %@.", NSStringFromASHierarchyChangeType(_changeType)); - return self; - } - return [[_ASHierarchySectionChange alloc] initWithChangeType:newType indexSet:_indexSet animationOptions:_animationOptions]; -} - -+ (void)sortAndCoalesceSectionChanges:(NSMutableArray<_ASHierarchySectionChange *> *)changes -{ - _ASHierarchySectionChange *firstChange = changes.firstObject; - if (firstChange == nil) { - return; - } - _ASHierarchyChangeType type = [firstChange changeType]; - - ASDisplayNodeAssert(ASHierarchyChangeTypeIsFinal(type), @"Attempt to sort and coalesce section changes of intermediary type %@. Why?", NSStringFromASHierarchyChangeType(type)); - - // Lookup table [Int: AnimationOptions] - __block std::unordered_map animationOptions; - - // All changed indexes - NSMutableIndexSet *allIndexes = [NSMutableIndexSet new]; - - for (_ASHierarchySectionChange *change in changes) { - ASDataControllerAnimationOptions options = change.animationOptions; - NSIndexSet *indexes = change.indexSet; - [indexes enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) { - for (NSUInteger i = range.location; i < NSMaxRange(range); i++) { - animationOptions[i] = options; - } - }]; - [allIndexes addIndexes:indexes]; - } - - // Create new changes by grouping sorted changes by animation option - NSMutableArray *result = [[NSMutableArray alloc] init]; - - __block ASDataControllerAnimationOptions currentOptions = 0; - const auto currentIndexes = [[NSMutableIndexSet alloc] init]; - - BOOL reverse = type == _ASHierarchyChangeTypeDelete || type == _ASHierarchyChangeTypeOriginalDelete; - NSEnumerationOptions options = reverse ? NSEnumerationReverse : kNilOptions; - - [allIndexes enumerateRangesWithOptions:options usingBlock:^(NSRange range, BOOL * _Nonnull stop) { - NSInteger increment = reverse ? -1 : 1; - NSUInteger start = reverse ? NSMaxRange(range) - 1 : range.location; - NSInteger limit = reverse ? range.location - 1 : NSMaxRange(range); - for (NSInteger i = start; i != limit; i += increment) { - ASDataControllerAnimationOptions options = animationOptions[i]; - - // End the previous group if needed. - if (options != currentOptions && currentIndexes.count > 0) { - _ASHierarchySectionChange *change = [[_ASHierarchySectionChange alloc] initWithChangeType:type indexSet:[currentIndexes copy] animationOptions:currentOptions]; - [result addObject:change]; - [currentIndexes removeAllIndexes]; - } - - // Start a new group if needed. - if (currentIndexes.count == 0) { - currentOptions = options; - } - - [currentIndexes addIndex:i]; - } - }]; - - // Finish up the last group. - if (currentIndexes.count > 0) { - _ASHierarchySectionChange *change = [[_ASHierarchySectionChange alloc] initWithChangeType:type indexSet:[currentIndexes copy] animationOptions:currentOptions]; - [result addObject:change]; - } - - [changes setArray:result]; -} - -+ (NSMutableIndexSet *)allIndexesInSectionChanges:(NSArray<_ASHierarchySectionChange *> *)changes -{ - const auto indexes = [[NSMutableIndexSet alloc] init]; - for (_ASHierarchySectionChange *change in changes) { - [indexes addIndexes:change.indexSet]; - } - return indexes; -} - -#pragma mark - Debugging (Private) - -+ (NSString *)smallDescriptionForSectionChanges:(NSArray<_ASHierarchySectionChange *> *)changes -{ - NSMutableIndexSet *unionIndexSet = [NSMutableIndexSet indexSet]; - for (_ASHierarchySectionChange *change in changes) { - [unionIndexSet addIndexes:change.indexSet]; - } - return [unionIndexSet as_smallDescription]; -} - -- (NSString *)description -{ - return ASObjectDescriptionMake(self, [self propertiesForDescription]); -} - -- (NSString *)debugDescription -{ - return ASObjectDescriptionMake(self, [self propertiesForDebugDescription]); -} - -- (NSString *)smallDescription -{ - return [self.indexSet as_smallDescription]; -} - -- (NSMutableArray *)propertiesForDescription -{ - NSMutableArray *result = [NSMutableArray array]; - [result addObject:@{ @"indexes" : [self.indexSet as_smallDescription] }]; - return result; -} - -- (NSMutableArray *)propertiesForDebugDescription -{ - NSMutableArray *result = [NSMutableArray array]; - [result addObject:@{ @"anim" : @(_animationOptions) }]; - [result addObject:@{ @"type" : NSStringFromASHierarchyChangeType(_changeType) }]; - [result addObject:@{ @"indexes" : self.indexSet }]; - return result; -} - -@end - -@implementation _ASHierarchyItemChange - -- (instancetype)initWithChangeType:(_ASHierarchyChangeType)changeType indexPaths:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)animationOptions presorted:(BOOL)presorted -{ - self = [super init]; - if (self) { - ASDisplayNodeAssert(indexPaths.count > 0, @"Request to create _ASHierarchyItemChange with no items!"); - _changeType = changeType; - if (presorted) { - _indexPaths = indexPaths; - } else { - SEL sorting = changeType == _ASHierarchyChangeTypeDelete ? @selector(asdk_inverseCompare:) : @selector(compare:); - _indexPaths = [indexPaths sortedArrayUsingSelector:sorting]; - } - _animationOptions = animationOptions; - } - return self; -} - -// Create a mapping out of changes indexPaths to a {@section : [indexSet]} fashion -// e.g. changes: (0 - 0), (0 - 1), (2 - 5) -// will become: {@0 : [0, 1], @2 : [5]} -+ (NSDictionary *)sectionToIndexSetMapFromChanges:(NSArray<_ASHierarchyItemChange *> *)changes -{ - NSMutableDictionary *sectionToIndexSetMap = [[NSMutableDictionary alloc] init]; - for (_ASHierarchyItemChange *change in changes) { - for (NSIndexPath *indexPath in change.indexPaths) { - NSNumber *sectionKey = @(indexPath.section); - NSMutableIndexSet *indexSet = sectionToIndexSetMap[sectionKey]; - if (indexSet) { - [indexSet addIndex:indexPath.item]; - } else { - indexSet = [NSMutableIndexSet indexSetWithIndex:indexPath.item]; - sectionToIndexSetMap[sectionKey] = indexSet; - } - } - } - return sectionToIndexSetMap; -} - -+ (void)ensureItemChanges:(NSArray<_ASHierarchyItemChange *> *)changes ofSameType:(_ASHierarchyChangeType)changeType -{ -#if ASDISPLAYNODE_ASSERTIONS_ENABLED - for (_ASHierarchyItemChange *change in changes) { - NSAssert(change.changeType == changeType, @"The map we created must all be of the same changeType as of now"); - } -#endif -} - -- (_ASHierarchyItemChange *)changeByFinalizingType -{ - _ASHierarchyChangeType newType; - switch (_changeType) { - case _ASHierarchyChangeTypeOriginalInsert: - newType = _ASHierarchyChangeTypeInsert; - break; - case _ASHierarchyChangeTypeOriginalDelete: - newType = _ASHierarchyChangeTypeDelete; - break; - default: - ASFailUpdateValidation(@"Attempt to finalize item change of invalid type %@.", NSStringFromASHierarchyChangeType(_changeType)); - return self; - } - return [[_ASHierarchyItemChange alloc] initWithChangeType:newType indexPaths:_indexPaths animationOptions:_animationOptions presorted:YES]; -} - -+ (void)sortAndCoalesceItemChanges:(NSMutableArray<_ASHierarchyItemChange *> *)changes ignoringChangesInSections:(NSIndexSet *)ignoredSections -{ - if (changes.count < 1) { - return; - } - - _ASHierarchyChangeType type = [changes.firstObject changeType]; - ASDisplayNodeAssert(ASHierarchyChangeTypeIsFinal(type), @"Attempt to sort and coalesce item changes of intermediary type %@. Why?", NSStringFromASHierarchyChangeType(type)); - - // Lookup table [NSIndexPath: AnimationOptions] - const auto animationOptions = [[NSMutableDictionary alloc] init]; - - // All changed index paths, sorted - const auto allIndexPaths = [[NSMutableArray alloc] init]; - - for (_ASHierarchyItemChange *change in changes) { - for (NSIndexPath *indexPath in change.indexPaths) { - if (![ignoredSections containsIndex:indexPath.section]) { - animationOptions[indexPath] = @(change.animationOptions); - [allIndexPaths addObject:indexPath]; - } - } - } - - SEL sorting = type == _ASHierarchyChangeTypeDelete ? @selector(asdk_inverseCompare:) : @selector(compare:); - [allIndexPaths sortUsingSelector:sorting]; - - // Create new changes by grouping sorted changes by animation option - const auto result = [[NSMutableArray<_ASHierarchyItemChange *> alloc] init]; - - ASDataControllerAnimationOptions currentOptions = 0; - const auto currentIndexPaths = [[NSMutableArray alloc] init]; - - for (NSIndexPath *indexPath in allIndexPaths) { - ASDataControllerAnimationOptions options = [animationOptions[indexPath] integerValue]; - - // End the previous group if needed. - if (options != currentOptions && currentIndexPaths.count > 0) { - _ASHierarchyItemChange *change = [[_ASHierarchyItemChange alloc] initWithChangeType:type indexPaths:[currentIndexPaths copy] animationOptions:currentOptions presorted:YES]; - [result addObject:change]; - [currentIndexPaths removeAllObjects]; - } - - // Start a new group if needed. - if (currentIndexPaths.count == 0) { - currentOptions = options; - } - - [currentIndexPaths addObject:indexPath]; - } - - // Finish up the last group. - if (currentIndexPaths.count > 0) { - _ASHierarchyItemChange *change = [[_ASHierarchyItemChange alloc] initWithChangeType:type indexPaths:[currentIndexPaths copy] animationOptions:currentOptions presorted:YES]; - [result addObject:change]; - } - - [changes setArray:result]; -} - -#pragma mark - Debugging (Private) - -+ (NSString *)smallDescriptionForItemChanges:(NSArray<_ASHierarchyItemChange *> *)changes -{ - NSDictionary *map = [self sectionToIndexSetMapFromChanges:changes]; - NSMutableString *str = [NSMutableString stringWithString:@"{ "]; - [map enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull section, NSIndexSet * _Nonnull indexSet, BOOL * _Nonnull stop) { - [str appendFormat:@"@%lu : %@ ", (long)section.integerValue, [indexSet as_smallDescription]]; - }]; - [str appendString:@"}"]; - return str; -} - -- (NSString *)description -{ - return ASObjectDescriptionMake(self, [self propertiesForDescription]); -} - -- (NSString *)debugDescription -{ - return ASObjectDescriptionMake(self, [self propertiesForDebugDescription]); -} - -- (NSMutableArray *)propertiesForDescription -{ - NSMutableArray *result = [NSMutableArray array]; - [result addObject:@{ @"indexPaths" : self.indexPaths }]; - return result; -} - -- (NSMutableArray *)propertiesForDebugDescription -{ - NSMutableArray *result = [NSMutableArray array]; - [result addObject:@{ @"anim" : @(_animationOptions) }]; - [result addObject:@{ @"type" : NSStringFromASHierarchyChangeType(_changeType) }]; - [result addObject:@{ @"indexPaths" : self.indexPaths }]; - return result; -} - -@end - -#endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSArray+Diffing.mm b/submodules/AsyncDisplayKit/Source/NSArray+Diffing.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSArray+Diffing.mm rename to submodules/AsyncDisplayKit/Source/NSArray+Diffing.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSIndexSet+ASHelpers.h b/submodules/AsyncDisplayKit/Source/NSIndexSet+ASHelpers.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSIndexSet+ASHelpers.h rename to submodules/AsyncDisplayKit/Source/NSIndexSet+ASHelpers.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSIndexSet+ASHelpers.mm b/submodules/AsyncDisplayKit/Source/NSIndexSet+ASHelpers.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSIndexSet+ASHelpers.mm rename to submodules/AsyncDisplayKit/Source/NSIndexSet+ASHelpers.mm index 0eba0358f4..615e1749f0 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSIndexSet+ASHelpers.mm +++ b/submodules/AsyncDisplayKit/Source/NSIndexSet+ASHelpers.mm @@ -10,7 +10,7 @@ // UIKit indexPath helpers #import -#import +#import "NSIndexSet+ASHelpers.h" @implementation NSIndexSet (ASHelpers) diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASEventLog.h b/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASEventLog.h deleted file mode 100644 index 9a147f259d..0000000000 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASEventLog.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// ASEventLog.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -#ifndef ASEVENTLOG_CAPACITY -#define ASEVENTLOG_CAPACITY 5 -#endif - -#ifndef ASEVENTLOG_ENABLE -#define ASEVENTLOG_ENABLE 0 -#endif - -NS_ASSUME_NONNULL_BEGIN - -AS_SUBCLASSING_RESTRICTED -@interface ASEventLog : NSObject - -/** - * Create a new event log. - * - * @param anObject The object whose events we are logging. This object is not retained. - */ -- (instancetype)initWithObject:(id)anObject; - -- (void)logEventWithBacktrace:(nullable NSArray *)backtrace format:(NSString *)format, ... NS_FORMAT_FUNCTION(2, 3); - -- (instancetype)init NS_UNAVAILABLE; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutRangeType.h b/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutRangeType.h deleted file mode 100644 index d4af470c06..0000000000 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutRangeType.h +++ /dev/null @@ -1,68 +0,0 @@ -// -// ASLayoutRangeType.h -// Texture -// -// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. -// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. -// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 -// - -#import -#import - -typedef struct { - CGFloat leadingBufferScreenfuls; - CGFloat trailingBufferScreenfuls; -} ASRangeTuningParameters; - -AS_EXTERN ASRangeTuningParameters const ASRangeTuningParametersZero; - -AS_EXTERN BOOL ASRangeTuningParametersEqualToRangeTuningParameters(ASRangeTuningParameters lhs, ASRangeTuningParameters rhs); - -/** - * Each mode has a complete set of tuning parameters for range types. - * Depending on some conditions (including interface state and direction of the scroll view, state of rendering engine, etc), - * a range controller can choose which mode it should use at a given time. - */ -typedef NS_ENUM(NSInteger, ASLayoutRangeMode) { - ASLayoutRangeModeUnspecified = -1, - - /** - * Minimum mode is used when a range controller should limit the amount of work it performs. - * Thus, fewer views/layers are created and less data is fetched, saving system resources. - * Range controller can automatically switch to full mode when conditions change. - */ - ASLayoutRangeModeMinimum = 0, - - /** - * Normal/Full mode that a range controller uses to provide the best experience for end users. - * This mode is usually used for an active scroll view. - * A range controller under this requires more resources compare to minimum mode. - */ - ASLayoutRangeModeFull, - - /** - * Visible Only mode is used when a range controller should set its display and preload regions to only the size of their bounds. - * This causes all additional backing stores & preloaded data to be released, while ensuring a user revisiting the view will - * still be able to see the expected content. This mode is automatically set on all ASRangeControllers when the app suspends, - * allowing the operating system to keep the app alive longer and increase the chance it is still warm when the user returns. - */ - ASLayoutRangeModeVisibleOnly, - - /** - * Low Memory mode is used when a range controller should discard ALL graphics buffers, including for the area that would be visible - * the next time the user views it (bounds). The only range it preserves is Preload, which is limited to the bounds, allowing - * the content to be restored relatively quickly by re-decoding images (the compressed images are ~10% the size of the decoded ones, - * and text is a tiny fraction of its rendered size). - */ - ASLayoutRangeModeLowMemory -}; - -static NSInteger const ASLayoutRangeModeCount = 4; - -typedef NS_ENUM(NSInteger, ASLayoutRangeType) { - ASLayoutRangeTypeDisplay, - ASLayoutRangeTypePreload -}; - -static NSInteger const ASLayoutRangeTypeCount = 2; diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASAbsoluteLayoutElement.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASAbsoluteLayoutElement.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASAbsoluteLayoutElement.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASAbsoluteLayoutElement.h index 2ae11bd2d6..18f488d9de 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASAbsoluteLayoutElement.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASAbsoluteLayoutElement.h @@ -7,8 +7,8 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import #import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASAsciiArtBoxCreator.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASAsciiArtBoxCreator.h new file mode 100644 index 0000000000..6d4fe22ea9 --- /dev/null +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASAsciiArtBoxCreator.h @@ -0,0 +1,61 @@ +// +// ASAsciiArtBoxCreator.h +// Texture +// +// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol ASLayoutElementAsciiArtProtocol +/** + * Returns an ascii-art representation of this object and its children. + * For example, an ASInsetSpec may return something like this: + * + * --ASInsetLayoutSpec-- + * | ASTextNode | + * --------------------- + */ +- (NSString *)asciiArtString; + +/** + * returns the name of this object that will display in the ascii art. Usually this can + * simply be NSStringFromClass([self class]). + */ +- (NSString *)asciiArtName; + +@end + +/** + * A that takes a parent and its children and renders as ascii art box. + */ +@interface ASAsciiArtBoxCreator : NSObject + +/** + * Renders an ascii art box with the children aligned horizontally + * Example: + * ------------ASStackLayoutSpec----------- + * | ASTextNode ASTextNode ASTextNode | + * ---------------------------------------- + */ ++ (NSString *)horizontalBoxStringForChildren:(NSArray *)children parent:(NSString *)parent; + +/** + * Renders an ascii art box with the children aligned vertically. + * Example: + * --ASStackLayoutSpec-- + * | ASTextNode | + * | ASTextNode | + * | ASTextNode | + * --------------------- + */ ++ (NSString *)verticalBoxStringForChildren:(NSArray *)children parent:(NSString *)parent; + +@end + +NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASAssert.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASAssert.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASAssert.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASAssert.h index f00ce967d6..d6e9dad1c2 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASAssert.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASAssert.h @@ -9,6 +9,7 @@ #pragma once +#import #import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASAvailability.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASAvailability.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASAvailability.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASAvailability.h diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASBaseDefines.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASBaseDefines.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASBaseDefines.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASBaseDefines.h index 4e880f9024..dd15d1aca4 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASBaseDefines.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASBaseDefines.h @@ -8,6 +8,7 @@ // #import +#import #define AS_EXTERN FOUNDATION_EXTERN #define unowned __unsafe_unretained diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASBlockTypes.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASBlockTypes.h similarity index 96% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASBlockTypes.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASBlockTypes.h index e1c7456019..a4c22ff0f4 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASBlockTypes.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASBlockTypes.h @@ -8,6 +8,7 @@ // #import +#import @class ASCellNode; diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASCollections.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASCollections.h old mode 100755 new mode 100644 similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASCollections.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASCollections.h index ca3b31c65c..ce1f0d1fd2 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASCollections.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASCollections.h @@ -7,6 +7,7 @@ // #import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfiguration.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASConfiguration.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfiguration.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASConfiguration.h index c529dad801..a97f62bb1b 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfiguration.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASConfiguration.h @@ -7,6 +7,7 @@ // #import +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfigurationDelegate.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASConfigurationDelegate.h similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfigurationDelegate.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASConfigurationDelegate.h index 127ec3eb14..45fdec442c 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfigurationDelegate.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASConfigurationDelegate.h @@ -7,6 +7,7 @@ // #import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfigurationInternal.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASConfigurationInternal.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfigurationInternal.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASConfigurationInternal.h index eb639c2243..7164d041cb 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASConfigurationInternal.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASConfigurationInternal.h @@ -10,6 +10,7 @@ /// It will be private again after exp_unfair_lock ends. #import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASContextTransitioning.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASContextTransitioning.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASContextTransitioning.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASContextTransitioning.h index 9802ecefc4..6bd5fb7b5f 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASContextTransitioning.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASContextTransitioning.h @@ -7,6 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import @class ASDisplayNode; diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASControlNode+Subclasses.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASControlNode+Subclasses.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASControlNode+Subclasses.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASControlNode+Subclasses.h diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASControlNode.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASControlNode.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASControlNode.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASControlNode.h index 0918fdb0b0..4370967387 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASControlNode.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASControlNode.h @@ -7,6 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import #pragma once diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASControlTargetAction.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASControlTargetAction.h similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASControlTargetAction.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASControlTargetAction.h index 5a3595c5d3..c37e8504bb 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASControlTargetAction.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASControlTargetAction.h @@ -8,6 +8,7 @@ // #import +#import /** @abstract ASControlTargetAction stores target action pairs registered for specific ASControlNodeEvent values. diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDimension.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDimension.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDimension.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDimension.h index 0b3c6b7beb..a10839459c 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDimension.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDimension.h @@ -8,6 +8,8 @@ // #pragma once + +#import #import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDimensionInternal.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDimensionInternal.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDimensionInternal.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDimensionInternal.h index df8f05600c..7bdcf8b739 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDimensionInternal.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDimensionInternal.h @@ -7,6 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Ancestry.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Ancestry.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Ancestry.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Ancestry.h index 2c61cee00c..a952e96a34 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Ancestry.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Ancestry.h @@ -8,6 +8,7 @@ // #import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+Beta.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Beta.h similarity index 89% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+Beta.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Beta.h index 2bb2a4c932..d08bce5d66 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+Beta.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Beta.h @@ -7,16 +7,9 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import #import -#import -#import - -#if YOGA - #import YOGA_HEADER_PATH - #import - #import -#endif NS_ASSUME_NONNULL_BEGIN @@ -152,15 +145,6 @@ AS_CATEGORY_IMPLEMENTABLE AS_CATEGORY_IMPLEMENTABLE - (void)willCalculateLayout:(ASSizeRange)constrainedSize NS_REQUIRES_SUPER; -/** - * Only ASLayoutRangeModeVisibleOnly or ASLayoutRangeModeLowMemory are recommended. Default is ASLayoutRangeModeVisibleOnly, - * because this is the only way to ensure an application will not have blank / flashing views as the user navigates back after - * a memory warning. Apps that wish to use the more effective / aggressive ASLayoutRangeModeLowMemory may need to take steps - * to mitigate this behavior, including: restoring a larger range mode to the next controller before the user navigates there, - * enabling .neverShowPlaceholders on ASCellNodes so that the navigation operation is blocked on redisplay completing, etc. - */ -+ (void)setRangeModeForMemoryWarnings:(ASLayoutRangeMode)rangeMode; - /** * @abstract Whether to draw all descendent nodes' contents into this node's layer's backing store. * diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Convenience.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Convenience.h similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Convenience.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Convenience.h index 3c00f67213..b7ff13220e 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+Convenience.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Convenience.h @@ -7,6 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h index c8d5476b3a..fab0646139 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h @@ -13,6 +13,7 @@ // #import +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+InterfaceState.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+InterfaceState.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+InterfaceState.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+InterfaceState.h index 1de83700ac..dfcb52f95d 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+InterfaceState.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+InterfaceState.h @@ -7,6 +7,7 @@ // #import +#import /** * Interface state is available on ASDisplayNode and ASViewController, and diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+LayoutSpec.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+LayoutSpec.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+LayoutSpec.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+LayoutSpec.h index d7cd862047..a3ae8cb5c5 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+LayoutSpec.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+LayoutSpec.h @@ -6,6 +6,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+Subclasses.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Subclasses.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+Subclasses.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Subclasses.h index d3c9575fbb..5ea0b2e6fe 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode+Subclasses.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode+Subclasses.h @@ -7,6 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode.h index 479d1acfe5..0d2cae2951 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNode.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode.h @@ -15,6 +15,7 @@ #import #import #import +#import #import #import #import @@ -982,4 +983,6 @@ typedef NS_ENUM(NSInteger, ASLayoutEngineType) { @end +#define ASScopedLockSelfOrToRoot() ASLockScopeSelf() + NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNodeExtras.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNodeExtras.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASDisplayNodeExtras.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNodeExtras.h diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASEditableTextNode.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASEditableTextNode.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASEditableTextNode.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASEditableTextNode.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASEqualityHelpers.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASEqualityHelpers.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASEqualityHelpers.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASEqualityHelpers.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASExperimentalFeatures.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASExperimentalFeatures.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASExperimentalFeatures.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASExperimentalFeatures.h index c3d56eb7d8..7b2a160c11 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASExperimentalFeatures.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASExperimentalFeatures.h @@ -7,6 +7,7 @@ // #import +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASGraphicsContext.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASGraphicsContext.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASGraphicsContext.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASGraphicsContext.h index d22d3806b0..1ef56518c9 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASGraphicsContext.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASGraphicsContext.h @@ -7,6 +7,7 @@ // #import +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASHashing.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASHashing.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASHashing.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASHashing.h index 084d74078a..d1393bfec5 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASHashing.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASHashing.h @@ -7,6 +7,7 @@ // #import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASImageNode.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASImageNode.h new file mode 100644 index 0000000000..902591c4f6 --- /dev/null +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASImageNode.h @@ -0,0 +1,219 @@ +// +// ASImageNode.h +// Texture +// +// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +#ifndef MINIMAL_ASDK +@protocol ASAnimatedImageProtocol; +#endif + +/** + * Image modification block. Use to transform an image before display. + * + * @param image The image to be displayed. + * + * @return A transformed image. + */ +typedef UIImage * _Nullable (^asimagenode_modification_block_t)(UIImage *image); + + +/** + * @abstract Draws images. + * @discussion Supports cropping, tinting, and arbitrary image modification blocks. + */ +@interface ASImageNode : ASControlNode + +/** + * @abstract The image to display. + * + * @discussion The node will efficiently display stretchable images by using + * the layer's contentsCenter property. Non-stretchable images work too, of + * course. + */ +@property (nullable) UIImage *image; + +/** + @abstract The placeholder color. + */ +@property (nullable, copy) UIColor *placeholderColor; + +/** + * @abstract Indicates whether efficient cropping of the receiver is enabled. + * + * @discussion Defaults to YES. See -setCropEnabled:recropImmediately:inBounds: for more + * information. + */ +@property (getter=isCropEnabled) BOOL cropEnabled; + +/** + * @abstract Indicates that efficient downsizing of backing store should *not* be enabled. + * + * @discussion Defaults to NO. @see ASCroppedImageBackingSizeAndDrawRectInBounds for more + * information. + */ +@property BOOL forceUpscaling; + +@property (nonatomic, assign) BOOL displayWithoutProcessing; + +/** + * @abstract Forces image to be rendered at forcedSize. + * @discussion Defaults to CGSizeZero to indicate that the forcedSize should not be used. + * Setting forcedSize to non-CGSizeZero will force the backing of the layer contents to + * be forcedSize (automatically adjusted for contentsSize). + */ +@property CGSize forcedSize; + +/** + * @abstract Enables or disables efficient cropping. + * + * @param cropEnabled YES to efficiently crop the receiver's contents such that + * contents outside of its bounds are not included; NO otherwise. + * + * @param recropImmediately If the receiver has an image, YES to redisplay the + * receiver immediately; NO otherwise. + * + * @param cropBounds The bounds into which the receiver will be cropped. Useful + * if bounds are to change in response to cropping (but have not yet done so). + * + * @discussion Efficient cropping is only performed when the receiver's view's + * contentMode is UIViewContentModeScaleAspectFill. By default, cropping is + * enabled. The crop alignment may be controlled via cropAlignmentFactor. + */ +- (void)setCropEnabled:(BOOL)cropEnabled recropImmediately:(BOOL)recropImmediately inBounds:(CGRect)cropBounds; + +/** + * @abstract A value that controls how the receiver's efficient cropping is aligned. + * + * @discussion This value defines a rectangle that is to be featured by the + * receiver. The rectangle is specified as a "unit rectangle," using + * fractions of the source image's width and height, e.g. CGRectMake(0.5, 0, + * 0.5, 1.0) will feature the full right half a photo. If the cropRect is + * empty, the content mode of the receiver will be used to determine its + * dimensions, and only the cropRect's origin will be used for positioning. The + * default value of this property is CGRectMake(0.5, 0.5, 0.0, 0.0). + */ +@property CGRect cropRect; + +/** + * @abstract An optional block which can perform drawing operations on image + * during the display phase. + * + * @discussion Can be used to add image effects (such as rounding, adding + * borders, or other pattern overlays) without extraneous display calls. + */ +@property (nullable) asimagenode_modification_block_t imageModificationBlock; + +/** + * @abstract Marks the receiver as needing display and performs a block after + * display has finished. + * + * @param displayCompletionBlock The block to be performed after display has + * finished. Its `canceled` property will be YES if display was prevented or + * canceled (via displaySuspended); NO otherwise. + * + * @discussion displayCompletionBlock will be performed on the main-thread. If + * `displaySuspended` is YES, `displayCompletionBlock` is will be + * performed immediately and `YES` will be passed for `canceled`. + */ +- (void)setNeedsDisplayWithCompletion:(nullable void (^)(BOOL canceled))displayCompletionBlock; + +#if TARGET_OS_TV +/** + * A bool to track if the current appearance of the node + * is the default focus appearance. + * Exposed here so the category methods can set it. + */ +@property BOOL isDefaultFocusAppearance; +#endif + +@end + +#if TARGET_OS_TV +@interface ASImageNode (tvOS) +@end +#endif + +#ifndef MINIMAL_ASDK +@interface ASImageNode (AnimatedImage) + +/** + * @abstract The animated image to playback + * + * @discussion Set this to an object which conforms to ASAnimatedImageProtocol + * to have the ASImageNode playback an animated image. + * @warning this method should not be overridden, it may not always be called as + * another method is used internally. If you need to know when the animatedImage + * is set, override @c animatedImageSet:previousAnimatedImage: + */ +@property (nullable) id animatedImage; + +/** + * @abstract Pause the playback of an animated image. + * + * @discussion Set to YES to pause playback of an animated image and NO to resume + * playback. + */ +@property BOOL animatedImagePaused; + +/** + * @abstract The runloop mode used to animate the image. + * + * @discussion Defaults to NSRunLoopCommonModes. Another commonly used mode is NSDefaultRunLoopMode. + * Setting NSDefaultRunLoopMode will cause animation to pause while scrolling (if the ASImageNode is + * in a scroll view), which may improve scroll performance in some use cases. + */ +@property (copy) NSString *animatedImageRunLoopMode; + +/** + * @abstract Method called when animated image has been set + * + * @discussion This method is for subclasses to override so they can know if an animated image + * has been set on the node. + */ +- (void)animatedImageSet:(nullable id )newAnimatedImage previousAnimatedImage:(nullable id )previousAnimatedImage ASDISPLAYNODE_REQUIRES_SUPER; + +@end +#endif + +@interface ASImageNode (Unavailable) + +- (instancetype)initWithLayerBlock:(ASDisplayNodeLayerBlock)viewBlock didLoadBlock:(nullable ASDisplayNodeDidLoadBlock)didLoadBlock AS_UNAVAILABLE(); + +- (instancetype)initWithViewBlock:(ASDisplayNodeViewBlock)viewBlock didLoadBlock:(nullable ASDisplayNodeDidLoadBlock)didLoadBlock AS_UNAVAILABLE(); + +@end + +/** + * @abstract Image modification block that rounds (and optionally adds a border to) an image. + * + * @param borderWidth The width of the round border to draw, or zero if no border is desired. + * @param borderColor What colour border to draw. + * + * @see + * + * @return An ASImageNode image modification block. + */ +AS_EXTERN asimagenode_modification_block_t ASImageNodeRoundBorderModificationBlock(CGFloat borderWidth, UIColor * _Nullable borderColor); + +/** + * @abstract Image modification block that applies a tint color à la UIImage configured with + * renderingMode set to UIImageRenderingModeAlwaysTemplate. + * + * @param color The color to tint the image. + * + * @see + * + * @return An ASImageNode image modification block. + */ +AS_EXTERN asimagenode_modification_block_t ASImageNodeTintColorModificationBlock(UIColor *color); + +NS_ASSUME_NONNULL_END diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASInternalHelpers.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASInternalHelpers.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASInternalHelpers.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASInternalHelpers.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayout.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayout.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayout.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayout.h index 0e40574d07..7ee6e80fc0 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayout.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayout.h @@ -8,7 +8,9 @@ // #pragma once + #import +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutElement.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutElement.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutElement.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutElement.h index bd871730aa..b32d9d73e9 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutElement.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutElement.h @@ -7,12 +7,14 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import #import #import #import #import #import +#import #import @class ASLayout; @@ -53,7 +55,7 @@ typedef NS_ENUM(NSUInteger, ASLayoutElementType) { * access to the options via convenience properties. If you are creating custom layout spec, then you can * extend the backing layout options class to accommodate any new layout options. */ -@protocol ASLayoutElement +@protocol ASLayoutElement #pragma mark - Getter diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutElementExtensibility.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutElementExtensibility.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutElementExtensibility.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutElementExtensibility.h index f46b63e812..8aae2e3442 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutElementExtensibility.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutElementExtensibility.h @@ -7,6 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutElementPrivate.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutElementPrivate.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutElementPrivate.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutElementPrivate.h index cf699f42a2..6f713f3908 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLayoutElementPrivate.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutElementPrivate.h @@ -7,6 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpec.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutSpec.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpec.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutSpec.h index 545f95e2d5..2056557b05 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASLayoutSpec.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLayoutSpec.h @@ -7,7 +7,9 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLocking.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLocking.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLocking.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLocking.h index 3e284dc26c..c78fcce43d 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASLocking.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASLocking.h @@ -7,6 +7,7 @@ // #import +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMainThreadDeallocation.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASMainThreadDeallocation.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMainThreadDeallocation.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASMainThreadDeallocation.h index 391b6bb696..1ac44fb6d4 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASMainThreadDeallocation.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASMainThreadDeallocation.h @@ -7,6 +7,7 @@ // #import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASObjectDescriptionHelpers.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASObjectDescriptionHelpers.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASObjectDescriptionHelpers.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASObjectDescriptionHelpers.h index 5a2823bd99..46aa7bacd9 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASObjectDescriptionHelpers.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASObjectDescriptionHelpers.h @@ -8,6 +8,7 @@ // #import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRecursiveUnfairLock.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASRecursiveUnfairLock.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRecursiveUnfairLock.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASRecursiveUnfairLock.h index d705e4d384..7ded8926b3 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRecursiveUnfairLock.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASRecursiveUnfairLock.h @@ -7,6 +7,7 @@ // #import +#import #import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRunLoopQueue.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASRunLoopQueue.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRunLoopQueue.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASRunLoopQueue.h index 07f3682bbf..ea61b2962a 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASRunLoopQueue.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASRunLoopQueue.h @@ -8,6 +8,7 @@ // #import +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASScrollDirection.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASScrollDirection.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASScrollDirection.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASScrollDirection.h index 41538ed31b..0b7842250a 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASScrollDirection.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASScrollDirection.h @@ -8,6 +8,7 @@ // #import +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASScrollNode.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASScrollNode.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASScrollNode.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASScrollNode.h index 35f6622f1a..6977047fe5 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASScrollNode.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASScrollNode.h @@ -7,6 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASStackLayoutDefines.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASStackLayoutDefines.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASStackLayoutDefines.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASStackLayoutDefines.h index 8a86be1b5a..357b7bee2e 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASStackLayoutDefines.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASStackLayoutDefines.h @@ -7,6 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import /** The direction children are stacked in */ diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASStackLayoutElement.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASStackLayoutElement.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASStackLayoutElement.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASStackLayoutElement.h index 46b263b4ff..246cd34384 100644 --- a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASStackLayoutElement.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASStackLayoutElement.h @@ -7,6 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitComponents.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASTextKitComponents.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextKitComponents.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASTextKitComponents.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextNodeTypes.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASTextNodeTypes.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASTextNodeTypes.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASTextNodeTypes.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASThread.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASThread.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASThread.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASThread.h diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASTraitCollection.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASTraitCollection.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/ASTraitCollection.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASTraitCollection.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakSet.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASWeakSet.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/ASWeakSet.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASWeakSet.h diff --git a/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/AsyncDisplayKit.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/AsyncDisplayKit.h new file mode 100644 index 0000000000..c84f8a9821 --- /dev/null +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/AsyncDisplayKit.h @@ -0,0 +1,64 @@ +// +// AsyncDisplayKit.h +// Texture +// +// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved. +// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 +// + +#ifndef MINIMAL_ASDK +#define MINIMAL_ASDK 1 +#endif + +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import + +#import + +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import +#import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/CoreGraphics+ASConvenience.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/CoreGraphics+ASConvenience.h similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/CoreGraphics+ASConvenience.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/CoreGraphics+ASConvenience.h index a0805f1701..da8c6273d9 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/CoreGraphics+ASConvenience.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/CoreGraphics+ASConvenience.h @@ -8,7 +8,7 @@ // #import - +#import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSArray+Diffing.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/NSArray+Diffing.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/NSArray+Diffing.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/NSArray+Diffing.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UIResponder+AsyncDisplayKit.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/UIResponder+AsyncDisplayKit.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UIResponder+AsyncDisplayKit.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/UIResponder+AsyncDisplayKit.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UIView+ASConvenience.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/UIView+ASConvenience.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UIView+ASConvenience.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/UIView+ASConvenience.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransaction.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASAsyncTransaction.h similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransaction.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASAsyncTransaction.h index 245c62b295..dd44b027a4 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransaction.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASAsyncTransaction.h @@ -8,6 +8,7 @@ // #import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/_ASAsyncTransactionContainer.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASAsyncTransactionContainer.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/_ASAsyncTransactionContainer.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASAsyncTransactionContainer.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransactionGroup.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASAsyncTransactionGroup.h similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransactionGroup.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASAsyncTransactionGroup.h index cd0b216c06..bda8e4170c 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransactionGroup.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASAsyncTransactionGroup.h @@ -8,6 +8,7 @@ // #import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/_ASDisplayLayer.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASDisplayLayer.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Public/AsyncDisplayKit/_ASDisplayLayer.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASDisplayLayer.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayView.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASDisplayView.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayView.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASDisplayView.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASTransitionContext.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASTransitionContext.h similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASTransitionContext.h rename to submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASTransitionContext.h index 44c4906c39..71cac29736 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASTransitionContext.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/_ASTransitionContext.h @@ -8,6 +8,7 @@ // #import +#import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UIResponder+AsyncDisplayKit.mm b/submodules/AsyncDisplayKit/Source/UIResponder+AsyncDisplayKit.mm similarity index 86% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UIResponder+AsyncDisplayKit.mm rename to submodules/AsyncDisplayKit/Source/UIResponder+AsyncDisplayKit.mm index 8c012723ad..0655f06503 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/UIResponder+AsyncDisplayKit.mm +++ b/submodules/AsyncDisplayKit/Source/UIResponder+AsyncDisplayKit.mm @@ -7,11 +7,11 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "UIResponder+AsyncDisplayKit.h" #import #import -#import +#import "ASResponderChainEnumerator.h" @implementation UIResponder (AsyncDisplayKit) diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransaction.mm b/submodules/AsyncDisplayKit/Source/_ASAsyncTransaction.mm similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransaction.mm rename to submodules/AsyncDisplayKit/Source/_ASAsyncTransaction.mm diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransactionContainer+Private.h b/submodules/AsyncDisplayKit/Source/_ASAsyncTransactionContainer+Private.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransactionContainer+Private.h rename to submodules/AsyncDisplayKit/Source/_ASAsyncTransactionContainer+Private.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransactionContainer.mm b/submodules/AsyncDisplayKit/Source/_ASAsyncTransactionContainer.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransactionContainer.mm rename to submodules/AsyncDisplayKit/Source/_ASAsyncTransactionContainer.mm index ed44231ce2..5bbfd95f15 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransactionContainer.mm +++ b/submodules/AsyncDisplayKit/Source/_ASAsyncTransactionContainer.mm @@ -8,7 +8,7 @@ // #import -#import +#import "_ASAsyncTransactionContainer+Private.h" #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransactionGroup.mm b/submodules/AsyncDisplayKit/Source/_ASAsyncTransactionGroup.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransactionGroup.mm rename to submodules/AsyncDisplayKit/Source/_ASAsyncTransactionGroup.mm index ae651d1870..ca170229b8 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASAsyncTransactionGroup.mm +++ b/submodules/AsyncDisplayKit/Source/_ASAsyncTransactionGroup.mm @@ -12,7 +12,7 @@ #import #import #import -#import +#import "_ASAsyncTransactionContainer+Private.h" @implementation _ASAsyncTransactionGroup { NSHashTable> *_containers; diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASCoreAnimationExtras.h b/submodules/AsyncDisplayKit/Source/_ASCoreAnimationExtras.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASCoreAnimationExtras.h rename to submodules/AsyncDisplayKit/Source/_ASCoreAnimationExtras.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASCoreAnimationExtras.mm b/submodules/AsyncDisplayKit/Source/_ASCoreAnimationExtras.mm similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASCoreAnimationExtras.mm rename to submodules/AsyncDisplayKit/Source/_ASCoreAnimationExtras.mm index b55bd6442f..a8a0a9fe89 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASCoreAnimationExtras.mm +++ b/submodules/AsyncDisplayKit/Source/_ASCoreAnimationExtras.mm @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "_ASCoreAnimationExtras.h" #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayLayer.mm b/submodules/AsyncDisplayKit/Source/_ASDisplayLayer.mm similarity index 97% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayLayer.mm rename to submodules/AsyncDisplayKit/Source/_ASDisplayLayer.mm index a7478f1883..9ad2ca289b 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayLayer.mm +++ b/submodules/AsyncDisplayKit/Source/_ASDisplayLayer.mm @@ -14,10 +14,9 @@ #import #import #import -#import +#import "ASDisplayNodeInternal.h" #import #import -#import @implementation _ASDisplayLayer { @@ -94,7 +93,6 @@ - (void)setNeedsLayout { ASDisplayNodeAssertMainThread(); - as_log_verbose(ASNodeLog(), "%s on %@", sel_getName(_cmd), self); [super setNeedsLayout]; } #endif diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayView.mm b/submodules/AsyncDisplayKit/Source/_ASDisplayView.mm similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayView.mm rename to submodules/AsyncDisplayKit/Source/_ASDisplayView.mm index d25f54c589..0d24318b3f 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayView.mm +++ b/submodules/AsyncDisplayKit/Source/_ASDisplayView.mm @@ -8,11 +8,11 @@ // #import -#import +#import "_ASDisplayViewAccessiblity.h" -#import +#import "_ASCoreAnimationExtras.h" #import -#import +#import "ASDisplayNodeInternal.h" #import #import #import diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayViewAccessiblity.h b/submodules/AsyncDisplayKit/Source/_ASDisplayViewAccessiblity.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayViewAccessiblity.h rename to submodules/AsyncDisplayKit/Source/_ASDisplayViewAccessiblity.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayViewAccessiblity.mm b/submodules/AsyncDisplayKit/Source/_ASDisplayViewAccessiblity.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayViewAccessiblity.mm rename to submodules/AsyncDisplayKit/Source/_ASDisplayViewAccessiblity.mm index 321c1af742..44941a0673 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASDisplayViewAccessiblity.mm +++ b/submodules/AsyncDisplayKit/Source/_ASDisplayViewAccessiblity.mm @@ -12,8 +12,8 @@ #import #import #import -#import -#import +#import "ASDisplayNode+FrameworkPrivate.h" +#import "ASDisplayNodeInternal.h" #import @@ -294,7 +294,9 @@ static void CollectAccessibilityElementsForView(UIView *view, NSMutableArray *el if (viewNode == nil) { return @[]; } - _accessibilityElements = [viewNode accessibilityElements]; + if (true || _accessibilityElements == nil) { + _accessibilityElements = [viewNode accessibilityElements]; + } return _accessibilityElements; } diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASPendingState.h b/submodules/AsyncDisplayKit/Source/_ASPendingState.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASPendingState.h rename to submodules/AsyncDisplayKit/Source/_ASPendingState.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASPendingState.mm b/submodules/AsyncDisplayKit/Source/_ASPendingState.mm similarity index 99% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASPendingState.mm rename to submodules/AsyncDisplayKit/Source/_ASPendingState.mm index 9e9778cf04..5ee9c60576 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASPendingState.mm +++ b/submodules/AsyncDisplayKit/Source/_ASPendingState.mm @@ -7,13 +7,13 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "_ASPendingState.h" -#import +#import "_ASCoreAnimationExtras.h" #import #import #import -#import +#import "ASDisplayNodeInternal.h" #import #define __shouldSetNeedsDisplay(layer) (flags.needsDisplay \ diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASScopeTimer.h b/submodules/AsyncDisplayKit/Source/_ASScopeTimer.h similarity index 100% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASScopeTimer.h rename to submodules/AsyncDisplayKit/Source/_ASScopeTimer.h diff --git a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASTransitionContext.mm b/submodules/AsyncDisplayKit/Source/_ASTransitionContext.mm similarity index 98% rename from submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASTransitionContext.mm rename to submodules/AsyncDisplayKit/Source/_ASTransitionContext.mm index 40a3573c15..e4539ee20b 100644 --- a/submodules/AsyncDisplayKit/Source/Implementation/AsyncDisplayKit/_ASTransitionContext.mm +++ b/submodules/AsyncDisplayKit/Source/_ASTransitionContext.mm @@ -7,7 +7,7 @@ // Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0 // -#import +#import "_ASTransitionContext.h" #import #import diff --git a/submodules/Display/BUILD b/submodules/Display/BUILD index 1332c37b35..afae8b4260 100644 --- a/submodules/Display/BUILD +++ b/submodules/Display/BUILD @@ -1,6 +1,9 @@ -load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") +load( + "@rules_apple_extras//apple:objc_library.bzl", + "my_swift_library", +) -swift_library( +my_swift_library( name = "Display", module_name = "Display", srcs = glob([ @@ -12,6 +15,10 @@ swift_library( "//submodules/AppBundle:AppBundle", "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/Markdown:Markdown", + "//submodules/AsyncDisplayKit:AsyncDisplayKit", + ], + copts = [ + "-Isubmodules/AsyncDisplayKit/Source/PublicHeaders", ], visibility = [ "//visibility:public", diff --git a/submodules/UIKitRuntimeUtils/BUILD b/submodules/UIKitRuntimeUtils/BUILD index e5ee2fd54d..7fd14becf8 100644 --- a/submodules/UIKitRuntimeUtils/BUILD +++ b/submodules/UIKitRuntimeUtils/BUILD @@ -1,3 +1,7 @@ +load( + "@rules_apple_extras//apple:objc_library.bzl", + "objc_library", +) objc_library( name = "UIKitRuntimeUtils", diff --git a/submodules/WalletCore/BUILD b/submodules/WalletCore/BUILD index 56b9d8ac32..d497c83b05 100644 --- a/submodules/WalletCore/BUILD +++ b/submodules/WalletCore/BUILD @@ -1,6 +1,9 @@ -load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") +load( + "@rules_apple_extras//apple:objc_library.bzl", + "my_swift_library", +) -swift_library( +my_swift_library( name = "WalletCore", module_name = "WalletCore", srcs = glob([