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