Skip to content

Commit

Permalink
Reverted commit D3598946
Browse files Browse the repository at this point in the history
Reviewed By: majak

Differential Revision: D3598946

fbshipit-source-id: fb70f5b031a85f30a6207eb95b7fd0ccd7d78039
  • Loading branch information
Wenjing Wang authored and Facebook Github Bot 2 committed Jul 23, 2016
1 parent 64b0929 commit 15dfa5b
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 40 deletions.
3 changes: 2 additions & 1 deletion Libraries/Text/RCTShadowRawText.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ - (void)dealloc

- (void)contentSizeMultiplierDidChange:(NSNotification *)note
{
CSSNodeMarkDirty(self.cssNode);
[self dirtyLayout];
[self dirtyText];
}

- (void)setText:(NSString *)text
{
if (_text != text && ![_text isEqualToString:text]) {
_text = [text copy];
[self dirtyLayout];
[self dirtyText];
}
}
Expand Down
4 changes: 2 additions & 2 deletions Libraries/Text/RCTShadowText.m
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ - (BOOL)isCSSLeafNode

- (void)contentSizeMultiplierDidChange:(NSNotification *)note
{
CSSNodeMarkDirty(self.cssNode);
[self dirtyLayout];
[self dirtyText];
}

Expand Down Expand Up @@ -330,7 +330,7 @@ - (NSAttributedString *)_attributedStringWithFontFamily:(NSString *)fontFamily

// create a non-mutable attributedString for use by the Text system which avoids copies down the line
_cachedAttributedString = [[NSAttributedString alloc] initWithAttributedString:attributedString];
CSSNodeMarkDirty(self.cssNode);
[self dirtyLayout];

return _cachedAttributedString;
}
Expand Down
3 changes: 1 addition & 2 deletions React/CSSLayout/CSSLayout-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,12 @@ typedef struct CSSNode {
int lineIndex;
bool shouldUpdate;
bool isTextNode;
CSSNodeRef parent;
CSSNodeListRef children;
bool isDirty;

struct CSSNode* nextChild;

CSSSize (*measure)(void *context, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode);
bool (*isDirty)(void *context);
void (*print)(void *context);
void *context;
} CSSNode;
Expand Down
30 changes: 4 additions & 26 deletions React/CSSLayout/CSSLayout.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ CSSNodeRef CSSNodeNew() {
CSSNodeRef node = calloc(1, sizeof(CSSNode));
assert(node != NULL);

node->children = CSSNodeListNew(4);
CSSNodeInit(node);
return node;
}
Expand All @@ -43,11 +44,6 @@ void CSSNodeFree(CSSNodeRef node) {
}

