1/*
2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
3 * (C) 2000 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
6 * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#pragma once
26
27#include "CounterContent.h"
28#include "StyleImage.h"
29#include "RenderPtr.h"
30#include <wtf/TypeCasts.h>
31
32namespace WebCore {
33
34class Document;
35class RenderObject;
36class RenderStyle;
37
38class ContentData {
39 WTF_MAKE_FAST_ALLOCATED;
40public:
41 enum Type {
42 CounterDataType,
43 ImageDataType,
44 QuoteDataType,
45 TextDataType
46 };
47 virtual ~ContentData() = default;
48
49 Type type() const { return m_type; }
50
51 bool isCounter() const { return type() == CounterDataType; }
52 bool isImage() const { return type() == ImageDataType; }
53 bool isQuote() const { return type() == QuoteDataType; }
54 bool isText() const { return type() == TextDataType; }
55
56 virtual RenderPtr<RenderObject> createContentRenderer(Document&, const RenderStyle&) const = 0;
57
58 std::unique_ptr<ContentData> clone() const;
59
60 ContentData* next() const { return m_next.get(); }
61 void setNext(std::unique_ptr<ContentData> next) { m_next = WTFMove(next); }
62
63 void setAltText(const String& alt) { m_altText = alt; }
64 const String& altText() const { return m_altText; }
65
66protected:
67 explicit ContentData(Type type)
68 : m_type(type)
69 {
70 }
71
72private:
73 virtual std::unique_ptr<ContentData> cloneInternal() const = 0;
74
75 std::unique_ptr<ContentData> m_next;
76 String m_altText;
77 Type m_type;
78};
79
80class ImageContentData final : public ContentData {
81public:
82 explicit ImageContentData(Ref<StyleImage>&& image)
83 : ContentData(ImageDataType)
84 , m_image(WTFMove(image))
85 {
86 }
87
88 const StyleImage& image() const { return m_image.get(); }
89 void setImage(Ref<StyleImage>&& image)
90 {
91 m_image = WTFMove(image);
92 }
93
94private:
95 RenderPtr<RenderObject> createContentRenderer(Document&, const RenderStyle&) const final;
96 std::unique_ptr<ContentData> cloneInternal() const final
97 {
98 auto image = std::make_unique<ImageContentData>(m_image.copyRef());
99 image->setAltText(altText());
100 return image;
101 }
102
103 Ref<StyleImage> m_image;
104};
105
106inline bool operator==(const ImageContentData& a, const ImageContentData& b)
107{
108 return &a.image() == &b.image();
109}
110
111inline bool operator!=(const ImageContentData& a, const ImageContentData& b)
112{
113 return !(a == b);
114}
115
116class TextContentData final : public ContentData {
117public:
118 explicit TextContentData(const String& text)
119 : ContentData(TextDataType)
120 , m_text(text)
121 {
122 }
123
124 const String& text() const { return m_text; }
125 void setText(const String& text) { m_text = text; }
126
127private:
128 RenderPtr<RenderObject> createContentRenderer(Document&, const RenderStyle&) const final;
129 std::unique_ptr<ContentData> cloneInternal() const final { return std::make_unique<TextContentData>(m_text); }
130
131 String m_text;
132};
133
134inline bool operator==(const TextContentData& a, const TextContentData& b)
135{
136 return a.text() == b.text();
137}
138
139inline bool operator!=(const TextContentData& a, const TextContentData& b)
140{
141 return !(a == b);
142}
143
144class CounterContentData final : public ContentData {
145public:
146 explicit CounterContentData(std::unique_ptr<CounterContent> counter)
147 : ContentData(CounterDataType)
148 , m_counter(WTFMove(counter))
149 {
150 ASSERT(m_counter);
151 }
152
153 const CounterContent& counter() const { return *m_counter; }
154 void setCounter(std::unique_ptr<CounterContent> counter)
155 {
156 ASSERT(counter);
157 m_counter = WTFMove(counter);
158 }
159
160private:
161 RenderPtr<RenderObject> createContentRenderer(Document&, const RenderStyle&) const final;
162 std::unique_ptr<ContentData> cloneInternal() const final
163 {
164 return std::make_unique<CounterContentData>(std::make_unique<CounterContent>(counter()));
165 }
166
167 std::unique_ptr<CounterContent> m_counter;
168};
169
170inline bool operator==(const CounterContentData& a, const CounterContentData& b)
171{
172 return a.counter() == b.counter();
173}
174
175inline bool operator!=(const CounterContentData& a, const CounterContentData& b)
176{
177 return !(a == b);
178}
179
180class QuoteContentData final : public ContentData {
181public:
182 explicit QuoteContentData(QuoteType quote)
183 : ContentData(QuoteDataType)
184 , m_quote(quote)
185 {
186 }
187
188 QuoteType quote() const { return m_quote; }
189 void setQuote(QuoteType quote) { m_quote = quote; }
190
191private:
192 RenderPtr<RenderObject> createContentRenderer(Document&, const RenderStyle&) const final;
193 std::unique_ptr<ContentData> cloneInternal() const final { return std::make_unique<QuoteContentData>(quote()); }
194
195 QuoteType m_quote;
196};
197
198inline bool operator==(const QuoteContentData& a, const QuoteContentData& b)
199{
200 return a.quote() == b.quote();
201}
202
203inline bool operator!=(const QuoteContentData& a, const QuoteContentData& b)
204{
205 return !(a == b);
206}
207
208inline bool operator==(const ContentData& a, const ContentData& b)
209{
210 if (a.type() != b.type())
211 return false;
212
213 switch (a.type()) {
214 case ContentData::CounterDataType:
215 return downcast<CounterContentData>(a) == downcast<CounterContentData>(b);
216 case ContentData::ImageDataType:
217 return downcast<ImageContentData>(a) == downcast<ImageContentData>(b);
218 case ContentData::QuoteDataType:
219 return downcast<QuoteContentData>(a) == downcast<QuoteContentData>(b);
220 case ContentData::TextDataType:
221 return downcast<TextContentData>(a) == downcast<TextContentData>(b);
222 }
223
224 ASSERT_NOT_REACHED();
225 return false;
226}
227
228inline bool operator!=(const ContentData& a, const ContentData& b)
229{
230 return !(a == b);
231}
232
233} // namespace WebCore
234
235#define SPECIALIZE_TYPE_TRAITS_CONTENT_DATA(ToClassName, ContentDataName) \
236SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToClassName) \
237 static bool isType(const WebCore::ContentData& contentData) { return contentData.is##ContentDataName(); } \
238SPECIALIZE_TYPE_TRAITS_END()
239
240SPECIALIZE_TYPE_TRAITS_CONTENT_DATA(ImageContentData, Image)
241SPECIALIZE_TYPE_TRAITS_CONTENT_DATA(TextContentData, Text)
242SPECIALIZE_TYPE_TRAITS_CONTENT_DATA(CounterContentData, Counter)
243SPECIALIZE_TYPE_TRAITS_CONTENT_DATA(QuoteContentData, Quote)
244