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