46435dae3211bfd617a2c17d266a669b8b68b77f
[WebKit-https.git] / Source / WebCore / layout / inlineformatting / textlayout / simple / SimpleLineBreaker.h
1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
29
30 #include "RenderStyleConstants.h"
31 #include "Runs.h"
32 #include <wtf/IsoMalloc.h>
33
34 namespace WebCore {
35
36 class RenderStyle;
37
38 namespace Layout {
39
40 class TextContentProvider;
41 struct TextRunSplitPair;
42
43 class SimpleLineBreaker {
44     WTF_MAKE_ISO_ALLOCATED(SimpleLineBreaker);
45 public:
46     struct LineConstraint {
47         // verticalPosition sets the bottom edge for this constraint. Last entry in the list
48         // should always be std::nullopt indicating that left/right pair is set for the rest of the lines
49         // (Normally there's only one entry with the left/right block edges).
50         std::optional<float> verticalPosition;
51         float left { 0 };
52         float right { 0 };
53     };
54     using LineConstraintList = Vector<LineConstraint>;
55     SimpleLineBreaker(const Vector<TextRun>&, const TextContentProvider&, LineConstraintList&&, const RenderStyle&);
56
57     void setLineHeight(float lineHeight) { m_lineHeight = lineHeight; }
58
59     Vector<LayoutRun> runs();
60
61 private:
62     struct Style {
63         explicit Style(const RenderStyle&);
64
65         bool wrapLines { false };
66         bool breakAnyWordOnOverflow { false };
67         bool breakFirstWordOnOverflow { false };
68         bool collapseWhitespace { false };
69         bool preWrap { false };
70         bool preserveNewline { false };
71         TextAlignMode textAlign { TextAlignMode::Left };
72     };
73
74     class TextRunList {
75     public:
76         TextRunList(const Vector<TextRun>& textRuns);
77
78         std::optional<TextRun> current() const;
79         TextRunList& operator++();
80
81         void overrideCurrent(TextRun textRun) { m_overrideTextRun = textRun; }
82         bool isCurrentOverridden() const { return m_overrideTextRun.has_value(); }
83
84     private:
85         const Vector<TextRun>& m_textRuns;
86         unsigned m_currentIndex { 0 };
87         std::optional<TextRun> m_overrideTextRun;
88     };
89
90     class Line {
91     public:
92         Line(Vector<LayoutRun>& layoutRuns);
93
94         void append(const TextRun&);
95         float availableWidth() const { return m_availableWidth - m_runsWidth; }
96         bool hasContent() const { return m_runsWidth; }
97
98         void reset();
99         bool hasTrailingWhitespace() const { return m_trailingWhitespaceWidth; }
100         bool isWhitespaceOnly() const { return m_runsWidth == m_trailingWhitespaceWidth; }
101         void collapseTrailingWhitespace();
102
103         void setAvailableWidth(float availableWidth) { m_availableWidth = availableWidth; }
104         void setLeft(float left) { m_left = left; }
105         void setTextAlign(TextAlignMode);
106         void setCollapseWhitespace(bool collapseWhitespace) { m_style.collapseWhitespace = collapseWhitespace; }
107
108         void closeLastRun();
109         void adjustRunsForTextAlign(bool lastLine);
110
111     private:
112         struct Style {
113             bool collapseWhitespace { false };
114             TextAlignMode textAlign { TextAlignMode::Left };
115         };
116         float adjustedLeftForTextAlign(TextAlignMode) const;
117         void justifyRuns();
118         void collectExpansionOpportunities(const TextRun&, bool textRunCreatesNewLayoutRun);
119
120         Vector<LayoutRun>& m_layoutRuns;
121         Style m_style;
122     
123         float m_runsWidth { 0 };
124         float m_availableWidth { 0 };
125         float m_left { 0 };
126         float m_trailingWhitespaceWidth { 0 };
127         unsigned m_firstRunIndex { 0 };
128         std::optional<TextRun> m_lastTextRun;
129         std::optional<TextRun> m_lastNonWhitespaceTextRun;
130         bool m_collectExpansionOpportunities { false };
131         struct ExpansionOpportunity {
132             unsigned count { 0 };
133             ExpansionBehavior behavior { DefaultExpansion };
134         };
135         Vector<ExpansionOpportunity> m_expansionOpportunityList;
136         std::optional<ExpansionOpportunity> m_lastNonWhitespaceExpansionOppportunity;
137     };
138
139     void handleLineStart();
140     void handleLineEnd();
141     bool wrapContentOnOverflow() const { return m_style.wrapLines || m_style.breakFirstWordOnOverflow || m_style.breakAnyWordOnOverflow; }
142     void collectRuns();
143     void createRunsForLine();
144     void handleOverflownRun();
145     void collapseLeadingWhitespace();
146     void collapseTrailingWhitespace();
147     bool splitTextRun(const TextRun&);
148     TextRunSplitPair split(const TextRun&, float leftSideMaximumWidth) const;
149     LineConstraint lineConstraint(float verticalPosition);
150     float verticalPosition() const { return m_numberOfLines * m_lineHeight; }
151
152     const TextContentProvider& m_contentProvider;
153     const Style m_style;
154
155     TextRunList m_textRunList;
156
157     Vector<LayoutRun> m_layoutRuns;
158     Line m_currentLine;
159
160     LineConstraintList m_lineConstraintList;
161     ConstVectorIterator<LineConstraint> m_lineConstraintIterator;
162
163     unsigned m_numberOfLines { 0 };
164     bool m_previousLineHasNonForcedContent { false };
165     float m_lineHeight { 0 };
166 };
167
168 inline std::optional<TextRun> SimpleLineBreaker::TextRunList::current() const
169 {
170     if (m_overrideTextRun)
171         return m_overrideTextRun;
172
173     if (m_currentIndex < m_textRuns.size())
174         return m_textRuns[m_currentIndex];
175
176     return { };
177 }
178
179 inline SimpleLineBreaker::TextRunList& SimpleLineBreaker::TextRunList::operator++()
180 {
181     m_overrideTextRun = { };
182     ++m_currentIndex;
183     return *this;
184 }
185
186 }
187 }
188 #endif