Files
linguist/samples/Reason/Layout.re
2016-12-22 17:03:18 -08:00

1326 lines
59 KiB
ReasonML

/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
/*
* From css-layout comments:
* The spec describes four different layout modes: "fill available", "max
* content", "min content", and "fit content". Of these, we don't use
* "min content" because we don't support default minimum main sizes (see
* above for details). Each of our measure modes maps to a layout mode
* from the spec (https://www.w3.org/TR/css3-sizing/#terms):
*
* -.CssMeasureModeUndefined: `max-content`
* -.CssMeasureModeExactly: `fill-available`
* -.CssMeasureModeAtMost: `fit-content`
* If infinite space available in that axis, then `max-content.`
* Else, `min(max-content size, max(min-content size, fill-available size))`
* (Although, we don't support min-content)
*/
open LayoutTypes;
open LayoutValue;
open LayoutSupport;
let gCurrentGenerationCount = ref 0;
let gDepth = ref 0;
let gPrintTree = {contents: false};
let gPrintChanges = {contents: false};
let gPrintSkips = {contents: false};
let measureString = "measure";
let stretchString = "stretch";
let absMeasureString = "abs-measure";
let absLayoutString = "abs-layout";
let initialString = "initial";
let flexString = "flex";
let spacer = " ";
let getSpacer level => {
let spacerLen = String.length spacer;
let lvl = level > spacerLen ? level : spacerLen;
String.sub spacer lvl (String.length spacer)
};
let getModeName (mode, isLayoutInsteadOfMeasure) =>
switch mode {
| CSS_MEASURE_MODE_NEGATIVE_ONE_WHATEVER_THAT_MEANS =>
isLayoutInsteadOfMeasure ?
"CSS_MEASURE_MODE_NEGATIVE_ONE_WHATEVER_THAT_MEANS" :
"CSS_MEASURE_MODE_NEGATIVE_ONE_WHATEVER_THAT_MEANS"
| CssMeasureModeUndefined => isLayoutInsteadOfMeasure ? "LAY_UNDEFINED" : "UNDEFINED"
| CssMeasureModeExactly => isLayoutInsteadOfMeasure ? "LAY_EXACTLY" : "EXACTLY"
| CssMeasureModeAtMost => isLayoutInsteadOfMeasure ? "LAY_AT_MOST" : "AT_MOST"
};
let canUseCachedMeasurement
(
availableWidth,
availableHeight,
marginRow,
marginColumn,
widthMeasureMode,
heightMeasureMode,
cachedLayout
) =>
if (
cachedLayout.availableWidth == availableWidth &&
cachedLayout.availableHeight == availableHeight &&
cachedLayout.widthMeasureMode == widthMeasureMode && cachedLayout.heightMeasureMode == heightMeasureMode
) {
true
} else if
/* Is it an exact match?*/
/* If the width is an exact match, try a fuzzy match on the height.*/
(
cachedLayout.widthMeasureMode == widthMeasureMode &&
cachedLayout.availableWidth == availableWidth &&
heightMeasureMode === CssMeasureModeExactly &&
availableHeight -. marginColumn == cachedLayout.computedHeight
) {
true
} else if
/* If the height is an exact match, try a fuzzy match on the width.*/
(
cachedLayout.heightMeasureMode == heightMeasureMode &&
cachedLayout.availableHeight == availableHeight &&
widthMeasureMode === CssMeasureModeExactly && availableWidth -. marginRow == cachedLayout.computedWidth
) {
true
} else {
false
};
let cachedMeasurementAt layout i =>
switch i {
| 0 => layout.cachedMeasurement1
| 1 => layout.cachedMeasurement2
| 2 => layout.cachedMeasurement3
| 3 => layout.cachedMeasurement4
| 4 => layout.cachedMeasurement5
| 5 => layout.cachedMeasurement6
| _ => raise (Invalid_argument ("No cached measurement at " ^ string_of_int i))
};
/**
* This is a wrapper around the layoutNodeImpl function. It determines
* whether the layout request is redundant and can be skipped.
*
* Parameters:
* Input parameters are the same as layoutNodeImpl (see above)
* Return parameter is true if layout was performed, false if skipped
*/
let rec layoutNodeInternal
node
availableWidth
availableHeight
parentDirection
widthMeasureMode
heightMeasureMode
performLayout
reason => {
let layout = node.layout;
gDepth.contents = gDepth.contents + 1;
let needToVisitNode =
node.isDirty node.context && layout.generationCount != gCurrentGenerationCount.contents ||
layout.lastParentDirection != parentDirection;
if needToVisitNode {
/* Invalidate the cached results.*/
layout.nextCachedMeasurementsIndex = 0;
layout.cachedLayout.widthMeasureMode = CSS_MEASURE_MODE_NEGATIVE_ONE_WHATEVER_THAT_MEANS;
layout.cachedLayout.heightMeasureMode = CSS_MEASURE_MODE_NEGATIVE_ONE_WHATEVER_THAT_MEANS
};
let cachedResults = ref None;
/* Determine whether the results are already cached. We maintain a separate*/
/* cache for layouts and measurements. A layout operation modifies the positions*/
/* and dimensions for nodes in the subtree. The algorithm assumes that each node*/
/* gets layed out a maximum of one time per tree layout, but multiple measurements*/
/* may be required to resolve all of the flex dimensions.*/
/* We handle nodes with measure functions specially here because they are the most
* expensive to measure, so it's worth avoiding redundant measurements if at all possible.*/
if (node.measure !== dummyMeasure && node.childrenCount === 0) {
let marginAxisRow = getMarginAxis node CssFlexDirectionRow;
let marginAxisColumn = getMarginAxis node CssFlexDirectionColumn;
/* First, try to use the layout cache.*/
if (
canUseCachedMeasurement (
availableWidth,
availableHeight,
marginAxisRow,
marginAxisColumn,
widthMeasureMode,
heightMeasureMode,
layout.cachedLayout
)
) {
cachedResults.contents = Some layout.cachedLayout
} else {
/* Try to use the measurement cache.*/
let foundCached = {contents: false};
for i in 0 to (layout.nextCachedMeasurementsIndex - 1) {
/* This is basically the "break" */
if (not foundCached.contents) {
let cachedMeasurementAtIndex = cachedMeasurementAt layout i;
if (
canUseCachedMeasurement (
availableWidth,
availableHeight,
marginAxisRow,
marginAxisColumn,
widthMeasureMode,
heightMeasureMode,
cachedMeasurementAtIndex
)
) {
cachedResults.contents = Some cachedMeasurementAtIndex;
foundCached.contents = true
}
}
}
}
} else if performLayout {
if (
layout.cachedLayout.availableWidth == availableWidth &&
layout.cachedLayout.availableHeight == availableHeight &&
layout.cachedLayout.widthMeasureMode == widthMeasureMode &&
layout.cachedLayout.heightMeasureMode == heightMeasureMode
) {
cachedResults.contents = Some layout.cachedLayout
}
} else {
let foundCached = {contents: false};
for i in 0 to (layout.nextCachedMeasurementsIndex - 1) {
/* This is basically the "break" */
if (not foundCached.contents) {
let cachedMeasurementAtIndex = cachedMeasurementAt layout i;
if (
cachedMeasurementAtIndex.availableWidth == availableWidth &&
cachedMeasurementAtIndex.availableHeight == availableHeight &&
cachedMeasurementAtIndex.widthMeasureMode == widthMeasureMode &&
cachedMeasurementAtIndex.heightMeasureMode == heightMeasureMode
) {
cachedResults.contents = Some cachedMeasurementAtIndex;
foundCached.contents = true
}
}
}
};
if (not needToVisitNode && cachedResults.contents != None) {
let cachedResults_ =
switch cachedResults.contents {
| None => raise (Invalid_argument "Not possible")
| Some cr => cr
};
layout.measuredWidth = cachedResults_.computedWidth;
layout.measuredHeight = cachedResults_.computedHeight;
if (gPrintChanges.contents && gPrintSkips.contents) {
Printf.printf "%s%d.{[skipped] " (getSpacer gDepth.contents) gDepth.contents;
switch node.print {
| None => ()
| Some printer => printer node.context
};
Printf.printf
"wm: %s, hm: %s, aw: %s ah: %s => d: (%s, %s) %s\n"
(getModeName (widthMeasureMode, performLayout))
(getModeName (heightMeasureMode, performLayout))
(scalarToString availableWidth)
(scalarToString availableHeight)
(scalarToString cachedResults_.computedWidth)
(scalarToString cachedResults_.computedHeight)
reason
}
} else {
if gPrintChanges.contents {
Printf.printf "%s%d.{%s" (getSpacer gDepth.contents) gDepth.contents (needToVisitNode ? "*" : "");
switch node.print {
| None => ()
| Some printer => printer node.context
};
Printf.printf
"wm: %s, hm: %s, aw: %s ah: %s %s\n"
(getModeName (widthMeasureMode, performLayout))
(getModeName (heightMeasureMode, performLayout))
(scalarToString availableWidth)
(scalarToString availableHeight)
reason
};
layoutNodeImpl (
node,
availableWidth,
availableHeight,
parentDirection,
widthMeasureMode,
heightMeasureMode,
performLayout
);
if gPrintChanges.contents {
Printf.printf "%s%d.}%s" (getSpacer gDepth.contents) gDepth.contents (needToVisitNode ? "*" : "");
switch node.print {
| None => ()
| Some printer => printer node.context
};
Printf.printf
"wm: %s, hm: %s, d: (%s, %s) %s\n"
(getModeName (widthMeasureMode, performLayout))
(getModeName (heightMeasureMode, performLayout))
(scalarToString layout.measuredWidth)
(scalarToString layout.measuredHeight)
reason
};
layout.lastParentDirection = parentDirection;
if (cachedResults.contents === None) {
if (layout.nextCachedMeasurementsIndex == css_max_cached_result_count) {
if gPrintChanges.contents {
Printf.printf "Out of cache entries!\n"
};
layout.nextCachedMeasurementsIndex = 0
};
let newCacheEntry =
performLayout ?
/* Use the single layout cache entry.*/
layout.cachedLayout :
{
/* Allocate a new measurement cache entry.*/
let newCacheEntry_ = cachedMeasurementAt layout layout.nextCachedMeasurementsIndex;
layout.nextCachedMeasurementsIndex = layout.nextCachedMeasurementsIndex + 1;
newCacheEntry_
};
newCacheEntry.availableWidth = availableWidth;
newCacheEntry.availableHeight = availableHeight;
newCacheEntry.widthMeasureMode = widthMeasureMode;
newCacheEntry.heightMeasureMode = heightMeasureMode;
newCacheEntry.computedWidth = layout.measuredWidth;
newCacheEntry.computedHeight = layout.measuredHeight
}
};
if performLayout {
node.layout.width = node.layout.measuredWidth;
node.layout.height = node.layout.measuredHeight;
layout.hasNewLayout = true
};
gDepth.contents = gDepth.contents - 1;
layout.generationCount = gCurrentGenerationCount.contents;
needToVisitNode || cachedResults.contents === None
}
and computeChildFlexBasis node child width widthMode height heightMode direction => {
let mainAxis = resolveAxis node.style.flexDirection direction;
let isMainAxisRow = isRowDirection mainAxis;
let childWidth = {contents: zero};
let childHeight = {contents: zero};
let childWidthMeasureMode = {contents: CssMeasureModeUndefined};
let childHeightMeasureMode = {contents: CssMeasureModeUndefined};
if (isMainAxisRow && isStyleDimDefined child.contents CssFlexDirectionRow) {
child.contents.layout.computedFlexBasis =
fmaxf child.contents.style.width (getPaddingAndBorderAxis child.contents CssFlexDirectionRow)
} else if (
not isMainAxisRow && isStyleDimDefined child.contents CssFlexDirectionColumn
) {
child.contents.layout.computedFlexBasis =
fmaxf child.contents.style.height (getPaddingAndBorderAxis child.contents CssFlexDirectionColumn)
} else if (
not (isUndefined child.contents.style.flexBasis)
) {
if (isUndefined child.contents.layout.computedFlexBasis) {
child.contents.layout.computedFlexBasis =
fmaxf child.contents.style.flexBasis (getPaddingAndBorderAxis child.contents mainAxis)
}
} else {
childWidth.contents = cssUndefined;
childHeight.contents = cssUndefined;
childWidthMeasureMode.contents = CssMeasureModeUndefined;
childHeightMeasureMode.contents = CssMeasureModeUndefined;
if (isStyleDimDefined child.contents CssFlexDirectionRow) {
childWidth.contents = child.contents.style.width +. getMarginAxis child.contents CssFlexDirectionRow;
childWidthMeasureMode.contents = CssMeasureModeExactly
};
/**
* Why can't this just be inlined to .height !== cssUndefined.
*/
if (isStyleDimDefined child.contents CssFlexDirectionColumn) {
childHeight.contents =
child.contents.style.height +. getMarginAxis child.contents CssFlexDirectionColumn;
childHeightMeasureMode.contents = CssMeasureModeExactly
};
if (not isMainAxisRow && node.style.overflow === Scroll || node.style.overflow !== Scroll) {
if (isUndefined childWidth.contents && not (isUndefined width)) {
childWidth.contents = width;
childWidthMeasureMode.contents = CssMeasureModeAtMost
}
};
if (isMainAxisRow && node.style.overflow === Scroll || node.style.overflow !== Scroll) {
if (isUndefined childHeight.contents && not (isUndefined height)) {
childHeight.contents = height;
childHeightMeasureMode.contents = CssMeasureModeAtMost
}
};
/*
* If child has no defined size in the cross axis and is set to
* stretch, set the cross axis to be measured exactly with the
* available inner width.
*/
if (
not isMainAxisRow &&
not (isUndefined width) &&
not (isStyleDimDefined child.contents CssFlexDirectionRow) &&
widthMode === CssMeasureModeExactly && getAlignItem node child.contents === CssAlignStretch
) {
childWidth.contents = width;
childWidthMeasureMode.contents = CssMeasureModeExactly
};
if (
isMainAxisRow &&
not (isUndefined height) &&
not (isStyleDimDefined child.contents CssFlexDirectionColumn) &&
heightMode === CssMeasureModeExactly && getAlignItem node child.contents === CssAlignStretch
) {
childHeight.contents = height;
childHeightMeasureMode.contents = CssMeasureModeExactly
};
let _ =
layoutNodeInternal
child.contents
childWidth.contents
childHeight.contents
direction
childWidthMeasureMode.contents
childHeightMeasureMode.contents
false
measureString;
child.contents.layout.computedFlexBasis =
fmaxf
(isMainAxisRow ? child.contents.layout.measuredWidth : child.contents.layout.measuredHeight)
(getPaddingAndBorderAxis child.contents mainAxis)
}
}
/**
* By default, mathematical operations are floating point.
*/
and layoutNodeImpl
(
node,
availableWidth,
availableHeight,
parentDirection,
widthMeasureMode,
heightMeasureMode,
performLayout
) => {
/** START_GENERATED **/
/* re_assert */
/* (isUndefined availableWidth ? widthMeasureMode === CssMeasureModeUndefined : true) */
/* "availableWidth is indefinite so widthMeasureMode must be CssMeasureModeUndefined"; */
/* re_assert */
/* (isUndefined availableHeight ? heightMeasureMode === CssMeasureModeUndefined : true) */
/* "availableHeight is indefinite so heightMeasureMode must be CssMeasureModeUndefined"; */
let paddingAndBorderAxisRow = getPaddingAndBorderAxis node CssFlexDirectionRow;
let paddingAndBorderAxisColumn = getPaddingAndBorderAxis node CssFlexDirectionColumn;
let marginAxisRow = getMarginAxis node CssFlexDirectionRow;
let marginAxisColumn = getMarginAxis node CssFlexDirectionColumn;
let direction = resolveDirection node parentDirection;
node.layout.direction = direction;
/* For content (text) nodes, determine the dimensions based on the text
contents. */
if (node.measure !== dummyMeasure && node.childrenCount === 0) {
let innerWidth = availableWidth -. marginAxisRow -. paddingAndBorderAxisRow;
let innerHeight = availableHeight -. marginAxisColumn -. paddingAndBorderAxisColumn;
if (widthMeasureMode === CssMeasureModeExactly && heightMeasureMode === CssMeasureModeExactly) {
node.layout.measuredWidth = boundAxis node CssFlexDirectionRow (availableWidth -. marginAxisRow);
node.layout.measuredHeight =
boundAxis node CssFlexDirectionColumn (availableHeight -. marginAxisColumn)
} else if (
not (isUndefined innerWidth) && innerWidth <= zero ||
not (isUndefined innerHeight) && innerHeight <= zero
) {
node.layout.measuredWidth = boundAxis node CssFlexDirectionRow zero;
node.layout.measuredHeight = boundAxis node CssFlexDirectionColumn zero
} else {
let measureDim = node.measure node innerWidth widthMeasureMode innerHeight heightMeasureMode;
node.layout.measuredWidth =
boundAxis
node
CssFlexDirectionRow
(
widthMeasureMode === CssMeasureModeUndefined || widthMeasureMode === CssMeasureModeAtMost ?
measureDim.width +. paddingAndBorderAxisRow : availableWidth -. marginAxisRow
);
node.layout.measuredHeight =
boundAxis
node
CssFlexDirectionColumn
(
heightMeasureMode === CssMeasureModeUndefined || heightMeasureMode === CssMeasureModeAtMost ?
measureDim.height +. paddingAndBorderAxisColumn : availableHeight -. marginAxisColumn
)
}
} else {
let childCount = Array.length node.children;
if (childCount === 0) {
node.layout.measuredWidth =
boundAxis
node
CssFlexDirectionRow
(
widthMeasureMode === CssMeasureModeUndefined || widthMeasureMode === CssMeasureModeAtMost ?
paddingAndBorderAxisRow : availableWidth -. marginAxisRow
);
node.layout.measuredHeight =
boundAxis
node
CssFlexDirectionColumn
(
heightMeasureMode === CssMeasureModeUndefined || heightMeasureMode === CssMeasureModeAtMost ?
paddingAndBorderAxisColumn : availableHeight -. marginAxisColumn
)
} else {
let shouldContinue = {contents: true};
if (not performLayout) {
if (
(
(
widthMeasureMode === CssMeasureModeAtMost &&
not (isUndefined availableWidth) && availableWidth <= zero
) &&
heightMeasureMode === CssMeasureModeAtMost
) &&
not (isUndefined availableHeight) && availableHeight <= zero
) {
node.layout.measuredWidth = boundAxis node CssFlexDirectionRow zero;
node.layout.measuredHeight = boundAxis node CssFlexDirectionColumn zero;
shouldContinue.contents = false
} else if (
widthMeasureMode === CssMeasureModeAtMost &&
not (isUndefined availableWidth) && availableWidth <= zero
) {
node.layout.measuredWidth = boundAxis node CssFlexDirectionRow zero;
node.layout.measuredHeight =
boundAxis
node
CssFlexDirectionColumn
(isUndefined availableHeight ? zero : availableHeight -. marginAxisColumn);
shouldContinue.contents = false
} else if (
heightMeasureMode === CssMeasureModeAtMost &&
not (isUndefined availableHeight) && availableHeight <= zero
) {
node.layout.measuredWidth =
boundAxis
node CssFlexDirectionRow (isUndefined availableWidth ? zero : availableWidth -. marginAxisRow);
node.layout.measuredHeight = boundAxis node CssFlexDirectionColumn zero;
shouldContinue.contents = false
} else if (
widthMeasureMode === CssMeasureModeExactly && heightMeasureMode === CssMeasureModeExactly
) {
node.layout.measuredWidth = boundAxis node CssFlexDirectionRow (availableWidth -. marginAxisRow);
node.layout.measuredHeight =
boundAxis node CssFlexDirectionColumn (availableHeight -. marginAxisColumn);
shouldContinue.contents = false
}
};
if shouldContinue.contents {
let mainAxis = resolveAxis node.style.flexDirection direction;
let crossAxis = getCrossFlexDirection mainAxis direction;
let isMainAxisRow = isRowDirection mainAxis;
let justifyContent = node.style.justifyContent;
let isNodeFlexWrap = node.style.flexWrap === CssWrap;
let firstAbsoluteChild = {contents: theNullNode};
let currentAbsoluteChild = {contents: theNullNode};
let leadingPaddingAndBorderMain = getLeadingPaddingAndBorder node mainAxis;
let trailingPaddingAndBorderMain = getTrailingPaddingAndBorder node mainAxis;
let leadingPaddingAndBorderCross = getLeadingPaddingAndBorder node crossAxis;
let paddingAndBorderAxisMain = getPaddingAndBorderAxis node mainAxis;
let paddingAndBorderAxisCross = getPaddingAndBorderAxis node crossAxis;
let measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
let measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
let availableInnerWidth = availableWidth -. marginAxisRow -. paddingAndBorderAxisRow;
let availableInnerHeight = availableHeight -. marginAxisColumn -. paddingAndBorderAxisColumn;
let availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight;
let availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;
let child = {contents: theNullNode};
/* let i = 0; */
/* STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM */
for i in 0 to (childCount - 1) {
child.contents = node.children.(i);
if performLayout {
let childDirection = resolveDirection child.contents direction;
setPosition child.contents childDirection
};
if (child.contents.style.positionType === CssPositionAbsolute) {
if (firstAbsoluteChild.contents === theNullNode) {
firstAbsoluteChild.contents = child.contents
};
if (currentAbsoluteChild.contents !== theNullNode) {
currentAbsoluteChild.contents.nextChild = child.contents
};
currentAbsoluteChild.contents = child.contents;
child.contents.nextChild = theNullNode
} else {
computeChildFlexBasis
node
child
availableInnerWidth
widthMeasureMode
availableInnerHeight
heightMeasureMode
direction
}
};
/* STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES */
let startOfLineIndex = {contents: 0};
let endOfLineIndex = {contents: 0};
let lineCount = {contents: 0};
let totalLineCrossDim = {contents: zero};
let maxLineMainDim = {contents: zero};
while (endOfLineIndex.contents < childCount) {
let itemsOnLine = {contents: 0};
let sizeConsumedOnCurrentLine = {contents: zero};
let totalFlexGrowFactors = {contents: zero};
let totalFlexShrinkScaledFactors = {contents: zero};
let curIndex = {contents: startOfLineIndex.contents};
let firstRelativeChild = {contents: theNullNode};
let currentRelativeChild = {contents: theNullNode};
let shouldContinue = {contents: true};
while (curIndex.contents < childCount && shouldContinue.contents) {
child.contents = node.children.(curIndex.contents);
child.contents.lineIndex = lineCount.contents;
if (child.contents.style.positionType !== CssPositionAbsolute) {
let outerFlexBasis =
child.contents.layout.computedFlexBasis +. getMarginAxis child.contents mainAxis;
if (
(
sizeConsumedOnCurrentLine.contents +. outerFlexBasis > availableInnerMainDim && isNodeFlexWrap
) &&
itemsOnLine.contents > 0
) {
shouldContinue.contents = false
} else {
sizeConsumedOnCurrentLine.contents = sizeConsumedOnCurrentLine.contents +. outerFlexBasis;
itemsOnLine.contents = itemsOnLine.contents + 1;
if (isFlex child.contents) {
totalFlexGrowFactors.contents =
totalFlexGrowFactors.contents +. child.contents.style.flexGrow;
totalFlexShrinkScaledFactors.contents =
totalFlexShrinkScaledFactors.contents +.
-. child.contents.style.flexShrink *. child.contents.layout.computedFlexBasis
};
if (firstRelativeChild.contents === theNullNode) {
firstRelativeChild.contents = child.contents
};
if (currentRelativeChild.contents !== theNullNode) {
currentRelativeChild.contents.nextChild = child.contents
};
currentRelativeChild.contents = child.contents;
child.contents.nextChild = theNullNode;
curIndex.contents = curIndex.contents + 1;
endOfLineIndex.contents = endOfLineIndex.contents + 1
}
} else {
curIndex.contents = curIndex.contents + 1;
endOfLineIndex.contents = endOfLineIndex.contents + 1
}
};
let canSkipFlex = not performLayout && measureModeCrossDim === CssMeasureModeExactly;
let leadingMainDim = {contents: zero};
let betweenMainDim = {contents: zero};
let remainingFreeSpace = {contents: zero};
if (not (isUndefined availableInnerMainDim)) {
remainingFreeSpace.contents = availableInnerMainDim -. sizeConsumedOnCurrentLine.contents
} else if (
sizeConsumedOnCurrentLine.contents < zero
) {
remainingFreeSpace.contents = -. sizeConsumedOnCurrentLine.contents
};
let originalRemainingFreeSpace = remainingFreeSpace.contents;
let deltaFreeSpace = {contents: zero};
if (not canSkipFlex) {
let childFlexBasis = {contents: zero};
let flexShrinkScaledFactor = {contents: zero};
let flexGrowFactor = {contents: zero};
let baseMainSize = {contents: zero};
let boundMainSize = {contents: zero};
let deltaFlexShrinkScaledFactors = {contents: zero};
let deltaFlexGrowFactors = {contents: zero};
currentRelativeChild.contents = firstRelativeChild.contents;
while (currentRelativeChild.contents !== theNullNode) {
childFlexBasis.contents = currentRelativeChild.contents.layout.computedFlexBasis;
if (remainingFreeSpace.contents < zero) {
flexShrinkScaledFactor.contents =
-. currentRelativeChild.contents.style.flexShrink *. childFlexBasis.contents;
if (flexShrinkScaledFactor.contents != zero) {
baseMainSize.contents =
childFlexBasis.contents +.
/*
* Important to first scale, then divide - to support fixed
* point encoding.
*/
flexShrinkScaledFactor.contents *. remainingFreeSpace.contents /.
totalFlexShrinkScaledFactors.contents;
boundMainSize.contents =
boundAxis currentRelativeChild.contents mainAxis baseMainSize.contents;
if (baseMainSize.contents != boundMainSize.contents) {
deltaFreeSpace.contents =
deltaFreeSpace.contents -. (boundMainSize.contents -. childFlexBasis.contents);
deltaFlexShrinkScaledFactors.contents =
deltaFlexShrinkScaledFactors.contents -. flexShrinkScaledFactor.contents
}
}
} else if (
remainingFreeSpace.contents > zero
) {
flexGrowFactor.contents = currentRelativeChild.contents.style.flexGrow;
if (flexGrowFactor.contents != zero) {
baseMainSize.contents =
childFlexBasis.contents +.
/*
* Important to first scale, then divide - to support fixed
* point encoding.
*/
flexGrowFactor.contents *. remainingFreeSpace.contents /. totalFlexGrowFactors.contents;
boundMainSize.contents =
boundAxis currentRelativeChild.contents mainAxis baseMainSize.contents;
if (baseMainSize.contents != boundMainSize.contents) {
deltaFreeSpace.contents =
deltaFreeSpace.contents -. (boundMainSize.contents -. childFlexBasis.contents);
deltaFlexGrowFactors.contents = deltaFlexGrowFactors.contents -. flexGrowFactor.contents
}
}
};
currentRelativeChild.contents = currentRelativeChild.contents.nextChild
};
totalFlexShrinkScaledFactors.contents =
totalFlexShrinkScaledFactors.contents +. deltaFlexShrinkScaledFactors.contents;
totalFlexGrowFactors.contents = totalFlexGrowFactors.contents +. deltaFlexGrowFactors.contents;
remainingFreeSpace.contents = remainingFreeSpace.contents +. deltaFreeSpace.contents;
deltaFreeSpace.contents = zero;
currentRelativeChild.contents = firstRelativeChild.contents;
while (currentRelativeChild.contents !== theNullNode) {
childFlexBasis.contents = currentRelativeChild.contents.layout.computedFlexBasis;
let updatedMainSize = {contents: childFlexBasis.contents};
if (remainingFreeSpace.contents < zero) {
flexShrinkScaledFactor.contents =
-. currentRelativeChild.contents.style.flexShrink *. childFlexBasis.contents;
if (flexShrinkScaledFactor.contents != zero) {
updatedMainSize.contents =
boundAxis
currentRelativeChild.contents
mainAxis
(
childFlexBasis.contents +.
/*
* Important to first scale, then divide - to support
* fixed point encoding.
*/
flexShrinkScaledFactor.contents *. remainingFreeSpace.contents /.
totalFlexShrinkScaledFactors.contents
)
}
} else if (
remainingFreeSpace.contents > zero
) {
flexGrowFactor.contents = currentRelativeChild.contents.style.flexGrow;
if (flexGrowFactor.contents != zero) {
updatedMainSize.contents =
boundAxis
currentRelativeChild.contents
mainAxis
(
childFlexBasis.contents +.
/*
* Important to first scale, then divide - to support
* fixed point encoding.
*/
flexGrowFactor.contents *. remainingFreeSpace.contents /.
totalFlexGrowFactors.contents
)
}
};
deltaFreeSpace.contents =
deltaFreeSpace.contents -. (updatedMainSize.contents -. childFlexBasis.contents);
let childWidth = {contents: zero};
let childHeight = {contents: zero};
let childWidthMeasureMode = {contents: CssMeasureModeUndefined};
let childHeightMeasureMode = {contents: CssMeasureModeUndefined};
if isMainAxisRow {
childWidth.contents =
updatedMainSize.contents +.
getMarginAxis currentRelativeChild.contents CssFlexDirectionRow;
childWidthMeasureMode.contents = CssMeasureModeExactly;
if (
not (isUndefined availableInnerCrossDim) &&
not (isStyleDimDefined currentRelativeChild.contents CssFlexDirectionColumn) &&
heightMeasureMode === CssMeasureModeExactly &&
getAlignItem node currentRelativeChild.contents === CssAlignStretch
) {
childHeight.contents = availableInnerCrossDim;
childHeightMeasureMode.contents = CssMeasureModeExactly
} else if (
not (isStyleDimDefined currentRelativeChild.contents CssFlexDirectionColumn)
) {
childHeight.contents = availableInnerCrossDim;
childHeightMeasureMode.contents =
isUndefined childHeight.contents ? CssMeasureModeUndefined : CssMeasureModeAtMost
} else {
childHeight.contents =
currentRelativeChild.contents.style.height +.
getMarginAxis currentRelativeChild.contents CssFlexDirectionColumn;
childHeightMeasureMode.contents = CssMeasureModeExactly
}
} else {
childHeight.contents =
updatedMainSize.contents +.
getMarginAxis currentRelativeChild.contents CssFlexDirectionColumn;
childHeightMeasureMode.contents = CssMeasureModeExactly;
if (
not (isUndefined availableInnerCrossDim) &&
not (isStyleDimDefined currentRelativeChild.contents CssFlexDirectionRow) &&
widthMeasureMode === CssMeasureModeExactly &&
getAlignItem node currentRelativeChild.contents === CssAlignStretch
) {
childWidth.contents = availableInnerCrossDim;
childWidthMeasureMode.contents = CssMeasureModeExactly
} else if (
not (isStyleDimDefined currentRelativeChild.contents CssFlexDirectionRow)
) {
childWidth.contents = availableInnerCrossDim;
childWidthMeasureMode.contents =
isUndefined childWidth.contents ? CssMeasureModeUndefined : CssMeasureModeAtMost
} else {
childWidth.contents =
currentRelativeChild.contents.style.width +.
getMarginAxis currentRelativeChild.contents CssFlexDirectionRow;
childWidthMeasureMode.contents = CssMeasureModeExactly
}
};
let requiresStretchLayout =
not (isStyleDimDefined currentRelativeChild.contents crossAxis) &&
getAlignItem node currentRelativeChild.contents === CssAlignStretch;
let _ =
layoutNodeInternal
currentRelativeChild.contents
childWidth.contents
childHeight.contents
direction
childWidthMeasureMode.contents
childHeightMeasureMode.contents
(performLayout && not requiresStretchLayout)
flexString;
currentRelativeChild.contents = currentRelativeChild.contents.nextChild
}
};
remainingFreeSpace.contents = originalRemainingFreeSpace +. deltaFreeSpace.contents;
/* If we are using "at most" rules in the main axis. Calculate the remaining space when
constraint by the min size defined for the main axis. */
if (measureModeMainDim === CssMeasureModeAtMost) {
let minDim = styleMinDimensionForAxis node mainAxis;
if (not (isUndefined minDim) && minDim >= 0) {
remainingFreeSpace.contents =
fmaxf 0 (minDim - (availableInnerMainDim -. remainingFreeSpace.contents))
} else {
remainingFreeSpace.contents = zero
}
};
switch justifyContent {
| CssJustifyCenter => leadingMainDim.contents = divideScalarByInt remainingFreeSpace.contents 2
| CssJustifyFlexEnd => leadingMainDim.contents = remainingFreeSpace.contents
| CssJustifySpaceBetween =>
if (itemsOnLine.contents > 1) {
betweenMainDim.contents =
divideScalarByInt (fmaxf remainingFreeSpace.contents zero) (itemsOnLine.contents - 1)
} else {
betweenMainDim.contents = zero
}
| CssJustifySpaceAround =>
betweenMainDim.contents = divideScalarByInt remainingFreeSpace.contents itemsOnLine.contents;
leadingMainDim.contents = divideScalarByInt betweenMainDim.contents 2
| CssJustifyFlexStart => ()
};
let mainDim = {contents: leadingPaddingAndBorderMain +. leadingMainDim.contents};
let crossDim = {contents: zero};
for i in startOfLineIndex.contents to (endOfLineIndex.contents - 1) {
child.contents = node.children.(i);
if (
child.contents.style.positionType === CssPositionAbsolute &&
isLeadingPosDefinedWithFallback child.contents mainAxis
) {
if performLayout {
setLayoutLeadingPositionForAxis
child.contents
mainAxis
(
getLeadingPositionWithFallback child.contents mainAxis +. getLeadingBorder node mainAxis +.
getLeadingMargin child.contents mainAxis
)
}
} else {
if performLayout {
setLayoutLeadingPositionForAxis
child.contents
mainAxis
(layoutPosPositionForAxis child.contents mainAxis +. mainDim.contents)
};
if (child.contents.style.positionType === CssPositionRelative) {
if canSkipFlex {
mainDim.contents =
mainDim.contents +. betweenMainDim.contents +. getMarginAxis child.contents mainAxis +.
child.contents.layout.computedFlexBasis;
crossDim.contents = availableInnerCrossDim
} else {
mainDim.contents =
mainDim.contents +. betweenMainDim.contents +. getDimWithMargin child.contents mainAxis;
crossDim.contents = fmaxf crossDim.contents (getDimWithMargin child.contents crossAxis)
}
}
}
};
mainDim.contents = mainDim.contents +. trailingPaddingAndBorderMain;
let containerCrossAxis = {contents: availableInnerCrossDim};
if (
measureModeCrossDim === CssMeasureModeUndefined || measureModeCrossDim === CssMeasureModeAtMost
) {
containerCrossAxis.contents =
boundAxis node crossAxis (crossDim.contents +. paddingAndBorderAxisCross) -. paddingAndBorderAxisCross;
if (measureModeCrossDim === CssMeasureModeAtMost) {
containerCrossAxis.contents = fminf containerCrossAxis.contents availableInnerCrossDim
}
};
if (not isNodeFlexWrap && measureModeCrossDim === CssMeasureModeExactly) {
crossDim.contents = availableInnerCrossDim
};
crossDim.contents =
boundAxis node crossAxis (crossDim.contents +. paddingAndBorderAxisCross) -. paddingAndBorderAxisCross;
/*
* STEP 7: CROSS-AXIS ALIGNMENT We can skip child alignment if we're
* just measuring the container.
*/
if performLayout {
for i in startOfLineIndex.contents to (endOfLineIndex.contents - 1) {
child.contents = node.children.(i);
if (child.contents.style.positionType === CssPositionAbsolute) {
if (isLeadingPosDefinedWithFallback child.contents crossAxis) {
setLayoutLeadingPositionForAxis
child.contents
crossAxis
(
getLeadingPositionWithFallback child.contents crossAxis +.
getLeadingBorder node crossAxis +.
getLeadingMargin child.contents crossAxis
)
} else {
setLayoutLeadingPositionForAxis
child.contents
crossAxis
(leadingPaddingAndBorderCross +. getLeadingMargin child.contents crossAxis)
}
} else {
let leadingCrossDim = {contents: leadingPaddingAndBorderCross};
let alignItem = getAlignItem node child.contents;
if (alignItem === CssAlignStretch) {
let childWidth = {contents: zero};
let childHeight = {contents: zero};
let childWidthMeasureMode = {contents: CssMeasureModeUndefined};
let childHeightMeasureMode = {contents: CssMeasureModeUndefined};
childWidth.contents =
child.contents.layout.measuredWidth +. getMarginAxis child.contents CssFlexDirectionRow;
childHeight.contents =
child.contents.layout.measuredHeight +.
getMarginAxis child.contents CssFlexDirectionColumn;
let isCrossSizeDefinite = {contents: false};
if isMainAxisRow {
isCrossSizeDefinite.contents = isStyleDimDefined child.contents CssFlexDirectionColumn;
childHeight.contents = crossDim.contents
} else {
isCrossSizeDefinite.contents = isStyleDimDefined child.contents CssFlexDirectionRow;
childWidth.contents = crossDim.contents
};
if (not isCrossSizeDefinite.contents) {
childWidthMeasureMode.contents =
isUndefined childWidth.contents ? CssMeasureModeUndefined : CssMeasureModeExactly;
childHeightMeasureMode.contents =
isUndefined childHeight.contents ? CssMeasureModeUndefined : CssMeasureModeExactly;
let _ =
layoutNodeInternal
child.contents
childWidth.contents
childHeight.contents
direction
childWidthMeasureMode.contents
childHeightMeasureMode.contents
true
stretchString;
()
}
} else if (
alignItem !== CssAlignFlexStart
) {
let remainingCrossDim =
containerCrossAxis.contents -. getDimWithMargin child.contents crossAxis;
if (alignItem === CssAlignCenter) {
leadingCrossDim.contents =
leadingCrossDim.contents +. divideScalarByInt remainingCrossDim 2
} else {
leadingCrossDim.contents = leadingCrossDim.contents +. remainingCrossDim
}
};
setLayoutLeadingPositionForAxis
child.contents
crossAxis
(
layoutPosPositionForAxis child.contents crossAxis +. totalLineCrossDim.contents +.
leadingCrossDim.contents
)
}
}
};
totalLineCrossDim.contents = totalLineCrossDim.contents +. crossDim.contents;
maxLineMainDim.contents = fmaxf maxLineMainDim.contents mainDim.contents;
lineCount.contents = lineCount.contents + 1;
startOfLineIndex.contents = endOfLineIndex.contents
};
if (lineCount.contents > 1 && performLayout && not (isUndefined availableInnerCrossDim)) {
let remainingAlignContentDim = availableInnerCrossDim -. totalLineCrossDim.contents;
let crossDimLead = {contents: zero};
let currentLead = {contents: leadingPaddingAndBorderCross};
let alignContent = node.style.alignContent;
if (alignContent === CssAlignFlexEnd) {
currentLead.contents = currentLead.contents +. remainingAlignContentDim
} else if (
alignContent === CssAlignCenter
) {
currentLead.contents = currentLead.contents +. divideScalarByInt remainingAlignContentDim 2
} else if (
alignContent === CssAlignStretch
) {
if (availableInnerCrossDim > totalLineCrossDim.contents) {
crossDimLead.contents = divideScalarByInt remainingAlignContentDim lineCount.contents
}
};
let endIndex = {contents: 0};
for i in 0 to (lineCount.contents - 1) {
let startIndex = endIndex.contents;
let j = {contents: startIndex};
let lineHeight = {contents: zero};
let shouldContinue = {contents: false};
while (j.contents < childCount && shouldContinue.contents) {
child.contents = node.children.(j.contents);
if (child.contents.style.positionType === CssPositionRelative) {
if (child.contents.lineIndex !== i) {
shouldContinue.contents = false
} else if (
isLayoutDimDefined child.contents crossAxis
) {
lineHeight.contents =
fmaxf
lineHeight.contents
(
layoutMeasuredDimensionForAxis child.contents crossAxis +.
getMarginAxis child.contents crossAxis
)
}
};
j.contents = j.contents + 1
};
endIndex.contents = j.contents;
lineHeight.contents = lineHeight.contents +. crossDimLead.contents;
if performLayout {
for j in startIndex to (endIndex.contents - 1) {
child.contents = node.children.(j);
if (child.contents.style.positionType === CssPositionRelative) {
switch (getAlignItem node child.contents) {
| CssAlignFlexStart =>
setLayoutLeadingPositionForAxis
child.contents
crossAxis
(currentLead.contents +. getLeadingMargin child.contents crossAxis)
| CssAlignFlexEnd =>
setLayoutLeadingPositionForAxis
child.contents
crossAxis
(
currentLead.contents +. lineHeight.contents -.
getTrailingMargin child.contents crossAxis -.
layoutMeasuredDimensionForAxis child.contents crossAxis
)
| CssAlignCenter =>
let childHeight = layoutMeasuredDimensionForAxis child.contents crossAxis;
setLayoutLeadingPositionForAxis
child.contents
crossAxis
(currentLead.contents +. divideScalarByInt (lineHeight.contents -. childHeight) 2)
| CssAlignStretch =>
setLayoutLeadingPositionForAxis
child.contents
crossAxis
(currentLead.contents +. getLeadingMargin child.contents crossAxis)
| CssAlignAuto => raise (Invalid_argument "getAlignItem should never return auto")
}
}
}
};
currentLead.contents = currentLead.contents +. lineHeight.contents
}
};
/* STEP 9: COMPUTING FINAL DIMENSIONS */
node.layout.measuredWidth = boundAxis node CssFlexDirectionRow (availableWidth -. marginAxisRow);
node.layout.measuredHeight =
boundAxis node CssFlexDirectionColumn (availableHeight -. marginAxisColumn);
/* If the user didn't specify a width or height for the node, set the
* dimensions based on the children. */
if (measureModeMainDim === CssMeasureModeUndefined) {
setLayoutMeasuredDimensionForAxis node mainAxis (boundAxis node mainAxis maxLineMainDim.contents)
} else if (
measureModeMainDim === CssMeasureModeAtMost
) {
setLayoutMeasuredDimensionForAxis
node
mainAxis
(
fmaxf
(
fminf
(availableInnerMainDim +. paddingAndBorderAxisMain)
(boundAxisWithinMinAndMax node mainAxis maxLineMainDim.contents)
)
paddingAndBorderAxisMain
)
};
if (measureModeCrossDim === CssMeasureModeUndefined) {
setLayoutMeasuredDimensionForAxis
node
crossAxis
(boundAxis node crossAxis (totalLineCrossDim.contents +. paddingAndBorderAxisCross))
} else if (
measureModeCrossDim === CssMeasureModeAtMost
) {
setLayoutMeasuredDimensionForAxis
node
crossAxis
(
fmaxf
(
fminf
(availableInnerCrossDim +. paddingAndBorderAxisCross)
(
boundAxisWithinMinAndMax
node crossAxis (totalLineCrossDim.contents +. paddingAndBorderAxisCross)
)
)
paddingAndBorderAxisCross
)
};
currentAbsoluteChild.contents = firstAbsoluteChild.contents;
while (currentAbsoluteChild.contents !== theNullNode) {
if performLayout {
let childWidth = {contents: cssUndefined};
let childHeight = {contents: cssUndefined};
let childWidthMeasureMode = {contents: CssMeasureModeUndefined};
let childHeightMeasureMode = {contents: CssMeasureModeUndefined};
if (isStyleDimDefined currentAbsoluteChild.contents CssFlexDirectionRow) {
childWidth.contents =
currentAbsoluteChild.contents.style.width +.
getMarginAxis currentAbsoluteChild.contents CssFlexDirectionRow
} else if (
isLeadingPosDefinedWithFallback currentAbsoluteChild.contents CssFlexDirectionRow &&
isTrailingPosDefinedWithFallback currentAbsoluteChild.contents CssFlexDirectionRow
) {
childWidth.contents =
node.layout.measuredWidth -. (
getLeadingBorder node CssFlexDirectionRow +. getTrailingBorder node CssFlexDirectionRow
) -. (
getLeadingPositionWithFallback currentAbsoluteChild.contents CssFlexDirectionRow +.
getTrailingPositionWithFallback currentAbsoluteChild.contents CssFlexDirectionRow
);
childWidth.contents =
boundAxis currentAbsoluteChild.contents CssFlexDirectionRow childWidth.contents
};
if (isStyleDimDefined currentAbsoluteChild.contents CssFlexDirectionColumn) {
childHeight.contents =
currentAbsoluteChild.contents.style.height +.
getMarginAxis currentAbsoluteChild.contents CssFlexDirectionColumn
} else if (
/* If the child doesn't have a specified height, compute the height based on the top/bottom offsets if they're defined. */
isLeadingPosDefinedWithFallback currentAbsoluteChild.contents CssFlexDirectionColumn &&
isTrailingPosDefinedWithFallback currentAbsoluteChild.contents CssFlexDirectionColumn
) {
childHeight.contents =
node.layout.measuredHeight -. (
getLeadingBorder node CssFlexDirectionColumn +.
getTrailingBorder node CssFlexDirectionColumn
) -. (
getLeadingPositionWithFallback currentAbsoluteChild.contents CssFlexDirectionColumn +.
getTrailingPositionWithFallback currentAbsoluteChild.contents CssFlexDirectionColumn
);
childHeight.contents =
boundAxis currentAbsoluteChild.contents CssFlexDirectionColumn childHeight.contents
};
if (isUndefined childWidth.contents || isUndefined childHeight.contents) {
childWidthMeasureMode.contents =
isUndefined childWidth.contents ? CssMeasureModeUndefined : CssMeasureModeExactly;
childHeightMeasureMode.contents =
isUndefined childHeight.contents ? CssMeasureModeUndefined : CssMeasureModeExactly;
/*
* According to the spec, if the main size is not definite and the
* child's inline axis is parallel to the main axis (i.e. it's
* horizontal), the child should be sized using "UNDEFINED" in
* the main size. Otherwise use "AT_MOST" in the cross axis.
*/
if (
(not isMainAxisRow && isUndefined childWidth.contents) &&
not (isUndefined availableInnerWidth)
) {
childWidth.contents = availableInnerWidth;
childWidthMeasureMode.contents = CssMeasureModeAtMost
};
/*
* If child has no defined size in the cross axis and is set to stretch, set the cross
* axis to be measured exactly with the available inner width
*/
let _ =
layoutNodeInternal
currentAbsoluteChild.contents
childWidth.contents
childHeight.contents
direction
childWidthMeasureMode.contents
childHeightMeasureMode.contents
false
absMeasureString;
childWidth.contents =
currentAbsoluteChild.contents.layout.measuredWidth +.
getMarginAxis currentAbsoluteChild.contents CssFlexDirectionRow;
childHeight.contents =
currentAbsoluteChild.contents.layout.measuredHeight +.
getMarginAxis currentAbsoluteChild.contents CssFlexDirectionColumn
};
let _ =
layoutNodeInternal
currentAbsoluteChild.contents
childWidth.contents
childHeight.contents
direction
CssMeasureModeExactly
CssMeasureModeExactly
true
absLayoutString;
if (
isTrailingPosDefinedWithFallback currentAbsoluteChild.contents mainAxis &&
not (isLeadingPosDefinedWithFallback currentAbsoluteChild.contents mainAxis)
) {
setLayoutLeadingPositionForAxis
currentAbsoluteChild.contents
mainAxis
(
layoutMeasuredDimensionForAxis node mainAxis -.
layoutMeasuredDimensionForAxis currentAbsoluteChild.contents mainAxis -.
getTrailingPositionWithFallback currentAbsoluteChild.contents mainAxis
)
};
if (
isTrailingPosDefinedWithFallback currentAbsoluteChild.contents crossAxis &&
not (isLeadingPosDefinedWithFallback currentAbsoluteChild.contents crossAxis)
) {
setLayoutLeadingPositionForAxis
currentAbsoluteChild.contents
crossAxis
(
layoutMeasuredDimensionForAxis node crossAxis -.
layoutMeasuredDimensionForAxis currentAbsoluteChild.contents crossAxis -.
getTrailingPositionWithFallback currentAbsoluteChild.contents crossAxis
)
}
};
currentAbsoluteChild.contents = currentAbsoluteChild.contents.nextChild
};
/* STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN */
if performLayout {
let needsMainTrailingPos =
mainAxis == CssFlexDirectionRowReverse || mainAxis == CssFlexDirectionColumnReverse;
let needsCrossTrailingPos =
crossAxis == CssFlexDirectionRowReverse || crossAxis == CssFlexDirectionColumnReverse;
/* Set trailing position if necessary. */
if (needsMainTrailingPos || needsCrossTrailingPos) {
for i in 0 to (childCount - 1) {
let child = node.children.(i);
if needsMainTrailingPos {
setTrailingPosition node child mainAxis
};
if needsCrossTrailingPos {
setTrailingPosition node child crossAxis
}
}
}
}
}
}
}
/** END_GENERATED **/
};
let layoutNode node availableWidth availableHeight parentDirection => {
/* Increment the generation count. This will force the recursive routine to visit*/
/* all dirty nodes at least once. Subsequent visits will be skipped if the input*/
/* parameters don't change.*/
gCurrentGenerationCount.contents = gCurrentGenerationCount.contents + 1;
/* If the caller didn't specify a height/width, use the dimensions*/
/* specified in the style.*/
let (availableWidth, widthMeasureMode) =
if (not (isUndefined availableWidth)) {
(availableWidth, CssMeasureModeExactly)
} else if (
isStyleDimDefined node CssFlexDirectionRow
) {
(node.style.width +. getMarginAxis node CssFlexDirectionRow, CssMeasureModeExactly)
} else if (
node.style.maxWidth >= zero
) {
(node.style.maxWidth, CssMeasureModeAtMost)
} else {
(availableWidth, CssMeasureModeUndefined)
};
let (availableHeight, heightMeasureMode) =
if (not (isUndefined availableHeight)) {
(availableHeight, CssMeasureModeExactly)
} else if (
isStyleDimDefined node CssFlexDirectionColumn
) {
(node.style.height +. getMarginAxis node CssFlexDirectionColumn, CssMeasureModeExactly)
} else if (
node.style.maxHeight >= zero
) {
(node.style.maxHeight, CssMeasureModeAtMost)
} else {
(availableHeight, CssMeasureModeUndefined)
};
if (
layoutNodeInternal
node
availableWidth
availableHeight
parentDirection
widthMeasureMode
heightMeasureMode
true
initialString
) {
setPosition node node.layout.direction;
if gPrintTree.contents {
LayoutPrint.printCssNode (node, {printLayout: true, printChildren: true, printStyle: true})
}
}
};