From 702c14bdf2556e14c370e100e9e48cd5ce02cec3 Mon Sep 17 00:00:00 2001 From: Konstantin Raev Date: Wed, 20 Jul 2016 02:46:38 -0700 Subject: [PATCH 01/12] Enabled Vertical ScrollView instrumentation test in SandCastle Reviewed By: emilsjolander Differential Revision: D3588423 fbshipit-source-id: ad2486b3da5fe7972e4ea9409a729d2ba2483782 --- ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK | 1 - 1 file changed, 1 deletion(-) 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 = [ From 102577565abb97530d73ec516daf8eb1c9120f33 Mon Sep 17 00:00:00 2001 From: Emil Sjolander Date: Wed, 20 Jul 2016 02:49:09 -0700 Subject: [PATCH 02/12] Remove fillCSSNode method Summary: fillCSSNode was only ever used in RCTShadowView to set the child count which is already performed in insert/remove subview calls and in RCTShadowText is was used to set the measure function which can be done in the initializer instead. Reviewed By: majak, javache Differential Revision: D3586418 fbshipit-source-id: de2155daf0f1702c8977bf23183a3b6a650d016b --- Libraries/Text/RCTShadowText.m | 8 +------- React/Views/RCTRootShadowView.m | 1 - React/Views/RCTShadowView.h | 1 - React/Views/RCTShadowView.m | 8 -------- 4 files changed, 1 insertion(+), 17 deletions(-) diff --git a/Libraries/Text/RCTShadowText.m b/Libraries/Text/RCTShadowText.m index 32e73997facaa7..edc8d0a8c938f8 100644 --- a/Libraries/Text/RCTShadowText.m +++ b/Libraries/Text/RCTShadowText.m @@ -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 @@ -442,13 +443,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]; diff --git a/React/Views/RCTRootShadowView.m b/React/Views/RCTRootShadowView.m index e012358966aa37..965025e2876d7f 100644 --- a/React/Views/RCTRootShadowView.m +++ b/React/Views/RCTRootShadowView.m @@ -49,7 +49,6 @@ - (void)applySizeConstraints { [self applySizeConstraints]; - [self fillCSSNode:self.cssNode]; layoutNode(self.cssNode, CSS_UNDEFINED, CSS_UNDEFINED, CSS_DIRECTION_INHERIT); NSMutableSet *viewsWithNewFrame = [NSMutableSet set]; diff --git a/React/Views/RCTShadowView.h b/React/Views/RCTShadowView.h index b76e3000da95c0..6c5bbf17c6320a 100644 --- a/React/Views/RCTShadowView.h +++ b/React/Views/RCTShadowView.h @@ -186,7 +186,6 @@ typedef void (^RCTApplierBlock)(NSDictionary *viewRegistry /** * 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; diff --git a/React/Views/RCTShadowView.m b/React/Views/RCTShadowView.m index 2ff78efc187a2e..a8cd30ae551804 100644 --- a/React/Views/RCTShadowView.m +++ b/React/Views/RCTShadowView.m @@ -89,11 +89,6 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st : 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: // @@ -253,7 +248,6 @@ - (void)collectUpdatedFrames:(NSMutableSet *)viewsWithNewFrame _layoutLifecycle = RCTUpdateLifecycleDirtied; } - [self fillCSSNode:_cssNode]; layoutNode(_cssNode, frame.size.width, frame.size.height, CSS_DIRECTION_INHERIT); [self applyLayoutNode:_cssNode viewsWithNewFrame:viewsWithNewFrame absolutePosition:absolutePosition]; } @@ -299,7 +293,6 @@ - (instancetype)init _cssNode->print = RCTPrint; _cssNode->get_child = RCTGetChild; _cssNode->is_dirty = RCTIsDirty; - [self fillCSSNode:_cssNode]; } return self; } @@ -637,7 +630,6 @@ - (void)didSetProps:(__unused NSArray *)changedProps if (_recomputePadding || _recomputeMargin || _recomputeBorder) { [self dirtyLayout]; } - [self fillCSSNode:_cssNode]; _recomputeMargin = NO; _recomputePadding = NO; _recomputeBorder = NO; From 0587c85094eadc11f97914e14f158ab1332e4861 Mon Sep 17 00:00:00 2001 From: Emil Sjolander Date: Wed, 20 Jul 2016 02:49:13 -0700 Subject: [PATCH 03/12] Add [RCTShadowView isCSSLeaf] for skipping css tree of children Summary: RCTShadowText currently overrides a couple methods from RCTShadowView to reset the count of the cssNode children to 0. This diff instead moves that logic into RCTShadowView behind a configurable flag making it easier to reason about. Reviewed By: javache Differential Revision: D3586434 fbshipit-source-id: 4389a8119dc49e3fc4357174c87c0c69287ae385 --- Libraries/Text/RCTShadowText.m | 17 +++++------------ React/Views/RCTShadowView.h | 7 +++++++ React/Views/RCTShadowView.m | 9 +++++++-- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Libraries/Text/RCTShadowText.m b/Libraries/Text/RCTShadowText.m index edc8d0a8c938f8..a9a5727602bd58 100644 --- a/Libraries/Text/RCTShadowText.m +++ b/Libraries/Text/RCTShadowText.m @@ -81,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]; @@ -443,18 +448,6 @@ - (void)_setParagraphStyleOnAttributedString:(NSMutableAttributedString *)attrib } } -- (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/React/Views/RCTShadowView.h b/React/Views/RCTShadowView.h index 6c5bbf17c6320a..f6f149d819c185 100644 --- a/React/Views/RCTShadowView.h +++ b/React/Views/RCTShadowView.h @@ -189,6 +189,13 @@ typedef void (^RCTApplierBlock)(NSDictionary *viewRegistry - (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 a8cd30ae551804..6fcb72128fd35b 100644 --- a/React/Views/RCTShadowView.m +++ b/React/Views/RCTShadowView.m @@ -320,6 +320,11 @@ - (BOOL)isLayoutDirty return _layoutLifecycle != RCTUpdateLifecycleComputed; } +- (BOOL)isCSSLeafNode +{ + return NO; +} + - (void)dirtyPropagation { if (_propagationLifecycle != RCTUpdateLifecycleDirtied) { @@ -354,7 +359,7 @@ - (void)setTextComputed - (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)atIndex { [_reactSubviews insertObject:subview atIndex:atIndex]; - _cssNode->children_count = (int)_reactSubviews.count; + _cssNode->children_count = [self isCSSLeafNode] ? 0 : (int)_reactSubviews.count; subview->_superview = self; _didUpdateSubviews = YES; [self dirtyText]; @@ -370,7 +375,7 @@ - (void)removeReactSubview:(RCTShadowView *)subview _didUpdateSubviews = YES; subview->_superview = nil; [_reactSubviews removeObject:subview]; - _cssNode->children_count = (int)_reactSubviews.count; + _cssNode->children_count = [self isCSSLeafNode] ? 0 : (int)_reactSubviews.count; } - (NSArray *)reactSubviews From e1b3bbdb0463260c5f3ed2f5593bd51a565a2eb7 Mon Sep 17 00:00:00 2001 From: Adam Comella Date: Wed, 20 Jul 2016 04:23:24 -0700 Subject: [PATCH 04/12] Android: Refactor HierarchyOptimizer in preparation of inline view support Summary: This PR was split from commits originally in #8619. /cc dmmiller These refactorings to the HierarchyOptimizer are in preparation for implementing support for inline views in #8619. **Refactoring 1: Collapse add*LayoutOnlyNodeToLayoutOnlyNode** addLayoutOnlyNodeToLayoutOnlyNode and addNonLayoutOnlyNodeToLayoutOnlyNode had nearly identical implementations. They both walk thru the ancestors looking for a nonlayout-only node and adjusting the passed in index at each step. This introduces a new function, walkUpUntilNonLayoutOnly, which takes care of that responsibility. This simplifies addNodeToNode because it can now consider the type of the parent and the type of the child independently. **Refactoring 2: Extract addGrandchildren** Pull out addLayoutOnlyNode's logic into a helper called addGrandchildren. We will need to call this method in another place later. **Test plan (required)** This change was tested with UIExplorer and a small test app and it's being used in my team's app. Closes https://github.com/facebook/react-native/pull/8908 Differential Revision: D3592783 Pulled By: dmmiller fbshipit-source-id: a513e8d381e71112ce6348bbee7d4a7c62c33619 --- .../NativeViewHierarchyOptimizer.java | 142 +++++++++--------- 1 file changed, 68 insertions(+), 74 deletions(-) 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)) { From 654e4bed2ee4fdde2034fbe1293fd40825147827 Mon Sep 17 00:00:00 2001 From: Dan Caspi Date: Wed, 20 Jul 2016 04:25:53 -0700 Subject: [PATCH 05/12] Better folly::dynamic ==> JSValue conversion Reviewed By: lexs Differential Revision: D3347854 fbshipit-source-id: 95b81152d1b0d5fe41e01991c44f5d1110be7ddb --- .../BatchedBridgedModules/NativeModules.js | 7 +- ReactCommon/cxxreact/JSCExecutor.cpp | 4 +- ReactCommon/cxxreact/Value.cpp | 74 ++++++++++++++++++- ReactCommon/cxxreact/Value.h | 3 +- 4 files changed, 82 insertions(+), 6 deletions(-) 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/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); }; } } From b7bf24bc7f4d62dd0f4417b45cbf4423fe664aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Vassb=C3=B8?= Date: Wed, 20 Jul 2016 05:41:32 -0700 Subject: [PATCH 06/12] Support geolocation in android webview Summary: Makes sure request for geolocation use in the webview is handled. This solves issue #7609 Currently use of geolocation in webview fails silently, as the permission request is never received by the native app. **Test plan (required)** 1. Create new project with webview 2. Add javascript for geolocation: ```javascript navigator.geolocation.getCurrentPosition(function (position) { console.log('success', position) }, function (error) { console.log('could not determine position', error) }) ``` 3. Run code and assert geolocation permission is requested, resulting in success (or error) callback being called Closes https://github.com/facebook/react-native/pull/8305 Differential Revision: D3592887 fbshipit-source-id: 84fe2383fba8873431c5e89d154c0a4fd58ffb70 --- .../facebook/react/views/webview/ReactWebViewManager.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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); From 1aa7ad0ab89cb17af7767dee3c935a7094bf3330 Mon Sep 17 00:00:00 2001 From: Emil Sjolander Date: Wed, 20 Jul 2016 06:40:26 -0700 Subject: [PATCH 07/12] CamelCase Reviewed By: majak Differential Revision: D3576069 fbshipit-source-id: cecda2cdb67f2f66ac92e336068d58731ccdb101 --- .../UIExplorerUnitTests/RCTShadowViewTests.m | 56 +- Libraries/Text/RCTShadowText.m | 36 +- Libraries/Text/RCTTextManager.m | 2 +- React/Base/RCTConvert.h | 10 +- React/Base/RCTConvert.m | 64 +- React/CSSLayout/CSSLayout.c | 1036 ++++++++--------- React/CSSLayout/CSSLayout.h | 248 ++-- React/Views/RCTRootShadowView.m | 12 +- React/Views/RCTShadowView.h | 18 +- React/Views/RCTShadowView.m | 144 +-- React/Views/RCTViewManager.m | 12 +- 11 files changed, 819 insertions(+), 819 deletions(-) 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/Libraries/Text/RCTShadowText.m b/Libraries/Text/RCTShadowText.m index a9a5727602bd58..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; } @@ -106,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; @@ -128,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 { @@ -136,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"); } @@ -175,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; @@ -196,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]; @@ -291,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"); } @@ -384,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) { 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..bfdd14d14a5105 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" 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 965025e2876d7f..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,7 +49,7 @@ - (void)applySizeConstraints { [self applySizeConstraints]; - 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 f6f149d819c185..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,14 +172,14 @@ 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; diff --git a/React/Views/RCTShadowView.m b/React/Views/RCTShadowView.m index 6fcb72128fd35b..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,20 +70,20 @@ 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; @@ -118,29 +118,29 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st // 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) @@ -151,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]; } @@ -237,18 +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; } - 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]; } @@ -273,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; @@ -288,11 +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; + _cssNode->getChild = RCTGetChild; + _cssNode->isDirty = RCTIsDirty; } return self; } @@ -304,7 +304,7 @@ - (BOOL)isReactRootView - (void)dealloc { - free_css_node(_cssNode); + CSSNodeFree(_cssNode); } - (void)dirtyLayout @@ -359,7 +359,7 @@ - (void)setTextComputed - (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)atIndex { [_reactSubviews insertObject:subview atIndex:atIndex]; - _cssNode->children_count = [self isCSSLeafNode] ? 0 : (int)_reactSubviews.count; + _cssNode->childCount = [self isCSSLeafNode] ? 0 : (int)_reactSubviews.count; subview->_superview = self; _didUpdateSubviews = YES; [self dirtyText]; @@ -375,7 +375,7 @@ - (void)removeReactSubview:(RCTShadowView *)subview _didUpdateSubviews = YES; subview->_superview = nil; [_reactSubviews removeObject:subview]; - _cssNode->children_count = [self isCSSLeafNode] ? 0 : (int)_reactSubviews.count; + _cssNode->childCount = [self isCSSLeafNode] ? 0 : (int)_reactSubviews.count; } - (NSArray *)reactSubviews @@ -475,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] }; } @@ -507,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; @@ -557,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]; } @@ -567,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]; } @@ -593,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 { 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) From c47f7457c0d8e8d6ccbd410d43d0dbda78edbe85 Mon Sep 17 00:00:00 2001 From: Andrew Jack Date: Wed, 20 Jul 2016 06:43:07 -0700 Subject: [PATCH 08/12] Update OkHttp to 3.4.0 and Okio to 1.9.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: - 3.3.1 wasn't compatible with Robolectric 3.0, however 3.4.0 [fixes](https://github.com/square/okhttp/issues/2533#issuecomment-230198063) this issue. - Few other fixes to OkHttp mentioned in the [CHANGELOG.md](https://github.com/square/okhttp/blob/master/CHANGELOG.md) > Fixes: #7743 > - Android apps can recover from a `REFUSED_STREAM` in HTTP/2. - A few other fixes mentioned in the [CHANGELOG.md](https://github.com/square/okhttp/blob/master/CHANGELOG.md) - CircleCi - Test with `/Examples` ✅ Closes https://github.com/facebook/react-native/pull/8672 Reviewed By: alsutton Differential Revision: D3541293 Pulled By: bestander fbshipit-source-id: 76429861b4f4df15cb9c18ab0f177daee3e1459d --- ReactAndroid/build.gradle | 8 ++++---- ReactAndroid/src/main/third-party/java/okhttp/BUCK | 12 ++++++------ ReactAndroid/src/main/third-party/java/okio/BUCK | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) 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/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', ) From c4ffc7d71c1c34599d3dd303e0b5bb674fa691f5 Mon Sep 17 00:00:00 2001 From: Adam Comella Date: Wed, 20 Jul 2016 07:12:48 -0700 Subject: [PATCH 09/12] Android: Fix handling of line height with inline images Summary: This PR was split from a commit originally in #8619. /cc dmmiller When an inline image was larger than the specified line height, the image would be clipped. This changes the behavior so that the line height is changed to make room for the inline image. This is consistent with the behavior of RN for iOS. Here's how the change works. ReactTextView now receives its line height from the layout thread rather than directly from JavaScript. The reason is that the layout thread may pick a different line height. In the case that the tallest inline image is larger than the line height supplied by JavaScript, we want to use that image's height as the line height rather than the supplied line height. Also fixed a bug where the image, which is supposed to be baseline aligned, would be positioned at the wrong y location. To fix this, we use `y` (the baseline) in the `draw` method rather than trying to calculate the baseline from `bottom`. For more information see https://code.google.com/p/andro Closes https://github.com/facebook/react-native/pull/8907 Differential Revision: D3592781 Pulled By: dmmiller fbshipit-source-id: cba6cd86eb4e3abef6a0d7a81f802bdb0958492e --- .../react/views/text/ReactTextShadowNode.java | 48 ++++++++++++------- .../react/views/text/ReactTextUpdate.java | 9 +++- .../react/views/text/ReactTextView.java | 12 +++++ .../views/text/ReactTextViewManager.java | 9 ---- .../react/views/text/TextInlineImageSpan.java | 10 ++++ .../FrescoBasedReactTextInlineImageSpan.java | 14 ++++-- .../textinput/ReactTextInputShadowNode.java | 2 +- 7 files changed, 74 insertions(+), 30 deletions(-) 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); } } From b25005a8335365a03e898a83b616e295b22ea224 Mon Sep 17 00:00:00 2001 From: Charles Dick Date: Wed, 20 Jul 2016 07:16:54 -0700 Subject: [PATCH 10/12] AdsManager now uses new react native QPL identifiers Reviewed By: fkgozali Differential Revision: D3543775 fbshipit-source-id: b7a6f811c579d35913ad5e480e1a5bc486a6172d --- Libraries/QuickPerformanceLogger/QuickPerformanceLogger.js | 6 ------ 1 file changed, 6 deletions(-) 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; From 768caf5e081d00b10310a0155774337c3292e019 Mon Sep 17 00:00:00 2001 From: Emil Sjolander Date: Wed, 20 Jul 2016 07:28:06 -0700 Subject: [PATCH 11/12] Use library style import for CSSMacros Reviewed By: javache Differential Revision: D3576815 fbshipit-source-id: 8d8cf34f701529b272f564088fb1b28708ec27a9 --- React/CSSLayout/CSSLayout.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/React/CSSLayout/CSSLayout.h b/React/CSSLayout/CSSLayout.h index bfdd14d14a5105..f85c72970571c1 100644 --- a/React/CSSLayout/CSSLayout.h +++ b/React/CSSLayout/CSSLayout.h @@ -23,7 +23,7 @@ static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff}; #define CSSUndefined NAN -#include "CSSMacros.h" +#include CSS_EXTERN_C_BEGIN From 12ec213c0d1610ebc6c0bd233818e387aa1ad4b9 Mon Sep 17 00:00:00 2001 From: Don Yu Date: Wed, 20 Jul 2016 08:07:06 -0700 Subject: [PATCH 12/12] Add support for layout gravity to ToastAndroid Summary: Add support for top, bottom, and center layout gravity to ToastAndroid Reviewed By: AaaChiuuu Differential Revision: D3590224 fbshipit-source-id: 84dbbcfbe4133f291d62723c5c261acd7b32b46e --- .../js/ToastAndroidExample.android.js | 38 ++++++++++++++++++- .../ToastAndroid/ToastAndroid.android.js | 16 ++++++++ .../react/modules/toast/ToastModule.java | 23 ++++++++++- 3 files changed, 74 insertions(+), 3 deletions(-) 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/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/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(); + } + }); + } }