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