Commit 84b451c8 authored by rniwa@webkit.org's avatar rniwa@webkit.org

2011-02-22 Ryosuke Niwa <rniwa@webkit.org>

        Reviewed by Darin Adler.

        Deploy EditingStyle in removeInlineStyleFromElement and removeCSSStyle
        https://bugs.webkit.org/show_bug.cgi?id=54944

        Deployed EditingStyle in removeInlineStyleFromElement and removeCSSStyle.

        Also extracted EditingStyle::conflictsWithInlineStyleOfElement from ApplyStyleCommand::removeCSSStyle,
        which returns true iff the specified element has inline style that conflicts or matches the editing style.
        It also appends conflicting property IDs to the vector of property IDs if one is specified.

        * editing/ApplyStyleCommand.cpp:
        (WebCore::ApplyStyleCommand::applyBlockStyle): Calls removeCSSStyle.
        (WebCore::ApplyStyleCommand::applyInlineStyle): Calls shouldSplitTextElement.
        (WebCore::ApplyStyleCommand::removeStyleFromRunBeforeApplyingStyle): Calls removeInlineStyleFromElement.
        (WebCore::ApplyStyleCommand::removeInlineStyleFromElement): Takes EditingStyle* instead of CSSMutableStyleDeclaration*.
        (WebCore::ApplyStyleCommand::removeCSSStyle): Ditto; extracted the logic to decide properties to remove as
        conflictsWithInlineStyleOfElement.
        (WebCore::ApplyStyleCommand::highestAncestorWithConflictingInlineStyle): Calls shouldRemoveInlineStyleFromElement.
        (WebCore::ApplyStyleCommand::pushDownInlineStyleAroundNode): Calls removeInlineStyleFromElement.
        (WebCore::ApplyStyleCommand::removeInlineStyle): Ditto.
        (WebCore::ApplyStyleCommand::shouldSplitTextElement): Takes EditingStyle* instead of CSSMutableStyleDeclaration*.
        * editing/ApplyStyleCommand.h:
        (WebCore::ApplyStyleCommand::shouldRemoveInlineStyleFromElement): Ditto.
        * editing/EditingStyle.cpp:
        (WebCore::EditingStyle::conflictsWithInlineStyleOfElement): Extracted from ApplyStyleCommand::removeCSSStyle.
        * editing/EditingStyle.h:
        (WebCore::EditingStyle::conflictsWithInlineStyleOfElement): Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@79382 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent e23c9a12
