📄 render_flexbox.cpp
字号:
if (lowestFlexGroup == 0) lowestFlexGroup = flexGroup; if (flexGroup < lowestFlexGroup) lowestFlexGroup = flexGroup; if (flexGroup > highestFlexGroup) highestFlexGroup = flexGroup; } child = iterator.next(); } // We do 2 passes. The first pass is simply to lay everyone out at // their preferred widths. The second pass handles flexing the children. do { // Reset our height. m_height = yPos; m_overflowHeight = m_height; xPos = borderLeft() + paddingLeft(); // Our first pass is done without flexing. We simply lay the children // out within the box. We have to do a layout first in order to determine // our box's intrinsic height. int maxAscent = 0, maxDescent = 0; child = iterator.first(); while (child) { // make sure we relayout children if we need it. if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))) child->setChildNeedsLayout(true, false); if (child->isPositioned()) { child = iterator.next(); continue; } // Compute the child's vertical margins. child->calcVerticalMargins(); // Now do the layout. child->layoutIfNeeded(); // Update our height and overflow height. 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; // Update our maximum ascent. maxAscent = kMax(maxAscent, ascent); // Update our maximum descent. maxDescent = kMax(maxDescent, descent); // Now update our height. 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; // Always make sure our overflowheight is at least our height. if (m_overflowHeight < m_height) m_overflowHeight = m_height; oldHeight = m_height; calcHeight(); relayoutChildren = false; if (oldHeight != m_height) { heightSpecified = true; // If the block got expanded in size, then increase our overflowheight to match. if (m_overflowHeight > m_height) m_overflowHeight -= (borderBottom() + paddingBottom()); if (m_overflowHeight < m_height) m_overflowHeight = m_height; } // Now that our height is actually known, we can place our boxes. 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; } // We need to see if this child's height has changed, since we make block elements // fill the height of a containing box by default. // Now do a layout. int oldChildHeight = child->height(); static_cast<RenderBox*>(child)->calcHeight(); if (oldChildHeight != child->height()) child->setChildNeedsLayout(true, false); child->layoutIfNeeded(); // We can place the child now, using our value of box-align. 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: // BSTART 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; // We're done. else if (haveFlex) { // We have some flexible objects. See if we need to grow/shrink them at all. if (!remainingSpace) break; // Allocate the remaining space among the flexible objects. If we are trying to // grow, then we go from the lowest flex group to the highest flex group. For shrinking, // we go from the highest flex group to the lowest group. 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++) { // Always start off by assuming the group can get all the remaining space. int groupRemainingSpace = remainingSpace; do { // Flexing consists of multiple passes, since we have to change ratios every time an object hits its max/min-width // For a given pass, we always start off by computing the totalFlex of all objects that can grow/shrink at all, and // computing the allowed growth before an object hits its min/max width (and thus // forces a totalFlex recomputation). 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(); } // The flex groups may not have any flexible objects this time around. if (!spaceAvailableThisPass || totalFlex == 0.0f) { // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group. groupRemainingSpace = 0; continue; } // Now distribute the space to objects. 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); } // We didn't find any children that could grow. 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))) { // Children must be repositioned. int offset = 0; if (style()->boxPack() == BJUSTIFY) { // Determine the total number of children. int totalChildren = 0; child = iterator.first(); while (child) { if (child->isPositioned()) { child = iterator.next(); continue; } totalChildren++; child = iterator.next(); } // Iterate over the children and space them out according to the // justification level. 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 // END for LTR, START for RTL offset += remainingSpace; child = iterator.first(); while (child) { if (child->isPositioned()) { child = iterator.next(); continue; } placeChild(child, child->xPos()+offset, child->yPos()); child = iterator.next(); } } } // So that the calcHeight in layoutBlock() knows to relayout positioned objects because of // a height change, we revert our height back to the intrinsic height before returning. 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; // The first walk over our kids is to find out if we have any flexible children. FlexBoxIterator iterator(this); RenderObject *child = iterator.next(); while (child) { // Check to see if this child flexes. if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) { // We always have to lay out flexible objects again, since the flex distribution // may have changed, and we need to reallocate space. 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 // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of // mainstream block layout) and put it all inside APPLE_CHANGES to denote that this is not // really part of the XUL box model. bool haveLineClamp = style()->lineClamp() >= 0 && style()->lineClamp() <= 100; if (haveLineClamp) { int maxLineCount = 1; 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); // Dirty all the positioned objects. 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(); } // Get the # of lines and then alter all block flow children with auto height to use the // specified height. int numVisibleLines = int(maxLineCount*style()->lineClamp()/100.0 + 1.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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -