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