2011-02-22 Ryosuke Niwa <rniwa@webkit.org>
Reviewed by Darin Adler.
Deploy EditingStyle in removeInlineStyleFromElement and removeCSSStyle
https://bugs.webkit.org/show_bug.cgi?id=54944
Deployed EditingStyle in removeInlineStyleFromElement and removeCSSStyle.
Also extracted EditingStyle::conflictsWithInlineStyleOfElement from ApplyStyleCommand::removeCSSStyle,
which returns true iff the specified element has inline style that conflicts or matches the editing style.
It also appends conflicting property IDs to the vector of property IDs if one is specified.
* editing/ApplyStyleCommand.cpp:
(WebCore::ApplyStyleCommand::applyBlockStyle): Calls removeCSSStyle.
(WebCore::ApplyStyleCommand::applyInlineStyle): Calls shouldSplitTextElement.
(WebCore::ApplyStyleCommand::removeStyleFromRunBeforeApplyingStyle): Calls removeInlineStyleFromElement.
(WebCore::ApplyStyleCommand::removeInlineStyleFromElement): Takes EditingStyle* instead of CSSMutableStyleDeclaration*.
(WebCore::ApplyStyleCommand::removeCSSStyle): Ditto; extracted the logic to decide properties to remove as
conflictsWithInlineStyleOfElement.
(WebCore::ApplyStyleCommand::highestAncestorWithConflictingInlineStyle): Calls shouldRemoveInlineStyleFromElement.
(WebCore::ApplyStyleCommand::pushDownInlineStyleAroundNode): Calls removeInlineStyleFromElement.
(WebCore::ApplyStyleCommand::removeInlineStyle): Ditto.
(WebCore::ApplyStyleCommand::shouldSplitTextElement): Takes EditingStyle* instead of CSSMutableStyleDeclaration*.
* editing/ApplyStyleCommand.h:
(WebCore::ApplyStyleCommand::shouldRemoveInlineStyleFromElement): Ditto.
* editing/EditingStyle.cpp:
(WebCore::EditingStyle::conflictsWithInlineStyleOfElement): Extracted from ApplyStyleCommand::removeCSSStyle.
* editing/EditingStyle.h:
(WebCore::EditingStyle::conflictsWithInlineStyleOfElement): Added.
2011-02-22 Chang Shu <cshu@webkit.org>
Reviewed by Csaba Osztrogonác.
......
......@@ -601,7 +601,7 @@ void ApplyStyleCommand::applyBlockStyle(EditingStyle *style)
}
ASSERT(block->isHTMLElement());
if (block->isHTMLElement()) {
removeCSSStyle(style->style(), toHTMLElement(block.get()));
removeCSSStyle(style, toHTMLElement(block.get()));
if (!m_removeOnly)
addBlockStyle(styleChange, toHTMLElement(block.get()));
}
......@@ -876,7 +876,7 @@ void ApplyStyleCommand::applyInlineStyle(EditingStyle* style)
// split the start node and containing element if the selection starts inside of it
bool splitStart = isValidCaretPositionInTextNode(start);
if (splitStart) {
if (shouldSplitTextElement(start.deprecatedNode()->parentElement(), style->style()))
if (shouldSplitTextElement(start.deprecatedNode()->parentElement(), style))
splitTextElementAtStart(start, end);
else
splitTextAtStart(start, end);
......@@ -888,7 +888,7 @@ void ApplyStyleCommand::applyInlineStyle(EditingStyle* style)
// split the end node and containing element if the selection ends inside of it
bool splitEnd = isValidCaretPositionInTextNode(end);
if (splitEnd) {
if (shouldSplitTextElement(end.deprecatedNode()->parentElement(), style->style()))
if (shouldSplitTextElement(end.deprecatedNode()->parentElement(), style))
splitTextElementAtEnd(start, end);
else
splitTextAtEnd(start, end);
......@@ -1117,7 +1117,7 @@ bool ApplyStyleCommand::removeStyleFromRunBeforeApplyingStyle(EditingStyle* styl
RefPtr<Node> previousSibling = node->previousSibling();
RefPtr<Node> nextSibling = node->nextSibling();
RefPtr<ContainerNode> parent = node->parentNode();
removeInlineStyleFromElement(style->style(), toHTMLElement(node.get()), RemoveAlways);
removeInlineStyleFromElement(style, toHTMLElement(node.get()), RemoveAlways);
if (!node->inDocument()) {
// FIXME: We might need to update the start and the end of current selection here but need a test.
if (runStart == node)
......@@ -1130,7 +1130,7 @@ bool ApplyStyleCommand::removeStyleFromRunBeforeApplyingStyle(EditingStyle* styl
return true;
}
bool ApplyStyleCommand::removeInlineStyleFromElement(CSSMutableStyleDeclaration* style, PassRefPtr<HTMLElement> element, InlineStyleRemovalMode mode, CSSMutableStyleDeclaration* extractedStyle)
bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, PassRefPtr<HTMLElement> element, InlineStyleRemovalMode mode, CSSMutableStyleDeclaration* extractedStyle)
{
ASSERT(element);
......@@ -1147,11 +1147,11 @@ bool ApplyStyleCommand::removeInlineStyleFromElement(CSSMutableStyleDeclaration*
return true;
}
if (!style)
if (!style->style())
return false;
bool removed = false;
if (removeImplicitlyStyledElement(style, element.get(), mode, extractedStyle))
if (removeImplicitlyStyledElement(style->style(), element.get(), mode, extractedStyle))
removed = true;
if (!element->inDocument())
......@@ -1289,50 +1289,37 @@ void ApplyStyleCommand::replaceWithSpanOrRemoveIfWithoutAttributes(HTMLElement*&
}
}
bool ApplyStyleCommand::removeCSSStyle(CSSMutableStyleDeclaration* style, HTMLElement* element, InlineStyleRemovalMode mode, CSSMutableStyleDeclaration* extractedStyle)
bool ApplyStyleCommand::removeCSSStyle(EditingStyle* style, HTMLElement* element, InlineStyleRemovalMode mode, CSSMutableStyleDeclaration* extractedStyle)
{
ASSERT(style);
ASSERT(element);
if (mode == RemoveNone)
return style->conflictsWithInlineStyleOfElement(element);
CSSMutableStyleDeclaration* decl = element->inlineStyleDecl();
if (!decl)
Vector<CSSPropertyID> properties;
if (!style->conflictsWithInlineStyleOfElement(element, properties))
return false;
bool removed = false;
CSSMutableStyleDeclaration::const_iterator end = style->end();
for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) {
CSSPropertyID propertyID = static_cast<CSSPropertyID>(it->id());
RefPtr<CSSValue> value = decl->getPropertyCSSValue(propertyID);
if (!value || (isTabSpanNode(element) && propertyID == CSSPropertyWhiteSpace))
continue;
removed = true;
if (mode == RemoveNone)
return true;
ExceptionCode ec = 0;
if (extractedStyle)
extractedStyle->setProperty(propertyID, value->cssText(), decl->getPropertyPriority(propertyID), ec);
removeCSSProperty(element, propertyID);
if (propertyID == CSSPropertyUnicodeBidi && !decl->getPropertyValue(CSSPropertyDirection).isEmpty()) {
if (extractedStyle)
extractedStyle->setProperty(CSSPropertyDirection, decl->getPropertyValue(CSSPropertyDirection), decl->getPropertyPriority(CSSPropertyDirection), ec);
removeCSSProperty(element, CSSPropertyDirection);
CSSMutableStyleDeclaration* inlineStyle = element->inlineStyleDecl();
ASSERT(inlineStyle);
for (size_t i = 0; i < properties.size(); i++) {
CSSPropertyID id = properties[i];
if (extractedStyle) {
ExceptionCode ec = 0;
extractedStyle->setProperty(id, inlineStyle->getPropertyValue(id), inlineStyle->getPropertyPriority(id), ec);
}
removeCSSProperty(element, id);
}
if (mode == RemoveNone)
return removed;
// No need to serialize <foo style=""> if we just removed the last css property
if (decl->isEmpty())
if (inlineStyle->isEmpty())
removeNodeAttribute(element, styleAttr);
if (isSpanWithoutAttributesOrUnstyleStyleSpan(element))
removeNodePreservingChildren(element);
return removed;
return true;
}
HTMLElement* ApplyStyleCommand::highestAncestorWithConflictingInlineStyle(EditingStyle* style, Node* node)
......@@ -1344,7 +1331,7 @@ HTMLElement* ApplyStyleCommand::highestAncestorWithConflictingInlineStyle(Editin
Node* unsplittableElement = unsplittableElementForPosition(firstPositionInOrBeforeNode(node));
for (Node *n = node; n; n = n->parentNode()) {
if (n->isHTMLElement() && shouldRemoveInlineStyleFromElement(style->style(), toHTMLElement(n)))
if (n->isHTMLElement() && shouldRemoveInlineStyleFromElement(style, toHTMLElement(n)))
result = toHTMLElement(n);
// Should stop at the editable root (cannot cross editing boundary) and
// also stop at the unsplittable element to be consistent with other UAs
......@@ -1436,7 +1423,7 @@ void ApplyStyleCommand::pushDownInlineStyleAroundNode(EditingStyle* style, Node*
elementsToPushDown.append(styledElement);
}
RefPtr<CSSMutableStyleDeclaration> styleToPushDown = CSSMutableStyleDeclaration::create();
removeInlineStyleFromElement(style->style(), toHTMLElement(current), RemoveIfNeeded, styleToPushDown.get());
removeInlineStyleFromElement(style, toHTMLElement(current), RemoveIfNeeded, styleToPushDown.get());
// The inner loop will go through children on each level
// FIXME: we should aggregate inline child elements together so that we don't wrap each child separately.
......@@ -1513,7 +1500,7 @@ void ApplyStyleCommand::removeInlineStyle(EditingStyle* style, const Position &s
childNode = elem->firstChild();
}
removeInlineStyleFromElement(style->style(), elem.get(), RemoveIfNeeded, styleToPushDown.get());
removeInlineStyleFromElement(style, elem.get(), RemoveIfNeeded, styleToPushDown.get());
if (!elem->inDocument()) {
if (s.deprecatedNode() == elem) {
// Since elem must have been fully selected, and it is at the start
......@@ -1622,7 +1609,7 @@ void ApplyStyleCommand::splitTextElementAtEnd(const Position& start, const Posit
updateStartEnd(newStart, Position(prevNode->parentNode(), prevNode->nodeIndex() + 1, Position::PositionIsOffsetInAnchor));
}
bool ApplyStyleCommand::shouldSplitTextElement(Element* element, CSSMutableStyleDeclaration* style)
bool ApplyStyleCommand::shouldSplitTextElement(Element* element, EditingStyle* style)
{
if (!element || !element->isHTMLElement())
return false;
......
......@@ -78,11 +78,11 @@ private:
// style-removal helpers
bool isStyledInlineElementToRemove(Element*) const;
bool removeStyleFromRunBeforeApplyingStyle(EditingStyle*, RefPtr<Node>& runStart, RefPtr<Node>& runEnd);
bool removeInlineStyleFromElement(CSSMutableStyleDeclaration*, PassRefPtr<HTMLElement>, InlineStyleRemovalMode = RemoveIfNeeded, CSSMutableStyleDeclaration* extractedStyle = 0);
inline bool shouldRemoveInlineStyleFromElement(CSSMutableStyleDeclaration* style, HTMLElement* element) {return removeInlineStyleFromElement(style, element, RemoveNone);}
bool removeInlineStyleFromElement(EditingStyle*, PassRefPtr<HTMLElement>, InlineStyleRemovalMode = RemoveIfNeeded, CSSMutableStyleDeclaration* extractedStyle = 0);
inline bool shouldRemoveInlineStyleFromElement(EditingStyle* style, HTMLElement* element) {return removeInlineStyleFromElement(style, element, RemoveNone);}
bool removeImplicitlyStyledElement(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode, CSSMutableStyleDeclaration* extractedStyle);
void replaceWithSpanOrRemoveIfWithoutAttributes(HTMLElement*&);
bool removeCSSStyle(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode = RemoveIfNeeded, CSSMutableStyleDeclaration* extractedStyle = 0);
bool removeCSSStyle(EditingStyle*, HTMLElement*, InlineStyleRemovalMode = RemoveIfNeeded, CSSMutableStyleDeclaration* extractedStyle = 0);
HTMLElement* highestAncestorWithConflictingInlineStyle(EditingStyle*, Node*);
void applyInlineStyleToPushDown(Node*, CSSMutableStyleDeclaration*);
void pushDownInlineStyleAroundNode(EditingStyle*, Node*);
......@@ -102,7 +102,7 @@ private:
void splitTextAtEnd(const Position& start, const Position& end);
void splitTextElementAtStart(const Position& start, const Position& end);
void splitTextElementAtEnd(const Position& start, const Position& end);
bool shouldSplitTextElement(Element* elem, CSSMutableStyleDeclaration*);
bool shouldSplitTextElement(Element*, EditingStyle*);
bool isValidCaretPositionInTextNode(const Position& position);
bool mergeStartWithPreviousIfIdentical(const Position& start, const Position& end);
bool mergeEndWithNextIfIdentical(const Position& start, const Position& end);
......
......@@ -32,10 +32,13 @@
#include "CSSMutableStyleDeclaration.h"
#include "CSSValueKeywords.h"
#include "Frame.h"
#include "HTMLNames.h"
#include "Node.h"
#include "Position.h"
#include "RenderStyle.h"
#include "SelectionController.h"
#include "StyledElement.h"
#include "htmlediting.h"
namespace WebCore {
......@@ -322,6 +325,46 @@ void EditingStyle::collapseTextDecorationProperties()
m_mutableStyle->removeProperty(CSSPropertyWebkitTextDecorationsInEffect);
}
bool EditingStyle::conflictsWithInlineStyleOfElement(StyledElement* element, Vector<CSSPropertyID>* conflictingProperties) const
{
ASSERT(element);
ASSERT(!conflictingProperties || conflictingProperties->isEmpty());
CSSMutableStyleDeclaration* inlineStyle = element->inlineStyleDecl();
if (!m_mutableStyle || !inlineStyle)
return false;
if (!conflictingProperties) {
CSSMutableStyleDeclaration::const_iterator end = m_mutableStyle->end();
for (CSSMutableStyleDeclaration::const_iterator it = m_mutableStyle->begin(); it != end; ++it) {
CSSPropertyID propertyID = static_cast<CSSPropertyID>(it->id());
// We don't override whitespace property of a tab span because that would collapse the tab into a space.
if (propertyID == CSSPropertyWhiteSpace && isTabSpanNode(element))
continue;
if (inlineStyle->getPropertyCSSValue(propertyID))
return true;
}
return false;
}
CSSMutableStyleDeclaration::const_iterator end = m_mutableStyle->end();
for (CSSMutableStyleDeclaration::const_iterator it = m_mutableStyle->begin(); it != end; ++it) {
CSSPropertyID propertyID = static_cast<CSSPropertyID>(it->id());
if ((propertyID == CSSPropertyWhiteSpace && isTabSpanNode(element)) || !inlineStyle->getPropertyCSSValue(propertyID))
continue;
if (propertyID == CSSPropertyUnicodeBidi && inlineStyle->getPropertyCSSValue(CSSPropertyDirection))
conflictingProperties->append(CSSPropertyDirection);
conflictingProperties->append(propertyID);
}
return !conflictingProperties->isEmpty();
}
void EditingStyle::prepareToApplyAt(const Position& position, ShouldPreserveWritingDirection shouldPreserveWritingDirection)
{
if (!m_mutableStyle)
......
......@@ -31,9 +31,11 @@
#ifndef EditingStyle_h
#define EditingStyle_h
#include "CSSPropertyNames.h"
#include "WritingDirection.h"
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
namespace WebCore {
......@@ -43,6 +45,7 @@ class CSSMutableStyleDeclaration;
class Node;
class Position;
class RenderStyle;
class StyledElement;
class EditingStyle : public RefCounted<EditingStyle> {
public:
......@@ -87,6 +90,11 @@ public:
void removeStyleConflictingWithStyleOfNode(Node*);
void removeNonEditingProperties();
void collapseTextDecorationProperties();
bool conflictsWithInlineStyleOfElement(StyledElement* element) const { return conflictsWithInlineStyleOfElement(element, 0); }
bool conflictsWithInlineStyleOfElement(StyledElement* element, Vector<CSSPropertyID>& conflictingProperties) const
{
return conflictsWithInlineStyleOfElement(element, &conflictingProperties);
}
void prepareToApplyAt(const Position&, ShouldPreserveWritingDirection = DoNotPreserveWritingDirection);
float fontSizeDelta() const { return m_fontSizeDelta; }
......@@ -101,6 +109,7 @@ private:
void removeTextFillAndStrokeColorsIfNeeded(RenderStyle*);
void replaceFontSizeByKeywordIfPossible(RenderStyle*, CSSComputedStyleDeclaration*);
void extractFontSizeDelta();
bool conflictsWithInlineStyleOfElement(StyledElement*, Vector<CSSPropertyID>* conflictingProperties) const;
RefPtr<CSSMutableStyleDeclaration> m_mutableStyle;
bool m_shouldUseFixedDefaultFontSize;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment