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

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

Issue 2692553002: Remove the methods of EditingStyle class moved to EditingStyleUtilities class (Closed)
Patch Set: Created 3 years, 10 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
« no previous file with comments | « third_party/WebKit/Source/core/editing/EditingStyle.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 StylePropertySet* styleWithRedundantProperties, 159 StylePropertySet* styleWithRedundantProperties,
160 CSSStyleDeclaration* baseStyle); 160 CSSStyleDeclaration* baseStyle);
161 enum LegacyFontSizeMode { 161 enum LegacyFontSizeMode {
162 AlwaysUseLegacyFontSize, 162 AlwaysUseLegacyFontSize,
163 UseLegacyFontSizeOnlyIfPixelValuesMatch 163 UseLegacyFontSizeOnlyIfPixelValuesMatch
164 }; 164 };
165 static int legacyFontSizeFromCSSValue(Document*, 165 static int legacyFontSizeFromCSSValue(Document*,
166 const CSSValue*, 166 const CSSValue*,
167 bool, 167 bool,
168 LegacyFontSizeMode); 168 LegacyFontSizeMode);
169 static bool isTransparentColorValue(const CSSValue*);
170 static bool hasTransparentBackgroundColor(CSSStyleDeclaration*);
171 static bool hasTransparentBackgroundColor(StylePropertySet*);
172 static const CSSValue* backgroundColorValueInEffect(Node*);
173 static bool hasAncestorVerticalAlignStyle(Node&, CSSValueID);
174 169
175 class HTMLElementEquivalent : public GarbageCollected<HTMLElementEquivalent> { 170 class HTMLElementEquivalent : public GarbageCollected<HTMLElementEquivalent> {
176 public: 171 public:
177 static HTMLElementEquivalent* create(CSSPropertyID propertyID, 172 static HTMLElementEquivalent* create(CSSPropertyID propertyID,
178 CSSValueID primitiveValue, 173 CSSValueID primitiveValue,
179 const HTMLQualifiedName& tagName) { 174 const HTMLQualifiedName& tagName) {
180 return new HTMLElementEquivalent(propertyID, primitiveValue, tagName); 175 return new HTMLElementEquivalent(propertyID, primitiveValue, tagName);
181 } 176 }
182 177
183 virtual bool matches(const Element* element) const { 178 virtual bool matches(const Element* element) const {
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 WTF_ARRAY_LENGTH(textOnlyProperties)); 765 WTF_ARRAY_LENGTH(textOnlyProperties));
771 766
772 if (difference->isEmpty()) 767 if (difference->isEmpty())
773 return TrueTriState; 768 return TrueTriState;
774 if (difference->propertyCount() == m_mutableStyle->propertyCount()) 769 if (difference->propertyCount() == m_mutableStyle->propertyCount())
775 return FalseTriState; 770 return FalseTriState;
776 771
777 return MixedTriState; 772 return MixedTriState;
778 } 773 }
779 774
780 static bool hasAncestorVerticalAlignStyle(Node& node, CSSValueID value) {
781 for (Node& runner : NodeTraversal::inclusiveAncestorsOf(node)) {
782 CSSComputedStyleDeclaration* ancestorStyle =
783 CSSComputedStyleDeclaration::create(&runner);
784 if (getIdentifierValue(ancestorStyle, CSSPropertyVerticalAlign) == value)
785 return true;
786 }
787 return false;
788 }
789
790 TriState EditingStyle::triStateOfStyle( 775 TriState EditingStyle::triStateOfStyle(
791 const VisibleSelection& selection) const { 776 const VisibleSelection& selection) const {
792 if (selection.isNone()) 777 if (selection.isNone())
793 return FalseTriState; 778 return FalseTriState;
794 779
795 if (selection.isCaret()) { 780 if (selection.isCaret()) {
796 return triStateOfStyle( 781 return triStateOfStyle(
797 EditingStyleUtilities::createStyleAtSelectionStart(selection)); 782 EditingStyleUtilities::createStyleAtSelectionStart(selection));
798 } 783 }
799 784
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
1247 htmlAttributeEquivalents(); 1232 htmlAttributeEquivalents();
1248 for (const auto& attribute : attributeEquivalents) { 1233 for (const auto& attribute : attributeEquivalents) {
1249 if (attribute->attributeName() == HTMLNames::dirAttr) 1234 if (attribute->attributeName() == HTMLNames::dirAttr)
1250 continue; // We don't want to include directionality 1235 continue; // We don't want to include directionality
1251 if (elementMatchesAndPropertyIsNotInInlineStyleDecl( 1236 if (elementMatchesAndPropertyIsNotInInlineStyleDecl(
1252 attribute.get(), element, mode, m_mutableStyle.get())) 1237 attribute.get(), element, mode, m_mutableStyle.get()))
1253 attribute->addToStyle(element, this); 1238 attribute->addToStyle(element, this);
1254 } 1239 }
1255 } 1240 }
1256 1241
1257 EditingStyle* EditingStyle::wrappingStyleForAnnotatedSerialization(
1258 ContainerNode* context) {
1259 EditingStyle* wrappingStyle =
1260 EditingStyle::create(context, EditingStyle::EditingPropertiesInEffect);
1261
1262 // Styles that Mail blockquotes contribute should only be placed on the Mail
1263 // blockquote, to help us differentiate those styles from ones that the user
1264 // has applied. This helps us get the color of content pasted into
1265 // blockquotes right.
1266 wrappingStyle->removeStyleAddedByElement(toHTMLElement(enclosingNodeOfType(
1267 firstPositionInOrBeforeNode(context), isMailHTMLBlockquoteElement,
1268 CanCrossEditingBoundary)));
1269
1270 // Call collapseTextDecorationProperties first or otherwise it'll copy the
1271 // value over from in-effect to text-decorations.
1272 wrappingStyle->collapseTextDecorationProperties();
1273
1274 return wrappingStyle;
1275 }
1276
1277 EditingStyle* EditingStyle::wrappingStyleForSerialization(
1278 ContainerNode* context) {
1279 DCHECK(context);
1280 EditingStyle* wrappingStyle = EditingStyle::create();
1281
1282 // When not annotating for interchange, we only preserve inline style
1283 // declarations.
1284 for (Node& node : NodeTraversal::inclusiveAncestorsOf(*context)) {
1285 if (node.isDocumentNode())
1286 break;
1287 if (node.isStyledElement() && !isMailHTMLBlockquoteElement(&node)) {
1288 wrappingStyle->mergeInlineAndImplicitStyleOfElement(
1289 toElement(&node), EditingStyle::DoNotOverrideValues,
1290 EditingStyle::EditingPropertiesInEffect);
1291 }
1292 }
1293
1294 return wrappingStyle;
1295 }
1296
1297 static const CSSValueList& mergeTextDecorationValues( 1242 static const CSSValueList& mergeTextDecorationValues(
1298 const CSSValueList& mergedValue, 1243 const CSSValueList& mergedValue,
1299 const CSSValueList& valueToMerge) { 1244 const CSSValueList& valueToMerge) {
1300 DEFINE_STATIC_LOCAL(CSSIdentifierValue, underline, 1245 DEFINE_STATIC_LOCAL(CSSIdentifierValue, underline,
1301 (CSSIdentifierValue::create(CSSValueUnderline))); 1246 (CSSIdentifierValue::create(CSSValueUnderline)));
1302 DEFINE_STATIC_LOCAL(CSSIdentifierValue, lineThrough, 1247 DEFINE_STATIC_LOCAL(CSSIdentifierValue, lineThrough,
1303 (CSSIdentifierValue::create(CSSValueLineThrough))); 1248 (CSSIdentifierValue::create(CSSValueLineThrough)));
1304 CSSValueList& result = *mergedValue.copy(); 1249 CSSValueList& result = *mergedValue.copy();
1305 if (valueToMerge.hasValue(underline) && !mergedValue.hasValue(underline)) 1250 if (valueToMerge.hasValue(underline) && !mergedValue.hasValue(underline))
1306 result.append(underline); 1251 result.append(underline);
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
1523 int EditingStyle::legacyFontSize(Document* document) const { 1468 int EditingStyle::legacyFontSize(Document* document) const {
1524 const CSSValue* cssValue = 1469 const CSSValue* cssValue =
1525 m_mutableStyle->getPropertyCSSValue(CSSPropertyFontSize); 1470 m_mutableStyle->getPropertyCSSValue(CSSPropertyFontSize);
1526 if (!cssValue || 1471 if (!cssValue ||
1527 !(cssValue->isPrimitiveValue() || cssValue->isIdentifierValue())) 1472 !(cssValue->isPrimitiveValue() || cssValue->isIdentifierValue()))
1528 return 0; 1473 return 0;
1529 return legacyFontSizeFromCSSValue(document, cssValue, m_isMonospaceFont, 1474 return legacyFontSizeFromCSSValue(document, cssValue, m_isMonospaceFont,
1530 AlwaysUseLegacyFontSize); 1475 AlwaysUseLegacyFontSize);
1531 } 1476 }
1532 1477
1533 EditingStyle* EditingStyle::styleAtSelectionStart(
1534 const VisibleSelection& selection,
1535 bool shouldUseBackgroundColorInEffect,
1536 MutableStylePropertySet* styleToCheck) {
1537 if (selection.isNone())
1538 return nullptr;
1539
1540 Document& document = *selection.start().document();
1541
1542 DCHECK(!document.needsLayoutTreeUpdate());
1543 DocumentLifecycle::DisallowTransitionScope disallowTransition(
1544 document.lifecycle());
1545
1546 Position position = adjustedSelectionStartForStyleComputation(selection);
1547
1548 // If the pos is at the end of a text node, then this node is not fully
1549 // selected. Move it to the next deep equivalent position to avoid removing
1550 // the style from this node.
1551 // e.g. if pos was at Position("hello", 5) in <b>hello<div>world</div></b>, we
1552 // want Position("world", 0) instead.
1553 // We only do this for range because caret at Position("hello", 5) in
1554 // <b>hello</b>world should give you font-weight: bold.
1555 Node* positionNode = position.computeContainerNode();
1556 if (selection.isRange() && positionNode && positionNode->isTextNode() &&
1557 position.computeOffsetInContainerNode() ==
1558 positionNode->maxCharacterOffset())
1559 position = nextVisuallyDistinctCandidate(position);
1560
1561 Element* element = associatedElementOf(position);
1562 if (!element)
1563 return nullptr;
1564
1565 EditingStyle* style =
1566 EditingStyle::create(element, EditingStyle::AllProperties);
1567 style->mergeTypingStyle(&element->document());
1568
1569 // If |element| has <sub> or <sup> ancestor element, apply the corresponding
1570 // style(vertical-align) to it so that document.queryCommandState() works with
1571 // the style. See bug http://crbug.com/582225.
1572 CSSValueID valueID =
1573 getIdentifierValue(styleToCheck, CSSPropertyVerticalAlign);
1574 if (valueID == CSSValueSub || valueID == CSSValueSuper) {
1575 CSSComputedStyleDeclaration* elementStyle =
1576 CSSComputedStyleDeclaration::create(element);
1577 // Find the ancestor that has CSSValueSub or CSSValueSuper as the value of
1578 // CSS vertical-align property.
1579 if (getIdentifierValue(elementStyle, CSSPropertyVerticalAlign) ==
1580 CSSValueBaseline &&
1581 hasAncestorVerticalAlignStyle(*element, valueID))
1582 style->m_mutableStyle->setProperty(CSSPropertyVerticalAlign, valueID);
1583 }
1584
1585 // If background color is transparent, traverse parent nodes until we hit a
1586 // different value or document root Also, if the selection is a range, ignore
1587 // the background color at the start of selection, and find the background
1588 // color of the common ancestor.
1589 if (shouldUseBackgroundColorInEffect &&
1590 (selection.isRange() ||
1591 hasTransparentBackgroundColor(style->m_mutableStyle.get()))) {
1592 const EphemeralRange range(selection.toNormalizedEphemeralRange());
1593 if (const CSSValue* value =
1594 backgroundColorValueInEffect(Range::commonAncestorContainer(
1595 range.startPosition().computeContainerNode(),
1596 range.endPosition().computeContainerNode())))
1597 style->setProperty(CSSPropertyBackgroundColor, value->cssText());
1598 }
1599
1600 return style;
1601 }
1602
1603 static bool isUnicodeBidiNestedOrMultipleEmbeddings(CSSValueID valueID) {
1604 return valueID == CSSValueEmbed || valueID == CSSValueBidiOverride ||
1605 valueID == CSSValueWebkitIsolate ||
1606 valueID == CSSValueWebkitIsolateOverride ||
1607 valueID == CSSValueWebkitPlaintext || valueID == CSSValueIsolate ||
1608 valueID == CSSValueIsolateOverride || valueID == CSSValuePlaintext;
1609 }
1610
1611 WritingDirection EditingStyle::textDirectionForSelection(
1612 const VisibleSelection& selection,
1613 EditingStyle* typingStyle,
1614 bool& hasNestedOrMultipleEmbeddings) {
1615 hasNestedOrMultipleEmbeddings = true;
1616
1617 if (selection.isNone())
1618 return NaturalWritingDirection;
1619
1620 Position position = mostForwardCaretPosition(selection.start());
1621
1622 Node* node = position.anchorNode();
1623 if (!node)
1624 return NaturalWritingDirection;
1625
1626 Position end;
1627 if (selection.isRange()) {
1628 end = mostBackwardCaretPosition(selection.end());
1629
1630 DCHECK(end.document());
1631 const EphemeralRange caretRange(position.parentAnchoredEquivalent(),
1632 end.parentAnchoredEquivalent());
1633 for (Node& n : caretRange.nodes()) {
1634 if (!n.isStyledElement())
1635 continue;
1636
1637 CSSComputedStyleDeclaration* style =
1638 CSSComputedStyleDeclaration::create(&n);
1639 const CSSValue* unicodeBidi =
1640 style->getPropertyCSSValue(CSSPropertyUnicodeBidi);
1641 if (!unicodeBidi || !unicodeBidi->isIdentifierValue())
1642 continue;
1643
1644 CSSValueID unicodeBidiValue =
1645 toCSSIdentifierValue(unicodeBidi)->getValueID();
1646 if (isUnicodeBidiNestedOrMultipleEmbeddings(unicodeBidiValue))
1647 return NaturalWritingDirection;
1648 }
1649 }
1650
1651 if (selection.isCaret()) {
1652 WritingDirection direction;
1653 if (typingStyle && typingStyle->textDirection(direction)) {
1654 hasNestedOrMultipleEmbeddings = false;
1655 return direction;
1656 }
1657 node = selection.visibleStart().deepEquivalent().anchorNode();
1658 }
1659 DCHECK(node);
1660
1661 // The selection is either a caret with no typing attributes or a range in
1662 // which no embedding is added, so just use the start position to decide.
1663 Node* block = enclosingBlock(node);
1664 WritingDirection foundDirection = NaturalWritingDirection;
1665
1666 for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*node)) {
1667 if (runner == block)
1668 break;
1669 if (!runner.isStyledElement())
1670 continue;
1671
1672 Element* element = &toElement(runner);
1673 CSSComputedStyleDeclaration* style =
1674 CSSComputedStyleDeclaration::create(element);
1675 const CSSValue* unicodeBidi =
1676 style->getPropertyCSSValue(CSSPropertyUnicodeBidi);
1677 if (!unicodeBidi || !unicodeBidi->isIdentifierValue())
1678 continue;
1679
1680 CSSValueID unicodeBidiValue =
1681 toCSSIdentifierValue(unicodeBidi)->getValueID();
1682 if (unicodeBidiValue == CSSValueNormal)
1683 continue;
1684
1685 if (unicodeBidiValue == CSSValueBidiOverride)
1686 return NaturalWritingDirection;
1687
1688 DCHECK(isEmbedOrIsolate(unicodeBidiValue)) << unicodeBidiValue;
1689 const CSSValue* direction =
1690 style->getPropertyCSSValue(CSSPropertyDirection);
1691 if (!direction || !direction->isIdentifierValue())
1692 continue;
1693
1694 int directionValue = toCSSIdentifierValue(direction)->getValueID();
1695 if (directionValue != CSSValueLtr && directionValue != CSSValueRtl)
1696 continue;
1697
1698 if (foundDirection != NaturalWritingDirection)
1699 return NaturalWritingDirection;
1700
1701 // In the range case, make sure that the embedding element persists until
1702 // the end of the range.
1703 if (selection.isRange() && !end.anchorNode()->isDescendantOf(element))
1704 return NaturalWritingDirection;
1705
1706 foundDirection = directionValue == CSSValueLtr
1707 ? LeftToRightWritingDirection
1708 : RightToLeftWritingDirection;
1709 }
1710 hasNestedOrMultipleEmbeddings = false;
1711 return foundDirection;
1712 }
1713
1714 DEFINE_TRACE(EditingStyle) { 1478 DEFINE_TRACE(EditingStyle) {
1715 visitor->trace(m_mutableStyle); 1479 visitor->trace(m_mutableStyle);
1716 } 1480 }
1717 1481
1718 static void reconcileTextDecorationProperties(MutableStylePropertySet* style) { 1482 static void reconcileTextDecorationProperties(MutableStylePropertySet* style) {
1719 const CSSValue* textDecorationsInEffect = 1483 const CSSValue* textDecorationsInEffect =
1720 style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect); 1484 style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
1721 const CSSValue* textDecoration = 1485 const CSSValue* textDecoration =
1722 style->getPropertyCSSValue(textDecorationPropertyForEditing()); 1486 style->getPropertyCSSValue(textDecorationPropertyForEditing());
1723 // "LayoutTests/editing/execCommand/insert-list-and-strikethrough.html" makes 1487 // "LayoutTests/editing/execCommand/insert-list-and-strikethrough.html" makes
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
2014 if (value->isIdentifierValue()) { 1778 if (value->isIdentifierValue()) {
2015 const CSSIdentifierValue& identifierValue = toCSSIdentifierValue(*value); 1779 const CSSIdentifierValue& identifierValue = toCSSIdentifierValue(*value);
2016 if (CSSValueXSmall <= identifierValue.getValueID() && 1780 if (CSSValueXSmall <= identifierValue.getValueID() &&
2017 identifierValue.getValueID() <= CSSValueWebkitXxxLarge) 1781 identifierValue.getValueID() <= CSSValueWebkitXxxLarge)
2018 return identifierValue.getValueID() - CSSValueXSmall + 1; 1782 return identifierValue.getValueID() - CSSValueXSmall + 1;
2019 } 1783 }
2020 1784
2021 return 0; 1785 return 0;
2022 } 1786 }
2023 1787
2024 bool isTransparentColorValue(const CSSValue* cssValue) {
2025 if (!cssValue)
2026 return true;
2027 if (cssValue->isColorValue())
2028 return !toCSSColorValue(cssValue)->value().alpha();
2029 if (!cssValue->isIdentifierValue())
2030 return false;
2031 return toCSSIdentifierValue(cssValue)->getValueID() == CSSValueTransparent;
2032 }
2033
2034 bool hasTransparentBackgroundColor(CSSStyleDeclaration* style) {
2035 const CSSValue* cssValue =
2036 style->getPropertyCSSValueInternal(CSSPropertyBackgroundColor);
2037 return isTransparentColorValue(cssValue);
2038 }
2039
2040 bool hasTransparentBackgroundColor(StylePropertySet* style) {
2041 const CSSValue* cssValue =
2042 style->getPropertyCSSValue(CSSPropertyBackgroundColor);
2043 return isTransparentColorValue(cssValue);
2044 }
2045
2046 const CSSValue* backgroundColorValueInEffect(Node* node) {
2047 for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) {
2048 CSSComputedStyleDeclaration* ancestorStyle =
2049 CSSComputedStyleDeclaration::create(ancestor);
2050 if (!hasTransparentBackgroundColor(ancestorStyle))
2051 return ancestorStyle->getPropertyCSSValue(CSSPropertyBackgroundColor);
2052 }
2053 return nullptr;
2054 }
2055
2056 } // namespace blink 1788 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/EditingStyle.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698