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