📄 renderinline.cpp
字号:
RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling(); if (madeNewBeforeBlock) block->children()->insertChildNode(block, pre, boxFirst); block->children()->insertChildNode(block, newBlockBox, boxFirst); block->children()->insertChildNode(block, post, boxFirst); block->setChildrenInline(false); if (madeNewBeforeBlock) { RenderObject* o = boxFirst; while (o) { RenderObject* no = o; o = no->nextSibling(); pre->children()->appendChildNode(pre, block->children()->removeChildNode(block, no)); no->setNeedsLayoutAndPrefWidthsRecalc(); } } splitInlines(pre, post, newBlockBox, beforeChild, oldCont); // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting // time in makeChildrenNonInline by just setting this explicitly up front. newBlockBox->setChildrenInline(false); // We delayed adding the newChild until now so that the |newBlockBox| would be fully // connected, thus allowing newChild access to a renderArena should it need // to wrap itself in additional boxes (e.g., table construction). newBlockBox->addChild(newChild); // Always just do a full layout in order to ensure that line boxes (especially wrappers for images) // get deleted properly. Because objects moves from the pre block into the post block, we want to // make new line boxes instead of leaving the old line boxes around. pre->setNeedsLayoutAndPrefWidthsRecalc(); block->setNeedsLayoutAndPrefWidthsRecalc(); post->setNeedsLayoutAndPrefWidthsRecalc();}void RenderInline::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild){ RenderBoxModelObject* flow = continuationBefore(beforeChild); ASSERT(!beforeChild || beforeChild->parent()->isRenderBlock() || beforeChild->parent()->isRenderInline()); RenderBoxModelObject* beforeChildParent = 0; if (beforeChild) beforeChildParent = static_cast<RenderBoxModelObject*>(beforeChild->parent()); else { RenderBoxModelObject* cont = nextContinuation(flow); if (cont) beforeChildParent = cont; else beforeChildParent = flow; } if (newChild->isFloatingOrPositioned()) return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); // A continuation always consists of two potential candidates: an inline or an anonymous // block box holding block children. bool childInline = newChild->isInline(); bool bcpInline = beforeChildParent->isInline(); bool flowInline = flow->isInline(); if (flow == beforeChildParent) return flow->addChildIgnoringContinuation(newChild, beforeChild); else { // The goal here is to match up if we can, so that we can coalesce and create the // minimal # of continuations needed for the inline. if (childInline == bcpInline) return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); else if (flowInline == childInline) return flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an append. else return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); }}void RenderInline::paint(PaintInfo& paintInfo, int tx, int ty){ m_lineBoxes.paint(this, paintInfo, tx, ty);}void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel){ for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) rects.append(IntRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height())); if (continuation() && topLevel) { if (continuation()->isBox()) { RenderBox* box = toRenderBox(continuation()); continuation()->absoluteRects(rects, tx - containingBlock()->x() + box->x(), ty - containingBlock()->y() + box->y(), topLevel); } else continuation()->absoluteRects(rects, tx - containingBlock()->x(), ty - containingBlock()->y(), topLevel); }}void RenderInline::absoluteQuads(Vector<FloatQuad>& quads, bool topLevel){ for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { FloatRect localRect(curr->x(), curr->y(), curr->width(), curr->height()); quads.append(localToAbsoluteQuad(localRect)); } if (continuation() && topLevel) continuation()->absoluteQuads(quads, topLevel);}int RenderInline::offsetLeft() const{ int x = RenderBoxModelObject::offsetLeft(); if (firstLineBox()) x += firstLineBox()->x(); return x;}int RenderInline::offsetTop() const{ int y = RenderBoxModelObject::offsetTop(); if (firstLineBox()) y += firstLineBox()->y(); return y;}int RenderInline::marginLeft() const{ Length margin = style()->marginLeft(); if (margin.isAuto()) return 0; if (margin.isFixed()) return margin.value(); if (margin.isPercent()) return margin.calcMinValue(max(0, containingBlock()->availableWidth())); return 0;}int RenderInline::marginRight() const{ Length margin = style()->marginRight(); if (margin.isAuto()) return 0; if (margin.isFixed()) return margin.value(); if (margin.isPercent()) return margin.calcMinValue(max(0, containingBlock()->availableWidth())); return 0;}const char* RenderInline::renderName() const{ if (isRelPositioned()) return "RenderInline (relative positioned)"; if (isAnonymous()) return "RenderInline (generated)"; if (isRunIn()) return "RenderInline (run-in)"; return "RenderInline";}bool RenderInline::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction){ return m_lineBoxes.hitTest(this, request, result, x, y, tx, ty, hitTestAction);}VisiblePosition RenderInline::positionForPoint(const IntPoint& point){ // FIXME: Does not deal with relative positioned inlines (should it?) RenderBlock* cb = containingBlock(); if (firstLineBox()) { // This inline actually has a line box. We must have clicked in the border/padding of one of these boxes. We // should try to find a result by asking our containing block. return cb->positionForPoint(point); } // Translate the coords from the pre-anonymous block to the post-anonymous block. int parentBlockX = cb->x() + point.x(); int parentBlockY = cb->y() + point.y(); RenderBoxModelObject* c = continuation(); while (c) { RenderBox* contBlock = c->isInline() ? c->containingBlock() : toRenderBlock(c); if (c->isInline() || c->firstChild()) return c->positionForCoordinates(parentBlockX - contBlock->x(), parentBlockY - contBlock->y()); c = toRenderBlock(c)->inlineContinuation(); } return RenderBoxModelObject::positionForPoint(point);}IntRect RenderInline::linesBoundingBox() const{ IntRect result; // See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero. We have been // unable to reproduce this at all (and consequently unable to figure ot why this is happening). The assert will hopefully catch the problem in debug // builds and help us someday figure out why. We also put in a redundant check of lastLineBox() to avoid the crash for now. ASSERT(!firstLineBox() == !lastLineBox()); // Either both are null or both exist. if (firstLineBox() && lastLineBox()) { // Return the width of the minimal left side and the maximal right side. int leftSide = 0; int rightSide = 0; for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { if (curr == firstLineBox() || curr->x() < leftSide) leftSide = curr->x(); if (curr == firstLineBox() || curr->x() + curr->width() > rightSide) rightSide = curr->x() + curr->width(); } result.setWidth(rightSide - leftSide); result.setX(leftSide); result.setHeight(lastLineBox()->y() + lastLineBox()->height() - firstLineBox()->y()); result.setY(firstLineBox()->y()); } return result;}IntRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer){ // Only run-ins are allowed in here during layout. ASSERT(!view() || !view()->layoutStateEnabled() || isRunIn()); if (!firstLineBox() && !continuation()) return IntRect(); // Find our leftmost position. IntRect boundingBox(linesBoundingBox()); int left = boundingBox.x(); int top = boundingBox.y(); // Now invalidate a rectangle. int ow = style() ? style()->outlineSize() : 0; // We need to add in the relative position offsets of any inlines (including us) up to our // containing block. RenderBlock* cb = containingBlock(); for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isRenderInline() && inlineFlow != cb; inlineFlow = inlineFlow->parent()) { if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer()) toRenderInline(inlineFlow)->layer()->relativePositionOffset(left, top); } IntRect r(-ow + left, -ow + top, boundingBox.width() + ow * 2, boundingBox.height() + ow * 2); if (cb->hasColumns()) cb->adjustRectForColumns(r); if (cb->hasOverflowClip()) { // cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint // anyway if its size does change. int x = r.x(); int y = r.y(); IntRect boxRect(0, 0, cb->layer()->width(), cb->layer()->height()); cb->layer()->subtractScrolledContentOffset(x, y); // For overflow:auto/scroll/hidden. IntRect repaintRect(x, y, r.width(), r.height()); r = intersection(repaintRect, boxRect); } // FIXME: need to ensure that we compute the correct repaint rect when the repaint container // is an inline. if (repaintContainer != this) cb->computeRectForRepaint(repaintContainer, r); if (ow) { for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText()) { IntRect childRect = curr->rectWithOutlineForRepaint(repaintContainer, ow); r.unite(childRect); } } if (continuation() && !continuation()->isInline()) { IntRect contRect = continuation()->rectWithOutlineForRepaint(repaintContainer, ow); r.unite(contRect); } } return r;}IntRect RenderInline::rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth){ IntRect r(RenderBoxModelObject::rectWithOutlineForRepaint(repaintContainer, outlineWidth)); for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText()) r.unite(curr->rectWithOutlineForRepaint(repaintContainer, outlineWidth)); } return r;}void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed){ if (RenderView* v = view()) { // LayoutState is only valid for root-relative repainting if (v->layoutStateEnabled() && !repaintContainer) { LayoutState* layoutState = v->layoutState(); if (style()->position() == RelativePosition && layer()) rect.move(layer()->relativePositionOffset()); rect.move(layoutState->m_offset); if (layoutState->m_clipped) rect.intersect(layoutState->m_clipRect); return; } } if (repaintContainer == this) return; RenderObject* o = container(); if (!o) return; IntPoint topLeft = rect.location(); if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition) { RenderBlock* cb = toRenderBlock(o); if (cb->hasColumns()) { IntRect repaintRect(topLeft, rect.size()); cb->adjustRectForColumns(repaintRect); topLeft = repaintRect.location(); rect = repaintRect; } } if (style()->position() == RelativePosition && layer()) { // Apply the relative position offset when invalidating a rectangle. The layer // is translated, but the render box isn't, so we need to do this to get the // right dirty rect. Since this is called from RenderObject::setStyle, the relative position // flag on the RenderObject has been cleared, so use the one on the style(). topLeft += layer()->relativePositionOffset(); } // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout, // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer. if (o->hasOverflowClip()) { RenderBox* containerBox = toRenderBox(o); // o->height() is inaccurate if we're in the middle of a layout of |o|, so use the // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint // anyway if its size does change. topLeft -= containerBox->layer()->scrolledContentOffset(); // For overflow:auto/scroll/hidden. IntRect repaintRect(topLeft, rect.size()); IntRect boxRect(0, 0, containerBox->layer()->width(), containerBox->layer()->height()); rect = intersection(repaintRect, boxRect);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -