layout.h 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. #ifdef __cplusplus
  20. #ifndef WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H
  21. #define WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H
  22. #include <string.h>
  23. #include <math.h>
  24. #include <vector>
  25. #include <iostream>
  26. #include <string>
  27. #include <algorithm>
  28. #include "style.h"
  29. #include "flex_enum.h"
  30. namespace WeexCore {
  31. class WXCoreLayoutNode;
  32. class WXCoreFlexLine;
  33. enum FormattingContext {
  34. kBFC,
  35. kNonBFC,
  36. } ;
  37. enum MeasureMode {
  38. kUnspecified = 0,
  39. kExactly,
  40. } ;
  41. struct WXCoreSize {
  42. private:
  43. float hypotheticalWidth;
  44. float hypotheticalHeight;
  45. public:
  46. friend class WXCoreLayoutNode;
  47. float width;
  48. float height;
  49. WXCoreSize() : hypotheticalWidth(NAN),
  50. hypotheticalHeight(NAN),
  51. width(0), height(0) {}
  52. inline void reset() {
  53. hypotheticalWidth = NAN ;
  54. hypotheticalHeight = NAN;
  55. width = 0;
  56. height = 0;
  57. }
  58. inline bool isNAN() {
  59. return isnan(width) || isnan(height);
  60. }
  61. };
  62. /**
  63. * layout-result:layout-height、layout-width、position(left、right、top、bottom)、direction
  64. */
  65. struct WXCorelayoutResult {
  66. WXCoreDirection mLayoutDirection;
  67. WXCoreSize mLayoutSize;
  68. WXCorePosition mLayoutPosition;
  69. inline bool isNAN() {
  70. return mLayoutSize.isNAN() || mLayoutPosition.isNAN();
  71. }
  72. inline void reset() {
  73. mLayoutSize.reset();
  74. mLayoutPosition.reset();
  75. mLayoutDirection = kDirectionInherit;
  76. }
  77. };
  78. typedef WXCoreSize(*WXCoreMeasureFunc)(WXCoreLayoutNode *node, float width,
  79. MeasureMode widthMeasureMode,
  80. float height, MeasureMode heightMeasureMode);
  81. using Index = std::vector<WXCoreLayoutNode *>::size_type;
  82. /**
  83. * flie line
  84. */
  85. class WXCoreFlexLine {
  86. public:
  87. float mMainSize;
  88. float mCrossSize;
  89. Index mItemCount;
  90. float mTotalFlexGrow;
  91. float mTotalFlexibleSize;
  92. /**
  93. * Store the indices of the children views whose mAlignSelf property is stretch.
  94. * The stored indices are the absolute indices including all children in the Flexbox,
  95. * not the relative indices in this flex line.
  96. */
  97. std::vector<Index> mIndicesAlignSelfStretch;
  98. WXCoreFlexLine() : mMainSize(0),
  99. mCrossSize(0),
  100. mItemCount(0),
  101. mTotalFlexGrow(0),
  102. mTotalFlexibleSize(0) {
  103. }
  104. ~WXCoreFlexLine() {
  105. mMainSize = 0;
  106. mCrossSize = 0;
  107. mItemCount = 0;
  108. mTotalFlexGrow = 0;
  109. mTotalFlexibleSize = 0;
  110. mIndicesAlignSelfStretch.clear();
  111. }
  112. };
  113. /**
  114. * Layout node
  115. */
  116. class WXCoreLayoutNode {
  117. public:
  118. WXCoreLayoutNode() :
  119. mParent(nullptr),
  120. dirty(true),
  121. widthDirty{false},
  122. heightDirty{false},
  123. mHasNewLayout(true),
  124. mIsDestroy(false),
  125. measureFunc(nullptr) {
  126. mCssStyle = new WXCoreCSSStyle();
  127. mLayoutResult = new WXCorelayoutResult();
  128. }
  129. virtual ~WXCoreLayoutNode() {
  130. mIsDestroy = true;
  131. mHasNewLayout = true;
  132. dirty = true;
  133. measureFunc = nullptr;
  134. mParent = nullptr;
  135. mChildList.clear();
  136. BFCs.clear();
  137. NonBFCs.clear();
  138. mChildrenFrozen.clear();
  139. for (WXCoreFlexLine *flexLine : mFlexLines) {
  140. if (flexLine != nullptr) {
  141. delete flexLine;
  142. flexLine = nullptr;
  143. }
  144. }
  145. mFlexLines.clear();
  146. if (mCssStyle != nullptr) {
  147. delete mCssStyle;
  148. mCssStyle = nullptr;
  149. }
  150. if (mLayoutResult != nullptr) {
  151. delete mLayoutResult;
  152. mLayoutResult = nullptr;
  153. }
  154. }
  155. private:
  156. /**
  157. * Holds the 'frozen' state of children during measure. If a view is frozen it will no longer
  158. * expand regardless of mFlexGrow. Items are indexed by the child's
  159. * reordered index.
  160. */
  161. std::vector<bool> mChildrenFrozen;
  162. std::vector<WXCoreFlexLine *> mFlexLines;
  163. std::vector<WXCoreLayoutNode *> mChildList;
  164. std::vector<WXCoreLayoutNode *> BFCs;
  165. std::vector<WXCoreLayoutNode *> NonBFCs;
  166. WXCoreLayoutNode *mParent = nullptr;
  167. WXCoreCSSStyle *mCssStyle = nullptr;
  168. MeasureMode widthMeasureMode = kUnspecified;
  169. MeasureMode heightMeasureMode = kUnspecified;
  170. WXCorelayoutResult *mLayoutResult = nullptr;
  171. WXCorePosition *absoultePositon = nullptr;
  172. bool mHasNewLayout;
  173. bool dirty, widthDirty, heightDirty;
  174. bool mIsDestroy = true;
  175. bool mNeedsPlatformDependentLayout = false;
  176. WXCoreMeasureFunc measureFunc = nullptr;
  177. void *context = nullptr;
  178. /** ================================ Cache:Last calculate result =================================== **/
  179. public:
  180. /** ================================ Engine Entry Function =================================== **/
  181. void calculateLayout(const std::pair<float,float>&);
  182. /** ================================ measureFunc =================================== **/
  183. inline void setMeasureFunc(WXCoreMeasureFunc measure) {
  184. measureFunc = measure;
  185. markDirty();
  186. }
  187. inline bool haveMeasureFunc() const {
  188. return nullptr != measureFunc;
  189. }
  190. inline WXCoreMeasureFunc getMeasureFunc() const {
  191. return measureFunc;
  192. }
  193. /** ================================ context =================================== **/
  194. inline void *getContext() const {
  195. return context;
  196. }
  197. inline void setContext(void * const context) {
  198. this->context = context;
  199. }
  200. inline void copyStyle(WXCoreLayoutNode *srcNode) {
  201. if (srcNode != nullptr && memcmp(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle)) != 0) {
  202. memcpy(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle));
  203. markDirty();
  204. }
  205. }
  206. void copyFrom(WXCoreLayoutNode* srcNode){
  207. if (srcNode == nullptr) return;
  208. memcpy(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle));
  209. }
  210. inline void copyMeasureFunc(WXCoreLayoutNode *srcNode) {
  211. if (srcNode != nullptr && memcmp(&measureFunc, &srcNode->measureFunc, sizeof(WXCoreMeasureFunc)) != 0) {
  212. memcpy(&measureFunc, &srcNode->measureFunc, sizeof(WXCoreMeasureFunc));
  213. markDirty();
  214. }
  215. }
  216. /** ================================ custom =================================== **/
  217. inline bool getNeedsPlatformDependentLayout() const {
  218. return mNeedsPlatformDependentLayout;
  219. }
  220. inline void setNeedsPlatformDependentLayout(bool v) {
  221. this->mNeedsPlatformDependentLayout = v;
  222. }
  223. private:
  224. /** ================================ measure =================================== **/
  225. inline void reset() {
  226. if (isDirty()) {
  227. mLayoutResult->reset();
  228. for (WXCoreFlexLine *flexLine : mFlexLines) {
  229. if (flexLine != nullptr) {
  230. delete flexLine;
  231. flexLine = nullptr;
  232. }
  233. }
  234. mFlexLines.clear();
  235. mChildrenFrozen.assign(getChildCount(kNonBFC), false);
  236. }
  237. widthMeasureMode = isnan(mCssStyle->mStyleWidth) ? kUnspecified : kExactly;
  238. heightMeasureMode = isnan(mCssStyle->mStyleHeight) ? kUnspecified : kExactly;
  239. }
  240. inline void setLayoutWidth(const float width) {
  241. if (mLayoutResult->mLayoutSize.width != width &&
  242. (!isnan(width) || !isnan(mLayoutResult->mLayoutSize.width))) {
  243. mLayoutResult->mLayoutSize.width = width;
  244. widthDirty = true;
  245. markDirty(false);
  246. }
  247. }
  248. inline void setLayoutHeight(const float height) {
  249. if (mLayoutResult->mLayoutSize.height != height &&
  250. (!isnan(height) || !isnan(mLayoutResult->mLayoutSize.height))) {
  251. mLayoutResult->mLayoutSize.height = height;
  252. heightDirty = true;
  253. markDirty(false);
  254. }
  255. }
  256. inline void setWidthMeasureMode(const MeasureMode measureMode) {
  257. if (widthMeasureMode != measureMode) {
  258. widthMeasureMode = measureMode;
  259. if (getChildCount(kNonBFC) > 0) {
  260. widthDirty = true;
  261. }
  262. }
  263. }
  264. inline void setHeightMeasureMode(const MeasureMode measureMode) {
  265. if (heightMeasureMode != measureMode) {
  266. heightMeasureMode = measureMode;
  267. if (getChildCount(kNonBFC) > 0) {
  268. heightDirty = true;
  269. }
  270. }
  271. }
  272. inline float firstLineCrossSize() const {
  273. float sum = sumPaddingBorderAlongAxis(this, !isMainAxisHorizontal(this));
  274. if (!mFlexLines.empty()) {
  275. sum += mFlexLines[0]->mCrossSize;
  276. }
  277. return sum;
  278. }
  279. inline float getSumOfCrossSize() const {
  280. float sum = sumPaddingBorderAlongAxis(this, !isMainAxisHorizontal(this));
  281. for (WXCoreFlexLine *flexLine: mFlexLines) {
  282. sum += flexLine->mCrossSize;
  283. }
  284. return sum;
  285. }
  286. inline bool isMainAxisHorizontal(const WXCoreLayoutNode* const node) const {
  287. return node->mCssStyle->mFlexDirection == kFlexDirectionRow ||
  288. node->mCssStyle->mFlexDirection == kFlexDirectionRowReverse;
  289. }
  290. inline bool isCrossExactly() const {
  291. return isMainAxisHorizontal(this) ? heightMeasureMode == kExactly
  292. : widthMeasureMode == kExactly;
  293. }
  294. inline float sumPaddingBorderAlongAxis(const WXCoreLayoutNode* const node, bool horizontal) const {
  295. float paddingBorderAlongAxis;
  296. if (horizontal) {
  297. paddingBorderAlongAxis =
  298. node->mCssStyle->mPadding.getPadding(kPaddingLeft) +
  299. node->mCssStyle->mPadding.getPadding(kPaddingRight) +
  300. node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthLeft) +
  301. node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthRight);
  302. } else {
  303. paddingBorderAlongAxis =
  304. node->mCssStyle->mPadding.getPadding(kPaddingTop) +
  305. node->mCssStyle->mPadding.getPadding(kPaddingBottom) +
  306. node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthTop) +
  307. node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthBottom);
  308. }
  309. return paddingBorderAlongAxis;
  310. }
  311. inline bool isWrapRequired(const float &width, const float &height,
  312. const float &currentLength, const float &childLength) const {
  313. float freeMainSize = CalculateFreeSpaceAlongMainAxis(width, height, currentLength);
  314. return !isSingleFlexLine(freeMainSize) && freeMainSize < childLength;
  315. }
  316. //If width/height is NAN, ret is NAN, which property we use on purpose.
  317. virtual float CalculateFreeSpaceAlongMainAxis(const float &width, const float &height,
  318. const float &currentLength) const{
  319. float ret;
  320. if(isMainAxisHorizontal(this)){
  321. ret = width - sumPaddingBorderAlongAxis(this, true) - currentLength;
  322. }
  323. else{
  324. ret = height - sumPaddingBorderAlongAxis(this, false) - currentLength;
  325. }
  326. return ret;
  327. }
  328. inline bool isSingleFlexLine(const float &mainSize) const {
  329. return mCssStyle->mFlexWrap == kNoWrap || isnan(mainSize);
  330. }
  331. inline void sumFlexGrow(const WXCoreLayoutNode* const child, WXCoreFlexLine* const flexLine, Index i){
  332. if (child->mCssStyle->mFlexGrow > 0) {
  333. flexLine->mTotalFlexGrow += child->mCssStyle->mFlexGrow;
  334. mChildrenFrozen[i] = false;
  335. if (isMainAxisHorizontal(this)) {
  336. if (!isnan(child->mLayoutResult->mLayoutSize.hypotheticalWidth)) {
  337. flexLine->mTotalFlexibleSize += child->mLayoutResult->mLayoutSize.hypotheticalWidth;
  338. }
  339. } else {
  340. if (!isnan(child->mLayoutResult->mLayoutSize.hypotheticalHeight)) {
  341. flexLine->mTotalFlexibleSize += child->mLayoutResult->mLayoutSize.hypotheticalHeight;
  342. }
  343. }
  344. } else {
  345. mChildrenFrozen[i] = true;
  346. }
  347. }
  348. inline void setMeasuredDimensionForFlex(
  349. const float width, const MeasureMode widthMeasureMode,
  350. const float height, const MeasureMode heightMeasureMode){
  351. float actualWidth, actualHeight;
  352. if (isMainAxisHorizontal(this)) {
  353. actualWidth = widthMeasureMode == kExactly ? width : getLargestMainSize();
  354. actualHeight = heightMeasureMode == kExactly ? height : getSumOfCrossSize();
  355. } else {
  356. actualHeight = heightMeasureMode == kExactly ? height : getLargestMainSize();
  357. actualWidth = widthMeasureMode == kExactly ? width : firstLineCrossSize();
  358. }
  359. setMeasuredDimension(actualWidth, actualHeight);
  360. }
  361. inline float calcItemSizeAlongAxis(const WXCoreLayoutNode* const node, const bool horizontal, const bool useHypotheticalSize = false) const {
  362. float ret;
  363. if (horizontal) {
  364. ret = node->mCssStyle->mMargin.getMargin(kMarginLeft) +
  365. node->mCssStyle->mMargin.getMargin(kMarginRight);
  366. ret += useHypotheticalSize ? node->mLayoutResult->mLayoutSize.hypotheticalWidth
  367. : node->mLayoutResult->mLayoutSize.width;
  368. } else {
  369. ret = node->mCssStyle->mMargin.getMargin(kMarginTop) +
  370. node->mCssStyle->mMargin.getMargin(kMarginBottom);
  371. ret += useHypotheticalSize ? node->mLayoutResult->mLayoutSize.hypotheticalHeight
  372. : node->mLayoutResult->mLayoutSize.height;
  373. }
  374. return ret;
  375. }
  376. inline void limitMainSizeForFlexGrow(WXCoreFlexLine* const flexLine, const Index childIndex,
  377. const float flexGrow) {
  378. mChildrenFrozen[childIndex] = true;
  379. flexLine->mTotalFlexGrow -= flexGrow;
  380. }
  381. inline void setMeasuredDimension(const float width, const float height) {
  382. mLayoutResult->mLayoutSize.width = width;
  383. mLayoutResult->mLayoutSize.height = height;
  384. }
  385. inline std::pair<bool, float> limitChildMainSize(WXCoreFlexLine* const flexLine, const WXCoreLayoutNode* const child,
  386. float childSizeAlongMainAxis, const Index childIndex){
  387. bool needsReexpand = false;
  388. if (isMainAxisHorizontal(this)) {
  389. if (!isnan(child->mCssStyle->mMaxWidth) &&
  390. childSizeAlongMainAxis > child->mCssStyle->mMaxWidth) {
  391. needsReexpand = true;
  392. childSizeAlongMainAxis = child->mCssStyle->mMaxWidth;
  393. } else if (!isnan(child->mCssStyle->mMinWidth) &&
  394. childSizeAlongMainAxis < child->mCssStyle->mMinWidth) {
  395. needsReexpand = true;
  396. childSizeAlongMainAxis = child->mCssStyle->mMinWidth;
  397. }
  398. } else {
  399. if (!isnan(child->mCssStyle->mMaxHeight) &&
  400. childSizeAlongMainAxis > child->mCssStyle->mMaxHeight) {
  401. needsReexpand = true;
  402. childSizeAlongMainAxis = child->mCssStyle->mMaxHeight;
  403. } else if (!isnan(child->mCssStyle->mMinHeight) &&
  404. childSizeAlongMainAxis < child->mCssStyle->mMinHeight) {
  405. needsReexpand = true;
  406. childSizeAlongMainAxis = child->mCssStyle->mMinHeight;
  407. }
  408. }
  409. limitMainSizeForFlexGrow(flexLine, childIndex, child->mCssStyle->mFlexGrow);
  410. return std::make_pair(needsReexpand, childSizeAlongMainAxis);
  411. }
  412. void updateLeftRightForAbsolute(float &left, float &right,
  413. const WXCorePadding &parentPadding,
  414. const WXCoreBorderWidth &parentBorder,
  415. const WXCoreSize &parentSize) const {
  416. if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft))) {
  417. if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeRight))) {
  418. ;
  419. } else {
  420. right += parentSize.width -
  421. (parentBorder.getBorderWidth(kBorderWidthRight) +
  422. mCssStyle->mStylePosition.getPosition(kPositionEdgeRight)
  423. + mLayoutResult->mLayoutSize.width);
  424. left += parentSize.width -
  425. (parentBorder.getBorderWidth(kBorderWidthRight) +
  426. mCssStyle->mStylePosition.getPosition(kPositionEdgeRight)
  427. + mLayoutResult->mLayoutSize.width);
  428. }
  429. } else {
  430. left += parentBorder.getBorderWidth(kBorderWidthLeft) +
  431. mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft);
  432. right += parentBorder.getBorderWidth(kBorderWidthLeft) +
  433. mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft);
  434. }
  435. }
  436. void updateTopBottomForAbsolute(float &top, float &bottom,
  437. const WXCorePadding &parentPadding,
  438. const WXCoreBorderWidth &parentBorder,
  439. const WXCoreSize &parentSize) const {
  440. if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeTop))) {
  441. if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom))) {
  442. ;
  443. } else {
  444. top += parentSize.height -
  445. (parentBorder.getBorderWidth(kBorderWidthBottom) +
  446. mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom)
  447. + mLayoutResult->mLayoutSize.height);
  448. bottom += parentSize.height -
  449. (parentBorder.getBorderWidth(kBorderWidthBottom) +
  450. mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom)
  451. + mLayoutResult->mLayoutSize.height);
  452. }
  453. } else {
  454. top += parentBorder.getBorderWidth(kBorderWidthTop) +
  455. mCssStyle->mStylePosition.getPosition(kPositionEdgeTop);
  456. bottom += parentBorder.getBorderWidth(kBorderWidthTop) +
  457. mCssStyle->mStylePosition.getPosition(kPositionEdgeTop);
  458. }
  459. }
  460. /** ================================ other =================================== **/
  461. inline void clearDirty() {
  462. dirty = false;
  463. widthDirty = false;
  464. heightDirty = false;
  465. }
  466. void
  467. measure(float, float, bool);
  468. void hypotheticalMeasure(float, float, bool = false);
  469. void measureLeafNode(float, float, bool, bool);
  470. void measureInternalNode(float, float, bool, bool);
  471. void updateCurrentFlexline(Index, WXCoreFlexLine *, Index, const WXCoreLayoutNode *, bool);
  472. void measureChild(WXCoreLayoutNode* , float, float, float, bool, bool);
  473. void adjustChildSize(WXCoreLayoutNode *, float);
  474. void adjustChildSize(const WXCoreLayoutNode *child,
  475. const float currentMainSize,
  476. const float parentWidth,
  477. const float parentHeight,
  478. float &childWidth,
  479. float &childHeight) const;
  480. void stretchViewCrossSize();
  481. void stretchViewCrossSize(WXCoreLayoutNode *, float);
  482. Index expandItemsInFlexLine(WXCoreFlexLine *, float, Index);
  483. void checkSizeConstraints(WXCoreLayoutNode *, bool);
  484. void
  485. determineMainSize(float width, float height);
  486. void
  487. determineCrossSize(float, float, bool);
  488. void
  489. determineCrossSize(float, float, WXCoreFlexLine *);
  490. void setFrame(float, float, float, float);
  491. void setFrame(WXCorePosition*,float, float, float, float);
  492. /** ================================ layout =================================== **/
  493. void layout(float left, float top, float right, float bottom, bool, const std::pair<float,float>* = nullptr);
  494. void calcRelativeOffset(float &left, float &top, float &right, float &bottom) const ;
  495. void calcAbsoluteOffset(float &left, float &top, float &right, float &bottom, const std::pair<float,float>* = nullptr);
  496. void positionAbsoluteFlexItem(float &left, float &top, float &right, float &bottom);
  497. void layoutHorizontal(bool isRtl, float left, float top, float right, float bottom,
  498. WXCoreLayoutNode*, WXCoreFlexLine *const flexLine);
  499. void layoutFlexlineHorizontal(const float width,
  500. const WXCoreFlexLine *const flexLine,
  501. float &childLeft,
  502. float &childRight,
  503. float &spaceBetweenItem) const;
  504. void layoutSingleChildHorizontal(WXCoreLayoutNode *node, WXCoreFlexLine *flexLine,
  505. WXCoreFlexWrap flexWrap, WXCoreAlignItems alignItems,
  506. float, float, float, float, bool);
  507. void layoutSingleChildHorizontal(const bool isRtl,
  508. const bool,
  509. float childBottom, float childTop,
  510. WXCoreFlexLine *const flexLine,
  511. WXCoreLayoutNode *const child,
  512. float&, float&);
  513. void layoutVertical(bool isRtl, bool fromBottomToTop, float left, float top, float right, float bottom,
  514. WXCoreLayoutNode*, WXCoreFlexLine *const flexLine);
  515. void layoutFlexlineVertical(const float height,
  516. const WXCoreFlexLine *const flexLine,
  517. float &childTop,
  518. float &childBottom,
  519. float &spaceBetweenItem) const;
  520. void layoutSingleChildVertical(WXCoreLayoutNode *node, WXCoreFlexLine *flexLine,
  521. bool isRtl, WXCoreAlignItems alignItems,
  522. float, float, float, float, bool);
  523. void layoutSingleChildVertical(const bool isRtl, const bool fromBottomToTop,
  524. const bool absoluteFlexItem,
  525. const float childLeft, const float childRight,
  526. WXCoreFlexLine *const flexLine,
  527. WXCoreLayoutNode *const child,
  528. float& ,float&);
  529. void updateFlexLineForAbsoluteItem(WXCoreLayoutNode *const absoluteFlexItem, WXCoreFlexLine *const flexLine);
  530. void initFormatingContext(std::vector<WXCoreLayoutNode *> &BFCs);
  531. std::pair<bool,float> calculateBFCWidth(float, float);
  532. std::pair<bool,float> calculateBFCHeight(float, float);
  533. std::tuple<bool, float, float> calculateBFCDimension(const std::pair<float,float>&);
  534. virtual void OnLayoutBefore() {
  535. }
  536. virtual void OnLayoutAfter(float width, float height) {
  537. }
  538. public:
  539. virtual void onLayout(float left, float top, float right, float bottom, WXCoreLayoutNode* = nullptr, WXCoreFlexLine *const flexLine = nullptr);
  540. /** ================================ tree =================================== **/
  541. inline Index getChildCount(FormattingContext formattingContext) const {
  542. switch (formattingContext) {
  543. case kNonBFC:
  544. return NonBFCs.size();
  545. case kBFC:
  546. return BFCs.size();
  547. default:
  548. return mChildList.size();
  549. }
  550. }
  551. inline Index getChildCount() const {
  552. return mChildList.size();
  553. }
  554. inline std::vector<WXCoreLayoutNode *>::const_iterator ChildListIterBegin() {
  555. return mChildList.cbegin();
  556. }
  557. inline std::vector<WXCoreLayoutNode *>::const_iterator ChildListIterEnd() {
  558. return mChildList.cend();
  559. }
  560. inline bool hasChild(const WXCoreLayoutNode* const child){
  561. if(std::find(mChildList.begin(), mChildList.end(), child) != mChildList.end()){
  562. return true;
  563. }else{
  564. return false;
  565. }
  566. }
  567. inline void removeChild(const WXCoreLayoutNode* const child) {
  568. for (int index = 0; index < mChildList.size(); index++) {
  569. if (child == mChildList[index]) {
  570. mChildList.erase(mChildList.begin() + index);
  571. break;
  572. }
  573. }
  574. markDirty();
  575. }
  576. inline void addChildAt(WXCoreLayoutNode* const child, Index index) {
  577. mChildList.insert(mChildList.begin() + index, child);
  578. child->mParent = this;
  579. markDirty();
  580. }
  581. inline WXCoreLayoutNode *getChildAt(const FormattingContext formattingContext, const Index index) const {
  582. switch (formattingContext) {
  583. case kNonBFC:
  584. return NonBFCs[index];
  585. case kBFC:
  586. return BFCs[index];
  587. default:
  588. return mChildList[index];
  589. }
  590. }
  591. inline WXCoreLayoutNode *getChildAt(const Index index) const {
  592. return mChildList[index];
  593. }
  594. inline WXCoreLayoutNode *getParent() const {
  595. return mParent;
  596. }
  597. inline void setParent(WXCoreLayoutNode * const parent, WXCoreLayoutNode * const child) const {
  598. child->mParent = parent;
  599. }
  600. inline bool isBFC(WXCoreLayoutNode* const node) const {
  601. return node->mCssStyle->mPositionType == kAbsolute || node->mCssStyle->mPositionType == kFixed;
  602. }
  603. /** ================================ margin =================================== **/
  604. inline float getMarginTop() const {
  605. return mCssStyle->mMargin.getMargin(kMarginTop);
  606. }
  607. inline float getMarginBottom() const {
  608. return mCssStyle->mMargin.getMargin(kMarginBottom);
  609. }
  610. inline float getMarginLeft() const {
  611. return mCssStyle->mMargin.getMargin(kMarginLeft);
  612. }
  613. inline float getMarginRight() const {
  614. return mCssStyle->mMargin.getMargin(kMarginRight);
  615. }
  616. inline void setMargin(const WXCoreMarginEdge &edge, const float margin) {
  617. if (mCssStyle->mMargin.setMargin(edge, margin)) {
  618. markDirty();
  619. }
  620. }
  621. inline const WXCoreMargin &GetMargins() const {
  622. return mCssStyle->mMargin;
  623. }
  624. /** ================================ padding =================================== **/
  625. inline float getPaddingLeft() const {
  626. return mCssStyle->mPadding.getPadding(kPaddingLeft);
  627. }
  628. inline float getPaddingRight() const {
  629. return mCssStyle->mPadding.getPadding(kPaddingRight);
  630. }
  631. inline float getPaddingTop() const {
  632. return mCssStyle->mPadding.getPadding(kPaddingTop);
  633. }
  634. inline float getPaddingBottom() const {
  635. return mCssStyle->mPadding.getPadding(kPaddingBottom);
  636. }
  637. inline void setPadding(const WXCorePaddingEdge edge, const float padding) {
  638. if (mCssStyle->mPadding.setPadding(edge, padding)) {
  639. markDirty();
  640. }
  641. }
  642. inline const WXCorePadding &GetPaddings() const {
  643. return mCssStyle->mPadding;
  644. }
  645. /** ================================ border-width =================================== **/
  646. inline float getBorderWidthLeft() const {
  647. return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthLeft);
  648. }
  649. inline float getBorderWidthRight() const {
  650. return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthRight);
  651. }
  652. inline float getBorderWidthTop() const {
  653. return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthTop);
  654. }
  655. inline float getBorderWidthBottom() const {
  656. return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthBottom);
  657. }
  658. inline void setBorderWidth(const WXCoreBorderWidthEdge edge, const float borderWidth) {
  659. if (mCssStyle->mBorderWidth.setBorderWidth(edge, borderWidth)) {
  660. markDirty();
  661. }
  662. }
  663. inline const WXCoreBorderWidth &GetBorders() const {
  664. return mCssStyle->mBorderWidth;
  665. }
  666. /** ================================ position-type =================================== **/
  667. inline void setStylePositionType(const WXCorePositionType positionType) {
  668. if (mCssStyle->mPositionType != positionType) {
  669. mCssStyle->mPositionType = positionType;
  670. markDirty();
  671. }
  672. }
  673. inline WXCorePositionType getStylePositionType() const {
  674. return mCssStyle->mPositionType;
  675. }
  676. /** ================================ position =================================== **/
  677. inline float getStylePositionTop() const {
  678. return mCssStyle->mStylePosition.getPosition(kPositionEdgeTop);
  679. }
  680. inline float getStylePositionBottom() const {
  681. return mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom);
  682. }
  683. inline float getStylePositionLeft() const {
  684. return mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft);
  685. }
  686. inline float getStylePositionRight() const {
  687. return mCssStyle->mStylePosition.getPosition(kPositionEdgeRight);
  688. }
  689. inline void setStylePosition(const WXCorePositionEdge edge, const float positionRight) {
  690. if (mCssStyle->mStylePosition.setPosition(edge, positionRight))
  691. markDirty();
  692. }
  693. /** ================================ dimension =================================== **/
  694. inline void setStyleWidthLevel(const DimensionLevel level) const {
  695. if (mCssStyle->mStyleWidthLevel != level) {
  696. mCssStyle->mStyleWidthLevel = level;
  697. }
  698. }
  699. inline void setStyleHeightLevel(const DimensionLevel level) const {
  700. if (mCssStyle->mStyleHeightLevel != level) {
  701. mCssStyle->mStyleHeightLevel = level;
  702. }
  703. }
  704. inline DimensionLevel getStyleHeightLevel() const {
  705. return mCssStyle->mStyleHeightLevel;
  706. }
  707. inline DimensionLevel getStyleWidthLevel() const {
  708. return mCssStyle->mStyleWidthLevel;
  709. }
  710. inline void setStyleWidth(const float width, const bool updating) {
  711. if (mCssStyle->mStyleWidth != width) {
  712. mCssStyle->mStyleWidth = width;
  713. markDirty();
  714. if(updating) {
  715. markChildrenDirty(true);
  716. }
  717. }
  718. }
  719. inline void setStyleWidthToNAN() {
  720. if (!isnan(mCssStyle->mStyleWidth)) {
  721. mCssStyle->mStyleWidth = NAN;
  722. markDirty();
  723. markChildrenDirty(true);
  724. }
  725. }
  726. inline float getStyleWidth() const {
  727. return mCssStyle->mStyleWidth;
  728. }
  729. inline void setStyleHeight(const float height) {
  730. if (mCssStyle->mStyleHeight != height) {
  731. mCssStyle->mStyleHeight = height;
  732. markDirty();
  733. }
  734. }
  735. inline float getStyleHeight() const {
  736. return mCssStyle->mStyleHeight;
  737. }
  738. inline void setMinWidth(const float minWidth, const bool updating) {
  739. if (mCssStyle->mMinWidth != minWidth) {
  740. mCssStyle->mMinWidth = minWidth;
  741. markDirty();
  742. if(updating) {
  743. markChildrenDirty(true);
  744. }
  745. }
  746. }
  747. inline float getMinWidth() const {
  748. return mCssStyle->mMinWidth;
  749. }
  750. inline void setMaxWidth(const float maxWidth, const bool updating) {
  751. if (mCssStyle->mMaxWidth != maxWidth) {
  752. mCssStyle->mMaxWidth = maxWidth;
  753. markDirty();
  754. if(updating) {
  755. markChildrenDirty(true);
  756. }
  757. }
  758. }
  759. inline float getMaxWidth() const {
  760. return mCssStyle->mMaxWidth;
  761. }
  762. inline void setMinHeight(const float minHeight) {
  763. if (mCssStyle->mMinHeight != minHeight) {
  764. mCssStyle->mMinHeight = minHeight;
  765. markDirty();
  766. }
  767. }
  768. inline float getMinHeight() const {
  769. return mCssStyle->mMinHeight;
  770. }
  771. inline void setMaxHeight(const float maxHeight) {
  772. if (mCssStyle->mMaxHeight != maxHeight) {
  773. mCssStyle->mMaxHeight = maxHeight;
  774. markDirty();
  775. }
  776. }
  777. inline float getMaxHeight() const {
  778. return mCssStyle->mMaxHeight;
  779. }
  780. inline void setDirection(const WXCoreDirection direction, const bool updating) {
  781. if (nullptr == mCssStyle) return;
  782. if (mCssStyle->mDirection != direction) {
  783. mCssStyle->mDirection = direction;
  784. markDirty();
  785. if (updating) {
  786. for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) {
  787. (*it)->markInheritableDirty();
  788. }
  789. }
  790. }
  791. }
  792. inline WXCoreDirection getDirection() const {
  793. if (mCssStyle == nullptr) {
  794. return WEEXCORE_CSS_DEFAULT_DIRECTION;
  795. }
  796. return mCssStyle->mDirection;
  797. }
  798. /** ================================ CSS direction For RTL =================================== **/
  799. void determineChildLayoutDirection(const WXCoreDirection direction);
  800. WXCoreDirection getLayoutDirectionFromPathNode();
  801. /** ================================ flex-style =================================== **/
  802. inline void setFlexDirection(const WXCoreFlexDirection flexDirection, const bool updating) {
  803. if (mCssStyle->mFlexDirection != flexDirection) {
  804. mCssStyle->mFlexDirection = flexDirection;
  805. markDirty();
  806. if (updating) {
  807. for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) {
  808. (*it)->markDirty(false);
  809. }
  810. }
  811. }
  812. }
  813. inline WXCoreFlexDirection getFlexDirection() const {
  814. return mCssStyle->mFlexDirection;
  815. }
  816. inline void setFlexWrap(const WXCoreFlexWrap flexWrap) {
  817. if (mCssStyle->mFlexWrap != flexWrap) {
  818. mCssStyle->mFlexWrap = flexWrap;
  819. markDirty();
  820. }
  821. }
  822. inline WXCoreFlexWrap getFlexWrap() const {
  823. return mCssStyle->mFlexWrap;
  824. }
  825. inline void setJustifyContent(const WXCoreJustifyContent justifyContent) {
  826. if (mCssStyle->mJustifyContent != justifyContent) {
  827. mCssStyle->mJustifyContent = justifyContent;
  828. }
  829. }
  830. inline WXCoreJustifyContent getJustifyContent() const {
  831. return mCssStyle->mJustifyContent;
  832. }
  833. inline void setAlignItems(const WXCoreAlignItems alignItems) {
  834. if (mCssStyle->mAlignItems != alignItems) {
  835. mCssStyle->mAlignItems = alignItems;
  836. markDirty();
  837. }
  838. }
  839. inline WXCoreAlignItems getAlignItems() const {
  840. return mCssStyle->mAlignItems;
  841. }
  842. inline void setAlignSelf(const WXCoreAlignSelf alignSelf) {
  843. if (mCssStyle->mAlignSelf != alignSelf) {
  844. mCssStyle->mAlignSelf = alignSelf;
  845. markDirty();
  846. }
  847. }
  848. inline WXCoreAlignSelf getAlignSelf() const {
  849. return mCssStyle->mAlignSelf;
  850. }
  851. virtual void set_flex(const float flex) {
  852. if (mCssStyle->mFlexGrow != flex) {
  853. mCssStyle->mFlexGrow = flex;
  854. markDirty();
  855. }
  856. }
  857. inline float getFlex() const {
  858. return mCssStyle->mFlexGrow;
  859. }
  860. /** ================================ layout-result =================================== **/
  861. inline float getLayoutWidth() const {
  862. return mLayoutResult->mLayoutSize.width;
  863. }
  864. inline float getLayoutHeight() const {
  865. return mLayoutResult->mLayoutSize.height;
  866. }
  867. inline float getLayoutPositionTop() const {
  868. return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeTop);
  869. }
  870. inline float getLayoutPositionBottom() const {
  871. return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeBottom);
  872. }
  873. inline float getLayoutPositionLeft() const {
  874. return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeLeft);
  875. }
  876. inline float getLayoutPositionRight() const {
  877. return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeRight);
  878. }
  879. virtual inline WXCoreDirection getLayoutDirection() const {
  880. if (nullptr == mLayoutResult) {
  881. return WEEXCORE_CSS_DEFAULT_DIRECTION;
  882. }
  883. return mLayoutResult->mLayoutDirection;
  884. }
  885. inline void setLayoutDirection(WXCoreDirection direction) {
  886. if (nullptr == mLayoutResult) return;
  887. mLayoutResult->mLayoutDirection = direction;
  888. }
  889. inline bool hasNewLayout() const {
  890. return mHasNewLayout;
  891. }
  892. inline bool isDirty() const {
  893. return dirty;
  894. }
  895. inline void markDirty(const bool recursion = true) {
  896. if (!isDirty()) {
  897. dirty = true;
  898. if (getParent() != nullptr && recursion) {
  899. getParent()->markDirty();
  900. }
  901. }
  902. }
  903. void markAllDirty() {
  904. markDirty(false);
  905. for (WXCoreLayoutNode* c : mChildList) {
  906. c->markAllDirty();
  907. }
  908. }
  909. bool markChildrenDirty(const bool updatedNode = false) {
  910. bool ret = false;
  911. if(getChildCount() == 0){
  912. if(measureFunc!= nullptr){
  913. ret = true;
  914. }
  915. }
  916. else {
  917. //isnan(mCssStyle->mStyleWidth) XOR updatedNode
  918. if(isnan(mCssStyle->mStyleWidth) != updatedNode){
  919. for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) {
  920. ret = ((*it)->markChildrenDirty() || ret) ;
  921. }
  922. }
  923. }
  924. dirty = ret || dirty;
  925. return ret;
  926. }
  927. void markInheritableDirty() {
  928. if (resetInheritableSet()) {
  929. // if some style was inherited from parent, reset those styles
  930. // then mark self dirty
  931. markDirty(false);
  932. // traverse children to mark dirty
  933. if(getChildCount() == 0){
  934. return;
  935. }
  936. else {
  937. for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) {
  938. (*it)->markInheritableDirty();
  939. }
  940. }
  941. }
  942. }
  943. /**
  944. * if some style was inherited from parent, reset those styles, then return true, eles return false
  945. */
  946. bool resetInheritableSet() {
  947. if (mCssStyle == nullptr || mLayoutResult == nullptr) return false;
  948. bool hasInheritedStyle = false;
  949. if (mCssStyle->mDirection == kDirectionInherit) {
  950. mLayoutResult->mLayoutDirection = kDirectionInherit;
  951. hasInheritedStyle = true;
  952. }
  953. return hasInheritedStyle;
  954. }
  955. inline void setHasNewLayout(const bool hasNewLayout) {
  956. this->mHasNewLayout = hasNewLayout;
  957. }
  958. inline float getLargestMainSize() const {
  959. float largestSize = 0;
  960. for (WXCoreFlexLine *flexLine : mFlexLines) {
  961. largestSize = std::max(largestSize, flexLine->mMainSize);
  962. }
  963. return largestSize + sumPaddingBorderAlongAxis(this, isMainAxisHorizontal(this));
  964. }
  965. inline void rewriteLayoutResult(float left, float top, float width, float height) {
  966. if (mLayoutResult != nullptr) {
  967. mLayoutResult->mLayoutPosition.setPosition(kPositionEdgeLeft, left);
  968. mLayoutResult->mLayoutPosition.setPosition(kPositionEdgeTop, top);
  969. mLayoutResult->mLayoutPosition.setPosition(kPositionEdgeRight, left + width);
  970. mLayoutResult->mLayoutPosition.setPosition(kPositionEdgeBottom, top + height);
  971. mLayoutResult->mLayoutSize.width = width;
  972. mLayoutResult->mLayoutSize.height = height;
  973. }
  974. }
  975. };
  976. }
  977. #endif //WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H
  978. #endif