void CSSNodeInit(CSSNodeRef node) {
node->parent = NULL;
node->children = CSSNodeListNew(4);
node->shouldUpdate = true;
node->isDirty = false;

node->style.alignItems = CSSAlignStretch;
node->style.alignContent = CSSAlignFlexStart;

Expand Down Expand Up @@ -83,6 +79,7 @@ void CSSNodeInit(CSSNodeRef node) {

// Such that the comparison is always going to be false
node->layout.lastParentDirection = (CSSDirection)-1;
node->shouldUpdate = true;
node->layout.nextCachedMeasurementsIndex = 0;

node->layout.measuredDimensions[CSSDimensionWidth] = CSSUndefined;
Expand All @@ -91,25 +88,12 @@ void CSSNodeInit(CSSNodeRef node) {
node->layout.cached_layout.heightMeasureMode = (CSSMeasureMode)-1;
}

void _CSSNodeMarkDirty(CSSNodeRef node) {
if (!node->isDirty) {
node->isDirty = true;
if (node->parent) {
_CSSNodeMarkDirty(node->parent);
}
}
}

void CSSNodeInsertChild(CSSNodeRef node, CSSNodeRef child, unsigned int index) {
CSSNodeListInsert(node->children, child, index);
child->parent = node;
_CSSNodeMarkDirty(node);
}

void CSSNodeRemoveChild(CSSNodeRef node, CSSNodeRef child) {
CSSNodeListDelete(node->children, child);
child->parent = NULL;
_CSSNodeMarkDirty(node);
}

CSSNodeRef CSSNodeGetChild(CSSNodeRef node, unsigned int index) {
Expand All @@ -120,12 +104,6 @@ unsigned int CSSNodeChildCount(CSSNodeRef node) {
return CSSNodeListCount(node->children);
}

void CSSNodeMarkDirty(CSSNodeRef node) {
// Nodes without custom measure functions should not manually mark themselves as dirty
assert(node->measure != NULL);
_CSSNodeMarkDirty(node);
}

#define CSS_NODE_PROPERTY_IMPL(type, name, paramName, instanceName) \
void CSSNodeSet##name(CSSNodeRef node, type paramName) { \
node->instanceName = paramName;\
Expand All @@ -138,7 +116,6 @@ type CSSNodeGet##name(CSSNodeRef node) { \
#define CSS_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName) \
void CSSNodeStyleSet##name(CSSNodeRef node, type paramName) { \
node->style.instanceName = paramName;\
_CSSNodeMarkDirty(node);\
} \
\
type CSSNodeStyleGet##name(CSSNodeRef node) { \
Expand All @@ -152,6 +129,7 @@ type CSSNodeLayoutGet##name(CSSNodeRef node) { \

CSS_NODE_PROPERTY_IMPL(void*, Context, context, context);
CSS_NODE_PROPERTY_IMPL(CSSMeasureFunc, MeasureFunc, measureFunc, measure);
CSS_NODE_PROPERTY_IMPL(CSSIsDirtyFunc, IsDirtyFunc, isDirtyFunc, isDirty);
CSS_NODE_PROPERTY_IMPL(CSSPrintFunc, PrintFunc, printFunc, print);
CSS_NODE_PROPERTY_IMPL(bool, IsTextnode, isTextNode, isTextNode);
CSS_NODE_PROPERTY_IMPL(bool, ShouldUpdate, shouldUpdate, shouldUpdate);
Expand Down Expand Up @@ -1757,7 +1735,7 @@ bool layoutNodeInternal(CSSNode* node, float availableWidth, float availableHeig

gDepth++;

bool needToVisitNode = (node->isDirty && layout->generationCount != gCurrentGenerationCount) ||
bool needToVisitNode = (node->isDirty(node->context) && layout->generationCount != gCurrentGenerationCount) ||
layout->lastParentDirection != parentDirection;

if (needToVisitNode) {
Expand Down
7 changes: 2 additions & 5 deletions React/CSSLayout/CSSLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ typedef struct CSSSize {

typedef struct CSSNode * CSSNodeRef;
typedef CSSSize (*CSSMeasureFunc)(void *context, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode);
typedef bool (*CSSIsDirtyFunc)(void *context);
typedef void (*CSSPrintFunc)(void *context);

// CSSNode
Expand All @@ -128,11 +129,6 @@ void CSSNodeCalculateLayout(
float availableHeight,
CSSDirection parentDirection);

// Mark a node as dirty. Only valid for nodes with a custom measure function set.
// CSSLayout knows when to mark all other nodes as dirty but because nodes with measure functions
// depends on information not known to CSSLayout they must perform this dirty marking manually.
void CSSNodeMarkDirty(CSSNodeRef node);

void CSSNodePrint(CSSNodeRef node, CSSPrintOptions options);

bool isUndefined(float value);
Expand All @@ -150,6 +146,7 @@ type CSSNodeLayoutGet##name(CSSNodeRef node);

CSS_NODE_PROPERTY(void*, Context, context);
CSS_NODE_PROPERTY(CSSMeasureFunc, MeasureFunc, measureFunc);
CSS_NODE_PROPERTY(CSSIsDirtyFunc, IsDirtyFunc, isDirtyFunc);
CSS_NODE_PROPERTY(CSSPrintFunc, PrintFunc, printFunc);
CSS_NODE_PROPERTY(bool, IsTextnode, isTextNode);
CSS_NODE_PROPERTY(bool, ShouldUpdate, shouldUpdate);
Expand Down
10 changes: 9 additions & 1 deletion React/Modules/RCTUIManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -424,8 +424,11 @@ - (void)setFrame:(CGRect)frame forView:(UIView *)view
RCTShadowView *shadowView = self->_shadowViewRegistry[reactTag];
RCTAssert(shadowView != nil, @"Could not locate shadow view with tag #%@", reactTag);

BOOL dirtyLayout = NO;

if (!CGRectEqualToRect(frame, shadowView.frame)) {
shadowView.frame = frame;
dirtyLayout = YES;
}

// Trigger re-layout when size flexibility changes, as the root view might grow or
Expand All @@ -434,9 +437,14 @@ - (void)setFrame:(CGRect)frame forView:(UIView *)view
RCTRootShadowView *rootShadowView = (RCTRootShadowView *)shadowView;
if (rootShadowView.sizeFlexibility != sizeFlexibility) {
rootShadowView.sizeFlexibility = sizeFlexibility;
[self batchDidComplete];
dirtyLayout = YES;
}
}

if (dirtyLayout) {
[shadowView dirtyLayout];
[self batchDidComplete];
}
});
}

Expand Down
7 changes: 7 additions & 0 deletions React/Views/RCTShadowView.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ typedef void (^RCTApplierBlock)(NSDictionary<NSNumber *, UIView *> *viewRegistry
@property (nonatomic, assign, readonly) CSSNodeRef cssNode;
@property (nonatomic, copy) NSString *viewName;
@property (nonatomic, strong) UIColor *backgroundColor; // Used to propagate to children
@property (nonatomic, assign) RCTUpdateLifecycle layoutLifecycle;
@property (nonatomic, copy) RCTDirectEventBlock onLayout;

/**
Expand Down Expand Up @@ -182,6 +183,12 @@ typedef void (^RCTApplierBlock)(NSDictionary<NSNumber *, UIView *> *viewRegistry
viewsWithNewFrame:(NSMutableSet<RCTShadowView *> *)viewsWithNewFrame
absolutePosition:(CGPoint)absolutePosition;

/**
* The following are implementation details exposed to subclasses. Do not call them directly
*/
- (void)dirtyLayout NS_REQUIRES_SUPER;
- (BOOL)isLayoutDirty;

/**
* Return whether or not this node acts as a leaf node in the eyes of CSSLayout. For example
* RCTShadowText has children which it does not want CSSLayout to lay out so in the eyes of
Expand Down
51 changes: 48 additions & 3 deletions React/Views/RCTShadowView.m
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ static void RCTPrint(void *context)
printf("%s(%zd), ", shadowView.viewName.UTF8String, shadowView.reactTag.integerValue);
}

static bool RCTIsDirty(void *context)
{
RCTShadowView *shadowView = (__bridge RCTShadowView *)context;
return [shadowView isLayoutDirty];
}

// Enforces precedence rules, e.g. marginLeft > marginHorizontal > margin.
#define DEFINE_PROCESS_META_PROPS(type) \
static void RCTProcessMetaProps##type(const float metaProps[META_PROP_COUNT], CSSNodeRef node) { \
Expand Down Expand Up @@ -141,6 +147,7 @@ - (void)applyLayoutNode:(CSSNodeRef)node
return;
}
CSSNodeSetShouldUpdate(node, false);
_layoutLifecycle = RCTUpdateLifecycleComputed;

CGPoint absoluteTopLeft = {
absolutePosition.x + CSSNodeLayoutGetLeft(node),
Expand Down Expand Up @@ -256,6 +263,11 @@ - (void)collectUpdatedFrames:(NSMutableSet<RCTShadowView *> *)viewsWithNewFrame
CSSNodeStyleSetHeight(_cssNode, frame.size.height);
CSSNodeStyleSetPositionLeft(_cssNode, frame.origin.x);
CSSNodeStyleSetPositionTop(_cssNode, frame.origin.y);

// Our parent has asked us to change our cssNode->styles. Dirty the layout
// so that we can rerun layout on this node. The request came from our parent
// so there's no need to dirty our ancestors by calling dirtyLayout.
_layoutLifecycle = RCTUpdateLifecycleDirtied;
}

CSSNodeCalculateLayout(_cssNode, frame.size.width, frame.size.height, CSSDirectionInherit);
Expand Down Expand Up @@ -292,6 +304,7 @@ - (instancetype)init
}

_newView = YES;
_layoutLifecycle = RCTUpdateLifecycleUninitialized;
_propagationLifecycle = RCTUpdateLifecycleUninitialized;
_textLifecycle = RCTUpdateLifecycleUninitialized;

Expand All @@ -300,6 +313,7 @@ - (instancetype)init
_cssNode = CSSNodeNew();
CSSNodeSetContext(_cssNode, (__bridge void *)self);
CSSNodeSetPrintFunc(_cssNode, RCTPrint);
CSSNodeSetIsDirtyFunc(_cssNode, RCTIsDirty);
}
return self;
}
Expand All @@ -314,6 +328,19 @@ - (void)dealloc
CSSNodeFree(_cssNode);
}

- (void)dirtyLayout
{
if (_layoutLifecycle != RCTUpdateLifecycleDirtied) {
_layoutLifecycle = RCTUpdateLifecycleDirtied;
[_superview dirtyLayout];
}
}

- (BOOL)isLayoutDirty
{
return _layoutLifecycle != RCTUpdateLifecycleComputed;
}

- (BOOL)isCSSLeafNode
{
return NO;
Expand Down Expand Up @@ -359,12 +386,14 @@ - (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)atIndex
subview->_superview = self;
_didUpdateSubviews = YES;
[self dirtyText];
[self dirtyLayout];
[self dirtyPropagation];
}

- (void)removeReactSubview:(RCTShadowView *)subview
{
[subview dirtyText];
[subview dirtyLayout];
[subview dirtyPropagation];
_didUpdateSubviews = YES;
subview->_superview = nil;
Expand Down Expand Up @@ -504,6 +533,7 @@ - (CGFloat)border##prop##Width \
- (void)set##setProp:(CGFloat)value \
{ \
CSSNodeStyleSet##cssProp(_cssNode, value); \
[self dirtyLayout]; \
[self dirtyText]; \
} \
- (CGFloat)getProp \
Expand Down Expand Up @@ -531,44 +561,55 @@ - (void)setFrame:(CGRect)frame
CSSNodeStyleSetPositionTop(_cssNode, CGRectGetMinY(frame));
CSSNodeStyleSetWidth(_cssNode, CGRectGetWidth(frame));
CSSNodeStyleSetHeight(_cssNode, CGRectGetHeight(frame));
[self dirtyLayout];
}

static inline void RCTAssignSuggestedDimension(CSSNodeRef cssNode, CSSDimension dimension, CGFloat amount)
static inline BOOL RCTAssignSuggestedDimension(CSSNodeRef cssNode, CSSDimension dimension, CGFloat amount)
{
if (amount != UIViewNoIntrinsicMetric) {
switch (dimension) {
case CSSDimensionWidth:
if (isnan(CSSNodeStyleGetWidth(cssNode))) {
CSSNodeStyleSetWidth(cssNode, amount);
return YES;
}
break;
case CSSDimensionHeight:
if (isnan(CSSNodeStyleGetHeight(cssNode))) {
CSSNodeStyleSetHeight(cssNode, amount);
return YES;
}
break;
}
}

return NO;
}

- (void)setIntrinsicContentSize:(CGSize)size
{
if (CSSNodeStyleGetFlex(_cssNode) == 0) {
RCTAssignSuggestedDimension(_cssNode, CSSDimensionHeight, size.height);
RCTAssignSuggestedDimension(_cssNode, CSSDimensionWidth, size.width);
BOOL dirty = NO;
dirty |= RCTAssignSuggestedDimension(_cssNode, CSSDimensionHeight, size.height);
dirty |= RCTAssignSuggestedDimension(_cssNode, CSSDimensionWidth, size.width);
if (dirty) {
[self dirtyLayout];
}
}
}

- (void)setTopLeft:(CGPoint)topLeft
{
CSSNodeStyleSetPositionLeft(_cssNode, topLeft.x);
CSSNodeStyleSetPositionTop(_cssNode, topLeft.y);
[self dirtyLayout];
}

- (void)setSize:(CGSize)size
{
CSSNodeStyleSetWidth(_cssNode, size.width);
CSSNodeStyleSetHeight(_cssNode, size.height);
[self dirtyLayout];
}

// Flex
Expand All @@ -577,6 +618,7 @@ - (void)setSize:(CGSize)size
- (void)set##setProp:(type)value \
{ \
CSSNodeStyleSet##cssProp(_cssNode, value); \
[self dirtyLayout]; \
} \
- (type)getProp \
{ \
Expand Down Expand Up @@ -623,6 +665,9 @@ - (void)didSetProps:(__unused NSArray<NSString *> *)changedProps
if (_recomputeBorder) {
RCTProcessMetaPropsBorder(_borderMetaProps, _cssNode);
}
if (_recomputePadding || _recomputeMargin || _recomputeBorder) {
[self dirtyLayout];
}
_recomputeMargin = NO;
_recomputePadding = NO;
_recomputeBorder = NO;
Expand Down

0 comments on commit 15dfa5b

Please sign in to comment.