initial import
[vuplus_webkit] / Source / WebCore / css / CSSStyleDeclaration.cpp
1 /*
2  * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #include "config.h"
22 #include "CSSStyleDeclaration.h"
23
24 #include "CSSMutableStyleDeclaration.h"
25 #include "CSSMutableValue.h"
26 #include "CSSParser.h"
27 #include "CSSProperty.h"
28 #include "CSSPropertyNames.h"
29 #include "CSSRule.h"
30 #include "Node.h"
31 #include "SVGElement.h"
32 #include <wtf/ASCIICType.h>
33 #include <wtf/text/CString.h>
34 #ifndef NDEBUG
35 #include <stdio.h>
36 #endif
37
38 using namespace WTF;
39
40 namespace WebCore {
41
42 CSSStyleDeclaration::CSSStyleDeclaration(CSSRule* parent)
43     : StyleBase(parent)
44 {
45 }
46
47 PassRefPtr<CSSValue> CSSStyleDeclaration::getPropertyCSSValue(const String& propertyName)
48 {
49     int propID = cssPropertyID(propertyName);
50     if (!propID)
51         return 0;
52
53     // Short-cut, not involving any change to the refcount.
54     if (!isMutableStyleDeclaration())
55         return getPropertyCSSValue(propID);
56
57     // Slow path.
58     RefPtr<CSSValue> value = getPropertyCSSValue(propID);
59     if (!value || !value->isMutableValue())
60         return value.release();
61
62     Node* node = static_cast<CSSMutableStyleDeclaration*>(this)->node();
63     if (!node || !node->isStyledElement())
64         return value.release();
65
66     Node* associatedNode = static_cast<CSSMutableValue*>(value.get())->node();
67     if (associatedNode) {
68         ASSERT(associatedNode == node);
69         return value.release();
70     }
71
72     static_cast<CSSMutableValue*>(value.get())->setNode(node);
73     return value.release();
74 }
75
76 String CSSStyleDeclaration::getPropertyValue(const String &propertyName)
77 {
78     int propID = cssPropertyID(propertyName);
79     if (!propID)
80         return String();
81     return getPropertyValue(propID);
82 }
83
84 String CSSStyleDeclaration::getPropertyPriority(const String& propertyName)
85 {
86     int propID = cssPropertyID(propertyName);
87     if (!propID)
88         return String();
89     return getPropertyPriority(propID) ? "important" : "";
90 }
91
92 String CSSStyleDeclaration::getPropertyShorthand(const String& propertyName)
93 {
94     int propID = cssPropertyID(propertyName);
95     if (!propID)
96         return String();
97     int shorthandID = getPropertyShorthand(propID);
98     if (!shorthandID)
99         return String();
100     return getPropertyName(static_cast<CSSPropertyID>(shorthandID));
101 }
102
103 bool CSSStyleDeclaration::isPropertyImplicit(const String& propertyName)
104 {
105     int propID = cssPropertyID(propertyName);
106     if (!propID)
107         return false;
108     return isPropertyImplicit(propID);
109 }
110
111 void CSSStyleDeclaration::setProperty(const String& propertyName, const String& value, ExceptionCode& ec)
112 {
113     size_t important = value.find("!important", 0, false);
114     int propertyID = cssPropertyID(propertyName);
115     if (!propertyID)
116         return;
117     if (important == notFound)
118         setProperty(propertyID, value, false, ec);
119     else
120         setProperty(propertyID, value.left(important - 1), true, ec);
121 }
122
123 void CSSStyleDeclaration::setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode& ec)
124 {
125     int propID = cssPropertyID(propertyName);
126     if (!propID) {
127         // FIXME: Should we raise an exception here?
128         return;
129     }
130     bool important = priority.find("important", 0, false) != notFound;
131     setProperty(propID, value, important, ec);
132 }
133
134 String CSSStyleDeclaration::removeProperty(const String& propertyName, ExceptionCode& ec)
135 {
136     int propID = cssPropertyID(propertyName);
137     if (!propID)
138         return String();
139     return removeProperty(propID, ec);
140 }
141
142 bool CSSStyleDeclaration::isPropertyName(const String& propertyName)
143 {
144     return cssPropertyID(propertyName);
145 }
146
147 CSSRule* CSSStyleDeclaration::parentRule() const
148 {
149     return (parent() && parent()->isRule()) ? static_cast<CSSRule*>(parent()) : 0;
150 }
151
152 bool CSSStyleDeclaration::cssPropertyMatches(const CSSProperty* property) const
153 {
154     RefPtr<CSSValue> value = getPropertyCSSValue(property->id());
155     return value && value->cssText() == property->value()->cssText();
156 }
157
158 void CSSStyleDeclaration::diff(CSSMutableStyleDeclaration* style) const
159 {
160     if (!style)
161         return;
162
163     Vector<int> propertiesToRemove;
164     {
165         CSSMutableStyleDeclaration::const_iterator end = style->end();
166         for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) {
167             const CSSProperty& property = *it;
168             if (cssPropertyMatches(&property))
169                 propertiesToRemove.append(property.id());
170         }
171     }
172
173     // FIXME: This should use mass removal.
174     for (unsigned i = 0; i < propertiesToRemove.size(); i++)
175         style->removeProperty(propertiesToRemove[i]);
176 }
177
178 PassRefPtr<CSSMutableStyleDeclaration> CSSStyleDeclaration::copyPropertiesInSet(const int* set, unsigned length) const
179 {
180     Vector<CSSProperty> list;
181     list.reserveInitialCapacity(length);
182     for (unsigned i = 0; i < length; i++) {
183         RefPtr<CSSValue> value = getPropertyCSSValue(set[i]);
184         if (value)
185             list.append(CSSProperty(set[i], value.release(), false));
186     }
187     return CSSMutableStyleDeclaration::create(list);
188 }
189
190 #ifndef NDEBUG
191 void CSSStyleDeclaration::showStyle()
192 {
193     fprintf(stderr, "%s\n", cssText().ascii().data());
194 }
195 #endif
196
197 } // namespace WebCore