|
|
@@ -23,7 +23,8 @@ __forceinline const float fmaxf(const float a, const float b) {
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
static float computedEdgeValue(float edges[CSSEdgeCount], CSSEdge edge, float defaultValue) {
|
|
|
|
static float
|
|
|
|
|
|
|
|
computedEdgeValue(const float edges[CSSEdgeCount], const CSSEdge edge, const float defaultValue) {
|
|
|
|
CSS_ASSERT(edge <= CSSEdgeEnd, "Cannot get computed value of multi-edge shorthands");
|
|
|
|
CSS_ASSERT(edge <= CSSEdgeEnd, "Cannot get computed value of multi-edge shorthands");
|
|
|
|
|
|
|
|
|
|
|
|
if (!CSSValueIsUndefined(edges[edge])) {
|
|
|
|
if (!CSSValueIsUndefined(edges[edge])) {
|
|
|
@@ -52,19 +53,19 @@ static float computedEdgeValue(float edges[CSSEdgeCount], CSSEdge edge, float de
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CSSNodeRef CSSNodeNew() {
|
|
|
|
CSSNodeRef CSSNodeNew() {
|
|
|
|
CSSNodeRef node = calloc(1, sizeof(CSSNode));
|
|
|
|
const CSSNodeRef node = calloc(1, sizeof(CSSNode));
|
|
|
|
CSS_ASSERT(node, "Could not allocate memory for node");
|
|
|
|
CSS_ASSERT(node, "Could not allocate memory for node");
|
|
|
|
|
|
|
|
|
|
|
|
CSSNodeInit(node);
|
|
|
|
CSSNodeInit(node);
|
|
|
|
return node;
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CSSNodeFree(CSSNodeRef node) {
|
|
|
|
void CSSNodeFree(const CSSNodeRef node) {
|
|
|
|
CSSNodeListFree(node->children);
|
|
|
|
CSSNodeListFree(node->children);
|
|
|
|
free(node);
|
|
|
|
free(node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CSSNodeInit(CSSNodeRef node) {
|
|
|
|
void CSSNodeInit(const CSSNodeRef node) {
|
|
|
|
node->parent = NULL;
|
|
|
|
node->parent = NULL;
|
|
|
|
node->children = CSSNodeListNew(4);
|
|
|
|
node->children = CSSNodeListNew(4);
|
|
|
|
node->hasNewLayout = true;
|
|
|
|
node->hasNewLayout = true;
|
|
|
@@ -112,7 +113,7 @@ void CSSNodeInit(CSSNodeRef node) {
|
|
|
|
node->layout.cached_layout.heightMeasureMode = (CSSMeasureMode) -1;
|
|
|
|
node->layout.cached_layout.heightMeasureMode = (CSSMeasureMode) -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void _CSSNodeMarkDirty(CSSNodeRef node) {
|
|
|
|
void _CSSNodeMarkDirty(const CSSNodeRef node) {
|
|
|
|
if (!node->isDirty) {
|
|
|
|
if (!node->isDirty) {
|
|
|
|
node->isDirty = true;
|
|
|
|
node->isDirty = true;
|
|
|
|
if (node->parent) {
|
|
|
|
if (node->parent) {
|
|
|
@@ -121,27 +122,27 @@ void _CSSNodeMarkDirty(CSSNodeRef node) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CSSNodeInsertChild(CSSNodeRef node, CSSNodeRef child, uint32_t index) {
|
|
|
|
void CSSNodeInsertChild(const CSSNodeRef node, const CSSNodeRef child, const uint32_t index) {
|
|
|
|
CSSNodeListInsert(node->children, child, index);
|
|
|
|
CSSNodeListInsert(node->children, child, index);
|
|
|
|
child->parent = node;
|
|
|
|
child->parent = node;
|
|
|
|
_CSSNodeMarkDirty(node);
|
|
|
|
_CSSNodeMarkDirty(node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CSSNodeRemoveChild(CSSNodeRef node, CSSNodeRef child) {
|
|
|
|
void CSSNodeRemoveChild(const CSSNodeRef node, const CSSNodeRef child) {
|
|
|
|
CSSNodeListDelete(node->children, child);
|
|
|
|
CSSNodeListDelete(node->children, child);
|
|
|
|
child->parent = NULL;
|
|
|
|
child->parent = NULL;
|
|
|
|
_CSSNodeMarkDirty(node);
|
|
|
|
_CSSNodeMarkDirty(node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CSSNodeRef CSSNodeGetChild(CSSNodeRef node, uint32_t index) {
|
|
|
|
CSSNodeRef CSSNodeGetChild(const CSSNodeRef node, const uint32_t index) {
|
|
|
|
return CSSNodeListGet(node->children, index);
|
|
|
|
return CSSNodeListGet(node->children, index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t CSSNodeChildCount(CSSNodeRef node) {
|
|
|
|
uint32_t CSSNodeChildCount(const CSSNodeRef node) {
|
|
|
|
return CSSNodeListCount(node->children);
|
|
|
|
return CSSNodeListCount(node->children);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CSSNodeMarkDirty(CSSNodeRef node) {
|
|
|
|
void CSSNodeMarkDirty(const CSSNodeRef node) {
|
|
|
|
CSS_ASSERT(node->measure != NULL,
|
|
|
|
CSS_ASSERT(node->measure != NULL,
|
|
|
|
"Nodes without custom measure functions "
|
|
|
|
"Nodes without custom measure functions "
|
|
|
|
"should not manually mark themselves as "
|
|
|
|
"should not manually mark themselves as "
|
|
|
@@ -149,11 +150,11 @@ void CSSNodeMarkDirty(CSSNodeRef node) {
|
|
|
|
_CSSNodeMarkDirty(node);
|
|
|
|
_CSSNodeMarkDirty(node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CSSNodeIsDirty(CSSNodeRef node) {
|
|
|
|
bool CSSNodeIsDirty(const CSSNodeRef node) {
|
|
|
|
return node->isDirty;
|
|
|
|
return node->isDirty;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CSSNodeStyleSetFlex(CSSNodeRef node, float flex) {
|
|
|
|
void CSSNodeStyleSetFlex(const CSSNodeRef node, const float flex) {
|
|
|
|
if (CSSValueIsUndefined(flex) || flex == 0) {
|
|
|
|
if (CSSValueIsUndefined(flex) || flex == 0) {
|
|
|
|
CSSNodeStyleSetFlexGrow(node, 0);
|
|
|
|
CSSNodeStyleSetFlexGrow(node, 0);
|
|
|
|
CSSNodeStyleSetFlexShrink(node, 0);
|
|
|
|
CSSNodeStyleSetFlexShrink(node, 0);
|
|
|
@@ -169,7 +170,7 @@ void CSSNodeStyleSetFlex(CSSNodeRef node, float flex) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float CSSNodeStyleGetFlex(CSSNodeRef node) {
|
|
|
|
float CSSNodeStyleGetFlex(const CSSNodeRef node) {
|
|
|
|
if (node->style.flexGrow > 0) {
|
|
|
|
if (node->style.flexGrow > 0) {
|
|
|
|
return node->style.flexGrow;
|
|
|
|
return node->style.flexGrow;
|
|
|
|
} else if (node->style.flexShrink > 0) {
|
|
|
|
} else if (node->style.flexShrink > 0) {
|
|
|
@@ -180,40 +181,40 @@ float CSSNodeStyleGetFlex(CSSNodeRef node) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define CSS_NODE_PROPERTY_IMPL(type, name, paramName, instanceName) \
|
|
|
|
#define CSS_NODE_PROPERTY_IMPL(type, name, paramName, instanceName) \
|
|
|
|
void CSSNodeSet##name(CSSNodeRef node, type paramName) { \
|
|
|
|
void CSSNodeSet##name(const CSSNodeRef node, type paramName) { \
|
|
|
|
node->instanceName = paramName; \
|
|
|
|
node->instanceName = paramName; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
\
|
|
|
|
type CSSNodeGet##name(CSSNodeRef node) { \
|
|
|
|
type CSSNodeGet##name(const CSSNodeRef node) { \
|
|
|
|
return node->instanceName; \
|
|
|
|
return node->instanceName; \
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define CSS_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName) \
|
|
|
|
#define CSS_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName) \
|
|
|
|
void CSSNodeStyleSet##name(CSSNodeRef node, type paramName) { \
|
|
|
|
void CSSNodeStyleSet##name(const CSSNodeRef node, const type paramName) { \
|
|
|
|
if (node->style.instanceName != paramName) { \
|
|
|
|
if (node->style.instanceName != paramName) { \
|
|
|
|
node->style.instanceName = paramName; \
|
|
|
|
node->style.instanceName = paramName; \
|
|
|
|
_CSSNodeMarkDirty(node); \
|
|
|
|
_CSSNodeMarkDirty(node); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
\
|
|
|
|
type CSSNodeStyleGet##name(CSSNodeRef node) { \
|
|
|
|
type CSSNodeStyleGet##name(const CSSNodeRef node) { \
|
|
|
|
return node->style.instanceName; \
|
|
|
|
return node->style.instanceName; \
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName, defaultValue) \
|
|
|
|
#define CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName, defaultValue) \
|
|
|
|
void CSSNodeStyleSet##name(CSSNodeRef node, CSSEdge edge, type paramName) { \
|
|
|
|
void CSSNodeStyleSet##name(const CSSNodeRef node, const CSSEdge edge, const type paramName) { \
|
|
|
|
if (node->style.instanceName[edge] != paramName) { \
|
|
|
|
if (node->style.instanceName[edge] != paramName) { \
|
|
|
|
node->style.instanceName[edge] = paramName; \
|
|
|
|
node->style.instanceName[edge] = paramName; \
|
|
|
|
_CSSNodeMarkDirty(node); \
|
|
|
|
_CSSNodeMarkDirty(node); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
\
|
|
|
|
type CSSNodeStyleGet##name(CSSNodeRef node, CSSEdge edge) { \
|
|
|
|
type CSSNodeStyleGet##name(const CSSNodeRef node, const CSSEdge edge) { \
|
|
|
|
return computedEdgeValue(node->style.instanceName, edge, defaultValue); \
|
|
|
|
return computedEdgeValue(node->style.instanceName, edge, defaultValue); \
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define CSS_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \
|
|
|
|
#define CSS_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \
|
|
|
|
type CSSNodeLayoutGet##name(CSSNodeRef node) { \
|
|
|
|
type CSSNodeLayoutGet##name(const CSSNodeRef node) { \
|
|
|
|
return node->layout.instanceName; \
|
|
|
|
return node->layout.instanceName; \
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@@ -258,49 +259,50 @@ CSS_NODE_LAYOUT_PROPERTY_IMPL(CSSDirection, Direction, direction);
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t gCurrentGenerationCount = 0;
|
|
|
|
uint32_t gCurrentGenerationCount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
bool layoutNodeInternal(CSSNode *node,
|
|
|
|
bool layoutNodeInternal(const CSSNodeRef node,
|
|
|
|
float availableWidth,
|
|
|
|
const float availableWidth,
|
|
|
|
float availableHeight,
|
|
|
|
const float availableHeight,
|
|
|
|
CSSDirection parentDirection,
|
|
|
|
const CSSDirection parentDirection,
|
|
|
|
CSSMeasureMode widthMeasureMode,
|
|
|
|
const CSSMeasureMode widthMeasureMode,
|
|
|
|
CSSMeasureMode heightMeasureMode,
|
|
|
|
const CSSMeasureMode heightMeasureMode,
|
|
|
|
bool performLayout,
|
|
|
|
const bool performLayout,
|
|
|
|
char *reason);
|
|
|
|
const char *reason);
|
|
|
|
|
|
|
|
|
|
|
|
bool CSSValueIsUndefined(float value) {
|
|
|
|
bool CSSValueIsUndefined(const float value) {
|
|
|
|
return isnan(value);
|
|
|
|
return isnan(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool eq(float a, float b) {
|
|
|
|
static bool eq(const float a, const float b) {
|
|
|
|
if (CSSValueIsUndefined(a)) {
|
|
|
|
if (CSSValueIsUndefined(a)) {
|
|
|
|
return CSSValueIsUndefined(b);
|
|
|
|
return CSSValueIsUndefined(b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fabs(a - b) < 0.0001;
|
|
|
|
return fabs(a - b) < 0.0001;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void indent(uint32_t n) {
|
|
|
|
static void indent(const uint32_t n) {
|
|
|
|
for (uint32_t i = 0; i < n; ++i) {
|
|
|
|
for (uint32_t i = 0; i < n; i++) {
|
|
|
|
printf(" ");
|
|
|
|
printf(" ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void print_number_0(const char *str, float number) {
|
|
|
|
static void print_number_0(const char *str, const float number) {
|
|
|
|
if (!eq(number, 0)) {
|
|
|
|
if (!eq(number, 0)) {
|
|
|
|
printf("%s: %g, ", str, number);
|
|
|
|
printf("%s: %g, ", str, number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void print_number_nan(const char *str, float number) {
|
|
|
|
static void print_number_nan(const char *str, const float number) {
|
|
|
|
if (!isnan(number)) {
|
|
|
|
if (!isnan(number)) {
|
|
|
|
printf("%s: %g, ", str, number);
|
|
|
|
printf("%s: %g, ", str, number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool four_equal(float four[4]) {
|
|
|
|
static bool four_equal(const float four[4]) {
|
|
|
|
return eq(four[0], four[1]) && eq(four[0], four[2]) && eq(four[0], four[3]);
|
|
|
|
return eq(four[0], four[1]) && eq(four[0], four[2]) && eq(four[0], four[3]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void print_css_node_rec(CSSNode *node, CSSPrintOptions options, uint32_t level) {
|
|
|
|
static void
|
|
|
|
|
|
|
|
print_css_node_rec(const CSSNodeRef node, const CSSPrintOptions options, const uint32_t level) {
|
|
|
|
indent(level);
|
|
|
|
indent(level);
|
|
|
|
printf("{");
|
|
|
|
printf("{");
|
|
|
|
|
|
|
|
|
|
|
@@ -425,10 +427,10 @@ static void print_css_node_rec(CSSNode *node, CSSPrintOptions options, uint32_t
|
|
|
|
computedEdgeValue(node->style.position, CSSEdgeBottom, CSSUndefined));
|
|
|
|
computedEdgeValue(node->style.position, CSSEdgeBottom, CSSUndefined));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t childCount = CSSNodeListCount(node->children);
|
|
|
|
const uint32_t childCount = CSSNodeListCount(node->children);
|
|
|
|
if (options & CSSPrintOptionsChildren && childCount > 0) {
|
|
|
|
if (options & CSSPrintOptionsChildren && childCount > 0) {
|
|
|
|
printf("children: [\n");
|
|
|
|
printf("children: [\n");
|
|
|
|
for (uint32_t i = 0; i < childCount; ++i) {
|
|
|
|
for (uint32_t i = 0; i < childCount; i++) {
|
|
|
|
print_css_node_rec(CSSNodeGetChild(node, i), options, level + 1);
|
|
|
|
print_css_node_rec(CSSNodeGetChild(node, i), options, level + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
indent(level);
|
|
|
|
indent(level);
|
|
|
@@ -438,44 +440,44 @@ static void print_css_node_rec(CSSNode *node, CSSPrintOptions options, uint32_t
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CSSNodePrint(CSSNode *node, CSSPrintOptions options) {
|
|
|
|
void CSSNodePrint(const CSSNodeRef node, const CSSPrintOptions options) {
|
|
|
|
print_css_node_rec(node, options, 0);
|
|
|
|
print_css_node_rec(node, options, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static CSSEdge leading[4] = {
|
|
|
|
static const CSSEdge leading[4] = {
|
|
|
|
[CSSFlexDirectionColumn] = CSSEdgeTop,
|
|
|
|
[CSSFlexDirectionColumn] = CSSEdgeTop,
|
|
|
|
[CSSFlexDirectionColumnReverse] = CSSEdgeBottom,
|
|
|
|
[CSSFlexDirectionColumnReverse] = CSSEdgeBottom,
|
|
|
|
[CSSFlexDirectionRow] = CSSEdgeLeft,
|
|
|
|
[CSSFlexDirectionRow] = CSSEdgeLeft,
|
|
|
|
[CSSFlexDirectionRowReverse] = CSSEdgeRight,
|
|
|
|
[CSSFlexDirectionRowReverse] = CSSEdgeRight,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
static CSSEdge trailing[4] = {
|
|
|
|
static const CSSEdge trailing[4] = {
|
|
|
|
[CSSFlexDirectionColumn] = CSSEdgeBottom,
|
|
|
|
[CSSFlexDirectionColumn] = CSSEdgeBottom,
|
|
|
|
[CSSFlexDirectionColumnReverse] = CSSEdgeTop,
|
|
|
|
[CSSFlexDirectionColumnReverse] = CSSEdgeTop,
|
|
|
|
[CSSFlexDirectionRow] = CSSEdgeRight,
|
|
|
|
[CSSFlexDirectionRow] = CSSEdgeRight,
|
|
|
|
[CSSFlexDirectionRowReverse] = CSSEdgeLeft,
|
|
|
|
[CSSFlexDirectionRowReverse] = CSSEdgeLeft,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
static CSSEdge pos[4] = {
|
|
|
|
static const CSSEdge pos[4] = {
|
|
|
|
[CSSFlexDirectionColumn] = CSSEdgeTop,
|
|
|
|
[CSSFlexDirectionColumn] = CSSEdgeTop,
|
|
|
|
[CSSFlexDirectionColumnReverse] = CSSEdgeBottom,
|
|
|
|
[CSSFlexDirectionColumnReverse] = CSSEdgeBottom,
|
|
|
|
[CSSFlexDirectionRow] = CSSEdgeLeft,
|
|
|
|
[CSSFlexDirectionRow] = CSSEdgeLeft,
|
|
|
|
[CSSFlexDirectionRowReverse] = CSSEdgeRight,
|
|
|
|
[CSSFlexDirectionRowReverse] = CSSEdgeRight,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
static CSSDimension dim[4] = {
|
|
|
|
static const CSSDimension dim[4] = {
|
|
|
|
[CSSFlexDirectionColumn] = CSSDimensionHeight,
|
|
|
|
[CSSFlexDirectionColumn] = CSSDimensionHeight,
|
|
|
|
[CSSFlexDirectionColumnReverse] = CSSDimensionHeight,
|
|
|
|
[CSSFlexDirectionColumnReverse] = CSSDimensionHeight,
|
|
|
|
[CSSFlexDirectionRow] = CSSDimensionWidth,
|
|
|
|
[CSSFlexDirectionRow] = CSSDimensionWidth,
|
|
|
|
[CSSFlexDirectionRowReverse] = CSSDimensionWidth,
|
|
|
|
[CSSFlexDirectionRowReverse] = CSSDimensionWidth,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static bool isRowDirection(CSSFlexDirection flexDirection) {
|
|
|
|
static bool isRowDirection(const CSSFlexDirection flexDirection) {
|
|
|
|
return flexDirection == CSSFlexDirectionRow || flexDirection == CSSFlexDirectionRowReverse;
|
|
|
|
return flexDirection == CSSFlexDirectionRow || flexDirection == CSSFlexDirectionRowReverse;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool isColumnDirection(CSSFlexDirection flexDirection) {
|
|
|
|
static bool isColumnDirection(const CSSFlexDirection flexDirection) {
|
|
|
|
return flexDirection == CSSFlexDirectionColumn || flexDirection == CSSFlexDirectionColumnReverse;
|
|
|
|
return flexDirection == CSSFlexDirectionColumn || flexDirection == CSSFlexDirectionColumnReverse;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getLeadingMargin(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getLeadingMargin(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.margin, CSSEdgeStart, 0))) {
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.margin, CSSEdgeStart, 0))) {
|
|
|
|
return computedEdgeValue(node->style.margin, CSSEdgeStart, 0);
|
|
|
|
return computedEdgeValue(node->style.margin, CSSEdgeStart, 0);
|
|
|
@@ -484,7 +486,7 @@ static float getLeadingMargin(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
return computedEdgeValue(node->style.margin, leading[axis], 0);
|
|
|
|
return computedEdgeValue(node->style.margin, leading[axis], 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getTrailingMargin(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getTrailingMargin(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.margin, CSSEdgeEnd, 0))) {
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.margin, CSSEdgeEnd, 0))) {
|
|
|
|
return computedEdgeValue(node->style.margin, CSSEdgeEnd, 0);
|
|
|
|
return computedEdgeValue(node->style.margin, CSSEdgeEnd, 0);
|
|
|
@@ -493,7 +495,7 @@ static float getTrailingMargin(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
return computedEdgeValue(node->style.margin, trailing[axis], 0);
|
|
|
|
return computedEdgeValue(node->style.margin, trailing[axis], 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getLeadingPadding(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getLeadingPadding(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.padding, CSSEdgeStart, 0)) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.padding, CSSEdgeStart, 0)) &&
|
|
|
|
computedEdgeValue(node->style.padding, CSSEdgeStart, 0) >= 0) {
|
|
|
|
computedEdgeValue(node->style.padding, CSSEdgeStart, 0) >= 0) {
|
|
|
@@ -507,7 +509,7 @@ static float getLeadingPadding(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getTrailingPadding(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getTrailingPadding(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.padding, CSSEdgeEnd, 0)) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.padding, CSSEdgeEnd, 0)) &&
|
|
|
|
computedEdgeValue(node->style.padding, CSSEdgeEnd, 0) >= 0) {
|
|
|
|
computedEdgeValue(node->style.padding, CSSEdgeEnd, 0) >= 0) {
|
|
|
@@ -521,7 +523,7 @@ static float getTrailingPadding(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getLeadingBorder(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getLeadingBorder(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.border, CSSEdgeStart, 0)) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.border, CSSEdgeStart, 0)) &&
|
|
|
|
computedEdgeValue(node->style.border, CSSEdgeStart, 0) >= 0) {
|
|
|
|
computedEdgeValue(node->style.border, CSSEdgeStart, 0) >= 0) {
|
|
|
@@ -535,7 +537,7 @@ static float getLeadingBorder(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getTrailingBorder(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getTrailingBorder(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.border, CSSEdgeEnd, 0)) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.border, CSSEdgeEnd, 0)) &&
|
|
|
|
computedEdgeValue(node->style.border, CSSEdgeEnd, 0) >= 0) {
|
|
|
|
computedEdgeValue(node->style.border, CSSEdgeEnd, 0) >= 0) {
|
|
|
@@ -549,40 +551,39 @@ static float getTrailingBorder(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getLeadingPaddingAndBorder(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getLeadingPaddingAndBorder(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
return getLeadingPadding(node, axis) + getLeadingBorder(node, axis);
|
|
|
|
return getLeadingPadding(node, axis) + getLeadingBorder(node, axis);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getTrailingPaddingAndBorder(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getTrailingPaddingAndBorder(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
return getTrailingPadding(node, axis) + getTrailingBorder(node, axis);
|
|
|
|
return getTrailingPadding(node, axis) + getTrailingBorder(node, axis);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getMarginAxis(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getMarginAxis(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
return getLeadingMargin(node, axis) + getTrailingMargin(node, axis);
|
|
|
|
return getLeadingMargin(node, axis) + getTrailingMargin(node, axis);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getPaddingAndBorderAxis(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getPaddingAndBorderAxis(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
return getLeadingPaddingAndBorder(node, axis) + getTrailingPaddingAndBorder(node, axis);
|
|
|
|
return getLeadingPaddingAndBorder(node, axis) + getTrailingPaddingAndBorder(node, axis);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static CSSAlign getAlignItem(CSSNode *node, CSSNode *child) {
|
|
|
|
static CSSAlign getAlignItem(const CSSNodeRef node, const CSSNodeRef child) {
|
|
|
|
if (child->style.alignSelf != CSSAlignAuto) {
|
|
|
|
if (child->style.alignSelf != CSSAlignAuto) {
|
|
|
|
return child->style.alignSelf;
|
|
|
|
return child->style.alignSelf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return node->style.alignItems;
|
|
|
|
return node->style.alignItems;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static CSSDirection resolveDirection(CSSNode *node, CSSDirection parentDirection) {
|
|
|
|
static CSSDirection resolveDirection(const CSSNodeRef node, const CSSDirection parentDirection) {
|
|
|
|
CSSDirection direction = node->style.direction;
|
|
|
|
if (node->style.direction == CSSDirectionInherit) {
|
|
|
|
|
|
|
|
return parentDirection > CSSDirectionInherit ? parentDirection : CSSDirectionLTR;
|
|
|
|
if (direction == CSSDirectionInherit) {
|
|
|
|
} else {
|
|
|
|
direction = parentDirection > CSSDirectionInherit ? parentDirection : CSSDirectionLTR;
|
|
|
|
return node->style.direction;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return direction;
|
|
|
|
static CSSFlexDirection resolveAxis(const CSSFlexDirection flexDirection,
|
|
|
|
}
|
|
|
|
const CSSDirection direction) {
|
|
|
|
|
|
|
|
|
|
|
|
static CSSFlexDirection resolveAxis(CSSFlexDirection flexDirection, CSSDirection direction) {
|
|
|
|
|
|
|
|
if (direction == CSSDirectionRTL) {
|
|
|
|
if (direction == CSSDirectionRTL) {
|
|
|
|
if (flexDirection == CSSFlexDirectionRow) {
|
|
|
|
if (flexDirection == CSSFlexDirectionRow) {
|
|
|
|
return CSSFlexDirectionRowReverse;
|
|
|
|
return CSSFlexDirectionRowReverse;
|
|
|
@@ -594,8 +595,8 @@ static CSSFlexDirection resolveAxis(CSSFlexDirection flexDirection, CSSDirection
|
|
|
|
return flexDirection;
|
|
|
|
return flexDirection;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static CSSFlexDirection getCrossFlexDirection(CSSFlexDirection flexDirection,
|
|
|
|
static CSSFlexDirection getCrossFlexDirection(const CSSFlexDirection flexDirection,
|
|
|
|
CSSDirection direction) {
|
|
|
|
const CSSDirection direction) {
|
|
|
|
if (isColumnDirection(flexDirection)) {
|
|
|
|
if (isColumnDirection(flexDirection)) {
|
|
|
|
return resolveAxis(CSSFlexDirectionRow, direction);
|
|
|
|
return resolveAxis(CSSFlexDirectionRow, direction);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@@ -603,34 +604,34 @@ static CSSFlexDirection getCrossFlexDirection(CSSFlexDirection flexDirection,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool isFlex(CSSNode *node) {
|
|
|
|
static bool isFlex(const CSSNodeRef node) {
|
|
|
|
return (node->style.positionType == CSSPositionTypeRelative &&
|
|
|
|
return (node->style.positionType == CSSPositionTypeRelative &&
|
|
|
|
(node->style.flexGrow != 0 || node->style.flexShrink != 0));
|
|
|
|
(node->style.flexGrow != 0 || node->style.flexShrink != 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getDimWithMargin(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getDimWithMargin(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
return node->layout.measuredDimensions[dim[axis]] + getLeadingMargin(node, axis) +
|
|
|
|
return node->layout.measuredDimensions[dim[axis]] + getLeadingMargin(node, axis) +
|
|
|
|
getTrailingMargin(node, axis);
|
|
|
|
getTrailingMargin(node, axis);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool isStyleDimDefined(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static bool isStyleDimDefined(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
float value = node->style.dimensions[dim[axis]];
|
|
|
|
const float value = node->style.dimensions[dim[axis]];
|
|
|
|
return !CSSValueIsUndefined(value) && value >= 0.0;
|
|
|
|
return !CSSValueIsUndefined(value) && value >= 0.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool isLayoutDimDefined(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static bool isLayoutDimDefined(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
float value = node->layout.measuredDimensions[dim[axis]];
|
|
|
|
const float value = node->layout.measuredDimensions[dim[axis]];
|
|
|
|
return !CSSValueIsUndefined(value) && value >= 0.0;
|
|
|
|
return !CSSValueIsUndefined(value) && value >= 0.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool isLeadingPosDefined(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static bool isLeadingPosDefined(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
return (isRowDirection(axis) &&
|
|
|
|
return (isRowDirection(axis) &&
|
|
|
|
!CSSValueIsUndefined(
|
|
|
|
!CSSValueIsUndefined(
|
|
|
|
computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined))) ||
|
|
|
|
computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined))) ||
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.position, leading[axis], CSSUndefined));
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.position, leading[axis], CSSUndefined));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool isTrailingPosDefined(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static bool isTrailingPosDefined(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
return (isRowDirection(axis) &&
|
|
|
|
return (isRowDirection(axis) &&
|
|
|
|
!CSSValueIsUndefined(
|
|
|
|
!CSSValueIsUndefined(
|
|
|
|
computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined))) ||
|
|
|
|
computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined))) ||
|
|
|
@@ -638,7 +639,7 @@ static bool isTrailingPosDefined(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
computedEdgeValue(node->style.position, trailing[axis], CSSUndefined));
|
|
|
|
computedEdgeValue(node->style.position, trailing[axis], CSSUndefined));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getLeadingPosition(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getLeadingPosition(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined))) {
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined))) {
|
|
|
|
return computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined);
|
|
|
|
return computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined);
|
|
|
@@ -649,7 +650,7 @@ static float getLeadingPosition(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float getTrailingPosition(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getTrailingPosition(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
if (isRowDirection(axis) &&
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined))) {
|
|
|
|
!CSSValueIsUndefined(computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined))) {
|
|
|
|
return computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined);
|
|
|
|
return computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined);
|
|
|
@@ -660,7 +661,8 @@ static float getTrailingPosition(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float boundAxisWithinMinAndMax(CSSNode *node, CSSFlexDirection axis, float value) {
|
|
|
|
static float
|
|
|
|
|
|
|
|
boundAxisWithinMinAndMax(const CSSNodeRef node, const CSSFlexDirection axis, const float value) {
|
|
|
|
float min = CSSUndefined;
|
|
|
|
float min = CSSUndefined;
|
|
|
|
float max = CSSUndefined;
|
|
|
|
float max = CSSUndefined;
|
|
|
|
|
|
|
|
|
|
|
@@ -677,6 +679,7 @@ static float boundAxisWithinMinAndMax(CSSNode *node, CSSFlexDirection axis, floa
|
|
|
|
if (!CSSValueIsUndefined(max) && max >= 0.0 && boundValue > max) {
|
|
|
|
if (!CSSValueIsUndefined(max) && max >= 0.0 && boundValue > max) {
|
|
|
|
boundValue = max;
|
|
|
|
boundValue = max;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!CSSValueIsUndefined(min) && min >= 0.0 && boundValue < min) {
|
|
|
|
if (!CSSValueIsUndefined(min) && min >= 0.0 && boundValue < min) {
|
|
|
|
boundValue = min;
|
|
|
|
boundValue = min;
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -687,28 +690,29 @@ static float boundAxisWithinMinAndMax(CSSNode *node, CSSFlexDirection axis, floa
|
|
|
|
// Like boundAxisWithinMinAndMax but also ensures that the value doesn't go
|
|
|
|
// Like boundAxisWithinMinAndMax but also ensures that the value doesn't go
|
|
|
|
// below the
|
|
|
|
// below the
|
|
|
|
// padding and border amount.
|
|
|
|
// padding and border amount.
|
|
|
|
static float boundAxis(CSSNode *node, CSSFlexDirection axis, float value) {
|
|
|
|
static float boundAxis(const CSSNodeRef node, const CSSFlexDirection axis, const float value) {
|
|
|
|
return fmaxf(boundAxisWithinMinAndMax(node, axis, value), getPaddingAndBorderAxis(node, axis));
|
|
|
|
return fmaxf(boundAxisWithinMinAndMax(node, axis, value), getPaddingAndBorderAxis(node, axis));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void setTrailingPosition(CSSNode *node, CSSNode *child, CSSFlexDirection axis) {
|
|
|
|
static void
|
|
|
|
float size = child->layout.measuredDimensions[dim[axis]];
|
|
|
|
setTrailingPosition(const CSSNodeRef node, const CSSNodeRef child, const CSSFlexDirection axis) {
|
|
|
|
|
|
|
|
const float size = child->layout.measuredDimensions[dim[axis]];
|
|
|
|
child->layout.position[trailing[axis]] =
|
|
|
|
child->layout.position[trailing[axis]] =
|
|
|
|
node->layout.measuredDimensions[dim[axis]] - size - child->layout.position[pos[axis]];
|
|
|
|
node->layout.measuredDimensions[dim[axis]] - size - child->layout.position[pos[axis]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If both left and right are defined, then use left. Otherwise return
|
|
|
|
// If both left and right are defined, then use left. Otherwise return
|
|
|
|
// +left or -right depending on which is defined.
|
|
|
|
// +left or -right depending on which is defined.
|
|
|
|
static float getRelativePosition(CSSNode *node, CSSFlexDirection axis) {
|
|
|
|
static float getRelativePosition(const CSSNodeRef node, const CSSFlexDirection axis) {
|
|
|
|
if (isLeadingPosDefined(node, axis)) {
|
|
|
|
if (isLeadingPosDefined(node, axis)) {
|
|
|
|
return getLeadingPosition(node, axis);
|
|
|
|
return getLeadingPosition(node, axis);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -getTrailingPosition(node, axis);
|
|
|
|
return -getTrailingPosition(node, axis);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void setPosition(CSSNode *node, CSSDirection direction) {
|
|
|
|
static void setPosition(const CSSNodeRef node, const CSSDirection direction) {
|
|
|
|
CSSFlexDirection mainAxis = resolveAxis(node->style.flexDirection, direction);
|
|
|
|
const CSSFlexDirection mainAxis = resolveAxis(node->style.flexDirection, direction);
|
|
|
|
CSSFlexDirection crossAxis = getCrossFlexDirection(mainAxis, direction);
|
|
|
|
const CSSFlexDirection crossAxis = getCrossFlexDirection(mainAxis, direction);
|
|
|
|
|
|
|
|
|
|
|
|
node->layout.position[leading[mainAxis]] =
|
|
|
|
node->layout.position[leading[mainAxis]] =
|
|
|
|
getLeadingMargin(node, mainAxis) + getRelativePosition(node, mainAxis);
|
|
|
|
getLeadingMargin(node, mainAxis) + getRelativePosition(node, mainAxis);
|
|
|
@@ -832,13 +836,13 @@ static void setPosition(CSSNode *node, CSSDirection direction) {
|
|
|
|
// undefined then it must also pass a measure mode of CSSMeasureModeUndefined
|
|
|
|
// undefined then it must also pass a measure mode of CSSMeasureModeUndefined
|
|
|
|
// in that dimension.
|
|
|
|
// in that dimension.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
static void layoutNodeImpl(CSSNode *node,
|
|
|
|
static void layoutNodeImpl(const CSSNodeRef node,
|
|
|
|
float availableWidth,
|
|
|
|
const float availableWidth,
|
|
|
|
float availableHeight,
|
|
|
|
const float availableHeight,
|
|
|
|
CSSDirection parentDirection,
|
|
|
|
const CSSDirection parentDirection,
|
|
|
|
CSSMeasureMode widthMeasureMode,
|
|
|
|
const CSSMeasureMode widthMeasureMode,
|
|
|
|
CSSMeasureMode heightMeasureMode,
|
|
|
|
const CSSMeasureMode heightMeasureMode,
|
|
|
|
bool performLayout) {
|
|
|
|
const bool performLayout) {
|
|
|
|
CSS_ASSERT(CSSValueIsUndefined(availableWidth) ? widthMeasureMode == CSSMeasureModeUndefined
|
|
|
|
CSS_ASSERT(CSSValueIsUndefined(availableWidth) ? widthMeasureMode == CSSMeasureModeUndefined
|
|
|
|
: true,
|
|
|
|
: true,
|
|
|
|
"availableWidth is indefinite so widthMeasureMode must be "
|
|
|
|
"availableWidth is indefinite so widthMeasureMode must be "
|
|
|
@@ -848,20 +852,20 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
"availableHeight is indefinite so heightMeasureMode must be "
|
|
|
|
"availableHeight is indefinite so heightMeasureMode must be "
|
|
|
|
"CSSMeasureModeUndefined");
|
|
|
|
"CSSMeasureModeUndefined");
|
|
|
|
|
|
|
|
|
|
|
|
float paddingAndBorderAxisRow = getPaddingAndBorderAxis(node, CSSFlexDirectionRow);
|
|
|
|
const float paddingAndBorderAxisRow = getPaddingAndBorderAxis(node, CSSFlexDirectionRow);
|
|
|
|
float paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSSFlexDirectionColumn);
|
|
|
|
const float paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSSFlexDirectionColumn);
|
|
|
|
float marginAxisRow = getMarginAxis(node, CSSFlexDirectionRow);
|
|
|
|
const float marginAxisRow = getMarginAxis(node, CSSFlexDirectionRow);
|
|
|
|
float marginAxisColumn = getMarginAxis(node, CSSFlexDirectionColumn);
|
|
|
|
const float marginAxisColumn = getMarginAxis(node, CSSFlexDirectionColumn);
|
|
|
|
|
|
|
|
|
|
|
|
// Set the resolved resolution in the node's layout.
|
|
|
|
// Set the resolved resolution in the node's layout.
|
|
|
|
CSSDirection direction = resolveDirection(node, parentDirection);
|
|
|
|
const CSSDirection direction = resolveDirection(node, parentDirection);
|
|
|
|
node->layout.direction = direction;
|
|
|
|
node->layout.direction = direction;
|
|
|
|
|
|
|
|
|
|
|
|
// For content (text) nodes, determine the dimensions based on the text
|
|
|
|
// For content (text) nodes, determine the dimensions based on the text
|
|
|
|
// contents.
|
|
|
|
// contents.
|
|
|
|
if (node->measure) {
|
|
|
|
if (node->measure) {
|
|
|
|
float innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
|
|
|
|
const float innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
|
|
|
|
float innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
|
|
|
|
const float innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
|
|
|
|
|
|
|
|
|
|
|
|
if (widthMeasureMode == CSSMeasureModeExactly && heightMeasureMode == CSSMeasureModeExactly) {
|
|
|
|
if (widthMeasureMode == CSSMeasureModeExactly && heightMeasureMode == CSSMeasureModeExactly) {
|
|
|
|
// Don't bother sizing the text if both dimensions are already defined.
|
|
|
|
// Don't bother sizing the text if both dimensions are already defined.
|
|
|
@@ -877,7 +881,7 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
boundAxis(node, CSSFlexDirectionColumn, 0);
|
|
|
|
boundAxis(node, CSSFlexDirectionColumn, 0);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// Measure the text under the current constraints.
|
|
|
|
// Measure the text under the current constraints.
|
|
|
|
CSSSize measuredSize = node->measure(node->context,
|
|
|
|
const CSSSize measuredSize = node->measure(node->context,
|
|
|
|
|
|
|
|
|
|
|
|
innerWidth,
|
|
|
|
innerWidth,
|
|
|
|
widthMeasureMode,
|
|
|
|
widthMeasureMode,
|
|
|
@@ -906,7 +910,7 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
// For nodes with no children, use the available values if they were provided,
|
|
|
|
// For nodes with no children, use the available values if they were provided,
|
|
|
|
// or
|
|
|
|
// or
|
|
|
|
// the minimum size as indicated by the padding and border sizes.
|
|
|
|
// the minimum size as indicated by the padding and border sizes.
|
|
|
|
uint32_t childCount = CSSNodeListCount(node->children);
|
|
|
|
const uint32_t childCount = CSSNodeListCount(node->children);
|
|
|
|
if (childCount == 0) {
|
|
|
|
if (childCount == 0) {
|
|
|
|
node->layout.measuredDimensions[CSSDimensionWidth] =
|
|
|
|
node->layout.measuredDimensions[CSSDimensionWidth] =
|
|
|
|
boundAxis(node,
|
|
|
|
boundAxis(node,
|
|
|
@@ -973,43 +977,42 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// STEP 1: CALCULATE VALUES FOR REMAINDER OF ALGORITHM
|
|
|
|
// STEP 1: CALCULATE VALUES FOR REMAINDER OF ALGORITHM
|
|
|
|
CSSFlexDirection mainAxis = resolveAxis(node->style.flexDirection, direction);
|
|
|
|
const CSSFlexDirection mainAxis = resolveAxis(node->style.flexDirection, direction);
|
|
|
|
CSSFlexDirection crossAxis = getCrossFlexDirection(mainAxis, direction);
|
|
|
|
const CSSFlexDirection crossAxis = getCrossFlexDirection(mainAxis, direction);
|
|
|
|
bool isMainAxisRow = isRowDirection(mainAxis);
|
|
|
|
const bool isMainAxisRow = isRowDirection(mainAxis);
|
|
|
|
CSSJustify justifyContent = node->style.justifyContent;
|
|
|
|
const CSSJustify justifyContent = node->style.justifyContent;
|
|
|
|
bool isNodeFlexWrap = node->style.flexWrap == CSSWrapTypeWrap;
|
|
|
|
const bool isNodeFlexWrap = node->style.flexWrap == CSSWrapTypeWrap;
|
|
|
|
|
|
|
|
|
|
|
|
CSSNode *firstAbsoluteChild = NULL;
|
|
|
|
CSSNodeRef firstAbsoluteChild = NULL;
|
|
|
|
CSSNode *currentAbsoluteChild = NULL;
|
|
|
|
CSSNodeRef currentAbsoluteChild = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
float leadingPaddingAndBorderMain = getLeadingPaddingAndBorder(node, mainAxis);
|
|
|
|
const float leadingPaddingAndBorderMain = getLeadingPaddingAndBorder(node, mainAxis);
|
|
|
|
float trailingPaddingAndBorderMain = getTrailingPaddingAndBorder(node, mainAxis);
|
|
|
|
const float trailingPaddingAndBorderMain = getTrailingPaddingAndBorder(node, mainAxis);
|
|
|
|
float leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);
|
|
|
|
const float leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);
|
|
|
|
float paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);
|
|
|
|
const float paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);
|
|
|
|
float paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);
|
|
|
|
const float paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);
|
|
|
|
|
|
|
|
|
|
|
|
CSSMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
|
|
|
|
const CSSMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
|
|
|
|
CSSMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
|
|
|
|
const CSSMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
|
|
|
|
|
|
|
|
|
|
|
|
// STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS
|
|
|
|
// STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS
|
|
|
|
float availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
|
|
|
|
const float availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
|
|
|
|
float availableInnerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
|
|
|
|
const float availableInnerHeight =
|
|
|
|
float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight;
|
|
|
|
availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
|
|
|
|
float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;
|
|
|
|
const float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight;
|
|
|
|
|
|
|
|
const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;
|
|
|
|
|
|
|
|
|
|
|
|
// STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM
|
|
|
|
// STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM
|
|
|
|
CSSNode *child;
|
|
|
|
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
float childWidth;
|
|
|
|
float childWidth;
|
|
|
|
float childHeight;
|
|
|
|
float childHeight;
|
|
|
|
CSSMeasureMode childWidthMeasureMode;
|
|
|
|
CSSMeasureMode childWidthMeasureMode;
|
|
|
|
CSSMeasureMode childHeightMeasureMode;
|
|
|
|
CSSMeasureMode childHeightMeasureMode;
|
|
|
|
for (i = 0; i < childCount; i++) {
|
|
|
|
for (uint32_t i = 0; i < childCount; i++) {
|
|
|
|
child = CSSNodeListGet(node->children, i);
|
|
|
|
const CSSNodeRef child = CSSNodeListGet(node->children, i);
|
|
|
|
|
|
|
|
|
|
|
|
if (performLayout) {
|
|
|
|
if (performLayout) {
|
|
|
|
// Set the initial position (relative to the parent).
|
|
|
|
// Set the initial position (relative to the parent).
|
|
|
|
CSSDirection childDirection = resolveDirection(child, direction);
|
|
|
|
const CSSDirection childDirection = resolveDirection(child, direction);
|
|
|
|
setPosition(child, childDirection);
|
|
|
|
setPosition(child, childDirection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@@ -1131,7 +1134,7 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
// Max main dimension of all the lines.
|
|
|
|
// Max main dimension of all the lines.
|
|
|
|
float maxLineMainDim = 0;
|
|
|
|
float maxLineMainDim = 0;
|
|
|
|
|
|
|
|
|
|
|
|
while (endOfLineIndex < childCount) {
|
|
|
|
for (; endOfLineIndex < childCount; lineCount++, startOfLineIndex = endOfLineIndex) {
|
|
|
|
// Number of items on the currently line. May be different than the
|
|
|
|
// Number of items on the currently line. May be different than the
|
|
|
|
// difference
|
|
|
|
// difference
|
|
|
|
// between start and end indicates because we skip over absolute-positioned
|
|
|
|
// between start and end indicates because we skip over absolute-positioned
|
|
|
@@ -1147,19 +1150,18 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
float totalFlexGrowFactors = 0;
|
|
|
|
float totalFlexGrowFactors = 0;
|
|
|
|
float totalFlexShrinkScaledFactors = 0;
|
|
|
|
float totalFlexShrinkScaledFactors = 0;
|
|
|
|
|
|
|
|
|
|
|
|
i = startOfLineIndex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Maintain a linked list of the child nodes that can shrink and/or grow.
|
|
|
|
// Maintain a linked list of the child nodes that can shrink and/or grow.
|
|
|
|
CSSNode *firstRelativeChild = NULL;
|
|
|
|
CSSNodeRef firstRelativeChild = NULL;
|
|
|
|
CSSNode *currentRelativeChild = NULL;
|
|
|
|
CSSNodeRef currentRelativeChild = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
// Add items to the current line until it's full or we run out of items.
|
|
|
|
// Add items to the current line until it's full or we run out of items.
|
|
|
|
while (i < childCount) {
|
|
|
|
for (uint32_t i = startOfLineIndex; i < childCount; i++, endOfLineIndex++) {
|
|
|
|
child = CSSNodeListGet(node->children, i);
|
|
|
|
const CSSNodeRef child = CSSNodeListGet(node->children, i);
|
|
|
|
child->lineIndex = lineCount;
|
|
|
|
child->lineIndex = lineCount;
|
|
|
|
|
|
|
|
|
|
|
|
if (child->style.positionType != CSSPositionTypeAbsolute) {
|
|
|
|
if (child->style.positionType != CSSPositionTypeAbsolute) {
|
|
|
|
float outerFlexBasis = child->layout.computedFlexBasis + getMarginAxis(child, mainAxis);
|
|
|
|
const float outerFlexBasis =
|
|
|
|
|
|
|
|
child->layout.computedFlexBasis + getMarginAxis(child, mainAxis);
|
|
|
|
|
|
|
|
|
|
|
|
// If this is a multi-line flow and this item pushes us over the
|
|
|
|
// If this is a multi-line flow and this item pushes us over the
|
|
|
|
// available size, we've
|
|
|
|
// available size, we've
|
|
|
@@ -1193,14 +1195,11 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
currentRelativeChild = child;
|
|
|
|
currentRelativeChild = child;
|
|
|
|
child->nextChild = NULL;
|
|
|
|
child->nextChild = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
endOfLineIndex++;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If we don't need to measure the cross axis, we can skip the entire flex
|
|
|
|
// If we don't need to measure the cross axis, we can skip the entire flex
|
|
|
|
// step.
|
|
|
|
// step.
|
|
|
|
bool canSkipFlex = !performLayout && measureModeCrossDim == CSSMeasureModeExactly;
|
|
|
|
const bool canSkipFlex = !performLayout && measureModeCrossDim == CSSMeasureModeExactly;
|
|
|
|
|
|
|
|
|
|
|
|
// In order to position the elements in the main axis, we have two
|
|
|
|
// In order to position the elements in the main axis, we have two
|
|
|
|
// controls. The space between the beginning and the first element
|
|
|
|
// controls. The space between the beginning and the first element
|
|
|
@@ -1226,7 +1225,7 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
remainingFreeSpace = -sizeConsumedOnCurrentLine;
|
|
|
|
remainingFreeSpace = -sizeConsumedOnCurrentLine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float originalRemainingFreeSpace = remainingFreeSpace;
|
|
|
|
const float originalRemainingFreeSpace = remainingFreeSpace;
|
|
|
|
float deltaFreeSpace = 0;
|
|
|
|
float deltaFreeSpace = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (!canSkipFlex) {
|
|
|
|
if (!canSkipFlex) {
|
|
|
@@ -1387,7 +1386,8 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool requiresStretchLayout = !isStyleDimDefined(currentRelativeChild, crossAxis) &&
|
|
|
|
const bool requiresStretchLayout =
|
|
|
|
|
|
|
|
!isStyleDimDefined(currentRelativeChild, crossAxis) &&
|
|
|
|
getAlignItem(node, currentRelativeChild) == CSSAlignStretch;
|
|
|
|
getAlignItem(node, currentRelativeChild) == CSSAlignStretch;
|
|
|
|
|
|
|
|
|
|
|
|
// Recursively call the layout algorithm for this child with the updated
|
|
|
|
// Recursively call the layout algorithm for this child with the updated
|
|
|
@@ -1446,8 +1446,8 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
float mainDim = leadingPaddingAndBorderMain + leadingMainDim;
|
|
|
|
float mainDim = leadingPaddingAndBorderMain + leadingMainDim;
|
|
|
|
float crossDim = 0;
|
|
|
|
float crossDim = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (i = startOfLineIndex; i < endOfLineIndex; ++i) {
|
|
|
|
for (uint32_t i = startOfLineIndex; i < endOfLineIndex; i++) {
|
|
|
|
child = CSSNodeListGet(node->children, i);
|
|
|
|
const CSSNodeRef child = CSSNodeListGet(node->children, i);
|
|
|
|
|
|
|
|
|
|
|
|
if (child->style.positionType == CSSPositionTypeAbsolute &&
|
|
|
|
if (child->style.positionType == CSSPositionTypeAbsolute &&
|
|
|
|
isLeadingPosDefined(child, mainAxis)) {
|
|
|
|
isLeadingPosDefined(child, mainAxis)) {
|
|
|
@@ -1517,8 +1517,8 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
// STEP 7: CROSS-AXIS ALIGNMENT
|
|
|
|
// STEP 7: CROSS-AXIS ALIGNMENT
|
|
|
|
// We can skip child alignment if we're just measuring the container.
|
|
|
|
// We can skip child alignment if we're just measuring the container.
|
|
|
|
if (performLayout) {
|
|
|
|
if (performLayout) {
|
|
|
|
for (i = startOfLineIndex; i < endOfLineIndex; ++i) {
|
|
|
|
for (uint32_t i = startOfLineIndex; i < endOfLineIndex; i++) {
|
|
|
|
child = CSSNodeListGet(node->children, i);
|
|
|
|
const CSSNodeRef child = CSSNodeListGet(node->children, i);
|
|
|
|
|
|
|
|
|
|
|
|
if (child->style.positionType == CSSPositionTypeAbsolute) {
|
|
|
|
if (child->style.positionType == CSSPositionTypeAbsolute) {
|
|
|
|
// If the child is absolutely positioned and has a
|
|
|
|
// If the child is absolutely positioned and has a
|
|
|
@@ -1539,25 +1539,25 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
// For a relative children, we're either using alignItems (parent) or
|
|
|
|
// For a relative children, we're either using alignItems (parent) or
|
|
|
|
// alignSelf (child) in order to determine the position in the cross
|
|
|
|
// alignSelf (child) in order to determine the position in the cross
|
|
|
|
// axis
|
|
|
|
// axis
|
|
|
|
CSSAlign alignItem = getAlignItem(node, child);
|
|
|
|
const CSSAlign alignItem = getAlignItem(node, child);
|
|
|
|
|
|
|
|
|
|
|
|
// If the child uses align stretch, we need to lay it out one more
|
|
|
|
// If the child uses align stretch, we need to lay it out one more
|
|
|
|
// time, this time
|
|
|
|
// time, this time
|
|
|
|
// forcing the cross-axis size to be the computed cross size for the
|
|
|
|
// forcing the cross-axis size to be the computed cross size for the
|
|
|
|
// current line.
|
|
|
|
// current line.
|
|
|
|
if (alignItem == CSSAlignStretch) {
|
|
|
|
if (alignItem == CSSAlignStretch) {
|
|
|
|
childWidth = child->layout.measuredDimensions[CSSDimensionWidth] +
|
|
|
|
const bool isCrossSizeDefinite =
|
|
|
|
getMarginAxis(child, CSSFlexDirectionRow);
|
|
|
|
(isMainAxisRow && isStyleDimDefined(child, CSSFlexDirectionColumn)) ||
|
|
|
|
childHeight = child->layout.measuredDimensions[CSSDimensionHeight] +
|
|
|
|
(!isMainAxisRow && isStyleDimDefined(child, CSSFlexDirectionRow));
|
|
|
|
getMarginAxis(child, CSSFlexDirectionColumn);
|
|
|
|
|
|
|
|
bool isCrossSizeDefinite = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isMainAxisRow) {
|
|
|
|
if (isMainAxisRow) {
|
|
|
|
isCrossSizeDefinite = isStyleDimDefined(child, CSSFlexDirectionColumn);
|
|
|
|
|
|
|
|
childHeight = crossDim;
|
|
|
|
childHeight = crossDim;
|
|
|
|
|
|
|
|
childWidth = child->layout.measuredDimensions[CSSDimensionWidth] +
|
|
|
|
|
|
|
|
getMarginAxis(child, CSSFlexDirectionRow);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
isCrossSizeDefinite = isStyleDimDefined(child, CSSFlexDirectionRow);
|
|
|
|
|
|
|
|
childWidth = crossDim;
|
|
|
|
childWidth = crossDim;
|
|
|
|
|
|
|
|
childHeight = child->layout.measuredDimensions[CSSDimensionHeight] +
|
|
|
|
|
|
|
|
getMarginAxis(child, CSSFlexDirectionColumn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If the child defines a definite size for its cross axis, there's
|
|
|
|
// If the child defines a definite size for its cross axis, there's
|
|
|
@@ -1577,7 +1577,7 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
"stretch");
|
|
|
|
"stretch");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (alignItem != CSSAlignFlexStart) {
|
|
|
|
} else if (alignItem != CSSAlignFlexStart) {
|
|
|
|
float remainingCrossDim = containerCrossAxis - getDimWithMargin(child, crossAxis);
|
|
|
|
const float remainingCrossDim = containerCrossAxis - getDimWithMargin(child, crossAxis);
|
|
|
|
|
|
|
|
|
|
|
|
if (alignItem == CSSAlignCenter) {
|
|
|
|
if (alignItem == CSSAlignCenter) {
|
|
|
|
leadingCrossDim += remainingCrossDim / 2;
|
|
|
|
leadingCrossDim += remainingCrossDim / 2;
|
|
|
@@ -1594,21 +1594,16 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
|
|
|
|
|
|
|
|
totalLineCrossDim += crossDim;
|
|
|
|
totalLineCrossDim += crossDim;
|
|
|
|
maxLineMainDim = fmaxf(maxLineMainDim, mainDim);
|
|
|
|
maxLineMainDim = fmaxf(maxLineMainDim, mainDim);
|
|
|
|
|
|
|
|
|
|
|
|
// Reset variables for new line.
|
|
|
|
|
|
|
|
lineCount++;
|
|
|
|
|
|
|
|
startOfLineIndex = endOfLineIndex;
|
|
|
|
|
|
|
|
endOfLineIndex = startOfLineIndex;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// STEP 8: MULTI-LINE CONTENT ALIGNMENT
|
|
|
|
// STEP 8: MULTI-LINE CONTENT ALIGNMENT
|
|
|
|
if (lineCount > 1 && performLayout && !CSSValueIsUndefined(availableInnerCrossDim)) {
|
|
|
|
if (lineCount > 1 && performLayout && !CSSValueIsUndefined(availableInnerCrossDim)) {
|
|
|
|
float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim;
|
|
|
|
const float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim;
|
|
|
|
|
|
|
|
|
|
|
|
float crossDimLead = 0;
|
|
|
|
float crossDimLead = 0;
|
|
|
|
float currentLead = leadingPaddingAndBorderCross;
|
|
|
|
float currentLead = leadingPaddingAndBorderCross;
|
|
|
|
|
|
|
|
|
|
|
|
CSSAlign alignContent = node->style.alignContent;
|
|
|
|
const CSSAlign alignContent = node->style.alignContent;
|
|
|
|
if (alignContent == CSSAlignFlexEnd) {
|
|
|
|
if (alignContent == CSSAlignFlexEnd) {
|
|
|
|
currentLead += remainingAlignContentDim;
|
|
|
|
currentLead += remainingAlignContentDim;
|
|
|
|
} else if (alignContent == CSSAlignCenter) {
|
|
|
|
} else if (alignContent == CSSAlignCenter) {
|
|
|
@@ -1620,14 +1615,14 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t endIndex = 0;
|
|
|
|
uint32_t endIndex = 0;
|
|
|
|
for (i = 0; i < lineCount; ++i) {
|
|
|
|
for (uint32_t i = 0; i < lineCount; i++) {
|
|
|
|
uint32_t startIndex = endIndex;
|
|
|
|
uint32_t startIndex = endIndex;
|
|
|
|
uint32_t j;
|
|
|
|
uint32_t ii;
|
|
|
|
|
|
|
|
|
|
|
|
// compute the line's height and find the endIndex
|
|
|
|
// compute the line's height and find the endIndex
|
|
|
|
float lineHeight = 0;
|
|
|
|
float lineHeight = 0;
|
|
|
|
for (j = startIndex; j < childCount; ++j) {
|
|
|
|
for (ii = startIndex; ii < childCount; ii++) {
|
|
|
|
child = CSSNodeListGet(node->children, j);
|
|
|
|
const CSSNodeRef child = CSSNodeListGet(node->children, ii);
|
|
|
|
if (child->style.positionType != CSSPositionTypeRelative) {
|
|
|
|
if (child->style.positionType != CSSPositionTypeRelative) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -1640,17 +1635,17 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
getMarginAxis(child, crossAxis));
|
|
|
|
getMarginAxis(child, crossAxis));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
endIndex = j;
|
|
|
|
endIndex = ii;
|
|
|
|
lineHeight += crossDimLead;
|
|
|
|
lineHeight += crossDimLead;
|
|
|
|
|
|
|
|
|
|
|
|
if (performLayout) {
|
|
|
|
if (performLayout) {
|
|
|
|
for (j = startIndex; j < endIndex; ++j) {
|
|
|
|
for (ii = startIndex; ii < endIndex; ii++) {
|
|
|
|
child = CSSNodeListGet(node->children, j);
|
|
|
|
const CSSNodeRef child = CSSNodeListGet(node->children, ii);
|
|
|
|
if (child->style.positionType != CSSPositionTypeRelative) {
|
|
|
|
if (child->style.positionType != CSSPositionTypeRelative) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CSSAlign alignContentAlignItem = getAlignItem(node, child);
|
|
|
|
const CSSAlign alignContentAlignItem = getAlignItem(node, child);
|
|
|
|
if (alignContentAlignItem == CSSAlignFlexStart) {
|
|
|
|
if (alignContentAlignItem == CSSAlignFlexStart) {
|
|
|
|
child->layout.position[pos[crossAxis]] =
|
|
|
|
child->layout.position[pos[crossAxis]] =
|
|
|
|
currentLead + getLeadingMargin(child, crossAxis);
|
|
|
|
currentLead + getLeadingMargin(child, crossAxis);
|
|
|
@@ -1824,21 +1819,15 @@ static void layoutNodeImpl(CSSNode *node,
|
|
|
|
|
|
|
|
|
|
|
|
// STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN
|
|
|
|
// STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN
|
|
|
|
if (performLayout) {
|
|
|
|
if (performLayout) {
|
|
|
|
bool needsMainTrailingPos = false;
|
|
|
|
const bool needsMainTrailingPos =
|
|
|
|
bool needsCrossTrailingPos = false;
|
|
|
|
mainAxis == CSSFlexDirectionRowReverse || mainAxis == CSSFlexDirectionColumnReverse;
|
|
|
|
|
|
|
|
const bool needsCrossTrailingPos =
|
|
|
|
if (mainAxis == CSSFlexDirectionRowReverse || mainAxis == CSSFlexDirectionColumnReverse) {
|
|
|
|
CSSFlexDirectionRowReverse || crossAxis == CSSFlexDirectionColumnReverse;
|
|
|
|
needsMainTrailingPos = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (crossAxis == CSSFlexDirectionRowReverse || crossAxis == CSSFlexDirectionColumnReverse) {
|
|
|
|
|
|
|
|
needsCrossTrailingPos = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set trailing position if necessary.
|
|
|
|
// Set trailing position if necessary.
|
|
|
|
if (needsMainTrailingPos || needsCrossTrailingPos) {
|
|
|
|
if (needsMainTrailingPos || needsCrossTrailingPos) {
|
|
|
|
for (i = 0; i < childCount; ++i) {
|
|
|
|
for (uint32_t i = 0; i < childCount; i++) {
|
|
|
|
child = CSSNodeListGet(node->children, i);
|
|
|
|
const CSSNodeRef child = CSSNodeListGet(node->children, i);
|
|
|
|
|
|
|
|
|
|
|
|
if (needsMainTrailingPos) {
|
|
|
|
if (needsMainTrailingPos) {
|
|
|
|
setTrailingPosition(node, child, mainAxis);
|
|
|
|
setTrailingPosition(node, child, mainAxis);
|
|
|
@@ -1859,15 +1848,16 @@ bool gPrintSkips = false;
|
|
|
|
|
|
|
|
|
|
|
|
static const char *spacer = " ";
|
|
|
|
static const char *spacer = " ";
|
|
|
|
|
|
|
|
|
|
|
|
static const char *getSpacer(unsigned long level) {
|
|
|
|
static const char *getSpacer(const unsigned long level) {
|
|
|
|
unsigned long spacerLen = strlen(spacer);
|
|
|
|
const unsigned long spacerLen = strlen(spacer);
|
|
|
|
if (level > spacerLen) {
|
|
|
|
if (level > spacerLen) {
|
|
|
|
level = spacerLen;
|
|
|
|
return &spacer[0];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return &spacer[spacerLen - level];
|
|
|
|
return &spacer[spacerLen - level];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char *getModeName(CSSMeasureMode mode, bool performLayout) {
|
|
|
|
static const char *getModeName(const CSSMeasureMode mode, const bool performLayout) {
|
|
|
|
const char *kMeasureModeNames[CSSMeasureModeCount] = {"UNDEFINED", "EXACTLY", "AT_MOST"};
|
|
|
|
const char *kMeasureModeNames[CSSMeasureModeCount] = {"UNDEFINED", "EXACTLY", "AT_MOST"};
|
|
|
|
const char *kLayoutModeNames[CSSMeasureModeCount] = {"LAY_UNDEFINED",
|
|
|
|
const char *kLayoutModeNames[CSSMeasureModeCount] = {"LAY_UNDEFINED",
|
|
|
|
"LAY_EXACTLY",
|
|
|
|
"LAY_EXACTLY",
|
|
|
@@ -1881,20 +1871,20 @@ static const char *getModeName(CSSMeasureMode mode, bool performLayout) {
|
|
|
|
return performLayout ? kLayoutModeNames[mode] : kMeasureModeNames[mode];
|
|
|
|
return performLayout ? kLayoutModeNames[mode] : kMeasureModeNames[mode];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool canUseCachedMeasurement(bool isTextNode,
|
|
|
|
static bool canUseCachedMeasurement(const bool isTextNode,
|
|
|
|
float availableWidth,
|
|
|
|
const float availableWidth,
|
|
|
|
float availableHeight,
|
|
|
|
const float availableHeight,
|
|
|
|
float margin_row,
|
|
|
|
const float margin_row,
|
|
|
|
float margin_column,
|
|
|
|
const float margin_column,
|
|
|
|
CSSMeasureMode widthMeasureMode,
|
|
|
|
const CSSMeasureMode widthMeasureMode,
|
|
|
|
CSSMeasureMode heightMeasureMode,
|
|
|
|
const CSSMeasureMode heightMeasureMode,
|
|
|
|
CSSCachedMeasurement cached_layout) {
|
|
|
|
CSSCachedMeasurement cached_layout) {
|
|
|
|
bool is_height_same = (cached_layout.heightMeasureMode == CSSMeasureModeUndefined &&
|
|
|
|
const bool is_height_same = (cached_layout.heightMeasureMode == CSSMeasureModeUndefined &&
|
|
|
|
heightMeasureMode == CSSMeasureModeUndefined) ||
|
|
|
|
heightMeasureMode == CSSMeasureModeUndefined) ||
|
|
|
|
(cached_layout.heightMeasureMode == heightMeasureMode &&
|
|
|
|
(cached_layout.heightMeasureMode == heightMeasureMode &&
|
|
|
|
eq(cached_layout.availableHeight, availableHeight));
|
|
|
|
eq(cached_layout.availableHeight, availableHeight));
|
|
|
|
|
|
|
|
|
|
|
|
bool is_width_same = (cached_layout.widthMeasureMode == CSSMeasureModeUndefined &&
|
|
|
|
const bool is_width_same = (cached_layout.widthMeasureMode == CSSMeasureModeUndefined &&
|
|
|
|
widthMeasureMode == CSSMeasureModeUndefined) ||
|
|
|
|
widthMeasureMode == CSSMeasureModeUndefined) ||
|
|
|
|
(cached_layout.widthMeasureMode == widthMeasureMode &&
|
|
|
|
(cached_layout.widthMeasureMode == widthMeasureMode &&
|
|
|
|
eq(cached_layout.availableWidth, availableWidth));
|
|
|
|
eq(cached_layout.availableWidth, availableWidth));
|
|
|
@@ -1903,7 +1893,8 @@ static bool canUseCachedMeasurement(bool isTextNode,
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool is_height_valid = (cached_layout.heightMeasureMode == CSSMeasureModeUndefined &&
|
|
|
|
const bool is_height_valid =
|
|
|
|
|
|
|
|
(cached_layout.heightMeasureMode == CSSMeasureModeUndefined &&
|
|
|
|
heightMeasureMode == CSSMeasureModeAtMost &&
|
|
|
|
heightMeasureMode == CSSMeasureModeAtMost &&
|
|
|
|
cached_layout.computedHeight <= (availableHeight - margin_column)) ||
|
|
|
|
cached_layout.computedHeight <= (availableHeight - margin_column)) ||
|
|
|
|
(heightMeasureMode == CSSMeasureModeExactly &&
|
|
|
|
(heightMeasureMode == CSSMeasureModeExactly &&
|
|
|
@@ -1913,7 +1904,7 @@ static bool canUseCachedMeasurement(bool isTextNode,
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool is_width_valid = (cached_layout.widthMeasureMode == CSSMeasureModeUndefined &&
|
|
|
|
const bool is_width_valid = (cached_layout.widthMeasureMode == CSSMeasureModeUndefined &&
|
|
|
|
widthMeasureMode == CSSMeasureModeAtMost &&
|
|
|
|
widthMeasureMode == CSSMeasureModeAtMost &&
|
|
|
|
cached_layout.computedWidth <= (availableWidth - margin_row)) ||
|
|
|
|
cached_layout.computedWidth <= (availableWidth - margin_row)) ||
|
|
|
|
(widthMeasureMode == CSSMeasureModeExactly &&
|
|
|
|
(widthMeasureMode == CSSMeasureModeExactly &&
|
|
|
@@ -1975,19 +1966,20 @@ static bool canUseCachedMeasurement(bool isTextNode,
|
|
|
|
// Input parameters are the same as layoutNodeImpl (see above)
|
|
|
|
// Input parameters are the same as layoutNodeImpl (see above)
|
|
|
|
// Return parameter is true if layout was performed, false if skipped
|
|
|
|
// Return parameter is true if layout was performed, false if skipped
|
|
|
|
//
|
|
|
|
//
|
|
|
|
bool layoutNodeInternal(CSSNode *node,
|
|
|
|
bool layoutNodeInternal(const CSSNodeRef node,
|
|
|
|
float availableWidth,
|
|
|
|
const float availableWidth,
|
|
|
|
float availableHeight,
|
|
|
|
const float availableHeight,
|
|
|
|
CSSDirection parentDirection,
|
|
|
|
const CSSDirection parentDirection,
|
|
|
|
CSSMeasureMode widthMeasureMode,
|
|
|
|
const CSSMeasureMode widthMeasureMode,
|
|
|
|
CSSMeasureMode heightMeasureMode,
|
|
|
|
const CSSMeasureMode heightMeasureMode,
|
|
|
|
bool performLayout,
|
|
|
|
const bool performLayout,
|
|
|
|
char *reason) {
|
|
|
|
const char *reason) {
|
|
|
|
CSSLayout *layout = &node->layout;
|
|
|
|
CSSLayout *layout = &node->layout;
|
|
|
|
|
|
|
|
|
|
|
|
gDepth++;
|
|
|
|
gDepth++;
|
|
|
|
|
|
|
|
|
|
|
|
bool needToVisitNode = (node->isDirty && layout->generationCount != gCurrentGenerationCount) ||
|
|
|
|
const bool needToVisitNode =
|
|
|
|
|
|
|
|
(node->isDirty && layout->generationCount != gCurrentGenerationCount) ||
|
|
|
|
layout->lastParentDirection != parentDirection;
|
|
|
|
layout->lastParentDirection != parentDirection;
|
|
|
|
|
|
|
|
|
|
|
|
if (needToVisitNode) {
|
|
|
|
if (needToVisitNode) {
|
|
|
@@ -2012,8 +2004,8 @@ bool layoutNodeInternal(CSSNode *node,
|
|
|
|
// expensive to measure, so it's worth avoiding redundant measurements if at
|
|
|
|
// expensive to measure, so it's worth avoiding redundant measurements if at
|
|
|
|
// all possible.
|
|
|
|
// all possible.
|
|
|
|
if (node->measure) {
|
|
|
|
if (node->measure) {
|
|
|
|
float marginAxisRow = getMarginAxis(node, CSSFlexDirectionRow);
|
|
|
|
const float marginAxisRow = getMarginAxis(node, CSSFlexDirectionRow);
|
|
|
|
float marginAxisColumn = getMarginAxis(node, CSSFlexDirectionColumn);
|
|
|
|
const float marginAxisColumn = getMarginAxis(node, CSSFlexDirectionColumn);
|
|
|
|
|
|
|
|
|
|
|
|
// First, try to use the layout cache.
|
|
|
|
// First, try to use the layout cache.
|
|
|
|
if (canUseCachedMeasurement(node->isTextNode,
|
|
|
|
if (canUseCachedMeasurement(node->isTextNode,
|
|
|
@@ -2155,10 +2147,10 @@ bool layoutNodeInternal(CSSNode *node,
|
|
|
|
return (needToVisitNode || cachedResults == NULL);
|
|
|
|
return (needToVisitNode || cachedResults == NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CSSNodeCalculateLayout(CSSNode *node,
|
|
|
|
void CSSNodeCalculateLayout(const CSSNodeRef node,
|
|
|
|
float availableWidth,
|
|
|
|
const float availableWidth,
|
|
|
|
float availableHeight,
|
|
|
|
const float availableHeight,
|
|
|
|
CSSDirection parentDirection) {
|
|
|
|
const CSSDirection parentDirection) {
|
|
|
|
// Increment the generation count. This will force the recursive routine to
|
|
|
|
// Increment the generation count. This will force the recursive routine to
|
|
|
|
// visit
|
|
|
|
// visit
|
|
|
|
// all dirty nodes at least once. Subsequent visits will be skipped if the
|
|
|
|
// all dirty nodes at least once. Subsequent visits will be skipped if the
|
|
|
@@ -2166,39 +2158,42 @@ void CSSNodeCalculateLayout(CSSNode *node,
|
|
|
|
// parameters don't change.
|
|
|
|
// parameters don't change.
|
|
|
|
gCurrentGenerationCount++;
|
|
|
|
gCurrentGenerationCount++;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float width = availableWidth;
|
|
|
|
|
|
|
|
float height = availableHeight;
|
|
|
|
CSSMeasureMode widthMeasureMode = CSSMeasureModeUndefined;
|
|
|
|
CSSMeasureMode widthMeasureMode = CSSMeasureModeUndefined;
|
|
|
|
CSSMeasureMode heightMeasureMode = CSSMeasureModeUndefined;
|
|
|
|
CSSMeasureMode heightMeasureMode = CSSMeasureModeUndefined;
|
|
|
|
|
|
|
|
|
|
|
|
if (!CSSValueIsUndefined(availableWidth)) {
|
|
|
|
if (!CSSValueIsUndefined(width)) {
|
|
|
|
widthMeasureMode = CSSMeasureModeExactly;
|
|
|
|
widthMeasureMode = CSSMeasureModeExactly;
|
|
|
|
} else if (isStyleDimDefined(node, CSSFlexDirectionRow)) {
|
|
|
|
} else if (isStyleDimDefined(node, CSSFlexDirectionRow)) {
|
|
|
|
availableWidth =
|
|
|
|
width =
|
|
|
|
node->style.dimensions[dim[CSSFlexDirectionRow]] + getMarginAxis(node, CSSFlexDirectionRow);
|
|
|
|
node->style.dimensions[dim[CSSFlexDirectionRow]] + getMarginAxis(node, CSSFlexDirectionRow);
|
|
|
|
widthMeasureMode = CSSMeasureModeExactly;
|
|
|
|
widthMeasureMode = CSSMeasureModeExactly;
|
|
|
|
} else if (node->style.maxDimensions[CSSDimensionWidth] >= 0.0) {
|
|
|
|
} else if (node->style.maxDimensions[CSSDimensionWidth] >= 0.0) {
|
|
|
|
availableWidth = node->style.maxDimensions[CSSDimensionWidth];
|
|
|
|
width = node->style.maxDimensions[CSSDimensionWidth];
|
|
|
|
widthMeasureMode = CSSMeasureModeAtMost;
|
|
|
|
widthMeasureMode = CSSMeasureModeAtMost;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!CSSValueIsUndefined(availableHeight)) {
|
|
|
|
if (!CSSValueIsUndefined(height)) {
|
|
|
|
heightMeasureMode = CSSMeasureModeExactly;
|
|
|
|
heightMeasureMode = CSSMeasureModeExactly;
|
|
|
|
} else if (isStyleDimDefined(node, CSSFlexDirectionColumn)) {
|
|
|
|
} else if (isStyleDimDefined(node, CSSFlexDirectionColumn)) {
|
|
|
|
availableHeight = node->style.dimensions[dim[CSSFlexDirectionColumn]] +
|
|
|
|
height = node->style.dimensions[dim[CSSFlexDirectionColumn]] +
|
|
|
|
getMarginAxis(node, CSSFlexDirectionColumn);
|
|
|
|
getMarginAxis(node, CSSFlexDirectionColumn);
|
|
|
|
heightMeasureMode = CSSMeasureModeExactly;
|
|
|
|
heightMeasureMode = CSSMeasureModeExactly;
|
|
|
|
} else if (node->style.maxDimensions[CSSDimensionHeight] >= 0.0) {
|
|
|
|
} else if (node->style.maxDimensions[CSSDimensionHeight] >= 0.0) {
|
|
|
|
availableHeight = node->style.maxDimensions[CSSDimensionHeight];
|
|
|
|
height = node->style.maxDimensions[CSSDimensionHeight];
|
|
|
|
heightMeasureMode = CSSMeasureModeAtMost;
|
|
|
|
heightMeasureMode = CSSMeasureModeAtMost;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (layoutNodeInternal(node,
|
|
|
|
if (layoutNodeInternal(node,
|
|
|
|
availableWidth,
|
|
|
|
width,
|
|
|
|
availableHeight,
|
|
|
|
height,
|
|
|
|
parentDirection,
|
|
|
|
parentDirection,
|
|
|
|
widthMeasureMode,
|
|
|
|
widthMeasureMode,
|
|
|
|
heightMeasureMode,
|
|
|
|
heightMeasureMode,
|
|
|
|
true,
|
|
|
|
true,
|
|
|
|
"initial")) {
|
|
|
|
"initia"
|
|
|
|
|
|
|
|
"l")) {
|
|
|
|
setPosition(node, node->layout.direction);
|
|
|
|
setPosition(node, node->layout.direction);
|
|
|
|
|
|
|
|
|
|
|
|
if (gPrintTree) {
|
|
|
|
if (gPrintTree) {
|
|
|
|