You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ky...@apache.org on 2018/04/28 06:53:44 UTC

[16/48] incubator-weex git commit: * [android] Merge WeexCore-master to master.

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/layout/layout.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/layout/layout.h b/weex_core/Source/core/layout/layout.h
new file mode 100644
index 0000000..2b201e4
--- /dev/null
+++ b/weex_core/Source/core/layout/layout.h
@@ -0,0 +1,1073 @@
+#ifdef __cplusplus
+
+#ifndef WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H
+#define WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H
+
+#include "style.h"
+#include "flex_enum.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 {
+
+  protected:
+      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
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/layout/style.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/layout/style.cpp b/weex_core/Source/core/layout/style.cpp
new file mode 100644
index 0000000..60c6e18
--- /dev/null
+++ b/weex_core/Source/core/layout/style.cpp
@@ -0,0 +1,247 @@
+#include "style.h"
+
+namespace WeexCore {
+
+  bool WXCoreMargin::setMargin(const WXCoreMarginEdge &edge, float margin) {
+    bool dirty = false;
+    switch (edge) {
+      case kMarginALL:
+        if (mMarginLeft != margin
+            || mMarginTop != margin
+            || mMarginRight != margin
+            || mMarginBottom != margin) {
+          mMarginLeft = margin;
+          mMarginTop = margin;
+          mMarginRight = margin;
+          mMarginBottom = margin;
+          dirty = true;
+        }
+        break;
+      case kMarginLeft:
+        if (mMarginLeft != margin) {
+          mMarginLeft = margin;
+          dirty = true;
+        }
+        break;
+      case kMarginTop:
+        if (mMarginTop != margin) {
+          mMarginTop = margin;
+          dirty = true;
+        }
+        break;
+      case kMarginRight:
+        if (mMarginRight != margin) {
+          mMarginRight = margin;
+          dirty = true;
+        }
+        break;
+      case kMarginBottom:
+        if (mMarginBottom != margin) {
+          mMarginBottom = margin;
+          dirty = true;
+        }
+        break;
+    }
+    return dirty;
+  }
+
+  float WXCoreMargin::getMargin(const WXCoreMarginEdge &edge)const {
+    float margin = 0;
+    switch (edge) {
+      case kMarginLeft:
+        margin = mMarginLeft;
+        break;
+      case kMarginTop:
+        margin = mMarginTop;
+        break;
+      case kMarginRight:
+        margin = mMarginRight;
+        break;
+      case kMarginBottom:
+        margin = mMarginBottom;
+        break;
+      default:
+        break;
+    }
+    return margin;
+  }
+
+  bool WXCorePadding::setPadding(const WXCorePaddingEdge &edge, float padding) {
+    bool dirty = false;
+    switch (edge) {
+      case kPaddingALL:
+        if (mPaddingLeft != padding
+            || mPaddingTop != padding
+            || mPaddingRight != padding
+            || mPaddingBottom != padding) {
+          mPaddingLeft = padding;
+          mPaddingTop = padding;
+          mPaddingRight = padding;
+          mPaddingBottom = padding;
+          dirty = true;
+        }
+        break;
+      case kPaddingLeft:
+        if (mPaddingLeft != padding) {
+          mPaddingLeft = padding;
+          dirty = true;
+        }
+        break;
+      case kPaddingTop:
+        if (mPaddingTop != padding) {
+          mPaddingTop = padding;
+          dirty = true;
+        }
+        break;
+      case kPaddingRight:
+        if (mPaddingRight != padding) {
+          mPaddingRight = padding;
+          dirty = true;
+        }
+        break;
+      case kPaddingBottom:
+        if (mPaddingBottom != padding) {
+          mPaddingBottom = padding;
+          dirty = true;
+        }
+        break;
+    }
+    return dirty;
+  }
+
+  float WXCorePadding::getPadding(const WXCorePaddingEdge &edge)const {
+    float padding = 0;
+    switch (edge) {
+      case kPaddingLeft:
+        padding = mPaddingLeft;
+        break;
+      case kPaddingTop:
+        padding = mPaddingTop;
+        break;
+      case kPaddingRight:
+        padding = mPaddingRight;
+        break;
+      case kPaddingBottom:
+        padding = mPaddingBottom;
+        break;
+      default:
+        break;
+    }
+    return padding;
+  }
+
+  bool WXCoreBorderWidth::setBorderWidth(const WXCoreBorderWidthEdge &edge, float borderWidth) {
+    bool dirty = false;
+    switch (edge) {
+      case kBorderWidthALL:
+        if (mBorderWidthLeft != borderWidth
+            || mBorderWidthTop != borderWidth
+            || mBorderWidthRight != borderWidth
+            || mBorderWidthBottom != borderWidth) {
+          mBorderWidthLeft = borderWidth;
+          mBorderWidthTop = borderWidth;
+          mBorderWidthRight = borderWidth;
+          mBorderWidthBottom = borderWidth;
+          dirty = true;
+        }
+        break;
+      case kBorderWidthLeft:
+        if (mBorderWidthLeft != borderWidth) {
+          mBorderWidthLeft = borderWidth;
+          dirty = true;
+        }
+        break;
+      case kBorderWidthTop:
+        if (mBorderWidthTop != borderWidth) {
+          mBorderWidthTop = borderWidth;
+          dirty = true;
+        }
+        break;
+      case kBorderWidthRight:
+        if (mBorderWidthRight != borderWidth) {
+          mBorderWidthRight = borderWidth;
+          dirty = true;
+        }
+        break;
+      case kBorderWidthBottom:
+        if (mBorderWidthBottom != borderWidth) {
+          mBorderWidthBottom = borderWidth;
+          dirty = true;
+        }
+        break;
+    }
+    return dirty;
+  }
+
+  float WXCoreBorderWidth::getBorderWidth(const WXCoreBorderWidthEdge &edge)const {
+    float borderWidth = 0;
+    switch (edge) {
+      case kBorderWidthLeft:
+        borderWidth = mBorderWidthLeft;
+        break;
+      case kBorderWidthTop:
+        borderWidth = mBorderWidthTop;
+        break;
+      case kBorderWidthRight:
+        borderWidth = mBorderWidthRight;
+        break;
+      case kBorderWidthBottom:
+        borderWidth = mBorderWidthBottom;
+        break;
+      default:
+        break;
+    }
+    return borderWidth;
+  }
+
+  bool WXCorePosition::setPosition(const WXCorePositionEdge &edge, float position) {
+    bool dirty = false;
+    switch (edge) {
+      case kPositionEdgeLeft:
+        if (mLeft != position) {
+          mLeft = position;
+          dirty = true;
+        }
+        break;
+      case kPositionEdgeTop:
+        if (mTop != position) {
+          mTop = position;
+          dirty = true;
+        }
+        break;
+      case kPositionEdgeRight:
+        if (mRight != position) {
+          mRight = position;
+          dirty = true;
+        }
+        break;
+      case kPositionEdgeBottom:
+        if (mBottom != position) {
+          mBottom = position;
+          dirty = true;
+        }
+        break;
+    }
+    return dirty;
+  }
+
+  float WXCorePosition::getPosition(const WXCorePositionEdge &edge) {
+    float position = 0;
+    switch (edge) {
+      case kPositionEdgeLeft:
+        position = mLeft;
+        break;
+      case kPositionEdgeTop:
+        position = mTop;
+        break;
+      case kPositionEdgeRight:
+        position = mRight;
+        break;
+      case kPositionEdgeBottom:
+        position = mBottom;
+        break;
+    }
+    return position;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/layout/style.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/layout/style.h b/weex_core/Source/core/layout/style.h
new file mode 100644
index 0000000..86a853f
--- /dev/null
+++ b/weex_core/Source/core/layout/style.h
@@ -0,0 +1,285 @@
+#ifdef __cplusplus
+
+#ifndef WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUMS_H
+#define WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUMS_H
+
+
+#include "flex_enum.h"
+#include <cmath>
+
+namespace WeexCore {
+
+  /**
+   * Margin: margin-left、margin-right、margin-top、margin-bottom
+   */
+  class WXCoreMargin {
+  private:
+    float mMarginTop;
+    float mMarginBottom;
+    float mMarginLeft;
+    float mMarginRight;
+
+  public:
+    WXCoreMargin() : mMarginTop(0),
+                     mMarginBottom(0),
+                     mMarginLeft(0),
+                     mMarginRight(0) {}
+
+    ~WXCoreMargin() {
+      mMarginTop = 0;
+      mMarginBottom = 0;
+      mMarginLeft = 0;
+      mMarginRight = 0;
+    }
+
+    bool setMargin(const WXCoreMarginEdge &edge, float margin);
+
+    float getMargin(const WXCoreMarginEdge &edge)const;
+  };
+
+
+  /**
+   * Padding:padding-left、padding-right、padding-top、padding-bottom
+   */
+  class WXCorePadding {
+  private:
+    float mPaddingTop;
+    float mPaddingBottom;
+    float mPaddingLeft;
+    float mPaddingRight;
+
+  public:
+    WXCorePadding() : mPaddingTop(0),
+                      mPaddingBottom(0),
+                      mPaddingLeft(0),
+                      mPaddingRight(0) {}
+
+    ~WXCorePadding() {
+      mPaddingTop = 0;
+      mPaddingBottom = 0;
+      mPaddingLeft = 0;
+      mPaddingRight = 0;
+    }
+
+    bool setPadding(const WXCorePaddingEdge &edge, float padding);
+
+    float getPadding(const WXCorePaddingEdge &edge)const;
+  };
+
+
+  /**
+   * BorderWidth:borderwidth-left、borderwidth-right、borderwidth-top、borderwidth-bottom
+   */
+  class WXCoreBorderWidth {
+  private:
+    float mBorderWidthTop;
+    float mBorderWidthBottom;
+    float mBorderWidthLeft;
+    float mBorderWidthRight;
+
+  public:
+    WXCoreBorderWidth() : mBorderWidthTop(0),
+                          mBorderWidthBottom(0),
+                          mBorderWidthLeft(0),
+                          mBorderWidthRight(0) {}
+
+    ~WXCoreBorderWidth() {
+      mBorderWidthTop = 0;
+      mBorderWidthBottom = 0;
+      mBorderWidthLeft = 0;
+      mBorderWidthRight = 0;
+    }
+
+    bool setBorderWidth(const WXCoreBorderWidthEdge &edge, float borderWidth);
+
+    float getBorderWidth(const WXCoreBorderWidthEdge &edge)const;
+  };
+
+
+  /**
+   * position:left、right、top、bottom
+   */
+  class WXCorePosition {
+  private:
+    float mTop;
+    float mBottom;
+    float mLeft;
+    float mRight;
+
+  public:
+    WXCorePosition() : mTop(NAN),
+                       mBottom(NAN),
+                       mLeft(NAN),
+                       mRight(NAN) {}
+
+    ~WXCorePosition() {
+      reset();
+    }
+
+    inline bool isNAN() {
+      return isnan(mTop) || isnan(mBottom) || isnan(mLeft) || isnan(mRight);
+    }
+
+    inline void reset() {
+      mTop = 0;
+      mBottom = 0;
+      mLeft = 0;
+      mRight = 0;
+    }
+
+    bool setPosition(const WXCorePositionEdge &edge, float position);
+
+    float getPosition(const WXCorePositionEdge &edge);
+  };
+
+  enum DimensionLevel{
+    CSS_STYLE = 1,
+    INSTANCE_STYLE = 2,
+    FALLBACK_STYLE = 3
+  };
+
+  /**
+   * css-style
+   */
+  class WXCoreCSSStyle {
+  public:
+    /**
+     * The direction children items are placed inside the Flexbox layout, it determines the
+     * direction of the main axis (and the cross axis, perpendicular to the main axis).
+     * The default value is {@link WXCoreFlexDirection #WXCore_Flex_Direction_Row}.
+     */
+    WXCoreFlexDirection mFlexDirection;
+
+    /**
+     * This attribute controls whether the flex container is single-line or multi-line, and the
+     * direction of the cross axis.
+     * <ul>
+     * <li>{@link WXCoreFlexWrap}: The flex container is single-line.</li>
+     * <li>{@link WXCoreFlexWrap}: The flex container is multi-line.</li>
+     * <li>{@link WXCoreFlexWrap}: The flex container is multi-line. The direction of the
+     * cross axis is opposed to the direction as the {@link WXCoreFlexWrap}</li>
+     * </ul>
+     * The default value is {@link WXCoreFlexWrap #WXCore_Wrap_NoWrap}.
+     */
+    WXCoreFlexWrap mFlexWrap;
+
+    /**
+     * This attribute controls the alignment along the main axis.
+     * The default value is {@link WXCoreJustifyContent #WXCore_Justify_Flex_Start}.
+     */
+    WXCoreJustifyContent mJustifyContent;
+
+    /**
+     * This attribute controls the alignment along the cross axis.
+     * The default value is {@link WXCoreAlignItems #WXCore_AlignItems_Stretch}.
+     */
+    WXCoreAlignItems mAlignItems;
+
+    /**
+     * This attribute controls the alignment along the cross axis.
+     * The default value is {@link WXCoreAlignSelf #WXCore_AlignSelf_Auto}.
+     */
+    WXCoreAlignSelf mAlignSelf;
+
+    WXCorePositionType mPositionType;
+
+    float mFlexGrow;
+
+    float mMinWidth;
+
+    float mMinHeight;
+
+    float mMaxWidth;
+
+    float mMaxHeight;
+
+    float mStyleWidth;
+
+    float mStyleHeight;
+
+    DimensionLevel mStyleWidthLevel;
+
+    DimensionLevel mStyleHeightLevel;
+
+    WXCoreMargin mMargin;
+
+    WXCorePadding mPadding;
+
+    WXCoreBorderWidth mBorderWidth;
+
+    WXCorePosition mStylePosition;
+
+    constexpr static float kFlexGrowDefault  = 0;
+
+    constexpr static WXCoreFlexDirection kFlexDirectionDefault= kFlexDirectionColumn;
+
+    constexpr static WXCoreFlexWrap kFlexWrapDefault = kNoWrap;
+
+    constexpr static WXCoreJustifyContent kFlexJustifyContentDefault = kJustifyFlexStart;
+
+    constexpr static WXCoreAlignItems kFlexAlignItemsDefault = kAlignItemsStretch;
+
+    constexpr static WXCoreAlignSelf kFlexAlignSelfDefault = kAlignSelfAuto;
+
+    constexpr static WXCorePositionType kWXCorePositionTypeDefault = kRelative;
+
+    WXCoreCSSStyle() : mFlexDirection(kFlexDirectionDefault),
+                       mFlexWrap(kFlexWrapDefault),
+                       mJustifyContent(kFlexJustifyContentDefault),
+                       mAlignItems(kFlexAlignItemsDefault),
+                       mAlignSelf(kFlexAlignSelfDefault),
+                       mFlexGrow(kFlexGrowDefault),
+                       mPositionType(kWXCorePositionTypeDefault),
+                       mStyleWidth(NAN), mStyleHeight(NAN),
+                       mStyleHeightLevel(FALLBACK_STYLE), mStyleWidthLevel(FALLBACK_STYLE),
+                       mMaxWidth(NAN), mMaxHeight(NAN),
+                       mMinWidth(NAN), mMinHeight(NAN) {
+
+    }
+
+    ~WXCoreCSSStyle() {
+      mFlexDirection = kFlexDirectionDefault;
+      mFlexWrap = kFlexWrapDefault;
+      mJustifyContent = kFlexJustifyContentDefault;
+      mAlignItems = kFlexAlignItemsDefault;
+      mAlignSelf = kFlexAlignSelfDefault;
+      mFlexGrow = kFlexGrowDefault;
+      mStyleWidth = NAN;
+      mStyleHeight = NAN;
+      mStyleWidthLevel = FALLBACK_STYLE;
+      mStyleHeightLevel = FALLBACK_STYLE;
+      mMaxWidth = NAN;
+      mMaxHeight = NAN;
+      mMinWidth = NAN;
+      mMinHeight = NAN;
+    }
+
+    inline float sumPaddingBorderOfEdge(const WXCoreEdge edge){
+      switch (edge) {
+        case kTop:
+          return mPadding.getPadding(kPaddingTop)
+              + mBorderWidth.getBorderWidth(kBorderWidthTop);
+        case kRight:
+          return mPadding.getPadding(kPaddingRight)
+              + mBorderWidth.getBorderWidth(kBorderWidthRight);
+        case kBottom:
+          return mPadding.getPadding(kPaddingBottom)
+              + mBorderWidth.getBorderWidth(kBorderWidthBottom);
+        case kLeft:
+          return mPadding.getPadding(kPaddingLeft)
+              + mBorderWidth.getBorderWidth(kBorderWidthLeft);
+      }
+    }
+
+    float sumMarginOfDirection(bool horizontal){
+      if(horizontal){
+        return mMargin.getMargin(kMarginLeft) + mMargin.getMargin(kMarginRight);
+      }
+      else{
+        return mMargin.getMargin(kMarginTop) + mMargin.getMargin(kMarginBottom);
+      }
+    }
+  };
+}
+#endif //WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUMS_H
+#endif
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/moniter/render_performance.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/moniter/render_performance.cpp b/weex_core/Source/core/moniter/render_performance.cpp
new file mode 100644
index 0000000..0e1b6f2
--- /dev/null
+++ b/weex_core/Source/core/moniter/render_performance.cpp
@@ -0,0 +1,32 @@
+#include "render_performance.h"
+#include <android/base/log_utils.h>
+
+namespace WeexCore {
+
+  int
+  RenderPerformance::PrintPerformanceLogImplAndroid(const PerformanceStage &performanceStage) {
+
+#if PERFORMANCE_LOG
+
+    if (performanceStage == onFirstScreen) {
+      LOGD("[WeexCore render time]onFirstScreen");
+    } else {
+      LOGD("[WeexCore render time]onRenderSuccess");
+    }
+    LOGD("[WeexCore render time]      jniCallTime: %lld", jniCallTime);
+    LOGD("[WeexCore render time]        -addElementActionJNITime: %lld", addElementActionJNITime);
+    LOGD("[WeexCore render time]         layoutActionJNITime: %lld", layoutActionJniTime);
+    LOGD("[WeexCore render time]        -jniCallBridgeTime: %lld", jniCallBridgeTime);
+    LOGD("[WeexCore render time]         createJMapJNITime: %lld", createJMapJNITime);
+    LOGD("[WeexCore render time]      cssLayoutTime: %lld", cssLayoutTime);
+    LOGD("[WeexCore render time]      parseJsonTime: %lld", parseJsonTime);
+    LOGD("[WeexCore render time]      buildRenderObjectTime: %lld", buildRenderObjectTime);
+#endif
+
+    return cssLayoutTime;
+  }
+
+  int RenderPerformance::PrintPerformanceLogImplIOS(const PerformanceStage &performanceStage) {
+    return 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/moniter/render_performance.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/moniter/render_performance.h b/weex_core/Source/core/moniter/render_performance.h
new file mode 100644
index 0000000..b382fe5
--- /dev/null
+++ b/weex_core/Source/core/moniter/render_performance.h
@@ -0,0 +1,51 @@
+#ifndef WEEX_PROJECT_WXPERFORMANCE_H
+#define WEEX_PROJECT_WXPERFORMANCE_H
+
+namespace WeexCore {
+
+  typedef enum PerformanceStage {
+    onFirstScreen, onRenderSuccess,
+  } PerformanceStage;
+
+  class RenderPerformance {
+
+  public:
+
+    long long jniCallTime;
+
+    long long jniCallBridgeTime;
+
+    long long cssLayoutTime;
+
+    long long addElementActionJNITime;
+
+    long long addEventActionJNITime;
+
+    long long removeEventActionJNITime;
+
+    long long layoutActionJniTime;
+
+    long long parseJsonTime;
+
+    long long buildRenderObjectTime;
+
+    long long createJMapJNITime;
+
+    RenderPerformance() : jniCallTime(0), jniCallBridgeTime(0), cssLayoutTime(0),
+                          addElementActionJNITime(0),
+                          layoutActionJniTime(0), parseJsonTime(0), buildRenderObjectTime(0),
+                          createJMapJNITime(0) {}
+
+    inline int PrintPerformanceLog(PerformanceStage performanceStage) {
+      return PrintPerformanceLogImplAndroid(performanceStage);
+    }
+
+  private:
+
+    int PrintPerformanceLogImplAndroid(const PerformanceStage &performanceStage);
+
+    int PrintPerformanceLogImplIOS(const PerformanceStage &performanceStage);
+  };
+}
+
+#endif //WEEX_PROJECT_WXPERFORMANCE_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/parser/dom_parser.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/parser/dom_parser.cpp b/weex_core/Source/core/parser/dom_parser.cpp
new file mode 100644
index 0000000..cf51297
--- /dev/null
+++ b/weex_core/Source/core/parser/dom_parser.cpp
@@ -0,0 +1,564 @@
+
+#include "dom_parser.h"
+#include <base/fpconv.h>
+#include <core/render/node/render_object.h>
+#include <core/render/page/render_page.h>
+#include <core/render/node/factory/render_creator.h>
+#include <android/base/log_utils.h>
+
+using namespace std;
+using namespace rapidjson;
+
+namespace WeexCore {
+
+  static inline int matchNum(std::string temp, std::string key, int startIndex, int endIndex) {
+    int num = 0;
+    while (startIndex < endIndex) {
+      int index = temp.find(key, startIndex);
+      if (index >= 0 && index < endIndex) {
+        num++;
+        startIndex = index + 1;
+      } else {
+        break;
+      }
+    }
+    return num;
+  }
+
+  bool JsonParserHandler::Null() {
+    st_ = kHasNull;
+    v_.SetNull();
+    return true;
+  }
+
+  bool JsonParserHandler::Bool(bool b) {
+    st_ = kHasBool;
+    v_.SetBool(b);
+    return true;
+  }
+
+  bool JsonParserHandler::Int(int i) {
+    st_ = kHasNumber;
+    v_.SetInt(i);
+    return true;
+  }
+
+  bool JsonParserHandler::Uint(unsigned u) {
+    st_ = kHasNumber;
+    v_.SetUint(u);
+    return true;
+  }
+
+  bool JsonParserHandler::Int64(int64_t i) {
+    st_ = kHasNumber;
+    v_.SetInt64(i);
+    return true;
+  }
+
+  bool JsonParserHandler::Uint64(uint64_t u) {
+    st_ = kHasNumber;
+    v_.SetUint64(u);
+    return true;
+  }
+
+  bool JsonParserHandler::Double(double d) {
+    st_ = kHasNumber;
+    v_.SetDouble(d);
+    return true;
+  }
+
+  bool JsonParserHandler::RawNumber(const char *, SizeType, bool) { return false; }
+
+  bool JsonParserHandler::String(const char *str, SizeType length, bool) {
+    st_ = kHasString;
+    v_.SetString(str, length);
+    return true;
+  }
+
+  bool JsonParserHandler::StartObject() {
+    st_ = kEnteringObject;
+    return true;
+  }
+
+  bool JsonParserHandler::Key(const char *str, SizeType length, bool) {
+    st_ = kHasKey;
+    v_.SetString(str, length);
+    return true;
+  }
+
+  bool JsonParserHandler::EndObject(SizeType) {
+    st_ = kExitingObject;
+    return true;
+  }
+
+  bool JsonParserHandler::StartArray() {
+    st_ = kEnteringArray;
+    return true;
+  }
+
+  bool JsonParserHandler::EndArray(SizeType) {
+    st_ = kExitingArray;
+    return true;
+  }
+
+  JsonParserHandler::JsonParserHandler(char *str) : v_(), st_(kInit), r_(), ss_(str) {
+    r_.IterativeParseInit();
+    ParseNext();
+  }
+
+  void JsonParserHandler::ParseNext() {
+    if (r_.HasParseError()) {
+      st_ = kError;
+      return;
+    }
+
+    r_.IterativeParseNext<parseFlags>(ss_, *this);
+  }
+
+  bool JsonParser::EnterObject() {
+    if (st_ != kEnteringObject) {
+      st_ = kError;
+      return false;
+    }
+
+    ParseNext();
+    return true;
+  }
+
+  bool JsonParser::EnterArray() {
+    if (st_ != kEnteringArray) {
+      st_ = kError;
+      return false;
+    }
+
+    ParseNext();
+    return true;
+  }
+
+  const char *JsonParser::NextObjectKey() {
+    if (st_ == kHasKey) {
+      const char *result = v_.GetString();
+      ParseNext();
+      return result;
+    }
+
+    if (st_ != kExitingObject) {
+      st_ = kError;
+      return 0;
+    }
+
+    ParseNext();
+    return 0;
+  }
+
+  bool JsonParser::NextArrayValue() {
+    if (st_ == kExitingArray) {
+      ParseNext();
+      return false;
+    }
+
+    if (st_ == kError || st_ == kExitingObject || st_ == kHasKey) {
+      st_ = kError;
+      return false;
+    }
+
+    return true;
+  }
+
+  int JsonParser::GetInt() {
+    if (st_ != kHasNumber || !v_.IsInt()) {
+      st_ = kError;
+      return 0;
+    }
+
+    int result = v_.GetInt();
+    ParseNext();
+    return result;
+  }
+
+  double JsonParser::GetDouble() {
+    if (st_ != kHasNumber) {
+      st_ = kError;
+      return 0.;
+    }
+
+    double result = v_.GetDouble();
+    ParseNext();
+    return result;
+  }
+
+  bool JsonParser::GetBool() {
+    if (st_ != kHasBool) {
+      st_ = kError;
+      return false;
+    }
+
+    bool result = v_.GetBool();
+    ParseNext();
+    return result;
+  }
+
+  void JsonParser::GetNull() {
+    if (st_ != kHasNull) {
+      st_ = kError;
+      return;
+    }
+
+    ParseNext();
+  }
+
+  const char *JsonParser::GetString() {
+    if (st_ != kHasString) {
+      st_ = kError;
+      return 0;
+    }
+
+    const char *temp = v_.GetString();
+    int len = v_.GetStringLength();
+    char *result = new char[len + 1];
+    strcpy(result, temp);
+    result[len] = '\0';
+    ParseNext();
+    return result;
+  }
+
+  const char *JsonParser::Stringify() {
+    return ss_.src_;
+  }
+
+  void JsonParser::SkipOut(int depth) {
+    do {
+      if (st_ == kEnteringArray || st_ == kEnteringObject) {
+        ++depth;
+      } else if (st_ == kExitingArray || st_ == kExitingObject) {
+        --depth;
+      } else if (st_ == kError) {
+        return;
+      }
+
+      ParseNext();
+    } while (depth > 0);
+  }
+
+  void JsonParser::SkipValue() {
+    SkipOut(0);
+  }
+
+  void JsonParser::SkipArray() {
+    SkipOut(1);
+  }
+
+  void JsonParser::SkipObject() {
+    SkipOut(1);
+  }
+
+  Value *JsonParser::PeekValue() {
+    if (st_ >= kHasNull && st_ <= kHasKey) {
+      return &v_;
+    }
+
+    return 0;
+  }
+
+  int JsonParser::PeekType() {
+    if (st_ >= kHasNull && st_ <= kHasKey) {
+      return v_.GetType();
+    }
+
+    if (st_ == kEnteringArray) {
+      return kArrayType;
+    }
+
+    if (st_ == kEnteringObject) {
+      return kObjectType;
+    }
+
+    return -1;
+  }
+
+  RenderObject *
+  ParseJsonObject(JsonParser &r, RenderObject *parent, int index, const std::string &pageId) {
+
+    RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
+    r.EnterObject();
+
+    RenderObject *render;
+    std::string ref;
+
+    while (const char *key = r.NextObjectKey()) {
+
+      if (0 == strcmp(key, "ref")) {
+        RAPIDJSON_ASSERT(r.PeekType() == kStringType);
+        const char *temp_ref = r.GetString();
+        ref = temp_ref;
+        if (temp_ref != nullptr) {
+          delete[]temp_ref;
+          temp_ref = nullptr;
+        }
+      } else if (0 == strcmp(key, "type")) {
+        RAPIDJSON_ASSERT(r.PeekType() == kStringType);
+        const char *temp_type = r.GetString();
+        render = (RenderObject *) RenderCreator::GetInstance()->CreateRender(temp_type, ref);
+        render->SetPageId(pageId);
+        if (parent != nullptr)
+          parent->AddRenderObject(index, render);
+        if (temp_type != nullptr) {
+          delete[]temp_type;
+          temp_type = nullptr;
+        }
+      } else if (0 == strcmp(key, "attr") || 0 == strcmp(key, "style")) {
+        RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
+        r.EnterObject();
+        while (const char *key2 = r.NextObjectKey()) {
+          if (r.PeekType() == kNumberType) {
+            RAPIDJSON_ASSERT(r.PeekType() == kNumberType);
+            char *temp = new char[65];
+            if (0 == strcmp(key, "attr")) {
+              int len = fpconv_dtoa(r.GetDouble(), temp);
+              temp[len] = '\0';
+              char value[len + 1];
+              strcpy(value, temp);
+              render->AddAttr(key2, value);
+            } else if (0 == strcmp(key, "style")) {
+              int len = fpconv_dtoa(r.GetDouble(), temp);
+              temp[len] = '\0';
+              char value[len + 1];
+              strcpy(value, temp);
+              render->AddStyle(key2, value);
+            }
+            if (temp != nullptr) {
+              delete[]temp;
+              temp = nullptr;
+            }
+          } else if (r.PeekType() == kStringType) {
+            RAPIDJSON_ASSERT(r.PeekType() == kStringType);
+            const char *temp_str = r.GetString();
+            if (0 == strcmp(key, "attr")) {
+              render->AddAttr(key2, temp_str);
+            } else if (0 == strcmp(key, "style")) {
+              render->AddStyle(key2, temp_str);
+            }
+            if (temp_str != nullptr) {
+              delete[]temp_str;
+              temp_str = nullptr;
+            }
+          } else if (r.PeekType() == kArrayType) {
+            RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
+            std::string temp = "[";
+            temp.append(r.Stringify());
+              int endIndex = temp.find(']');
+              if(endIndex > 0) {
+                  // has found!
+                  int startIndex = 0;
+                  int leftMatchSize = matchNum(temp, "[", startIndex, endIndex) - 1;
+                  while (leftMatchSize > 0 && startIndex < endIndex) {
+                      startIndex = endIndex + 1;
+                      int markIndex = temp.find(']', startIndex);
+                      if(markIndex > 0) {
+                          endIndex = markIndex;
+                          leftMatchSize--;
+                      }
+                      leftMatchSize += matchNum(temp, "[", startIndex, endIndex);
+                  }
+              }
+            std::string value = temp.substr(0, endIndex + 1);
+            if (0 == strcmp(key, "attr")) {
+              render->AddAttr(key2, value);
+            } else if (0 == strcmp(key, "style")) {
+              render->AddStyle(key2, value);
+            }
+            r.SkipValue();
+          } else if (r.PeekType() == kTrueType) {
+            RAPIDJSON_ASSERT(r.PeekType() == kTrueType);
+            if (0 == strcmp(key, "attr")) {
+              render->AddAttr(key2, "true");
+            } else if (0 == strcmp(key, "style")) {
+              render->AddStyle(key2, "true");
+            }
+            r.SkipValue();
+          } else if (r.PeekType() == kFalseType) {
+            RAPIDJSON_ASSERT(r.PeekType() == kFalseType);
+            if (0 == strcmp(key, "attr")) {
+              render->AddAttr(key2, "false");
+            } else if (0 == strcmp(key, "style")) {
+              render->AddStyle(key2, "false");
+            }
+            r.SkipValue();
+          } else if (r.PeekType() == kObjectType) {
+            RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
+            std::string temp = "{";
+            temp.append(r.Stringify());
+            int endIndex = temp.find('}');
+            if(endIndex > 0) {
+              // has found!
+              int startIndex = 0;
+              int leftMatchSize = matchNum(temp, "{", startIndex, endIndex) - 1;
+              while (leftMatchSize > 0 && startIndex < endIndex) {
+                startIndex = endIndex + 1;
+                int markIndex = temp.find('}', startIndex);
+                if(markIndex > 0) {
+                  endIndex = markIndex;
+                  leftMatchSize--;
+                }
+                leftMatchSize += matchNum(temp, "{", startIndex, endIndex);
+              }
+            }
+            std::string value = temp.substr(0, endIndex + 1);
+
+            if (0 == strcmp(key, "attr")) {
+              render->AddAttr(key2, value);
+            } else if (0 == strcmp(key, "style")) {
+              render->AddStyle(key2, value);
+            }
+            r.SkipValue();
+          } else {
+            r.SkipValue();
+          }
+        }
+      } else if (0 == strcmp(key, "event")) {
+        RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
+        r.EnterArray();
+        while (r.NextArrayValue()) {
+          RAPIDJSON_ASSERT(r.PeekType() == kStringType);
+          const char *temp_event = r.GetString();
+          render->AddEvent(temp_event);
+          if (temp_event != nullptr) {
+            delete[]temp_event;
+            temp_event = nullptr;
+          }
+        }
+      } else if (0 == strcmp(key, "children")) {
+        RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
+        r.EnterArray();
+
+        int index = 0;
+
+        while (r.NextArrayValue()) {
+          RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
+          ParseJsonObject(r, render, index, pageId);
+          index++;
+        }
+      } else {
+        r.SkipValue();
+      }
+    }
+
+    if (render != nullptr) {
+      render->ApplyDefaultStyle();
+      render->ApplyDefaultAttr();
+    }
+
+    return render;
+  }
+
+/**
+ * Parse json data to RenderObject
+ * @param data : json data (include ref/style/attr/event/children)
+ * @param page : {@link RenderPage}
+ * @return {@link RenderObject*}
+ */
+  RenderObject *Json2RenderObject(char *data, const std::string &pageId) {
+
+    JsonParser r(data);
+    return ParseJsonObject(r, nullptr, 0, pageId);
+  }
+
+  std::vector<std::pair<std::string, std::string>> *Json2Pairs(char *data) {
+    std::vector<std::pair<std::string, std::string>> *pairs = nullptr;
+    JsonParser r(data);
+    RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
+    r.EnterObject();
+    pairs = new std::vector<std::pair<std::string, std::string>>();
+    while (const char *key = r.NextObjectKey()) {
+      if (r.PeekType() == kNumberType) {
+        RAPIDJSON_ASSERT(r.PeekType() == kNumberType);
+        char *temp = new char[65];
+        int len = fpconv_dtoa(r.GetDouble(), temp);
+        temp[len] = '\0';
+        char value[len + 1];
+        strcpy(value, temp);
+        std::pair<std::string, std::string> myPair(key, value);
+        pairs->insert(pairs->end(), myPair);
+        if (temp != nullptr) {
+          delete[]temp;
+          temp = nullptr;
+        }
+      } else if (r.PeekType() == kStringType) {
+        RAPIDJSON_ASSERT(r.PeekType() == kStringType);
+        const char *value = r.GetString();
+        std::pair<std::string, std::string> myPair(key, value);
+        pairs->insert(pairs->end(), myPair);
+        if (value != nullptr) {
+          delete value;
+          value = nullptr;
+        }
+      } else if (r.PeekType() == kArrayType) {
+        RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
+        std::string temp = "[";
+        temp.append(r.Stringify());
+        int endIndex = temp.find(']');
+        if(endIndex > 0) {
+          // has found!
+          int startIndex = 0;
+          int leftMatchSize = matchNum(temp, "[", startIndex, endIndex) - 1;
+          while (leftMatchSize > 0 && startIndex < endIndex) {
+            startIndex = endIndex + 1;
+            int markIndex = temp.find(']', startIndex);
+            if(markIndex > 0) {
+              endIndex = markIndex;
+              leftMatchSize--;
+            }
+            leftMatchSize += matchNum(temp, "[", startIndex, endIndex);
+          }
+        }
+        std::string value = temp.substr(0, endIndex + 1);
+        std::pair<std::string, std::string> myPair(key, value);
+        pairs->insert(pairs->end(), myPair);
+        r.SkipValue();
+      } else if (r.PeekType() == kTrueType) {
+        RAPIDJSON_ASSERT(r.PeekType() == kTrueType);
+        std::pair<std::string, std::string> myPair(key, "true");
+        pairs->insert(pairs->end(), myPair);
+        r.SkipValue();
+      } else if (r.PeekType() == kFalseType) {
+        RAPIDJSON_ASSERT(r.PeekType() == kFalseType);
+        std::pair<std::string, std::string> myPair(key, "false");
+        pairs->insert(pairs->end(), myPair);
+        r.SkipValue();
+      } else if (r.PeekType() == kNullType) {
+        RAPIDJSON_ASSERT(r.PeekType() == kNullType);
+        std::pair<std::string, std::string> myPair(key, "");
+        pairs->insert(pairs->end(), myPair);
+        r.SkipValue();
+      } else if (r.PeekType() == kObjectType) {
+        RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
+        std::string temp = "{";
+        temp.append(r.Stringify());
+        int endIndex = temp.find('}');
+        if(endIndex > 0) {
+          // has found!
+          int startIndex = 0;
+          int leftMatchSize = matchNum(temp, "{", startIndex, endIndex) - 1;
+          while (leftMatchSize > 0 && startIndex < endIndex) {
+            startIndex = endIndex + 1;
+            int markIndex = temp.find('}', startIndex);
+            if(markIndex > 0) {
+              endIndex = markIndex;
+              leftMatchSize--;
+            }
+            leftMatchSize += matchNum(temp, "{", startIndex, endIndex);
+          }
+        }
+        std::string value = temp.substr(0, endIndex + 1);
+
+        std::pair<std::string, std::string> myPair(key, value);
+        pairs->insert(pairs->end(), myPair);
+        r.SkipValue();
+      } else {
+        r.SkipValue();
+      }
+    }
+    return pairs;
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/parser/dom_parser.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/parser/dom_parser.h b/weex_core/Source/core/parser/dom_parser.h
new file mode 100644
index 0000000..064de63
--- /dev/null
+++ b/weex_core/Source/core/parser/dom_parser.h
@@ -0,0 +1,129 @@
+#ifndef WEEX_JSON_TOOLS
+#define WEEX_JSON_TOOLS
+
+#include "rapidjson/pointer.h"
+#include <vector>
+#include <string>
+
+namespace WeexCore {
+
+  class RenderObject;
+
+  class RenderPage;
+
+/**
+ * Use to handler json parser result
+ */
+  class JsonParserHandler {
+  public:
+    bool Null();
+
+    bool Bool(bool b);
+
+    bool Int(int i);
+
+    bool Uint(unsigned u);
+
+    bool Int64(int64_t i);
+
+    bool Uint64(uint64_t u);
+
+    bool Double(double d);
+
+    bool RawNumber(const char *, rapidjson::SizeType, bool);
+
+    bool String(const char *str, rapidjson::SizeType length, bool);
+
+    bool StartObject();
+
+    bool Key(const char *str, rapidjson::SizeType length, bool);
+
+    bool EndObject(rapidjson::SizeType);
+
+    bool StartArray();
+
+    bool EndArray(rapidjson::SizeType);
+
+  protected:
+    JsonParserHandler(char *str);
+
+    void ParseNext();
+
+  protected:
+    enum JsonParsingState {
+      kInit,
+      kError,
+      kHasNull,
+      kHasBool,
+      kHasNumber,
+      kHasString,
+      kHasKey,
+      kEnteringObject,
+      kExitingObject,
+      kEnteringArray,
+      kExitingArray
+    };
+
+    rapidjson::Value v_;
+    JsonParsingState st_;
+    rapidjson::Reader r_;
+    rapidjson::InsituStringStream ss_;
+
+    static const int parseFlags = rapidjson::kParseDefaultFlags | rapidjson::kParseInsituFlag;
+  };
+
+/**
+ * Use to parse json data
+ */
+  class JsonParser : public JsonParserHandler {
+  public:
+    JsonParser(char *str) : JsonParserHandler(str) {}
+
+    bool EnterObject();
+
+    bool EnterArray();
+
+    const char *NextObjectKey();
+
+    bool NextArrayValue();
+
+    int GetInt();
+
+    double GetDouble();
+
+    const char *GetString();
+
+    const char *Stringify();
+
+    bool GetBool();
+
+    void GetNull();
+
+    void SkipObject();
+
+    void SkipArray();
+
+    void SkipValue();
+
+    rapidjson::Value *PeekValue();
+
+    int PeekType(); // returns a rapidjson::Type, or -1 for no value (at end of object/array)
+
+    bool IsValid() { return st_ != kError; }
+
+  protected:
+    void SkipOut(int depth);
+  };
+
+/**
+ * Parse json data to RenderObject
+ * @param data : json data (include ref/style/attr/event/children)
+ * @param page : {@link RenderPage*}
+ * @return {@link RenderObject*}
+ */
+  RenderObject *Json2RenderObject(char *data, const std::string &pageId);
+
+  std::vector<std::pair<std::string, std::string>> *Json2Pairs(char *data);
+}
+
+#endif //WEEX_JSON_TOOLS

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action.h b/weex_core/Source/core/render/action/render_action.h
new file mode 100644
index 0000000..3172ab2
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action.h
@@ -0,0 +1,20 @@
+#ifndef WEEXV8_RENDERACTION_H
+#define WEEXV8_RENDERACTION_H
+
+#include <core/layout/layout.h>
+#include <core/render/node/render_object.h>
+#include <core/render/manager/render_manager.h>
+#include <core/render/page/render_page.h>
+#include <android/bridge/impl/bridge_impl_android.h>
+#include <string>
+#include <base/TimeUtils.h>
+
+namespace WeexCore {
+
+  class render_action {
+  public:
+    virtual void ExecuteAction() = 0;
+  };
+}
+
+#endif //WEEXV8_RENDERACTION_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action_add_element.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_add_element.cpp b/weex_core/Source/core/render/action/render_action_add_element.cpp
new file mode 100644
index 0000000..047359c
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_add_element.cpp
@@ -0,0 +1,33 @@
+#include "render_action_add_element.h"
+
+namespace WeexCore {
+
+  RenderActionAddElement::RenderActionAddElement(const std::string &pageId, const RenderObject *render,
+                                                 const RenderObject *parent, int index) {
+    this->mAttributes = render->Attributes();
+    this->mStyles = render->Styles();
+    this->mEvents = render->Events();
+    this->mMargins = render->GetMargins();
+    this->mPaddings = render->GetPaddings();
+    this->mBorders = render->GetBorders();
+    this->mPageId = pageId;
+    this->mComponentType = render->Type();
+    this->mRef = render->Ref();
+    this->mParentRef = parent->Ref();
+    this->mIndex = index;
+  }
+
+  void RenderActionAddElement::ExecuteAction() {
+    RenderPage *page = RenderManager::GetInstance()->GetPage(mPageId);
+    if (page == nullptr)
+      return;
+
+    long long startTime = getCurrentTime();
+    Bridge_Impl_Android::getInstance()->callAddElement(mPageId.c_str(), mComponentType.c_str(), mRef.c_str(),
+                                                       mIndex, mParentRef.c_str(), mStyles, mAttributes,
+                                                       mEvents, mMargins, mPaddings, mBorders);
+    page->JniCallTime(getCurrentTime() - startTime);
+    page->AddElementActionJNITime(getCurrentTime() - startTime);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action_add_element.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_add_element.h b/weex_core/Source/core/render/action/render_action_add_element.h
new file mode 100644
index 0000000..c87b943
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_add_element.h
@@ -0,0 +1,31 @@
+#ifndef WEEX_PROJECT_ADDELEMENTACTION_H
+#define WEEX_PROJECT_ADDELEMENTACTION_H
+
+#include "render_action.h"
+
+namespace WeexCore {
+
+  class RenderActionAddElement : public render_action {
+
+  public:
+    RenderActionAddElement(const std::string &pageId, const RenderObject *render, const RenderObject *parent,
+                           int index);
+
+    void ExecuteAction();
+
+  public:
+    StylesMap *mStyles;
+    AttributesMap *mAttributes;
+    EventsSet *mEvents;
+    WXCoreMargin mMargins;
+    WXCorePadding mPaddings;
+    WXCoreBorderWidth mBorders;
+    std::string mPageId;
+    std::string mComponentType;
+    std::string mParentRef;
+    std::string mRef;
+    int mIndex;
+  };
+}
+
+#endif //WEEX_PROJECT_ADDELEMENTACTION_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action_add_event.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_add_event.cpp b/weex_core/Source/core/render/action/render_action_add_event.cpp
new file mode 100644
index 0000000..66d8910
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_add_event.cpp
@@ -0,0 +1,24 @@
+#include "render_action_add_event.h"
+
+namespace WeexCore {
+
+  RenderActionAddEvent::RenderActionAddEvent(const std::string &pageId, const std::string &ref, const std::string &event) {
+    this->mPageId = pageId;
+    this->mRef = ref;
+    this->mEvent = event;
+  }
+
+  void RenderActionAddEvent::ExecuteAction() {
+    RenderPage *page = RenderManager::GetInstance()->GetPage(mPageId);
+    if (page == nullptr)
+      return;
+
+    long long startTime = getCurrentTime();
+
+    Bridge_Impl_Android::getInstance()->callAddEvent(mPageId.c_str(), mRef.c_str(), mEvent.c_str());
+
+    page->JniCallTime(getCurrentTime() - startTime);
+    page->AddEventActionJNITime(getCurrentTime() - startTime);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action_add_event.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_add_event.h b/weex_core/Source/core/render/action/render_action_add_event.h
new file mode 100644
index 0000000..d6da682
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_add_event.h
@@ -0,0 +1,22 @@
+#ifndef WEEX_PROJECT_ADDEVENTACTION_H
+#define WEEX_PROJECT_ADDEVENTACTION_H
+
+#include "render_action.h"
+
+namespace WeexCore {
+
+  class RenderActionAddEvent : public render_action {
+
+  public:
+    RenderActionAddEvent(const std::string &pageId, const std::string &ref, const std::string &event);
+
+    void ExecuteAction();
+
+  public:
+    std::string mPageId;
+    std::string mRef;
+    std::string mEvent;
+  };
+}
+
+#endif //WEEX_PROJECT_ADDEVENTACTION_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action_createbody.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_createbody.cpp b/weex_core/Source/core/render/action/render_action_createbody.cpp
new file mode 100644
index 0000000..7a97ec2
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_createbody.cpp
@@ -0,0 +1,29 @@
+#include "render_action_createbody.h"
+
+namespace WeexCore {
+
+  RenderActionCreateBody::RenderActionCreateBody(const std::string &pageId, const RenderObject *render) {
+    this->mAttributes = render->Attributes();
+    this->mStyles = render->Styles();
+    this->mEvents = render->Events();
+    this->mMargins = render->GetMargins();
+    this->mPaddings = render->GetPaddings();
+    this->mBorders = render->GetBorders();
+    this->mPageId = pageId;
+    this->mComponentType = render->Type();
+    this->mRef = render->Ref();
+  }
+
+  void RenderActionCreateBody::ExecuteAction() {
+    RenderPage *page = RenderManager::GetInstance()->GetPage(mPageId);
+    if (page == nullptr)
+      return;
+
+    long long startTime = getCurrentTime();
+    Bridge_Impl_Android::getInstance()->callCreateBody(mPageId.c_str(), mComponentType.c_str(), mRef.c_str(),
+                                                       mStyles, mAttributes, mEvents,
+                                                       mMargins, mPaddings, mBorders);
+    page->JniCallTime(getCurrentTime() - startTime);
+    page->AddElementActionJNITime(getCurrentTime() - startTime);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action_createbody.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_createbody.h b/weex_core/Source/core/render/action/render_action_createbody.h
new file mode 100644
index 0000000..f8dcd8a
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_createbody.h
@@ -0,0 +1,27 @@
+#ifndef WEEX_PROJECT_CREATEBODYACTION_H
+#define WEEX_PROJECT_CREATEBODYACTION_H
+
+#include "render_action.h"
+
+namespace WeexCore {
+  class RenderActionCreateBody : public render_action {
+
+  public:
+    RenderActionCreateBody(const std::string &pageId, const RenderObject *render);
+
+    void ExecuteAction();
+
+  public:
+    StylesMap *mStyles;
+    AttributesMap *mAttributes;
+    EventsSet *mEvents;
+    WXCoreMargin mMargins;
+    WXCorePadding mPaddings;
+    WXCoreBorderWidth mBorders;
+    std::string mPageId;
+    std::string mComponentType;
+    std::string mRef;
+  };
+}
+
+#endif //WEEX_PROJECT_CREATEBODYACTION_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action_createfinish.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_createfinish.cpp b/weex_core/Source/core/render/action/render_action_createfinish.cpp
new file mode 100644
index 0000000..0e72b03
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_createfinish.cpp
@@ -0,0 +1,19 @@
+#include "render_action_createfinish.h"
+
+namespace WeexCore {
+
+  RenderActionCreateFinish::RenderActionCreateFinish(const std::string &pageId) {
+    this->mPageId = pageId;
+  }
+
+  void RenderActionCreateFinish::ExecuteAction() {
+    RenderPage *page = RenderManager::GetInstance()->GetPage(mPageId);
+    if (page == nullptr)
+      return;
+
+    long long startTime = getCurrentTime();
+    Bridge_Impl_Android::getInstance()->callCreateFinish(mPageId.c_str());
+
+    page->JniCallTime(getCurrentTime() - startTime);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action_createfinish.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_createfinish.h b/weex_core/Source/core/render/action/render_action_createfinish.h
new file mode 100644
index 0000000..513ab45
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_createfinish.h
@@ -0,0 +1,20 @@
+#ifndef WEEX_PROJECT_CREATEFINISHACTION_H
+#define WEEX_PROJECT_CREATEFINISHACTION_H
+
+#include "render_action.h"
+
+namespace WeexCore {
+
+  class RenderActionCreateFinish : public render_action {
+
+  public:
+    RenderActionCreateFinish(const std::string &pageId);
+
+    void ExecuteAction();
+
+  public:
+    std::string mPageId;
+  };
+}
+
+#endif //WEEX_PROJECT_CREATEFINISHACTION_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action_layout.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_layout.cpp b/weex_core/Source/core/render/action/render_action_layout.cpp
new file mode 100644
index 0000000..4417b5c
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_layout.cpp
@@ -0,0 +1,33 @@
+#include "render_action_layout.h"
+
+namespace WeexCore {
+
+  RenderActionLayout::RenderActionLayout(const std::string &pageId, const RenderObject *render,int index) {
+    this->mPageId = pageId;
+    this->mRef = render->Ref();
+    this->index = index;
+    GetLayoutInfo(render);
+  }
+
+  void RenderActionLayout::ExecuteAction() {
+    RenderPage *page = RenderManager::GetInstance()->GetPage(mPageId);
+    if (page == nullptr)
+      return;
+
+    long long startTime = getCurrentTime();
+    Bridge_Impl_Android::getInstance()->callLayout(mPageId.c_str(), mRef.c_str(),
+                                                   mTop, mBottom, mLeft, mRight,
+                                                   mHeight, mWidth, index);
+    page->JniCallTime(getCurrentTime() - startTime);
+    page->LayoutActionJniTime(getCurrentTime() - startTime);
+  }
+
+  void RenderActionLayout::GetLayoutInfo(const WXCoreLayoutNode *node) {
+    mTop = node->getLayoutPositionTop();
+    mBottom = node->getLayoutPositionBottom();
+    mRight = node->getLayoutPositionRight();
+    mLeft = node->getLayoutPositionLeft();
+    mHeight = node->getLayoutHeight();
+    mWidth = node->getLayoutWidth();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action_layout.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_layout.h b/weex_core/Source/core/render/action/render_action_layout.h
new file mode 100644
index 0000000..0344e54
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_layout.h
@@ -0,0 +1,31 @@
+#ifndef WEEX_PROJECT_RELAYOUTRENDERACTION_H
+#define WEEX_PROJECT_RELAYOUTRENDERACTION_H
+
+#include "render_action.h"
+
+namespace WeexCore {
+
+  class RenderActionLayout : public render_action {
+
+  public:
+    RenderActionLayout(const std::string &pageId, const RenderObject *render, const int index);
+
+    void ExecuteAction();
+
+    void GetLayoutInfo(const WXCoreLayoutNode *node);
+
+  public:
+    EventsSet *mEvents;
+    std::string mPageId;
+    std::string mRef;
+    float mWidth;
+    float mHeight;
+    float mTop;
+    float mLeft;
+    float mBottom;
+    float mRight;
+    int index;
+  };
+}
+
+#endif //WEEX_PROJECT_RELAYOUTRENDERACTION_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/core/render/action/render_action_move_element.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_move_element.cpp b/weex_core/Source/core/render/action/render_action_move_element.cpp
new file mode 100644
index 0000000..98bb9b1
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_move_element.cpp
@@ -0,0 +1,22 @@
+#include "render_action_move_element.h"
+
+namespace WeexCore {
+
+  RenderActionMoveElement::RenderActionMoveElement(const std::string &pageId, const std::string &ref,
+                                                   const std::string &parentRef, int index) {
+    this->mPageId = pageId;
+    this->mRef = ref;
+    this->mParentRef = parentRef;
+    this->mIndex = index;
+  }
+
+  void RenderActionMoveElement::ExecuteAction() {
+    RenderPage *page = RenderManager::GetInstance()->GetPage(mPageId);
+    if (page == nullptr)
+      return;
+
+    long long startTime = getCurrentTime();
+    Bridge_Impl_Android::getInstance()->callMoveElement(mPageId.c_str(), mRef.c_str(), mParentRef.c_str(), mIndex);
+    page->JniCallTime(getCurrentTime() - startTime);
+  }
+}
\ No newline at end of file