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 "InlineFlowBox.h"
     22 
     23 #include "CachedImage.h"
     24 #include "Document.h"
     25 #include "EllipsisBox.h"
     26 #include "GraphicsContext.h"
     27 #include "InlineTextBox.h"
     28 #include "HitTestResult.h"
     29 #include "RootInlineBox.h"
     30 #include "RenderBlock.h"
     31 #include "RenderInline.h"
     32 #include "RenderLayer.h"
     33 #include "RenderListMarker.h"
     34 #include "RenderTableCell.h"
     35 #include "RootInlineBox.h"
     36 #include "Text.h"
     37 
     38 #include <math.h>
     39 
     40 using namespace std;
     41 
     42 namespace WebCore {
     43 
     44 #ifndef NDEBUG
     45 
     46 InlineFlowBox::~InlineFlowBox()
     47 {
     48     if (!m_hasBadChildList)
     49         for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
     50             child->setHasBadParent();
     51 }
     52 
     53 #endif
     54 
     55 int InlineFlowBox::getFlowSpacingWidth()
     56 {
     57     int totWidth = marginBorderPaddingLeft() + marginBorderPaddingRight();
     58     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
     59         if (curr->isInlineFlowBox())
     60             totWidth += static_cast<InlineFlowBox*>(curr)->getFlowSpacingWidth();
     61     }
     62     return totWidth;
     63 }
     64 
     65 void InlineFlowBox::addToLine(InlineBox* child)
     66 {
     67     ASSERT(!child->parent());
     68     ASSERT(!child->nextOnLine());
     69     ASSERT(!child->prevOnLine());
     70     checkConsistency();
     71 
     72     child->setParent(this);
     73     if (!m_firstChild) {
     74         m_firstChild = child;
     75         m_lastChild = child;
     76     } else {
     77         m_lastChild->setNextOnLine(child);
     78         child->setPrevOnLine(m_lastChild);
     79         m_lastChild = child;
     80     }
     81     child->setFirstLineStyleBit(m_firstLine);
     82     if (child->isText())
     83         m_hasTextChildren = true;
     84     if (child->renderer()->selectionState() != RenderObject::SelectionNone)
     85         root()->setHasSelectedChildren(true);
     86 
     87     checkConsistency();
     88 }
     89 
     90 void InlineFlowBox::removeChild(InlineBox* child)
     91 {
     92     checkConsistency();
     93 
     94     if (!m_dirty)
     95         dirtyLineBoxes();
     96 
     97     root()->childRemoved(child);
     98 
     99     if (child == m_firstChild)
    100         m_firstChild = child->nextOnLine();
    101     if (child == m_lastChild)
    102         m_lastChild = child->prevOnLine();
    103     if (child->nextOnLine())
    104         child->nextOnLine()->setPrevOnLine(child->prevOnLine());
    105     if (child->prevOnLine())
    106         child->prevOnLine()->setNextOnLine(child->nextOnLine());
    107 
    108     child->setParent(0);
    109 
    110     checkConsistency();
    111 }
    112 
    113 void InlineFlowBox::deleteLine(RenderArena* arena)
    114 {
    115     InlineBox* child = firstChild();
    116     InlineBox* next = 0;
    117     while (child) {
    118         ASSERT(this == child->parent());
    119         next = child->nextOnLine();
    120 #ifndef NDEBUG
    121         child->setParent(0);
    122 #endif
    123         child->deleteLine(arena);
    124         child = next;
    125     }
    126 #ifndef NDEBUG
    127     m_firstChild = 0;
    128     m_lastChild = 0;
    129 #endif
    130 
    131     removeLineBoxFromRenderObject();
    132     destroy(arena);
    133 }
    134 
    135 void InlineFlowBox::removeLineBoxFromRenderObject()
    136 {
    137     toRenderInline(renderer())->lineBoxes()->removeLineBox(this);
    138 }
    139 
    140 void InlineFlowBox::extractLine()
    141 {
    142     if (!m_extracted)
    143         extractLineBoxFromRenderObject();
    144     for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
    145         child->extractLine();
    146 }
    147 
    148 void InlineFlowBox::extractLineBoxFromRenderObject()
    149 {
    150     toRenderInline(renderer())->lineBoxes()->extractLineBox(this);
    151 }
    152 
    153 void InlineFlowBox::attachLine()
    154 {
    155     if (m_extracted)
    156         attachLineBoxToRenderObject();
    157     for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
    158         child->attachLine();
    159 }
    160 
    161 void InlineFlowBox::attachLineBoxToRenderObject()
    162 {
    163     toRenderInline(renderer())->lineBoxes()->attachLineBox(this);
    164 }
    165 
    166 void InlineFlowBox::adjustPosition(int dx, int dy)
    167 {
    168     InlineRunBox::adjustPosition(dx, dy);
    169     for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
    170         child->adjustPosition(dx, dy);
    171     if (m_overflow)
    172         m_overflow->move(dx, dy);
    173 }
    174 
    175 RenderLineBoxList* InlineFlowBox::rendererLineBoxes() const
    176 {
    177     return toRenderInline(renderer())->lineBoxes();
    178 }
    179 
    180 bool InlineFlowBox::onEndChain(RenderObject* endObject)
    181 {
    182     if (!endObject)
    183         return false;
    184 
    185     if (endObject == renderer())
    186         return true;
    187 
    188     RenderObject* curr = endObject;
    189     RenderObject* parent = curr->parent();
    190     while (parent && !parent->isRenderBlock()) {
    191         if (parent->lastChild() != curr || parent == renderer())
    192             return false;
    193 
    194         curr = parent;
    195         parent = curr->parent();
    196     }
    197 
    198     return true;
    199 }
    200 
    201 void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject)
    202 {
    203     // All boxes start off open.  They will not apply any margins/border/padding on
    204     // any side.
    205     bool includeLeftEdge = false;
    206     bool includeRightEdge = false;
    207 
    208     // The root inline box never has borders/margins/padding.
    209     if (parent()) {
    210         bool ltr = renderer()->style()->direction() == LTR;
    211 
    212         // Check to see if all initial lines are unconstructed.  If so, then
    213         // we know the inline began on this line (unless we are a continuation).
    214         RenderLineBoxList* lineBoxList = rendererLineBoxes();
    215         if (!lineBoxList->firstLineBox()->isConstructed() && !renderer()->isInlineContinuation()) {
    216             if (ltr && lineBoxList->firstLineBox() == this)
    217                 includeLeftEdge = true;
    218             else if (!ltr && lineBoxList->lastLineBox() == this)
    219                 includeRightEdge = true;
    220         }
    221 
    222         // In order to determine if the inline ends on this line, we check three things:
    223         // (1) If we are the last line and we don't have a continuation(), then we can
    224         // close up.
    225         // (2) If the last line box for the flow has an object following it on the line (ltr,
    226         // reverse for rtl), then the inline has closed.
    227         // (3) The line may end on the inline.  If we are the last child (climbing up
    228         // the end object's chain), then we just closed as well.
    229         if (!lineBoxList->lastLineBox()->isConstructed()) {
    230             RenderInline* inlineFlow = toRenderInline(renderer());
    231             if (ltr) {
    232                 if (!nextLineBox() &&
    233                     ((lastLine && !inlineFlow->continuation()) || nextOnLineExists() || onEndChain(endObject)))
    234                     includeRightEdge = true;
    235             } else {
    236                 if ((!prevLineBox() || prevLineBox()->isConstructed()) &&
    237                     ((lastLine && !inlineFlow->continuation()) || prevOnLineExists() || onEndChain(endObject)))
    238                     includeLeftEdge = true;
    239             }
    240         }
    241     }
    242 
    243     setEdges(includeLeftEdge, includeRightEdge);
    244 
    245     // Recur into our children.
    246     for (InlineBox* currChild = firstChild(); currChild; currChild = currChild->nextOnLine()) {
    247         if (currChild->isInlineFlowBox()) {
    248             InlineFlowBox* currFlow = static_cast<InlineFlowBox*>(currChild);
    249             currFlow->determineSpacingForFlowBoxes(lastLine, endObject);
    250         }
    251     }
    252 }
    253 
    254 int InlineFlowBox::placeBoxesHorizontally(int xPos, bool& needsWordSpacing)
    255 {
    256     // Set our x position.
    257     setX(xPos);
    258 
    259     int leftLayoutOverflow = xPos;
    260     int rightLayoutOverflow = xPos;
    261     int leftVisualOverflow = xPos;
    262     int rightVisualOverflow = xPos;
    263 
    264     int boxShadowLeft;
    265     int boxShadowRight;
    266     renderer()->style(m_firstLine)->getBoxShadowHorizontalExtent(boxShadowLeft, boxShadowRight);
    267 
    268     leftVisualOverflow = min(xPos + boxShadowLeft, leftVisualOverflow);
    269 
    270     int startX = xPos;
    271     xPos += borderLeft() + paddingLeft();
    272 
    273     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    274         if (curr->renderer()->isText()) {
    275             InlineTextBox* text = static_cast<InlineTextBox*>(curr);
    276             RenderText* rt = toRenderText(text->renderer());
    277             if (rt->textLength()) {
    278                 if (needsWordSpacing && isSpaceOrNewline(rt->characters()[text->start()]))
    279                     xPos += rt->style(m_firstLine)->font().wordSpacing();
    280                 needsWordSpacing = !isSpaceOrNewline(rt->characters()[text->end()]);
    281             }
    282             text->setX(xPos);
    283 
    284             int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f));
    285 
    286             // If letter-spacing is negative, we should factor that into right layout overflow. (Even in RTL, letter-spacing is
    287             // applied to the right, so this is not an issue with left overflow.
    288             int letterSpacing = min(0, (int)rt->style(m_firstLine)->font().letterSpacing());
    289             rightLayoutOverflow = max(xPos + text->width() - letterSpacing, rightLayoutOverflow);
    290 
    291             int leftGlyphOverflow = -strokeOverflow;
    292             int rightGlyphOverflow = strokeOverflow - letterSpacing;
    293 
    294             int childOverflowLeft = leftGlyphOverflow;
    295             int childOverflowRight = rightGlyphOverflow;
    296             for (ShadowData* shadow = rt->style()->textShadow(); shadow; shadow = shadow->next) {
    297                 childOverflowLeft = min(childOverflowLeft, shadow->x - shadow->blur + leftGlyphOverflow);
    298                 childOverflowRight = max(childOverflowRight, shadow->x + shadow->blur + rightGlyphOverflow);
    299             }
    300 
    301             leftVisualOverflow = min(xPos + childOverflowLeft, leftVisualOverflow);
    302             rightVisualOverflow = max(xPos + text->width() + childOverflowRight, rightVisualOverflow);
    303 
    304             xPos += text->width();
    305         } else {
    306             if (curr->renderer()->isPositioned()) {
    307                 if (curr->renderer()->parent()->style()->direction() == LTR)
    308                     curr->setX(xPos);
    309                 else
    310                     // Our offset that we cache needs to be from the edge of the right border box and
    311                     // not the left border box.  We have to subtract |x| from the width of the block
    312                     // (which can be obtained from the root line box).
    313                     curr->setX(root()->block()->width() - xPos);
    314                 continue; // The positioned object has no effect on the width.
    315             }
    316             if (curr->renderer()->isRenderInline()) {
    317                 InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
    318                 xPos += flow->marginLeft();
    319                 xPos = flow->placeBoxesHorizontally(xPos, needsWordSpacing);
    320                 xPos += flow->marginRight();
    321                 leftLayoutOverflow = min(leftLayoutOverflow, flow->leftLayoutOverflow());
    322                 rightLayoutOverflow = max(rightLayoutOverflow, flow->rightLayoutOverflow());
    323                 leftVisualOverflow = min(leftVisualOverflow, flow->leftVisualOverflow());
    324                 rightVisualOverflow = max(rightVisualOverflow, flow->rightVisualOverflow());
    325             } else if (!curr->renderer()->isListMarker() || toRenderListMarker(curr->renderer())->isInside()) {
    326                 xPos += curr->boxModelObject()->marginLeft();
    327                 curr->setX(xPos);
    328 
    329                 RenderBox* box = toRenderBox(curr->renderer());
    330                 int childLeftOverflow = box->hasOverflowClip() ? 0 : box->leftLayoutOverflow();
    331                 int childRightOverflow = box->hasOverflowClip() ? curr->width() : box->rightLayoutOverflow();
    332 
    333                 leftLayoutOverflow = min(xPos + childLeftOverflow, leftLayoutOverflow);
    334                 rightLayoutOverflow = max(xPos + childRightOverflow, rightLayoutOverflow);
    335 
    336                 leftVisualOverflow = min(xPos + box->leftVisualOverflow(), leftVisualOverflow);
    337                 rightVisualOverflow = max(xPos + box->rightVisualOverflow(), rightVisualOverflow);
    338 
    339                 xPos += curr->width() + curr->boxModelObject()->marginRight();
    340             }
    341         }
    342     }
    343 
    344     xPos += borderRight() + paddingRight();
    345     setWidth(xPos - startX);
    346     rightVisualOverflow = max(x() + width() + boxShadowRight, rightVisualOverflow);
    347     rightLayoutOverflow = max(x() + width(), rightLayoutOverflow);
    348 
    349     setHorizontalOverflowPositions(leftLayoutOverflow, rightLayoutOverflow, leftVisualOverflow, rightVisualOverflow);
    350     return xPos;
    351 }
    352 
    353 void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
    354                                               int maxPositionTop, int maxPositionBottom)
    355 {
    356     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    357         // The computed lineheight needs to be extended for the
    358         // positioned elements
    359         if (curr->renderer()->isPositioned())
    360             continue; // Positioned placeholders don't affect calculations.
    361         if (curr->y() == PositionTop || curr->y() == PositionBottom) {
    362             int lineHeight = curr->lineHeight(false);
    363             if (curr->y() == PositionTop) {
    364                 if (maxAscent + maxDescent < lineHeight)
    365                     maxDescent = lineHeight - maxAscent;
    366             }
    367             else {
    368                 if (maxAscent + maxDescent < lineHeight)
    369                     maxAscent = lineHeight - maxDescent;
    370             }
    371 
    372             if (maxAscent + maxDescent >= max(maxPositionTop, maxPositionBottom))
    373                 break;
    374         }
    375 
    376         if (curr->isInlineFlowBox())
    377             static_cast<InlineFlowBox*>(curr)->adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
    378     }
    379 }
    380 
    381 static int verticalPositionForBox(InlineBox* curr, bool firstLine)
    382 {
    383     if (curr->renderer()->isText())
    384         return curr->parent()->y();
    385     if (curr->renderer()->isBox())
    386         return toRenderBox(curr->renderer())->verticalPosition(firstLine);
    387     return toRenderInline(curr->renderer())->verticalPositionFromCache(firstLine);
    388 }
    389 
    390 void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
    391                                              int& maxAscent, int& maxDescent, bool strictMode)
    392 {
    393     if (isRootInlineBox()) {
    394         // Examine our root box.
    395         int height = lineHeight(true);
    396         int baseline = baselinePosition(true);
    397         if (hasTextChildren() || strictMode) {
    398             int ascent = baseline;
    399             int descent = height - ascent;
    400             if (maxAscent < ascent)
    401                 maxAscent = ascent;
    402             if (maxDescent < descent)
    403                 maxDescent = descent;
    404         }
    405     }
    406 
    407     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    408         if (curr->renderer()->isPositioned())
    409             continue; // Positioned placeholders don't affect calculations.
    410 
    411         bool isInlineFlow = curr->isInlineFlowBox();
    412 
    413         int lineHeight;
    414         int baseline;
    415         Vector<const SimpleFontData*> usedFonts;
    416         if (curr->isInlineTextBox())
    417             static_cast<InlineTextBox*>(curr)->takeFallbackFonts(usedFonts);
    418 
    419         if (!usedFonts.isEmpty()) {
    420             usedFonts.append(curr->renderer()->style(m_firstLine)->font().primaryFont());
    421             Length parentLineHeight = curr->renderer()->parent()->style()->lineHeight();
    422             if (parentLineHeight.isNegative()) {
    423                 int baselineToBottom = 0;
    424                 baseline = 0;
    425                 for (size_t i = 0; i < usedFonts.size(); ++i) {
    426                     int halfLeading = (usedFonts[i]->lineSpacing() - usedFonts[i]->ascent() - usedFonts[i]->descent()) / 2;
    427                     baseline = max(baseline, halfLeading + usedFonts[i]->ascent());
    428                     baselineToBottom = max(baselineToBottom, usedFonts[i]->lineSpacing() - usedFonts[i]->ascent() - usedFonts[i]->descent() - halfLeading);
    429                 }
    430                 lineHeight = baseline + baselineToBottom;
    431             } else if (parentLineHeight.isPercent()) {
    432                 lineHeight = parentLineHeight.calcMinValue(curr->renderer()->style()->fontSize());
    433                 baseline = 0;
    434                 for (size_t i = 0; i < usedFonts.size(); ++i) {
    435                     int halfLeading = (lineHeight - usedFonts[i]->ascent() - usedFonts[i]->descent()) / 2;
    436                     baseline = max(baseline, halfLeading + usedFonts[i]->ascent());
    437                 }
    438             } else {
    439                 lineHeight = parentLineHeight.value();
    440                 baseline = 0;
    441                 for (size_t i = 0; i < usedFonts.size(); ++i) {
    442                     int halfLeading = (lineHeight - usedFonts[i]->ascent() - usedFonts[i]->descent()) / 2;
    443                     baseline = max(baseline, halfLeading + usedFonts[i]->ascent());
    444                 }
    445             }
    446         } else {
    447             lineHeight = curr->lineHeight(false);
    448             baseline = curr->baselinePosition(false);
    449         }
    450 
    451         curr->setY(verticalPositionForBox(curr, m_firstLine));
    452         if (curr->y() == PositionTop) {
    453             if (maxPositionTop < lineHeight)
    454                 maxPositionTop = lineHeight;
    455         } else if (curr->y() == PositionBottom) {
    456             if (maxPositionBottom < lineHeight)
    457                 maxPositionBottom = lineHeight;
    458         } else if ((!isInlineFlow || static_cast<InlineFlowBox*>(curr)->hasTextChildren()) || curr->boxModelObject()->hasHorizontalBordersOrPadding() || strictMode) {
    459             int ascent = baseline - curr->y();
    460             int descent = lineHeight - ascent;
    461             if (maxAscent < ascent)
    462                 maxAscent = ascent;
    463             if (maxDescent < descent)
    464                 maxDescent = descent;
    465         }
    466 
    467         if (curr->isInlineFlowBox())
    468             static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
    469     }
    470 }
    471 
    472 void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent, bool strictMode, int& selectionTop, int& selectionBottom)
    473 {
    474     if (isRootInlineBox())
    475         setY(yPos + maxAscent - baselinePosition(true)); // Place our root box.
    476 
    477     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    478         if (curr->renderer()->isPositioned())
    479             continue; // Positioned placeholders don't affect calculations.
    480 
    481         // Adjust boxes to use their real box y/height and not the logical height (as dictated by
    482         // line-height).
    483         bool isInlineFlow = curr->isInlineFlowBox();
    484         if (isInlineFlow)
    485             static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(yPos, maxHeight, maxAscent, strictMode, selectionTop, selectionBottom);
    486 
    487         bool childAffectsTopBottomPos = true;
    488         if (curr->y() == PositionTop)
    489             curr->setY(yPos);
    490         else if (curr->y() == PositionBottom)
    491             curr->setY(yPos + maxHeight - curr->lineHeight(false));
    492         else {
    493             if ((isInlineFlow && !static_cast<InlineFlowBox*>(curr)->hasTextChildren()) && !curr->boxModelObject()->hasHorizontalBordersOrPadding() && !strictMode)
    494                 childAffectsTopBottomPos = false;
    495             int posAdjust = maxAscent - curr->baselinePosition(false);
    496             curr->setY(curr->y() + yPos + posAdjust);
    497         }
    498 
    499         int newY = curr->y();
    500         if (curr->isText() || curr->isInlineFlowBox()) {
    501             const Font& font = curr->renderer()->style(m_firstLine)->font();
    502             newY += curr->baselinePosition(false) - font.ascent();
    503             if (curr->isInlineFlowBox())
    504                 newY -= curr->boxModelObject()->borderTop() + curr->boxModelObject()->paddingTop();
    505         } else if (!curr->renderer()->isBR()) {
    506             RenderBox* box = toRenderBox(curr->renderer());
    507             newY += box->marginTop();
    508         }
    509 
    510         curr->setY(newY);
    511 
    512         if (childAffectsTopBottomPos) {
    513             int boxHeight = curr->height();
    514             selectionTop = min(selectionTop, newY);
    515             selectionBottom = max(selectionBottom, newY + boxHeight);
    516         }
    517     }
    518 
    519     if (isRootInlineBox()) {
    520         const Font& font = renderer()->style(m_firstLine)->font();
    521         setY(y() + baselinePosition(true) - font.ascent());
    522         if (hasTextChildren() || strictMode) {
    523             selectionTop = min(selectionTop, y());
    524             selectionBottom = max(selectionBottom, y() + height());
    525         }
    526     }
    527 }
    528 
    529 void InlineFlowBox::computeVerticalOverflow(int lineTop, int lineBottom, bool strictMode)
    530 {
    531     int boxHeight = height();
    532 
    533     // Any spillage outside of the line top and bottom is not considered overflow.  We just ignore this, since it only happens
    534     // from the "your ascent/descent don't affect the line" quirk.
    535     int topOverflow = max(y(), lineTop);
    536     int bottomOverflow = min(y() + boxHeight, lineBottom);
    537 
    538     int topLayoutOverflow = topOverflow;
    539     int bottomLayoutOverflow = bottomOverflow;
    540 
    541     int topVisualOverflow = topOverflow;
    542     int bottomVisualOverflow = bottomOverflow;
    543 
    544     // box-shadow on root line boxes is applying to the block and not to the lines.
    545     if (parent()) {
    546         int boxShadowTop;
    547         int boxShadowBottom;
    548         renderer()->style(m_firstLine)->getBoxShadowVerticalExtent(boxShadowTop, boxShadowBottom);
    549 
    550         topVisualOverflow = min(y() + boxShadowTop, topVisualOverflow);
    551         bottomVisualOverflow = max(y() + boxHeight + boxShadowBottom, bottomVisualOverflow);
    552     }
    553 
    554     for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    555         if (curr->renderer()->isPositioned())
    556             continue; // Positioned placeholders don't affect calculations.
    557 
    558         if (curr->renderer()->isText()) {
    559             InlineTextBox* text = static_cast<InlineTextBox*>(curr);
    560             RenderText* rt = toRenderText(text->renderer());
    561             if (rt->isBR())
    562                 continue;
    563 
    564             int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f));
    565 
    566             int topGlyphOverflow = -strokeOverflow;
    567             int bottomGlyphOverflow = strokeOverflow;
    568 
    569             int childOverflowTop = topGlyphOverflow;
    570             int childOverflowBottom = bottomGlyphOverflow;
    571             for (ShadowData* shadow = rt->style()->textShadow(); shadow; shadow = shadow->next) {
    572                 childOverflowTop = min(childOverflowTop, shadow->y - shadow->blur + topGlyphOverflow);
    573                 childOverflowBottom = max(childOverflowBottom, shadow->y + shadow->blur + bottomGlyphOverflow);
    574             }
    575 
    576             topVisualOverflow = min(curr->y() + childOverflowTop, topVisualOverflow);
    577             bottomVisualOverflow = max(curr->y() + text->height() + childOverflowBottom, bottomVisualOverflow);
    578         } else  if (curr->renderer()->isRenderInline()) {
    579             InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
    580             flow->computeVerticalOverflow(lineTop, lineBottom, strictMode);
    581             topLayoutOverflow = min(topLayoutOverflow, flow->topLayoutOverflow());
    582             bottomLayoutOverflow = max(bottomLayoutOverflow, flow->bottomLayoutOverflow());
    583             topVisualOverflow = min(topVisualOverflow, flow->topVisualOverflow());
    584             bottomVisualOverflow = max(bottomVisualOverflow, flow->bottomVisualOverflow());
    585         } else if (!curr->boxModelObject()->hasSelfPaintingLayer()){
    586             // Only include overflow from replaced inlines if they do not paint themselves.
    587             RenderBox* box = toRenderBox(curr->renderer());
    588             int boxY = curr->y();
    589             int childTopOverflow = box->hasOverflowClip() ? 0 : box->topLayoutOverflow();
    590             int childBottomOverflow = box->hasOverflowClip() ? curr->height() : box->bottomLayoutOverflow();
    591             topLayoutOverflow = min(boxY + childTopOverflow, topLayoutOverflow);
    592             bottomLayoutOverflow = max(boxY + childBottomOverflow, bottomLayoutOverflow);
    593             topVisualOverflow = min(boxY + box->topVisualOverflow(), topVisualOverflow);
    594             bottomVisualOverflow = max(boxY + box->bottomVisualOverflow(), bottomVisualOverflow);
    595         }
    596     }
    597 
    598     setVerticalOverflowPositions(topLayoutOverflow, bottomLayoutOverflow, topVisualOverflow, bottomVisualOverflow, boxHeight);
    599 }
    600 
    601 bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
    602 {
    603     IntRect overflowRect(visibleOverflowRect());
    604     overflowRect.move(tx, ty);
    605     if (!overflowRect.contains(x, y))
    606         return false;
    607 
    608     // Check children first.
    609     for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
    610         if ((curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) && curr->nodeAtPoint(request, result, x, y, tx, ty)) {
    611             renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
    612             return true;
    613         }
    614     }
    615 
    616     // Now check ourselves.
    617     IntRect rect(tx + m_x, ty + m_y, m_width, height());
    618     if (visibleToHitTesting() && rect.contains(x, y)) {
    619         renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); // Don't add in m_x or m_y here, we want coords in the containing block's space.
    620         return true;
    621     }
    622 
    623     return false;
    624 }
    625 
    626 void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
    627 {
    628     IntRect overflowRect(visibleOverflowRect());
    629     overflowRect.inflate(renderer()->maximalOutlineSize(paintInfo.phase));
    630     overflowRect.move(tx, ty);
    631 
    632     if (!paintInfo.rect.intersects(overflowRect))
    633         return;
    634 
    635     if (paintInfo.phase != PaintPhaseChildOutlines) {
    636         if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
    637             // Add ourselves to the paint info struct's list of inlines that need to paint their
    638             // outlines.
    639             if (renderer()->style()->visibility() == VISIBLE && renderer()->hasOutline() && !isRootInlineBox()) {
    640                 RenderInline* inlineFlow = toRenderInline(renderer());
    641                 if ((inlineFlow->continuation() || inlineFlow->isInlineContinuation()) && !boxModelObject()->hasSelfPaintingLayer()) {
    642                     // Add ourselves to the containing block of the entire continuation so that it can
    643                     // paint us atomically.
    644                     RenderBlock* block = renderer()->containingBlock()->containingBlock();
    645                     block->addContinuationWithOutline(toRenderInline(renderer()->node()->renderer()));
    646                 } else if (!inlineFlow->isInlineContinuation())
    647                     paintInfo.outlineObjects->add(inlineFlow);
    648             }
    649         } else if (paintInfo.phase == PaintPhaseMask) {
    650             paintMask(paintInfo, tx, ty);
    651             return;
    652         } else {
    653             // 1. Paint our background, border and box-shadow.
    654             paintBoxDecorations(paintInfo, tx, ty);
    655 
    656             // 2. Paint our underline and overline.
    657             paintTextDecorations(paintInfo, tx, ty, false);
    658         }
    659     }
    660 
    661     if (paintInfo.phase == PaintPhaseMask)
    662         return;
    663 
    664     PaintPhase paintPhase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;
    665     RenderObject::PaintInfo childInfo(paintInfo);
    666     childInfo.phase = paintPhase;
    667     childInfo.paintingRoot = renderer()->paintingRootForChildren(paintInfo);
    668 
    669     // 3. Paint our children.
    670     if (paintPhase != PaintPhaseSelfOutline) {
    671         for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    672             if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer())
    673                 curr->paint(childInfo, tx, ty);
    674         }
    675     }
    676 
    677     // 4. Paint our strike-through
    678     if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)
    679         paintTextDecorations(paintInfo, tx, ty, true);
    680 }
    681 
    682 void InlineFlowBox::paintFillLayers(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int _tx, int _ty, int w, int h, CompositeOperator op)
    683 {
    684     if (!fillLayer)
    685         return;
    686     paintFillLayers(paintInfo, c, fillLayer->next(), _tx, _ty, w, h, op);
    687     paintFillLayer(paintInfo, c, fillLayer, _tx, _ty, w, h, op);
    688 }
    689 
    690 void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int w, int h, CompositeOperator op)
    691 {
    692     StyleImage* img = fillLayer->image();
    693     bool hasFillImage = img && img->canRender(renderer()->style()->effectiveZoom());
    694     if ((!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
    695         boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, w, h, this, op);
    696     else {
    697         // We have a fill image that spans multiple lines.
    698         // We need to adjust _tx and _ty by the width of all previous lines.
    699         // Think of background painting on inlines as though you had one long line, a single continuous
    700         // strip.  Even though that strip has been broken up across multiple lines, you still paint it
    701         // as though you had one single line.  This means each line has to pick up the background where
    702         // the previous line left off.
    703         // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
    704         // but it isn't even clear how this should work at all.
    705         int xOffsetOnLine = 0;
    706         for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
    707             xOffsetOnLine += curr->width();
    708         int startX = tx - xOffsetOnLine;
    709         int totalWidth = xOffsetOnLine;
    710         for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
    711             totalWidth += curr->width();
    712         paintInfo.context->save();
    713         paintInfo.context->clip(IntRect(tx, ty, width(), height()));
    714         boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, startX, ty, totalWidth, h, this, op);
    715         paintInfo.context->restore();
    716     }
    717 }
    718 
    719 void InlineFlowBox::paintBoxShadow(GraphicsContext* context, RenderStyle* s, ShadowStyle shadowStyle, int tx, int ty, int w, int h)
    720 {
    721     if ((!prevLineBox() && !nextLineBox()) || !parent())
    722         boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s, shadowStyle);
    723     else {
    724         // FIXME: We can do better here in the multi-line case. We want to push a clip so that the shadow doesn't
    725         // protrude incorrectly at the edges, and we want to possibly include shadows cast from the previous/following lines
    726         boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s, shadowStyle, includeLeftEdge(), includeRightEdge());
    727     }
    728 }
    729 
    730 void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int tx, int ty)
    731 {
    732     if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
    733         return;
    734 
    735     int x = m_x;
    736     int y = m_y;
    737     int w = width();
    738     int h = height();
    739 
    740     // Constrain our background/border painting to the line top and bottom if necessary.
    741     bool strictMode = renderer()->document()->inStrictMode();
    742     if (!hasTextChildren() && !strictMode) {
    743         RootInlineBox* rootBox = root();
    744         int bottom = min(rootBox->lineBottom(), y + h);
    745         y = max(rootBox->lineTop(), y);
    746         h = bottom - y;
    747     }
    748 
    749     // Move x/y to our coordinates.
    750     tx += x;
    751     ty += y;
    752 
    753     GraphicsContext* context = paintInfo.context;
    754 
    755     // You can use p::first-line to specify a background. If so, the root line boxes for
    756     // a line may actually have to paint a background.
    757     RenderStyle* styleToUse = renderer()->style(m_firstLine);
    758     if ((!parent() && m_firstLine && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) {
    759         // Shadow comes first and is behind the background and border.
    760         if (styleToUse->boxShadow())
    761             paintBoxShadow(context, styleToUse, Normal, tx, ty, w, h);
    762 
    763         Color c = styleToUse->backgroundColor();
    764         paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), tx, ty, w, h);
    765 
    766         if (styleToUse->boxShadow())
    767             paintBoxShadow(context, styleToUse, Inset, tx, ty, w, h);
    768 
    769         // :first-line cannot be used to put borders on a line. Always paint borders with our
    770         // non-first-line style.
    771         if (parent() && renderer()->style()->hasBorder()) {
    772             StyleImage* borderImage = renderer()->style()->borderImage().image();
    773             bool hasBorderImage = borderImage && borderImage->canRender(styleToUse->effectiveZoom());
    774             if (hasBorderImage && !borderImage->isLoaded())
    775                 return; // Don't paint anything while we wait for the image to load.
    776 
    777             // The simple case is where we either have no border image or we are the only box for this object.  In those
    778             // cases only a single call to draw is required.
    779             if (!hasBorderImage || (!prevLineBox() && !nextLineBox()))
    780                 boxModelObject()->paintBorder(context, tx, ty, w, h, renderer()->style(), includeLeftEdge(), includeRightEdge());
    781             else {
    782                 // We have a border image that spans multiple lines.
    783                 // We need to adjust _tx and _ty by the width of all previous lines.
    784                 // Think of border image painting on inlines as though you had one long line, a single continuous
    785                 // strip.  Even though that strip has been broken up across multiple lines, you still paint it
    786                 // as though you had one single line.  This means each line has to pick up the image where
    787                 // the previous line left off.
    788                 // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
    789                 // but it isn't even clear how this should work at all.
    790                 int xOffsetOnLine = 0;
    791                 for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
    792                     xOffsetOnLine += curr->width();
    793                 int startX = tx - xOffsetOnLine;
    794                 int totalWidth = xOffsetOnLine;
    795                 for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
    796                     totalWidth += curr->width();
    797                 context->save();
    798                 context->clip(IntRect(tx, ty, w, h));
    799                 boxModelObject()->paintBorder(context, startX, ty, totalWidth, h, renderer()->style());
    800                 context->restore();
    801             }
    802         }
    803     }
    804 }
    805 
    806 void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty)
    807 {
    808     if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
    809         return;
    810 
    811     int x = m_x;
    812     int y = m_y;
    813     int w = width();
    814     int h = height();
    815 
    816     // Constrain our background/border painting to the line top and bottom if necessary.
    817     bool strictMode = renderer()->document()->inStrictMode();
    818     if (!hasTextChildren() && !strictMode) {
    819         RootInlineBox* rootBox = root();
    820         int bottom = min(rootBox->lineBottom(), y + h);
    821         y = max(rootBox->lineTop(), y);
    822         h = bottom - y;
    823     }
    824 
    825     // Move x/y to our coordinates.
    826     tx += x;
    827     ty += y;
    828 
    829     const NinePieceImage& maskNinePieceImage = renderer()->style()->maskBoxImage();
    830     StyleImage* maskBoxImage = renderer()->style()->maskBoxImage().image();
    831 
    832     // Figure out if we need to push a transparency layer to render our mask.
    833     bool pushTransparencyLayer = false;
    834     bool compositedMask = renderer()->hasLayer() && boxModelObject()->layer()->hasCompositedMask();
    835     CompositeOperator compositeOp = CompositeSourceOver;
    836     if (!compositedMask) {
    837         if ((maskBoxImage && renderer()->style()->maskLayers()->hasImage()) || renderer()->style()->maskLayers()->next())
    838             pushTransparencyLayer = true;
    839 
    840         compositeOp = CompositeDestinationIn;
    841         if (pushTransparencyLayer) {
    842             paintInfo.context->setCompositeOperation(CompositeDestinationIn);
    843             paintInfo.context->beginTransparencyLayer(1.0f);
    844             compositeOp = CompositeSourceOver;
    845         }
    846     }
    847 
    848     paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), tx, ty, w, h, compositeOp);
    849 
    850     bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer()->style()->effectiveZoom());
    851     if (!hasBoxImage || !maskBoxImage->isLoaded())
    852         return; // Don't paint anything while we wait for the image to load.
    853 
    854     // The simple case is where we are the only box for this object.  In those
    855     // cases only a single call to draw is required.
    856     if (!prevLineBox() && !nextLineBox()) {
    857         boxModelObject()->paintNinePieceImage(paintInfo.context, tx, ty, w, h, renderer()->style(), maskNinePieceImage, compositeOp);
    858     } else {
    859         // We have a mask image that spans multiple lines.
    860         // We need to adjust _tx and _ty by the width of all previous lines.
    861         int xOffsetOnLine = 0;
    862         for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
    863             xOffsetOnLine += curr->width();
    864         int startX = tx - xOffsetOnLine;
    865         int totalWidth = xOffsetOnLine;
    866         for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
    867             totalWidth += curr->width();
    868         paintInfo.context->save();
    869         paintInfo.context->clip(IntRect(tx, ty, w, h));
    870         boxModelObject()->paintNinePieceImage(paintInfo.context, startX, ty, totalWidth, h, renderer()->style(), maskNinePieceImage, compositeOp);
    871         paintInfo.context->restore();
    872     }
    873 
    874     if (pushTransparencyLayer)
    875         paintInfo.context->endTransparencyLayer();
    876 }
    877 
    878 static bool shouldDrawTextDecoration(RenderObject* obj)
    879 {
    880     for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling()) {
    881         if (curr->isRenderInline())
    882             return true;
    883         if (curr->isText() && !curr->isBR()) {
    884             if (!curr->style()->collapseWhiteSpace())
    885                 return true;
    886             Node* currElement = curr->node();
    887             if (!currElement)
    888                 return true;
    889             if (!currElement->isTextNode())
    890                 return true;
    891             if (!static_cast<Text*>(currElement)->containsOnlyWhitespace())
    892                 return true;
    893         }
    894     }
    895     return false;
    896 }
    897 
    898 void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int tx, int ty, bool paintedChildren)
    899 {
    900     // Paint text decorations like underlines/overlines. We only do this if we aren't in quirks mode (i.e., in
    901     // almost-strict mode or strict mode).
    902     if (renderer()->style()->htmlHacks() || !renderer()->shouldPaintWithinRoot(paintInfo) ||
    903         renderer()->style()->visibility() != VISIBLE)
    904         return;
    905 
    906     // We don't want underlines or other decorations when we're trying to draw nothing but the selection as white text.
    907     if (paintInfo.phase == PaintPhaseSelection && paintInfo.forceBlackText)
    908         return;
    909 
    910     GraphicsContext* context = paintInfo.context;
    911     tx += m_x;
    912     ty += m_y;
    913     RenderStyle* styleToUse = renderer()->style(m_firstLine);
    914     int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect();
    915     if (deco != TDNONE &&
    916         ((!paintedChildren && ((deco & UNDERLINE) || (deco & OVERLINE))) || (paintedChildren && (deco & LINE_THROUGH))) &&
    917         shouldDrawTextDecoration(renderer())) {
    918         int x = m_x + borderLeft() + paddingLeft();
    919         int w = m_width - (borderLeft() + paddingLeft() + borderRight() + paddingRight());
    920         RootInlineBox* rootLine = root();
    921         if (rootLine->ellipsisBox()) {
    922             int ellipsisX = m_x + rootLine->ellipsisBox()->x();
    923             int ellipsisWidth = rootLine->ellipsisBox()->width();
    924             bool ltr = renderer()->style()->direction() == LTR;
    925             if (rootLine == this) {
    926                 // Trim w and x so that the underline isn't drawn underneath the ellipsis.
    927                 // ltr: is our right edge farther right than the right edge of the ellipsis.
    928                 // rtl: is the left edge of our box farther left than the left edge of the ellipsis.
    929                 bool ltrTruncation = ltr && (x + w >= ellipsisX + ellipsisWidth);
    930                 bool rtlTruncation = !ltr && (x <= ellipsisX + ellipsisWidth);
    931                 if (ltrTruncation)
    932                     w -= (x + w) - (ellipsisX + ellipsisWidth);
    933                 else if (rtlTruncation) {
    934                     int dx = m_x - ((ellipsisX - m_x) + ellipsisWidth);
    935                     tx -= dx;
    936                     w += dx;
    937                 }
    938             } else {
    939                 bool ltrPastEllipsis = ltr && x >= ellipsisX;
    940                 bool rtlPastEllipsis = !ltr && (x + w) <= (ellipsisX + ellipsisWidth);
    941                 if (ltrPastEllipsis || rtlPastEllipsis)
    942                     return;
    943 
    944                 bool ltrTruncation = ltr && x + w >= ellipsisX;
    945                 bool rtlTruncation = !ltr && x <= ellipsisX;
    946                 if (ltrTruncation)
    947                     w -= (x + w - ellipsisX);
    948                 else if (rtlTruncation) {
    949                     int dx = m_x - ((ellipsisX - m_x) + ellipsisWidth);
    950                     tx -= dx;
    951                     w += dx;
    952                 }
    953             }
    954         }
    955 
    956         // We must have child boxes and have decorations defined.
    957         tx += borderLeft() + paddingLeft();
    958 
    959         Color underline, overline, linethrough;
    960         underline = overline = linethrough = styleToUse->color();
    961         if (!parent())
    962             renderer()->getTextDecorationColors(deco, underline, overline, linethrough);
    963 
    964         bool isPrinting = renderer()->document()->printing();
    965         context->setStrokeThickness(1.0f); // FIXME: We should improve this rule and not always just assume 1.
    966 
    967         bool paintUnderline = deco & UNDERLINE && !paintedChildren;
    968         bool paintOverline = deco & OVERLINE && !paintedChildren;
    969         bool paintLineThrough = deco & LINE_THROUGH && paintedChildren;
    970 
    971         bool linesAreOpaque = !isPrinting && (!paintUnderline || underline.alpha() == 255) && (!paintOverline || overline.alpha() == 255) && (!paintLineThrough || linethrough.alpha() == 255);
    972 
    973         int baselinePos = renderer()->style(m_firstLine)->font().ascent();
    974         if (!isRootInlineBox())
    975             baselinePos += borderTop() + paddingTop();
    976 
    977         bool setClip = false;
    978         int extraOffset = 0;
    979         ShadowData* shadow = styleToUse->textShadow();
    980         if (!linesAreOpaque && shadow && shadow->next) {
    981             IntRect clipRect(tx, ty, w, baselinePos + 2);
    982             for (ShadowData* s = shadow; s; s = s->next) {
    983                 IntRect shadowRect(tx, ty, w, baselinePos + 2);
    984                 shadowRect.inflate(s->blur);
    985                 shadowRect.move(s->x, s->y);
    986                 clipRect.unite(shadowRect);
    987                 extraOffset = max(extraOffset, max(0, s->y) + s->blur);
    988             }
    989             context->save();
    990             context->clip(clipRect);
    991             extraOffset += baselinePos + 2;
    992             ty += extraOffset;
    993             setClip = true;
    994         }
    995 
    996         ColorSpace colorSpace = renderer()->style()->colorSpace();
    997         bool setShadow = false;
    998         do {
    999             if (shadow) {
   1000                 if (!shadow->next) {
   1001                     // The last set of lines paints normally inside the clip.
   1002                     ty -= extraOffset;
   1003                     extraOffset = 0;
   1004                 }
   1005                 context->setShadow(IntSize(shadow->x, shadow->y - extraOffset), shadow->blur, shadow->color, colorSpace);
   1006                 setShadow = true;
   1007                 shadow = shadow->next;
   1008             }
   1009 
   1010             if (paintUnderline) {
   1011                 context->setStrokeColor(underline, colorSpace);
   1012                 context->setStrokeStyle(SolidStroke);
   1013                 // Leave one pixel of white between the baseline and the underline.
   1014                 context->drawLineForText(IntPoint(tx, ty + baselinePos + 1), w, isPrinting);
   1015             }
   1016             if (paintOverline) {
   1017                 context->setStrokeColor(overline, colorSpace);
   1018                 context->setStrokeStyle(SolidStroke);
   1019                 context->drawLineForText(IntPoint(tx, ty), w, isPrinting);
   1020             }
   1021             if (paintLineThrough) {
   1022                 context->setStrokeColor(linethrough, colorSpace);
   1023                 context->setStrokeStyle(SolidStroke);
   1024                 context->drawLineForText(IntPoint(tx, ty + 2 * baselinePos / 3), w, isPrinting);
   1025             }
   1026         } while (shadow);
   1027 
   1028         if (setClip)
   1029             context->restore();
   1030         else if (setShadow)
   1031             context->clearShadow();
   1032     }
   1033 }
   1034 
   1035 InlineBox* InlineFlowBox::firstLeafChild() const
   1036 {
   1037     InlineBox* leaf = 0;
   1038     for (InlineBox* child = firstChild(); child && !leaf; child = child->nextOnLine())
   1039         leaf = child->isLeaf() ? child : static_cast<InlineFlowBox*>(child)->firstLeafChild();
   1040     return leaf;
   1041 }
   1042 
   1043 InlineBox* InlineFlowBox::lastLeafChild() const
   1044 {
   1045     InlineBox* leaf = 0;
   1046     for (InlineBox* child = lastChild(); child && !leaf; child = child->prevOnLine())
   1047         leaf = child->isLeaf() ? child : static_cast<InlineFlowBox*>(child)->lastLeafChild();
   1048     return leaf;
   1049 }
   1050 
   1051 RenderObject::SelectionState InlineFlowBox::selectionState()
   1052 {
   1053     return RenderObject::SelectionNone;
   1054 }
   1055 
   1056 bool InlineFlowBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth)
   1057 {
   1058     for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {
   1059         if (!box->canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth))
   1060             return false;
   1061     }
   1062     return true;
   1063 }
   1064 
   1065 int InlineFlowBox::placeEllipsisBox(bool ltr, int blockLeftEdge, int blockRightEdge, int ellipsisWidth, bool& foundBox)
   1066 {
   1067     int result = -1;
   1068     // We iterate over all children, the foundBox variable tells us when we've found the
   1069     // box containing the ellipsis.  All boxes after that one in the flow are hidden.
   1070     // If our flow is ltr then iterate over the boxes from left to right, otherwise iterate
   1071     // from right to left. Varying the order allows us to correctly hide the boxes following the ellipsis.
   1072     InlineBox *box = ltr ? firstChild() : lastChild();
   1073 
   1074     // NOTE: these will cross after foundBox = true.
   1075     int visibleLeftEdge = blockLeftEdge;
   1076     int visibleRightEdge = blockRightEdge;
   1077 
   1078     while (box) {
   1079         int currResult = box->placeEllipsisBox(ltr, visibleLeftEdge, visibleRightEdge, ellipsisWidth, foundBox);
   1080         if (currResult != -1 && result == -1)
   1081             result = currResult;
   1082 
   1083         if (ltr) {
   1084             visibleLeftEdge += box->width();
   1085             box = box->nextOnLine();
   1086         }
   1087         else {
   1088             visibleRightEdge -= box->width();
   1089             box = box->prevOnLine();
   1090         }
   1091     }
   1092     return result;
   1093 }
   1094 
   1095 void InlineFlowBox::clearTruncation()
   1096 {
   1097     for (InlineBox *box = firstChild(); box; box = box->nextOnLine())
   1098         box->clearTruncation();
   1099 }
   1100 
   1101 #ifndef NDEBUG
   1102 
   1103 void InlineFlowBox::checkConsistency() const
   1104 {
   1105 #ifdef CHECK_CONSISTENCY
   1106     ASSERT(!m_hasBadChildList);
   1107     const InlineBox* prev = 0;
   1108     for (const InlineBox* child = m_firstChild; child; child = child->nextOnLine()) {
   1109         ASSERT(child->parent() == this);
   1110         ASSERT(child->prevOnLine() == prev);
   1111         prev = child;
   1112     }
   1113     ASSERT(prev == m_lastChild);
   1114 #endif
   1115 }
   1116 
   1117 #endif
   1118 
   1119 } // namespace WebCore
   1120