1/*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#pragma once
33
34#include "CSSPropertyNames.h"
35#include "CSSValueKeywords.h"
36#include "StyleProperties.h"
37#include "WritingDirection.h"
38#include <wtf/RefCounted.h>
39#include <wtf/TriState.h>
40#include <wtf/text/WTFString.h>
41
42namespace WebCore {
43
44class CSSStyleDeclaration;
45class CSSComputedStyleDeclaration;
46class CSSPrimitiveValue;
47class CSSValue;
48class ComputedStyleExtractor;
49class Document;
50class Element;
51class HTMLElement;
52class MutableStyleProperties;
53class Node;
54class Position;
55class QualifiedName;
56class RenderStyle;
57class StyleProperties;
58class StyledElement;
59class VisibleSelection;
60
61enum class TextDecorationChange { None, Add, Remove };
62
63class EditingStyle : public RefCounted<EditingStyle> {
64public:
65
66 enum PropertiesToInclude { AllProperties, OnlyEditingInheritableProperties, EditingPropertiesInEffect };
67
68 enum ShouldPreserveWritingDirection { PreserveWritingDirection, DoNotPreserveWritingDirection };
69 enum ShouldExtractMatchingStyle { ExtractMatchingStyle, DoNotExtractMatchingStyle };
70 static float NoFontDelta;
71
72 static Ref<EditingStyle> create()
73 {
74 return adoptRef(*new EditingStyle);
75 }
76
77 static Ref<EditingStyle> create(Node* node, PropertiesToInclude propertiesToInclude = OnlyEditingInheritableProperties)
78 {
79 return adoptRef(*new EditingStyle(node, propertiesToInclude));
80 }
81
82 static Ref<EditingStyle> create(const Position& position, PropertiesToInclude propertiesToInclude = OnlyEditingInheritableProperties)
83 {
84 return adoptRef(*new EditingStyle(position, propertiesToInclude));
85 }
86
87 static Ref<EditingStyle> create(const StyleProperties* style)
88 {
89 return adoptRef(*new EditingStyle(style));
90 }
91
92 static Ref<EditingStyle> create(const CSSStyleDeclaration* style)
93 {
94 return adoptRef(*new EditingStyle(style));
95 }
96
97 static Ref<EditingStyle> create(CSSPropertyID propertyID, const String& value)
98 {
99 return adoptRef(*new EditingStyle(propertyID, value));
100 }
101
102 static Ref<EditingStyle> create(CSSPropertyID propertyID, CSSValueID value)
103 {
104 return adoptRef(*new EditingStyle(propertyID, value));
105 }
106
107 WEBCORE_EXPORT ~EditingStyle();
108
109 MutableStyleProperties* style() { return m_mutableStyle.get(); }
110 Ref<MutableStyleProperties> styleWithResolvedTextDecorations() const;
111 Optional<WritingDirection> textDirection() const;
112 bool isEmpty() const;
113 void setStyle(RefPtr<MutableStyleProperties>&&);
114 void overrideWithStyle(const StyleProperties&);
115 void overrideTypingStyleAt(const EditingStyle&, const Position&);
116 void clear();
117 Ref<EditingStyle> copy() const;
118 Ref<EditingStyle> extractAndRemoveBlockProperties();
119 Ref<EditingStyle> extractAndRemoveTextDirection();
120 void removeBlockProperties();
121 void removeStyleAddedByNode(Node*);
122 void removeStyleConflictingWithStyleOfNode(Node&);
123 template<typename T> void removeEquivalentProperties(T&);
124 void collapseTextDecorationProperties();
125 enum ShouldIgnoreTextOnlyProperties { IgnoreTextOnlyProperties, DoNotIgnoreTextOnlyProperties };
126 TriState triStateOfStyle(EditingStyle*) const;
127 TriState triStateOfStyle(const VisibleSelection&) const;
128 bool conflictsWithInlineStyleOfElement(StyledElement& element) const { return conflictsWithInlineStyleOfElement(element, nullptr, nullptr); }
129 bool conflictsWithInlineStyleOfElement(StyledElement& element, RefPtr<MutableStyleProperties>& newInlineStyle, EditingStyle* extractedStyle) const
130 {
131 return conflictsWithInlineStyleOfElement(element, &newInlineStyle, extractedStyle);
132 }
133 bool conflictsWithImplicitStyleOfElement(HTMLElement&, EditingStyle* extractedStyle = nullptr, ShouldExtractMatchingStyle = DoNotExtractMatchingStyle) const;
134 bool conflictsWithImplicitStyleOfAttributes(HTMLElement&) const;
135 bool extractConflictingImplicitStyleOfAttributes(HTMLElement&, ShouldPreserveWritingDirection, EditingStyle* extractedStyle, Vector<QualifiedName>& conflictingAttributes, ShouldExtractMatchingStyle) const;
136 bool styleIsPresentInComputedStyleOfNode(Node&) const;
137
138 static bool elementIsStyledSpanOrHTMLEquivalent(const HTMLElement&);
139
140 void prepareToApplyAt(const Position&, ShouldPreserveWritingDirection = DoNotPreserveWritingDirection);
141 void mergeTypingStyle(Document&);
142 enum CSSPropertyOverrideMode { OverrideValues, DoNotOverrideValues };
143 void mergeInlineStyleOfElement(StyledElement&, CSSPropertyOverrideMode, PropertiesToInclude = AllProperties);
144 static Ref<EditingStyle> wrappingStyleForSerialization(Node& context, bool shouldAnnotate);
145 void mergeStyleFromRules(StyledElement&);
146 void mergeStyleFromRulesForSerialization(StyledElement&);
147 void removeStyleFromRulesAndContext(StyledElement&, Node* context);
148 void removePropertiesInElementDefaultStyle(Element&);
149 void forceInline();
150 void addDisplayContents();
151 bool convertPositionStyle();
152 bool isFloating();
153 int legacyFontSize(Document&) const;
154
155 float fontSizeDelta() const { return m_fontSizeDelta; }
156 bool hasFontSizeDelta() const { return m_fontSizeDelta != NoFontDelta; }
157 bool shouldUseFixedDefaultFontSize() const { return m_shouldUseFixedDefaultFontSize; }
158
159 void setUnderlineChange(TextDecorationChange change) { m_underlineChange = static_cast<unsigned>(change); }
160 TextDecorationChange underlineChange() const { return static_cast<TextDecorationChange>(m_underlineChange); }
161 void setStrikeThroughChange(TextDecorationChange change) { m_strikeThroughChange = static_cast<unsigned>(change); }
162 TextDecorationChange strikeThroughChange() const { return static_cast<TextDecorationChange>(m_strikeThroughChange); }
163
164 WEBCORE_EXPORT bool hasStyle(CSSPropertyID, const String& value);
165 WEBCORE_EXPORT static RefPtr<EditingStyle> styleAtSelectionStart(const VisibleSelection&, bool shouldUseBackgroundColorInEffect = false);
166 static WritingDirection textDirectionForSelection(const VisibleSelection&, EditingStyle* typingStyle, bool& hasNestedOrMultipleEmbeddings);
167
168 Ref<EditingStyle> inverseTransformColorIfNeeded(Element&);
169
170private:
171 EditingStyle();
172 EditingStyle(Node*, PropertiesToInclude);
173 EditingStyle(const Position&, PropertiesToInclude);
174 WEBCORE_EXPORT explicit EditingStyle(const CSSStyleDeclaration*);
175 explicit EditingStyle(const StyleProperties*);
176 EditingStyle(CSSPropertyID, const String& value);
177 EditingStyle(CSSPropertyID, CSSValueID);
178 void init(Node*, PropertiesToInclude);
179 void removeTextFillAndStrokeColorsIfNeeded(const RenderStyle*);
180 void setProperty(CSSPropertyID, const String& value, bool important = false);
181 void extractFontSizeDelta();
182 template<typename T> TriState triStateOfStyle(T& styleToCompare, ShouldIgnoreTextOnlyProperties) const;
183 bool conflictsWithInlineStyleOfElement(StyledElement&, RefPtr<MutableStyleProperties>* newInlineStyle, EditingStyle* extractedStyle) const;
184 void mergeInlineAndImplicitStyleOfElement(StyledElement&, CSSPropertyOverrideMode, PropertiesToInclude);
185 void mergeStyle(const StyleProperties*, CSSPropertyOverrideMode);
186
187 RefPtr<MutableStyleProperties> m_mutableStyle;
188 unsigned m_shouldUseFixedDefaultFontSize : 1;
189 unsigned m_underlineChange : 2;
190 unsigned m_strikeThroughChange : 2;
191 float m_fontSizeDelta = NoFontDelta;
192
193 friend class HTMLElementEquivalent;
194 friend class HTMLAttributeEquivalent;
195 friend class HTMLTextDecorationEquivalent;
196};
197
198class StyleChange {
199public:
200 StyleChange() { }
201 StyleChange(EditingStyle*, const Position&);
202
203 const StyleProperties* cssStyle() const { return m_cssStyle.get(); }
204 bool applyBold() const { return m_applyBold; }
205 bool applyItalic() const { return m_applyItalic; }
206 bool applyUnderline() const { return m_applyUnderline; }
207 bool applyLineThrough() const { return m_applyLineThrough; }
208 bool applySubscript() const { return m_applySubscript; }
209 bool applySuperscript() const { return m_applySuperscript; }
210 bool applyFontColor() const { return m_applyFontColor.length() > 0; }
211 bool applyFontFace() const { return m_applyFontFace.length() > 0; }
212 bool applyFontSize() const { return m_applyFontSize.length() > 0; }
213
214 String fontColor() { return m_applyFontColor; }
215 String fontFace() { return m_applyFontFace; }
216 String fontSize() { return m_applyFontSize; }
217
218 bool operator==(const StyleChange&);
219 bool operator!=(const StyleChange& other)
220 {
221 return !(*this == other);
222 }
223private:
224 void extractTextStyles(Document&, MutableStyleProperties&, bool shouldUseFixedFontDefaultSize);
225
226 RefPtr<MutableStyleProperties> m_cssStyle;
227 bool m_applyBold = false;
228 bool m_applyItalic = false;
229 bool m_applyUnderline = false;
230 bool m_applyLineThrough = false;
231 bool m_applySubscript = false;
232 bool m_applySuperscript = false;
233 String m_applyFontColor;
234 String m_applyFontFace;
235 String m_applyFontSize;
236};
237
238} // namespace WebCore
239