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 ¤tLength, 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 ¤tLength) 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