summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderInline.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/RenderInline.cpp')
-rw-r--r--Source/WebCore/rendering/RenderInline.cpp1090
1 files changed, 608 insertions, 482 deletions
diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp
index 89b8ca407..8b529030b 100644
--- a/Source/WebCore/rendering/RenderInline.cpp
+++ b/Source/WebCore/rendering/RenderInline.cpp
@@ -25,20 +25,24 @@
#include "Chrome.h"
#include "FloatQuad.h"
+#include "FrameSelection.h"
#include "GraphicsContext.h"
#include "HitTestResult.h"
#include "InlineElementBox.h"
#include "InlineTextBox.h"
-#include "Page.h"
#include "RenderBlock.h"
+#include "RenderChildIterator.h"
#include "RenderFullScreen.h"
#include "RenderGeometryMap.h"
#include "RenderIterator.h"
#include "RenderLayer.h"
#include "RenderLineBreak.h"
+#include "RenderListMarker.h"
#include "RenderNamedFlowThread.h"
+#include "RenderTable.h"
#include "RenderTheme.h"
#include "RenderView.h"
+#include "Settings.h"
#include "StyleInheritedData.h"
#include "TransformState.h"
#include "VisiblePosition.h"
@@ -49,14 +53,14 @@
namespace WebCore {
-RenderInline::RenderInline(Element& element, PassRef<RenderStyle> style)
- : RenderBoxModelObject(element, std::move(style), RenderInlineFlag)
+RenderInline::RenderInline(Element& element, RenderStyle&& style)
+ : RenderBoxModelObject(element, WTFMove(style), RenderInlineFlag)
{
setChildrenInline(true);
}
-RenderInline::RenderInline(Document& document, PassRef<RenderStyle> style)
- : RenderBoxModelObject(document, std::move(style), RenderInlineFlag)
+RenderInline::RenderInline(Document& document, RenderStyle&& style)
+ : RenderBoxModelObject(document, WTFMove(style), RenderInlineFlag)
{
setChildrenInline(true);
}
@@ -79,24 +83,13 @@ void RenderInline::willBeDestroyed()
// Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
// properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
destroyLeftoverChildren();
-
- // Destroy our continuation before anything other than anonymous children.
- // The reason we don't destroy it before anonymous children is that they may
- // have continuations of their own that are anonymous children of our continuation.
- RenderBoxModelObject* continuation = this->continuation();
- if (continuation) {
- continuation->destroy();
- setContinuation(0);
- }
- if (!documentBeingDestroyed()) {
+ if (!renderTreeBeingDestroyed()) {
if (firstLineBox()) {
// We can't wait for RenderBoxModelObject::destroy to clear the selection,
// because by then we will have nuked the line boxes.
- // FIXME: The FrameSelection should be responsible for this when it
- // is notified of DOM mutations.
if (isSelectionBorder())
- view().clearSelection();
+ frame().selection().setNeedsSelectionUpdate();
// If line boxes are contained inside a root, that means we're an inline.
// In that case, we need to remove all the line boxes so that the parent
@@ -104,11 +97,11 @@ void RenderInline::willBeDestroyed()
// not have a parent that means they are either already disconnected or
// root lines that can just be destroyed without disconnecting.
if (firstLineBox()->parent()) {
- for (auto box = firstLineBox(); box; box = box->nextLineBox())
+ for (auto* box = firstLineBox(); box; box = box->nextLineBox())
box->removeFromParent();
}
- } else if (parent())
- parent()->dirtyLinesFromChangedChild(this);
+ } else if (parent())
+ parent()->dirtyLinesFromChangedChild(*this);
}
m_lineBoxes.deleteLineBoxes();
@@ -122,20 +115,18 @@ RenderInline* RenderInline::inlineElementContinuation() const
if (!continuation)
return nullptr;
- if (continuation->isRenderInline())
- return toRenderInline(continuation);
+ if (is<RenderInline>(*continuation))
+ return downcast<RenderInline>(continuation);
- return continuation->isRenderBlock() ? toRenderBlock(continuation)->inlineElementContinuation() : nullptr;
+ return is<RenderBlock>(*continuation) ? downcast<RenderBlock>(*continuation).inlineElementContinuation() : nullptr;
}
void RenderInline::updateFromStyle()
{
RenderBoxModelObject::updateFromStyle();
- setInline(true); // Needed for run-ins, since run-in is considered a block display type.
-
// FIXME: Support transforms and reflections on inline flows someday.
- setHasTransform(false);
+ setHasTransformRelatedProperty(false);
setHasReflection(false);
}
@@ -146,30 +137,43 @@ static RenderElement* inFlowPositionedInlineAncestor(RenderElement* p)
return p;
p = p->parent();
}
- return 0;
+ return nullptr;
}
-static void updateStyleOfAnonymousBlockContinuations(RenderBlock& block, const RenderStyle* newStyle, const RenderStyle* oldStyle)
+static void updateStyleOfAnonymousBlockContinuations(const RenderBlock& block, const RenderStyle* newStyle, const RenderStyle* oldStyle)
{
- for (RenderBox* box = &block; box && box->isAnonymousBlock(); box = box->nextSiblingBox()) {
+ // If any descendant blocks exist then they will be in the next anonymous block and its siblings.
+ for (RenderBox* box = block.nextSiblingBox(); box && box->isAnonymousBlock(); box = box->nextSiblingBox()) {
if (box->style().position() == newStyle->position())
continue;
- if (!box->isRenderBlock())
- break; // We're done if we ever encounter something other than a RenderBlock.
+ if (!is<RenderBlock>(*box))
+ continue;
- RenderBlock* block = toRenderBlock(box);
- if (!block->isAnonymousBlockContinuation())
- break; // We're done if we ever encounter something other than a continuation RenderBlock.
+ RenderBlock& block = downcast<RenderBlock>(*box);
+ if (!block.isAnonymousBlockContinuation())
+ continue;
// If we are no longer in-flow positioned but our descendant block(s) still have an in-flow positioned ancestor then
// their containing anonymous block should keep its in-flow positioning.
- RenderInline* cont = block->inlineElementContinuation();
- if (oldStyle->hasInFlowPosition() && inFlowPositionedInlineAncestor(cont))
+ RenderInline* continuation = block.inlineElementContinuation();
+ if (oldStyle->hasInFlowPosition() && inFlowPositionedInlineAncestor(continuation))
continue;
- auto blockStyle = RenderStyle::createAnonymousStyleWithDisplay(&block->style(), BLOCK);
- blockStyle.get().setPosition(newStyle->position());
- block->setStyle(std::move(blockStyle));
+ auto blockStyle = RenderStyle::createAnonymousStyleWithDisplay(block.style(), BLOCK);
+ blockStyle.setPosition(newStyle->position());
+ block.setStyle(WTFMove(blockStyle));
+ }
+}
+
+void RenderInline::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
+{
+ RenderBoxModelObject::styleWillChange(diff, newStyle);
+ // RenderInlines forward their absolute positioned descendants to their (non-anonymous) containing block.
+ // Check if this non-anonymous containing block can hold the absolute positioned elements when the inline is no longer positioned.
+ if (canContainAbsolutelyPositionedObjects() && newStyle.position() == StaticPosition) {
+ auto* container = containingBlockForAbsolutePosition();
+ if (container && !container->canContainAbsolutelyPositionedObjects())
+ container->removePositionedObjects(nullptr, NewContainingBlock);
}
}
@@ -183,29 +187,24 @@ void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
// e.g., <font>foo <h4>goo</h4> moo</font>. The <font> inlines before
// and after the block share the same style, but the block doesn't
// need to pass its style on to anyone else.
- RenderStyle& newStyle = style();
+ auto& newStyle = style();
RenderInline* continuation = inlineElementContinuation();
if (continuation) {
for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation()) {
RenderBoxModelObject* nextCont = currCont->continuation();
currCont->setContinuation(nullptr);
- currCont->setStyle(newStyle);
+ currCont->setStyle(RenderStyle::clone(newStyle));
currCont->setContinuation(nextCont);
}
// If an inline's in-flow positioning has changed and it is part of an active continuation as a descendant of an anonymous containing block,
// then any descendant blocks will need to change their in-flow positioning accordingly.
// Do this by updating the position of the descendant blocks' containing anonymous blocks - there may be more than one.
- if (containingBlock()->isAnonymousBlock() && oldStyle && newStyle.position() != oldStyle->position() && (newStyle.hasInFlowPosition() || oldStyle->hasInFlowPosition())) {
- // If any descendant blocks exist then they will be in the next anonymous block and its siblings.
- ASSERT(containingBlock()->nextSibling());
- RenderBlock& block = *toRenderBlock(containingBlock()->nextSibling());
- ASSERT(block.isAnonymousBlock());
- updateStyleOfAnonymousBlockContinuations(block, &newStyle, oldStyle);
- }
+ if (containingBlock()->isAnonymousBlock() && oldStyle && newStyle.position() != oldStyle->position() && (newStyle.hasInFlowPosition() || oldStyle->hasInFlowPosition()))
+ updateStyleOfAnonymousBlockContinuations(*containingBlock(), &newStyle, oldStyle);
}
if (!alwaysCreateLineBoxes()) {
- bool alwaysCreateLineBoxes = hasSelfPaintingLayer() || hasBoxDecorations() || newStyle.hasPadding() || newStyle.hasMargin() || hasOutline();
+ bool alwaysCreateLineBoxes = hasSelfPaintingLayer() || hasVisibleBoxDecorations() || newStyle.hasBorder() || newStyle.hasPadding() || newStyle.hasMargin() || hasOutline();
if (oldStyle && alwaysCreateLineBoxes) {
dirtyLineBoxes(false);
setNeedsLayout();
@@ -221,23 +220,23 @@ void RenderInline::updateAlwaysCreateLineBoxes(bool fullLayout)
if (alwaysCreateLineBoxes())
return;
- RenderStyle* parentStyle = &parent()->style();
- RenderInline* parentRenderInline = parent()->isRenderInline() ? toRenderInline(parent()) : 0;
+ auto* parentStyle = &parent()->style();
+ RenderInline* parentRenderInline = is<RenderInline>(*parent()) ? downcast<RenderInline>(parent()) : nullptr;
bool checkFonts = document().inNoQuirksMode();
RenderFlowThread* flowThread = flowThreadContainingBlock();
bool alwaysCreateLineBoxes = (parentRenderInline && parentRenderInline->alwaysCreateLineBoxes())
|| (parentRenderInline && parentStyle->verticalAlign() != BASELINE)
|| style().verticalAlign() != BASELINE
|| style().textEmphasisMark() != TextEmphasisMarkNone
- || (checkFonts && (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(style().font().fontMetrics())
+ || (checkFonts && (!parentStyle->fontCascade().fontMetrics().hasIdenticalAscentDescentAndLineGap(style().fontCascade().fontMetrics())
|| parentStyle->lineHeight() != style().lineHeight()))
|| (flowThread && flowThread->isRenderNamedFlowThread()); // FIXME: Enable the optimization once we make overflow computation for culled inlines in regions.
- if (!alwaysCreateLineBoxes && checkFonts && document().styleSheetCollection().usesFirstLineRules()) {
+ if (!alwaysCreateLineBoxes && checkFonts && view().usesFirstLineRules()) {
// Have to check the first line style as well.
parentStyle = &parent()->firstLineStyle();
- RenderStyle& childStyle = firstLineStyle();
- alwaysCreateLineBoxes = !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle.font().fontMetrics())
+ auto& childStyle = firstLineStyle();
+ alwaysCreateLineBoxes = !parentStyle->fontCascade().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle.fontCascade().fontMetrics())
|| childStyle.verticalAlign() != BASELINE
|| parentStyle->lineHeight() != childStyle.lineHeight();
}
@@ -249,7 +248,7 @@ void RenderInline::updateAlwaysCreateLineBoxes(bool fullLayout)
}
}
-LayoutRect RenderInline::localCaretRect(InlineBox* inlineBox, int, LayoutUnit* extraWidthToEndOfLine)
+LayoutRect RenderInline::localCaretRect(InlineBox* inlineBox, unsigned, LayoutUnit* extraWidthToEndOfLine)
{
if (firstChild()) {
// This condition is possible if the RenderInline is at an editing boundary,
@@ -265,26 +264,29 @@ LayoutRect RenderInline::localCaretRect(InlineBox* inlineBox, int, LayoutUnit* e
if (extraWidthToEndOfLine)
*extraWidthToEndOfLine = 0;
- LayoutRect caretRect = localCaretRectForEmptyElement(borderAndPaddingWidth(), 0);
+ LayoutRect caretRect = localCaretRectForEmptyElement(horizontalBorderAndPaddingExtent(), 0);
if (InlineBox* firstBox = firstLineBox())
- caretRect.moveBy(roundedLayoutPoint(firstBox->topLeft()));
+ caretRect.moveBy(LayoutPoint(firstBox->topLeft()));
return caretRect;
}
void RenderInline::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
+ auto* beforeChildOrPlaceholder = beforeChild;
+ if (auto* flowThread = flowThreadContainingBlock())
+ beforeChildOrPlaceholder = flowThread->resolveMovedChild(beforeChild);
if (continuation())
- return addChildToContinuation(newChild, beforeChild);
- return addChildIgnoringContinuation(newChild, beforeChild);
+ return addChildToContinuation(newChild, beforeChildOrPlaceholder);
+ return addChildIgnoringContinuation(newChild, beforeChildOrPlaceholder);
}
static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
{
- if (renderer->isInline() && !renderer->isReplaced())
- return toRenderInline(renderer)->continuation();
- return toRenderBlock(renderer)->inlineElementContinuation();
+ if (is<RenderInline>(*renderer) && !renderer->isReplaced())
+ return downcast<RenderInline>(*renderer).continuation();
+ return downcast<RenderBlock>(*renderer).inlineElementContinuation();
}
RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild)
@@ -312,25 +314,34 @@ RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild
return last;
}
+static bool newChildIsInline(const RenderObject& newChild, const RenderInline& parent)
+{
+ // inline parent generates inline-table.
+ return newChild.isInline() | (parent.childRequiresTable(newChild) && parent.style().display() == INLINE);
+}
+
void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
{
// Make sure we don't append things after :after-generated content if we have it.
if (!beforeChild && isAfterContent(lastChild()))
beforeChild = lastChild();
-
- if (!newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned()) {
+
+ bool useNewBlockInsideInlineModel = settings().newBlockInsideInlineModelEnabled();
+ bool childInline = newChildIsInline(*newChild, *this);
+ // This code is for the old block-inside-inline model that uses continuations.
+ if (!useNewBlockInsideInlineModel && !childInline && !newChild->isFloatingOrOutOfFlowPositioned()) {
// We are placing a block inside an inline. We have to perform a split of this
// inline into continuations. This involves creating an anonymous block box to hold
// |newChild|. We then make that block box a continuation of this inline. We take all of
// the children after |beforeChild| and put them in a clone of this object.
- auto newStyle = RenderStyle::createAnonymousStyleWithDisplay(&style(), BLOCK);
+ auto newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
// If inside an inline affected by in-flow positioning the block needs to be affected by it too.
// Giving the block a layer like this allows it to collect the x/y offsets from inline parents later.
if (auto positionedAncestor = inFlowPositionedInlineAncestor(this))
- newStyle.get().setPosition(positionedAncestor->style().position());
+ newStyle.setPosition(positionedAncestor->style().position());
- RenderBlock* newBox = new RenderBlockFlow(document(), std::move(newStyle));
+ RenderBlock* newBox = new RenderBlockFlow(document(), WTFMove(newStyle));
newBox->initializeStyle();
RenderBoxModelObject* oldContinuation = continuation();
setContinuation(newBox);
@@ -338,6 +349,65 @@ void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderOb
splitFlow(beforeChild, newBox, newChild, oldContinuation);
return;
}
+
+ if (!useNewBlockInsideInlineModel) {
+ RenderBoxModelObject::addChild(newChild, beforeChild);
+ newChild->setNeedsLayoutAndPrefWidthsRecalc();
+ return;
+ }
+
+ // This code is for the new block-inside-inline model that uses anonymous inline blocks.
+ // If the requested beforeChild is not one of our children, then this is most likely because
+ // there is an anonymous inline-block box within this object that contains the beforeChild.
+ // Insert the child into the anonymous inline-block box instead of here.
+ // A second possibility is that the beforeChild is an anonymous block inside the anonymous inline block.
+ // This can happen if inlines are inserted in between two of the anonymous inline block's block-level
+ // children after it has been created.
+ if (beforeChild && beforeChild->parent() != this) {
+ ASSERT(beforeChild->parent());
+ ASSERT(beforeChild->parent()->isAnonymousInlineBlock() || beforeChild->parent()->isAnonymousBlock());
+ if (beforeChild->parent()->isAnonymousInlineBlock()) {
+ if (!childInline || (childInline && beforeChild->parent()->firstChild() != beforeChild))
+ beforeChild->parent()->addChild(newChild, beforeChild);
+ else
+ addChild(newChild, beforeChild->parent());
+ } else if (beforeChild->parent()->isAnonymousBlock()) {
+ ASSERT(!beforeChild->parent()->parent() || beforeChild->parent()->parent()->isAnonymousInlineBlock());
+ ASSERT(childInline);
+ if (childInline || (!childInline && beforeChild->parent()->firstChild() != beforeChild))
+ beforeChild->parent()->addChild(newChild, beforeChild);
+ else
+ addChild(newChild, beforeChild->parent());
+ }
+ return;
+ }
+
+ if (!childInline) {
+ // We are placing a block inside an inline. We have to place the block inside an anonymous inline-block.
+ // This inline-block can house a sequence of contiguous block-level children, and they will all sit on the
+ // same "line" together. We try to reuse an existing inline-block if possible.
+ if (beforeChild) {
+ if (beforeChild->previousSibling() && beforeChild->previousSibling()->isAnonymousInlineBlock()) {
+ downcast<RenderBlockFlow>(beforeChild->previousSibling())->addChild(newChild);
+ return;
+ }
+ } else {
+ if (lastChild() && lastChild()->isAnonymousInlineBlock()) {
+ downcast<RenderBlockFlow>(lastChild())->addChild(newChild);
+ return;
+ }
+ }
+
+ if (!newChild->isFloatingOrOutOfFlowPositioned()) {
+ // There was no suitable existing anonymous inline-block. Create a new one.
+ RenderBlockFlow* anonymousInlineBlock = new RenderBlockFlow(document(), RenderStyle::createAnonymousStyleWithDisplay(style(), INLINE_BLOCK));
+ anonymousInlineBlock->initializeStyle();
+
+ RenderBoxModelObject::addChild(anonymousInlineBlock, beforeChild);
+ anonymousInlineBlock->addChild(newChild);
+ return;
+ }
+ }
RenderBoxModelObject::addChild(newChild, beforeChild);
@@ -346,9 +416,10 @@ void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderOb
RenderPtr<RenderInline> RenderInline::clone() const
{
- RenderPtr<RenderInline> cloneInline = createRenderer<RenderInline>(*element(), style());
+ RenderPtr<RenderInline> cloneInline = createRenderer<RenderInline>(*element(), RenderStyle::clone(style()));
cloneInline->initializeStyle();
cloneInline->setFlowThreadState(flowThreadState());
+ cloneInline->setHasOutlineAutoAncestor(hasOutlineAutoAncestor());
return cloneInline;
}
@@ -358,8 +429,6 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
{
// Create a clone of this inline.
RenderPtr<RenderInline> cloneInline = clone();
- cloneInline->setContinuation(oldCont);
-
#if ENABLE(FULLSCREEN_API)
// If we're splitting the inline containing the fullscreened element,
// |beforeChild| may be the renderer for the fullscreened element. However,
@@ -370,26 +439,51 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
if (fullScreenElement && beforeChild && beforeChild->node() == fullScreenElement)
beforeChild = document().fullScreenRenderer();
#endif
-
// Now take all of the children from beforeChild to the end and remove
// them from |this| and place them in the clone.
- RenderObject* o = beforeChild;
- while (o) {
- RenderObject* tmp = o;
- o = tmp->nextSibling();
- removeChildInternal(*tmp, NotifyChildren);
- cloneInline->addChildIgnoringContinuation(tmp, 0);
- tmp->setNeedsLayoutAndPrefWidthsRecalc();
+ for (RenderObject* rendererToMove = beforeChild; rendererToMove;) {
+ RenderObject* nextSibling = rendererToMove->nextSibling();
+ // When anonymous wrapper is present, we might need to move the whole subtree instead.
+ if (rendererToMove->parent() != this) {
+ auto* anonymousParent = rendererToMove->parent();
+ while (anonymousParent && anonymousParent->parent() != this) {
+ ASSERT(anonymousParent->isAnonymous());
+ anonymousParent = anonymousParent->parent();
+ }
+ if (!anonymousParent) {
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ // If beforeChild is the first child in the subtree, we could just move the whole subtree.
+ if (!rendererToMove->previousSibling()) {
+ // Reparent the whole anonymous wrapper tree.
+ rendererToMove = anonymousParent;
+ // Skip to the next sibling that is not in this subtree.
+ nextSibling = anonymousParent->nextSibling();
+ } else if (!rendererToMove->nextSibling()) {
+ // This is the last renderer in the subtree. We need to jump out of the wrapper subtree, so that
+ // the siblings are getting reparented too.
+ nextSibling = anonymousParent->nextSibling();
+ }
+ // Otherwise just move the renderer to the inline clone. Should the renderer need an anon
+ // wrapper, the addChild() will generate one for it.
+ // FIXME: When the anonymous wrapper has multiple children, we end up traversing up to the topmost wrapper
+ // every time, which is a bit wasteful.
+ }
+ rendererToMove->parent()->removeChildInternal(*rendererToMove, NotifyChildren);
+ cloneInline->addChildIgnoringContinuation(rendererToMove);
+ rendererToMove->setNeedsLayoutAndPrefWidthsRecalc();
+ rendererToMove = nextSibling;
}
-
+ cloneInline->setContinuation(oldCont);
// Hook |clone| up as the continuation of the middle block.
middleBlock->setContinuation(cloneInline.get());
// We have been reparented and are now under the fromBlock. We need
// to walk up our inline parent chain until we hit the containing block.
// Once we hit the containing block we're done.
- RenderBoxModelObject* curr = toRenderBoxModelObject(parent());
- RenderBoxModelObject* currChild = this;
+ RenderBoxModelObject* current = downcast<RenderBoxModelObject>(parent());
+ RenderBoxModelObject* currentChild = this;
// FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone.
// There will eventually be a better approach to this problem that will let us nest to a much
@@ -397,58 +491,59 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
// incorrect rendering, but the alternative is to hang forever.
unsigned splitDepth = 1;
const unsigned cMaxSplitDepth = 200;
- while (curr && curr != fromBlock) {
- ASSERT(curr->isRenderInline());
+ while (current && current != fromBlock) {
if (splitDepth < cMaxSplitDepth) {
// Create a new clone.
- RenderPtr<RenderInline> cloneChild = std::move(cloneInline);
- cloneInline = toRenderInline(curr)->clone();
+ RenderPtr<RenderInline> cloneChild = WTFMove(cloneInline);
+ cloneInline = downcast<RenderInline>(*current).clone();
// Insert our child clone as the first child.
- cloneInline->addChildIgnoringContinuation(cloneChild.leakPtr(), 0);
+ cloneInline->addChildIgnoringContinuation(cloneChild.leakPtr());
// Hook the clone up as a continuation of |curr|.
- RenderInline* inlineCurr = toRenderInline(curr);
- oldCont = inlineCurr->continuation();
- inlineCurr->setContinuation(cloneInline.get());
+ RenderInline& currentInline = downcast<RenderInline>(*current);
+ oldCont = currentInline.continuation();
+ currentInline.setContinuation(cloneInline.get());
cloneInline->setContinuation(oldCont);
// Now we need to take all of the children starting from the first child
- // *after* currChild and append them all to the clone.
- o = currChild->nextSibling();
- while (o) {
- RenderObject* tmp = o;
- o = tmp->nextSibling();
- inlineCurr->removeChildInternal(*tmp, NotifyChildren);
- cloneInline->addChildIgnoringContinuation(tmp, 0);
- tmp->setNeedsLayoutAndPrefWidthsRecalc();
+ // *after* currentChild and append them all to the clone.
+ for (auto* current = currentChild->nextSibling(); current;) {
+ auto* next = current->nextSibling();
+ currentInline.removeChildInternal(*current, NotifyChildren);
+ cloneInline->addChildIgnoringContinuation(current);
+ current->setNeedsLayoutAndPrefWidthsRecalc();
+ current = next;
}
}
// Keep walking up the chain.
- currChild = curr;
- curr = toRenderBoxModelObject(curr->parent());
- splitDepth++;
+ currentChild = current;
+ current = downcast<RenderBoxModelObject>(current->parent());
+ ++splitDepth;
}
+ // Clear the flow thread containing blocks cached during the detached state insertions.
+ for (auto& cloneBlockChild : childrenOfType<RenderBlock>(*cloneInline))
+ cloneBlockChild.resetFlowThreadContainingBlockAndChildInfoIncludingDescendants();
+
// Now we are at the block level. We need to put the clone into the toBlock.
toBlock->insertChildInternal(cloneInline.leakPtr(), nullptr, NotifyChildren);
- // Now take all the children after currChild and remove them from the fromBlock
+ // Now take all the children after currentChild and remove them from the fromBlock
// and put them in the toBlock.
- o = currChild->nextSibling();
- while (o) {
- RenderObject* tmp = o;
- o = tmp->nextSibling();
- fromBlock->removeChildInternal(*tmp, NotifyChildren);
- toBlock->insertChildInternal(tmp, nullptr, NotifyChildren);
+ for (auto* current = currentChild->nextSibling(); current;) {
+ auto* next = current->nextSibling();
+ fromBlock->removeChildInternal(*current, NotifyChildren);
+ toBlock->insertChildInternal(current, nullptr, NotifyChildren);
+ current = next;
}
}
void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
RenderObject* newChild, RenderBoxModelObject* oldCont)
{
- RenderBlock* pre = 0;
+ RenderBlock* pre = nullptr;
RenderBlock* block = containingBlock();
// Delete our line boxes before we do the inline split into continuations.
@@ -458,12 +553,12 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
if (block->isAnonymousBlock() && (!block->parent() || !block->parent()->createsAnonymousWrapper())) {
// We can reuse this block and make it the preBlock of the next continuation.
pre = block;
- pre->removePositionedObjects(0);
+ pre->removePositionedObjects(nullptr);
// FIXME-BLOCKFLOW: The enclosing method should likely be switched over
// to only work on RenderBlockFlow, in which case this conversion can be
// removed.
- if (pre->isRenderBlockFlow())
- toRenderBlockFlow(pre)->removeFloatingObjects();
+ if (is<RenderBlockFlow>(*pre))
+ downcast<RenderBlockFlow>(*pre).removeFloatingObjects();
block = block->containingBlock();
} else {
// No anonymous block available for use. Make one.
@@ -471,13 +566,13 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
madeNewBeforeBlock = true;
}
- RenderBlock* post = toRenderBlock(pre->createAnonymousBoxWithSameTypeAs(block));
+ auto& post = downcast<RenderBlock>(*pre->createAnonymousBoxWithSameTypeAs(*block).release());
RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
if (madeNewBeforeBlock)
block->insertChildInternal(pre, boxFirst, NotifyChildren);
block->insertChildInternal(newBlockBox, boxFirst, NotifyChildren);
- block->insertChildInternal(post, boxFirst, NotifyChildren);
+ block->insertChildInternal(&post, boxFirst, NotifyChildren);
block->setChildrenInline(false);
if (madeNewBeforeBlock) {
@@ -491,7 +586,7 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
}
}
- splitInlines(pre, post, newBlockBox, beforeChild, oldCont);
+ 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.
@@ -507,45 +602,59 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
// make new line boxes instead of leaving the old line boxes around.
pre->setNeedsLayoutAndPrefWidthsRecalc();
block->setNeedsLayoutAndPrefWidthsRecalc();
- post->setNeedsLayoutAndPrefWidthsRecalc();
+ post.setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+static bool canUseAsParentForContinuation(const RenderObject* renderer)
+{
+ if (!renderer)
+ return false;
+ if (!is<RenderBlock>(renderer) && renderer->isAnonymous())
+ return false;
+ if (is<RenderTable>(renderer))
+ return false;
+ return true;
}
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 = toRenderBoxModelObject(beforeChild->parent());
- else {
- RenderBoxModelObject* cont = nextContinuation(flow);
- if (cont)
- beforeChildParent = cont;
- else
- beforeChildParent = flow;
- }
+ auto* flow = continuationBefore(beforeChild);
+ // It may or may not be the direct parent of the beforeChild.
+ RenderBoxModelObject* beforeChildAncestor = nullptr;
+ if (!beforeChild) {
+ auto* continuation = nextContinuation(flow);
+ beforeChildAncestor = continuation ? continuation : flow;
+ } else if (canUseAsParentForContinuation(beforeChild->parent()))
+ beforeChildAncestor = downcast<RenderBoxModelObject>(beforeChild->parent());
+ else if (beforeChild->parent()) {
+ // In case of anonymous wrappers, the parent of the beforeChild is mostly irrelevant. What we need is the topmost wrapper.
+ auto* parent = beforeChild->parent();
+ while (parent && parent->parent() && parent->parent()->isAnonymous()) {
+ // The ancestor candidate needs to be inside the continuation.
+ if (parent->hasContinuation())
+ break;
+ parent = parent->parent();
+ }
+ ASSERT(parent && parent->parent());
+ beforeChildAncestor = downcast<RenderBoxModelObject>(parent->parent());
+ } else
+ ASSERT_NOT_REACHED();
if (newChild->isFloatingOrOutOfFlowPositioned())
- return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
+ return beforeChildAncestor->addChildIgnoringContinuation(newChild, beforeChild);
+ if (flow == beforeChildAncestor)
+ return flow->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);
- }
+ bool childInline = newChildIsInline(*newChild, *this);
+ // 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 == beforeChildAncestor->isInline())
+ return beforeChildAncestor->addChildIgnoringContinuation(newChild, beforeChild);
+ if (flow->isInline() == childInline)
+ return flow->addChildIgnoringContinuation(newChild); // Just treat like an append.
+ return beforeChildAncestor->addChildIgnoringContinuation(newChild, beforeChild);
}
void RenderInline::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
@@ -554,91 +663,92 @@ void RenderInline::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
}
template<typename GeneratorContext>
-void RenderInline::generateLineBoxRects(GeneratorContext& yield) const
+void RenderInline::generateLineBoxRects(GeneratorContext& context) const
{
if (!alwaysCreateLineBoxes())
- generateCulledLineBoxRects(yield, this);
+ generateCulledLineBoxRects(context, this);
else if (InlineFlowBox* curr = firstLineBox()) {
for (; curr; curr = curr->nextLineBox())
- yield(FloatRect(curr->topLeft(), curr->size()));
+ context.addRect(FloatRect(curr->topLeft(), curr->size()));
} else
- yield(FloatRect());
+ context.addRect(FloatRect());
}
template<typename GeneratorContext>
-void RenderInline::generateCulledLineBoxRects(GeneratorContext& yield, const RenderInline* container) const
+void RenderInline::generateCulledLineBoxRects(GeneratorContext& context, const RenderInline* container) const
{
if (!culledInlineFirstLineBox()) {
- yield(FloatRect());
+ context.addRect(FloatRect());
return;
}
bool isHorizontal = style().isHorizontalWritingMode();
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (curr->isFloatingOrOutOfFlowPositioned())
+ for (auto& current : childrenOfType<RenderObject>(*this)) {
+ if (current.isFloatingOrOutOfFlowPositioned())
continue;
-
+
// We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
// direction (aligned to the root box's baseline).
- if (curr->isBox()) {
- RenderBox* currBox = toRenderBox(curr);
- if (currBox->inlineBoxWrapper()) {
- const RootInlineBox& rootBox = currBox->inlineBoxWrapper()->root();
+ if (is<RenderBox>(current)) {
+ auto& renderBox = downcast<RenderBox>(current);
+ if (renderBox.inlineBoxWrapper()) {
+ const RootInlineBox& rootBox = renderBox.inlineBoxWrapper()->root();
const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
- int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
- int logicalHeight = containerStyle.font().fontMetrics().height();
+ int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().fontCascade().fontMetrics().ascent() - containerStyle.fontCascade().fontMetrics().ascent());
+ int logicalHeight = containerStyle.fontCascade().fontMetrics().height();
if (isHorizontal)
- yield(FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, currBox->width() + currBox->marginWidth(), logicalHeight));
+ context.addRect(FloatRect(renderBox.inlineBoxWrapper()->x() - renderBox.marginLeft(), logicalTop, renderBox.width() + renderBox.horizontalMarginExtent(), logicalHeight));
else
- yield(FloatRect(logicalTop, currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginHeight()));
+ context.addRect(FloatRect(logicalTop, renderBox.inlineBoxWrapper()->y() - renderBox.marginTop(), logicalHeight, renderBox.height() + renderBox.verticalMarginExtent()));
}
- } else if (curr->isRenderInline()) {
+ } else if (is<RenderInline>(current)) {
// If the child doesn't need line boxes either, then we can recur.
- RenderInline* currInline = toRenderInline(curr);
- if (!currInline->alwaysCreateLineBoxes())
- currInline->generateCulledLineBoxRects(yield, container);
+ auto& renderInline = downcast<RenderInline>(current);
+ if (!renderInline.alwaysCreateLineBoxes())
+ renderInline.generateCulledLineBoxRects(context, container);
else {
- for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
+ for (InlineFlowBox* childLine = renderInline.firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
const RootInlineBox& rootBox = childLine->root();
const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
- int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
+ int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().fontCascade().fontMetrics().ascent() - containerStyle.fontCascade().fontMetrics().ascent());
int logicalHeight = containerStyle.fontMetrics().height();
- if (isHorizontal)
- yield(FloatRect(childLine->x() - childLine->marginLogicalLeft(),
+ if (isHorizontal) {
+ context.addRect(FloatRect(childLine->x() - childLine->marginLogicalLeft(),
logicalTop,
childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(),
logicalHeight));
- else
- yield(FloatRect(logicalTop,
+ } else {
+ context.addRect(FloatRect(logicalTop,
childLine->y() - childLine->marginLogicalLeft(),
logicalHeight,
childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight()));
+ }
}
}
- } else if (curr->isText()) {
- RenderText* currText = toRenderText(curr);
- for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) {
+ } else if (is<RenderText>(current)) {
+ auto& currText = downcast<RenderText>(current);
+ for (InlineTextBox* childText = currText.firstTextBox(); childText; childText = childText->nextTextBox()) {
const RootInlineBox& rootBox = childText->root();
const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
- int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
- int logicalHeight = containerStyle.font().fontMetrics().height();
+ int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().fontCascade().fontMetrics().ascent() - containerStyle.fontCascade().fontMetrics().ascent());
+ int logicalHeight = containerStyle.fontCascade().fontMetrics().height();
if (isHorizontal)
- yield(FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight));
+ context.addRect(FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight));
else
- yield(FloatRect(logicalTop, childText->y(), logicalHeight, childText->logicalWidth()));
+ context.addRect(FloatRect(logicalTop, childText->y(), logicalHeight, childText->logicalWidth()));
}
- } else if (curr->isLineBreak()) {
- if (InlineBox* inlineBox = toRenderLineBreak(curr)->inlineBoxWrapper()) {
+ } else if (is<RenderLineBreak>(current)) {
+ if (auto* inlineBox = downcast<RenderLineBreak>(current).inlineBoxWrapper()) {
// FIXME: This could use a helper to share these with text path.
const RootInlineBox& rootBox = inlineBox->root();
const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
- int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
+ int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().fontCascade().fontMetrics().ascent() - containerStyle.fontCascade().fontMetrics().ascent());
int logicalHeight = containerStyle.fontMetrics().height();
if (isHorizontal)
- yield(FloatRect(inlineBox->x(), logicalTop, inlineBox->logicalWidth(), logicalHeight));
+ context.addRect(FloatRect(inlineBox->x(), logicalTop, inlineBox->logicalWidth(), logicalHeight));
else
- yield(FloatRect(logicalTop, inlineBox->y(), logicalHeight, inlineBox->logicalWidth()));
+ context.addRect(FloatRect(logicalTop, inlineBox->y(), logicalHeight, inlineBox->logicalWidth()));
}
}
}
@@ -648,18 +758,18 @@ namespace {
class AbsoluteRectsGeneratorContext {
public:
- AbsoluteRectsGeneratorContext(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset)
+ AbsoluteRectsGeneratorContext(Vector<LayoutRect>& rects, const LayoutPoint& accumulatedOffset)
: m_rects(rects)
, m_accumulatedOffset(accumulatedOffset) { }
- void operator()(const FloatRect& rect)
+ void addRect(const FloatRect& rect)
{
- IntRect intRect = enclosingIntRect(rect);
- intRect.move(m_accumulatedOffset.x(), m_accumulatedOffset.y());
- m_rects.append(intRect);
+ LayoutRect adjustedRect = LayoutRect(rect);
+ adjustedRect.moveBy(m_accumulatedOffset);
+ m_rects.append(adjustedRect);
}
private:
- Vector<IntRect>& m_rects;
+ Vector<LayoutRect>& m_rects;
const LayoutPoint& m_accumulatedOffset;
};
@@ -667,13 +777,16 @@ private:
void RenderInline::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
{
- AbsoluteRectsGeneratorContext context(rects, accumulatedOffset);
+ Vector<LayoutRect> lineboxRects;
+ AbsoluteRectsGeneratorContext context(lineboxRects, accumulatedOffset);
generateLineBoxRects(context);
+ for (const auto& rect : lineboxRects)
+ rects.append(snappedIntRect(rect));
if (RenderBoxModelObject* continuation = this->continuation()) {
- if (continuation->isBox()) {
- RenderBox* box = toRenderBox(continuation);
- continuation->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location() + box->locationOffset()));
+ if (is<RenderBox>(*continuation)) {
+ auto& box = downcast<RenderBox>(*continuation);
+ continuation->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location() + box.locationOffset()));
} else
continuation->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location()));
}
@@ -688,10 +801,10 @@ public:
: m_quads(quads)
, m_geometryMap()
{
- m_geometryMap.pushMappingsToAncestor(renderer, 0);
+ m_geometryMap.pushMappingsToAncestor(renderer, nullptr);
}
- void operator()(const FloatRect& rect)
+ void addRect(const FloatRect& rect)
{
m_quads.append(m_geometryMap.absoluteRect(rect));
}
@@ -741,10 +854,8 @@ static LayoutUnit computeMargin(const RenderInline* renderer, const Length& marg
return 0;
if (margin.isFixed())
return margin.value();
- if (margin.isPercent())
+ if (margin.isPercentOrCalculated())
return minimumValueForLength(margin, std::max<LayoutUnit>(0, renderer->containingBlock()->availableLogicalWidth()));
- if (margin.isViewportPercentage())
- return valueForLength(margin, 0, &renderer->view());
return 0;
}
@@ -799,8 +910,6 @@ const char* RenderInline::renderName() const
return "RenderInline (generated)";
if (isAnonymous())
return "RenderInline (generated)";
- if (isRunIn())
- return "RenderInline (run-in)";
return "RenderInline";
}
@@ -814,13 +923,20 @@ namespace {
class HitTestCulledInlinesGeneratorContext {
public:
- HitTestCulledInlinesGeneratorContext(Region& region, const HitTestLocation& location) : m_intersected(false), m_region(region), m_location(location) { }
- void operator()(const FloatRect& rect)
+ HitTestCulledInlinesGeneratorContext(Region& region, const HitTestLocation& location)
+ : m_intersected(false)
+ , m_region(region)
+ , m_location(location)
+ { }
+
+ void addRect(const FloatRect& rect)
{
m_intersected = m_intersected || m_location.intersects(rect);
m_region.unite(enclosingIntRect(rect));
}
+
bool intersected() const { return m_intersected; }
+
private:
bool m_intersected;
Region& m_region;
@@ -851,27 +967,27 @@ bool RenderInline::hitTestCulledInline(const HitTestRequest& request, HitTestRes
return false;
}
-VisiblePosition RenderInline::positionForPoint(const LayoutPoint& point)
+VisiblePosition RenderInline::positionForPoint(const LayoutPoint& point, const RenderRegion* region)
{
// FIXME: Does not deal with relative or sticky positioned inlines (should it?)
- RenderBlock* cb = containingBlock();
+ RenderBlock& containingBlock = *this->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);
+ return containingBlock.positionForPoint(point, region);
}
// Translate the coords from the pre-anonymous block to the post-anonymous block.
- LayoutPoint parentBlockPoint = cb->location() + point;
- RenderBoxModelObject* c = continuation();
- while (c) {
- RenderBox* contBlock = c->isInline() ? c->containingBlock() : toRenderBlock(c);
- if (c->isInline() || c->firstChild())
- return c->positionForPoint(parentBlockPoint - contBlock->locationOffset());
- c = toRenderBlock(c)->inlineElementContinuation();
+ LayoutPoint parentBlockPoint = containingBlock.location() + point;
+ RenderBoxModelObject* continuation = this->continuation();
+ while (continuation) {
+ RenderBlock* currentBlock = continuation->isInline() ? continuation->containingBlock() : downcast<RenderBlock>(continuation);
+ if (continuation->isInline() || continuation->firstChild())
+ return continuation->positionForPoint(parentBlockPoint - currentBlock->locationOffset(), region);
+ continuation = downcast<RenderBlock>(*continuation).inlineElementContinuation();
}
- return RenderBoxModelObject::positionForPoint(point);
+ return RenderBoxModelObject::positionForPoint(point, region);
}
namespace {
@@ -879,7 +995,8 @@ namespace {
class LinesBoundingBoxGeneratorContext {
public:
LinesBoundingBoxGeneratorContext(FloatRect& rect) : m_rect(rect) { }
- void operator()(const FloatRect& rect)
+
+ void addRect(const FloatRect& rect)
{
m_rect.uniteIfNonZero(rect);
}
@@ -930,62 +1047,60 @@ IntRect RenderInline::linesBoundingBox() const
InlineBox* RenderInline::culledInlineFirstLineBox() const
{
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (curr->isFloatingOrOutOfFlowPositioned())
+ for (auto& current : childrenOfType<RenderObject>(*this)) {
+ if (current.isFloatingOrOutOfFlowPositioned())
continue;
-
+
// We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
// direction (aligned to the root box's baseline).
- if (curr->isBox()) {
- const auto& renderBox = *toRenderBox(curr);
+ if (is<RenderBox>(current)) {
+ auto& renderBox = downcast<RenderBox>(current);
if (renderBox.inlineBoxWrapper())
return renderBox.inlineBoxWrapper();
- } else if (curr->isLineBreak()) {
- RenderLineBreak* renderBR = toRenderLineBreak(curr);
- if (renderBR->inlineBoxWrapper())
- return renderBR->inlineBoxWrapper();
- } else if (curr->isRenderInline()) {
- RenderInline* currInline = toRenderInline(curr);
- InlineBox* result = currInline->firstLineBoxIncludingCulling();
- if (result)
+ } else if (is<RenderLineBreak>(current)) {
+ auto& renderBR = downcast<RenderLineBreak>(current);
+ if (renderBR.inlineBoxWrapper())
+ return renderBR.inlineBoxWrapper();
+ } else if (is<RenderInline>(current)) {
+ auto& renderInline = downcast<RenderInline>(current);
+ if (InlineBox* result = renderInline.firstLineBoxIncludingCulling())
return result;
- } else if (curr->isText()) {
- RenderText* currText = toRenderText(curr);
- if (currText->firstTextBox())
- return currText->firstTextBox();
+ } else if (is<RenderText>(current)) {
+ auto& renderText = downcast<RenderText>(current);
+ if (renderText.firstTextBox())
+ return renderText.firstTextBox();
}
}
- return 0;
+ return nullptr;
}
InlineBox* RenderInline::culledInlineLastLineBox() const
{
- for (RenderObject* curr = lastChild(); curr; curr = curr->previousSibling()) {
- if (curr->isFloatingOrOutOfFlowPositioned())
+ for (RenderObject* current = lastChild(); current; current = current->previousSibling()) {
+ if (current->isFloatingOrOutOfFlowPositioned())
continue;
// We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
// direction (aligned to the root box's baseline).
- if (curr->isBox()) {
- const auto& renderBox = *toRenderBox(curr);
+ if (is<RenderBox>(*current)) {
+ const auto& renderBox = downcast<RenderBox>(*current);
if (renderBox.inlineBoxWrapper())
return renderBox.inlineBoxWrapper();
- } else if (curr->isLineBreak()) {
- RenderLineBreak* renderBR = toRenderLineBreak(curr);
- if (renderBR->inlineBoxWrapper())
- return renderBR->inlineBoxWrapper();
- } else if (curr->isRenderInline()) {
- RenderInline* currInline = toRenderInline(curr);
- InlineBox* result = currInline->lastLineBoxIncludingCulling();
- if (result)
+ } else if (is<RenderLineBreak>(*current)) {
+ RenderLineBreak& renderBR = downcast<RenderLineBreak>(*current);
+ if (renderBR.inlineBoxWrapper())
+ return renderBR.inlineBoxWrapper();
+ } else if (is<RenderInline>(*current)) {
+ RenderInline& renderInline = downcast<RenderInline>(*current);
+ if (InlineBox* result = renderInline.lastLineBoxIncludingCulling())
return result;
- } else if (curr->isText()) {
- RenderText* currText = toRenderText(curr);
- if (currText->lastTextBox())
- return currText->lastTextBox();
+ } else if (is<RenderText>(*current)) {
+ RenderText& renderText = downcast<RenderText>(*current);
+ if (renderText.lastTextBox())
+ return renderText.lastTextBox();
}
}
- return 0;
+ return nullptr;
}
LayoutRect RenderInline::culledInlineVisualOverflowBoundingBox() const
@@ -995,35 +1110,35 @@ LayoutRect RenderInline::culledInlineVisualOverflowBoundingBox() const
generateCulledLineBoxRects(context, this);
LayoutRect result(enclosingLayoutRect(floatResult));
bool isHorizontal = style().isHorizontalWritingMode();
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (curr->isFloatingOrOutOfFlowPositioned())
+ for (auto& current : childrenOfType<RenderObject>(*this)) {
+ if (current.isFloatingOrOutOfFlowPositioned())
continue;
-
+
// For overflow we just have to propagate by hand and recompute it all.
- if (curr->isBox()) {
- RenderBox* currBox = toRenderBox(curr);
- if (!currBox->hasSelfPaintingLayer() && currBox->inlineBoxWrapper()) {
- LayoutRect logicalRect = currBox->logicalVisualOverflowRectForPropagation(&style());
+ if (is<RenderBox>(current)) {
+ auto& renderBox = downcast<RenderBox>(current);
+ if (!renderBox.hasSelfPaintingLayer() && renderBox.inlineBoxWrapper()) {
+ LayoutRect logicalRect = renderBox.logicalVisualOverflowRectForPropagation(&style());
if (isHorizontal) {
- logicalRect.moveBy(currBox->location());
+ logicalRect.moveBy(renderBox.location());
result.uniteIfNonZero(logicalRect);
} else {
- logicalRect.moveBy(currBox->location());
+ logicalRect.moveBy(renderBox.location());
result.uniteIfNonZero(logicalRect.transposedRect());
}
}
- } else if (curr->isRenderInline()) {
+ } else if (is<RenderInline>(current)) {
// If the child doesn't need line boxes either, then we can recur.
- RenderInline* currInline = toRenderInline(curr);
- if (!currInline->alwaysCreateLineBoxes())
- result.uniteIfNonZero(currInline->culledInlineVisualOverflowBoundingBox());
- else if (!currInline->hasSelfPaintingLayer())
- result.uniteIfNonZero(currInline->linesVisualOverflowBoundingBox());
- } else if (curr->isText()) {
+ auto& renderInline = downcast<RenderInline>(current);
+ if (!renderInline.alwaysCreateLineBoxes())
+ result.uniteIfNonZero(renderInline.culledInlineVisualOverflowBoundingBox());
+ else if (!renderInline.hasSelfPaintingLayer())
+ result.uniteIfNonZero(renderInline.linesVisualOverflowBoundingBox());
+ } else if (is<RenderText>(current)) {
// FIXME; Overflow from text boxes is lost. We will need to cache this information in
// InlineTextBoxes.
- RenderText* currText = toRenderText(curr);
- result.uniteIfNonZero(currText->linesVisualOverflowBoundingBox());
+ auto& renderText = downcast<RenderText>(current);
+ result.uniteIfNonZero(renderText.linesVisualOverflowBoundingBox());
}
}
return result;
@@ -1104,8 +1219,8 @@ LayoutRect RenderInline::linesVisualOverflowBoundingBoxInRegion(const RenderRegi
LayoutRect RenderInline::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
{
- // Only run-ins and first-letter renderers are allowed in here during layout. They mutate the tree triggering repaints.
- ASSERT(!view().layoutStateEnabled() || isRunIn() || style().styleType() == FIRST_LETTER);
+ // Only first-letter renderers are allowed in here during layout. They mutate the tree triggering repaints.
+ ASSERT(!view().layoutStateEnabled() || style().styleType() == FIRST_LETTER || hasSelfPaintingLayer());
if (!firstLineBoxIncludingCulling() && !continuation())
return LayoutRect();
@@ -1115,30 +1230,27 @@ LayoutRect RenderInline::clippedOverflowRectForRepaint(const RenderLayerModelObj
// We need to add in the in-flow position offsets of any inlines (including us) up to our
// containing block.
- RenderBlock* cb = containingBlock();
- for (const RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isRenderInline() && inlineFlow != cb;
+ RenderBlock* containingBlock = this->containingBlock();
+ for (const RenderElement* inlineFlow = this; is<RenderInline>(inlineFlow) && inlineFlow != containingBlock;
inlineFlow = inlineFlow->parent()) {
if (inlineFlow == repaintContainer) {
hitRepaintContainer = true;
break;
}
if (inlineFlow->style().hasInFlowPosition() && inlineFlow->hasLayer())
- repaintRect.move(toRenderInline(inlineFlow)->layer()->offsetForInFlowPosition());
+ repaintRect.move(downcast<RenderInline>(*inlineFlow).layer()->offsetForInFlowPosition());
}
LayoutUnit outlineSize = style().outlineSize();
repaintRect.inflate(outlineSize);
- if (hitRepaintContainer || !cb)
+ if (hitRepaintContainer || !containingBlock)
return repaintRect;
- if (cb->hasColumns())
- cb->adjustRectForColumns(repaintRect);
-
- if (cb->hasOverflowClip())
- cb->applyCachedClipAndScrollOffsetForRepaint(repaintRect);
+ if (containingBlock->hasOverflowClip() && containingBlock->shouldApplyClipAndScrollPositionForRepaint(repaintContainer))
+ containingBlock->applyCachedClipAndScrollPositionForRepaint(repaintRect);
- cb->computeRectForRepaint(repaintContainer, repaintRect);
+ repaintRect = containingBlock->computeRectForRepaint(repaintRect, repaintContainer);
if (outlineSize) {
for (auto& child : childrenOfType<RenderElement>(*this))
@@ -1161,38 +1273,29 @@ LayoutRect RenderInline::rectWithOutlineForRepaint(const RenderLayerModelObject*
return r;
}
-void RenderInline::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+LayoutRect RenderInline::computeRectForRepaint(const LayoutRect& rect, const RenderLayerModelObject* repaintContainer, RepaintContext context) const
{
// LayoutState is only valid for root-relative repainting
+ LayoutRect adjustedRect = rect;
if (view().layoutStateEnabled() && !repaintContainer) {
LayoutState* layoutState = view().layoutState();
if (style().hasInFlowPosition() && layer())
- rect.move(layer()->offsetForInFlowPosition());
- rect.move(layoutState->m_paintOffset);
+ adjustedRect.move(layer()->offsetForInFlowPosition());
+ adjustedRect.move(layoutState->m_paintOffset);
if (layoutState->m_clipped)
- rect.intersect(layoutState->m_clipRect);
- return;
+ adjustedRect.intersect(layoutState->m_clipRect);
+ return adjustedRect;
}
if (repaintContainer == this)
- return;
+ return adjustedRect;
bool containerSkipped;
- RenderElement* o = container(repaintContainer, &containerSkipped);
- if (!o)
- return;
-
- LayoutPoint topLeft = rect.location();
+ RenderElement* container = this->container(repaintContainer, containerSkipped);
+ if (!container)
+ return adjustedRect;
- if (o->isRenderBlockFlow() && !style().hasOutOfFlowPosition()) {
- RenderBlock* cb = toRenderBlock(o);
- if (cb->hasColumns()) {
- LayoutRect repaintRect(topLeft, rect.size());
- cb->adjustRectForColumns(repaintRect);
- topLeft = repaintRect.location();
- rect = repaintRect;
- }
- }
+ LayoutPoint topLeft = adjustedRect.location();
if (style().hasInFlowPosition() && layer()) {
// Apply the in-flow position offset when invalidating a rectangle. The layer
@@ -1204,41 +1307,35 @@ void RenderInline::computeRectForRepaint(const RenderLayerModelObject* repaintCo
// 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.
- rect.setLocation(topLeft);
- if (o->hasOverflowClip()) {
- RenderBox* containerBox = toRenderBox(o);
- containerBox->applyCachedClipAndScrollOffsetForRepaint(rect);
- if (rect.isEmpty())
- return;
+ adjustedRect.setLocation(topLeft);
+ if (container->hasOverflowClip()) {
+ downcast<RenderBox>(*container).applyCachedClipAndScrollPositionForRepaint(adjustedRect);
+ if (adjustedRect.isEmpty())
+ return adjustedRect;
}
if (containerSkipped) {
// If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
- LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
- rect.move(-containerOffset);
- return;
+ LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(*container);
+ adjustedRect.move(-containerOffset);
+ return adjustedRect;
}
-
- o->computeRectForRepaint(repaintContainer, rect, fixed);
+ return container->computeRectForRepaint(adjustedRect, repaintContainer, context);
}
-LayoutSize RenderInline::offsetFromContainer(RenderObject* container, const LayoutPoint& point, bool* offsetDependsOnPoint) const
+LayoutSize RenderInline::offsetFromContainer(RenderElement& container, const LayoutPoint&, bool* offsetDependsOnPoint) const
{
- ASSERT(container == this->container());
+ ASSERT(&container == this->container());
LayoutSize offset;
if (isInFlowPositioned())
offset += offsetForInFlowPosition();
- container->adjustForColumns(offset, point);
-
- if (container->hasOverflowClip())
- offset -= toRenderBox(container)->scrolledContentOffset();
+ if (is<RenderBox>(container))
+ offset -= toLayoutSize(downcast<RenderBox>(container).scrollPosition());
if (offsetDependsOnPoint)
- *offsetDependsOnPoint = container->hasColumns()
- || (container->isBox() && container->style().isFlippedBlocksWritingMode())
- || container->isRenderFlowThread();
+ *offsetDependsOnPoint = (is<RenderBox>(container) && container.style().isFlippedBlocksWritingMode()) || is<RenderFlowThread>(container);
return offset;
}
@@ -1258,24 +1355,24 @@ void RenderInline::mapLocalToContainer(const RenderLayerModelObject* repaintCont
}
bool containerSkipped;
- RenderElement* o = container(repaintContainer, &containerSkipped);
- if (!o)
+ RenderElement* container = this->container(repaintContainer, containerSkipped);
+ if (!container)
return;
- if (mode & ApplyContainerFlip && o->isBox()) {
- if (o->style().isFlippedBlocksWritingMode()) {
- IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint());
- transformState.move(toRenderBox(o)->flipForWritingModeIncludingColumns(centerPoint) - centerPoint);
+ if (mode & ApplyContainerFlip && is<RenderBox>(*container)) {
+ if (container->style().isFlippedBlocksWritingMode()) {
+ LayoutPoint centerPoint(transformState.mappedPoint());
+ transformState.move(downcast<RenderBox>(*container).flipForWritingMode(centerPoint) - centerPoint);
}
mode &= ~ApplyContainerFlip;
}
- LayoutSize containerOffset = offsetFromContainer(o, roundedLayoutPoint(transformState.mappedPoint()));
+ LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(transformState.mappedPoint()));
- bool preserve3D = mode & UseTransforms && (o->style().preserves3D() || style().preserves3D());
- if (mode & UseTransforms && shouldUseTransformFromContainer(o)) {
+ bool preserve3D = mode & UseTransforms && (container->style().preserves3D() || style().preserves3D());
+ if (mode & UseTransforms && shouldUseTransformFromContainer(container)) {
TransformationMatrix t;
- getTransformFromContainer(o, containerOffset, t);
+ getTransformFromContainer(container, containerOffset, t);
transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
} else
transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
@@ -1283,12 +1380,12 @@ void RenderInline::mapLocalToContainer(const RenderLayerModelObject* repaintCont
if (containerSkipped) {
// There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
// to just subtract the delta between the repaintContainer and o.
- LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
+ LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(*container);
transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
return;
}
- o->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
+ container->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
}
const RenderObject* RenderInline::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
@@ -1296,19 +1393,19 @@ const RenderObject* RenderInline::pushMappingToContainer(const RenderLayerModelO
ASSERT(ancestorToStopAt != this);
bool ancestorSkipped;
- RenderElement* container = this->container(ancestorToStopAt, &ancestorSkipped);
+ RenderElement* container = this->container(ancestorToStopAt, ancestorSkipped);
if (!container)
- return 0;
+ return nullptr;
LayoutSize adjustmentForSkippedAncestor;
if (ancestorSkipped) {
// There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
// to just subtract the delta between the ancestor and o.
- adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(container);
+ adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(*container);
}
bool offsetDependsOnPoint = false;
- LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), &offsetDependsOnPoint);
+ LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(), &offsetDependsOnPoint);
bool preserve3D = container->style().preserves3D() || style().preserves3D();
if (shouldUseTransformFromContainer(container)) {
@@ -1331,15 +1428,15 @@ void RenderInline::updateDragState(bool dragOn)
continuation->updateDragState(dragOn);
}
-void RenderInline::childBecameNonInline(RenderObject* child)
+void RenderInline::childBecameNonInline(RenderElement& child)
{
// We have to split the parent flow.
RenderBlock* newBox = containingBlock()->createAnonymousBlock();
RenderBoxModelObject* oldContinuation = continuation();
setContinuation(newBox);
- RenderObject* beforeChild = child->nextSibling();
- removeChildInternal(*child, NotifyChildren);
- splitFlow(beforeChild, newBox, child, oldContinuation);
+ RenderObject* beforeChild = child.nextSibling();
+ removeChildInternal(child, NotifyChildren);
+ splitFlow(beforeChild, newBox, &child, oldContinuation);
}
void RenderInline::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
@@ -1375,26 +1472,26 @@ void RenderInline::dirtyLineBoxes(bool fullLayout)
if (!alwaysCreateLineBoxes()) {
// We have to grovel into our children in order to dirty the appropriate lines.
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (curr->isFloatingOrOutOfFlowPositioned())
+ for (auto& current : childrenOfType<RenderObject>(*this)) {
+ if (current.isFloatingOrOutOfFlowPositioned())
continue;
- if (curr->isBox() && !curr->needsLayout()) {
- RenderBox* currBox = toRenderBox(curr);
- if (currBox->inlineBoxWrapper())
- currBox->inlineBoxWrapper()->root().markDirty();
- } else if (!curr->selfNeedsLayout()) {
- if (curr->isRenderInline()) {
- RenderInline* currInline = toRenderInline(curr);
- for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox())
+ if (is<RenderBox>(current) && !current.needsLayout()) {
+ auto& renderBox = downcast<RenderBox>(current);
+ if (renderBox.inlineBoxWrapper())
+ renderBox.inlineBoxWrapper()->root().markDirty();
+ } else if (!current.selfNeedsLayout()) {
+ if (is<RenderInline>(current)) {
+ auto& renderInline = downcast<RenderInline>(current);
+ for (InlineFlowBox* childLine = renderInline.firstLineBox(); childLine; childLine = childLine->nextLineBox())
childLine->root().markDirty();
- } else if (curr->isText()) {
- RenderText* currText = toRenderText(curr);
- for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox())
+ } else if (is<RenderText>(current)) {
+ auto& renderText = downcast<RenderText>(current);
+ for (InlineTextBox* childText = renderText.firstTextBox(); childText; childText = childText->nextTextBox())
childText->root().markDirty();
- } else if (curr->isLineBreak()) {
- RenderLineBreak* currBR = toRenderLineBreak(curr);
- if (currBR->inlineBoxWrapper())
- currBR->inlineBoxWrapper()->root().markDirty();
+ } else if (is<RenderLineBreak>(current)) {
+ auto& renderBR = downcast<RenderLineBreak>(current);
+ if (renderBR.inlineBoxWrapper())
+ renderBR.inlineBoxWrapper()->root().markDirty();
}
}
}
@@ -1417,19 +1514,19 @@ InlineFlowBox* RenderInline::createAndAppendInlineFlowBox()
setAlwaysCreateLineBoxes();
auto newFlowBox = createInlineFlowBox();
auto flowBox = newFlowBox.get();
- m_lineBoxes.appendLineBox(std::move(newFlowBox));
+ m_lineBoxes.appendLineBox(WTFMove(newFlowBox));
return flowBox;
}
LayoutUnit RenderInline::lineHeight(bool firstLine, LineDirectionMode /*direction*/, LinePositionMode /*linePositionMode*/) const
{
- if (firstLine && document().styleSheetCollection().usesFirstLineRules()) {
+ if (firstLine && view().usesFirstLineRules()) {
const RenderStyle& firstLineStyle = this->firstLineStyle();
if (&firstLineStyle != &style())
- return firstLineStyle.computedLineHeight(&view());
+ return firstLineStyle.computedLineHeight();
}
- return style().computedLineHeight(&view());
+ return style().computedLineHeight();
}
int RenderInline::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
@@ -1455,7 +1552,7 @@ LayoutSize RenderInline::offsetForInFlowPositionedInline(const RenderBox* child)
LayoutUnit inlinePosition;
LayoutUnit blockPosition;
if (firstLineBox()) {
- inlinePosition = roundedLayoutUnit(firstLineBox()->logicalLeft());
+ inlinePosition = LayoutUnit::fromFloatRound(firstLineBox()->logicalLeft());
blockPosition = firstLineBox()->logicalTop();
} else {
inlinePosition = layer()->staticInlinePosition();
@@ -1488,28 +1585,28 @@ void RenderInline::imageChanged(WrappedImagePtr, const IntRect*)
repaint();
}
-void RenderInline::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
+void RenderInline::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
{
AbsoluteRectsGeneratorContext context(rects, additionalOffset);
generateLineBoxRects(context);
for (auto& child : childrenOfType<RenderElement>(*this)) {
- if (child.isListMarker())
+ if (is<RenderListMarker>(child))
continue;
FloatPoint pos(additionalOffset);
// FIXME: This doesn't work correctly with transforms.
if (child.hasLayer())
pos = child.localToContainerPoint(FloatPoint(), paintContainer);
- else if (child.isBox())
- pos.move(toRenderBox(child).locationOffset());
+ else if (is<RenderBox>(child))
+ pos.move(downcast<RenderBox>(child).locationOffset());
child.addFocusRingRects(rects, flooredIntPoint(pos), paintContainer);
}
if (RenderBoxModelObject* continuation = this->continuation()) {
if (continuation->isInline())
- continuation->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + continuation->containingBlock()->location() - containingBlock()->location()), paintContainer);
+ continuation->addFocusRingRects(rects, flooredLayoutPoint(LayoutPoint(additionalOffset + continuation->containingBlock()->location() - containingBlock()->location())), paintContainer);
else
- continuation->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + toRenderBox(continuation)->location() - containingBlock()->location()), paintContainer);
+ continuation->addFocusRingRects(rects, flooredLayoutPoint(LayoutPoint(additionalOffset + downcast<RenderBox>(*continuation).location() - containingBlock()->location())), paintContainer);
}
}
@@ -1517,24 +1614,26 @@ void RenderInline::paintOutline(PaintInfo& paintInfo, const LayoutPoint& paintOf
{
if (!hasOutline())
return;
-
- RenderStyle& styleToUse = style();
- if (styleToUse.outlineStyleIsAuto() || hasOutlineAnnotation()) {
- if (!theme().supportsFocusRing(&styleToUse)) {
- // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
- paintFocusRing(paintInfo, paintOffset, &styleToUse);
- }
+
+ auto& styleToUse = style();
+ // Only paint the focus ring by hand if the theme isn't able to draw it.
+ if (styleToUse.outlineStyleIsAuto() && !theme().supportsFocusRing(styleToUse)) {
+ Vector<LayoutRect> focusRingRects;
+ addFocusRingRects(focusRingRects, paintOffset, paintInfo.paintContainer);
+ paintFocusRing(paintInfo, styleToUse, focusRingRects);
}
- GraphicsContext* graphicsContext = paintInfo.context;
- if (graphicsContext->paintingDisabled())
+ if (hasOutlineAnnotation() && !styleToUse.outlineStyleIsAuto() && !theme().supportsFocusRing(styleToUse))
+ addPDFURLRect(paintInfo, paintOffset);
+
+ GraphicsContext& graphicsContext = paintInfo.context();
+ if (graphicsContext.paintingDisabled())
return;
- if (styleToUse.outlineStyleIsAuto() || styleToUse.outlineStyle() == BNONE)
+ if (styleToUse.outlineStyleIsAuto() || !styleToUse.hasOutline())
return;
Vector<LayoutRect> rects;
-
rects.append(LayoutRect());
for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
const RootInlineBox& rootBox = curr->root();
@@ -1545,128 +1644,156 @@ void RenderInline::paintOutline(PaintInfo& paintInfo, const LayoutPoint& paintOf
rects.append(LayoutRect());
Color outlineColor = styleToUse.visitedDependentColor(CSSPropertyOutlineColor);
- bool useTransparencyLayer = outlineColor.hasAlpha();
+ bool useTransparencyLayer = !outlineColor.isOpaque();
if (useTransparencyLayer) {
- graphicsContext->beginTransparencyLayer(static_cast<float>(outlineColor.alpha()) / 255);
- outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue());
+ graphicsContext.beginTransparencyLayer(outlineColor.alphaAsFloat());
+ outlineColor = outlineColor.opaqueColor();
}
for (unsigned i = 1; i < rects.size() - 1; i++)
paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor);
if (useTransparencyLayer)
- graphicsContext->endTransparencyLayer();
+ graphicsContext.endTransparencyLayer();
}
-void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset,
- const LayoutRect& lastline, const LayoutRect& thisline, const LayoutRect& nextline,
- const Color outlineColor)
+void RenderInline::paintOutlineForLine(GraphicsContext& graphicsContext, const LayoutPoint& paintOffset,
+ const LayoutRect& previousLine, const LayoutRect& thisLine, const LayoutRect& nextLine, const Color& outlineColor)
{
- const RenderStyle& styleToUse = style();
- int outlineWidth = styleToUse.outlineWidth();
- EBorderStyle outlineStyle = styleToUse.outlineStyle();
+ const auto& styleToUse = style();
+ float outlineOffset = styleToUse.outlineOffset();
+ LayoutRect outlineBoxRect = thisLine;
+ outlineBoxRect.inflate(outlineOffset);
+ outlineBoxRect.moveBy(paintOffset);
+ if (outlineBoxRect.isEmpty())
+ return;
+ float outlineWidth = styleToUse.outlineWidth();
+ EBorderStyle outlineStyle = styleToUse.outlineStyle();
bool antialias = shouldAntialiasLines(graphicsContext);
- int offset = style().outlineOffset();
-
- LayoutRect box(LayoutPoint(paintOffset.x() + thisline.x() - offset, paintOffset.y() + thisline.y() - offset),
- LayoutSize(thisline.width() + offset, thisline.height() + offset));
-
- IntRect pixelSnappedBox = pixelSnappedIntRect(box);
- if (pixelSnappedBox.isEmpty())
- return;
- IntRect pixelSnappedLastLine = pixelSnappedIntRect(paintOffset.x() + lastline.x(), 0, lastline.width(), 0);
- IntRect pixelSnappedNextLine = pixelSnappedIntRect(paintOffset.x() + nextline.x(), 0, nextline.width(), 0);
+ auto adjustedPreviousLine = previousLine;
+ adjustedPreviousLine.moveBy(paintOffset);
+ auto adjustedNextLine = nextLine;
+ adjustedNextLine.moveBy(paintOffset);
+ float adjacentWidth1 = 0;
+ float adjacentWidth2 = 0;
// left edge
- drawLineForBoxSide(graphicsContext,
- pixelSnappedBox.x() - outlineWidth,
- pixelSnappedBox.y() - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : 0),
- pixelSnappedBox.x(),
- pixelSnappedBox.maxY() + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : 0),
- BSLeft,
- outlineColor, outlineStyle,
- (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth),
- (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth),
- antialias);
+ auto topLeft = outlineBoxRect.minXMinYCorner();
+ if (previousLine.isEmpty() || thisLine.x() < previousLine.x() || (previousLine.maxX()) <= thisLine.x()) {
+ topLeft.move(-outlineWidth, -outlineWidth);
+ adjacentWidth1 = outlineWidth;
+ } else {
+ topLeft.move(-outlineWidth, 2 * outlineOffset);
+ adjacentWidth1 = -outlineWidth;
+ }
+ auto bottomRight = outlineBoxRect.minXMaxYCorner();
+ if (nextLine.isEmpty() || thisLine.x() <= nextLine.x() || (nextLine.maxX()) <= thisLine.x()) {
+ bottomRight.move(0, outlineWidth);
+ adjacentWidth2 = outlineWidth;
+ } else {
+ bottomRight.move(0, -2 * outlineOffset);
+ adjacentWidth2 = -outlineWidth;
+ }
+ drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSLeft, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
// right edge
- drawLineForBoxSide(graphicsContext,
- pixelSnappedBox.maxX(),
- pixelSnappedBox.y() - (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : 0),
- pixelSnappedBox.maxX() + outlineWidth,
- pixelSnappedBox.maxY() + (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : 0),
- BSRight,
- outlineColor, outlineStyle,
- (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : -outlineWidth),
- (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : -outlineWidth),
- antialias);
+ topLeft = outlineBoxRect.maxXMinYCorner();
+ if (previousLine.isEmpty() || previousLine.maxX() < thisLine.maxX() || thisLine.maxX() <= previousLine.x()) {
+ topLeft.move(0, -outlineWidth);
+ adjacentWidth1 = outlineWidth;
+ } else {
+ topLeft.move(0, 2 * outlineOffset);
+ adjacentWidth1 = -outlineWidth;
+ }
+ bottomRight = outlineBoxRect.maxXMaxYCorner();
+ if (nextLine.isEmpty() || nextLine.maxX() <= thisLine.maxX() || thisLine.maxX() <= nextLine.x()) {
+ bottomRight.move(outlineWidth, outlineWidth);
+ adjacentWidth2 = outlineWidth;
+ } else {
+ bottomRight.move(outlineWidth, -2 * outlineOffset);
+ adjacentWidth2 = -outlineWidth;
+ }
+ drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSRight, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
+
// upper edge
- if (thisline.x() < lastline.x())
- drawLineForBoxSide(graphicsContext,
- pixelSnappedBox.x() - outlineWidth,
- pixelSnappedBox.y() - outlineWidth,
- std::min(pixelSnappedBox.maxX() + outlineWidth, (lastline.isEmpty() ? 1000000 : pixelSnappedLastLine.x())),
- pixelSnappedBox.y(),
- BSTop, outlineColor, outlineStyle,
- outlineWidth,
- (!lastline.isEmpty() && paintOffset.x() + lastline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth,
- antialias);
+ if (thisLine.x() < previousLine.x()) {
+ topLeft = outlineBoxRect.minXMinYCorner();
+ topLeft.move(-outlineWidth, -outlineWidth);
+ adjacentWidth1 = outlineWidth;
+ bottomRight = outlineBoxRect.maxXMinYCorner();
+ bottomRight.move(outlineWidth, 0);
+ if (!previousLine.isEmpty() && adjustedPreviousLine.x() < bottomRight.x()) {
+ bottomRight.setX(adjustedPreviousLine.x() - outlineOffset);
+ adjacentWidth2 = -outlineWidth;
+ } else
+ adjacentWidth2 = outlineWidth;
+ drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSTop, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
+ }
- if (lastline.maxX() < thisline.maxX())
- drawLineForBoxSide(graphicsContext,
- std::max(lastline.isEmpty() ? -1000000 : pixelSnappedLastLine.maxX(), pixelSnappedBox.x() - outlineWidth),
- pixelSnappedBox.y() - outlineWidth,
- pixelSnappedBox.maxX() + outlineWidth,
- pixelSnappedBox.y(),
- BSTop, outlineColor, outlineStyle,
- (!lastline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + lastline.maxX()) ? -outlineWidth : outlineWidth,
- outlineWidth, antialias);
-
- if (thisline.x() == thisline.maxX())
- drawLineForBoxSide(graphicsContext,
- pixelSnappedBox.x() - outlineWidth,
- pixelSnappedBox.y() - outlineWidth,
- pixelSnappedBox.maxX() + outlineWidth,
- pixelSnappedBox.y(),
- BSTop, outlineColor, outlineStyle,
- outlineWidth,
- outlineWidth,
- antialias);
+ if (previousLine.maxX() < thisLine.maxX()) {
+ topLeft = outlineBoxRect.minXMinYCorner();
+ topLeft.move(-outlineWidth, -outlineWidth);
+ if (!previousLine.isEmpty() && adjustedPreviousLine.maxX() > topLeft.x()) {
+ topLeft.setX(adjustedPreviousLine.maxX() + outlineOffset);
+ adjacentWidth1 = -outlineWidth;
+ } else
+ adjacentWidth1 = outlineWidth;
+ bottomRight = outlineBoxRect.maxXMinYCorner();
+ bottomRight.move(outlineWidth, 0);
+ adjacentWidth2 = outlineWidth;
+ drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSTop, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
+ }
+
+ if (thisLine.x() == thisLine.maxX()) {
+ topLeft = outlineBoxRect.minXMinYCorner();
+ topLeft.move(-outlineWidth, -outlineWidth);
+ adjacentWidth1 = outlineWidth;
+ bottomRight = outlineBoxRect.maxXMinYCorner();
+ bottomRight.move(outlineWidth, 0);
+ adjacentWidth2 = outlineWidth;
+ drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSTop, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
+ }
// lower edge
- if (thisline.x() < nextline.x())
- drawLineForBoxSide(graphicsContext,
- pixelSnappedBox.x() - outlineWidth,
- pixelSnappedBox.maxY(),
- std::min(pixelSnappedBox.maxX() + outlineWidth, !nextline.isEmpty() ? pixelSnappedNextLine.x() + 1 : 1000000),
- pixelSnappedBox.maxY() + outlineWidth,
- BSBottom, outlineColor, outlineStyle,
- outlineWidth,
- (!nextline.isEmpty() && paintOffset.x() + nextline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth,
- antialias);
+ if (thisLine.x() < nextLine.x()) {
+ topLeft = outlineBoxRect.minXMaxYCorner();
+ topLeft.move(-outlineWidth, 0);
+ adjacentWidth1 = outlineWidth;
+ bottomRight = outlineBoxRect.maxXMaxYCorner();
+ bottomRight.move(outlineWidth, outlineWidth);
+ if (!nextLine.isEmpty() && (adjustedNextLine.x() < bottomRight.x())) {
+ bottomRight.setX(adjustedNextLine.x() - outlineOffset);
+ adjacentWidth2 = -outlineWidth;
+ } else
+ adjacentWidth2 = outlineWidth;
+ drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSBottom, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
+ }
- if (nextline.maxX() < thisline.maxX())
- drawLineForBoxSide(graphicsContext,
- std::max(!nextline.isEmpty() ? pixelSnappedNextLine.maxX() : -1000000, pixelSnappedBox.x() - outlineWidth),
- pixelSnappedBox.maxY(),
- pixelSnappedBox.maxX() + outlineWidth,
- pixelSnappedBox.maxY() + outlineWidth,
- BSBottom, outlineColor, outlineStyle,
- (!nextline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + nextline.maxX()) ? -outlineWidth : outlineWidth,
- outlineWidth, antialias);
-
- if (thisline.x() == thisline.maxX())
- drawLineForBoxSide(graphicsContext,
- pixelSnappedBox.x() - outlineWidth,
- pixelSnappedBox.maxY(),
- pixelSnappedBox.maxX() + outlineWidth,
- pixelSnappedBox.maxY() + outlineWidth,
- BSBottom, outlineColor, outlineStyle,
- outlineWidth,
- outlineWidth,
- antialias);
+ if (nextLine.maxX() < thisLine.maxX()) {
+ topLeft = outlineBoxRect.minXMaxYCorner();
+ topLeft.move(-outlineWidth, 0);
+ if (!nextLine.isEmpty() && adjustedNextLine.maxX() > topLeft.x()) {
+ topLeft.setX(adjustedNextLine.maxX() + outlineOffset);
+ adjacentWidth1 = -outlineWidth;
+ } else
+ adjacentWidth1 = outlineWidth;
+ bottomRight = outlineBoxRect.maxXMaxYCorner();
+ bottomRight.move(outlineWidth, outlineWidth);
+ adjacentWidth2 = outlineWidth;
+ drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSBottom, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
+ }
+
+ if (thisLine.x() == thisLine.maxX()) {
+ topLeft = outlineBoxRect.minXMaxYCorner();
+ topLeft.move(-outlineWidth, 0);
+ adjacentWidth1 = outlineWidth;
+ bottomRight = outlineBoxRect.maxXMaxYCorner();
+ bottomRight.move(outlineWidth, outlineWidth);
+ adjacentWidth2 = outlineWidth;
+ drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSBottom, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
+ }
}
#if ENABLE(DASHBOARD_SUPPORT)
@@ -1697,8 +1824,7 @@ void RenderInline::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
if (!container)
container = this;
- region.clip = region.bounds;
- container->computeAbsoluteRepaintRect(region.clip);
+ region.clip = container->computeAbsoluteRepaintRect(region.bounds);
if (region.clip.height() < 0) {
region.clip.setHeight(0);
region.clip.setWidth(0);