1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006, 2007 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 
21 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LINE_INLINE_FLOW_BOX_H_
22 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LINE_INLINE_FLOW_BOX_H_
23 
24 #include <memory>
25 #include "third_party/blink/renderer/core/layout/geometry/box_sides.h"
26 #include "third_party/blink/renderer/core/layout/line/inline_box.h"
27 #include "third_party/blink/renderer/core/layout/overflow_model.h"
28 #include "third_party/blink/renderer/core/style/shadow_data.h"
29 
30 namespace blink {
31 
32 class HitTestResult;
33 class InlineTextBox;
34 class LineBoxList;
35 class SimpleFontData;
36 class VerticalPositionCache;
37 
38 struct GlyphOverflow;
39 
40 typedef HashMap<const InlineTextBox*,
41                 std::pair<Vector<const SimpleFontData*>, GlyphOverflow>>
42     GlyphOverflowAndFallbackFontsMap;
43 
44 class InlineFlowBox : public InlineBox {
45  public:
InlineFlowBox(LineLayoutItem line_layout_item)46   InlineFlowBox(LineLayoutItem line_layout_item)
47       : InlineBox(line_layout_item),
48         first_child_(nullptr),
49         last_child_(nullptr),
50         prev_line_box_(nullptr),
51         next_line_box_(nullptr),
52         include_logical_left_edge_(false),
53         include_logical_right_edge_(false),
54         descendants_have_same_line_height_and_baseline_(true),
55         baseline_type_(kAlphabeticBaseline),
56         has_annotations_before_(false),
57         has_annotations_after_(false),
58         line_break_bidi_status_eor_(WTF::unicode::kLeftToRight),
59         line_break_bidi_status_last_strong_(WTF::unicode::kLeftToRight),
60         line_break_bidi_status_last_(WTF::unicode::kLeftToRight),
61         is_first_after_page_break_(false)
62 #if DCHECK_IS_ON()
63         ,
64         has_bad_child_list_(false)
65 #endif
66   {
67     // Internet Explorer and Firefox always create a marker for list items, even
68     // when the list-style-type is none.  We do not make a marker in the
69     // list-style-type: none case, since it is wasteful to do so.
70     // However, in order to match other browsers we have to pretend like an
71     // invisible marker exists.  The side effect of having an invisible marker
72     // is that the quirks mode behavior of shrinking lines with no text children
73     // must not apply. This change also means that gaps will exist between image
74     // bullet list items.  Even when the list bullet is an image, the line is
75     // still considered to be immune from the quirk.
76     has_text_children_ =
77         line_layout_item.StyleRef().Display() == EDisplay::kListItem;
78     has_text_descendants_ = has_text_children_;
79   }
80 
81 #if DCHECK_IS_ON()
82   ~InlineFlowBox() override;
83 
84   void DumpLineTreeAndMark(StringBuilder&,
85                            const InlineBox* = nullptr,
86                            const char* = nullptr,
87                            const InlineBox* = nullptr,
88                            const char* = nullptr,
89                            const LayoutObject* = nullptr,
90                            int = 0) const override;
91 #endif
92   const char* BoxName() const override;
93 
PrevForSameLayoutObject()94   InlineFlowBox* PrevForSameLayoutObject() const { return prev_line_box_; }
NextForSameLayoutObject()95   InlineFlowBox* NextForSameLayoutObject() const { return next_line_box_; }
SetNextForSameLayoutObject(InlineFlowBox * n)96   void SetNextForSameLayoutObject(InlineFlowBox* n) { next_line_box_ = n; }
SetPreviousForSameLayoutObject(InlineFlowBox * p)97   void SetPreviousForSameLayoutObject(InlineFlowBox* p) { prev_line_box_ = p; }
98 
FirstChild()99   InlineBox* FirstChild() const { return first_child_; }
LastChild()100   InlineBox* LastChild() const { return last_child_; }
101 
IsLeaf()102   bool IsLeaf() const final { return false; }
103 
104   InlineBox* FirstLeafChild() const;
105   InlineBox* LastLeafChild() const;
106 
107   DISABLE_CFI_PERF
SetConstructed()108   void SetConstructed() final {
109     InlineBox::SetConstructed();
110     for (InlineBox* child = FirstChild(); child; child = child->NextOnLine())
111       child->SetConstructed();
112   }
113 
114   void AddToLine(InlineBox* child);
115   void DeleteLine() final;
116   void ExtractLine() final;
117   void AttachLine() final;
118   void Move(const LayoutSize&) override;
119 
120   virtual void ExtractLineBoxFromLayoutObject();
121   virtual void AttachLineBoxToLayoutObject();
122   virtual void RemoveLineBoxFromLayoutObject();
123 
124   void ClearTruncation() override;
125 
126   LayoutRect FrameRect() const;
127 
128   void Paint(const PaintInfo&,
129              const PhysicalOffset&,
130              LayoutUnit line_top,
131              LayoutUnit line_bottom) const override;
132   bool NodeAtPoint(HitTestResult&,
133                    const HitTestLocation&,
134                    const PhysicalOffset& accumulated_offset,
135                    LayoutUnit line_top,
136                    LayoutUnit line_bottom) override;
137 
138   bool BoxShadowCanBeAppliedToBackground(const FillLayer&) const;
139 
140   virtual LineBoxList* LineBoxes() const;
141 
142   // logicalLeft = left in a horizontal line and top in a vertical line.
MarginBorderPaddingLogicalLeft()143   LayoutUnit MarginBorderPaddingLogicalLeft() const {
144     return MarginLogicalLeft() + BorderLogicalLeft() + PaddingLogicalLeft();
145   }
MarginBorderPaddingLogicalRight()146   LayoutUnit MarginBorderPaddingLogicalRight() const {
147     return MarginLogicalRight() + BorderLogicalRight() + PaddingLogicalRight();
148   }
MarginLogicalLeft()149   LayoutUnit MarginLogicalLeft() const {
150     if (!IncludeLogicalLeftEdge())
151       return LayoutUnit();
152     return IsHorizontal() ? BoxModelObject().MarginLeft()
153                           : BoxModelObject().MarginTop();
154   }
MarginLogicalRight()155   LayoutUnit MarginLogicalRight() const {
156     if (!IncludeLogicalRightEdge())
157       return LayoutUnit();
158     return IsHorizontal() ? BoxModelObject().MarginRight()
159                           : BoxModelObject().MarginBottom();
160   }
MarginLogicalWidth()161   LayoutUnit MarginLogicalWidth() const {
162     return MarginLogicalLeft() + MarginLogicalRight();
163   }
BorderLogicalLeft()164   LayoutUnit BorderLogicalLeft() const {
165     if (!IncludeLogicalLeftEdge())
166       return LayoutUnit();
167     return LayoutUnit(
168         IsHorizontal()
169             ? GetLineLayoutItem().Style(IsFirstLineStyle())->BorderLeftWidth()
170             : GetLineLayoutItem().Style(IsFirstLineStyle())->BorderTopWidth());
171   }
BorderLogicalRight()172   LayoutUnit BorderLogicalRight() const {
173     if (!IncludeLogicalRightEdge())
174       return LayoutUnit();
175     return LayoutUnit(
176         IsHorizontal()
177             ? GetLineLayoutItem().Style(IsFirstLineStyle())->BorderRightWidth()
178             : GetLineLayoutItem()
179                   .Style(IsFirstLineStyle())
180                   ->BorderBottomWidth());
181   }
PaddingLogicalLeft()182   int PaddingLogicalLeft() const {
183     if (!IncludeLogicalLeftEdge())
184       return 0;
185     return (IsHorizontal() ? BoxModelObject().PaddingLeft()
186                            : BoxModelObject().PaddingTop())
187         .ToInt();
188   }
PaddingLogicalRight()189   int PaddingLogicalRight() const {
190     if (!IncludeLogicalRightEdge())
191       return 0;
192     return (IsHorizontal() ? BoxModelObject().PaddingRight()
193                            : BoxModelObject().PaddingBottom())
194         .ToInt();
195   }
196 
IncludeLogicalLeftEdge()197   bool IncludeLogicalLeftEdge() const { return include_logical_left_edge_; }
IncludeLogicalRightEdge()198   bool IncludeLogicalRightEdge() const { return include_logical_right_edge_; }
SetEdges(bool include_left,bool include_right)199   void SetEdges(bool include_left, bool include_right) {
200     include_logical_left_edge_ = include_left;
201     include_logical_right_edge_ = include_right;
202   }
203 
SidesToInclude()204   PhysicalBoxSides SidesToInclude() const {
205     const LogicalBoxSides logical_sides(true, IncludeLogicalRightEdge(), true,
206                                         IncludeLogicalLeftEdge());
207     return PhysicalBoxSides(logical_sides,
208                             GetLineLayoutItem().StyleRef().GetWritingMode());
209   }
210 
211   // Helper functions used during line construction and placement.
212   void DetermineSpacingForFlowBoxes(
213       bool last_line,
214       bool is_logically_last_run_wrapped,
215       LineLayoutItem logically_last_run_layout_object);
216   LayoutUnit GetFlowSpacingLogicalWidth();
217   LayoutUnit PlaceBoxesInInlineDirection(LayoutUnit logical_left,
218                                          bool& needs_word_spacing);
219 
220   void ComputeLogicalBoxHeights(RootInlineBox*,
221                                 LayoutUnit& max_position_top,
222                                 LayoutUnit& max_position_bottom,
223                                 LayoutUnit& max_ascent,
224                                 LayoutUnit& max_descent,
225                                 bool& set_max_ascent,
226                                 bool& set_max_descent,
227                                 bool no_quirks_mode,
228                                 GlyphOverflowAndFallbackFontsMap&,
229                                 FontBaseline,
230                                 VerticalPositionCache&);
231   void AdjustMaxAscentAndDescent(LayoutUnit& max_ascent,
232                                  LayoutUnit& max_descent,
233                                  int max_position_top,
234                                  int max_position_bottom);
235   void PlaceBoxesInBlockDirection(LayoutUnit logical_top,
236                                   LayoutUnit max_height,
237                                   LayoutUnit max_ascent,
238                                   bool no_quirks_mode,
239                                   LayoutUnit& line_top,
240                                   LayoutUnit& line_bottom,
241                                   LayoutUnit& selection_bottom,
242                                   bool& set_line_top,
243                                   LayoutUnit& line_top_including_margins,
244                                   LayoutUnit& line_bottom_including_margins,
245                                   bool& has_annotations_before,
246                                   bool& has_annotations_after,
247                                   FontBaseline);
248   void FlipLinesInBlockDirection(LayoutUnit line_top, LayoutUnit line_bottom);
249   FontBaseline DominantBaseline() const;
250 
251   LayoutUnit ComputeOverAnnotationAdjustment(LayoutUnit allowed_position) const;
252   LayoutUnit ComputeUnderAnnotationAdjustment(
253       LayoutUnit allowed_position) const;
254 
255   // Computes all layout overflow, plus visual overflow not due to replaced
256   // children. Visual overflow due to replaced children is computed during
257   // the RecalcVisualOverflow tree walk. Other visual overflow is computed
258   // during layout for performance reasons.
259   void ComputeOverflow(LayoutUnit line_top,
260                        LayoutUnit line_bottom,
261                        GlyphOverflowAndFallbackFontsMap&);
262   // Adds visual flow to the current visual overflow for replaced children.
263   void AddReplacedChildrenVisualOverflow(LayoutUnit line_top,
264                                          LayoutUnit line_bottom);
265 
266   void RemoveChild(InlineBox* child, MarkLineBoxes);
267 
IsSelected()268   bool IsSelected() const override { return false; }
269 
270   bool CanAccommodateEllipsis(bool ltr,
271                               LayoutUnit block_edge,
272                               LayoutUnit ellipsis_width) const final;
273   LayoutUnit PlaceEllipsisBox(bool ltr,
274                               LayoutUnit block_left_edge,
275                               LayoutUnit block_right_edge,
276                               LayoutUnit ellipsis_width,
277                               LayoutUnit& truncated_width,
278                               InlineBox**,
279                               LayoutUnit logical_left_offset) override;
280 
HasTextChildren()281   bool HasTextChildren() const { return has_text_children_; }
HasTextDescendants()282   bool HasTextDescendants() const { return has_text_descendants_; }
SetHasTextDescendants()283   void SetHasTextDescendants() { has_text_descendants_ = true; }
284 
285   void SetHasBadChildList();
286 
287   // Line visual and layout overflow are in the coordinate space of the block.
288   // This means that they aren't purely physical directions. For horizontal-tb
289   // and vertical-lr they will match physical directions, but for vertical-rl,
290   // the left/right respectively are flipped when compared to their physical
291   // counterparts.  For example minX is on the left in vertical-lr, but it is on
292   // the right in vertical-rl.
LayoutOverflowRect(LayoutUnit line_top,LayoutUnit line_bottom)293   LayoutRect LayoutOverflowRect(LayoutUnit line_top,
294                                 LayoutUnit line_bottom) const {
295     return LayoutOverflowIsSet()
296                ? overflow_->layout_overflow->LayoutOverflowRect()
297                : FrameRectIncludingLineHeight(line_top, line_bottom);
298   }
LogicalTopLayoutOverflow(LayoutUnit line_top)299   LayoutUnit LogicalTopLayoutOverflow(LayoutUnit line_top) const {
300     if (LayoutOverflowIsSet()) {
301       return IsHorizontal()
302                  ? overflow_->layout_overflow->LayoutOverflowRect().Y()
303                  : overflow_->layout_overflow->LayoutOverflowRect().X();
304     }
305     return line_top;
306   }
LogicalBottomLayoutOverflow(LayoutUnit line_bottom)307   LayoutUnit LogicalBottomLayoutOverflow(LayoutUnit line_bottom) const {
308     if (LayoutOverflowIsSet()) {
309       return IsHorizontal()
310                  ? overflow_->layout_overflow->LayoutOverflowRect().MaxY()
311                  : overflow_->layout_overflow->LayoutOverflowRect().MaxX();
312     }
313     return line_bottom;
314   }
LogicalLayoutOverflowRect(LayoutUnit line_top,LayoutUnit line_bottom)315   LayoutRect LogicalLayoutOverflowRect(LayoutUnit line_top,
316                                        LayoutUnit line_bottom) const {
317     LayoutRect result = LayoutOverflowRect(line_top, line_bottom);
318     if (!GetLineLayoutItem().IsHorizontalWritingMode())
319       result = result.TransposedRect();
320     return result;
321   }
322 
VisualOverflowRect(LayoutUnit line_top,LayoutUnit line_bottom)323   LayoutRect VisualOverflowRect(LayoutUnit line_top,
324                                 LayoutUnit line_bottom) const {
325     return VisualOverflowIsSet()
326                ? overflow_->visual_overflow->VisualOverflowRect()
327                : FrameRectIncludingLineHeight(line_top, line_bottom);
328   }
PhysicalVisualOverflowRect(LayoutUnit line_top,LayoutUnit line_bottom)329   PhysicalRect PhysicalVisualOverflowRect(LayoutUnit line_top,
330                                           LayoutUnit line_bottom) const {
331     LayoutRect rect = VisualOverflowRect(line_top, line_bottom);
332     FlipForWritingMode(rect);
333     return PhysicalRect(rect);
334   }
LogicalLeftVisualOverflow()335   LayoutUnit LogicalLeftVisualOverflow() const {
336     return VisualOverflowIsSet()
337                ? (IsHorizontal()
338                       ? overflow_->visual_overflow->VisualOverflowRect().X()
339                       : overflow_->visual_overflow->VisualOverflowRect().Y())
340                : LogicalLeft();
341   }
LogicalRightVisualOverflow()342   LayoutUnit LogicalRightVisualOverflow() const {
343     return VisualOverflowIsSet()
344                ? (IsHorizontal()
345                       ? overflow_->visual_overflow->VisualOverflowRect().MaxX()
346                       : overflow_->visual_overflow->VisualOverflowRect().MaxY())
347                : static_cast<LayoutUnit>(LogicalRight().Ceil());
348   }
LogicalTopVisualOverflow(LayoutUnit line_top)349   LayoutUnit LogicalTopVisualOverflow(LayoutUnit line_top) const {
350     if (VisualOverflowIsSet()) {
351       return IsHorizontal()
352                  ? overflow_->visual_overflow->VisualOverflowRect().Y()
353                  : overflow_->visual_overflow->VisualOverflowRect().X();
354     }
355     return line_top;
356   }
LogicalBottomVisualOverflow(LayoutUnit line_bottom)357   LayoutUnit LogicalBottomVisualOverflow(LayoutUnit line_bottom) const {
358     if (VisualOverflowIsSet()) {
359       return IsHorizontal()
360                  ? overflow_->visual_overflow->VisualOverflowRect().MaxY()
361                  : overflow_->visual_overflow->VisualOverflowRect().MaxX();
362     }
363     return line_bottom;
364   }
LogicalVisualOverflowRect(LayoutUnit line_top,LayoutUnit line_bottom)365   LayoutRect LogicalVisualOverflowRect(LayoutUnit line_top,
366                                        LayoutUnit line_bottom) const {
367     LayoutRect result = VisualOverflowRect(line_top, line_bottom);
368     if (!GetLineLayoutItem().IsHorizontalWritingMode())
369       result = result.TransposedRect();
370     return result;
371   }
372 
FrameRectIncludingLineHeight(LayoutUnit line_top,LayoutUnit line_bottom)373   LayoutRect FrameRectIncludingLineHeight(LayoutUnit line_top,
374                                           LayoutUnit line_bottom) const {
375     if (IsHorizontal())
376       return LayoutRect(X(), line_top, LogicalWidth(), line_bottom - line_top);
377     return LayoutRect(line_top, Y(), line_bottom - line_top, LogicalWidth());
378   }
379 
LogicalFrameRectIncludingLineHeight(LayoutUnit line_top,LayoutUnit line_bottom)380   LayoutRect LogicalFrameRectIncludingLineHeight(LayoutUnit line_top,
381                                                  LayoutUnit line_bottom) const {
382     return LayoutRect(LogicalLeft(), line_top, LogicalWidth(),
383                       line_bottom - line_top);
384   }
385 
DescendantsHaveSameLineHeightAndBaseline()386   bool DescendantsHaveSameLineHeightAndBaseline() const {
387     return descendants_have_same_line_height_and_baseline_;
388   }
ClearDescendantsHaveSameLineHeightAndBaseline()389   void ClearDescendantsHaveSameLineHeightAndBaseline() {
390     descendants_have_same_line_height_and_baseline_ = false;
391     if (Parent() && Parent()->DescendantsHaveSameLineHeightAndBaseline())
392       Parent()->ClearDescendantsHaveSameLineHeightAndBaseline();
393   }
394 
IsFirstAfterPageBreak()395   bool IsFirstAfterPageBreak() const { return is_first_after_page_break_; }
SetIsFirstAfterPageBreak(bool is_first_after_page_break)396   void SetIsFirstAfterPageBreak(bool is_first_after_page_break) {
397     is_first_after_page_break_ = is_first_after_page_break;
398   }
399 
400   bool OverrideVisualOverflowFromLogicalRect(
401       const LayoutRect& logical_visual_overflow,
402       LayoutUnit line_top,
403       LayoutUnit line_bottom);
404 
405   void OverrideLayoutOverflowFromLogicalRect(
406       const LayoutRect& logical_layout_overflow,
407       LayoutUnit line_top,
408       LayoutUnit line_bottom);
409 
410   LayoutUnit FarthestPositionForUnderline(LineLayoutItem decorating_box,
411                                           FontVerticalPositionType,
412                                           FontBaseline,
413                                           LayoutUnit current) const;
414 
415  private:
LayoutOverflowIsSet()416   inline bool LayoutOverflowIsSet() const {
417     return overflow_ && overflow_->layout_overflow;
418   }
VisualOverflowIsSet()419   inline bool VisualOverflowIsSet() const {
420     return overflow_ && overflow_->visual_overflow;
421   }
422   void PlaceBoxRangeInInlineDirection(InlineBox* first_child,
423                                       InlineBox* last_child,
424                                       LayoutUnit& logical_left,
425                                       LayoutUnit& min_logical_left,
426                                       LayoutUnit& max_logical_right,
427                                       bool& needs_word_spacing);
BeginPlacingBoxRangesInInlineDirection(LayoutUnit logical_left)428   void BeginPlacingBoxRangesInInlineDirection(LayoutUnit logical_left) {
429     SetLogicalLeft(logical_left);
430   }
EndPlacingBoxRangesInInlineDirection(LayoutUnit logical_left,LayoutUnit logical_right,LayoutUnit min_logical_left,LayoutUnit max_logical_right)431   void EndPlacingBoxRangesInInlineDirection(LayoutUnit logical_left,
432                                             LayoutUnit logical_right,
433                                             LayoutUnit min_logical_left,
434                                             LayoutUnit max_logical_right) {
435     SetLogicalWidth(logical_right - logical_left);
436     if (KnownToHaveNoOverflow() &&
437         (min_logical_left < logical_left || max_logical_right > logical_right))
438       ClearKnownToHaveNoOverflow();
439   }
440 
441   void AddBoxShadowVisualOverflow(LayoutRect& logical_visual_overflow);
442   void AddBorderOutsetVisualOverflow(LayoutRect& logical_visual_overflow);
443   void AddOutlineVisualOverflow(LayoutRect& logical_visual_overflow);
444   void AddTextBoxVisualOverflow(InlineTextBox*,
445                                 GlyphOverflowAndFallbackFontsMap&,
446                                 LayoutRect& logical_visual_overflow);
447   void AddReplacedChildLayoutOverflow(const InlineBox*,
448                                       LayoutRect& logical_layout_overflow);
449   bool HasEmphasisMarkBefore(const InlineTextBox*) const;
450   bool HasEmphasisMarkOver(const InlineTextBox*) const;
451   bool HasEmphasisMarkUnder(const InlineTextBox*) const;
452 
453   void SetLayoutOverflow(const LayoutRect&, const LayoutRect&);
454   void SetVisualOverflow(const LayoutRect&, const LayoutRect&);
455 
456   void SetLayoutOverflowFromLogicalRect(
457       const LayoutRect& logical_layout_overflow,
458       LayoutUnit line_top,
459       LayoutUnit line_bottom);
460   void SetVisualOverflowFromLogicalRect(
461       const LayoutRect& logical_visual_overflow,
462       LayoutUnit line_top,
463       LayoutUnit line_bottom);
464 
465  protected:
466   std::unique_ptr<SimpleOverflowModel> overflow_;
467 
IsInlineFlowBox()468   bool IsInlineFlowBox() const final { return true; }
469 
470   InlineBox* first_child_;
471   InlineBox* last_child_;
472 
473   // The next/previous box that also uses our LayoutObject.
474   // RootInlineBox, a subclass of this class, uses these fields for
475   // next/previous RootInlineBox.
476   InlineFlowBox* prev_line_box_;
477   InlineFlowBox* next_line_box_;
478 
479  private:
480   unsigned include_logical_left_edge_ : 1;
481   unsigned include_logical_right_edge_ : 1;
482   unsigned has_text_children_ : 1;
483   unsigned has_text_descendants_ : 1;
484   unsigned descendants_have_same_line_height_and_baseline_ : 1;
485 
486  protected:
487   // The following members are only used by RootInlineBox but moved here to keep
488   // the bits packed.
489 
490   // Whether or not this line uses alphabetic or ideographic baselines by
491   // default.
492   unsigned baseline_type_ : 1;  // FontBaseline
493 
494   // If the line contains any ruby runs, then this will be true.
495   unsigned has_annotations_before_ : 1;
496   unsigned has_annotations_after_ : 1;
497 
498   unsigned line_break_bidi_status_eor_ : 5;          // WTF::unicode::Direction
499   unsigned line_break_bidi_status_last_strong_ : 5;  // WTF::unicode::Direction
500   unsigned line_break_bidi_status_last_ : 5;         // WTF::unicode::Direction
501 
502   unsigned is_first_after_page_break_ : 1;
503 
504 // End of RootInlineBox-specific members.
505 
506 #if DCHECK_IS_ON()
507  private:
508   unsigned has_bad_child_list_ : 1;
509 #endif
510 };
511 
512 template <>
513 struct DowncastTraits<InlineFlowBox> {
514   static bool AllowFrom(const InlineBox& box) { return box.IsInlineFlowBox(); }
515 };
516 
517 inline void InlineFlowBox::SetHasBadChildList() {
518 #if DCHECK_IS_ON()
519   has_bad_child_list_ = true;
520 #endif
521 }
522 
523 }  // namespace blink
524 
525 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LINE_INLINE_FLOW_BOX_H_
526