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