RenderFlowThread's containing block cache should be invalidated before calling styleD...
[WebKit-https.git] / Source / WebCore / rendering / RenderInline.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "config.h"
24 #include "RenderInline.h"
25
26 #include "Chrome.h"
27 #include "FloatQuad.h"
28 #include "FrameSelection.h"
29 #include "GraphicsContext.h"
30 #include "HitTestResult.h"
31 #include "InlineElementBox.h"
32 #include "InlineTextBox.h"
33 #include "Page.h"
34 #include "RenderBlock.h"
35 #include "RenderChildIterator.h"
36 #include "RenderFullScreen.h"
37 #include "RenderGeometryMap.h"
38 #include "RenderIterator.h"
39 #include "RenderLayer.h"
40 #include "RenderLineBreak.h"
41 #include "RenderListMarker.h"
42 #include "RenderNamedFlowThread.h"
43 #include "RenderTable.h"
44 #include "RenderTheme.h"
45 #include "RenderView.h"
46 #include "Settings.h"
47 #include "StyleInheritedData.h"
48 #include "TransformState.h"
49 #include "VisiblePosition.h"
50
51 #if ENABLE(DASHBOARD_SUPPORT)
52 #include "Frame.h"
53 #endif
54
55 namespace WebCore {
56
57 RenderInline::RenderInline(Element& element, RenderStyle&& style)
58     : RenderBoxModelObject(element, WTFMove(style), RenderInlineFlag)
59 {
60     setChildrenInline(true);
61 }
62
63 RenderInline::RenderInline(Document& document, RenderStyle&& style)
64     : RenderBoxModelObject(document, WTFMove(style), RenderInlineFlag)
65 {
66     setChildrenInline(true);
67 }
68
69 void RenderInline::willBeDestroyed()
70 {
71 #if !ASSERT_DISABLED
72     // Make sure we do not retain "this" in the continuation outline table map of our containing blocks.
73     if (parent() && style().visibility() == VISIBLE && hasOutline()) {
74         bool containingBlockPaintsContinuationOutline = continuation() || isInlineElementContinuation();
75         if (containingBlockPaintsContinuationOutline) {
76             if (RenderBlock* cb = containingBlock()) {
77                 if (RenderBlock* cbCb = cb->containingBlock())
78                     ASSERT(!cbCb->paintsContinuationOutline(this));
79             }
80         }
81     }
82 #endif
83
84     // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
85     // properly dirty line boxes that they are removed from.  Effects that do :before/:after only on hover could crash otherwise.
86     destroyLeftoverChildren();
87     
88     if (!documentBeingDestroyed()) {
89         if (firstLineBox()) {
90             // We can't wait for RenderBoxModelObject::destroy to clear the selection,
91             // because by then we will have nuked the line boxes.
92             if (isSelectionBorder())
93                 frame().selection().setNeedsSelectionUpdate();
94
95             // If line boxes are contained inside a root, that means we're an inline.
96             // In that case, we need to remove all the line boxes so that the parent
97             // lines aren't pointing to deleted children. If the first line box does
98             // not have a parent that means they are either already disconnected or
99             // root lines that can just be destroyed without disconnecting.
100             if (firstLineBox()->parent()) {
101                 for (auto* box = firstLineBox(); box; box = box->nextLineBox())
102                     box->removeFromParent();
103             }
104         } else if (parent())
105             parent()->dirtyLinesFromChangedChild(*this);
106     }
107
108     m_lineBoxes.deleteLineBoxes();
109
110     RenderBoxModelObject::willBeDestroyed();
111 }
112
113 RenderInline* RenderInline::inlineElementContinuation() const
114 {
115     RenderBoxModelObject* continuation = this->continuation();
116     if (!continuation)
117         return nullptr;
118
119     if (is<RenderInline>(*continuation))
120         return downcast<RenderInline>(continuation);
121
122     return is<RenderBlock>(*continuation) ? downcast<RenderBlock>(*continuation).inlineElementContinuation() : nullptr;
123 }
124
125 void RenderInline::updateFromStyle()
126 {
127     RenderBoxModelObject::updateFromStyle();
128
129     // FIXME: Support transforms and reflections on inline flows someday.
130     setHasTransformRelatedProperty(false);
131     setHasReflection(false);    
132 }
133
134 static RenderElement* inFlowPositionedInlineAncestor(RenderElement* p)
135 {
136     while (p && p->isRenderInline()) {
137         if (p->isInFlowPositioned())
138             return p;
139         p = p->parent();
140     }
141     return nullptr;
142 }
143
144 static void updateStyleOfAnonymousBlockContinuations(const RenderBlock& block, const RenderStyle* newStyle, const RenderStyle* oldStyle)
145 {
146     // If any descendant blocks exist then they will be in the next anonymous block and its siblings.
147     for (RenderBox* box = block.nextSiblingBox(); box && box->isAnonymousBlock(); box = box->nextSiblingBox()) {
148         if (box->style().position() == newStyle->position())
149             continue;
150         
151         if (!is<RenderBlock>(*box))
152             continue;
153
154         RenderBlock& block = downcast<RenderBlock>(*box);
155         if (!block.isAnonymousBlockContinuation())
156             continue;
157         
158         // If we are no longer in-flow positioned but our descendant block(s) still have an in-flow positioned ancestor then
159         // their containing anonymous block should keep its in-flow positioning. 
160         RenderInline* continuation = block.inlineElementContinuation();
161         if (oldStyle->hasInFlowPosition() && inFlowPositionedInlineAncestor(continuation))
162             continue;
163         auto blockStyle = RenderStyle::createAnonymousStyleWithDisplay(block.style(), BLOCK);
164         blockStyle.setPosition(newStyle->position());
165         block.setStyle(WTFMove(blockStyle));
166     }
167 }
168
169 void RenderInline::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
170 {
171     RenderBoxModelObject::styleWillChange(diff, newStyle);
172     // RenderInlines forward their absolute positioned descendants to their (non-anonymous) containing block.
173     // Check if this non-anonymous containing block can hold the absolute positioned elements when the inline is no longer positioned.
174     if (canContainAbsolutelyPositionedObjects() && newStyle.position() == StaticPosition) {
175         auto* container = containingBlockForAbsolutePosition();
176         if (container && !container->canContainAbsolutelyPositionedObjects())
177             container->removePositionedObjects(nullptr, NewContainingBlock);
178     }
179 }
180
181 void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
182 {
183     RenderBoxModelObject::styleDidChange(diff, oldStyle);
184
185     // Ensure that all of the split inlines pick up the new style. We
186     // only do this if we're an inline, since we don't want to propagate
187     // a block's style to the other inlines.
188     // e.g., <font>foo <h4>goo</h4> moo</font>.  The <font> inlines before
189     // and after the block share the same style, but the block doesn't
190     // need to pass its style on to anyone else.
191     auto& newStyle = style();
192     RenderInline* continuation = inlineElementContinuation();
193     if (continuation) {
194         for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation()) {
195             RenderBoxModelObject* nextCont = currCont->continuation();
196             currCont->setContinuation(nullptr);
197             currCont->setStyle(RenderStyle::clone(newStyle));
198             currCont->setContinuation(nextCont);
199         }
200         // 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,
201         // then any descendant blocks will need to change their in-flow positioning accordingly.
202         // Do this by updating the position of the descendant blocks' containing anonymous blocks - there may be more than one.
203         if (containingBlock()->isAnonymousBlock() && oldStyle && newStyle.position() != oldStyle->position() && (newStyle.hasInFlowPosition() || oldStyle->hasInFlowPosition()))
204             updateStyleOfAnonymousBlockContinuations(*containingBlock(), &newStyle, oldStyle);
205     }
206
207     if (!alwaysCreateLineBoxes()) {
208         bool alwaysCreateLineBoxes = hasSelfPaintingLayer() || hasVisibleBoxDecorations() || newStyle.hasBorder() || newStyle.hasPadding() || newStyle.hasMargin() || hasOutline();
209         if (oldStyle && alwaysCreateLineBoxes) {
210             dirtyLineBoxes(false);
211             setNeedsLayout();
212         }
213         setRenderInlineAlwaysCreatesLineBoxes(alwaysCreateLineBoxes);
214     }
215 }
216
217 void RenderInline::updateAlwaysCreateLineBoxes(bool fullLayout)
218 {
219     // Once we have been tainted once, just assume it will happen again. This way effects like hover highlighting that change the
220     // background color will only cause a layout on the first rollover.
221     if (alwaysCreateLineBoxes())
222         return;
223
224     auto* parentStyle = &parent()->style();
225     RenderInline* parentRenderInline = is<RenderInline>(*parent()) ? downcast<RenderInline>(parent()) : nullptr;
226     bool checkFonts = document().inNoQuirksMode();
227     RenderFlowThread* flowThread = flowThreadContainingBlock();
228     bool alwaysCreateLineBoxes = (parentRenderInline && parentRenderInline->alwaysCreateLineBoxes())
229         || (parentRenderInline && parentStyle->verticalAlign() != BASELINE)
230         || style().verticalAlign() != BASELINE
231         || style().textEmphasisMark() != TextEmphasisMarkNone
232         || (checkFonts && (!parentStyle->fontCascade().fontMetrics().hasIdenticalAscentDescentAndLineGap(style().fontCascade().fontMetrics())
233         || parentStyle->lineHeight() != style().lineHeight()))
234         || (flowThread && flowThread->isRenderNamedFlowThread()); // FIXME: Enable the optimization once we make overflow computation for culled inlines in regions.
235
236     if (!alwaysCreateLineBoxes && checkFonts && view().usesFirstLineRules()) {
237         // Have to check the first line style as well.
238         parentStyle = &parent()->firstLineStyle();
239         auto& childStyle = firstLineStyle();
240         alwaysCreateLineBoxes = !parentStyle->fontCascade().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle.fontCascade().fontMetrics())
241             || childStyle.verticalAlign() != BASELINE
242             || parentStyle->lineHeight() != childStyle.lineHeight();
243     }
244
245     if (alwaysCreateLineBoxes) {
246         if (!fullLayout)
247             dirtyLineBoxes(false);
248         setAlwaysCreateLineBoxes();
249     }
250 }
251
252 LayoutRect RenderInline::localCaretRect(InlineBox* inlineBox, unsigned, LayoutUnit* extraWidthToEndOfLine)
253 {
254     if (firstChild()) {
255         // This condition is possible if the RenderInline is at an editing boundary,
256         // i.e. the VisiblePosition is:
257         //   <RenderInline editingBoundary=true>|<RenderText> </RenderText></RenderInline>
258         // FIXME: need to figure out how to make this return a valid rect, note that
259         // there are no line boxes created in the above case.
260         return LayoutRect();
261     }
262
263     ASSERT_UNUSED(inlineBox, !inlineBox);
264
265     if (extraWidthToEndOfLine)
266         *extraWidthToEndOfLine = 0;
267
268     LayoutRect caretRect = localCaretRectForEmptyElement(horizontalBorderAndPaddingExtent(), 0);
269
270     if (InlineBox* firstBox = firstLineBox())
271         caretRect.moveBy(LayoutPoint(firstBox->topLeft()));
272
273     return caretRect;
274 }
275
276 void RenderInline::addChild(RenderObject* newChild, RenderObject* beforeChild)
277 {
278     if (continuation())
279         return addChildToContinuation(newChild, beforeChild);
280     return addChildIgnoringContinuation(newChild, beforeChild);
281 }
282
283 static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
284 {
285     if (is<RenderInline>(*renderer) && !renderer->isReplaced())
286         return downcast<RenderInline>(*renderer).continuation();
287     return downcast<RenderBlock>(*renderer).inlineElementContinuation();
288 }
289
290 RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild)
291 {
292     if (beforeChild && beforeChild->parent() == this)
293         return this;
294
295     RenderBoxModelObject* curr = nextContinuation(this);
296     RenderBoxModelObject* nextToLast = this;
297     RenderBoxModelObject* last = this;
298     while (curr) {
299         if (beforeChild && beforeChild->parent() == curr) {
300             if (curr->firstChild() == beforeChild)
301                 return last;
302             return curr;
303         }
304
305         nextToLast = last;
306         last = curr;
307         curr = nextContinuation(curr);
308     }
309
310     if (!beforeChild && !last->firstChild())
311         return nextToLast;
312     return last;
313 }
314
315 static bool newChildIsInline(const RenderObject& newChild, const RenderInline& parent)
316 {
317     // inline parent generates inline-table.
318     return newChild.isInline() | (parent.childRequiresTable(newChild) && parent.style().display() == INLINE);
319 }
320
321 void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
322 {
323     // Make sure we don't append things after :after-generated content if we have it.
324     if (!beforeChild && isAfterContent(lastChild()))
325         beforeChild = lastChild();
326     
327     bool useNewBlockInsideInlineModel = document().settings()->newBlockInsideInlineModelEnabled();
328     bool childInline = newChildIsInline(*newChild, *this);
329     // This code is for the old block-inside-inline model that uses continuations.
330     if (!useNewBlockInsideInlineModel && !childInline && !newChild->isFloatingOrOutOfFlowPositioned()) {
331         // We are placing a block inside an inline. We have to perform a split of this
332         // inline into continuations.  This involves creating an anonymous block box to hold
333         // |newChild|.  We then make that block box a continuation of this inline.  We take all of
334         // the children after |beforeChild| and put them in a clone of this object.
335         auto newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
336         
337         // If inside an inline affected by in-flow positioning the block needs to be affected by it too.
338         // Giving the block a layer like this allows it to collect the x/y offsets from inline parents later.
339         if (auto positionedAncestor = inFlowPositionedInlineAncestor(this))
340             newStyle.setPosition(positionedAncestor->style().position());
341
342         RenderBlock* newBox = new RenderBlockFlow(document(), WTFMove(newStyle));
343         newBox->initializeStyle();
344         RenderBoxModelObject* oldContinuation = continuation();
345         setContinuation(newBox);
346
347         splitFlow(beforeChild, newBox, newChild, oldContinuation);
348         return;
349     }
350     
351     if (!useNewBlockInsideInlineModel) {
352         RenderBoxModelObject::addChild(newChild, beforeChild);
353         newChild->setNeedsLayoutAndPrefWidthsRecalc();
354         return;
355     }
356
357     // This code is for the new block-inside-inline model that uses anonymous inline blocks.
358     // If the requested beforeChild is not one of our children, then this is most likely because
359     // there is an anonymous inline-block box within this object that contains the beforeChild.
360     // Insert the child into the anonymous inline-block box instead of here.
361     // A second possibility is that the beforeChild is an anonymous block inside the anonymous inline block.
362     // This can happen if inlines are inserted in between two of the anonymous inline block's block-level
363     // children after it has been created.
364     if (beforeChild && beforeChild->parent() != this) {
365         ASSERT(beforeChild->parent());
366         ASSERT(beforeChild->parent()->isAnonymousInlineBlock() || beforeChild->parent()->isAnonymousBlock());
367         if (beforeChild->parent()->isAnonymousInlineBlock()) {
368             if (!childInline || (childInline && beforeChild->parent()->firstChild() != beforeChild))
369                 beforeChild->parent()->addChild(newChild, beforeChild);
370             else
371                 addChild(newChild, beforeChild->parent());
372         } else if (beforeChild->parent()->isAnonymousBlock()) {
373             ASSERT(!beforeChild->parent()->parent() || beforeChild->parent()->parent()->isAnonymousInlineBlock());
374             ASSERT(childInline);
375             if (childInline || (!childInline && beforeChild->parent()->firstChild() != beforeChild))
376                 beforeChild->parent()->addChild(newChild, beforeChild);
377             else
378                 addChild(newChild, beforeChild->parent());
379         }
380         return;
381     }
382
383     if (!childInline) {
384         // We are placing a block inside an inline. We have to place the block inside an anonymous inline-block.
385         // This inline-block can house a sequence of contiguous block-level children, and they will all sit on the
386         // same "line" together. We try to reuse an existing inline-block if possible.
387         if (beforeChild) {
388             if (beforeChild->previousSibling() && beforeChild->previousSibling()->isAnonymousInlineBlock()) {
389                 downcast<RenderBlockFlow>(beforeChild->previousSibling())->addChild(newChild);
390                 return;
391             }
392         } else {
393             if (lastChild() && lastChild()->isAnonymousInlineBlock()) {
394                 downcast<RenderBlockFlow>(lastChild())->addChild(newChild);
395                 return;
396             }
397         }
398  
399         if (!newChild->isFloatingOrOutOfFlowPositioned()) {
400             // There was no suitable existing anonymous inline-block. Create a new one.
401             RenderBlockFlow* anonymousInlineBlock = new RenderBlockFlow(document(), RenderStyle::createAnonymousStyleWithDisplay(style(), INLINE_BLOCK));
402             anonymousInlineBlock->initializeStyle();
403     
404             RenderBoxModelObject::addChild(anonymousInlineBlock, beforeChild);
405             anonymousInlineBlock->addChild(newChild);
406             return;
407         }
408     }
409
410     RenderBoxModelObject::addChild(newChild, beforeChild);
411
412     newChild->setNeedsLayoutAndPrefWidthsRecalc();
413 }
414
415 RenderPtr<RenderInline> RenderInline::clone() const
416 {
417     RenderPtr<RenderInline> cloneInline = createRenderer<RenderInline>(*element(), RenderStyle::clone(style()));
418     cloneInline->initializeStyle();
419     cloneInline->setFlowThreadState(flowThreadState());
420     cloneInline->setHasOutlineAutoAncestor(hasOutlineAutoAncestor());
421     return cloneInline;
422 }
423
424 void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
425                                 RenderBlock* middleBlock,
426                                 RenderObject* beforeChild, RenderBoxModelObject* oldCont)
427 {
428     // Create a clone of this inline.
429     RenderPtr<RenderInline> cloneInline = clone();
430 #if ENABLE(FULLSCREEN_API)
431     // If we're splitting the inline containing the fullscreened element,
432     // |beforeChild| may be the renderer for the fullscreened element. However,
433     // that renderer is wrapped in a RenderFullScreen, so |this| is not its
434     // parent. Since the splitting logic expects |this| to be the parent, set
435     // |beforeChild| to be the RenderFullScreen.
436     const Element* fullScreenElement = document().webkitCurrentFullScreenElement();
437     if (fullScreenElement && beforeChild && beforeChild->node() == fullScreenElement)
438         beforeChild = document().fullScreenRenderer();
439 #endif
440     // Now take all of the children from beforeChild to the end and remove
441     // them from |this| and place them in the clone.
442     for (RenderObject* rendererToMove = beforeChild; rendererToMove;) {
443         RenderObject* nextSibling = rendererToMove->nextSibling();
444         // When anonymous wrapper is present, we might need to move the whole subtree instead.
445         if (rendererToMove->parent() != this) {
446             auto* anonymousParent = rendererToMove->parent();
447             while (anonymousParent && anonymousParent->parent() != this) {
448                 ASSERT(anonymousParent->isAnonymous());
449                 anonymousParent = anonymousParent->parent();
450             }
451             if (!anonymousParent) {
452                 ASSERT_NOT_REACHED();
453                 break;
454             }
455             // If beforeChild is the first child in the subtree, we could just move the whole subtree.
456             if (!rendererToMove->previousSibling()) {
457                 // Reparent the whole anonymous wrapper tree.
458                 rendererToMove = anonymousParent;
459                 // Skip to the next sibling that is not in this subtree.
460                 nextSibling = anonymousParent->nextSibling();
461             } else if (!rendererToMove->nextSibling()) {
462                 // This is the last renderer in the subtree. We need to jump out of the wrapper subtree, so that
463                 // the siblings are getting reparented too.
464                 nextSibling = anonymousParent->nextSibling();
465             }
466             // Otherwise just move the renderer to the inline clone. Should the renderer need an anon
467             // wrapper, the addChild() will generate one for it.
468             // FIXME: When the anonymous wrapper has multiple children, we end up traversing up to the topmost wrapper
469             // every time, which is a bit wasteful.
470         }
471         rendererToMove->parent()->removeChildInternal(*rendererToMove, NotifyChildren);
472         cloneInline->addChildIgnoringContinuation(rendererToMove);
473         rendererToMove->setNeedsLayoutAndPrefWidthsRecalc();
474         rendererToMove = nextSibling;
475     }
476     cloneInline->setContinuation(oldCont);
477     // Hook |clone| up as the continuation of the middle block.
478     middleBlock->setContinuation(cloneInline.get());
479
480     // We have been reparented and are now under the fromBlock.  We need
481     // to walk up our inline parent chain until we hit the containing block.
482     // Once we hit the containing block we're done.
483     RenderBoxModelObject* current = downcast<RenderBoxModelObject>(parent());
484     RenderBoxModelObject* currentChild = this;
485     
486     // FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone.
487     // There will eventually be a better approach to this problem that will let us nest to a much
488     // greater depth (see bugzilla bug 13430) but for now we have a limit.  This *will* result in
489     // incorrect rendering, but the alternative is to hang forever.
490     unsigned splitDepth = 1;
491     const unsigned cMaxSplitDepth = 200; 
492     while (current && current != fromBlock) {
493         if (splitDepth < cMaxSplitDepth) {
494             // Create a new clone.
495             RenderPtr<RenderInline> cloneChild = WTFMove(cloneInline);
496             cloneInline = downcast<RenderInline>(*current).clone();
497
498             // Insert our child clone as the first child.
499             cloneInline->addChildIgnoringContinuation(cloneChild.leakPtr());
500
501             // Hook the clone up as a continuation of |curr|.
502             RenderInline& currentInline = downcast<RenderInline>(*current);
503             oldCont = currentInline.continuation();
504             currentInline.setContinuation(cloneInline.get());
505             cloneInline->setContinuation(oldCont);
506
507             // Now we need to take all of the children starting from the first child
508             // *after* currentChild and append them all to the clone.
509             for (auto* current = currentChild->nextSibling(); current;) {
510                 auto* next = current->nextSibling();
511                 currentInline.removeChildInternal(*current, NotifyChildren);
512                 cloneInline->addChildIgnoringContinuation(current);
513                 current->setNeedsLayoutAndPrefWidthsRecalc();
514                 current = next;
515             }
516         }
517         
518         // Keep walking up the chain.
519         currentChild = current;
520         current = downcast<RenderBoxModelObject>(current->parent());
521         ++splitDepth;
522     }
523
524     // Clear the flow thread containing blocks cached during the detached state insertions.
525     for (auto& cloneBlockChild : childrenOfType<RenderBlock>(*cloneInline))
526         cloneBlockChild.resetFlowThreadContainingBlockAndChildInfoIncludingDescendants();
527
528     // Now we are at the block level. We need to put the clone into the toBlock.
529     toBlock->insertChildInternal(cloneInline.leakPtr(), nullptr, NotifyChildren);
530
531     // Now take all the children after currentChild and remove them from the fromBlock
532     // and put them in the toBlock.
533     for (auto* current = currentChild->nextSibling(); current;) {
534         auto* next = current->nextSibling();
535         fromBlock->removeChildInternal(*current, NotifyChildren);
536         toBlock->insertChildInternal(current, nullptr, NotifyChildren);
537         current = next;
538     }
539 }
540
541 void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
542                              RenderObject* newChild, RenderBoxModelObject* oldCont)
543 {
544     RenderBlock* pre = nullptr;
545     RenderBlock* block = containingBlock();
546     
547     // Delete our line boxes before we do the inline split into continuations.
548     block->deleteLines();
549     
550     bool madeNewBeforeBlock = false;
551     if (block->isAnonymousBlock() && (!block->parent() || !block->parent()->createsAnonymousWrapper())) {
552         // We can reuse this block and make it the preBlock of the next continuation.
553         pre = block;
554         pre->removePositionedObjects(nullptr);
555         // FIXME-BLOCKFLOW: The enclosing method should likely be switched over
556         // to only work on RenderBlockFlow, in which case this conversion can be
557         // removed.
558         if (is<RenderBlockFlow>(*pre))
559             downcast<RenderBlockFlow>(*pre).removeFloatingObjects();
560         block = block->containingBlock();
561     } else {
562         // No anonymous block available for use.  Make one.
563         pre = block->createAnonymousBlock();
564         madeNewBeforeBlock = true;
565     }
566
567     auto& post = downcast<RenderBlock>(*pre->createAnonymousBoxWithSameTypeAs(*block).release());
568
569     RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
570     if (madeNewBeforeBlock)
571         block->insertChildInternal(pre, boxFirst, NotifyChildren);
572     block->insertChildInternal(newBlockBox, boxFirst, NotifyChildren);
573     block->insertChildInternal(&post, boxFirst, NotifyChildren);
574     block->setChildrenInline(false);
575     
576     if (madeNewBeforeBlock) {
577         RenderObject* o = boxFirst;
578         while (o) {
579             RenderObject* no = o;
580             o = no->nextSibling();
581             block->removeChildInternal(*no, NotifyChildren);
582             pre->insertChildInternal(no, nullptr, NotifyChildren);
583             no->setNeedsLayoutAndPrefWidthsRecalc();
584         }
585     }
586
587     splitInlines(pre, &post, newBlockBox, beforeChild, oldCont);
588
589     // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
590     // time in makeChildrenNonInline by just setting this explicitly up front.
591     newBlockBox->setChildrenInline(false);
592
593     // We delayed adding the newChild until now so that the |newBlockBox| would be fully
594     // connected, thus allowing newChild access to a renderArena should it need
595     // to wrap itself in additional boxes (e.g., table construction).
596     newBlockBox->addChild(newChild);
597
598     // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
599     // get deleted properly.  Because objects moves from the pre block into the post block, we want to
600     // make new line boxes instead of leaving the old line boxes around.
601     pre->setNeedsLayoutAndPrefWidthsRecalc();
602     block->setNeedsLayoutAndPrefWidthsRecalc();
603     post.setNeedsLayoutAndPrefWidthsRecalc();
604 }
605
606 static bool canUseAsParentForContinuation(const RenderObject* renderer)
607 {
608     if (!renderer)
609         return false;
610     if (!is<RenderBlock>(renderer) && renderer->isAnonymous())
611         return false;
612     if (is<RenderTable>(renderer))
613         return false;
614     return true;
615 }
616
617 void RenderInline::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
618 {
619     auto* flow = continuationBefore(beforeChild);
620     // It may or may not be the direct parent of the beforeChild.
621     RenderBoxModelObject* beforeChildAncestor = nullptr;
622     // In case of anonymous wrappers, the parent of the beforeChild is mostly irrelevant. What we need is the topmost wrapper.
623     if (!beforeChild) {
624         auto* continuation = nextContinuation(flow);
625         beforeChildAncestor = continuation ? continuation : flow;
626     } else if (canUseAsParentForContinuation(beforeChild->parent()))
627         beforeChildAncestor = downcast<RenderBoxModelObject>(beforeChild->parent());
628     else if (beforeChild->parent()) {
629         auto* parent = beforeChild->parent();
630         while (parent && parent->parent() && parent->parent()->isAnonymous())
631             parent = parent->parent();
632         ASSERT(parent && parent->parent());
633         beforeChildAncestor = downcast<RenderBoxModelObject>(parent->parent());
634     } else
635         ASSERT_NOT_REACHED();
636
637     if (newChild->isFloatingOrOutOfFlowPositioned())
638         return beforeChildAncestor->addChildIgnoringContinuation(newChild, beforeChild);
639
640     if (flow == beforeChildAncestor)
641         return flow->addChildIgnoringContinuation(newChild, beforeChild);
642     // A continuation always consists of two potential candidates: an inline or an anonymous
643     // block box holding block children.
644     bool childInline = newChildIsInline(*newChild, *this);
645     // The goal here is to match up if we can, so that we can coalesce and create the
646     // minimal # of continuations needed for the inline.
647     if (childInline == beforeChildAncestor->isInline())
648         return beforeChildAncestor->addChildIgnoringContinuation(newChild, beforeChild);
649     if (flow->isInline() == childInline)
650         return flow->addChildIgnoringContinuation(newChild); // Just treat like an append.
651     return beforeChildAncestor->addChildIgnoringContinuation(newChild, beforeChild);
652 }
653
654 void RenderInline::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
655 {
656     m_lineBoxes.paint(this, paintInfo, paintOffset);
657 }
658
659 template<typename GeneratorContext>
660 void RenderInline::generateLineBoxRects(GeneratorContext& context) const
661 {
662     if (!alwaysCreateLineBoxes())
663         generateCulledLineBoxRects(context, this);
664     else if (InlineFlowBox* curr = firstLineBox()) {
665         for (; curr; curr = curr->nextLineBox())
666             context.addRect(FloatRect(curr->topLeft(), curr->size()));
667     } else
668         context.addRect(FloatRect());
669 }
670
671 template<typename GeneratorContext>
672 void RenderInline::generateCulledLineBoxRects(GeneratorContext& context, const RenderInline* container) const
673 {
674     if (!culledInlineFirstLineBox()) {
675         context.addRect(FloatRect());
676         return;
677     }
678
679     bool isHorizontal = style().isHorizontalWritingMode();
680
681     for (auto& current : childrenOfType<RenderObject>(*this)) {
682         if (current.isFloatingOrOutOfFlowPositioned())
683             continue;
684
685         // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
686         // direction (aligned to the root box's baseline).
687         if (is<RenderBox>(current)) {
688             auto& renderBox = downcast<RenderBox>(current);
689             if (renderBox.inlineBoxWrapper()) {
690                 const RootInlineBox& rootBox = renderBox.inlineBoxWrapper()->root();
691                 const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
692                 int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().fontCascade().fontMetrics().ascent() - containerStyle.fontCascade().fontMetrics().ascent());
693                 int logicalHeight = containerStyle.fontCascade().fontMetrics().height();
694                 if (isHorizontal)
695                     context.addRect(FloatRect(renderBox.inlineBoxWrapper()->x() - renderBox.marginLeft(), logicalTop, renderBox.width() + renderBox.horizontalMarginExtent(), logicalHeight));
696                 else
697                     context.addRect(FloatRect(logicalTop, renderBox.inlineBoxWrapper()->y() - renderBox.marginTop(), logicalHeight, renderBox.height() + renderBox.verticalMarginExtent()));
698             }
699         } else if (is<RenderInline>(current)) {
700             // If the child doesn't need line boxes either, then we can recur.
701             auto& renderInline = downcast<RenderInline>(current);
702             if (!renderInline.alwaysCreateLineBoxes())
703                 renderInline.generateCulledLineBoxRects(context, container);
704             else {
705                 for (InlineFlowBox* childLine = renderInline.firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
706                     const RootInlineBox& rootBox = childLine->root();
707                     const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
708                     int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().fontCascade().fontMetrics().ascent() - containerStyle.fontCascade().fontMetrics().ascent());
709                     int logicalHeight = containerStyle.fontMetrics().height();
710                     if (isHorizontal) {
711                         context.addRect(FloatRect(childLine->x() - childLine->marginLogicalLeft(),
712                             logicalTop,
713                             childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(),
714                             logicalHeight));
715                     } else {
716                         context.addRect(FloatRect(logicalTop,
717                             childLine->y() - childLine->marginLogicalLeft(),
718                             logicalHeight,
719                             childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight()));
720                     }
721                 }
722             }
723         } else if (is<RenderText>(current)) {
724             auto& currText = downcast<RenderText>(current);
725             for (InlineTextBox* childText = currText.firstTextBox(); childText; childText = childText->nextTextBox()) {
726                 const RootInlineBox& rootBox = childText->root();
727                 const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
728                 int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().fontCascade().fontMetrics().ascent() - containerStyle.fontCascade().fontMetrics().ascent());
729                 int logicalHeight = containerStyle.fontCascade().fontMetrics().height();
730                 if (isHorizontal)
731                     context.addRect(FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight));
732                 else
733                     context.addRect(FloatRect(logicalTop, childText->y(), logicalHeight, childText->logicalWidth()));
734             }
735         } else if (is<RenderLineBreak>(current)) {
736             if (auto* inlineBox = downcast<RenderLineBreak>(current).inlineBoxWrapper()) {
737                 // FIXME: This could use a helper to share these with text path.
738                 const RootInlineBox& rootBox = inlineBox->root();
739                 const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
740                 int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().fontCascade().fontMetrics().ascent() - containerStyle.fontCascade().fontMetrics().ascent());
741                 int logicalHeight = containerStyle.fontMetrics().height();
742                 if (isHorizontal)
743                     context.addRect(FloatRect(inlineBox->x(), logicalTop, inlineBox->logicalWidth(), logicalHeight));
744                 else
745                     context.addRect(FloatRect(logicalTop, inlineBox->y(), logicalHeight, inlineBox->logicalWidth()));
746             }
747         }
748     }
749 }
750
751 namespace {
752
753 class AbsoluteRectsGeneratorContext {
754 public:
755     AbsoluteRectsGeneratorContext(Vector<LayoutRect>& rects, const LayoutPoint& accumulatedOffset)
756         : m_rects(rects)
757         , m_accumulatedOffset(accumulatedOffset) { }
758
759     void addRect(const FloatRect& rect)
760     {
761         LayoutRect adjustedRect = LayoutRect(rect);
762         adjustedRect.moveBy(m_accumulatedOffset);
763         m_rects.append(adjustedRect);
764     }
765 private:
766     Vector<LayoutRect>& m_rects;
767     const LayoutPoint& m_accumulatedOffset;
768 };
769
770 } // unnamed namespace
771
772 void RenderInline::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
773 {
774     Vector<LayoutRect> lineboxRects;
775     AbsoluteRectsGeneratorContext context(lineboxRects, accumulatedOffset);
776     generateLineBoxRects(context);
777     for (const auto& rect : lineboxRects)
778         rects.append(snappedIntRect(rect));
779
780     if (RenderBoxModelObject* continuation = this->continuation()) {
781         if (is<RenderBox>(*continuation)) {
782             auto& box = downcast<RenderBox>(*continuation);
783             continuation->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location() + box.locationOffset()));
784         } else
785             continuation->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location()));
786     }
787 }
788
789
790 namespace {
791
792 class AbsoluteQuadsGeneratorContext {
793 public:
794     AbsoluteQuadsGeneratorContext(const RenderInline* renderer, Vector<FloatQuad>& quads)
795         : m_quads(quads)
796         , m_geometryMap()
797     {
798         m_geometryMap.pushMappingsToAncestor(renderer, nullptr);
799     }
800
801     void addRect(const FloatRect& rect)
802     {
803         m_quads.append(m_geometryMap.absoluteRect(rect));
804     }
805 private:
806     Vector<FloatQuad>& m_quads;
807     RenderGeometryMap m_geometryMap;
808 };
809
810 } // unnamed namespace
811
812 void RenderInline::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
813 {
814     AbsoluteQuadsGeneratorContext context(this, quads);
815     generateLineBoxRects(context);
816
817     if (RenderBoxModelObject* continuation = this->continuation())
818         continuation->absoluteQuads(quads, wasFixed);
819 }
820
821 #if PLATFORM(IOS)
822 void RenderInline::absoluteQuadsForSelection(Vector<FloatQuad>& quads) const
823 {
824     AbsoluteQuadsGeneratorContext context(this, quads);
825     generateLineBoxRects(context);
826 }
827 #endif
828
829 LayoutUnit RenderInline::offsetLeft() const
830 {
831     LayoutPoint topLeft;
832     if (InlineBox* firstBox = firstLineBoxIncludingCulling())
833         topLeft = flooredLayoutPoint(firstBox->topLeft());
834     return adjustedPositionRelativeToOffsetParent(topLeft).x();
835 }
836
837 LayoutUnit RenderInline::offsetTop() const
838 {
839     LayoutPoint topLeft;
840     if (InlineBox* firstBox = firstLineBoxIncludingCulling())
841         topLeft = flooredLayoutPoint(firstBox->topLeft());
842     return adjustedPositionRelativeToOffsetParent(topLeft).y();
843 }
844
845 static LayoutUnit computeMargin(const RenderInline* renderer, const Length& margin)
846 {
847     if (margin.isAuto())
848         return 0;
849     if (margin.isFixed())
850         return margin.value();
851     if (margin.isPercentOrCalculated())
852         return minimumValueForLength(margin, std::max<LayoutUnit>(0, renderer->containingBlock()->availableLogicalWidth()));
853     return 0;
854 }
855
856 LayoutUnit RenderInline::marginLeft() const
857 {
858     return computeMargin(this, style().marginLeft());
859 }
860
861 LayoutUnit RenderInline::marginRight() const
862 {
863     return computeMargin(this, style().marginRight());
864 }
865
866 LayoutUnit RenderInline::marginTop() const
867 {
868     return computeMargin(this, style().marginTop());
869 }
870
871 LayoutUnit RenderInline::marginBottom() const
872 {
873     return computeMargin(this, style().marginBottom());
874 }
875
876 LayoutUnit RenderInline::marginStart(const RenderStyle* otherStyle) const
877 {
878     return computeMargin(this, style().marginStartUsing(otherStyle ? otherStyle : &style()));
879 }
880
881 LayoutUnit RenderInline::marginEnd(const RenderStyle* otherStyle) const
882 {
883     return computeMargin(this, style().marginEndUsing(otherStyle ? otherStyle : &style()));
884 }
885
886 LayoutUnit RenderInline::marginBefore(const RenderStyle* otherStyle) const
887 {
888     return computeMargin(this, style().marginBeforeUsing(otherStyle ? otherStyle : &style()));
889 }
890
891 LayoutUnit RenderInline::marginAfter(const RenderStyle* otherStyle) const
892 {
893     return computeMargin(this, style().marginAfterUsing(otherStyle ? otherStyle : &style()));
894 }
895
896 const char* RenderInline::renderName() const
897 {
898     if (isRelPositioned())
899         return "RenderInline (relative positioned)";
900     if (isStickyPositioned())
901         return "RenderInline (sticky positioned)";
902     // FIXME: Temporary hack while the new generated content system is being implemented.
903     if (isPseudoElement())
904         return "RenderInline (generated)";
905     if (isAnonymous())
906         return "RenderInline (generated)";
907     return "RenderInline";
908 }
909
910 bool RenderInline::nodeAtPoint(const HitTestRequest& request, HitTestResult& result,
911                                 const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
912 {
913     return m_lineBoxes.hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction);
914 }
915
916 namespace {
917
918 class HitTestCulledInlinesGeneratorContext {
919 public:
920     HitTestCulledInlinesGeneratorContext(Region& region, const HitTestLocation& location)
921         : m_intersected(false)
922         , m_region(region)
923         , m_location(location)
924     { }
925
926     void addRect(const FloatRect& rect)
927     {
928         m_intersected = m_intersected || m_location.intersects(rect);
929         m_region.unite(enclosingIntRect(rect));
930     }
931
932     bool intersected() const { return m_intersected; }
933
934 private:
935     bool m_intersected;
936     Region& m_region;
937     const HitTestLocation& m_location;
938 };
939
940 } // unnamed namespace
941
942 bool RenderInline::hitTestCulledInline(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset)
943 {
944     ASSERT(result.isRectBasedTest() && !alwaysCreateLineBoxes());
945     if (!visibleToHitTesting())
946         return false;
947
948     HitTestLocation tmpLocation(locationInContainer, -toLayoutSize(accumulatedOffset));
949
950     Region regionResult;
951     HitTestCulledInlinesGeneratorContext context(regionResult, tmpLocation);
952     generateCulledLineBoxRects(context, this);
953
954     if (context.intersected()) {
955         updateHitTestResult(result, tmpLocation.point());
956         // We can not use addNodeToRectBasedTestResult to determine if we fully enclose the hit-test area
957         // because it can only handle rectangular targets.
958         result.addNodeToRectBasedTestResult(element(), request, locationInContainer);
959         return regionResult.contains(tmpLocation.boundingBox());
960     }
961     return false;
962 }
963
964 VisiblePosition RenderInline::positionForPoint(const LayoutPoint& point, const RenderRegion* region)
965 {
966     // FIXME: Does not deal with relative or sticky positioned inlines (should it?)
967     RenderBlock& containingBlock = *this->containingBlock();
968     if (firstLineBox()) {
969         // This inline actually has a line box.  We must have clicked in the border/padding of one of these boxes.  We
970         // should try to find a result by asking our containing block.
971         return containingBlock.positionForPoint(point, region);
972     }
973
974     // Translate the coords from the pre-anonymous block to the post-anonymous block.
975     LayoutPoint parentBlockPoint = containingBlock.location() + point;
976     RenderBoxModelObject* continuation = this->continuation();
977     while (continuation) {
978         RenderBlock* currentBlock = continuation->isInline() ? continuation->containingBlock() : downcast<RenderBlock>(continuation);
979         if (continuation->isInline() || continuation->firstChild())
980             return continuation->positionForPoint(parentBlockPoint - currentBlock->locationOffset(), region);
981         continuation = downcast<RenderBlock>(*continuation).inlineElementContinuation();
982     }
983     
984     return RenderBoxModelObject::positionForPoint(point, region);
985 }
986
987 namespace {
988
989 class LinesBoundingBoxGeneratorContext {
990 public:
991     LinesBoundingBoxGeneratorContext(FloatRect& rect) : m_rect(rect) { }
992
993     void addRect(const FloatRect& rect)
994     {
995         m_rect.uniteIfNonZero(rect);
996     }
997 private:
998     FloatRect& m_rect;
999 };
1000
1001 } // unnamed namespace
1002
1003 IntRect RenderInline::linesBoundingBox() const
1004 {
1005     if (!alwaysCreateLineBoxes()) {
1006         ASSERT(!firstLineBox());
1007         FloatRect floatResult;
1008         LinesBoundingBoxGeneratorContext context(floatResult);
1009         generateCulledLineBoxRects(context, this);
1010         return enclosingIntRect(floatResult);
1011     }
1012
1013     IntRect result;
1014     
1015     // See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero.  We have been
1016     // unable to reproduce this at all (and consequently unable to figure ot why this is happening).  The assert will hopefully catch the problem in debug
1017     // builds and help us someday figure out why.  We also put in a redundant check of lastLineBox() to avoid the crash for now.
1018     ASSERT(!firstLineBox() == !lastLineBox());  // Either both are null or both exist.
1019     if (firstLineBox() && lastLineBox()) {
1020         // Return the width of the minimal left side and the maximal right side.
1021         float logicalLeftSide = 0;
1022         float logicalRightSide = 0;
1023         for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
1024             if (curr == firstLineBox() || curr->logicalLeft() < logicalLeftSide)
1025                 logicalLeftSide = curr->logicalLeft();
1026             if (curr == firstLineBox() || curr->logicalRight() > logicalRightSide)
1027                 logicalRightSide = curr->logicalRight();
1028         }
1029         
1030         bool isHorizontal = style().isHorizontalWritingMode();
1031         
1032         float x = isHorizontal ? logicalLeftSide : firstLineBox()->x();
1033         float y = isHorizontal ? firstLineBox()->y() : logicalLeftSide;
1034         float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastLineBox()->logicalBottom() - x;
1035         float height = isHorizontal ? lastLineBox()->logicalBottom() - y : logicalRightSide - logicalLeftSide;
1036         result = enclosingIntRect(FloatRect(x, y, width, height));
1037     }
1038
1039     return result;
1040 }
1041
1042 InlineBox* RenderInline::culledInlineFirstLineBox() const
1043 {
1044     for (auto& current : childrenOfType<RenderObject>(*this)) {
1045         if (current.isFloatingOrOutOfFlowPositioned())
1046             continue;
1047
1048         // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
1049         // direction (aligned to the root box's baseline).
1050         if (is<RenderBox>(current)) {
1051             auto& renderBox = downcast<RenderBox>(current);
1052             if (renderBox.inlineBoxWrapper())
1053                 return renderBox.inlineBoxWrapper();
1054         } else if (is<RenderLineBreak>(current)) {
1055             auto& renderBR = downcast<RenderLineBreak>(current);
1056             if (renderBR.inlineBoxWrapper())
1057                 return renderBR.inlineBoxWrapper();
1058         } else if (is<RenderInline>(current)) {
1059             auto& renderInline = downcast<RenderInline>(current);
1060             if (InlineBox* result = renderInline.firstLineBoxIncludingCulling())
1061                 return result;
1062         } else if (is<RenderText>(current)) {
1063             auto& renderText = downcast<RenderText>(current);
1064             if (renderText.firstTextBox())
1065                 return renderText.firstTextBox();
1066         }
1067     }
1068     return nullptr;
1069 }
1070
1071 InlineBox* RenderInline::culledInlineLastLineBox() const
1072 {
1073     for (RenderObject* current = lastChild(); current; current = current->previousSibling()) {
1074         if (current->isFloatingOrOutOfFlowPositioned())
1075             continue;
1076             
1077         // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
1078         // direction (aligned to the root box's baseline).
1079         if (is<RenderBox>(*current)) {
1080             const auto& renderBox = downcast<RenderBox>(*current);
1081             if (renderBox.inlineBoxWrapper())
1082                 return renderBox.inlineBoxWrapper();
1083         } else if (is<RenderLineBreak>(*current)) {
1084             RenderLineBreak& renderBR = downcast<RenderLineBreak>(*current);
1085             if (renderBR.inlineBoxWrapper())
1086                 return renderBR.inlineBoxWrapper();
1087         } else if (is<RenderInline>(*current)) {
1088             RenderInline& renderInline = downcast<RenderInline>(*current);
1089             if (InlineBox* result = renderInline.lastLineBoxIncludingCulling())
1090                 return result;
1091         } else if (is<RenderText>(*current)) {
1092             RenderText& renderText = downcast<RenderText>(*current);
1093             if (renderText.lastTextBox())
1094                 return renderText.lastTextBox();
1095         }
1096     }
1097     return nullptr;
1098 }
1099
1100 LayoutRect RenderInline::culledInlineVisualOverflowBoundingBox() const
1101 {
1102     FloatRect floatResult;
1103     LinesBoundingBoxGeneratorContext context(floatResult);
1104     generateCulledLineBoxRects(context, this);
1105     LayoutRect result(enclosingLayoutRect(floatResult));
1106     bool isHorizontal = style().isHorizontalWritingMode();
1107     for (auto& current : childrenOfType<RenderObject>(*this)) {
1108         if (current.isFloatingOrOutOfFlowPositioned())
1109             continue;
1110
1111         // For overflow we just have to propagate by hand and recompute it all.
1112         if (is<RenderBox>(current)) {
1113             auto& renderBox = downcast<RenderBox>(current);
1114             if (!renderBox.hasSelfPaintingLayer() && renderBox.inlineBoxWrapper()) {
1115                 LayoutRect logicalRect = renderBox.logicalVisualOverflowRectForPropagation(&style());
1116                 if (isHorizontal) {
1117                     logicalRect.moveBy(renderBox.location());
1118                     result.uniteIfNonZero(logicalRect);
1119                 } else {
1120                     logicalRect.moveBy(renderBox.location());
1121                     result.uniteIfNonZero(logicalRect.transposedRect());
1122                 }
1123             }
1124         } else if (is<RenderInline>(current)) {
1125             // If the child doesn't need line boxes either, then we can recur.
1126             auto& renderInline = downcast<RenderInline>(current);
1127             if (!renderInline.alwaysCreateLineBoxes())
1128                 result.uniteIfNonZero(renderInline.culledInlineVisualOverflowBoundingBox());
1129             else if (!renderInline.hasSelfPaintingLayer())
1130                 result.uniteIfNonZero(renderInline.linesVisualOverflowBoundingBox());
1131         } else if (is<RenderText>(current)) {
1132             // FIXME; Overflow from text boxes is lost. We will need to cache this information in
1133             // InlineTextBoxes.
1134             auto& renderText = downcast<RenderText>(current);
1135             result.uniteIfNonZero(renderText.linesVisualOverflowBoundingBox());
1136         }
1137     }
1138     return result;
1139 }
1140
1141 LayoutRect RenderInline::linesVisualOverflowBoundingBox() const
1142 {
1143     if (!alwaysCreateLineBoxes())
1144         return culledInlineVisualOverflowBoundingBox();
1145
1146     if (!firstLineBox() || !lastLineBox())
1147         return LayoutRect();
1148
1149     // Return the width of the minimal left side and the maximal right side.
1150     LayoutUnit logicalLeftSide = LayoutUnit::max();
1151     LayoutUnit logicalRightSide = LayoutUnit::min();
1152     for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
1153         logicalLeftSide = std::min(logicalLeftSide, curr->logicalLeftVisualOverflow());
1154         logicalRightSide = std::max(logicalRightSide, curr->logicalRightVisualOverflow());
1155     }
1156
1157     const RootInlineBox& firstRootBox = firstLineBox()->root();
1158     const RootInlineBox& lastRootBox = lastLineBox()->root();
1159     
1160     LayoutUnit logicalTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox.lineTop());
1161     LayoutUnit logicalWidth = logicalRightSide - logicalLeftSide;
1162     LayoutUnit logicalHeight = lastLineBox()->logicalBottomVisualOverflow(lastRootBox.lineBottom()) - logicalTop;
1163     
1164     LayoutRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
1165     if (!style().isHorizontalWritingMode())
1166         rect = rect.transposedRect();
1167     return rect;
1168 }
1169
1170 LayoutRect RenderInline::linesVisualOverflowBoundingBoxInRegion(const RenderRegion* region) const
1171 {
1172     ASSERT(alwaysCreateLineBoxes());
1173     ASSERT(region);
1174
1175     if (!firstLineBox() || !lastLineBox())
1176         return LayoutRect();
1177
1178     // Return the width of the minimal left side and the maximal right side.
1179     LayoutUnit logicalLeftSide = LayoutUnit::max();
1180     LayoutUnit logicalRightSide = LayoutUnit::min();
1181     LayoutUnit logicalTop;
1182     LayoutUnit logicalHeight;
1183     InlineFlowBox* lastInlineInRegion = 0;
1184     for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
1185         const RootInlineBox& root = curr->root();
1186         if (root.containingRegion() != region) {
1187             if (lastInlineInRegion)
1188                 break;
1189             continue;
1190         }
1191
1192         if (!lastInlineInRegion)
1193             logicalTop = curr->logicalTopVisualOverflow(root.lineTop());
1194
1195         lastInlineInRegion = curr;
1196
1197         logicalLeftSide = std::min(logicalLeftSide, curr->logicalLeftVisualOverflow());
1198         logicalRightSide = std::max(logicalRightSide, curr->logicalRightVisualOverflow());
1199     }
1200
1201     if (!lastInlineInRegion)
1202         return LayoutRect();
1203
1204     logicalHeight = lastInlineInRegion->logicalBottomVisualOverflow(lastInlineInRegion->root().lineBottom()) - logicalTop;
1205     
1206     LayoutUnit logicalWidth = logicalRightSide - logicalLeftSide;
1207     
1208     LayoutRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
1209     if (!style().isHorizontalWritingMode())
1210         rect = rect.transposedRect();
1211     return rect;
1212 }
1213
1214 LayoutRect RenderInline::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
1215 {
1216     // Only first-letter renderers are allowed in here during layout. They mutate the tree triggering repaints.
1217     ASSERT(!view().layoutStateEnabled() || style().styleType() == FIRST_LETTER || hasSelfPaintingLayer());
1218
1219     if (!firstLineBoxIncludingCulling() && !continuation())
1220         return LayoutRect();
1221
1222     LayoutRect repaintRect(linesVisualOverflowBoundingBox());
1223     bool hitRepaintContainer = false;
1224
1225     // We need to add in the in-flow position offsets of any inlines (including us) up to our
1226     // containing block.
1227     RenderBlock* containingBlock = this->containingBlock();
1228     for (const RenderElement* inlineFlow = this; is<RenderInline>(inlineFlow) && inlineFlow != containingBlock;
1229          inlineFlow = inlineFlow->parent()) {
1230          if (inlineFlow == repaintContainer) {
1231             hitRepaintContainer = true;
1232             break;
1233         }
1234         if (inlineFlow->style().hasInFlowPosition() && inlineFlow->hasLayer())
1235             repaintRect.move(downcast<RenderInline>(*inlineFlow).layer()->offsetForInFlowPosition());
1236     }
1237
1238     LayoutUnit outlineSize = style().outlineSize();
1239     repaintRect.inflate(outlineSize);
1240
1241     if (hitRepaintContainer || !containingBlock)
1242         return repaintRect;
1243
1244     if (containingBlock->hasOverflowClip() && containingBlock->shouldApplyClipAndScrollPositionForRepaint(repaintContainer))
1245         containingBlock->applyCachedClipAndScrollPositionForRepaint(repaintRect);
1246
1247     repaintRect = containingBlock->computeRectForRepaint(repaintRect, repaintContainer);
1248
1249     if (outlineSize) {
1250         for (auto& child : childrenOfType<RenderElement>(*this))
1251             repaintRect.unite(child.rectWithOutlineForRepaint(repaintContainer, outlineSize));
1252
1253         if (RenderBoxModelObject* continuation = this->continuation()) {
1254             if (!continuation->isInline() && continuation->parent())
1255                 repaintRect.unite(continuation->rectWithOutlineForRepaint(repaintContainer, outlineSize));
1256         }
1257     }
1258
1259     return repaintRect;
1260 }
1261
1262 LayoutRect RenderInline::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
1263 {
1264     LayoutRect r(RenderBoxModelObject::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
1265     for (auto& child : childrenOfType<RenderElement>(*this))
1266         r.unite(child.rectWithOutlineForRepaint(repaintContainer, outlineWidth));
1267     return r;
1268 }
1269
1270 LayoutRect RenderInline::computeRectForRepaint(const LayoutRect& rect, const RenderLayerModelObject* repaintContainer, RepaintContext context) const
1271 {
1272     // LayoutState is only valid for root-relative repainting
1273     LayoutRect adjustedRect = rect;
1274     if (view().layoutStateEnabled() && !repaintContainer) {
1275         LayoutState* layoutState = view().layoutState();
1276         if (style().hasInFlowPosition() && layer())
1277             adjustedRect.move(layer()->offsetForInFlowPosition());
1278         adjustedRect.move(layoutState->m_paintOffset);
1279         if (layoutState->m_clipped)
1280             adjustedRect.intersect(layoutState->m_clipRect);
1281         return adjustedRect;
1282     }
1283
1284     if (repaintContainer == this)
1285         return adjustedRect;
1286
1287     bool containerSkipped;
1288     RenderElement* container = this->container(repaintContainer, containerSkipped);
1289     if (!container)
1290         return adjustedRect;
1291
1292     LayoutPoint topLeft = adjustedRect.location();
1293
1294     if (style().hasInFlowPosition() && layer()) {
1295         // Apply the in-flow position offset when invalidating a rectangle. The layer
1296         // is translated, but the render box isn't, so we need to do this to get the
1297         // right dirty rect. Since this is called from RenderObject::setStyle, the relative or sticky position
1298         // flag on the RenderObject has been cleared, so use the one on the style().
1299         topLeft += layer()->offsetForInFlowPosition();
1300     }
1301     
1302     // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
1303     // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
1304     adjustedRect.setLocation(topLeft);
1305     if (container->hasOverflowClip()) {
1306         downcast<RenderBox>(*container).applyCachedClipAndScrollPositionForRepaint(adjustedRect);
1307         if (adjustedRect.isEmpty())
1308             return adjustedRect;
1309     }
1310
1311     if (containerSkipped) {
1312         // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
1313         LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(*container);
1314         adjustedRect.move(-containerOffset);
1315         return adjustedRect;
1316     }
1317     return container->computeRectForRepaint(adjustedRect, repaintContainer, context);
1318 }
1319
1320 LayoutSize RenderInline::offsetFromContainer(RenderElement& container, const LayoutPoint&, bool* offsetDependsOnPoint) const
1321 {
1322     ASSERT(&container == this->container());
1323     
1324     LayoutSize offset;    
1325     if (isInFlowPositioned())
1326         offset += offsetForInFlowPosition();
1327
1328     if (is<RenderBox>(container))
1329         offset -= toLayoutSize(downcast<RenderBox>(container).scrollPosition());
1330
1331     if (offsetDependsOnPoint)
1332         *offsetDependsOnPoint = (is<RenderBox>(container) && container.style().isFlippedBlocksWritingMode()) || is<RenderFlowThread>(container);
1333
1334     return offset;
1335 }
1336
1337 void RenderInline::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
1338 {
1339     if (repaintContainer == this)
1340         return;
1341
1342     if (view().layoutStateEnabled() && !repaintContainer) {
1343         LayoutState* layoutState = view().layoutState();
1344         LayoutSize offset = layoutState->m_paintOffset;
1345         if (style().hasInFlowPosition() && layer())
1346             offset += layer()->offsetForInFlowPosition();
1347         transformState.move(offset);
1348         return;
1349     }
1350
1351     bool containerSkipped;
1352     RenderElement* container = this->container(repaintContainer, containerSkipped);
1353     if (!container)
1354         return;
1355
1356     if (mode & ApplyContainerFlip && is<RenderBox>(*container)) {
1357         if (container->style().isFlippedBlocksWritingMode()) {
1358             LayoutPoint centerPoint(transformState.mappedPoint());
1359             transformState.move(downcast<RenderBox>(*container).flipForWritingMode(centerPoint) - centerPoint);
1360         }
1361         mode &= ~ApplyContainerFlip;
1362     }
1363
1364     LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(transformState.mappedPoint()));
1365
1366     bool preserve3D = mode & UseTransforms && (container->style().preserves3D() || style().preserves3D());
1367     if (mode & UseTransforms && shouldUseTransformFromContainer(container)) {
1368         TransformationMatrix t;
1369         getTransformFromContainer(container, containerOffset, t);
1370         transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1371     } else
1372         transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1373
1374     if (containerSkipped) {
1375         // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
1376         // to just subtract the delta between the repaintContainer and o.
1377         LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(*container);
1378         transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1379         return;
1380     }
1381
1382     container->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
1383 }
1384
1385 const RenderObject* RenderInline::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
1386 {
1387     ASSERT(ancestorToStopAt != this);
1388
1389     bool ancestorSkipped;
1390     RenderElement* container = this->container(ancestorToStopAt, ancestorSkipped);
1391     if (!container)
1392         return nullptr;
1393
1394     LayoutSize adjustmentForSkippedAncestor;
1395     if (ancestorSkipped) {
1396         // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
1397         // to just subtract the delta between the ancestor and o.
1398         adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(*container);
1399     }
1400
1401     bool offsetDependsOnPoint = false;
1402     LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(), &offsetDependsOnPoint);
1403
1404     bool preserve3D = container->style().preserves3D() || style().preserves3D();
1405     if (shouldUseTransformFromContainer(container)) {
1406         TransformationMatrix t;
1407         getTransformFromContainer(container, containerOffset, t);
1408         t.translateRight(adjustmentForSkippedAncestor.width(), adjustmentForSkippedAncestor.height()); // FIXME: right?
1409         geometryMap.push(this, t, preserve3D, offsetDependsOnPoint);
1410     } else {
1411         containerOffset += adjustmentForSkippedAncestor;
1412         geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint);
1413     }
1414     
1415     return ancestorSkipped ? ancestorToStopAt : container;
1416 }
1417
1418 void RenderInline::updateDragState(bool dragOn)
1419 {
1420     RenderBoxModelObject::updateDragState(dragOn);
1421     if (RenderBoxModelObject* continuation = this->continuation())
1422         continuation->updateDragState(dragOn);
1423 }
1424
1425 void RenderInline::childBecameNonInline(RenderElement& child)
1426 {
1427     // We have to split the parent flow.
1428     RenderBlock* newBox = containingBlock()->createAnonymousBlock();
1429     RenderBoxModelObject* oldContinuation = continuation();
1430     setContinuation(newBox);
1431     RenderObject* beforeChild = child.nextSibling();
1432     removeChildInternal(child, NotifyChildren);
1433     splitFlow(beforeChild, newBox, &child, oldContinuation);
1434 }
1435
1436 void RenderInline::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
1437 {
1438     if (result.innerNode())
1439         return;
1440
1441     LayoutPoint localPoint(point);
1442     if (Element* element = this->element()) {
1443         if (isInlineElementContinuation()) {
1444             // We're in the continuation of a split inline.  Adjust our local point to be in the coordinate space
1445             // of the principal renderer's containing block.  This will end up being the innerNonSharedNode.
1446             RenderBlock* firstBlock = element->renderer()->containingBlock();
1447             
1448             // Get our containing block.
1449             RenderBox* block = containingBlock();
1450             localPoint.moveBy(block->location() - firstBlock->locationOffset());
1451         }
1452
1453         result.setInnerNode(element);
1454         if (!result.innerNonSharedNode())
1455             result.setInnerNonSharedNode(element);
1456         result.setLocalPoint(localPoint);
1457     }
1458 }
1459
1460 void RenderInline::dirtyLineBoxes(bool fullLayout)
1461 {
1462     if (fullLayout) {
1463         m_lineBoxes.deleteLineBoxes();
1464         return;
1465     }
1466
1467     if (!alwaysCreateLineBoxes()) {
1468         // We have to grovel into our children in order to dirty the appropriate lines.
1469         for (auto& current : childrenOfType<RenderObject>(*this)) {
1470             if (current.isFloatingOrOutOfFlowPositioned())
1471                 continue;
1472             if (is<RenderBox>(current) && !current.needsLayout()) {
1473                 auto& renderBox = downcast<RenderBox>(current);
1474                 if (renderBox.inlineBoxWrapper())
1475                     renderBox.inlineBoxWrapper()->root().markDirty();
1476             } else if (!current.selfNeedsLayout()) {
1477                 if (is<RenderInline>(current)) {
1478                     auto& renderInline = downcast<RenderInline>(current);
1479                     for (InlineFlowBox* childLine = renderInline.firstLineBox(); childLine; childLine = childLine->nextLineBox())
1480                         childLine->root().markDirty();
1481                 } else if (is<RenderText>(current)) {
1482                     auto& renderText = downcast<RenderText>(current);
1483                     for (InlineTextBox* childText = renderText.firstTextBox(); childText; childText = childText->nextTextBox())
1484                         childText->root().markDirty();
1485                 } else if (is<RenderLineBreak>(current)) {
1486                     auto& renderBR = downcast<RenderLineBreak>(current);
1487                     if (renderBR.inlineBoxWrapper())
1488                         renderBR.inlineBoxWrapper()->root().markDirty();
1489                 }
1490             }
1491         }
1492     } else
1493         m_lineBoxes.dirtyLineBoxes();
1494 }
1495
1496 void RenderInline::deleteLines()
1497 {
1498     m_lineBoxes.deleteLineBoxTree();
1499 }
1500
1501 std::unique_ptr<InlineFlowBox> RenderInline::createInlineFlowBox()
1502 {
1503     return std::make_unique<InlineFlowBox>(*this);
1504 }
1505
1506 InlineFlowBox* RenderInline::createAndAppendInlineFlowBox()
1507 {
1508     setAlwaysCreateLineBoxes();
1509     auto newFlowBox = createInlineFlowBox();
1510     auto flowBox = newFlowBox.get();
1511     m_lineBoxes.appendLineBox(WTFMove(newFlowBox));
1512     return flowBox;
1513 }
1514
1515 LayoutUnit RenderInline::lineHeight(bool firstLine, LineDirectionMode /*direction*/, LinePositionMode /*linePositionMode*/) const
1516 {
1517     if (firstLine && view().usesFirstLineRules()) {
1518         const RenderStyle& firstLineStyle = this->firstLineStyle();
1519         if (&firstLineStyle != &style())
1520             return firstLineStyle.computedLineHeight();
1521     }
1522
1523     return style().computedLineHeight();
1524 }
1525
1526 int RenderInline::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
1527 {
1528     const RenderStyle& style = firstLine ? firstLineStyle() : this->style();
1529     const FontMetrics& fontMetrics = style.fontMetrics();
1530     return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
1531 }
1532
1533 LayoutSize RenderInline::offsetForInFlowPositionedInline(const RenderBox* child) const
1534 {
1535     // FIXME: This function isn't right with mixed writing modes.
1536
1537     ASSERT(isInFlowPositioned());
1538     if (!isInFlowPositioned())
1539         return LayoutSize();
1540
1541     // When we have an enclosing relpositioned inline, we need to add in the offset of the first line
1542     // box from the rest of the content, but only in the cases where we know we're positioned
1543     // relative to the inline itself.
1544
1545     LayoutSize logicalOffset;
1546     LayoutUnit inlinePosition;
1547     LayoutUnit blockPosition;
1548     if (firstLineBox()) {
1549         inlinePosition = LayoutUnit::fromFloatRound(firstLineBox()->logicalLeft());
1550         blockPosition = firstLineBox()->logicalTop();
1551     } else {
1552         inlinePosition = layer()->staticInlinePosition();
1553         blockPosition = layer()->staticBlockPosition();
1554     }
1555
1556     if (!child->style().hasStaticInlinePosition(style().isHorizontalWritingMode()))
1557         logicalOffset.setWidth(inlinePosition);
1558
1559     // This is not terribly intuitive, but we have to match other browsers.  Despite being a block display type inside
1560     // an inline, we still keep our x locked to the left of the relative positioned inline.  Arguably the correct
1561     // behavior would be to go flush left to the block that contains the inline, but that isn't what other browsers
1562     // do.
1563     else if (!child->style().isOriginalDisplayInlineType())
1564         // Avoid adding in the left border/padding of the containing block twice.  Subtract it out.
1565         logicalOffset.setWidth(inlinePosition - child->containingBlock()->borderAndPaddingLogicalLeft());
1566
1567     if (!child->style().hasStaticBlockPosition(style().isHorizontalWritingMode()))
1568         logicalOffset.setHeight(blockPosition);
1569
1570     return style().isHorizontalWritingMode() ? logicalOffset : logicalOffset.transposedSize();
1571 }
1572
1573 void RenderInline::imageChanged(WrappedImagePtr, const IntRect*)
1574 {
1575     if (!parent())
1576         return;
1577         
1578     // FIXME: We can do better.
1579     repaint();
1580 }
1581
1582 void RenderInline::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
1583 {
1584     AbsoluteRectsGeneratorContext context(rects, additionalOffset);
1585     generateLineBoxRects(context);
1586
1587     for (auto& child : childrenOfType<RenderElement>(*this)) {
1588         if (is<RenderListMarker>(child))
1589             continue;
1590         FloatPoint pos(additionalOffset);
1591         // FIXME: This doesn't work correctly with transforms.
1592         if (child.hasLayer())
1593             pos = child.localToContainerPoint(FloatPoint(), paintContainer);
1594         else if (is<RenderBox>(child))
1595             pos.move(downcast<RenderBox>(child).locationOffset());
1596         child.addFocusRingRects(rects, flooredIntPoint(pos), paintContainer);
1597     }
1598
1599     if (RenderBoxModelObject* continuation = this->continuation()) {
1600         if (continuation->isInline())
1601             continuation->addFocusRingRects(rects, flooredLayoutPoint(LayoutPoint(additionalOffset + continuation->containingBlock()->location() - containingBlock()->location())), paintContainer);
1602         else
1603             continuation->addFocusRingRects(rects, flooredLayoutPoint(LayoutPoint(additionalOffset + downcast<RenderBox>(*continuation).location() - containingBlock()->location())), paintContainer);
1604     }
1605 }
1606
1607 void RenderInline::paintOutline(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1608 {
1609     if (!hasOutline())
1610         return;
1611
1612     auto& styleToUse = style();
1613     // Only paint the focus ring by hand if the theme isn't able to draw it.
1614     if (styleToUse.outlineStyleIsAuto() && !theme().supportsFocusRing(styleToUse)) {
1615         Vector<LayoutRect> focusRingRects;
1616         addFocusRingRects(focusRingRects, paintOffset, paintInfo.paintContainer);
1617         paintFocusRing(paintInfo, styleToUse, focusRingRects);
1618     }
1619
1620     if (hasOutlineAnnotation() && !styleToUse.outlineStyleIsAuto() && !theme().supportsFocusRing(styleToUse))
1621         addPDFURLRect(paintInfo, paintOffset);
1622
1623     GraphicsContext& graphicsContext = paintInfo.context();
1624     if (graphicsContext.paintingDisabled())
1625         return;
1626
1627     if (styleToUse.outlineStyleIsAuto() || !styleToUse.hasOutline())
1628         return;
1629
1630     Vector<LayoutRect> rects;
1631     rects.append(LayoutRect());
1632     for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
1633         const RootInlineBox& rootBox = curr->root();
1634         LayoutUnit top = std::max<LayoutUnit>(rootBox.lineTop(), curr->logicalTop());
1635         LayoutUnit bottom = std::min<LayoutUnit>(rootBox.lineBottom(), curr->logicalBottom());
1636         rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top));
1637     }
1638     rects.append(LayoutRect());
1639
1640     Color outlineColor = styleToUse.visitedDependentColor(CSSPropertyOutlineColor);
1641     bool useTransparencyLayer = !outlineColor.isOpaque();
1642     if (useTransparencyLayer) {
1643         graphicsContext.beginTransparencyLayer(outlineColor.alphaAsFloat());
1644         outlineColor = outlineColor.opaqueColor();
1645     }
1646
1647     for (unsigned i = 1; i < rects.size() - 1; i++)
1648         paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor);
1649
1650     if (useTransparencyLayer)
1651         graphicsContext.endTransparencyLayer();
1652 }
1653
1654 void RenderInline::paintOutlineForLine(GraphicsContext& graphicsContext, const LayoutPoint& paintOffset,
1655     const LayoutRect& previousLine, const LayoutRect& thisLine, const LayoutRect& nextLine, const Color& outlineColor)
1656 {
1657     const auto& styleToUse = style();
1658     float outlineOffset = styleToUse.outlineOffset();
1659     LayoutRect outlineBoxRect = thisLine;
1660     outlineBoxRect.inflate(outlineOffset);
1661     outlineBoxRect.moveBy(paintOffset);
1662     if (outlineBoxRect.isEmpty())
1663         return;
1664
1665     float outlineWidth = styleToUse.outlineWidth();
1666     EBorderStyle outlineStyle = styleToUse.outlineStyle();
1667     bool antialias = shouldAntialiasLines(graphicsContext);
1668
1669     auto adjustedPreviousLine = previousLine;
1670     adjustedPreviousLine.moveBy(paintOffset);
1671     auto adjustedNextLine = nextLine;
1672     adjustedNextLine.moveBy(paintOffset);
1673     
1674     float adjacentWidth1 = 0;
1675     float adjacentWidth2 = 0;
1676     // left edge
1677     auto topLeft = outlineBoxRect.minXMinYCorner();
1678     if (previousLine.isEmpty() || thisLine.x() < previousLine.x() || (previousLine.maxX()) <= thisLine.x()) {
1679         topLeft.move(-outlineWidth, -outlineWidth);
1680         adjacentWidth1 = outlineWidth;
1681     } else {
1682         topLeft.move(-outlineWidth, 2 * outlineOffset);
1683         adjacentWidth1 = -outlineWidth;
1684     }
1685     auto bottomRight = outlineBoxRect.minXMaxYCorner();
1686     if (nextLine.isEmpty() || thisLine.x() <= nextLine.x() || (nextLine.maxX()) <= thisLine.x()) {
1687         bottomRight.move(0, outlineWidth);
1688         adjacentWidth2 = outlineWidth;
1689     } else {
1690         bottomRight.move(0, -2 * outlineOffset);
1691         adjacentWidth2 = -outlineWidth;
1692     }
1693     drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSLeft, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
1694     
1695     // right edge
1696     topLeft = outlineBoxRect.maxXMinYCorner();
1697     if (previousLine.isEmpty() || previousLine.maxX() < thisLine.maxX() || thisLine.maxX() <= previousLine.x()) {
1698         topLeft.move(0, -outlineWidth);
1699         adjacentWidth1 = outlineWidth;
1700     } else {
1701         topLeft.move(0, 2 * outlineOffset);
1702         adjacentWidth1 = -outlineWidth;
1703     }
1704     bottomRight = outlineBoxRect.maxXMaxYCorner();
1705     if (nextLine.isEmpty() || nextLine.maxX() <= thisLine.maxX() || thisLine.maxX() <= nextLine.x()) {
1706         bottomRight.move(outlineWidth, outlineWidth);
1707         adjacentWidth2 = outlineWidth;
1708     } else {
1709         bottomRight.move(outlineWidth, -2 * outlineOffset);
1710         adjacentWidth2 = -outlineWidth;
1711     }
1712     drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSRight, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
1713
1714     // upper edge
1715     if (thisLine.x() < previousLine.x()) {
1716         topLeft = outlineBoxRect.minXMinYCorner();
1717         topLeft.move(-outlineWidth, -outlineWidth);
1718         adjacentWidth1 = outlineWidth;
1719         bottomRight = outlineBoxRect.maxXMinYCorner();
1720         bottomRight.move(outlineWidth, 0);
1721         if (!previousLine.isEmpty() && adjustedPreviousLine.x() < bottomRight.x()) {
1722             bottomRight.setX(adjustedPreviousLine.x() - outlineOffset);
1723             adjacentWidth2 = -outlineWidth;
1724         } else
1725             adjacentWidth2 = outlineWidth;
1726         drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSTop, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
1727     }
1728     
1729     if (previousLine.maxX() < thisLine.maxX()) {
1730         topLeft = outlineBoxRect.minXMinYCorner();
1731         topLeft.move(-outlineWidth, -outlineWidth);
1732         if (!previousLine.isEmpty() && adjustedPreviousLine.maxX() > topLeft.x()) {
1733             topLeft.setX(adjustedPreviousLine.maxX() + outlineOffset);
1734             adjacentWidth1 = -outlineWidth;
1735         } else
1736             adjacentWidth1 = outlineWidth;
1737         bottomRight = outlineBoxRect.maxXMinYCorner();
1738         bottomRight.move(outlineWidth, 0);
1739         adjacentWidth2 = outlineWidth;
1740         drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSTop, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
1741     }
1742
1743     if (thisLine.x() == thisLine.maxX()) {
1744         topLeft = outlineBoxRect.minXMinYCorner();
1745         topLeft.move(-outlineWidth, -outlineWidth);
1746         adjacentWidth1 = outlineWidth;
1747         bottomRight = outlineBoxRect.maxXMinYCorner();
1748         bottomRight.move(outlineWidth, 0);
1749         adjacentWidth2 = outlineWidth;
1750         drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSTop, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
1751     }
1752
1753     // lower edge
1754     if (thisLine.x() < nextLine.x()) {
1755         topLeft = outlineBoxRect.minXMaxYCorner();
1756         topLeft.move(-outlineWidth, 0);
1757         adjacentWidth1 = outlineWidth;
1758         bottomRight = outlineBoxRect.maxXMaxYCorner();
1759         bottomRight.move(outlineWidth, outlineWidth);
1760         if (!nextLine.isEmpty() && (adjustedNextLine.x() < bottomRight.x())) {
1761             bottomRight.setX(adjustedNextLine.x() - outlineOffset);
1762             adjacentWidth2 = -outlineWidth;
1763         } else
1764             adjacentWidth2 = outlineWidth;
1765         drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSBottom, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
1766     }
1767     
1768     if (nextLine.maxX() < thisLine.maxX()) {
1769         topLeft = outlineBoxRect.minXMaxYCorner();
1770         topLeft.move(-outlineWidth, 0);
1771         if (!nextLine.isEmpty() && adjustedNextLine.maxX() > topLeft.x()) {
1772             topLeft.setX(adjustedNextLine.maxX() + outlineOffset);
1773             adjacentWidth1 = -outlineWidth;
1774         } else
1775             adjacentWidth1 = outlineWidth;
1776         bottomRight = outlineBoxRect.maxXMaxYCorner();
1777         bottomRight.move(outlineWidth, outlineWidth);
1778         adjacentWidth2 = outlineWidth;
1779         drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSBottom, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
1780     }
1781
1782     if (thisLine.x() == thisLine.maxX()) {
1783         topLeft = outlineBoxRect.minXMaxYCorner();
1784         topLeft.move(-outlineWidth, 0);
1785         adjacentWidth1 = outlineWidth;
1786         bottomRight = outlineBoxRect.maxXMaxYCorner();
1787         bottomRight.move(outlineWidth, outlineWidth);
1788         adjacentWidth2 = outlineWidth;
1789         drawLineForBoxSide(graphicsContext, FloatRect(topLeft, bottomRight), BSBottom, outlineColor, outlineStyle, adjacentWidth1, adjacentWidth2, antialias);
1790     }
1791 }
1792
1793 #if ENABLE(DASHBOARD_SUPPORT)
1794 void RenderInline::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
1795 {
1796     // Convert the style regions to absolute coordinates.
1797     if (style().visibility() != VISIBLE)
1798         return;
1799
1800     const Vector<StyleDashboardRegion>& styleRegions = style().dashboardRegions();
1801     unsigned i, count = styleRegions.size();
1802     for (i = 0; i < count; i++) {
1803         StyleDashboardRegion styleRegion = styleRegions[i];
1804
1805         LayoutRect linesBoundingBox = this->linesBoundingBox();
1806         LayoutUnit w = linesBoundingBox.width();
1807         LayoutUnit h = linesBoundingBox.height();
1808
1809         AnnotatedRegionValue region;
1810         region.label = styleRegion.label;
1811         region.bounds = LayoutRect(linesBoundingBox.x() + styleRegion.offset.left().value(),
1812                                 linesBoundingBox.y() + styleRegion.offset.top().value(),
1813                                 w - styleRegion.offset.left().value() - styleRegion.offset.right().value(),
1814                                 h - styleRegion.offset.top().value() - styleRegion.offset.bottom().value());
1815         region.type = styleRegion.type;
1816
1817         RenderObject* container = containingBlock();
1818         if (!container)
1819             container = this;
1820
1821         region.clip = container->computeAbsoluteRepaintRect(region.bounds);
1822         if (region.clip.height() < 0) {
1823             region.clip.setHeight(0);
1824             region.clip.setWidth(0);
1825         }
1826
1827         FloatPoint absPos = container->localToAbsolute();
1828         region.bounds.setX(absPos.x() + region.bounds.x());
1829         region.bounds.setY(absPos.y() + region.bounds.y());
1830
1831         regions.append(region);
1832     }
1833 }
1834 #endif
1835
1836 } // namespace WebCore