📄 renderblock.cpp
字号:
if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrPositioned()) { // This is a block with inline content. Wrap the inline content in anonymous blocks. makeChildrenNonInline(beforeChild); madeBoxesNonInline = true; if (beforeChild && beforeChild->parent() != this) { beforeChild = beforeChild->parent(); ASSERT(beforeChild->isAnonymousBlock()); ASSERT(beforeChild->parent() == this); } } else if (!childrenInline() && (newChild->isFloatingOrPositioned() || newChild->isInline())) { // If we're inserting an inline child but all of our children are blocks, then we have to make sure // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise // a new one is created and inserted into our list of children in the appropriate position. RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : lastChild(); if (afterChild && afterChild->isAnonymousBlock()) { afterChild->addChild(newChild); return; } if (newChild->isInline()) { // No suitable existing anonymous box - create a new one. RenderBlock* newBox = createAnonymousBlock(); RenderBox::addChild(newBox, beforeChild); newBox->addChild(newChild); return; } } RenderBox::addChild(newChild, beforeChild); if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock()) toRenderBlock(parent())->removeLeftoverAnonymousBlock(this); // this object may be dead here}static void getInlineRun(RenderObject* start, RenderObject* boundary, RenderObject*& inlineRunStart, RenderObject*& inlineRunEnd){ // Beginning at |start| we find the largest contiguous run of inlines that // we can. We denote the run with start and end points, |inlineRunStart| // and |inlineRunEnd|. Note that these two values may be the same if // we encounter only one inline. // // We skip any non-inlines we encounter as long as we haven't found any // inlines yet. // // |boundary| indicates a non-inclusive boundary point. Regardless of whether |boundary| // is inline or not, we will not include it in a run with inlines before it. It's as though we encountered // a non-inline. // Start by skipping as many non-inlines as we can. RenderObject * curr = start; bool sawInline; do { while (curr && !(curr->isInline() || curr->isFloatingOrPositioned())) curr = curr->nextSibling(); inlineRunStart = inlineRunEnd = curr; if (!curr) return; // No more inline children to be found. sawInline = curr->isInline(); curr = curr->nextSibling(); while (curr && (curr->isInline() || curr->isFloatingOrPositioned()) && (curr != boundary)) { inlineRunEnd = curr; if (curr->isInline()) sawInline = true; curr = curr->nextSibling(); } } while (!sawInline);}void RenderBlock::deleteLineBoxTree(){ m_lineBoxes.deleteLineBoxTree(renderArena());}RootInlineBox* RenderBlock::createRootBox(){ return new (renderArena()) RootInlineBox(this);}RootInlineBox* RenderBlock::createRootInlineBox(){ RootInlineBox* rootBox = createRootBox(); m_lineBoxes.appendLineBox(rootBox); return rootBox;}void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint){ // makeChildrenNonInline takes a block whose children are *all* inline and it // makes sure that inline children are coalesced under anonymous // blocks. If |insertionPoint| is defined, then it represents the insertion point for // the new block child that is causing us to have to wrap all the inlines. This // means that we cannot coalesce inlines before |insertionPoint| with inlines following // |insertionPoint|, because the new child is going to be inserted in between the inlines, // splitting them. ASSERT(isInlineBlockOrInlineTable() || !isInline()); ASSERT(!insertionPoint || insertionPoint->parent() == this); setChildrenInline(false); RenderObject *child = firstChild(); if (!child) return; deleteLineBoxTree(); while (child) { RenderObject *inlineRunStart, *inlineRunEnd; getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd); if (!inlineRunStart) break; child = inlineRunEnd->nextSibling(); RenderBlock* block = createAnonymousBlock(); children()->insertChildNode(this, block, inlineRunStart); RenderObject* o = inlineRunStart; while (o != inlineRunEnd) { RenderObject* no = o; o = no->nextSibling(); moveChild(block, block->children(), this, children(), no); } moveChild(block, block->children(), this, children(), inlineRunEnd); }#ifndef NDEBUG for (RenderObject *c = firstChild(); c; c = c->nextSibling()) ASSERT(!c->isInline());#endif repaint();}void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child){ ASSERT(child->isAnonymousBlock()); ASSERT(!child->childrenInline()); if (child->inlineContinuation()) return; RenderObject* firstAnChild = child->m_children.firstChild(); RenderObject* lastAnChild = child->m_children.lastChild(); if (firstAnChild) { RenderObject* o = firstAnChild; while (o) { o->setParent(this); o = o->nextSibling(); } firstAnChild->setPreviousSibling(child->previousSibling()); lastAnChild->setNextSibling(child->nextSibling()); if (child->previousSibling()) child->previousSibling()->setNextSibling(firstAnChild); if (child->nextSibling()) child->nextSibling()->setPreviousSibling(lastAnChild); } else { if (child->previousSibling()) child->previousSibling()->setNextSibling(child->nextSibling()); if (child->nextSibling()) child->nextSibling()->setPreviousSibling(child->previousSibling()); } if (child == m_children.firstChild()) m_children.setFirstChild(firstAnChild); if (child == m_children.lastChild()) m_children.setLastChild(lastAnChild); child->setParent(0); child->setPreviousSibling(0); child->setNextSibling(0); child->children()->setFirstChild(0); child->m_next = 0; child->destroy();}void RenderBlock::removeChild(RenderObject* oldChild){ // If this child is a block, and if our previous and next siblings are // both anonymous blocks with inline content, then we can go ahead and // fold the inline content back together. RenderObject* prev = oldChild->previousSibling(); RenderObject* next = oldChild->nextSibling(); bool canDeleteAnonymousBlocks = !documentBeingDestroyed() && !isInline() && !oldChild->isInline() && (!oldChild->isRenderBlock() || !toRenderBlock(oldChild)->inlineContinuation()) && (!prev || (prev->isAnonymousBlock() && prev->childrenInline())) && (!next || (next->isAnonymousBlock() && next->childrenInline())); if (canDeleteAnonymousBlocks && prev && next) { // Take all the children out of the |next| block and put them in // the |prev| block. prev->setNeedsLayoutAndPrefWidthsRecalc(); RenderObject* o = next->firstChild(); RenderBlock* nextBlock = toRenderBlock(next); RenderBlock* prevBlock = toRenderBlock(prev); while (o) { RenderObject* no = o; o = no->nextSibling(); moveChild(prevBlock, prevBlock->children(), nextBlock, nextBlock->children(), no); } nextBlock->deleteLineBoxTree(); // Nuke the now-empty block. next->destroy(); } RenderBox::removeChild(oldChild); RenderObject* child = prev ? prev : next; if (canDeleteAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && !isFlexibleBox()) { // The removal has knocked us down to containing only a single anonymous // box. We can go ahead and pull the content right back up into our // box. setNeedsLayoutAndPrefWidthsRecalc(); RenderBlock* anonBlock = toRenderBlock(children()->removeChildNode(this, child, false)); setChildrenInline(true); RenderObject* o = anonBlock->firstChild(); while (o) { RenderObject* no = o; o = no->nextSibling(); moveChild(this, children(), anonBlock, anonBlock->children(), no); } // Delete the now-empty block's lines and nuke it. anonBlock->deleteLineBoxTree(); anonBlock->destroy(); }}int RenderBlock::overflowHeight(bool includeInterior) const{ if (!includeInterior && hasOverflowClip()) { int shadowHeight = 0; for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) shadowHeight = max(boxShadow->y + boxShadow->blur, shadowHeight); int inflatedHeight = height() + shadowHeight; if (hasReflection()) inflatedHeight = max(inflatedHeight, reflectionBox().bottom()); return inflatedHeight; } return m_overflowHeight;}int RenderBlock::overflowWidth(bool includeInterior) const{ if (!includeInterior && hasOverflowClip()) { int shadowWidth = 0; for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) shadowWidth = max(boxShadow->x + boxShadow->blur, shadowWidth); int inflatedWidth = width() + shadowWidth; if (hasReflection()) inflatedWidth = max(inflatedWidth, reflectionBox().right()); return inflatedWidth; } return m_overflowWidth;}int RenderBlock::overflowLeft(bool includeInterior) const{ if (!includeInterior && hasOverflowClip()) { int shadowLeft = 0; for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft); int left = shadowLeft; if (hasReflection()) left = min(left, reflectionBox().x()); return left; } return m_overflowLeft;}int RenderBlock::overflowTop(bool includeInterior) const{ if (!includeInterior && hasOverflowClip()) { int shadowTop = 0; for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) shadowTop = min(boxShadow->y - boxShadow->blur, shadowTop); int top = shadowTop; if (hasReflection()) top = min(top, reflectionBox().y()); return top; } return m_overflowTop;}IntRect RenderBlock::overflowRect(bool includeInterior) const{ if (!includeInterior && hasOverflowClip()) { IntRect box = borderBoxRect(); int shadowLeft = 0; int shadowRight = 0; int shadowTop = 0; int shadowBottom = 0; for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) { shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft); shadowRight = max(boxShadow->x + boxShadow->blur, shadowRight);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -