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