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