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/platform/graphics/Font.h"
     26 #include "core/platform/graphics/GraphicsContextStateSaver.h"
     27 #include "core/rendering/HitTestResult.h"
     28 #include "core/rendering/InlineTextBox.h"
     29 #include "core/rendering/RenderBlock.h"
     30 #include "core/rendering/RenderInline.h"
     31 #include "core/rendering/RenderLayer.h"
     32 #include "core/rendering/RenderListMarker.h"
     33 #include "core/rendering/RenderRubyBase.h"
     34 #include "core/rendering/RenderRubyRun.h"
     35 #include "core/rendering/RenderRubyText.h"
     36 #include "core/rendering/RenderView.h"
     37 #include "core/rendering/RootInlineBox.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 #if ENABLE(CSS3_TEXT)
    732 void InlineFlowBox::computeMaxLogicalTop(float& maxLogicalTop) const
    733 {
    734     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    735         if (curr->renderer()->isOutOfFlowPositioned())
    736             continue; // Positioned placeholders don't affect calculations.
    737 
    738         if (descendantsHaveSameLineHeightAndBaseline())
    739             continue;
    740 
    741         maxLogicalTop = max<float>(maxLogicalTop, curr->y());
    742         float localMaxLogicalTop = 0;
    743         if (curr->isInlineFlowBox())
    744             toInlineFlowBox(curr)->computeMaxLogicalTop(localMaxLogicalTop);
    745         maxLogicalTop = max<float>(maxLogicalTop, localMaxLogicalTop);
    746     }
    747 }
    748 #endif // CSS3_TEXT
    749 
    750 void InlineFlowBox::flipLinesInBlockDirection(LayoutUnit lineTop, LayoutUnit lineBottom)
    751 {
    752     // Flip the box on the line such that the top is now relative to the lineBottom instead of the lineTop.
    753     setLogicalTop(lineBottom - (logicalTop() - lineTop) - logicalHeight());
    754 
    755     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    756         if (curr->renderer()->isOutOfFlowPositioned())
    757             continue; // Positioned placeholders aren't affected here.
    758 
    759         if (curr->isInlineFlowBox())
    760             toInlineFlowBox(curr)->flipLinesInBlockDirection(lineTop, lineBottom);
    761         else
    762             curr->setLogicalTop(lineBottom - (curr->logicalTop() - lineTop) - curr->logicalHeight());
    763     }
    764 }
    765 
    766 inline void InlineFlowBox::addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow)
    767 {
    768     // box-shadow on root line boxes is applying to the block and not to the lines.
    769     if (!parent())
    770         return;
    771 
    772     RenderStyle* style = renderer()->style(isFirstLineStyle());
    773     if (!style->boxShadow())
    774         return;
    775 
    776     LayoutUnit boxShadowLogicalTop;
    777     LayoutUnit boxShadowLogicalBottom;
    778     style->getBoxShadowBlockDirectionExtent(boxShadowLogicalTop, boxShadowLogicalBottom);
    779 
    780     // Similar to how glyph overflow works, if our lines are flipped, then it's actually the opposite shadow that applies, since
    781     // the line is "upside down" in terms of block coordinates.
    782     LayoutUnit shadowLogicalTop = style->isFlippedLinesWritingMode() ? -boxShadowLogicalBottom : boxShadowLogicalTop;
    783     LayoutUnit shadowLogicalBottom = style->isFlippedLinesWritingMode() ? -boxShadowLogicalTop : boxShadowLogicalBottom;
    784 
    785     LayoutUnit logicalTopVisualOverflow = min(pixelSnappedLogicalTop() + shadowLogicalTop, logicalVisualOverflow.y());
    786     LayoutUnit logicalBottomVisualOverflow = max(pixelSnappedLogicalBottom() + shadowLogicalBottom, logicalVisualOverflow.maxY());
    787 
    788     LayoutUnit boxShadowLogicalLeft;
    789     LayoutUnit boxShadowLogicalRight;
    790     style->getBoxShadowInlineDirectionExtent(boxShadowLogicalLeft, boxShadowLogicalRight);
    791 
    792     LayoutUnit logicalLeftVisualOverflow = min(pixelSnappedLogicalLeft() + boxShadowLogicalLeft, logicalVisualOverflow.x());
    793     LayoutUnit logicalRightVisualOverflow = max(pixelSnappedLogicalRight() + boxShadowLogicalRight, logicalVisualOverflow.maxX());
    794 
    795     logicalVisualOverflow = LayoutRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
    796                                        logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
    797 }
    798 
    799 inline void InlineFlowBox::addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow)
    800 {
    801     // border-image-outset on root line boxes is applying to the block and not to the lines.
    802     if (!parent())
    803         return;
    804 
    805     RenderStyle* style = renderer()->style(isFirstLineStyle());
    806     if (!style->hasBorderImageOutsets())
    807         return;
    808 
    809     LayoutBoxExtent borderOutsets = style->borderImageOutsets();
    810 
    811     LayoutUnit borderOutsetLogicalTop = borderOutsets.logicalTop(style->writingMode());
    812     LayoutUnit borderOutsetLogicalBottom = borderOutsets.logicalBottom(style->writingMode());
    813     LayoutUnit borderOutsetLogicalLeft = borderOutsets.logicalLeft(style->writingMode());
    814     LayoutUnit borderOutsetLogicalRight = borderOutsets.logicalRight(style->writingMode());
    815 
    816     // Similar to how glyph overflow works, if our lines are flipped, then it's actually the opposite border that applies, since
    817     // the line is "upside down" in terms of block coordinates. vertical-rl and horizontal-bt are the flipped line modes.
    818     LayoutUnit outsetLogicalTop = style->isFlippedLinesWritingMode() ? borderOutsetLogicalBottom : borderOutsetLogicalTop;
    819     LayoutUnit outsetLogicalBottom = style->isFlippedLinesWritingMode() ? borderOutsetLogicalTop : borderOutsetLogicalBottom;
    820 
    821     LayoutUnit logicalTopVisualOverflow = min(pixelSnappedLogicalTop() - outsetLogicalTop, logicalVisualOverflow.y());
    822     LayoutUnit logicalBottomVisualOverflow = max(pixelSnappedLogicalBottom() + outsetLogicalBottom, logicalVisualOverflow.maxY());
    823 
    824     LayoutUnit outsetLogicalLeft = includeLogicalLeftEdge() ? borderOutsetLogicalLeft : LayoutUnit();
    825     LayoutUnit outsetLogicalRight = includeLogicalRightEdge() ? borderOutsetLogicalRight : LayoutUnit();
    826 
    827     LayoutUnit logicalLeftVisualOverflow = min(pixelSnappedLogicalLeft() - outsetLogicalLeft, logicalVisualOverflow.x());
    828     LayoutUnit logicalRightVisualOverflow = max(pixelSnappedLogicalRight() + outsetLogicalRight, logicalVisualOverflow.maxX());
    829 
    830     logicalVisualOverflow = LayoutRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
    831                                        logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
    832 }
    833 
    834 inline void InlineFlowBox::addTextBoxVisualOverflow(InlineTextBox* textBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, LayoutRect& logicalVisualOverflow)
    835 {
    836     if (textBox->knownToHaveNoOverflow())
    837         return;
    838 
    839     RenderStyle* style = textBox->renderer()->style(isFirstLineStyle());
    840 
    841     GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(textBox);
    842     GlyphOverflow* glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->value.second;
    843     bool isFlippedLine = style->isFlippedLinesWritingMode();
    844 
    845     int topGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->bottom : glyphOverflow->top) : 0;
    846     int bottomGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->top : glyphOverflow->bottom) : 0;
    847     int leftGlyphEdge = glyphOverflow ? glyphOverflow->left : 0;
    848     int rightGlyphEdge = glyphOverflow ? glyphOverflow->right : 0;
    849 
    850     int strokeOverflow = static_cast<int>(ceilf(style->textStrokeWidth() / 2.0f));
    851     int topGlyphOverflow = -strokeOverflow - topGlyphEdge;
    852     int bottomGlyphOverflow = strokeOverflow + bottomGlyphEdge;
    853     int leftGlyphOverflow = -strokeOverflow - leftGlyphEdge;
    854     int rightGlyphOverflow = strokeOverflow + rightGlyphEdge;
    855 
    856     TextEmphasisPosition emphasisMarkPosition;
    857     if (style->textEmphasisMark() != TextEmphasisMarkNone && textBox->getEmphasisMarkPosition(style, emphasisMarkPosition)) {
    858         int emphasisMarkHeight = style->font().emphasisMarkHeight(style->textEmphasisMarkString());
    859         if ((emphasisMarkPosition == TextEmphasisPositionOver) == (!style->isFlippedLinesWritingMode()))
    860             topGlyphOverflow = min(topGlyphOverflow, -emphasisMarkHeight);
    861         else
    862             bottomGlyphOverflow = max(bottomGlyphOverflow, emphasisMarkHeight);
    863     }
    864 
    865     // If letter-spacing is negative, we should factor that into right layout overflow. (Even in RTL, letter-spacing is
    866     // applied to the right, so this is not an issue with left overflow.
    867     rightGlyphOverflow -= min(0, (int)style->font().letterSpacing());
    868 
    869     LayoutUnit textShadowLogicalTop;
    870     LayoutUnit textShadowLogicalBottom;
    871     style->getTextShadowBlockDirectionExtent(textShadowLogicalTop, textShadowLogicalBottom);
    872 
    873     LayoutUnit childOverflowLogicalTop = min<LayoutUnit>(textShadowLogicalTop + topGlyphOverflow, topGlyphOverflow);
    874     LayoutUnit childOverflowLogicalBottom = max<LayoutUnit>(textShadowLogicalBottom + bottomGlyphOverflow, bottomGlyphOverflow);
    875 
    876     LayoutUnit textShadowLogicalLeft;
    877     LayoutUnit textShadowLogicalRight;
    878     style->getTextShadowInlineDirectionExtent(textShadowLogicalLeft, textShadowLogicalRight);
    879 
    880     LayoutUnit childOverflowLogicalLeft = min<LayoutUnit>(textShadowLogicalLeft + leftGlyphOverflow, leftGlyphOverflow);
    881     LayoutUnit childOverflowLogicalRight = max<LayoutUnit>(textShadowLogicalRight + rightGlyphOverflow, rightGlyphOverflow);
    882 
    883     LayoutUnit logicalTopVisualOverflow = min(textBox->pixelSnappedLogicalTop() + childOverflowLogicalTop, logicalVisualOverflow.y());
    884     LayoutUnit logicalBottomVisualOverflow = max(textBox->pixelSnappedLogicalBottom() + childOverflowLogicalBottom, logicalVisualOverflow.maxY());
    885     LayoutUnit logicalLeftVisualOverflow = min(textBox->pixelSnappedLogicalLeft() + childOverflowLogicalLeft, logicalVisualOverflow.x());
    886     LayoutUnit logicalRightVisualOverflow = max(textBox->pixelSnappedLogicalRight() + childOverflowLogicalRight, logicalVisualOverflow.maxX());
    887 
    888     logicalVisualOverflow = LayoutRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
    889                                        logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
    890 
    891     textBox->setLogicalOverflowRect(logicalVisualOverflow);
    892 }
    893 
    894 inline void InlineFlowBox::addReplacedChildOverflow(const InlineBox* inlineBox, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow)
    895 {
    896     RenderBox* box = toRenderBox(inlineBox->renderer());
    897 
    898     // Visual overflow only propagates if the box doesn't have a self-painting layer.  This rectangle does not include
    899     // transforms or relative positioning (since those objects always have self-painting layers), but it does need to be adjusted
    900     // for writing-mode differences.
    901     if (!box->hasSelfPaintingLayer()) {
    902         LayoutRect childLogicalVisualOverflow = box->logicalVisualOverflowRectForPropagation(renderer()->style());
    903         childLogicalVisualOverflow.move(inlineBox->logicalLeft(), inlineBox->logicalTop());
    904         logicalVisualOverflow.unite(childLogicalVisualOverflow);
    905     }
    906 
    907     // Layout overflow internal to the child box only propagates if the child box doesn't have overflow clip set.
    908     // Otherwise the child border box propagates as layout overflow.  This rectangle must include transforms and relative positioning
    909     // and be adjusted for writing-mode differences.
    910     LayoutRect childLogicalLayoutOverflow = box->logicalLayoutOverflowRectForPropagation(renderer()->style());
    911     childLogicalLayoutOverflow.move(inlineBox->logicalLeft(), inlineBox->logicalTop());
    912     logicalLayoutOverflow.unite(childLogicalLayoutOverflow);
    913 }
    914 
    915 void InlineFlowBox::computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
    916 {
    917     // If we know we have no overflow, we can just bail.
    918     if (knownToHaveNoOverflow())
    919         return;
    920 
    921     // Visual overflow just includes overflow for stuff we need to repaint ourselves.  Self-painting layers are ignored.
    922     // Layout overflow is used to determine scrolling extent, so it still includes child layers and also factors in
    923     // transforms, relative positioning, etc.
    924     LayoutRect logicalLayoutOverflow(enclosingLayoutRect(logicalFrameRectIncludingLineHeight(lineTop, lineBottom)));
    925     LayoutRect logicalVisualOverflow(logicalLayoutOverflow);
    926 
    927     addBoxShadowVisualOverflow(logicalVisualOverflow);
    928     addBorderOutsetVisualOverflow(logicalVisualOverflow);
    929 
    930     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    931         if (curr->renderer()->isOutOfFlowPositioned())
    932             continue; // Positioned placeholders don't affect calculations.
    933 
    934         if (curr->renderer()->isText()) {
    935             InlineTextBox* text = toInlineTextBox(curr);
    936             RenderText* rt = toRenderText(text->renderer());
    937             if (rt->isBR())
    938                 continue;
    939             LayoutRect textBoxOverflow(enclosingLayoutRect(text->logicalFrameRect()));
    940             addTextBoxVisualOverflow(text, textBoxDataMap, textBoxOverflow);
    941             logicalVisualOverflow.unite(textBoxOverflow);
    942         } else  if (curr->renderer()->isRenderInline()) {
    943             InlineFlowBox* flow = toInlineFlowBox(curr);
    944             flow->computeOverflow(lineTop, lineBottom, textBoxDataMap);
    945             if (!flow->boxModelObject()->hasSelfPaintingLayer())
    946                 logicalVisualOverflow.unite(flow->logicalVisualOverflowRect(lineTop, lineBottom));
    947             LayoutRect childLayoutOverflow = flow->logicalLayoutOverflowRect(lineTop, lineBottom);
    948             childLayoutOverflow.move(flow->boxModelObject()->relativePositionLogicalOffset());
    949             logicalLayoutOverflow.unite(childLayoutOverflow);
    950         } else
    951             addReplacedChildOverflow(curr, logicalLayoutOverflow, logicalVisualOverflow);
    952     }
    953 
    954     setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, lineTop, lineBottom);
    955 }
    956 
    957 void InlineFlowBox::setLayoutOverflow(const LayoutRect& rect, LayoutUnit lineTop, LayoutUnit lineBottom)
    958 {
    959     LayoutRect frameBox = enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
    960     if (frameBox.contains(rect) || rect.isEmpty())
    961         return;
    962 
    963     if (!m_overflow)
    964         m_overflow = adoptPtr(new RenderOverflow(frameBox, frameBox));
    965 
    966     m_overflow->setLayoutOverflow(rect);
    967 }
    968 
    969 void InlineFlowBox::setVisualOverflow(const LayoutRect& rect, LayoutUnit lineTop, LayoutUnit lineBottom)
    970 {
    971     LayoutRect frameBox = enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
    972     if (frameBox.contains(rect) || rect.isEmpty())
    973         return;
    974 
    975     if (!m_overflow)
    976         m_overflow = adoptPtr(new RenderOverflow(frameBox, frameBox));
    977 
    978     m_overflow->setVisualOverflow(rect);
    979 }
    980 
    981 void InlineFlowBox::setOverflowFromLogicalRects(const LayoutRect& logicalLayoutOverflow, const LayoutRect& logicalVisualOverflow, LayoutUnit lineTop, LayoutUnit lineBottom)
    982 {
    983     LayoutRect layoutOverflow(isHorizontal() ? logicalLayoutOverflow : logicalLayoutOverflow.transposedRect());
    984     setLayoutOverflow(layoutOverflow, lineTop, lineBottom);
    985 
    986     LayoutRect visualOverflow(isHorizontal() ? logicalVisualOverflow : logicalVisualOverflow.transposedRect());
    987     setVisualOverflow(visualOverflow, lineTop, lineBottom);
    988 }
    989 
    990 bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
    991 {
    992     LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom));
    993     flipForWritingMode(overflowRect);
    994     overflowRect.moveBy(accumulatedOffset);
    995     if (!locationInContainer.intersects(overflowRect))
    996         return false;
    997 
    998     // Check children first.
    999     // 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.
   1000     RenderObject* culledParent = 0;
   1001     for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
   1002         if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) {
   1003             RenderObject* newParent = 0;
   1004             // Culled parents are only relevant for area-based hit-tests, so ignore it in point-based ones.
   1005             if (locationInContainer.isRectBasedTest()) {
   1006                 newParent = curr->renderer()->parent();
   1007                 if (newParent == renderer())
   1008                     newParent = 0;
   1009             }
   1010             // Check the culled parent after all its children have been checked, to do this we wait until
   1011             // we are about to test an element with a different parent.
   1012             if (newParent != culledParent) {
   1013                 if (!newParent || !newParent->isDescendantOf(culledParent)) {
   1014                     while (culledParent && culledParent != renderer() && culledParent != newParent) {
   1015                         if (culledParent->isRenderInline() && toRenderInline(culledParent)->hitTestCulledInline(request, result, locationInContainer, accumulatedOffset))
   1016                             return true;
   1017                         culledParent = culledParent->parent();
   1018                     }
   1019                 }
   1020                 culledParent = newParent;
   1021             }
   1022             if (curr->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, lineTop, lineBottom)) {
   1023                 renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
   1024                 return true;
   1025             }
   1026         }
   1027     }
   1028     // Check any culled ancestor of the final children tested.
   1029     while (culledParent && culledParent != renderer()) {
   1030         if (culledParent->isRenderInline() && toRenderInline(culledParent)->hitTestCulledInline(request, result, locationInContainer, accumulatedOffset))
   1031             return true;
   1032         culledParent = culledParent->parent();
   1033     }
   1034 
   1035     // Now check ourselves. Pixel snap hit testing.
   1036     LayoutRect frameRect = roundedFrameRect();
   1037     LayoutUnit minX = frameRect.x();
   1038     LayoutUnit minY = frameRect.y();
   1039     LayoutUnit width = frameRect.width();
   1040     LayoutUnit height = frameRect.height();
   1041 
   1042     // Constrain our hit testing to the line top and bottom if necessary.
   1043     bool noQuirksMode = renderer()->document()->inNoQuirksMode();
   1044     if (!noQuirksMode && !hasTextChildren() && !(descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) {
   1045         RootInlineBox* rootBox = root();
   1046         LayoutUnit& top = isHorizontal() ? minY : minX;
   1047         LayoutUnit& logicalHeight = isHorizontal() ? height : width;
   1048         LayoutUnit bottom = min(rootBox->lineBottom(), top + logicalHeight);
   1049         top = max(rootBox->lineTop(), top);
   1050         logicalHeight = bottom - top;
   1051     }
   1052 
   1053     // Move x/y to our coordinates.
   1054     LayoutRect rect(minX, minY, width, height);
   1055     flipForWritingMode(rect);
   1056     rect.moveBy(accumulatedOffset);
   1057 
   1058     if (visibleToHitTestRequest(request) && locationInContainer.intersects(rect)) {
   1059         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.
   1060         if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
   1061             return true;
   1062     }
   1063 
   1064     return false;
   1065 }
   1066 
   1067 void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
   1068 {
   1069     LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom));
   1070     overflowRect.inflate(renderer()->maximalOutlineSize(paintInfo.phase));
   1071     flipForWritingMode(overflowRect);
   1072     overflowRect.moveBy(paintOffset);
   1073 
   1074     if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
   1075         return;
   1076 
   1077     if (paintInfo.phase != PaintPhaseChildOutlines) {
   1078         if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
   1079             // Add ourselves to the paint info struct's list of inlines that need to paint their
   1080             // outlines.
   1081             if (renderer()->style()->visibility() == VISIBLE && renderer()->hasOutline() && !isRootInlineBox()) {
   1082                 RenderInline* inlineFlow = toRenderInline(renderer());
   1083 
   1084                 RenderBlock* cb = 0;
   1085                 bool containingBlockPaintsContinuationOutline = inlineFlow->continuation() || inlineFlow->isInlineElementContinuation();
   1086                 if (containingBlockPaintsContinuationOutline) {
   1087                     // FIXME: See https://bugs.webkit.org/show_bug.cgi?id=54690. We currently don't reconnect inline continuations
   1088                     // after a child removal. As a result, those merged inlines do not get seperated and hence not get enclosed by
   1089                     // anonymous blocks. In this case, it is better to bail out and paint it ourself.
   1090                     RenderBlock* enclosingAnonymousBlock = renderer()->containingBlock();
   1091                     if (!enclosingAnonymousBlock->isAnonymousBlock())
   1092                         containingBlockPaintsContinuationOutline = false;
   1093                     else {
   1094                         cb = enclosingAnonymousBlock->containingBlock();
   1095                         for (RenderBoxModelObject* box = boxModelObject(); box != cb; box = box->parent()->enclosingBoxModelObject()) {
   1096                             if (box->hasSelfPaintingLayer()) {
   1097                                 containingBlockPaintsContinuationOutline = false;
   1098                                 break;
   1099                             }
   1100                         }
   1101                     }
   1102                 }
   1103 
   1104                 if (containingBlockPaintsContinuationOutline) {
   1105                     // Add ourselves to the containing block of the entire continuation so that it can
   1106                     // paint us atomically.
   1107                     cb->addContinuationWithOutline(toRenderInline(renderer()->node()->renderer()));
   1108                 } else if (!inlineFlow->isInlineElementContinuation())
   1109                     paintInfo.outlineObjects->add(inlineFlow);
   1110             }
   1111         } else if (paintInfo.phase == PaintPhaseMask) {
   1112             paintMask(paintInfo, paintOffset);
   1113             return;
   1114         } else {
   1115             // Paint our background, border and box-shadow.
   1116             paintBoxDecorations(paintInfo, paintOffset);
   1117         }
   1118     }
   1119 
   1120     if (paintInfo.phase == PaintPhaseMask)
   1121         return;
   1122 
   1123     PaintPhase paintPhase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;
   1124     PaintInfo childInfo(paintInfo);
   1125     childInfo.phase = paintPhase;
   1126     childInfo.updatePaintingRootForChildren(renderer());
   1127 
   1128     // Paint our children.
   1129     if (paintPhase != PaintPhaseSelfOutline) {
   1130         for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
   1131             if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer())
   1132                 curr->paint(childInfo, paintOffset, lineTop, lineBottom);
   1133         }
   1134     }
   1135 }
   1136 
   1137 void InlineFlowBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect, CompositeOperator op)
   1138 {
   1139     if (!fillLayer)
   1140         return;
   1141     paintFillLayers(paintInfo, c, fillLayer->next(), rect, op);
   1142     paintFillLayer(paintInfo, c, fillLayer, rect, op);
   1143 }
   1144 
   1145 bool InlineFlowBox::boxShadowCanBeAppliedToBackground(const FillLayer& lastBackgroundLayer) const
   1146 {
   1147     // The checks here match how paintFillLayer() decides whether to clip (if it does, the shadow
   1148     // would be clipped out, so it has to be drawn separately).
   1149     StyleImage* image = lastBackgroundLayer.image();
   1150     bool hasFillImage = image && image->canRender(renderer(), renderer()->style()->effectiveZoom());
   1151     return (!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent();
   1152 }
   1153 
   1154 void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect, CompositeOperator op)
   1155 {
   1156     StyleImage* img = fillLayer->image();
   1157     bool hasFillImage = img && img->canRender(renderer(), renderer()->style()->effectiveZoom());
   1158     if ((!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
   1159         boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, rect, BackgroundBleedNone, this, rect.size(), op);
   1160     else if (renderer()->style()->boxDecorationBreak() == DCLONE) {
   1161         GraphicsContextStateSaver stateSaver(*paintInfo.context);
   1162         paintInfo.context->clip(LayoutRect(rect.x(), rect.y(), width(), height()));
   1163         boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, rect, BackgroundBleedNone, this, rect.size(), op);
   1164     } else {
   1165         // We have a fill image that spans multiple lines.
   1166         // We need to adjust tx and ty by the width of all previous lines.
   1167         // Think of background painting on inlines as though you had one long line, a single continuous
   1168         // strip.  Even though that strip has been broken up across multiple lines, you still paint it
   1169         // as though you had one single line.  This means each line has to pick up the background where
   1170         // the previous line left off.
   1171         LayoutUnit logicalOffsetOnLine = 0;
   1172         LayoutUnit totalLogicalWidth;
   1173         if (renderer()->style()->direction() == LTR) {
   1174             for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
   1175                 logicalOffsetOnLine += curr->logicalWidth();
   1176             totalLogicalWidth = logicalOffsetOnLine;
   1177             for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
   1178                 totalLogicalWidth += curr->logicalWidth();
   1179         } else {
   1180             for (InlineFlowBox* curr = nextLineBox(); curr; curr = curr->nextLineBox())
   1181                 logicalOffsetOnLine += curr->logicalWidth();
   1182             totalLogicalWidth = logicalOffsetOnLine;
   1183             for (InlineFlowBox* curr = this; curr; curr = curr->prevLineBox())
   1184                 totalLogicalWidth += curr->logicalWidth();
   1185         }
   1186         LayoutUnit stripX = rect.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
   1187         LayoutUnit stripY = rect.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
   1188         LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : static_cast<LayoutUnit>(width());
   1189         LayoutUnit stripHeight = isHorizontal() ? static_cast<LayoutUnit>(height()) : totalLogicalWidth;
   1190 
   1191         GraphicsContextStateSaver stateSaver(*paintInfo.context);
   1192         paintInfo.context->clip(LayoutRect(rect.x(), rect.y(), width(), height()));
   1193         boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, LayoutRect(stripX, stripY, stripWidth, stripHeight), BackgroundBleedNone, this, rect.size(), op);
   1194     }
   1195 }
   1196 
   1197 void InlineFlowBox::paintBoxShadow(const PaintInfo& info, RenderStyle* s, ShadowStyle shadowStyle, const LayoutRect& paintRect)
   1198 {
   1199     if ((!prevLineBox() && !nextLineBox()) || !parent())
   1200         boxModelObject()->paintBoxShadow(info, paintRect, s, shadowStyle);
   1201     else {
   1202         // FIXME: We can do better here in the multi-line case. We want to push a clip so that the shadow doesn't
   1203         // protrude incorrectly at the edges, and we want to possibly include shadows cast from the previous/following lines
   1204         boxModelObject()->paintBoxShadow(info, paintRect, s, shadowStyle, includeLogicalLeftEdge(), includeLogicalRightEdge());
   1205     }
   1206 }
   1207 
   1208 void InlineFlowBox::constrainToLineTopAndBottomIfNeeded(LayoutRect& rect) const
   1209 {
   1210     bool noQuirksMode = renderer()->document()->inNoQuirksMode();
   1211     if (!noQuirksMode && !hasTextChildren() && !(descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) {
   1212         const RootInlineBox* rootBox = root();
   1213         LayoutUnit logicalTop = isHorizontal() ? rect.y() : rect.x();
   1214         LayoutUnit logicalHeight = isHorizontal() ? rect.height() : rect.width();
   1215         LayoutUnit bottom = min(rootBox->lineBottom(), logicalTop + logicalHeight);
   1216         logicalTop = max(rootBox->lineTop(), logicalTop);
   1217         logicalHeight = bottom - logicalTop;
   1218         if (isHorizontal()) {
   1219             rect.setY(logicalTop);
   1220             rect.setHeight(logicalHeight);
   1221         } else {
   1222             rect.setX(logicalTop);
   1223             rect.setWidth(logicalHeight);
   1224         }
   1225     }
   1226 }
   1227 
   1228 static LayoutRect clipRectForNinePieceImageStrip(InlineFlowBox* box, const NinePieceImage& image, const LayoutRect& paintRect)
   1229 {
   1230     LayoutRect clipRect(paintRect);
   1231     RenderStyle* style = box->renderer()->style();
   1232     LayoutBoxExtent outsets = style->imageOutsets(image);
   1233     if (box->isHorizontal()) {
   1234         clipRect.setY(paintRect.y() - outsets.top());
   1235         clipRect.setHeight(paintRect.height() + outsets.top() + outsets.bottom());
   1236         if (box->includeLogicalLeftEdge()) {
   1237             clipRect.setX(paintRect.x() - outsets.left());
   1238             clipRect.setWidth(paintRect.width() + outsets.left());
   1239         }
   1240         if (box->includeLogicalRightEdge())
   1241             clipRect.setWidth(clipRect.width() + outsets.right());
   1242     } else {
   1243         clipRect.setX(paintRect.x() - outsets.left());
   1244         clipRect.setWidth(paintRect.width() + outsets.left() + outsets.right());
   1245         if (box->includeLogicalLeftEdge()) {
   1246             clipRect.setY(paintRect.y() - outsets.top());
   1247             clipRect.setHeight(paintRect.height() + outsets.top());
   1248         }
   1249         if (box->includeLogicalRightEdge())
   1250             clipRect.setHeight(clipRect.height() + outsets.bottom());
   1251     }
   1252     return clipRect;
   1253 }
   1254 
   1255 void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
   1256 {
   1257     if (!paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
   1258         return;
   1259 
   1260     // Pixel snap background/border painting.
   1261     LayoutRect frameRect = roundedFrameRect();
   1262 
   1263     constrainToLineTopAndBottomIfNeeded(frameRect);
   1264 
   1265     // Move x/y to our coordinates.
   1266     LayoutRect localRect(frameRect);
   1267     flipForWritingMode(localRect);
   1268     LayoutPoint adjustedPaintoffset = paintOffset + localRect.location();
   1269 
   1270     GraphicsContext* context = paintInfo.context;
   1271 
   1272     // You can use p::first-line to specify a background. If so, the root line boxes for
   1273     // a line may actually have to paint a background.
   1274     RenderStyle* styleToUse = renderer()->style(isFirstLineStyle());
   1275     if ((!parent() && isFirstLineStyle() && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) {
   1276         LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size());
   1277         // Shadow comes first and is behind the background and border.
   1278         if (!boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone, this))
   1279             paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
   1280 
   1281         Color c = renderer()->resolveColor(styleToUse, CSSPropertyBackgroundColor);
   1282         paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), paintRect);
   1283         paintBoxShadow(paintInfo, styleToUse, Inset, paintRect);
   1284 
   1285         // :first-line cannot be used to put borders on a line. Always paint borders with our
   1286         // non-first-line style.
   1287         if (parent() && renderer()->style()->hasBorder()) {
   1288             const NinePieceImage& borderImage = renderer()->style()->borderImage();
   1289             StyleImage* borderImageSource = borderImage.image();
   1290             bool hasBorderImage = borderImageSource && borderImageSource->canRender(renderer(), styleToUse->effectiveZoom());
   1291             if (hasBorderImage && !borderImageSource->isLoaded())
   1292                 return; // Don't paint anything while we wait for the image to load.
   1293 
   1294             // The simple case is where we either have no border image or we are the only box for this object.  In those
   1295             // cases only a single call to draw is required.
   1296             if (!hasBorderImage || (!prevLineBox() && !nextLineBox()))
   1297                 boxModelObject()->paintBorder(paintInfo, paintRect, renderer()->style(isFirstLineStyle()), BackgroundBleedNone, includeLogicalLeftEdge(), includeLogicalRightEdge());
   1298             else {
   1299                 // We have a border image that spans multiple lines.
   1300                 // We need to adjust tx and ty by the width of all previous lines.
   1301                 // Think of border image painting on inlines as though you had one long line, a single continuous
   1302                 // strip.  Even though that strip has been broken up across multiple lines, you still paint it
   1303                 // as though you had one single line.  This means each line has to pick up the image where
   1304                 // the previous line left off.
   1305                 // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
   1306                 // but it isn't even clear how this should work at all.
   1307                 LayoutUnit logicalOffsetOnLine = 0;
   1308                 for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
   1309                     logicalOffsetOnLine += curr->logicalWidth();
   1310                 LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
   1311                 for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
   1312                     totalLogicalWidth += curr->logicalWidth();
   1313                 LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
   1314                 LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
   1315                 LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
   1316                 LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
   1317 
   1318                 LayoutRect clipRect = clipRectForNinePieceImageStrip(this, borderImage, paintRect);
   1319                 GraphicsContextStateSaver stateSaver(*context);
   1320                 context->clip(clipRect);
   1321                 boxModelObject()->paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer()->style(isFirstLineStyle()));
   1322             }
   1323         }
   1324     }
   1325 }
   1326 
   1327 void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
   1328 {
   1329     if (!paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
   1330         return;
   1331 
   1332     // Pixel snap mask painting.
   1333     LayoutRect frameRect = roundedFrameRect();
   1334 
   1335     constrainToLineTopAndBottomIfNeeded(frameRect);
   1336 
   1337     // Move x/y to our coordinates.
   1338     LayoutRect localRect(frameRect);
   1339     flipForWritingMode(localRect);
   1340     LayoutPoint adjustedPaintOffset = paintOffset + localRect.location();
   1341 
   1342     const NinePieceImage& maskNinePieceImage = renderer()->style()->maskBoxImage();
   1343     StyleImage* maskBoxImage = renderer()->style()->maskBoxImage().image();
   1344 
   1345     // Figure out if we need to push a transparency layer to render our mask.
   1346     bool pushTransparencyLayer = false;
   1347     bool compositedMask = renderer()->hasLayer() && boxModelObject()->layer()->hasCompositedMask();
   1348     bool flattenCompositingLayers = renderer()->view()->frameView() && renderer()->view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
   1349     CompositeOperator compositeOp = CompositeSourceOver;
   1350     if (!compositedMask || flattenCompositingLayers) {
   1351         if ((maskBoxImage && renderer()->style()->maskLayers()->hasImage()) || renderer()->style()->maskLayers()->next())
   1352             pushTransparencyLayer = true;
   1353 
   1354         compositeOp = CompositeDestinationIn;
   1355         if (pushTransparencyLayer) {
   1356             paintInfo.context->setCompositeOperation(CompositeDestinationIn);
   1357             paintInfo.context->beginTransparencyLayer(1.0f);
   1358             compositeOp = CompositeSourceOver;
   1359         }
   1360     }
   1361 
   1362     LayoutRect paintRect = LayoutRect(adjustedPaintOffset, frameRect.size());
   1363     paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), paintRect, compositeOp);
   1364 
   1365     bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer(), renderer()->style()->effectiveZoom());
   1366     if (!hasBoxImage || !maskBoxImage->isLoaded()) {
   1367         if (pushTransparencyLayer)
   1368             paintInfo.context->endTransparencyLayer();
   1369         return; // Don't paint anything while we wait for the image to load.
   1370     }
   1371 
   1372     // The simple case is where we are the only box for this object.  In those
   1373     // cases only a single call to draw is required.
   1374     if (!prevLineBox() && !nextLineBox()) {
   1375         boxModelObject()->paintNinePieceImage(paintInfo.context, LayoutRect(adjustedPaintOffset, frameRect.size()), renderer()->style(), maskNinePieceImage, compositeOp);
   1376     } else {
   1377         // We have a mask image that spans multiple lines.
   1378         // We need to adjust _tx and _ty by the width of all previous lines.
   1379         LayoutUnit logicalOffsetOnLine = 0;
   1380         for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
   1381             logicalOffsetOnLine += curr->logicalWidth();
   1382         LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
   1383         for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
   1384             totalLogicalWidth += curr->logicalWidth();
   1385         LayoutUnit stripX = adjustedPaintOffset.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
   1386         LayoutUnit stripY = adjustedPaintOffset.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
   1387         LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
   1388         LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
   1389 
   1390         LayoutRect clipRect = clipRectForNinePieceImageStrip(this, maskNinePieceImage, paintRect);
   1391         GraphicsContextStateSaver stateSaver(*paintInfo.context);
   1392         paintInfo.context->clip(clipRect);
   1393         boxModelObject()->paintNinePieceImage(paintInfo.context, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer()->style(), maskNinePieceImage, compositeOp);
   1394     }
   1395 
   1396     if (pushTransparencyLayer)
   1397         paintInfo.context->endTransparencyLayer();
   1398 }
   1399 
   1400 InlineBox* InlineFlowBox::firstLeafChild() const
   1401 {
   1402     InlineBox* leaf = 0;
   1403     for (InlineBox* child = firstChild(); child && !leaf; child = child->nextOnLine())
   1404         leaf = child->isLeaf() ? child : toInlineFlowBox(child)->firstLeafChild();
   1405     return leaf;
   1406 }
   1407 
   1408 InlineBox* InlineFlowBox::lastLeafChild() const
   1409 {
   1410     InlineBox* leaf = 0;
   1411     for (InlineBox* child = lastChild(); child && !leaf; child = child->prevOnLine())
   1412         leaf = child->isLeaf() ? child : toInlineFlowBox(child)->lastLeafChild();
   1413     return leaf;
   1414 }
   1415 
   1416 RenderObject::SelectionState InlineFlowBox::selectionState()
   1417 {
   1418     return RenderObject::SelectionNone;
   1419 }
   1420 
   1421 bool InlineFlowBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const
   1422 {
   1423     for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {
   1424         if (!box->canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth))
   1425             return false;
   1426     }
   1427     return true;
   1428 }
   1429 
   1430 float InlineFlowBox::placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox)
   1431 {
   1432     float result = -1;
   1433     // We iterate over all children, the foundBox variable tells us when we've found the
   1434     // box containing the ellipsis.  All boxes after that one in the flow are hidden.
   1435     // If our flow is ltr then iterate over the boxes from left to right, otherwise iterate
   1436     // from right to left. Varying the order allows us to correctly hide the boxes following the ellipsis.
   1437     InlineBox* box = ltr ? firstChild() : lastChild();
   1438 
   1439     // NOTE: these will cross after foundBox = true.
   1440     int visibleLeftEdge = blockLeftEdge;
   1441     int visibleRightEdge = blockRightEdge;
   1442 
   1443     while (box) {
   1444         int currResult = box->placeEllipsisBox(ltr, visibleLeftEdge, visibleRightEdge, ellipsisWidth, truncatedWidth, foundBox);
   1445         if (currResult != -1 && result == -1)
   1446             result = currResult;
   1447 
   1448         if (ltr) {
   1449             visibleLeftEdge += box->logicalWidth();
   1450             box = box->nextOnLine();
   1451         }
   1452         else {
   1453             visibleRightEdge -= box->logicalWidth();
   1454             box = box->prevOnLine();
   1455         }
   1456     }
   1457     return result;
   1458 }
   1459 
   1460 void InlineFlowBox::clearTruncation()
   1461 {
   1462     for (InlineBox *box = firstChild(); box; box = box->nextOnLine())
   1463         box->clearTruncation();
   1464 }
   1465 
   1466 LayoutUnit InlineFlowBox::computeOverAnnotationAdjustment(LayoutUnit allowedPosition) const
   1467 {
   1468     LayoutUnit result = 0;
   1469     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
   1470         if (curr->renderer()->isOutOfFlowPositioned())
   1471             continue; // Positioned placeholders don't affect calculations.
   1472 
   1473         if (curr->isInlineFlowBox())
   1474             result = max(result, toInlineFlowBox(curr)->computeOverAnnotationAdjustment(allowedPosition));
   1475 
   1476         if (curr->renderer()->isReplaced() && curr->renderer()->isRubyRun() && curr->renderer()->style()->rubyPosition() == RubyPositionBefore) {
   1477             RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
   1478             RenderRubyText* rubyText = rubyRun->rubyText();
   1479             if (!rubyText)
   1480                 continue;
   1481 
   1482             if (!rubyRun->style()->isFlippedLinesWritingMode()) {
   1483                 LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit());
   1484                 if (topOfFirstRubyTextLine >= 0)
   1485                     continue;
   1486                 topOfFirstRubyTextLine += curr->logicalTop();
   1487                 result = max(result, allowedPosition - topOfFirstRubyTextLine);
   1488             } else {
   1489                 LayoutUnit bottomOfLastRubyTextLine = rubyText->logicalTop() + (rubyText->lastRootBox() ? rubyText->lastRootBox()->lineBottom() : rubyText->logicalHeight());
   1490                 if (bottomOfLastRubyTextLine <= curr->logicalHeight())
   1491                     continue;
   1492                 bottomOfLastRubyTextLine += curr->logicalTop();
   1493                 result = max(result, bottomOfLastRubyTextLine - allowedPosition);
   1494             }
   1495         }
   1496 
   1497         if (curr->isInlineTextBox()) {
   1498             RenderStyle* style = curr->renderer()->style(isFirstLineStyle());
   1499             TextEmphasisPosition emphasisMarkPosition;
   1500             if (style->textEmphasisMark() != TextEmphasisMarkNone && toInlineTextBox(curr)->getEmphasisMarkPosition(style, emphasisMarkPosition) && emphasisMarkPosition == TextEmphasisPositionOver) {
   1501                 if (!style->isFlippedLinesWritingMode()) {
   1502                     int topOfEmphasisMark = curr->logicalTop() - style->font().emphasisMarkHeight(style->textEmphasisMarkString());
   1503                     result = max(result, allowedPosition - topOfEmphasisMark);
   1504                 } else {
   1505                     int bottomOfEmphasisMark = curr->logicalBottom() + style->font().emphasisMarkHeight(style->textEmphasisMarkString());
   1506                     result = max(result, bottomOfEmphasisMark - allowedPosition);
   1507                 }
   1508             }
   1509         }
   1510     }
   1511     return result;
   1512 }
   1513 
   1514 LayoutUnit InlineFlowBox::computeUnderAnnotationAdjustment(LayoutUnit allowedPosition) const
   1515 {
   1516     LayoutUnit result = 0;
   1517     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
   1518         if (curr->renderer()->isOutOfFlowPositioned())
   1519             continue; // Positioned placeholders don't affect calculations.
   1520 
   1521         if (curr->isInlineFlowBox())
   1522             result = max(result, toInlineFlowBox(curr)->computeUnderAnnotationAdjustment(allowedPosition));
   1523 
   1524         if (curr->renderer()->isReplaced() && curr->renderer()->isRubyRun() && curr->renderer()->style()->rubyPosition() == RubyPositionAfter) {
   1525             RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
   1526             RenderRubyText* rubyText = rubyRun->rubyText();
   1527             if (!rubyText)
   1528                 continue;
   1529 
   1530             if (rubyRun->style()->isFlippedLinesWritingMode()) {
   1531                 LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit());
   1532                 if (topOfFirstRubyTextLine >= 0)
   1533                     continue;
   1534                 topOfFirstRubyTextLine += curr->logicalTop();
   1535                 result = max(result, allowedPosition - topOfFirstRubyTextLine);
   1536             } else {
   1537                 LayoutUnit bottomOfLastRubyTextLine = rubyText->logicalTop() + (rubyText->lastRootBox() ? rubyText->lastRootBox()->lineBottom() : rubyText->logicalHeight());
   1538                 if (bottomOfLastRubyTextLine <= curr->logicalHeight())
   1539                     continue;
   1540                 bottomOfLastRubyTextLine += curr->logicalTop();
   1541                 result = max(result, bottomOfLastRubyTextLine - allowedPosition);
   1542             }
   1543         }
   1544 
   1545         if (curr->isInlineTextBox()) {
   1546             RenderStyle* style = curr->renderer()->style(isFirstLineStyle());
   1547             if (style->textEmphasisMark() != TextEmphasisMarkNone && style->textEmphasisPosition() == TextEmphasisPositionUnder) {
   1548                 if (!style->isFlippedLinesWritingMode()) {
   1549                     LayoutUnit bottomOfEmphasisMark = curr->logicalBottom() + style->font().emphasisMarkHeight(style->textEmphasisMarkString());
   1550                     result = max(result, bottomOfEmphasisMark - allowedPosition);
   1551                 } else {
   1552                     LayoutUnit topOfEmphasisMark = curr->logicalTop() - style->font().emphasisMarkHeight(style->textEmphasisMarkString());
   1553                     result = max(result, allowedPosition - topOfEmphasisMark);
   1554                 }
   1555             }
   1556         }
   1557     }
   1558     return result;
   1559 }
   1560 
   1561 void InlineFlowBox::collectLeafBoxesInLogicalOrder(Vector<InlineBox*>& leafBoxesInLogicalOrder, CustomInlineBoxRangeReverse customReverseImplementation, void* userData) const
   1562 {
   1563     InlineBox* leaf = firstLeafChild();
   1564 
   1565     // FIXME: The reordering code is a copy of parts from BidiResolver::createBidiRunsForLine, operating directly on InlineBoxes, instead of BidiRuns.
   1566     // Investigate on how this code could possibly be shared.
   1567     unsigned char minLevel = 128;
   1568     unsigned char maxLevel = 0;
   1569 
   1570     // First find highest and lowest levels, and initialize leafBoxesInLogicalOrder with the leaf boxes in visual order.
   1571     for (; leaf; leaf = leaf->nextLeafChild()) {
   1572         minLevel = min(minLevel, leaf->bidiLevel());
   1573         maxLevel = max(maxLevel, leaf->bidiLevel());
   1574         leafBoxesInLogicalOrder.append(leaf);
   1575     }
   1576 
   1577     if (renderer()->style()->rtlOrdering() == VisualOrder)
   1578         return;
   1579 
   1580     // Reverse of reordering of the line (L2 according to Bidi spec):
   1581     // L2. From the highest level found in the text to the lowest odd level on each line,
   1582     // reverse any contiguous sequence of characters that are at that level or higher.
   1583 
   1584     // Reversing the reordering of the line is only done up to the lowest odd level.
   1585     if (!(minLevel % 2))
   1586         ++minLevel;
   1587 
   1588     Vector<InlineBox*>::iterator end = leafBoxesInLogicalOrder.end();
   1589     while (minLevel <= maxLevel) {
   1590         Vector<InlineBox*>::iterator it = leafBoxesInLogicalOrder.begin();
   1591         while (it != end) {
   1592             while (it != end) {
   1593                 if ((*it)->bidiLevel() >= minLevel)
   1594                     break;
   1595                 ++it;
   1596             }
   1597             Vector<InlineBox*>::iterator first = it;
   1598             while (it != end) {
   1599                 if ((*it)->bidiLevel() < minLevel)
   1600                     break;
   1601                 ++it;
   1602             }
   1603             Vector<InlineBox*>::iterator last = it;
   1604             if (customReverseImplementation) {
   1605                 ASSERT(userData);
   1606                 (*customReverseImplementation)(userData, first, last);
   1607             } else
   1608                 std::reverse(first, last);
   1609         }
   1610         ++minLevel;
   1611     }
   1612 }
   1613 
   1614 #ifndef NDEBUG
   1615 
   1616 const char* InlineFlowBox::boxName() const
   1617 {
   1618     return "InlineFlowBox";
   1619 }
   1620 
   1621 void InlineFlowBox::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const RenderObject* obj, int depth) const
   1622 {
   1623     InlineBox::showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLabel2, obj, depth);
   1624     for (const InlineBox* box = firstChild(); box; box = box->nextOnLine())
   1625         box->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLabel2, obj, depth + 1);
   1626 }
   1627 
   1628 void InlineFlowBox::checkConsistency() const
   1629 {
   1630 #ifdef CHECK_CONSISTENCY
   1631     ASSERT(!m_hasBadChildList);
   1632     const InlineBox* prev = 0;
   1633     for (const InlineBox* child = m_firstChild; child; child = child->nextOnLine()) {
   1634         ASSERT(child->parent() == this);
   1635         ASSERT(child->prevOnLine() == prev);
   1636         prev = child;
   1637     }
   1638     ASSERT(prev == m_lastChild);
   1639 #endif
   1640 }
   1641 
   1642 #endif
   1643 
   1644 } // namespace WebCore
   1645