http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/bridge/bridge.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/bridge/bridge.h 
b/weex_core/Source/core/bridge/bridge.h
new file mode 100644
index 0000000..8076232
--- /dev/null
+++ b/weex_core/Source/core/bridge/bridge.h
@@ -0,0 +1,81 @@
+#ifndef Bridge_h
+#define Bridge_h
+
+#include <jni.h>
+#include <string>
+#include <map>
+#include <set>
+#include <vector>
+
+namespace WeexCore {
+
+  class WXCoreMargin;
+
+  class WXCorePadding;
+
+  class WXCoreBorderWidth;
+
+  class Bridge {
+  public:
+    virtual void setJSVersion(const char* version) = 0;
+
+    virtual void reportException(const char* pageId, const char *func, const 
char *exception_string) = 0;
+
+    virtual int callNative(const char* pageId, const char *task, const char 
*callback) = 0;
+
+    virtual jobject callNativeModule(const char* pageId, const char *module, 
const char *method,
+                                     const char *argString, const char 
*optString) = 0;
+
+    virtual void callNativeComponent(const char* pageId, const char* ref, 
const char *method,
+                                     const char *argString, const char 
*optString) = 0;
+
+    virtual void setTimeout(const char* callbackID, const char* time) = 0;
+
+    virtual void callNativeLog(const char* str_array) = 0;
+
+    virtual int callUpdateFinish(const char* pageId, const char *task, const 
char *callback) = 0;
+
+    virtual int callRefreshFinish(const char* pageId, const char *task, const 
char *callback) = 0;
+
+    virtual int callAddEvent(const char* pageId, const char* ref, const char 
*event) = 0;
+
+    virtual int callRemoveEvent(const char* pageId, const char* ref, const 
char *event) = 0;
+
+    virtual int callCreateBody(const char* pageId, const char *componentType, 
const char* ref,
+                               std::map<std::string, std::string> *styles,
+                               std::map<std::string, std::string> *attributes,
+                               std::set<std::string> *events,
+                               const WXCoreMargin &margins,
+                               const WXCorePadding &paddings,
+                               const WXCoreBorderWidth &borders) = 0;
+
+    virtual int callAddElement(const char* pageId, const char *componentType, 
const char* ref,
+                               int &index, const char* parentRef,
+                               std::map<std::string, std::string> *styles,
+                               std::map<std::string, std::string> *attributes,
+                               std::set<std::string> *events,
+                               const WXCoreMargin &margins,
+                               const WXCorePadding &paddings,
+                               const WXCoreBorderWidth &borders) = 0;
+
+    virtual int callLayout(const char* pageId, const char* ref,
+                           int top, int bottom, int left, int right,
+                           int height, int width, int index) = 0;
+
+    virtual int callUpdateStyle(const char* pageId, const char* ref,
+                                std::vector<std::pair<std::string, 
std::string>> *style,
+                                std::vector<std::pair<std::string, 
std::string>> *margin,
+                                std::vector<std::pair<std::string, 
std::string>> *padding,
+                                std::vector<std::pair<std::string, 
std::string>> *border) = 0;
+
+    virtual int callUpdateAttr(const char* pageId, const char* ref,
+                               std::vector<std::pair<std::string, 
std::string>> *attrs) = 0;
+
+    virtual int callCreateFinish(const char* pageId) = 0;
+
+    virtual int callRemoveElement(const char* pageId, const char* ref) = 0;
+
+    virtual int callMoveElement(const char* pageId, const char* ref, const 
char* parentRef, int index) = 0;
+  };
+} //end WeexCore
+#endif //Bridge_h

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/config/core_environment.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/config/core_environment.cpp 
b/weex_core/Source/core/config/core_environment.cpp
new file mode 100644
index 0000000..5b7d928
--- /dev/null
+++ b/weex_core/Source/core/config/core_environment.cpp
@@ -0,0 +1,63 @@
+#include "core_environment.h"
+#include "base/CoreConstants.h"
+#include <stdlib.h>
+#include <base/ViewUtils.h>
+
+namespace WeexCore {
+
+  WXCoreEnvironment *WXCoreEnvironment::m_pInstance = nullptr;
+
+  bool WXCoreEnvironment::SetPlatform(std::string platformName) {
+    if (platformName.empty())
+      return false;
+    this->mPlatformName = platformName;
+    if (platformName == OS_Android || platformName == OS_iOS) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  bool WXCoreEnvironment::IsAndroid() {
+    return mPlatformName == OS_Android;
+  }
+
+  bool WXCoreEnvironment::IsIOS() {
+    return mPlatformName == OS_iOS;
+  }
+
+  bool WXCoreEnvironment::SetDeviceWidth(const std::string &width) {
+    if (width.empty() || isnan(getFloat(width.c_str())))
+      return false;
+    mDeviceWidth = getFloat(width.c_str());
+    return true;
+  }
+
+  bool WXCoreEnvironment::SetDeviceHeight(const std::string &height) {
+    if (height.empty() || isnan(getFloat(height.c_str())))
+      return false;
+    mDeviceHeight = getFloat(height.c_str());
+    return true;
+  }
+
+  const float &WXCoreEnvironment::DeviceWidth() {
+    return mDeviceWidth;
+  }
+
+  const float &WXCoreEnvironment::DeviceHeight() {
+    return mDeviceHeight;
+  }
+
+  const std::string &WXCoreEnvironment::GetOption(const std::string &key) {
+    std::map<std::string, std::string>::iterator iter = mOptions.find(key);
+    if (iter != mOptions.end()) {
+      return iter->second;
+    } else {
+      return "";
+    }
+  }
+
+  void WXCoreEnvironment::AddOption(std::string key, std::string value) {
+    mOptions.insert(std::pair<std::string, std::string>(key, value));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/config/core_environment.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/config/core_environment.h 
b/weex_core/Source/core/config/core_environment.h
new file mode 100644
index 0000000..ac89845
--- /dev/null
+++ b/weex_core/Source/core/config/core_environment.h
@@ -0,0 +1,68 @@
+#ifndef WEEX_PROJECT_WXCOREENVIRONMENT_H
+#define WEEX_PROJECT_WXCOREENVIRONMENT_H
+
+#include <string>
+#include <map>
+
+namespace WeexCore {
+
+  class WXCoreEnvironment {
+
+  private:
+
+    WXCoreEnvironment() {}
+
+    ~WXCoreEnvironment() {}
+
+    static WXCoreEnvironment *m_pInstance;
+
+    //just to release singleton object
+    class Garbo {
+    public:
+      ~Garbo() {
+        if (WXCoreEnvironment::m_pInstance) {
+          delete WXCoreEnvironment::m_pInstance;
+        }
+      }
+    };
+
+    static Garbo garbo;
+
+    std::string mPlatformName;
+
+    float mDeviceWidth;
+
+    float mDeviceHeight;
+
+    std::map<std::string, std::string> mOptions;
+
+  public:
+
+    bool SetPlatform(std::string platformName);
+
+    bool IsAndroid();
+
+    bool IsIOS();
+
+    bool SetDeviceWidth(const std::string &width);
+
+    bool SetDeviceHeight(const std::string &height);
+
+    const float &DeviceWidth();
+
+    const float &DeviceHeight();
+
+    const std::string &GetOption(const std::string &key);
+
+    void AddOption(std::string key, std::string value);
+
+    static WXCoreEnvironment *getInstance() {
+      if (!m_pInstance) {
+        m_pInstance = new WXCoreEnvironment();
+      }
+      return m_pInstance;
+    }
+  };
+}
+
+#endif //WEEX_PROJECT_WXCOREENVIRONMENT_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/css/constants_name.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/css/constants_name.h 
b/weex_core/Source/core/css/constants_name.h
new file mode 100644
index 0000000..8e07e04
--- /dev/null
+++ b/weex_core/Source/core/css/constants_name.h
@@ -0,0 +1,63 @@
+
+#ifndef WEEXV8_CONSTANTSNAME_H
+#define WEEXV8_CONSTANTSNAME_H
+
+#include <string>
+
+namespace WeexCore {
+
+  constexpr char FLEX[] = "flex";
+  constexpr char HORIZONTAL[] = "horizontal";
+  constexpr char ALIGN_ITEMS[] = "alignItems";
+  constexpr char ALIGN_SELF[] = "alignSelf";
+  constexpr char FLEX_DIRECTION[] = "flexDirection";
+  constexpr char JUSTIFY_CONTENT[] = "justifyContent";
+  constexpr char FLEX_WRAP[] = "flexWrap";
+
+  constexpr char MIN_WIDTH[] = "minWidth";
+  constexpr char MIN_HEIGHT[] = "minHeight";
+  constexpr char MAX_WIDTH[] = "maxWidth";
+  constexpr char MAX_HEIGHT[] = "maxHeight";
+
+  constexpr char DEFAULT_HEIGHT[] = "defaultHeight";
+  constexpr char HEIGHT[] = "height";
+
+  constexpr char DEFAULT_WIDTH[] = "defaultWidth";
+  constexpr char WIDTH[] = "width";
+  constexpr char SCROLL_DIRECTION[] = "scrollDirection";
+
+  constexpr char POSITION[] = "position";
+
+  constexpr char LEFT[] = "left";
+  constexpr char TOP[] = "top";
+  constexpr char RIGHT[] = "right";
+  constexpr char BOTTOM[] = "bottom";
+
+  constexpr char MARGIN[] = "margin";
+  constexpr char MARGIN_LEFT[] = "marginLeft";
+  constexpr char MARGIN_TOP[] = "marginTop";
+  constexpr char MARGIN_RIGHT[] = "marginRight";
+  constexpr char MARGIN_BOTTOM[] = "marginBottom";
+
+  constexpr char BORDER_WIDTH[] = "borderWidth";
+  constexpr char BORDER_TOP_WIDTH[] = "borderTopWidth";
+  constexpr char BORDER_RIGHT_WIDTH[] = "borderRightWidth";
+  constexpr char BORDER_BOTTOM_WIDTH[] = "borderBottomWidth";
+  constexpr char BORDER_LEFT_WIDTH[] = "borderLeftWidth";
+
+  constexpr char PADDING[] = "padding";
+  constexpr char PADDING_LEFT[] = "paddingLeft";
+  constexpr char PADDING_TOP[] = "paddingTop";
+  constexpr char PADDING_RIGHT[] = "paddingRight";
+  constexpr char PADDING_BOTTOM[] = "paddingBottom";
+
+  constexpr char FONT_STYLE[] = "fontStyle";
+  constexpr char COLUMN_WIDTH[] = "columnWidth";
+  constexpr char COLUMN_COUNT[] = "columnCount";
+  constexpr char COLUMN_GAP[] = "columnGap";
+
+  constexpr char COLOR[] = "color";
+  constexpr char BACKGROUND_COLOR[] = "backgroundColor";
+}
+
+#endif //WEEXV8_CONSTANTSNAME_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/css/constants_value.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/css/constants_value.h 
b/weex_core/Source/core/css/constants_value.h
new file mode 100644
index 0000000..71cd013
--- /dev/null
+++ b/weex_core/Source/core/css/constants_value.h
@@ -0,0 +1,45 @@
+
+#ifndef WEEXV8_CONSTANTSVALUE_H
+#define WEEXV8_CONSTANTSVALUE_H
+
+#include <string>
+
+namespace WeexCore {
+
+  // flex-direction
+  constexpr char ROW[] = "row";
+  constexpr char ROW_REVERSE[] = "row-reverse";
+  constexpr char COLUMN[] = "column";
+  constexpr char COLUMN_REVERSE[] = "column-reverse";
+
+  // flex-wrap
+  constexpr char NOWRAP[] = "nowrap";
+  constexpr char WRAP[] = "wrap";
+  constexpr char WRAP_REVERSE[] = "wrap-reverse";
+
+  // align
+  constexpr char FLEX_START[] = "flex-start";
+  constexpr char FLEX_END[] = "flex-end";
+  constexpr char CENTER[] = "center";
+  constexpr char SPACE_BETWEEN[] = "space-between";
+  constexpr char SPACE_AROUND[] = "space-around";
+  constexpr char STRETCH[] = "stretch";
+  constexpr char AUTO[] = "auto";
+
+  // position
+  constexpr char RELATIVE[] = "relative";
+  constexpr char ABSOLUTE[] = "absolute";
+  constexpr char FIXED[] = "fixed";
+  constexpr char STICKY[] = "sticky";
+
+  constexpr char NORMAL[] = "normal";
+  constexpr int COLUMN_COUNT_NORMAL = 1;
+  constexpr float AUTO_VALUE = -1;
+  constexpr float COLUMN_GAP_NORMAL = 32;
+
+  constexpr int HORIZONTAL_VALUE = 0;
+  constexpr int VERTICAL_VALUE = 1;
+
+  constexpr float kDefaultViewPortWidth = 750.0f;
+}
+#endif //WEEXV8_CONSTANTSVALUE_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/css/css_value_getter.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/css/css_value_getter.cpp 
b/weex_core/Source/core/css/css_value_getter.cpp
new file mode 100644
index 0000000..5241cd6
--- /dev/null
+++ b/weex_core/Source/core/css/css_value_getter.cpp
@@ -0,0 +1,88 @@
+#include "css_value_getter.h"
+#include "constants_value.h"
+#include "constants_name.h"
+#include "core/layout/style.h"
+
+namespace WeexCore {
+
+  const WXCoreFlexDirection &GetWXCoreFlexDirection(const std::string &value) {
+    if (value == COLUMN) {
+      return WeexCore::kFlexDirectionColumn;
+    } else if (value == ROW) {
+      return WeexCore::kFlexDirectionRow;
+    } else if (value == COLUMN_REVERSE) {
+      return WeexCore::kFlexDirectionColumnReverse;
+    } else if (value == ROW_REVERSE) {
+      return WeexCore::kFlexDirectionRowReverse;
+    }
+    return WeexCore::kFlexDirectionColumn;
+  }
+
+  const WXCoreJustifyContent &GetWXCoreJustifyContent(const std::string 
&value) {
+    if (value == FLEX_START) {
+      return WeexCore::kJustifyFlexStart;
+    } else if (value == FLEX_END) {
+      return WeexCore::kJustifyFlexEnd;
+    } else if (value == CENTER) {
+      return WeexCore::kJustifyCenter;
+    } else if (value == SPACE_BETWEEN) {
+      return WeexCore::kJustifySpaceBetween;
+    } else if (value == SPACE_AROUND) {
+      return WeexCore::kJustifySpaceAround;
+    }
+    return WeexCore::kJustifyFlexStart;
+  }
+
+  const WXCoreAlignItems &GetWXCoreAlignItem(const std::string &value) {
+    if (value == STRETCH) {
+      return WeexCore::kAlignItemsStretch;
+    } else if (value == FLEX_START) {
+      return WeexCore::kAlignItemsFlexStart;
+    } else if (value == FLEX_END) {
+      return WeexCore::kAlignItemsFlexEnd;
+    } else if (value == CENTER) {
+      return WeexCore::kAlignItemsCenter;
+    }
+    return WeexCore::kAlignItemsStretch;
+  }
+
+  const WXCoreFlexWrap &GetWXCoreFlexWrap(const std::string &value) {
+    if (value == NOWRAP) {
+      return WeexCore::kNoWrap;
+    } else if (value == WRAP) {
+      return WeexCore::kWrap;
+    } else if (value == WRAP_REVERSE) {
+      return WeexCore::kWrapReverse;
+    }
+    return WeexCore::kNoWrap;
+  }
+
+  const WXCoreAlignSelf &GetWXCoreAlignSelf(const std::string &value) {
+    if (value == AUTO) {
+      return WeexCore::kAlignSelfAuto;
+    } else if (value == STRETCH) {
+      return WeexCore::kAlignSelfStretch;
+    } else if (value == FLEX_START) {
+      return WeexCore::kAlignSelfFlexStart;
+    } else if (value == FLEX_END) {
+      return WeexCore::kAlignSelfFlexEnd;
+    } else if (value == CENTER) {
+      return WeexCore::kAlignSelfCenter;
+    }
+    return WeexCore::kAlignSelfAuto;
+  }
+
+  const WXCorePositionType &GetWXCorePositionType(const std::string &value) {
+    auto ret = kRelative;
+    if (value == RELATIVE) {
+      ret = kRelative;
+    } else if (value == ABSOLUTE) {
+      ret = kAbsolute;
+    } else if(value == STICKY){
+      ret = kSticky;
+    }else if(value == FIXED){
+      ret = kFixed;
+    }
+    return ret;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/css/css_value_getter.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/css/css_value_getter.h 
b/weex_core/Source/core/css/css_value_getter.h
new file mode 100644
index 0000000..1a045b3
--- /dev/null
+++ b/weex_core/Source/core/css/css_value_getter.h
@@ -0,0 +1,23 @@
+#ifndef WEEX_PROJECT_STYLEGETTER_H
+#define WEEX_PROJECT_STYLEGETTER_H
+
+#include "core/layout/flex_enum.h"
+#include <string>
+
+namespace WeexCore {
+
+  const WXCoreFlexDirection &GetWXCoreFlexDirection(const std::string &value);
+
+  const WXCoreJustifyContent &GetWXCoreJustifyContent(const std::string 
&value);
+
+  const WXCoreAlignItems &GetWXCoreAlignItem(const std::string &value);
+
+  const WXCoreFlexWrap &GetWXCoreFlexWrap(const std::string &value);
+
+  const WXCoreAlignSelf &GetWXCoreAlignSelf(const std::string &value);
+
+  const WXCorePositionType &GetWXCorePositionType(const std::string &value);
+}
+
+
+#endif //WEEX_PROJECT_STYLEGETTER_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/layout/flex_enum.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/layout/flex_enum.h 
b/weex_core/Source/core/layout/flex_enum.h
new file mode 100644
index 0000000..26fe8a3
--- /dev/null
+++ b/weex_core/Source/core/layout/flex_enum.h
@@ -0,0 +1,107 @@
+#ifdef __cplusplus
+
+#ifndef WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUM_H
+#define WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUM_H
+
+namespace WeexCore {
+
+  /**
+   * MainAxis direction
+   */
+  enum WXCoreFlexDirection {
+    kFlexDirectionColumn,
+    kFlexDirectionColumnReverse,
+    kFlexDirectionRow,
+    kFlexDirectionRowReverse,
+  };
+
+  /**
+   * Controls the position of the element on the MainAxis
+   */
+  enum WXCoreJustifyContent {
+    kJustifyFlexStart,
+    kJustifyCenter,
+    kJustifyFlexEnd,
+    kJustifySpaceBetween,
+    kJustifySpaceAround,
+  };
+
+  /**
+   * Controls the position of the element on the CrossAxis and whether Stretch
+   */
+  enum WXCoreAlignItems {
+    kAlignItemsFlexStart,
+    kAlignItemsCenter,
+    kAlignItemsFlexEnd,
+    kAlignItemsStretch,
+  };
+
+  /**
+   * Controls the count of flexlines
+   */
+  enum WXCoreFlexWrap {
+    kNoWrap,
+    kWrap,
+    kWrapReverse,
+  };
+
+  /**
+   * The align-self will overrides the align-items specified by the Flex 
container.
+   * The two attributes have the same range of values.
+   */
+  enum WXCoreAlignSelf {
+    kAlignSelfAuto = -1,
+    kAlignSelfFlexStart = kAlignItemsFlexStart,
+    kAlignSelfCenter = kAlignItemsCenter,
+    kAlignSelfFlexEnd = kAlignItemsFlexEnd,
+    kAlignSelfStretch = kAlignItemsStretch,
+  };
+
+  enum WXCorePositionType {
+    kRelative,
+    kAbsolute,
+    kFixed,
+    kSticky = kRelative
+  };
+
+  enum WXCorePositionEdge {
+    kPositionEdgeTop,
+    kPositionEdgeBottom,
+    kPositionEdgeLeft,
+    kPositionEdgeRight,
+  };
+
+  enum WXCoreMarginEdge {
+    kMarginALL,
+    kMarginTop,
+    kMarginBottom,
+    kMarginLeft,
+    kMarginRight,
+  };
+
+  enum WXCorePaddingEdge {
+    kPaddingALL,
+    kPaddingTop,
+    kPaddingBottom,
+    kPaddingLeft,
+    kPaddingRight,
+  };
+
+  enum WXCoreBorderWidthEdge {
+    kBorderWidthALL,
+    kBorderWidthTop,
+    kBorderWidthBottom,
+    kBorderWidthLeft,
+    kBorderWidthRight,
+  };
+
+  enum WXCoreEdge{
+    kTop,
+    kRight,
+    kBottom,
+    kLeft,
+  };
+
+}
+#endif //WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUM_H
+#endif
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/layout/layout.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/layout/layout.cpp 
b/weex_core/Source/core/layout/layout.cpp
new file mode 100644
index 0000000..d4655e3
--- /dev/null
+++ b/weex_core/Source/core/layout/layout.cpp
@@ -0,0 +1,1034 @@
+#include "layout.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;
+      }
+      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;
+      }
+      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;
+    }
+  }
+}
+
+

Reply via email to