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