| Index: third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
|
| diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
|
| index 2f2478ea8995c980aba97a71120a36575bfe5239..192d2407224bfc6d765470af8c471777b1ed5566 100644
|
| --- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
|
| +++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
|
| @@ -32,6 +32,7 @@
|
| #include "core/CSSValueKeywords.h"
|
| #include "core/HTMLNames.h"
|
| #include "core/clipboard/Pasteboard.h"
|
| +#include "core/css/CSSComputedStyleDeclaration.h"
|
| #include "core/css/CSSIdentifierValue.h"
|
| #include "core/css/CSSValueList.h"
|
| #include "core/css/StylePropertySet.h"
|
| @@ -461,15 +462,128 @@ static String valueStyle(LocalFrame& frame, CSSPropertyID propertyID) {
|
| return frame.editor().selectionStartCSSPropertyValue(propertyID);
|
| }
|
|
|
| +static bool isUnicodeBidiNestedOrMultipleEmbeddings(CSSValueID valueID) {
|
| + return valueID == CSSValueEmbed || valueID == CSSValueBidiOverride ||
|
| + valueID == CSSValueWebkitIsolate ||
|
| + valueID == CSSValueWebkitIsolateOverride ||
|
| + valueID == CSSValueWebkitPlaintext || valueID == CSSValueIsolate ||
|
| + valueID == CSSValueIsolateOverride || valueID == CSSValuePlaintext;
|
| +}
|
| +
|
| +// TODO(editing-dev): We should make |textDirectionForSelection()| to take
|
| +// |selectionInDOMTree|.
|
| +static WritingDirection textDirectionForSelection(
|
| + const VisibleSelection& selection,
|
| + EditingStyle* typingStyle,
|
| + bool& hasNestedOrMultipleEmbeddings) {
|
| + hasNestedOrMultipleEmbeddings = true;
|
| +
|
| + if (selection.isNone())
|
| + return NaturalWritingDirection;
|
| +
|
| + Position position = mostForwardCaretPosition(selection.start());
|
| +
|
| + Node* node = position.anchorNode();
|
| + if (!node)
|
| + return NaturalWritingDirection;
|
| +
|
| + Position end;
|
| + if (selection.isRange()) {
|
| + end = mostBackwardCaretPosition(selection.end());
|
| +
|
| + DCHECK(end.document());
|
| + const EphemeralRange caretRange(position.parentAnchoredEquivalent(),
|
| + end.parentAnchoredEquivalent());
|
| + for (Node& n : caretRange.nodes()) {
|
| + if (!n.isStyledElement())
|
| + continue;
|
| +
|
| + CSSComputedStyleDeclaration* style =
|
| + CSSComputedStyleDeclaration::create(&n);
|
| + const CSSValue* unicodeBidi =
|
| + style->getPropertyCSSValue(CSSPropertyUnicodeBidi);
|
| + if (!unicodeBidi || !unicodeBidi->isIdentifierValue())
|
| + continue;
|
| +
|
| + CSSValueID unicodeBidiValue =
|
| + toCSSIdentifierValue(unicodeBidi)->getValueID();
|
| + if (isUnicodeBidiNestedOrMultipleEmbeddings(unicodeBidiValue))
|
| + return NaturalWritingDirection;
|
| + }
|
| + }
|
| +
|
| + if (selection.isCaret()) {
|
| + WritingDirection direction;
|
| + if (typingStyle && typingStyle->textDirection(direction)) {
|
| + hasNestedOrMultipleEmbeddings = false;
|
| + return direction;
|
| + }
|
| + node = selection.visibleStart().deepEquivalent().anchorNode();
|
| + }
|
| + DCHECK(node);
|
| +
|
| + // The selection is either a caret with no typing attributes or a range in
|
| + // which no embedding is added, so just use the start position to decide.
|
| + Node* block = enclosingBlock(node);
|
| + WritingDirection foundDirection = NaturalWritingDirection;
|
| +
|
| + for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*node)) {
|
| + if (runner == block)
|
| + break;
|
| + if (!runner.isStyledElement())
|
| + continue;
|
| +
|
| + Element* element = &toElement(runner);
|
| + CSSComputedStyleDeclaration* style =
|
| + CSSComputedStyleDeclaration::create(element);
|
| + const CSSValue* unicodeBidi =
|
| + style->getPropertyCSSValue(CSSPropertyUnicodeBidi);
|
| + if (!unicodeBidi || !unicodeBidi->isIdentifierValue())
|
| + continue;
|
| +
|
| + CSSValueID unicodeBidiValue =
|
| + toCSSIdentifierValue(unicodeBidi)->getValueID();
|
| + if (unicodeBidiValue == CSSValueNormal)
|
| + continue;
|
| +
|
| + if (unicodeBidiValue == CSSValueBidiOverride)
|
| + return NaturalWritingDirection;
|
| +
|
| + DCHECK(EditingStyleUtilities::isEmbedOrIsolate(unicodeBidiValue))
|
| + << unicodeBidiValue;
|
| + const CSSValue* direction =
|
| + style->getPropertyCSSValue(CSSPropertyDirection);
|
| + if (!direction || !direction->isIdentifierValue())
|
| + continue;
|
| +
|
| + int directionValue = toCSSIdentifierValue(direction)->getValueID();
|
| + if (directionValue != CSSValueLtr && directionValue != CSSValueRtl)
|
| + continue;
|
| +
|
| + if (foundDirection != NaturalWritingDirection)
|
| + return NaturalWritingDirection;
|
| +
|
| + // In the range case, make sure that the embedding element persists until
|
| + // the end of the range.
|
| + if (selection.isRange() && !end.anchorNode()->isDescendantOf(element))
|
| + return NaturalWritingDirection;
|
| +
|
| + foundDirection = directionValue == CSSValueLtr
|
| + ? LeftToRightWritingDirection
|
| + : RightToLeftWritingDirection;
|
| + }
|
| + hasNestedOrMultipleEmbeddings = false;
|
| + return foundDirection;
|
| +}
|
| +
|
| static TriState stateTextWritingDirection(LocalFrame& frame,
|
| WritingDirection direction) {
|
| frame.document()->updateStyleAndLayoutIgnorePendingStylesheets();
|
|
|
| bool hasNestedOrMultipleEmbeddings;
|
| - WritingDirection selectionDirection =
|
| - EditingStyleUtilities::textDirectionForSelection(
|
| - frame.selection().computeVisibleSelectionInDOMTreeDeprecated(),
|
| - frame.editor().typingStyle(), hasNestedOrMultipleEmbeddings);
|
| + WritingDirection selectionDirection = textDirectionForSelection(
|
| + frame.selection().computeVisibleSelectionInDOMTreeDeprecated(),
|
| + frame.editor().typingStyle(), hasNestedOrMultipleEmbeddings);
|
| // FXIME: We should be returning MixedTriState when selectionDirection ==
|
| // direction && hasNestedOrMultipleEmbeddings
|
| return (selectionDirection == direction && !hasNestedOrMultipleEmbeddings)
|
|
|