Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: third_party/WebKit/Source/core/editing/EditingStyle.cpp

Issue 2628943009: Introduce EditingStyleUtilities.{cpp,h} (Closed)
Patch Set: add STATIC_ONLY Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 30 matching lines...) Expand all
41 #include "core/css/StylePropertySet.h" 41 #include "core/css/StylePropertySet.h"
42 #include "core/css/StyleRule.h" 42 #include "core/css/StyleRule.h"
43 #include "core/css/parser/CSSParser.h" 43 #include "core/css/parser/CSSParser.h"
44 #include "core/css/resolver/StyleResolver.h" 44 #include "core/css/resolver/StyleResolver.h"
45 #include "core/dom/Document.h" 45 #include "core/dom/Document.h"
46 #include "core/dom/Element.h" 46 #include "core/dom/Element.h"
47 #include "core/dom/Node.h" 47 #include "core/dom/Node.h"
48 #include "core/dom/NodeComputedStyle.h" 48 #include "core/dom/NodeComputedStyle.h"
49 #include "core/dom/NodeTraversal.h" 49 #include "core/dom/NodeTraversal.h"
50 #include "core/dom/QualifiedName.h" 50 #include "core/dom/QualifiedName.h"
51 #include "core/editing/EditingStyleUtilities.h"
51 #include "core/editing/EditingUtilities.h" 52 #include "core/editing/EditingUtilities.h"
52 #include "core/editing/Editor.h" 53 #include "core/editing/Editor.h"
53 #include "core/editing/FrameSelection.h" 54 #include "core/editing/FrameSelection.h"
54 #include "core/editing/Position.h" 55 #include "core/editing/Position.h"
55 #include "core/editing/commands/ApplyStyleCommand.h" 56 #include "core/editing/commands/ApplyStyleCommand.h"
56 #include "core/editing/serializers/HTMLInterchange.h" 57 #include "core/editing/serializers/HTMLInterchange.h"
57 #include "core/frame/LocalFrame.h" 58 #include "core/frame/LocalFrame.h"
58 #include "core/html/HTMLFontElement.h" 59 #include "core/html/HTMLFontElement.h"
59 #include "core/html/HTMLSpanElement.h" 60 #include "core/html/HTMLSpanElement.h"
60 #include "core/layout/LayoutBox.h" 61 #include "core/layout/LayoutBox.h"
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 StylePropertySet* styleWithRedundantProperties, 159 StylePropertySet* styleWithRedundantProperties,
159 CSSStyleDeclaration* baseStyle); 160 CSSStyleDeclaration* baseStyle);
160 enum LegacyFontSizeMode { 161 enum LegacyFontSizeMode {
161 AlwaysUseLegacyFontSize, 162 AlwaysUseLegacyFontSize,
162 UseLegacyFontSizeOnlyIfPixelValuesMatch 163 UseLegacyFontSizeOnlyIfPixelValuesMatch
163 }; 164 };
164 static int legacyFontSizeFromCSSValue(Document*, 165 static int legacyFontSizeFromCSSValue(Document*,
165 const CSSValue*, 166 const CSSValue*,
166 bool, 167 bool,
167 LegacyFontSizeMode); 168 LegacyFontSizeMode);
168 static bool isTransparentColorValue(const CSSValue*);
169 static bool hasTransparentBackgroundColor(CSSStyleDeclaration*);
170 static bool hasTransparentBackgroundColor(StylePropertySet*);
171 static const CSSValue* backgroundColorValueInEffect(Node*);
172 static bool hasAncestorVerticalAlignStyle(Node&, CSSValueID);
173 169
174 class HTMLElementEquivalent : public GarbageCollected<HTMLElementEquivalent> { 170 class HTMLElementEquivalent : public GarbageCollected<HTMLElementEquivalent> {
175 public: 171 public:
176 static HTMLElementEquivalent* create(CSSPropertyID propertyID, 172 static HTMLElementEquivalent* create(CSSPropertyID propertyID,
177 CSSValueID primitiveValue, 173 CSSValueID primitiveValue,
178 const HTMLQualifiedName& tagName) { 174 const HTMLQualifiedName& tagName) {
179 return new HTMLElementEquivalent(propertyID, primitiveValue, tagName); 175 return new HTMLElementEquivalent(propertyID, primitiveValue, tagName);
180 } 176 }
181 177
182 virtual bool matches(const Element* element) const { 178 virtual bool matches(const Element* element) const {
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 return cssValueToColor( 422 return cssValueToColor(
427 style->getPropertyCSSValueInternal(CSSPropertyBackgroundColor)); 423 style->getPropertyCSSValueInternal(CSSPropertyBackgroundColor));
428 } 424 }
429 425
430 static inline Color getBackgroundColor(StylePropertySet* style) { 426 static inline Color getBackgroundColor(StylePropertySet* style) {
431 return cssValueToColor( 427 return cssValueToColor(
432 style->getPropertyCSSValue(CSSPropertyBackgroundColor)); 428 style->getPropertyCSSValue(CSSPropertyBackgroundColor));
433 } 429 }
434 430
435 static inline Color backgroundColorInEffect(Node* node) { 431 static inline Color backgroundColorInEffect(Node* node) {
436 return cssValueToColor(backgroundColorValueInEffect(node)); 432 return cssValueToColor(
433 EditingStyleUtilities::backgroundColorValueInEffect(node));
437 } 434 }
438 435
439 static int textAlignResolvingStartAndEnd(int textAlign, int direction) { 436 static int textAlignResolvingStartAndEnd(int textAlign, int direction) {
440 switch (textAlign) { 437 switch (textAlign) {
441 case CSSValueCenter: 438 case CSSValueCenter:
442 case CSSValueWebkitCenter: 439 case CSSValueWebkitCenter:
443 return CSSValueCenter; 440 return CSSValueCenter;
444 case CSSValueJustify: 441 case CSSValueJustify:
445 return CSSValueJustify; 442 return CSSValueJustify;
446 case CSSValueLeft: 443 case CSSValueLeft:
(...skipping 24 matching lines...) Expand all
471 node = node->parentNode(); 468 node = node->parentNode();
472 469
473 CSSComputedStyleDeclaration* computedStyleAtPosition = 470 CSSComputedStyleDeclaration* computedStyleAtPosition =
474 CSSComputedStyleDeclaration::create(node); 471 CSSComputedStyleDeclaration::create(node);
475 m_mutableStyle = 472 m_mutableStyle =
476 propertiesToInclude == AllProperties && computedStyleAtPosition 473 propertiesToInclude == AllProperties && computedStyleAtPosition
477 ? computedStyleAtPosition->copyProperties() 474 ? computedStyleAtPosition->copyProperties()
478 : editingStyleFromComputedStyle(computedStyleAtPosition); 475 : editingStyleFromComputedStyle(computedStyleAtPosition);
479 476
480 if (propertiesToInclude == EditingPropertiesInEffect) { 477 if (propertiesToInclude == EditingPropertiesInEffect) {
481 if (const CSSValue* value = backgroundColorValueInEffect(node)) 478 if (const CSSValue* value =
479 EditingStyleUtilities::backgroundColorValueInEffect(node))
482 m_mutableStyle->setProperty(CSSPropertyBackgroundColor, value->cssText()); 480 m_mutableStyle->setProperty(CSSPropertyBackgroundColor, value->cssText());
483 if (const CSSValue* value = computedStyleAtPosition->getPropertyCSSValue( 481 if (const CSSValue* value = computedStyleAtPosition->getPropertyCSSValue(
484 CSSPropertyWebkitTextDecorationsInEffect)) 482 CSSPropertyWebkitTextDecorationsInEffect))
485 m_mutableStyle->setProperty(CSSPropertyTextDecoration, value->cssText()); 483 m_mutableStyle->setProperty(CSSPropertyTextDecoration, value->cssText());
486 } 484 }
487 485
488 if (node && node->ensureComputedStyle()) { 486 if (node && node->ensureComputedStyle()) {
489 const ComputedStyle* computedStyle = node->ensureComputedStyle(); 487 const ComputedStyle* computedStyle = node->ensureComputedStyle();
490 removeInheritedColorsIfNeeded(computedStyle); 488 removeInheritedColorsIfNeeded(computedStyle);
491 replaceFontSizeByKeywordIfPossible(computedStyle, computedStyleAtPosition); 489 replaceFontSizeByKeywordIfPossible(computedStyle, computedStyleAtPosition);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 bool EditingStyle::textDirection(WritingDirection& writingDirection) const { 562 bool EditingStyle::textDirection(WritingDirection& writingDirection) const {
565 if (!m_mutableStyle) 563 if (!m_mutableStyle)
566 return false; 564 return false;
567 565
568 const CSSValue* unicodeBidi = 566 const CSSValue* unicodeBidi =
569 m_mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi); 567 m_mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi);
570 if (!unicodeBidi || !unicodeBidi->isIdentifierValue()) 568 if (!unicodeBidi || !unicodeBidi->isIdentifierValue())
571 return false; 569 return false;
572 570
573 CSSValueID unicodeBidiValue = toCSSIdentifierValue(unicodeBidi)->getValueID(); 571 CSSValueID unicodeBidiValue = toCSSIdentifierValue(unicodeBidi)->getValueID();
574 if (isEmbedOrIsolate(unicodeBidiValue)) { 572 if (EditingStyleUtilities::isEmbedOrIsolate(unicodeBidiValue)) {
575 const CSSValue* direction = 573 const CSSValue* direction =
576 m_mutableStyle->getPropertyCSSValue(CSSPropertyDirection); 574 m_mutableStyle->getPropertyCSSValue(CSSPropertyDirection);
577 if (!direction || !direction->isIdentifierValue()) 575 if (!direction || !direction->isIdentifierValue())
578 return false; 576 return false;
579 577
580 writingDirection = 578 writingDirection =
581 toCSSIdentifierValue(direction)->getValueID() == CSSValueLtr 579 toCSSIdentifierValue(direction)->getValueID() == CSSValueLtr
582 ? LeftToRightWritingDirection 580 ? LeftToRightWritingDirection
583 : RightToLeftWritingDirection; 581 : RightToLeftWritingDirection;
584 582
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 WTF_ARRAY_LENGTH(textOnlyProperties)); 765 WTF_ARRAY_LENGTH(textOnlyProperties));
768 766
769 if (difference->isEmpty()) 767 if (difference->isEmpty())
770 return TrueTriState; 768 return TrueTriState;
771 if (difference->propertyCount() == m_mutableStyle->propertyCount()) 769 if (difference->propertyCount() == m_mutableStyle->propertyCount())
772 return FalseTriState; 770 return FalseTriState;
773 771
774 return MixedTriState; 772 return MixedTriState;
775 } 773 }
776 774
777 static bool hasAncestorVerticalAlignStyle(Node& node, CSSValueID value) {
778 for (Node& runner : NodeTraversal::inclusiveAncestorsOf(node)) {
779 CSSComputedStyleDeclaration* ancestorStyle =
780 CSSComputedStyleDeclaration::create(&runner);
781 if (getIdentifierValue(ancestorStyle, CSSPropertyVerticalAlign) == value)
782 return true;
783 }
784 return false;
785 }
786
787 TriState EditingStyle::triStateOfStyle( 775 TriState EditingStyle::triStateOfStyle(
788 const VisibleSelection& selection) const { 776 const VisibleSelection& selection) const {
789 if (selection.isNone()) 777 if (selection.isNone())
790 return FalseTriState; 778 return FalseTriState;
791 779
792 if (selection.isCaret()) 780 if (selection.isCaret()) {
793 return triStateOfStyle(EditingStyle::styleAtSelectionStart(selection)); 781 return triStateOfStyle(
782 EditingStyleUtilities::createStyleAtSelectionStart(selection));
783 }
794 784
795 TriState state = FalseTriState; 785 TriState state = FalseTriState;
796 bool nodeIsStart = true; 786 bool nodeIsStart = true;
797 for (Node& node : NodeTraversal::startsAt(*selection.start().anchorNode())) { 787 for (Node& node : NodeTraversal::startsAt(*selection.start().anchorNode())) {
798 if (node.layoutObject() && hasEditableStyle(node)) { 788 if (node.layoutObject() && hasEditableStyle(node)) {
799 CSSComputedStyleDeclaration* nodeStyle = 789 CSSComputedStyleDeclaration* nodeStyle =
800 CSSComputedStyleDeclaration::create(&node); 790 CSSComputedStyleDeclaration::create(&node);
801 if (nodeStyle) { 791 if (nodeStyle) {
802 // If the selected element has <sub> or <sup> ancestor element, apply 792 // If the selected element has <sub> or <sup> ancestor element, apply
803 // the corresponding style(vertical-align) to it so that 793 // the corresponding style(vertical-align) to it so that
804 // document.queryCommandState() works with the style. See bug 794 // document.queryCommandState() works with the style. See bug
805 // http://crbug.com/582225. 795 // http://crbug.com/582225.
806 if (m_isVerticalAlign && 796 if (m_isVerticalAlign &&
807 getIdentifierValue(nodeStyle, CSSPropertyVerticalAlign) == 797 getIdentifierValue(nodeStyle, CSSPropertyVerticalAlign) ==
808 CSSValueBaseline) { 798 CSSValueBaseline) {
809 const CSSIdentifierValue* verticalAlign = toCSSIdentifierValue( 799 const CSSIdentifierValue* verticalAlign = toCSSIdentifierValue(
810 m_mutableStyle->getPropertyCSSValue(CSSPropertyVerticalAlign)); 800 m_mutableStyle->getPropertyCSSValue(CSSPropertyVerticalAlign));
811 if (hasAncestorVerticalAlignStyle(node, verticalAlign->getValueID())) 801 if (EditingStyleUtilities::hasAncestorVerticalAlignStyle(
802 node, verticalAlign->getValueID()))
812 node.mutableComputedStyle()->setVerticalAlign( 803 node.mutableComputedStyle()->setVerticalAlign(
813 verticalAlign->convertTo<EVerticalAlign>()); 804 verticalAlign->convertTo<EVerticalAlign>());
814 } 805 }
815 806
816 // Pass EditingStyle::DoNotIgnoreTextOnlyProperties without checking if 807 // Pass EditingStyle::DoNotIgnoreTextOnlyProperties without checking if
817 // node.isTextNode() because the node can be an element node. See bug 808 // node.isTextNode() because the node can be an element node. See bug
818 // http://crbug.com/584939. 809 // http://crbug.com/584939.
819 TriState nodeState = triStateOfStyle( 810 TriState nodeState = triStateOfStyle(
820 nodeStyle, EditingStyle::DoNotIgnoreTextOnlyProperties); 811 nodeStyle, EditingStyle::DoNotIgnoreTextOnlyProperties);
821 if (nodeIsStart) { 812 if (nodeIsStart) {
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 1115
1125 m_mutableStyle->removeEquivalentProperties(styleAtPosition); 1116 m_mutableStyle->removeEquivalentProperties(styleAtPosition);
1126 1117
1127 if (textAlignResolvingStartAndEnd(m_mutableStyle.get()) == 1118 if (textAlignResolvingStartAndEnd(m_mutableStyle.get()) ==
1128 textAlignResolvingStartAndEnd(styleAtPosition)) 1119 textAlignResolvingStartAndEnd(styleAtPosition))
1129 m_mutableStyle->removeProperty(CSSPropertyTextAlign); 1120 m_mutableStyle->removeProperty(CSSPropertyTextAlign);
1130 1121
1131 if (getFontColor(m_mutableStyle.get()) == getFontColor(styleAtPosition)) 1122 if (getFontColor(m_mutableStyle.get()) == getFontColor(styleAtPosition))
1132 m_mutableStyle->removeProperty(CSSPropertyColor); 1123 m_mutableStyle->removeProperty(CSSPropertyColor);
1133 1124
1134 if (hasTransparentBackgroundColor(m_mutableStyle.get()) || 1125 if (EditingStyleUtilities::hasTransparentBackgroundColor(
1126 m_mutableStyle.get()) ||
1135 cssValueToColor( 1127 cssValueToColor(
1136 m_mutableStyle->getPropertyCSSValue(CSSPropertyBackgroundColor)) == 1128 m_mutableStyle->getPropertyCSSValue(CSSPropertyBackgroundColor)) ==
1137 backgroundColorInEffect(position.computeContainerNode())) 1129 backgroundColorInEffect(position.computeContainerNode()))
1138 m_mutableStyle->removeProperty(CSSPropertyBackgroundColor); 1130 m_mutableStyle->removeProperty(CSSPropertyBackgroundColor);
1139 1131
1140 if (unicodeBidi && unicodeBidi->isIdentifierValue()) { 1132 if (unicodeBidi && unicodeBidi->isIdentifierValue()) {
1141 m_mutableStyle->setProperty( 1133 m_mutableStyle->setProperty(
1142 CSSPropertyUnicodeBidi, 1134 CSSPropertyUnicodeBidi,
1143 toCSSIdentifierValue(unicodeBidi)->getValueID()); 1135 toCSSIdentifierValue(unicodeBidi)->getValueID());
1144 if (direction && direction->isIdentifierValue()) { 1136 if (direction && direction->isIdentifierValue()) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1240 htmlAttributeEquivalents(); 1232 htmlAttributeEquivalents();
1241 for (const auto& attribute : attributeEquivalents) { 1233 for (const auto& attribute : attributeEquivalents) {
1242 if (attribute->attributeName() == HTMLNames::dirAttr) 1234 if (attribute->attributeName() == HTMLNames::dirAttr)
1243 continue; // We don't want to include directionality 1235 continue; // We don't want to include directionality
1244 if (elementMatchesAndPropertyIsNotInInlineStyleDecl( 1236 if (elementMatchesAndPropertyIsNotInInlineStyleDecl(
1245 attribute.get(), element, mode, m_mutableStyle.get())) 1237 attribute.get(), element, mode, m_mutableStyle.get()))
1246 attribute->addToStyle(element, this); 1238 attribute->addToStyle(element, this);
1247 } 1239 }
1248 } 1240 }
1249 1241
1250 EditingStyle* EditingStyle::wrappingStyleForAnnotatedSerialization(
1251 ContainerNode* context) {
1252 EditingStyle* wrappingStyle =
1253 EditingStyle::create(context, EditingStyle::EditingPropertiesInEffect);
1254
1255 // Styles that Mail blockquotes contribute should only be placed on the Mail
1256 // blockquote, to help us differentiate those styles from ones that the user
1257 // has applied. This helps us get the color of content pasted into
1258 // blockquotes right.
1259 wrappingStyle->removeStyleAddedByElement(toHTMLElement(enclosingNodeOfType(
1260 firstPositionInOrBeforeNode(context), isMailHTMLBlockquoteElement,
1261 CanCrossEditingBoundary)));
1262
1263 // Call collapseTextDecorationProperties first or otherwise it'll copy the
1264 // value over from in-effect to text-decorations.
1265 wrappingStyle->collapseTextDecorationProperties();
1266
1267 return wrappingStyle;
1268 }
1269
1270 EditingStyle* EditingStyle::wrappingStyleForSerialization(
1271 ContainerNode* context) {
1272 DCHECK(context);
1273 EditingStyle* wrappingStyle = EditingStyle::create();
1274
1275 // When not annotating for interchange, we only preserve inline style
1276 // declarations.
1277 for (Node& node : NodeTraversal::inclusiveAncestorsOf(*context)) {
1278 if (node.isDocumentNode())
1279 break;
1280 if (node.isStyledElement() && !isMailHTMLBlockquoteElement(&node)) {
1281 wrappingStyle->mergeInlineAndImplicitStyleOfElement(
1282 toElement(&node), EditingStyle::DoNotOverrideValues,
1283 EditingStyle::EditingPropertiesInEffect);
1284 }
1285 }
1286
1287 return wrappingStyle;
1288 }
1289 1242
1290 static const CSSValueList& mergeTextDecorationValues( 1243 static const CSSValueList& mergeTextDecorationValues(
1291 const CSSValueList& mergedValue, 1244 const CSSValueList& mergedValue,
1292 const CSSValueList& valueToMerge) { 1245 const CSSValueList& valueToMerge) {
1293 DEFINE_STATIC_LOCAL(CSSIdentifierValue, underline, 1246 DEFINE_STATIC_LOCAL(CSSIdentifierValue, underline,
1294 (CSSIdentifierValue::create(CSSValueUnderline))); 1247 (CSSIdentifierValue::create(CSSValueUnderline)));
1295 DEFINE_STATIC_LOCAL(CSSIdentifierValue, lineThrough, 1248 DEFINE_STATIC_LOCAL(CSSIdentifierValue, lineThrough,
1296 (CSSIdentifierValue::create(CSSValueLineThrough))); 1249 (CSSIdentifierValue::create(CSSValueLineThrough)));
1297 CSSValueList& result = *mergedValue.copy(); 1250 CSSValueList& result = *mergedValue.copy();
1298 if (valueToMerge.hasValue(underline) && !mergedValue.hasValue(underline)) 1251 if (valueToMerge.hasValue(underline) && !mergedValue.hasValue(underline))
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1516 int EditingStyle::legacyFontSize(Document* document) const { 1469 int EditingStyle::legacyFontSize(Document* document) const {
1517 const CSSValue* cssValue = 1470 const CSSValue* cssValue =
1518 m_mutableStyle->getPropertyCSSValue(CSSPropertyFontSize); 1471 m_mutableStyle->getPropertyCSSValue(CSSPropertyFontSize);
1519 if (!cssValue || 1472 if (!cssValue ||
1520 !(cssValue->isPrimitiveValue() || cssValue->isIdentifierValue())) 1473 !(cssValue->isPrimitiveValue() || cssValue->isIdentifierValue()))
1521 return 0; 1474 return 0;
1522 return legacyFontSizeFromCSSValue(document, cssValue, m_isMonospaceFont, 1475 return legacyFontSizeFromCSSValue(document, cssValue, m_isMonospaceFont,
1523 AlwaysUseLegacyFontSize); 1476 AlwaysUseLegacyFontSize);
1524 } 1477 }
1525 1478
1526 EditingStyle* EditingStyle::styleAtSelectionStart(
1527 const VisibleSelection& selection,
1528 bool shouldUseBackgroundColorInEffect,
1529 MutableStylePropertySet* styleToCheck) {
1530 if (selection.isNone())
1531 return nullptr;
1532
1533 Document& document = *selection.start().document();
1534
1535 DCHECK(!document.needsLayoutTreeUpdate());
1536 DocumentLifecycle::DisallowTransitionScope disallowTransition(
1537 document.lifecycle());
1538
1539 Position position = adjustedSelectionStartForStyleComputation(selection);
1540
1541 // If the pos is at the end of a text node, then this node is not fully
1542 // selected. Move it to the next deep equivalent position to avoid removing
1543 // the style from this node.
1544 // e.g. if pos was at Position("hello", 5) in <b>hello<div>world</div></b>, we
1545 // want Position("world", 0) instead.
1546 // We only do this for range because caret at Position("hello", 5) in
1547 // <b>hello</b>world should give you font-weight: bold.
1548 Node* positionNode = position.computeContainerNode();
1549 if (selection.isRange() && positionNode && positionNode->isTextNode() &&
1550 position.computeOffsetInContainerNode() ==
1551 positionNode->maxCharacterOffset())
1552 position = nextVisuallyDistinctCandidate(position);
1553
1554 Element* element = associatedElementOf(position);
1555 if (!element)
1556 return nullptr;
1557
1558 EditingStyle* style =
1559 EditingStyle::create(element, EditingStyle::AllProperties);
1560 style->mergeTypingStyle(&element->document());
1561
1562 // If |element| has <sub> or <sup> ancestor element, apply the corresponding
1563 // style(vertical-align) to it so that document.queryCommandState() works with
1564 // the style. See bug http://crbug.com/582225.
1565 CSSValueID valueID =
1566 getIdentifierValue(styleToCheck, CSSPropertyVerticalAlign);
1567 if (valueID == CSSValueSub || valueID == CSSValueSuper) {
1568 CSSComputedStyleDeclaration* elementStyle =
1569 CSSComputedStyleDeclaration::create(element);
1570 // Find the ancestor that has CSSValueSub or CSSValueSuper as the value of
1571 // CSS vertical-align property.
1572 if (getIdentifierValue(elementStyle, CSSPropertyVerticalAlign) ==
1573 CSSValueBaseline &&
1574 hasAncestorVerticalAlignStyle(*element, valueID))
1575 style->m_mutableStyle->setProperty(CSSPropertyVerticalAlign, valueID);
1576 }
1577
1578 // If background color is transparent, traverse parent nodes until we hit a
1579 // different value or document root Also, if the selection is a range, ignore
1580 // the background color at the start of selection, and find the background
1581 // color of the common ancestor.
1582 if (shouldUseBackgroundColorInEffect &&
1583 (selection.isRange() ||
1584 hasTransparentBackgroundColor(style->m_mutableStyle.get()))) {
1585 const EphemeralRange range(selection.toNormalizedEphemeralRange());
1586 if (const CSSValue* value =
1587 backgroundColorValueInEffect(Range::commonAncestorContainer(
1588 range.startPosition().computeContainerNode(),
1589 range.endPosition().computeContainerNode())))
1590 style->setProperty(CSSPropertyBackgroundColor, value->cssText());
1591 }
1592
1593 return style;
1594 }
1595
1596 static bool isUnicodeBidiNestedOrMultipleEmbeddings(CSSValueID valueID) {
1597 return valueID == CSSValueEmbed || valueID == CSSValueBidiOverride ||
1598 valueID == CSSValueWebkitIsolate ||
1599 valueID == CSSValueWebkitIsolateOverride ||
1600 valueID == CSSValueWebkitPlaintext || valueID == CSSValueIsolate ||
1601 valueID == CSSValueIsolateOverride || valueID == CSSValuePlaintext;
1602 }
1603
1604 WritingDirection EditingStyle::textDirectionForSelection(
1605 const VisibleSelection& selection,
1606 EditingStyle* typingStyle,
1607 bool& hasNestedOrMultipleEmbeddings) {
1608 hasNestedOrMultipleEmbeddings = true;
1609
1610 if (selection.isNone())
1611 return NaturalWritingDirection;
1612
1613 Position position = mostForwardCaretPosition(selection.start());
1614
1615 Node* node = position.anchorNode();
1616 if (!node)
1617 return NaturalWritingDirection;
1618
1619 Position end;
1620 if (selection.isRange()) {
1621 end = mostBackwardCaretPosition(selection.end());
1622
1623 DCHECK(end.document());
1624 const EphemeralRange caretRange(position.parentAnchoredEquivalent(),
1625 end.parentAnchoredEquivalent());
1626 for (Node& n : caretRange.nodes()) {
1627 if (!n.isStyledElement())
1628 continue;
1629
1630 CSSComputedStyleDeclaration* style =
1631 CSSComputedStyleDeclaration::create(&n);
1632 const CSSValue* unicodeBidi =
1633 style->getPropertyCSSValue(CSSPropertyUnicodeBidi);
1634 if (!unicodeBidi || !unicodeBidi->isIdentifierValue())
1635 continue;
1636
1637 CSSValueID unicodeBidiValue =
1638 toCSSIdentifierValue(unicodeBidi)->getValueID();
1639 if (isUnicodeBidiNestedOrMultipleEmbeddings(unicodeBidiValue))
1640 return NaturalWritingDirection;
1641 }
1642 }
1643
1644 if (selection.isCaret()) {
1645 WritingDirection direction;
1646 if (typingStyle && typingStyle->textDirection(direction)) {
1647 hasNestedOrMultipleEmbeddings = false;
1648 return direction;
1649 }
1650 node = selection.visibleStart().deepEquivalent().anchorNode();
1651 }
1652 DCHECK(node);
1653
1654 // The selection is either a caret with no typing attributes or a range in
1655 // which no embedding is added, so just use the start position to decide.
1656 Node* block = enclosingBlock(node);
1657 WritingDirection foundDirection = NaturalWritingDirection;
1658
1659 for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*node)) {
1660 if (runner == block)
1661 break;
1662 if (!runner.isStyledElement())
1663 continue;
1664
1665 Element* element = &toElement(runner);
1666 CSSComputedStyleDeclaration* style =
1667 CSSComputedStyleDeclaration::create(element);
1668 const CSSValue* unicodeBidi =
1669 style->getPropertyCSSValue(CSSPropertyUnicodeBidi);
1670 if (!unicodeBidi || !unicodeBidi->isIdentifierValue())
1671 continue;
1672
1673 CSSValueID unicodeBidiValue =
1674 toCSSIdentifierValue(unicodeBidi)->getValueID();
1675 if (unicodeBidiValue == CSSValueNormal)
1676 continue;
1677
1678 if (unicodeBidiValue == CSSValueBidiOverride)
1679 return NaturalWritingDirection;
1680
1681 DCHECK(isEmbedOrIsolate(unicodeBidiValue)) << unicodeBidiValue;
1682 const CSSValue* direction =
1683 style->getPropertyCSSValue(CSSPropertyDirection);
1684 if (!direction || !direction->isIdentifierValue())
1685 continue;
1686
1687 int directionValue = toCSSIdentifierValue(direction)->getValueID();
1688 if (directionValue != CSSValueLtr && directionValue != CSSValueRtl)
1689 continue;
1690
1691 if (foundDirection != NaturalWritingDirection)
1692 return NaturalWritingDirection;
1693
1694 // In the range case, make sure that the embedding element persists until
1695 // the end of the range.
1696 if (selection.isRange() && !end.anchorNode()->isDescendantOf(element))
1697 return NaturalWritingDirection;
1698
1699 foundDirection = directionValue == CSSValueLtr
1700 ? LeftToRightWritingDirection
1701 : RightToLeftWritingDirection;
1702 }
1703 hasNestedOrMultipleEmbeddings = false;
1704 return foundDirection;
1705 }
1706
1707 DEFINE_TRACE(EditingStyle) { 1479 DEFINE_TRACE(EditingStyle) {
1708 visitor->trace(m_mutableStyle); 1480 visitor->trace(m_mutableStyle);
1709 } 1481 }
1710 1482
1711 static void reconcileTextDecorationProperties(MutableStylePropertySet* style) { 1483 static void reconcileTextDecorationProperties(MutableStylePropertySet* style) {
1712 const CSSValue* textDecorationsInEffect = 1484 const CSSValue* textDecorationsInEffect =
1713 style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect); 1485 style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
1714 const CSSValue* textDecoration = 1486 const CSSValue* textDecoration =
1715 style->getPropertyCSSValue(textDecorationPropertyForEditing()); 1487 style->getPropertyCSSValue(textDecorationPropertyForEditing());
1716 // "LayoutTests/editing/execCommand/insert-list-and-strikethrough.html" makes 1488 // "LayoutTests/editing/execCommand/insert-list-and-strikethrough.html" makes
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
2007 if (value->isIdentifierValue()) { 1779 if (value->isIdentifierValue()) {
2008 const CSSIdentifierValue& identifierValue = toCSSIdentifierValue(*value); 1780 const CSSIdentifierValue& identifierValue = toCSSIdentifierValue(*value);
2009 if (CSSValueXSmall <= identifierValue.getValueID() && 1781 if (CSSValueXSmall <= identifierValue.getValueID() &&
2010 identifierValue.getValueID() <= CSSValueWebkitXxxLarge) 1782 identifierValue.getValueID() <= CSSValueWebkitXxxLarge)
2011 return identifierValue.getValueID() - CSSValueXSmall + 1; 1783 return identifierValue.getValueID() - CSSValueXSmall + 1;
2012 } 1784 }
2013 1785
2014 return 0; 1786 return 0;
2015 } 1787 }
2016 1788
2017 bool isTransparentColorValue(const CSSValue* cssValue) {
2018 if (!cssValue)
2019 return true;
2020 if (cssValue->isColorValue())
2021 return !toCSSColorValue(cssValue)->value().alpha();
2022 if (!cssValue->isIdentifierValue())
2023 return false;
2024 return toCSSIdentifierValue(cssValue)->getValueID() == CSSValueTransparent;
2025 }
2026
2027 bool hasTransparentBackgroundColor(CSSStyleDeclaration* style) {
2028 const CSSValue* cssValue =
2029 style->getPropertyCSSValueInternal(CSSPropertyBackgroundColor);
2030 return isTransparentColorValue(cssValue);
2031 }
2032
2033 bool hasTransparentBackgroundColor(StylePropertySet* style) {
2034 const CSSValue* cssValue =
2035 style->getPropertyCSSValue(CSSPropertyBackgroundColor);
2036 return isTransparentColorValue(cssValue);
2037 }
2038
2039 const CSSValue* backgroundColorValueInEffect(Node* node) {
2040 for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) {
2041 CSSComputedStyleDeclaration* ancestorStyle =
2042 CSSComputedStyleDeclaration::create(ancestor);
2043 if (!hasTransparentBackgroundColor(ancestorStyle))
2044 return ancestorStyle->getPropertyCSSValue(CSSPropertyBackgroundColor);
2045 }
2046 return nullptr;
2047 }
2048
2049 } // namespace blink 1789 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/EditingStyle.h ('k') | third_party/WebKit/Source/core/editing/EditingStyleUtilities.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698