📄 renderflexiblebox.cpp
字号:
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->x()+offset, child->y()); 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->x()+offset, child->y()); child = iterator.next(); } } } child = iterator.first(); while (child && child->isPositioned()) { child = iterator.next(); } if (child) { m_overflowLeft = min(child->x() + child->overflowLeft(false), m_overflowLeft); RenderBox* lastChild = child; while ((child = iterator.next())) { if (!child->isPositioned()) lastChild = child; } m_overflowWidth = max(lastChild->x() + lastChild->overflowWidth(false), m_overflowWidth); } // 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) setHeight(oldHeight);}void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren){ int xPos = borderLeft() + paddingLeft(); int yPos = borderTop() + paddingTop(); if( style()->direction() == RTL ) xPos = width() - paddingRight() - borderRight(); int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight(); 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); RenderBox* 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, 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(); } // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of // mainstream block layout); this is not really part of the XUL box model. 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().isAuto() && child->isBlockFlow() && !child->needsLayout())) { child->setChildNeedsLayout(true, false); // Dirty all the positioned objects. if (child->isRenderBlock()) { toRenderBlock(child)->markPositionedObjectsForLayout(); toRenderBlock(child)->clearTruncation(); } } child->layoutIfNeeded(); if (child->style()->height().isAuto() && child->isBlockFlow()) maxLineCount = max(maxLineCount, toRenderBlock(child)->lineCount()); } child = iterator.next(); } // Get the # of lines and then alter all block flow children with auto height to use the // specified height. We always try to leave room for at least one line. int numVisibleLines = max(1, static_cast<int>((maxLineCount + 1) * style()->lineClamp() / 100.0)); if (numVisibleLines < maxLineCount) { for (child = iterator.first(); child; child = iterator.next()) { if (child->isPositioned() || !child->style()->height().isAuto() || !child->isBlockFlow()) continue; RenderBlock* blockChild = toRenderBlock(child); int lineCount = blockChild->lineCount(); if (lineCount <= numVisibleLines) continue; int newHeight = blockChild->heightForLineCount(numVisibleLines); if (newHeight == child->height()) continue; child->setChildNeedsLayout(true, false); child->setOverrideSize(newHeight); m_flexingChildren = true; child->layoutIfNeeded(); m_flexingChildren = false; child->setOverrideSize(-1); // FIXME: For now don't support RTL. if (style()->direction() != LTR) continue; // Get the last line RootInlineBox* lastLine = blockChild->lineAtIndex(lineCount-1); if (!lastLine) continue; // See if the last item is an anchor InlineBox* anchorBox = lastLine->lastChild(); if (!anchorBox) continue; if (!anchorBox->renderer()->node()) continue; if (!anchorBox->renderer()->node()->isLink()) continue; RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines-1); if (!lastVisibleLine) continue; const UChar ellipsisAndSpace[2] = { horizontalEllipsis, ' ' }; DEFINE_STATIC_LOCAL(AtomicString, ellipsisAndSpaceStr, (ellipsisAndSpace, 2)); const Font& font = style(numVisibleLines == 1)->font(); int ellipsisAndSpaceWidth = font.width(TextRun(ellipsisAndSpace, 2)); // Get ellipsis width + " " + anchor width int totalWidth = ellipsisAndSpaceWidth + anchorBox->width(); // See if this width can be accommodated on the last visible line RenderBlock* destBlock = toRenderBlock(lastVisibleLine->renderer()); RenderBlock* srcBlock = toRenderBlock(lastLine->renderer()); // FIXME: Directions of src/destBlock could be different from our direction and from one another. if (srcBlock->style()->direction() != LTR) continue; if (destBlock->style()->direction() != LTR) continue; int blockEdge = destBlock->rightOffset(lastVisibleLine->y(), false); if (!lastVisibleLine->canAccommodateEllipsis(true, blockEdge, lastVisibleLine->x() + lastVisibleLine->width(), totalWidth)) continue; // Let the truncation code kick in. lastVisibleLine->placeEllipsis(ellipsisAndSpaceStr, true, blockEdge, totalWidth, anchorBox); destBlock->setHasMarkupTruncation(true); } } } // We do 2 passes. The first pass is simply to lay everyone out at // their preferred widths. The second pass handles flexing the children. // Our first pass is done without flexing. We simply lay the children // out within the box. do { setHeight(borderTop() + paddingTop()); int minHeight = height() + toAdd; m_overflowHeight = height(); child = iterator.first(); while (child) { // make sure we relayout children if we need it. if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))) child->setChildNeedsLayout(true, false); if (child->isPositioned()) { child->containingBlock()->insertPositionedObject(child); if (child->style()->hasStaticX()) { if (style()->direction() == LTR) child->layer()->setStaticX(borderLeft()+paddingLeft()); else child->layer()->setStaticX(borderRight()+paddingRight()); } if (child->style()->hasStaticY()) child->layer()->setStaticY(height()); child = iterator.next(); continue; } // Compute the child's vertical margins. child->calcVerticalMargins(); // Add in the child's marginTop to our height. setHeight(height() + child->marginTop()); // Now do a layout. child->layoutIfNeeded(); // We can place the child now, using our value of box-align. int childX = borderLeft() + paddingLeft(); switch (style()->boxAlign()) { case BCENTER: case BBASELINE: // Baseline just maps to center for vertical boxes childX += child->marginLeft() + max(0, (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: // BSTART/BSTRETCH if (style()->direction() == LTR) childX += child->marginLeft(); else childX += contentWidth() - child->marginRight() - child->width(); break; } // Place the child. placeChild(child, childX, height()); setHeight(height() + child->height() + child->marginBottom()); if (child->isRenderBlock()) toRenderBlock(child)->addVisualOverflow(toRenderBlock(child)->floatRect()); // See if this child has made our overflow need to grow.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -