diff --git a/Examples/UIExplorer/UIExplorerUnitTests/RCTShadowViewTests.m b/Examples/UIExplorer/UIExplorerUnitTests/RCTShadowViewTests.m index 7a49a86034e757..a966f9022b729d 100644 --- a/Examples/UIExplorer/UIExplorerUnitTests/RCTShadowViewTests.m +++ b/Examples/UIExplorer/UIExplorerUnitTests/RCTShadowViewTests.m @@ -28,8 +28,8 @@ - (void)setUp { [super setUp]; - self.parentView = [self _shadowViewWithStyle:^(css_style_t *style) { - style->flex_direction = CSS_FLEX_DIRECTION_COLUMN; + self.parentView = [self _shadowViewWithStyle:^(CSSStyle *style) { + style->flexDirection = CSSFlexDirectionColumn; style->dimensions[0] = 440; style->dimensions[1] = 440; }]; @@ -50,22 +50,22 @@ - (void)setUp // - (void)testApplyingLayoutRecursivelyToShadowView { - RCTShadowView *leftView = [self _shadowViewWithStyle:^(css_style_t *style) { + RCTShadowView *leftView = [self _shadowViewWithStyle:^(CSSStyle *style) { style->flex = 1; }]; - RCTShadowView *centerView = [self _shadowViewWithStyle:^(css_style_t *style) { + RCTShadowView *centerView = [self _shadowViewWithStyle:^(CSSStyle *style) { style->flex = 2; style->margin[0] = 10; style->margin[2] = 10; }]; - RCTShadowView *rightView = [self _shadowViewWithStyle:^(css_style_t *style) { + RCTShadowView *rightView = [self _shadowViewWithStyle:^(CSSStyle *style) { style->flex = 1; }]; - RCTShadowView *mainView = [self _shadowViewWithStyle:^(css_style_t *style) { - style->flex_direction = CSS_FLEX_DIRECTION_ROW; + RCTShadowView *mainView = [self _shadowViewWithStyle:^(CSSStyle *style) { + style->flexDirection = CSSFlexDirectionRow; style->flex = 2; style->margin[1] = 10; style->margin[3] = 10; @@ -75,11 +75,11 @@ - (void)testApplyingLayoutRecursivelyToShadowView [mainView insertReactSubview:centerView atIndex:1]; [mainView insertReactSubview:rightView atIndex:2]; - RCTShadowView *headerView = [self _shadowViewWithStyle:^(css_style_t *style) { + RCTShadowView *headerView = [self _shadowViewWithStyle:^(CSSStyle *style) { style->flex = 1; }]; - RCTShadowView *footerView = [self _shadowViewWithStyle:^(css_style_t *style) { + RCTShadowView *footerView = [self _shadowViewWithStyle:^(CSSStyle *style) { style->flex = 1; }]; @@ -108,10 +108,10 @@ - (void)testApplyingLayoutRecursivelyToShadowView - (void)testAssignsSuggestedWidthDimension { - [self _withShadowViewWithStyle:^(css_style_t *style) { - style->position[CSS_LEFT] = 0; - style->position[CSS_TOP] = 0; - style->dimensions[CSS_HEIGHT] = 10; + [self _withShadowViewWithStyle:^(CSSStyle *style) { + style->position[CSSPositionLeft] = 0; + style->position[CSSPositionTop] = 0; + style->dimensions[CSSDimensionHeight] = 10; } assertRelativeLayout:CGRectMake(0, 0, 3, 10) withIntrinsicContentSize:CGSizeMake(3, UIViewNoIntrinsicMetric)]; @@ -119,10 +119,10 @@ - (void)testAssignsSuggestedWidthDimension - (void)testAssignsSuggestedHeightDimension { - [self _withShadowViewWithStyle:^(css_style_t *style) { - style->position[CSS_LEFT] = 0; - style->position[CSS_TOP] = 0; - style->dimensions[CSS_WIDTH] = 10; + [self _withShadowViewWithStyle:^(CSSStyle *style) { + style->position[CSSPositionLeft] = 0; + style->position[CSSPositionTop] = 0; + style->dimensions[CSSDimensionWidth] = 10; } assertRelativeLayout:CGRectMake(0, 0, 10, 4) withIntrinsicContentSize:CGSizeMake(UIViewNoIntrinsicMetric, 4)]; @@ -130,11 +130,11 @@ - (void)testAssignsSuggestedHeightDimension - (void)testDoesNotOverrideDimensionStyleWithSuggestedDimensions { - [self _withShadowViewWithStyle:^(css_style_t *style) { - style->position[CSS_LEFT] = 0; - style->position[CSS_TOP] = 0; - style->dimensions[CSS_WIDTH] = 10; - style->dimensions[CSS_HEIGHT] = 10; + [self _withShadowViewWithStyle:^(CSSStyle *style) { + style->position[CSSPositionLeft] = 0; + style->position[CSSPositionTop] = 0; + style->dimensions[CSSDimensionWidth] = 10; + style->dimensions[CSSDimensionHeight] = 10; } assertRelativeLayout:CGRectMake(0, 0, 10, 10) withIntrinsicContentSize:CGSizeMake(3, 4)]; @@ -142,16 +142,16 @@ - (void)testDoesNotOverrideDimensionStyleWithSuggestedDimensions - (void)testDoesNotAssignSuggestedDimensionsWhenStyledWithFlexAttribute { - float parentWidth = self.parentView.cssNode->style.dimensions[CSS_WIDTH]; - float parentHeight = self.parentView.cssNode->style.dimensions[CSS_HEIGHT]; - [self _withShadowViewWithStyle:^(css_style_t *style) { + float parentWidth = self.parentView.cssNode->style.dimensions[CSSDimensionWidth]; + float parentHeight = self.parentView.cssNode->style.dimensions[CSSDimensionHeight]; + [self _withShadowViewWithStyle:^(CSSStyle *style) { style->flex = 1; } assertRelativeLayout:CGRectMake(0, 0, parentWidth, parentHeight) withIntrinsicContentSize:CGSizeMake(3, 4)]; } -- (void)_withShadowViewWithStyle:(void(^)(css_style_t *style))styleBlock +- (void)_withShadowViewWithStyle:(void(^)(CSSStyle *style))styleBlock assertRelativeLayout:(CGRect)expectedRect withIntrinsicContentSize:(CGSize)contentSize { @@ -166,11 +166,11 @@ - (void)_withShadowViewWithStyle:(void(^)(css_style_t *style))styleBlock NSStringFromCGRect(actualRect)); } -- (RCTRootShadowView *)_shadowViewWithStyle:(void(^)(css_style_t *style))styleBlock +- (RCTRootShadowView *)_shadowViewWithStyle:(void(^)(CSSStyle *style))styleBlock { RCTRootShadowView *shadowView = [RCTRootShadowView new]; - css_style_t style = shadowView.cssNode->style; + CSSStyle style = shadowView.cssNode->style; styleBlock(&style); shadowView.cssNode->style = style; diff --git a/Examples/UIExplorer/js/ToastAndroidExample.android.js b/Examples/UIExplorer/js/ToastAndroidExample.android.js index 53cd3a95a85d29..86866b1c346d68 100644 --- a/Examples/UIExplorer/js/ToastAndroidExample.android.js +++ b/Examples/UIExplorer/js/ToastAndroidExample.android.js @@ -60,7 +60,43 @@ var ToastExample = React.createClass({ ToastAndroid.show('This is a toast with long duration', ToastAndroid.LONG)}> - Click me too. + Click me. + + + + + ToastAndroid.showWithGravity( + 'This is a toast with top gravity', + ToastAndroid.SHORT, + ToastAndroid.TOP, + ) + }> + Click me. + + + + + ToastAndroid.showWithGravity( + 'This is a toast with center gravity', + ToastAndroid.SHORT, + ToastAndroid.CENTER, + ) + }> + Click me. + + + + + ToastAndroid.showWithGravity( + 'This is a toast with bottom gravity', + ToastAndroid.SHORT, + ToastAndroid.BOTTOM, + ) + }> + Click me. diff --git a/Libraries/BatchedBridge/BatchedBridgedModules/NativeModules.js b/Libraries/BatchedBridge/BatchedBridgedModules/NativeModules.js index dfbd9edd1a3554..f1a4da1d4c2412 100644 --- a/Libraries/BatchedBridge/BatchedBridgedModules/NativeModules.js +++ b/Libraries/BatchedBridge/BatchedBridgedModules/NativeModules.js @@ -46,8 +46,11 @@ Object.keys(RemoteModules).forEach((moduleName) => { get: () => { let module = RemoteModules[moduleName]; if (module && typeof module.moduleID === 'number' && global.nativeRequireModuleConfig) { - const json = global.nativeRequireModuleConfig(moduleName); - const config = json && JSON.parse(json); + // The old bridge (still used by iOS) will send the config as + // a JSON string that needs parsing, so we set config according + // to the type of response we got. + const rawConfig = global.nativeRequireModuleConfig(moduleName); + const config = typeof rawConfig === 'string' ? JSON.parse(rawConfig) : rawConfig; module = config && BatchedBridge.processModuleConfig(config, module.moduleID); RemoteModules[moduleName] = module; } diff --git a/Libraries/Components/ToastAndroid/ToastAndroid.android.js b/Libraries/Components/ToastAndroid/ToastAndroid.android.js index 1006b929387ced..ac03e62d4805e8 100644 --- a/Libraries/Components/ToastAndroid/ToastAndroid.android.js +++ b/Libraries/Components/ToastAndroid/ToastAndroid.android.js @@ -19,13 +19,22 @@ var RCTToastAndroid = require('NativeModules').ToastAndroid; * * 1. String message: A string with the text to toast * 2. int duration: The duration of the toast. May be ToastAndroid.SHORT or ToastAndroid.LONG + * + * There is also a function `showWithGravity` to specify the layout gravity. May be + * ToastAndroid.TOP, ToastAndroid.BOTTOM, ToastAndroid.CENTER */ var ToastAndroid = { + // Toast duration constants SHORT: RCTToastAndroid.SHORT, LONG: RCTToastAndroid.LONG, + // Toast gravity constants + TOP: RCTToastAndroid.TOP, + BOTTOM: RCTToastAndroid.BOTTOM, + CENTER: RCTToastAndroid.CENTER, + show: function ( message: string, duration: number @@ -33,6 +42,13 @@ var ToastAndroid = { RCTToastAndroid.show(message, duration); }, + showWithGravity: function ( + message: string, + duration: number, + gravity: number, + ): void { + RCTToastAndroid.showWithGravity(message, duration, gravity); + }, }; module.exports = ToastAndroid; diff --git a/Libraries/QuickPerformanceLogger/QuickPerformanceLogger.js b/Libraries/QuickPerformanceLogger/QuickPerformanceLogger.js index fa6b257dd3e64d..42f75f688bd231 100644 --- a/Libraries/QuickPerformanceLogger/QuickPerformanceLogger.js +++ b/Libraries/QuickPerformanceLogger/QuickPerformanceLogger.js @@ -21,12 +21,6 @@ var fixOpts = function(opts) { }; var QuickPerformanceLogger = { - - // These two empty containers will cause all calls to ActionId.SOMETHING or MarkerId.OTHER - // to equal 'undefined', unless they are given a concrete value elsewhere. - ActionId: {}, - MarkerId: {}, - markerStart(markerId, opts) { if (typeof markerId !== 'number') { return; diff --git a/Libraries/Text/RCTShadowText.m b/Libraries/Text/RCTShadowText.m index 32e73997facaa7..bbff4ac1b6ed23 100644 --- a/Libraries/Text/RCTShadowText.m +++ b/Libraries/Text/RCTShadowText.m @@ -33,7 +33,7 @@ @implementation RCTShadowText CGFloat _effectiveLetterSpacing; } -static css_dim_t RCTMeasure(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode) +static CSSMeasureResult RCTMeasure(void *context, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode) { RCTShadowText *shadowText = (__bridge RCTShadowText *)context; NSTextStorage *textStorage = [shadowText buildTextStorageForWidth:width widthMode:widthMode]; @@ -41,12 +41,12 @@ static css_dim_t RCTMeasure(void *context, float width, css_measure_mode_t width NSTextContainer *textContainer = layoutManager.textContainers.firstObject; CGSize computedSize = [layoutManager usedRectForTextContainer:textContainer].size; - css_dim_t result; - result.dimensions[CSS_WIDTH] = RCTCeilPixelValue(computedSize.width); + CSSMeasureResult result; + result.dimensions[CSSDimensionWidth] = RCTCeilPixelValue(computedSize.width); if (shadowText->_effectiveLetterSpacing < 0) { - result.dimensions[CSS_WIDTH] -= shadowText->_effectiveLetterSpacing; + result.dimensions[CSSDimensionWidth] -= shadowText->_effectiveLetterSpacing; } - result.dimensions[CSS_HEIGHT] = RCTCeilPixelValue(computedSize.height); + result.dimensions[CSSDimensionHeight] = RCTCeilPixelValue(computedSize.height); return result; } @@ -61,6 +61,7 @@ - (instancetype)init _cachedTextStorageWidth = -1; _cachedTextStorageWidthMode = -1; _fontSizeMultiplier = 1.0; + self.cssNode->measure = RCTMeasure; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentSizeMultiplierDidChange:) name:RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification @@ -80,6 +81,11 @@ - (NSString *)description return [[superDescription substringToIndex:superDescription.length - 1] stringByAppendingFormat:@"; text: %@>", [self attributedString].string]; } +- (BOOL)isCSSLeafNode +{ + return YES; +} + - (void)contentSizeMultiplierDidChange:(NSNotification *)note { [self dirtyLayout]; @@ -100,7 +106,7 @@ - (void)contentSizeMultiplierDidChange:(NSNotification *)note CGFloat width = self.frame.size.width - (padding.left + padding.right); NSNumber *parentTag = [[self reactSuperview] reactTag]; - NSTextStorage *textStorage = [self buildTextStorageForWidth:width widthMode:CSS_MEASURE_MODE_EXACTLY]; + NSTextStorage *textStorage = [self buildTextStorageForWidth:width widthMode:CSSMeasureModeExactly]; [applierBlocks addObject:^(NSDictionary *viewRegistry) { RCTText *view = (RCTText *)viewRegistry[self.reactTag]; view.textStorage = textStorage; @@ -122,7 +128,7 @@ - (void)contentSizeMultiplierDidChange:(NSNotification *)note return parentProperties; } -- (void)applyLayoutNode:(css_node_t *)node +- (void)applyLayoutNode:(CSSNode *)node viewsWithNewFrame:(NSMutableSet *)viewsWithNewFrame absolutePosition:(CGPoint)absolutePosition { @@ -130,21 +136,21 @@ - (void)applyLayoutNode:(css_node_t *)node [self dirtyPropagation]; } -- (void)applyLayoutToChildren:(css_node_t *)node +- (void)applyLayoutToChildren:(CSSNode *)node viewsWithNewFrame:(NSMutableSet *)viewsWithNewFrame absolutePosition:(CGPoint)absolutePosition { // Run layout on subviews. - NSTextStorage *textStorage = [self buildTextStorageForWidth:self.frame.size.width widthMode:CSS_MEASURE_MODE_EXACTLY]; + NSTextStorage *textStorage = [self buildTextStorageForWidth:self.frame.size.width widthMode:CSSMeasureModeExactly]; NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject; NSTextContainer *textContainer = layoutManager.textContainers.firstObject; NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer]; NSRange characterRange = [layoutManager characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL]; [layoutManager.textStorage enumerateAttribute:RCTShadowViewAttributeName inRange:characterRange options:0 usingBlock:^(RCTShadowView *child, NSRange range, BOOL *_) { if (child) { - css_node_t *childNode = child.cssNode; - float width = childNode->style.dimensions[CSS_WIDTH]; - float height = childNode->style.dimensions[CSS_HEIGHT]; + CSSNode *childNode = child.cssNode; + float width = childNode->style.dimensions[CSSDimensionWidth]; + float height = childNode->style.dimensions[CSSDimensionHeight]; if (isUndefined(width) || isUndefined(height)) { RCTLogError(@"Views nested within a must have a width and height"); } @@ -169,7 +175,7 @@ - (void)applyLayoutToChildren:(css_node_t *)node }]; } -- (NSTextStorage *)buildTextStorageForWidth:(CGFloat)width widthMode:(css_measure_mode_t)widthMode +- (NSTextStorage *)buildTextStorageForWidth:(CGFloat)width widthMode:(CSSMeasureMode)widthMode { if (_cachedTextStorage && width == _cachedTextStorageWidth && widthMode == _cachedTextStorageWidthMode) { return _cachedTextStorage; @@ -190,7 +196,7 @@ - (NSTextStorage *)buildTextStorageForWidth:(CGFloat)width widthMode:(css_measur } textContainer.maximumNumberOfLines = _numberOfLines; - textContainer.size = (CGSize){widthMode == CSS_MEASURE_MODE_UNDEFINED ? CGFLOAT_MAX : width, CGFLOAT_MAX}; + textContainer.size = (CGSize){widthMode == CSSMeasureModeUndefined ? CGFLOAT_MAX : width, CGFLOAT_MAX}; [layoutManager addTextContainer:textContainer]; [layoutManager ensureLayoutForTextContainer:textContainer]; @@ -285,8 +291,8 @@ - (NSAttributedString *)_attributedStringWithFontFamily:(NSString *)fontFamily [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:shadowRawText.text ?: @""]]; [child setTextComputed]; } else { - float width = child.cssNode->style.dimensions[CSS_WIDTH]; - float height = child.cssNode->style.dimensions[CSS_HEIGHT]; + float width = child.cssNode->style.dimensions[CSSDimensionWidth]; + float height = child.cssNode->style.dimensions[CSSDimensionHeight]; if (isUndefined(width) || isUndefined(height)) { RCTLogError(@"Views nested within a must have a width and height"); } @@ -378,10 +384,10 @@ - (void)_setParagraphStyleOnAttributedString:(NSMutableAttributedString *)attrib // We will climb up to the first node which style has been setted as non-inherit if (newTextAlign == NSTextAlignmentRight || newTextAlign == NSTextAlignmentLeft) { RCTShadowView *view = self; - while (view != nil && view.cssNode->style.direction == CSS_DIRECTION_INHERIT) { + while (view != nil && view.cssNode->style.direction == CSSDirectionInherit) { view = [view reactSuperview]; } - if (view != nil && view.cssNode->style.direction == CSS_DIRECTION_RTL) { + if (view != nil && view.cssNode->style.direction == CSSDirectionRTL) { if (newTextAlign == NSTextAlignmentRight) { newTextAlign = NSTextAlignmentLeft; } else if (newTextAlign == NSTextAlignmentLeft) { @@ -442,25 +448,6 @@ - (void)_setParagraphStyleOnAttributedString:(NSMutableAttributedString *)attrib } } -- (void)fillCSSNode:(css_node_t *)node -{ - [super fillCSSNode:node]; - node->measure = RCTMeasure; - node->children_count = 0; -} - -- (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)atIndex -{ - [super insertReactSubview:subview atIndex:atIndex]; - self.cssNode->children_count = 0; -} - -- (void)removeReactSubview:(RCTShadowView *)subview -{ - [super removeReactSubview:subview]; - self.cssNode->children_count = 0; -} - - (void)setBackgroundColor:(UIColor *)backgroundColor { super.backgroundColor = backgroundColor; diff --git a/Libraries/Text/RCTTextManager.m b/Libraries/Text/RCTTextManager.m index 676ff9bb2063b8..c8fe246ddbc69b 100644 --- a/Libraries/Text/RCTTextManager.m +++ b/Libraries/Text/RCTTextManager.m @@ -34,7 +34,7 @@ static void collectDirtyNonTextDescendants(RCTShadowText *shadowView, NSMutableA @interface RCTShadowText (Private) -- (NSTextStorage *)buildTextStorageForWidth:(CGFloat)width widthMode:(css_measure_mode_t)widthMode; +- (NSTextStorage *)buildTextStorageForWidth:(CGFloat)width widthMode:(CSSMeasureMode)widthMode; @end diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h index 086e5dfca6623f..8aeda7e28064a3 100644 --- a/React/Base/RCTConvert.h +++ b/React/Base/RCTConvert.h @@ -116,11 +116,11 @@ typedef id NSPropertyList; typedef BOOL css_clip_t, css_backface_visibility_t; + (css_clip_t)css_clip_t:(id)json; + (css_backface_visibility_t)css_backface_visibility_t:(id)json; -+ (css_flex_direction_t)css_flex_direction_t:(id)json; -+ (css_justify_t)css_justify_t:(id)json; -+ (css_align_t)css_align_t:(id)json; -+ (css_position_type_t)css_position_type_t:(id)json; -+ (css_wrap_type_t)css_wrap_type_t:(id)json; ++ (CSSFlexDirection)CSSFlexDirection:(id)json; ++ (CSSJustify)CSSJustify:(id)json; ++ (CSSAlign)CSSAlign:(id)json; ++ (CSSPositionType)CSSPositionType:(id)json; ++ (CSSWrapType)CSSWrapType:(id)json; + (RCTPointerEvents)RCTPointerEvents:(id)json; + (RCTAnimationType)RCTAnimationType:(id)json; diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index e37766cee88a27..24683744cd39f9 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -822,38 +822,38 @@ + (NSPropertyList)NSPropertyList:(id)json @"visible": @NO }), NO, boolValue) -RCT_ENUM_CONVERTER(css_flex_direction_t, (@{ - @"row": @(CSS_FLEX_DIRECTION_ROW), - @"row-reverse": @(CSS_FLEX_DIRECTION_ROW_REVERSE), - @"column": @(CSS_FLEX_DIRECTION_COLUMN), - @"column-reverse": @(CSS_FLEX_DIRECTION_COLUMN_REVERSE) -}), CSS_FLEX_DIRECTION_COLUMN, intValue) - -RCT_ENUM_CONVERTER(css_justify_t, (@{ - @"flex-start": @(CSS_JUSTIFY_FLEX_START), - @"flex-end": @(CSS_JUSTIFY_FLEX_END), - @"center": @(CSS_JUSTIFY_CENTER), - @"space-between": @(CSS_JUSTIFY_SPACE_BETWEEN), - @"space-around": @(CSS_JUSTIFY_SPACE_AROUND) -}), CSS_JUSTIFY_FLEX_START, intValue) - -RCT_ENUM_CONVERTER(css_align_t, (@{ - @"flex-start": @(CSS_ALIGN_FLEX_START), - @"flex-end": @(CSS_ALIGN_FLEX_END), - @"center": @(CSS_ALIGN_CENTER), - @"auto": @(CSS_ALIGN_AUTO), - @"stretch": @(CSS_ALIGN_STRETCH) -}), CSS_ALIGN_FLEX_START, intValue) - -RCT_ENUM_CONVERTER(css_position_type_t, (@{ - @"absolute": @(CSS_POSITION_ABSOLUTE), - @"relative": @(CSS_POSITION_RELATIVE) -}), CSS_POSITION_RELATIVE, intValue) - -RCT_ENUM_CONVERTER(css_wrap_type_t, (@{ - @"wrap": @(CSS_WRAP), - @"nowrap": @(CSS_NOWRAP) -}), CSS_NOWRAP, intValue) +RCT_ENUM_CONVERTER(CSSFlexDirection, (@{ + @"row": @(CSSFlexDirectionRow), + @"row-reverse": @(CSSFlexDirectionRowReverse), + @"column": @(CSSFlexDirectionColumn), + @"column-reverse": @(CSSFlexDirectionColumnReverse) +}), CSSFlexDirectionColumn, intValue) + +RCT_ENUM_CONVERTER(CSSJustify, (@{ + @"flex-start": @(CSSJustifyFlexStart), + @"flex-end": @(CSSJustifyFlexEnd), + @"center": @(CSSJustifyCenter), + @"space-between": @(CSSJustifySpaceBetween), + @"space-around": @(CSSJustifySpaceAround) +}), CSSJustifyFlexStart, intValue) + +RCT_ENUM_CONVERTER(CSSAlign, (@{ + @"flex-start": @(CSSAlignFlexStart), + @"flex-end": @(CSSAlignFlexEnd), + @"center": @(CSSAlignCenter), + @"auto": @(CSSAlignAuto), + @"stretch": @(CSSAlignStretch) +}), CSSAlignFlexStart, intValue) + +RCT_ENUM_CONVERTER(CSSPositionType, (@{ + @"absolute": @(CSSPositionTypeAbsolute), + @"relative": @(CSSPositionTypeRelative) +}), CSSPositionTypeRelative, intValue) + +RCT_ENUM_CONVERTER(CSSWrapType, (@{ + @"wrap": @(CSSWrapTypeWrap), + @"nowrap": @(CSSWrapTypeNoWrap) +}), CSSWrapTypeNoWrap, intValue) RCT_ENUM_CONVERTER(RCTPointerEvents, (@{ @"none": @(RCTPointerEventsNone), diff --git a/React/CSSLayout/CSSLayout.c b/React/CSSLayout/CSSLayout.c index ae44f8897149dd..6db70b40e8da77 100644 --- a/React/CSSLayout/CSSLayout.c +++ b/React/CSSLayout/CSSLayout.c @@ -31,8 +31,8 @@ __forceinline const float fmaxf(const float a, const float b) { int gCurrentGenerationCount = 0; -bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableHeight, css_direction_t parentDirection, - css_measure_mode_t widthMeasureMode, css_measure_mode_t heightMeasureMode, bool performLayout, char* reason); +bool layoutNodeInternal(CSSNode* node, float availableWidth, float availableHeight, CSSDirection parentDirection, + CSSMeasureMode widthMeasureMode, CSSMeasureMode heightMeasureMode, bool performLayout, char* reason); bool isUndefined(float value) { return isnan(value); @@ -45,58 +45,58 @@ static bool eq(float a, float b) { return fabs(a - b) < 0.0001; } -void init_css_node(css_node_t* node) { - node->style.align_items = CSS_ALIGN_STRETCH; - node->style.align_content = CSS_ALIGN_FLEX_START; +void CSSNodeInit(CSSNode* node) { + node->style.alignItems = CSSAlignStretch; + node->style.alignContent = CSSAlignFlexStart; - node->style.direction = CSS_DIRECTION_INHERIT; - node->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN; + node->style.direction = CSSDirectionInherit; + node->style.flexDirection = CSSFlexDirectionColumn; - node->style.overflow = CSS_OVERFLOW_VISIBLE; + node->style.overflow = CSSOverflowVisible; // Some of the fields default to undefined and not 0 - node->style.dimensions[CSS_WIDTH] = CSS_UNDEFINED; - node->style.dimensions[CSS_HEIGHT] = CSS_UNDEFINED; + node->style.dimensions[CSSDimensionWidth] = CSSUndefined; + node->style.dimensions[CSSDimensionHeight] = CSSUndefined; - node->style.minDimensions[CSS_WIDTH] = CSS_UNDEFINED; - node->style.minDimensions[CSS_HEIGHT] = CSS_UNDEFINED; + node->style.minDimensions[CSSDimensionWidth] = CSSUndefined; + node->style.minDimensions[CSSDimensionHeight] = CSSUndefined; - node->style.maxDimensions[CSS_WIDTH] = CSS_UNDEFINED; - node->style.maxDimensions[CSS_HEIGHT] = CSS_UNDEFINED; + node->style.maxDimensions[CSSDimensionWidth] = CSSUndefined; + node->style.maxDimensions[CSSDimensionHeight] = CSSUndefined; - node->style.position[CSS_LEFT] = CSS_UNDEFINED; - node->style.position[CSS_TOP] = CSS_UNDEFINED; - node->style.position[CSS_RIGHT] = CSS_UNDEFINED; - node->style.position[CSS_BOTTOM] = CSS_UNDEFINED; + node->style.position[CSSPositionLeft] = CSSUndefined; + node->style.position[CSSPositionTop] = CSSUndefined; + node->style.position[CSSPositionRight] = CSSUndefined; + node->style.position[CSSPositionBottom] = CSSUndefined; - node->style.margin[CSS_START] = CSS_UNDEFINED; - node->style.margin[CSS_END] = CSS_UNDEFINED; - node->style.padding[CSS_START] = CSS_UNDEFINED; - node->style.padding[CSS_END] = CSS_UNDEFINED; - node->style.border[CSS_START] = CSS_UNDEFINED; - node->style.border[CSS_END] = CSS_UNDEFINED; + node->style.margin[CSSPositionStart] = CSSUndefined; + node->style.margin[CSSPositionEnd] = CSSUndefined; + node->style.padding[CSSPositionStart] = CSSUndefined; + node->style.padding[CSSPositionEnd] = CSSUndefined; + node->style.border[CSSPositionStart] = CSSUndefined; + node->style.border[CSSPositionEnd] = CSSUndefined; - node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED; - node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED; + node->layout.dimensions[CSSDimensionWidth] = CSSUndefined; + node->layout.dimensions[CSSDimensionHeight] = CSSUndefined; // Such that the comparison is always going to be false - node->layout.last_parent_direction = (css_direction_t)-1; - node->layout.should_update = true; - node->layout.next_cached_measurements_index = 0; - - node->layout.measured_dimensions[CSS_WIDTH] = CSS_UNDEFINED; - node->layout.measured_dimensions[CSS_HEIGHT] = CSS_UNDEFINED; - node->layout.cached_layout.width_measure_mode = (css_measure_mode_t)-1; - node->layout.cached_layout.height_measure_mode = (css_measure_mode_t)-1; + node->layout.lastParentDirection = (CSSDirection)-1; + node->layout.shouldUpdate = true; + node->layout.nextCachedMeasurementsIndex = 0; + + node->layout.measuredDimensions[CSSDimensionWidth] = CSSUndefined; + node->layout.measuredDimensions[CSSDimensionHeight] = CSSUndefined; + node->layout.cached_layout.widthMeasureMode = (CSSMeasureMode)-1; + node->layout.cached_layout.heightMeasureMode = (CSSMeasureMode)-1; } -css_node_t* new_css_node() { - css_node_t* node = (css_node_t*)calloc(1, sizeof(*node)); - init_css_node(node); +CSSNode* CSSNodeNew() { + CSSNode* node = (CSSNode*)calloc(1, sizeof(*node)); + CSSNodeInit(node); return node; } -void free_css_node(css_node_t* node) { +void CSSNodeFree(CSSNode* node) { free(node); } @@ -127,8 +127,8 @@ static bool four_equal(float four[4]) { static void print_css_node_rec( - css_node_t* node, - css_print_options_t options, + CSSNode* node, + CSSPrintOptions options, int level ) { indent(level); @@ -138,124 +138,124 @@ static void print_css_node_rec( node->print(node->context); } - if (options & CSS_PRINT_LAYOUT) { + if (options & CSSPrintOptionsLayout) { printf("layout: {"); - printf("width: %g, ", node->layout.dimensions[CSS_WIDTH]); - printf("height: %g, ", node->layout.dimensions[CSS_HEIGHT]); - printf("top: %g, ", node->layout.position[CSS_TOP]); - printf("left: %g", node->layout.position[CSS_LEFT]); + printf("width: %g, ", node->layout.dimensions[CSSDimensionWidth]); + printf("height: %g, ", node->layout.dimensions[CSSDimensionHeight]); + printf("top: %g, ", node->layout.position[CSSPositionTop]); + printf("left: %g", node->layout.position[CSSPositionLeft]); printf("}, "); } - if (options & CSS_PRINT_STYLE) { - if (node->style.flex_direction == CSS_FLEX_DIRECTION_COLUMN) { + if (options & CSSPrintOptionsStyle) { + if (node->style.flexDirection == CSSFlexDirectionColumn) { printf("flexDirection: 'column', "); - } else if (node->style.flex_direction == CSS_FLEX_DIRECTION_COLUMN_REVERSE) { + } else if (node->style.flexDirection == CSSFlexDirectionColumnReverse) { printf("flexDirection: 'column-reverse', "); - } else if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW) { + } else if (node->style.flexDirection == CSSFlexDirectionRow) { printf("flexDirection: 'row', "); - } else if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE) { + } else if (node->style.flexDirection == CSSFlexDirectionRowReverse) { printf("flexDirection: 'row-reverse', "); } - if (node->style.justify_content == CSS_JUSTIFY_CENTER) { + if (node->style.justifyContent == CSSJustifyCenter) { printf("justifyContent: 'center', "); - } else if (node->style.justify_content == CSS_JUSTIFY_FLEX_END) { + } else if (node->style.justifyContent == CSSJustifyFlexEnd) { printf("justifyContent: 'flex-end', "); - } else if (node->style.justify_content == CSS_JUSTIFY_SPACE_AROUND) { + } else if (node->style.justifyContent == CSSJustifySpaceAround) { printf("justifyContent: 'space-around', "); - } else if (node->style.justify_content == CSS_JUSTIFY_SPACE_BETWEEN) { + } else if (node->style.justifyContent == CSSJustifySpaceBetween) { printf("justifyContent: 'space-between', "); } - if (node->style.align_items == CSS_ALIGN_CENTER) { + if (node->style.alignItems == CSSAlignCenter) { printf("alignItems: 'center', "); - } else if (node->style.align_items == CSS_ALIGN_FLEX_END) { + } else if (node->style.alignItems == CSSAlignFlexEnd) { printf("alignItems: 'flex-end', "); - } else if (node->style.align_items == CSS_ALIGN_STRETCH) { + } else if (node->style.alignItems == CSSAlignStretch) { printf("alignItems: 'stretch', "); } - if (node->style.align_content == CSS_ALIGN_CENTER) { + if (node->style.alignContent == CSSAlignCenter) { printf("alignContent: 'center', "); - } else if (node->style.align_content == CSS_ALIGN_FLEX_END) { + } else if (node->style.alignContent == CSSAlignFlexEnd) { printf("alignContent: 'flex-end', "); - } else if (node->style.align_content == CSS_ALIGN_STRETCH) { + } else if (node->style.alignContent == CSSAlignStretch) { printf("alignContent: 'stretch', "); } - if (node->style.align_self == CSS_ALIGN_FLEX_START) { + if (node->style.alignSelf == CSSAlignFlexStart) { printf("alignSelf: 'flex-start', "); - } else if (node->style.align_self == CSS_ALIGN_CENTER) { + } else if (node->style.alignSelf == CSSAlignCenter) { printf("alignSelf: 'center', "); - } else if (node->style.align_self == CSS_ALIGN_FLEX_END) { + } else if (node->style.alignSelf == CSSAlignFlexEnd) { printf("alignSelf: 'flex-end', "); - } else if (node->style.align_self == CSS_ALIGN_STRETCH) { + } else if (node->style.alignSelf == CSSAlignStretch) { printf("alignSelf: 'stretch', "); } print_number_nan("flex", node->style.flex); - if (node->style.overflow == CSS_OVERFLOW_HIDDEN) { + if (node->style.overflow == CSSOverflowHidden) { printf("overflow: 'hidden', "); - } else if (node->style.overflow == CSS_OVERFLOW_VISIBLE) { + } else if (node->style.overflow == CSSOverflowVisible) { printf("overflow: 'visible', "); } if (four_equal(node->style.margin)) { - print_number_0("margin", node->style.margin[CSS_LEFT]); + print_number_0("margin", node->style.margin[CSSPositionLeft]); } else { - print_number_0("marginLeft", node->style.margin[CSS_LEFT]); - print_number_0("marginRight", node->style.margin[CSS_RIGHT]); - print_number_0("marginTop", node->style.margin[CSS_TOP]); - print_number_0("marginBottom", node->style.margin[CSS_BOTTOM]); - print_number_0("marginStart", node->style.margin[CSS_START]); - print_number_0("marginEnd", node->style.margin[CSS_END]); + print_number_0("marginLeft", node->style.margin[CSSPositionLeft]); + print_number_0("marginRight", node->style.margin[CSSPositionRight]); + print_number_0("marginTop", node->style.margin[CSSPositionTop]); + print_number_0("marginBottom", node->style.margin[CSSPositionBottom]); + print_number_0("marginStart", node->style.margin[CSSPositionStart]); + print_number_0("marginEnd", node->style.margin[CSSPositionEnd]); } if (four_equal(node->style.padding)) { - print_number_0("padding", node->style.padding[CSS_LEFT]); + print_number_0("padding", node->style.padding[CSSPositionLeft]); } else { - print_number_0("paddingLeft", node->style.padding[CSS_LEFT]); - print_number_0("paddingRight", node->style.padding[CSS_RIGHT]); - print_number_0("paddingTop", node->style.padding[CSS_TOP]); - print_number_0("paddingBottom", node->style.padding[CSS_BOTTOM]); - print_number_0("paddingStart", node->style.padding[CSS_START]); - print_number_0("paddingEnd", node->style.padding[CSS_END]); + print_number_0("paddingLeft", node->style.padding[CSSPositionLeft]); + print_number_0("paddingRight", node->style.padding[CSSPositionRight]); + print_number_0("paddingTop", node->style.padding[CSSPositionTop]); + print_number_0("paddingBottom", node->style.padding[CSSPositionBottom]); + print_number_0("paddingStart", node->style.padding[CSSPositionStart]); + print_number_0("paddingEnd", node->style.padding[CSSPositionEnd]); } if (four_equal(node->style.border)) { - print_number_0("borderWidth", node->style.border[CSS_LEFT]); + print_number_0("borderWidth", node->style.border[CSSPositionLeft]); } else { - print_number_0("borderLeftWidth", node->style.border[CSS_LEFT]); - print_number_0("borderRightWidth", node->style.border[CSS_RIGHT]); - print_number_0("borderTopWidth", node->style.border[CSS_TOP]); - print_number_0("borderBottomWidth", node->style.border[CSS_BOTTOM]); - print_number_0("borderStartWidth", node->style.border[CSS_START]); - print_number_0("borderEndWidth", node->style.border[CSS_END]); + print_number_0("borderLeftWidth", node->style.border[CSSPositionLeft]); + print_number_0("borderRightWidth", node->style.border[CSSPositionRight]); + print_number_0("borderTopWidth", node->style.border[CSSPositionTop]); + print_number_0("borderBottomWidth", node->style.border[CSSPositionBottom]); + print_number_0("borderStartWidth", node->style.border[CSSPositionStart]); + print_number_0("borderEndWidth", node->style.border[CSSPositionEnd]); } - print_number_nan("width", node->style.dimensions[CSS_WIDTH]); - print_number_nan("height", node->style.dimensions[CSS_HEIGHT]); - print_number_nan("maxWidth", node->style.maxDimensions[CSS_WIDTH]); - print_number_nan("maxHeight", node->style.maxDimensions[CSS_HEIGHT]); - print_number_nan("minWidth", node->style.minDimensions[CSS_WIDTH]); - print_number_nan("minHeight", node->style.minDimensions[CSS_HEIGHT]); + print_number_nan("width", node->style.dimensions[CSSDimensionWidth]); + print_number_nan("height", node->style.dimensions[CSSDimensionHeight]); + print_number_nan("maxWidth", node->style.maxDimensions[CSSDimensionWidth]); + print_number_nan("maxHeight", node->style.maxDimensions[CSSDimensionHeight]); + print_number_nan("minWidth", node->style.minDimensions[CSSDimensionWidth]); + print_number_nan("minHeight", node->style.minDimensions[CSSDimensionHeight]); - if (node->style.position_type == CSS_POSITION_ABSOLUTE) { + if (node->style.positionType == CSSPositionTypeAbsolute) { printf("position: 'absolute', "); } - print_number_nan("left", node->style.position[CSS_LEFT]); - print_number_nan("right", node->style.position[CSS_RIGHT]); - print_number_nan("top", node->style.position[CSS_TOP]); - print_number_nan("bottom", node->style.position[CSS_BOTTOM]); + print_number_nan("left", node->style.position[CSSPositionLeft]); + print_number_nan("right", node->style.position[CSSPositionRight]); + print_number_nan("top", node->style.position[CSSPositionTop]); + print_number_nan("bottom", node->style.position[CSSPositionBottom]); } - if (options & CSS_PRINT_CHILDREN && node->children_count > 0) { + if (options & CSSPrintOptionsChildren && node->childCount > 0) { printf("children: [\n"); - for (int i = 0; i < node->children_count; ++i) { - print_css_node_rec(node->get_child(node->context, i), options, level + 1); + for (int i = 0; i < node->childCount; ++i) { + print_css_node_rec(node->getChild(node->context, i), options, level + 1); } indent(level); printf("]},\n"); @@ -264,46 +264,46 @@ static void print_css_node_rec( } } -void print_css_node(css_node_t* node, css_print_options_t options) { +void CSSNodePrint(CSSNode* node, CSSPrintOptions options) { print_css_node_rec(node, options, 0); } -static css_position_t leading[4] = { - /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP, - /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_BOTTOM, - /* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT, - /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_RIGHT +static CSSPosition leading[4] = { + /* CSSFlexDirectionColumn = */ CSSPositionTop, + /* CSSFlexDirectionColumnReverse = */ CSSPositionBottom, + /* CSSFlexDirectionRow = */ CSSPositionLeft, + /* CSSFlexDirectionRowReverse = */ CSSPositionRight }; -static css_position_t trailing[4] = { - /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_BOTTOM, - /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_TOP, - /* CSS_FLEX_DIRECTION_ROW = */ CSS_RIGHT, - /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_LEFT +static CSSPosition trailing[4] = { + /* CSSFlexDirectionColumn = */ CSSPositionBottom, + /* CSSFlexDirectionColumnReverse = */ CSSPositionTop, + /* CSSFlexDirectionRow = */ CSSPositionRight, + /* CSSFlexDirectionRowReverse = */ CSSPositionLeft }; -static css_position_t pos[4] = { - /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP, - /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_BOTTOM, - /* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT, - /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_RIGHT +static CSSPosition pos[4] = { + /* CSSFlexDirectionColumn = */ CSSPositionTop, + /* CSSFlexDirectionColumnReverse = */ CSSPositionBottom, + /* CSSFlexDirectionRow = */ CSSPositionLeft, + /* CSSFlexDirectionRowReverse = */ CSSPositionRight }; -static css_dimension_t dim[4] = { - /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_HEIGHT, - /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_HEIGHT, - /* CSS_FLEX_DIRECTION_ROW = */ CSS_WIDTH, - /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_WIDTH +static CSSDimension dim[4] = { + /* CSSFlexDirectionColumn = */ CSSDimensionHeight, + /* CSSFlexDirectionColumnReverse = */ CSSDimensionHeight, + /* CSSFlexDirectionRow = */ CSSDimensionWidth, + /* CSSFlexDirectionRowReverse = */ CSSDimensionWidth }; -static bool isRowDirection(css_flex_direction_t flex_direction) { - return flex_direction == CSS_FLEX_DIRECTION_ROW || - flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE; +static bool isRowDirection(CSSFlexDirection flexDirection) { + return flexDirection == CSSFlexDirectionRow || + flexDirection == CSSFlexDirectionRowReverse; } -static bool isColumnDirection(css_flex_direction_t flex_direction) { - return flex_direction == CSS_FLEX_DIRECTION_COLUMN || - flex_direction == CSS_FLEX_DIRECTION_COLUMN_REVERSE; +static bool isColumnDirection(CSSFlexDirection flexDirection) { + return flexDirection == CSSFlexDirectionColumn || + flexDirection == CSSFlexDirectionColumnReverse; } -static bool isFlexBasisAuto(css_node_t* node) { +static bool isFlexBasisAuto(CSSNode* node) { #if POSITIVE_FLEX_IS_AUTO // All flex values are auto. (void) node; @@ -314,7 +314,7 @@ static bool isFlexBasisAuto(css_node_t* node) { #endif } -static float getFlexGrowFactor(css_node_t* node) { +static float getFlexGrowFactor(CSSNode* node) { // Flex grow is implied by positive values for flex. if (node->style.flex > 0) { return node->style.flex; @@ -322,7 +322,7 @@ static float getFlexGrowFactor(css_node_t* node) { return 0; } -static float getFlexShrinkFactor(css_node_t* node) { +static float getFlexShrinkFactor(CSSNode* node) { #if POSITIVE_FLEX_IS_AUTO // A flex shrink factor of 1 is implied by non-zero values for flex. if (node->style.flex != 0) { @@ -337,27 +337,27 @@ static float getFlexShrinkFactor(css_node_t* node) { return 0; } -static float getLeadingMargin(css_node_t* node, css_flex_direction_t axis) { - if (isRowDirection(axis) && !isUndefined(node->style.margin[CSS_START])) { - return node->style.margin[CSS_START]; +static float getLeadingMargin(CSSNode* node, CSSFlexDirection axis) { + if (isRowDirection(axis) && !isUndefined(node->style.margin[CSSPositionStart])) { + return node->style.margin[CSSPositionStart]; } return node->style.margin[leading[axis]]; } -static float getTrailingMargin(css_node_t* node, css_flex_direction_t axis) { - if (isRowDirection(axis) && !isUndefined(node->style.margin[CSS_END])) { - return node->style.margin[CSS_END]; +static float getTrailingMargin(CSSNode* node, CSSFlexDirection axis) { + if (isRowDirection(axis) && !isUndefined(node->style.margin[CSSPositionEnd])) { + return node->style.margin[CSSPositionEnd]; } return node->style.margin[trailing[axis]]; } -static float getLeadingPadding(css_node_t* node, css_flex_direction_t axis) { +static float getLeadingPadding(CSSNode* node, CSSFlexDirection axis) { if (isRowDirection(axis) && - !isUndefined(node->style.padding[CSS_START]) && - node->style.padding[CSS_START] >= 0) { - return node->style.padding[CSS_START]; + !isUndefined(node->style.padding[CSSPositionStart]) && + node->style.padding[CSSPositionStart] >= 0) { + return node->style.padding[CSSPositionStart]; } if (node->style.padding[leading[axis]] >= 0) { @@ -367,11 +367,11 @@ static float getLeadingPadding(css_node_t* node, css_flex_direction_t axis) { return 0; } -static float getTrailingPadding(css_node_t* node, css_flex_direction_t axis) { +static float getTrailingPadding(CSSNode* node, CSSFlexDirection axis) { if (isRowDirection(axis) && - !isUndefined(node->style.padding[CSS_END]) && - node->style.padding[CSS_END] >= 0) { - return node->style.padding[CSS_END]; + !isUndefined(node->style.padding[CSSPositionEnd]) && + node->style.padding[CSSPositionEnd] >= 0) { + return node->style.padding[CSSPositionEnd]; } if (node->style.padding[trailing[axis]] >= 0) { @@ -381,11 +381,11 @@ static float getTrailingPadding(css_node_t* node, css_flex_direction_t axis) { return 0; } -static float getLeadingBorder(css_node_t* node, css_flex_direction_t axis) { +static float getLeadingBorder(CSSNode* node, CSSFlexDirection axis) { if (isRowDirection(axis) && - !isUndefined(node->style.border[CSS_START]) && - node->style.border[CSS_START] >= 0) { - return node->style.border[CSS_START]; + !isUndefined(node->style.border[CSSPositionStart]) && + node->style.border[CSSPositionStart] >= 0) { + return node->style.border[CSSPositionStart]; } if (node->style.border[leading[axis]] >= 0) { @@ -395,11 +395,11 @@ static float getLeadingBorder(css_node_t* node, css_flex_direction_t axis) { return 0; } -static float getTrailingBorder(css_node_t* node, css_flex_direction_t axis) { +static float getTrailingBorder(CSSNode* node, CSSFlexDirection axis) { if (isRowDirection(axis) && - !isUndefined(node->style.border[CSS_END]) && - node->style.border[CSS_END] >= 0) { - return node->style.border[CSS_END]; + !isUndefined(node->style.border[CSSPositionEnd]) && + node->style.border[CSSPositionEnd] >= 0) { + return node->style.border[CSSPositionEnd]; } if (node->style.border[trailing[axis]] >= 0) { @@ -409,103 +409,103 @@ static float getTrailingBorder(css_node_t* node, css_flex_direction_t axis) { return 0; } -static float getLeadingPaddingAndBorder(css_node_t* node, css_flex_direction_t axis) { +static float getLeadingPaddingAndBorder(CSSNode* node, CSSFlexDirection axis) { return getLeadingPadding(node, axis) + getLeadingBorder(node, axis); } -static float getTrailingPaddingAndBorder(css_node_t* node, css_flex_direction_t axis) { +static float getTrailingPaddingAndBorder(CSSNode* node, CSSFlexDirection axis) { return getTrailingPadding(node, axis) + getTrailingBorder(node, axis); } -static float getMarginAxis(css_node_t* node, css_flex_direction_t axis) { +static float getMarginAxis(CSSNode* node, CSSFlexDirection axis) { return getLeadingMargin(node, axis) + getTrailingMargin(node, axis); } -static float getPaddingAndBorderAxis(css_node_t* node, css_flex_direction_t axis) { +static float getPaddingAndBorderAxis(CSSNode* node, CSSFlexDirection axis) { return getLeadingPaddingAndBorder(node, axis) + getTrailingPaddingAndBorder(node, axis); } -static css_align_t getAlignItem(css_node_t* node, css_node_t* child) { - if (child->style.align_self != CSS_ALIGN_AUTO) { - return child->style.align_self; +static CSSAlign getAlignItem(CSSNode* node, CSSNode* child) { + if (child->style.alignSelf != CSSAlignAuto) { + return child->style.alignSelf; } - return node->style.align_items; + return node->style.alignItems; } -static css_direction_t resolveDirection(css_node_t* node, css_direction_t parentDirection) { - css_direction_t direction = node->style.direction; +static CSSDirection resolveDirection(CSSNode* node, CSSDirection parentDirection) { + CSSDirection direction = node->style.direction; - if (direction == CSS_DIRECTION_INHERIT) { - direction = parentDirection > CSS_DIRECTION_INHERIT ? parentDirection : CSS_DIRECTION_LTR; + if (direction == CSSDirectionInherit) { + direction = parentDirection > CSSDirectionInherit ? parentDirection : CSSDirectionLTR; } return direction; } -static css_flex_direction_t getFlexDirection(css_node_t* node) { - return node->style.flex_direction; +static CSSFlexDirection getFlexDirection(CSSNode* node) { + return node->style.flexDirection; } -static css_flex_direction_t resolveAxis(css_flex_direction_t flex_direction, css_direction_t direction) { - if (direction == CSS_DIRECTION_RTL) { - if (flex_direction == CSS_FLEX_DIRECTION_ROW) { - return CSS_FLEX_DIRECTION_ROW_REVERSE; - } else if (flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE) { - return CSS_FLEX_DIRECTION_ROW; +static CSSFlexDirection resolveAxis(CSSFlexDirection flexDirection, CSSDirection direction) { + if (direction == CSSDirectionRTL) { + if (flexDirection == CSSFlexDirectionRow) { + return CSSFlexDirectionRowReverse; + } else if (flexDirection == CSSFlexDirectionRowReverse) { + return CSSFlexDirectionRow; } } - return flex_direction; + return flexDirection; } -static css_flex_direction_t getCrossFlexDirection(css_flex_direction_t flex_direction, css_direction_t direction) { - if (isColumnDirection(flex_direction)) { - return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction); +static CSSFlexDirection getCrossFlexDirection(CSSFlexDirection flexDirection, CSSDirection direction) { + if (isColumnDirection(flexDirection)) { + return resolveAxis(CSSFlexDirectionRow, direction); } else { - return CSS_FLEX_DIRECTION_COLUMN; + return CSSFlexDirectionColumn; } } -static float getFlex(css_node_t* node) { +static float getFlex(CSSNode* node) { return node->style.flex; } -static bool isFlex(css_node_t* node) { +static bool isFlex(CSSNode* node) { return ( - node->style.position_type == CSS_POSITION_RELATIVE && + node->style.positionType == CSSPositionTypeRelative && getFlex(node) != 0 ); } -static bool isFlexWrap(css_node_t* node) { - return node->style.flex_wrap == CSS_WRAP; +static bool isFlexWrap(CSSNode* node) { + return node->style.flexWrap == CSSWrapTypeWrap; } -static float getDimWithMargin(css_node_t* node, css_flex_direction_t axis) { - return node->layout.measured_dimensions[dim[axis]] + +static float getDimWithMargin(CSSNode* node, CSSFlexDirection axis) { + return node->layout.measuredDimensions[dim[axis]] + getLeadingMargin(node, axis) + getTrailingMargin(node, axis); } -static bool isStyleDimDefined(css_node_t* node, css_flex_direction_t axis) { +static bool isStyleDimDefined(CSSNode* node, CSSFlexDirection axis) { float value = node->style.dimensions[dim[axis]]; return !isUndefined(value) && value >= 0.0; } -static bool isLayoutDimDefined(css_node_t* node, css_flex_direction_t axis) { - float value = node->layout.measured_dimensions[dim[axis]]; +static bool isLayoutDimDefined(CSSNode* node, CSSFlexDirection axis) { + float value = node->layout.measuredDimensions[dim[axis]]; return !isUndefined(value) && value >= 0.0; } -static bool isPosDefined(css_node_t* node, css_position_t position) { +static bool isPosDefined(CSSNode* node, CSSPosition position) { return !isUndefined(node->style.position[position]); } -static bool isMeasureDefined(css_node_t* node) { +static bool isMeasureDefined(CSSNode* node) { return node->measure; } -static float getPosition(css_node_t* node, css_position_t position) { +static float getPosition(CSSNode* node, CSSPosition position) { float result = node->style.position[position]; if (!isUndefined(result)) { return result; @@ -513,16 +513,16 @@ static float getPosition(css_node_t* node, css_position_t position) { return 0; } -static float boundAxisWithinMinAndMax(css_node_t* node, css_flex_direction_t axis, float value) { - float min = CSS_UNDEFINED; - float max = CSS_UNDEFINED; +static float boundAxisWithinMinAndMax(CSSNode* node, CSSFlexDirection axis, float value) { + float min = CSSUndefined; + float max = CSSUndefined; if (isColumnDirection(axis)) { - min = node->style.minDimensions[CSS_HEIGHT]; - max = node->style.maxDimensions[CSS_HEIGHT]; + min = node->style.minDimensions[CSSDimensionHeight]; + max = node->style.maxDimensions[CSSDimensionHeight]; } else if (isRowDirection(axis)) { - min = node->style.minDimensions[CSS_WIDTH]; - max = node->style.maxDimensions[CSS_WIDTH]; + min = node->style.minDimensions[CSSDimensionWidth]; + max = node->style.maxDimensions[CSSDimensionWidth]; } float boundValue = value; @@ -539,20 +539,20 @@ static float boundAxisWithinMinAndMax(css_node_t* node, css_flex_direction_t axi // Like boundAxisWithinMinAndMax but also ensures that the value doesn't go below the // padding and border amount. -static float boundAxis(css_node_t* node, css_flex_direction_t axis, float value) { +static float boundAxis(CSSNode* node, CSSFlexDirection axis, float value) { return fmaxf(boundAxisWithinMinAndMax(node, axis, value), getPaddingAndBorderAxis(node, axis)); } -static void setTrailingPosition(css_node_t* node, css_node_t* child, css_flex_direction_t axis) { - float size = child->style.position_type == CSS_POSITION_ABSOLUTE ? +static void setTrailingPosition(CSSNode* node, CSSNode* child, CSSFlexDirection axis) { + float size = child->style.positionType == CSSPositionTypeAbsolute ? 0 : - child->layout.measured_dimensions[dim[axis]]; - child->layout.position[trailing[axis]] = node->layout.measured_dimensions[dim[axis]] - size - child->layout.position[pos[axis]]; + child->layout.measuredDimensions[dim[axis]]; + child->layout.position[trailing[axis]] = node->layout.measuredDimensions[dim[axis]] - size - child->layout.position[pos[axis]]; } // If both left and right are defined, then use left. Otherwise return // +left or -right depending on which is defined. -static float getRelativePosition(css_node_t* node, css_flex_direction_t axis) { +static float getRelativePosition(CSSNode* node, CSSFlexDirection axis) { float lead = node->style.position[leading[axis]]; if (!isUndefined(lead)) { return lead; @@ -560,9 +560,9 @@ static float getRelativePosition(css_node_t* node, css_flex_direction_t axis) { return -getPosition(node, trailing[axis]); } -static void setPosition(css_node_t* node, css_direction_t direction) { - css_flex_direction_t mainAxis = resolveAxis(getFlexDirection(node), direction); - css_flex_direction_t crossAxis = getCrossFlexDirection(mainAxis, direction); +static void setPosition(CSSNode* node, CSSDirection direction) { + CSSFlexDirection mainAxis = resolveAxis(getFlexDirection(node), direction); + CSSFlexDirection crossAxis = getCrossFlexDirection(mainAxis, direction); node->layout.position[leading[mainAxis]] = getLeadingMargin(node, mainAxis) + getRelativePosition(node, mainAxis); @@ -620,7 +620,7 @@ static void setPosition(css_node_t* node, css_direction_t direction) { // Input parameters: // - node: current node to be sized and layed out // - availableWidth & availableHeight: available size to be used for sizing the node -// or CSS_UNDEFINED if the size is not available; interpretation depends on layout +// or CSSUndefined if the size is not available; interpretation depends on layout // flags // - parentDirection: the inline (text) direction within the parent (left-to-right or // right-to-left) @@ -633,35 +633,35 @@ static void setPosition(css_node_t* node, css_direction_t direction) { // Details: // This routine is called recursively to lay out subtrees of flexbox elements. It uses the // information in node.style, which is treated as a read-only input. It is responsible for -// setting the layout.direction and layout.measured_dimensions fields for the input node as well -// as the layout.position and layout.line_index fields for its child nodes. The -// layout.measured_dimensions field includes any border or padding for the node but does +// setting the layout.direction and layout.measuredDimensions fields for the input node as well +// as the layout.position and layout.lineIndex fields for its child nodes. The +// layout.measuredDimensions field includes any border or padding for the node but does // not include margins. // // The spec describes four different layout modes: "fill available", "max content", "min content", // and "fit content". Of these, we don't use "min content" because we don't support default // minimum main sizes (see above for details). Each of our measure modes maps to a layout mode // from the spec (https://www.w3.org/TR/css3-sizing/#terms): -// - CSS_MEASURE_MODE_UNDEFINED: max content -// - CSS_MEASURE_MODE_EXACTLY: fill available -// - CSS_MEASURE_MODE_AT_MOST: fit content +// - CSSMeasureModeUndefined: max content +// - CSSMeasureModeExactly: fill available +// - CSSMeasureModeAtMost: fit content // // When calling layoutNodeImpl and layoutNodeInternal, if the caller passes an available size of -// undefined then it must also pass a measure mode of CSS_MEASURE_MODE_UNDEFINED in that dimension. +// undefined then it must also pass a measure mode of CSSMeasureModeUndefined in that dimension. // -static void layoutNodeImpl(css_node_t* node, float availableWidth, float availableHeight, - css_direction_t parentDirection, css_measure_mode_t widthMeasureMode, css_measure_mode_t heightMeasureMode, bool performLayout) { +static void layoutNodeImpl(CSSNode* node, float availableWidth, float availableHeight, + CSSDirection parentDirection, CSSMeasureMode widthMeasureMode, CSSMeasureMode heightMeasureMode, bool performLayout) { - assert(isUndefined(availableWidth) ? widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED : true); // availableWidth is indefinite so widthMeasureMode must be CSS_MEASURE_MODE_UNDEFINED - assert(isUndefined(availableHeight) ? heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED : true); // availableHeight is indefinite so heightMeasureMode must be CSS_MEASURE_MODE_UNDEFINED + assert(isUndefined(availableWidth) ? widthMeasureMode == CSSMeasureModeUndefined : true); // availableWidth is indefinite so widthMeasureMode must be CSSMeasureModeUndefined + assert(isUndefined(availableHeight) ? heightMeasureMode == CSSMeasureModeUndefined : true); // availableHeight is indefinite so heightMeasureMode must be CSSMeasureModeUndefined - float paddingAndBorderAxisRow = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW); - float paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN); - float marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW); - float marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN); + float paddingAndBorderAxisRow = getPaddingAndBorderAxis(node, CSSFlexDirectionRow); + float paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSSFlexDirectionColumn); + float marginAxisRow = getMarginAxis(node, CSSFlexDirectionRow); + float marginAxisColumn = getMarginAxis(node, CSSFlexDirectionColumn); // Set the resolved resolution in the node's layout. - css_direction_t direction = resolveDirection(node, parentDirection); + CSSDirection direction = resolveDirection(node, parentDirection); node->layout.direction = direction; // For content (text) nodes, determine the dimensions based on the text contents. @@ -669,20 +669,20 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab float innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow; float innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn; - if (widthMeasureMode == CSS_MEASURE_MODE_EXACTLY && heightMeasureMode == CSS_MEASURE_MODE_EXACTLY) { + if (widthMeasureMode == CSSMeasureModeExactly && heightMeasureMode == CSSMeasureModeExactly) { // Don't bother sizing the text if both dimensions are already defined. - node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow); - node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn); + node->layout.measuredDimensions[CSSDimensionWidth] = boundAxis(node, CSSFlexDirectionRow, availableWidth - marginAxisRow); + node->layout.measuredDimensions[CSSDimensionHeight] = boundAxis(node, CSSFlexDirectionColumn, availableHeight - marginAxisColumn); } else if (innerWidth <= 0 || innerHeight <= 0) { // Don't bother sizing the text if there's no horizontal or vertical space. - node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0); - node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0); + node->layout.measuredDimensions[CSSDimensionWidth] = boundAxis(node, CSSFlexDirectionRow, 0); + node->layout.measuredDimensions[CSSDimensionHeight] = boundAxis(node, CSSFlexDirectionColumn, 0); } else { // Measure the text under the current constraints. - css_dim_t measureDim = node->measure( + CSSMeasureResult measureDim = node->measure( node->context, innerWidth, @@ -691,13 +691,13 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab heightMeasureMode ); - node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, - (widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED || widthMeasureMode == CSS_MEASURE_MODE_AT_MOST) ? - measureDim.dimensions[CSS_WIDTH] + paddingAndBorderAxisRow : + node->layout.measuredDimensions[CSSDimensionWidth] = boundAxis(node, CSSFlexDirectionRow, + (widthMeasureMode == CSSMeasureModeUndefined || widthMeasureMode == CSSMeasureModeAtMost) ? + measureDim.dimensions[CSSDimensionWidth] + paddingAndBorderAxisRow : availableWidth - marginAxisRow); - node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, - (heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED || heightMeasureMode == CSS_MEASURE_MODE_AT_MOST) ? - measureDim.dimensions[CSS_HEIGHT] + paddingAndBorderAxisColumn : + node->layout.measuredDimensions[CSSDimensionHeight] = boundAxis(node, CSSFlexDirectionColumn, + (heightMeasureMode == CSSMeasureModeUndefined || heightMeasureMode == CSSMeasureModeAtMost) ? + measureDim.dimensions[CSSDimensionHeight] + paddingAndBorderAxisColumn : availableHeight - marginAxisColumn); } @@ -706,14 +706,14 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab // For nodes with no children, use the available values if they were provided, or // the minimum size as indicated by the padding and border sizes. - int childCount = node->children_count; + int childCount = node->childCount; if (childCount == 0) { - node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, - (widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED || widthMeasureMode == CSS_MEASURE_MODE_AT_MOST) ? + node->layout.measuredDimensions[CSSDimensionWidth] = boundAxis(node, CSSFlexDirectionRow, + (widthMeasureMode == CSSMeasureModeUndefined || widthMeasureMode == CSSMeasureModeAtMost) ? paddingAndBorderAxisRow : availableWidth - marginAxisRow); - node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, - (heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED || heightMeasureMode == CSS_MEASURE_MODE_AT_MOST) ? + node->layout.measuredDimensions[CSSDimensionHeight] = boundAxis(node, CSSFlexDirectionColumn, + (heightMeasureMode == CSSMeasureModeUndefined || heightMeasureMode == CSSMeasureModeAtMost) ? paddingAndBorderAxisColumn : availableHeight - marginAxisColumn); return; @@ -724,42 +724,42 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab if (!performLayout) { // If we're being asked to size the content with an at most constraint but there is no available width, // the measurement will always be zero. - if (widthMeasureMode == CSS_MEASURE_MODE_AT_MOST && availableWidth <= 0 && - heightMeasureMode == CSS_MEASURE_MODE_AT_MOST && availableHeight <= 0) { - node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0); - node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0); + if (widthMeasureMode == CSSMeasureModeAtMost && availableWidth <= 0 && + heightMeasureMode == CSSMeasureModeAtMost && availableHeight <= 0) { + node->layout.measuredDimensions[CSSDimensionWidth] = boundAxis(node, CSSFlexDirectionRow, 0); + node->layout.measuredDimensions[CSSDimensionHeight] = boundAxis(node, CSSFlexDirectionColumn, 0); return; } - if (widthMeasureMode == CSS_MEASURE_MODE_AT_MOST && availableWidth <= 0) { - node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0); - node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, isUndefined(availableHeight) ? 0 : (availableHeight - marginAxisColumn)); + if (widthMeasureMode == CSSMeasureModeAtMost && availableWidth <= 0) { + node->layout.measuredDimensions[CSSDimensionWidth] = boundAxis(node, CSSFlexDirectionRow, 0); + node->layout.measuredDimensions[CSSDimensionHeight] = boundAxis(node, CSSFlexDirectionColumn, isUndefined(availableHeight) ? 0 : (availableHeight - marginAxisColumn)); return; } - if (heightMeasureMode == CSS_MEASURE_MODE_AT_MOST && availableHeight <= 0) { - node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, isUndefined(availableWidth) ? 0 : (availableWidth - marginAxisRow)); - node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0); + if (heightMeasureMode == CSSMeasureModeAtMost && availableHeight <= 0) { + node->layout.measuredDimensions[CSSDimensionWidth] = boundAxis(node, CSSFlexDirectionRow, isUndefined(availableWidth) ? 0 : (availableWidth - marginAxisRow)); + node->layout.measuredDimensions[CSSDimensionHeight] = boundAxis(node, CSSFlexDirectionColumn, 0); return; } // If we're being asked to use an exact width/height, there's no need to measure the children. - if (widthMeasureMode == CSS_MEASURE_MODE_EXACTLY && heightMeasureMode == CSS_MEASURE_MODE_EXACTLY) { - node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow); - node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn); + if (widthMeasureMode == CSSMeasureModeExactly && heightMeasureMode == CSSMeasureModeExactly) { + node->layout.measuredDimensions[CSSDimensionWidth] = boundAxis(node, CSSFlexDirectionRow, availableWidth - marginAxisRow); + node->layout.measuredDimensions[CSSDimensionHeight] = boundAxis(node, CSSFlexDirectionColumn, availableHeight - marginAxisColumn); return; } } // STEP 1: CALCULATE VALUES FOR REMAINDER OF ALGORITHM - css_flex_direction_t mainAxis = resolveAxis(getFlexDirection(node), direction); - css_flex_direction_t crossAxis = getCrossFlexDirection(mainAxis, direction); + CSSFlexDirection mainAxis = resolveAxis(getFlexDirection(node), direction); + CSSFlexDirection crossAxis = getCrossFlexDirection(mainAxis, direction); bool isMainAxisRow = isRowDirection(mainAxis); - css_justify_t justifyContent = node->style.justify_content; + CSSJustify justifyContent = node->style.justifyContent; bool isNodeFlexWrap = isFlexWrap(node); - css_node_t* firstAbsoluteChild = NULL; - css_node_t* currentAbsoluteChild = NULL; + CSSNode* firstAbsoluteChild = NULL; + CSSNode* currentAbsoluteChild = NULL; float leadingPaddingAndBorderMain = getLeadingPaddingAndBorder(node, mainAxis); float trailingPaddingAndBorderMain = getTrailingPaddingAndBorder(node, mainAxis); @@ -767,8 +767,8 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab float paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis); float paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis); - css_measure_mode_t measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode; - css_measure_mode_t measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode; + CSSMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode; + CSSMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode; // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS float availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow; @@ -777,24 +777,24 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth; // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM - css_node_t* child; + CSSNode* child; int i; float childWidth; float childHeight; - css_measure_mode_t childWidthMeasureMode; - css_measure_mode_t childHeightMeasureMode; + CSSMeasureMode childWidthMeasureMode; + CSSMeasureMode childHeightMeasureMode; for (i = 0; i < childCount; i++) { - child = node->get_child(node->context, i); + child = node->getChild(node->context, i); if (performLayout) { // Set the initial position (relative to the parent). - css_direction_t childDirection = resolveDirection(child, direction); + CSSDirection childDirection = resolveDirection(child, direction); setPosition(child, childDirection); } // Absolute-positioned children don't participate in flex layout. Add them // to a list that we can process later. - if (child->style.position_type == CSS_POSITION_ABSOLUTE) { + if (child->style.positionType == CSSPositionTypeAbsolute) { // Store a private linked list of absolutely positioned children // so that we can efficiently traverse them later. @@ -802,39 +802,39 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab firstAbsoluteChild = child; } if (currentAbsoluteChild != NULL) { - currentAbsoluteChild->next_child = child; + currentAbsoluteChild->nextChild = child; } currentAbsoluteChild = child; - child->next_child = NULL; + child->nextChild = NULL; } else { - if (isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) { + if (isMainAxisRow && isStyleDimDefined(child, CSSFlexDirectionRow)) { // The width is definite, so use that as the flex basis. - child->layout.flex_basis = fmaxf(child->style.dimensions[CSS_WIDTH], getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_ROW)); - } else if (!isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN)) { + child->layout.flexBasis = fmaxf(child->style.dimensions[CSSDimensionWidth], getPaddingAndBorderAxis(child, CSSFlexDirectionRow)); + } else if (!isMainAxisRow && isStyleDimDefined(child, CSSFlexDirectionColumn)) { // The height is definite, so use that as the flex basis. - child->layout.flex_basis = fmaxf(child->style.dimensions[CSS_HEIGHT], getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_COLUMN)); + child->layout.flexBasis = fmaxf(child->style.dimensions[CSSDimensionHeight], getPaddingAndBorderAxis(child, CSSFlexDirectionColumn)); } else if (!isFlexBasisAuto(child) && !isUndefined(availableInnerMainDim)) { // If the basis isn't 'auto', it is assumed to be zero. - child->layout.flex_basis = fmaxf(0, getPaddingAndBorderAxis(child, mainAxis)); + child->layout.flexBasis = fmaxf(0, getPaddingAndBorderAxis(child, mainAxis)); } else { // Compute the flex basis and hypothetical main size (i.e. the clamped flex basis). - childWidth = CSS_UNDEFINED; - childHeight = CSS_UNDEFINED; - childWidthMeasureMode = CSS_MEASURE_MODE_UNDEFINED; - childHeightMeasureMode = CSS_MEASURE_MODE_UNDEFINED; - - if (isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) { - childWidth = child->style.dimensions[CSS_WIDTH] + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW); - childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY; + childWidth = CSSUndefined; + childHeight = CSSUndefined; + childWidthMeasureMode = CSSMeasureModeUndefined; + childHeightMeasureMode = CSSMeasureModeUndefined; + + if (isStyleDimDefined(child, CSSFlexDirectionRow)) { + childWidth = child->style.dimensions[CSSDimensionWidth] + getMarginAxis(child, CSSFlexDirectionRow); + childWidthMeasureMode = CSSMeasureModeExactly; } - if (isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN)) { - childHeight = child->style.dimensions[CSS_HEIGHT] + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN); - childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY; + if (isStyleDimDefined(child, CSSFlexDirectionColumn)) { + childHeight = child->style.dimensions[CSSDimensionHeight] + getMarginAxis(child, CSSFlexDirectionColumn); + childHeightMeasureMode = CSSMeasureModeExactly; } // According to the spec, if the main size is not definite and the @@ -843,15 +843,15 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab // the main size. Otherwise use "AT_MOST" in the cross axis. if (!isMainAxisRow && isUndefined(childWidth) && !isUndefined(availableInnerWidth)) { childWidth = availableInnerWidth; - childWidthMeasureMode = CSS_MEASURE_MODE_AT_MOST; + childWidthMeasureMode = CSSMeasureModeAtMost; } // The W3C spec doesn't say anything about the 'overflow' property, // but all major browsers appear to implement the following logic. - if (node->style.overflow == CSS_OVERFLOW_HIDDEN) { + if (node->style.overflow == CSSOverflowHidden) { if (isMainAxisRow && isUndefined(childHeight) && !isUndefined(availableInnerHeight)) { childHeight = availableInnerHeight; - childHeightMeasureMode = CSS_MEASURE_MODE_AT_MOST; + childHeightMeasureMode = CSSMeasureModeAtMost; } } @@ -859,25 +859,25 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab // axis to be measured exactly with the available inner width if (!isMainAxisRow && !isUndefined(availableInnerWidth) && - !isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW) && - widthMeasureMode == CSS_MEASURE_MODE_EXACTLY && - getAlignItem(node, child) == CSS_ALIGN_STRETCH) { + !isStyleDimDefined(child, CSSFlexDirectionRow) && + widthMeasureMode == CSSMeasureModeExactly && + getAlignItem(node, child) == CSSAlignStretch) { childWidth = availableInnerWidth; - childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY; + childWidthMeasureMode = CSSMeasureModeExactly; } if (isMainAxisRow && !isUndefined(availableInnerHeight) && - !isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN) && - heightMeasureMode == CSS_MEASURE_MODE_EXACTLY && - getAlignItem(node, child) == CSS_ALIGN_STRETCH) { + !isStyleDimDefined(child, CSSFlexDirectionColumn) && + heightMeasureMode == CSSMeasureModeExactly && + getAlignItem(node, child) == CSSAlignStretch) { childHeight = availableInnerHeight; - childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY; + childHeightMeasureMode = CSSMeasureModeExactly; } // Measure the child layoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "measure"); - child->layout.flex_basis = fmaxf(isMainAxisRow ? child->layout.measured_dimensions[CSS_WIDTH] : child->layout.measured_dimensions[CSS_HEIGHT], getPaddingAndBorderAxis(child, mainAxis)); + child->layout.flexBasis = fmaxf(isMainAxisRow ? child->layout.measuredDimensions[CSSDimensionWidth] : child->layout.measuredDimensions[CSSDimensionHeight], getPaddingAndBorderAxis(child, mainAxis)); } } } @@ -915,16 +915,16 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab i = startOfLineIndex; // Maintain a linked list of the child nodes that can shrink and/or grow. - css_node_t* firstRelativeChild = NULL; - css_node_t* currentRelativeChild = NULL; + CSSNode* firstRelativeChild = NULL; + CSSNode* currentRelativeChild = NULL; // Add items to the current line until it's full or we run out of items. while (i < childCount) { - child = node->get_child(node->context, i); - child->line_index = lineCount; + child = node->getChild(node->context, i); + child->lineIndex = lineCount; - if (child->style.position_type != CSS_POSITION_ABSOLUTE) { - float outerFlexBasis = child->layout.flex_basis + getMarginAxis(child, mainAxis); + if (child->style.positionType != CSSPositionTypeAbsolute) { + float outerFlexBasis = child->layout.flexBasis + getMarginAxis(child, mainAxis); // If this is a multi-line flow and this item pushes us over the available size, we've // hit the end of the current line. Break out of the loop and lay out the current line. @@ -940,7 +940,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab // Unlike the grow factor, the shrink factor is scaled relative to the child // dimension. - totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child->layout.flex_basis; + totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child->layout.flexBasis; } // Store a private linked list of children that need to be layed out. @@ -948,10 +948,10 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab firstRelativeChild = child; } if (currentRelativeChild != NULL) { - currentRelativeChild->next_child = child; + currentRelativeChild->nextChild = child; } currentRelativeChild = child; - child->next_child = NULL; + child->nextChild = NULL; } i++; @@ -959,7 +959,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab } // If we don't need to measure the cross axis, we can skip the entire flex step. - bool canSkipFlex = !performLayout && measureModeCrossDim == CSS_MEASURE_MODE_EXACTLY; + bool canSkipFlex = !performLayout && measureModeCrossDim == CSSMeasureModeExactly; // In order to position the elements in the main axis, we have two // controls. The space between the beginning and the first element @@ -1009,7 +1009,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab float deltaFlexGrowFactors = 0; currentRelativeChild = firstRelativeChild; while (currentRelativeChild != NULL) { - childFlexBasis = currentRelativeChild->layout.flex_basis; + childFlexBasis = currentRelativeChild->layout.flexBasis; if (remainingFreeSpace < 0) { flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis; @@ -1045,7 +1045,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab } } - currentRelativeChild = currentRelativeChild->next_child; + currentRelativeChild = currentRelativeChild->nextChild; } totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors; @@ -1056,7 +1056,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab deltaFreeSpace = 0; currentRelativeChild = firstRelativeChild; while (currentRelativeChild != NULL) { - childFlexBasis = currentRelativeChild->layout.flex_basis; + childFlexBasis = currentRelativeChild->layout.flexBasis; float updatedMainSize = childFlexBasis; if (remainingFreeSpace < 0) { @@ -1080,48 +1080,48 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab deltaFreeSpace -= updatedMainSize - childFlexBasis; if (isMainAxisRow) { - childWidth = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_ROW); - childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY; + childWidth = updatedMainSize + getMarginAxis(currentRelativeChild, CSSFlexDirectionRow); + childWidthMeasureMode = CSSMeasureModeExactly; if (!isUndefined(availableInnerCrossDim) && - !isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN) && - heightMeasureMode == CSS_MEASURE_MODE_EXACTLY && - getAlignItem(node, currentRelativeChild) == CSS_ALIGN_STRETCH) { + !isStyleDimDefined(currentRelativeChild, CSSFlexDirectionColumn) && + heightMeasureMode == CSSMeasureModeExactly && + getAlignItem(node, currentRelativeChild) == CSSAlignStretch) { childHeight = availableInnerCrossDim; - childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY; - } else if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN)) { + childHeightMeasureMode = CSSMeasureModeExactly; + } else if (!isStyleDimDefined(currentRelativeChild, CSSFlexDirectionColumn)) { childHeight = availableInnerCrossDim; - childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST; + childHeightMeasureMode = isUndefined(childHeight) ? CSSMeasureModeUndefined : CSSMeasureModeAtMost; } else { - childHeight = currentRelativeChild->style.dimensions[CSS_HEIGHT] + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN); - childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY; + childHeight = currentRelativeChild->style.dimensions[CSSDimensionHeight] + getMarginAxis(currentRelativeChild, CSSFlexDirectionColumn); + childHeightMeasureMode = CSSMeasureModeExactly; } } else { - childHeight = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN); - childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY; + childHeight = updatedMainSize + getMarginAxis(currentRelativeChild, CSSFlexDirectionColumn); + childHeightMeasureMode = CSSMeasureModeExactly; if (!isUndefined(availableInnerCrossDim) && - !isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_ROW) && - widthMeasureMode == CSS_MEASURE_MODE_EXACTLY && - getAlignItem(node, currentRelativeChild) == CSS_ALIGN_STRETCH) { + !isStyleDimDefined(currentRelativeChild, CSSFlexDirectionRow) && + widthMeasureMode == CSSMeasureModeExactly && + getAlignItem(node, currentRelativeChild) == CSSAlignStretch) { childWidth = availableInnerCrossDim; - childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY; - } else if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_ROW)) { + childWidthMeasureMode = CSSMeasureModeExactly; + } else if (!isStyleDimDefined(currentRelativeChild, CSSFlexDirectionRow)) { childWidth = availableInnerCrossDim; - childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST; + childWidthMeasureMode = isUndefined(childWidth) ? CSSMeasureModeUndefined : CSSMeasureModeAtMost; } else { - childWidth = currentRelativeChild->style.dimensions[CSS_WIDTH] + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_ROW); - childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY; + childWidth = currentRelativeChild->style.dimensions[CSSDimensionWidth] + getMarginAxis(currentRelativeChild, CSSFlexDirectionRow); + childWidthMeasureMode = CSSMeasureModeExactly; } } bool requiresStretchLayout = !isStyleDimDefined(currentRelativeChild, crossAxis) && - getAlignItem(node, currentRelativeChild) == CSS_ALIGN_STRETCH; + getAlignItem(node, currentRelativeChild) == CSSAlignStretch; // Recursively call the layout algorithm for this child with the updated main size. layoutNodeInternal(currentRelativeChild, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, performLayout && !requiresStretchLayout, "flex"); - currentRelativeChild = currentRelativeChild->next_child; + currentRelativeChild = currentRelativeChild->nextChild; } } @@ -1136,25 +1136,25 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab // If we are using "at most" rules in the main axis, we won't distribute // any remaining space at this point. - if (measureModeMainDim == CSS_MEASURE_MODE_AT_MOST) { + if (measureModeMainDim == CSSMeasureModeAtMost) { remainingFreeSpace = 0; } // Use justifyContent to figure out how to allocate the remaining space // available in the main axis. - if (justifyContent != CSS_JUSTIFY_FLEX_START) { - if (justifyContent == CSS_JUSTIFY_CENTER) { + if (justifyContent != CSSJustifyFlexStart) { + if (justifyContent == CSSJustifyCenter) { leadingMainDim = remainingFreeSpace / 2; - } else if (justifyContent == CSS_JUSTIFY_FLEX_END) { + } else if (justifyContent == CSSJustifyFlexEnd) { leadingMainDim = remainingFreeSpace; - } else if (justifyContent == CSS_JUSTIFY_SPACE_BETWEEN) { + } else if (justifyContent == CSSJustifySpaceBetween) { remainingFreeSpace = fmaxf(remainingFreeSpace, 0); if (itemsOnLine > 1) { betweenMainDim = remainingFreeSpace / (itemsOnLine - 1); } else { betweenMainDim = 0; } - } else if (justifyContent == CSS_JUSTIFY_SPACE_AROUND) { + } else if (justifyContent == CSSJustifySpaceAround) { // Space on the edges is half of the space between elements betweenMainDim = remainingFreeSpace / itemsOnLine; leadingMainDim = betweenMainDim / 2; @@ -1165,9 +1165,9 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab float crossDim = 0; for (i = startOfLineIndex; i < endOfLineIndex; ++i) { - child = node->get_child(node->context, i); + child = node->getChild(node->context, i); - if (child->style.position_type == CSS_POSITION_ABSOLUTE && + if (child->style.positionType == CSSPositionTypeAbsolute && isPosDefined(child, leading[mainAxis])) { if (performLayout) { // In case the child is position absolute and has left/top being @@ -1187,11 +1187,11 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab // Now that we placed the element, we need to update the variables. // We need to do that only for relative elements. Absolute elements // do not take part in that phase. - if (child->style.position_type == CSS_POSITION_RELATIVE) { + if (child->style.positionType == CSSPositionTypeRelative) { if (canSkipFlex) { // If we skipped the flex step, then we can't rely on the measuredDims because // they weren't computed. This means we can't call getDimWithMargin. - mainDim += betweenMainDim + getMarginAxis(child, mainAxis) + child->layout.flex_basis; + mainDim += betweenMainDim + getMarginAxis(child, mainAxis) + child->layout.flexBasis; crossDim = availableInnerCrossDim; } else { // The main dimension is the sum of all the elements dimension plus @@ -1209,17 +1209,17 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab mainDim += trailingPaddingAndBorderMain; float containerCrossAxis = availableInnerCrossDim; - if (measureModeCrossDim == CSS_MEASURE_MODE_UNDEFINED || measureModeCrossDim == CSS_MEASURE_MODE_AT_MOST) { + if (measureModeCrossDim == CSSMeasureModeUndefined || measureModeCrossDim == CSSMeasureModeAtMost) { // Compute the cross axis from the max cross dimension of the children. containerCrossAxis = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross; - if (measureModeCrossDim == CSS_MEASURE_MODE_AT_MOST) { + if (measureModeCrossDim == CSSMeasureModeAtMost) { containerCrossAxis = fminf(containerCrossAxis, availableInnerCrossDim); } } // If there's no flex wrap, the cross dimension is defined by the container. - if (!isNodeFlexWrap && measureModeCrossDim == CSS_MEASURE_MODE_EXACTLY) { + if (!isNodeFlexWrap && measureModeCrossDim == CSSMeasureModeExactly) { crossDim = availableInnerCrossDim; } @@ -1230,9 +1230,9 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab // We can skip child alignment if we're just measuring the container. if (performLayout) { for (i = startOfLineIndex; i < endOfLineIndex; ++i) { - child = node->get_child(node->context, i); + child = node->getChild(node->context, i); - if (child->style.position_type == CSS_POSITION_ABSOLUTE) { + if (child->style.positionType == CSSPositionTypeAbsolute) { // If the child is absolutely positioned and has a top/left/bottom/right // set, override all the previously computed positions to set it correctly. if (isPosDefined(child, leading[crossAxis])) { @@ -1248,35 +1248,35 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab // For a relative children, we're either using alignItems (parent) or // alignSelf (child) in order to determine the position in the cross axis - css_align_t alignItem = getAlignItem(node, child); + CSSAlign alignItem = getAlignItem(node, child); // If the child uses align stretch, we need to lay it out one more time, this time // forcing the cross-axis size to be the computed cross size for the current line. - if (alignItem == CSS_ALIGN_STRETCH) { - childWidth = child->layout.measured_dimensions[CSS_WIDTH] + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW); - childHeight = child->layout.measured_dimensions[CSS_HEIGHT] + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN); + if (alignItem == CSSAlignStretch) { + childWidth = child->layout.measuredDimensions[CSSDimensionWidth] + getMarginAxis(child, CSSFlexDirectionRow); + childHeight = child->layout.measuredDimensions[CSSDimensionHeight] + getMarginAxis(child, CSSFlexDirectionColumn); bool isCrossSizeDefinite = false; if (isMainAxisRow) { - isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN); + isCrossSizeDefinite = isStyleDimDefined(child, CSSFlexDirectionColumn); childHeight = crossDim; } else { - isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW); + isCrossSizeDefinite = isStyleDimDefined(child, CSSFlexDirectionRow); childWidth = crossDim; } // If the child defines a definite size for its cross axis, there's no need to stretch. if (!isCrossSizeDefinite) { - childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY; - childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY; + childWidthMeasureMode = isUndefined(childWidth) ? CSSMeasureModeUndefined : CSSMeasureModeExactly; + childHeightMeasureMode = isUndefined(childHeight) ? CSSMeasureModeUndefined : CSSMeasureModeExactly; layoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, true, "stretch"); } - } else if (alignItem != CSS_ALIGN_FLEX_START) { + } else if (alignItem != CSSAlignFlexStart) { float remainingCrossDim = containerCrossAxis - getDimWithMargin(child, crossAxis); - if (alignItem == CSS_ALIGN_CENTER) { + if (alignItem == CSSAlignCenter) { leadingCrossDim += remainingCrossDim / 2; - } else { // CSS_ALIGN_FLEX_END + } else { // CSSAlignFlexEnd leadingCrossDim += remainingCrossDim; } } @@ -1303,12 +1303,12 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab float crossDimLead = 0; float currentLead = leadingPaddingAndBorderCross; - css_align_t alignContent = node->style.align_content; - if (alignContent == CSS_ALIGN_FLEX_END) { + CSSAlign alignContent = node->style.alignContent; + if (alignContent == CSSAlignFlexEnd) { currentLead += remainingAlignContentDim; - } else if (alignContent == CSS_ALIGN_CENTER) { + } else if (alignContent == CSSAlignCenter) { currentLead += remainingAlignContentDim / 2; - } else if (alignContent == CSS_ALIGN_STRETCH) { + } else if (alignContent == CSSAlignStretch) { if (availableInnerCrossDim > totalLineCrossDim) { crossDimLead = (remainingAlignContentDim / lineCount); } @@ -1322,16 +1322,16 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab // compute the line's height and find the endIndex float lineHeight = 0; for (j = startIndex; j < childCount; ++j) { - child = node->get_child(node->context, j); - if (child->style.position_type != CSS_POSITION_RELATIVE) { + child = node->getChild(node->context, j); + if (child->style.positionType != CSSPositionTypeRelative) { continue; } - if (child->line_index != i) { + if (child->lineIndex != i) { break; } if (isLayoutDimDefined(child, crossAxis)) { lineHeight = fmaxf(lineHeight, - child->layout.measured_dimensions[dim[crossAxis]] + getMarginAxis(child, crossAxis)); + child->layout.measuredDimensions[dim[crossAxis]] + getMarginAxis(child, crossAxis)); } } endIndex = j; @@ -1339,20 +1339,20 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab if (performLayout) { for (j = startIndex; j < endIndex; ++j) { - child = node->get_child(node->context, j); - if (child->style.position_type != CSS_POSITION_RELATIVE) { + child = node->getChild(node->context, j); + if (child->style.positionType != CSSPositionTypeRelative) { continue; } - css_align_t alignContentAlignItem = getAlignItem(node, child); - if (alignContentAlignItem == CSS_ALIGN_FLEX_START) { + CSSAlign alignContentAlignItem = getAlignItem(node, child); + if (alignContentAlignItem == CSSAlignFlexStart) { child->layout.position[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis); - } else if (alignContentAlignItem == CSS_ALIGN_FLEX_END) { - child->layout.position[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child->layout.measured_dimensions[dim[crossAxis]]; - } else if (alignContentAlignItem == CSS_ALIGN_CENTER) { - childHeight = child->layout.measured_dimensions[dim[crossAxis]]; + } else if (alignContentAlignItem == CSSAlignFlexEnd) { + child->layout.position[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child->layout.measuredDimensions[dim[crossAxis]]; + } else if (alignContentAlignItem == CSSAlignCenter) { + childHeight = child->layout.measuredDimensions[dim[crossAxis]]; child->layout.position[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2; - } else if (alignContentAlignItem == CSS_ALIGN_STRETCH) { + } else if (alignContentAlignItem == CSSAlignStretch) { child->layout.position[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis); // TODO(prenaux): Correctly set the height of items with indefinite // (auto) crossAxis dimension. @@ -1365,28 +1365,28 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab } // STEP 9: COMPUTING FINAL DIMENSIONS - node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow); - node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn); + node->layout.measuredDimensions[CSSDimensionWidth] = boundAxis(node, CSSFlexDirectionRow, availableWidth - marginAxisRow); + node->layout.measuredDimensions[CSSDimensionHeight] = boundAxis(node, CSSFlexDirectionColumn, availableHeight - marginAxisColumn); // If the user didn't specify a width or height for the node, set the // dimensions based on the children. - if (measureModeMainDim == CSS_MEASURE_MODE_UNDEFINED) { + if (measureModeMainDim == CSSMeasureModeUndefined) { // Clamp the size to the min/max size, if specified, and make sure it // doesn't go below the padding and border amount. - node->layout.measured_dimensions[dim[mainAxis]] = boundAxis(node, mainAxis, maxLineMainDim); - } else if (measureModeMainDim == CSS_MEASURE_MODE_AT_MOST) { - node->layout.measured_dimensions[dim[mainAxis]] = fmaxf( + node->layout.measuredDimensions[dim[mainAxis]] = boundAxis(node, mainAxis, maxLineMainDim); + } else if (measureModeMainDim == CSSMeasureModeAtMost) { + node->layout.measuredDimensions[dim[mainAxis]] = fmaxf( fminf(availableInnerMainDim + paddingAndBorderAxisMain, boundAxisWithinMinAndMax(node, mainAxis, maxLineMainDim)), paddingAndBorderAxisMain); } - if (measureModeCrossDim == CSS_MEASURE_MODE_UNDEFINED) { + if (measureModeCrossDim == CSSMeasureModeUndefined) { // Clamp the size to the min/max size, if specified, and make sure it // doesn't go below the padding and border amount. - node->layout.measured_dimensions[dim[crossAxis]] = boundAxis(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross); - } else if (measureModeCrossDim == CSS_MEASURE_MODE_AT_MOST) { - node->layout.measured_dimensions[dim[crossAxis]] = fmaxf( + node->layout.measuredDimensions[dim[crossAxis]] = boundAxis(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross); + } else if (measureModeCrossDim == CSSMeasureModeAtMost) { + node->layout.measuredDimensions[dim[crossAxis]] = fmaxf( fminf(availableInnerCrossDim + paddingAndBorderAxisCross, boundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)), paddingAndBorderAxisCross); @@ -1397,20 +1397,20 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab bool needsMainTrailingPos = false; bool needsCrossTrailingPos = false; - if (mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE || - mainAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) { + if (mainAxis == CSSFlexDirectionRowReverse || + mainAxis == CSSFlexDirectionColumnReverse) { needsMainTrailingPos = true; } - if (crossAxis == CSS_FLEX_DIRECTION_ROW_REVERSE || - crossAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) { + if (crossAxis == CSSFlexDirectionRowReverse || + crossAxis == CSSFlexDirectionColumnReverse) { needsCrossTrailingPos = true; } // Set trailing position if necessary. if (needsMainTrailingPos || needsCrossTrailingPos) { for (i = 0; i < childCount; ++i) { - child = node->get_child(node->context, i); + child = node->getChild(node->context, i); if (needsMainTrailingPos) { setTrailingPosition(node, child, mainAxis); @@ -1430,37 +1430,37 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab // absolutely-positioned children. if (performLayout) { - childWidth = CSS_UNDEFINED; - childHeight = CSS_UNDEFINED; + childWidth = CSSUndefined; + childHeight = CSSUndefined; - if (isStyleDimDefined(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW)) { - childWidth = currentAbsoluteChild->style.dimensions[CSS_WIDTH] + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW); + if (isStyleDimDefined(currentAbsoluteChild, CSSFlexDirectionRow)) { + childWidth = currentAbsoluteChild->style.dimensions[CSSDimensionWidth] + getMarginAxis(currentAbsoluteChild, CSSFlexDirectionRow); } else { // If the child doesn't have a specified width, compute the width based on the left/right offsets if they're defined. - if (isPosDefined(currentAbsoluteChild, CSS_LEFT) && isPosDefined(currentAbsoluteChild, CSS_RIGHT)) { - childWidth = node->layout.measured_dimensions[CSS_WIDTH] - - (getLeadingBorder(node, CSS_FLEX_DIRECTION_ROW) + getTrailingBorder(node, CSS_FLEX_DIRECTION_ROW)) - - (currentAbsoluteChild->style.position[CSS_LEFT] + currentAbsoluteChild->style.position[CSS_RIGHT]); - childWidth = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW, childWidth); + if (isPosDefined(currentAbsoluteChild, CSSPositionLeft) && isPosDefined(currentAbsoluteChild, CSSPositionRight)) { + childWidth = node->layout.measuredDimensions[CSSDimensionWidth] - + (getLeadingBorder(node, CSSFlexDirectionRow) + getTrailingBorder(node, CSSFlexDirectionRow)) - + (currentAbsoluteChild->style.position[CSSPositionLeft] + currentAbsoluteChild->style.position[CSSPositionRight]); + childWidth = boundAxis(currentAbsoluteChild, CSSFlexDirectionRow, childWidth); } } - if (isStyleDimDefined(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN)) { - childHeight = currentAbsoluteChild->style.dimensions[CSS_HEIGHT] + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN); + if (isStyleDimDefined(currentAbsoluteChild, CSSFlexDirectionColumn)) { + childHeight = currentAbsoluteChild->style.dimensions[CSSDimensionHeight] + getMarginAxis(currentAbsoluteChild, CSSFlexDirectionColumn); } else { // If the child doesn't have a specified height, compute the height based on the top/bottom offsets if they're defined. - if (isPosDefined(currentAbsoluteChild, CSS_TOP) && isPosDefined(currentAbsoluteChild, CSS_BOTTOM)) { - childHeight = node->layout.measured_dimensions[CSS_HEIGHT] - - (getLeadingBorder(node, CSS_FLEX_DIRECTION_COLUMN) + getTrailingBorder(node, CSS_FLEX_DIRECTION_COLUMN)) - - (currentAbsoluteChild->style.position[CSS_TOP] + currentAbsoluteChild->style.position[CSS_BOTTOM]); - childHeight = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN, childHeight); + if (isPosDefined(currentAbsoluteChild, CSSPositionTop) && isPosDefined(currentAbsoluteChild, CSSPositionBottom)) { + childHeight = node->layout.measuredDimensions[CSSDimensionHeight] - + (getLeadingBorder(node, CSSFlexDirectionColumn) + getTrailingBorder(node, CSSFlexDirectionColumn)) - + (currentAbsoluteChild->style.position[CSSPositionTop] + currentAbsoluteChild->style.position[CSSPositionBottom]); + childHeight = boundAxis(currentAbsoluteChild, CSSFlexDirectionColumn, childHeight); } } // If we're still missing one or the other dimension, measure the content. if (isUndefined(childWidth) || isUndefined(childHeight)) { - childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY; - childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY; + childWidthMeasureMode = isUndefined(childWidth) ? CSSMeasureModeUndefined : CSSMeasureModeExactly; + childHeightMeasureMode = isUndefined(childHeight) ? CSSMeasureModeUndefined : CSSMeasureModeExactly; // According to the spec, if the main size is not definite and the // child's inline axis is parallel to the main axis (i.e. it's @@ -1468,43 +1468,43 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab // the main size. Otherwise use "AT_MOST" in the cross axis. if (!isMainAxisRow && isUndefined(childWidth) && !isUndefined(availableInnerWidth)) { childWidth = availableInnerWidth; - childWidthMeasureMode = CSS_MEASURE_MODE_AT_MOST; + childWidthMeasureMode = CSSMeasureModeAtMost; } // The W3C spec doesn't say anything about the 'overflow' property, // but all major browsers appear to implement the following logic. - if (node->style.overflow == CSS_OVERFLOW_HIDDEN) { + if (node->style.overflow == CSSOverflowHidden) { if (isMainAxisRow && isUndefined(childHeight) && !isUndefined(availableInnerHeight)) { childHeight = availableInnerHeight; - childHeightMeasureMode = CSS_MEASURE_MODE_AT_MOST; + childHeightMeasureMode = CSSMeasureModeAtMost; } } layoutNodeInternal(currentAbsoluteChild, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "abs-measure"); - childWidth = currentAbsoluteChild->layout.measured_dimensions[CSS_WIDTH] + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW); - childHeight = currentAbsoluteChild->layout.measured_dimensions[CSS_HEIGHT] + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN); + childWidth = currentAbsoluteChild->layout.measuredDimensions[CSSDimensionWidth] + getMarginAxis(currentAbsoluteChild, CSSFlexDirectionRow); + childHeight = currentAbsoluteChild->layout.measuredDimensions[CSSDimensionHeight] + getMarginAxis(currentAbsoluteChild, CSSFlexDirectionColumn); } - layoutNodeInternal(currentAbsoluteChild, childWidth, childHeight, direction, CSS_MEASURE_MODE_EXACTLY, CSS_MEASURE_MODE_EXACTLY, true, "abs-layout"); + layoutNodeInternal(currentAbsoluteChild, childWidth, childHeight, direction, CSSMeasureModeExactly, CSSMeasureModeExactly, true, "abs-layout"); - if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]) && - !isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_ROW])) { - currentAbsoluteChild->layout.position[leading[CSS_FLEX_DIRECTION_ROW]] = - node->layout.measured_dimensions[dim[CSS_FLEX_DIRECTION_ROW]] - - currentAbsoluteChild->layout.measured_dimensions[dim[CSS_FLEX_DIRECTION_ROW]] - - getPosition(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]); + if (isPosDefined(currentAbsoluteChild, trailing[CSSFlexDirectionRow]) && + !isPosDefined(currentAbsoluteChild, leading[CSSFlexDirectionRow])) { + currentAbsoluteChild->layout.position[leading[CSSFlexDirectionRow]] = + node->layout.measuredDimensions[dim[CSSFlexDirectionRow]] - + currentAbsoluteChild->layout.measuredDimensions[dim[CSSFlexDirectionRow]] - + getPosition(currentAbsoluteChild, trailing[CSSFlexDirectionRow]); } - if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_COLUMN]) && - !isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_COLUMN])) { - currentAbsoluteChild->layout.position[leading[CSS_FLEX_DIRECTION_COLUMN]] = - node->layout.measured_dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] - - currentAbsoluteChild->layout.measured_dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] - - getPosition(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_COLUMN]); + if (isPosDefined(currentAbsoluteChild, trailing[CSSFlexDirectionColumn]) && + !isPosDefined(currentAbsoluteChild, leading[CSSFlexDirectionColumn])) { + currentAbsoluteChild->layout.position[leading[CSSFlexDirectionColumn]] = + node->layout.measuredDimensions[dim[CSSFlexDirectionColumn]] - + currentAbsoluteChild->layout.measuredDimensions[dim[CSSFlexDirectionColumn]] - + getPosition(currentAbsoluteChild, trailing[CSSFlexDirectionColumn]); } } - currentAbsoluteChild = currentAbsoluteChild->next_child; + currentAbsoluteChild = currentAbsoluteChild->nextChild; } } @@ -1523,19 +1523,19 @@ static const char* getSpacer(unsigned long level) { return &spacer[spacerLen - level]; } -static const char* getModeName(css_measure_mode_t mode, bool performLayout) { - const char* kMeasureModeNames[CSS_MEASURE_MODE_COUNT] = { +static const char* getModeName(CSSMeasureMode mode, bool performLayout) { + const char* kMeasureModeNames[CSSMeasureModeCount] = { "UNDEFINED", "EXACTLY", "AT_MOST" }; - const char* kLayoutModeNames[CSS_MEASURE_MODE_COUNT] = { + const char* kLayoutModeNames[CSSMeasureModeCount] = { "LAY_UNDEFINED", "LAY_EXACTLY", "LAY_AT_MOST" }; - if (mode >= CSS_MEASURE_MODE_COUNT) { + if (mode >= CSSMeasureModeCount) { return ""; } @@ -1543,38 +1543,38 @@ static const char* getModeName(css_measure_mode_t mode, bool performLayout) { } static bool canUseCachedMeasurement( - bool is_text_node, - float available_width, - float available_height, + bool isTextNode, + float availableWidth, + float availableHeight, float margin_row, float margin_column, - css_measure_mode_t width_measure_mode, - css_measure_mode_t height_measure_mode, - css_cached_measurement_t cached_layout) { + CSSMeasureMode widthMeasureMode, + CSSMeasureMode heightMeasureMode, + CSSCachedMeasurement cached_layout) { bool is_height_same = - (cached_layout.height_measure_mode == CSS_MEASURE_MODE_UNDEFINED && height_measure_mode == CSS_MEASURE_MODE_UNDEFINED) || - (cached_layout.height_measure_mode == height_measure_mode && eq(cached_layout.available_height, available_height)); + (cached_layout.heightMeasureMode == CSSMeasureModeUndefined && heightMeasureMode == CSSMeasureModeUndefined) || + (cached_layout.heightMeasureMode == heightMeasureMode && eq(cached_layout.availableHeight, availableHeight)); bool is_width_same = - (cached_layout.width_measure_mode == CSS_MEASURE_MODE_UNDEFINED && width_measure_mode == CSS_MEASURE_MODE_UNDEFINED) || - (cached_layout.width_measure_mode == width_measure_mode && eq(cached_layout.available_width, available_width)); + (cached_layout.widthMeasureMode == CSSMeasureModeUndefined && widthMeasureMode == CSSMeasureModeUndefined) || + (cached_layout.widthMeasureMode == widthMeasureMode && eq(cached_layout.availableWidth, availableWidth)); if (is_height_same && is_width_same) { return true; } bool is_height_valid = - (cached_layout.height_measure_mode == CSS_MEASURE_MODE_UNDEFINED && height_measure_mode == CSS_MEASURE_MODE_AT_MOST && cached_layout.computed_height <= (available_height - margin_column)) || - (height_measure_mode == CSS_MEASURE_MODE_EXACTLY && eq(cached_layout.computed_height, available_height - margin_column)); + (cached_layout.heightMeasureMode == CSSMeasureModeUndefined && heightMeasureMode == CSSMeasureModeAtMost && cached_layout.computedHeight <= (availableHeight - margin_column)) || + (heightMeasureMode == CSSMeasureModeExactly && eq(cached_layout.computedHeight, availableHeight - margin_column)); if (is_width_same && is_height_valid) { return true; } bool is_width_valid = - (cached_layout.width_measure_mode == CSS_MEASURE_MODE_UNDEFINED && width_measure_mode == CSS_MEASURE_MODE_AT_MOST && cached_layout.computed_width <= (available_width - margin_row)) || - (width_measure_mode == CSS_MEASURE_MODE_EXACTLY && eq(cached_layout.computed_width, available_width - margin_row)); + (cached_layout.widthMeasureMode == CSSMeasureModeUndefined && widthMeasureMode == CSSMeasureModeAtMost && cached_layout.computedWidth <= (availableWidth - margin_row)) || + (widthMeasureMode == CSSMeasureModeExactly && eq(cached_layout.computedWidth, availableWidth - margin_row)); if (is_height_same && is_width_valid) { return true; @@ -1585,29 +1585,29 @@ static bool canUseCachedMeasurement( } // We know this to be text so we can apply some more specialized heuristics. - if (is_text_node) { + if (isTextNode) { if (is_width_same) { - if (height_measure_mode == CSS_MEASURE_MODE_UNDEFINED) { + if (heightMeasureMode == CSSMeasureModeUndefined) { // Width is the same and height is not restricted. Re-use cahced value. return true; } - if (height_measure_mode == CSS_MEASURE_MODE_AT_MOST && - cached_layout.computed_height < (available_height - margin_column)) { + if (heightMeasureMode == CSSMeasureModeAtMost && + cached_layout.computedHeight < (availableHeight - margin_column)) { // Width is the same and height restriction is greater than the cached height. Re-use cached value. return true; } // Width is the same but height restriction imposes smaller height than previously measured. // Update the cached value to respect the new height restriction. - cached_layout.computed_height = available_height - margin_column; + cached_layout.computedHeight = availableHeight - margin_column; return true; } - if (cached_layout.width_measure_mode == CSS_MEASURE_MODE_UNDEFINED) { - if (width_measure_mode == CSS_MEASURE_MODE_UNDEFINED || - (width_measure_mode == CSS_MEASURE_MODE_AT_MOST && - cached_layout.computed_width <= (available_width - margin_row))) { + if (cached_layout.widthMeasureMode == CSSMeasureModeUndefined) { + if (widthMeasureMode == CSSMeasureModeUndefined || + (widthMeasureMode == CSSMeasureModeAtMost && + cached_layout.computedWidth <= (availableWidth - margin_row))) { // Previsouly this text was measured with no width restriction, if width is now restricted // but to a larger value than the previsouly measured width we can re-use the measurement // as we know it will fit. @@ -1627,23 +1627,23 @@ static bool canUseCachedMeasurement( // Input parameters are the same as layoutNodeImpl (see above) // Return parameter is true if layout was performed, false if skipped // -bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableHeight, - css_direction_t parentDirection, css_measure_mode_t widthMeasureMode, css_measure_mode_t heightMeasureMode, bool performLayout, char* reason) { - css_layout_t* layout = &node->layout; +bool layoutNodeInternal(CSSNode* node, float availableWidth, float availableHeight, + CSSDirection parentDirection, CSSMeasureMode widthMeasureMode, CSSMeasureMode heightMeasureMode, bool performLayout, char* reason) { + CSSLayout* layout = &node->layout; gDepth++; - bool needToVisitNode = (node->is_dirty(node->context) && layout->generation_count != gCurrentGenerationCount) || - layout->last_parent_direction != parentDirection; + bool needToVisitNode = (node->isDirty(node->context) && layout->generationCount != gCurrentGenerationCount) || + layout->lastParentDirection != parentDirection; if (needToVisitNode) { // Invalidate the cached results. - layout->next_cached_measurements_index = 0; - layout->cached_layout.width_measure_mode = (css_measure_mode_t)-1; - layout->cached_layout.height_measure_mode = (css_measure_mode_t)-1; + layout->nextCachedMeasurementsIndex = 0; + layout->cached_layout.widthMeasureMode = (CSSMeasureMode)-1; + layout->cached_layout.heightMeasureMode = (CSSMeasureMode)-1; } - css_cached_measurement_t* cachedResults = NULL; + CSSCachedMeasurement* cachedResults = NULL; // Determine whether the results are already cached. We maintain a separate // cache for layouts and measurements. A layout operation modifies the positions @@ -1653,47 +1653,47 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH // We handle nodes with measure functions specially here because they are the most // expensive to measure, so it's worth avoiding redundant measurements if at all possible. if (isMeasureDefined(node)) { - float marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW); - float marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN); + float marginAxisRow = getMarginAxis(node, CSSFlexDirectionRow); + float marginAxisColumn = getMarginAxis(node, CSSFlexDirectionColumn); // First, try to use the layout cache. - if (canUseCachedMeasurement(node->is_text_node && node->is_text_node(node->context), availableWidth, availableHeight, marginAxisRow, marginAxisColumn, + if (canUseCachedMeasurement(node->isTextNode && node->isTextNode(node->context), availableWidth, availableHeight, marginAxisRow, marginAxisColumn, widthMeasureMode, heightMeasureMode, layout->cached_layout)) { cachedResults = &layout->cached_layout; } else { // Try to use the measurement cache. - for (int i = 0; i < layout->next_cached_measurements_index; i++) { - if (canUseCachedMeasurement(node->is_text_node && node->is_text_node(node->context), availableWidth, availableHeight, marginAxisRow, marginAxisColumn, - widthMeasureMode, heightMeasureMode, layout->cached_measurements[i])) { - cachedResults = &layout->cached_measurements[i]; + for (int i = 0; i < layout->nextCachedMeasurementsIndex; i++) { + if (canUseCachedMeasurement(node->isTextNode && node->isTextNode(node->context), availableWidth, availableHeight, marginAxisRow, marginAxisColumn, + widthMeasureMode, heightMeasureMode, layout->cachedMeasurements[i])) { + cachedResults = &layout->cachedMeasurements[i]; break; } } } } else if (performLayout) { - if (eq(layout->cached_layout.available_width, availableWidth) && - eq(layout->cached_layout.available_height, availableHeight) && - layout->cached_layout.width_measure_mode == widthMeasureMode && - layout->cached_layout.height_measure_mode == heightMeasureMode) { + if (eq(layout->cached_layout.availableWidth, availableWidth) && + eq(layout->cached_layout.availableHeight, availableHeight) && + layout->cached_layout.widthMeasureMode == widthMeasureMode && + layout->cached_layout.heightMeasureMode == heightMeasureMode) { cachedResults = &layout->cached_layout; } } else { - for (int i = 0; i < layout->next_cached_measurements_index; i++) { - if (eq(layout->cached_measurements[i].available_width, availableWidth) && - eq(layout->cached_measurements[i].available_height, availableHeight) && - layout->cached_measurements[i].width_measure_mode == widthMeasureMode && - layout->cached_measurements[i].height_measure_mode == heightMeasureMode) { + for (int i = 0; i < layout->nextCachedMeasurementsIndex; i++) { + if (eq(layout->cachedMeasurements[i].availableWidth, availableWidth) && + eq(layout->cachedMeasurements[i].availableHeight, availableHeight) && + layout->cachedMeasurements[i].widthMeasureMode == widthMeasureMode && + layout->cachedMeasurements[i].heightMeasureMode == heightMeasureMode) { - cachedResults = &layout->cached_measurements[i]; + cachedResults = &layout->cachedMeasurements[i]; break; } } } if (!needToVisitNode && cachedResults != NULL) { - layout->measured_dimensions[CSS_WIDTH] = cachedResults->computed_width; - layout->measured_dimensions[CSS_HEIGHT] = cachedResults->computed_height; + layout->measuredDimensions[CSSDimensionWidth] = cachedResults->computedWidth; + layout->measuredDimensions[CSSDimensionHeight] = cachedResults->computedHeight; if (gPrintChanges && gPrintSkips) { printf("%s%d.{[skipped] ", getSpacer(gDepth), gDepth); @@ -1704,7 +1704,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH getModeName(widthMeasureMode, performLayout), getModeName(heightMeasureMode, performLayout), availableWidth, availableHeight, - cachedResults->computed_width, cachedResults->computed_height, reason); + cachedResults->computedWidth, cachedResults->computedHeight, reason); } } else { @@ -1729,76 +1729,76 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH printf("wm: %s, hm: %s, d: (%f, %f) %s\n", getModeName(widthMeasureMode, performLayout), getModeName(heightMeasureMode, performLayout), - layout->measured_dimensions[CSS_WIDTH], layout->measured_dimensions[CSS_HEIGHT], reason); + layout->measuredDimensions[CSSDimensionWidth], layout->measuredDimensions[CSSDimensionHeight], reason); } - layout->last_parent_direction = parentDirection; + layout->lastParentDirection = parentDirection; if (cachedResults == NULL) { - if (layout->next_cached_measurements_index == CSS_MAX_CACHED_RESULT_COUNT) { + if (layout->nextCachedMeasurementsIndex == CSS_MAX_CACHED_RESULT_COUNT) { if (gPrintChanges) { printf("Out of cache entries!\n"); } - layout->next_cached_measurements_index = 0; + layout->nextCachedMeasurementsIndex = 0; } - css_cached_measurement_t* newCacheEntry; + CSSCachedMeasurement* newCacheEntry; if (performLayout) { // Use the single layout cache entry. newCacheEntry = &layout->cached_layout; } else { // Allocate a new measurement cache entry. - newCacheEntry = &layout->cached_measurements[layout->next_cached_measurements_index]; - layout->next_cached_measurements_index++; + newCacheEntry = &layout->cachedMeasurements[layout->nextCachedMeasurementsIndex]; + layout->nextCachedMeasurementsIndex++; } - newCacheEntry->available_width = availableWidth; - newCacheEntry->available_height = availableHeight; - newCacheEntry->width_measure_mode = widthMeasureMode; - newCacheEntry->height_measure_mode = heightMeasureMode; - newCacheEntry->computed_width = layout->measured_dimensions[CSS_WIDTH]; - newCacheEntry->computed_height = layout->measured_dimensions[CSS_HEIGHT]; + newCacheEntry->availableWidth = availableWidth; + newCacheEntry->availableHeight = availableHeight; + newCacheEntry->widthMeasureMode = widthMeasureMode; + newCacheEntry->heightMeasureMode = heightMeasureMode; + newCacheEntry->computedWidth = layout->measuredDimensions[CSSDimensionWidth]; + newCacheEntry->computedHeight = layout->measuredDimensions[CSSDimensionHeight]; } } if (performLayout) { - node->layout.dimensions[CSS_WIDTH] = node->layout.measured_dimensions[CSS_WIDTH]; - node->layout.dimensions[CSS_HEIGHT] = node->layout.measured_dimensions[CSS_HEIGHT]; - layout->should_update = true; + node->layout.dimensions[CSSDimensionWidth] = node->layout.measuredDimensions[CSSDimensionWidth]; + node->layout.dimensions[CSSDimensionHeight] = node->layout.measuredDimensions[CSSDimensionHeight]; + layout->shouldUpdate = true; } gDepth--; - layout->generation_count = gCurrentGenerationCount; + layout->generationCount = gCurrentGenerationCount; return (needToVisitNode || cachedResults == NULL); } -void layoutNode(css_node_t* node, float availableWidth, float availableHeight, css_direction_t parentDirection) { +void layoutNode(CSSNode* node, float availableWidth, float availableHeight, CSSDirection parentDirection) { // Increment the generation count. This will force the recursive routine to visit // all dirty nodes at least once. Subsequent visits will be skipped if the input // parameters don't change. gCurrentGenerationCount++; - css_measure_mode_t widthMeasureMode = CSS_MEASURE_MODE_UNDEFINED; - css_measure_mode_t heightMeasureMode = CSS_MEASURE_MODE_UNDEFINED; + CSSMeasureMode widthMeasureMode = CSSMeasureModeUndefined; + CSSMeasureMode heightMeasureMode = CSSMeasureModeUndefined; if (!isUndefined(availableWidth)) { - widthMeasureMode = CSS_MEASURE_MODE_EXACTLY; - } else if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_ROW)) { - availableWidth = node->style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] + getMarginAxis(node, CSS_FLEX_DIRECTION_ROW); - widthMeasureMode = CSS_MEASURE_MODE_EXACTLY; - } else if (node->style.maxDimensions[CSS_WIDTH] >= 0.0) { - availableWidth = node->style.maxDimensions[CSS_WIDTH]; - widthMeasureMode = CSS_MEASURE_MODE_AT_MOST; + widthMeasureMode = CSSMeasureModeExactly; + } else if (isStyleDimDefined(node, CSSFlexDirectionRow)) { + availableWidth = node->style.dimensions[dim[CSSFlexDirectionRow]] + getMarginAxis(node, CSSFlexDirectionRow); + widthMeasureMode = CSSMeasureModeExactly; + } else if (node->style.maxDimensions[CSSDimensionWidth] >= 0.0) { + availableWidth = node->style.maxDimensions[CSSDimensionWidth]; + widthMeasureMode = CSSMeasureModeAtMost; } if (!isUndefined(availableHeight)) { - heightMeasureMode = CSS_MEASURE_MODE_EXACTLY; - } else if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { - availableHeight = node->style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] + getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN); - heightMeasureMode = CSS_MEASURE_MODE_EXACTLY; - } else if (node->style.maxDimensions[CSS_HEIGHT] >= 0.0) { - availableHeight = node->style.maxDimensions[CSS_HEIGHT]; - heightMeasureMode = CSS_MEASURE_MODE_AT_MOST; + heightMeasureMode = CSSMeasureModeExactly; + } else if (isStyleDimDefined(node, CSSFlexDirectionColumn)) { + availableHeight = node->style.dimensions[dim[CSSFlexDirectionColumn]] + getMarginAxis(node, CSSFlexDirectionColumn); + heightMeasureMode = CSSMeasureModeExactly; + } else if (node->style.maxDimensions[CSSDimensionHeight] >= 0.0) { + availableHeight = node->style.maxDimensions[CSSDimensionHeight]; + heightMeasureMode = CSSMeasureModeAtMost; } if (layoutNodeInternal(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, true, "initial")) { @@ -1806,7 +1806,7 @@ void layoutNode(css_node_t* node, float availableWidth, float availableHeight, c setPosition(node, node->layout.direction); if (gPrintTree) { - print_css_node(node, CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN | CSS_PRINT_STYLE); + CSSNodePrint(node, CSSPrintOptionsLayout | CSSPrintOptionsChildren | CSSPrintOptionsStyle); } } } diff --git a/React/CSSLayout/CSSLayout.h b/React/CSSLayout/CSSLayout.h index 91835281b969cd..f85c72970571c1 100644 --- a/React/CSSLayout/CSSLayout.h +++ b/React/CSSLayout/CSSLayout.h @@ -21,132 +21,132 @@ static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff}; #define NAN (*(const float *)__nan) #endif -#define CSS_UNDEFINED NAN +#define CSSUndefined NAN -#include "CSSMacros.h" +#include CSS_EXTERN_C_BEGIN -typedef enum { - CSS_DIRECTION_INHERIT = 0, - CSS_DIRECTION_LTR, - CSS_DIRECTION_RTL -} css_direction_t; - -typedef enum { - CSS_FLEX_DIRECTION_COLUMN = 0, - CSS_FLEX_DIRECTION_COLUMN_REVERSE, - CSS_FLEX_DIRECTION_ROW, - CSS_FLEX_DIRECTION_ROW_REVERSE -} css_flex_direction_t; - -typedef enum { - CSS_JUSTIFY_FLEX_START = 0, - CSS_JUSTIFY_CENTER, - CSS_JUSTIFY_FLEX_END, - CSS_JUSTIFY_SPACE_BETWEEN, - CSS_JUSTIFY_SPACE_AROUND -} css_justify_t; - -typedef enum { - CSS_OVERFLOW_VISIBLE = 0, - CSS_OVERFLOW_HIDDEN -} css_overflow_t; +typedef enum CSSDirection { + CSSDirectionInherit, + CSSDirectionLTR, + CSSDirectionRTL, +} CSSDirection; + +typedef enum CSSFlexDirection { + CSSFlexDirectionColumn, + CSSFlexDirectionColumnReverse, + CSSFlexDirectionRow, + CSSFlexDirectionRowReverse, +} CSSFlexDirection; + +typedef enum CSSJustify { + CSSJustifyFlexStart, + CSSJustifyCenter, + CSSJustifyFlexEnd, + CSSJustifySpaceBetween, + CSSJustifySpaceAround, +} CSSJustify; + +typedef enum CSSOverflow { + CSSOverflowVisible, + CSSOverflowHidden, +} CSSOverflow; // Note: auto is only a valid value for alignSelf. It is NOT a valid value for // alignItems. -typedef enum { - CSS_ALIGN_AUTO = 0, - CSS_ALIGN_FLEX_START, - CSS_ALIGN_CENTER, - CSS_ALIGN_FLEX_END, - CSS_ALIGN_STRETCH -} css_align_t; - -typedef enum { - CSS_POSITION_RELATIVE = 0, - CSS_POSITION_ABSOLUTE -} css_position_type_t; - -typedef enum { - CSS_NOWRAP = 0, - CSS_WRAP -} css_wrap_type_t; +typedef enum CSSAlign { + CSSAlignAuto, + CSSAlignFlexStart, + CSSAlignCenter, + CSSAlignFlexEnd, + CSSAlignStretch, +} CSSAlign; + +typedef enum CSSPositionType { + CSSPositionTypeRelative, + CSSPositionTypeAbsolute, +} CSSPositionType; + +typedef enum CSSWrapType { + CSSWrapTypeNoWrap, + CSSWrapTypeWrap, +} CSSWrapType; // Note: left and top are shared between position[2] and position[4], so // they have to be before right and bottom. -typedef enum { - CSS_LEFT = 0, - CSS_TOP, - CSS_RIGHT, - CSS_BOTTOM, - CSS_START, - CSS_END, - CSS_POSITION_COUNT -} css_position_t; - -typedef enum { - CSS_MEASURE_MODE_UNDEFINED = 0, - CSS_MEASURE_MODE_EXACTLY, - CSS_MEASURE_MODE_AT_MOST, - CSS_MEASURE_MODE_COUNT -} css_measure_mode_t; - -typedef enum { - CSS_WIDTH = 0, - CSS_HEIGHT -} css_dimension_t; - -typedef struct { - float available_width; - float available_height; - css_measure_mode_t width_measure_mode; - css_measure_mode_t height_measure_mode; - - float computed_width; - float computed_height; -} css_cached_measurement_t; - +typedef enum CSSPosition { + CSSPositionLeft, + CSSPositionTop, + CSSPositionRight, + CSSPositionBottom, + CSSPositionStart, + CSSPositionEnd, + CSSPositionCount, +} CSSPosition; + +typedef enum CSSMeasureMode { + CSSMeasureModeUndefined, + CSSMeasureModeExactly, + CSSMeasureModeAtMost, + CSSMeasureModeCount, +} CSSMeasureMode; + +typedef enum CSSDimension { + CSSDimensionWidth, + CSSDimensionHeight, +} CSSDimension; + +typedef struct CSSCachedMeasurement { + float availableWidth; + float availableHeight; + CSSMeasureMode widthMeasureMode; + CSSMeasureMode heightMeasureMode; + + float computedWidth; + float computedHeight; +} CSSCachedMeasurement; + +// This value was chosen based on empiracle data. Even the most complicated +// layouts should not require more than 16 entries to fit within the cache. enum { - // This value was chosen based on empiracle data. Even the most complicated - // layouts should not require more than 16 entries to fit within the cache. CSS_MAX_CACHED_RESULT_COUNT = 16 }; -typedef struct { +typedef struct CSSLayout { float position[4]; float dimensions[2]; - css_direction_t direction; + CSSDirection direction; - float flex_basis; + float flexBasis; // Instead of recomputing the entire layout every single time, we // cache some information to break early when nothing changed - bool should_update; - int generation_count; - css_direction_t last_parent_direction; + bool shouldUpdate; + int generationCount; + CSSDirection lastParentDirection; - int next_cached_measurements_index; - css_cached_measurement_t cached_measurements[CSS_MAX_CACHED_RESULT_COUNT]; - float measured_dimensions[2]; + int nextCachedMeasurementsIndex; + CSSCachedMeasurement cachedMeasurements[CSS_MAX_CACHED_RESULT_COUNT]; + float measuredDimensions[2]; - css_cached_measurement_t cached_layout; -} css_layout_t; + CSSCachedMeasurement cached_layout; +} CSSLayout; -typedef struct { +typedef struct CSSMeasureResult { float dimensions[2]; -} css_dim_t; - -typedef struct { - css_direction_t direction; - css_flex_direction_t flex_direction; - css_justify_t justify_content; - css_align_t align_content; - css_align_t align_items; - css_align_t align_self; - css_position_type_t position_type; - css_wrap_type_t flex_wrap; - css_overflow_t overflow; +} CSSMeasureResult; + +typedef struct CSSStyle { + CSSDirection direction; + CSSFlexDirection flexDirection; + CSSJustify justifyContent; + CSSAlign alignContent; + CSSAlign alignItems; + CSSAlign alignSelf; + CSSPositionType positionType; + CSSWrapType flexWrap; + CSSOverflow overflow; float flex; float margin[6]; float position[4]; @@ -165,40 +165,40 @@ typedef struct { float dimensions[2]; float minDimensions[2]; float maxDimensions[2]; -} css_style_t; +} CSSStyle; -typedef struct css_node css_node_t; -struct css_node { - css_style_t style; - css_layout_t layout; - int children_count; - int line_index; +typedef struct CSSNode { + CSSStyle style; + CSSLayout layout; + int childCount; + int lineIndex; - css_node_t* next_child; + struct CSSNode* nextChild; - css_dim_t (*measure)(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode); + CSSMeasureResult (*measure)(void *context, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode); void (*print)(void *context); - struct css_node* (*get_child)(void *context, int i); - bool (*is_dirty)(void *context); - bool (*is_text_node)(void *context); + struct CSSNode* (*getChild)(void *context, int i); + bool (*isDirty)(void *context); + bool (*isTextNode)(void *context); void *context; -}; +} CSSNode; // Lifecycle of nodes and children -css_node_t *new_css_node(void); -void init_css_node(css_node_t *node); -void free_css_node(css_node_t *node); +CSSNode *CSSNodeNew(); +void CSSNodeInit(CSSNode *node); +void CSSNodeFree(CSSNode *node); // Print utilities -typedef enum { - CSS_PRINT_LAYOUT = 1, - CSS_PRINT_STYLE = 2, - CSS_PRINT_CHILDREN = 4, -} css_print_options_t; -void print_css_node(css_node_t *node, css_print_options_t options); +typedef enum CSSPrintOptions { + CSSPrintOptionsLayout = 1, + CSSPrintOptionsStyle = 2, + CSSPrintOptionsChildren = 4, +} CSSPrintOptions; + +void CSSNodePrint(CSSNode *node, CSSPrintOptions options); // Function that computes the layout! -void layoutNode(css_node_t *node, float availableWidth, float availableHeight, css_direction_t parentDirection); +void layoutNode(CSSNode *node, float availableWidth, float availableHeight, CSSDirection parentDirection); bool isUndefined(float value); CSS_EXTERN_C_END diff --git a/React/Views/RCTRootShadowView.m b/React/Views/RCTRootShadowView.m index e012358966aa37..d6d8cfe270b542 100644 --- a/React/Views/RCTRootShadowView.m +++ b/React/Views/RCTRootShadowView.m @@ -21,7 +21,7 @@ - (instancetype)init self = [super init]; if (self) { if ([[RCTI18nUtil sharedInstance] isRTL]) { - self.cssNode->style.direction = CSS_DIRECTION_RTL; + self.cssNode->style.direction = CSSDirectionRTL; } } return self; @@ -33,14 +33,14 @@ - (void)applySizeConstraints case RCTRootViewSizeFlexibilityNone: break; case RCTRootViewSizeFlexibilityWidth: - self.cssNode->style.dimensions[CSS_WIDTH] = CSS_UNDEFINED; + self.cssNode->style.dimensions[CSSDimensionWidth] = CSSUndefined; break; case RCTRootViewSizeFlexibilityHeight: - self.cssNode->style.dimensions[CSS_HEIGHT] = CSS_UNDEFINED; + self.cssNode->style.dimensions[CSSDimensionHeight] = CSSUndefined; break; case RCTRootViewSizeFlexibilityWidthAndHeight: - self.cssNode->style.dimensions[CSS_WIDTH] = CSS_UNDEFINED; - self.cssNode->style.dimensions[CSS_HEIGHT] = CSS_UNDEFINED; + self.cssNode->style.dimensions[CSSDimensionWidth] = CSSUndefined; + self.cssNode->style.dimensions[CSSDimensionHeight] = CSSUndefined; break; } } @@ -49,8 +49,7 @@ - (void)applySizeConstraints { [self applySizeConstraints]; - [self fillCSSNode:self.cssNode]; - layoutNode(self.cssNode, CSS_UNDEFINED, CSS_UNDEFINED, CSS_DIRECTION_INHERIT); + layoutNode(self.cssNode, CSSUndefined, CSSUndefined, CSSDirectionInherit); NSMutableSet *viewsWithNewFrame = [NSMutableSet set]; [self applyLayoutNode:self.cssNode viewsWithNewFrame:viewsWithNewFrame absolutePosition:CGPointZero]; diff --git a/React/Views/RCTShadowView.h b/React/Views/RCTShadowView.h index b76e3000da95c0..454a8e8e406492 100644 --- a/React/Views/RCTShadowView.h +++ b/React/Views/RCTShadowView.h @@ -44,7 +44,7 @@ typedef void (^RCTApplierBlock)(NSDictionary *viewRegistry - (void)removeReactSubview:(RCTShadowView *)subview NS_REQUIRES_SUPER; @property (nonatomic, weak, readonly) RCTShadowView *superview; -@property (nonatomic, assign, readonly) css_node_t *cssNode; +@property (nonatomic, assign, readonly) CSSNode *cssNode; @property (nonatomic, copy) NSString *viewName; @property (nonatomic, strong) UIColor *backgroundColor; // Used to propagate to children @property (nonatomic, assign) RCTUpdateLifecycle layoutLifecycle; @@ -127,12 +127,12 @@ typedef void (^RCTApplierBlock)(NSDictionary *viewRegistry /** * Flexbox properties. All zero/disabled by default */ -@property (nonatomic, assign) css_flex_direction_t flexDirection; -@property (nonatomic, assign) css_justify_t justifyContent; -@property (nonatomic, assign) css_align_t alignSelf; -@property (nonatomic, assign) css_align_t alignItems; -@property (nonatomic, assign) css_position_type_t position; -@property (nonatomic, assign) css_wrap_type_t flexWrap; +@property (nonatomic, assign) CSSFlexDirection flexDirection; +@property (nonatomic, assign) CSSJustify justifyContent; +@property (nonatomic, assign) CSSAlign alignSelf; +@property (nonatomic, assign) CSSAlign alignItems; +@property (nonatomic, assign) CSSPositionType position; +@property (nonatomic, assign) CSSWrapType flexWrap; @property (nonatomic, assign) CGFloat flex; /** @@ -172,24 +172,30 @@ typedef void (^RCTApplierBlock)(NSDictionary *viewRegistry * is split into two methods so subclasses can override `applyLayoutToChildren:` * while using default implementation of `applyLayoutNode:`. */ -- (void)applyLayoutNode:(css_node_t *)node +- (void)applyLayoutNode:(CSSNode *)node viewsWithNewFrame:(NSMutableSet *)viewsWithNewFrame absolutePosition:(CGPoint)absolutePosition NS_REQUIRES_SUPER; /** * Enumerate the child nodes and tell them to apply layout. */ -- (void)applyLayoutToChildren:(css_node_t *)node +- (void)applyLayoutToChildren:(CSSNode *)node viewsWithNewFrame:(NSMutableSet *)viewsWithNewFrame absolutePosition:(CGPoint)absolutePosition; /** * The following are implementation details exposed to subclasses. Do not call them directly */ -- (void)fillCSSNode:(css_node_t *)node NS_REQUIRES_SUPER; - (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 + * CSSLayout it is a leaf node. + */ +- (BOOL)isCSSLeafNode; + - (void)dirtyPropagation NS_REQUIRES_SUPER; - (BOOL)isPropagationDirty; diff --git a/React/Views/RCTShadowView.m b/React/Views/RCTShadowView.m index 2ff78efc187a2e..4dd78a1cbff057 100644 --- a/React/Views/RCTShadowView.m +++ b/React/Views/RCTShadowView.m @@ -48,7 +48,7 @@ @implementation RCTShadowView @synthesize reactTag = _reactTag; -// css_node api +// cssNode api static void RCTPrint(void *context) { @@ -56,7 +56,7 @@ static void RCTPrint(void *context) printf("%s(%zd), ", shadowView.viewName.UTF8String, shadowView.reactTag.integerValue); } -static css_node_t *RCTGetChild(void *context, int i) +static CSSNode *RCTGetChild(void *context, int i) { RCTShadowView *shadowView = (__bridge RCTShadowView *)context; RCTShadowView *child = [shadowView reactSubviews][i]; @@ -70,30 +70,25 @@ static bool RCTIsDirty(void *context) } // Enforces precedence rules, e.g. marginLeft > marginHorizontal > margin. -static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float style[CSS_POSITION_COUNT]) { - style[CSS_LEFT] = !isUndefined(metaProps[META_PROP_LEFT]) ? metaProps[META_PROP_LEFT] +static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float style[CSSPositionCount]) { + style[CSSPositionLeft] = !isUndefined(metaProps[META_PROP_LEFT]) ? metaProps[META_PROP_LEFT] : !isUndefined(metaProps[META_PROP_HORIZONTAL]) ? metaProps[META_PROP_HORIZONTAL] : !isUndefined(metaProps[META_PROP_ALL]) ? metaProps[META_PROP_ALL] : 0; - style[CSS_RIGHT] = !isUndefined(metaProps[META_PROP_RIGHT]) ? metaProps[META_PROP_RIGHT] + style[CSSPositionRight] = !isUndefined(metaProps[META_PROP_RIGHT]) ? metaProps[META_PROP_RIGHT] : !isUndefined(metaProps[META_PROP_HORIZONTAL]) ? metaProps[META_PROP_HORIZONTAL] : !isUndefined(metaProps[META_PROP_ALL]) ? metaProps[META_PROP_ALL] : 0; - style[CSS_TOP] = !isUndefined(metaProps[META_PROP_TOP]) ? metaProps[META_PROP_TOP] + style[CSSPositionTop] = !isUndefined(metaProps[META_PROP_TOP]) ? metaProps[META_PROP_TOP] : !isUndefined(metaProps[META_PROP_VERTICAL]) ? metaProps[META_PROP_VERTICAL] : !isUndefined(metaProps[META_PROP_ALL]) ? metaProps[META_PROP_ALL] : 0; - style[CSS_BOTTOM] = !isUndefined(metaProps[META_PROP_BOTTOM]) ? metaProps[META_PROP_BOTTOM] + style[CSSPositionBottom] = !isUndefined(metaProps[META_PROP_BOTTOM]) ? metaProps[META_PROP_BOTTOM] : !isUndefined(metaProps[META_PROP_VERTICAL]) ? metaProps[META_PROP_VERTICAL] : !isUndefined(metaProps[META_PROP_ALL]) ? metaProps[META_PROP_ALL] : 0; } -- (void)fillCSSNode:(css_node_t *)node -{ - node->children_count = (int)_reactSubviews.count; -} - // The absolute stuff is so that we can take into account our absolute position when rounding in order to // snap to the pixel grid. For example, say you have the following structure: // @@ -123,29 +118,29 @@ - (void)fillCSSNode:(css_node_t *)node // width = 213.5 - 106.5 = 107 // You'll notice that this is the same width we calculated for the parent view because we've taken its position into account. -- (void)applyLayoutNode:(css_node_t *)node +- (void)applyLayoutNode:(CSSNode *)node viewsWithNewFrame:(NSMutableSet *)viewsWithNewFrame absolutePosition:(CGPoint)absolutePosition { - if (!node->layout.should_update) { + if (!node->layout.shouldUpdate) { return; } - node->layout.should_update = false; + node->layout.shouldUpdate = false; _layoutLifecycle = RCTUpdateLifecycleComputed; CGPoint absoluteTopLeft = { - absolutePosition.x + node->layout.position[CSS_LEFT], - absolutePosition.y + node->layout.position[CSS_TOP] + absolutePosition.x + node->layout.position[CSSPositionLeft], + absolutePosition.y + node->layout.position[CSSPositionTop] }; CGPoint absoluteBottomRight = { - absolutePosition.x + node->layout.position[CSS_LEFT] + node->layout.dimensions[CSS_WIDTH], - absolutePosition.y + node->layout.position[CSS_TOP] + node->layout.dimensions[CSS_HEIGHT] + absolutePosition.x + node->layout.position[CSSPositionLeft] + node->layout.dimensions[CSSDimensionWidth], + absolutePosition.y + node->layout.position[CSSPositionTop] + node->layout.dimensions[CSSDimensionHeight] }; CGRect frame = {{ - RCTRoundPixelValue(node->layout.position[CSS_LEFT]), - RCTRoundPixelValue(node->layout.position[CSS_TOP]), + RCTRoundPixelValue(node->layout.position[CSSPositionLeft]), + RCTRoundPixelValue(node->layout.position[CSSPositionTop]), }, { RCTRoundPixelValue(absoluteBottomRight.x - absoluteTopLeft.x), RCTRoundPixelValue(absoluteBottomRight.y - absoluteTopLeft.y) @@ -156,19 +151,19 @@ - (void)applyLayoutNode:(css_node_t *)node [viewsWithNewFrame addObject:self]; } - absolutePosition.x += node->layout.position[CSS_LEFT]; - absolutePosition.y += node->layout.position[CSS_TOP]; + absolutePosition.x += node->layout.position[CSSPositionLeft]; + absolutePosition.y += node->layout.position[CSSPositionTop]; [self applyLayoutToChildren:node viewsWithNewFrame:viewsWithNewFrame absolutePosition:absolutePosition]; } -- (void)applyLayoutToChildren:(css_node_t *)node +- (void)applyLayoutToChildren:(CSSNode *)node viewsWithNewFrame:(NSMutableSet *)viewsWithNewFrame absolutePosition:(CGPoint)absolutePosition { - for (int i = 0; i < node->children_count; ++i) { + for (int i = 0; i < node->childCount; ++i) { RCTShadowView *child = (RCTShadowView *)_reactSubviews[i]; - [child applyLayoutNode:node->get_child(node->context, i) + [child applyLayoutNode:node->getChild(node->context, i) viewsWithNewFrame:viewsWithNewFrame absolutePosition:absolutePosition]; } @@ -242,19 +237,18 @@ - (void)collectUpdatedFrames:(NSMutableSet *)viewsWithNewFrame } if (!CGRectEqualToRect(frame, _frame)) { - _cssNode->style.position_type = CSS_POSITION_ABSOLUTE; - _cssNode->style.dimensions[CSS_WIDTH] = frame.size.width; - _cssNode->style.dimensions[CSS_HEIGHT] = frame.size.height; - _cssNode->style.position[CSS_LEFT] = frame.origin.x; - _cssNode->style.position[CSS_TOP] = frame.origin.y; + _cssNode->style.positionType = CSSPositionTypeAbsolute; + _cssNode->style.dimensions[CSSDimensionWidth] = frame.size.width; + _cssNode->style.dimensions[CSSDimensionHeight] = frame.size.height; + _cssNode->style.position[CSSPositionLeft] = frame.origin.x; + _cssNode->style.position[CSSPositionTop] = 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; } - [self fillCSSNode:_cssNode]; - layoutNode(_cssNode, frame.size.width, frame.size.height, CSS_DIRECTION_INHERIT); + layoutNode(_cssNode, frame.size.width, frame.size.height, CSSDirectionInherit); [self applyLayoutNode:_cssNode viewsWithNewFrame:viewsWithNewFrame absolutePosition:absolutePosition]; } @@ -279,12 +273,12 @@ - (instancetype)init { if ((self = [super init])) { - _frame = CGRectMake(0, 0, CSS_UNDEFINED, CSS_UNDEFINED); + _frame = CGRectMake(0, 0, CSSUndefined, CSSUndefined); for (unsigned int ii = 0; ii < META_PROP_COUNT; ii++) { - _paddingMetaProps[ii] = CSS_UNDEFINED; - _marginMetaProps[ii] = CSS_UNDEFINED; - _borderMetaProps[ii] = CSS_UNDEFINED; + _paddingMetaProps[ii] = CSSUndefined; + _marginMetaProps[ii] = CSSUndefined; + _borderMetaProps[ii] = CSSUndefined; } _newView = YES; @@ -294,12 +288,11 @@ - (instancetype)init _reactSubviews = [NSMutableArray array]; - _cssNode = new_css_node(); + _cssNode = CSSNodeNew(); _cssNode->context = (__bridge void *)self; _cssNode->print = RCTPrint; - _cssNode->get_child = RCTGetChild; - _cssNode->is_dirty = RCTIsDirty; - [self fillCSSNode:_cssNode]; + _cssNode->getChild = RCTGetChild; + _cssNode->isDirty = RCTIsDirty; } return self; } @@ -311,7 +304,7 @@ - (BOOL)isReactRootView - (void)dealloc { - free_css_node(_cssNode); + CSSNodeFree(_cssNode); } - (void)dirtyLayout @@ -327,6 +320,11 @@ - (BOOL)isLayoutDirty return _layoutLifecycle != RCTUpdateLifecycleComputed; } +- (BOOL)isCSSLeafNode +{ + return NO; +} + - (void)dirtyPropagation { if (_propagationLifecycle != RCTUpdateLifecycleDirtied) { @@ -361,7 +359,7 @@ - (void)setTextComputed - (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)atIndex { [_reactSubviews insertObject:subview atIndex:atIndex]; - _cssNode->children_count = (int)_reactSubviews.count; + _cssNode->childCount = [self isCSSLeafNode] ? 0 : (int)_reactSubviews.count; subview->_superview = self; _didUpdateSubviews = YES; [self dirtyText]; @@ -377,7 +375,7 @@ - (void)removeReactSubview:(RCTShadowView *)subview _didUpdateSubviews = YES; subview->_superview = nil; [_reactSubviews removeObject:subview]; - _cssNode->children_count = (int)_reactSubviews.count; + _cssNode->childCount = [self isCSSLeafNode] ? 0 : (int)_reactSubviews.count; } - (NSArray *)reactSubviews @@ -477,10 +475,10 @@ - (CGFloat)padding##prop \ - (UIEdgeInsets)paddingAsInsets { return (UIEdgeInsets){ - _cssNode->style.padding[CSS_TOP], - _cssNode->style.padding[CSS_LEFT], - _cssNode->style.padding[CSS_BOTTOM], - _cssNode->style.padding[CSS_RIGHT] + _cssNode->style.padding[CSSPositionTop], + _cssNode->style.padding[CSSPositionLeft], + _cssNode->style.padding[CSSPositionBottom], + _cssNode->style.padding[CSSPositionRight] }; } @@ -509,47 +507,47 @@ - (CGFloat)border##prop##Width \ #define RCT_DIMENSION_PROPERTY(setProp, getProp, cssProp, category) \ - (void)set##setProp:(CGFloat)value \ { \ - _cssNode->style.category[CSS_##cssProp] = value; \ + _cssNode->style.category[CSS##cssProp] = value; \ [self dirtyLayout]; \ [self dirtyText]; \ } \ - (CGFloat)getProp \ { \ - return _cssNode->style.category[CSS_##cssProp]; \ + return _cssNode->style.category[CSS##cssProp]; \ } -RCT_DIMENSION_PROPERTY(Width, width, WIDTH, dimensions) -RCT_DIMENSION_PROPERTY(Height, height, HEIGHT, dimensions) +RCT_DIMENSION_PROPERTY(Width, width, DimensionWidth, dimensions) +RCT_DIMENSION_PROPERTY(Height, height, DimensionHeight, dimensions) -RCT_DIMENSION_PROPERTY(MinWidth, minWidth, WIDTH, minDimensions) -RCT_DIMENSION_PROPERTY(MaxWidth, maxWidth, WIDTH, maxDimensions) -RCT_DIMENSION_PROPERTY(MinHeight, minHeight, HEIGHT, minDimensions) -RCT_DIMENSION_PROPERTY(MaxHeight, maxHeight, HEIGHT, maxDimensions) +RCT_DIMENSION_PROPERTY(MinWidth, minWidth, DimensionWidth, minDimensions) +RCT_DIMENSION_PROPERTY(MaxWidth, maxWidth, DimensionWidth, maxDimensions) +RCT_DIMENSION_PROPERTY(MinHeight, minHeight, DimensionHeight, minDimensions) +RCT_DIMENSION_PROPERTY(MaxHeight, maxHeight, DimensionHeight, maxDimensions) // Position #define RCT_POSITION_PROPERTY(setProp, getProp, cssProp) \ RCT_DIMENSION_PROPERTY(setProp, getProp, cssProp, position) -RCT_POSITION_PROPERTY(Top, top, TOP) -RCT_POSITION_PROPERTY(Right, right, RIGHT) -RCT_POSITION_PROPERTY(Bottom, bottom, BOTTOM) -RCT_POSITION_PROPERTY(Left, left, LEFT) +RCT_POSITION_PROPERTY(Top, top, PositionTop) +RCT_POSITION_PROPERTY(Right, right, PositionRight) +RCT_POSITION_PROPERTY(Bottom, bottom, PositionBottom) +RCT_POSITION_PROPERTY(Left, left, PositionLeft) - (void)setFrame:(CGRect)frame { - _cssNode->style.position[CSS_LEFT] = CGRectGetMinX(frame); - _cssNode->style.position[CSS_TOP] = CGRectGetMinY(frame); - _cssNode->style.dimensions[CSS_WIDTH] = CGRectGetWidth(frame); - _cssNode->style.dimensions[CSS_HEIGHT] = CGRectGetHeight(frame); + _cssNode->style.position[CSSPositionLeft] = CGRectGetMinX(frame); + _cssNode->style.position[CSSPositionTop] = CGRectGetMinY(frame); + _cssNode->style.dimensions[CSSDimensionWidth] = CGRectGetWidth(frame); + _cssNode->style.dimensions[CSSDimensionHeight] = CGRectGetHeight(frame); [self dirtyLayout]; } -static inline BOOL RCTAssignSuggestedDimension(css_node_t *css_node, int dimension, CGFloat amount) +static inline BOOL RCTAssignSuggestedDimension(CSSNode *cssNode, int dimension, CGFloat amount) { if (amount != UIViewNoIntrinsicMetric - && isnan(css_node->style.dimensions[dimension])) { - css_node->style.dimensions[dimension] = amount; + && isnan(cssNode->style.dimensions[dimension])) { + cssNode->style.dimensions[dimension] = amount; return YES; } return NO; @@ -559,8 +557,8 @@ - (void)setIntrinsicContentSize:(CGSize)size { if (_cssNode->style.flex == 0) { BOOL dirty = NO; - dirty |= RCTAssignSuggestedDimension(_cssNode, CSS_HEIGHT, size.height); - dirty |= RCTAssignSuggestedDimension(_cssNode, CSS_WIDTH, size.width); + dirty |= RCTAssignSuggestedDimension(_cssNode, CSSDimensionHeight, size.height); + dirty |= RCTAssignSuggestedDimension(_cssNode, CSSDimensionWidth, size.width); if (dirty) { [self dirtyLayout]; } @@ -569,15 +567,15 @@ - (void)setIntrinsicContentSize:(CGSize)size - (void)setTopLeft:(CGPoint)topLeft { - _cssNode->style.position[CSS_LEFT] = topLeft.x; - _cssNode->style.position[CSS_TOP] = topLeft.y; + _cssNode->style.position[CSSPositionLeft] = topLeft.x; + _cssNode->style.position[CSSPositionTop] = topLeft.y; [self dirtyLayout]; } - (void)setSize:(CGSize)size { - _cssNode->style.dimensions[CSS_WIDTH] = size.width; - _cssNode->style.dimensions[CSS_HEIGHT] = size.height; + _cssNode->style.dimensions[CSSDimensionWidth] = size.width; + _cssNode->style.dimensions[CSSDimensionHeight] = size.height; [self dirtyLayout]; } @@ -595,12 +593,12 @@ - (type)getProp \ } RCT_STYLE_PROPERTY(Flex, flex, flex, CGFloat) -RCT_STYLE_PROPERTY(FlexDirection, flexDirection, flex_direction, css_flex_direction_t) -RCT_STYLE_PROPERTY(JustifyContent, justifyContent, justify_content, css_justify_t) -RCT_STYLE_PROPERTY(AlignSelf, alignSelf, align_self, css_align_t) -RCT_STYLE_PROPERTY(AlignItems, alignItems, align_items, css_align_t) -RCT_STYLE_PROPERTY(Position, position, position_type, css_position_type_t) -RCT_STYLE_PROPERTY(FlexWrap, flexWrap, flex_wrap, css_wrap_type_t) +RCT_STYLE_PROPERTY(FlexDirection, flexDirection, flexDirection, CSSFlexDirection) +RCT_STYLE_PROPERTY(JustifyContent, justifyContent, justifyContent, CSSJustify) +RCT_STYLE_PROPERTY(AlignSelf, alignSelf, alignSelf, CSSAlign) +RCT_STYLE_PROPERTY(AlignItems, alignItems, alignItems, CSSAlign) +RCT_STYLE_PROPERTY(Position, position, positionType, CSSPositionType) +RCT_STYLE_PROPERTY(FlexWrap, flexWrap, flexWrap, CSSWrapType) - (void)setBackgroundColor:(UIColor *)color { @@ -637,7 +635,6 @@ - (void)didSetProps:(__unused NSArray *)changedProps if (_recomputePadding || _recomputeMargin || _recomputeBorder) { [self dirtyLayout]; } - [self fillCSSNode:_cssNode]; _recomputeMargin = NO; _recomputePadding = NO; _recomputeBorder = NO; diff --git a/React/Views/RCTViewManager.m b/React/Views/RCTViewManager.m index 4b6cb0a0e4d78a..d14cc32a90671c 100644 --- a/React/Views/RCTViewManager.m +++ b/React/Views/RCTViewManager.m @@ -288,12 +288,12 @@ - (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(__unused NSDictio RCT_EXPORT_SHADOW_PROPERTY(padding, CGFloat) RCT_EXPORT_SHADOW_PROPERTY(flex, CGFloat) -RCT_EXPORT_SHADOW_PROPERTY(flexDirection, css_flex_direction_t) -RCT_EXPORT_SHADOW_PROPERTY(flexWrap, css_wrap_type_t) -RCT_EXPORT_SHADOW_PROPERTY(justifyContent, css_justify_t) -RCT_EXPORT_SHADOW_PROPERTY(alignItems, css_align_t) -RCT_EXPORT_SHADOW_PROPERTY(alignSelf, css_align_t) -RCT_EXPORT_SHADOW_PROPERTY(position, css_position_type_t) +RCT_EXPORT_SHADOW_PROPERTY(flexDirection, CSSFlexDirection) +RCT_EXPORT_SHADOW_PROPERTY(flexWrap, CSSWrapType) +RCT_EXPORT_SHADOW_PROPERTY(justifyContent, CSSJustify) +RCT_EXPORT_SHADOW_PROPERTY(alignItems, CSSAlign) +RCT_EXPORT_SHADOW_PROPERTY(alignSelf, CSSAlign) +RCT_EXPORT_SHADOW_PROPERTY(position, CSSPositionType) RCT_EXPORT_SHADOW_PROPERTY(onLayout, RCTDirectEventBlock) diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index 7a142cefe04c2c..52dd2258899967 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -269,10 +269,10 @@ dependencies { compile 'com.facebook.soloader:soloader:0.1.0' compile 'com.fasterxml.jackson.core:jackson-core:2.2.3' compile 'com.google.code.findbugs:jsr305:3.0.0' - compile 'com.squareup.okhttp3:okhttp:3.2.0' - compile 'com.squareup.okhttp3:okhttp-urlconnection:3.2.0' - compile 'com.squareup.okhttp3:okhttp-ws:3.2.0' - compile 'com.squareup.okio:okio:1.8.0' + compile 'com.squareup.okhttp3:okhttp:3.4.1' + compile 'com.squareup.okhttp3:okhttp-urlconnection:3.4.1' + compile 'com.squareup.okhttp3:okhttp-ws:3.4.1' + compile 'com.squareup.okio:okio:1.9.0' compile 'org.webkit:android-jsc:r174650' testCompile "junit:junit:${JUNIT_VERSION}" diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK index f052dc129744b9..b9ba1265462874 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK @@ -3,7 +3,6 @@ include_defs('//ReactAndroid/DEFS') # Tests that are too flaky to run on SandCastle # TODO t11057216 stabilise them SANDCASTLE_FLAKY = [ - 'ReactScrollViewTestCase.java', ] deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/toast/ToastModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/toast/ToastModule.java index af128a96149532..243c917a6fe207 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/toast/ToastModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/toast/ToastModule.java @@ -9,11 +9,11 @@ package com.facebook.react.modules.toast; +import android.view.Gravity; import android.widget.Toast; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.common.MapBuilder; @@ -29,6 +29,10 @@ public class ToastModule extends ReactContextBaseJavaModule { private static final String DURATION_SHORT_KEY = "SHORT"; private static final String DURATION_LONG_KEY = "LONG"; + private static final String GRAVITY_TOP_KEY = "TOP"; + private static final String GRAVITY_BOTTOM_KEY = "BOTTOM"; + private static final String GRAVITY_CENTER = "CENTER"; + public ToastModule(ReactApplicationContext reactContext) { super(reactContext); } @@ -43,6 +47,9 @@ public Map getConstants() { final Map constants = MapBuilder.newHashMap(); constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT); constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG); + constants.put(GRAVITY_TOP_KEY, Gravity.TOP | Gravity.CENTER_HORIZONTAL); + constants.put(GRAVITY_BOTTOM_KEY, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL); + constants.put(GRAVITY_CENTER, Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL); return constants; } @@ -50,9 +57,21 @@ public Map getConstants() { public void show(final String message, final int duration) { UiThreadUtil.runOnUiThread(new Runnable() { @Override - public void run(){ + public void run() { Toast.makeText(getReactApplicationContext(), message, duration).show(); } }); } + + @ReactMethod + public void showWithGravity(final String message, final int duration, final int gravity) { + UiThreadUtil.runOnUiThread(new Runnable() { + @Override + public void run() { + Toast toast = Toast.makeText(getReactApplicationContext(), message, duration); + toast.setGravity(gravity, 0, 0); + toast.show(); + } + }); + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyOptimizer.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyOptimizer.java index 7b9741bd8ddbd5..2d921bb0f1c230 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyOptimizer.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyOptimizer.java @@ -52,6 +52,16 @@ */ public class NativeViewHierarchyOptimizer { + private static class NodeIndexPair { + public final ReactShadowNode node; + public final int index; + + NodeIndexPair(ReactShadowNode node, int index) { + this.node = node; + this.index = index; + } + } + private static final boolean ENABLED = true; private final UIViewOperationQueue mUIViewOperationQueue; @@ -221,21 +231,39 @@ public void onBatchComplete() { mTagsWithLayoutVisited.clear(); } + private NodeIndexPair walkUpUntilNonLayoutOnly( + ReactShadowNode node, + int indexInNativeChildren) { + while (node.isLayoutOnly()) { + ReactShadowNode parent = node.getParent(); + if (parent == null) { + return null; + } + + indexInNativeChildren = indexInNativeChildren + parent.getNativeOffsetForChild(node); + node = parent; + } + + return new NodeIndexPair(node, indexInNativeChildren); + } + private void addNodeToNode(ReactShadowNode parent, ReactShadowNode child, int index) { int indexInNativeChildren = parent.getNativeOffsetForChild(parent.getChildAt(index)); - boolean parentIsLayoutOnly = parent.isLayoutOnly(); - boolean childIsLayoutOnly = child.isLayoutOnly(); - - // Switch on the four cases of: - // add (layout-only|not layout-only) to (layout-only|not layout-only) - if (!parentIsLayoutOnly && !childIsLayoutOnly) { - addNonLayoutNodeToNonLayoutNode(parent, child, indexInNativeChildren); - } else if (!childIsLayoutOnly) { - addNonLayoutOnlyNodeToLayoutOnlyNode(parent, child, indexInNativeChildren); - } else if (!parentIsLayoutOnly) { - addLayoutOnlyNodeToNonLayoutOnlyNode(parent, child, indexInNativeChildren); + if (parent.isLayoutOnly()) { + NodeIndexPair result = walkUpUntilNonLayoutOnly(parent, indexInNativeChildren); + if (result == null) { + // If the parent hasn't been attached to its native parent yet, don't issue commands to the + // native hierarchy. We'll do that when the parent node actually gets attached somewhere. + return; + } + parent = result.node; + indexInNativeChildren = result.index; + } + + if (!child.isLayoutOnly()) { + addNonLayoutNode(parent, child, indexInNativeChildren); } else { - addLayoutOnlyNodeToLayoutOnlyNode(parent, child, indexInNativeChildren); + addLayoutOnlyNode(parent, child, indexInNativeChildren); } } @@ -262,73 +290,14 @@ private void removeNodeFromParent(ReactShadowNode nodeToRemove, boolean shouldDe } } - private void addLayoutOnlyNodeToLayoutOnlyNode( - ReactShadowNode parent, - ReactShadowNode child, - int index) { - ReactShadowNode parentParent = parent.getParent(); - - // If the parent hasn't been attached to its parent yet, don't issue commands to the native - // hierarchy. We'll do that when the parent node actually gets attached somewhere. - if (parentParent == null) { - return; - } - - int transformedIndex = index + parentParent.getNativeOffsetForChild(parent); - if (parentParent.isLayoutOnly()) { - addLayoutOnlyNodeToLayoutOnlyNode(parentParent, child, transformedIndex); - } else { - addLayoutOnlyNodeToNonLayoutOnlyNode(parentParent, child, transformedIndex); - } - } - - private void addNonLayoutOnlyNodeToLayoutOnlyNode( - ReactShadowNode layoutOnlyNode, - ReactShadowNode nonLayoutOnlyNode, - int index) { - ReactShadowNode parent = layoutOnlyNode.getParent(); - - // If the parent hasn't been attached to its parent yet, don't issue commands to the native - // hierarchy. We'll do that when the parent node actually gets attached somewhere. - if (parent == null) { - return; - } - - int transformedIndex = index + parent.getNativeOffsetForChild(layoutOnlyNode); - if (parent.isLayoutOnly()) { - addNonLayoutOnlyNodeToLayoutOnlyNode(parent, nonLayoutOnlyNode, transformedIndex); - } else { - addNonLayoutNodeToNonLayoutNode(parent, nonLayoutOnlyNode, transformedIndex); - } - } - - private void addLayoutOnlyNodeToNonLayoutOnlyNode( + private void addLayoutOnlyNode( ReactShadowNode nonLayoutOnlyNode, ReactShadowNode layoutOnlyNode, int index) { - // Add all of the layout-only node's children to its parent instead - int currentIndex = index; - for (int i = 0; i < layoutOnlyNode.getChildCount(); i++) { - ReactShadowNode childToAdd = layoutOnlyNode.getChildAt(i); - Assertions.assertCondition(childToAdd.getNativeParent() == null); - - if (childToAdd.isLayoutOnly()) { - // Adding this layout-only child could result in adding multiple native views - int childCountBefore = nonLayoutOnlyNode.getNativeChildCount(); - addLayoutOnlyNodeToNonLayoutOnlyNode( - nonLayoutOnlyNode, - childToAdd, - currentIndex); - int childCountAfter = nonLayoutOnlyNode.getNativeChildCount(); - currentIndex += childCountAfter - childCountBefore; - } else { - addNonLayoutNodeToNonLayoutNode(nonLayoutOnlyNode, childToAdd, currentIndex); - currentIndex++; - } - } + addGrandchildren(nonLayoutOnlyNode, layoutOnlyNode, index); } - private void addNonLayoutNodeToNonLayoutNode( + private void addNonLayoutNode( ReactShadowNode parent, ReactShadowNode child, int index) { @@ -340,6 +309,31 @@ private void addNonLayoutNodeToNonLayoutNode( null); } + private void addGrandchildren( + ReactShadowNode nativeParent, + ReactShadowNode child, + int index) { + Assertions.assertCondition(!nativeParent.isLayoutOnly()); + + // `child` can't hold native children. Add all of `child`'s children to `parent`. + int currentIndex = index; + for (int i = 0; i < child.getChildCount(); i++) { + ReactShadowNode grandchild = child.getChildAt(i); + Assertions.assertCondition(grandchild.getNativeParent() == null); + + if (grandchild.isLayoutOnly()) { + // Adding this child could result in adding multiple native views + int grandchildCountBefore = nativeParent.getNativeChildCount(); + addLayoutOnlyNode(nativeParent, grandchild, currentIndex); + int grandchildCountAfter = nativeParent.getNativeChildCount(); + currentIndex += grandchildCountAfter - grandchildCountBefore; + } else { + addNonLayoutNode(nativeParent, grandchild, currentIndex); + currentIndex++; + } + } + } + private void applyLayoutBase(ReactShadowNode node) { int tag = node.getReactTag(); if (mTagsWithLayoutVisited.get(tag)) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java index ae623bf0e69763..5178281a1d8c7a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java @@ -190,12 +190,17 @@ protected static Spannable fromTextCSSNode(ReactTextShadowNode textCSSNode) { } textCSSNode.mContainsImages = false; + textCSSNode.mHeightOfTallestInlineImage = Float.NaN; // While setting the Spans on the final text, we also check whether any of them are images for (int i = ops.size() - 1; i >= 0; i--) { SetSpanOperation op = ops.get(i); if (op.what instanceof TextInlineImageSpan) { + int height = ((TextInlineImageSpan)op.what).getHeight(); textCSSNode.mContainsImages = true; + if (Float.isNaN(textCSSNode.mHeightOfTallestInlineImage) || height > textCSSNode.mHeightOfTallestInlineImage) { + textCSSNode.mHeightOfTallestInlineImage = height; + } } op.execute(sb); } @@ -226,6 +231,14 @@ public void measure( // technically, width should never be negative, but there is currently a bug in boolean unconstrainedWidth = widthMode == CSSMeasureMode.UNDEFINED || width < 0; + float effectiveLineHeight = reactCSSNode.getEffectiveLineHeight(); + float lineSpacingExtra = 0; + float lineSpacingMultiplier = 1; + if (!Float.isNaN(effectiveLineHeight)) { + lineSpacingExtra = effectiveLineHeight; + lineSpacingMultiplier = 0; + } + if (boring == null && (unconstrainedWidth || (!CSSConstants.isUndefined(desiredWidth) && desiredWidth <= width))) { @@ -236,8 +249,8 @@ public void measure( textPaint, (int) Math.ceil(desiredWidth), Layout.Alignment.ALIGN_NORMAL, - 1, - 0, + lineSpacingMultiplier, + lineSpacingExtra, true); } else if (boring != null && (unconstrainedWidth || boring.width <= width)) { // Is used for single-line, boring text when the width is either unknown or bigger @@ -247,8 +260,8 @@ public void measure( textPaint, boring.width, Layout.Alignment.ALIGN_NORMAL, - 1, - 0, + lineSpacingMultiplier, + lineSpacingExtra, boring, true); } else { @@ -258,8 +271,8 @@ public void measure( textPaint, (int) width, Layout.Alignment.ALIGN_NORMAL, - 1, - 0, + lineSpacingMultiplier, + lineSpacingExtra, true); } @@ -269,13 +282,6 @@ public void measure( reactCSSNode.mNumberOfLines < layout.getLineCount()) { measureOutput.height = layout.getLineBottom(reactCSSNode.mNumberOfLines - 1); } - if (reactCSSNode.mLineHeight != UNSET) { - int lines = reactCSSNode.mNumberOfLines != UNSET - ? Math.min(reactCSSNode.mNumberOfLines, layout.getLineCount()) - : layout.getLineCount(); - float lineHeight = PixelUtil.toPixelFromSP(reactCSSNode.mLineHeight); - measureOutput.height = lineHeight * lines; - } } }; @@ -293,7 +299,7 @@ private static int parseNumericFontWeight(String fontWeightString) { 100 * (fontWeightString.charAt(0) - '0') : -1; } - private int mLineHeight = UNSET; + private float mLineHeight = Float.NaN; private boolean mIsColorSet = false; private int mColor; private boolean mIsBackgroundColorSet = false; @@ -340,6 +346,7 @@ private static int parseNumericFontWeight(String fontWeightString) { private final boolean mIsVirtual; protected boolean mContainsImages = false; + private float mHeightOfTallestInlineImage = Float.NaN; public ReactTextShadowNode(boolean isVirtual) { mIsVirtual = isVirtual; @@ -348,6 +355,15 @@ public ReactTextShadowNode(boolean isVirtual) { } } + // Returns a line height which takes into account the requested line height + // and the height of the inline images. + public float getEffectiveLineHeight() { + boolean useInlineViewHeight = !Float.isNaN(mLineHeight) && + !Float.isNaN(mHeightOfTallestInlineImage) && + mHeightOfTallestInlineImage > mLineHeight; + return useInlineViewHeight ? mHeightOfTallestInlineImage : mLineHeight; + } + @Override public void onBeforeLayout() { if (mIsVirtual) { @@ -380,7 +396,7 @@ public void setNumberOfLines(int numberOfLines) { @ReactProp(name = ViewProps.LINE_HEIGHT, defaultInt = UNSET) public void setLineHeight(int lineHeight) { - mLineHeight = lineHeight; + mLineHeight = lineHeight == UNSET ? Float.NaN : PixelUtil.toPixelFromSP(lineHeight); markUpdated(); } @@ -530,7 +546,7 @@ public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) { super.onCollectExtraUpdates(uiViewOperationQueue); if (mPreparedSpannableText != null) { ReactTextUpdate reactTextUpdate = - new ReactTextUpdate(mPreparedSpannableText, UNSET, mContainsImages, getPadding()); + new ReactTextUpdate(mPreparedSpannableText, UNSET, mContainsImages, getPadding(), getEffectiveLineHeight()); uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), reactTextUpdate); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java index dca68669d1d72e..5acb167c56acf0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java @@ -27,12 +27,14 @@ public class ReactTextUpdate { private final float mPaddingTop; private final float mPaddingRight; private final float mPaddingBottom; + private final float mLineHeight; public ReactTextUpdate( Spannable text, int jsEventCounter, boolean containsImages, - Spacing padding) { + Spacing padding, + float lineHeight) { mText = text; mJsEventCounter = jsEventCounter; mContainsImages = containsImages; @@ -40,6 +42,7 @@ public ReactTextUpdate( mPaddingTop = padding.get(Spacing.TOP); mPaddingRight = padding.get(Spacing.RIGHT); mPaddingBottom = padding.get(Spacing.BOTTOM); + mLineHeight = lineHeight; } public Spannable getText() { @@ -69,4 +72,8 @@ public float getPaddingRight() { public float getPaddingBottom() { return mPaddingBottom; } + + public float getLineHeight() { + return mLineHeight; + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index 71bb5ccf10d245..9ef3df91a8ab58 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -17,6 +17,7 @@ import android.view.ViewGroup; import android.widget.TextView; +import com.facebook.csslayout.FloatUtil; import com.facebook.react.uimanager.ReactCompoundView; public class ReactTextView extends TextView implements ReactCompoundView { @@ -28,6 +29,7 @@ public class ReactTextView extends TextView implements ReactCompoundView { private int mDefaultGravityHorizontal; private int mDefaultGravityVertical; private boolean mTextIsSelectable; + private float mLineHeight = Float.NaN; public ReactTextView(Context context) { super(context); @@ -50,6 +52,16 @@ public void setText(ReactTextUpdate update) { (int) Math.ceil(update.getPaddingTop()), (int) Math.ceil(update.getPaddingRight()), (int) Math.ceil(update.getPaddingBottom())); + + float nextLineHeight = update.getLineHeight(); + if (!FloatUtil.floatsEqual(mLineHeight, nextLineHeight)) { + mLineHeight = nextLineHeight; + if (Float.isNaN(mLineHeight)) { // NaN will be used if property gets reset + setLineSpacing(0, 1); + } else { + setLineSpacing(mLineHeight, 0); + } + } } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java index 97e780a6d0f59e..dc200c1fcb7a74 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java @@ -103,15 +103,6 @@ public void setTextAlignVertical(ReactTextView view, @Nullable String textAlignV } } - @ReactProp(name = ViewProps.LINE_HEIGHT, defaultFloat = Float.NaN) - public void setLineHeight(ReactTextView view, float lineHeight) { - if (Float.isNaN(lineHeight)) { // NaN will be used if property gets reset - view.setLineSpacing(0, 1); - } else { - view.setLineSpacing(PixelUtil.toPixelFromSP(lineHeight), 0); - } - } - @ReactProp(name = "selectable") public void setSelectable(ReactTextView view, boolean isSelectable) { view.setTextIsSelectable(isSelectable); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextInlineImageSpan.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextInlineImageSpan.java index 0308ee20c28c87..c987260fd0f380 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextInlineImageSpan.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextInlineImageSpan.java @@ -67,4 +67,14 @@ public static void possiblyUpdateInlineImageSpans(Spannable spannable, TextView * Set the textview that will contain this span. */ public abstract void setTextView(TextView textView); + + /** + * Get the width of the span. + */ + public abstract int getWidth(); + + /** + * Get the height of the span. + */ + public abstract int getHeight(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/FrescoBasedReactTextInlineImageSpan.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/FrescoBasedReactTextInlineImageSpan.java index 0613457e59f7b2..0c0c5c1246768c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/FrescoBasedReactTextInlineImageSpan.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/FrescoBasedReactTextInlineImageSpan.java @@ -146,13 +146,21 @@ public void draw( canvas.save(); - int transY = bottom - mDrawable.getBounds().bottom; - // Align to baseline by default - transY -= paint.getFontMetricsInt().descent; + int transY = y - mDrawable.getBounds().bottom; canvas.translate(x, transY); mDrawable.draw(canvas); canvas.restore(); } + + @Override + public int getWidth() { + return mWidth; + } + + @Override + public int getHeight() { + return mHeight; + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java index c75e9797beda38..cc71f6b88c13b0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java @@ -119,7 +119,7 @@ public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) { if (mJsEventCount != UNSET) { Spannable preparedSpannableText = fromTextCSSNode(this); ReactTextUpdate reactTextUpdate = - new ReactTextUpdate(preparedSpannableText, mJsEventCount, mContainsImages, getPadding()); + new ReactTextUpdate(preparedSpannableText, mJsEventCount, mContainsImages, getPadding(), getEffectiveLineHeight()); uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), reactTextUpdate); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java index 3ed60497b8886a..9f4c5a7adf727c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java @@ -18,6 +18,7 @@ import android.graphics.Bitmap; import android.os.Build; import android.text.TextUtils; +import android.webkit.GeolocationPermissions; import android.webkit.WebView; import android.webkit.WebViewClient; import android.webkit.WebChromeClient; @@ -259,7 +260,12 @@ public String getName() { @Override protected WebView createViewInstance(ThemedReactContext reactContext) { ReactWebView webView = new ReactWebView(reactContext); - webView.setWebChromeClient(new WebChromeClient()); + webView.setWebChromeClient(new WebChromeClient() { + @Override + public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { + callback.invoke(origin, true, false); + } + }); reactContext.addLifecycleEventListener(webView); mWebViewConfig.configWebView(webView); webView.getSettings().setBuiltInZoomControls(true); diff --git a/ReactAndroid/src/main/third-party/java/okhttp/BUCK b/ReactAndroid/src/main/third-party/java/okhttp/BUCK index 07d870bdbbe52d..a6d9925259e7f6 100644 --- a/ReactAndroid/src/main/third-party/java/okhttp/BUCK +++ b/ReactAndroid/src/main/third-party/java/okhttp/BUCK @@ -6,8 +6,8 @@ prebuilt_jar( remote_file( name = 'okhttp3-binary-jar', - url = 'mvn:com.squareup.okhttp3:okhttp:jar:3.2.0', - sha1 = 'f7873a2ebde246a45c2a8d6f3247108b4c88a879' + url = 'mvn:com.squareup.okhttp3:okhttp:jar:3.4.1', + sha1 = 'c7c4f9e35c2fd5900da24f9872e3971801f08ce0' ) prebuilt_jar( @@ -18,8 +18,8 @@ prebuilt_jar( remote_file( name = 'okhttp3-urlconnection-binary-jar', - url = 'mvn:com.squareup.okhttp3:okhttp-urlconnection:jar:3.2.0', - sha1 = '6f8a4b1435c9e0a6f9c5fe4a1be46627b848fd0c' + url = 'mvn:com.squareup.okhttp3:okhttp-urlconnection:jar:3.4.1', + sha1 = '63994437f62bc861bc20c605d12962f7246116d1' ) prebuilt_jar( @@ -30,6 +30,6 @@ prebuilt_jar( remote_file( name = 'okhttp3-ws-binary-jar', - url = 'mvn:com.squareup.okhttp3:okhttp-ws:jar:3.2.0', - sha1 = '1ea229d6984444c8c58b8e97ba4c8429d9d135b3', + url = 'mvn:com.squareup.okhttp3:okhttp-ws:jar:3.4.1', + sha1 = '8ace66ef7002d98f633377c9e67daeeb196d8c3b', ) diff --git a/ReactAndroid/src/main/third-party/java/okio/BUCK b/ReactAndroid/src/main/third-party/java/okio/BUCK index 3f3339840c4265..900a79732a3541 100644 --- a/ReactAndroid/src/main/third-party/java/okio/BUCK +++ b/ReactAndroid/src/main/third-party/java/okio/BUCK @@ -6,6 +6,6 @@ prebuilt_jar( remote_file( name = 'okio-binary-jar', - url = 'mvn:com.squareup.okio:okio:jar:1.8.0', - sha1 = '05ea7af56cc7c567ed9856d99efb30740e9b17ff', + url = 'mvn:com.squareup.okio:okio:jar:1.9.0', + sha1 = 'f824591a0016efbaeddb8300bee54832a1398cfa', ) diff --git a/ReactCommon/cxxreact/JSCExecutor.cpp b/ReactCommon/cxxreact/JSCExecutor.cpp index 25efa9f3ecb120..42967be0c879d2 100644 --- a/ReactCommon/cxxreact/JSCExecutor.cpp +++ b/ReactCommon/cxxreact/JSCExecutor.cpp @@ -596,7 +596,7 @@ JSValueRef JSCExecutor::nativeRequireModuleConfig( std::string moduleName = Value(m_context, arguments[0]).toString().str(); folly::dynamic config = m_delegate->getModuleConfig(moduleName); - return JSValueMakeString(m_context, String(folly::toJson(config).c_str())); + return Value::fromDynamic(m_context, config); } JSValueRef JSCExecutor::nativeFlushQueueImmediate( @@ -681,7 +681,7 @@ JSValueRef JSCExecutor::nativeCallSyncHook( if (result.isUndefined) { return JSValueMakeUndefined(m_context); } - return Value::fromJSON(m_context, String(folly::toJson(result.result).c_str())); + return Value::fromDynamic(m_context, result.result); } static JSValueRef nativeInjectHMRUpdate( diff --git a/ReactCommon/cxxreact/Value.cpp b/ReactCommon/cxxreact/Value.cpp index c328701ec362d3..7bc40b20fd6e45 100644 --- a/ReactCommon/cxxreact/Value.cpp +++ b/ReactCommon/cxxreact/Value.cpp @@ -6,6 +6,9 @@ #include "JSCHelpers.h" +// See the comment under Value::fromDynamic() +#define USE_FAST_FOLLY_DYNAMIC_CONVERSION !defined(__APPLE__) && defined(WITH_FB_JSC_TUNING) + namespace facebook { namespace react { @@ -51,9 +54,78 @@ Value Value::fromJSON(JSContextRef ctx, const String& json) throw(JSException) { return Value(ctx, result); } -Value Value::fromDynamic(JSContextRef ctx, folly::dynamic value) throw(JSException) { +JSValueRef Value::fromDynamic(JSContextRef ctx, const folly::dynamic& value) { +// JavaScriptCore's iOS APIs have their own version of this direct conversion. +// In addition, using this requires exposing some of JSC's private APIs, +// so it's limited to non-apple platforms and to builds that use the custom JSC. +// Otherwise, we use the old way of converting through JSON. +#if USE_FAST_FOLLY_DYNAMIC_CONVERSION + // Defer GC during the creation of the JSValue, as we don't want + // intermediate objects to be collected. + // We could use JSValueProtect(), but it will make the process much slower. + JSDeferredGCRef deferGC = JSDeferGarbageCollection(ctx); + // Set a global lock for the whole process, + // instead of re-acquiring the lock for each operation. + JSLock(ctx); + JSValueRef jsVal = Value::fromDynamicInner(ctx, value); + JSUnlock(ctx); + JSResumeGarbageCollection(ctx, deferGC); + return jsVal; +#else auto json = folly::toJson(value); return fromJSON(ctx, String(json.c_str())); +#endif +} + +JSValueRef Value::fromDynamicInner(JSContextRef ctx, const folly::dynamic& obj) { + switch (obj.type()) { + // For premitive types (and strings), just create and return an equivalent JSValue + case folly::dynamic::Type::NULLT: + return JSValueMakeNull(ctx); + + case folly::dynamic::Type::BOOL: + return JSValueMakeBoolean(ctx, obj.getBool()); + + case folly::dynamic::Type::DOUBLE: + return JSValueMakeNumber(ctx, obj.getDouble()); + + case folly::dynamic::Type::INT64: + return JSValueMakeNumber(ctx, obj.asDouble()); + + case folly::dynamic::Type::STRING: + return JSValueMakeString(ctx, String(obj.getString().c_str())); + + case folly::dynamic::Type::ARRAY: { + // Collect JSValue for every element in the array + JSValueRef vals[obj.size()]; + for (size_t i = 0; i < obj.size(); ++i) { + vals[i] = fromDynamicInner(ctx, obj[i]); + } + // Create a JSArray with the values + JSValueRef arr = JSObjectMakeArray(ctx, obj.size(), vals, nullptr); + return arr; + } + + case folly::dynamic::Type::OBJECT: { + // Create an empty object + JSObjectRef jsObj = JSObjectMake(ctx, nullptr, nullptr); + // Create a JSValue for each of the object's children and set them in the object + for (auto it = obj.items().begin(); it != obj.items().end(); ++it) { + JSObjectSetProperty( + ctx, + jsObj, + String(it->first.asString().c_str()), + fromDynamicInner(ctx, it->second), + kJSPropertyAttributeNone, + nullptr); + } + return jsObj; + } + default: + // Assert not reached + LOG(FATAL) << "Trying to convert a folly object of unsupported type."; + return JSValueMakeNull(ctx); + } } Object Value::asObject() { diff --git a/ReactCommon/cxxreact/Value.h b/ReactCommon/cxxreact/Value.h index 1aa965e9c31415..044f3a52256f8a 100644 --- a/ReactCommon/cxxreact/Value.h +++ b/ReactCommon/cxxreact/Value.h @@ -284,11 +284,12 @@ class Value : public noncopyable { std::string toJSONString(unsigned indent = 0) const throw(JSException); static Value fromJSON(JSContextRef ctx, const String& json) throw(JSException); - static Value fromDynamic(JSContextRef ctx, folly::dynamic value) throw(JSException); + static JSValueRef fromDynamic(JSContextRef ctx, const folly::dynamic& value); JSContextRef context() const; protected: JSContextRef m_context; JSValueRef m_value; + static JSValueRef fromDynamicInner(JSContextRef ctx, const folly::dynamic& obj); }; } }