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