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