render_flexbox.cpp [plain text]
#include "render_flexbox.h"
using namespace DOM;
namespace khtml {
class FlexBoxIterator {
public:
FlexBoxIterator(RenderFlexibleBox* parent) {
box = parent;
if (box->style()->boxOrient() == HORIZONTAL && box->style()->direction() == RTL)
forward = box->style()->boxDirection() != BNORMAL;
else
forward = box->style()->boxDirection() == BNORMAL;
lastOrdinal = 1;
if (!forward) {
RenderObject* child = box->firstChild();
while (child) {
if (child->style()->boxOrdinalGroup() > lastOrdinal)
lastOrdinal = child->style()->boxOrdinalGroup();
child = child->nextSibling();
}
}
reset();
}
void reset() {
current = 0;
currentOrdinal = forward ? 0 : lastOrdinal+1;
}
RenderObject* first() {
reset();
return next();
}
RenderObject* next() {
do {
if (!current) {
if (forward) {
currentOrdinal++;
if (currentOrdinal > lastOrdinal)
return 0;
current = box->firstChild();
}
else {
currentOrdinal--;
if (currentOrdinal == 0)
return 0;
current = box->lastChild();
}
}
else
current = forward ? current->nextSibling() : current->previousSibling();
if (current && current->style()->boxOrdinalGroup() > lastOrdinal)
lastOrdinal = current->style()->boxOrdinalGroup();
} while (!current || current->style()->boxOrdinalGroup() != currentOrdinal ||
current->style()->visibility() == COLLAPSE);
return current;
}
private:
RenderFlexibleBox* box;
RenderObject* current;
bool forward;
unsigned int currentOrdinal;
unsigned int lastOrdinal;
};
RenderFlexibleBox::RenderFlexibleBox(DOM::NodeImpl* node)
:RenderBlock(node)
{
setChildrenInline(false); m_flexingChildren = m_stretchingChildren = false;
}
RenderFlexibleBox::~RenderFlexibleBox()
{
}
void RenderFlexibleBox::calcHorizontalMinMaxWidth()
{
RenderObject *child = firstChild();
while (child) {
if (child->isPositioned() || child->style()->visibility() == COLLAPSE)
{
child = child->nextSibling();
continue;
}
int margin=0;
Length ml = child->style()->marginLeft();
Length mr = child->style()->marginRight();
child->calcWidth();
if (!(ml.type==Variable) && !(mr.type==Variable))
{
if (!(child->style()->width().type==Variable))
{
if (child->style()->direction()==LTR)
margin = child->marginLeft();
else
margin = child->marginRight();
}
else
margin = child->marginLeft()+child->marginRight();
}
else if (!(ml.type == Variable))
margin = child->marginLeft();
else if (!(mr.type == Variable))
margin = child->marginRight();
if (margin < 0) margin = 0;
m_minWidth += child->minWidth() + margin;
m_maxWidth += child->maxWidth() + margin;
child = child->nextSibling();
}
}
void RenderFlexibleBox::calcVerticalMinMaxWidth()
{
RenderObject *child = firstChild();
while(child != 0)
{
if (child->isPositioned() || child->style()->visibility() == COLLAPSE) {
child = child->nextSibling();
continue;
}
Length ml = child->style()->marginLeft();
Length mr = child->style()->marginRight();
if (ml.type == Percent || mr.type == Percent)
calcWidth();
int margin = 0;
if (ml.type == Fixed)
margin += ml.value;
else if (ml.type == Percent)
margin += child->marginLeft();
if (mr.type == Fixed)
margin += mr.value;
else if (mr.type == Percent)
margin += child->marginRight();
if (margin < 0) margin = 0;
int w = child->minWidth() + margin;
if(m_minWidth < w) m_minWidth = w;
w = child->maxWidth() + margin;
if(m_maxWidth < w) m_maxWidth = w;
child = child->nextSibling();
}
}
void RenderFlexibleBox::calcMinMaxWidth()
{
KHTMLAssert( !minMaxKnown() );
m_minWidth = 0;
m_maxWidth = 0;
if (hasMultipleLines() || isVertical())
calcVerticalMinMaxWidth();
else
calcHorizontalMinMaxWidth();
if(m_maxWidth < m_minWidth) m_maxWidth = m_minWidth;
if (style()->width().isFixed() && style()->width().value > 0)
m_minWidth = m_maxWidth = style()->width().value;
if (style()->minWidth().isFixed() && style()->minWidth().value > 0) {
m_maxWidth = kMax(m_maxWidth, style()->minWidth().value);
m_minWidth = kMax(m_minWidth, style()->minWidth().value);
}
if (style()->maxWidth().isFixed() && style()->maxWidth().value != UNDEFINED) {
m_maxWidth = kMin(m_maxWidth, style()->maxWidth().value);
m_minWidth = kMin(m_minWidth, style()->maxWidth().value);
}
int toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
m_minWidth += toAdd;
m_maxWidth += toAdd;
setMinMaxKnown();
}
void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
{
KHTMLAssert(needsLayout());
KHTMLAssert(minMaxKnown());
if (!relayoutChildren && posChildNeedsLayout() && !normalChildNeedsLayout() && !selfNeedsLayout()) {
layoutPositionedObjects(relayoutChildren);
if (hasOverflowClip())
m_layer->updateScrollInfoAfterLayout();
setNeedsLayout(false);
return;
}
QRect oldBounds;
bool checkForRepaint = checkForRepaintDuringLayout();
if (checkForRepaint)
oldBounds = getAbsoluteRepaintRect();
int oldWidth = m_width;
int oldHeight = m_height;
calcWidth();
calcHeight();
m_overflowWidth = m_width;
if (oldWidth != m_width || oldHeight != m_height ||
(parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL &&
parent()->style()->boxAlign() == BSTRETCH))
relayoutChildren = true;
m_height = 0;
m_overflowHeight = 0;
m_flexingChildren = m_stretchingChildren = false;
initMaxMarginValues();
if (scrollsOverflow()) {
if (style()->overflow() == OSCROLL) {
m_layer->setHasHorizontalScrollbar(true);
m_layer->setHasVerticalScrollbar(true);
}
m_layer->moveScrollbarsAside();
}
if (isHorizontal())
layoutHorizontalBox(relayoutChildren);
else
layoutVerticalBox(relayoutChildren);
oldHeight = m_height;
calcHeight();
if (oldHeight != m_height) {
relayoutChildren = true;
if (m_overflowHeight > m_height)
m_overflowHeight -= (borderBottom()+paddingBottom());
if (m_overflowHeight < m_height)
m_overflowHeight = m_height;
}
layoutPositionedObjects( relayoutChildren );
if (!isFloatingOrPositioned() && m_height == 0) {
if (m_maxBottomPosMargin > m_maxTopPosMargin)
m_maxTopPosMargin = m_maxBottomPosMargin;
if (m_maxBottomNegMargin > m_maxTopNegMargin)
m_maxTopNegMargin = m_maxBottomNegMargin;
m_maxBottomNegMargin = m_maxBottomPosMargin = 0;
}
if (m_overflowWidth < m_width)
m_overflowWidth = m_width;
if (hasOverflowClip())
m_layer->updateScrollInfoAfterLayout();
if (checkForRepaint)
repaintAfterLayoutIfNeeded(oldBounds, oldBounds);
setNeedsLayout(false);
}
void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
{
int toAdd = borderBottom() + paddingBottom();
int yPos = borderTop() + paddingTop();
int xPos = borderLeft() + paddingLeft();
bool heightSpecified = false;
int oldHeight = 0;
unsigned int highestFlexGroup = 0;
unsigned int lowestFlexGroup = 0;
bool haveFlex = false;
int remainingSpace = 0;
m_overflowHeight = m_height;
FlexBoxIterator iterator(this);
RenderObject* child = iterator.next();
while (child) {
if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) {
child->setOverrideSize(-1);
if (!relayoutChildren)
child->setChildNeedsLayout(true, false);
haveFlex = true;
unsigned int flexGroup = child->style()->boxFlexGroup();
if (lowestFlexGroup == 0)
lowestFlexGroup = flexGroup;
if (flexGroup < lowestFlexGroup)
lowestFlexGroup = flexGroup;
if (flexGroup > highestFlexGroup)
highestFlexGroup = flexGroup;
}
child = iterator.next();
}
do {
m_height = yPos;
m_overflowHeight = m_height;
xPos = borderLeft() + paddingLeft();
int maxAscent = 0, maxDescent = 0;
child = iterator.first();
while (child) {
if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))
child->setChildNeedsLayout(true, false);
if (child->isPositioned()) {
child = iterator.next();
continue;
}
child->calcVerticalMargins();
child->layoutIfNeeded();
if (style()->boxAlign() == BBASELINE) {
int ascent = child->marginTop() + child->getBaselineOfFirstLineBox();
if (ascent == -1)
ascent = child->marginTop() + child->height() + child->marginBottom();
int descent = (child->marginTop() + child->height() + child->marginBottom()) - ascent;
maxAscent = kMax(maxAscent, ascent);
maxDescent = kMax(maxDescent, descent);
m_height = kMax(yPos + maxAscent + maxDescent, m_height);
}
else
m_height = kMax(m_height, yPos + child->marginTop() + child->height() + child->marginBottom());
child = iterator.next();
}
m_height += toAdd;
if (m_overflowHeight < m_height)
m_overflowHeight = m_height;
oldHeight = m_height;
calcHeight();
relayoutChildren = false;
if (oldHeight != m_height) {
heightSpecified = true;
if (m_overflowHeight > m_height)
m_overflowHeight -= (borderBottom() + paddingBottom());
if (m_overflowHeight < m_height)
m_overflowHeight = m_height;
}
m_stretchingChildren = (style()->boxAlign() == BSTRETCH);
child = iterator.first();
while (child) {
if (child->isPositioned()) {
child->containingBlock()->insertPositionedObject(child);
if (child->hasStaticX()) {
if (style()->direction() == LTR)
child->setStaticX(xPos);
else child->setStaticX(width() - xPos);
}
if (child->hasStaticY())
child->setStaticY(yPos);
child = iterator.next();
continue;
}
int oldChildHeight = child->height();
static_cast<RenderBox*>(child)->calcHeight();
if (oldChildHeight != child->height())
child->setChildNeedsLayout(true, false);
child->layoutIfNeeded();
xPos += child->marginLeft();
int childY = yPos;
switch (style()->boxAlign()) {
case BCENTER:
childY += child->marginTop() + (contentHeight() - (child->height() + child->marginTop() + child->marginBottom()))/2;
break;
case BBASELINE: {
int ascent = child->marginTop() + child->getBaselineOfFirstLineBox();
if (ascent == -1)
ascent = child->marginTop() + child->height() + child->marginBottom();
childY += child->marginTop() + (maxAscent - ascent);
break;
}
case BEND:
childY += contentHeight() - child->marginBottom() - child->height();
break;
default: childY += child->marginTop();
break;
}
placeChild(child, xPos, childY);
m_overflowHeight = kMax(m_overflowHeight, childY + child->overflowHeight(false));
xPos += child->width() + child->marginRight();
child = iterator.next();
}
remainingSpace = borderLeft() + paddingLeft() + contentWidth() - xPos;
m_stretchingChildren = false;
if (m_flexingChildren)
haveFlex = false; else if (haveFlex) {
if (!remainingSpace)
break;
bool expanding = remainingSpace > 0;
unsigned int start = expanding ? lowestFlexGroup : highestFlexGroup;
unsigned int end = expanding? highestFlexGroup : lowestFlexGroup;
for (unsigned int i = start; i <= end && remainingSpace; i++) {
int groupRemainingSpace = remainingSpace;
do {
float totalFlex = 0.0f;
child = iterator.first();
while (child) {
if (allowedChildFlex(child, expanding, i))
totalFlex += child->style()->boxFlex();
child = iterator.next();
}
child = iterator.first();
int spaceAvailableThisPass = groupRemainingSpace;
while (child) {
int allowedFlex = allowedChildFlex(child, expanding, i);
if (allowedFlex) {
int projectedFlex = (allowedFlex == INT_MAX) ? allowedFlex : (int)(allowedFlex * (totalFlex / child->style()->boxFlex()));
spaceAvailableThisPass = expanding ? kMin(spaceAvailableThisPass, projectedFlex) : kMax(spaceAvailableThisPass, projectedFlex);
}
child = iterator.next();
}
if (!spaceAvailableThisPass || totalFlex == 0.0f) {
groupRemainingSpace = 0;
continue;
}
child = iterator.first();
while (child && spaceAvailableThisPass && totalFlex) {
if (allowedChildFlex(child, expanding, i)) {
int spaceAdd = (int)(spaceAvailableThisPass * (child->style()->boxFlex()/totalFlex));
if (spaceAdd) {
child->setOverrideSize(child->overrideWidth() + spaceAdd);
m_flexingChildren = true;
relayoutChildren = true;
}
spaceAvailableThisPass -= spaceAdd;
remainingSpace -= spaceAdd;
groupRemainingSpace -= spaceAdd;
totalFlex -= child->style()->boxFlex();
}
child = iterator.next();
}
} while (groupRemainingSpace);
}
if (haveFlex && !m_flexingChildren)
haveFlex = false;
}
} while (haveFlex);
m_flexingChildren = false;
if (xPos > m_overflowWidth)
m_overflowWidth = xPos;
if (remainingSpace > 0 && ((style()->direction() == LTR && style()->boxPack() != BSTART) ||
(style()->direction() == RTL && style()->boxPack() != BEND))) {
int offset = 0;
if (style()->boxPack() == BJUSTIFY) {
int totalChildren = 0;
child = iterator.first();
while (child) {
if (child->isPositioned()) {
child = iterator.next();
continue;
}
totalChildren++;
child = iterator.next();
}
if (totalChildren > 1) {
totalChildren--;
bool firstChild = true;
child = iterator.first();
while (child) {
if (child->isPositioned()) {
child = iterator.next();
continue;
}
if (firstChild) {
firstChild = false;
child = iterator.next();
continue;
}
offset += remainingSpace/totalChildren;
remainingSpace -= (remainingSpace/totalChildren);
totalChildren--;
placeChild(child, child->xPos()+offset, child->yPos());
child = iterator.next();
}
}
}
else {
if (style()->boxPack() == BCENTER)
offset += remainingSpace/2;
else offset += remainingSpace;
child = iterator.first();
while (child) {
if (child->isPositioned()) {
child = iterator.next();
continue;
}
placeChild(child, child->xPos()+offset, child->yPos());
child = iterator.next();
}
}
}
if (heightSpecified)
m_height = oldHeight;
}
void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
{
int xPos = borderLeft() + paddingLeft();
int yPos = borderTop() + paddingTop();
if( style()->direction() == RTL )
xPos = m_width - paddingRight() - borderRight();
int toAdd = borderBottom() + paddingBottom();
bool heightSpecified = false;
int oldHeight = 0;
unsigned int highestFlexGroup = 0;
unsigned int lowestFlexGroup = 0;
bool haveFlex = false;
int remainingSpace = 0;
FlexBoxIterator iterator(this);
RenderObject *child = iterator.next();
while (child) {
if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) {
child->setOverrideSize(-1);
if (!relayoutChildren)
child->setChildNeedsLayout(true);
haveFlex = true;
unsigned int flexGroup = child->style()->boxFlexGroup();
if (lowestFlexGroup == 0)
lowestFlexGroup = flexGroup;
if (flexGroup < lowestFlexGroup)
lowestFlexGroup = flexGroup;
if (flexGroup > highestFlexGroup)
highestFlexGroup = flexGroup;
}
child = iterator.next();
}
#if APPLE_CHANGES
bool haveLineClamp = style()->lineClamp() >= 0 && style()->lineClamp() <= 100;
if (haveLineClamp) {
int maxLineCount = 0;
child = iterator.first();
while (child) {
if (!child->isPositioned()) {
if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())) ||
(child->style()->height().isVariable() && child->isBlockFlow() && !child->needsLayout())) {
child->setChildNeedsLayout(true);
static_cast<RenderBlock*>(child)->markPositionedObjectsForLayout();
static_cast<RenderBlock*>(child)->clearTruncation();
}
child->layoutIfNeeded();
if (child->style()->height().isVariable() && child->isBlockFlow())
maxLineCount = kMax(maxLineCount, static_cast<RenderBlock*>(child)->lineCount());
}
child = iterator.next();
}
int numVisibleLines = int((maxLineCount+1)*style()->lineClamp()/100.0);
if (numVisibleLines < maxLineCount) {
for (child = iterator.first(); child; child = iterator.next()) {
if (child->isPositioned() || !child->style()->height().isVariable() || !child->isBlockFlow())
continue;
RenderBlock* blockChild = static_cast<RenderBlock*>(child);
int lineCount = blockChild->lineCount();
if (lineCount <= numVisibleLines) continue;
int newHeight = blockChild->heightForLineCount(numVisibleLines);
if (newHeight == child->height()) continue;
child->setChildNeedsLayout(true);
child->setOverrideSize(newHeight);
m_flexingChildren = true;
child->layoutIfNeeded();
m_flexingChildren = false;
child->setOverrideSize(-1);
if (style()->direction() != LTR) continue;
RootInlineBox* lastLine = blockChild->lineAtIndex(lineCount-1);
if (!lastLine) continue;
InlineBox* anchorBox = lastLine->lastChild();
if (!anchorBox) continue;
if (!anchorBox->object()->element()) continue;
if (!anchorBox->object()->element()->hasAnchor()) continue;
RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines-1);
if (!lastVisibleLine) continue;
const unsigned short ellipsisAndSpace[2] = { 0x2026, ' ' };
static AtomicString ellipsisAndSpaceStr(ellipsisAndSpace, 2);
const Font& font = style(numVisibleLines == 1)->htmlFont();
int ellipsisAndSpaceWidth = font.width(const_cast<QChar*>(ellipsisAndSpaceStr.unicode()), 2, 0, 2);
int totalWidth = ellipsisAndSpaceWidth + anchorBox->width();
RenderBlock* destBlock = static_cast<RenderBlock*>(lastVisibleLine->object());
RenderBlock* srcBlock = static_cast<RenderBlock*>(lastLine->object());
if (srcBlock->style()->direction() != LTR) continue;
if (destBlock->style()->direction() != LTR) continue;
int blockEdge = destBlock->rightOffset(lastVisibleLine->yPos());
if (!lastVisibleLine->canAccommodateEllipsis(true, blockEdge,
lastVisibleLine->xPos() + lastVisibleLine->width(),
totalWidth))
continue;
lastVisibleLine->placeEllipsis(ellipsisAndSpaceStr, true, blockEdge, totalWidth, anchorBox);
destBlock->setHasMarkupTruncation(true);
}
}
}
#endif
do {
m_height = borderTop() + paddingTop();
int minHeight = m_height + toAdd;
m_overflowHeight = m_height;
child = iterator.first();
while (child) {
if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))))
child->setChildNeedsLayout(true);
if (child->isPositioned())
{
child->containingBlock()->insertPositionedObject(child);
if (child->hasStaticX()) {
if (style()->direction() == LTR)
child->setStaticX(borderLeft()+paddingLeft());
else
child->setStaticX(borderRight()+paddingRight());
}
if (child->hasStaticY())
child->setStaticY(m_height);
child = iterator.next();
continue;
}
child->calcVerticalMargins();
m_height += child->marginTop();
child->layoutIfNeeded();
int childX = borderLeft() + paddingLeft();
switch (style()->boxAlign()) {
case BCENTER:
case BBASELINE: childX += child->marginLeft() + (contentWidth() - (child->width() + child->marginLeft() + child->marginRight()))/2;
break;
case BEND:
if (style()->direction() == RTL)
childX += child->marginLeft();
else
childX += contentWidth() - child->marginRight() - child->width();
break;
default: if (style()->direction() == LTR)
childX += child->marginLeft();
else
childX += contentWidth() - child->marginRight() - child->width();
break;
}
placeChild(child, childX, m_height);
m_height += child->height() + child->marginBottom();
int rightChildPos = child->xPos() + kMax(child->overflowWidth(false), child->width());
if (rightChildPos > m_overflowWidth)
m_overflowWidth = rightChildPos;
child = iterator.next();
}
yPos = m_height;
m_height += toAdd;
if (m_height < minHeight)
m_height = minHeight;
if (m_overflowHeight < m_height)
m_overflowHeight = m_height;
oldHeight = m_height;
calcHeight();
if (oldHeight != m_height)
heightSpecified = true;
remainingSpace = borderTop() + paddingTop() + contentHeight() - yPos;
if (m_flexingChildren)
haveFlex = false; else if (haveFlex) {
if (!remainingSpace)
break;
bool expanding = remainingSpace > 0;
unsigned int start = expanding ? lowestFlexGroup : highestFlexGroup;
unsigned int end = expanding? highestFlexGroup : lowestFlexGroup;
for (unsigned int i = start; i <= end && remainingSpace; i++) {
int groupRemainingSpace = remainingSpace;
do {
float totalFlex = 0.0f;
child = iterator.first();
while (child) {
if (allowedChildFlex(child, expanding, i))
totalFlex += child->style()->boxFlex();
child = iterator.next();
}
child = iterator.first();
int spaceAvailableThisPass = groupRemainingSpace;
while (child) {
int allowedFlex = allowedChildFlex(child, expanding, i);
if (allowedFlex) {
int projectedFlex = (allowedFlex == INT_MAX) ? allowedFlex : (int)(allowedFlex * (totalFlex / child->style()->boxFlex()));
spaceAvailableThisPass = expanding ? kMin(spaceAvailableThisPass, projectedFlex) : kMax(spaceAvailableThisPass, projectedFlex);
}
child = iterator.next();
}
if (!spaceAvailableThisPass || totalFlex == 0.0f) {
groupRemainingSpace = 0;
continue;
}
child = iterator.first();
while (child && spaceAvailableThisPass && totalFlex) {
if (allowedChildFlex(child, expanding, i)) {
int spaceAdd = (int)(spaceAvailableThisPass * (child->style()->boxFlex()/totalFlex));
if (spaceAdd) {
child->setOverrideSize(child->overrideHeight() + spaceAdd);
m_flexingChildren = true;
relayoutChildren = true;
}
spaceAvailableThisPass -= spaceAdd;
remainingSpace -= spaceAdd;
groupRemainingSpace -= spaceAdd;
totalFlex -= child->style()->boxFlex();
}
child = iterator.next();
}
} while (groupRemainingSpace);
}
if (haveFlex && !m_flexingChildren)
haveFlex = false;
}
} while (haveFlex);
if (style()->boxPack() != BSTART && remainingSpace > 0) {
int offset = 0;
if (style()->boxPack() == BJUSTIFY) {
int totalChildren = 0;
child = iterator.first();
while (child) {
if (child->isPositioned()) {
child = iterator.next();
continue;
}
totalChildren++;
child = iterator.next();
}
if (totalChildren > 1) {
totalChildren--;
bool firstChild = true;
child = iterator.first();
while (child) {
if (child->isPositioned()) {
child = iterator.next();
continue;
}
if (firstChild) {
firstChild = false;
child = iterator.next();
continue;
}
offset += remainingSpace/totalChildren;
remainingSpace -= (remainingSpace/totalChildren);
totalChildren--;
placeChild(child, child->xPos(), child->yPos()+offset);
child = iterator.next();
}
}
}
else {
if (style()->boxPack() == BCENTER)
offset += remainingSpace/2;
else offset += remainingSpace;
child = iterator.first();
while (child) {
if (child->isPositioned()) {
child = iterator.next();
continue;
}
placeChild(child, child->xPos(), child->yPos()+offset);
child = iterator.next();
}
}
}
if (heightSpecified)
m_height = oldHeight;
}
void RenderFlexibleBox::placeChild(RenderObject* child, int x, int y)
{
int oldChildX = child->xPos();
int oldChildY = child->yPos();
child->setPos(x, y);
if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
child->repaintDuringLayoutIfMoved(oldChildX, oldChildY);
}
int RenderFlexibleBox::allowedChildFlex(RenderObject* child, bool expanding, unsigned int group)
{
if (child->isPositioned() || child->style()->boxFlex() == 0.0f || child->style()->boxFlexGroup() != group)
return 0;
if (expanding) {
if (isHorizontal()) {
int maxW = INT_MAX;
int w = child->overrideWidth() - (child->borderLeft() + child->borderRight() + child->paddingLeft() + child->paddingRight());
if (child->style()->maxWidth().value != UNDEFINED &&
child->style()->maxWidth().isFixed())
maxW = child->style()->maxWidth().value;
else if (child->style()->maxWidth().type == Intrinsic)
maxW = child->maxWidth();
else if (child->style()->maxWidth().type == MinIntrinsic)
maxW = child->minWidth();
int allowedGrowth = kMax(0, maxW - w);
return allowedGrowth;
}
else {
int maxH = INT_MAX;
int h = child->overrideHeight() - (child->borderTop() + child->borderBottom() + child->paddingTop() + child->paddingBottom());
if (child->style()->maxHeight().value != UNDEFINED &&
child->style()->maxHeight().isFixed())
maxH = child->style()->maxHeight().value;
int allowedGrowth = kMax(0, maxH - h);
return allowedGrowth;
}
}
if (isHorizontal()) {
int minW = child->minWidth();
int w = child->contentWidth();
if (child->style()->minWidth().isFixed())
minW = child->style()->minWidth().value;
else if (child->style()->minWidth().type == Intrinsic)
minW = child->maxWidth();
else if (child->style()->minWidth().type == MinIntrinsic)
minW = child->minWidth();
int allowedShrinkage = kMin(0, minW - w);
return allowedShrinkage;
}
else {
if (child->style()->minHeight().isFixed()) {
int minH = child->style()->minHeight().value;
int h = child->contentHeight();
int allowedShrinkage = kMin(0, minH - h);
return allowedShrinkage;
}
}
return 0;
}
const char *RenderFlexibleBox::renderName() const
{
if (isFloating())
return "RenderFlexibleBox (floating)";
if (isPositioned())
return "RenderFlexibleBox (positioned)";
if (isRelPositioned())
return "RenderFlexibleBox (relative positioned)";
return "RenderFlexibleBox";
}
}