Skip to content

Commit

Permalink
Move dirty layout into css-layout
Browse files Browse the repository at this point in the history
Reviewed By: majak

Differential Revision: D3610634

fbshipit-source-id: 1dc9017c0a34ced231b5bebe334591f3d0b89bf3
  • Loading branch information
Emil Sjolander authored and Facebook Github Bot 7 committed Jul 25, 2016
1 parent 3b35732 commit 471eefc
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 80 deletions.
2 changes: 0 additions & 2 deletions Libraries/Text/RCTShadowRawText.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,13 @@ - (void)dealloc

- (void)contentSizeMultiplierDidChange:(NSNotification *)note
{
[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
{
[self dirtyLayout];
CSSNodeMarkDirty(self.cssNode);
[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];
[self dirtyLayout];
CSSNodeMarkDirty(self.cssNode);

return _cachedAttributedString;
}
Expand Down
3 changes: 2 additions & 1 deletion React/CSSLayout/CSSLayout-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,13 @@ 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
43 changes: 34 additions & 9 deletions React/CSSLayout/CSSLayout.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ CSSNodeRef CSSNodeNew() {
CSSNodeRef node = calloc(1, sizeof(CSSNode));
assert(node != NULL);

node->children = CSSNodeListNew(4);
CSSNodeInit(node);
return node;
}
Expand All @@ -44,6 +43,11 @@ 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 @@ -79,7 +83,6 @@ 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 @@ -88,12 +91,25 @@ 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 @@ -104,32 +120,40 @@ 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;\
node->instanceName = paramName; \
} \
\
type CSSNodeGet##name(CSSNodeRef node) { \
return node->instanceName;\
return node->instanceName; \
} \

#define CSS_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName) \
void CSSNodeStyleSet##name(CSSNodeRef node, type paramName) { \
node->style.instanceName = paramName;\
if (node->style.instanceName != paramName) { \
node->style.instanceName = paramName; \
_CSSNodeMarkDirty(node); \
} \
} \
\
type CSSNodeStyleGet##name(CSSNodeRef node) { \
return node->style.instanceName;\
return node->style.instanceName; \
} \

#define CSS_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \
type CSSNodeLayoutGet##name(CSSNodeRef node) { \
return node->layout.instanceName;\
return node->layout.instanceName; \
} \

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 @@ -1735,7 +1759,7 @@ bool layoutNodeInternal(CSSNode* node, float availableWidth, float availableHeig

gDepth++;

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

if (needToVisitNode) {
Expand Down Expand Up @@ -1867,6 +1891,7 @@ bool layoutNodeInternal(CSSNode* node, float availableWidth, float availableHeig
node->layout.dimensions[CSSDimensionWidth] = node->layout.measuredDimensions[CSSDimensionWidth];
node->layout.dimensions[CSSDimensionHeight] = node->layout.measuredDimensions[CSSDimensionHeight];
node->shouldUpdate = true;
node->isDirty = false;
}

gDepth--;
Expand Down
7 changes: 5 additions & 2 deletions React/CSSLayout/CSSLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ 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 @@ -129,6 +128,11 @@ 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 @@ -146,7 +150,6 @@ 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: 1 addition & 9 deletions React/Modules/RCTUIManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -424,11 +424,8 @@ - (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 @@ -437,14 +434,9 @@ - (void)setFrame:(CGRect)frame forView:(UIView *)view
RCTRootShadowView *rootShadowView = (RCTRootShadowView *)shadowView;
if (rootShadowView.sizeFlexibility != sizeFlexibility) {
rootShadowView.sizeFlexibility = sizeFlexibility;
dirtyLayout = YES;
[self batchDidComplete];
}
}

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

Expand Down
7 changes: 0 additions & 7 deletions React/Views/RCTShadowView.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ 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 @@ -183,12 +182,6 @@ 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
Loading

0 comments on commit 471eefc

Please sign in to comment.