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