http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Layout/WXCoreLayout.cpp
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXCoreLayout.cpp 
b/ios/sdk/WeexSDK/Sources/Layout/WXCoreLayout.cpp
new file mode 100644
index 0000000..7d34d83
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXCoreLayout.cpp
@@ -0,0 +1,1038 @@
+#include "WXCoreLayout.h"
+
+using namespace WeexCore;
+
+namespace WeexCore {
+
+  /**
+   * Entry function to calculate layout
+   */
+  void WXCoreLayoutNode::calculateLayout(const std::pair<float,float> 
&renderPageSize) {
+    BFCs.clear();
+    initFormatingContext(BFCs);
+    auto bfcDimension = calculateBFCDimension(renderPageSize);
+    if (std::get<0>(bfcDimension) || isDirty()) {
+      mChildrenFrozen.assign(getChildCount(kNonBFC), false);
+      measure(std::get<1>(bfcDimension), std::get<2>(bfcDimension), true);
+      checkSizeConstraints(this, false);
+    }
+    layout(mCssStyle->mMargin.getMargin(kMarginLeft),
+           mCssStyle->mMargin.getMargin(kMarginTop),
+           mCssStyle->mMargin.getMargin(kMarginLeft) + getLayoutWidth(),
+           mCssStyle->mMargin.getMargin(kMarginTop) + getLayoutHeight(),
+           false, &renderPageSize);
+    for (Index i = 0; i < getChildCount(kBFC); ++i) {
+      WXCoreLayoutNode *child = getChildAt(kBFC, i);
+      child->calculateLayout(renderPageSize);
+    }
+  }
+
+  void WXCoreLayoutNode::initFormatingContext(std::vector<WXCoreLayoutNode *> 
&BFCs) {
+    NonBFCs.clear();
+    for(auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) {
+      WXCoreLayoutNode* child = *it;
+      if (child != nullptr) {
+        if (isBFC(child)) {
+          BFCs.push_back(child);
+        } else {
+          NonBFCs.push_back(child);
+          child->initFormatingContext(BFCs);
+        }
+      }
+    }
+    reset();
+  }
+
+  std::tuple<bool, float, float> WXCoreLayoutNode::calculateBFCDimension(const 
std::pair<float,float>& renderPageSize) {
+    bool sizeChanged = false;
+    float width = mCssStyle->mStyleWidth, height = mCssStyle->mStyleHeight;
+    std::pair<bool,float> ret;
+    if (isBFC(this)) {
+      ret = calculateBFCWidth(width, renderPageSize.first);
+      sizeChanged |=ret.first;
+      width = ret.second;
+
+      ret = calculateBFCHeight(height,renderPageSize.second);
+      sizeChanged |=ret.first;
+      height = ret.second;
+    }
+    return std::make_tuple(sizeChanged, width, height);
+  }
+
+  std::pair<bool,float> WXCoreLayoutNode::calculateBFCWidth(float width, const 
float renderPageWidth){
+    bool sizeChanged = false;
+    if (isnan(width) &&
+        mParent != nullptr &&
+        !isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft)) &&
+        !isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeRight))) {
+      float containingBlockWidth = NAN;
+      switch (mCssStyle->mPositionType) {
+        case kAbsolute:
+          containingBlockWidth = mParent->mLayoutResult->mLayoutSize.width;
+          break;
+        case kFixed:
+          if (!isnan(renderPageWidth)) {
+            containingBlockWidth = renderPageWidth;
+          }
+          break;
+        default:
+              break;
+      }
+      if (!isnan(containingBlockWidth)) {
+        width = containingBlockWidth -
+            mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft) -
+            mCssStyle->mStylePosition.getPosition(kPositionEdgeRight);
+        setWidthMeasureMode(kExactly);
+        sizeChanged = true;
+      }
+    }
+    return std::make_pair(sizeChanged, width);
+  }
+
+
+  std::pair<bool,float> WXCoreLayoutNode::calculateBFCHeight(float height, 
const float renderPageHeight){
+    bool sizeChanged = false;
+    if (isnan(mCssStyle->mStyleHeight) &&
+        mParent != nullptr &&
+        !isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeTop)) &&
+        !isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom))) {
+      float containingBlockHeight = NAN;
+      switch (mCssStyle->mPositionType) {
+        case kAbsolute:
+          containingBlockHeight = mParent->mLayoutResult->mLayoutSize.height;
+          break;
+        case kFixed:
+          if (!isnan(renderPageHeight)) {
+            containingBlockHeight = renderPageHeight;
+          }
+          break;
+        default:
+          break;
+      }
+      if (!isnan(containingBlockHeight)) {
+        height = containingBlockHeight -
+            mCssStyle->mStylePosition.getPosition(kPositionEdgeTop) -
+            mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom);
+        setHeightMeasureMode(kExactly);
+        sizeChanged = true;
+      }
+    }
+    return std::make_pair(sizeChanged, height);
+  }
+
+  void WXCoreLayoutNode::measure(const float width, const float height, const 
bool hypotheticalMeasurment){
+    if(hypotheticalMeasurment){
+      //Only BFC will enter this case.
+      hypotheticalMeasure(width, height);
+    }
+
+    if(getChildCount(kNonBFC) > 0){
+      if((isMainAxisHorizontal(this) && widthDirty) || 
(!isMainAxisHorizontal(this) && heightDirty)){
+        measureInternalNode(width, height, false, false);
+      }
+      determineMainSize(width, height);
+      determineCrossSize(width, height, true);
+      measureInternalNode(width, height, true, false);
+      determineCrossSize(width, height, false);
+    }
+    else {
+      if (widthDirty || heightDirty) {
+        measureLeafNode(width, height, hypotheticalMeasurment, false);
+      }
+    }
+    clearDirty();
+  }
+
+  void WXCoreLayoutNode::hypotheticalMeasure(const float width, const float 
height, const bool stretch){
+    if (getChildCount(kNonBFC) > 0) {
+      measureInternalNode(width, height, true, true);
+    } else {
+      measureLeafNode(width, height, true, stretch);
+    }
+
+    widthDirty = false;
+    heightDirty = false;
+    mLayoutResult->mLayoutSize.hypotheticalWidth = 
mLayoutResult->mLayoutSize.width;
+    mLayoutResult->mLayoutSize.hypotheticalHeight = 
mLayoutResult->mLayoutSize.height;
+  }
+
+  void WXCoreLayoutNode::measureLeafNode(float width, float height, const bool 
hypothetical, const bool stretch) {
+    if ((measureFunc != nullptr) &&
+        (widthMeasureMode == kUnspecified
+            || heightMeasureMode == kUnspecified)) {
+      float constrainsWidth = width;
+      if(widthMeasureMode == kExactly && !isnan(width)){
+        constrainsWidth -= sumPaddingBorderAlongAxis(this, true);
+      }
+      WXCoreSize dimension = measureFunc(this, constrainsWidth,
+                                         (stretch && !isnan(width)) ? 
kExactly:widthMeasureMode,
+                                         height, heightMeasureMode);
+      if (widthMeasureMode == kUnspecified) {
+        float actualWidth = dimension.width + sumPaddingBorderAlongAxis(this, 
true);
+        if (isnan(width)) {
+          width = actualWidth;
+        } else if (!stretch) {
+          width = std::min(width, actualWidth);
+        }
+      }
+      if (heightMeasureMode == kUnspecified) {
+        float actualHeight = dimension.height + 
sumPaddingBorderAlongAxis(this, false);
+        if (isnan(height)) {
+          height = actualHeight;
+        } else if (!stretch) {
+          height = std::min(height, actualHeight);
+        }
+      }
+    } else {
+      width = widthMeasureMode == kUnspecified ? 
sumPaddingBorderAlongAxis(this, true)
+                                               : width;
+      height = heightMeasureMode == kUnspecified ? 
sumPaddingBorderAlongAxis(this, false)
+                                                 : height;
+    }
+    setMeasuredDimension(width, height);
+  }
+
+
+  /**
+   * Determine the main size by expanding the individual flexGrow attribute.
+   */
+  void WXCoreLayoutNode::determineMainSize(const float width, const float 
height) {
+      bool horizontal = isMainAxisHorizontal(this);
+      if((horizontal && widthMeasureMode == kExactly) || (!horizontal && 
heightMeasureMode == kExactly)) {
+        //The measureMode along main axis is exactly
+        float maxMainSize = horizontal ? width: height;
+        maxMainSize -= sumPaddingBorderAlongAxis(this, 
isMainAxisHorizontal(this));
+        Index childIndex = 0;
+        for (WXCoreFlexLine *flexLine : mFlexLines) {
+          childIndex = expandItemsInFlexLine(flexLine, maxMainSize, 
childIndex);
+        }
+      }
+    }
+
+
+  /**
+   * @param flexDirection         the flex direction attribute
+   * @param width                 stylewidth by this node
+   * @param height                styleheight by this node
+   * @param paddingAlongCrossAxis the padding value for this node along the 
cross axis
+   */
+    void WXCoreLayoutNode::determineCrossSize(const float width, const float 
height, const bool stretch) {
+      if (mFlexLines.size() == 1 && isCrossExactly()) {
+        bool horizontal = isMainAxisHorizontal(this);
+        float size = mFlexLines[0]->mCrossSize;
+        float paddingAlongCrossAxis = sumPaddingBorderAlongAxis(this, 
!horizontal);
+        if (horizontal) {
+          if (heightMeasureMode == kExactly) {
+            size = height - paddingAlongCrossAxis;
+          }
+        } else {
+          if (widthMeasureMode == kExactly) {
+            size = width - paddingAlongCrossAxis;
+          }
+        }
+        mFlexLines[0]->mCrossSize = size;
+      }
+      if (stretch) {
+        stretchViewCrossSize();
+      }
+    }
+
+
+    void WXCoreLayoutNode::measureInternalNode(const float width, const float 
height, const bool needMeasure,
+                                               const bool 
hypotheticalMeasurment) {
+      for (WXCoreFlexLine *flexLine : mFlexLines) {
+        if(flexLine!= nullptr) {
+          delete flexLine;
+        }
+        flexLine = nullptr;
+      }
+      mFlexLines.clear();
+      Index childCount = getChildCount(kNonBFC);
+      WXCoreFlexLine *flexLine = new WXCoreFlexLine();
+
+      for (Index i = 0; i < childCount; i++) {
+        WXCoreLayoutNode *child = getChildAt(kNonBFC, i);
+        if (child->mCssStyle->mAlignSelf == kAlignSelfStretch) {
+          flexLine->mIndicesAlignSelfStretch.push_back(i);
+        }
+        measureChild(child, flexLine->mMainSize, width, height, needMeasure, 
hypotheticalMeasurment);
+        checkSizeConstraints(child, hypotheticalMeasurment);
+
+        if (isWrapRequired(width, height, flexLine->mMainSize,
+                           calcItemSizeAlongAxis(child, 
isMainAxisHorizontal(this)))) {
+          if (flexLine->mItemCount > 0) {
+            mFlexLines.push_back(flexLine);
+          }
+          flexLine = new WXCoreFlexLine();
+          flexLine->mItemCount = 1;
+        } else {
+          flexLine->mItemCount++;
+        }
+        updateCurrentFlexline(childCount, flexLine, i, child, 
hypotheticalMeasurment || (!hypotheticalMeasurment && !needMeasure));
+      }
+      setMeasuredDimensionForFlex(width, widthMeasureMode, height, 
heightMeasureMode);
+    }
+
+    void WXCoreLayoutNode::updateCurrentFlexline(const Index childCount, 
WXCoreFlexLine* const flexLine, const Index i,
+                                                 const WXCoreLayoutNode* const 
child, const bool useHypotheticalSize){
+      flexLine->mMainSize += calcItemSizeAlongAxis(child, 
isMainAxisHorizontal(this), useHypotheticalSize);
+      sumFlexGrow(child, flexLine, i);
+      flexLine->mCrossSize =
+          std::max(flexLine->mCrossSize, calcItemSizeAlongAxis(child, 
!isMainAxisHorizontal(this), useHypotheticalSize));
+      if (i == childCount - 1 && flexLine->mItemCount != 0) {
+        mFlexLines.push_back(flexLine);
+      }
+    }
+
+    void WXCoreLayoutNode::measureChild(WXCoreLayoutNode* const child, const 
float currentMainSize,
+                                        const float parentWidth, const float 
parentHeight,
+                                        const bool needMeasure, const bool 
hypotheticalMeasurment) {
+      if (needMeasure && child->isDirty()) {
+        if (hypotheticalMeasurment) {
+          float childWidth = child->mCssStyle->mStyleWidth;
+          float childHeight = child->mCssStyle->mStyleHeight;
+          bool stretch = !isMainAxisHorizontal(this) &&
+              child->measureFunc != nullptr &&
+              widthMeasureMode == kExactly &&
+              isSingleFlexLine(parentHeight) &&
+              ((child->mCssStyle->mAlignSelf == kAlignSelfStretch) ||
+                  (mCssStyle->mAlignItems == kAlignItemsStretch
+                      && child->mCssStyle->mAlignSelf == kAlignSelfAuto));
+
+          adjustChildSize(child, currentMainSize, parentWidth,
+                          parentHeight, childWidth, childHeight);
+          child->hypotheticalMeasure(childWidth, childHeight, stretch);
+        } else {
+          if(isSingleFlexLine(isMainAxisHorizontal(this) ? parentWidth : 
parentHeight)
+              && !isMainAxisHorizontal(this) && child->widthMeasureMode == 
kUnspecified){
+            child->setLayoutWidth(parentWidth - 
sumPaddingBorderAlongAxis(this, true)
+                                      
-child->mCssStyle->sumMarginOfDirection(true));
+            if(child->heightMeasureMode == kUnspecified && child->widthDirty) {
+              child->mLayoutResult->mLayoutSize.height = NAN;
+            }
+          }
+          child->measure(child->mLayoutResult->mLayoutSize.width,
+                         child->mLayoutResult->mLayoutSize.height, 
hypotheticalMeasurment);
+        }
+      }
+    }
+
+    void WXCoreLayoutNode::adjustChildSize(const WXCoreLayoutNode *child,
+                                        const float currentMainSize,
+                                        const float parentWidth,
+                                        const float parentHeight,
+                                        float &childWidth,
+                                        float &childHeight) const {
+      if(child->measureFunc == nullptr) {
+        if(!isnan(childWidth)){
+          childWidth = std::max(childWidth, 
child->sumPaddingBorderAlongAxis(child, true));
+        }
+        if(!isnan(childHeight)){
+          childHeight = std::max(childHeight, 
child->sumPaddingBorderAlongAxis(child, false));
+        }
+      }
+
+      if (isSingleFlexLine(isMainAxisHorizontal(this) ? parentWidth : 
parentHeight)) {
+        if (isMainAxisHorizontal(this)) {
+          if (!isnan(parentHeight) && isnan(child->mCssStyle->mStyleHeight)
+              && child->mCssStyle->mAlignSelf == kAlignSelfAuto
+              && mCssStyle->mAlignItems == kAlignItemsStretch) {
+            childHeight = parentHeight - sumPaddingBorderAlongAxis(this, 
false) -
+                child->mCssStyle->sumMarginOfDirection(false);
+          }
+        } else {
+          if (!isnan(parentWidth) && isnan(child->mCssStyle->mStyleWidth)) {
+            childWidth = parentWidth - sumPaddingBorderAlongAxis(this, true) -
+                child->mCssStyle->sumMarginOfDirection(true);
+          }
+       }
+      }
+    }
+
+    void WXCoreLayoutNode::checkSizeConstraints(WXCoreLayoutNode* const node, 
const bool hypotheticalMeasurment) {
+      bool widthRemeasure = false, heightRemeasure = false;
+      float nodeWidth,nodeHeight;
+      nodeWidth = node->mLayoutResult->mLayoutSize.width;
+      nodeHeight = node->mLayoutResult->mLayoutSize.height;
+
+      if (!isnan(node->mCssStyle->mMinWidth) &&
+          nodeWidth < node->mCssStyle->mMinWidth) {
+        widthRemeasure = true;
+        nodeWidth = node->mCssStyle->mMinWidth;
+      } else if (!isnan(node->mCssStyle->mMaxWidth)
+          && nodeWidth > node->mCssStyle->mMaxWidth) {
+        widthRemeasure = true;
+        nodeWidth = node->mCssStyle->mMaxWidth;
+      }
+
+      if (!isnan(node->mCssStyle->mMinHeight) &&
+          nodeHeight < node->mCssStyle->mMinHeight) {
+        heightRemeasure = true;
+        nodeHeight = node->mCssStyle->mMinHeight;
+      } else if (!isnan(node->mCssStyle->mMaxHeight) &&
+          nodeHeight > node->mCssStyle->mMaxHeight) {
+        heightRemeasure = true;
+        nodeHeight = node->mCssStyle->mMaxHeight;
+      }
+
+      node->setWidthMeasureMode(widthRemeasure ? kExactly : 
node->widthMeasureMode);
+      node->setHeightMeasureMode(heightRemeasure ? kExactly : 
node->heightMeasureMode);
+
+      if (hypotheticalMeasurment) {
+        if (widthRemeasure) {
+          node->setLayoutWidth(nodeWidth);
+          node->mLayoutResult->mLayoutSize.hypotheticalWidth = nodeWidth;
+        }
+        if (heightRemeasure) {
+          node->setLayoutHeight(nodeHeight);
+          node->mLayoutResult->mLayoutSize.hypotheticalHeight = nodeHeight;
+        }
+      } else {
+        if (widthRemeasure || heightRemeasure) {
+          node->measure(nodeWidth, nodeHeight, hypotheticalMeasurment);
+        }
+      }
+    }
+
+    Index WXCoreLayoutNode::expandItemsInFlexLine(WXCoreFlexLine* const 
flexLine,
+                                      const float maxMainSize,
+                                      const Index startIndex) {
+      Index childIndex = startIndex;
+      if (flexLine->mTotalFlexGrow <= 0) {
+        childIndex += flexLine->mItemCount;
+      } else {
+        bool needsReexpand = false;
+        const float unitSpace = (maxMainSize - flexLine->mMainSize + 
flexLine->mTotalFlexibleSize) /
+                                (flexLine->mTotalFlexGrow > 1 ? 
flexLine->mTotalFlexGrow : 1);
+        float sizeBeforeExpand = flexLine->mMainSize;
+        flexLine->mMainSize = 0;
+
+        for (Index i = 0; i < flexLine->mItemCount; i++) {
+          WXCoreLayoutNode *child = getChildAt(kNonBFC, childIndex);
+          if (!mChildrenFrozen[childIndex]) {
+            float childSizeAlongMainAxis = unitSpace * 
child->mCssStyle->mFlexGrow;
+            std::pair<bool, float> limitSize = limitChildMainSize(flexLine, 
child,
+                                                                
childSizeAlongMainAxis, childIndex);
+            needsReexpand = limitSize.first;
+            adjustChildSize(child, limitSize.second);
+          }
+          flexLine->mMainSize += calcItemSizeAlongAxis(child, 
isMainAxisHorizontal(this));
+          childIndex++;
+        }
+
+        if (needsReexpand && sizeBeforeExpand != flexLine->mMainSize) {
+          // Re-invoke the method with the same startIndex to distribute the 
positive free space
+          // that wasn't fully distributed (because of maximum/minimum length 
constraint)
+          expandItemsInFlexLine(flexLine, maxMainSize, startIndex);
+        }
+      }
+      return childIndex;
+    }
+
+    void WXCoreLayoutNode::adjustChildSize(WXCoreLayoutNode* const child, 
const float childMainSize) {
+      if (isMainAxisHorizontal(this)) {
+        child->setWidthMeasureMode(kExactly);
+        child->setLayoutWidth(childMainSize);
+      } else {
+        child->setHeightMeasureMode(kExactly);
+        child->setLayoutHeight(childMainSize);
+      }
+    }
+
+    void WXCoreLayoutNode::stretchViewCrossSize(){
+      if (mCssStyle->mAlignItems == kAlignItemsStretch) {
+        Index viewIndex = 0;
+        for (Index i = 0; i< mFlexLines.size(); i++ ) {
+            WXCoreFlexLine *flexLine = mFlexLines.at(i);
+            for (Index j = 0; j < flexLine->mItemCount; j++, viewIndex++) {
+                WXCoreLayoutNode* child = getChildAt(kNonBFC, viewIndex);
+              if (child->mCssStyle->mAlignSelf == kAlignSelfAuto ||
+                  child->mCssStyle->mAlignSelf == kAlignSelfStretch) {
+                stretchViewCrossSize(child, flexLine->mCrossSize);
+              }
+          }
+        }
+      } else {
+        for (WXCoreFlexLine *flexLine : mFlexLines) {
+          for (auto index : flexLine->mIndicesAlignSelfStretch) {
+            stretchViewCrossSize(getChildAt(kNonBFC, index), 
flexLine->mCrossSize);
+          }
+        }
+      }
+    }
+
+    void WXCoreLayoutNode::stretchViewCrossSize(WXCoreLayoutNode* const child, 
float crossSize){
+      if (isMainAxisHorizontal(this)) {
+        if (child->heightMeasureMode != kExactly) {
+            crossSize -=
+                child->mCssStyle->mMargin.getMargin(kMarginTop) +
+                    child->mCssStyle->mMargin.getMargin(kMarginBottom);
+          child->setHeightMeasureMode(kExactly);
+          child->setLayoutHeight(std::max(0.f, crossSize));
+        }
+      } else {
+        if (child->widthMeasureMode != kExactly) {
+            crossSize -=
+                child->mCssStyle->mMargin.getMargin(kMarginLeft) +
+                    child->mCssStyle->mMargin.getMargin(kMarginRight);
+          child->setWidthMeasureMode(kExactly);
+          child->setLayoutWidth(std::max(0.f, crossSize));
+        }
+      }
+    }
+
+    void WXCoreLayoutNode::setFrame(const float l, const float t, const float 
r, const float b) {
+      if (mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeLeft) != l
+          || mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeTop) != t
+          || mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeRight) != 
r
+          || mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeBottom) 
!= b) {
+        setHasNewLayout(true);
+        setFrame(&mLayoutResult->mLayoutPosition, l, t, r, b);
+      }
+    }
+
+  void WXCoreLayoutNode::setFrame(WXCorePosition* position,const float l, 
const float t, const float r, const float b){
+    position->setPosition(kPositionEdgeLeft, l);
+    position->setPosition(kPositionEdgeTop, t);
+    position->setPosition(kPositionEdgeRight, r);
+    position->setPosition(kPositionEdgeBottom, b);
+  }
+
+  void WXCoreLayoutNode::layout(float left, float top, float right, float 
bottom, const bool absoluteFlexItem, const std::pair<float,float>* const 
renderPageSize) {
+    if(absoluteFlexItem) {
+      absoultePositon = new WXCorePosition();
+      setFrame(absoultePositon, left, top, right, bottom);
+    }
+    else{
+      switch (mCssStyle->mPositionType) {
+        case kFixed:
+        case kAbsolute:
+          calcAbsoluteOffset(left, top, right, bottom, renderPageSize);
+          break;
+        default:
+        case kRelative:
+          calcRelativeOffset(left, top, right, bottom);
+          break;
+      }
+      setFrame(left, top, right, bottom);
+      onLayout(left, top, right, bottom);
+    }
+  }
+
+  void WXCoreLayoutNode::calcRelativeOffset(float &left, float &top, float 
&right, float &bottom) const {
+    if (!isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft))) {
+      left += mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft);
+      right += mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft);
+    } else if 
(!isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeRight))) {
+      left -= mCssStyle->mStylePosition.getPosition(kPositionEdgeRight);
+      right -= mCssStyle->mStylePosition.getPosition(kPositionEdgeRight);
+    }
+
+    if (!isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeTop))) {
+      top += mCssStyle->mStylePosition.getPosition(kPositionEdgeTop);
+      bottom += mCssStyle->mStylePosition.getPosition(kPositionEdgeTop);
+    } else if 
(!isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom))) {
+      top -= mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom);
+      bottom -= mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom);
+    }
+  }
+
+  void WXCoreLayoutNode::calcAbsoluteOffset(float &left, float &top, float 
&right, float &bottom, const std::pair<float,float>* const renderPageSize){
+    WXCorePadding parentPadding;
+    WXCoreBorderWidth parentBorder;
+    WXCoreSize parentSize;
+    if (mCssStyle->mPositionType == kAbsolute && mParent != nullptr) {
+      parentPadding = mParent->mCssStyle->mPadding;
+      parentBorder = mParent->mCssStyle->mBorderWidth;
+      parentSize = mParent->mLayoutResult->mLayoutSize;
+      positionAbsoluteFlexItem(left, top, right, bottom);
+    } else if(mCssStyle->mPositionType == kFixed && renderPageSize!= nullptr){
+      parentSize.width = renderPageSize->first;
+      parentSize.height = renderPageSize->second;
+    }
+    updateLeftRightForAbsolute(left, right, parentPadding, parentBorder, 
parentSize);
+    updateTopBottomForAbsolute(top, bottom, parentPadding, parentBorder, 
parentSize);
+  }
+
+  void WXCoreLayoutNode::positionAbsoluteFlexItem(float &left, float &top, 
float &right, float &bottom){
+    if ((isnan(getStylePositionLeft()) && isnan(getStylePositionRight())) ||
+        (isnan(getStylePositionTop()) && isnan(getStylePositionBottom()))) {
+      WXCoreFlexLine tempLine;
+      mParent->updateFlexLineForAbsoluteItem(this, &tempLine);
+      mParent->onLayout(mParent->getLayoutPositionLeft(),
+                        mParent->getLayoutPositionTop(),
+                        mParent->getLayoutPositionRight(),
+                        mParent->getLayoutPositionBottom(),
+                        this, &tempLine);
+      if(absoultePositon != nullptr) {
+        if (isnan(getStylePositionLeft()) && isnan(getStylePositionRight())) {
+          left = absoultePositon->getPosition(kPositionEdgeLeft);
+          right = absoultePositon->getPosition(kPositionEdgeRight);
+        }
+        if (isnan(getStylePositionTop()) && isnan(getStylePositionBottom())) {
+          top = absoultePositon->getPosition(kPositionEdgeTop);
+          bottom = absoultePositon->getPosition(kPositionEdgeBottom);
+        }
+        delete absoultePositon;
+        absoultePositon = nullptr;
+      }
+    }
+  }
+
+  void WXCoreLayoutNode::updateFlexLineForAbsoluteItem(WXCoreLayoutNode *const 
absoluteFlexItem, WXCoreFlexLine *const flexLine){
+    flexLine->mMainSize = isMainAxisHorizontal(this) ?
+                         absoluteFlexItem->getLayoutWidth() + 
absoluteFlexItem->getMarginLeft()
+                             + absoluteFlexItem->getMarginRight() :
+                         absoluteFlexItem->getLayoutHeight() + 
absoluteFlexItem->getMarginTop()
+                             + absoluteFlexItem->getMarginBottom();
+    flexLine->mCrossSize = isMainAxisHorizontal(this) ?
+                          absoluteFlexItem->getLayoutHeight() + 
absoluteFlexItem->getMarginTop()
+                              + absoluteFlexItem->getMarginBottom() :
+                          absoluteFlexItem->getLayoutWidth() + 
absoluteFlexItem->getMarginLeft()
+                              + absoluteFlexItem->getMarginRight();
+    flexLine->mItemCount = 1;
+  }
+
+  void WXCoreLayoutNode::onLayout(const float left, const float top, const 
float right, const float bottom,
+                                  WXCoreLayoutNode *const absoulteItem, 
WXCoreFlexLine *const flexLine) {
+    switch (mCssStyle->mFlexDirection) {
+      case kFlexDirectionRow:
+        layoutHorizontal(false, left, top, right, bottom, absoulteItem, 
flexLine);
+        break;
+      case kFlexDirectionRowReverse:
+        layoutHorizontal(true, left, top, right, bottom, absoulteItem, 
flexLine);
+        break;
+      case kFlexDirectionColumnReverse:
+        layoutVertical(mCssStyle->mFlexWrap == kWrapReverse, true, left, top, 
right, bottom, absoulteItem, flexLine);
+        break;
+      case kFlexDirectionColumn:
+      default:
+        layoutVertical(mCssStyle->mFlexWrap == kWrapReverse, false, left, top, 
right, bottom, absoulteItem, flexLine);
+        break;
+    }
+  }
+
+  /**
+   * Sub method for {@link WXCoreLayoutNode #onLayout(int, int, int, int)} 
when the
+   * {@link #mFlexDirection} is either {@link WXCoreFlexDirection 
#WXCore_Flex_Direction_Row} or
+   * {@link WXCoreFlexDirection #WXCore_Flex_Direction_Row_REVERSE}.
+   *
+   * @param isRtl  {@code true} if the horizontal layout direction is 
mStyleRight to mStyleLeft, {@code
+   *               false} otherwise.
+   * @param left   the mStyleLeft position of this View
+   * @param top    the mStyleTop position of this View
+   * @param right  the mStyleRight position of this View
+   * @param bottom the mStyleBottom position of this View
+   */
+  void WXCoreLayoutNode::layoutHorizontal(const bool isRtl,
+                                          const float left, const float top,
+                                          const float right, const float 
bottom,
+                                          WXCoreLayoutNode *const absoulteItem,
+                                          WXCoreFlexLine *const flexLine) {
+    Index currentViewIndex = 0;
+    float height = bottom - top;
+    float width = right - left;
+
+    // childBottom is used if the mFlexWrap is FLEX_WRAP_WRAP_REVERSE otherwise
+    // childTop is used to align the vertical position of the children views.
+    float childBottom = height - getPaddingBottom() - getBorderWidthBottom();
+    float childTop = getPaddingTop() + getBorderWidthTop();
+
+    // Used only for RTL layout
+    // Use float to reduce the round error that may happen in when 
justifyContent ==
+    // SPACE_BETWEEN or SPACE_AROUND
+    float childLeft, childRight;
+    const std::vector<WXCoreFlexLine*> &lines = (flexLine == nullptr? 
mFlexLines: std::vector<WXCoreFlexLine*>{flexLine});
+
+    for (WXCoreFlexLine *flexLine: lines) {
+      float spaceBetweenItem = 0.f;
+      layoutFlexlineHorizontal(width, flexLine, childLeft, childRight, 
spaceBetweenItem);
+      spaceBetweenItem = std::max(spaceBetweenItem, 0.f);
+
+      if(absoulteItem == nullptr) {
+        for (Index j = 0; j < flexLine->mItemCount; j++) {
+          WXCoreLayoutNode *child = getChildAt(kNonBFC, currentViewIndex);
+          if (child == nullptr) {
+            continue;
+          }
+          layoutSingleChildHorizontal(isRtl, false, childBottom, childTop,
+                                     flexLine, child, childLeft, childRight);
+          childLeft += child->mLayoutResult->mLayoutSize.width + 
spaceBetweenItem + child->getMarginRight();
+          childRight -= child->mLayoutResult->mLayoutSize.width + 
spaceBetweenItem + child->getMarginLeft();
+          currentViewIndex++;
+        }
+        childTop += flexLine->mCrossSize;
+        childBottom -= flexLine->mCrossSize;
+      }
+      else{
+        layoutSingleChildHorizontal(isRtl, true, childBottom, childTop,
+                                   flexLine, absoulteItem, childLeft, 
childRight);
+      }
+    }
+  }
+
+  void WXCoreLayoutNode::layoutFlexlineHorizontal(const float width,
+                              const WXCoreFlexLine *const flexLine,
+                              float &childLeft,
+                              float &childRight,
+                              float &spaceBetweenItem) const {
+    Index visibleCount, visibleItem;
+    float denominator;
+    switch (mCssStyle->mJustifyContent) {
+      case kJustifyFlexEnd:
+        childLeft = width - flexLine->mMainSize - getPaddingRight() - 
getBorderWidthRight();
+        childRight = width - getPaddingLeft() - getBorderWidthLeft();
+        break;
+      case kJustifyCenter:
+        childLeft = (width - flexLine->mMainSize - 
mCssStyle->sumPaddingBorderOfEdge(kRight)
+            + mCssStyle->sumPaddingBorderOfEdge(kLeft)) / 2;
+        childRight = childLeft + flexLine->mMainSize;
+        break;
+      case kJustifySpaceAround:
+        visibleCount = flexLine->mItemCount;
+        if (visibleCount != 0) {
+          spaceBetweenItem =
+              (width - flexLine->mMainSize - sumPaddingBorderAlongAxis(this, 
true)) / visibleCount;
+        }
+        childLeft = getPaddingLeft() + getBorderWidthLeft() + spaceBetweenItem 
/ 2.f;
+        childRight = width - getPaddingRight() - getBorderWidthRight() - 
spaceBetweenItem / 2.f;
+        break;
+      case kJustifySpaceBetween:
+        childLeft = getPaddingLeft() + getBorderWidthLeft();
+        visibleItem = flexLine->mItemCount;
+        denominator = visibleItem != 1 ? visibleItem - 1 : 1.f;
+        spaceBetweenItem =
+            (width - flexLine->mMainSize - sumPaddingBorderAlongAxis(this, 
true)) / denominator;
+        childRight = width - getPaddingRight() - getBorderWidthRight();
+        break;
+      case kJustifyFlexStart:
+      default:
+        childLeft = getPaddingLeft() + getBorderWidthLeft();
+        childRight = width - getPaddingRight() - getBorderWidthRight();
+        break;
+    }
+  }
+
+  void WXCoreLayoutNode::layoutSingleChildHorizontal(const bool isRtl, const 
bool absoulteItem,
+                                                  float childBottom, float 
childTop,
+                                                  WXCoreFlexLine *const 
flexLine,
+                                                  WXCoreLayoutNode *const 
child,
+                                                  float &childLeft, float 
&childRight) {
+    childLeft += child->getMarginLeft();
+    childRight -= child->getMarginRight();
+    if (mCssStyle->mFlexWrap == kWrapReverse) {
+      if (isRtl) {
+        layoutSingleChildHorizontal(child,
+                                    flexLine,
+                                    mCssStyle->mFlexWrap,
+                                    mCssStyle->mAlignItems,
+                                    childRight - 
child->mLayoutResult->mLayoutSize.width,
+                                    childBottom - 
child->mLayoutResult->mLayoutSize.height,
+                                    childRight,
+                                    childBottom,
+                                    absoulteItem);
+      } else {
+        layoutSingleChildHorizontal(child,
+                                    flexLine,
+                                    mCssStyle->mFlexWrap,
+                                    mCssStyle->mAlignItems,
+                                    childLeft,
+                                    childBottom - 
child->mLayoutResult->mLayoutSize.height,
+                                    childLeft + 
child->mLayoutResult->mLayoutSize.width,
+                                    childBottom,
+                                    absoulteItem);
+      }
+    } else {
+      if (isRtl) {
+        layoutSingleChildHorizontal(child, flexLine, mCssStyle->mFlexWrap, 
mCssStyle->mAlignItems,
+                                    childRight - 
child->mLayoutResult->mLayoutSize.width, childTop,
+                                    childRight, childTop + 
child->mLayoutResult->mLayoutSize.height,
+                                    absoulteItem);
+      } else {
+        layoutSingleChildHorizontal(child, flexLine, mCssStyle->mFlexWrap, 
mCssStyle->mAlignItems,
+                                    childLeft, childTop,
+                                    childLeft + 
child->mLayoutResult->mLayoutSize.width,
+                                    childTop + 
child->mLayoutResult->mLayoutSize.height,
+                                    absoulteItem);
+      }
+    }
+  }
+
+  /**
+   * Place a single View when the layout direction is horizontal ({@link 
#mFlexDirection} is
+   * either {@link WXCoreFlexDirection #WXCore_Flex_Direction_Row} or
+   * {@link WXCoreFlexDirection #WXCore_Flex_Direction_Row_REVERSE}).
+   *
+   * @param node       the View to be placed
+   * @param flexLine   the {@link WXCoreFlexLine} where the View belongs to
+   * @param flexWrap   the flex wrap attribute of this BasicLayoutNode
+   * @param alignItems the align items attribute of this BasicLayoutNode
+   * @param left       the mStyleLeft position of the View, which the View's 
margin is already taken
+   *                   into account
+   * @param top        the mStyleTop position of the flex line where the View 
belongs to. The actual
+   *                   View's mStyleTop position is shifted depending on the 
flexWrap and alignItems
+   *                   attributes
+   * @param right      the mStyleRight position of the View, which the View's 
margin is already taken
+   *                   into account
+   * @param bottom     the mStyleBottom position of the flex line where the 
View belongs to. The actual
+   *                   View's mStyleBottom position is shifted depending on 
the flexWrap and alignItems
+   *                   attributes
+   */
+  void WXCoreLayoutNode::layoutSingleChildHorizontal(WXCoreLayoutNode *const 
node, WXCoreFlexLine* const flexLine,
+                                                     const WXCoreFlexWrap 
flexWrap, WXCoreAlignItems alignItems,
+                                                     const float left, const 
float top, const float right, const float bottom, const bool absoluteFlexItem) {
+    if (node->mCssStyle->mAlignSelf != kAlignSelfAuto) {
+      // Expecting the values for alignItems and alignSelf match except for 
ALIGN_SELF_AUTO.
+      // Assigning the alignSelf value as alignItems should work.
+      alignItems = static_cast<WXCoreAlignItems>(node->mCssStyle->mAlignSelf);
+    }
+
+    float crossSize = flexLine->mCrossSize;
+
+    switch (alignItems) {
+      case kAlignItemsFlexStart:
+      case kAlignItemsStretch:
+        if (flexWrap != kWrapReverse) {
+          node->layout(left, top + node->getMarginTop(), right, bottom + 
node->getMarginTop(), absoluteFlexItem);
+        } else {
+          node->layout(left, top - node->getMarginBottom(), right, bottom - 
node->getMarginBottom(), absoluteFlexItem);
+        }
+        break;
+      case kAlignItemsFlexEnd:
+        if (flexWrap != kWrapReverse) {
+          node->layout(left,
+                       top + crossSize - 
node->mLayoutResult->mLayoutSize.height - node->getMarginBottom(),
+                       right, top + crossSize - node->getMarginBottom(), 
absoluteFlexItem);
+        } else {
+          // If the flexWrap == FLEX_WRAP_WRAP_REVERSE, the direction of the
+          // flexEnd is flipped (from mStyleTop to mStyleBottom).
+          node->layout(left, top - crossSize + 
node->mLayoutResult->mLayoutSize.height + node->getMarginTop(),
+                       right, bottom - crossSize + 
node->mLayoutResult->mLayoutSize.height + node->getMarginTop(), 
absoluteFlexItem);
+        }
+        break;
+      case kAlignItemsCenter:
+        float topFromCrossAxis = (crossSize - 
node->mLayoutResult->mLayoutSize.height
+                                  + node->getMarginTop() - 
node->getMarginBottom()) / 2;
+        if (flexWrap != kWrapReverse) {
+          node->layout(left, top + topFromCrossAxis,
+                       right, top + topFromCrossAxis + 
node->mLayoutResult->mLayoutSize.height, absoluteFlexItem);
+        } else {
+          node->layout(left, top - topFromCrossAxis,
+                       right, top - topFromCrossAxis + 
node->mLayoutResult->mLayoutSize.height, absoluteFlexItem);
+        }
+        break;
+    }
+  }
+
+  /**
+   * Sub method for {@link WXCoreLayoutNode #onLayout(int, int, int, int)} 
when the
+   * {@link #mFlexDirection} is either {@link WXCoreFlexDirection 
#WXCore_Flex_Direction_Column} or
+   * {@link WXCoreFlexDirection #WXCore_Flex_Direction_Column_Reverse}.
+   *
+   * @param isRtl           {@code true} if the horizontal layout direction is 
mStyleRight to mStyleLeft,
+   *                        {@code false}
+   *                        otherwise
+   * @param fromBottomToTop {@code true} if the layout direction is 
mStyleBottom to mStyleTop, {@code false}
+   *                        otherwise
+   * @param left            the mStyleLeft position of this View
+   * @param top             the mStyleTop position of this View
+   * @param right           the mStyleRight position of this View
+   * @param bottom          the mStyleBottom position of this View
+   */
+  void
+  WXCoreLayoutNode::layoutVertical(const bool isRtl,
+                                   const bool fromBottomToTop,
+                                   const float left, const float top,
+                                   const float right, const float bottom,
+                                   WXCoreLayoutNode *const absoulteItem,
+                                   WXCoreFlexLine *const flexLine) {
+    float childLeft = getPaddingLeft() + getBorderWidthLeft();
+    Index currentViewIndex = 0;
+    float width = right - left;
+    float height = bottom - top;
+
+    // childRight is used if the mFlexWrap is FLEX_WRAP_WRAP_REVERSE otherwise
+    // childLeft is used to align the horizontal position of the children 
views.
+    float childRight = width - getPaddingRight() - getBorderWidthRight();
+
+    // Use float to reduce the round error that may happen in when 
justifyContent ==
+    // SPACE_BETWEEN or SPACE_AROUND
+    float childTop, childBottom;
+    const std::vector<WXCoreFlexLine*> &lines = (flexLine == nullptr? 
mFlexLines: std::vector<WXCoreFlexLine*>{flexLine});
+
+    for (WXCoreFlexLine *flexLine : lines) {
+      float spaceBetweenItem = 0.f;
+      layoutFlexlineVertical(height, flexLine, childTop, childBottom, 
spaceBetweenItem);
+      spaceBetweenItem = std::max(spaceBetweenItem, 0.f);
+      if(absoulteItem == nullptr) {
+        for (Index j = 0; j < flexLine->mItemCount; j++) {
+          WXCoreLayoutNode *child = getChildAt(kNonBFC, currentViewIndex);
+          if (child == nullptr) {
+            continue;
+          }
+          layoutSingleChildVertical(isRtl, fromBottomToTop, false,
+                                    childLeft, childRight, flexLine,
+                                    child, childTop, childBottom);
+          childTop += child->mLayoutResult->mLayoutSize.height + 
spaceBetweenItem + child->getMarginBottom();
+          childBottom -= child->mLayoutResult->mLayoutSize.height + 
spaceBetweenItem + child->getMarginTop();
+          currentViewIndex++;
+        }
+        childLeft += flexLine->mCrossSize;
+        childRight -= flexLine->mCrossSize;
+      }
+      else{
+        layoutSingleChildVertical(isRtl, fromBottomToTop, true,
+                                  childLeft, childRight, flexLine,
+                                  absoulteItem, childTop, childBottom);
+      }
+    }
+  }
+
+  void WXCoreLayoutNode::layoutFlexlineVertical(const float height,
+                            const WXCoreFlexLine *const flexLine,
+                            float &childTop,
+                            float &childBottom,
+                            float &spaceBetweenItem) const {
+    Index visibleCount, visibleItem;
+    float denominator;
+    switch (mCssStyle->mJustifyContent) {
+      case kJustifyFlexEnd:
+        childTop = height - flexLine->mMainSize - getPaddingBottom() - 
getBorderWidthBottom();
+        childBottom = height - getPaddingTop() - getBorderWidthTop();
+        break;
+      case kJustifyCenter:
+        childTop = (height - flexLine->mMainSize - 
mCssStyle->sumPaddingBorderOfEdge(kBottom)
+            + mCssStyle->sumPaddingBorderOfEdge(kTop)) / 2;
+        childBottom = childTop + flexLine->mMainSize;
+        break;
+      case kJustifySpaceAround:
+        visibleCount = flexLine->mItemCount;
+        if (visibleCount != 0) {
+          spaceBetweenItem = (height - flexLine->mMainSize - 
sumPaddingBorderAlongAxis(this, false))
+              / visibleCount;
+        }
+        childTop = getPaddingTop() + getBorderWidthTop() + spaceBetweenItem / 
2;
+        childBottom = height - getPaddingBottom() - getBorderWidthBottom() - 
spaceBetweenItem / 2;
+        break;
+      case kJustifySpaceBetween:
+        childTop = getPaddingTop() + getBorderWidthTop();
+        visibleItem = flexLine->mItemCount;
+        denominator = visibleItem != 1 ? visibleItem - 1 : 1.f;
+        spaceBetweenItem =
+            (height - flexLine->mMainSize - sumPaddingBorderAlongAxis(this, 
false)) / denominator;
+        childBottom = height - getPaddingBottom() - getBorderWidthBottom();
+        break;
+      case kJustifyFlexStart:
+      default:
+        childTop = getPaddingTop() + getBorderWidthTop();
+        childBottom = height - getPaddingBottom() - getBorderWidthBottom();
+        break;
+    }
+  }
+
+  void WXCoreLayoutNode::layoutSingleChildVertical(const bool isRtl, const 
bool fromBottomToTop,
+                                                   const bool absoluteFlexItem,
+                                                   const float childLeft, 
const float childRight,
+                                                   WXCoreFlexLine *const 
flexLine,
+                                                   WXCoreLayoutNode *const 
child,
+                                                   float &childTop, float 
&childBottom) {
+    childTop += child->getMarginTop();
+    childBottom -= child->getMarginBottom();
+    if (isRtl) {
+      if (fromBottomToTop) {
+        layoutSingleChildVertical(child, flexLine, true,
+                                  mCssStyle->mAlignItems,
+                                  childRight - 
child->mLayoutResult->mLayoutSize.width,
+                                  childBottom - 
child->mLayoutResult->mLayoutSize.height,
+                                  childRight, childBottom, absoluteFlexItem);
+      } else {
+        layoutSingleChildVertical(child, flexLine, true, 
mCssStyle->mAlignItems,
+                                  childRight - 
child->mLayoutResult->mLayoutSize.width, childTop,
+                                  childRight, childTop + 
child->mLayoutResult->mLayoutSize.height,
+                                  absoluteFlexItem);
+      }
+    } else {
+      if (fromBottomToTop) {
+        layoutSingleChildVertical(child, flexLine, false, 
mCssStyle->mAlignItems,
+                                  childLeft, childBottom - 
child->mLayoutResult->mLayoutSize.height,
+                                  childLeft + 
child->mLayoutResult->mLayoutSize.width, childBottom,
+                                  absoluteFlexItem);
+      } else {
+        layoutSingleChildVertical(child, flexLine, false, 
mCssStyle->mAlignItems,
+                                  childLeft, childTop,
+                                  childLeft + 
child->mLayoutResult->mLayoutSize.width,
+                                  childTop + 
child->mLayoutResult->mLayoutSize.height,
+                                  absoluteFlexItem);
+      }
+    }
+  }
+
+  /**
+   * Place a single View when the layout direction is vertical ({@link 
#mFlexDirection} is
+   * either {@link WXCoreFlexDirection #WXCore_Flex_Direction_Column} or
+   * {@link WXCoreFlexDirection #WXCore_Flex_Direction_Column_Reverse}).
+   *
+   * @param node       the View to be placed
+   * @param flexLine   the {@link FlexLine} where the View belongs to
+   * @param isRtl      {@code true} if the layout direction is mStyleRight to 
mStyleLeft, {@code false}
+   *                   otherwise
+   * @param alignItems the align items attribute of this BasicLayoutNode
+   * @param left       the mStyleLeft position of the flex line where the View 
belongs to. The actual
+   *                   View's mStyleLeft position is shifted depending on the 
isRtl and alignItems
+   *                   attributes
+   * @param top        the mStyleTop position of the View, which the View's 
margin is already taken
+   *                   into account
+   * @param right      the mStyleRight position of the flex line where the 
View belongs to. The actual
+   *                   View's mStyleRight position is shifted depending on the 
isRtl and alignItems
+   *                   attributes
+   * @param bottom     the mStyleBottom position of the View, which the View's 
margin is already taken
+   *                   into account
+   */
+  void WXCoreLayoutNode::layoutSingleChildVertical(WXCoreLayoutNode* const 
node, WXCoreFlexLine* const flexLine, const bool isRtl,
+                                                   WXCoreAlignItems 
alignItems, const float left, const float top, const float right,
+                                                   const float bottom, const 
bool absoluteFlexItem) {
+    if (node->mCssStyle->mAlignSelf != kAlignSelfAuto) {
+      // Expecting the values for alignItems and alignSelf match except for 
ALIGN_SELF_AUTO.
+      // Assigning the alignSelf value as alignItems should work.
+      alignItems = static_cast<WXCoreAlignItems>(node->mCssStyle->mAlignSelf);
+    }
+
+    float crossSize = flexLine->mCrossSize;
+
+    switch (alignItems) {
+      case kAlignItemsFlexStart:
+      case kAlignItemsStretch:
+        if (!isRtl) {
+          node->layout(left + node->getMarginLeft(), top, right + 
node->getMarginLeft(), bottom, absoluteFlexItem);
+        } else {
+          node->layout(left - node->getMarginRight(), top, right - 
node->getMarginRight(), bottom, absoluteFlexItem);
+        }
+        break;
+      case kAlignItemsFlexEnd:
+        if (!isRtl) {
+          node->layout(left + crossSize - 
node->mLayoutResult->mLayoutSize.width - node->getMarginRight(),
+                       top, right + crossSize - 
node->mLayoutResult->mLayoutSize.width - node->getMarginRight(),
+                       bottom, absoluteFlexItem);
+        } else {
+          // If the flexWrap == FLEX_WRAP_WRAP_REVERSE, the direction of the
+          // flexEnd is flipped (from mStyleLeft to mStyleRight).
+          node->layout(left - crossSize + 
node->mLayoutResult->mLayoutSize.width + node->getMarginLeft(), top,
+                       right - crossSize + 
node->mLayoutResult->mLayoutSize.width + node->getMarginLeft(),
+                       bottom, absoluteFlexItem);
+        }
+        break;
+      case kAlignItemsCenter:
+        float leftFromCrossAxis = (crossSize - 
node->mLayoutResult->mLayoutSize.width
+                                   + node->getMarginLeft()
+                                   - node->getMarginRight()) / 2.f;
+        if (!isRtl) {
+          node->layout(left + leftFromCrossAxis, top, right + 
leftFromCrossAxis, bottom, absoluteFlexItem);
+        } else {
+          node->layout(left - leftFromCrossAxis, top, right - 
leftFromCrossAxis, bottom, absoluteFlexItem);
+        }
+        break;
+    }
+  }
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Layout/WXCoreLayout.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXCoreLayout.h 
b/ios/sdk/WeexSDK/Sources/Layout/WXCoreLayout.h
new file mode 100644
index 0000000..498c243
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXCoreLayout.h
@@ -0,0 +1,1073 @@
+#ifdef __cplusplus
+
+#ifndef WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H
+#define WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H
+
+#include "WXCoreStyle.h"
+#include "WXCoreFlexEnum.h"
+#include <vector>
+#include <iostream>
+#include <string>
+#include <algorithm>
+
+namespace WeexCore {
+
+  class WXCoreLayoutNode;
+
+  class WXCoreFlexLine;
+
+  enum FormattingContext {
+    kBFC,
+    kNonBFC,
+  } ;
+
+  enum MeasureMode {
+    kUnspecified,
+    kExactly,
+  } ;
+
+  struct WXCoreSize {
+   private:
+    float hypotheticalWidth;
+    float hypotheticalHeight;
+   public:
+    friend class WXCoreLayoutNode;
+    float width;
+    float height;
+
+    WXCoreSize() : hypotheticalWidth(NAN),
+                   hypotheticalHeight(NAN),
+                   width(0), height(0) {}
+
+    inline void reset() {
+      hypotheticalWidth = NAN ;
+      hypotheticalHeight = NAN;
+      width = 0;
+      height = 0;
+    }
+
+    inline bool isNAN() {
+      return isnan(width) || isnan(height);
+    }
+  };
+
+  /**
+   * 
layout-result:layout-height、layout-width、position(left、right、top、bottom)
+   */
+  struct WXCorelayoutResult {
+    WXCoreSize mLayoutSize;
+    WXCorePosition mLayoutPosition;
+
+    inline bool isNAN() {
+      return mLayoutSize.isNAN() || mLayoutPosition.isNAN();
+    }
+
+    inline void reset() {
+      mLayoutSize.reset();
+      mLayoutPosition.reset();
+    }
+  };
+
+  typedef WXCoreSize(*WXCoreMeasureFunc)(WXCoreLayoutNode *node, float width,
+                                         MeasureMode widthMeasureMode,
+                                         float height, MeasureMode 
heightMeasureMode);
+
+  using Index = std::vector<WXCoreLayoutNode *>::size_type;
+
+  /**
+   * flie line
+   */
+  class WXCoreFlexLine {
+  public:
+    float mMainSize;
+
+    float mCrossSize;
+
+    Index mItemCount;
+
+    float mTotalFlexGrow;
+
+    float mTotalFlexibleSize;
+
+    /**
+     * Store the indices of the children views whose mAlignSelf property is 
stretch.
+     * The stored indices are the absolute indices including all children in 
the Flexbox,
+     * not the relative indices in this flex line.
+     */
+    std::vector<Index> mIndicesAlignSelfStretch;
+
+    WXCoreFlexLine() : mMainSize(0),
+                       mCrossSize(0),
+                       mItemCount(0),
+                       mTotalFlexGrow(0),
+                       mTotalFlexibleSize(0) {
+    }
+
+    ~WXCoreFlexLine() {
+      mMainSize = 0;
+      mCrossSize = 0;
+      mItemCount = 0;
+      mTotalFlexGrow = 0;
+      mTotalFlexibleSize = 0;
+      mIndicesAlignSelfStretch.clear();
+    }
+  };
+
+  /**
+   * Layout node
+   */
+  class WXCoreLayoutNode {
+
+  public:
+      WXCoreLayoutNode() :
+              mParent(nullptr),
+              dirty(true),
+              widthDirty{false},
+              heightDirty{false},
+              mHasNewLayout(true),
+              mIsDestroy(false),
+              measureFunc(nullptr) {
+        mCssStyle = new WXCoreCSSStyle();
+        mLayoutResult = new WXCorelayoutResult();
+      }
+
+
+      ~WXCoreLayoutNode() {
+          mIsDestroy = true;
+        mHasNewLayout = true;
+        dirty = true;
+        measureFunc = nullptr;
+        mParent = nullptr;
+        mChildList.clear();
+        BFCs.clear();
+        NonBFCs.clear();
+        mChildrenFrozen.clear();
+
+        for (WXCoreFlexLine *flexLine : mFlexLines) {
+          if (flexLine != nullptr) {
+            delete flexLine;
+            flexLine = nullptr;
+          }
+        }
+        mFlexLines.clear();
+
+        if (mCssStyle != nullptr) {
+          delete mCssStyle;
+          mCssStyle = nullptr;
+        }
+
+        if (mLayoutResult != nullptr) {
+          delete mLayoutResult;
+          mLayoutResult = nullptr;
+        }
+      }
+
+  private:
+
+    /**
+     * Holds the 'frozen' state of children during measure. If a view is 
frozen it will no longer
+     * expand regardless of mFlexGrow. Items are indexed by the child's
+     * reordered index.
+     */
+    std::vector<bool> mChildrenFrozen;
+
+    std::vector<WXCoreFlexLine *> mFlexLines;
+
+    std::vector<WXCoreLayoutNode *> mChildList;
+
+    std::vector<WXCoreLayoutNode *> BFCs;
+
+    std::vector<WXCoreLayoutNode *> NonBFCs;
+
+    WXCoreLayoutNode *mParent = nullptr;
+
+    WXCoreCSSStyle *mCssStyle = nullptr;
+
+    MeasureMode widthMeasureMode = kUnspecified;
+
+    MeasureMode heightMeasureMode = kUnspecified;
+
+    WXCorelayoutResult *mLayoutResult = nullptr;
+
+    WXCorePosition *absoultePositon = nullptr;
+
+    bool mHasNewLayout;
+
+    bool dirty, widthDirty, heightDirty;
+
+    bool mIsDestroy = true;
+
+    WXCoreMeasureFunc measureFunc = nullptr;
+
+    void *context;
+
+    /** ================================ Cache:Last calculate result 
=================================== **/
+
+  public:
+
+
+    /** ================================ Engine Entry Function 
=================================== **/
+
+    void calculateLayout(const std::pair<float,float>&);
+
+    /** ================================ measureFunc 
=================================== **/
+
+    inline void setMeasureFunc(WXCoreMeasureFunc measure) {
+      measureFunc = measure;
+      markDirty();
+    }
+
+    inline WXCoreMeasureFunc getMeasureFunc() const {
+      return measureFunc;
+    }
+
+    inline bool haveMeasureFunc() const {
+      return measureFunc != nullptr;
+    }
+
+    /** ================================ context 
=================================== **/
+
+
+    inline void *getContext() const {
+      return context;
+    }
+
+    inline void setContext(void * const context) {
+      this->context = context;
+    }
+
+    inline void copyStyle(WXCoreLayoutNode *srcNode) {
+      if (memcmp(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle)) != 0) {
+        memcpy(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle));
+        markDirty();
+      }
+    }
+
+    inline void copyMeasureFunc(WXCoreLayoutNode *srcNode) {
+      if (memcmp(&measureFunc, &srcNode->measureFunc, 
sizeof(WXCoreMeasureFunc)) != 0) {
+        memcpy(&measureFunc, &srcNode->measureFunc, sizeof(WXCoreMeasureFunc));
+        markDirty();
+      }
+    }
+
+  private:
+
+    /** ================================ measure 
=================================== **/
+
+    inline void reset() {
+      if (isDirty()) {
+        mLayoutResult->reset();
+        for (WXCoreFlexLine *flexLine : mFlexLines) {
+          if (flexLine != nullptr) {
+            delete flexLine;
+            flexLine = nullptr;
+          }
+        }
+        mFlexLines.clear();
+
+        mChildrenFrozen.assign(getChildCount(kNonBFC), false);
+      }
+      widthMeasureMode = isnan(mCssStyle->mStyleWidth) ? kUnspecified : 
kExactly;
+      heightMeasureMode = isnan(mCssStyle->mStyleHeight) ? kUnspecified : 
kExactly;
+    }
+
+    inline void setLayoutWidth(const float width) {
+      if (mLayoutResult->mLayoutSize.width != width &&
+          (!isnan(width) || !isnan(mLayoutResult->mLayoutSize.width))) {
+        mLayoutResult->mLayoutSize.width = width;
+        widthDirty = true;
+        markDirty(false);
+      }
+    }
+
+    inline void setLayoutHeight(const float height) {
+      if (mLayoutResult->mLayoutSize.height != height &&
+          (!isnan(height) || !isnan(mLayoutResult->mLayoutSize.height))) {
+        mLayoutResult->mLayoutSize.height = height;
+        heightDirty = true;
+        markDirty(false);
+      }
+    }
+
+    inline void setWidthMeasureMode(const MeasureMode measureMode) {
+      if (widthMeasureMode != measureMode) {
+        widthMeasureMode = measureMode;
+        if (getChildCount(kNonBFC) > 0) {
+          widthDirty = true;
+        }
+      }
+    }
+
+    inline void setHeightMeasureMode(const MeasureMode measureMode) {
+      if (heightMeasureMode != measureMode) {
+        heightMeasureMode = measureMode;
+        if (getChildCount(kNonBFC) > 0) {
+          heightDirty = true;
+        }
+      }
+    }
+
+    inline float firstLineCrossSize() const {
+      float sum = sumPaddingBorderAlongAxis(this, !isMainAxisHorizontal(this));
+      if (!mFlexLines.empty()) {
+        sum += mFlexLines[0]->mCrossSize;
+      }
+      return sum;
+    }
+
+    inline float getSumOfCrossSize() const {
+      float sum = sumPaddingBorderAlongAxis(this, !isMainAxisHorizontal(this));
+      for (WXCoreFlexLine *flexLine: mFlexLines) {
+        sum += flexLine->mCrossSize;
+      }
+      return sum;
+    }
+
+    inline bool isMainAxisHorizontal(const WXCoreLayoutNode* const node) const 
{
+      return node->mCssStyle->mFlexDirection == kFlexDirectionRow ||
+             node->mCssStyle->mFlexDirection == kFlexDirectionRowReverse;
+    }
+
+    inline bool isCrossExactly() const {
+      return isMainAxisHorizontal(this) ? heightMeasureMode == kExactly
+                                        : widthMeasureMode == kExactly;
+    }
+
+    inline float sumPaddingBorderAlongAxis(const WXCoreLayoutNode* const node, 
bool horizontal) const {
+      float paddingBorderAlongAxis;
+      if (horizontal) {
+        paddingBorderAlongAxis =
+            node->mCssStyle->mPadding.getPadding(kPaddingLeft) +
+            node->mCssStyle->mPadding.getPadding(kPaddingRight) +
+            node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthLeft) +
+            node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthRight);
+      } else {
+        paddingBorderAlongAxis =
+            node->mCssStyle->mPadding.getPadding(kPaddingTop) +
+            node->mCssStyle->mPadding.getPadding(kPaddingBottom) +
+            node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthTop) +
+            node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthBottom);
+      }
+      return paddingBorderAlongAxis;
+    }
+
+    inline bool isWrapRequired(const float &width, const float &height,
+                               const float &currentLength, const float 
&childLength) const {
+      float freeMainSize = calcFreeSpaceAlongMainAxis(width, height, 
currentLength);
+      return !isSingleFlexLine(freeMainSize) && freeMainSize < childLength;
+    }
+
+    //If width/height is NAN, ret is NAN, which property we use on purpose.
+    virtual float calcFreeSpaceAlongMainAxis(const float &width, const float 
&height, const float &currentLength) const{
+      float ret;
+      if(isMainAxisHorizontal(this)){
+        ret = width - sumPaddingBorderAlongAxis(this, true) - currentLength;
+      }
+      else{
+        ret = height - sumPaddingBorderAlongAxis(this, false) - currentLength;
+      }
+      return ret;
+    }
+
+    inline bool isSingleFlexLine(const float &mainSize) const {
+      return mCssStyle->mFlexWrap == kNoWrap || isnan(mainSize);
+    }
+
+    inline void sumFlexGrow(const WXCoreLayoutNode* const child, 
WXCoreFlexLine* const flexLine, Index i){
+      if (child->mCssStyle->mFlexGrow > 0) {
+        flexLine->mTotalFlexGrow += child->mCssStyle->mFlexGrow;
+        mChildrenFrozen[i] = false;
+        if (isMainAxisHorizontal(this)) {
+          if (!isnan(child->mLayoutResult->mLayoutSize.hypotheticalWidth)) {
+            flexLine->mTotalFlexibleSize += 
child->mLayoutResult->mLayoutSize.hypotheticalWidth;
+          }
+        } else {
+          if (!isnan(child->mLayoutResult->mLayoutSize.hypotheticalHeight)) {
+            flexLine->mTotalFlexibleSize += 
child->mLayoutResult->mLayoutSize.hypotheticalHeight;
+          }
+        }
+      } else {
+        mChildrenFrozen[i] = true;
+      }
+    }
+
+    inline void setMeasuredDimensionForFlex(
+        const float width, const MeasureMode widthMeasureMode,
+        const float height, const MeasureMode heightMeasureMode){
+      float actualWidth, actualHeight;
+      if (isMainAxisHorizontal(this)) {
+        actualWidth = widthMeasureMode == kExactly ? width : 
getLargestMainSize();
+        actualHeight = heightMeasureMode == kExactly ? height : 
getSumOfCrossSize();
+      } else {
+        actualHeight = heightMeasureMode == kExactly ? height : 
getLargestMainSize();
+        actualWidth = widthMeasureMode == kExactly ? width : 
firstLineCrossSize();
+      }
+      setMeasuredDimension(actualWidth, actualHeight);
+    }
+
+    inline float calcItemSizeAlongAxis(const WXCoreLayoutNode* const node, 
const bool horizontal, const bool useHypotheticalSize = false) const {
+      float ret;
+      if (horizontal) {
+        ret = node->mCssStyle->mMargin.getMargin(kMarginLeft) +
+            node->mCssStyle->mMargin.getMargin(kMarginRight);
+        ret += useHypotheticalSize ? 
node->mLayoutResult->mLayoutSize.hypotheticalWidth
+                                   : node->mLayoutResult->mLayoutSize.width;
+      } else {
+        ret = node->mCssStyle->mMargin.getMargin(kMarginTop) +
+            node->mCssStyle->mMargin.getMargin(kMarginBottom);
+        ret += useHypotheticalSize ? 
node->mLayoutResult->mLayoutSize.hypotheticalHeight
+                                   : node->mLayoutResult->mLayoutSize.height;
+      }
+      return ret;
+    }
+
+    inline void limitMainSizeForFlexGrow(WXCoreFlexLine* const flexLine, const 
Index childIndex,
+                                  const float flexGrow) {
+      mChildrenFrozen[childIndex] = true;
+      flexLine->mTotalFlexGrow -= flexGrow;
+    }
+
+    inline void setMeasuredDimension(const float width, const float height) {
+      mLayoutResult->mLayoutSize.width = width;
+      mLayoutResult->mLayoutSize.height = height;
+    }
+
+    inline std::pair<bool, float> limitChildMainSize(WXCoreFlexLine* const 
flexLine, const WXCoreLayoutNode* const child,
+                                                                       float 
childSizeAlongMainAxis, const Index childIndex){
+      bool needsReexpand = false;
+      if (isMainAxisHorizontal(this)) {
+        if (!isnan(child->mCssStyle->mMaxWidth) &&
+            childSizeAlongMainAxis > child->mCssStyle->mMaxWidth) {
+          needsReexpand = true;
+          childSizeAlongMainAxis = child->mCssStyle->mMaxWidth;
+        } else if (!isnan(child->mCssStyle->mMinWidth) &&
+            childSizeAlongMainAxis < child->mCssStyle->mMinWidth) {
+          needsReexpand = true;
+          childSizeAlongMainAxis = child->mCssStyle->mMinWidth;
+        }
+      } else {
+        if (!isnan(child->mCssStyle->mMaxHeight) &&
+            childSizeAlongMainAxis > child->mCssStyle->mMaxHeight) {
+          needsReexpand = true;
+          childSizeAlongMainAxis = child->mCssStyle->mMaxHeight;
+        } else if (!isnan(child->mCssStyle->mMinHeight) &&
+            childSizeAlongMainAxis < child->mCssStyle->mMinHeight) {
+          needsReexpand = true;
+          childSizeAlongMainAxis = child->mCssStyle->mMinHeight;
+        }
+      }
+      limitMainSizeForFlexGrow(flexLine, childIndex, 
child->mCssStyle->mFlexGrow);
+      return std::make_pair(needsReexpand, childSizeAlongMainAxis);
+    }
+
+    void updateLeftRightForAbsolute(float &left, float &right,
+                                    const WXCorePadding &parentPadding,
+                                    const WXCoreBorderWidth &parentBorder,
+                                    const WXCoreSize &parentSize) const {
+      if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft))) {
+        if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeRight))) {
+          ;
+        } else {
+          right += parentSize.width -
+              (parentBorder.getBorderWidth(kBorderWidthRight) +
+                  mCssStyle->mStylePosition.getPosition(kPositionEdgeRight)
+                  + mLayoutResult->mLayoutSize.width);
+          left += parentSize.width -
+              (parentBorder.getBorderWidth(kBorderWidthRight) +
+                  mCssStyle->mStylePosition.getPosition(kPositionEdgeRight)
+                  + mLayoutResult->mLayoutSize.width);
+        }
+      } else {
+        left += parentBorder.getBorderWidth(kBorderWidthLeft) +
+            mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft);
+        right += parentBorder.getBorderWidth(kBorderWidthLeft) +
+            mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft);
+      }
+    }
+
+    void updateTopBottomForAbsolute(float &top, float &bottom,
+                                    const WXCorePadding &parentPadding,
+                                    const WXCoreBorderWidth &parentBorder,
+                                    const WXCoreSize &parentSize) const {
+      if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeTop))) {
+        if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom))) 
{
+          ;
+        } else {
+          top += parentSize.height -
+              (parentBorder.getBorderWidth(kBorderWidthBottom) +
+                  mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom)
+                  + mLayoutResult->mLayoutSize.height);
+          bottom += parentSize.height -
+              (parentBorder.getBorderWidth(kBorderWidthBottom) +
+                  mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom)
+                  + mLayoutResult->mLayoutSize.height);
+        }
+      } else {
+        top += parentBorder.getBorderWidth(kBorderWidthTop) +
+            mCssStyle->mStylePosition.getPosition(kPositionEdgeTop);
+        bottom += parentBorder.getBorderWidth(kBorderWidthTop) +
+            mCssStyle->mStylePosition.getPosition(kPositionEdgeTop);
+      }
+    }
+
+    /** ================================ other 
=================================== **/
+
+    inline void clearDirty() {
+      dirty = false;
+      widthDirty = false;
+      heightDirty = false;
+    }
+
+    void
+    measure(float, float, bool);
+
+    void hypotheticalMeasure(float, float, bool = false);
+
+    void measureLeafNode(float, float, bool, bool);
+
+    void measureInternalNode(float, float, bool, bool);
+
+    void updateCurrentFlexline(Index, WXCoreFlexLine *, Index, const 
WXCoreLayoutNode *, bool);
+
+    void measureChild(WXCoreLayoutNode* , float, float, float, bool, bool);
+
+    void adjustChildSize(WXCoreLayoutNode *, float);
+
+    void adjustChildSize(const WXCoreLayoutNode *child,
+                         const float currentMainSize,
+                         const float parentWidth,
+                         const float parentHeight,
+                         float &childWidth,
+                         float &childHeight) const;
+
+    void stretchViewCrossSize();
+
+    void stretchViewCrossSize(WXCoreLayoutNode *, float);
+
+    Index expandItemsInFlexLine(WXCoreFlexLine *, float, Index);
+
+    void checkSizeConstraints(WXCoreLayoutNode *, bool);
+
+    void
+    determineMainSize(float width, float height);
+
+    void
+    determineCrossSize(float, float, bool);
+
+    void setFrame(float, float, float, float);
+
+    void setFrame(WXCorePosition*,float, float, float, float);
+
+    /** ================================ layout 
=================================== **/
+
+    void layout(float left, float top, float right, float bottom, bool, const 
std::pair<float,float>* = nullptr);
+
+    void calcRelativeOffset(float &left, float &top, float &right, float 
&bottom) const ;
+
+    void calcAbsoluteOffset(float &left, float &top, float &right, float 
&bottom, const std::pair<float,float>* = nullptr);
+
+    void positionAbsoluteFlexItem(float &left, float &top, float &right, float 
&bottom);
+
+    void onLayout(float left, float top, float right, float bottom, 
WXCoreLayoutNode* = nullptr, WXCoreFlexLine *const flexLine = nullptr);
+
+    void layoutHorizontal(bool isRtl, float left, float top, float right, 
float bottom,
+                          WXCoreLayoutNode*, WXCoreFlexLine *const flexLine);
+
+    void layoutFlexlineHorizontal(const float width,
+                                         const WXCoreFlexLine *const flexLine,
+                                         float &childLeft,
+                                         float &childRight,
+                                         float &spaceBetweenItem) const;
+
+    void layoutSingleChildHorizontal(WXCoreLayoutNode *node, WXCoreFlexLine 
*flexLine,
+                                     WXCoreFlexWrap flexWrap, WXCoreAlignItems 
alignItems,
+                                     float, float, float, float, bool);
+
+    void layoutSingleChildHorizontal(const bool isRtl,
+                                    const bool,
+                                    float childBottom, float childTop,
+                                    WXCoreFlexLine *const flexLine,
+                                    WXCoreLayoutNode *const child,
+                                    float&, float&);
+
+    void layoutVertical(bool isRtl, bool fromBottomToTop, float left, float 
top, float right, float bottom,
+                        WXCoreLayoutNode*, WXCoreFlexLine *const flexLine);
+
+    void layoutFlexlineVertical(const float height,
+                                const WXCoreFlexLine *const flexLine,
+                                float &childTop,
+                                float &childBottom,
+                                float &spaceBetweenItem) const;
+    void layoutSingleChildVertical(WXCoreLayoutNode *node, WXCoreFlexLine 
*flexLine,
+                                   bool isRtl, WXCoreAlignItems alignItems,
+                                   float, float, float, float, bool);
+
+    void layoutSingleChildVertical(const bool isRtl, const bool 
fromBottomToTop,
+                                   const bool absoluteFlexItem,
+                                   const float childLeft, const float 
childRight,
+                                   WXCoreFlexLine *const flexLine,
+                                   WXCoreLayoutNode *const child,
+                                   float& ,float&);
+
+    void updateFlexLineForAbsoluteItem(WXCoreLayoutNode *const 
absoluteFlexItem, WXCoreFlexLine *const flexLine);
+
+    void initFormatingContext(std::vector<WXCoreLayoutNode *> &BFCs);
+
+    std::pair<bool,float> calculateBFCWidth(float, float);
+
+    std::pair<bool,float> calculateBFCHeight(float, float);
+
+    std::tuple<bool, float, float> calculateBFCDimension(const 
std::pair<float,float>&);
+
+    virtual void onLayoutBefore() {
+
+    }
+
+    virtual void onLayoutAfter(float width, float height) {
+
+    }
+
+
+  public:
+
+    /** ================================ tree 
=================================== **/
+
+    inline Index getChildCount(FormattingContext formattingContext) const {
+      switch (formattingContext) {
+        case kNonBFC:
+          return NonBFCs.size();
+        case kBFC:
+          return BFCs.size();
+        default:
+          return mChildList.size();
+      }
+    }
+
+    inline Index getChildCount() const {
+      return mChildList.size();
+    }
+
+    inline std::vector<WXCoreLayoutNode *>::const_iterator 
ChildListIterBegin() {
+      return mChildList.cbegin();
+    }
+
+    inline std::vector<WXCoreLayoutNode *>::const_iterator ChildListIterEnd() {
+      return mChildList.cend();
+    }
+
+    inline void removeChild(const WXCoreLayoutNode* const child) {
+      for (int index = 0; index < mChildList.size(); index++) {
+        if (child == mChildList[index]) {
+          mChildList.erase(mChildList.begin() + index);
+          break;
+        }
+      }
+      markDirty();
+    }
+
+    inline void addChildAt(WXCoreLayoutNode* const child, Index index) {
+      mChildList.insert(mChildList.begin() + index, child);
+      child->mParent = this;
+      markDirty();
+    }
+
+    inline WXCoreLayoutNode *getChildAt(const FormattingContext 
formattingContext, const Index index) const {
+      switch (formattingContext) {
+        case kNonBFC:
+          return NonBFCs[index];
+        case kBFC:
+          return BFCs[index];
+        default:
+          return mChildList[index];
+      }
+    }
+
+    inline WXCoreLayoutNode *getChildAt(const Index index) const {
+      return mChildList[index];
+    }
+
+    inline WXCoreLayoutNode *getParent() const {
+      return mParent;
+    }
+
+    inline bool isBFC(WXCoreLayoutNode* const node) const {
+      return node->mCssStyle->mPositionType == kAbsolute || 
node->mCssStyle->mPositionType == kFixed;
+    }
+
+    /** ================================ margin 
=================================== **/
+
+    inline float getMarginTop() const {
+      return mCssStyle->mMargin.getMargin(kMarginTop);
+    }
+
+    inline float getMarginBottom() const {
+      return mCssStyle->mMargin.getMargin(kMarginBottom);
+    }
+
+    inline float getMarginLeft() const  {
+      return mCssStyle->mMargin.getMargin(kMarginLeft);
+    }
+
+    inline float getMarginRight() const {
+      return mCssStyle->mMargin.getMargin(kMarginRight);
+    }
+
+    inline void setMargin(const WXCoreMarginEdge &edge, const float margin) {
+      if (mCssStyle->mMargin.setMargin(edge, margin)) {
+        markDirty();
+      }
+    }
+
+    inline const WXCoreMargin &GetMargins() const {
+      return mCssStyle->mMargin;
+    }
+
+    /** ================================ padding 
=================================== **/
+
+    inline float getPaddingLeft() const {
+      return mCssStyle->mPadding.getPadding(kPaddingLeft);
+    }
+
+    inline float getPaddingRight() const {
+      return mCssStyle->mPadding.getPadding(kPaddingRight);
+    }
+
+    inline float getPaddingTop() const {
+      return mCssStyle->mPadding.getPadding(kPaddingTop);
+    }
+
+    inline float getPaddingBottom() const {
+      return mCssStyle->mPadding.getPadding(kPaddingBottom);
+    }
+
+    inline void setPadding(const WXCorePaddingEdge edge, const float padding) {
+      if (mCssStyle->mPadding.setPadding(edge, padding)) {
+        markDirty();
+      }
+    }
+
+    inline const WXCorePadding &GetPaddings() const {
+      return mCssStyle->mPadding;
+    }
+
+    /** ================================ border-width 
=================================== **/
+
+    inline float getBorderWidthLeft() const {
+      return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthLeft);
+    }
+
+    inline float getBorderWidthRight() const {
+      return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthRight);
+    }
+
+    inline float getBorderWidthTop() const {
+      return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthTop);
+    }
+
+    inline float getBorderWidthBottom() const {
+      return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthBottom);
+    }
+
+    inline void setBorderWidth(const WXCoreBorderWidthEdge edge, const float 
borderWidth) {
+      if (mCssStyle->mBorderWidth.setBorderWidth(edge, borderWidth)) {
+        markDirty();
+      }
+    }
+
+    inline const WXCoreBorderWidth &GetBorders() const {
+      return mCssStyle->mBorderWidth;
+    }
+
+    /** ================================ position-type 
=================================== **/
+
+    inline void setStylePositionType(const WXCorePositionType positionType) {
+      if (mCssStyle->mPositionType != positionType) {
+        mCssStyle->mPositionType = positionType;
+        markDirty();
+      }
+    }
+
+    inline WXCorePositionType getStypePositionType() const {
+      return mCssStyle->mPositionType;
+    }
+
+
+    /** ================================ position 
=================================== **/
+
+    inline float getStylePositionTop() const {
+      return mCssStyle->mStylePosition.getPosition(kPositionEdgeTop);
+    }
+
+    inline float getStylePositionBottom() const {
+      return mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom);
+    }
+
+    inline float getStylePositionLeft() const {
+      return mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft);
+    }
+
+    inline float getStylePositionRight() const {
+      return mCssStyle->mStylePosition.getPosition(kPositionEdgeRight);
+    }
+
+    inline void setStylePosition(const WXCorePositionEdge edge, const float 
positionRight) {
+      if (mCssStyle->mStylePosition.setPosition(edge, positionRight))
+        markDirty();
+    }
+
+
+    /** ================================ dimension 
=================================== **/
+
+    inline void setStyleWidthLevel(const DimensionLevel level) const {
+      if (mCssStyle->mStyleWidthLevel != level) {
+        mCssStyle->mStyleWidthLevel = level;
+      }
+    }
+
+    inline void setStyleHeightLevel(const DimensionLevel level) const {
+      if (mCssStyle->mStyleHeightLevel != level) {
+        mCssStyle->mStyleHeightLevel = level;
+      }
+    }
+
+    inline DimensionLevel getStyleHeightLevel() const {
+      return mCssStyle->mStyleHeightLevel;
+    }
+
+    inline DimensionLevel getStyleWidthLevel() const {
+      return mCssStyle->mStyleWidthLevel;
+    }
+
+    inline void setStyleWidth(const float width, const bool updating) {
+      if (mCssStyle->mStyleWidth != width) {
+        mCssStyle->mStyleWidth = width;
+        markDirty();
+        if(updating) {
+          markChildrenDirty(true);
+        }
+      }
+    }
+
+    inline void setStyleWidthToNAN() {
+      if (!isnan(mCssStyle->mStyleWidth)) {
+        mCssStyle->mStyleWidth = NAN;
+        markDirty();
+        markChildrenDirty(true);
+      }
+    }
+
+    inline float getStyleWidth() const {
+      return mCssStyle->mStyleWidth;
+    }
+
+    inline void setStyleHeight(const float height) {
+      if (mCssStyle->mStyleHeight != height) {
+        mCssStyle->mStyleHeight = height;
+        markDirty();
+      }
+    }
+
+    inline float getStyleHeight() const {
+      return mCssStyle->mStyleHeight;
+    }
+
+    inline void setMinWidth(const float minWidth, const bool updating) {
+      if (mCssStyle->mMinWidth != minWidth) {
+        mCssStyle->mMinWidth = minWidth;
+        markDirty();
+        if(updating) {
+          markChildrenDirty(true);
+        }
+      }
+    }
+
+    inline float getMinWidth() const {
+      return mCssStyle->mMinWidth;
+    }
+
+    inline void setMaxWidth(const float maxWidth, const bool updating) {
+      if (mCssStyle->mMaxWidth != maxWidth) {
+        mCssStyle->mMaxWidth = maxWidth;
+        markDirty();
+        if(updating) {
+          markChildrenDirty(true);
+        }
+      }
+    }
+
+    inline float getMaxWidth() const {
+      return mCssStyle->mMaxWidth;
+    }
+
+    inline void setMinHeight(const float minHeight) {
+      if (mCssStyle->mMinHeight != minHeight) {
+        mCssStyle->mMinHeight = minHeight;
+        markDirty();
+      }
+    }
+
+    inline float getMinHeight() const {
+      return mCssStyle->mMinHeight;
+    }
+
+    inline void setMaxHeight(const float maxHeight) {
+      if (mCssStyle->mMaxHeight != maxHeight) {
+        mCssStyle->mMaxHeight = maxHeight;
+        markDirty();
+      }
+    }
+
+    inline float getMaxHeight() const {
+      return mCssStyle->mMaxHeight;
+    }
+
+
+    /** ================================ flex-style 
=================================== **/
+
+    inline void setFlexDirection(const WXCoreFlexDirection flexDirection, 
const bool updating) {
+      if (mCssStyle->mFlexDirection != flexDirection) {
+        mCssStyle->mFlexDirection = flexDirection;
+        markDirty();
+        if (updating) {
+          for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) 
{
+            (*it)->markDirty(false);
+          }
+        }
+      }
+    }
+
+    inline WXCoreFlexDirection getFlexDirection() const {
+      return mCssStyle->mFlexDirection;
+    }
+
+    inline void setFlexWrap(const WXCoreFlexWrap flexWrap) {
+      if (mCssStyle->mFlexWrap != flexWrap) {
+        mCssStyle->mFlexWrap = flexWrap;
+        markDirty();
+      }
+    }
+
+    inline WXCoreFlexWrap getFlexWrap() const {
+      return mCssStyle->mFlexWrap;
+    }
+
+    inline void setJustifyContent(const WXCoreJustifyContent justifyContent) {
+      if (mCssStyle->mJustifyContent != justifyContent) {
+        mCssStyle->mJustifyContent = justifyContent;
+      }
+    }
+
+    inline WXCoreJustifyContent getJustifyContent() const {
+      return mCssStyle->mJustifyContent;
+    }
+
+    inline void setAlignItems(const WXCoreAlignItems alignItems) {
+      if (mCssStyle->mAlignItems != alignItems) {
+        mCssStyle->mAlignItems = alignItems;
+        markDirty();
+      }
+    }
+
+    inline WXCoreAlignItems getAlignItems() const {
+      return mCssStyle->mAlignItems;
+    }
+
+    inline void setAlignSelf(const WXCoreAlignSelf alignSelf) {
+      if (mCssStyle->mAlignSelf != alignSelf) {
+        mCssStyle->mAlignSelf = alignSelf;
+        markDirty();
+      }
+    }
+
+    inline WXCoreAlignSelf getAlignSelf() const {
+      return mCssStyle->mAlignSelf;
+    }
+
+    virtual void setFlex(const float flex) {
+      if (mCssStyle->mFlexGrow != flex) {
+        mCssStyle->mFlexGrow = flex;
+        markDirty();
+      }
+    }
+
+    inline float getFlex() const {
+      return mCssStyle->mFlexGrow;
+    }
+
+    /** ================================ layout-result 
=================================== **/
+
+    inline float getLayoutWidth() const {
+      return mLayoutResult->mLayoutSize.width;
+    }
+
+    inline float getLayoutHeight() const {
+      return mLayoutResult->mLayoutSize.height;
+    }
+
+    inline float getLayoutPositionTop() const {
+      return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeTop);
+    }
+
+    inline float getLayoutPositionBottom() const {
+      return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeBottom);
+    }
+
+    inline float getLayoutPositionLeft() const {
+      return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeLeft);
+    }
+
+    inline float getLayoutPositionRight() const  {
+      return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeRight);
+    }
+
+    inline bool hasNewLayout() const {
+      return mHasNewLayout;
+    }
+
+    inline bool isDirty() const {
+      return dirty;
+    }
+
+    inline void markDirty(const bool recursion = true) {
+      if (!isDirty()) {
+        dirty = true;
+        if (getParent() != nullptr && recursion) {
+          getParent()->markDirty();
+        }
+      }
+    }
+
+    bool markChildrenDirty(const bool updatedNode = false) {
+      bool ret = false;
+      if(getChildCount() == 0){
+        if(measureFunc!= nullptr){
+          ret = true;
+        }
+      }
+      else {
+        //isnan(mCssStyle->mStyleWidth) XOR updatedNode
+        if(isnan(mCssStyle->mStyleWidth) != updatedNode){
+          for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) 
{
+            ret = ((*it)->markChildrenDirty() || ret) ;
+          }
+        }
+      }
+      dirty = ret || dirty;
+      return ret;
+    }
+
+    inline void setHasNewLayout(const bool hasNewLayout) {
+      this->mHasNewLayout = hasNewLayout;
+    }
+
+    inline float getLargestMainSize() const {
+      float largestSize = 0;
+      for (WXCoreFlexLine *flexLine : mFlexLines) {
+        largestSize = std::max(largestSize, flexLine->mMainSize);
+      }
+      return largestSize + sumPaddingBorderAlongAxis(this, 
isMainAxisHorizontal(this));
+    }
+  };
+}
+#endif //WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H
+#endif

Reply via email to