diff --git a/Source/Layout/ASStackLayoutSpec.h b/Source/Layout/ASStackLayoutSpec.h index d218db7b42..a87673b8f0 100644 --- a/Source/Layout/ASStackLayoutSpec.h +++ b/Source/Layout/ASStackLayoutSpec.h @@ -59,11 +59,14 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) ASStackLayoutJustifyContent justifyContent; /** Orientation of children along cross axis. Defaults to ASStackLayoutAlignItemsStretch */ @property (nonatomic, assign) ASStackLayoutAlignItems alignItems; -//TODO documentation. Defaults to ASStackLayoutFlexWrapNoWrap +/** Whether children are stacked into a single or multiple lines. Defaults to single line (ASStackLayoutFlexWrapNoWrap) */ @property (nonatomic, assign) ASStackLayoutFlexWrap flexWrap; -//TODO documentation. Defaults to ASStackLayoutAlignContentStart +/** Orientation of lines along cross axis if there are multiple lines. Defaults to ASStackLayoutAlignContentStart */ @property (nonatomic, assign) ASStackLayoutAlignContent alignContent; +/** Whether this stack can dispatch to other threads, regardless of which thread it's running on */ +@property (nonatomic, assign, getter=isConcurrent) BOOL concurrent; + - (instancetype)init; /** @@ -84,8 +87,9 @@ NS_ASSUME_NONNULL_BEGIN @param spacing The spacing between the children @param justifyContent If no children are flexible, this describes how to fill any extra space @param alignItems Orientation of the children along the cross axis + @param flexWrap Whether children are stacked into a single or multiple lines + @param alignContent Orientation of lines along cross axis if there are multiple lines @param children ASLayoutElement children to be positioned. - TODO documentation flex wrap and align content */ + (instancetype)stackLayoutSpecWithDirection:(ASStackLayoutDirection)direction spacing:(CGFloat)spacing diff --git a/Source/Layout/ASStackLayoutSpec.mm b/Source/Layout/ASStackLayoutSpec.mm index 1a78a5428c..30eea4950b 100644 --- a/Source/Layout/ASStackLayoutSpec.mm +++ b/Source/Layout/ASStackLayoutSpec.mm @@ -136,7 +136,7 @@ const ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems, .flexWrap = _flexWrap, .alignContent = _alignContent}; - const auto unpositionedLayout = ASStackUnpositionedLayout::compute(stackChildren, style, constrainedSize); + const auto unpositionedLayout = ASStackUnpositionedLayout::compute(stackChildren, style, constrainedSize, _concurrent); const auto positionedLayout = ASStackPositionedLayout::compute(unpositionedLayout, style, constrainedSize); if (style.direction == ASStackLayoutDirectionVertical) { diff --git a/Source/Private/Layout/ASStackUnpositionedLayout.h b/Source/Private/Layout/ASStackUnpositionedLayout.h index e98852b948..88781b14c1 100644 --- a/Source/Private/Layout/ASStackUnpositionedLayout.h +++ b/Source/Private/Layout/ASStackUnpositionedLayout.h @@ -58,7 +58,8 @@ struct ASStackUnpositionedLayout { /** Given a set of children, computes the unpositioned layouts for those children. */ static ASStackUnpositionedLayout compute(const std::vector &children, const ASStackLayoutSpecStyle &style, - const ASSizeRange &sizeRange); + const ASSizeRange &sizeRange, + const BOOL concurrent); static CGFloat baselineForItem(const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecItem &l); diff --git a/Source/Private/Layout/ASStackUnpositionedLayout.mm b/Source/Private/Layout/ASStackUnpositionedLayout.mm index e808b427eb..9bb5166171 100644 --- a/Source/Private/Layout/ASStackUnpositionedLayout.mm +++ b/Source/Private/Layout/ASStackUnpositionedLayout.mm @@ -16,7 +16,6 @@ #import #import #import -#import CGFloat const kViolationEpsilon = 0.01; @@ -69,7 +68,7 @@ static ASLayout *crossChildLayout(const ASStackLayoutSpecChild &child, return layout ? : [ASLayout layoutWithLayoutElement:child.element size:{0, 0}]; } -static void dispatchApplyIfNeeded(size_t iterationCount, void(^work)(size_t i)) +static void dispatchApplyIfNeeded(size_t iterationCount, BOOL forced, void(^work)(size_t i)) { if (iterationCount == 0) { return; @@ -80,7 +79,8 @@ static void dispatchApplyIfNeeded(size_t iterationCount, void(^work)(size_t i)) return; } - if (ASDisplayNodeThreadIsMain() == NO) { + // TODO Once the locking situation in ASDisplayNode has improved, always dispatch if on main + if (forced == NO) { for (size_t i = 0; i < iterationCount; i++) { work(i); } @@ -196,10 +196,11 @@ CGFloat ASStackUnpositionedLayout::computeCrossViolation(const CGFloat crossDime */ static void stretchItemsAlongCrossDimension(std::vector &items, const ASStackLayoutSpecStyle &style, + const BOOL concurrent, const CGSize parentSize, const CGFloat crossSize) { - dispatchApplyIfNeeded(items.size(), ^(size_t i) { + dispatchApplyIfNeeded(items.size(), concurrent, ^(size_t i) { auto &item = items[i]; const ASStackLayoutAlignItems alignItems = alignment(item.child.style.alignSelf, style.alignItems); if (alignItems == ASStackLayoutAlignItemsStretch) { @@ -222,6 +223,7 @@ static void stretchItemsAlongCrossDimension(std::vector & */ static void stretchLinesAlongCrossDimension(std::vector &lines, const ASStackLayoutSpecStyle &style, + const BOOL concurrent, const ASSizeRange &sizeRange, const CGSize parentSize) { @@ -239,7 +241,7 @@ static void stretchLinesAlongCrossDimension(std::vector line.crossSize += extraCrossSizePerLine; } - stretchItemsAlongCrossDimension(line.items, style, parentSize, line.crossSize); + stretchItemsAlongCrossDimension(line.items, style, concurrent, parentSize, line.crossSize); } } @@ -425,10 +427,11 @@ ASDISPLAYNODE_INLINE BOOL isFlexibleInBothDirections(const ASStackLayoutSpecChil */ static void layoutFlexibleChildrenAtZeroSize(std::vector &items, const ASStackLayoutSpecStyle &style, + const BOOL concurrent, const ASSizeRange &sizeRange, const CGSize parentSize) { - dispatchApplyIfNeeded(items.size(), ^(size_t i) { + dispatchApplyIfNeeded(items.size(), concurrent, ^(size_t i) { auto &item = items[i]; if (isFlexibleInBothDirections(item.child)) { item.layout = crossChildLayout(item.child, @@ -550,6 +553,7 @@ ASDISPLAYNODE_INLINE BOOL useOptimizedFlexing(const std::vector &lines, const ASStackLayoutSpecStyle &style, + const BOOL concurrent, const ASSizeRange &sizeRange, const CGSize parentSize, const BOOL useOptimizedFlexing) @@ -567,7 +571,7 @@ static void flexLinesAlongStackDimension(std::vector &l if (flexFactorSum == 0) { // If optimized flexing was used then we have to clean up the unsized children and lay them out at zero size. if (useOptimizedFlexing) { - layoutFlexibleChildrenAtZeroSize(items, style, sizeRange, parentSize); + layoutFlexibleChildrenAtZeroSize(items, style, concurrent, sizeRange, parentSize); } return; } @@ -591,7 +595,7 @@ static void flexLinesAlongStackDimension(std::vector &l } ASDisplayNodeCAssert(firstFlexItem != -1, @"At this point there must be at least 1 flexible item"); - dispatchApplyIfNeeded(items.size(), ^(size_t i) { + dispatchApplyIfNeeded(items.size(), concurrent, ^(size_t i) { auto &item = items[i]; const CGFloat currentFlexAdjustment = flexAdjustment(item); // Children are consider inflexible if they do not need to make a flex adjustment. @@ -655,6 +659,7 @@ static std::vector collectChildrenIntoLines(const std:: */ static void layoutItemsAlongUnconstrainedStackDimension(std::vector &items, const ASStackLayoutSpecStyle &style, + const BOOL concurrent, const ASSizeRange &sizeRange, const CGSize parentSize, const BOOL useOptimizedFlexing) @@ -662,7 +667,7 @@ static void layoutItemsAlongUnconstrainedStackDimension(std::vector &children, const ASStackLayoutSpecStyle &style, - const ASSizeRange &sizeRange) + const ASSizeRange &sizeRange, + const BOOL concurrent) { if (children.empty()) { return {}; @@ -705,6 +711,7 @@ ASStackUnpositionedLayout ASStackUnpositionedLayout::compute(const std::vector lines = collectChildrenIntoLines(items, style, sizeRange); // Resolve the flexible lengths (https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths) - flexLinesAlongStackDimension(lines, style, sizeRange, parentSize, optimizedFlexing); + flexLinesAlongStackDimension(lines, style, concurrent, sizeRange, parentSize, optimizedFlexing); // Calculate the cross size of each flex line (https://www.w3.org/TR/css-flexbox-1/#algo-cross-line) computeLinesCrossSizeAndBaseline(lines, style, sizeRange); // Handle 'align-content: stretch' (https://www.w3.org/TR/css-flexbox-1/#algo-line-stretch) // Determine the used cross size of each item (https://www.w3.org/TR/css-flexbox-1/#algo-stretch) - stretchLinesAlongCrossDimension(lines, style, sizeRange, parentSize); + stretchLinesAlongCrossDimension(lines, style, concurrent, sizeRange, parentSize); // Compute stack dimension sum of each line and the whole stack CGFloat layoutStackDimensionSum = 0;