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