diff options
Diffstat (limited to 'Source/WebCore/rendering/RenderLineBoxList.cpp')
-rw-r--r-- | Source/WebCore/rendering/RenderLineBoxList.cpp | 127 |
1 files changed, 63 insertions, 64 deletions
diff --git a/Source/WebCore/rendering/RenderLineBoxList.cpp b/Source/WebCore/rendering/RenderLineBoxList.cpp index 3f51a6167..b1439a97b 100644 --- a/Source/WebCore/rendering/RenderLineBoxList.cpp +++ b/Source/WebCore/rendering/RenderLineBoxList.cpp @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -76,7 +76,7 @@ void RenderLineBoxList::deleteLineBoxTree() line->deleteLine(); line = nextLine; } - m_firstLineBox = m_lastLineBox = 0; + m_firstLineBox = m_lastLineBox = nullptr; } void RenderLineBoxList::extractLineBox(InlineFlowBox* box) @@ -87,8 +87,8 @@ void RenderLineBoxList::extractLineBox(InlineFlowBox* box) if (box == m_firstLineBox) m_firstLineBox = 0; if (box->prevLineBox()) - box->prevLineBox()->setNextLineBox(0); - box->setPreviousLineBox(0); + box->prevLineBox()->setNextLineBox(nullptr); + box->setPreviousLineBox(nullptr); for (InlineFlowBox* curr = box; curr; curr = curr->nextLineBox()) curr->setExtracted(); @@ -138,8 +138,8 @@ void RenderLineBoxList::deleteLineBoxes() next = curr->nextLineBox(); delete curr; } - m_firstLineBox = 0; - m_lastLineBox = 0; + m_firstLineBox = nullptr; + m_lastLineBox = nullptr; } } @@ -149,15 +149,21 @@ void RenderLineBoxList::dirtyLineBoxes() curr->dirtyLineBoxes(); } +// FIXME: This should take a RenderBoxModelObject&. bool RenderLineBoxList::rangeIntersectsRect(RenderBoxModelObject* renderer, LayoutUnit logicalTop, LayoutUnit logicalBottom, const LayoutRect& rect, const LayoutPoint& offset) const { - RenderBox* block; - if (renderer->isBox()) - block = toRenderBox(renderer); - else - block = renderer->containingBlock(); - LayoutUnit physicalStart = block->flipForWritingMode(logicalTop); - LayoutUnit physicalEnd = block->flipForWritingMode(logicalBottom); + LayoutUnit physicalStart = logicalTop; + LayoutUnit physicalEnd = logicalBottom; + if (renderer->view().frameView().hasFlippedBlockRenderers()) { + RenderBox* block; + if (is<RenderBox>(*renderer)) + block = downcast<RenderBox>(renderer); + else + block = renderer->containingBlock(); + physicalStart = block->flipForWritingMode(logicalTop); + physicalEnd = block->flipForWritingMode(logicalBottom); + } + LayoutUnit physicalExtent = absoluteValue(physicalEnd - physicalStart); physicalStart = std::min(physicalStart, physicalEnd); @@ -174,7 +180,7 @@ bool RenderLineBoxList::rangeIntersectsRect(RenderBoxModelObject* renderer, Layo return true; } -bool RenderLineBoxList::anyLineIntersectsRect(RenderBoxModelObject* renderer, const LayoutRect& rect, const LayoutPoint& offset, bool usePrintRect, LayoutUnit outlineSize) const +bool RenderLineBoxList::anyLineIntersectsRect(RenderBoxModelObject* renderer, const LayoutRect& rect, const LayoutPoint& offset, bool usePrintRect) const { // We can check the first box and last box and avoid painting/hit testing if we don't // intersect. This is a quick short-circuit that we can take to avoid walking any lines. @@ -188,29 +194,19 @@ bool RenderLineBoxList::anyLineIntersectsRect(RenderBoxModelObject* renderer, co LayoutUnit lastLineBottom = lastLineBox()->logicalBottomVisualOverflow(lastRootBox.lineBottom()); if (usePrintRect && !lastLineBox()->parent()) lastLineBottom = std::max(lastLineBottom, lastRootBox.lineBottom()); - LayoutUnit logicalTop = firstLineTop - outlineSize; - LayoutUnit logicalBottom = outlineSize + lastLineBottom; - - return rangeIntersectsRect(renderer, logicalTop, logicalBottom, rect, offset); + return rangeIntersectsRect(renderer, firstLineTop, lastLineBottom, rect, offset); } bool RenderLineBoxList::lineIntersectsDirtyRect(RenderBoxModelObject* renderer, InlineFlowBox* box, const PaintInfo& paintInfo, const LayoutPoint& offset) const { const RootInlineBox& rootBox = box->root(); - LayoutUnit logicalTop = std::min<LayoutUnit>(box->logicalTopVisualOverflow(rootBox.lineTop()), rootBox.selectionTop()) - renderer->maximalOutlineSize(paintInfo.phase); - LayoutUnit logicalBottom = box->logicalBottomVisualOverflow(rootBox.lineBottom()) + renderer->maximalOutlineSize(paintInfo.phase); - + LayoutUnit logicalTop = std::min(box->logicalTopVisualOverflow(rootBox.lineTop()), rootBox.selectionTop()); + LayoutUnit logicalBottom = box->logicalBottomVisualOverflow(rootBox.lineBottom()); return rangeIntersectsRect(renderer, logicalTop, logicalBottom, paintInfo.rect, offset); } void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintInfo, const LayoutPoint& paintOffset) const { - // Only paint during the foreground/selection phases. - if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseOutline - && paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines && paintInfo.phase != PaintPhaseTextClip - && paintInfo.phase != PaintPhaseMask) - return; - ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could paint like this is if it has a layer. // If we have no lines then we have no work to do. @@ -221,8 +217,7 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintIn // NSViews. Do not add any more code for this. RenderView& v = renderer->view(); bool usePrintRect = !v.printRect().isEmpty(); - LayoutUnit outlineSize = renderer->maximalOutlineSize(paintInfo.phase); - if (!anyLineIntersectsRect(renderer, paintInfo.rect, paintOffset, usePrintRect, outlineSize)) + if (!anyLineIntersectsRect(renderer, paintInfo.rect, paintOffset, usePrintRect)) return; PaintInfo info(paintInfo); @@ -278,9 +273,6 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintIn bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) const { - if (hitTestAction != HitTestForeground) - return false; - ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could hit test like this is if it has a layer. // If we have no lines then we have no work to do. @@ -301,7 +293,7 @@ bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestReq for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevLineBox()) { const RootInlineBox& rootBox = curr->root(); if (rangeIntersectsRect(renderer, curr->logicalTopVisualOverflow(rootBox.lineTop()), curr->logicalBottomVisualOverflow(rootBox.lineBottom()), rect, accumulatedOffset)) { - bool inside = curr->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, rootBox.lineTop(), rootBox.lineBottom()); + bool inside = curr->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, rootBox.lineTop(), rootBox.lineBottom(), hitTestAction); if (inside) { renderer->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset)); return true; @@ -312,47 +304,45 @@ bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestReq return false; } -void RenderLineBoxList::dirtyLinesFromChangedChild(RenderBoxModelObject* container, RenderObject* child) +void RenderLineBoxList::dirtyLinesFromChangedChild(RenderBoxModelObject& container, RenderObject& child) { - ASSERT(container->isRenderInline() || container->isRenderBlockFlow()); - if (!container->parent() || (container->isRenderBlockFlow() && container->selfNeedsLayout())) + ASSERT(is<RenderInline>(container) || is<RenderBlockFlow>(container)); + if (!container.parent() || (is<RenderBlockFlow>(container) && container.selfNeedsLayout())) return; - RenderInline* inlineContainer = container->isRenderInline() ? toRenderInline(container) : 0; + RenderInline* inlineContainer = is<RenderInline>(container) ? &downcast<RenderInline>(container) : nullptr; InlineBox* firstBox = inlineContainer ? inlineContainer->firstLineBoxIncludingCulling() : firstLineBox(); // If we have no first line box, then just bail early. if (!firstBox) { - // For an empty inline, go ahead and propagate the check up to our parent, unless the parent - // is already dirty. - if (container->isInline() && !container->ancestorLineBoxDirty()) { - container->parent()->dirtyLinesFromChangedChild(container); - container->setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree. + // For an empty inline, propagate the check up to our parent, unless the parent is already dirty. + if (container.isInline() && !container.ancestorLineBoxDirty()) { + container.parent()->dirtyLinesFromChangedChild(container); + container.setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree. } return; } - // Try to figure out which line box we belong in. First try to find a previous - // line box by examining our siblings. If we didn't find a line box, then use our + // Try to figure out which line box we belong in. First try to find a previous + // line box by examining our siblings. If we didn't find a line box, then use our // parent's first line box. - RootInlineBox* box = 0; - RenderObject* curr = 0; - for (curr = child->previousSibling(); curr; curr = curr->previousSibling()) { - if (curr->isFloatingOrOutOfFlowPositioned()) + RootInlineBox* box = nullptr; + RenderObject* current; + for (current = child.previousSibling(); current; current = current->previousSibling()) { + if (current->isFloatingOrOutOfFlowPositioned()) continue; - if (curr->isReplaced()) { - if (auto wrapper = toRenderBox(curr)->inlineBoxWrapper()) + if (current->isReplaced()) { + if (auto wrapper = downcast<RenderBox>(*current).inlineBoxWrapper()) box = &wrapper->root(); - } if (curr->isLineBreak()) { - if (auto wrapper = toRenderLineBreak(curr)->inlineBoxWrapper()) + } if (is<RenderLineBreak>(*current)) { + if (auto wrapper = downcast<RenderLineBreak>(*current).inlineBoxWrapper()) box = &wrapper->root(); - } else if (curr->isText()) { - InlineTextBox* textBox = toRenderText(curr)->lastTextBox(); - if (textBox) + } else if (is<RenderText>(*current)) { + if (InlineTextBox* textBox = downcast<RenderText>(*current).lastTextBox()) box = &textBox->root(); - } else if (curr->isRenderInline()) { - InlineBox* lastSiblingBox = toRenderInline(curr)->lastLineBoxIncludingCulling(); + } else if (is<RenderInline>(*current)) { + InlineBox* lastSiblingBox = downcast<RenderInline>(*current).lastLineBoxIncludingCulling(); if (lastSiblingBox) box = &lastSiblingBox->root(); } @@ -368,7 +358,7 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderBoxModelObject* contain // This isn't good enough, since we won't locate the root line box that encloses the removed // <br>. We have to just over-invalidate a bit and go up to our parent. if (!inlineContainer->ancestorLineBoxDirty()) { - inlineContainer->parent()->dirtyLinesFromChangedChild(inlineContainer); + inlineContainer->parent()->dirtyLinesFromChangedChild(*inlineContainer); inlineContainer->setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree. } return; @@ -380,11 +370,11 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderBoxModelObject* contain if (box) { box->markDirty(); - // dirty the adjacent lines that might be affected + // Dirty the adjacent lines that might be affected. // NOTE: we dirty the previous line because RootInlineBox objects cache // the address of the first object on the next line after a BR, which we may be - // invalidating here. For more info, see how RenderBlock::layoutInlineChildren - // calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak, + // invalidating here. For more info, see how RenderBlock::layoutInlineChildren + // calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak, // despite the name, actually returns the first RenderObject after the BR. // <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize." if (RootInlineBox* prevBox = box->prevRootBox()) @@ -392,8 +382,17 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderBoxModelObject* contain // FIXME: We shouldn't need to always dirty the next line. This is only strictly // necessary some of the time, in situations involving BRs. - if (RootInlineBox* nextBox = box->nextRootBox()) + if (RootInlineBox* nextBox = box->nextRootBox()) { nextBox->markDirty(); + // Dedicated linebox for floats may be added as the last rootbox. If this occurs with BRs inside inlines that propagte their lineboxes to + // the parent flow, we need to invalidate it explicitly. + // FIXME: We should be able to figure out the actual "changed child" even when we are calling through empty inlines recursively. + if (is<RenderInline>(child) && !downcast<RenderInline>(child).firstLineBoxIncludingCulling()) { + auto* lastRootBox = nextBox->blockFlow().lastRootBox(); + if (lastRootBox->isTrailingFloatsRootInlineBox() && !lastRootBox->isDirty()) + lastRootBox->markDirty(); + } + } } } @@ -402,8 +401,8 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderBoxModelObject* contain void RenderLineBoxList::checkConsistency() const { #ifdef CHECK_CONSISTENCY - const InlineFlowBox* prev = 0; - for (const InlineFlowBox* child = m_firstLineBox; child != 0; child = child->nextLineBox()) { + const InlineFlowBox* prev = nullptr; + for (const InlineFlowBox* child = m_firstLineBox; child != nullptr; child = child->nextLineBox()) { ASSERT(child->prevLineBox() == prev); prev = child; } |