From f96f9c5fd692000f561e87cba68642ef7daf43e7 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 7 Jan 2018 18:21:41 -0800 Subject: [PATCH] Sideeffectless measuring of shadow views Summary: That's now possible thanks to new Yoga's clonning API. That will speed up RCTSurface measuring (see the next diff in stack) and should illuminate a class of problems in CK interop layer. We also will use it in the new text layout engine (in React Native). Reviewed By: gkassabli Differential Revision: D6665632 fbshipit-source-id: e94909f0af89e9c7fc5e46b95090ecb3c52546a2 --- React/Views/RCTShadowView+Layout.h | 7 +++++++ React/Views/RCTShadowView+Layout.m | 33 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/React/Views/RCTShadowView+Layout.h b/React/Views/RCTShadowView+Layout.h index fe40dca40dcefd..c0711a63530782 100644 --- a/React/Views/RCTShadowView+Layout.h +++ b/React/Views/RCTShadowView+Layout.h @@ -27,6 +27,13 @@ RCT_EXTERN CGFloat RCTCoreGraphicsFloatFromYogaFloat(float value); @property (nonatomic, readonly) UIEdgeInsets compoundInsets; @property (nonatomic, readonly) CGSize availableSize; +#pragma mark - Measuring + +/** + * Measures shadow view without side-effects. + */ +- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize; + #pragma mark - Dirty Propagation Control /** diff --git a/React/Views/RCTShadowView+Layout.m b/React/Views/RCTShadowView+Layout.m index 614a538892249a..e554e23e1b7c15 100644 --- a/React/Views/RCTShadowView+Layout.m +++ b/React/Views/RCTShadowView+Layout.m @@ -81,6 +81,39 @@ - (CGSize)availableSize return UIEdgeInsetsInsetRect((CGRect){CGPointZero, self.frame.size}, self.compoundInsets).size; } +#pragma mark - Measuring + +- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize +{ + YGNodeRef clonnedYogaNode = YGNodeClone(self.yogaNode); + YGNodeRef constraintYogaNode = YGNodeNewWithConfig([[self class] yogaConfig]); + + YGNodeInsertChild(constraintYogaNode, clonnedYogaNode, 0); + + YGNodeStyleSetMinWidth(constraintYogaNode, RCTYogaFloatFromCoreGraphicsFloat(minimumSize.width)); + YGNodeStyleSetMinHeight(constraintYogaNode, RCTYogaFloatFromCoreGraphicsFloat(minimumSize.height)); + YGNodeStyleSetMaxWidth(constraintYogaNode, RCTYogaFloatFromCoreGraphicsFloat(maximumSize.width)); + YGNodeStyleSetMaxHeight(constraintYogaNode, RCTYogaFloatFromCoreGraphicsFloat(maximumSize.height)); + + YGNodeCalculateLayout( + constraintYogaNode, + YGUndefined, + YGUndefined, + self.layoutDirection + ); + + CGSize measuredSize = (CGSize){ + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetWidth(constraintYogaNode)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetHeight(constraintYogaNode)), + }; + + YGNodeRemoveChild(constraintYogaNode, clonnedYogaNode); + YGNodeFree(constraintYogaNode); + YGNodeFree(clonnedYogaNode); + + return measuredSize; +} + #pragma mark - Dirty Propagation Control - (void)dirtyLayout