128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu/*
228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * Copyright (C) 2007, 2008, 2009 Apple Computer, Inc.
328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * Copyright (C) 2010 Google Inc. All rights reserved.
428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu *
528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * Redistribution and use in source and binary forms, with or without
628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * modification, are permitted provided that the following conditions
728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * are met:
828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * 1. Redistributions of source code must retain the above copyright
928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu *    notice, this list of conditions and the following disclaimer.
1028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * 2. Redistributions in binary form must reproduce the above copyright
1128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu *    notice, this list of conditions and the following disclaimer in the
1228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu *    documentation and/or other materials provided with the distribution.
1328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu *
1428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu */
2628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
2728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#include "config.h"
2828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#include "EditingStyle.h"
2928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
3028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#include "ApplyStyleCommand.h"
3128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#include "CSSComputedStyleDeclaration.h"
3228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#include "CSSMutableStyleDeclaration.h"
332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "CSSParser.h"
342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "CSSStyleSelector.h"
354576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang#include "CSSValueKeywords.h"
3681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "CSSValueList.h"
3728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#include "Frame.h"
3881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "HTMLFontElement.h"
3981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "HTMLNames.h"
40cad810f21b803229eb11403f9209855525a25d57Steve Block#include "Node.h"
41cad810f21b803229eb11403f9209855525a25d57Steve Block#include "Position.h"
4228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#include "RenderStyle.h"
4328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#include "SelectionController.h"
4481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "StyledElement.h"
4581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "htmlediting.h"
4628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
4728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhunamespace WebCore {
4828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
4928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu// Editing style properties must be preserved during editing operation.
5028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu// e.g. when a user inserts a new paragraph, all properties listed here must be copied to the new paragraph.
5128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu// FIXME: The current editingStyleProperties contains all inheritableProperties but we may not need to preserve all inheritable properties
5228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhustatic const int editingStyleProperties[] = {
5328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // CSS inheritable properties
5428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyBorderCollapse,
5528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyColor,
5628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyFontFamily,
5728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyFontSize,
5828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyFontStyle,
5928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyFontVariant,
6028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyFontWeight,
6128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyLetterSpacing,
6228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyLineHeight,
6328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyOrphans,
6428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyTextAlign,
6528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyTextIndent,
6628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyTextTransform,
6728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyWhiteSpace,
6828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyWidows,
6928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyWordSpacing,
7028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyWebkitBorderHorizontalSpacing,
7128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyWebkitBorderVerticalSpacing,
7228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyWebkitTextDecorationsInEffect,
7328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyWebkitTextFillColor,
7428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyWebkitTextSizeAdjust,
7528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyWebkitTextStrokeColor,
7628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSPropertyWebkitTextStrokeWidth,
7728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu};
784576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangsize_t numEditingStyleProperties = WTF_ARRAY_LENGTH(editingStyleProperties);
7928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
8028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhustatic PassRefPtr<CSSMutableStyleDeclaration> copyEditingProperties(CSSStyleDeclaration* style)
8128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
8228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    return style->copyPropertiesInSet(editingStyleProperties, numEditingStyleProperties);
8328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
8428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
8528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhustatic PassRefPtr<CSSMutableStyleDeclaration> editingStyleFromComputedStyle(PassRefPtr<CSSComputedStyleDeclaration> style)
8628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
8728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (!style)
8828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        return CSSMutableStyleDeclaration::create();
8928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    return copyEditingProperties(style.get());
9028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
9128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic RefPtr<CSSMutableStyleDeclaration> getPropertiesNotIn(CSSStyleDeclaration* styleWithRedundantProperties, CSSStyleDeclaration* baseStyle);
932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochclass HTMLElementEquivalent {
9581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochpublic:
9681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    static PassOwnPtr<HTMLElementEquivalent> create(CSSPropertyID propertyID, int primitiveValue, const QualifiedName& tagName)
9781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    {
9881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return adoptPtr(new HTMLElementEquivalent(propertyID, primitiveValue, tagName));
9981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
10081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
10181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    virtual ~HTMLElementEquivalent() { }
10281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    virtual bool matches(Element* element) const { return !m_tagName || element->hasTagName(*m_tagName); }
10381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    virtual bool hasAttribute() const { return false; }
10481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    bool propertyExistsInStyle(CSSStyleDeclaration* style) const { return style->getPropertyCSSValue(m_propertyID); }
10581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    virtual bool valueIsPresentInStyle(Element*, CSSStyleDeclaration*) const;
10681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    virtual void addToStyle(Element*, EditingStyle*) const;
10781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
10881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochprotected:
10981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    HTMLElementEquivalent(CSSPropertyID);
11081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    HTMLElementEquivalent(CSSPropertyID, const QualifiedName& tagName);
11181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    HTMLElementEquivalent(CSSPropertyID, int primitiveValue, const QualifiedName& tagName);
11281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    const int m_propertyID;
11381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    const RefPtr<CSSPrimitiveValue> m_primitiveValue;
11481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    const QualifiedName* m_tagName; // We can store a pointer because HTML tag names are const global.
11581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch};
11681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
11781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochHTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id)
11881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    : m_propertyID(id)
11981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_tagName(0)
12081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
12181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
12281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
12381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochHTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id, const QualifiedName& tagName)
12481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    : m_propertyID(id)
12581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_tagName(&tagName)
12681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
12781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
12881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
12981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochHTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id, int primitiveValue, const QualifiedName& tagName)
13081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    : m_propertyID(id)
13181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_primitiveValue(CSSPrimitiveValue::createIdentifier(primitiveValue))
13281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_tagName(&tagName)
13381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
13481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(primitiveValue != CSSValueInvalid);
13581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
13681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
13781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool HTMLElementEquivalent::valueIsPresentInStyle(Element* element, CSSStyleDeclaration* style) const
13881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
13981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RefPtr<CSSValue> value = style->getPropertyCSSValue(m_propertyID);
14081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return matches(element) && value && value->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(value.get())->getIdent() == m_primitiveValue->getIdent();
14181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
14281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
14381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid HTMLElementEquivalent::addToStyle(Element*, EditingStyle* style) const
14481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
14581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    style->setProperty(m_propertyID, m_primitiveValue->cssText());
14681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
14781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
14881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochclass HTMLTextDecorationEquivalent : public HTMLElementEquivalent {
14981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochpublic:
15081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    static PassOwnPtr<HTMLElementEquivalent> create(int primitiveValue, const QualifiedName& tagName)
15181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    {
15281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return adoptPtr(new HTMLTextDecorationEquivalent(primitiveValue, tagName));
15381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
15481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    virtual bool valueIsPresentInStyle(Element*, CSSStyleDeclaration*) const;
15581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
15681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochprivate:
15781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    HTMLTextDecorationEquivalent(int primitiveValue, const QualifiedName& tagName);
15881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch};
15981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
16081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochHTMLTextDecorationEquivalent::HTMLTextDecorationEquivalent(int primitiveValue, const QualifiedName& tagName)
16181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    : HTMLElementEquivalent(CSSPropertyTextDecoration, primitiveValue, tagName)
16281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
16381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
16481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
16581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool HTMLTextDecorationEquivalent::valueIsPresentInStyle(Element* element, CSSStyleDeclaration* style) const
16681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
16781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RefPtr<CSSValue> styleValue = style->getPropertyCSSValue(m_propertyID);
16881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return matches(element) && styleValue && styleValue->isValueList() && static_cast<CSSValueList*>(styleValue.get())->hasValue(m_primitiveValue.get());
16981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
17081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
17181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochclass HTMLAttributeEquivalent : public HTMLElementEquivalent {
17281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochpublic:
17381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    static PassOwnPtr<HTMLAttributeEquivalent> create(CSSPropertyID propertyID, const QualifiedName& tagName, const QualifiedName& attrName)
17481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    {
17581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return adoptPtr(new HTMLAttributeEquivalent(propertyID, tagName, attrName));
17681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
17781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    static PassOwnPtr<HTMLAttributeEquivalent> create(CSSPropertyID propertyID, const QualifiedName& attrName)
17881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    {
17981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return adoptPtr(new HTMLAttributeEquivalent(propertyID, attrName));
18081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
18181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
18281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    bool matches(Element* elem) const { return HTMLElementEquivalent::matches(elem) && elem->hasAttribute(m_attrName); }
18381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    virtual bool hasAttribute() const { return true; }
18481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    virtual bool valueIsPresentInStyle(Element*, CSSStyleDeclaration*) const;
18581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    virtual void addToStyle(Element*, EditingStyle*) const;
18681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    virtual PassRefPtr<CSSValue> attributeValueAsCSSValue(Element*) const;
18781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    inline const QualifiedName& attributeName() const { return m_attrName; }
18881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
18981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochprotected:
19081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    HTMLAttributeEquivalent(CSSPropertyID, const QualifiedName& tagName, const QualifiedName& attrName);
19181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    HTMLAttributeEquivalent(CSSPropertyID, const QualifiedName& attrName);
19281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    const QualifiedName& m_attrName; // We can store a reference because HTML attribute names are const global.
19381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch};
19481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
19581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochHTMLAttributeEquivalent::HTMLAttributeEquivalent(CSSPropertyID id, const QualifiedName& tagName, const QualifiedName& attrName)
19681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    : HTMLElementEquivalent(id, tagName)
19781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_attrName(attrName)
19881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
19981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
20081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
20181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochHTMLAttributeEquivalent::HTMLAttributeEquivalent(CSSPropertyID id, const QualifiedName& attrName)
20281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    : HTMLElementEquivalent(id)
20381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_attrName(attrName)
20481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
20581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
20681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
20781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool HTMLAttributeEquivalent::valueIsPresentInStyle(Element* element, CSSStyleDeclaration* style) const
20881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
20981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RefPtr<CSSValue> value = attributeValueAsCSSValue(element);
21081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RefPtr<CSSValue> styleValue = style->getPropertyCSSValue(m_propertyID);
21181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
21281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // FIXME: This is very inefficient way of comparing values
21381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // but we can't string compare attribute value and CSS property value.
21481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return value && styleValue && value->cssText() == styleValue->cssText();
21581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
21681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
21781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid HTMLAttributeEquivalent::addToStyle(Element* element, EditingStyle* style) const
21881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
21981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (RefPtr<CSSValue> value = attributeValueAsCSSValue(element))
22081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        style->setProperty(m_propertyID, value->cssText());
22181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
22281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
22381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochPassRefPtr<CSSValue> HTMLAttributeEquivalent::attributeValueAsCSSValue(Element* element) const
22481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
22581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(element);
22681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!element->hasAttribute(m_attrName))
22781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return 0;
22881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
22981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RefPtr<CSSMutableStyleDeclaration> dummyStyle;
23081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    dummyStyle = CSSMutableStyleDeclaration::create();
23181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    dummyStyle->setProperty(m_propertyID, element->getAttribute(m_attrName));
23281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return dummyStyle->getPropertyCSSValue(m_propertyID);
23381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
23481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
23581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochclass HTMLFontSizeEquivalent : public HTMLAttributeEquivalent {
23681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochpublic:
23781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    static PassOwnPtr<HTMLFontSizeEquivalent> create()
23881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    {
23981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return adoptPtr(new HTMLFontSizeEquivalent());
24081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
24181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    virtual PassRefPtr<CSSValue> attributeValueAsCSSValue(Element*) const;
24281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
24381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochprivate:
24481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    HTMLFontSizeEquivalent();
24581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch};
24681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
24781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochHTMLFontSizeEquivalent::HTMLFontSizeEquivalent()
24881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    : HTMLAttributeEquivalent(CSSPropertyFontSize, HTMLNames::fontTag, HTMLNames::sizeAttr)
24981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
25081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
25181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
25281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochPassRefPtr<CSSValue> HTMLFontSizeEquivalent::attributeValueAsCSSValue(Element* element) const
25381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
25481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(element);
25581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!element->hasAttribute(m_attrName))
25681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return 0;
25781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    int size;
25881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!HTMLFontElement::cssValueFromFontSizeNumber(element->getAttribute(m_attrName), size))
25981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return 0;
26081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return CSSPrimitiveValue::createIdentifier(size);
26181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
26281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
263cad810f21b803229eb11403f9209855525a25d57Steve Blockfloat EditingStyle::NoFontDelta = 0.0f;
264cad810f21b803229eb11403f9209855525a25d57Steve Block
26528040489d744e0c5d475a88663056c9040ed5320Teng-Hui ZhuEditingStyle::EditingStyle()
26628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    : m_shouldUseFixedDefaultFontSize(false)
267cad810f21b803229eb11403f9209855525a25d57Steve Block    , m_fontSizeDelta(NoFontDelta)
26828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
26928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
27028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
2712fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockEditingStyle::EditingStyle(Node* node, PropertiesToInclude propertiesToInclude)
27228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    : m_shouldUseFixedDefaultFontSize(false)
273cad810f21b803229eb11403f9209855525a25d57Steve Block    , m_fontSizeDelta(NoFontDelta)
27428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
2752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    init(node, propertiesToInclude);
27628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
27728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
27828040489d744e0c5d475a88663056c9040ed5320Teng-Hui ZhuEditingStyle::EditingStyle(const Position& position)
27928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    : m_shouldUseFixedDefaultFontSize(false)
280cad810f21b803229eb11403f9209855525a25d57Steve Block    , m_fontSizeDelta(NoFontDelta)
28128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
28281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    init(position.deprecatedNode(), OnlyInheritableProperties);
28328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
28428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
28528040489d744e0c5d475a88663056c9040ed5320Teng-Hui ZhuEditingStyle::EditingStyle(const CSSStyleDeclaration* style)
28628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    : m_mutableStyle(style->copy())
28728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    , m_shouldUseFixedDefaultFontSize(false)
288cad810f21b803229eb11403f9209855525a25d57Steve Block    , m_fontSizeDelta(NoFontDelta)
28928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
290cad810f21b803229eb11403f9209855525a25d57Steve Block    extractFontSizeDelta();
29128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
29228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
29381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochEditingStyle::EditingStyle(int propertyID, const String& value)
29481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    : m_mutableStyle(0)
29581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_shouldUseFixedDefaultFontSize(false)
29681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_fontSizeDelta(NoFontDelta)
29781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
29881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    setProperty(propertyID, value);
29981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
30081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
301f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochEditingStyle::~EditingStyle()
302f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
303f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
304f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
3052fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid EditingStyle::init(Node* node, PropertiesToInclude propertiesToInclude)
30628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
3072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (isTabSpanTextNode(node))
3082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        node = tabSpanNode(node)->parentNode();
3092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    else if (isTabSpanNode(node))
3102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        node = node->parentNode();
3112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
31228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    RefPtr<CSSComputedStyleDeclaration> computedStyleAtPosition = computedStyle(node);
3132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_mutableStyle = propertiesToInclude == AllProperties && computedStyleAtPosition ? computedStyleAtPosition->copy() : editingStyleFromComputedStyle(computedStyleAtPosition);
31428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
31528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (node && node->computedStyle()) {
31628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        RenderStyle* renderStyle = node->computedStyle();
31728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        removeTextFillAndStrokeColorsIfNeeded(renderStyle);
31828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        replaceFontSizeByKeywordIfPossible(renderStyle, computedStyleAtPosition.get());
31928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    }
32028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
32128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    m_shouldUseFixedDefaultFontSize = computedStyleAtPosition->useFixedFontDefaultSize();
322cad810f21b803229eb11403f9209855525a25d57Steve Block    extractFontSizeDelta();
32328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
32428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
32528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid EditingStyle::removeTextFillAndStrokeColorsIfNeeded(RenderStyle* renderStyle)
32628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
32728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // If a node's text fill color is invalid, then its children use
32828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // their font-color as their text fill color (they don't
32928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // inherit it).  Likewise for stroke color.
33028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    ExceptionCode ec = 0;
33128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (!renderStyle->textFillColor().isValid())
33228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        m_mutableStyle->removeProperty(CSSPropertyWebkitTextFillColor, ec);
33328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (!renderStyle->textStrokeColor().isValid())
33428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        m_mutableStyle->removeProperty(CSSPropertyWebkitTextStrokeColor, ec);
33528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    ASSERT(!ec);
33628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
33728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
33881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid EditingStyle::setProperty(int propertyID, const String& value, bool important)
33981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
34081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!m_mutableStyle)
34181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        m_mutableStyle = CSSMutableStyleDeclaration::create();
34281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
34381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ExceptionCode ec;
34481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    m_mutableStyle->setProperty(propertyID, value, important, ec);
34581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
34681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
34728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid EditingStyle::replaceFontSizeByKeywordIfPossible(RenderStyle* renderStyle, CSSComputedStyleDeclaration* computedStyle)
34828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
34928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    ASSERT(renderStyle);
35028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (renderStyle->fontDescription().keywordSize())
35128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        m_mutableStyle->setProperty(CSSPropertyFontSize, computedStyle->getFontSizeCSSValuePreferringKeyword()->cssText());
35228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
35328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
354cad810f21b803229eb11403f9209855525a25d57Steve Blockvoid EditingStyle::extractFontSizeDelta()
355cad810f21b803229eb11403f9209855525a25d57Steve Block{
356cad810f21b803229eb11403f9209855525a25d57Steve Block    if (m_mutableStyle->getPropertyCSSValue(CSSPropertyFontSize)) {
357cad810f21b803229eb11403f9209855525a25d57Steve Block        // Explicit font size overrides any delta.
358cad810f21b803229eb11403f9209855525a25d57Steve Block        m_mutableStyle->removeProperty(CSSPropertyWebkitFontSizeDelta);
359cad810f21b803229eb11403f9209855525a25d57Steve Block        return;
360cad810f21b803229eb11403f9209855525a25d57Steve Block    }
361cad810f21b803229eb11403f9209855525a25d57Steve Block
362cad810f21b803229eb11403f9209855525a25d57Steve Block    // Get the adjustment amount out of the style.
363cad810f21b803229eb11403f9209855525a25d57Steve Block    RefPtr<CSSValue> value = m_mutableStyle->getPropertyCSSValue(CSSPropertyWebkitFontSizeDelta);
364cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!value || value->cssValueType() != CSSValue::CSS_PRIMITIVE_VALUE)
365cad810f21b803229eb11403f9209855525a25d57Steve Block        return;
366cad810f21b803229eb11403f9209855525a25d57Steve Block
367cad810f21b803229eb11403f9209855525a25d57Steve Block    CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value.get());
368cad810f21b803229eb11403f9209855525a25d57Steve Block
369cad810f21b803229eb11403f9209855525a25d57Steve Block    // Only PX handled now. If we handle more types in the future, perhaps
370cad810f21b803229eb11403f9209855525a25d57Steve Block    // a switch statement here would be more appropriate.
371cad810f21b803229eb11403f9209855525a25d57Steve Block    if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_PX)
372cad810f21b803229eb11403f9209855525a25d57Steve Block        return;
373cad810f21b803229eb11403f9209855525a25d57Steve Block
374cad810f21b803229eb11403f9209855525a25d57Steve Block    m_fontSizeDelta = primitiveValue->getFloatValue();
375cad810f21b803229eb11403f9209855525a25d57Steve Block    m_mutableStyle->removeProperty(CSSPropertyWebkitFontSizeDelta);
376cad810f21b803229eb11403f9209855525a25d57Steve Block}
377cad810f21b803229eb11403f9209855525a25d57Steve Block
37828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhubool EditingStyle::isEmpty() const
37928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
380cad810f21b803229eb11403f9209855525a25d57Steve Block    return (!m_mutableStyle || m_mutableStyle->isEmpty()) && m_fontSizeDelta == NoFontDelta;
38128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
38228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
3834576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool EditingStyle::textDirection(WritingDirection& writingDirection) const
3844576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang{
38581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!m_mutableStyle)
38681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return false;
38781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
3884576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    RefPtr<CSSValue> unicodeBidi = m_mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi);
3892bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!unicodeBidi || !unicodeBidi->isPrimitiveValue())
3904576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        return false;
3914576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
3924576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    int unicodeBidiValue = static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent();
3934576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (unicodeBidiValue == CSSValueEmbed) {
3944576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        RefPtr<CSSValue> direction = m_mutableStyle->getPropertyCSSValue(CSSPropertyDirection);
3952bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!direction || !direction->isPrimitiveValue())
3964576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            return false;
3974576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
3984576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        writingDirection = static_cast<CSSPrimitiveValue*>(direction.get())->getIdent() == CSSValueLtr ? LeftToRightWritingDirection : RightToLeftWritingDirection;
3994576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
4004576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        return true;
4014576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
4024576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
4034576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (unicodeBidiValue == CSSValueNormal) {
4044576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        writingDirection = NaturalWritingDirection;
4054576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        return true;
4064576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
4074576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
4084576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    return false;
4094576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang}
4104576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
41128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid EditingStyle::setStyle(PassRefPtr<CSSMutableStyleDeclaration> style)
41228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
41328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    m_mutableStyle = style;
41428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // FIXME: We should be able to figure out whether or not font is fixed width for mutable style.
41528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // We need to check font-family is monospace as in FontDescription but we don't want to duplicate code here.
41628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    m_shouldUseFixedDefaultFontSize = false;
417cad810f21b803229eb11403f9209855525a25d57Steve Block    extractFontSizeDelta();
41828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
41928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
420f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid EditingStyle::overrideWithStyle(const CSSMutableStyleDeclaration* style)
421f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
422f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!style || !style->length())
423f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
424f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_mutableStyle)
425f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_mutableStyle = CSSMutableStyleDeclaration::create();
426f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_mutableStyle->merge(style);
427cad810f21b803229eb11403f9209855525a25d57Steve Block    extractFontSizeDelta();
428f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
429f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
43028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid EditingStyle::clear()
43128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
43228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    m_mutableStyle.clear();
43328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    m_shouldUseFixedDefaultFontSize = false;
434cad810f21b803229eb11403f9209855525a25d57Steve Block    m_fontSizeDelta = NoFontDelta;
43528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
43628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
437f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochPassRefPtr<EditingStyle> EditingStyle::copy() const
438f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
439f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    RefPtr<EditingStyle> copy = EditingStyle::create();
440f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (m_mutableStyle)
441f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        copy->m_mutableStyle = m_mutableStyle->copy();
442f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    copy->m_shouldUseFixedDefaultFontSize = m_shouldUseFixedDefaultFontSize;
443cad810f21b803229eb11403f9209855525a25d57Steve Block    copy->m_fontSizeDelta = m_fontSizeDelta;
444f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return copy;
445f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
446f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
447f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochPassRefPtr<EditingStyle> EditingStyle::extractAndRemoveBlockProperties()
448f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
449f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    RefPtr<EditingStyle> blockProperties = EditingStyle::create();
450f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_mutableStyle)
451f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return blockProperties;
452f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
453f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    blockProperties->m_mutableStyle = m_mutableStyle->copyBlockProperties();
454f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_mutableStyle->removeBlockProperties();
455f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
456f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return blockProperties;
457f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
458f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
4592fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockPassRefPtr<EditingStyle> EditingStyle::extractAndRemoveTextDirection()
4602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
4612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RefPtr<EditingStyle> textDirection = EditingStyle::create();
4622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    textDirection->m_mutableStyle = CSSMutableStyleDeclaration::create();
4632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    textDirection->m_mutableStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueEmbed, m_mutableStyle->getPropertyPriority(CSSPropertyUnicodeBidi));
4642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    textDirection->m_mutableStyle->setProperty(CSSPropertyDirection, m_mutableStyle->getPropertyValue(CSSPropertyDirection),
4652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        m_mutableStyle->getPropertyPriority(CSSPropertyDirection));
4662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
4672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_mutableStyle->removeProperty(CSSPropertyUnicodeBidi);
4682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_mutableStyle->removeProperty(CSSPropertyDirection);
4692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
4702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return textDirection;
4712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
4722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
47328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid EditingStyle::removeBlockProperties()
47428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
47528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (!m_mutableStyle)
47628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        return;
47728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
47828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    m_mutableStyle->removeBlockProperties();
47928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
48028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
48128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid EditingStyle::removeStyleAddedByNode(Node* node)
48228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
48328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (!node || !node->parentNode())
48428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        return;
48528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    RefPtr<CSSMutableStyleDeclaration> parentStyle = editingStyleFromComputedStyle(computedStyle(node->parentNode()));
48628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    RefPtr<CSSMutableStyleDeclaration> nodeStyle = editingStyleFromComputedStyle(computedStyle(node));
48728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    parentStyle->diff(nodeStyle.get());
48828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    nodeStyle->diff(m_mutableStyle.get());
48928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
49028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
49128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid EditingStyle::removeStyleConflictingWithStyleOfNode(Node* node)
49228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
4934576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (!node || !node->parentNode() || !m_mutableStyle)
49428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        return;
49528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    RefPtr<CSSMutableStyleDeclaration> parentStyle = editingStyleFromComputedStyle(computedStyle(node->parentNode()));
49628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    RefPtr<CSSMutableStyleDeclaration> nodeStyle = editingStyleFromComputedStyle(computedStyle(node));
49728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    parentStyle->diff(nodeStyle.get());
49828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
49928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    CSSMutableStyleDeclaration::const_iterator end = nodeStyle->end();
50028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    for (CSSMutableStyleDeclaration::const_iterator it = nodeStyle->begin(); it != end; ++it)
50128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        m_mutableStyle->removeProperty(it->id());
50228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
50328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
50428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid EditingStyle::removeNonEditingProperties()
50528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
50628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (m_mutableStyle)
50728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        m_mutableStyle = copyEditingProperties(m_mutableStyle.get());
50828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
50928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
51081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid EditingStyle::collapseTextDecorationProperties()
51181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
51281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!m_mutableStyle)
51381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return;
51481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
51581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RefPtr<CSSValue> textDecorationsInEffect = m_mutableStyle->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
51681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!textDecorationsInEffect)
51781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return;
51881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
51981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    m_mutableStyle->setProperty(CSSPropertyTextDecoration, textDecorationsInEffect->cssText(), m_mutableStyle->getPropertyPriority(CSSPropertyTextDecoration));
52081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    m_mutableStyle->removeProperty(CSSPropertyWebkitTextDecorationsInEffect);
52181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
52281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
52381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch// CSS properties that create a visual difference only when applied to text.
52481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic const int textOnlyProperties[] = {
52581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    CSSPropertyTextDecoration,
52681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    CSSPropertyWebkitTextDecorationsInEffect,
52781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    CSSPropertyFontStyle,
52881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    CSSPropertyFontWeight,
52981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    CSSPropertyColor,
53081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch};
53181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
53281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochTriState EditingStyle::triStateOfStyle(CSSStyleDeclaration* styleToCompare, ShouldIgnoreTextOnlyProperties shouldIgnoreTextOnlyProperties) const
53381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
53481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RefPtr<CSSMutableStyleDeclaration> difference = getPropertiesNotIn(m_mutableStyle.get(), styleToCompare);
53581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
53681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (shouldIgnoreTextOnlyProperties == IgnoreTextOnlyProperties)
53781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        difference->removePropertiesInSet(textOnlyProperties, WTF_ARRAY_LENGTH(textOnlyProperties));
53881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
53981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!difference->length())
54081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return TrueTriState;
54181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (difference->length() == m_mutableStyle->length())
54281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return FalseTriState;
54381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
54481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return MixedTriState;
54581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
54681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
54781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool EditingStyle::conflictsWithInlineStyleOfElement(StyledElement* element, EditingStyle* extractedStyle, Vector<CSSPropertyID>* conflictingProperties) const
54881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
54981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(element);
55081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(!conflictingProperties || conflictingProperties->isEmpty());
55181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
55281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    CSSMutableStyleDeclaration* inlineStyle = element->inlineStyleDecl();
55381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!m_mutableStyle || !inlineStyle)
55481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return false;
55581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
55681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!conflictingProperties) {
55781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        CSSMutableStyleDeclaration::const_iterator end = m_mutableStyle->end();
55881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        for (CSSMutableStyleDeclaration::const_iterator it = m_mutableStyle->begin(); it != end; ++it) {
55981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            CSSPropertyID propertyID = static_cast<CSSPropertyID>(it->id());
56081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
56181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            // We don't override whitespace property of a tab span because that would collapse the tab into a space.
56281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (propertyID == CSSPropertyWhiteSpace && isTabSpanNode(element))
56381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                continue;
56481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
56581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (inlineStyle->getPropertyCSSValue(propertyID))
56681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                return true;
56781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
56881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
56981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return false;
57081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
57181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
57281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    CSSMutableStyleDeclaration::const_iterator end = m_mutableStyle->end();
57381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    for (CSSMutableStyleDeclaration::const_iterator it = m_mutableStyle->begin(); it != end; ++it) {
57481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        CSSPropertyID propertyID = static_cast<CSSPropertyID>(it->id());
57581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if ((propertyID == CSSPropertyWhiteSpace && isTabSpanNode(element)) || !inlineStyle->getPropertyCSSValue(propertyID))
57681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            continue;
57781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
57881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (propertyID == CSSPropertyUnicodeBidi && inlineStyle->getPropertyCSSValue(CSSPropertyDirection)) {
57981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (extractedStyle)
58081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                extractedStyle->setProperty(propertyID, inlineStyle->getPropertyValue(propertyID), inlineStyle->getPropertyPriority(propertyID));
58181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            conflictingProperties->append(CSSPropertyDirection);
58281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
58381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
58481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        conflictingProperties->append(propertyID);
58581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (extractedStyle)
58681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            extractedStyle->setProperty(propertyID, inlineStyle->getPropertyValue(propertyID), inlineStyle->getPropertyPriority(propertyID));
58781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
58881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
58981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return !conflictingProperties->isEmpty();
59081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
59181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
59281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool EditingStyle::conflictsWithImplicitStyleOfElement(HTMLElement* element, EditingStyle* extractedStyle, ShouldExtractMatchingStyle shouldExtractMatchingStyle) const
59381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
59481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!m_mutableStyle)
59581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return false;
59681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
59781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    static const HTMLElementEquivalent* HTMLEquivalents[] = {
59881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLElementEquivalent::create(CSSPropertyFontWeight, CSSValueBold, HTMLNames::bTag).leakPtr(),
59981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLElementEquivalent::create(CSSPropertyFontWeight, CSSValueBold, HTMLNames::strongTag).leakPtr(),
60081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLElementEquivalent::create(CSSPropertyVerticalAlign, CSSValueSub, HTMLNames::subTag).leakPtr(),
60181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLElementEquivalent::create(CSSPropertyVerticalAlign, CSSValueSuper, HTMLNames::supTag).leakPtr(),
60281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLElementEquivalent::create(CSSPropertyFontStyle, CSSValueItalic, HTMLNames::iTag).leakPtr(),
60381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLElementEquivalent::create(CSSPropertyFontStyle, CSSValueItalic, HTMLNames::emTag).leakPtr(),
60481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
60581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLTextDecorationEquivalent::create(CSSValueUnderline, HTMLNames::uTag).leakPtr(),
60681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLTextDecorationEquivalent::create(CSSValueLineThrough, HTMLNames::sTag).leakPtr(),
60781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLTextDecorationEquivalent::create(CSSValueLineThrough, HTMLNames::strikeTag).leakPtr(),
60881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    };
60981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
61081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    for (size_t i = 0; i < WTF_ARRAY_LENGTH(HTMLEquivalents); ++i) {
61181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        const HTMLElementEquivalent* equivalent = HTMLEquivalents[i];
61281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (equivalent->matches(element) && equivalent->propertyExistsInStyle(m_mutableStyle.get())
61381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            && (shouldExtractMatchingStyle == ExtractMatchingStyle || !equivalent->valueIsPresentInStyle(element, m_mutableStyle.get()))) {
61481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (extractedStyle)
61581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                equivalent->addToStyle(element, extractedStyle);
61681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            return true;
61781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
61881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
61981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return false;
62081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
62181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
62281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic const Vector<OwnPtr<HTMLAttributeEquivalent> >& htmlAttributeEquivalents()
62381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
62481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    DEFINE_STATIC_LOCAL(Vector<OwnPtr<HTMLAttributeEquivalent> >, HTMLAttributeEquivalents, ());
62581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
62681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!HTMLAttributeEquivalents.size()) {
62781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create(CSSPropertyColor, HTMLNames::fontTag, HTMLNames::colorAttr));
62881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create(CSSPropertyFontFamily, HTMLNames::fontTag, HTMLNames::faceAttr));
62981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLAttributeEquivalents.append(HTMLFontSizeEquivalent::create());
63081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
63181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create(CSSPropertyDirection, HTMLNames::dirAttr));
63281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        HTMLAttributeEquivalents.append(HTMLAttributeEquivalent::create(CSSPropertyUnicodeBidi, HTMLNames::dirAttr));
63381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
63481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
63581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return HTMLAttributeEquivalents;
63681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
63781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
63881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool EditingStyle::conflictsWithImplicitStyleOfAttributes(HTMLElement* element) const
63981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
64081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(element);
64181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!m_mutableStyle)
64281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return false;
64381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
64481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    const Vector<OwnPtr<HTMLAttributeEquivalent> >& HTMLAttributeEquivalents = htmlAttributeEquivalents();
64581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    for (size_t i = 0; i < HTMLAttributeEquivalents.size(); ++i) {
64681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (HTMLAttributeEquivalents[i]->matches(element) && HTMLAttributeEquivalents[i]->propertyExistsInStyle(m_mutableStyle.get())
64781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            && !HTMLAttributeEquivalents[i]->valueIsPresentInStyle(element, m_mutableStyle.get()))
64881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            return true;
64981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
65081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
65181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return false;
65281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
65381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
65481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool EditingStyle::extractConflictingImplicitStyleOfAttributes(HTMLElement* element, ShouldPreserveWritingDirection shouldPreserveWritingDirection,
65581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    EditingStyle* extractedStyle, Vector<QualifiedName>& conflictingAttributes, ShouldExtractMatchingStyle shouldExtractMatchingStyle) const
65681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
65781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(element);
65881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // HTMLAttributeEquivalent::addToStyle doesn't support unicode-bidi and direction properties
65981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(!extractedStyle || shouldPreserveWritingDirection == PreserveWritingDirection);
66081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!m_mutableStyle)
66181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return false;
66281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
66381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    const Vector<OwnPtr<HTMLAttributeEquivalent> >& HTMLAttributeEquivalents = htmlAttributeEquivalents();
66481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    bool removed = false;
66581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    for (size_t i = 0; i < HTMLAttributeEquivalents.size(); ++i) {
66681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        const HTMLAttributeEquivalent* equivalent = HTMLAttributeEquivalents[i].get();
66781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
66881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        // unicode-bidi and direction are pushed down separately so don't push down with other styles.
66981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (shouldPreserveWritingDirection == PreserveWritingDirection && equivalent->attributeName() == HTMLNames::dirAttr)
67081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            continue;
67181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
67281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (!equivalent->matches(element) || !equivalent->propertyExistsInStyle(m_mutableStyle.get())
67381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            || (shouldExtractMatchingStyle == DoNotExtractMatchingStyle && equivalent->valueIsPresentInStyle(element, m_mutableStyle.get())))
67481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            continue;
67581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
67681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (extractedStyle)
67781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            equivalent->addToStyle(element, extractedStyle);
67881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        conflictingAttributes.append(equivalent->attributeName());
67981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        removed = true;
68081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
68181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
68281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return removed;
68381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
68481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
6852bde8e466a4451c7319e3a072d118917957d6554Steve Blockbool EditingStyle::styleIsPresentInComputedStyleOfNode(Node* node) const
6862bde8e466a4451c7319e3a072d118917957d6554Steve Block{
6872bde8e466a4451c7319e3a072d118917957d6554Steve Block    return !m_mutableStyle || !getPropertiesNotIn(m_mutableStyle.get(), computedStyle(node).get())->length();
6882bde8e466a4451c7319e3a072d118917957d6554Steve Block}
6892bde8e466a4451c7319e3a072d118917957d6554Steve Block
6904576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangvoid EditingStyle::prepareToApplyAt(const Position& position, ShouldPreserveWritingDirection shouldPreserveWritingDirection)
69128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
6924576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (!m_mutableStyle)
6934576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        return;
6944576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
69528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // ReplaceSelectionCommand::handleStyleSpans() requires that this function only removes the editing style.
69628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // If this function was modified in the future to delete all redundant properties, then add a boolean value to indicate
69728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // which one of editingStyleAtPosition or computedStyle is called.
69828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    RefPtr<EditingStyle> style = EditingStyle::create(position);
6994576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
7004576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    RefPtr<CSSValue> unicodeBidi;
7014576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    RefPtr<CSSValue> direction;
7024576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (shouldPreserveWritingDirection == PreserveWritingDirection) {
7034576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        unicodeBidi = m_mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi);
7044576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        direction = m_mutableStyle->getPropertyCSSValue(CSSPropertyDirection);
7054576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
7064576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
70728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    style->m_mutableStyle->diff(m_mutableStyle.get());
70828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
70928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // if alpha value is zero, we don't add the background color.
71028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    RefPtr<CSSValue> backgroundColor = m_mutableStyle->getPropertyCSSValue(CSSPropertyBackgroundColor);
71128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (backgroundColor && backgroundColor->isPrimitiveValue()
71228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        && !alphaChannel(static_cast<CSSPrimitiveValue*>(backgroundColor.get())->getRGBA32Value())) {
71328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        ExceptionCode ec;
71428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        m_mutableStyle->removeProperty(CSSPropertyBackgroundColor, ec);
71528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    }
7164576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
7172bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (unicodeBidi && unicodeBidi->isPrimitiveValue()) {
7184576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        m_mutableStyle->setProperty(CSSPropertyUnicodeBidi, static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent());
7192bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (direction && direction->isPrimitiveValue())
7204576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            m_mutableStyle->setProperty(CSSPropertyDirection, static_cast<CSSPrimitiveValue*>(direction.get())->getIdent());
7214576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
72228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
72328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
72481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid EditingStyle::mergeTypingStyle(Document* document)
72528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
72681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(document);
72781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
72881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RefPtr<EditingStyle> typingStyle = document->frame()->selection()->typingStyle();
72981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!typingStyle || typingStyle == this)
73081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return;
73181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
73281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    mergeStyle(typingStyle->style());
73328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
73481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
73581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid EditingStyle::mergeInlineStyleOfElement(StyledElement* element)
73681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
73781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(element);
73881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    mergeStyle(element->inlineStyleDecl());
73981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
74081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
74181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid EditingStyle::mergeStyle(CSSMutableStyleDeclaration* style)
74281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
74381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!style)
74481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return;
74581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
74681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!m_mutableStyle) {
74781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        m_mutableStyle = style->copy();
74881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return;
74981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
75081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
75181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    CSSMutableStyleDeclaration::const_iterator end = style->end();
75281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) {
75381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        RefPtr<CSSValue> value;
75481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if ((it->id() == CSSPropertyTextDecoration || it->id() == CSSPropertyWebkitTextDecorationsInEffect) && it->value()->isValueList()) {
75581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            value = m_mutableStyle->getPropertyCSSValue(it->id());
75681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (value && !value->isValueList())
75781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                value = 0;
75881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
75981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
76081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (!value) {
76181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            ExceptionCode ec;
76281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            m_mutableStyle->setProperty(it->id(), it->value()->cssText(), it->isImportant(), ec);
76381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            continue;
76481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
76581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
76681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        CSSValueList* newTextDecorations = static_cast<CSSValueList*>(it->value());
76781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        CSSValueList* textDecorations = static_cast<CSSValueList*>(value.get());
76881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
76981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        DEFINE_STATIC_LOCAL(const RefPtr<CSSPrimitiveValue>, underline, (CSSPrimitiveValue::createIdentifier(CSSValueUnderline)));
77081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        DEFINE_STATIC_LOCAL(const RefPtr<CSSPrimitiveValue>, lineThrough, (CSSPrimitiveValue::createIdentifier(CSSValueLineThrough)));
77181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
77281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (newTextDecorations->hasValue(underline.get()) && !textDecorations->hasValue(underline.get()))
77381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            textDecorations->append(underline.get());
77481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
77581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (newTextDecorations->hasValue(lineThrough.get()) && !textDecorations->hasValue(lineThrough.get()))
77681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            textDecorations->append(lineThrough.get());
77781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    }
77881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
77981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
7802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void reconcileTextDecorationProperties(CSSMutableStyleDeclaration* style)
7812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
7822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSValue> textDecorationsInEffect = style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
7832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(CSSPropertyTextDecoration);
7842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // We shouldn't have both text-decoration and -webkit-text-decorations-in-effect because that wouldn't make sense.
7852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(!textDecorationsInEffect || !textDecoration);
7862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (textDecorationsInEffect) {
7872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        style->setProperty(CSSPropertyTextDecoration, textDecorationsInEffect->cssText());
7882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        style->removeProperty(CSSPropertyWebkitTextDecorationsInEffect);
7892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        textDecoration = textDecorationsInEffect;
7902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // If text-decoration is set to "none", remove the property because we don't want to add redundant "text-decoration: none".
7932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (textDecoration && !textDecoration->isValueList())
7942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        style->removeProperty(CSSPropertyTextDecoration);
7952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
7962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochStyleChange::StyleChange(EditingStyle* style, const Position& position)
7982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    : m_applyBold(false)
7992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_applyItalic(false)
8002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_applyUnderline(false)
8012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_applyLineThrough(false)
8022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_applySubscript(false)
8032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_applySuperscript(false)
8042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
8052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Document* document = position.anchorNode() ? position.anchorNode()->document() : 0;
8062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!style || !style->style() || !document || !document->frame())
8072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
8082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSComputedStyleDeclaration> computedStyle = position.computedStyle();
8102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSMutableStyleDeclaration> mutableStyle = getPropertiesNotIn(style->style(), computedStyle.get());
8112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    reconcileTextDecorationProperties(mutableStyle.get());
8132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!document->frame()->editor()->shouldStyleWithCSS())
8142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        extractTextStyles(document, mutableStyle.get(), computedStyle->useFixedFontDefaultSize());
8152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Changing the whitespace style in a tab span would collapse the tab into a space.
8172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (isTabSpanTextNode(position.deprecatedNode()) || isTabSpanNode((position.deprecatedNode())))
8182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        mutableStyle->removeProperty(CSSPropertyWhiteSpace);
8192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // If unicode-bidi is present in mutableStyle and direction is not, then add direction to mutableStyle.
8212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: Shouldn't this be done in getPropertiesNotIn?
8222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi) && !style->style()->getPropertyCSSValue(CSSPropertyDirection))
8232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        mutableStyle->setProperty(CSSPropertyDirection, style->style()->getPropertyValue(CSSPropertyDirection));
8242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Save the result for later
8262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_cssStyle = mutableStyle->cssText().stripWhiteSpace();
8272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
8282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void setTextDecorationProperty(CSSMutableStyleDeclaration* style, const CSSValueList* newTextDecoration, int propertyID)
8302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
8312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (newTextDecoration->length())
8322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        style->setProperty(propertyID, newTextDecoration->cssText(), style->getPropertyPriority(propertyID));
8332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    else {
8342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // text-decoration: none is redundant since it does not remove any text decorations.
8352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!style->getPropertyPriority(propertyID));
8362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        style->removeProperty(propertyID);
8372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
8392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic RGBA32 getRGBAFontColor(CSSStyleDeclaration* style)
8412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
8422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSValue> colorValue = style->getPropertyCSSValue(CSSPropertyColor);
8432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!colorValue || !colorValue->isPrimitiveValue())
8442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return Color::transparent;
8452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    CSSPrimitiveValue* primitiveColor = static_cast<CSSPrimitiveValue*>(colorValue.get());
8472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (primitiveColor->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
8482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return primitiveColor->getRGBA32Value();
8492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Need to take care of named color such as green and black
8512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // This code should be removed after https://bugs.webkit.org/show_bug.cgi?id=28282 is fixed.
8522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RGBA32 rgba = 0;
8532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    CSSParser::parseColor(rgba, colorValue->cssText());
8542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return rgba;
8552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
8562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid StyleChange::extractTextStyles(Document* document, CSSMutableStyleDeclaration* style, bool shouldUseFixedFontDefaultSize)
8582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
8592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(style);
8602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (getIdentifierValue(style, CSSPropertyFontWeight) == CSSValueBold) {
8622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        style->removeProperty(CSSPropertyFontWeight);
8632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_applyBold = true;
8642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int fontStyle = getIdentifierValue(style, CSSPropertyFontStyle);
8672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (fontStyle == CSSValueItalic || fontStyle == CSSValueOblique) {
8682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        style->removeProperty(CSSPropertyFontStyle);
8692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_applyItalic = true;
8702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Assuming reconcileTextDecorationProperties has been called, there should not be -webkit-text-decorations-in-effect
8732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Furthermore, text-decoration: none has been trimmed so that text-decoration property is always a CSSValueList.
8742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(CSSPropertyTextDecoration);
8752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (textDecoration && textDecoration->isValueList()) {
8762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, underline, (CSSPrimitiveValue::createIdentifier(CSSValueUnderline)));
8772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, lineThrough, (CSSPrimitiveValue::createIdentifier(CSSValueLineThrough)));
8782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        RefPtr<CSSValueList> newTextDecoration = static_cast<CSSValueList*>(textDecoration.get())->copy();
8802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (newTextDecoration->removeAll(underline.get()))
8812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_applyUnderline = true;
8822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (newTextDecoration->removeAll(lineThrough.get()))
8832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_applyLineThrough = true;
8842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // If trimTextDecorations, delete underline and line-through
8862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        setTextDecorationProperty(style, newTextDecoration.get(), CSSPropertyTextDecoration);
8872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int verticalAlign = getIdentifierValue(style, CSSPropertyVerticalAlign);
8902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    switch (verticalAlign) {
8912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case CSSValueSub:
8922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        style->removeProperty(CSSPropertyVerticalAlign);
8932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_applySubscript = true;
8942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        break;
8952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case CSSValueSuper:
8962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        style->removeProperty(CSSPropertyVerticalAlign);
8972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_applySuperscript = true;
8982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        break;
8992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (style->getPropertyCSSValue(CSSPropertyColor)) {
9022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_applyFontColor = Color(getRGBAFontColor(style)).serialized();
9032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        style->removeProperty(CSSPropertyColor);
9042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_applyFontFace = style->getPropertyValue(CSSPropertyFontFamily);
9072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    style->removeProperty(CSSPropertyFontFamily);
9082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (RefPtr<CSSValue> fontSize = style->getPropertyCSSValue(CSSPropertyFontSize)) {
9102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!fontSize->isPrimitiveValue())
9112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            style->removeProperty(CSSPropertyFontSize); // Can't make sense of the number. Put no font size.
9122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        else if (int legacyFontSize = legacyFontSizeFromCSSValue(document, static_cast<CSSPrimitiveValue*>(fontSize.get()),
9132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                shouldUseFixedFontDefaultSize, UseLegacyFontSizeOnlyIfPixelValuesMatch)) {
9142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_applyFontSize = String::number(legacyFontSize);
9152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            style->removeProperty(CSSPropertyFontSize);
9162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
9172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
9192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void diffTextDecorations(CSSMutableStyleDeclaration* style, int propertID, CSSValue* refTextDecoration)
9212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
9222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(propertID);
9232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!textDecoration || !textDecoration->isValueList() || !refTextDecoration || !refTextDecoration->isValueList())
9242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
9252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSValueList> newTextDecoration = static_cast<CSSValueList*>(textDecoration.get())->copy();
9272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    CSSValueList* valuesInRefTextDecoration = static_cast<CSSValueList*>(refTextDecoration);
9282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (size_t i = 0; i < valuesInRefTextDecoration->length(); i++)
9302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        newTextDecoration->removeAll(valuesInRefTextDecoration->item(i));
9312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    setTextDecorationProperty(style, newTextDecoration.get(), propertID);
9332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
9342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool fontWeightIsBold(CSSStyleDeclaration* style)
9362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
9372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(style);
9382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSValue> fontWeight = style->getPropertyCSSValue(CSSPropertyFontWeight);
9392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!fontWeight)
9412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
9422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!fontWeight->isPrimitiveValue())
9432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
9442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Because b tag can only bold text, there are only two states in plain html: bold and not bold.
9462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Collapse all other values to either one of these two states for editing purposes.
9472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    switch (static_cast<CSSPrimitiveValue*>(fontWeight.get())->getIdent()) {
9482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case CSSValue100:
9492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case CSSValue200:
9502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case CSSValue300:
9512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case CSSValue400:
9522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case CSSValue500:
9532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case CSSValueNormal:
9542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
9552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case CSSValueBold:
9562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case CSSValue600:
9572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case CSSValue700:
9582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case CSSValue800:
9592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case CSSValue900:
9602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return true;
9612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_NOT_REACHED(); // For CSSValueBolder and CSSValueLighter
9642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return false; // Make compiler happy
9652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
9662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int getTextAlignment(CSSStyleDeclaration* style)
9682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
9692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int textAlign = getIdentifierValue(style, CSSPropertyTextAlign);
9702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    switch (textAlign) {
9712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case CSSValueCenter:
9722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case CSSValueWebkitCenter:
9732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return CSSValueCenter;
9742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case CSSValueJustify:
9752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return CSSValueJustify;
9762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case CSSValueLeft:
9772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case CSSValueWebkitLeft:
9782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return CSSValueLeft;
9792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case CSSValueRight:
9802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case CSSValueWebkitRight:
9812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return CSSValueRight;
9822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return CSSValueInvalid;
9842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
9852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochRefPtr<CSSMutableStyleDeclaration> getPropertiesNotIn(CSSStyleDeclaration* styleWithRedundantProperties, CSSStyleDeclaration* baseStyle)
9872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
9882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(styleWithRedundantProperties);
9892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(baseStyle);
9902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSMutableStyleDeclaration> result = styleWithRedundantProperties->copy();
9912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    baseStyle->diff(result.get());
9922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSValue> baseTextDecorationsInEffect = baseStyle->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
9942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    diffTextDecorations(result.get(), CSSPropertyTextDecoration, baseTextDecorationsInEffect.get());
9952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    diffTextDecorations(result.get(), CSSPropertyWebkitTextDecorationsInEffect, baseTextDecorationsInEffect.get());
9962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (fontWeightIsBold(result.get()) == fontWeightIsBold(baseStyle))
9982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->removeProperty(CSSPropertyFontWeight);
9992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (getRGBAFontColor(result.get()) == getRGBAFontColor(baseStyle))
10012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->removeProperty(CSSPropertyColor);
10022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (getTextAlignment(result.get()) == getTextAlignment(baseStyle))
10042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->removeProperty(CSSPropertyTextAlign);
10052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return result;
10072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
10082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochint getIdentifierValue(CSSStyleDeclaration* style, int propertyID)
10112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
10122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!style)
10132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
10142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<CSSValue> value = style->getPropertyCSSValue(propertyID);
10162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!value || !value->isPrimitiveValue())
10172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
10182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return static_cast<CSSPrimitiveValue*>(value.get())->getIdent();
10202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
10212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool isCSSValueLength(CSSPrimitiveValue* value)
10232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
10242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return value->primitiveType() >= CSSPrimitiveValue::CSS_PX && value->primitiveType() <= CSSPrimitiveValue::CSS_PC;
10252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
10262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochint legacyFontSizeFromCSSValue(Document* document, CSSPrimitiveValue* value, bool shouldUseFixedFontDefaultSize, LegacyFontSizeMode mode)
10282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
10292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (isCSSValueLength(value)) {
10302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        int pixelFontSize = value->getIntValue(CSSPrimitiveValue::CSS_PX);
10312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        int legacyFontSize = CSSStyleSelector::legacyFontSize(document, pixelFontSize, shouldUseFixedFontDefaultSize);
10322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Use legacy font size only if pixel value matches exactly to that of legacy font size.
10332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        int cssPrimitiveEquivalent = legacyFontSize - 1 + CSSValueXSmall;
10342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (mode == AlwaysUseLegacyFontSize || CSSStyleSelector::fontSizeForKeyword(document, cssPrimitiveEquivalent, shouldUseFixedFontDefaultSize) == pixelFontSize)
10352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return legacyFontSize;
10362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
10382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
10392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (CSSValueXSmall <= value->getIdent() && value->getIdent() <= CSSValueWebkitXxxLarge)
10412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return value->getIdent() - CSSValueXSmall + 1;
10422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return 0;
10442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
10452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
104628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
1047