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