1 /*
2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
4 * Copyright (C) 2010 Google Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "config.h"
24 #include "core/rendering/line/LineBreaker.h"
25
26 #include "core/rendering/line/BreakingContextInlineHeaders.h"
27
28 namespace blink {
29
skipLeadingWhitespace(InlineBidiResolver & resolver,LineInfo & lineInfo,FloatingObject * lastFloatFromPreviousLine,LineWidth & width)30 void LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo,
31 FloatingObject* lastFloatFromPreviousLine, LineWidth& width)
32 {
33 while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), lineInfo, LeadingWhitespace)) {
34 RenderObject* object = resolver.position().object();
35 if (object->isOutOfFlowPositioned()) {
36 setStaticPositions(m_block, toRenderBox(object));
37 if (object->style()->isOriginalDisplayInlineType()) {
38 resolver.runs().addRun(createRun(0, 1, object, resolver));
39 lineInfo.incrementRunsFromLeadingWhitespace();
40 }
41 } else if (object->isFloating()) {
42 m_block->positionNewFloatOnLine(m_block->insertFloatingObject(toRenderBox(object)), lastFloatFromPreviousLine, lineInfo, width);
43 } else if (object->isText() && object->style()->hasTextCombine() && object->isCombineText() && !toRenderCombineText(object)->isCombined()) {
44 toRenderCombineText(object)->combineText();
45 if (toRenderCombineText(object)->isCombined())
46 continue;
47 }
48 resolver.position().increment(&resolver);
49 }
50 resolver.commitExplicitEmbedding(resolver.runs());
51 }
52
reset()53 void LineBreaker::reset()
54 {
55 m_positionedObjects.clear();
56 m_hyphenated = false;
57 m_clear = CNONE;
58 }
59
nextLineBreak(InlineBidiResolver & resolver,LineInfo & lineInfo,RenderTextInfo & renderTextInfo,FloatingObject * lastFloatFromPreviousLine,WordMeasurements & wordMeasurements)60 InlineIterator LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo,
61 RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine,
62 WordMeasurements& wordMeasurements)
63 {
64 reset();
65
66 ASSERT(resolver.position().root() == m_block);
67
68 bool appliedStartWidth = resolver.position().offset() > 0;
69
70 LineWidth width(*m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.isFirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style()));
71
72 skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width);
73
74 if (resolver.position().atEnd())
75 return resolver.position();
76
77 BreakingContext context(resolver, lineInfo, width, renderTextInfo, lastFloatFromPreviousLine, appliedStartWidth, m_block);
78
79 while (context.currentObject()) {
80 context.initializeForCurrentObject();
81 if (context.currentObject()->isBR()) {
82 context.handleBR(m_clear);
83 } else if (context.currentObject()->isOutOfFlowPositioned()) {
84 context.handleOutOfFlowPositioned(m_positionedObjects);
85 } else if (context.currentObject()->isFloating()) {
86 context.handleFloat();
87 } else if (context.currentObject()->isRenderInline()) {
88 context.handleEmptyInline();
89 } else if (context.currentObject()->isReplaced()) {
90 context.handleReplaced();
91 } else if (context.currentObject()->isText()) {
92 if (context.handleText(wordMeasurements, m_hyphenated)) {
93 // We've hit a hard text line break. Our line break iterator is updated, so go ahead and early return.
94 return context.lineBreak();
95 }
96 } else {
97 ASSERT_NOT_REACHED();
98 }
99
100 if (context.atEnd())
101 return context.handleEndOfLine();
102
103 context.commitAndUpdateLineBreakIfNeeded();
104
105 if (context.atEnd())
106 return context.handleEndOfLine();
107
108 context.increment();
109 }
110
111 context.clearLineBreakIfFitsOnLine();
112
113 return context.handleEndOfLine();
114 }
115
116 }
117