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