Update To 11.40.268.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     setHasTransformRelatedProperty(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     if (isAnonymous())
776         return "RenderInline (generated)";
777     return "RenderInline";
778 }
779
780 bool RenderInline::nodeAtPoint(const HitTestRequest& request, HitTestResult& result,
781                                 const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
782 {
783     return m_lineBoxes.hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction);
784 }
785
786 namespace {
787
788 class HitTestCulledInlinesGeneratorContext {
789 public:
790     HitTestCulledInlinesGeneratorContext(Region& region, const HitTestLocation& location) : m_intersected(false), m_region(region), m_location(location) { }
791     void operator()(const FloatRect& rect)
792     {
793         m_intersected = m_intersected || m_location.intersects(rect);
794         m_region.unite(enclosingIntRect(rect));
795     }
796     bool intersected() const { return m_intersected; }
797 private:
798     bool m_intersected;
799     Region& m_region;
800     const HitTestLocation& m_location;
801 };
802
803 } // unnamed namespace
804
805 bool RenderInline::hitTestCulledInline(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset)
806 {
807     ASSERT(result.isRectBasedTest() && !alwaysCreateLineBoxes());
808     if (!visibleToHitTestRequest(request))
809         return false;
810
811     HitTestLocation tmpLocation(locationInContainer, -toLayoutSize(accumulatedOffset));
812
813     Region regionResult;
814     HitTestCulledInlinesGeneratorContext context(regionResult, tmpLocation);
815     generateCulledLineBoxRects(context, this);
816
817     if (context.intersected()) {
818         updateHitTestResult(result, tmpLocation.point());
819         // We can not use addNodeToRectBasedTestResult to determine if we fully enclose the hit-test area
820         // because it can only handle rectangular targets.
821         result.addNodeToRectBasedTestResult(node(), request, locationInContainer);
822         return regionResult.contains(tmpLocation.boundingBox());
823     }
824     return false;
825 }
826
827 PositionWithAffinity RenderInline::positionForPoint(const LayoutPoint& point)
828 {
829     // FIXME: Does not deal with relative positioned inlines (should it?)
830     RenderBlock* cb = containingBlock();
831     if (firstLineBox()) {
832         // This inline actually has a line box.  We must have clicked in the border/padding of one of these boxes.  We
833         // should try to find a result by asking our containing block.
834         return cb->positionForPoint(point);
835     }
836
837     // Translate the coords from the pre-anonymous block to the post-anonymous block.
838     LayoutPoint parentBlockPoint = cb->location() + point;
839     RenderBoxModelObject* c = continuation();
840     while (c) {
841         RenderBox* contBlock = c->isInline() ? c->containingBlock() : toRenderBlock(c);
842         if (c->isInline() || c->slowFirstChild())
843             return c->positionForPoint(parentBlockPoint - contBlock->locationOffset());
844         c = toRenderBlock(c)->inlineElementContinuation();
845     }
846
847     return RenderBoxModelObject::positionForPoint(point);
848 }
849
850 namespace {
851
852 class LinesBoundingBoxGeneratorContext {
853 public:
854     LinesBoundingBoxGeneratorContext(FloatRect& rect) : m_rect(rect) { }
855     void operator()(const FloatRect& rect)
856     {
857         m_rect.uniteIfNonZero(rect);
858     }
859 private:
860     FloatRect& m_rect;
861 };
862
863 } // unnamed namespace
864
865 IntRect RenderInline::linesBoundingBox() const
866 {
867     if (!alwaysCreateLineBoxes()) {
868         ASSERT(!firstLineBox());
869         FloatRect floatResult;
870         LinesBoundingBoxGeneratorContext context(floatResult);
871         generateCulledLineBoxRects(context, this);
872         return enclosingIntRect(floatResult);
873     }
874
875     IntRect result;
876
877     // 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
878     // 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
879     // builds and help us someday figure out why.  We also put in a redundant check of lastLineBox() to avoid the crash for now.
880     ASSERT(!firstLineBox() == !lastLineBox());  // Either both are null or both exist.
881     if (firstLineBox() && lastLineBox()) {
882         // Return the width of the minimal left side and the maximal right side.
883         float logicalLeftSide = 0;
884         float logicalRightSide = 0;
885         for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
886             if (curr == firstLineBox() || curr->logicalLeft() < logicalLeftSide)
887                 logicalLeftSide = curr->logicalLeft();
888             if (curr == firstLineBox() || curr->logicalRight() > logicalRightSide)
889                 logicalRightSide = curr->logicalRight();
890         }
891
892         bool isHorizontal = style()->isHorizontalWritingMode();
893
894         float x = isHorizontal ? logicalLeftSide : firstLineBox()->x();
895         float y = isHorizontal ? firstLineBox()->y() : logicalLeftSide;
896         float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastLineBox()->logicalBottom() - x;
897         float height = isHorizontal ? lastLineBox()->logicalBottom() - y : logicalRightSide - logicalLeftSide;
898         result = enclosingIntRect(FloatRect(x, y, width, height));
899     }
900
901     return result;
902 }
903
904 InlineBox* RenderInline::culledInlineFirstLineBox() const
905 {
906     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
907         if (curr->isFloatingOrOutOfFlowPositioned())
908             continue;
909
910         // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
911         // direction (aligned to the root box's baseline).
912         if (curr->isBox())
913             return toRenderBox(curr)->inlineBoxWrapper();
914         if (curr->isRenderInline()) {
915             RenderInline* currInline = toRenderInline(curr);
916             InlineBox* result = currInline->firstLineBoxIncludingCulling();
917             if (result)
918                 return result;
919         } else if (curr->isText()) {
920             RenderText* currText = toRenderText(curr);
921             if (currText->firstTextBox())
922                 return currText->firstTextBox();
923         }
924     }
925     return 0;
926 }
927
928 InlineBox* RenderInline::culledInlineLastLineBox() const
929 {
930     for (RenderObject* curr = lastChild(); curr; curr = curr->previousSibling()) {
931         if (curr->isFloatingOrOutOfFlowPositioned())
932             continue;
933
934         // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
935         // direction (aligned to the root box's baseline).
936         if (curr->isBox())
937             return toRenderBox(curr)->inlineBoxWrapper();
938         if (curr->isRenderInline()) {
939             RenderInline* currInline = toRenderInline(curr);
940             InlineBox* result = currInline->lastLineBoxIncludingCulling();
941             if (result)
942                 return result;
943         } else if (curr->isText()) {
944             RenderText* currText = toRenderText(curr);
945             if (currText->lastTextBox())
946                 return currText->lastTextBox();
947         }
948     }
949     return 0;
950 }
951
952 LayoutRect RenderInline::culledInlineVisualOverflowBoundingBox() const
953 {
954     FloatRect floatResult;
955     LinesBoundingBoxGeneratorContext context(floatResult);
956     generateCulledLineBoxRects(context, this);
957     LayoutRect result(enclosingLayoutRect(floatResult));
958     bool isHorizontal = style()->isHorizontalWritingMode();
959     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
960         if (curr->isFloatingOrOutOfFlowPositioned())
961             continue;
962
963         // For overflow we just have to propagate by hand and recompute it all.
964         if (curr->isBox()) {
965             RenderBox* currBox = toRenderBox(curr);
966             if (!currBox->hasSelfPaintingLayer() && currBox->inlineBoxWrapper()) {
967                 LayoutRect logicalRect = currBox->logicalVisualOverflowRectForPropagation(style());
968                 if (isHorizontal) {
969                     logicalRect.moveBy(currBox->location());
970                     result.uniteIfNonZero(logicalRect);
971                 } else {
972                     logicalRect.moveBy(currBox->location());
973                     result.uniteIfNonZero(logicalRect.transposedRect());
974                 }
975             }
976         } else if (curr->isRenderInline()) {
977             // If the child doesn't need line boxes either, then we can recur.
978             RenderInline* currInline = toRenderInline(curr);
979             if (!currInline->alwaysCreateLineBoxes())
980                 result.uniteIfNonZero(currInline->culledInlineVisualOverflowBoundingBox());
981             else if (!currInline->hasSelfPaintingLayer())
982                 result.uniteIfNonZero(currInline->linesVisualOverflowBoundingBox());
983         } else if (curr->isText()) {
984             // FIXME; Overflow from text boxes is lost. We will need to cache this information in
985             // InlineTextBoxes.
986             RenderText* currText = toRenderText(curr);
987             result.uniteIfNonZero(currText->linesVisualOverflowBoundingBox());
988         }
989     }
990     return result;
991 }
992
993 LayoutRect RenderInline::linesVisualOverflowBoundingBox() const
994 {
995     if (!alwaysCreateLineBoxes())
996         return culledInlineVisualOverflowBoundingBox();
997
998     if (!firstLineBox() || !lastLineBox())
999         return LayoutRect();
1000
1001     // Return the width of the minimal left side and the maximal right side.
1002     LayoutUnit logicalLeftSide = LayoutUnit::max();
1003     LayoutUnit logicalRightSide = LayoutUnit::min();
1004     for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
1005         logicalLeftSide = std::min(logicalLeftSide, curr->logicalLeftVisualOverflow());
1006         logicalRightSide = std::max(logicalRightSide, curr->logicalRightVisualOverflow());
1007     }
1008
1009     RootInlineBox& firstRootBox = firstLineBox()->root();
1010     RootInlineBox& lastRootBox = lastLineBox()->root();
1011
1012     LayoutUnit logicalTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox.lineTop());
1013     LayoutUnit logicalWidth = logicalRightSide - logicalLeftSide;
1014     LayoutUnit logicalHeight = lastLineBox()->logicalBottomVisualOverflow(lastRootBox.lineBottom()) - logicalTop;
1015
1016     LayoutRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
1017     if (!style()->isHorizontalWritingMode())
1018         rect = rect.transposedRect();
1019     return rect;
1020 }
1021
1022 LayoutRect RenderInline::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const
1023 {
1024     if ((!firstLineBoxIncludingCulling() && !continuation()) || style()->visibility() != VISIBLE)
1025         return LayoutRect();
1026
1027     LayoutRect paintInvalidationRect(linesVisualOverflowBoundingBox());
1028
1029     LayoutUnit outlineSize = style()->outlineSize();
1030     paintInvalidationRect.inflate(outlineSize);
1031
1032     mapRectToPaintInvalidationBacking(paintInvalidationContainer, paintInvalidationRect, paintInvalidationState);
1033
1034     if (outlineSize) {
1035         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
1036             if (!curr->isText())
1037                 paintInvalidationRect.unite(curr->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineSize));
1038         }
1039
1040         if (continuation() && !continuation()->isInline() && continuation()->parent())
1041             paintInvalidationRect.unite(continuation()->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineSize));
1042     }
1043
1044     return paintInvalidationRect;
1045 }
1046
1047 LayoutRect RenderInline::rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth, const PaintInvalidationState* paintInvalidationState) const
1048 {
1049     LayoutRect r(RenderBoxModelObject::rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineWidth, paintInvalidationState));
1050     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
1051         if (!curr->isText())
1052             r.unite(curr->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineWidth, paintInvalidationState));
1053     }
1054     return r;
1055 }
1056
1057 void RenderInline::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect, const PaintInvalidationState* paintInvalidationState) const
1058 {
1059     if (paintInvalidationState && paintInvalidationState->canMapToContainer(paintInvalidationContainer)) {
1060         if (style()->hasInFlowPosition() && layer())
1061             rect.move(layer()->offsetForInFlowPosition());
1062         rect.move(paintInvalidationState->paintOffset());
1063         if (paintInvalidationState->isClipped())
1064             rect.intersect(paintInvalidationState->clipRect());
1065         return;
1066     }
1067
1068     if (paintInvalidationContainer == this)
1069         return;
1070
1071     bool containerSkipped;
1072     RenderObject* o = container(paintInvalidationContainer, &containerSkipped);
1073     if (!o)
1074         return;
1075
1076     LayoutPoint topLeft = rect.location();
1077
1078     if (o->isRenderBlockFlow() && !style()->hasOutOfFlowPosition()) {
1079         RenderBlock* cb = toRenderBlock(o);
1080         if (cb->hasColumns()) {
1081             LayoutRect paintInvalidationRect(topLeft, rect.size());
1082             cb->adjustRectForColumns(paintInvalidationRect);
1083             topLeft = paintInvalidationRect.location();
1084             rect = paintInvalidationRect;
1085         }
1086     }
1087
1088     if (style()->hasInFlowPosition() && layer()) {
1089         // Apply the in-flow position offset when invalidating a rectangle. The layer
1090         // is translated, but the render box isn't, so we need to do this to get the
1091         // right dirty rect. Since this is called from RenderObject::setStyle, the relative position
1092         // flag on the RenderObject has been cleared, so use the one on the style().
1093         topLeft += layer()->offsetForInFlowPosition();
1094     }
1095
1096     // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
1097     // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
1098     rect.setLocation(topLeft);
1099     if (o->hasOverflowClip()) {
1100         RenderBox* containerBox = toRenderBox(o);
1101         containerBox->applyCachedClipAndScrollOffsetForPaintInvalidation(rect);
1102         if (rect.isEmpty())
1103             return;
1104     }
1105
1106     if (containerSkipped) {
1107         // If the paintInvalidationContainer is below o, then we need to map the rect into paintInvalidationContainer's coordinates.
1108         LayoutSize containerOffset = paintInvalidationContainer->offsetFromAncestorContainer(o);
1109         rect.move(-containerOffset);
1110         return;
1111     }
1112
1113     o->mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, paintInvalidationState);
1114 }
1115
1116 LayoutSize RenderInline::offsetFromContainer(const RenderObject* container, const LayoutPoint& point, bool* offsetDependsOnPoint) const
1117 {
1118     ASSERT(container == this->container());
1119
1120     LayoutSize offset;
1121     if (isRelPositioned())
1122         offset += offsetForInFlowPosition();
1123
1124     offset += container->columnOffset(point);
1125
1126     if (container->hasOverflowClip())
1127         offset -= toRenderBox(container)->scrolledContentOffset();
1128
1129     if (offsetDependsOnPoint) {
1130         *offsetDependsOnPoint = container->hasColumns()
1131             || (container->isBox() && container->style()->slowIsFlippedBlocksWritingMode())
1132             || container->isRenderFlowThread();
1133     }
1134
1135     return offset;
1136 }
1137
1138 void RenderInline::mapLocalToContainer(const RenderLayerModelObject* paintInvalidationContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const
1139 {
1140     if (paintInvalidationContainer == this)
1141         return;
1142
1143     if (paintInvalidationState && paintInvalidationState->canMapToContainer(paintInvalidationContainer)) {
1144         LayoutSize offset = paintInvalidationState->paintOffset();
1145         if (style()->hasInFlowPosition() && layer())
1146             offset += layer()->offsetForInFlowPosition();
1147         transformState.move(offset);
1148         return;
1149     }
1150
1151     bool containerSkipped;
1152     RenderObject* o = container(paintInvalidationContainer, &containerSkipped);
1153     if (!o)
1154         return;
1155
1156     if (mode & ApplyContainerFlip && o->isBox()) {
1157         if (o->style()->slowIsFlippedBlocksWritingMode()) {
1158             IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint());
1159             transformState.move(toRenderBox(o)->flipForWritingModeIncludingColumns(centerPoint) - centerPoint);
1160         }
1161         mode &= ~ApplyContainerFlip;
1162     }
1163
1164     LayoutSize containerOffset = offsetFromContainer(o, roundedLayoutPoint(transformState.mappedPoint()));
1165
1166     bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || style()->preserves3D());
1167     if (mode & UseTransforms && shouldUseTransformFromContainer(o)) {
1168         TransformationMatrix t;
1169         getTransformFromContainer(o, containerOffset, t);
1170         transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1171     } else
1172         transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1173
1174     if (containerSkipped) {
1175         // There can't be a transform between paintInvalidationContainer and o, because transforms create containers, so it should be safe
1176         // to just subtract the delta between the paintInvalidationContainer and o.
1177         LayoutSize containerOffset = paintInvalidationContainer->offsetFromAncestorContainer(o);
1178         transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1179         return;
1180     }
1181
1182     o->mapLocalToContainer(paintInvalidationContainer, transformState, mode, wasFixed, paintInvalidationState);
1183 }
1184
1185 void RenderInline::updateDragState(bool dragOn)
1186 {
1187     RenderBoxModelObject::updateDragState(dragOn);
1188     if (continuation())
1189         continuation()->updateDragState(dragOn);
1190 }
1191
1192 void RenderInline::childBecameNonInline(RenderObject* child)
1193 {
1194     // We have to split the parent flow.
1195     RenderBlock* newBox = containingBlock()->createAnonymousBlock();
1196     RenderBoxModelObject* oldContinuation = continuation();
1197     setContinuation(newBox);
1198     RenderObject* beforeChild = child->nextSibling();
1199     children()->removeChildNode(this, child);
1200     splitFlow(beforeChild, newBox, child, oldContinuation);
1201 }
1202
1203 void RenderInline::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
1204 {
1205     if (result.innerNode())
1206         return;
1207
1208     Node* n = node();
1209     LayoutPoint localPoint(point);
1210     if (n) {
1211         if (isInlineElementContinuation()) {
1212             // We're in the continuation of a split inline.  Adjust our local point to be in the coordinate space
1213             // of the principal renderer's containing block.  This will end up being the innerNonSharedNode.
1214             RenderBlock* firstBlock = n->renderer()->containingBlock();
1215
1216             // Get our containing block.
1217             RenderBox* block = containingBlock();
1218             localPoint.moveBy(block->location() - firstBlock->locationOffset());
1219         }
1220
1221         result.setInnerNode(n);
1222         if (!result.innerNonSharedNode())
1223             result.setInnerNonSharedNode(n);
1224         result.setLocalPoint(localPoint);
1225     }
1226 }
1227
1228 void RenderInline::dirtyLineBoxes(bool fullLayout)
1229 {
1230     if (fullLayout) {
1231         m_lineBoxes.deleteLineBoxes();
1232         return;
1233     }
1234
1235     if (!alwaysCreateLineBoxes()) {
1236         // We have to grovel into our children in order to dirty the appropriate lines.
1237         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
1238             if (curr->isFloatingOrOutOfFlowPositioned())
1239                 continue;
1240             if (curr->isBox() && !curr->needsLayout()) {
1241                 RenderBox* currBox = toRenderBox(curr);
1242                 if (currBox->inlineBoxWrapper())
1243                     currBox->inlineBoxWrapper()->root().markDirty();
1244             } else if (!curr->selfNeedsLayout()) {
1245                 if (curr->isRenderInline()) {
1246                     RenderInline* currInline = toRenderInline(curr);
1247                     for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox())
1248                         childLine->root().markDirty();
1249                 } else if (curr->isText()) {
1250                     RenderText* currText = toRenderText(curr);
1251                     for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox())
1252                         childText->root().markDirty();
1253                 }
1254             }
1255         }
1256     } else
1257         m_lineBoxes.dirtyLineBoxes();
1258 }
1259
1260 InlineFlowBox* RenderInline::createInlineFlowBox()
1261 {
1262     return new InlineFlowBox(*this);
1263 }
1264
1265 InlineFlowBox* RenderInline::createAndAppendInlineFlowBox()
1266 {
1267     setAlwaysCreateLineBoxes();
1268     InlineFlowBox* flowBox = createInlineFlowBox();
1269     m_lineBoxes.appendLineBox(flowBox);
1270     return flowBox;
1271 }
1272
1273 LayoutUnit RenderInline::lineHeight(bool firstLine, LineDirectionMode /*direction*/, LinePositionMode /*linePositionMode*/) const
1274 {
1275     if (firstLine && document().styleEngine()->usesFirstLineRules()) {
1276         RenderStyle* s = style(firstLine);
1277         if (s != style())
1278             return s->computedLineHeight();
1279     }
1280
1281     return style()->computedLineHeight();
1282 }
1283
1284 int RenderInline::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
1285 {
1286     ASSERT(linePositionMode == PositionOnContainingLine);
1287     const FontMetrics& fontMetrics = style(firstLine)->fontMetrics();
1288     return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
1289 }
1290
1291 LayoutSize RenderInline::offsetForInFlowPositionedInline(const RenderBox& child) const
1292 {
1293     // FIXME: This function isn't right with mixed writing modes.
1294
1295     ASSERT(isRelPositioned());
1296     if (!isRelPositioned())
1297         return LayoutSize();
1298
1299     // When we have an enclosing relpositioned inline, we need to add in the offset of the first line
1300     // box from the rest of the content, but only in the cases where we know we're positioned
1301     // relative to the inline itself.
1302
1303     LayoutSize logicalOffset;
1304     LayoutUnit inlinePosition;
1305     LayoutUnit blockPosition;
1306     if (firstLineBox()) {
1307         inlinePosition = LayoutUnit::fromFloatRound(firstLineBox()->logicalLeft());
1308         blockPosition = firstLineBox()->logicalTop();
1309     } else {
1310         inlinePosition = layer()->staticInlinePosition();
1311         blockPosition = layer()->staticBlockPosition();
1312     }
1313
1314     // Per http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width an absolute positioned box
1315     // with a static position should locate itself as though it is a normal flow box in relation to
1316     // its containing block. If this relative-positioned inline has a negative offset we need to
1317     // compensate for it so that we align the positioned object with the edge of its containing block.
1318     if (child.style()->hasStaticInlinePosition(style()->isHorizontalWritingMode()))
1319         logicalOffset.setWidth(std::max(LayoutUnit(), -offsetForInFlowPosition().width()));
1320     else
1321         logicalOffset.setWidth(inlinePosition);
1322
1323     if (!child.style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
1324         logicalOffset.setHeight(blockPosition);
1325
1326     return style()->isHorizontalWritingMode() ? logicalOffset : logicalOffset.transposedSize();
1327 }
1328
1329 void RenderInline::imageChanged(WrappedImagePtr, const IntRect*)
1330 {
1331     if (!parent())
1332         return;
1333
1334     // FIXME: We can do better.
1335     setShouldDoFullPaintInvalidation();
1336 }
1337
1338 namespace {
1339
1340 class AbsoluteLayoutRectsGeneratorContext {
1341 public:
1342     AbsoluteLayoutRectsGeneratorContext(Vector<LayoutRect>& rects, const LayoutPoint& accumulatedOffset)
1343         : m_rects(rects)
1344         , m_accumulatedOffset(accumulatedOffset) { }
1345
1346     void operator()(const FloatRect& rect)
1347     {
1348         LayoutRect layoutRect(rect);
1349         layoutRect.move(m_accumulatedOffset.x(), m_accumulatedOffset.y());
1350         m_rects.append(layoutRect);
1351     }
1352 private:
1353     Vector<LayoutRect>& m_rects;
1354     const LayoutPoint& m_accumulatedOffset;
1355 };
1356
1357 class AbsoluteLayoutRectsIgnoringEmptyRectsGeneratorContext : public AbsoluteLayoutRectsGeneratorContext {
1358 public:
1359     AbsoluteLayoutRectsIgnoringEmptyRectsGeneratorContext(Vector<LayoutRect>& rects, const LayoutPoint& accumulatedOffset)
1360         : AbsoluteLayoutRectsGeneratorContext(rects, accumulatedOffset) { }
1361
1362     void operator()(const FloatRect& rect)
1363     {
1364         if (!rect.isEmpty())
1365             AbsoluteLayoutRectsGeneratorContext::operator()(rect);
1366     }
1367 };
1368
1369 } // unnamed namespace
1370
1371 void RenderInline::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer) const
1372 {
1373     AbsoluteLayoutRectsIgnoringEmptyRectsGeneratorContext context(rects, additionalOffset);
1374     generateLineBoxRects(context);
1375
1376     addChildFocusRingRects(rects, additionalOffset, paintContainer);
1377
1378     if (continuation()) {
1379         // If the continuation doesn't paint into the same container, let its paint invalidation container handle it.
1380         if (paintContainer != continuation()->containerForPaintInvalidation())
1381             return;
1382         if (continuation()->isInline())
1383             continuation()->addFocusRingRects(rects, additionalOffset + (continuation()->containingBlock()->location() - containingBlock()->location()), paintContainer);
1384         else
1385             continuation()->addFocusRingRects(rects, additionalOffset + (toRenderBox(continuation())->location() - containingBlock()->location()), paintContainer);
1386     }
1387 }
1388
1389 void RenderInline::computeSelfHitTestRects(Vector<LayoutRect>& rects, const LayoutPoint& layerOffset) const
1390 {
1391     AbsoluteLayoutRectsGeneratorContext context(rects, layerOffset);
1392     generateLineBoxRects(context);
1393 }
1394
1395 void RenderInline::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
1396 {
1397     // Convert the style regions to absolute coordinates.
1398     if (style()->visibility() != VISIBLE)
1399         return;
1400
1401     if (style()->getDraggableRegionMode() == DraggableRegionNone)
1402         return;
1403
1404     AnnotatedRegionValue region;
1405     region.draggable = style()->getDraggableRegionMode() == DraggableRegionDrag;
1406     region.bounds = linesBoundingBox();
1407
1408     RenderObject* container = containingBlock();
1409     if (!container)
1410         container = this;
1411
1412     FloatPoint absPos = container->localToAbsolute();
1413     region.bounds.setX(absPos.x() + region.bounds.x());
1414     region.bounds.setY(absPos.y() + region.bounds.y());
1415
1416     regions.append(region);
1417 }
1418
1419 } // namespace blink