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#ifndef EditingStyle_h
33#define EditingStyle_h
34
35#include "CSSPropertyNames.h"
36#include "CSSValueKeywords.h"
37#include "WritingDirection.h"
38#include <wtf/Forward.h>
39#include <wtf/RefCounted.h>
40#include <wtf/RefPtr.h>
41#include <wtf/TriState.h>
42#include <wtf/Vector.h>
43#include <wtf/text/WTFString.h>
44
45namespace WebCore {
46
47class CSSStyleDeclaration;
48class CSSComputedStyleDeclaration;
49class CSSPrimitiveValue;
50class CSSValue;
51class ComputedStyleExtractor;
52class Document;
53class Element;
54class HTMLElement;
55class MutableStyleProperties;
56class Node;
57class Position;
58class QualifiedName;
59class RenderStyle;
60class StyleProperties;
61class StyledElement;
62class VisibleSelection;
63
64class EditingStyle : public RefCounted<EditingStyle> {
65public:
66
67    enum PropertiesToInclude { AllProperties, OnlyEditingInheritableProperties, EditingPropertiesInEffect };
68
69    enum ShouldPreserveWritingDirection { PreserveWritingDirection, DoNotPreserveWritingDirection };
70    enum ShouldExtractMatchingStyle { ExtractMatchingStyle, DoNotExtractMatchingStyle };
71    static float NoFontDelta;
72
73    static PassRefPtr<EditingStyle> create()
74    {
75        return adoptRef(new EditingStyle());
76    }
77
78    static PassRefPtr<EditingStyle> create(Node* node, PropertiesToInclude propertiesToInclude = OnlyEditingInheritableProperties)
79    {
80        return adoptRef(new EditingStyle(node, propertiesToInclude));
81    }
82
83    static PassRefPtr<EditingStyle> create(const Position& position, PropertiesToInclude propertiesToInclude = OnlyEditingInheritableProperties)
84    {
85        return adoptRef(new EditingStyle(position, propertiesToInclude));
86    }
87
88    static PassRefPtr<EditingStyle> create(const StyleProperties* style)
89    {
90        return adoptRef(new EditingStyle(style));
91    }
92
93    static PassRefPtr<EditingStyle> create(CSSPropertyID propertyID, const String& value)
94    {
95        return adoptRef(new EditingStyle(propertyID, value));
96    }
97
98    ~EditingStyle();
99
100    MutableStyleProperties* style() { return m_mutableStyle.get(); }
101    bool textDirection(WritingDirection&) const;
102    bool isEmpty() const;
103    void setStyle(PassRefPtr<MutableStyleProperties>);
104    void overrideWithStyle(const StyleProperties*);
105    void clear();
106    PassRefPtr<EditingStyle> copy() const;
107    PassRefPtr<EditingStyle> extractAndRemoveBlockProperties();
108    PassRefPtr<EditingStyle> extractAndRemoveTextDirection();
109    void removeBlockProperties();
110    void removeStyleAddedByNode(Node*);
111    void removeStyleConflictingWithStyleOfNode(Node*);
112    template<typename T> void removeEquivalentProperties(const T&);
113    void collapseTextDecorationProperties();
114    enum ShouldIgnoreTextOnlyProperties { IgnoreTextOnlyProperties, DoNotIgnoreTextOnlyProperties };
115    TriState triStateOfStyle(EditingStyle*) const;
116    TriState triStateOfStyle(const VisibleSelection&) const;
117    bool conflictsWithInlineStyleOfElement(StyledElement* element) const { return conflictsWithInlineStyleOfElement(element, 0, 0); }
118    bool conflictsWithInlineStyleOfElement(StyledElement* element, EditingStyle* extractedStyle, Vector<CSSPropertyID>& conflictingProperties) const
119    {
120        return conflictsWithInlineStyleOfElement(element, extractedStyle, &conflictingProperties);
121    }
122    bool conflictsWithImplicitStyleOfElement(HTMLElement*, EditingStyle* extractedStyle = 0, ShouldExtractMatchingStyle = DoNotExtractMatchingStyle) const;
123    bool conflictsWithImplicitStyleOfAttributes(HTMLElement*) const;
124    bool extractConflictingImplicitStyleOfAttributes(HTMLElement*, ShouldPreserveWritingDirection, EditingStyle* extractedStyle,
125            Vector<QualifiedName>& conflictingAttributes, ShouldExtractMatchingStyle) const;
126    bool styleIsPresentInComputedStyleOfNode(Node*) const;
127
128    static bool elementIsStyledSpanOrHTMLEquivalent(const HTMLElement*);
129
130    void prepareToApplyAt(const Position&, ShouldPreserveWritingDirection = DoNotPreserveWritingDirection);
131    void mergeTypingStyle(Document&);
132    enum CSSPropertyOverrideMode { OverrideValues, DoNotOverrideValues };
133    void mergeInlineStyleOfElement(StyledElement*, CSSPropertyOverrideMode, PropertiesToInclude = AllProperties);
134    static PassRefPtr<EditingStyle> wrappingStyleForSerialization(Node* context, bool shouldAnnotate);
135    void mergeStyleFromRules(StyledElement*);
136    void mergeStyleFromRulesForSerialization(StyledElement*);
137    void removeStyleFromRulesAndContext(StyledElement*, Node* context);
138    void removePropertiesInElementDefaultStyle(Element*);
139    void forceInline();
140    bool convertPositionStyle();
141    bool isFloating();
142    int legacyFontSize(Document*) const;
143
144    float fontSizeDelta() const { return m_fontSizeDelta; }
145    bool hasFontSizeDelta() const { return m_fontSizeDelta != NoFontDelta; }
146    bool shouldUseFixedDefaultFontSize() const { return m_shouldUseFixedDefaultFontSize; }
147
148    static PassRefPtr<EditingStyle> styleAtSelectionStart(const VisibleSelection&, bool shouldUseBackgroundColorInEffect = false);
149    static WritingDirection textDirectionForSelection(const VisibleSelection&, EditingStyle* typingStyle, bool& hasNestedOrMultipleEmbeddings);
150private:
151    EditingStyle();
152    EditingStyle(Node*, PropertiesToInclude);
153    EditingStyle(const Position&, PropertiesToInclude);
154    explicit EditingStyle(const StyleProperties*);
155    EditingStyle(CSSPropertyID, const String& value);
156    void init(Node*, PropertiesToInclude);
157    void removeTextFillAndStrokeColorsIfNeeded(RenderStyle*);
158    void setProperty(CSSPropertyID, const String& value, bool important = false);
159    void extractFontSizeDelta();
160    template<typename T> TriState triStateOfStyle(T* styleToCompare, ShouldIgnoreTextOnlyProperties) const;
161    bool conflictsWithInlineStyleOfElement(StyledElement*, EditingStyle* extractedStyle, Vector<CSSPropertyID>* conflictingProperties) const;
162    void mergeInlineAndImplicitStyleOfElement(StyledElement*, CSSPropertyOverrideMode, PropertiesToInclude);
163    void mergeStyle(const StyleProperties*, CSSPropertyOverrideMode);
164
165    RefPtr<MutableStyleProperties> m_mutableStyle;
166    bool m_shouldUseFixedDefaultFontSize;
167    float m_fontSizeDelta;
168
169    friend class HTMLElementEquivalent;
170    friend class HTMLAttributeEquivalent;
171};
172
173class StyleChange {
174public:
175    StyleChange()
176        : m_applyBold(false)
177        , m_applyItalic(false)
178        , m_applyUnderline(false)
179        , m_applyLineThrough(false)
180        , m_applySubscript(false)
181        , m_applySuperscript(false)
182    { }
183
184    StyleChange(EditingStyle*, const Position&);
185
186    String cssStyle() const { return m_cssStyle; }
187    bool applyBold() const { return m_applyBold; }
188    bool applyItalic() const { return m_applyItalic; }
189    bool applyUnderline() const { return m_applyUnderline; }
190    bool applyLineThrough() const { return m_applyLineThrough; }
191    bool applySubscript() const { return m_applySubscript; }
192    bool applySuperscript() const { return m_applySuperscript; }
193    bool applyFontColor() const { return m_applyFontColor.length() > 0; }
194    bool applyFontFace() const { return m_applyFontFace.length() > 0; }
195    bool applyFontSize() const { return m_applyFontSize.length() > 0; }
196
197    String fontColor() { return m_applyFontColor; }
198    String fontFace() { return m_applyFontFace; }
199    String fontSize() { return m_applyFontSize; }
200
201    bool operator==(const StyleChange& other)
202    {
203        return m_cssStyle == other.m_cssStyle
204            && m_applyBold == other.m_applyBold
205            && m_applyItalic == other.m_applyItalic
206            && m_applyUnderline == other.m_applyUnderline
207            && m_applyLineThrough == other.m_applyLineThrough
208            && m_applySubscript == other.m_applySubscript
209            && m_applySuperscript == other.m_applySuperscript
210            && m_applyFontColor == other.m_applyFontColor
211            && m_applyFontFace == other.m_applyFontFace
212            && m_applyFontSize == other.m_applyFontSize;
213    }
214    bool operator!=(const StyleChange& other)
215    {
216        return !(*this == other);
217    }
218private:
219    void extractTextStyles(Document*, MutableStyleProperties*, bool shouldUseFixedFontDefaultSize);
220
221    String m_cssStyle;
222    bool m_applyBold;
223    bool m_applyItalic;
224    bool m_applyUnderline;
225    bool m_applyLineThrough;
226    bool m_applySubscript;
227    bool m_applySuperscript;
228    String m_applyFontColor;
229    String m_applyFontFace;
230    String m_applyFontSize;
231};
232
233} // namespace WebCore
234
235#endif // EditingStyle_h
236