c9a4eb29f11b395d01e2dc9ddac4fe7249509f86
[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 FrameSelection 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 (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, const LayoutPoint& paintOffset)
464 {
465     m_lineBoxes.paint(this, paintInfo, paintOffset);
466 }
467
468 void RenderInline::absoluteRects(Vector<LayoutRect>& rects, const LayoutPoint& accumulatedOffset)
469 {
470     if (!alwaysCreateLineBoxes())
471         culledInlineAbsoluteRects(this, rects, toLayoutSize(accumulatedOffset));
472     else if (InlineFlowBox* curr = firstLineBox()) {
473         for (; curr; curr = curr->nextLineBox())
474             rects.append(enclosingLayoutRect(FloatRect(accumulatedOffset + curr->topLeft(), curr->size())));
475     } else
476         rects.append(LayoutRect(accumulatedOffset, LayoutSize()));
477
478     if (continuation()) {
479         if (continuation()->isBox()) {
480             RenderBox* box = toRenderBox(continuation());
481             continuation()->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location() + box->size()));
482         } else
483             continuation()->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location()));
484     }
485 }
486
487 void RenderInline::culledInlineAbsoluteRects(const RenderInline* container, Vector<IntRect>& rects, const IntSize& offset)
488 {
489     bool isHorizontal = style()->isHorizontalWritingMode();
490     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
491         if (curr->isFloatingOrPositioned())
492             continue;
493             
494         // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
495         // direction (aligned to the root box's baseline).
496         if (curr->isBox()) {
497             RenderBox* currBox = toRenderBox(curr);
498             if (currBox->inlineBoxWrapper()) {
499                 RootInlineBox* rootBox = currBox->inlineBoxWrapper()->root();
500                 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
501                 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
502                 FloatRect result;
503                 if (isHorizontal)
504                     result = FloatRect(offset.width() + currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), offset.height() + logicalTop, currBox->width() + currBox->marginLeft() + currBox->marginRight(), logicalHeight);
505                 else
506                     result = FloatRect(offset.width() + logicalTop, offset.height() + currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginTop() + currBox->marginBottom());
507                 rects.append(enclosingIntRect(result));
508             }
509         } else if (curr->isRenderInline()) {
510             // If the child doesn't need line boxes either, then we can recur.
511             RenderInline* currInline = toRenderInline(curr);
512             if (!currInline->alwaysCreateLineBoxes())
513                 currInline->culledInlineAbsoluteRects(container, rects, offset);
514             else {
515                 for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
516                     RootInlineBox* rootBox = childLine->root();
517                     int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
518                     int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
519                     FloatRect result;
520                     if (isHorizontal)
521                         result = FloatRect(offset.width() + childLine->x() - childLine->marginLogicalLeft(),
522                             offset.height() + logicalTop,
523                             childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(),
524                             logicalHeight);
525                     else
526                         result = FloatRect(offset.width() + logicalTop,
527                             offset.height() + childLine->y() - childLine->marginLogicalLeft(),
528                             logicalHeight,
529                             childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight());
530                     rects.append(enclosingIntRect(result));
531                 }
532             }
533         } else if (curr->isText()) {
534             RenderText* currText = toRenderText(curr);
535             for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) {
536                 RootInlineBox* rootBox = childText->root();
537                 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
538                 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
539                 FloatRect result;
540                 if (isHorizontal)
541                     result = FloatRect(offset.width() + childText->x(), offset.height() + logicalTop, childText->logicalWidth(), logicalHeight);
542                 else
543                     result = FloatRect(offset.width() + logicalTop, offset.height() + childText->y(), logicalHeight, childText->logicalWidth());
544                 rects.append(enclosingIntRect(result));
545             }
546         }
547     }
548 }
549
550 void RenderInline::absoluteQuads(Vector<FloatQuad>& quads)
551 {
552     if (!alwaysCreateLineBoxes())
553         culledInlineAbsoluteQuads(this, quads);
554     else if (InlineFlowBox* curr = firstLineBox()) {
555         for (; curr; curr = curr->nextLineBox()) {
556             FloatRect localRect(curr->x(), curr->y(), curr->width(), curr->height());
557             quads.append(localToAbsoluteQuad(localRect));
558         }
559     } else
560         quads.append(localToAbsoluteQuad(FloatRect()));
561
562     if (continuation())
563         continuation()->absoluteQuads(quads);
564 }
565
566 void RenderInline::culledInlineAbsoluteQuads(const RenderInline* container, Vector<FloatQuad>& quads)
567 {
568     if (!culledInlineFirstLineBox()) {
569         quads.append(localToAbsoluteQuad(FloatRect()));
570         return;
571     }
572
573     bool isHorizontal = style()->isHorizontalWritingMode();
574     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
575         if (curr->isFloatingOrPositioned())
576             continue;
577             
578         // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
579         // direction (aligned to the root box's baseline).
580         if (curr->isBox()) {
581             RenderBox* currBox = toRenderBox(curr);
582             if (currBox->inlineBoxWrapper()) {
583                 RootInlineBox* rootBox = currBox->inlineBoxWrapper()->root();
584                 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
585                 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
586                 FloatRect result;
587                 if (isHorizontal)
588                     result = FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, currBox->width() + currBox->marginLeft() + currBox->marginRight(), logicalHeight);
589                 else
590                     result = FloatRect(logicalTop, currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginTop() + currBox->marginBottom());
591                 quads.append(localToAbsoluteQuad(result));
592             }
593         } else if (curr->isRenderInline()) {
594             // If the child doesn't need line boxes either, then we can recur.
595             RenderInline* currInline = toRenderInline(curr);
596             if (!currInline->alwaysCreateLineBoxes())
597                 currInline->culledInlineAbsoluteQuads(container, quads);
598             else {
599                 for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
600                     RootInlineBox* rootBox = childLine->root();
601                     int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
602                     int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
603                     FloatRect result;
604                     if (isHorizontal)
605                         result = FloatRect(childLine->x() - childLine->marginLogicalLeft(),
606                             logicalTop,
607                             childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(),
608                             logicalHeight);
609                     else
610                         result = FloatRect(logicalTop,
611                             childLine->y() - childLine->marginLogicalLeft(),
612                             logicalHeight,
613                             childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight());
614                     quads.append(localToAbsoluteQuad(result));
615                 }
616             }
617         } else if (curr->isText()) {
618             RenderText* currText = toRenderText(curr);
619             for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) {
620                 RootInlineBox* rootBox = childText->root();
621                 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
622                 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
623                 FloatRect result;
624                 if (isHorizontal)
625                     result = FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight);
626                 else
627                     result = FloatRect(logicalTop, childText->y(), logicalHeight, childText->logicalWidth());
628                 quads.append(localToAbsoluteQuad(result));
629             }
630         }
631     }
632 }
633
634 LayoutUnit RenderInline::offsetLeft() const
635 {
636     LayoutUnit x = RenderBoxModelObject::offsetLeft();
637     if (InlineBox* firstBox = firstLineBoxIncludingCulling())
638         x += firstBox->x();
639     return x;
640 }
641
642 LayoutUnit RenderInline::offsetTop() const
643 {
644     LayoutUnit y = RenderBoxModelObject::offsetTop();
645     if (InlineBox* firstBox = firstLineBoxIncludingCulling())
646         y += firstBox->y();
647     return y;
648 }
649
650 static LayoutUnit computeMargin(const RenderInline* renderer, const Length& margin)
651 {
652     if (margin.isAuto())
653         return 0;
654     if (margin.isFixed())
655         return margin.value();
656     if (margin.isPercent())
657         return margin.calcMinValue(max(0, renderer->containingBlock()->availableLogicalWidth()));
658     return 0;
659 }
660
661 LayoutUnit RenderInline::marginLeft() const
662 {
663     return computeMargin(this, style()->marginLeft());
664 }
665
666 LayoutUnit RenderInline::marginRight() const
667 {
668     return computeMargin(this, style()->marginRight());
669 }
670
671 LayoutUnit RenderInline::marginTop() const
672 {
673     return computeMargin(this, style()->marginTop());
674 }
675
676 LayoutUnit RenderInline::marginBottom() const
677 {
678     return computeMargin(this, style()->marginBottom());
679 }
680
681 LayoutUnit RenderInline::marginStart() const
682 {
683     return computeMargin(this, style()->marginStart());
684 }
685
686 LayoutUnit RenderInline::marginEnd() const
687 {
688     return computeMargin(this, style()->marginEnd());
689 }
690
691 LayoutUnit RenderInline::marginBefore() const
692 {
693     return computeMargin(this, style()->marginBefore());
694 }
695
696 LayoutUnit RenderInline::marginAfter() const
697 {
698     return computeMargin(this, style()->marginAfter());
699 }
700
701 const char* RenderInline::renderName() const
702 {
703     if (isRelPositioned())
704         return "RenderInline (relative positioned)";
705     if (isAnonymous())
706         return "RenderInline (generated)";
707     if (isRunIn())
708         return "RenderInline (run-in)";
709     return "RenderInline";
710 }
711
712 bool RenderInline::nodeAtPoint(const HitTestRequest& request, HitTestResult& result,
713                                 const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
714 {
715     return m_lineBoxes.hitTest(this, request, result, pointInContainer, accumulatedOffset, hitTestAction);
716 }
717
718 VisiblePosition RenderInline::positionForPoint(const LayoutPoint& point)
719 {
720     // FIXME: Does not deal with relative positioned inlines (should it?)
721     RenderBlock* cb = containingBlock();
722     if (firstLineBox()) {
723         // This inline actually has a line box.  We must have clicked in the border/padding of one of these boxes.  We
724         // should try to find a result by asking our containing block.
725         return cb->positionForPoint(point);
726     }
727
728     // Translate the coords from the pre-anonymous block to the post-anonymous block.
729     LayoutPoint parentBlockPoint = cb->location() + point;  
730     RenderBoxModelObject* c = continuation();
731     while (c) {
732         RenderBox* contBlock = c->isInline() ? c->containingBlock() : toRenderBlock(c);
733         if (c->isInline() || c->firstChild())
734             return c->positionForPoint(parentBlockPoint - contBlock->locationOffset());
735         c = toRenderBlock(c)->inlineElementContinuation();
736     }
737     
738     return RenderBoxModelObject::positionForPoint(point);
739 }
740
741 LayoutRect RenderInline::linesBoundingBox() const
742 {
743     if (!alwaysCreateLineBoxes()) {
744         ASSERT(!firstLineBox());
745         return enclosingLayoutRect(culledInlineBoundingBox(this));
746     }
747
748     LayoutRect result;
749     
750     // 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
751     // 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
752     // builds and help us someday figure out why.  We also put in a redundant check of lastLineBox() to avoid the crash for now.
753     ASSERT(!firstLineBox() == !lastLineBox());  // Either both are null or both exist.
754     if (firstLineBox() && lastLineBox()) {
755         // Return the width of the minimal left side and the maximal right side.
756         float logicalLeftSide = 0;
757         float logicalRightSide = 0;
758         for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
759             if (curr == firstLineBox() || curr->logicalLeft() < logicalLeftSide)
760                 logicalLeftSide = curr->logicalLeft();
761             if (curr == firstLineBox() || curr->logicalRight() > logicalRightSide)
762                 logicalRightSide = curr->logicalRight();
763         }
764         
765         bool isHorizontal = style()->isHorizontalWritingMode();
766         
767         float x = isHorizontal ? logicalLeftSide : firstLineBox()->x();
768         float y = isHorizontal ? firstLineBox()->y() : logicalLeftSide;
769         float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastLineBox()->logicalBottom() - x;
770         float height = isHorizontal ? lastLineBox()->logicalBottom() - y : logicalRightSide - logicalLeftSide;
771         result = enclosingLayoutRect(FloatRect(x, y, width, height));
772     }
773
774     return result;
775 }
776
777 FloatRect RenderInline::culledInlineBoundingBox(const RenderInline* container) const
778 {
779     FloatRect result;
780     bool isHorizontal = style()->isHorizontalWritingMode();
781     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
782         if (curr->isFloatingOrPositioned())
783             continue;
784             
785         // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
786         // direction (aligned to the root box's baseline).
787         if (curr->isBox()) {
788             RenderBox* currBox = toRenderBox(curr);
789             if (currBox->inlineBoxWrapper()) {
790                 RootInlineBox* rootBox = currBox->inlineBoxWrapper()->root();
791                 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
792                 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
793                 if (isHorizontal)
794                     result.uniteIfNonZero(FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, currBox->width() + currBox->marginLeft() + currBox->marginRight(), logicalHeight));
795                 else
796                     result.uniteIfNonZero(FloatRect(logicalTop, currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginTop() + currBox->marginBottom()));
797             }
798         } else if (curr->isRenderInline()) {
799             // If the child doesn't need line boxes either, then we can recur.
800             RenderInline* currInline = toRenderInline(curr);
801             if (!currInline->alwaysCreateLineBoxes())
802                 result.uniteIfNonZero(currInline->culledInlineBoundingBox(container));
803             else {
804                 for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
805                     RootInlineBox* rootBox = childLine->root();
806                     int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
807                     int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
808                     if (isHorizontal)
809                         result.uniteIfNonZero(FloatRect(childLine->x() - childLine->marginLogicalLeft(),
810                             logicalTop,
811                             childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(),
812                             logicalHeight));
813                     else
814                         result.uniteIfNonZero(FloatRect(logicalTop,
815                             childLine->y() - childLine->marginLogicalLeft(),
816                             logicalHeight,
817                             childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight()));
818                                      
819                 }
820             }
821         } else if (curr->isText()) {
822             RenderText* currText = toRenderText(curr);
823             for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) {
824                 RootInlineBox* rootBox = childText->root();
825                 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
826                 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
827                 if (isHorizontal)
828                     result.uniteIfNonZero(FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight));
829                 else
830                     result.uniteIfNonZero(FloatRect(logicalTop, childText->y(), logicalHeight, childText->logicalWidth()));
831             }
832         }
833     }
834     return enclosingIntRect(result);
835 }
836
837 InlineBox* RenderInline::culledInlineFirstLineBox() const
838 {
839     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
840         if (curr->isFloatingOrPositioned())
841             continue;
842             
843         // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
844         // direction (aligned to the root box's baseline).
845         if (curr->isBox())
846             return toRenderBox(curr)->inlineBoxWrapper();
847         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             return toRenderBox(curr)->inlineBoxWrapper();
871         if (curr->isRenderInline()) {
872             RenderInline* currInline = toRenderInline(curr);
873             InlineBox* result = currInline->lastLineBoxIncludingCulling();
874             if (result)
875                 return result;
876         } else if (curr->isText()) {
877             RenderText* currText = toRenderText(curr);
878             if (currText->lastTextBox())
879                 return currText->lastTextBox();
880         }
881     }
882     return 0;
883 }
884
885 IntRect RenderInline::culledInlineVisualOverflowBoundingBox() const
886 {
887     IntRect result(culledInlineBoundingBox(this));
888     bool isHorizontal = style()->isHorizontalWritingMode();
889     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
890         if (curr->isFloatingOrPositioned())
891             continue;
892             
893         // For overflow we just have to propagate by hand and recompute it all.
894         if (curr->isBox()) {
895             RenderBox* currBox = toRenderBox(curr);
896             if (!currBox->hasSelfPaintingLayer() && currBox->inlineBoxWrapper()) {
897                 IntRect logicalRect = currBox->logicalVisualOverflowRectForPropagation(style());
898                 if (isHorizontal) {
899                     logicalRect.moveBy(currBox->location());
900                     result.uniteIfNonZero(logicalRect);
901                 } else {
902                     logicalRect.moveBy(currBox->location());
903                     result.uniteIfNonZero(logicalRect.transposedRect());
904                 }
905             }
906         } else if (curr->isRenderInline()) {
907             // If the child doesn't need line boxes either, then we can recur.
908             RenderInline* currInline = toRenderInline(curr);
909             if (!currInline->alwaysCreateLineBoxes())
910                 result.uniteIfNonZero(currInline->culledInlineVisualOverflowBoundingBox());
911             else if (!currInline->hasSelfPaintingLayer())
912                 result.uniteIfNonZero(currInline->linesVisualOverflowBoundingBox());
913         } else if (curr->isText()) {
914             // FIXME; Overflow from text boxes is lost. We will need to cache this information in
915             // InlineTextBoxes.
916             RenderText* currText = toRenderText(curr);
917             result.uniteIfNonZero(currText->linesVisualOverflowBoundingBox());
918         }
919     }
920     return result;
921 }
922
923 IntRect RenderInline::linesVisualOverflowBoundingBox() const
924 {
925     if (!alwaysCreateLineBoxes())
926         return culledInlineVisualOverflowBoundingBox();
927
928     if (!firstLineBox() || !lastLineBox())
929         return IntRect();
930
931     // Return the width of the minimal left side and the maximal right side.
932     int logicalLeftSide = numeric_limits<int>::max();
933     int logicalRightSide = numeric_limits<int>::min();
934     for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
935         logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow());
936         logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow());
937     }
938
939     RootInlineBox* firstRootBox = firstLineBox()->root();
940     RootInlineBox* lastRootBox = lastLineBox()->root();
941     
942     int logicalTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox->lineTop());
943     int logicalWidth = logicalRightSide - logicalLeftSide;
944     int logicalHeight = lastLineBox()->logicalBottomVisualOverflow(lastRootBox->lineBottom()) - logicalTop;
945     
946     IntRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
947     if (!style()->isHorizontalWritingMode())
948         rect = rect.transposedRect();
949     return rect;
950 }
951
952 IntRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
953 {
954     // Only run-ins are allowed in here during layout.
955     ASSERT(!view() || !view()->layoutStateEnabled() || isRunIn());
956
957     if (!firstLineBoxIncludingCulling() && !continuation())
958         return IntRect();
959
960     // Find our leftmost position.
961     IntRect boundingBox(linesVisualOverflowBoundingBox());
962     int left = boundingBox.x();
963     int top = boundingBox.y();
964
965     // Now invalidate a rectangle.
966     int ow = style() ? style()->outlineSize() : 0;
967     
968     // We need to add in the relative position offsets of any inlines (including us) up to our
969     // containing block.
970     RenderBlock* cb = containingBlock();
971     for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isRenderInline() && inlineFlow != cb; 
972          inlineFlow = inlineFlow->parent()) {
973          if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer())
974             toRenderInline(inlineFlow)->layer()->relativePositionOffset(left, top);
975     }
976
977     IntRect r(-ow + left, -ow + top, boundingBox.width() + ow * 2, boundingBox.height() + ow * 2);
978
979     if (cb->hasColumns())
980         cb->adjustRectForColumns(r);
981
982     if (cb->hasOverflowClip()) {
983         // cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the
984         // layer's size instead.  Even if the layer's size is wrong, the layer itself will repaint
985         // anyway if its size does change.
986         IntRect repaintRect(r);
987         repaintRect.move(-cb->layer()->scrolledContentOffset()); // For overflow:auto/scroll/hidden.
988
989         IntRect boxRect(IntPoint(), cb->layer()->size());
990         r = intersection(repaintRect, boxRect);
991     }
992     
993     // FIXME: need to ensure that we compute the correct repaint rect when the repaint container
994     // is an inline.
995     if (repaintContainer != this)
996         cb->computeRectForRepaint(repaintContainer, r);
997
998     if (ow) {
999         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
1000             if (!curr->isText()) {
1001                 IntRect childRect = curr->rectWithOutlineForRepaint(repaintContainer, ow);
1002                 r.unite(childRect);
1003             }
1004         }
1005
1006         if (continuation() && !continuation()->isInline()) {
1007             IntRect contRect = continuation()->rectWithOutlineForRepaint(repaintContainer, ow);
1008             r.unite(contRect);
1009         }
1010     }
1011
1012     return r;
1013 }
1014
1015 IntRect RenderInline::rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth)
1016 {
1017     IntRect r(RenderBoxModelObject::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
1018     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
1019         if (!curr->isText())
1020             r.unite(curr->rectWithOutlineForRepaint(repaintContainer, outlineWidth));
1021     }
1022     return r;
1023 }
1024
1025 void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed)
1026 {
1027     if (RenderView* v = view()) {
1028         // LayoutState is only valid for root-relative repainting
1029         if (v->layoutStateEnabled() && !repaintContainer) {
1030             LayoutState* layoutState = v->layoutState();
1031             if (style()->position() == RelativePosition && layer())
1032                 rect.move(layer()->relativePositionOffset());
1033             rect.move(layoutState->m_paintOffset);
1034             if (layoutState->m_clipped)
1035                 rect.intersect(layoutState->m_clipRect);
1036             return;
1037         }
1038     }
1039
1040     if (repaintContainer == this)
1041         return;
1042
1043     bool containerSkipped;
1044     RenderObject* o = container(repaintContainer, &containerSkipped);
1045     if (!o)
1046         return;
1047
1048     IntPoint topLeft = rect.location();
1049
1050     if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition) {
1051         RenderBlock* cb = toRenderBlock(o);
1052         if (cb->hasColumns()) {
1053             IntRect repaintRect(topLeft, rect.size());
1054             cb->adjustRectForColumns(repaintRect);
1055             topLeft = repaintRect.location();
1056             rect = repaintRect;
1057         }
1058     }
1059
1060     if (style()->position() == RelativePosition && layer()) {
1061         // Apply the relative position offset when invalidating a rectangle.  The layer
1062         // is translated, but the render box isn't, so we need to do this to get the
1063         // right dirty rect.  Since this is called from RenderObject::setStyle, the relative position
1064         // flag on the RenderObject has been cleared, so use the one on the style().
1065         topLeft += layer()->relativePositionOffset();
1066     }
1067     
1068     // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
1069     // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
1070     if (o->hasOverflowClip()) {
1071         RenderBox* containerBox = toRenderBox(o);
1072
1073         // o->height() is inaccurate if we're in the middle of a layout of |o|, so use the
1074         // layer's size instead.  Even if the layer's size is wrong, the layer itself will repaint
1075         // anyway if its size does change.
1076         topLeft -= containerBox->layer()->scrolledContentOffset(); // For overflow:auto/scroll/hidden.
1077
1078         IntRect repaintRect(topLeft, rect.size());
1079         IntRect boxRect(IntPoint(), containerBox->layer()->size());
1080         rect = intersection(repaintRect, boxRect);
1081         if (rect.isEmpty())
1082             return;
1083     } else
1084         rect.setLocation(topLeft);
1085
1086     if (containerSkipped) {
1087         // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
1088         IntSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
1089         rect.move(-containerOffset);
1090         return;
1091     }
1092     
1093     o->computeRectForRepaint(repaintContainer, rect, fixed);
1094 }
1095
1096 LayoutSize RenderInline::offsetFromContainer(RenderObject* container, const LayoutPoint& point) const
1097 {
1098     ASSERT(container == this->container());
1099     
1100     LayoutSize offset;    
1101     if (isRelPositioned())
1102         offset += relativePositionOffset();
1103
1104     container->adjustForColumns(offset, point);
1105
1106     if (container->hasOverflowClip())
1107         offset -= toRenderBox(container)->layer()->scrolledContentOffset();
1108
1109     return offset;
1110 }
1111
1112 void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, bool* wasFixed) const
1113 {
1114     if (repaintContainer == this)
1115         return;
1116
1117     if (RenderView *v = view()) {
1118         if (v->layoutStateEnabled() && !repaintContainer) {
1119             LayoutState* layoutState = v->layoutState();
1120             IntSize offset = layoutState->m_paintOffset;
1121             if (style()->position() == RelativePosition && layer())
1122                 offset += layer()->relativePositionOffset();
1123             transformState.move(offset);
1124             return;
1125         }
1126     }
1127
1128     bool containerSkipped;
1129     RenderObject* o = container(repaintContainer, &containerSkipped);
1130     if (!o)
1131         return;
1132
1133     IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint());
1134     if (o->isBox() && o->style()->isFlippedBlocksWritingMode())
1135         transformState.move(toRenderBox(o)->flipForWritingModeIncludingColumns(roundedIntPoint(transformState.mappedPoint())) - centerPoint);
1136
1137     LayoutSize containerOffset = offsetFromContainer(o, roundedLayoutPoint(transformState.mappedPoint()));
1138
1139     bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D());
1140     if (useTransforms && shouldUseTransformFromContainer(o)) {
1141         TransformationMatrix t;
1142         getTransformFromContainer(o, containerOffset, t);
1143         transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1144     } else
1145         transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1146
1147     if (containerSkipped) {
1148         // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
1149         // to just subtract the delta between the repaintContainer and o.
1150         IntSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
1151         transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1152         return;
1153     }
1154
1155     o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, wasFixed);
1156 }
1157
1158 void RenderInline::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
1159 {
1160     // We don't expect this function to be called during layout.
1161     ASSERT(!view() || !view()->layoutStateEnabled());
1162
1163     RenderObject* o = container();
1164     if (!o)
1165         return;
1166
1167     o->mapAbsoluteToLocalPoint(fixed, useTransforms, transformState);
1168
1169     LayoutSize containerOffset = offsetFromContainer(o, LayoutPoint());
1170
1171     bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D());
1172     if (useTransforms && shouldUseTransformFromContainer(o)) {
1173         TransformationMatrix t;
1174         getTransformFromContainer(o, containerOffset, t);
1175         transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1176     } else
1177         transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1178 }
1179
1180 void RenderInline::updateDragState(bool dragOn)
1181 {
1182     RenderBoxModelObject::updateDragState(dragOn);
1183     if (continuation())
1184         continuation()->updateDragState(dragOn);
1185 }
1186
1187 void RenderInline::childBecameNonInline(RenderObject* child)
1188 {
1189     // We have to split the parent flow.
1190     RenderBlock* newBox = containingBlock()->createAnonymousBlock();
1191     RenderBoxModelObject* oldContinuation = continuation();
1192     setContinuation(newBox);
1193     RenderObject* beforeChild = child->nextSibling();
1194     children()->removeChildNode(this, child);
1195     splitFlow(beforeChild, newBox, child, oldContinuation);
1196 }
1197
1198 void RenderInline::updateHitTestResult(HitTestResult& result, const IntPoint& point)
1199 {
1200     if (result.innerNode())
1201         return;
1202
1203     Node* n = node();
1204     IntPoint localPoint(point);
1205     if (n) {
1206         if (isInlineElementContinuation()) {
1207             // We're in the continuation of a split inline.  Adjust our local point to be in the coordinate space
1208             // of the principal renderer's containing block.  This will end up being the innerNonSharedNode.
1209             RenderBlock* firstBlock = n->renderer()->containingBlock();
1210             
1211             // Get our containing block.
1212             RenderBox* block = containingBlock();
1213             localPoint.move(block->x() - firstBlock->x(), block->y() - firstBlock->y());
1214         }
1215
1216         result.setInnerNode(n);
1217         if (!result.innerNonSharedNode())
1218             result.setInnerNonSharedNode(n);
1219         result.setLocalPoint(localPoint);
1220     }
1221 }
1222
1223 void RenderInline::dirtyLineBoxes(bool fullLayout)
1224 {
1225     if (fullLayout) {
1226         m_lineBoxes.deleteLineBoxes(renderArena());
1227         return;
1228     }
1229
1230     if (!alwaysCreateLineBoxes()) {
1231         // We have to grovel into our children in order to dirty the appropriate lines.
1232         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
1233             if (curr->isFloatingOrPositioned())
1234                 continue;
1235             if (curr->isBox() && !curr->needsLayout()) {
1236                 RenderBox* currBox = toRenderBox(curr);
1237                 if (currBox->inlineBoxWrapper())
1238                     currBox->inlineBoxWrapper()->root()->markDirty();
1239             } else if (!curr->selfNeedsLayout()) {
1240                 if (curr->isRenderInline()) {
1241                     RenderInline* currInline = toRenderInline(curr);
1242                     for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox())
1243                         childLine->root()->markDirty();
1244                 } else if (curr->isText()) {
1245                     RenderText* currText = toRenderText(curr);
1246                     for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox())
1247                         childText->root()->markDirty();
1248                 }
1249             }
1250         }
1251     } else
1252         m_lineBoxes.dirtyLineBoxes();
1253 }
1254
1255 InlineFlowBox* RenderInline::createInlineFlowBox() 
1256 {
1257     return new (renderArena()) InlineFlowBox(this);
1258 }
1259
1260 InlineFlowBox* RenderInline::createAndAppendInlineFlowBox()
1261 {
1262     setAlwaysCreateLineBoxes();
1263     InlineFlowBox* flowBox = createInlineFlowBox();
1264     m_lineBoxes.appendLineBox(flowBox);
1265     return flowBox;
1266 }
1267
1268 int RenderInline::lineHeight(bool firstLine, LineDirectionMode /*direction*/, LinePositionMode /*linePositionMode*/) const
1269 {
1270     if (firstLine && document()->usesFirstLineRules()) {
1271         RenderStyle* s = style(firstLine);
1272         if (s != style())
1273             return s->computedLineHeight();
1274     }
1275     
1276     if (m_lineHeight == -1)
1277         m_lineHeight = style()->computedLineHeight();
1278     
1279     return m_lineHeight;
1280 }
1281
1282 int RenderInline::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
1283 {
1284     const FontMetrics& fontMetrics = style(firstLine)->fontMetrics();
1285     return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
1286 }
1287
1288 LayoutSize RenderInline::relativePositionedInlineOffset(const RenderBox* child) const
1289 {
1290     // FIXME: This function isn't right with mixed writing modes.
1291
1292     ASSERT(isRelPositioned());
1293     if (!isRelPositioned())
1294         return LayoutSize();
1295
1296     // When we have an enclosing relpositioned inline, we need to add in the offset of the first line
1297     // box from the rest of the content, but only in the cases where we know we're positioned
1298     // relative to the inline itself.
1299
1300     LayoutSize logicalOffset;
1301     LayoutUnit inlinePosition;
1302     LayoutUnit blockPosition;
1303     if (firstLineBox()) {
1304         inlinePosition = roundedLayoutUnit(firstLineBox()->logicalLeft());
1305         blockPosition = firstLineBox()->logicalTop();
1306     } else {
1307         inlinePosition = layer()->staticInlinePosition();
1308         blockPosition = layer()->staticBlockPosition();
1309     }
1310
1311     if (!child->style()->hasStaticInlinePosition(style()->isHorizontalWritingMode()))
1312         logicalOffset.setWidth(inlinePosition);
1313
1314     // This is not terribly intuitive, but we have to match other browsers.  Despite being a block display type inside
1315     // an inline, we still keep our x locked to the left of the relative positioned inline.  Arguably the correct
1316     // behavior would be to go flush left to the block that contains the inline, but that isn't what other browsers
1317     // do.
1318     else if (!child->style()->isOriginalDisplayInlineType())
1319         // Avoid adding in the left border/padding of the containing block twice.  Subtract it out.
1320         logicalOffset.setWidth(inlinePosition - child->containingBlock()->borderAndPaddingLogicalLeft());
1321
1322     if (!child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
1323         logicalOffset.setHeight(blockPosition);
1324
1325     return style()->isHorizontalWritingMode() ? logicalOffset : logicalOffset.transposedSize();
1326 }
1327
1328 void RenderInline::imageChanged(WrappedImagePtr, const IntRect*)
1329 {
1330     if (!parent())
1331         return;
1332         
1333     // FIXME: We can do better.
1334     repaint();
1335 }
1336
1337 void RenderInline::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint& additionalOffset)
1338 {
1339     if (!alwaysCreateLineBoxes())
1340         culledInlineAbsoluteRects(this, rects, toLayoutSize(additionalOffset));
1341     else {
1342         for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
1343             rects.append(enclosingLayoutRect(FloatRect(additionalOffset.x() + curr->x(), additionalOffset.y() + curr->y(), curr->width(), curr->height())));
1344     }
1345
1346     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
1347         if (!curr->isText() && !curr->isListMarker()) {
1348             FloatPoint pos(additionalOffset);
1349             // FIXME: This doesn't work correctly with transforms.
1350             if (curr->hasLayer()) 
1351                 pos = curr->localToAbsolute();
1352             else if (curr->isBox())
1353                 pos.move(toRenderBox(curr)->x(), toRenderBox(curr)->y());
1354             curr->addFocusRingRects(rects, flooredIntPoint(pos));
1355         }
1356     }
1357
1358     if (continuation()) {
1359         if (continuation()->isInline())
1360             continuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + continuation()->containingBlock()->location() - containingBlock()->location()));
1361         else
1362             continuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + toRenderBox(continuation())->location() - containingBlock()->location()));
1363     }
1364 }
1365
1366 void RenderInline::paintOutline(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset)
1367 {
1368     if (!hasOutline())
1369         return;
1370     
1371     RenderStyle* styleToUse = style();
1372     if (styleToUse->outlineStyleIsAuto() || hasOutlineAnnotation()) {
1373         if (!theme()->supportsFocusRing(styleToUse)) {
1374             // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
1375             paintFocusRing(graphicsContext, paintOffset, styleToUse);
1376         }
1377     }
1378
1379     if (graphicsContext->paintingDisabled())
1380         return;
1381
1382     if (styleToUse->outlineStyleIsAuto() || styleToUse->outlineStyle() == BNONE)
1383         return;
1384
1385     Vector<LayoutRect> rects;
1386
1387     rects.append(LayoutRect());
1388     for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
1389         RootInlineBox* root = curr->root();
1390         LayoutUnit top = max(root->lineTop(), curr->logicalTop());
1391         LayoutUnit bottom = min(root->lineBottom(), curr->logicalBottom());
1392         rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top));
1393     }
1394     rects.append(LayoutRect());
1395
1396     Color outlineColor = styleToUse->visitedDependentColor(CSSPropertyOutlineColor);
1397 // FIXME: Using a transparency layer for rgba outlines exacerbates an existing SKIA bug. The #if
1398 // below prevents this; it should be removed when https://bugs.webkit.org/show_bug.cgi?id=60342 is fixed.
1399 #if !USE(SKIA)
1400     bool useTransparencyLayer = outlineColor.hasAlpha();
1401     if (useTransparencyLayer) {
1402         graphicsContext->beginTransparencyLayer(static_cast<float>(outlineColor.alpha()) / 255);
1403         outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue());
1404     }
1405 #endif
1406
1407     for (unsigned i = 1; i < rects.size() - 1; i++)
1408         paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor);
1409
1410 // FIXME: Using a transparency layer for rgba outlines exacerbates an existing SKIA bug. The #if
1411 // below prevents this; it should be removed when https://bugs.webkit.org/show_bug.cgi?id=60342 is fixed.
1412 #if !USE(SKIA)
1413     if (useTransparencyLayer)
1414         graphicsContext->endTransparencyLayer();
1415 #endif
1416 }
1417
1418 void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset,
1419                                        const LayoutRect& lastline, const LayoutRect& thisline, const LayoutRect& nextline,
1420                                        const Color outlineColor)
1421 {
1422     RenderStyle* styleToUse = style();
1423     LayoutUnit outlineWidth = styleToUse->outlineWidth();
1424     EBorderStyle outlineStyle = styleToUse->outlineStyle();
1425
1426     const AffineTransform& currentCTM = graphicsContext->getCTM();
1427     bool antialias = !currentCTM.isIdentityOrTranslationOrFlipped();
1428
1429     LayoutUnit offset = style()->outlineOffset();
1430
1431     LayoutUnit top = paintOffset.y() + thisline.y() - offset;
1432     LayoutUnit left = paintOffset.x() + thisline.x() - offset;
1433     LayoutUnit bottom = paintOffset.y() + thisline.maxY() + offset;
1434     LayoutUnit right = paintOffset.x() + thisline.maxX() + offset;
1435     
1436     // left edge
1437     drawLineForBoxSide(graphicsContext,
1438         left - outlineWidth,
1439         top - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : 0),
1440         left,
1441         bottom + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : 0),
1442         BSLeft,
1443         outlineColor, outlineStyle,
1444         (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth),
1445         (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth),
1446         antialias);
1447     
1448     // right edge
1449     drawLineForBoxSide(graphicsContext,
1450         right,
1451         top - (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : 0),
1452         right + outlineWidth,
1453         bottom + (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : 0),
1454         BSRight,
1455         outlineColor, outlineStyle,
1456         (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : -outlineWidth),
1457         (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : -outlineWidth),
1458         antialias);
1459     // upper edge
1460     if (thisline.x() < lastline.x())
1461         drawLineForBoxSide(graphicsContext,
1462             left - outlineWidth,
1463             top - outlineWidth,
1464             min(right + outlineWidth, (lastline.isEmpty() ? 1000000 : paintOffset.x() + lastline.x())),
1465             top,
1466             BSTop, outlineColor, outlineStyle,
1467             outlineWidth,
1468             (!lastline.isEmpty() && paintOffset.x() + lastline.x() + 1 < right + outlineWidth) ? -outlineWidth : outlineWidth,
1469             antialias);
1470     
1471     if (lastline.maxX() < thisline.maxX())
1472         drawLineForBoxSide(graphicsContext,
1473             max(lastline.isEmpty() ? -1000000 : paintOffset.x() + lastline.maxX(), left - outlineWidth),
1474             top - outlineWidth,
1475             right + outlineWidth,
1476             top,
1477             BSTop, outlineColor, outlineStyle,
1478             (!lastline.isEmpty() && left - outlineWidth < paintOffset.x() + lastline.maxX()) ? -outlineWidth : outlineWidth,
1479             outlineWidth, antialias);
1480     
1481     // lower edge
1482     if (thisline.x() < nextline.x())
1483         drawLineForBoxSide(graphicsContext,
1484             left - outlineWidth,
1485             bottom,
1486             min(right + outlineWidth, !nextline.isEmpty() ? paintOffset.x() + nextline.x() + 1 : 1000000),
1487             bottom + outlineWidth,
1488             BSBottom, outlineColor, outlineStyle,
1489             outlineWidth,
1490             (!nextline.isEmpty() && paintOffset.x() + nextline.x() + 1 < right + outlineWidth) ? -outlineWidth : outlineWidth,
1491             antialias);
1492     
1493     if (nextline.maxX() < thisline.maxX())
1494         drawLineForBoxSide(graphicsContext,
1495             max(!nextline.isEmpty() ? paintOffset.x() + nextline.maxX() : -1000000, left - outlineWidth),
1496             bottom,
1497             right + outlineWidth,
1498             bottom + outlineWidth,
1499             BSBottom, outlineColor, outlineStyle,
1500             (!nextline.isEmpty() && left - outlineWidth < paintOffset.x() + nextline.maxX()) ? -outlineWidth : outlineWidth,
1501             outlineWidth, antialias);
1502 }
1503
1504 #if ENABLE(DASHBOARD_SUPPORT)
1505 void RenderInline::addDashboardRegions(Vector<DashboardRegionValue>& regions)
1506 {
1507     // Convert the style regions to absolute coordinates.
1508     if (style()->visibility() != VISIBLE)
1509         return;
1510
1511     const Vector<StyleDashboardRegion>& styleRegions = style()->dashboardRegions();
1512     unsigned i, count = styleRegions.size();
1513     for (i = 0; i < count; i++) {
1514         StyleDashboardRegion styleRegion = styleRegions[i];
1515
1516         IntRect linesBoundingBox = this->linesBoundingBox();
1517         int w = linesBoundingBox.width();
1518         int h = linesBoundingBox.height();
1519
1520         DashboardRegionValue region;
1521         region.label = styleRegion.label;
1522         region.bounds = IntRect(linesBoundingBox.x() + styleRegion.offset.left().value(),
1523                                 linesBoundingBox.y() + styleRegion.offset.top().value(),
1524                                 w - styleRegion.offset.left().value() - styleRegion.offset.right().value(),
1525                                 h - styleRegion.offset.top().value() - styleRegion.offset.bottom().value());
1526         region.type = styleRegion.type;
1527
1528         RenderObject* container = containingBlock();
1529         if (!container)
1530             container = this;
1531
1532         region.clip = region.bounds;
1533         container->computeAbsoluteRepaintRect(region.clip);
1534         if (region.clip.height() < 0) {
1535             region.clip.setHeight(0);
1536             region.clip.setWidth(0);
1537         }
1538
1539         FloatPoint absPos = container->localToAbsolute();
1540         region.bounds.setX(absPos.x() + region.bounds.x());
1541         region.bounds.setY(absPos.y() + region.bounds.y());
1542
1543         if (frame()) {
1544             float pageScaleFactor = frame()->page()->chrome()->scaleFactor();
1545             if (pageScaleFactor != 1.0f) {
1546                 region.bounds.scale(pageScaleFactor);
1547                 region.clip.scale(pageScaleFactor);
1548             }
1549         }
1550
1551         regions.append(region);
1552     }
1553 }
1554 #endif
1555
1556 } // namespace WebCore