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