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