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