OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007, 2008, 2009 Apple Computer, Inc. | 2 * Copyright (C) 2007, 2008, 2009 Apple Computer, Inc. |
3 * Copyright (C) 2010, 2011 Google Inc. All rights reserved. | 3 * Copyright (C) 2010, 2011 Google Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 | 66 |
67 static const CSSPropertyID& textDecorationPropertyForEditing() { | 67 static const CSSPropertyID& textDecorationPropertyForEditing() { |
68 static const CSSPropertyID property = | 68 static const CSSPropertyID property = |
69 RuntimeEnabledFeatures::css3TextDecorationsEnabled() | 69 RuntimeEnabledFeatures::css3TextDecorationsEnabled() |
70 ? CSSPropertyTextDecorationLine | 70 ? CSSPropertyTextDecorationLine |
71 : CSSPropertyTextDecoration; | 71 : CSSPropertyTextDecoration; |
72 return property; | 72 return property; |
73 } | 73 } |
74 | 74 |
75 // Editing style properties must be preserved during editing operation. | 75 // Editing style properties must be preserved during editing operation. |
76 // e.g. when a user inserts a new paragraph, all properties listed here must be
copied to the new paragraph. | 76 // e.g. when a user inserts a new paragraph, all properties listed here must be |
| 77 // copied to the new paragraph. |
77 // NOTE: Use either allEditingProperties() or inheritableEditingProperties() to | 78 // NOTE: Use either allEditingProperties() or inheritableEditingProperties() to |
78 // respect runtime enabling of properties. | 79 // respect runtime enabling of properties. |
79 static const CSSPropertyID staticEditingProperties[] = { | 80 static const CSSPropertyID staticEditingProperties[] = { |
80 CSSPropertyBackgroundColor, CSSPropertyColor, CSSPropertyFontFamily, | 81 CSSPropertyBackgroundColor, CSSPropertyColor, CSSPropertyFontFamily, |
81 CSSPropertyFontSize, CSSPropertyFontStyle, CSSPropertyFontVariantLigatures, | 82 CSSPropertyFontSize, CSSPropertyFontStyle, CSSPropertyFontVariantLigatures, |
82 CSSPropertyFontVariantCaps, CSSPropertyFontWeight, CSSPropertyLetterSpacing, | 83 CSSPropertyFontVariantCaps, CSSPropertyFontWeight, CSSPropertyLetterSpacing, |
83 CSSPropertyOrphans, CSSPropertyTextAlign, | 84 CSSPropertyOrphans, CSSPropertyTextAlign, |
84 // FIXME: CSSPropertyTextDecoration needs to be removed when CSS3 Text | 85 // FIXME: CSSPropertyTextDecoration needs to be removed when CSS3 Text |
85 // Decoration feature is no longer experimental. | 86 // Decoration feature is no longer experimental. |
86 CSSPropertyTextDecoration, CSSPropertyTextDecorationLine, | 87 CSSPropertyTextDecoration, CSSPropertyTextDecorationLine, |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(m_identifierValue); } | 192 DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(m_identifierValue); } |
192 | 193 |
193 protected: | 194 protected: |
194 HTMLElementEquivalent(CSSPropertyID); | 195 HTMLElementEquivalent(CSSPropertyID); |
195 HTMLElementEquivalent(CSSPropertyID, const HTMLQualifiedName& tagName); | 196 HTMLElementEquivalent(CSSPropertyID, const HTMLQualifiedName& tagName); |
196 HTMLElementEquivalent(CSSPropertyID, | 197 HTMLElementEquivalent(CSSPropertyID, |
197 CSSValueID primitiveValue, | 198 CSSValueID primitiveValue, |
198 const HTMLQualifiedName& tagName); | 199 const HTMLQualifiedName& tagName); |
199 const CSSPropertyID m_propertyID; | 200 const CSSPropertyID m_propertyID; |
200 const Member<CSSIdentifierValue> m_identifierValue; | 201 const Member<CSSIdentifierValue> m_identifierValue; |
201 const HTMLQualifiedName* | 202 // We can store a pointer because HTML tag names are const global. |
202 m_tagName; // We can store a pointer because HTML tag names are const glo
bal. | 203 const HTMLQualifiedName* m_tagName; |
203 }; | 204 }; |
204 | 205 |
205 HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id) | 206 HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id) |
206 : m_propertyID(id), m_tagName(0) {} | 207 : m_propertyID(id), m_tagName(0) {} |
207 | 208 |
208 HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id, | 209 HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id, |
209 const HTMLQualifiedName& tagName) | 210 const HTMLQualifiedName& tagName) |
210 : m_propertyID(id), m_tagName(&tagName) {} | 211 : m_propertyID(id), m_tagName(&tagName) {} |
211 | 212 |
212 HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id, | 213 HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 virtual const CSSValue* attributeValueAsCSSValue(Element*) const; | 296 virtual const CSSValue* attributeValueAsCSSValue(Element*) const; |
296 inline const QualifiedName& attributeName() const { return m_attrName; } | 297 inline const QualifiedName& attributeName() const { return m_attrName; } |
297 | 298 |
298 DEFINE_INLINE_VIRTUAL_TRACE() { HTMLElementEquivalent::trace(visitor); } | 299 DEFINE_INLINE_VIRTUAL_TRACE() { HTMLElementEquivalent::trace(visitor); } |
299 | 300 |
300 protected: | 301 protected: |
301 HTMLAttributeEquivalent(CSSPropertyID, | 302 HTMLAttributeEquivalent(CSSPropertyID, |
302 const HTMLQualifiedName& tagName, | 303 const HTMLQualifiedName& tagName, |
303 const QualifiedName& attrName); | 304 const QualifiedName& attrName); |
304 HTMLAttributeEquivalent(CSSPropertyID, const QualifiedName& attrName); | 305 HTMLAttributeEquivalent(CSSPropertyID, const QualifiedName& attrName); |
305 const QualifiedName& | 306 // We can store a reference because HTML attribute names are const global. |
306 m_attrName; // We can store a reference because HTML attribute names are
const global. | 307 const QualifiedName& m_attrName; |
307 }; | 308 }; |
308 | 309 |
309 HTMLAttributeEquivalent::HTMLAttributeEquivalent( | 310 HTMLAttributeEquivalent::HTMLAttributeEquivalent( |
310 CSSPropertyID id, | 311 CSSPropertyID id, |
311 const HTMLQualifiedName& tagName, | 312 const HTMLQualifiedName& tagName, |
312 const QualifiedName& attrName) | 313 const QualifiedName& attrName) |
313 : HTMLElementEquivalent(id, tagName), m_attrName(attrName) {} | 314 : HTMLElementEquivalent(id, tagName), m_attrName(attrName) {} |
314 | 315 |
315 HTMLAttributeEquivalent::HTMLAttributeEquivalent(CSSPropertyID id, | 316 HTMLAttributeEquivalent::HTMLAttributeEquivalent(CSSPropertyID id, |
316 const QualifiedName& attrName) | 317 const QualifiedName& attrName) |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 | 606 |
606 EditingStyle* EditingStyle::copy() const { | 607 EditingStyle* EditingStyle::copy() const { |
607 EditingStyle* copy = EditingStyle::create(); | 608 EditingStyle* copy = EditingStyle::create(); |
608 if (m_mutableStyle) | 609 if (m_mutableStyle) |
609 copy->m_mutableStyle = m_mutableStyle->mutableCopy(); | 610 copy->m_mutableStyle = m_mutableStyle->mutableCopy(); |
610 copy->m_isMonospaceFont = m_isMonospaceFont; | 611 copy->m_isMonospaceFont = m_isMonospaceFont; |
611 copy->m_fontSizeDelta = m_fontSizeDelta; | 612 copy->m_fontSizeDelta = m_fontSizeDelta; |
612 return copy; | 613 return copy; |
613 } | 614 } |
614 | 615 |
615 // This is the list of CSS properties that apply specially to block-level elemen
ts. | 616 // This is the list of CSS properties that apply specially to block-level |
| 617 // elements. |
616 static const CSSPropertyID staticBlockProperties[] = { | 618 static const CSSPropertyID staticBlockProperties[] = { |
617 CSSPropertyBreakAfter, | 619 CSSPropertyBreakAfter, |
618 CSSPropertyBreakBefore, | 620 CSSPropertyBreakBefore, |
619 CSSPropertyBreakInside, | 621 CSSPropertyBreakInside, |
620 CSSPropertyOrphans, | 622 CSSPropertyOrphans, |
621 CSSPropertyOverflow, // This can be also be applied to replaced elements | 623 CSSPropertyOverflow, // This can be also be applied to replaced elements |
622 CSSPropertyColumnCount, | 624 CSSPropertyColumnCount, |
623 CSSPropertyColumnGap, | 625 CSSPropertyColumnGap, |
624 CSSPropertyColumnRuleColor, | 626 CSSPropertyColumnRuleColor, |
625 CSSPropertyColumnRuleStyle, | 627 CSSPropertyColumnRuleStyle, |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 if (selection.isCaret()) | 788 if (selection.isCaret()) |
787 return triStateOfStyle(EditingStyle::styleAtSelectionStart(selection)); | 789 return triStateOfStyle(EditingStyle::styleAtSelectionStart(selection)); |
788 | 790 |
789 TriState state = FalseTriState; | 791 TriState state = FalseTriState; |
790 bool nodeIsStart = true; | 792 bool nodeIsStart = true; |
791 for (Node& node : NodeTraversal::startsAt(*selection.start().anchorNode())) { | 793 for (Node& node : NodeTraversal::startsAt(*selection.start().anchorNode())) { |
792 if (node.layoutObject() && hasEditableStyle(node)) { | 794 if (node.layoutObject() && hasEditableStyle(node)) { |
793 CSSComputedStyleDeclaration* nodeStyle = | 795 CSSComputedStyleDeclaration* nodeStyle = |
794 CSSComputedStyleDeclaration::create(&node); | 796 CSSComputedStyleDeclaration::create(&node); |
795 if (nodeStyle) { | 797 if (nodeStyle) { |
796 // If the selected element has <sub> or <sup> ancestor element, apply th
e corresponding | 798 // If the selected element has <sub> or <sup> ancestor element, apply |
797 // style(vertical-align) to it so that document.queryCommandState() work
s with the style. | 799 // the corresponding style(vertical-align) to it so that |
798 // See bug http://crbug.com/582225. | 800 // document.queryCommandState() works with the style. See bug |
| 801 // http://crbug.com/582225. |
799 if (m_isVerticalAlign && | 802 if (m_isVerticalAlign && |
800 getIdentifierValue(nodeStyle, CSSPropertyVerticalAlign) == | 803 getIdentifierValue(nodeStyle, CSSPropertyVerticalAlign) == |
801 CSSValueBaseline) { | 804 CSSValueBaseline) { |
802 const CSSIdentifierValue* verticalAlign = toCSSIdentifierValue( | 805 const CSSIdentifierValue* verticalAlign = toCSSIdentifierValue( |
803 m_mutableStyle->getPropertyCSSValue(CSSPropertyVerticalAlign)); | 806 m_mutableStyle->getPropertyCSSValue(CSSPropertyVerticalAlign)); |
804 if (hasAncestorVerticalAlignStyle(node, verticalAlign->getValueID())) | 807 if (hasAncestorVerticalAlignStyle(node, verticalAlign->getValueID())) |
805 node.mutableComputedStyle()->setVerticalAlign( | 808 node.mutableComputedStyle()->setVerticalAlign( |
806 verticalAlign->convertTo<EVerticalAlign>()); | 809 verticalAlign->convertTo<EVerticalAlign>()); |
807 } | 810 } |
808 | 811 |
809 // Pass EditingStyle::DoNotIgnoreTextOnlyProperties without checking if
node.isTextNode() | 812 // Pass EditingStyle::DoNotIgnoreTextOnlyProperties without checking if |
810 // because the node can be an element node. See bug http://crbug.com/584
939. | 813 // node.isTextNode() because the node can be an element node. See bug |
| 814 // http://crbug.com/584939. |
811 TriState nodeState = triStateOfStyle( | 815 TriState nodeState = triStateOfStyle( |
812 nodeStyle, EditingStyle::DoNotIgnoreTextOnlyProperties); | 816 nodeStyle, EditingStyle::DoNotIgnoreTextOnlyProperties); |
813 if (nodeIsStart) { | 817 if (nodeIsStart) { |
814 state = nodeState; | 818 state = nodeState; |
815 nodeIsStart = false; | 819 nodeIsStart = false; |
816 } else if (state != nodeState && node.isTextNode()) { | 820 } else if (state != nodeState && node.isTextNode()) { |
817 state = MixedTriState; | 821 state = MixedTriState; |
818 break; | 822 break; |
819 } | 823 } |
820 } | 824 } |
(...skipping 13 matching lines...) Expand all Loading... |
834 DCHECK(!conflictingProperties || conflictingProperties->isEmpty()); | 838 DCHECK(!conflictingProperties || conflictingProperties->isEmpty()); |
835 | 839 |
836 const StylePropertySet* inlineStyle = element->inlineStyle(); | 840 const StylePropertySet* inlineStyle = element->inlineStyle(); |
837 if (!m_mutableStyle || !inlineStyle) | 841 if (!m_mutableStyle || !inlineStyle) |
838 return false; | 842 return false; |
839 | 843 |
840 unsigned propertyCount = m_mutableStyle->propertyCount(); | 844 unsigned propertyCount = m_mutableStyle->propertyCount(); |
841 for (unsigned i = 0; i < propertyCount; ++i) { | 845 for (unsigned i = 0; i < propertyCount; ++i) { |
842 CSSPropertyID propertyID = m_mutableStyle->propertyAt(i).id(); | 846 CSSPropertyID propertyID = m_mutableStyle->propertyAt(i).id(); |
843 | 847 |
844 // We don't override whitespace property of a tab span because that would co
llapse the tab into a space. | 848 // We don't override whitespace property of a tab span because that would |
| 849 // collapse the tab into a space. |
845 if (propertyID == CSSPropertyWhiteSpace && isTabHTMLSpanElement(element)) | 850 if (propertyID == CSSPropertyWhiteSpace && isTabHTMLSpanElement(element)) |
846 continue; | 851 continue; |
847 | 852 |
848 if (propertyID == CSSPropertyWebkitTextDecorationsInEffect && | 853 if (propertyID == CSSPropertyWebkitTextDecorationsInEffect && |
849 inlineStyle->getPropertyCSSValue(textDecorationPropertyForEditing())) { | 854 inlineStyle->getPropertyCSSValue(textDecorationPropertyForEditing())) { |
850 if (!conflictingProperties) | 855 if (!conflictingProperties) |
851 return true; | 856 return true; |
852 conflictingProperties->append(CSSPropertyTextDecoration); | 857 conflictingProperties->append(CSSPropertyTextDecoration); |
853 // Because text-decoration expands to text-decoration-line when CSS3 | 858 // Because text-decoration expands to text-decoration-line when CSS3 |
854 // Text Decoration is enabled, we also state it as conflicting. | 859 // Text Decoration is enabled, we also state it as conflicting. |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
943 } | 948 } |
944 return false; | 949 return false; |
945 } | 950 } |
946 | 951 |
947 static const HeapVector<Member<HTMLAttributeEquivalent>>& | 952 static const HeapVector<Member<HTMLAttributeEquivalent>>& |
948 htmlAttributeEquivalents() { | 953 htmlAttributeEquivalents() { |
949 DEFINE_STATIC_LOCAL(HeapVector<Member<HTMLAttributeEquivalent>>, | 954 DEFINE_STATIC_LOCAL(HeapVector<Member<HTMLAttributeEquivalent>>, |
950 HTMLAttributeEquivalents, | 955 HTMLAttributeEquivalents, |
951 (new HeapVector<Member<HTMLAttributeEquivalent>>)); | 956 (new HeapVector<Member<HTMLAttributeEquivalent>>)); |
952 if (!HTMLAttributeEquivalents.size()) { | 957 if (!HTMLAttributeEquivalents.size()) { |
953 // elementIsStyledSpanOrHTMLEquivalent depends on the fact each HTMLAttriute
Equivalent matches exactly one attribute | 958 // elementIsStyledSpanOrHTMLEquivalent depends on the fact each |
954 // of exactly one element except dirAttr. | 959 // HTMLAttriuteEquivalent matches exactly one attribute of exactly one |
| 960 // element except dirAttr. |
955 HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create( | 961 HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create( |
956 CSSPropertyColor, HTMLNames::fontTag, HTMLNames::colorAttr)); | 962 CSSPropertyColor, HTMLNames::fontTag, HTMLNames::colorAttr)); |
957 HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create( | 963 HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create( |
958 CSSPropertyFontFamily, HTMLNames::fontTag, HTMLNames::faceAttr)); | 964 CSSPropertyFontFamily, HTMLNames::fontTag, HTMLNames::faceAttr)); |
959 HTMLAttributeEquivalents.append(HTMLFontSizeEquivalent::create()); | 965 HTMLAttributeEquivalents.append(HTMLFontSizeEquivalent::create()); |
960 | 966 |
961 HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create( | 967 HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create( |
962 CSSPropertyDirection, HTMLNames::dirAttr)); | 968 CSSPropertyDirection, HTMLNames::dirAttr)); |
963 HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create( | 969 HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create( |
964 CSSPropertyUnicodeBidi, HTMLNames::dirAttr)); | 970 CSSPropertyUnicodeBidi, HTMLNames::dirAttr)); |
(...skipping 20 matching lines...) Expand all Loading... |
985 return false; | 991 return false; |
986 } | 992 } |
987 | 993 |
988 bool EditingStyle::extractConflictingImplicitStyleOfAttributes( | 994 bool EditingStyle::extractConflictingImplicitStyleOfAttributes( |
989 HTMLElement* element, | 995 HTMLElement* element, |
990 ShouldPreserveWritingDirection shouldPreserveWritingDirection, | 996 ShouldPreserveWritingDirection shouldPreserveWritingDirection, |
991 EditingStyle* extractedStyle, | 997 EditingStyle* extractedStyle, |
992 Vector<QualifiedName>& conflictingAttributes, | 998 Vector<QualifiedName>& conflictingAttributes, |
993 ShouldExtractMatchingStyle shouldExtractMatchingStyle) const { | 999 ShouldExtractMatchingStyle shouldExtractMatchingStyle) const { |
994 DCHECK(element); | 1000 DCHECK(element); |
995 // HTMLAttributeEquivalent::addToStyle doesn't support unicode-bidi and direct
ion properties | 1001 // HTMLAttributeEquivalent::addToStyle doesn't support unicode-bidi and |
| 1002 // direction properties |
996 if (extractedStyle) | 1003 if (extractedStyle) |
997 DCHECK_EQ(shouldPreserveWritingDirection, PreserveWritingDirection); | 1004 DCHECK_EQ(shouldPreserveWritingDirection, PreserveWritingDirection); |
998 if (!m_mutableStyle) | 1005 if (!m_mutableStyle) |
999 return false; | 1006 return false; |
1000 | 1007 |
1001 const HeapVector<Member<HTMLAttributeEquivalent>>& HTMLAttributeEquivalents = | 1008 const HeapVector<Member<HTMLAttributeEquivalent>>& HTMLAttributeEquivalents = |
1002 htmlAttributeEquivalents(); | 1009 htmlAttributeEquivalents(); |
1003 bool removed = false; | 1010 bool removed = false; |
1004 for (const auto& attribute : HTMLAttributeEquivalents) { | 1011 for (const auto& attribute : HTMLAttributeEquivalents) { |
1005 const HTMLAttributeEquivalent* equivalent = attribute.get(); | 1012 const HTMLAttributeEquivalent* equivalent = attribute.get(); |
1006 | 1013 |
1007 // unicode-bidi and direction are pushed down separately so don't push down
with other styles. | 1014 // unicode-bidi and direction are pushed down separately so don't push down |
| 1015 // with other styles. |
1008 if (shouldPreserveWritingDirection == PreserveWritingDirection && | 1016 if (shouldPreserveWritingDirection == PreserveWritingDirection && |
1009 equivalent->attributeName() == HTMLNames::dirAttr) | 1017 equivalent->attributeName() == HTMLNames::dirAttr) |
1010 continue; | 1018 continue; |
1011 | 1019 |
1012 if (!equivalent->matches(element) || | 1020 if (!equivalent->matches(element) || |
1013 !equivalent->propertyExistsInStyle(m_mutableStyle.get()) || | 1021 !equivalent->propertyExistsInStyle(m_mutableStyle.get()) || |
1014 (shouldExtractMatchingStyle == DoNotExtractMatchingStyle && | 1022 (shouldExtractMatchingStyle == DoNotExtractMatchingStyle && |
1015 equivalent->valueIsPresentInStyle(element, m_mutableStyle.get()))) | 1023 equivalent->valueIsPresentInStyle(element, m_mutableStyle.get()))) |
1016 continue; | 1024 continue; |
1017 | 1025 |
(...skipping 25 matching lines...) Expand all Loading... |
1043 size_t i; | 1051 size_t i; |
1044 for (i = 0; i < HTMLElementEquivalents.size(); ++i) { | 1052 for (i = 0; i < HTMLElementEquivalents.size(); ++i) { |
1045 if (HTMLElementEquivalents[i]->matches(element)) { | 1053 if (HTMLElementEquivalents[i]->matches(element)) { |
1046 elementIsSpanOrElementEquivalent = true; | 1054 elementIsSpanOrElementEquivalent = true; |
1047 break; | 1055 break; |
1048 } | 1056 } |
1049 } | 1057 } |
1050 } | 1058 } |
1051 | 1059 |
1052 AttributeCollection attributes = element->attributes(); | 1060 AttributeCollection attributes = element->attributes(); |
1053 if (attributes.isEmpty()) | 1061 if (attributes.isEmpty()) { |
1054 return elementIsSpanOrElementEquivalent; // span, b, etc... without any att
ributes | 1062 // span, b, etc... without any attributes |
| 1063 return elementIsSpanOrElementEquivalent; |
| 1064 } |
1055 | 1065 |
1056 unsigned matchedAttributes = 0; | 1066 unsigned matchedAttributes = 0; |
1057 const HeapVector<Member<HTMLAttributeEquivalent>>& HTMLAttributeEquivalents = | 1067 const HeapVector<Member<HTMLAttributeEquivalent>>& HTMLAttributeEquivalents = |
1058 htmlAttributeEquivalents(); | 1068 htmlAttributeEquivalents(); |
1059 for (const auto& equivalent : HTMLAttributeEquivalents) { | 1069 for (const auto& equivalent : HTMLAttributeEquivalents) { |
1060 if (equivalent->matches(element) && | 1070 if (equivalent->matches(element) && |
1061 equivalent->attributeName() != HTMLNames::dirAttr) | 1071 equivalent->attributeName() != HTMLNames::dirAttr) |
1062 matchedAttributes++; | 1072 matchedAttributes++; |
1063 } | 1073 } |
1064 | 1074 |
1065 if (!elementIsSpanOrElementEquivalent && !matchedAttributes) | 1075 if (!elementIsSpanOrElementEquivalent && !matchedAttributes) { |
1066 return false; // element is not a span, a html element equivalent, or font
element. | 1076 // element is not a span, a html element equivalent, or font element. |
| 1077 return false; |
| 1078 } |
1067 | 1079 |
1068 if (element->getAttribute(HTMLNames::classAttr) == AppleStyleSpanClass) | 1080 if (element->getAttribute(HTMLNames::classAttr) == AppleStyleSpanClass) |
1069 matchedAttributes++; | 1081 matchedAttributes++; |
1070 | 1082 |
1071 if (element->hasAttribute(HTMLNames::styleAttr)) { | 1083 if (element->hasAttribute(HTMLNames::styleAttr)) { |
1072 if (const StylePropertySet* style = element->inlineStyle()) { | 1084 if (const StylePropertySet* style = element->inlineStyle()) { |
1073 unsigned propertyCount = style->propertyCount(); | 1085 unsigned propertyCount = style->propertyCount(); |
1074 for (unsigned i = 0; i < propertyCount; ++i) { | 1086 for (unsigned i = 0; i < propertyCount; ++i) { |
1075 if (!isEditingProperty(style->propertyAt(i).id())) | 1087 if (!isEditingProperty(style->propertyAt(i).id())) |
1076 return false; | 1088 return false; |
1077 } | 1089 } |
1078 } | 1090 } |
1079 matchedAttributes++; | 1091 matchedAttributes++; |
1080 } | 1092 } |
1081 | 1093 |
1082 // font with color attribute, span with style attribute, etc... | 1094 // font with color attribute, span with style attribute, etc... |
1083 DCHECK_LE(matchedAttributes, attributes.size()); | 1095 DCHECK_LE(matchedAttributes, attributes.size()); |
1084 return matchedAttributes >= attributes.size(); | 1096 return matchedAttributes >= attributes.size(); |
1085 } | 1097 } |
1086 | 1098 |
1087 void EditingStyle::prepareToApplyAt( | 1099 void EditingStyle::prepareToApplyAt( |
1088 const Position& position, | 1100 const Position& position, |
1089 ShouldPreserveWritingDirection shouldPreserveWritingDirection) { | 1101 ShouldPreserveWritingDirection shouldPreserveWritingDirection) { |
1090 if (!m_mutableStyle) | 1102 if (!m_mutableStyle) |
1091 return; | 1103 return; |
1092 | 1104 |
1093 // ReplaceSelectionCommand::handleStyleSpans() requires that this function onl
y removes the editing style. | 1105 // ReplaceSelectionCommand::handleStyleSpans() requires that this function |
1094 // If this function was modified in the future to delete all redundant propert
ies, then add a boolean value to indicate | 1106 // only removes the editing style. If this function was modified in the future |
| 1107 // to delete all redundant properties, then add a boolean value to indicate |
1095 // which one of editingStyleAtPosition or computedStyle is called. | 1108 // which one of editingStyleAtPosition or computedStyle is called. |
1096 EditingStyle* editingStyleAtPosition = | 1109 EditingStyle* editingStyleAtPosition = |
1097 EditingStyle::create(position, EditingPropertiesInEffect); | 1110 EditingStyle::create(position, EditingPropertiesInEffect); |
1098 StylePropertySet* styleAtPosition = | 1111 StylePropertySet* styleAtPosition = |
1099 editingStyleAtPosition->m_mutableStyle.get(); | 1112 editingStyleAtPosition->m_mutableStyle.get(); |
1100 | 1113 |
1101 const CSSValue* unicodeBidi = nullptr; | 1114 const CSSValue* unicodeBidi = nullptr; |
1102 const CSSValue* direction = nullptr; | 1115 const CSSValue* direction = nullptr; |
1103 if (shouldPreserveWritingDirection == PreserveWritingDirection) { | 1116 if (shouldPreserveWritingDirection == PreserveWritingDirection) { |
1104 unicodeBidi = m_mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi); | 1117 unicodeBidi = m_mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 EditingStyle::create(context, EditingStyle::EditingPropertiesInEffect); | 1249 EditingStyle::create(context, EditingStyle::EditingPropertiesInEffect); |
1237 | 1250 |
1238 // Styles that Mail blockquotes contribute should only be placed on the Mail | 1251 // Styles that Mail blockquotes contribute should only be placed on the Mail |
1239 // blockquote, to help us differentiate those styles from ones that the user | 1252 // blockquote, to help us differentiate those styles from ones that the user |
1240 // has applied. This helps us get the color of content pasted into | 1253 // has applied. This helps us get the color of content pasted into |
1241 // blockquotes right. | 1254 // blockquotes right. |
1242 wrappingStyle->removeStyleAddedByElement(toHTMLElement(enclosingNodeOfType( | 1255 wrappingStyle->removeStyleAddedByElement(toHTMLElement(enclosingNodeOfType( |
1243 firstPositionInOrBeforeNode(context), isMailHTMLBlockquoteElement, | 1256 firstPositionInOrBeforeNode(context), isMailHTMLBlockquoteElement, |
1244 CanCrossEditingBoundary))); | 1257 CanCrossEditingBoundary))); |
1245 | 1258 |
1246 // Call collapseTextDecorationProperties first or otherwise it'll copy the val
ue over from in-effect to text-decorations. | 1259 // Call collapseTextDecorationProperties first or otherwise it'll copy the |
| 1260 // value over from in-effect to text-decorations. |
1247 wrappingStyle->collapseTextDecorationProperties(); | 1261 wrappingStyle->collapseTextDecorationProperties(); |
1248 | 1262 |
1249 return wrappingStyle; | 1263 return wrappingStyle; |
1250 } | 1264 } |
1251 | 1265 |
1252 EditingStyle* EditingStyle::wrappingStyleForSerialization( | 1266 EditingStyle* EditingStyle::wrappingStyleForSerialization( |
1253 ContainerNode* context) { | 1267 ContainerNode* context) { |
1254 DCHECK(context); | 1268 DCHECK(context); |
1255 EditingStyle* wrappingStyle = EditingStyle::create(); | 1269 EditingStyle* wrappingStyle = EditingStyle::create(); |
1256 | 1270 |
1257 // When not annotating for interchange, we only preserve inline style declarat
ions. | 1271 // When not annotating for interchange, we only preserve inline style |
| 1272 // declarations. |
1258 for (Node& node : NodeTraversal::inclusiveAncestorsOf(*context)) { | 1273 for (Node& node : NodeTraversal::inclusiveAncestorsOf(*context)) { |
1259 if (node.isDocumentNode()) | 1274 if (node.isDocumentNode()) |
1260 break; | 1275 break; |
1261 if (node.isStyledElement() && !isMailHTMLBlockquoteElement(&node)) { | 1276 if (node.isStyledElement() && !isMailHTMLBlockquoteElement(&node)) { |
1262 wrappingStyle->mergeInlineAndImplicitStyleOfElement( | 1277 wrappingStyle->mergeInlineAndImplicitStyleOfElement( |
1263 toElement(&node), EditingStyle::DoNotOverrideValues, | 1278 toElement(&node), EditingStyle::DoNotOverrideValues, |
1264 EditingStyle::EditingPropertiesInEffect); | 1279 EditingStyle::EditingPropertiesInEffect); |
1265 } | 1280 } |
1266 } | 1281 } |
1267 | 1282 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1304 if ((property.id() == textDecorationPropertyForEditing() || | 1319 if ((property.id() == textDecorationPropertyForEditing() || |
1305 property.id() == CSSPropertyWebkitTextDecorationsInEffect) && | 1320 property.id() == CSSPropertyWebkitTextDecorationsInEffect) && |
1306 property.value().isValueList() && value) { | 1321 property.value().isValueList() && value) { |
1307 if (value->isValueList()) { | 1322 if (value->isValueList()) { |
1308 const CSSValueList& result = mergeTextDecorationValues( | 1323 const CSSValueList& result = mergeTextDecorationValues( |
1309 *toCSSValueList(value), toCSSValueList(property.value())); | 1324 *toCSSValueList(value), toCSSValueList(property.value())); |
1310 m_mutableStyle->setProperty(property.id(), result, | 1325 m_mutableStyle->setProperty(property.id(), result, |
1311 property.isImportant()); | 1326 property.isImportant()); |
1312 continue; | 1327 continue; |
1313 } | 1328 } |
1314 value = | 1329 // text-decoration: none is equivalent to not having the property |
1315 nullptr; // text-decoration: none is equivalent to not having the pro
perty | 1330 value = nullptr; |
1316 } | 1331 } |
1317 | 1332 |
1318 if (mode == OverrideValues || (mode == DoNotOverrideValues && !value)) | 1333 if (mode == OverrideValues || (mode == DoNotOverrideValues && !value)) |
1319 m_mutableStyle->setProperty(property.toCSSProperty()); | 1334 m_mutableStyle->setProperty(property.toCSSProperty()); |
1320 } | 1335 } |
1321 } | 1336 } |
1322 | 1337 |
1323 static MutableStylePropertySet* styleFromMatchedRulesForElement( | 1338 static MutableStylePropertySet* styleFromMatchedRulesForElement( |
1324 Element* element, | 1339 Element* element, |
1325 unsigned rulesToInclude) { | 1340 unsigned rulesToInclude) { |
1326 MutableStylePropertySet* style = | 1341 MutableStylePropertySet* style = |
1327 MutableStylePropertySet::create(HTMLQuirksMode); | 1342 MutableStylePropertySet::create(HTMLQuirksMode); |
1328 StyleRuleList* matchedRules = | 1343 StyleRuleList* matchedRules = |
1329 element->document().ensureStyleResolver().styleRulesForElement( | 1344 element->document().ensureStyleResolver().styleRulesForElement( |
1330 element, rulesToInclude); | 1345 element, rulesToInclude); |
1331 if (matchedRules) { | 1346 if (matchedRules) { |
1332 for (unsigned i = 0; i < matchedRules->size(); ++i) | 1347 for (unsigned i = 0; i < matchedRules->size(); ++i) |
1333 style->mergeAndOverrideOnConflict(&matchedRules->at(i)->properties()); | 1348 style->mergeAndOverrideOnConflict(&matchedRules->at(i)->properties()); |
1334 } | 1349 } |
1335 return style; | 1350 return style; |
1336 } | 1351 } |
1337 | 1352 |
1338 void EditingStyle::mergeStyleFromRules(Element* element) { | 1353 void EditingStyle::mergeStyleFromRules(Element* element) { |
1339 MutableStylePropertySet* styleFromMatchedRules = | 1354 MutableStylePropertySet* styleFromMatchedRules = |
1340 styleFromMatchedRulesForElement( | 1355 styleFromMatchedRulesForElement( |
1341 element, | 1356 element, |
1342 StyleResolver::AuthorCSSRules | StyleResolver::CrossOriginCSSRules); | 1357 StyleResolver::AuthorCSSRules | StyleResolver::CrossOriginCSSRules); |
1343 // Styles from the inline style declaration, held in the variable "style", tak
e precedence | 1358 // Styles from the inline style declaration, held in the variable "style", |
1344 // over those from matched rules. | 1359 // take precedence over those from matched rules. |
1345 if (m_mutableStyle) | 1360 if (m_mutableStyle) |
1346 styleFromMatchedRules->mergeAndOverrideOnConflict(m_mutableStyle.get()); | 1361 styleFromMatchedRules->mergeAndOverrideOnConflict(m_mutableStyle.get()); |
1347 | 1362 |
1348 clear(); | 1363 clear(); |
1349 m_mutableStyle = styleFromMatchedRules; | 1364 m_mutableStyle = styleFromMatchedRules; |
1350 } | 1365 } |
1351 | 1366 |
1352 void EditingStyle::mergeStyleFromRulesForSerialization(Element* element) { | 1367 void EditingStyle::mergeStyleFromRulesForSerialization(Element* element) { |
1353 mergeStyleFromRules(element); | 1368 mergeStyleFromRules(element); |
1354 | 1369 |
1355 // The property value, if it's a percentage, may not reflect the actual comput
ed value. | 1370 // The property value, if it's a percentage, may not reflect the actual |
| 1371 // computed value. |
1356 // For example: style="height: 1%; overflow: visible;" in quirksmode | 1372 // For example: style="height: 1%; overflow: visible;" in quirksmode |
1357 // FIXME: There are others like this, see <rdar://problem/5195123> Slashdot co
py/paste fidelity problem | 1373 // FIXME: There are others like this, see <rdar://problem/5195123> Slashdot |
| 1374 // copy/paste fidelity problem |
1358 CSSComputedStyleDeclaration* computedStyleForElement = | 1375 CSSComputedStyleDeclaration* computedStyleForElement = |
1359 CSSComputedStyleDeclaration::create(element); | 1376 CSSComputedStyleDeclaration::create(element); |
1360 MutableStylePropertySet* fromComputedStyle = | 1377 MutableStylePropertySet* fromComputedStyle = |
1361 MutableStylePropertySet::create(HTMLQuirksMode); | 1378 MutableStylePropertySet::create(HTMLQuirksMode); |
1362 { | 1379 { |
1363 unsigned propertyCount = m_mutableStyle->propertyCount(); | 1380 unsigned propertyCount = m_mutableStyle->propertyCount(); |
1364 for (unsigned i = 0; i < propertyCount; ++i) { | 1381 for (unsigned i = 0; i < propertyCount; ++i) { |
1365 StylePropertySet::PropertyReference property = | 1382 StylePropertySet::PropertyReference property = |
1366 m_mutableStyle->propertyAt(i); | 1383 m_mutableStyle->propertyAt(i); |
1367 const CSSValue& value = property.value(); | 1384 const CSSValue& value = property.value(); |
(...skipping 26 matching lines...) Expand all Loading... |
1394 ContainerNode* context) { | 1411 ContainerNode* context) { |
1395 DCHECK(element); | 1412 DCHECK(element); |
1396 if (!m_mutableStyle) | 1413 if (!m_mutableStyle) |
1397 return; | 1414 return; |
1398 | 1415 |
1399 // TODO(yosin): The use of updateStyleAndLayoutIgnorePendingStylesheets | 1416 // TODO(yosin): The use of updateStyleAndLayoutIgnorePendingStylesheets |
1400 // needs to be audited. see http://crbug.com/590369 for more details. | 1417 // needs to be audited. see http://crbug.com/590369 for more details. |
1401 element->document().updateStyleAndLayoutIgnorePendingStylesheetsForNode( | 1418 element->document().updateStyleAndLayoutIgnorePendingStylesheetsForNode( |
1402 element); | 1419 element); |
1403 | 1420 |
1404 // 1. Remove style from matched rules because style remain without repeating i
t in inline style declaration | 1421 // 1. Remove style from matched rules because style remain without repeating |
| 1422 // it in inline style declaration |
1405 MutableStylePropertySet* styleFromMatchedRules = | 1423 MutableStylePropertySet* styleFromMatchedRules = |
1406 styleFromMatchedRulesForElement(element, | 1424 styleFromMatchedRulesForElement(element, |
1407 StyleResolver::AllButEmptyCSSRules); | 1425 StyleResolver::AllButEmptyCSSRules); |
1408 if (styleFromMatchedRules && !styleFromMatchedRules->isEmpty()) | 1426 if (styleFromMatchedRules && !styleFromMatchedRules->isEmpty()) |
1409 m_mutableStyle = | 1427 m_mutableStyle = |
1410 getPropertiesNotIn(m_mutableStyle.get(), | 1428 getPropertiesNotIn(m_mutableStyle.get(), |
1411 styleFromMatchedRules->ensureCSSStyleDeclaration()); | 1429 styleFromMatchedRules->ensureCSSStyleDeclaration()); |
1412 | 1430 |
1413 // 2. Remove style present in context and not overriden by matched rules. | 1431 // 2. Remove style present in context and not overriden by matched rules. |
1414 EditingStyle* computedStyle = | 1432 EditingStyle* computedStyle = |
1415 EditingStyle::create(context, EditingPropertiesInEffect); | 1433 EditingStyle::create(context, EditingPropertiesInEffect); |
1416 if (computedStyle->m_mutableStyle) { | 1434 if (computedStyle->m_mutableStyle) { |
1417 if (!computedStyle->m_mutableStyle->getPropertyCSSValue( | 1435 if (!computedStyle->m_mutableStyle->getPropertyCSSValue( |
1418 CSSPropertyBackgroundColor)) | 1436 CSSPropertyBackgroundColor)) |
1419 computedStyle->m_mutableStyle->setProperty(CSSPropertyBackgroundColor, | 1437 computedStyle->m_mutableStyle->setProperty(CSSPropertyBackgroundColor, |
1420 CSSValueTransparent); | 1438 CSSValueTransparent); |
1421 | 1439 |
1422 removePropertiesInStyle(computedStyle->m_mutableStyle.get(), | 1440 removePropertiesInStyle(computedStyle->m_mutableStyle.get(), |
1423 styleFromMatchedRules); | 1441 styleFromMatchedRules); |
1424 m_mutableStyle = getPropertiesNotIn( | 1442 m_mutableStyle = getPropertiesNotIn( |
1425 m_mutableStyle.get(), | 1443 m_mutableStyle.get(), |
1426 computedStyle->m_mutableStyle->ensureCSSStyleDeclaration()); | 1444 computedStyle->m_mutableStyle->ensureCSSStyleDeclaration()); |
1427 } | 1445 } |
1428 | 1446 |
1429 // 3. If this element is a span and has display: inline or float: none, remove
them unless they are overriden by rules. | 1447 // 3. If this element is a span and has display: inline or float: none, remove |
1430 // These rules are added by serialization code to wrap text nodes. | 1448 // them unless they are overriden by rules. These rules are added by |
| 1449 // serialization code to wrap text nodes. |
1431 if (isStyleSpanOrSpanWithOnlyStyleAttribute(element)) { | 1450 if (isStyleSpanOrSpanWithOnlyStyleAttribute(element)) { |
1432 if (!styleFromMatchedRules->getPropertyCSSValue(CSSPropertyDisplay) && | 1451 if (!styleFromMatchedRules->getPropertyCSSValue(CSSPropertyDisplay) && |
1433 getIdentifierValue(m_mutableStyle.get(), CSSPropertyDisplay) == | 1452 getIdentifierValue(m_mutableStyle.get(), CSSPropertyDisplay) == |
1434 CSSValueInline) | 1453 CSSValueInline) |
1435 m_mutableStyle->removeProperty(CSSPropertyDisplay); | 1454 m_mutableStyle->removeProperty(CSSPropertyDisplay); |
1436 if (!styleFromMatchedRules->getPropertyCSSValue(CSSPropertyFloat) && | 1455 if (!styleFromMatchedRules->getPropertyCSSValue(CSSPropertyFloat) && |
1437 getIdentifierValue(m_mutableStyle.get(), CSSPropertyFloat) == | 1456 getIdentifierValue(m_mutableStyle.get(), CSSPropertyFloat) == |
1438 CSSValueNone) | 1457 CSSValueNone) |
1439 m_mutableStyle->removeProperty(CSSPropertyFloat); | 1458 m_mutableStyle->removeProperty(CSSPropertyFloat); |
1440 } | 1459 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1511 | 1530 |
1512 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 1531 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
1513 // needs to be audited. see http://crbug.com/590369 for more details. | 1532 // needs to be audited. see http://crbug.com/590369 for more details. |
1514 document.updateStyleAndLayoutIgnorePendingStylesheets(); | 1533 document.updateStyleAndLayoutIgnorePendingStylesheets(); |
1515 | 1534 |
1516 DocumentLifecycle::DisallowTransitionScope disallowTransition( | 1535 DocumentLifecycle::DisallowTransitionScope disallowTransition( |
1517 document.lifecycle()); | 1536 document.lifecycle()); |
1518 | 1537 |
1519 Position position = adjustedSelectionStartForStyleComputation(selection); | 1538 Position position = adjustedSelectionStartForStyleComputation(selection); |
1520 | 1539 |
1521 // If the pos is at the end of a text node, then this node is not fully select
ed. | 1540 // If the pos is at the end of a text node, then this node is not fully |
1522 // Move it to the next deep equivalent position to avoid removing the style fr
om this node. | 1541 // selected. Move it to the next deep equivalent position to avoid removing |
1523 // e.g. if pos was at Position("hello", 5) in <b>hello<div>world</div></b>, we
want Position("world", 0) instead. | 1542 // the style from this node. |
1524 // We only do this for range because caret at Position("hello", 5) in <b>hello
</b>world should give you font-weight: bold. | 1543 // e.g. if pos was at Position("hello", 5) in <b>hello<div>world</div></b>, we |
| 1544 // want Position("world", 0) instead. |
| 1545 // We only do this for range because caret at Position("hello", 5) in |
| 1546 // <b>hello</b>world should give you font-weight: bold. |
1525 Node* positionNode = position.computeContainerNode(); | 1547 Node* positionNode = position.computeContainerNode(); |
1526 if (selection.isRange() && positionNode && positionNode->isTextNode() && | 1548 if (selection.isRange() && positionNode && positionNode->isTextNode() && |
1527 position.computeOffsetInContainerNode() == | 1549 position.computeOffsetInContainerNode() == |
1528 positionNode->maxCharacterOffset()) | 1550 positionNode->maxCharacterOffset()) |
1529 position = nextVisuallyDistinctCandidate(position); | 1551 position = nextVisuallyDistinctCandidate(position); |
1530 | 1552 |
1531 Element* element = associatedElementOf(position); | 1553 Element* element = associatedElementOf(position); |
1532 if (!element) | 1554 if (!element) |
1533 return nullptr; | 1555 return nullptr; |
1534 | 1556 |
1535 EditingStyle* style = | 1557 EditingStyle* style = |
1536 EditingStyle::create(element, EditingStyle::AllProperties); | 1558 EditingStyle::create(element, EditingStyle::AllProperties); |
1537 style->mergeTypingStyle(&element->document()); | 1559 style->mergeTypingStyle(&element->document()); |
1538 | 1560 |
1539 // If |element| has <sub> or <sup> ancestor element, apply the corresponding | 1561 // If |element| has <sub> or <sup> ancestor element, apply the corresponding |
1540 // style(vertical-align) to it so that document.queryCommandState() works with
the style. | 1562 // style(vertical-align) to it so that document.queryCommandState() works with |
1541 // See bug http://crbug.com/582225. | 1563 // the style. See bug http://crbug.com/582225. |
1542 CSSValueID valueID = | 1564 CSSValueID valueID = |
1543 getIdentifierValue(styleToCheck, CSSPropertyVerticalAlign); | 1565 getIdentifierValue(styleToCheck, CSSPropertyVerticalAlign); |
1544 if (valueID == CSSValueSub || valueID == CSSValueSuper) { | 1566 if (valueID == CSSValueSub || valueID == CSSValueSuper) { |
1545 CSSComputedStyleDeclaration* elementStyle = | 1567 CSSComputedStyleDeclaration* elementStyle = |
1546 CSSComputedStyleDeclaration::create(element); | 1568 CSSComputedStyleDeclaration::create(element); |
1547 // Find the ancestor that has CSSValueSub or CSSValueSuper as the value of C
SS vertical-align property. | 1569 // Find the ancestor that has CSSValueSub or CSSValueSuper as the value of |
| 1570 // CSS vertical-align property. |
1548 if (getIdentifierValue(elementStyle, CSSPropertyVerticalAlign) == | 1571 if (getIdentifierValue(elementStyle, CSSPropertyVerticalAlign) == |
1549 CSSValueBaseline && | 1572 CSSValueBaseline && |
1550 hasAncestorVerticalAlignStyle(*element, valueID)) | 1573 hasAncestorVerticalAlignStyle(*element, valueID)) |
1551 style->m_mutableStyle->setProperty(CSSPropertyVerticalAlign, valueID); | 1574 style->m_mutableStyle->setProperty(CSSPropertyVerticalAlign, valueID); |
1552 } | 1575 } |
1553 | 1576 |
1554 // If background color is transparent, traverse parent nodes until we hit a di
fferent value or document root | 1577 // If background color is transparent, traverse parent nodes until we hit a |
1555 // Also, if the selection is a range, ignore the background color at the start
of selection, | 1578 // different value or document root Also, if the selection is a range, ignore |
1556 // and find the background color of the common ancestor. | 1579 // the background color at the start of selection, and find the background |
| 1580 // color of the common ancestor. |
1557 if (shouldUseBackgroundColorInEffect && | 1581 if (shouldUseBackgroundColorInEffect && |
1558 (selection.isRange() || | 1582 (selection.isRange() || |
1559 hasTransparentBackgroundColor(style->m_mutableStyle.get()))) { | 1583 hasTransparentBackgroundColor(style->m_mutableStyle.get()))) { |
1560 const EphemeralRange range(selection.toNormalizedEphemeralRange()); | 1584 const EphemeralRange range(selection.toNormalizedEphemeralRange()); |
1561 if (const CSSValue* value = | 1585 if (const CSSValue* value = |
1562 backgroundColorValueInEffect(Range::commonAncestorContainer( | 1586 backgroundColorValueInEffect(Range::commonAncestorContainer( |
1563 range.startPosition().computeContainerNode(), | 1587 range.startPosition().computeContainerNode(), |
1564 range.endPosition().computeContainerNode()))) | 1588 range.endPosition().computeContainerNode()))) |
1565 style->setProperty(CSSPropertyBackgroundColor, value->cssText()); | 1589 style->setProperty(CSSPropertyBackgroundColor, value->cssText()); |
1566 } | 1590 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1619 if (selection.isCaret()) { | 1643 if (selection.isCaret()) { |
1620 WritingDirection direction; | 1644 WritingDirection direction; |
1621 if (typingStyle && typingStyle->textDirection(direction)) { | 1645 if (typingStyle && typingStyle->textDirection(direction)) { |
1622 hasNestedOrMultipleEmbeddings = false; | 1646 hasNestedOrMultipleEmbeddings = false; |
1623 return direction; | 1647 return direction; |
1624 } | 1648 } |
1625 node = selection.visibleStart().deepEquivalent().anchorNode(); | 1649 node = selection.visibleStart().deepEquivalent().anchorNode(); |
1626 } | 1650 } |
1627 DCHECK(node); | 1651 DCHECK(node); |
1628 | 1652 |
1629 // The selection is either a caret with no typing attributes or a range in whi
ch no embedding is added, so just use the start position | 1653 // The selection is either a caret with no typing attributes or a range in |
1630 // to decide. | 1654 // which no embedding is added, so just use the start position to decide. |
1631 Node* block = enclosingBlock(node); | 1655 Node* block = enclosingBlock(node); |
1632 WritingDirection foundDirection = NaturalWritingDirection; | 1656 WritingDirection foundDirection = NaturalWritingDirection; |
1633 | 1657 |
1634 for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*node)) { | 1658 for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*node)) { |
1635 if (runner == block) | 1659 if (runner == block) |
1636 break; | 1660 break; |
1637 if (!runner.isStyledElement()) | 1661 if (!runner.isStyledElement()) |
1638 continue; | 1662 continue; |
1639 | 1663 |
1640 Element* element = &toElement(runner); | 1664 Element* element = &toElement(runner); |
(...skipping 18 matching lines...) Expand all Loading... |
1659 if (!direction || !direction->isIdentifierValue()) | 1683 if (!direction || !direction->isIdentifierValue()) |
1660 continue; | 1684 continue; |
1661 | 1685 |
1662 int directionValue = toCSSIdentifierValue(direction)->getValueID(); | 1686 int directionValue = toCSSIdentifierValue(direction)->getValueID(); |
1663 if (directionValue != CSSValueLtr && directionValue != CSSValueRtl) | 1687 if (directionValue != CSSValueLtr && directionValue != CSSValueRtl) |
1664 continue; | 1688 continue; |
1665 | 1689 |
1666 if (foundDirection != NaturalWritingDirection) | 1690 if (foundDirection != NaturalWritingDirection) |
1667 return NaturalWritingDirection; | 1691 return NaturalWritingDirection; |
1668 | 1692 |
1669 // In the range case, make sure that the embedding element persists until th
e end of the range. | 1693 // In the range case, make sure that the embedding element persists until |
| 1694 // the end of the range. |
1670 if (selection.isRange() && !end.anchorNode()->isDescendantOf(element)) | 1695 if (selection.isRange() && !end.anchorNode()->isDescendantOf(element)) |
1671 return NaturalWritingDirection; | 1696 return NaturalWritingDirection; |
1672 | 1697 |
1673 foundDirection = directionValue == CSSValueLtr | 1698 foundDirection = directionValue == CSSValueLtr |
1674 ? LeftToRightWritingDirection | 1699 ? LeftToRightWritingDirection |
1675 : RightToLeftWritingDirection; | 1700 : RightToLeftWritingDirection; |
1676 } | 1701 } |
1677 hasNestedOrMultipleEmbeddings = false; | 1702 hasNestedOrMultipleEmbeddings = false; |
1678 return foundDirection; | 1703 return foundDirection; |
1679 } | 1704 } |
1680 | 1705 |
1681 DEFINE_TRACE(EditingStyle) { | 1706 DEFINE_TRACE(EditingStyle) { |
1682 visitor->trace(m_mutableStyle); | 1707 visitor->trace(m_mutableStyle); |
1683 } | 1708 } |
1684 | 1709 |
1685 static void reconcileTextDecorationProperties(MutableStylePropertySet* style) { | 1710 static void reconcileTextDecorationProperties(MutableStylePropertySet* style) { |
1686 const CSSValue* textDecorationsInEffect = | 1711 const CSSValue* textDecorationsInEffect = |
1687 style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect); | 1712 style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect); |
1688 const CSSValue* textDecoration = | 1713 const CSSValue* textDecoration = |
1689 style->getPropertyCSSValue(textDecorationPropertyForEditing()); | 1714 style->getPropertyCSSValue(textDecorationPropertyForEditing()); |
1690 // We shouldn't have both text-decoration and -webkit-text-decorations-in-effe
ct because that wouldn't make sense. | 1715 // We shouldn't have both text-decoration and |
| 1716 // -webkit-text-decorations-in-effect because that wouldn't make sense. |
1691 DCHECK(!textDecorationsInEffect || !textDecoration); | 1717 DCHECK(!textDecorationsInEffect || !textDecoration); |
1692 if (textDecorationsInEffect) { | 1718 if (textDecorationsInEffect) { |
1693 style->setProperty(textDecorationPropertyForEditing(), | 1719 style->setProperty(textDecorationPropertyForEditing(), |
1694 textDecorationsInEffect->cssText()); | 1720 textDecorationsInEffect->cssText()); |
1695 style->removeProperty(CSSPropertyWebkitTextDecorationsInEffect); | 1721 style->removeProperty(CSSPropertyWebkitTextDecorationsInEffect); |
1696 textDecoration = textDecorationsInEffect; | 1722 textDecoration = textDecorationsInEffect; |
1697 } | 1723 } |
1698 | 1724 |
1699 // If text-decoration is set to "none", remove the property because we don't w
ant to add redundant "text-decoration: none". | 1725 // If text-decoration is set to "none", remove the property because we don't |
| 1726 // want to add redundant "text-decoration: none". |
1700 if (textDecoration && !textDecoration->isValueList()) | 1727 if (textDecoration && !textDecoration->isValueList()) |
1701 style->removeProperty(textDecorationPropertyForEditing()); | 1728 style->removeProperty(textDecorationPropertyForEditing()); |
1702 } | 1729 } |
1703 | 1730 |
1704 StyleChange::StyleChange(EditingStyle* style, const Position& position) | 1731 StyleChange::StyleChange(EditingStyle* style, const Position& position) |
1705 : m_applyBold(false), | 1732 : m_applyBold(false), |
1706 m_applyItalic(false), | 1733 m_applyItalic(false), |
1707 m_applyUnderline(false), | 1734 m_applyUnderline(false), |
1708 m_applyLineThrough(false), | 1735 m_applyLineThrough(false), |
1709 m_applySubscript(false), | 1736 m_applySubscript(false), |
1710 m_applySuperscript(false) { | 1737 m_applySuperscript(false) { |
1711 Document* document = position.document(); | 1738 Document* document = position.document(); |
1712 if (!style || !style->style() || !document || !document->frame() || | 1739 if (!style || !style->style() || !document || !document->frame() || |
1713 !associatedElementOf(position)) | 1740 !associatedElementOf(position)) |
1714 return; | 1741 return; |
1715 | 1742 |
1716 CSSComputedStyleDeclaration* computedStyle = ensureComputedStyle(position); | 1743 CSSComputedStyleDeclaration* computedStyle = ensureComputedStyle(position); |
1717 // FIXME: take care of background-color in effect | 1744 // FIXME: take care of background-color in effect |
1718 MutableStylePropertySet* mutableStyle = | 1745 MutableStylePropertySet* mutableStyle = |
1719 getPropertiesNotIn(style->style(), computedStyle); | 1746 getPropertiesNotIn(style->style(), computedStyle); |
1720 DCHECK(mutableStyle); | 1747 DCHECK(mutableStyle); |
1721 | 1748 |
1722 reconcileTextDecorationProperties(mutableStyle); | 1749 reconcileTextDecorationProperties(mutableStyle); |
1723 if (!document->frame()->editor().shouldStyleWithCSS()) | 1750 if (!document->frame()->editor().shouldStyleWithCSS()) |
1724 extractTextStyles(document, mutableStyle, computedStyle->isMonospaceFont()); | 1751 extractTextStyles(document, mutableStyle, computedStyle->isMonospaceFont()); |
1725 | 1752 |
1726 // Changing the whitespace style in a tab span would collapse the tab into a s
pace. | 1753 // Changing the whitespace style in a tab span would collapse the tab into a |
| 1754 // space. |
1727 if (isTabHTMLSpanElementTextNode(position.anchorNode()) || | 1755 if (isTabHTMLSpanElementTextNode(position.anchorNode()) || |
1728 isTabHTMLSpanElement((position.anchorNode()))) | 1756 isTabHTMLSpanElement((position.anchorNode()))) |
1729 mutableStyle->removeProperty(CSSPropertyWhiteSpace); | 1757 mutableStyle->removeProperty(CSSPropertyWhiteSpace); |
1730 | 1758 |
1731 // If unicode-bidi is present in mutableStyle and direction is not, then add d
irection to mutableStyle. | 1759 // If unicode-bidi is present in mutableStyle and direction is not, then add |
| 1760 // direction to mutableStyle. |
1732 // FIXME: Shouldn't this be done in getPropertiesNotIn? | 1761 // FIXME: Shouldn't this be done in getPropertiesNotIn? |
1733 if (mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi) && | 1762 if (mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi) && |
1734 !style->style()->getPropertyCSSValue(CSSPropertyDirection)) | 1763 !style->style()->getPropertyCSSValue(CSSPropertyDirection)) |
1735 mutableStyle->setProperty( | 1764 mutableStyle->setProperty( |
1736 CSSPropertyDirection, | 1765 CSSPropertyDirection, |
1737 style->style()->getPropertyValue(CSSPropertyDirection)); | 1766 style->style()->getPropertyValue(CSSPropertyDirection)); |
1738 | 1767 |
1739 // Save the result for later | 1768 // Save the result for later |
1740 m_cssStyle = mutableStyle->asText().stripWhiteSpace(); | 1769 m_cssStyle = mutableStyle->asText().stripWhiteSpace(); |
1741 } | 1770 } |
(...skipping 20 matching lines...) Expand all Loading... |
1762 style->removeProperty(CSSPropertyFontWeight); | 1791 style->removeProperty(CSSPropertyFontWeight); |
1763 m_applyBold = true; | 1792 m_applyBold = true; |
1764 } | 1793 } |
1765 | 1794 |
1766 int fontStyle = getIdentifierValue(style, CSSPropertyFontStyle); | 1795 int fontStyle = getIdentifierValue(style, CSSPropertyFontStyle); |
1767 if (fontStyle == CSSValueItalic || fontStyle == CSSValueOblique) { | 1796 if (fontStyle == CSSValueItalic || fontStyle == CSSValueOblique) { |
1768 style->removeProperty(CSSPropertyFontStyle); | 1797 style->removeProperty(CSSPropertyFontStyle); |
1769 m_applyItalic = true; | 1798 m_applyItalic = true; |
1770 } | 1799 } |
1771 | 1800 |
1772 // Assuming reconcileTextDecorationProperties has been called, there should no
t be -webkit-text-decorations-in-effect | 1801 // Assuming reconcileTextDecorationProperties has been called, there should |
1773 // Furthermore, text-decoration: none has been trimmed so that text-decoration
property is always a CSSValueList. | 1802 // not be -webkit-text-decorations-in-effect |
| 1803 // Furthermore, text-decoration: none has been trimmed so that text-decoration |
| 1804 // property is always a CSSValueList. |
1774 const CSSValue* textDecoration = | 1805 const CSSValue* textDecoration = |
1775 style->getPropertyCSSValue(textDecorationPropertyForEditing()); | 1806 style->getPropertyCSSValue(textDecorationPropertyForEditing()); |
1776 if (textDecoration && textDecoration->isValueList()) { | 1807 if (textDecoration && textDecoration->isValueList()) { |
1777 DEFINE_STATIC_LOCAL(CSSIdentifierValue, underline, | 1808 DEFINE_STATIC_LOCAL(CSSIdentifierValue, underline, |
1778 (CSSIdentifierValue::create(CSSValueUnderline))); | 1809 (CSSIdentifierValue::create(CSSValueUnderline))); |
1779 DEFINE_STATIC_LOCAL(CSSIdentifierValue, lineThrough, | 1810 DEFINE_STATIC_LOCAL(CSSIdentifierValue, lineThrough, |
1780 (CSSIdentifierValue::create(CSSValueLineThrough))); | 1811 (CSSIdentifierValue::create(CSSValueLineThrough))); |
1781 CSSValueList* newTextDecoration = toCSSValueList(textDecoration)->copy(); | 1812 CSSValueList* newTextDecoration = toCSSValueList(textDecoration)->copy(); |
1782 if (newTextDecoration->removeAll(underline)) | 1813 if (newTextDecoration->removeAll(underline)) |
1783 m_applyUnderline = true; | 1814 m_applyUnderline = true; |
(...skipping 16 matching lines...) Expand all Loading... |
1800 m_applySuperscript = true; | 1831 m_applySuperscript = true; |
1801 break; | 1832 break; |
1802 } | 1833 } |
1803 | 1834 |
1804 if (style->getPropertyCSSValue(CSSPropertyColor)) { | 1835 if (style->getPropertyCSSValue(CSSPropertyColor)) { |
1805 m_applyFontColor = getFontColor(style).serialized(); | 1836 m_applyFontColor = getFontColor(style).serialized(); |
1806 style->removeProperty(CSSPropertyColor); | 1837 style->removeProperty(CSSPropertyColor); |
1807 } | 1838 } |
1808 | 1839 |
1809 m_applyFontFace = style->getPropertyValue(CSSPropertyFontFamily); | 1840 m_applyFontFace = style->getPropertyValue(CSSPropertyFontFamily); |
1810 // Remove double quotes for Outlook 2007 compatibility. See https://bugs.webki
t.org/show_bug.cgi?id=79448 | 1841 // Remove double quotes for Outlook 2007 compatibility. See |
| 1842 // https://bugs.webkit.org/show_bug.cgi?id=79448 |
1811 m_applyFontFace.replace('"', ""); | 1843 m_applyFontFace.replace('"', ""); |
1812 style->removeProperty(CSSPropertyFontFamily); | 1844 style->removeProperty(CSSPropertyFontFamily); |
1813 | 1845 |
1814 if (const CSSValue* fontSize = | 1846 if (const CSSValue* fontSize = |
1815 style->getPropertyCSSValue(CSSPropertyFontSize)) { | 1847 style->getPropertyCSSValue(CSSPropertyFontSize)) { |
1816 if (!fontSize->isPrimitiveValue() && !fontSize->isIdentifierValue()) { | 1848 if (!fontSize->isPrimitiveValue() && !fontSize->isIdentifierValue()) { |
1817 style->removeProperty( | 1849 // Can't make sense of the number. Put no font size. |
1818 CSSPropertyFontSize); // Can't make sense of the number. Put no font
size. | 1850 style->removeProperty(CSSPropertyFontSize); |
1819 } else if (int legacyFontSize = legacyFontSizeFromCSSValue( | 1851 } else if (int legacyFontSize = legacyFontSizeFromCSSValue( |
1820 document, fontSize, isMonospaceFont, | 1852 document, fontSize, isMonospaceFont, |
1821 UseLegacyFontSizeOnlyIfPixelValuesMatch)) { | 1853 UseLegacyFontSizeOnlyIfPixelValuesMatch)) { |
1822 m_applyFontSize = String::number(legacyFontSize); | 1854 m_applyFontSize = String::number(legacyFontSize); |
1823 style->removeProperty(CSSPropertyFontSize); | 1855 style->removeProperty(CSSPropertyFontSize); |
1824 } | 1856 } |
1825 } | 1857 } |
1826 } | 1858 } |
1827 | 1859 |
1828 static void diffTextDecorations(MutableStylePropertySet* style, | 1860 static void diffTextDecorations(MutableStylePropertySet* style, |
(...skipping 11 matching lines...) Expand all Loading... |
1840 for (size_t i = 0; i < valuesInRefTextDecoration->length(); i++) | 1872 for (size_t i = 0; i < valuesInRefTextDecoration->length(); i++) |
1841 newTextDecoration->removeAll(valuesInRefTextDecoration->item(i)); | 1873 newTextDecoration->removeAll(valuesInRefTextDecoration->item(i)); |
1842 | 1874 |
1843 setTextDecorationProperty(style, newTextDecoration, propertyID); | 1875 setTextDecorationProperty(style, newTextDecoration, propertyID); |
1844 } | 1876 } |
1845 | 1877 |
1846 static bool fontWeightIsBold(const CSSValue* fontWeight) { | 1878 static bool fontWeightIsBold(const CSSValue* fontWeight) { |
1847 if (!fontWeight->isIdentifierValue()) | 1879 if (!fontWeight->isIdentifierValue()) |
1848 return false; | 1880 return false; |
1849 | 1881 |
1850 // Because b tag can only bold text, there are only two states in plain html:
bold and not bold. | 1882 // Because b tag can only bold text, there are only two states in plain html: |
1851 // Collapse all other values to either one of these two states for editing pur
poses. | 1883 // bold and not bold. Collapse all other values to either one of these two |
| 1884 // states for editing purposes. |
1852 switch (toCSSIdentifierValue(fontWeight)->getValueID()) { | 1885 switch (toCSSIdentifierValue(fontWeight)->getValueID()) { |
1853 case CSSValue100: | 1886 case CSSValue100: |
1854 case CSSValue200: | 1887 case CSSValue200: |
1855 case CSSValue300: | 1888 case CSSValue300: |
1856 case CSSValue400: | 1889 case CSSValue400: |
1857 case CSSValue500: | 1890 case CSSValue500: |
1858 case CSSValueNormal: | 1891 case CSSValueNormal: |
1859 return false; | 1892 return false; |
1860 case CSSValueBold: | 1893 case CSSValueBold: |
1861 case CSSValue600: | 1894 case CSSValue600: |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1953 if (CSSPrimitiveValue::unitTypeToLengthUnitType( | 1986 if (CSSPrimitiveValue::unitTypeToLengthUnitType( |
1954 primitiveValue.typeWithCalcResolved(), lengthType) && | 1987 primitiveValue.typeWithCalcResolved(), lengthType) && |
1955 lengthType == CSSPrimitiveValue::UnitTypePixels) { | 1988 lengthType == CSSPrimitiveValue::UnitTypePixels) { |
1956 double conversion = | 1989 double conversion = |
1957 CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor( | 1990 CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor( |
1958 primitiveValue.typeWithCalcResolved()); | 1991 primitiveValue.typeWithCalcResolved()); |
1959 int pixelFontSize = | 1992 int pixelFontSize = |
1960 clampTo<int>(primitiveValue.getDoubleValue() * conversion); | 1993 clampTo<int>(primitiveValue.getDoubleValue() * conversion); |
1961 int legacyFontSize = | 1994 int legacyFontSize = |
1962 FontSize::legacyFontSize(document, pixelFontSize, isMonospaceFont); | 1995 FontSize::legacyFontSize(document, pixelFontSize, isMonospaceFont); |
1963 // Use legacy font size only if pixel value matches exactly to that of leg
acy font size. | 1996 // Use legacy font size only if pixel value matches exactly to that of |
| 1997 // legacy font size. |
1964 if (mode == AlwaysUseLegacyFontSize || | 1998 if (mode == AlwaysUseLegacyFontSize || |
1965 FontSize::fontSizeForKeyword(document, legacyFontSize, | 1999 FontSize::fontSizeForKeyword(document, legacyFontSize, |
1966 isMonospaceFont) == pixelFontSize) | 2000 isMonospaceFont) == pixelFontSize) |
1967 return legacyFontSize; | 2001 return legacyFontSize; |
1968 | 2002 |
1969 return 0; | 2003 return 0; |
1970 } | 2004 } |
1971 } | 2005 } |
1972 | 2006 |
1973 if (value->isIdentifierValue()) { | 2007 if (value->isIdentifierValue()) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2006 for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) { | 2040 for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) { |
2007 CSSComputedStyleDeclaration* ancestorStyle = | 2041 CSSComputedStyleDeclaration* ancestorStyle = |
2008 CSSComputedStyleDeclaration::create(ancestor); | 2042 CSSComputedStyleDeclaration::create(ancestor); |
2009 if (!hasTransparentBackgroundColor(ancestorStyle)) | 2043 if (!hasTransparentBackgroundColor(ancestorStyle)) |
2010 return ancestorStyle->getPropertyCSSValue(CSSPropertyBackgroundColor); | 2044 return ancestorStyle->getPropertyCSSValue(CSSPropertyBackgroundColor); |
2011 } | 2045 } |
2012 return nullptr; | 2046 return nullptr; |
2013 } | 2047 } |
2014 | 2048 |
2015 } // namespace blink | 2049 } // namespace blink |
OLD | NEW |