Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  */
     19 
     20 #include "config.h"
     21 #include "core/rendering/InlineFlowBox.h"
     22 
     23 #include "CSSPropertyNames.h"
     24 #include "core/dom/Document.h"
     25 #include "core/rendering/HitTestResult.h"
     26 #include "core/rendering/InlineTextBox.h"
     27 #include "core/rendering/RenderBlock.h"
     28 #include "core/rendering/RenderInline.h"
     29 #include "core/rendering/RenderLayer.h"
     30 #include "core/rendering/RenderListMarker.h"
     31 #include "core/rendering/RenderRubyBase.h"
     32 #include "core/rendering/RenderRubyRun.h"
     33 #include "core/rendering/RenderRubyText.h"
     34 #include "core/rendering/RenderView.h"
     35 #include "core/rendering/RootInlineBox.h"
     36 #include "platform/fonts/Font.h"
     37 #include "platform/graphics/GraphicsContextStateSaver.h"
     38 
     39 #include <math.h>
     40 
     41 using namespace std;
     42 
     43 namespace WebCore {
     44 
     45 struct SameSizeAsInlineFlowBox : public InlineBox {
     46     void* pointers[5];
     47     uint32_t bitfields : 23;
     48 };
     49 
     50 COMPILE_ASSERT(sizeof(InlineFlowBox) == sizeof(SameSizeAsInlineFlowBox), InlineFlowBox_should_stay_small);
     51 
     52 #ifndef NDEBUG
     53 
     54 InlineFlowBox::~InlineFlowBox()
     55 {
     56     if (!m_hasBadChildList)
     57         for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
     58             child->setHasBadParent();
     59 }
     60 
     61 #endif
     62 
     63 LayoutUnit InlineFlowBox::getFlowSpacingLogicalWidth()
     64 {
     65     LayoutUnit totWidth = marginBorderPaddingLogicalLeft() + marginBorderPaddingLogicalRight();
     66     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
     67         if (curr->isInlineFlowBox())
     68             totWidth += toInlineFlowBox(curr)->getFlowSpacingLogicalWidth();
     69     }
     70     return totWidth;
     71 }
     72 
     73 IntRect InlineFlowBox::roundedFrameRect() const
     74 {
     75     // Begin by snapping the x and y coordinates to the nearest pixel.
     76     int snappedX = lroundf(x());
     77     int snappedY = lroundf(y());
     78 
     79     int snappedMaxX = lroundf(x() + width());
     80     int snappedMaxY = lroundf(y() + height());
     81 
     82     return IntRect(snappedX, snappedY, snappedMaxX - snappedX, snappedMaxY - snappedY);
     83 }
     84 
     85 static void setHasTextDescendantsOnAncestors(InlineFlowBox* box)
     86 {
     87     while (box && !box->hasTextDescendants()) {
     88         box->setHasTextDescendants();
     89         box = box->parent();
     90     }
     91 }
     92 
     93 void InlineFlowBox::addToLine(InlineBox* child)
     94 {
     95     ASSERT(!child->parent());
     96     ASSERT(!child->nextOnLine());
     97     ASSERT(!child->prevOnLine());
     98     checkConsistency();
     99 
    100     child->setParent(this);
    101     if (!m_firstChild) {
    102         m_firstChild = child;
    103         m_lastChild = child;
    104     } else {
    105         m_lastChild->setNextOnLine(child);
    106         child->setPrevOnLine(m_lastChild);
    107         m_lastChild = child;
    108     }
    109     child->setFirstLineStyleBit(isFirstLineStyle());
    110     child->setIsHorizontal(isHorizontal());
    111     if (child->isText()) {
    112         if (child->renderer()->parent() == renderer())
    113             m_hasTextChildren = true;
    114         setHasTextDescendantsOnAncestors(this);
    115     } else if (child->isInlineFlowBox()) {
    116         if (toInlineFlowBox(child)->hasTextDescendants())
    117             setHasTextDescendantsOnAncestors(this);
    118     }
    119 
    120     if (descendantsHaveSameLineHeightAndBaseline() && !child->renderer()->isOutOfFlowPositioned()) {
    121         RenderStyle* parentStyle = renderer()->style(isFirstLineStyle());
    122         RenderStyle* childStyle = child->renderer()->style(isFirstLineStyle());
    123         bool shouldClearDescendantsHaveSameLineHeightAndBaseline = false;
    124         if (child->renderer()->isReplaced())
    125             shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
    126         else if (child->isText()) {
    127             if (child->renderer()->isBR() || child->renderer()->parent() != renderer()) {
    128                 if (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
    129                     || parentStyle->lineHeight() != childStyle->lineHeight()
    130                     || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE)
    131                     shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
    132             }
    133             if (childStyle->hasTextCombine() || childStyle->textEmphasisMark() != TextEmphasisMarkNone)
    134                 shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
    135         } else {
    136             if (child->renderer()->isBR()) {
    137                 // FIXME: This is dumb. We only turn off because current layout test results expect the <br> to be 0-height on the baseline.
    138                 // Other than making a zillion tests have to regenerate results, there's no reason to ditch the optimization here.
    139                 shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
    140             } else {
    141                 ASSERT(isInlineFlowBox());
    142                 InlineFlowBox* childFlowBox = toInlineFlowBox(child);
    143                 // Check the child's bit, and then also check for differences in font, line-height, vertical-align
    144                 if (!childFlowBox->descendantsHaveSameLineHeightAndBaseline()
    145                     || !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
    146                     || parentStyle->lineHeight() != childStyle->lineHeight()
    147                     || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE
    148                     || childStyle->hasBorder() || childStyle->hasPadding() || childStyle->hasTextCombine())
    149                     shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
    150             }
    151         }
    152 
    153         if (shouldClearDescendantsHaveSameLineHeightAndBaseline)
    154             clearDescendantsHaveSameLineHeightAndBaseline();
    155     }
    156 
    157     if (!child->renderer()->isOutOfFlowPositioned()) {
    158         if (child->isText()) {
    159             RenderStyle* childStyle = child->renderer()->style(isFirstLineStyle());
    160             if (childStyle->letterSpacing() < 0 || childStyle->textShadow() || childStyle->textEmphasisMark() != TextEmphasisMarkNone || childStyle->textStrokeWidth())
    161                 child->clearKnownToHaveNoOverflow();
    162         } else if (child->renderer()->isReplaced()) {
    163             RenderBox* box = toRenderBox(child->renderer());
    164             if (box->hasRenderOverflow() || box->hasSelfPaintingLayer())
    165                 child->clearKnownToHaveNoOverflow();
    166         } else if (!child->renderer()->isBR() && (child->renderer()->style(isFirstLineStyle())->boxShadow() || child->boxModelObject()->hasSelfPaintingLayer()
    167                    || (child->renderer()->isListMarker() && !toRenderListMarker(child->renderer())->isInside())
    168                    || child->renderer()->style(isFirstLineStyle())->hasBorderImageOutsets()))
    169             child->clearKnownToHaveNoOverflow();
    170 
    171         if (knownToHaveNoOverflow() && child->isInlineFlowBox() && !toInlineFlowBox(child)->knownToHaveNoOverflow())
    172             clearKnownToHaveNoOverflow();
    173     }
    174 
    175     checkConsistency();
    176 }
    177 
    178 void InlineFlowBox::removeChild(InlineBox* child)
    179 {
    180     checkConsistency();
    181 
    182     if (!isDirty())
    183         dirtyLineBoxes();
    184 
    185     root()->childRemoved(child);
    186 
    187     if (child == m_firstChild)
    188         m_firstChild = child->nextOnLine();
    189     if (child == m_lastChild)
    190         m_lastChild = child->prevOnLine();
    191     if (child->nextOnLine())
    192         child->nextOnLine()->setPrevOnLine(child->prevOnLine());
    193     if (child->prevOnLine())
    194         child->prevOnLine()->setNextOnLine(child->nextOnLine());
    195 
    196     child->setParent(0);
    197 
    198     checkConsistency();
    199 }
    200 
    201 void InlineFlowBox::deleteLine()
    202 {
    203     InlineBox* child = firstChild();
    204     InlineBox* next = 0;
    205     while (child) {
    206         ASSERT(this == child->parent());
    207         next = child->nextOnLine();
    208 #ifndef NDEBUG
    209         child->setParent(0);
    210 #endif
    211         child->deleteLine();
    212         child = next;
    213     }
    214 #ifndef NDEBUG
    215     m_firstChild = 0;
    216     m_lastChild = 0;
    217 #endif
    218 
    219     removeLineBoxFromRenderObject();
    220     destroy();
    221 }
    222 
    223 void InlineFlowBox::removeLineBoxFromRenderObject()
    224 {
    225     toRenderInline(renderer())->lineBoxes()->removeLineBox(this);
    226 }
    227 
    228 void InlineFlowBox::extractLine()
    229 {
    230     if (!extracted())
    231         extractLineBoxFromRenderObject();
    232     for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
    233         child->extractLine();
    234 }
    235 
    236 void InlineFlowBox::extractLineBoxFromRenderObject()
    237 {
    238     toRenderInline(renderer())->lineBoxes()->extractLineBox(this);
    239 }
    240 
    241 void InlineFlowBox::attachLine()
    242 {
    243     if (extracted())
    244         attachLineBoxToRenderObject();
    245     for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
    246         child->attachLine();
    247 }
    248 
    249 void InlineFlowBox::attachLineBoxToRenderObject()
    250 {
    251     toRenderInline(renderer())->lineBoxes()->attachLineBox(this);
    252 }
    253 
    254 void InlineFlowBox::adjustPosition(float dx, float dy)
    255 {
    256     InlineBox::adjustPosition(dx, dy);
    257     for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
    258         child->adjustPosition(dx, dy);
    259     if (m_overflow)
    260         m_overflow->move(dx, dy); // FIXME: Rounding error here since overflow was pixel snapped, but nobody other than list markers passes non-integral values here.
    261 }
    262 
    263 RenderLineBoxList* InlineFlowBox::rendererLineBoxes() const
    264 {
    265     return toRenderInline(renderer())->lineBoxes();
    266 }
    267 
    268 static inline bool isLastChildForRenderer(RenderObject* ancestor, RenderObject* child)
    269 {
    270     if (!child)
    271         return false;
    272 
    273     if (child == ancestor)
    274         return true;
    275 
    276     RenderObject* curr = child;
    277     RenderObject* parent = curr->parent();
    278     while (parent && (!parent->isRenderBlock() || parent->isInline())) {
    279         if (parent->lastChild() != curr)
    280             return false;
    281         if (parent == ancestor)
    282             return true;
    283 
    284         curr = parent;
    285         parent = curr->parent();
    286     }
    287 
    288     return true;
    289 }
    290 
    291 static bool isAnsectorAndWithinBlock(RenderObject* ancestor, RenderObject* child)
    292 {
    293     RenderObject* object = child;
    294     while (object && (!object->isRenderBlock() || object->isInline())) {
    295         if (object == ancestor)
    296             return true;
    297         object = object->parent();
    298     }
    299     return false;
    300 }
    301 
    302 void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, RenderObject* logicallyLastRunRenderer)
    303 {
    304     // All boxes start off open.  They will not apply any margins/border/padding on
    305     // any side.
    306     bool includeLeftEdge = false;
    307     bool includeRightEdge = false;
    308 
    309     // The root inline box never has borders/margins/padding.
    310     if (parent()) {
    311         bool ltr = renderer()->style()->isLeftToRightDirection();
    312 
    313         // Check to see if all initial lines are unconstructed.  If so, then
    314         // we know the inline began on this line (unless we are a continuation).
    315         RenderLineBoxList* lineBoxList = rendererLineBoxes();
    316         if (!lineBoxList->firstLineBox()->isConstructed() && !renderer()->isInlineElementContinuation()) {
    317             if (renderer()->style()->boxDecorationBreak() == DCLONE)
    318                 includeLeftEdge = includeRightEdge = true;
    319             else if (ltr && lineBoxList->firstLineBox() == this)
    320                 includeLeftEdge = true;
    321             else if (!ltr && lineBoxList->lastLineBox() == this)
    322                 includeRightEdge = true;
    323         }
    324 
    325         if (!lineBoxList->lastLineBox()->isConstructed()) {
    326             RenderInline* inlineFlow = toRenderInline(renderer());
    327             bool isLastObjectOnLine = !isAnsectorAndWithinBlock(renderer(), logicallyLastRunRenderer) || (isLastChildForRenderer(renderer(), logicallyLastRunRenderer) && !isLogicallyLastRunWrapped);
    328 
    329             // We include the border under these conditions:
    330             // (1) The next line was not created, or it is constructed. We check the previous line for rtl.
    331             // (2) The logicallyLastRun is not a descendant of this renderer.
    332             // (3) The logicallyLastRun is a descendant of this renderer, but it is the last child of this renderer and it does not wrap to the next line.
    333             // (4) The decoration break is set to clone therefore there will be borders on every sides.
    334             if (renderer()->style()->boxDecorationBreak() == DCLONE)
    335                 includeLeftEdge = includeRightEdge = true;
    336             else if (ltr) {
    337                 if (!nextLineBox()
    338                     && ((lastLine || isLastObjectOnLine) && !inlineFlow->continuation()))
    339                     includeRightEdge = true;
    340             } else {
    341                 if ((!prevLineBox() || prevLineBox()->isConstructed())
    342                     && ((lastLine || isLastObjectOnLine) && !inlineFlow->continuation()))
    343                     includeLeftEdge = true;
    344             }
    345         }
    346     }
    347 
    348     setEdges(includeLeftEdge, includeRightEdge);
    349 
    350     // Recur into our children.
    351     for (InlineBox* currChild = firstChild(); currChild; currChild = currChild->nextOnLine()) {
    352         if (currChild->isInlineFlowBox()) {
    353             InlineFlowBox* currFlow = toInlineFlowBox(currChild);
    354             currFlow->determineSpacingForFlowBoxes(lastLine, isLogicallyLastRunWrapped, logicallyLastRunRenderer);
    355         }
    356     }
    357 }
    358 
    359 float InlineFlowBox::placeBoxesInInlineDirection(float logicalLeft, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
    360 {
    361     // Set our x position.
    362     beginPlacingBoxRangesInInlineDirection(logicalLeft);
    363 
    364     float startLogicalLeft = logicalLeft;
    365     logicalLeft += borderLogicalLeft() + paddingLogicalLeft();
    366 
    367     float minLogicalLeft = startLogicalLeft;
    368     float maxLogicalRight = logicalLeft;
    369 
    370     placeBoxRangeInInlineDirection(firstChild(), 0, logicalLeft, minLogicalLeft, maxLogicalRight, needsWordSpacing, textBoxDataMap);
    371 
    372     logicalLeft += borderLogicalRight() + paddingLogicalRight();
    373     endPlacingBoxRangesInInlineDirection(startLogicalLeft, logicalLeft, minLogicalLeft, maxLogicalRight);
    374     return logicalLeft;
    375 }
    376 
    377 float InlineFlowBox::placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild, float& logicalLeft, float& minLogicalLeft, float& maxLogicalRight, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
    378 {
    379     for (InlineBox* curr = firstChild; curr && curr != lastChild; curr = curr->nextOnLine()) {
    380         if (curr->renderer()->isText()) {
    381             InlineTextBox* text = toInlineTextBox(curr);
    382             RenderText* rt = toRenderText(text->renderer());
    383             if (rt->textLength()) {
    384                 if (needsWordSpacing && isSpaceOrNewline(rt->characterAt(text->start())))
    385                     logicalLeft += rt->style(isFirstLineStyle())->font().wordSpacing();
    386                 needsWordSpacing = !isSpaceOrNewline(rt->characterAt(text->end()));
    387             }
    388             text->setLogicalLeft(logicalLeft);
    389             if (knownToHaveNoOverflow())
    390                 minLogicalLeft = min(logicalLeft, minLogicalLeft);
    391             logicalLeft += text->logicalWidth();
    392             if (knownToHaveNoOverflow())
    393                 maxLogicalRight = max(logicalLeft, maxLogicalRight);
    394         } else {
    395             if (curr->renderer()->isOutOfFlowPositioned()) {
    396                 if (curr->renderer()->parent()->style()->isLeftToRightDirection())
    397                     curr->setLogicalLeft(logicalLeft);
    398                 else
    399                     // Our offset that we cache needs to be from the edge of the right border box and
    400                     // not the left border box.  We have to subtract |x| from the width of the block
    401                     // (which can be obtained from the root line box).
    402                     curr->setLogicalLeft(root()->block()->logicalWidth() - logicalLeft);
    403                 continue; // The positioned object has no effect on the width.
    404             }
    405             if (curr->renderer()->isRenderInline()) {
    406                 InlineFlowBox* flow = toInlineFlowBox(curr);
    407                 logicalLeft += flow->marginLogicalLeft();
    408                 if (knownToHaveNoOverflow())
    409                     minLogicalLeft = min(logicalLeft, minLogicalLeft);
    410                 logicalLeft = flow->placeBoxesInInlineDirection(logicalLeft, needsWordSpacing, textBoxDataMap);
    411                 if (knownToHaveNoOverflow())
    412                     maxLogicalRight = max(logicalLeft, maxLogicalRight);
    413                 logicalLeft += flow->marginLogicalRight();
    414             } else if (!curr->renderer()->isListMarker() || toRenderListMarker(curr->renderer())->isInside()) {
    415                 // The box can have a different writing-mode than the overall line, so this is a bit complicated.
    416                 // Just get all the physical margin and overflow values by hand based off |isVertical|.
    417                 LayoutUnit logicalLeftMargin = isHorizontal() ? curr->boxModelObject()->marginLeft() : curr->boxModelObject()->marginTop();
    418                 LayoutUnit logicalRightMargin = isHorizontal() ? curr->boxModelObject()->marginRight() : curr->boxModelObject()->marginBottom();
    419 
    420                 logicalLeft += logicalLeftMargin;
    421                 curr->setLogicalLeft(logicalLeft);
    422                 if (knownToHaveNoOverflow())
    423                     minLogicalLeft = min(logicalLeft, minLogicalLeft);
    424                 logicalLeft += curr->logicalWidth();
    425                 if (knownToHaveNoOverflow())
    426                     maxLogicalRight = max(logicalLeft, maxLogicalRight);
    427                 logicalLeft += logicalRightMargin;
    428                 // If we encounter any space after this inline block then ensure it is treated as the space between two words.
    429                 needsWordSpacing = true;
    430             }
    431         }
    432     }
    433     return logicalLeft;
    434 }
    435 
    436 bool InlineFlowBox::requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap& textBoxDataMap) const
    437 {
    438     if (isHorizontal())
    439         return false;
    440 
    441     if (renderer()->style(isFirstLineStyle())->fontDescription().nonCJKGlyphOrientation() == NonCJKGlyphOrientationUpright
    442         || renderer()->style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
    443         return true;
    444 
    445     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    446         if (curr->renderer()->isOutOfFlowPositioned())
    447             continue; // Positioned placeholders don't affect calculations.
    448 
    449         if (curr->isInlineFlowBox()) {
    450             if (toInlineFlowBox(curr)->requiresIdeographicBaseline(textBoxDataMap))
    451                 return true;
    452         } else {
    453             if (curr->renderer()->style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
    454                 return true;
    455 
    456             const Vector<const SimpleFontData*>* usedFonts = 0;
    457             if (curr->isInlineTextBox()) {
    458                 GlyphOverflowAndFallbackFontsMap::const_iterator it = textBoxDataMap.find(toInlineTextBox(curr));
    459                 usedFonts = it == textBoxDataMap.end() ? 0 : &it->value.first;
    460             }
    461 
    462             if (usedFonts) {
    463                 for (size_t i = 0; i < usedFonts->size(); ++i) {
    464                     if (usedFonts->at(i)->hasVerticalGlyphs())
    465                         return true;
    466                 }
    467             }
    468         }
    469     }
    470 
    471     return false;
    472 }
    473 
    474 void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, int maxPositionTop, int maxPositionBottom)
    475 {
    476     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    477         // The computed lineheight needs to be extended for the
    478         // positioned elements
    479         if (curr->renderer()->isOutOfFlowPositioned())
    480             continue; // Positioned placeholders don't affect calculations.
    481         if (curr->verticalAlign() == TOP || curr->verticalAlign() == BOTTOM) {
    482             int lineHeight = curr->lineHeight();
    483             if (curr->verticalAlign() == TOP) {
    484                 if (maxAscent + maxDescent < lineHeight)
    485                     maxDescent = lineHeight - maxAscent;
    486             }
    487             else {
    488                 if (maxAscent + maxDescent < lineHeight)
    489                     maxAscent = lineHeight - maxDescent;
    490             }
    491 
    492             if (maxAscent + maxDescent >= max(maxPositionTop, maxPositionBottom))
    493                 break;
    494         }
    495 
    496         if (curr->isInlineFlowBox())
    497             toInlineFlowBox(curr)->adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
    498     }
    499 }
    500 
    501 void InlineFlowBox::computeLogicalBoxHeights(RootInlineBox* rootBox, LayoutUnit& maxPositionTop, LayoutUnit& maxPositionBottom,
    502                                              int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent,
    503                                              bool strictMode, GlyphOverflowAndFallbackFontsMap& textBoxDataMap,
    504                                              FontBaseline baselineType, VerticalPositionCache& verticalPositionCache)
    505 {
    506     // The primary purpose of this function is to compute the maximal ascent and descent values for
    507     // a line. These values are computed based off the block's line-box-contain property, which indicates
    508     // what parts of descendant boxes have to fit within the line.
    509     //
    510     // The maxAscent value represents the distance of the highest point of any box (typically including line-height) from
    511     // the root box's baseline. The maxDescent value represents the distance of the lowest point of any box
    512     // (also typically including line-height) from the root box baseline. These values can be negative.
    513     //
    514     // A secondary purpose of this function is to store the offset of every box's baseline from the root box's
    515     // baseline. This information is cached in the logicalTop() of every box. We're effectively just using
    516     // the logicalTop() as scratch space.
    517     //
    518     // Because a box can be positioned such that it ends up fully above or fully below the
    519     // root line box, we only consider it to affect the maxAscent and maxDescent values if some
    520     // part of the box (EXCLUDING leading) is above (for ascent) or below (for descent) the root box's baseline.
    521     bool affectsAscent = false;
    522     bool affectsDescent = false;
    523     bool checkChildren = !descendantsHaveSameLineHeightAndBaseline();
    524 
    525     if (isRootInlineBox()) {
    526         // Examine our root box.
    527         int ascent = 0;
    528         int descent = 0;
    529         rootBox->ascentAndDescentForBox(rootBox, textBoxDataMap, ascent, descent, affectsAscent, affectsDescent);
    530         if (strictMode || hasTextChildren() || (!checkChildren && hasTextDescendants())) {
    531             if (maxAscent < ascent || !setMaxAscent) {
    532                 maxAscent = ascent;
    533                 setMaxAscent = true;
    534             }
    535             if (maxDescent < descent || !setMaxDescent) {
    536                 maxDescent = descent;
    537                 setMaxDescent = true;
    538             }
    539         }
    540     }
    541 
    542     if (!checkChildren)
    543         return;
    544 
    545     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    546         if (curr->renderer()->isOutOfFlowPositioned())
    547             continue; // Positioned placeholders don't affect calculations.
    548 
    549         InlineFlowBox* inlineFlowBox = curr->isInlineFlowBox() ? toInlineFlowBox(curr) : 0;
    550 
    551         bool affectsAscent = false;
    552         bool affectsDescent = false;
    553 
    554         // The verticalPositionForBox function returns the distance between the child box's baseline
    555         // and the root box's baseline.  The value is negative if the child box's baseline is above the
    556         // root box's baseline, and it is positive if the child box's baseline is below the root box's baseline.
    557         curr->setLogicalTop(rootBox->verticalPositionForBox(curr, verticalPositionCache));
    558 
    559         int ascent = 0;
    560         int descent = 0;
    561         rootBox->ascentAndDescentForBox(curr, textBoxDataMap, ascent, descent, affectsAscent, affectsDescent);
    562 
    563         LayoutUnit boxHeight = ascent + descent;
    564         if (curr->verticalAlign() == TOP) {
    565             if (maxPositionTop < boxHeight)
    566                 maxPositionTop = boxHeight;
    567         } else if (curr->verticalAlign() == BOTTOM) {
    568             if (maxPositionBottom < boxHeight)
    569                 maxPositionBottom = boxHeight;
    570         } else if (!inlineFlowBox || strictMode || inlineFlowBox->hasTextChildren() || (inlineFlowBox->descendantsHaveSameLineHeightAndBaseline() && inlineFlowBox->hasTextDescendants())
    571                    || inlineFlowBox->boxModelObject()->hasInlineDirectionBordersOrPadding()) {
    572             // Note that these values can be negative.  Even though we only affect the maxAscent and maxDescent values
    573             // if our box (excluding line-height) was above (for ascent) or below (for descent) the root baseline, once you factor in line-height
    574             // the final box can end up being fully above or fully below the root box's baseline!  This is ok, but what it
    575             // means is that ascent and descent (including leading), can end up being negative.  The setMaxAscent and
    576             // setMaxDescent booleans are used to ensure that we're willing to initially set maxAscent/Descent to negative
    577             // values.
    578             ascent -= curr->logicalTop();
    579             descent += curr->logicalTop();
    580             if (affectsAscent && (maxAscent < ascent || !setMaxAscent)) {
    581                 maxAscent = ascent;
    582                 setMaxAscent = true;
    583             }
    584 
    585             if (affectsDescent && (maxDescent < descent || !setMaxDescent)) {
    586                 maxDescent = descent;
    587                 setMaxDescent = true;
    588             }
    589         }
    590 
    591         if (inlineFlowBox)
    592             inlineFlowBox->computeLogicalBoxHeights(rootBox, maxPositionTop, maxPositionBottom, maxAscent, maxDescent,
    593                                                     setMaxAscent, setMaxDescent, strictMode, textBoxDataMap,
    594                                                     baselineType, verticalPositionCache);
    595     }
    596 }
    597 
    598 void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit top, LayoutUnit maxHeight, int maxAscent, bool strictMode, LayoutUnit& lineTop, LayoutUnit& lineBottom, bool& setLineTop,
    599                                                LayoutUnit& lineTopIncludingMargins, LayoutUnit& lineBottomIncludingMargins, bool& hasAnnotationsBefore, bool& hasAnnotationsAfter, FontBaseline baselineType)
    600 {
    601     bool isRootBox = isRootInlineBox();
    602     if (isRootBox) {
    603         const FontMetrics& fontMetrics = renderer()->style(isFirstLineStyle())->fontMetrics();
    604         // RootInlineBoxes are always placed on at pixel boundaries in their logical y direction. Not doing
    605         // so results in incorrect rendering of text decorations, most notably underlines.
    606         setLogicalTop(roundToInt(top + maxAscent - fontMetrics.ascent(baselineType)));
    607     }
    608 
    609     LayoutUnit adjustmentForChildrenWithSameLineHeightAndBaseline = 0;
    610     if (descendantsHaveSameLineHeightAndBaseline()) {
    611         adjustmentForChildrenWithSameLineHeightAndBaseline = logicalTop();
    612         if (parent())
    613             adjustmentForChildrenWithSameLineHeightAndBaseline += (boxModelObject()->borderBefore() + boxModelObject()->paddingBefore());
    614     }
    615 
    616     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    617         if (curr->renderer()->isOutOfFlowPositioned())
    618             continue; // Positioned placeholders don't affect calculations.
    619 
    620         if (descendantsHaveSameLineHeightAndBaseline()) {
    621             curr->adjustBlockDirectionPosition(adjustmentForChildrenWithSameLineHeightAndBaseline);
    622             continue;
    623         }
    624 
    625         InlineFlowBox* inlineFlowBox = curr->isInlineFlowBox() ? toInlineFlowBox(curr) : 0;
    626         bool childAffectsTopBottomPos = true;
    627         if (curr->verticalAlign() == TOP)
    628             curr->setLogicalTop(top);
    629         else if (curr->verticalAlign() == BOTTOM)
    630             curr->setLogicalTop(top + maxHeight - curr->lineHeight());
    631         else {
    632             if (!strictMode && inlineFlowBox && !inlineFlowBox->hasTextChildren() && !curr->boxModelObject()->hasInlineDirectionBordersOrPadding()
    633                 && !(inlineFlowBox->descendantsHaveSameLineHeightAndBaseline() && inlineFlowBox->hasTextDescendants()))
    634                 childAffectsTopBottomPos = false;
    635             LayoutUnit posAdjust = maxAscent - curr->baselinePosition(baselineType);
    636             curr->setLogicalTop(curr->logicalTop() + top + posAdjust);
    637         }
    638 
    639         LayoutUnit newLogicalTop = curr->logicalTop();
    640         LayoutUnit newLogicalTopIncludingMargins = newLogicalTop;
    641         LayoutUnit boxHeight = curr->logicalHeight();
    642         LayoutUnit boxHeightIncludingMargins = boxHeight;
    643 
    644         if (curr->isText() || curr->isInlineFlowBox()) {
    645             const FontMetrics& fontMetrics = curr->renderer()->style(isFirstLineStyle())->fontMetrics();
    646             newLogicalTop += curr->baselinePosition(baselineType) - fontMetrics.ascent(baselineType);
    647             if (curr->isInlineFlowBox()) {
    648                 RenderBoxModelObject* boxObject = toRenderBoxModelObject(curr->renderer());
    649                 newLogicalTop -= boxObject->style(isFirstLineStyle())->isHorizontalWritingMode() ? boxObject->borderTop() + boxObject->paddingTop() :
    650                                  boxObject->borderRight() + boxObject->paddingRight();
    651             }
    652             newLogicalTopIncludingMargins = newLogicalTop;
    653         } else if (!curr->renderer()->isBR()) {
    654             RenderBox* box = toRenderBox(curr->renderer());
    655             newLogicalTopIncludingMargins = newLogicalTop;
    656             LayoutUnit overSideMargin = curr->isHorizontal() ? box->marginTop() : box->marginRight();
    657             LayoutUnit underSideMargin = curr->isHorizontal() ? box->marginBottom() : box->marginLeft();
    658             newLogicalTop += overSideMargin;
    659             boxHeightIncludingMargins += overSideMargin + underSideMargin;
    660         }
    661 
    662         curr->setLogicalTop(newLogicalTop);
    663 
    664         if (childAffectsTopBottomPos) {
    665             if (curr->renderer()->isRubyRun()) {
    666                 // Treat the leading on the first and last lines of ruby runs as not being part of the overall lineTop/lineBottom.
    667                 // Really this is a workaround hack for the fact that ruby should have been done as line layout and not done using
    668                 // inline-block.
    669                 if (renderer()->style()->isFlippedLinesWritingMode() == (curr->renderer()->style()->rubyPosition() == RubyPositionAfter))
    670                     hasAnnotationsBefore = true;
    671                 else
    672                     hasAnnotationsAfter = true;
    673 
    674                 RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
    675                 if (RenderRubyBase* rubyBase = rubyRun->rubyBase()) {
    676                     LayoutUnit bottomRubyBaseLeading = (curr->logicalHeight() - rubyBase->logicalBottom()) + rubyBase->logicalHeight() - (rubyBase->lastRootBox() ? rubyBase->lastRootBox()->lineBottom() : LayoutUnit());
    677                     LayoutUnit topRubyBaseLeading = rubyBase->logicalTop() + (rubyBase->firstRootBox() ? rubyBase->firstRootBox()->lineTop() : LayoutUnit());
    678                     newLogicalTop += !renderer()->style()->isFlippedLinesWritingMode() ? topRubyBaseLeading : bottomRubyBaseLeading;
    679                     boxHeight -= (topRubyBaseLeading + bottomRubyBaseLeading);
    680                 }
    681             }
    682             if (curr->isInlineTextBox()) {
    683                 TextEmphasisPosition emphasisMarkPosition;
    684                 if (toInlineTextBox(curr)->getEmphasisMarkPosition(curr->renderer()->style(isFirstLineStyle()), emphasisMarkPosition)) {
    685                     bool emphasisMarkIsOver = emphasisMarkPosition == TextEmphasisPositionOver;
    686                     if (emphasisMarkIsOver != curr->renderer()->style(isFirstLineStyle())->isFlippedLinesWritingMode())
    687                         hasAnnotationsBefore = true;
    688                     else
    689                         hasAnnotationsAfter = true;
    690                 }
    691             }
    692 
    693             if (!setLineTop) {
    694                 setLineTop = true;
    695                 lineTop = newLogicalTop;
    696                 lineTopIncludingMargins = min(lineTop, newLogicalTopIncludingMargins);
    697             } else {
    698                 lineTop = min(lineTop, newLogicalTop);
    699                 lineTopIncludingMargins = min(lineTop, min(lineTopIncludingMargins, newLogicalTopIncludingMargins));
    700             }
    701             lineBottom = max(lineBottom, newLogicalTop + boxHeight);
    702             lineBottomIncludingMargins = max(lineBottom, max(lineBottomIncludingMargins, newLogicalTopIncludingMargins + boxHeightIncludingMargins));
    703         }
    704 
    705         // Adjust boxes to use their real box y/height and not the logical height (as dictated by
    706         // line-height).
    707         if (inlineFlowBox)
    708             inlineFlowBox->placeBoxesInBlockDirection(top, maxHeight, maxAscent, strictMode, lineTop, lineBottom, setLineTop,
    709                                                       lineTopIncludingMargins, lineBottomIncludingMargins, hasAnnotationsBefore, hasAnnotationsAfter, baselineType);
    710     }
    711 
    712     if (isRootBox) {
    713         if (strictMode || hasTextChildren() || (descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) {
    714             if (!setLineTop) {
    715                 setLineTop = true;
    716                 lineTop = pixelSnappedLogicalTop();
    717                 lineTopIncludingMargins = lineTop;
    718             } else {
    719                 lineTop = min<LayoutUnit>(lineTop, pixelSnappedLogicalTop());
    720                 lineTopIncludingMargins = min(lineTop, lineTopIncludingMargins);
    721             }
    722             lineBottom = max<LayoutUnit>(lineBottom, pixelSnappedLogicalBottom());
    723             lineBottomIncludingMargins = max(lineBottom, lineBottomIncludingMargins);
    724         }
    725 
    726         if (renderer()->style()->isFlippedLinesWritingMode())
    727             flipLinesInBlockDirection(lineTopIncludingMargins, lineBottomIncludingMargins);
    728     }
    729 }
    730 
    731 void InlineFlowBox::computeMaxLogicalTop(float& maxLogicalTop) const
    732 {
    733     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    734         if (curr->renderer()->isOutOfFlowPositioned())
    735             continue; // Positioned placeholders don't affect calculations.
    736 
    737         if (descendantsHaveSameLineHeightAndBaseline())
    738             continue;
    739 
    740         maxLogicalTop = max<float>(maxLogicalTop, curr->y());
    741         float localMaxLogicalTop = 0;
    742         if (curr->isInlineFlowBox())
    743             toInlineFlowBox(curr)->computeMaxLogicalTop(localMaxLogicalTop);
    744         maxLogicalTop = max<float>(maxLogicalTop, localMaxLogicalTop);
    745     }
    746 }
    747 
    748 void InlineFlowBox::flipLinesInBlockDirection(LayoutUnit lineTop, LayoutUnit lineBottom)
    749 {
    750     // Flip the box on the line such that the top is now relative to the lineBottom instead of the lineTop.
    751     setLogicalTop(lineBottom - (logicalTop() - lineTop) - logicalHeight());
    752 
    753     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    754         if (curr->renderer()->isOutOfFlowPositioned())
    755             continue; // Positioned placeholders aren't affected here.
    756 
    757         if (curr->isInlineFlowBox())
    758             toInlineFlowBox(curr)->flipLinesInBlockDirection(lineTop, lineBottom);
    759         else
    760             curr->setLogicalTop(lineBottom - (curr->logicalTop() - lineTop) - curr->logicalHeight());
    761     }
    762 }
    763 
    764 inline void InlineFlowBox::addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow)
    765 {
    766     // box-shadow on root line boxes is applying to the block and not to the lines.
    767     if (!parent())
    768         return;
    769 
    770     RenderStyle* style = renderer()->style(isFirstLineStyle());
    771     if (!style->boxShadow())
    772         return;
    773 
    774     LayoutUnit boxShadowLogicalTop;
    775     LayoutUnit boxShadowLogicalBottom;
    776     style->getBoxShadowBlockDirectionExtent(boxShadowLogicalTop, boxShadowLogicalBottom);
    777 
    778     // Similar to how glyph overflow works, if our lines are flipped, then it's actually the opposite shadow that applies, since
    779     // the line is "upside down" in terms of block coordinates.
    780     LayoutUnit shadowLogicalTop = style->isFlippedLinesWritingMode() ? -boxShadowLogicalBottom : boxShadowLogicalTop;
    781     LayoutUnit shadowLogicalBottom = style->isFlippedLinesWritingMode() ? -boxShadowLogicalTop : boxShadowLogicalBottom;
    782 
    783     LayoutUnit logicalTopVisualOverflow = min(pixelSnappedLogicalTop() + shadowLogicalTop, logicalVisualOverflow.y());
    784     LayoutUnit logicalBottomVisualOverflow = max(pixelSnappedLogicalBottom() + shadowLogicalBottom, logicalVisualOverflow.maxY());
    785 
    786     LayoutUnit boxShadowLogicalLeft;
    787     LayoutUnit boxShadowLogicalRight;
    788     style->getBoxShadowInlineDirectionExtent(boxShadowLogicalLeft, boxShadowLogicalRight);
    789 
    790     LayoutUnit logicalLeftVisualOverflow = min(pixelSnappedLogicalLeft() + boxShadowLogicalLeft, logicalVisualOverflow.x());
    791     LayoutUnit logicalRightVisualOverflow = max(pixelSnappedLogicalRight() + boxShadowLogicalRight, logicalVisualOverflow.maxX());
    792 
    793     logicalVisualOverflow = LayoutRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
    794                                        logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
    795 }
    796 
    797 inline void InlineFlowBox::addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow)
    798 {
    799     // border-image-outset on root line boxes is applying to the block and not to the lines.
    800     if (!parent())
    801         return;
    802 
    803     RenderStyle* style = renderer()->style(isFirstLineStyle());
    804     if (!style->hasBorderImageOutsets())
    805         return;
    806 
    807     LayoutBoxExtent borderOutsets = style->borderImageOutsets();
    808 
    809     LayoutUnit borderOutsetLogicalTop = borderOutsets.logicalTop(style->writingMode());
    810     LayoutUnit borderOutsetLogicalBottom = borderOutsets.logicalBottom(style->writingMode());
    811     LayoutUnit borderOutsetLogicalLeft = borderOutsets.logicalLeft(style->writingMode());
    812     LayoutUnit borderOutsetLogicalRight = borderOutsets.logicalRight(style->writingMode());
    813 
    814     // Similar to how glyph overflow works, if our lines are flipped, then it's actually the opposite border that applies, since
    815     // the line is "upside down" in terms of block coordinates. vertical-rl and horizontal-bt are the flipped line modes.
    816     LayoutUnit outsetLogicalTop = style->isFlippedLinesWritingMode() ? borderOutsetLogicalBottom : borderOutsetLogicalTop;
    817     LayoutUnit outsetLogicalBottom = style->isFlippedLinesWritingMode() ? borderOutsetLogicalTop : borderOutsetLogicalBottom;
    818 
    819     LayoutUnit logicalTopVisualOverflow = min(pixelSnappedLogicalTop() - outsetLogicalTop, logicalVisualOverflow.y());
    820     LayoutUnit logicalBottomVisualOverflow = max(pixelSnappedLogicalBottom() + outsetLogicalBottom, logicalVisualOverflow.maxY());
    821 
    822     LayoutUnit outsetLogicalLeft = includeLogicalLeftEdge() ? borderOutsetLogicalLeft : LayoutUnit();
    823     LayoutUnit outsetLogicalRight = includeLogicalRightEdge() ? borderOutsetLogicalRight : LayoutUnit();
    824 
    825     LayoutUnit logicalLeftVisualOverflow = min(pixelSnappedLogicalLeft() - outsetLogicalLeft, logicalVisualOverflow.x());
    826     LayoutUnit logicalRightVisualOverflow = max(pixelSnappedLogicalRight() + outsetLogicalRight, logicalVisualOverflow.maxX());
    827 
    828     logicalVisualOverflow = LayoutRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
    829                                        logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
    830 }
    831 
    832 inline void InlineFlowBox::addTextBoxVisualOverflow(InlineTextBox* textBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, LayoutRect& logicalVisualOverflow)
    833 {
    834     if (textBox->knownToHaveNoOverflow())
    835         return;
    836 
    837     RenderStyle* style = textBox->renderer()->style(isFirstLineStyle());
    838 
    839     GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(textBox);
    840     GlyphOverflow* glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->value.second;
    841     bool isFlippedLine = style->isFlippedLinesWritingMode();
    842 
    843     int topGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->bottom : glyphOverflow->top) : 0;
    844     int bottomGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->top : glyphOverflow->bottom) : 0;
    845     int leftGlyphEdge = glyphOverflow ? glyphOverflow->left : 0;
    846     int rightGlyphEdge = glyphOverflow ? glyphOverflow->right : 0;
    847 
    848     int strokeOverflow = static_cast<int>(ceilf(style->textStrokeWidth() / 2.0f));
    849     int topGlyphOverflow = -strokeOverflow - topGlyphEdge;
    850     int bottomGlyphOverflow = strokeOverflow + bottomGlyphEdge;
    851     int leftGlyphOverflow = -strokeOverflow - leftGlyphEdge;
    852     int rightGlyphOverflow = strokeOverflow + rightGlyphEdge;
    853 
    854     TextEmphasisPosition emphasisMarkPosition;
    855     if (style->textEmphasisMark() != TextEmphasisMarkNone && textBox->getEmphasisMarkPosition(style, emphasisMarkPosition)) {
    856         int emphasisMarkHeight = style->font().emphasisMarkHeight(style->textEmphasisMarkString());
    857         if ((emphasisMarkPosition == TextEmphasisPositionOver) == (!style->isFlippedLinesWritingMode()))
    858             topGlyphOverflow = min(topGlyphOverflow, -emphasisMarkHeight);
    859         else
    860             bottomGlyphOverflow = max(bottomGlyphOverflow, emphasisMarkHeight);
    861     }
    862 
    863     // If letter-spacing is negative, we should factor that into right layout overflow. (Even in RTL, letter-spacing is
    864     // applied to the right, so this is not an issue with left overflow.
    865     rightGlyphOverflow -= min(0, (int)style->font().letterSpacing());
    866 
    867     LayoutUnit textShadowLogicalTop;
    868     LayoutUnit textShadowLogicalBottom;
    869     style->getTextShadowBlockDirectionExtent(textShadowLogicalTop, textShadowLogicalBottom);
    870 
    871     LayoutUnit childOverflowLogicalTop = min<LayoutUnit>(textShadowLogicalTop + topGlyphOverflow, topGlyphOverflow);
    872     LayoutUnit childOverflowLogicalBottom = max<LayoutUnit>(textShadowLogicalBottom + bottomGlyphOverflow, bottomGlyphOverflow);
    873 
    874     LayoutUnit textShadowLogicalLeft;
    875     LayoutUnit textShadowLogicalRight;
    876     style->getTextShadowInlineDirectionExtent(textShadowLogicalLeft, textShadowLogicalRight);
    877 
    878     LayoutUnit childOverflowLogicalLeft = min<LayoutUnit>(textShadowLogicalLeft + leftGlyphOverflow, leftGlyphOverflow);
    879     LayoutUnit childOverflowLogicalRight = max<LayoutUnit>(textShadowLogicalRight + rightGlyphOverflow, rightGlyphOverflow);
    880 
    881     LayoutUnit logicalTopVisualOverflow = min(textBox->pixelSnappedLogicalTop() + childOverflowLogicalTop, logicalVisualOverflow.y());
    882     LayoutUnit logicalBottomVisualOverflow = max(textBox->pixelSnappedLogicalBottom() + childOverflowLogicalBottom, logicalVisualOverflow.maxY());
    883     LayoutUnit logicalLeftVisualOverflow = min(textBox->pixelSnappedLogicalLeft() + childOverflowLogicalLeft, logicalVisualOverflow.x());
    884     LayoutUnit logicalRightVisualOverflow = max(textBox->pixelSnappedLogicalRight() + childOverflowLogicalRight, logicalVisualOverflow.maxX());
    885 
    886     logicalVisualOverflow = LayoutRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
    887                                        logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
    888 
    889     textBox->setLogicalOverflowRect(logicalVisualOverflow);
    890 }
    891 
    892 inline void InlineFlowBox::addReplacedChildOverflow(const InlineBox* inlineBox, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow)
    893 {
    894     RenderBox* box = toRenderBox(inlineBox->renderer());
    895 
    896     // Visual overflow only propagates if the box doesn't have a self-painting layer.  This rectangle does not include
    897     // transforms or relative positioning (since those objects always have self-painting layers), but it does need to be adjusted
    898     // for writing-mode differences.
    899     if (!box->hasSelfPaintingLayer()) {
    900         LayoutRect childLogicalVisualOverflow = box->logicalVisualOverflowRectForPropagation(renderer()->style());
    901         childLogicalVisualOverflow.move(inlineBox->logicalLeft(), inlineBox->logicalTop());
    902         logicalVisualOverflow.unite(childLogicalVisualOverflow);
    903     }
    904 
    905     // Layout overflow internal to the child box only propagates if the child box doesn't have overflow clip set.
    906     // Otherwise the child border box propagates as layout overflow.  This rectangle must include transforms and relative positioning
    907     // and be adjusted for writing-mode differences.
    908     LayoutRect childLogicalLayoutOverflow = box->logicalLayoutOverflowRectForPropagation(renderer()->style());
    909     childLogicalLayoutOverflow.move(inlineBox->logicalLeft(), inlineBox->logicalTop());
    910     logicalLayoutOverflow.unite(childLogicalLayoutOverflow);
    911 }
    912 
    913 void InlineFlowBox::computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
    914 {
    915     // If we know we have no overflow, we can just bail.
    916     if (knownToHaveNoOverflow())
    917         return;
    918 
    919     // Visual overflow just includes overflow for stuff we need to repaint ourselves.  Self-painting layers are ignored.
    920     // Layout overflow is used to determine scrolling extent, so it still includes child layers and also factors in
    921     // transforms, relative positioning, etc.
    922     LayoutRect logicalLayoutOverflow(enclosingLayoutRect(logicalFrameRectIncludingLineHeight(lineTop, lineBottom)));
    923     LayoutRect logicalVisualOverflow(logicalLayoutOverflow);
    924 
    925     addBoxShadowVisualOverflow(logicalVisualOverflow);
    926     addBorderOutsetVisualOverflow(logicalVisualOverflow);
    927 
    928     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    929         if (curr->renderer()->isOutOfFlowPositioned())
    930             continue; // Positioned placeholders don't affect calculations.
    931 
    932         if (curr->renderer()->isText()) {
    933             InlineTextBox* text = toInlineTextBox(curr);
    934             RenderText* rt = toRenderText(text->renderer());
    935             if (rt->isBR())
    936                 continue;
    937             LayoutRect textBoxOverflow(enclosingLayoutRect(text->logicalFrameRect()));
    938             addTextBoxVisualOverflow(text, textBoxDataMap, textBoxOverflow);
    939             logicalVisualOverflow.unite(textBoxOverflow);
    940         } else  if (curr->renderer()->isRenderInline()) {
    941             InlineFlowBox* flow = toInlineFlowBox(curr);
    942             flow->computeOverflow(lineTop, lineBottom, textBoxDataMap);
    943             if (!flow->boxModelObject()->hasSelfPaintingLayer())
    944                 logicalVisualOverflow.unite(flow->logicalVisualOverflowRect(lineTop, lineBottom));
    945             LayoutRect childLayoutOverflow = flow->logicalLayoutOverflowRect(lineTop, lineBottom);
    946             childLayoutOverflow.move(flow->boxModelObject()->relativePositionLogicalOffset());
    947             logicalLayoutOverflow.unite(childLayoutOverflow);
    948         } else
    949             addReplacedChildOverflow(curr, logicalLayoutOverflow, logicalVisualOverflow);
    950     }
    951 
    952     setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, lineTop, lineBottom);
    953 }
    954 
    955 void InlineFlowBox::setLayoutOverflow(const LayoutRect& rect, LayoutUnit lineTop, LayoutUnit lineBottom)
    956 {
    957     LayoutRect frameBox = enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
    958     if (frameBox.contains(rect) || rect.isEmpty())
    959         return;
    960 
    961     if (!m_overflow)
    962         m_overflow = adoptPtr(new RenderOverflow(frameBox, frameBox));
    963 
    964     m_overflow->setLayoutOverflow(rect);
    965 }
    966 
    967 void InlineFlowBox::setVisualOverflow(const LayoutRect& rect, LayoutUnit lineTop, LayoutUnit lineBottom)
    968 {
    969     LayoutRect frameBox = enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
    970     if (frameBox.contains(rect) || rect.isEmpty())
    971         return;
    972 
    973     if (!m_overflow)
    974         m_overflow = adoptPtr(new RenderOverflow(frameBox, frameBox));
    975 
    976     m_overflow->setVisualOverflow(rect);
    977 }
    978 
    979 void InlineFlowBox::setOverflowFromLogicalRects(const LayoutRect& logicalLayoutOverflow, const LayoutRect& logicalVisualOverflow, LayoutUnit lineTop, LayoutUnit lineBottom)
    980 {
    981     LayoutRect layoutOverflow(isHorizontal() ? logicalLayoutOverflow : logicalLayoutOverflow.transposedRect());
    982     setLayoutOverflow(layoutOverflow, lineTop, lineBottom);
    983 
    984     LayoutRect visualOverflow(isHorizontal() ? logicalVisualOverflow : logicalVisualOverflow.transposedRect());
    985     setVisualOverflow(visualOverflow, lineTop, lineBottom);
    986 }
    987 
    988 bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
    989 {
    990     LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom));
    991     flipForWritingMode(overflowRect);
    992     overflowRect.moveBy(accumulatedOffset);
    993     if (!locationInContainer.intersects(overflowRect))
    994         return false;
    995 
    996     // Check children first.
    997     // We need to account for culled inline parents of the hit-tested nodes, so that they may also get included in area-based hit-tests.
    998     RenderObject* culledParent = 0;
    999     for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
   1000         if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) {
   1001             RenderObject* newParent = 0;
   1002             // Culled parents are only relevant for area-based hit-tests, so ignore it in point-based ones.
   1003             if (locationInContainer.isRectBasedTest()) {
   1004                 newParent = curr->renderer()->parent();
   1005                 if (newParent == renderer())
   1006                     newParent = 0;
   1007             }
   1008             // Check the culled parent after all its children have been checked, to do this we wait until
   1009             // we are about to test an element with a different parent.
   1010             if (newParent != culledParent) {
   1011                 if (!newParent || !newParent->isDescendantOf(culledParent)) {
   1012                     while (culledParent && culledParent != renderer() && culledParent != newParent) {
   1013                         if (culledParent->isRenderInline() && toRenderInline(culledParent)->hitTestCulledInline(request, result, locationInContainer, accumulatedOffset))
   1014                             return true;
   1015                         culledParent = culledParent->parent();
   1016                     }
   1017                 }
   1018                 culledParent = newParent;
   1019             }
   1020             if (curr->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, lineTop, lineBottom)) {
   1021                 renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
   1022                 return true;
   1023             }
   1024         }
   1025     }
   1026     // Check any culled ancestor of the final children tested.
   1027     while (culledParent && culledParent != renderer()) {
   1028         if (culledParent->isRenderInline() && toRenderInline(culledParent)->hitTestCulledInline(request, result, locationInContainer, accumulatedOffset))
   1029             return true;
   1030         culledParent = culledParent->parent();
   1031     }
   1032 
   1033     // Now check ourselves. Pixel snap hit testing.
   1034     LayoutRect frameRect = roundedFrameRect();
   1035     LayoutUnit minX = frameRect.x();
   1036     LayoutUnit minY = frameRect.y();
   1037     LayoutUnit width = frameRect.width();
   1038     LayoutUnit height = frameRect.height();
   1039 
   1040     // Constrain our hit testing to the line top and bottom if necessary.
   1041     bool noQuirksMode = renderer()->document().inNoQuirksMode();
   1042     if (!noQuirksMode && !hasTextChildren() && !(descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) {
   1043         RootInlineBox* rootBox = root();
   1044         LayoutUnit& top = isHorizontal() ? minY : minX;
   1045         LayoutUnit& logicalHeight = isHorizontal() ? height : width;
   1046         LayoutUnit bottom = min(rootBox->lineBottom(), top + logicalHeight);
   1047         top = max(rootBox->lineTop(), top);
   1048         logicalHeight = bottom - top;
   1049     }
   1050 
   1051     // Move x/y to our coordinates.
   1052     LayoutRect rect(minX, minY, width, height);
   1053     flipForWritingMode(rect);
   1054     rect.moveBy(accumulatedOffset);
   1055 
   1056     if (visibleToHitTestRequest(request) && locationInContainer.intersects(rect)) {
   1057         renderer()->updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset))); // Don't add in m_x or m_y here, we want coords in the containing block's space.
   1058         if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
   1059             return true;
   1060     }
   1061 
   1062     return false;
   1063 }
   1064 
   1065 void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
   1066 {
   1067     LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom));
   1068     overflowRect.inflate(renderer()->maximalOutlineSize(paintInfo.phase));
   1069     flipForWritingMode(overflowRect);
   1070     overflowRect.moveBy(paintOffset);
   1071 
   1072     if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
   1073         return;
   1074 
   1075     if (paintInfo.phase != PaintPhaseChildOutlines) {
   1076         if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
   1077             // Add ourselves to the paint info struct's list of inlines that need to paint their
   1078             // outlines.
   1079             if (renderer()->style()->visibility() == VISIBLE && renderer()->hasOutline() && !isRootInlineBox()) {
   1080                 RenderInline* inlineFlow = toRenderInline(renderer());
   1081 
   1082                 RenderBlock* cb = 0;
   1083                 bool containingBlockPaintsContinuationOutline = inlineFlow->continuation() || inlineFlow->isInlineElementContinuation();
   1084                 if (containingBlockPaintsContinuationOutline) {
   1085                     // FIXME: See https://bugs.webkit.org/show_bug.cgi?id=54690. We currently don't reconnect inline continuations
   1086                     // after a child removal. As a result, those merged inlines do not get seperated and hence not get enclosed by
   1087                     // anonymous blocks. In this case, it is better to bail out and paint it ourself.
   1088                     RenderBlock* enclosingAnonymousBlock = renderer()->containingBlock();
   1089                     if (!enclosingAnonymousBlock->isAnonymousBlock())
   1090                         containingBlockPaintsContinuationOutline = false;
   1091                     else {
   1092                         cb = enclosingAnonymousBlock->containingBlock();
   1093                         for (RenderBoxModelObject* box = boxModelObject(); box != cb; box = box->parent()->enclosingBoxModelObject()) {
   1094                             if (box->hasSelfPaintingLayer()) {
   1095                                 containingBlockPaintsContinuationOutline = false;
   1096                                 break;
   1097                             }
   1098                         }
   1099                     }
   1100                 }
   1101 
   1102                 if (containingBlockPaintsContinuationOutline) {
   1103                     // Add ourselves to the containing block of the entire continuation so that it can
   1104                     // paint us atomically.
   1105                     cb->addContinuationWithOutline(toRenderInline(renderer()->node()->renderer()));
   1106                 } else if (!inlineFlow->isInlineElementContinuation()) {
   1107                     paintInfo.outlineObjects()->add(inlineFlow);
   1108                 }
   1109             }
   1110         } else if (paintInfo.phase == PaintPhaseMask) {
   1111             paintMask(paintInfo, paintOffset);
   1112             return;
   1113         } else {
   1114             // Paint our background, border and box-shadow.
   1115             paintBoxDecorations(paintInfo, paintOffset);
   1116         }
   1117     }
   1118 
   1119     if (paintInfo.phase == PaintPhaseMask)
   1120         return;
   1121 
   1122     PaintPhase paintPhase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;
   1123     PaintInfo childInfo(paintInfo);
   1124     childInfo.phase = paintPhase;
   1125     childInfo.updatePaintingRootForChildren(renderer());
   1126 
   1127     // Paint our children.
   1128     if (paintPhase != PaintPhaseSelfOutline) {
   1129         for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
   1130             if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer())
   1131                 curr->paint(childInfo, paintOffset, lineTop, lineBottom);
   1132         }
   1133     }
   1134 }
   1135 
   1136 void InlineFlowBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect, CompositeOperator op)
   1137 {
   1138     if (!fillLayer)
   1139         return;
   1140     paintFillLayers(paintInfo, c, fillLayer->next(), rect, op);
   1141     paintFillLayer(paintInfo, c, fillLayer, rect, op);
   1142 }
   1143 
   1144 bool InlineFlowBox::boxShadowCanBeAppliedToBackground(const FillLayer& lastBackgroundLayer) const
   1145 {
   1146     // The checks here match how paintFillLayer() decides whether to clip (if it does, the shadow
   1147     // would be clipped out, so it has to be drawn separately).
   1148     StyleImage* image = lastBackgroundLayer.image();
   1149     bool hasFillImage = image && image->canRender(renderer(), renderer()->style()->effectiveZoom());
   1150     return (!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent();
   1151 }
   1152 
   1153 void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect, CompositeOperator op)
   1154 {
   1155     StyleImage* img = fillLayer->image();
   1156     bool hasFillImage = img && img->canRender(renderer(), renderer()->style()->effectiveZoom());
   1157     if ((!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
   1158         boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, rect, BackgroundBleedNone, this, rect.size(), op);
   1159     else if (renderer()->style()->boxDecorationBreak() == DCLONE) {
   1160         GraphicsContextStateSaver stateSaver(*paintInfo.context);
   1161         paintInfo.context->clip(LayoutRect(rect.x(), rect.y(), width(), height()));
   1162         boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, rect, BackgroundBleedNone, this, rect.size(), op);
   1163     } else {
   1164         // We have a fill image that spans multiple lines.
   1165         // We need to adjust tx and ty by the width of all previous lines.
   1166         // Think of background painting on inlines as though you had one long line, a single continuous
   1167         // strip.  Even though that strip has been broken up across multiple lines, you still paint it
   1168         // as though you had one single line.  This means each line has to pick up the background where
   1169         // the previous line left off.
   1170         LayoutUnit logicalOffsetOnLine = 0;
   1171         LayoutUnit totalLogicalWidth;
   1172         if (renderer()->style()->direction() == LTR) {
   1173             for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
   1174                 logicalOffsetOnLine += curr->logicalWidth();
   1175             totalLogicalWidth = logicalOffsetOnLine;
   1176             for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
   1177                 totalLogicalWidth += curr->logicalWidth();
   1178         } else {
   1179             for (InlineFlowBox* curr = nextLineBox(); curr; curr = curr->nextLineBox())
   1180                 logicalOffsetOnLine += curr->logicalWidth();
   1181             totalLogicalWidth = logicalOffsetOnLine;
   1182             for (InlineFlowBox* curr = this; curr; curr = curr->prevLineBox())
   1183                 totalLogicalWidth += curr->logicalWidth();
   1184         }
   1185         LayoutUnit stripX = rect.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
   1186         LayoutUnit stripY = rect.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
   1187         LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : static_cast<LayoutUnit>(width());
   1188         LayoutUnit stripHeight = isHorizontal() ? static_cast<LayoutUnit>(height()) : totalLogicalWidth;
   1189 
   1190         GraphicsContextStateSaver stateSaver(*paintInfo.context);
   1191         paintInfo.context->clip(LayoutRect(rect.x(), rect.y(), width(), height()));
   1192         boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, LayoutRect(stripX, stripY, stripWidth, stripHeight), BackgroundBleedNone, this, rect.size(), op);
   1193     }
   1194 }
   1195 
   1196 void InlineFlowBox::paintBoxShadow(const PaintInfo& info, RenderStyle* s, ShadowStyle shadowStyle, const LayoutRect& paintRect)
   1197 {
   1198     if ((!prevLineBox() && !nextLineBox()) || !parent())
   1199         boxModelObject()->paintBoxShadow(info, paintRect, s, shadowStyle);
   1200     else {
   1201         // FIXME: We can do better here in the multi-line case. We want to push a clip so that the shadow doesn't
   1202         // protrude incorrectly at the edges, and we want to possibly include shadows cast from the previous/following lines
   1203         boxModelObject()->paintBoxShadow(info, paintRect, s, shadowStyle, includeLogicalLeftEdge(), includeLogicalRightEdge());
   1204     }
   1205 }
   1206 
   1207 void InlineFlowBox::constrainToLineTopAndBottomIfNeeded(LayoutRect& rect) const
   1208 {
   1209     bool noQuirksMode = renderer()->document().inNoQuirksMode();
   1210     if (!noQuirksMode && !hasTextChildren() && !(descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) {
   1211         const RootInlineBox* rootBox = root();
   1212         LayoutUnit logicalTop = isHorizontal() ? rect.y() : rect.x();
   1213         LayoutUnit logicalHeight = isHorizontal() ? rect.height() : rect.width();
   1214         LayoutUnit bottom = min(rootBox->lineBottom(), logicalTop + logicalHeight);
   1215         logicalTop = max(rootBox->lineTop(), logicalTop);
   1216         logicalHeight = bottom - logicalTop;
   1217         if (isHorizontal()) {
   1218             rect.setY(logicalTop);
   1219             rect.setHeight(logicalHeight);
   1220         } else {
   1221             rect.setX(logicalTop);
   1222             rect.setWidth(logicalHeight);
   1223         }
   1224     }
   1225 }
   1226 
   1227 static LayoutRect clipRectForNinePieceImageStrip(InlineFlowBox* box, const NinePieceImage& image, const LayoutRect& paintRect)
   1228 {
   1229     LayoutRect clipRect(paintRect);
   1230     RenderStyle* style = box->renderer()->style();
   1231     LayoutBoxExtent outsets = style->imageOutsets(image);
   1232     if (box->isHorizontal()) {
   1233         clipRect.setY(paintRect.y() - outsets.top());
   1234         clipRect.setHeight(paintRect.height() + outsets.top() + outsets.bottom());
   1235         if (box->includeLogicalLeftEdge()) {
   1236             clipRect.setX(paintRect.x() - outsets.left());
   1237             clipRect.setWidth(paintRect.width() + outsets.left());
   1238         }
   1239         if (box->includeLogicalRightEdge())
   1240             clipRect.setWidth(clipRect.width() + outsets.right());
   1241     } else {
   1242         clipRect.setX(paintRect.x() - outsets.left());
   1243         clipRect.setWidth(paintRect.width() + outsets.left() + outsets.right());
   1244         if (box->includeLogicalLeftEdge()) {
   1245             clipRect.setY(paintRect.y() - outsets.top());
   1246             clipRect.setHeight(paintRect.height() + outsets.top());
   1247         }
   1248         if (box->includeLogicalRightEdge())
   1249             clipRect.setHeight(clipRect.height() + outsets.bottom());
   1250     }
   1251     return clipRect;
   1252 }
   1253 
   1254 void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
   1255 {
   1256     if (!paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
   1257         return;
   1258 
   1259     // Pixel snap background/border painting.
   1260     LayoutRect frameRect = roundedFrameRect();
   1261 
   1262     constrainToLineTopAndBottomIfNeeded(frameRect);
   1263 
   1264     // Move x/y to our coordinates.
   1265     LayoutRect localRect(frameRect);
   1266     flipForWritingMode(localRect);
   1267     LayoutPoint adjustedPaintoffset = paintOffset + localRect.location();
   1268 
   1269     GraphicsContext* context = paintInfo.context;
   1270 
   1271     // You can use p::first-line to specify a background. If so, the root line boxes for
   1272     // a line may actually have to paint a background.
   1273     RenderStyle* styleToUse = renderer()->style(isFirstLineStyle());
   1274     if ((!parent() && isFirstLineStyle() && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) {
   1275         LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size());
   1276         // Shadow comes first and is behind the background and border.
   1277         if (!boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone, this))
   1278             paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
   1279 
   1280         Color c = renderer()->resolveColor(styleToUse, CSSPropertyBackgroundColor);
   1281         paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), paintRect);
   1282         paintBoxShadow(paintInfo, styleToUse, Inset, paintRect);
   1283 
   1284         // :first-line cannot be used to put borders on a line. Always paint borders with our
   1285         // non-first-line style.
   1286         if (parent() && renderer()->style()->hasBorder()) {
   1287             const NinePieceImage& borderImage = renderer()->style()->borderImage();
   1288             StyleImage* borderImageSource = borderImage.image();
   1289             bool hasBorderImage = borderImageSource && borderImageSource->canRender(renderer(), styleToUse->effectiveZoom());
   1290             if (hasBorderImage && !borderImageSource->isLoaded())
   1291                 return; // Don't paint anything while we wait for the image to load.
   1292 
   1293             // The simple case is where we either have no border image or we are the only box for this object.  In those
   1294             // cases only a single call to draw is required.
   1295             if (!hasBorderImage || (!prevLineBox() && !nextLineBox()))
   1296                 boxModelObject()->paintBorder(paintInfo, paintRect, renderer()->style(isFirstLineStyle()), BackgroundBleedNone, includeLogicalLeftEdge(), includeLogicalRightEdge());
   1297             else {
   1298                 // We have a border image that spans multiple lines.
   1299                 // We need to adjust tx and ty by the width of all previous lines.
   1300                 // Think of border image painting on inlines as though you had one long line, a single continuous
   1301                 // strip.  Even though that strip has been broken up across multiple lines, you still paint it
   1302                 // as though you had one single line.  This means each line has to pick up the image where
   1303                 // the previous line left off.
   1304                 // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
   1305                 // but it isn't even clear how this should work at all.
   1306                 LayoutUnit logicalOffsetOnLine = 0;
   1307                 for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
   1308                     logicalOffsetOnLine += curr->logicalWidth();
   1309                 LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
   1310                 for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
   1311                     totalLogicalWidth += curr->logicalWidth();
   1312                 LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
   1313                 LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
   1314                 LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
   1315                 LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
   1316 
   1317                 LayoutRect clipRect = clipRectForNinePieceImageStrip(this, borderImage, paintRect);
   1318                 GraphicsContextStateSaver stateSaver(*context);
   1319                 context->clip(clipRect);
   1320                 boxModelObject()->paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer()->style(isFirstLineStyle()));
   1321             }
   1322         }
   1323     }
   1324 }
   1325 
   1326 void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
   1327 {
   1328     if (!paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
   1329         return;
   1330 
   1331     // Pixel snap mask painting.
   1332     LayoutRect frameRect = roundedFrameRect();
   1333 
   1334     constrainToLineTopAndBottomIfNeeded(frameRect);
   1335 
   1336     // Move x/y to our coordinates.
   1337     LayoutRect localRect(frameRect);
   1338     flipForWritingMode(localRect);
   1339     LayoutPoint adjustedPaintOffset = paintOffset + localRect.location();
   1340 
   1341     const NinePieceImage& maskNinePieceImage = renderer()->style()->maskBoxImage();
   1342     StyleImage* maskBoxImage = renderer()->style()->maskBoxImage().image();
   1343 
   1344     // Figure out if we need to push a transparency layer to render our mask.
   1345     bool pushTransparencyLayer = false;
   1346     bool compositedMask = renderer()->hasLayer() && boxModelObject()->layer()->hasCompositedMask();
   1347     bool flattenCompositingLayers = renderer()->view()->frameView() && renderer()->view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
   1348     CompositeOperator compositeOp = CompositeSourceOver;
   1349     if (!compositedMask || flattenCompositingLayers) {
   1350         if ((maskBoxImage && renderer()->style()->maskLayers()->hasImage()) || renderer()->style()->maskLayers()->next())
   1351             pushTransparencyLayer = true;
   1352 
   1353         compositeOp = CompositeDestinationIn;
   1354         if (pushTransparencyLayer) {
   1355             paintInfo.context->setCompositeOperation(CompositeDestinationIn);
   1356             paintInfo.context->beginTransparencyLayer(1.0f);
   1357             compositeOp = CompositeSourceOver;
   1358         }
   1359     }
   1360 
   1361     LayoutRect paintRect = LayoutRect(adjustedPaintOffset, frameRect.size());
   1362     paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), paintRect, compositeOp);
   1363 
   1364     bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer(), renderer()->style()->effectiveZoom());
   1365     if (!hasBoxImage || !maskBoxImage->isLoaded()) {
   1366         if (pushTransparencyLayer)
   1367             paintInfo.context->endLayer();
   1368         return; // Don't paint anything while we wait for the image to load.
   1369     }
   1370 
   1371     // The simple case is where we are the only box for this object.  In those
   1372     // cases only a single call to draw is required.
   1373     if (!prevLineBox() && !nextLineBox()) {
   1374         boxModelObject()->paintNinePieceImage(paintInfo.context, LayoutRect(adjustedPaintOffset, frameRect.size()), renderer()->style(), maskNinePieceImage, compositeOp);
   1375     } else {
   1376         // We have a mask image that spans multiple lines.
   1377         // We need to adjust _tx and _ty by the width of all previous lines.
   1378         LayoutUnit logicalOffsetOnLine = 0;
   1379         for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
   1380             logicalOffsetOnLine += curr->logicalWidth();
   1381         LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
   1382         for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
   1383             totalLogicalWidth += curr->logicalWidth();
   1384         LayoutUnit stripX = adjustedPaintOffset.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
   1385         LayoutUnit stripY = adjustedPaintOffset.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
   1386         LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
   1387         LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
   1388 
   1389         LayoutRect clipRect = clipRectForNinePieceImageStrip(this, maskNinePieceImage, paintRect);
   1390         GraphicsContextStateSaver stateSaver(*paintInfo.context);
   1391         paintInfo.context->clip(clipRect);
   1392         boxModelObject()->paintNinePieceImage(paintInfo.context, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer()->style(), maskNinePieceImage, compositeOp);
   1393     }
   1394 
   1395     if (pushTransparencyLayer)
   1396         paintInfo.context->endLayer();
   1397 }
   1398 
   1399 InlineBox* InlineFlowBox::firstLeafChild() const
   1400 {
   1401     InlineBox* leaf = 0;
   1402     for (InlineBox* child = firstChild(); child && !leaf; child = child->nextOnLine())
   1403         leaf = child->isLeaf() ? child : toInlineFlowBox(child)->firstLeafChild();
   1404     return leaf;
   1405 }
   1406 
   1407 InlineBox* InlineFlowBox::lastLeafChild() const
   1408 {
   1409     InlineBox* leaf = 0;
   1410     for (InlineBox* child = lastChild(); child && !leaf; child = child->prevOnLine())
   1411         leaf = child->isLeaf() ? child : toInlineFlowBox(child)->lastLeafChild();
   1412     return leaf;
   1413 }
   1414 
   1415 RenderObject::SelectionState InlineFlowBox::selectionState()
   1416 {
   1417     return RenderObject::SelectionNone;
   1418 }
   1419 
   1420 bool InlineFlowBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const
   1421 {
   1422     for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {
   1423         if (!box->canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth))
   1424             return false;
   1425     }
   1426     return true;
   1427 }
   1428 
   1429 float InlineFlowBox::placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox)
   1430 {
   1431     float result = -1;
   1432     // We iterate over all children, the foundBox variable tells us when we've found the
   1433     // box containing the ellipsis.  All boxes after that one in the flow are hidden.
   1434     // If our flow is ltr then iterate over the boxes from left to right, otherwise iterate
   1435     // from right to left. Varying the order allows us to correctly hide the boxes following the ellipsis.
   1436     InlineBox* box = ltr ? firstChild() : lastChild();
   1437 
   1438     // NOTE: these will cross after foundBox = true.
   1439     int visibleLeftEdge = blockLeftEdge;
   1440     int visibleRightEdge = blockRightEdge;
   1441 
   1442     while (box) {
   1443         int currResult = box->placeEllipsisBox(ltr, visibleLeftEdge, visibleRightEdge, ellipsisWidth, truncatedWidth, foundBox);
   1444         if (currResult != -1 && result == -1)
   1445             result = currResult;
   1446 
   1447         if (ltr) {
   1448             visibleLeftEdge += box->logicalWidth();
   1449             box = box->nextOnLine();
   1450         }
   1451         else {
   1452             visibleRightEdge -= box->logicalWidth();
   1453             box = box->prevOnLine();
   1454         }
   1455     }
   1456     return result;
   1457 }
   1458 
   1459 void InlineFlowBox::clearTruncation()
   1460 {
   1461     for (InlineBox *box = firstChild(); box; box = box->nextOnLine())
   1462         box->clearTruncation();
   1463 }
   1464 
   1465 LayoutUnit InlineFlowBox::computeOverAnnotationAdjustment(LayoutUnit allowedPosition) const
   1466 {
   1467     LayoutUnit result = 0;
   1468     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
   1469         if (curr->renderer()->isOutOfFlowPositioned())
   1470             continue; // Positioned placeholders don't affect calculations.
   1471 
   1472         if (curr->isInlineFlowBox())
   1473             result = max(result, toInlineFlowBox(curr)->computeOverAnnotationAdjustment(allowedPosition));
   1474 
   1475         if (curr->renderer()->isReplaced() && curr->renderer()->isRubyRun() && curr->renderer()->style()->rubyPosition() == RubyPositionBefore) {
   1476             RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
   1477             RenderRubyText* rubyText = rubyRun->rubyText();
   1478             if (!rubyText)
   1479                 continue;
   1480 
   1481             if (!rubyRun->style()->isFlippedLinesWritingMode()) {
   1482                 LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit());
   1483                 if (topOfFirstRubyTextLine >= 0)
   1484                     continue;
   1485                 topOfFirstRubyTextLine += curr->logicalTop();
   1486                 result = max(result, allowedPosition - topOfFirstRubyTextLine);
   1487             } else {
   1488                 LayoutUnit bottomOfLastRubyTextLine = rubyText->logicalTop() + (rubyText->lastRootBox() ? rubyText->lastRootBox()->lineBottom() : rubyText->logicalHeight());
   1489                 if (bottomOfLastRubyTextLine <= curr->logicalHeight())
   1490                     continue;
   1491                 bottomOfLastRubyTextLine += curr->logicalTop();
   1492                 result = max(result, bottomOfLastRubyTextLine - allowedPosition);
   1493             }
   1494         }
   1495 
   1496         if (curr->isInlineTextBox()) {
   1497             RenderStyle* style = curr->renderer()->style(isFirstLineStyle());
   1498             TextEmphasisPosition emphasisMarkPosition;
   1499             if (style->textEmphasisMark() != TextEmphasisMarkNone && toInlineTextBox(curr)->getEmphasisMarkPosition(style, emphasisMarkPosition) && emphasisMarkPosition == TextEmphasisPositionOver) {
   1500                 if (!style->isFlippedLinesWritingMode()) {
   1501                     int topOfEmphasisMark = curr->logicalTop() - style->font().emphasisMarkHeight(style->textEmphasisMarkString());
   1502                     result = max(result, allowedPosition - topOfEmphasisMark);
   1503                 } else {
   1504                     int bottomOfEmphasisMark = curr->logicalBottom() + style->font().emphasisMarkHeight(style->textEmphasisMarkString());
   1505                     result = max(result, bottomOfEmphasisMark - allowedPosition);
   1506                 }
   1507             }
   1508         }
   1509     }
   1510     return result;
   1511 }
   1512 
   1513 LayoutUnit InlineFlowBox::computeUnderAnnotationAdjustment(LayoutUnit allowedPosition) const
   1514 {
   1515     LayoutUnit result = 0;
   1516     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
   1517         if (curr->renderer()->isOutOfFlowPositioned())
   1518             continue; // Positioned placeholders don't affect calculations.
   1519 
   1520         if (curr->isInlineFlowBox())
   1521             result = max(result, toInlineFlowBox(curr)->computeUnderAnnotationAdjustment(allowedPosition));
   1522 
   1523         if (curr->renderer()->isReplaced() && curr->renderer()->isRubyRun() && curr->renderer()->style()->rubyPosition() == RubyPositionAfter) {
   1524             RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
   1525             RenderRubyText* rubyText = rubyRun->rubyText();
   1526             if (!rubyText)
   1527                 continue;
   1528 
   1529             if (rubyRun->style()->isFlippedLinesWritingMode()) {
   1530                 LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit());
   1531                 if (topOfFirstRubyTextLine >= 0)
   1532                     continue;
   1533                 topOfFirstRubyTextLine += curr->logicalTop();
   1534                 result = max(result, allowedPosition - topOfFirstRubyTextLine);
   1535             } else {
   1536                 LayoutUnit bottomOfLastRubyTextLine = rubyText->logicalTop() + (rubyText->lastRootBox() ? rubyText->lastRootBox()->lineBottom() : rubyText->logicalHeight());
   1537                 if (bottomOfLastRubyTextLine <= curr->logicalHeight())
   1538                     continue;
   1539                 bottomOfLastRubyTextLine += curr->logicalTop();
   1540                 result = max(result, bottomOfLastRubyTextLine - allowedPosition);
   1541             }
   1542         }
   1543 
   1544         if (curr->isInlineTextBox()) {
   1545             RenderStyle* style = curr->renderer()->style(isFirstLineStyle());
   1546             if (style->textEmphasisMark() != TextEmphasisMarkNone && style->textEmphasisPosition() == TextEmphasisPositionUnder) {
   1547                 if (!style->isFlippedLinesWritingMode()) {
   1548                     LayoutUnit bottomOfEmphasisMark = curr->logicalBottom() + style->font().emphasisMarkHeight(style->textEmphasisMarkString());
   1549                     result = max(result, bottomOfEmphasisMark - allowedPosition);
   1550                 } else {
   1551                     LayoutUnit topOfEmphasisMark = curr->logicalTop() - style->font().emphasisMarkHeight(style->textEmphasisMarkString());
   1552                     result = max(result, allowedPosition - topOfEmphasisMark);
   1553                 }
   1554             }
   1555         }
   1556     }
   1557     return result;
   1558 }
   1559 
   1560 void InlineFlowBox::collectLeafBoxesInLogicalOrder(Vector<InlineBox*>& leafBoxesInLogicalOrder, CustomInlineBoxRangeReverse customReverseImplementation, void* userData) const
   1561 {
   1562     InlineBox* leaf = firstLeafChild();
   1563 
   1564     // FIXME: The reordering code is a copy of parts from BidiResolver::createBidiRunsForLine, operating directly on InlineBoxes, instead of BidiRuns.
   1565     // Investigate on how this code could possibly be shared.
   1566     unsigned char minLevel = 128;
   1567     unsigned char maxLevel = 0;
   1568 
   1569     // First find highest and lowest levels, and initialize leafBoxesInLogicalOrder with the leaf boxes in visual order.
   1570     for (; leaf; leaf = leaf->nextLeafChild()) {
   1571         minLevel = min(minLevel, leaf->bidiLevel());
   1572         maxLevel = max(maxLevel, leaf->bidiLevel());
   1573         leafBoxesInLogicalOrder.append(leaf);
   1574     }
   1575 
   1576     if (renderer()->style()->rtlOrdering() == VisualOrder)
   1577         return;
   1578 
   1579     // Reverse of reordering of the line (L2 according to Bidi spec):
   1580     // L2. From the highest level found in the text to the lowest odd level on each line,
   1581     // reverse any contiguous sequence of characters that are at that level or higher.
   1582 
   1583     // Reversing the reordering of the line is only done up to the lowest odd level.
   1584     if (!(minLevel % 2))
   1585         ++minLevel;
   1586 
   1587     Vector<InlineBox*>::iterator end = leafBoxesInLogicalOrder.end();
   1588     while (minLevel <= maxLevel) {
   1589         Vector<InlineBox*>::iterator it = leafBoxesInLogicalOrder.begin();
   1590         while (it != end) {
   1591             while (it != end) {
   1592                 if ((*it)->bidiLevel() >= minLevel)
   1593                     break;
   1594                 ++it;
   1595             }
   1596             Vector<InlineBox*>::iterator first = it;
   1597             while (it != end) {
   1598                 if ((*it)->bidiLevel() < minLevel)
   1599                     break;
   1600                 ++it;
   1601             }
   1602             Vector<InlineBox*>::iterator last = it;
   1603             if (customReverseImplementation) {
   1604                 ASSERT(userData);
   1605                 (*customReverseImplementation)(userData, first, last);
   1606             } else
   1607                 std::reverse(first, last);
   1608         }
   1609         ++minLevel;
   1610     }
   1611 }
   1612 
   1613 #ifndef NDEBUG
   1614 
   1615 const char* InlineFlowBox::boxName() const
   1616 {
   1617     return "InlineFlowBox";
   1618 }
   1619 
   1620 void InlineFlowBox::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const RenderObject* obj, int depth) const
   1621 {
   1622     InlineBox::showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLabel2, obj, depth);
   1623     for (const InlineBox* box = firstChild(); box; box = box->nextOnLine())
   1624         box->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLabel2, obj, depth + 1);
   1625 }
   1626 
   1627 void InlineFlowBox::checkConsistency() const
   1628 {
   1629 #ifdef CHECK_CONSISTENCY
   1630     ASSERT(!m_hasBadChildList);
   1631     const InlineBox* prev = 0;
   1632     for (const InlineBox* child = m_firstChild; child; child = child->nextOnLine()) {
   1633         ASSERT(child->parent() == this);
   1634         ASSERT(child->prevOnLine() == prev);
   1635         prev = child;
   1636     }
   1637     ASSERT(prev == m_lastChild);
   1638 #endif
   1639 }
   1640 
   1641 #endif
   1642 
   1643 } // namespace WebCore
   1644