[LFC][IFC] Add generic inline run generator.
[WebKit-https.git] / Source / WebCore / layout / inlineformatting / InlineRunProvider.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 "InlineItem.h"
31 #include <wtf/IsoMalloc.h>
32 #include <wtf/text/TextBreakIterator.h>
33
34 namespace WebCore {
35 namespace Layout {
36
37 class InlineFormattingState;
38
39 using ItemPosition = unsigned;
40
41 class InlineRunProvider {
42     WTF_MAKE_ISO_ALLOCATED(InlineRunProvider);
43 public:
44     InlineRunProvider(InlineFormattingState&);
45
46     void append(const Box&);
47     void insertBefore(const Box&, const Box& before);
48     void remove(const Box&);
49
50     struct Run {
51
52         static Run createBoxRun(const InlineItem&);
53         static Run createFloatRun(const InlineItem&);
54         static Run createHardLineBreakRun(const InlineItem&);
55         static Run createSoftLineBreakRun(const InlineItem&);
56         static Run createWhitespaceRun(const InlineItem&, ItemPosition start, unsigned length, bool isCollapsible);
57         static Run createNonWhitespaceRun(const InlineItem&, ItemPosition start, unsigned length);
58
59         enum class Type {
60             Box,
61             Float,
62             SoftLineBreak,
63             HardLineBreak,
64             Whitespace,
65             NonWhitespace
66         };
67         Type type() const { return m_type; }
68         bool isText() const { return m_type == Run::Type::Whitespace || m_type == Run::Type::NonWhitespace || m_type == Run::Type::SoftLineBreak || m_type == Run::Type::HardLineBreak; }
69         bool isWhitespace() const { return m_type == Type::Whitespace; }
70         bool isNonWhitespace() const { return m_type == Type::NonWhitespace; }
71         bool isLineBreak() const { return m_type == Run::Type::SoftLineBreak || m_type == Run::Type::HardLineBreak; }
72         bool isBox() const { return m_type == Type::Box; }
73         bool isFloat() const { return m_type == Type::Float; }
74
75         struct TextContext {
76
77             enum class IsCollapsed { No, Yes };
78             TextContext(ItemPosition, unsigned length, IsCollapsed);
79
80             ItemPosition start() const { return m_start; }
81             // Note that 'end' position does not equal to start + length when run overlaps multiple InlineItems.
82             unsigned length() const { return m_length; }
83             bool isCollapsed() const { return m_isCollapsed == IsCollapsed::Yes; }
84
85             void setStart(ItemPosition start) { m_start = start; }
86             void setLength(unsigned length) { m_length = length; }
87
88         private:
89             ItemPosition m_start { 0 };
90             unsigned m_length { 0 };
91             IsCollapsed m_isCollapsed { IsCollapsed::No };
92         };
93         std::optional<TextContext> textContext() const { return m_textContext; }
94         // Note that style() and inlineItem() always returns the first InlineItem for a run.
95         const RenderStyle& style() const { return m_inlineItem.style(); }
96         const InlineItem& inlineItem() const { return m_inlineItem; }
97
98     private:
99         Run(const InlineItem&, Type, std::optional<TextContext>);
100
101         const Type m_type;
102         const InlineItem& m_inlineItem;
103         std::optional<TextContext> m_textContext;
104     };
105     const Vector<InlineRunProvider::Run>& runs() const { return m_inlineRuns; }
106
107 private:
108     void commitTextRun();
109     void processInlineTextItem(const InlineItem&);
110     unsigned moveToNextNonWhitespacePosition(const InlineItem&, ItemPosition currentPosition);
111     unsigned moveToNextBreakablePosition(const InlineItem&, ItemPosition currentPosition);
112     bool isContinousContent(Run::Type newRunType, const InlineItem& newInlineItem);
113
114     LazyLineBreakIterator m_lineBreakIterator;
115
116     InlineFormattingState& m_inlineFormattingState;
117     Vector<InlineRunProvider::Run> m_inlineRuns;
118 };
119
120 inline InlineRunProvider::Run InlineRunProvider::Run::createBoxRun(const InlineItem& inlineItem)
121 {
122     return { inlineItem, Type::Box, std::nullopt };
123 }
124
125 inline InlineRunProvider::Run InlineRunProvider::Run::createFloatRun(const InlineItem& inlineItem)
126 {
127     return { inlineItem, Type::Float, std::nullopt };
128 }
129
130 inline InlineRunProvider::Run InlineRunProvider::Run::createSoftLineBreakRun(const InlineItem& inlineItem)
131 {
132     return { inlineItem, Type::SoftLineBreak, std::nullopt };
133 }
134
135 inline InlineRunProvider::Run InlineRunProvider::Run::createHardLineBreakRun(const InlineItem& inlineItem)
136 {
137     return { inlineItem, Type::HardLineBreak, std::nullopt };
138 }
139
140 inline InlineRunProvider::Run InlineRunProvider::Run::createWhitespaceRun(const InlineItem& inlineItem, ItemPosition start, unsigned length, bool isCollapsible)
141 {
142     ASSERT(length);
143     auto isCollapsed = isCollapsible && length > 1 ? TextContext::IsCollapsed::Yes : TextContext::IsCollapsed::No;
144     return { inlineItem, Type::Whitespace, TextContext(start, length, isCollapsed) };
145 }
146
147 inline InlineRunProvider::Run InlineRunProvider::Run::createNonWhitespaceRun(const InlineItem& inlineItem, ItemPosition start, unsigned length)
148 {
149     return { inlineItem, Type::NonWhitespace, TextContext(start, length, TextContext::IsCollapsed::No) };
150 }
151
152 inline InlineRunProvider::Run::Run(const InlineItem& inlineItem, Type type, std::optional<TextContext> textContext)
153     : m_type(type)
154     , m_inlineItem(inlineItem)
155     , m_textContext(textContext)
156 {
157 }
158
159 inline InlineRunProvider::Run::TextContext::TextContext(ItemPosition start, unsigned length, IsCollapsed isCollapsed)
160     : m_start(start)
161     , m_length(length)
162     , m_isCollapsed(isCollapsed)
163 {
164 }
165
166 }
167 }
168 #endif