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