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