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