1 /*
2  * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
4  *               All right reserved.
5  * Copyright (C) 2010 Google Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23 
24 #include "third_party/blink/renderer/core/layout/line/line_breaker.h"
25 
26 #include "third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h"
27 
28 namespace blink {
29 
SkipLeadingWhitespace(InlineBidiResolver & resolver,LineInfo & line_info,LineWidth & width)30 void LineBreaker::SkipLeadingWhitespace(InlineBidiResolver& resolver,
31                                         LineInfo& line_info,
32                                         LineWidth& width) {
33   while (
34       !resolver.GetPosition().AtEnd() &&
35       !RequiresLineBox(resolver.GetPosition(), line_info, kLeadingWhitespace)) {
36     LineLayoutItem line_layout_item =
37         resolver.GetPosition().GetLineLayoutItem();
38     if (line_layout_item.IsOutOfFlowPositioned()) {
39       SetStaticPositions(block_, LineLayoutBox(line_layout_item),
40                          width.IndentText());
41       if (line_layout_item.StyleRef().IsOriginalDisplayInlineType()) {
42         resolver.Runs().AddRun(
43             CreateRun(0, 1, LineLayoutItem(line_layout_item), resolver));
44         line_info.IncrementRunsFromLeadingWhitespace();
45       }
46     } else if (line_layout_item.IsFloating()) {
47       block_.InsertFloatingObject(LineLayoutBox(line_layout_item));
48       block_.PlaceNewFloats(block_.LogicalHeight(), &width);
49     }
50     resolver.GetPosition().Increment(&resolver);
51   }
52   resolver.CommitExplicitEmbedding(resolver.Runs());
53 }
54 
Reset()55 void LineBreaker::Reset() {
56   positioned_objects_.clear();
57   hyphenated_ = false;
58   clear_ = EClear::kNone;
59 }
60 
NextLineBreak(InlineBidiResolver & resolver,LineInfo & line_info,LayoutTextInfo & layout_text_info,WordMeasurements & word_measurements)61 InlineIterator LineBreaker::NextLineBreak(InlineBidiResolver& resolver,
62                                           LineInfo& line_info,
63                                           LayoutTextInfo& layout_text_info,
64                                           WordMeasurements& word_measurements) {
65   Reset();
66 
67   DCHECK(resolver.GetPosition().Root() == block_);
68 
69   bool applied_start_width = resolver.GetPosition().Offset() > 0;
70 
71   bool is_first_formatted_line =
72       line_info.IsFirstLine() && block_.CanContainFirstFormattedLine();
73   LineWidth width(
74       block_, line_info.IsFirstLine(),
75       RequiresIndent(is_first_formatted_line,
76                      line_info.PreviousLineBrokeCleanly(), block_.StyleRef()));
77 
78   SkipLeadingWhitespace(resolver, line_info, width);
79 
80   if (resolver.GetPosition().AtEnd())
81     return resolver.GetPosition();
82 
83   BreakingContext context(resolver, line_info, width, layout_text_info,
84                           applied_start_width, block_);
85 
86   while (context.CurrentItem()) {
87     context.InitializeForCurrentObject();
88     if (context.CurrentItem().IsBR()) {
89       context.HandleBR(clear_);
90     } else if (context.CurrentItem().IsOutOfFlowPositioned()) {
91       context.HandleOutOfFlowPositioned(positioned_objects_);
92     } else if (context.CurrentItem().IsFloating()) {
93       context.HandleFloat();
94     } else if (context.CurrentItem().IsLayoutInline()) {
95       context.HandleEmptyInline();
96     } else if (context.CurrentItem().IsAtomicInlineLevel()) {
97       context.HandleReplaced();
98     } else if (context.CurrentItem().IsText()) {
99       if (context.HandleText(word_measurements, hyphenated_)) {
100         // We've hit a hard text line break. Our line break iterator is updated,
101         // so go ahead and early return.
102         return context.LineBreak();
103       }
104     } else {
105       NOTREACHED();
106     }
107 
108     if (context.AtEnd())
109       return context.HandleEndOfLine();
110 
111     context.CommitAndUpdateLineBreakIfNeeded();
112 
113     if (context.AtEnd())
114       return context.HandleEndOfLine();
115 
116     context.Increment();
117   }
118 
119   context.ClearLineBreakIfFitsOnLine();
120 
121   return context.HandleEndOfLine();
122 }
123 
124 }  // namespace blink
125