Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / line / LineBreaker.cpp
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
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
53 void LineBreaker::reset()
54 {
55     m_positionedObjects.clear();
56     m_hyphenated = false;
57     m_clear = CNONE;
58 }
59
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 }