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