|
1 /* |
|
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
|
3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) |
|
4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) |
|
5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. |
|
6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> |
|
7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> |
|
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) |
|
9 * |
|
10 * This library is free software; you can redistribute it and/or |
|
11 * modify it under the terms of the GNU Library General Public |
|
12 * License as published by the Free Software Foundation; either |
|
13 * version 2 of the License, or (at your option) any later version. |
|
14 * |
|
15 * This library is distributed in the hope that it will be useful, |
|
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
18 * Library General Public License for more details. |
|
19 * |
|
20 * You should have received a copy of the GNU Library General Public License |
|
21 * along with this library; see the file COPYING.LIB. If not, write to |
|
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
23 * Boston, MA 02110-1301, USA. |
|
24 */ |
|
25 |
|
26 #include "config.h" |
|
27 #include "CSSStyleSelector.h" |
|
28 |
|
29 #include "Attribute.h" |
|
30 #include "CSSBorderImageValue.h" |
|
31 #include "CSSCursorImageValue.h" |
|
32 #include "CSSFontFaceRule.h" |
|
33 #include "CSSImportRule.h" |
|
34 #include "CSSMediaRule.h" |
|
35 #include "CSSPageRule.h" |
|
36 #include "CSSParser.h" |
|
37 #include "CSSPrimitiveValueMappings.h" |
|
38 #include "CSSPropertyNames.h" |
|
39 #include "CSSReflectValue.h" |
|
40 #include "CSSRuleList.h" |
|
41 #include "CSSSelector.h" |
|
42 #include "CSSSelectorList.h" |
|
43 #include "CSSStyleRule.h" |
|
44 #include "CSSStyleSheet.h" |
|
45 #include "CSSTimingFunctionValue.h" |
|
46 #include "CSSValueList.h" |
|
47 #include "CSSVariableDependentValue.h" |
|
48 #include "CSSVariablesDeclaration.h" |
|
49 #include "CSSVariablesRule.h" |
|
50 #include "CachedImage.h" |
|
51 #include "Counter.h" |
|
52 #include "CounterContent.h" |
|
53 #include "FocusController.h" |
|
54 #include "FontFamilyValue.h" |
|
55 #include "FontValue.h" |
|
56 #include "Frame.h" |
|
57 #include "FrameView.h" |
|
58 #include "HTMLDocument.h" |
|
59 #include "HTMLElement.h" |
|
60 #include "HTMLInputElement.h" |
|
61 #include "HTMLNames.h" |
|
62 #include "HTMLTextAreaElement.h" |
|
63 #include "KeyframeList.h" |
|
64 #include "LinkHash.h" |
|
65 #include "Matrix3DTransformOperation.h" |
|
66 #include "MatrixTransformOperation.h" |
|
67 #include "MediaList.h" |
|
68 #include "MediaQueryEvaluator.h" |
|
69 #include "NodeRenderStyle.h" |
|
70 #include "Page.h" |
|
71 #include "PageGroup.h" |
|
72 #include "Pair.h" |
|
73 #include "PerspectiveTransformOperation.h" |
|
74 #include "Rect.h" |
|
75 #include "RenderScrollbar.h" |
|
76 #include "RenderScrollbarTheme.h" |
|
77 #include "RenderStyleConstants.h" |
|
78 #include "RenderTheme.h" |
|
79 #include "RotateTransformOperation.h" |
|
80 #include "ScaleTransformOperation.h" |
|
81 #include "SelectionController.h" |
|
82 #include "Settings.h" |
|
83 #include "ShadowValue.h" |
|
84 #include "SkewTransformOperation.h" |
|
85 #include "StyleCachedImage.h" |
|
86 #include "StyleGeneratedImage.h" |
|
87 #include "StyleSheetList.h" |
|
88 #include "Text.h" |
|
89 #include "TransformationMatrix.h" |
|
90 #include "TranslateTransformOperation.h" |
|
91 #include "UserAgentStyleSheets.h" |
|
92 #include "WebKitCSSKeyframeRule.h" |
|
93 #include "WebKitCSSKeyframesRule.h" |
|
94 #include "WebKitCSSTransformValue.h" |
|
95 #include "XMLNames.h" |
|
96 #include "loader.h" |
|
97 #include <wtf/StdLibExtras.h> |
|
98 #include <wtf/Vector.h> |
|
99 |
|
100 #if ENABLE(DASHBOARD_SUPPORT) |
|
101 #include "DashboardRegion.h" |
|
102 #endif |
|
103 |
|
104 #if ENABLE(SVG) |
|
105 #include "XLinkNames.h" |
|
106 #include "SVGNames.h" |
|
107 #endif |
|
108 |
|
109 #if ENABLE(WML) |
|
110 #include "WMLNames.h" |
|
111 #endif |
|
112 |
|
113 #if PLATFORM(QT) |
|
114 #include <qwebhistoryinterface.h> |
|
115 #endif |
|
116 |
|
117 using namespace std; |
|
118 |
|
119 namespace WebCore { |
|
120 |
|
121 using namespace HTMLNames; |
|
122 |
|
123 // #define STYLE_SHARING_STATS 1 |
|
124 |
|
125 #define HANDLE_INHERIT(prop, Prop) \ |
|
126 if (isInherit) { \ |
|
127 m_style->set##Prop(m_parentStyle->prop()); \ |
|
128 return; \ |
|
129 } |
|
130 |
|
131 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ |
|
132 HANDLE_INHERIT(prop, Prop) \ |
|
133 if (isInitial) { \ |
|
134 m_style->set##Prop(RenderStyle::initial##Prop()); \ |
|
135 return; \ |
|
136 } |
|
137 |
|
138 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \ |
|
139 HANDLE_INHERIT(prop, Prop) \ |
|
140 if (isInitial) { \ |
|
141 m_style->set##Prop(RenderStyle::initial##Value());\ |
|
142 return;\ |
|
143 } |
|
144 |
|
145 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \ |
|
146 HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ |
|
147 if (primitiveValue) \ |
|
148 m_style->set##Prop(*primitiveValue); |
|
149 |
|
150 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(prop, Prop, Value) \ |
|
151 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \ |
|
152 if (primitiveValue) \ |
|
153 m_style->set##Prop(*primitiveValue); |
|
154 |
|
155 #define HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \ |
|
156 if (isInherit) { \ |
|
157 FillLayer* currChild = m_style->access##LayerType##Layers(); \ |
|
158 FillLayer* prevChild = 0; \ |
|
159 const FillLayer* currParent = m_parentStyle->layerType##Layers(); \ |
|
160 while (currParent && currParent->is##Prop##Set()) { \ |
|
161 if (!currChild) { \ |
|
162 /* Need to make a new layer.*/ \ |
|
163 currChild = new FillLayer(LayerType##FillLayer); \ |
|
164 prevChild->setNext(currChild); \ |
|
165 } \ |
|
166 currChild->set##Prop(currParent->prop()); \ |
|
167 prevChild = currChild; \ |
|
168 currChild = prevChild->next(); \ |
|
169 currParent = currParent->next(); \ |
|
170 } \ |
|
171 \ |
|
172 while (currChild) { \ |
|
173 /* Reset any remaining layers to not have the property set. */ \ |
|
174 currChild->clear##Prop(); \ |
|
175 currChild = currChild->next(); \ |
|
176 } \ |
|
177 } else if (isInitial) { \ |
|
178 FillLayer* currChild = m_style->access##LayerType##Layers(); \ |
|
179 currChild->set##Prop(FillLayer::initialFill##Prop(LayerType##FillLayer)); \ |
|
180 for (currChild = currChild->next(); currChild; currChild = currChild->next()) \ |
|
181 currChild->clear##Prop(); \ |
|
182 } |
|
183 |
|
184 #define HANDLE_FILL_LAYER_VALUE(layerType, LayerType, prop, Prop, value) { \ |
|
185 HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \ |
|
186 if (isInherit || isInitial) \ |
|
187 return; \ |
|
188 FillLayer* currChild = m_style->access##LayerType##Layers(); \ |
|
189 FillLayer* prevChild = 0; \ |
|
190 if (value->isValueList()) { \ |
|
191 /* Walk each value and put it into a layer, creating new layers as needed. */ \ |
|
192 CSSValueList* valueList = static_cast<CSSValueList*>(value); \ |
|
193 for (unsigned int i = 0; i < valueList->length(); i++) { \ |
|
194 if (!currChild) { \ |
|
195 /* Need to make a new layer to hold this value */ \ |
|
196 currChild = new FillLayer(LayerType##FillLayer); \ |
|
197 prevChild->setNext(currChild); \ |
|
198 } \ |
|
199 mapFill##Prop(currChild, valueList->itemWithoutBoundsCheck(i)); \ |
|
200 prevChild = currChild; \ |
|
201 currChild = currChild->next(); \ |
|
202 } \ |
|
203 } else { \ |
|
204 mapFill##Prop(currChild, value); \ |
|
205 currChild = currChild->next(); \ |
|
206 } \ |
|
207 while (currChild) { \ |
|
208 /* Reset all remaining layers to not have the property set. */ \ |
|
209 currChild->clear##Prop(); \ |
|
210 currChild = currChild->next(); \ |
|
211 } } |
|
212 |
|
213 #define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \ |
|
214 HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(background, Background, prop, Prop) |
|
215 |
|
216 #define HANDLE_BACKGROUND_VALUE(prop, Prop, value) \ |
|
217 HANDLE_FILL_LAYER_VALUE(background, Background, prop, Prop, value) |
|
218 |
|
219 #define HANDLE_MASK_INHERIT_AND_INITIAL(prop, Prop) \ |
|
220 HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(mask, Mask, prop, Prop) |
|
221 |
|
222 #define HANDLE_MASK_VALUE(prop, Prop, value) \ |
|
223 HANDLE_FILL_LAYER_VALUE(mask, Mask, prop, Prop, value) |
|
224 |
|
225 #define HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \ |
|
226 if (isInherit) { \ |
|
227 AnimationList* list = m_style->accessAnimations(); \ |
|
228 const AnimationList* parentList = m_parentStyle->animations(); \ |
|
229 size_t i = 0, parentSize = parentList ? parentList->size() : 0; \ |
|
230 for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \ |
|
231 if (list->size() <= i) \ |
|
232 list->append(Animation::create()); \ |
|
233 list->animation(i)->set##Prop(parentList->animation(i)->prop()); \ |
|
234 } \ |
|
235 \ |
|
236 /* Reset any remaining animations to not have the property set. */ \ |
|
237 for ( ; i < list->size(); ++i) \ |
|
238 list->animation(i)->clear##Prop(); \ |
|
239 } else if (isInitial) { \ |
|
240 AnimationList* list = m_style->accessAnimations(); \ |
|
241 if (list->isEmpty()) \ |
|
242 list->append(Animation::create()); \ |
|
243 list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \ |
|
244 for (size_t i = 1; i < list->size(); ++i) \ |
|
245 list->animation(0)->clear##Prop(); \ |
|
246 } |
|
247 |
|
248 #define HANDLE_ANIMATION_VALUE(prop, Prop, value) { \ |
|
249 HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \ |
|
250 if (isInherit || isInitial) \ |
|
251 return; \ |
|
252 AnimationList* list = m_style->accessAnimations(); \ |
|
253 size_t childIndex = 0; \ |
|
254 if (value->isValueList()) { \ |
|
255 /* Walk each value and put it into an animation, creating new animations as needed. */ \ |
|
256 CSSValueList* valueList = static_cast<CSSValueList*>(value); \ |
|
257 for (unsigned int i = 0; i < valueList->length(); i++) { \ |
|
258 if (childIndex <= list->size()) \ |
|
259 list->append(Animation::create()); \ |
|
260 mapAnimation##Prop(list->animation(childIndex), valueList->itemWithoutBoundsCheck(i)); \ |
|
261 ++childIndex; \ |
|
262 } \ |
|
263 } else { \ |
|
264 if (list->isEmpty()) \ |
|
265 list->append(Animation::create()); \ |
|
266 mapAnimation##Prop(list->animation(childIndex), value); \ |
|
267 childIndex = 1; \ |
|
268 } \ |
|
269 for ( ; childIndex < list->size(); ++childIndex) { \ |
|
270 /* Reset all remaining animations to not have the property set. */ \ |
|
271 list->animation(childIndex)->clear##Prop(); \ |
|
272 } \ |
|
273 } |
|
274 |
|
275 #define HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \ |
|
276 if (isInherit) { \ |
|
277 AnimationList* list = m_style->accessTransitions(); \ |
|
278 const AnimationList* parentList = m_parentStyle->transitions(); \ |
|
279 size_t i = 0, parentSize = parentList ? parentList->size() : 0; \ |
|
280 for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \ |
|
281 if (list->size() <= i) \ |
|
282 list->append(Animation::create()); \ |
|
283 list->animation(i)->set##Prop(parentList->animation(i)->prop()); \ |
|
284 } \ |
|
285 \ |
|
286 /* Reset any remaining transitions to not have the property set. */ \ |
|
287 for ( ; i < list->size(); ++i) \ |
|
288 list->animation(i)->clear##Prop(); \ |
|
289 } else if (isInitial) { \ |
|
290 AnimationList* list = m_style->accessTransitions(); \ |
|
291 if (list->isEmpty()) \ |
|
292 list->append(Animation::create()); \ |
|
293 list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \ |
|
294 for (size_t i = 1; i < list->size(); ++i) \ |
|
295 list->animation(0)->clear##Prop(); \ |
|
296 } |
|
297 |
|
298 #define HANDLE_TRANSITION_VALUE(prop, Prop, value) { \ |
|
299 HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \ |
|
300 if (isInherit || isInitial) \ |
|
301 return; \ |
|
302 AnimationList* list = m_style->accessTransitions(); \ |
|
303 size_t childIndex = 0; \ |
|
304 if (value->isValueList()) { \ |
|
305 /* Walk each value and put it into a transition, creating new animations as needed. */ \ |
|
306 CSSValueList* valueList = static_cast<CSSValueList*>(value); \ |
|
307 for (unsigned int i = 0; i < valueList->length(); i++) { \ |
|
308 if (childIndex <= list->size()) \ |
|
309 list->append(Animation::create()); \ |
|
310 mapAnimation##Prop(list->animation(childIndex), valueList->itemWithoutBoundsCheck(i)); \ |
|
311 ++childIndex; \ |
|
312 } \ |
|
313 } else { \ |
|
314 if (list->isEmpty()) \ |
|
315 list->append(Animation::create()); \ |
|
316 mapAnimation##Prop(list->animation(childIndex), value); \ |
|
317 childIndex = 1; \ |
|
318 } \ |
|
319 for ( ; childIndex < list->size(); ++childIndex) { \ |
|
320 /* Reset all remaining transitions to not have the property set. */ \ |
|
321 list->animation(childIndex)->clear##Prop(); \ |
|
322 } \ |
|
323 } |
|
324 |
|
325 #define HANDLE_INHERIT_COND(propID, prop, Prop) \ |
|
326 if (id == propID) { \ |
|
327 m_style->set##Prop(m_parentStyle->prop()); \ |
|
328 return; \ |
|
329 } |
|
330 |
|
331 #define HANDLE_INHERIT_COND_WITH_BACKUP(propID, prop, propAlt, Prop) \ |
|
332 if (id == propID) { \ |
|
333 if (m_parentStyle->prop().isValid()) \ |
|
334 m_style->set##Prop(m_parentStyle->prop()); \ |
|
335 else \ |
|
336 m_style->set##Prop(m_parentStyle->propAlt()); \ |
|
337 return; \ |
|
338 } |
|
339 |
|
340 #define HANDLE_INITIAL_COND(propID, Prop) \ |
|
341 if (id == propID) { \ |
|
342 m_style->set##Prop(RenderStyle::initial##Prop()); \ |
|
343 return; \ |
|
344 } |
|
345 |
|
346 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \ |
|
347 if (id == propID) { \ |
|
348 m_style->set##Prop(RenderStyle::initial##Value()); \ |
|
349 return; \ |
|
350 } |
|
351 |
|
352 class CSSRuleSet : public Noncopyable { |
|
353 public: |
|
354 CSSRuleSet(); |
|
355 ~CSSRuleSet(); |
|
356 |
|
357 typedef HashMap<AtomicStringImpl*, CSSRuleDataList*> AtomRuleMap; |
|
358 |
|
359 void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0); |
|
360 |
|
361 void addStyleRule(StyleBase* item); |
|
362 void addRule(CSSStyleRule* rule, CSSSelector* sel); |
|
363 void addPageRule(CSSStyleRule* rule, CSSSelector* sel); |
|
364 void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, |
|
365 CSSStyleRule* rule, CSSSelector* sel); |
|
366 |
|
367 CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); } |
|
368 CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); } |
|
369 CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); } |
|
370 CSSRuleDataList* getUniversalRules() { return m_universalRules; } |
|
371 CSSRuleDataList* getPageRules() { return m_pageRules; } |
|
372 |
|
373 public: |
|
374 AtomRuleMap m_idRules; |
|
375 AtomRuleMap m_classRules; |
|
376 AtomRuleMap m_tagRules; |
|
377 CSSRuleDataList* m_universalRules; |
|
378 CSSRuleDataList* m_pageRules; |
|
379 unsigned m_ruleCount; |
|
380 unsigned m_pageRuleCount; |
|
381 }; |
|
382 |
|
383 static CSSRuleSet* defaultStyle; |
|
384 static CSSRuleSet* defaultQuirksStyle; |
|
385 static CSSRuleSet* defaultPrintStyle; |
|
386 static CSSRuleSet* defaultViewSourceStyle; |
|
387 static CSSStyleSheet* simpleDefaultStyleSheet; |
|
388 |
|
389 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable; |
|
390 |
|
391 static void loadFullDefaultStyle(); |
|
392 static void loadSimpleDefaultStyle(); |
|
393 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet. |
|
394 static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}"; |
|
395 |
|
396 static bool elementCanUseSimpleDefaultStyle(Element* e) |
|
397 { |
|
398 return e->hasTagName(htmlTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag); |
|
399 } |
|
400 |
|
401 static const MediaQueryEvaluator& screenEval() |
|
402 { |
|
403 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen")); |
|
404 return staticScreenEval; |
|
405 } |
|
406 |
|
407 static const MediaQueryEvaluator& printEval() |
|
408 { |
|
409 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print")); |
|
410 return staticPrintEval; |
|
411 } |
|
412 |
|
413 CSSStyleSelector::CSSStyleSelector(Document* doc, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet, |
|
414 CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets, |
|
415 bool strictParsing, bool matchAuthorAndUserStyles) |
|
416 : m_backgroundData(BackgroundFillLayer) |
|
417 , m_checker(doc, strictParsing) |
|
418 , m_element(0) |
|
419 , m_styledElement(0) |
|
420 , m_elementLinkState(NotInsideLink) |
|
421 , m_fontSelector(CSSFontSelector::create(doc)) |
|
422 { |
|
423 init(); |
|
424 |
|
425 m_matchAuthorAndUserStyles = matchAuthorAndUserStyles; |
|
426 |
|
427 Element* root = doc->documentElement(); |
|
428 |
|
429 if (!defaultStyle) { |
|
430 if (!root || elementCanUseSimpleDefaultStyle(root)) |
|
431 loadSimpleDefaultStyle(); |
|
432 else |
|
433 loadFullDefaultStyle(); |
|
434 } |
|
435 |
|
436 m_userStyle = 0; |
|
437 |
|
438 // construct document root element default style. this is needed |
|
439 // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)" |
|
440 // This is here instead of constructor, because when constructor is run, |
|
441 // document doesn't have documentElement |
|
442 // NOTE: this assumes that element that gets passed to styleForElement -call |
|
443 // is always from the document that owns the style selector |
|
444 FrameView* view = doc->view(); |
|
445 if (view) |
|
446 m_medium = new MediaQueryEvaluator(view->mediaType()); |
|
447 else |
|
448 m_medium = new MediaQueryEvaluator("all"); |
|
449 |
|
450 if (root) |
|
451 m_rootDefaultStyle = styleForElement(root, 0, false, true); // don't ref, because the RenderStyle is allocated from global heap |
|
452 |
|
453 if (m_rootDefaultStyle && view) { |
|
454 delete m_medium; |
|
455 m_medium = new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()); |
|
456 } |
|
457 |
|
458 // FIXME: This sucks! The user sheet is reparsed every time! |
|
459 if (pageUserSheet || pageGroupUserSheets) { |
|
460 m_userStyle = new CSSRuleSet(); |
|
461 if (pageUserSheet) |
|
462 m_userStyle->addRulesFromSheet(pageUserSheet, *m_medium, this); |
|
463 if (pageGroupUserSheets) { |
|
464 unsigned length = pageGroupUserSheets->size(); |
|
465 for (unsigned i = 0; i < length; i++) |
|
466 m_userStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this); |
|
467 } |
|
468 } |
|
469 |
|
470 // add stylesheets from document |
|
471 m_authorStyle = new CSSRuleSet(); |
|
472 |
|
473 // Add rules from elements like SVG's <font-face> |
|
474 if (mappedElementSheet) |
|
475 m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this); |
|
476 |
|
477 unsigned length = styleSheets->length(); |
|
478 for (unsigned i = 0; i < length; i++) { |
|
479 StyleSheet* sheet = styleSheets->item(i); |
|
480 if (sheet->isCSSStyleSheet() && !sheet->disabled()) |
|
481 m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this); |
|
482 } |
|
483 |
|
484 if (doc->renderer() && doc->renderer()->style()) |
|
485 doc->renderer()->style()->font().update(fontSelector()); |
|
486 } |
|
487 |
|
488 // This is a simplified style setting function for keyframe styles |
|
489 void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule) |
|
490 { |
|
491 AtomicString s(rule->name()); |
|
492 m_keyframesRuleMap.add(s.impl(), rule); |
|
493 } |
|
494 |
|
495 void CSSStyleSelector::init() |
|
496 { |
|
497 initElement(0); |
|
498 m_matchedDecls.clear(); |
|
499 m_ruleList = 0; |
|
500 m_rootDefaultStyle = 0; |
|
501 m_medium = 0; |
|
502 } |
|
503 |
|
504 CSSStyleSelector::~CSSStyleSelector() |
|
505 { |
|
506 m_fontSelector->clearDocument(); |
|
507 delete m_medium; |
|
508 delete m_authorStyle; |
|
509 delete m_userStyle; |
|
510 deleteAllValues(m_viewportDependentMediaQueryResults); |
|
511 m_keyframesRuleMap.clear(); |
|
512 } |
|
513 |
|
514 static CSSStyleSheet* parseUASheet(const String& str) |
|
515 { |
|
516 CSSStyleSheet* sheet = CSSStyleSheet::create().releaseRef(); // leak the sheet on purpose |
|
517 sheet->parseString(str); |
|
518 return sheet; |
|
519 } |
|
520 |
|
521 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size) |
|
522 { |
|
523 return parseUASheet(String(characters, size)); |
|
524 } |
|
525 |
|
526 static void loadFullDefaultStyle() |
|
527 { |
|
528 if (simpleDefaultStyleSheet) { |
|
529 ASSERT(defaultStyle); |
|
530 delete defaultStyle; |
|
531 simpleDefaultStyleSheet->deref(); |
|
532 defaultStyle = new CSSRuleSet; |
|
533 simpleDefaultStyleSheet = 0; |
|
534 } else { |
|
535 ASSERT(!defaultStyle); |
|
536 defaultStyle = new CSSRuleSet; |
|
537 defaultPrintStyle = new CSSRuleSet; |
|
538 defaultQuirksStyle = new CSSRuleSet; |
|
539 } |
|
540 |
|
541 // Strict-mode rules. |
|
542 String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet(); |
|
543 CSSStyleSheet* defaultSheet = parseUASheet(defaultRules); |
|
544 defaultStyle->addRulesFromSheet(defaultSheet, screenEval()); |
|
545 defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval()); |
|
546 |
|
547 // Quirks-mode rules. |
|
548 String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet(); |
|
549 CSSStyleSheet* quirksSheet = parseUASheet(quirksRules); |
|
550 defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval()); |
|
551 } |
|
552 |
|
553 static void loadSimpleDefaultStyle() |
|
554 { |
|
555 ASSERT(!defaultStyle); |
|
556 ASSERT(!simpleDefaultStyleSheet); |
|
557 |
|
558 defaultStyle = new CSSRuleSet; |
|
559 defaultPrintStyle = new CSSRuleSet; |
|
560 defaultQuirksStyle = new CSSRuleSet; |
|
561 |
|
562 simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet)); |
|
563 defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval()); |
|
564 |
|
565 // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style. |
|
566 } |
|
567 |
|
568 static void loadViewSourceStyle() |
|
569 { |
|
570 ASSERT(!defaultViewSourceStyle); |
|
571 defaultViewSourceStyle = new CSSRuleSet; |
|
572 defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval()); |
|
573 } |
|
574 |
|
575 void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* decl) |
|
576 { |
|
577 if (!decl->hasVariableDependentValue()) { |
|
578 m_matchedDecls.append(decl); |
|
579 return; |
|
580 } |
|
581 |
|
582 // See if we have already resolved the variables in this declaration. |
|
583 CSSMutableStyleDeclaration* resolvedDecl = m_resolvedVariablesDeclarations.get(decl).get(); |
|
584 if (resolvedDecl) { |
|
585 m_matchedDecls.append(resolvedDecl); |
|
586 return; |
|
587 } |
|
588 |
|
589 // If this declaration has any variables in it, then we need to make a cloned |
|
590 // declaration with as many variables resolved as possible for this style selector's media. |
|
591 RefPtr<CSSMutableStyleDeclaration> newDecl = CSSMutableStyleDeclaration::create(decl->parentRule()); |
|
592 m_matchedDecls.append(newDecl.get()); |
|
593 m_resolvedVariablesDeclarations.set(decl, newDecl); |
|
594 |
|
595 HashSet<String> usedBlockVariables; |
|
596 resolveVariablesForDeclaration(decl, newDecl.get(), usedBlockVariables); |
|
597 } |
|
598 |
|
599 void CSSStyleSelector::resolveVariablesForDeclaration(CSSMutableStyleDeclaration* decl, CSSMutableStyleDeclaration* newDecl, HashSet<String>& usedBlockVariables) |
|
600 { |
|
601 // Now iterate over the properties in the original declaration. As we resolve variables we'll end up |
|
602 // mutating the new declaration (possibly expanding shorthands). The new declaration has no m_node |
|
603 // though, so it can't mistakenly call setChanged on anything. |
|
604 CSSMutableStyleDeclaration::const_iterator end = decl->end(); |
|
605 for (CSSMutableStyleDeclaration::const_iterator it = decl->begin(); it != end; ++it) { |
|
606 const CSSProperty& current = *it; |
|
607 if (!current.value()->isVariableDependentValue()) { |
|
608 // We can just add the parsed property directly. |
|
609 newDecl->addParsedProperty(current); |
|
610 continue; |
|
611 } |
|
612 CSSValueList* valueList = static_cast<CSSVariableDependentValue*>(current.value())->valueList(); |
|
613 if (!valueList) |
|
614 continue; |
|
615 CSSParserValueList resolvedValueList; |
|
616 unsigned s = valueList->length(); |
|
617 bool fullyResolved = true; |
|
618 for (unsigned i = 0; i < s; ++i) { |
|
619 CSSValue* val = valueList->item(i); |
|
620 CSSPrimitiveValue* primitiveValue = val->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(val) : 0; |
|
621 if (primitiveValue && primitiveValue->isVariable()) { |
|
622 CSSVariablesRule* rule = m_variablesMap.get(primitiveValue->getStringValue()); |
|
623 if (!rule || !rule->variables()) { |
|
624 fullyResolved = false; |
|
625 break; |
|
626 } |
|
627 |
|
628 if (current.id() == CSSPropertyWebkitVariableDeclarationBlock && s == 1) { |
|
629 fullyResolved = false; |
|
630 if (!usedBlockVariables.contains(primitiveValue->getStringValue())) { |
|
631 CSSMutableStyleDeclaration* declBlock = rule->variables()->getParsedVariableDeclarationBlock(primitiveValue->getStringValue()); |
|
632 if (declBlock) { |
|
633 usedBlockVariables.add(primitiveValue->getStringValue()); |
|
634 resolveVariablesForDeclaration(declBlock, newDecl, usedBlockVariables); |
|
635 } |
|
636 } |
|
637 } |
|
638 |
|
639 CSSValueList* resolvedVariable = rule->variables()->getParsedVariable(primitiveValue->getStringValue()); |
|
640 if (!resolvedVariable) { |
|
641 fullyResolved = false; |
|
642 break; |
|
643 } |
|
644 unsigned valueSize = resolvedVariable->length(); |
|
645 for (unsigned j = 0; j < valueSize; ++j) |
|
646 resolvedValueList.addValue(resolvedVariable->item(j)->parserValue()); |
|
647 } else |
|
648 resolvedValueList.addValue(val->parserValue()); |
|
649 } |
|
650 |
|
651 if (!fullyResolved) |
|
652 continue; |
|
653 |
|
654 // We now have a fully resolved new value list. We want the parser to use this value list |
|
655 // and parse our new declaration. |
|
656 CSSParser(m_checker.m_strictParsing).parsePropertyWithResolvedVariables(current.id(), current.isImportant(), newDecl, &resolvedValueList); |
|
657 } |
|
658 } |
|
659 |
|
660 void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex) |
|
661 { |
|
662 m_matchedRules.clear(); |
|
663 |
|
664 if (!rules || !m_element) |
|
665 return; |
|
666 |
|
667 // We need to collect the rules for id, class, tag, and everything else into a buffer and |
|
668 // then sort the buffer. |
|
669 if (m_element->hasID()) |
|
670 matchRulesForList(rules->getIDRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex); |
|
671 if (m_element->hasClass()) { |
|
672 ASSERT(m_styledElement); |
|
673 const SpaceSplitString& classNames = m_styledElement->classNames(); |
|
674 size_t size = classNames.size(); |
|
675 for (size_t i = 0; i < size; ++i) |
|
676 matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex); |
|
677 } |
|
678 matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex); |
|
679 matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex); |
|
680 |
|
681 // If we didn't match any rules, we're done. |
|
682 if (m_matchedRules.isEmpty()) |
|
683 return; |
|
684 |
|
685 // Sort the set of matched rules. |
|
686 sortMatchedRules(0, m_matchedRules.size()); |
|
687 |
|
688 // Now transfer the set of matched rules over to our list of decls. |
|
689 if (!m_checker.m_collectRulesOnly) { |
|
690 for (unsigned i = 0; i < m_matchedRules.size(); i++) |
|
691 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration()); |
|
692 } else { |
|
693 for (unsigned i = 0; i < m_matchedRules.size(); i++) { |
|
694 if (!m_ruleList) |
|
695 m_ruleList = CSSRuleList::create(); |
|
696 m_ruleList->append(m_matchedRules[i]->rule()); |
|
697 } |
|
698 } |
|
699 } |
|
700 |
|
701 void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex) |
|
702 { |
|
703 if (!rules) |
|
704 return; |
|
705 |
|
706 for (CSSRuleData* d = rules->first(); d; d = d->next()) { |
|
707 CSSStyleRule* rule = d->rule(); |
|
708 if (checkSelector(d->selector())) { |
|
709 // If the rule has no properties to apply, then ignore it. |
|
710 CSSMutableStyleDeclaration* decl = rule->declaration(); |
|
711 if (!decl || !decl->length()) |
|
712 continue; |
|
713 |
|
714 // If we're matching normal rules, set a pseudo bit if |
|
715 // we really just matched a pseudo-element. |
|
716 if (m_dynamicPseudo != NOPSEUDO && m_checker.m_pseudoStyle == NOPSEUDO) { |
|
717 if (m_checker.m_collectRulesOnly) |
|
718 continue; |
|
719 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID) |
|
720 m_style->setHasPseudoStyle(m_dynamicPseudo); |
|
721 } else { |
|
722 // Update our first/last rule indices in the matched rules array. |
|
723 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size(); |
|
724 if (firstRuleIndex == -1) |
|
725 firstRuleIndex = lastRuleIndex; |
|
726 |
|
727 // Add this rule to our list of matched rules. |
|
728 addMatchedRule(d); |
|
729 } |
|
730 } |
|
731 } |
|
732 } |
|
733 |
|
734 static bool operator >(CSSRuleData& r1, CSSRuleData& r2) |
|
735 { |
|
736 int spec1 = r1.selector()->specificity(); |
|
737 int spec2 = r2.selector()->specificity(); |
|
738 return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2; |
|
739 } |
|
740 |
|
741 static bool operator <=(CSSRuleData& r1, CSSRuleData& r2) |
|
742 { |
|
743 return !(r1 > r2); |
|
744 } |
|
745 |
|
746 void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end) |
|
747 { |
|
748 if (start >= end || (end - start == 1)) |
|
749 return; // Sanity check. |
|
750 |
|
751 if (end - start <= 6) { |
|
752 // Apply a bubble sort for smaller lists. |
|
753 for (unsigned i = end - 1; i > start; i--) { |
|
754 bool sorted = true; |
|
755 for (unsigned j = start; j < i; j++) { |
|
756 CSSRuleData* elt = m_matchedRules[j]; |
|
757 CSSRuleData* elt2 = m_matchedRules[j + 1]; |
|
758 if (*elt > *elt2) { |
|
759 sorted = false; |
|
760 m_matchedRules[j] = elt2; |
|
761 m_matchedRules[j + 1] = elt; |
|
762 } |
|
763 } |
|
764 if (sorted) |
|
765 return; |
|
766 } |
|
767 return; |
|
768 } |
|
769 |
|
770 // Perform a merge sort for larger lists. |
|
771 unsigned mid = (start + end) / 2; |
|
772 sortMatchedRules(start, mid); |
|
773 sortMatchedRules(mid, end); |
|
774 |
|
775 CSSRuleData* elt = m_matchedRules[mid - 1]; |
|
776 CSSRuleData* elt2 = m_matchedRules[mid]; |
|
777 |
|
778 // Handle the fast common case (of equal specificity). The list may already |
|
779 // be completely sorted. |
|
780 if (*elt <= *elt2) |
|
781 return; |
|
782 |
|
783 // We have to merge sort. Ensure our merge buffer is big enough to hold |
|
784 // all the items. |
|
785 Vector<CSSRuleData*> rulesMergeBuffer; |
|
786 rulesMergeBuffer.reserveInitialCapacity(end - start); |
|
787 |
|
788 unsigned i1 = start; |
|
789 unsigned i2 = mid; |
|
790 |
|
791 elt = m_matchedRules[i1]; |
|
792 elt2 = m_matchedRules[i2]; |
|
793 |
|
794 while (i1 < mid || i2 < end) { |
|
795 if (i1 < mid && (i2 == end || *elt <= *elt2)) { |
|
796 rulesMergeBuffer.append(elt); |
|
797 if (++i1 < mid) |
|
798 elt = m_matchedRules[i1]; |
|
799 } else { |
|
800 rulesMergeBuffer.append(elt2); |
|
801 if (++i2 < end) |
|
802 elt2 = m_matchedRules[i2]; |
|
803 } |
|
804 } |
|
805 |
|
806 for (unsigned i = start; i < end; i++) |
|
807 m_matchedRules[i] = rulesMergeBuffer[i - start]; |
|
808 } |
|
809 |
|
810 inline EInsideLink CSSStyleSelector::SelectorChecker::determineLinkState(Element* element) const |
|
811 { |
|
812 if (!element || !element->isLink()) |
|
813 return NotInsideLink; |
|
814 return determineLinkStateSlowCase(element); |
|
815 } |
|
816 |
|
817 inline void CSSStyleSelector::initElement(Element* e) |
|
818 { |
|
819 if (m_element != e) { |
|
820 m_element = e; |
|
821 m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0; |
|
822 m_elementLinkState = m_checker.determineLinkState(m_element); |
|
823 } |
|
824 } |
|
825 |
|
826 inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID) |
|
827 { |
|
828 m_checker.m_pseudoStyle = pseudoID; |
|
829 |
|
830 m_parentNode = e ? e->parentNode() : 0; |
|
831 |
|
832 #if ENABLE(SVG) |
|
833 if (!m_parentNode && e && e->isSVGElement() && e->isShadowNode()) |
|
834 m_parentNode = e->shadowParentNode(); |
|
835 #endif |
|
836 |
|
837 if (parentStyle) |
|
838 m_parentStyle = parentStyle; |
|
839 else |
|
840 m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0; |
|
841 |
|
842 Node* docElement = e ? e->document()->documentElement() : 0; |
|
843 RenderStyle* docStyle = m_checker.m_document->renderStyle(); |
|
844 m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle; |
|
845 |
|
846 m_style = 0; |
|
847 |
|
848 m_matchedDecls.clear(); |
|
849 |
|
850 m_ruleList = 0; |
|
851 |
|
852 m_fontDirty = false; |
|
853 } |
|
854 |
|
855 static inline const AtomicString* linkAttribute(Node* node) |
|
856 { |
|
857 if (!node->isLink()) |
|
858 return 0; |
|
859 |
|
860 ASSERT(node->isElementNode()); |
|
861 Element* element = static_cast<Element*>(node); |
|
862 if (element->isHTMLElement()) |
|
863 return &element->fastGetAttribute(hrefAttr); |
|
864 |
|
865 #if ENABLE(WML) |
|
866 if (element->isWMLElement()) { |
|
867 // <anchor> elements don't have href attributes, but we still want to |
|
868 // appear as link, so linkAttribute() has to return a non-null value! |
|
869 if (element->hasTagName(WMLNames::anchorTag)) |
|
870 return &emptyAtom; |
|
871 |
|
872 return &element->fastGetAttribute(hrefAttr); |
|
873 } |
|
874 #endif |
|
875 |
|
876 #if ENABLE(SVG) |
|
877 if (element->isSVGElement()) |
|
878 return &element->fastGetAttribute(XLinkNames::hrefAttr); |
|
879 #endif |
|
880 |
|
881 return 0; |
|
882 } |
|
883 |
|
884 CSSStyleSelector::SelectorChecker::SelectorChecker(Document* document, bool strictParsing) |
|
885 : m_document(document) |
|
886 , m_strictParsing(strictParsing) |
|
887 , m_collectRulesOnly(false) |
|
888 , m_pseudoStyle(NOPSEUDO) |
|
889 , m_documentIsHTML(document->isHTMLDocument()) |
|
890 , m_matchVisitedPseudoClass(false) |
|
891 { |
|
892 } |
|
893 |
|
894 EInsideLink CSSStyleSelector::SelectorChecker::determineLinkStateSlowCase(Element* element) const |
|
895 { |
|
896 ASSERT(element->isLink()); |
|
897 |
|
898 const AtomicString* attr = linkAttribute(element); |
|
899 if (!attr || attr->isNull()) |
|
900 return NotInsideLink; |
|
901 |
|
902 #if PLATFORM(QT) |
|
903 Vector<UChar, 512> url; |
|
904 visitedURL(m_document->baseURL(), *attr, url); |
|
905 if (url.isEmpty()) |
|
906 return InsideUnvisitedLink; |
|
907 |
|
908 // If the Qt4.4 interface for the history is used, we will have to fallback |
|
909 // to the old global history. |
|
910 QWebHistoryInterface* iface = QWebHistoryInterface::defaultInterface(); |
|
911 if (iface) |
|
912 return iface->historyContains(QString(reinterpret_cast<QChar*>(url.data()), url.size())) ? InsideVisitedLink : InsideUnvisitedLink; |
|
913 |
|
914 LinkHash hash = visitedLinkHash(url.data(), url.size()); |
|
915 if (!hash) |
|
916 return InsideUnvisitedLink; |
|
917 #else |
|
918 LinkHash hash = visitedLinkHash(m_document->baseURL(), *attr); |
|
919 if (!hash) |
|
920 return InsideUnvisitedLink; |
|
921 #endif |
|
922 |
|
923 Frame* frame = m_document->frame(); |
|
924 if (!frame) |
|
925 return InsideUnvisitedLink; |
|
926 |
|
927 Page* page = frame->page(); |
|
928 if (!page) |
|
929 return InsideUnvisitedLink; |
|
930 |
|
931 m_linksCheckedForVisitedState.add(hash); |
|
932 return page->group().isLinkVisited(hash) ? InsideVisitedLink : InsideUnvisitedLink; |
|
933 } |
|
934 |
|
935 bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const |
|
936 { |
|
937 PseudoId dynamicPseudo = NOPSEUDO; |
|
938 return checkSelector(sel, element, 0, dynamicPseudo, false, false) == SelectorMatches; |
|
939 } |
|
940 |
|
941 #ifdef STYLE_SHARING_STATS |
|
942 static int fraction = 0; |
|
943 static int total = 0; |
|
944 #endif |
|
945 |
|
946 static const unsigned cStyleSearchThreshold = 10; |
|
947 |
|
948 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth) |
|
949 { |
|
950 if (parent && parent->isStyledElement()) { |
|
951 StyledElement* p = static_cast<StyledElement*>(parent); |
|
952 if (!p->inlineStyleDecl() && !p->hasID()) { |
|
953 Node* r = p->previousSibling(); |
|
954 unsigned subcount = 0; |
|
955 RenderStyle* st = p->renderStyle(); |
|
956 while (r) { |
|
957 if (r->renderStyle() == st) |
|
958 return r->lastChild(); |
|
959 if (subcount++ == cStyleSearchThreshold) |
|
960 return 0; |
|
961 r = r->previousSibling(); |
|
962 } |
|
963 if (!r && depth < cStyleSearchThreshold) |
|
964 r = locateCousinList(parent->parentElement(), depth + 1); |
|
965 while (r) { |
|
966 if (r->renderStyle() == st) |
|
967 return r->lastChild(); |
|
968 if (subcount++ == cStyleSearchThreshold) |
|
969 return 0; |
|
970 r = r->previousSibling(); |
|
971 } |
|
972 } |
|
973 } |
|
974 return 0; |
|
975 } |
|
976 |
|
977 bool CSSStyleSelector::canShareStyleWithElement(Node* n) |
|
978 { |
|
979 if (n->isStyledElement()) { |
|
980 StyledElement* s = static_cast<StyledElement*>(n); |
|
981 RenderStyle* style = s->renderStyle(); |
|
982 if (style && !style->unique() && |
|
983 (s->tagQName() == m_element->tagQName()) && !s->hasID() && |
|
984 (s->hasClass() == m_element->hasClass()) && !s->inlineStyleDecl() && |
|
985 (s->hasMappedAttributes() == m_styledElement->hasMappedAttributes()) && |
|
986 (s->isLink() == m_element->isLink()) && |
|
987 !style->affectedByAttributeSelectors() && |
|
988 (s->hovered() == m_element->hovered()) && |
|
989 (s->active() == m_element->active()) && |
|
990 (s->focused() == m_element->focused()) && |
|
991 (s != s->document()->cssTarget() && m_element != m_element->document()->cssTarget()) && |
|
992 (s->fastGetAttribute(typeAttr) == m_element->fastGetAttribute(typeAttr)) && |
|
993 (s->fastGetAttribute(XMLNames::langAttr) == m_element->fastGetAttribute(XMLNames::langAttr)) && |
|
994 (s->fastGetAttribute(langAttr) == m_element->fastGetAttribute(langAttr)) && |
|
995 (s->fastGetAttribute(readonlyAttr) == m_element->fastGetAttribute(readonlyAttr)) && |
|
996 (s->fastGetAttribute(cellpaddingAttr) == m_element->fastGetAttribute(cellpaddingAttr))) { |
|
997 bool isControl = s->isFormControlElement(); |
|
998 if (isControl != m_element->isFormControlElement()) |
|
999 return false; |
|
1000 if (isControl) { |
|
1001 InputElement* thisInputElement = toInputElement(s); |
|
1002 InputElement* otherInputElement = toInputElement(m_element); |
|
1003 if (thisInputElement && otherInputElement) { |
|
1004 if ((thisInputElement->isAutofilled() != otherInputElement->isAutofilled()) || |
|
1005 (thisInputElement->isChecked() != otherInputElement->isChecked()) || |
|
1006 (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())) |
|
1007 return false; |
|
1008 } else |
|
1009 return false; |
|
1010 |
|
1011 if (s->isEnabledFormControl() != m_element->isEnabledFormControl()) |
|
1012 return false; |
|
1013 |
|
1014 if (s->isDefaultButtonForForm() != m_element->isDefaultButtonForForm()) |
|
1015 return false; |
|
1016 |
|
1017 if (!m_element->document()->containsValidityStyleRules()) |
|
1018 return false; |
|
1019 |
|
1020 bool willValidate = s->willValidate(); |
|
1021 if (willValidate != m_element->willValidate()) |
|
1022 return false; |
|
1023 |
|
1024 if (willValidate && (s->isValidFormControlElement() != m_element->isValidFormControlElement())) |
|
1025 return false; |
|
1026 } |
|
1027 |
|
1028 if (style->transitions() || style->animations()) |
|
1029 return false; |
|
1030 |
|
1031 bool classesMatch = true; |
|
1032 if (s->hasClass()) { |
|
1033 const AtomicString& class1 = m_element->fastGetAttribute(classAttr); |
|
1034 const AtomicString& class2 = s->fastGetAttribute(classAttr); |
|
1035 classesMatch = (class1 == class2); |
|
1036 } |
|
1037 |
|
1038 if (classesMatch) { |
|
1039 bool mappedAttrsMatch = true; |
|
1040 if (s->hasMappedAttributes()) |
|
1041 mappedAttrsMatch = s->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap()); |
|
1042 if (mappedAttrsMatch) { |
|
1043 if (s->isLink()) { |
|
1044 if (m_elementLinkState != style->insideLink()) |
|
1045 return false; |
|
1046 } |
|
1047 return true; |
|
1048 } |
|
1049 } |
|
1050 } |
|
1051 } |
|
1052 return false; |
|
1053 } |
|
1054 |
|
1055 ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle() |
|
1056 { |
|
1057 if (m_styledElement && !m_styledElement->inlineStyleDecl() && !m_styledElement->hasID() && !m_styledElement->document()->usesSiblingRules()) { |
|
1058 // Check previous siblings. |
|
1059 unsigned count = 0; |
|
1060 Node* n; |
|
1061 for (n = m_element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { } |
|
1062 while (n) { |
|
1063 if (canShareStyleWithElement(n)) |
|
1064 return n->renderStyle(); |
|
1065 if (count++ == cStyleSearchThreshold) |
|
1066 return 0; |
|
1067 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { } |
|
1068 } |
|
1069 if (!n) |
|
1070 n = locateCousinList(m_element->parentElement()); |
|
1071 while (n) { |
|
1072 if (canShareStyleWithElement(n)) |
|
1073 return n->renderStyle(); |
|
1074 if (count++ == cStyleSearchThreshold) |
|
1075 return 0; |
|
1076 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { } |
|
1077 } |
|
1078 } |
|
1079 return 0; |
|
1080 } |
|
1081 |
|
1082 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule) |
|
1083 { |
|
1084 // First we match rules from the user agent sheet. |
|
1085 CSSRuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print") |
|
1086 ? defaultPrintStyle : defaultStyle; |
|
1087 matchRules(userAgentStyleSheet, firstUARule, lastUARule); |
|
1088 |
|
1089 // In quirks mode, we match rules from the quirks user agent sheet. |
|
1090 if (!m_checker.m_strictParsing) |
|
1091 matchRules(defaultQuirksStyle, firstUARule, lastUARule); |
|
1092 |
|
1093 // If we're in view source mode, then we match rules from the view source style sheet. |
|
1094 if (m_checker.m_document->frame() && m_checker.m_document->frame()->inViewSourceMode()) { |
|
1095 if (!defaultViewSourceStyle) |
|
1096 loadViewSourceStyle(); |
|
1097 matchRules(defaultViewSourceStyle, firstUARule, lastUARule); |
|
1098 } |
|
1099 } |
|
1100 |
|
1101 PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document) |
|
1102 { |
|
1103 FrameView* view = document->view(); |
|
1104 |
|
1105 RefPtr<RenderStyle> documentStyle = RenderStyle::create(); |
|
1106 documentStyle->setDisplay(BLOCK); |
|
1107 documentStyle->setVisuallyOrdered(document->visuallyOrdered()); |
|
1108 documentStyle->setZoom(view ? view->pageZoomFactor() : 1); |
|
1109 |
|
1110 FontDescription fontDescription; |
|
1111 fontDescription.setUsePrinterFont(document->printing()); |
|
1112 if (Settings* settings = document->settings()) { |
|
1113 fontDescription.setRenderingMode(settings->fontRenderingMode()); |
|
1114 if (document->printing() && !settings->shouldPrintBackgrounds()) |
|
1115 documentStyle->setForceBackgroundsToWhite(true); |
|
1116 const AtomicString& stdfont = settings->standardFontFamily(); |
|
1117 if (!stdfont.isEmpty()) { |
|
1118 fontDescription.firstFamily().setFamily(stdfont); |
|
1119 fontDescription.firstFamily().appendFamily(0); |
|
1120 } |
|
1121 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); |
|
1122 int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false); |
|
1123 fontDescription.setSpecifiedSize(size); |
|
1124 bool useSVGZoomRules = document->isSVGDocument(); |
|
1125 fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules)); |
|
1126 } |
|
1127 |
|
1128 documentStyle->setFontDescription(fontDescription); |
|
1129 documentStyle->font().update(0); |
|
1130 if (document->inCompatMode()) |
|
1131 documentStyle->setHtmlHacks(true); // enable html specific rendering tricks |
|
1132 |
|
1133 return documentStyle.release(); |
|
1134 } |
|
1135 |
|
1136 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where |
|
1137 // relative units are interpreted according to document root element style, styled only with UA stylesheet |
|
1138 |
|
1139 PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault, bool matchVisitedPseudoClass) |
|
1140 { |
|
1141 // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer |
|
1142 // will vanish if a style recalc happens during loading. |
|
1143 if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) { |
|
1144 if (!s_styleNotYetAvailable) { |
|
1145 s_styleNotYetAvailable = RenderStyle::create().releaseRef(); |
|
1146 s_styleNotYetAvailable->ref(); |
|
1147 s_styleNotYetAvailable->setDisplay(NONE); |
|
1148 s_styleNotYetAvailable->font().update(m_fontSelector); |
|
1149 } |
|
1150 s_styleNotYetAvailable->ref(); |
|
1151 e->document()->setHasNodesWithPlaceholderStyle(); |
|
1152 return s_styleNotYetAvailable; |
|
1153 } |
|
1154 |
|
1155 initElement(e); |
|
1156 if (allowSharing) { |
|
1157 RenderStyle* sharedStyle = locateSharedStyle(); |
|
1158 if (sharedStyle) |
|
1159 return sharedStyle; |
|
1160 } |
|
1161 initForStyleResolve(e, defaultParent); |
|
1162 |
|
1163 // Compute our style allowing :visited to match first. |
|
1164 RefPtr<RenderStyle> visitedStyle; |
|
1165 if (!matchVisitedPseudoClass && m_parentStyle && (m_parentStyle->insideLink() || e->isLink()) && e->document()->usesLinkRules()) { |
|
1166 // Fetch our parent style. |
|
1167 RenderStyle* parentStyle = m_parentStyle; |
|
1168 if (!e->isLink()) { |
|
1169 // Use the parent's visited style if one exists. |
|
1170 RenderStyle* parentVisitedStyle = m_parentStyle->getCachedPseudoStyle(VISITED_LINK); |
|
1171 if (parentVisitedStyle) |
|
1172 parentStyle = parentVisitedStyle; |
|
1173 } |
|
1174 visitedStyle = styleForElement(e, parentStyle, false, false, true); |
|
1175 if (visitedStyle) { |
|
1176 if (m_elementLinkState == InsideUnvisitedLink) |
|
1177 visitedStyle = 0; // We made the style to avoid timing attacks. Just throw it away now that we did that, since we don't need it. |
|
1178 else |
|
1179 visitedStyle->setStyleType(VISITED_LINK); |
|
1180 } |
|
1181 initForStyleResolve(e, defaultParent); |
|
1182 } |
|
1183 |
|
1184 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass; |
|
1185 |
|
1186 m_style = RenderStyle::create(); |
|
1187 |
|
1188 if (m_parentStyle) |
|
1189 m_style->inheritFrom(m_parentStyle); |
|
1190 else |
|
1191 m_parentStyle = style(); |
|
1192 |
|
1193 if (e->isLink()) { |
|
1194 m_style->setIsLink(true); |
|
1195 m_style->setInsideLink(m_elementLinkState); |
|
1196 } |
|
1197 |
|
1198 if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(e)) |
|
1199 loadFullDefaultStyle(); |
|
1200 |
|
1201 #if ENABLE(SVG) |
|
1202 static bool loadedSVGUserAgentSheet; |
|
1203 if (e->isSVGElement() && !loadedSVGUserAgentSheet) { |
|
1204 // SVG rules. |
|
1205 loadedSVGUserAgentSheet = true; |
|
1206 CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet)); |
|
1207 defaultStyle->addRulesFromSheet(svgSheet, screenEval()); |
|
1208 defaultPrintStyle->addRulesFromSheet(svgSheet, printEval()); |
|
1209 } |
|
1210 #endif |
|
1211 |
|
1212 #if ENABLE(MATHML) |
|
1213 static bool loadedMathMLUserAgentSheet; |
|
1214 if (e->isMathMLElement() && !loadedMathMLUserAgentSheet) { |
|
1215 // MathML rules. |
|
1216 loadedMathMLUserAgentSheet = true; |
|
1217 CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet)); |
|
1218 defaultStyle->addRulesFromSheet(mathMLSheet, screenEval()); |
|
1219 defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval()); |
|
1220 } |
|
1221 #endif |
|
1222 |
|
1223 #if ENABLE(WML) |
|
1224 static bool loadedWMLUserAgentSheet; |
|
1225 if (e->isWMLElement() && !loadedWMLUserAgentSheet) { |
|
1226 // WML rules. |
|
1227 loadedWMLUserAgentSheet = true; |
|
1228 CSSStyleSheet* wmlSheet = parseUASheet(wmlUserAgentStyleSheet, sizeof(wmlUserAgentStyleSheet)); |
|
1229 defaultStyle->addRulesFromSheet(wmlSheet, screenEval()); |
|
1230 defaultPrintStyle->addRulesFromSheet(wmlSheet, printEval()); |
|
1231 } |
|
1232 #endif |
|
1233 |
|
1234 #if ENABLE(VIDEO) |
|
1235 static bool loadedMediaStyleSheet; |
|
1236 if (!loadedMediaStyleSheet && (e->hasTagName(videoTag) || e->hasTagName(audioTag))) { |
|
1237 loadedMediaStyleSheet = true; |
|
1238 String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraMediaControlsStyleSheet(); |
|
1239 CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules); |
|
1240 defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval()); |
|
1241 defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval()); |
|
1242 } |
|
1243 #endif |
|
1244 |
|
1245 int firstUARule = -1, lastUARule = -1; |
|
1246 int firstUserRule = -1, lastUserRule = -1; |
|
1247 int firstAuthorRule = -1, lastAuthorRule = -1; |
|
1248 matchUARules(firstUARule, lastUARule); |
|
1249 |
|
1250 if (!resolveForRootDefault) { |
|
1251 // 4. Now we check user sheet rules. |
|
1252 if (m_matchAuthorAndUserStyles) |
|
1253 matchRules(m_userStyle, firstUserRule, lastUserRule); |
|
1254 |
|
1255 // 5. Now check author rules, beginning first with presentational attributes |
|
1256 // mapped from HTML. |
|
1257 if (m_styledElement) { |
|
1258 // Ask if the HTML element has mapped attributes. |
|
1259 if (m_styledElement->hasMappedAttributes()) { |
|
1260 // Walk our attribute list and add in each decl. |
|
1261 const NamedNodeMap* map = m_styledElement->attributeMap(); |
|
1262 for (unsigned i = 0; i < map->length(); i++) { |
|
1263 Attribute* attr = map->attributeItem(i); |
|
1264 if (attr->isMappedAttribute() && attr->decl()) { |
|
1265 lastAuthorRule = m_matchedDecls.size(); |
|
1266 if (firstAuthorRule == -1) |
|
1267 firstAuthorRule = lastAuthorRule; |
|
1268 addMatchedDeclaration(attr->decl()); |
|
1269 } |
|
1270 } |
|
1271 } |
|
1272 |
|
1273 // Now we check additional mapped declarations. |
|
1274 // Tables and table cells share an additional mapped rule that must be applied |
|
1275 // after all attributes, since their mapped style depends on the values of multiple attributes. |
|
1276 if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) { |
|
1277 m_additionalAttributeStyleDecls.clear(); |
|
1278 m_styledElement->additionalAttributeStyleDecls(m_additionalAttributeStyleDecls); |
|
1279 if (!m_additionalAttributeStyleDecls.isEmpty()) { |
|
1280 unsigned additionalDeclsSize = m_additionalAttributeStyleDecls.size(); |
|
1281 if (firstAuthorRule == -1) |
|
1282 firstAuthorRule = m_matchedDecls.size(); |
|
1283 lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1; |
|
1284 for (unsigned i = 0; i < additionalDeclsSize; i++) |
|
1285 addMatchedDeclaration(m_additionalAttributeStyleDecls[i]); |
|
1286 } |
|
1287 } |
|
1288 } |
|
1289 |
|
1290 // 6. Check the rules in author sheets next. |
|
1291 if (m_matchAuthorAndUserStyles) |
|
1292 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule); |
|
1293 |
|
1294 // 7. Now check our inline style attribute. |
|
1295 if (m_matchAuthorAndUserStyles && m_styledElement) { |
|
1296 CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl(); |
|
1297 if (inlineDecl) { |
|
1298 lastAuthorRule = m_matchedDecls.size(); |
|
1299 if (firstAuthorRule == -1) |
|
1300 firstAuthorRule = lastAuthorRule; |
|
1301 addMatchedDeclaration(inlineDecl); |
|
1302 } |
|
1303 } |
|
1304 } |
|
1305 |
|
1306 // Reset the value back before applying properties, so that -webkit-link knows what color to use. |
|
1307 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass; |
|
1308 |
|
1309 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply |
|
1310 // high-priority properties first, i.e., those properties that other properties depend on. |
|
1311 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important |
|
1312 // and (4) normal important. |
|
1313 m_lineHeightValue = 0; |
|
1314 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1); |
|
1315 if (!resolveForRootDefault) { |
|
1316 applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule); |
|
1317 applyDeclarations<true>(true, firstUserRule, lastUserRule); |
|
1318 } |
|
1319 applyDeclarations<true>(true, firstUARule, lastUARule); |
|
1320 |
|
1321 // If our font got dirtied, go ahead and update it now. |
|
1322 if (m_fontDirty) |
|
1323 updateFont(); |
|
1324 |
|
1325 // Line-height is set when we are sure we decided on the font-size |
|
1326 if (m_lineHeightValue) |
|
1327 applyProperty(CSSPropertyLineHeight, m_lineHeightValue); |
|
1328 |
|
1329 // Now do the normal priority UA properties. |
|
1330 applyDeclarations<false>(false, firstUARule, lastUARule); |
|
1331 |
|
1332 // Cache our border and background so that we can examine them later. |
|
1333 cacheBorderAndBackground(); |
|
1334 |
|
1335 // Now do the author and user normal priority properties and all the !important properties. |
|
1336 if (!resolveForRootDefault) { |
|
1337 applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1); |
|
1338 applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule); |
|
1339 applyDeclarations<false>(true, firstUserRule, lastUserRule); |
|
1340 } |
|
1341 applyDeclarations<false>(true, firstUARule, lastUARule); |
|
1342 |
|
1343 // If our font got dirtied by one of the non-essential font props, |
|
1344 // go ahead and update it a second time. |
|
1345 if (m_fontDirty) |
|
1346 updateFont(); |
|
1347 |
|
1348 // Clean up our style object's display and text decorations (among other fixups). |
|
1349 adjustRenderStyle(style(), e); |
|
1350 |
|
1351 // If we have first-letter pseudo style, do not share this style |
|
1352 if (m_style->hasPseudoStyle(FIRST_LETTER)) |
|
1353 m_style->setUnique(); |
|
1354 |
|
1355 if (visitedStyle) { |
|
1356 // Copy any pseudo bits that the visited style has to the primary style so that |
|
1357 // pseudo element styles will continue to work for pseudo elements inside :visited |
|
1358 // links. |
|
1359 for (unsigned pseudo = FIRST_PUBLIC_PSEUDOID; pseudo < FIRST_INTERNAL_PSEUDOID; ++pseudo) { |
|
1360 if (visitedStyle->hasPseudoStyle(static_cast<PseudoId>(pseudo))) |
|
1361 m_style->setHasPseudoStyle(static_cast<PseudoId>(pseudo)); |
|
1362 } |
|
1363 |
|
1364 // Add the visited style off the main style. |
|
1365 m_style->addCachedPseudoStyle(visitedStyle.release()); |
|
1366 } |
|
1367 |
|
1368 if (!matchVisitedPseudoClass) |
|
1369 initElement(0); // Clear out for the next resolve. |
|
1370 |
|
1371 // Now return the style. |
|
1372 return m_style.release(); |
|
1373 } |
|
1374 |
|
1375 PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeList& list) |
|
1376 { |
|
1377 if (keyframeRule->style()) |
|
1378 addMatchedDeclaration(keyframeRule->style()); |
|
1379 |
|
1380 ASSERT(!m_style); |
|
1381 |
|
1382 // Create the style |
|
1383 m_style = RenderStyle::clone(elementStyle); |
|
1384 |
|
1385 m_lineHeightValue = 0; |
|
1386 |
|
1387 // We don't need to bother with !important. Since there is only ever one |
|
1388 // decl, there's nothing to override. So just add the first properties. |
|
1389 if (keyframeRule->style()) |
|
1390 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1); |
|
1391 |
|
1392 // If our font got dirtied, go ahead and update it now. |
|
1393 if (m_fontDirty) |
|
1394 updateFont(); |
|
1395 |
|
1396 // Line-height is set when we are sure we decided on the font-size |
|
1397 if (m_lineHeightValue) |
|
1398 applyProperty(CSSPropertyLineHeight, m_lineHeightValue); |
|
1399 |
|
1400 // Now do rest of the properties. |
|
1401 if (keyframeRule->style()) |
|
1402 applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1); |
|
1403 |
|
1404 // If our font got dirtied by one of the non-essential font props, |
|
1405 // go ahead and update it a second time. |
|
1406 if (m_fontDirty) |
|
1407 updateFont(); |
|
1408 |
|
1409 // Add all the animating properties to the list |
|
1410 if (keyframeRule->style()) { |
|
1411 CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end(); |
|
1412 for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) { |
|
1413 int property = (*it).id(); |
|
1414 // Timing-function within keyframes is special, because it is not animated; it just |
|
1415 // describes the timing function between this keyframe and the next. |
|
1416 if (property != CSSPropertyWebkitAnimationTimingFunction) |
|
1417 list.addProperty(property); |
|
1418 } |
|
1419 } |
|
1420 |
|
1421 return m_style.release(); |
|
1422 } |
|
1423 |
|
1424 void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list) |
|
1425 { |
|
1426 list.clear(); |
|
1427 |
|
1428 // Get the keyframesRule for this name |
|
1429 if (!e || list.animationName().isEmpty()) |
|
1430 return; |
|
1431 |
|
1432 m_keyframesRuleMap.checkConsistency(); |
|
1433 |
|
1434 if (!m_keyframesRuleMap.contains(list.animationName().impl())) |
|
1435 return; |
|
1436 |
|
1437 const WebKitCSSKeyframesRule* rule = m_keyframesRuleMap.find(list.animationName().impl()).get()->second.get(); |
|
1438 RefPtr<RenderStyle> keyframeStyle; |
|
1439 |
|
1440 // Construct and populate the style for each keyframe |
|
1441 for (unsigned i = 0; i < rule->length(); ++i) { |
|
1442 // Apply the declaration to the style. This is a simplified version of the logic in styleForElement |
|
1443 initElement(e); |
|
1444 initForStyleResolve(e); |
|
1445 |
|
1446 const WebKitCSSKeyframeRule* keyframeRule = rule->item(i); |
|
1447 |
|
1448 keyframeStyle = styleForKeyframe(elementStyle, keyframeRule, list); |
|
1449 |
|
1450 // Add this keyframe style to all the indicated key times |
|
1451 Vector<float> keys; |
|
1452 keyframeRule->getKeys(keys); |
|
1453 for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) { |
|
1454 float key = keys[keyIndex]; |
|
1455 list.insert(key, keyframeStyle.get()); |
|
1456 } |
|
1457 keyframeStyle.release(); |
|
1458 } |
|
1459 |
|
1460 // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe) |
|
1461 int initialListSize = list.size(); |
|
1462 if (initialListSize > 0 && list.beginKeyframes()->key() != 0) { |
|
1463 RefPtr<WebKitCSSKeyframeRule> keyframe = WebKitCSSKeyframeRule::create(); |
|
1464 keyframe->setKeyText("0%"); |
|
1465 keyframeStyle = styleForKeyframe(elementStyle, keyframe.get(), list); |
|
1466 list.insert(0, keyframeStyle.release()); |
|
1467 } |
|
1468 |
|
1469 // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe) |
|
1470 if (initialListSize > 0 && (list.endKeyframes() - 1)->key() != 1) { |
|
1471 RefPtr<WebKitCSSKeyframeRule> keyframe = WebKitCSSKeyframeRule::create(); |
|
1472 keyframe->setKeyText("100%"); |
|
1473 keyframeStyle = styleForKeyframe(elementStyle, keyframe.get(), list); |
|
1474 list.insert(1, keyframeStyle.release()); |
|
1475 } |
|
1476 } |
|
1477 |
|
1478 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle, bool matchVisitedPseudoClass) |
|
1479 { |
|
1480 if (!e) |
|
1481 return 0; |
|
1482 |
|
1483 initElement(e); |
|
1484 |
|
1485 // Compute our :visited style first, so that we know whether or not we'll need to create a normal style just to hang it |
|
1486 // off of. |
|
1487 RefPtr<RenderStyle> visitedStyle; |
|
1488 if (!matchVisitedPseudoClass && parentStyle && parentStyle->insideLink()) { |
|
1489 // Fetch our parent style with :visited in effect. |
|
1490 RenderStyle* parentVisitedStyle = parentStyle->getCachedPseudoStyle(VISITED_LINK); |
|
1491 visitedStyle = pseudoStyleForElement(pseudo, e, parentVisitedStyle ? parentVisitedStyle : parentStyle, true); |
|
1492 if (visitedStyle) { |
|
1493 if (m_elementLinkState == InsideUnvisitedLink) |
|
1494 visitedStyle = 0; // We made the style to avoid timing attacks. Just throw it away now that we did that. |
|
1495 else |
|
1496 visitedStyle->setStyleType(VISITED_LINK); |
|
1497 } |
|
1498 } |
|
1499 |
|
1500 initForStyleResolve(e, parentStyle, pseudo); |
|
1501 m_style = parentStyle; |
|
1502 |
|
1503 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass; |
|
1504 |
|
1505 // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking |
|
1506 // those rules. |
|
1507 |
|
1508 // Check UA, user and author rules. |
|
1509 int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1; |
|
1510 matchUARules(firstUARule, lastUARule); |
|
1511 |
|
1512 if (m_matchAuthorAndUserStyles) { |
|
1513 matchRules(m_userStyle, firstUserRule, lastUserRule); |
|
1514 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule); |
|
1515 } |
|
1516 |
|
1517 if (m_matchedDecls.isEmpty() && !visitedStyle) |
|
1518 return 0; |
|
1519 |
|
1520 m_style = RenderStyle::create(); |
|
1521 if (parentStyle) |
|
1522 m_style->inheritFrom(parentStyle); |
|
1523 |
|
1524 m_style->setStyleType(pseudo); |
|
1525 |
|
1526 m_lineHeightValue = 0; |
|
1527 |
|
1528 // Reset the value back before applying properties, so that -webkit-link knows what color to use. |
|
1529 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass; |
|
1530 |
|
1531 // High-priority properties. |
|
1532 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1); |
|
1533 applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule); |
|
1534 applyDeclarations<true>(true, firstUserRule, lastUserRule); |
|
1535 applyDeclarations<true>(true, firstUARule, lastUARule); |
|
1536 |
|
1537 // If our font got dirtied, go ahead and update it now. |
|
1538 if (m_fontDirty) |
|
1539 updateFont(); |
|
1540 |
|
1541 // Line-height is set when we are sure we decided on the font-size |
|
1542 if (m_lineHeightValue) |
|
1543 applyProperty(CSSPropertyLineHeight, m_lineHeightValue); |
|
1544 |
|
1545 // Now do the normal priority properties. |
|
1546 applyDeclarations<false>(false, firstUARule, lastUARule); |
|
1547 |
|
1548 // Cache our border and background so that we can examine them later. |
|
1549 cacheBorderAndBackground(); |
|
1550 |
|
1551 applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1); |
|
1552 applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule); |
|
1553 applyDeclarations<false>(true, firstUserRule, lastUserRule); |
|
1554 applyDeclarations<false>(true, firstUARule, lastUARule); |
|
1555 |
|
1556 // If our font got dirtied by one of the non-essential font props, |
|
1557 // go ahead and update it a second time. |
|
1558 if (m_fontDirty) |
|
1559 updateFont(); |
|
1560 |
|
1561 // Clean up our style object's display and text decorations (among other fixups). |
|
1562 adjustRenderStyle(style(), 0); |
|
1563 |
|
1564 // Hang our visited style off m_style. |
|
1565 if (visitedStyle) |
|
1566 m_style->addCachedPseudoStyle(visitedStyle.release()); |
|
1567 |
|
1568 // Now return the style. |
|
1569 return m_style.release(); |
|
1570 } |
|
1571 |
|
1572 PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex) |
|
1573 { |
|
1574 initForStyleResolve(m_checker.m_document->body()); |
|
1575 |
|
1576 m_style = RenderStyle::create(); |
|
1577 m_style->inheritFrom(m_rootElementStyle); |
|
1578 |
|
1579 const bool isLeft = isLeftPage(pageIndex); |
|
1580 const bool isFirst = isFirstPage(pageIndex); |
|
1581 const String page = pageName(pageIndex); |
|
1582 matchPageRules(defaultPrintStyle, isLeft, isFirst, page); |
|
1583 matchPageRules(m_userStyle, isLeft, isFirst, page); |
|
1584 matchPageRules(m_authorStyle, isLeft, isFirst, page); |
|
1585 m_lineHeightValue = 0; |
|
1586 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1); |
|
1587 |
|
1588 // If our font got dirtied, go ahead and update it now. |
|
1589 if (m_fontDirty) |
|
1590 updateFont(); |
|
1591 |
|
1592 // Line-height is set when we are sure we decided on the font-size |
|
1593 if (m_lineHeightValue) |
|
1594 applyProperty(CSSPropertyLineHeight, m_lineHeightValue); |
|
1595 |
|
1596 applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1); |
|
1597 |
|
1598 // Now return the style. |
|
1599 return m_style.release(); |
|
1600 } |
|
1601 |
|
1602 #if ENABLE(DATAGRID) |
|
1603 |
|
1604 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumn(DataGridColumn*, RenderStyle*) |
|
1605 { |
|
1606 // FIXME: Implement |
|
1607 return 0; |
|
1608 } |
|
1609 |
|
1610 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumnHeader(DataGridColumn*, RenderStyle*) |
|
1611 { |
|
1612 // FIXME: Implement |
|
1613 return 0; |
|
1614 } |
|
1615 |
|
1616 #endif |
|
1617 |
|
1618 static void addIntrinsicMargins(RenderStyle* style) |
|
1619 { |
|
1620 // Intrinsic margin value. |
|
1621 const int intrinsicMargin = 2 * style->effectiveZoom(); |
|
1622 |
|
1623 // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed. |
|
1624 // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame. |
|
1625 if (style->width().isIntrinsicOrAuto()) { |
|
1626 if (style->marginLeft().quirk()) |
|
1627 style->setMarginLeft(Length(intrinsicMargin, Fixed)); |
|
1628 if (style->marginRight().quirk()) |
|
1629 style->setMarginRight(Length(intrinsicMargin, Fixed)); |
|
1630 } |
|
1631 |
|
1632 if (style->height().isAuto()) { |
|
1633 if (style->marginTop().quirk()) |
|
1634 style->setMarginTop(Length(intrinsicMargin, Fixed)); |
|
1635 if (style->marginBottom().quirk()) |
|
1636 style->setMarginBottom(Length(intrinsicMargin, Fixed)); |
|
1637 } |
|
1638 } |
|
1639 |
|
1640 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, Element *e) |
|
1641 { |
|
1642 // Cache our original display. |
|
1643 style->setOriginalDisplay(style->display()); |
|
1644 |
|
1645 if (style->display() != NONE) { |
|
1646 // If we have a <td> that specifies a float property, in quirks mode we just drop the float |
|
1647 // property. |
|
1648 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force |
|
1649 // these tags to retain their display types. |
|
1650 if (!m_checker.m_strictParsing && e) { |
|
1651 if (e->hasTagName(tdTag)) { |
|
1652 style->setDisplay(TABLE_CELL); |
|
1653 style->setFloating(FNONE); |
|
1654 } |
|
1655 else if (e->hasTagName(tableTag)) |
|
1656 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE); |
|
1657 } |
|
1658 |
|
1659 if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) { |
|
1660 if (style->whiteSpace() == KHTML_NOWRAP) { |
|
1661 // Figure out if we are really nowrapping or if we should just |
|
1662 // use normal instead. If the width of the cell is fixed, then |
|
1663 // we don't actually use NOWRAP. |
|
1664 if (style->width().isFixed()) |
|
1665 style->setWhiteSpace(NORMAL); |
|
1666 else |
|
1667 style->setWhiteSpace(NOWRAP); |
|
1668 } |
|
1669 } |
|
1670 |
|
1671 // Tables never support the -webkit-* values for text-align and will reset back to the default. |
|
1672 if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT)) |
|
1673 style->setTextAlign(TAAUTO); |
|
1674 |
|
1675 // Frames and framesets never honor position:relative or position:absolute. This is necessary to |
|
1676 // fix a crash where a site tries to position these objects. They also never honor display. |
|
1677 if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) { |
|
1678 style->setPosition(StaticPosition); |
|
1679 style->setDisplay(BLOCK); |
|
1680 } |
|
1681 |
|
1682 // Table headers with a text-align of auto will change the text-align to center. |
|
1683 if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO) |
|
1684 style->setTextAlign(CENTER); |
|
1685 |
|
1686 if (e && e->hasTagName(legendTag)) |
|
1687 style->setDisplay(BLOCK); |
|
1688 |
|
1689 // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to |
|
1690 // position or float an inline, compact, or run-in. Cache the original display, since it |
|
1691 // may be needed for positioned elements that have to compute their static normal flow |
|
1692 // positions. We also force inline-level roots to be block-level. |
|
1693 if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX && |
|
1694 (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE || |
|
1695 (e && e->document()->documentElement() == e))) { |
|
1696 if (style->display() == INLINE_TABLE) |
|
1697 style->setDisplay(TABLE); |
|
1698 else if (style->display() == INLINE_BOX) |
|
1699 style->setDisplay(BOX); |
|
1700 else if (style->display() == LIST_ITEM) { |
|
1701 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, |
|
1702 // but only in quirks mode. |
|
1703 if (!m_checker.m_strictParsing && style->floating() != FNONE) |
|
1704 style->setDisplay(BLOCK); |
|
1705 } |
|
1706 else |
|
1707 style->setDisplay(BLOCK); |
|
1708 } |
|
1709 |
|
1710 // After performing the display mutation, check table rows. We do not honor position:relative on |
|
1711 // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock() |
|
1712 // on some sites). |
|
1713 if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP || |
|
1714 style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_CELL) && |
|
1715 style->position() == RelativePosition) |
|
1716 style->setPosition(StaticPosition); |
|
1717 } |
|
1718 |
|
1719 // Make sure our z-index value is only applied if the object is positioned. |
|
1720 if (style->position() == StaticPosition) |
|
1721 style->setHasAutoZIndex(); |
|
1722 |
|
1723 // Auto z-index becomes 0 for the root element and transparent objects. This prevents |
|
1724 // cases where objects that should be blended as a single unit end up with a non-transparent |
|
1725 // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections. |
|
1726 if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f || |
|
1727 style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect())) |
|
1728 style->setZIndex(0); |
|
1729 |
|
1730 // Button, legend, input, select and textarea all consider width values of 'auto' to be 'intrinsic'. |
|
1731 // This will be important when we use block flows for all form controls. |
|
1732 if (e && (e->hasTagName(legendTag) || e->hasTagName(buttonTag) || e->hasTagName(inputTag) || |
|
1733 e->hasTagName(selectTag) || e->hasTagName(textareaTag) || e->hasTagName(datagridTag) |
|
1734 #if ENABLE(WML) |
|
1735 || e->hasTagName(WMLNames::insertedLegendTag) |
|
1736 || e->hasTagName(WMLNames::inputTag) |
|
1737 #endif |
|
1738 )) { |
|
1739 if (style->width().isAuto()) |
|
1740 style->setWidth(Length(Intrinsic)); |
|
1741 |
|
1742 // Textarea considers overflow visible as auto. |
|
1743 if (e && e->hasTagName(textareaTag)) { |
|
1744 style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX()); |
|
1745 style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY()); |
|
1746 } |
|
1747 } |
|
1748 |
|
1749 // Finally update our text decorations in effect, but don't allow text-decoration to percolate through |
|
1750 // tables, inline blocks, inline tables, or run-ins. |
|
1751 if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN |
|
1752 || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX) |
|
1753 style->setTextDecorationsInEffect(style->textDecoration()); |
|
1754 else |
|
1755 style->addToTextDecorationsInEffect(style->textDecoration()); |
|
1756 |
|
1757 // If either overflow value is not visible, change to auto. |
|
1758 if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE) |
|
1759 style->setOverflowY(OMARQUEE); |
|
1760 else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE) |
|
1761 style->setOverflowX(OMARQUEE); |
|
1762 else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) |
|
1763 style->setOverflowX(OAUTO); |
|
1764 else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE) |
|
1765 style->setOverflowY(OAUTO); |
|
1766 |
|
1767 // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto. |
|
1768 // FIXME: Eventually table sections will support auto and scroll. |
|
1769 if (style->display() == TABLE || style->display() == INLINE_TABLE || |
|
1770 style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) { |
|
1771 if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) |
|
1772 style->setOverflowX(OVISIBLE); |
|
1773 if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) |
|
1774 style->setOverflowY(OVISIBLE); |
|
1775 } |
|
1776 |
|
1777 // Menulists should have visible overflow |
|
1778 if (style->appearance() == MenulistPart) { |
|
1779 style->setOverflowX(OVISIBLE); |
|
1780 style->setOverflowY(OVISIBLE); |
|
1781 } |
|
1782 |
|
1783 // Cull out any useless layers and also repeat patterns into additional layers. |
|
1784 style->adjustBackgroundLayers(); |
|
1785 style->adjustMaskLayers(); |
|
1786 |
|
1787 // Do the same for animations and transitions. |
|
1788 style->adjustAnimations(); |
|
1789 style->adjustTransitions(); |
|
1790 |
|
1791 // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will |
|
1792 // alter fonts and heights/widths. |
|
1793 if (e && e->isFormControlElement() && style->fontSize() >= 11) { |
|
1794 // Don't apply intrinsic margins to image buttons. The designer knows how big the images are, |
|
1795 // so we have to treat all image buttons as though they were explicitly sized. |
|
1796 if (!e->hasTagName(inputTag) || static_cast<HTMLInputElement*>(e)->inputType() != HTMLInputElement::IMAGE) |
|
1797 addIntrinsicMargins(style); |
|
1798 } |
|
1799 |
|
1800 // Let the theme also have a crack at adjusting the style. |
|
1801 if (style->hasAppearance()) |
|
1802 RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor); |
|
1803 |
|
1804 #if ENABLE(SVG) |
|
1805 if (e && e->isSVGElement()) { |
|
1806 // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty |
|
1807 if (style->overflowY() == OSCROLL) |
|
1808 style->setOverflowY(OHIDDEN); |
|
1809 else if (style->overflowY() == OAUTO) |
|
1810 style->setOverflowY(OVISIBLE); |
|
1811 |
|
1812 if (style->overflowX() == OSCROLL) |
|
1813 style->setOverflowX(OHIDDEN); |
|
1814 else if (style->overflowX() == OAUTO) |
|
1815 style->setOverflowX(OVISIBLE); |
|
1816 |
|
1817 // Only the root <svg> element in an SVG document fragment tree honors css position |
|
1818 if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement())) |
|
1819 style->setPosition(RenderStyle::initialPosition()); |
|
1820 } |
|
1821 #endif |
|
1822 } |
|
1823 |
|
1824 void CSSStyleSelector::updateFont() |
|
1825 { |
|
1826 checkForTextSizeAdjust(); |
|
1827 checkForGenericFamilyChange(style(), m_parentStyle); |
|
1828 checkForZoomChange(style(), m_parentStyle); |
|
1829 m_style->font().update(m_fontSelector); |
|
1830 m_fontDirty = false; |
|
1831 } |
|
1832 |
|
1833 void CSSStyleSelector::cacheBorderAndBackground() |
|
1834 { |
|
1835 m_hasUAAppearance = m_style->hasAppearance(); |
|
1836 if (m_hasUAAppearance) { |
|
1837 m_borderData = m_style->border(); |
|
1838 m_backgroundData = *m_style->backgroundLayers(); |
|
1839 m_backgroundColor = m_style->backgroundColor(); |
|
1840 } |
|
1841 } |
|
1842 |
|
1843 PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly) |
|
1844 { |
|
1845 return pseudoStyleRulesForElement(e, NOPSEUDO, authorOnly); |
|
1846 } |
|
1847 |
|
1848 PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, bool authorOnly) |
|
1849 { |
|
1850 if (!e || !e->document()->haveStylesheetsLoaded()) |
|
1851 return 0; |
|
1852 |
|
1853 m_checker.m_collectRulesOnly = true; |
|
1854 |
|
1855 initElement(e); |
|
1856 initForStyleResolve(e, 0, pseudoId); |
|
1857 |
|
1858 if (!authorOnly) { |
|
1859 int firstUARule = -1, lastUARule = -1; |
|
1860 // First we match rules from the user agent sheet. |
|
1861 matchUARules(firstUARule, lastUARule); |
|
1862 |
|
1863 // Now we check user sheet rules. |
|
1864 if (m_matchAuthorAndUserStyles) { |
|
1865 int firstUserRule = -1, lastUserRule = -1; |
|
1866 matchRules(m_userStyle, firstUserRule, lastUserRule); |
|
1867 } |
|
1868 } |
|
1869 |
|
1870 if (m_matchAuthorAndUserStyles) { |
|
1871 // Check the rules in author sheets. |
|
1872 int firstAuthorRule = -1, lastAuthorRule = -1; |
|
1873 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule); |
|
1874 } |
|
1875 |
|
1876 m_checker.m_collectRulesOnly = false; |
|
1877 |
|
1878 return m_ruleList.release(); |
|
1879 } |
|
1880 |
|
1881 bool CSSStyleSelector::checkSelector(CSSSelector* sel) |
|
1882 { |
|
1883 m_dynamicPseudo = NOPSEUDO; |
|
1884 |
|
1885 // Check the selector |
|
1886 SelectorMatch match = m_checker.checkSelector(sel, m_element, &m_selectorAttrs, m_dynamicPseudo, false, false, style(), m_parentStyle); |
|
1887 if (match != SelectorMatches) |
|
1888 return false; |
|
1889 |
|
1890 if (m_checker.m_pseudoStyle != NOPSEUDO && m_checker.m_pseudoStyle != m_dynamicPseudo) |
|
1891 return false; |
|
1892 |
|
1893 return true; |
|
1894 } |
|
1895 |
|
1896 // Recursive check of selectors and combinators |
|
1897 // It can return 3 different values: |
|
1898 // * SelectorMatches - the selector matches the element e |
|
1899 // * SelectorFailsLocally - the selector fails for the element e |
|
1900 // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e |
|
1901 CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const |
|
1902 { |
|
1903 #if ENABLE(SVG) |
|
1904 // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree |
|
1905 // because its contents are not part of the formal document structure. |
|
1906 if (e->isSVGElement() && e->isShadowNode()) |
|
1907 return SelectorFailsCompletely; |
|
1908 #endif |
|
1909 |
|
1910 // first selector has to match |
|
1911 if (!checkOneSelector(sel, e, selectorAttrs, dynamicPseudo, isSubSelector, elementStyle, elementParentStyle)) |
|
1912 return SelectorFailsLocally; |
|
1913 |
|
1914 // The rest of the selectors has to match |
|
1915 CSSSelector::Relation relation = sel->relation(); |
|
1916 |
|
1917 // Prepare next sel |
|
1918 sel = sel->tagHistory(); |
|
1919 if (!sel) |
|
1920 return SelectorMatches; |
|
1921 |
|
1922 if (relation != CSSSelector::SubSelector) |
|
1923 // Bail-out if this selector is irrelevant for the pseudoStyle |
|
1924 if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != dynamicPseudo) |
|
1925 return SelectorFailsCompletely; |
|
1926 |
|
1927 // Check for nested links. |
|
1928 if (m_matchVisitedPseudoClass && !isSubSelector) { |
|
1929 RenderStyle* currentStyle = elementStyle ? elementStyle : e->renderStyle(); |
|
1930 if (currentStyle && currentStyle->insideLink() && e->isLink()) { |
|
1931 if (encounteredLink) |
|
1932 m_matchVisitedPseudoClass = false; // This link is not relevant to the style being resolved, so disable matching. |
|
1933 else |
|
1934 encounteredLink = true; |
|
1935 } |
|
1936 } |
|
1937 |
|
1938 switch (relation) { |
|
1939 case CSSSelector::Descendant: |
|
1940 while (true) { |
|
1941 Node* n = e->parentNode(); |
|
1942 if (!n || !n->isElementNode()) |
|
1943 return SelectorFailsCompletely; |
|
1944 e = static_cast<Element*>(n); |
|
1945 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); |
|
1946 if (match != SelectorFailsLocally) |
|
1947 return match; |
|
1948 } |
|
1949 break; |
|
1950 case CSSSelector::Child: |
|
1951 { |
|
1952 Node* n = e->parentNode(); |
|
1953 if (!n || !n->isElementNode()) |
|
1954 return SelectorFailsCompletely; |
|
1955 e = static_cast<Element*>(n); |
|
1956 return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); |
|
1957 } |
|
1958 case CSSSelector::DirectAdjacent: |
|
1959 { |
|
1960 if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) { |
|
1961 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); |
|
1962 if (parentStyle) |
|
1963 parentStyle->setChildrenAffectedByDirectAdjacentRules(); |
|
1964 } |
|
1965 Node* n = e->previousSibling(); |
|
1966 while (n && !n->isElementNode()) |
|
1967 n = n->previousSibling(); |
|
1968 if (!n) |
|
1969 return SelectorFailsLocally; |
|
1970 e = static_cast<Element*>(n); |
|
1971 m_matchVisitedPseudoClass = false; |
|
1972 return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); |
|
1973 } |
|
1974 case CSSSelector::IndirectAdjacent: |
|
1975 if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) { |
|
1976 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); |
|
1977 if (parentStyle) |
|
1978 parentStyle->setChildrenAffectedByForwardPositionalRules(); |
|
1979 } |
|
1980 while (true) { |
|
1981 Node* n = e->previousSibling(); |
|
1982 while (n && !n->isElementNode()) |
|
1983 n = n->previousSibling(); |
|
1984 if (!n) |
|
1985 return SelectorFailsLocally; |
|
1986 e = static_cast<Element*>(n); |
|
1987 m_matchVisitedPseudoClass = false; |
|
1988 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); |
|
1989 if (match != SelectorFailsLocally) |
|
1990 return match; |
|
1991 }; |
|
1992 break; |
|
1993 case CSSSelector::SubSelector: |
|
1994 // a selector is invalid if something follows a pseudo-element |
|
1995 // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else) |
|
1996 // to follow the pseudo elements. |
|
1997 if ((elementStyle || m_collectRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION && |
|
1998 !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass)) |
|
1999 return SelectorFailsCompletely; |
|
2000 return checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle); |
|
2001 } |
|
2002 |
|
2003 return SelectorFailsCompletely; |
|
2004 } |
|
2005 |
|
2006 static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName) |
|
2007 { |
|
2008 set->add(qName.localName().impl()); |
|
2009 } |
|
2010 |
|
2011 static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet() |
|
2012 { |
|
2013 // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive |
|
2014 // Mozilla treats all other values as case-sensitive, thus so do we. |
|
2015 HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>; |
|
2016 |
|
2017 addLocalNameToSet(attrSet, accept_charsetAttr); |
|
2018 addLocalNameToSet(attrSet, acceptAttr); |
|
2019 addLocalNameToSet(attrSet, alignAttr); |
|
2020 addLocalNameToSet(attrSet, alinkAttr); |
|
2021 addLocalNameToSet(attrSet, axisAttr); |
|
2022 addLocalNameToSet(attrSet, bgcolorAttr); |
|
2023 addLocalNameToSet(attrSet, charsetAttr); |
|
2024 addLocalNameToSet(attrSet, checkedAttr); |
|
2025 addLocalNameToSet(attrSet, clearAttr); |
|
2026 addLocalNameToSet(attrSet, codetypeAttr); |
|
2027 addLocalNameToSet(attrSet, colorAttr); |
|
2028 addLocalNameToSet(attrSet, compactAttr); |
|
2029 addLocalNameToSet(attrSet, declareAttr); |
|
2030 addLocalNameToSet(attrSet, deferAttr); |
|
2031 addLocalNameToSet(attrSet, dirAttr); |
|
2032 addLocalNameToSet(attrSet, disabledAttr); |
|
2033 addLocalNameToSet(attrSet, enctypeAttr); |
|
2034 addLocalNameToSet(attrSet, faceAttr); |
|
2035 addLocalNameToSet(attrSet, frameAttr); |
|
2036 addLocalNameToSet(attrSet, hreflangAttr); |
|
2037 addLocalNameToSet(attrSet, http_equivAttr); |
|
2038 addLocalNameToSet(attrSet, langAttr); |
|
2039 addLocalNameToSet(attrSet, languageAttr); |
|
2040 addLocalNameToSet(attrSet, linkAttr); |
|
2041 addLocalNameToSet(attrSet, mediaAttr); |
|
2042 addLocalNameToSet(attrSet, methodAttr); |
|
2043 addLocalNameToSet(attrSet, multipleAttr); |
|
2044 addLocalNameToSet(attrSet, nohrefAttr); |
|
2045 addLocalNameToSet(attrSet, noresizeAttr); |
|
2046 addLocalNameToSet(attrSet, noshadeAttr); |
|
2047 addLocalNameToSet(attrSet, nowrapAttr); |
|
2048 addLocalNameToSet(attrSet, readonlyAttr); |
|
2049 addLocalNameToSet(attrSet, relAttr); |
|
2050 addLocalNameToSet(attrSet, revAttr); |
|
2051 addLocalNameToSet(attrSet, rulesAttr); |
|
2052 addLocalNameToSet(attrSet, scopeAttr); |
|
2053 addLocalNameToSet(attrSet, scrollingAttr); |
|
2054 addLocalNameToSet(attrSet, selectedAttr); |
|
2055 addLocalNameToSet(attrSet, shapeAttr); |
|
2056 addLocalNameToSet(attrSet, targetAttr); |
|
2057 addLocalNameToSet(attrSet, textAttr); |
|
2058 addLocalNameToSet(attrSet, typeAttr); |
|
2059 addLocalNameToSet(attrSet, valignAttr); |
|
2060 addLocalNameToSet(attrSet, valuetypeAttr); |
|
2061 addLocalNameToSet(attrSet, vlinkAttr); |
|
2062 |
|
2063 return attrSet; |
|
2064 } |
|
2065 |
|
2066 static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr) |
|
2067 { |
|
2068 static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet(); |
|
2069 bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom); |
|
2070 return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl()); |
|
2071 } |
|
2072 |
|
2073 bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const |
|
2074 { |
|
2075 if (!e) |
|
2076 return false; |
|
2077 |
|
2078 if (sel->hasTag()) { |
|
2079 const AtomicString& selLocalName = sel->m_tag.localName(); |
|
2080 if (selLocalName != starAtom && selLocalName != e->localName()) |
|
2081 return false; |
|
2082 const AtomicString& selNS = sel->m_tag.namespaceURI(); |
|
2083 if (selNS != starAtom && selNS != e->namespaceURI()) |
|
2084 return false; |
|
2085 } |
|
2086 |
|
2087 if (sel->hasAttribute()) { |
|
2088 if (sel->m_match == CSSSelector::Class) |
|
2089 return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->m_value); |
|
2090 |
|
2091 if (sel->m_match == CSSSelector::Id) |
|
2092 return e->hasID() && e->idForStyleResolution() == sel->m_value; |
|
2093 |
|
2094 const QualifiedName& attr = sel->attribute(); |
|
2095 |
|
2096 // FIXME: Handle the case were elementStyle is 0. |
|
2097 if (elementStyle && (!e->isStyledElement() || (!static_cast<StyledElement*>(e)->isMappedAttribute(attr) && attr != typeAttr && attr != readonlyAttr))) { |
|
2098 elementStyle->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style. |
|
2099 if (selectorAttrs) |
|
2100 selectorAttrs->add(attr.localName().impl()); |
|
2101 } |
|
2102 |
|
2103 const AtomicString& value = e->getAttribute(attr); |
|
2104 if (value.isNull()) |
|
2105 return false; // attribute is not set |
|
2106 |
|
2107 bool caseSensitive = !m_documentIsHTML || !htmlAttributeHasCaseInsensitiveValue(attr); |
|
2108 |
|
2109 switch (sel->m_match) { |
|
2110 case CSSSelector::Exact: |
|
2111 if (caseSensitive ? sel->m_value != value : !equalIgnoringCase(sel->m_value, value)) |
|
2112 return false; |
|
2113 break; |
|
2114 case CSSSelector::List: |
|
2115 { |
|
2116 // Ignore empty selectors or selectors containing spaces |
|
2117 if (sel->m_value.contains(' ') || sel->m_value.isEmpty()) |
|
2118 return false; |
|
2119 |
|
2120 int startSearchAt = 0; |
|
2121 while (true) { |
|
2122 int foundPos = value.find(sel->m_value, startSearchAt, caseSensitive); |
|
2123 if (foundPos == -1) |
|
2124 return false; |
|
2125 if (foundPos == 0 || value[foundPos-1] == ' ') { |
|
2126 unsigned endStr = foundPos + sel->m_value.length(); |
|
2127 if (endStr == value.length() || value[endStr] == ' ') |
|
2128 break; // We found a match. |
|
2129 } |
|
2130 |
|
2131 // No match. Keep looking. |
|
2132 startSearchAt = foundPos + 1; |
|
2133 } |
|
2134 break; |
|
2135 } |
|
2136 case CSSSelector::Contain: |
|
2137 if (!value.contains(sel->m_value, caseSensitive) || sel->m_value.isEmpty()) |
|
2138 return false; |
|
2139 break; |
|
2140 case CSSSelector::Begin: |
|
2141 if (!value.startsWith(sel->m_value, caseSensitive) || sel->m_value.isEmpty()) |
|
2142 return false; |
|
2143 break; |
|
2144 case CSSSelector::End: |
|
2145 if (!value.endsWith(sel->m_value, caseSensitive) || sel->m_value.isEmpty()) |
|
2146 return false; |
|
2147 break; |
|
2148 case CSSSelector::Hyphen: |
|
2149 if (value.length() < sel->m_value.length()) |
|
2150 return false; |
|
2151 if (!value.startsWith(sel->m_value, caseSensitive)) |
|
2152 return false; |
|
2153 // It they start the same, check for exact match or following '-': |
|
2154 if (value.length() != sel->m_value.length() && value[sel->m_value.length()] != '-') |
|
2155 return false; |
|
2156 break; |
|
2157 case CSSSelector::PseudoClass: |
|
2158 case CSSSelector::PseudoElement: |
|
2159 default: |
|
2160 break; |
|
2161 } |
|
2162 } |
|
2163 |
|
2164 if (sel->m_match == CSSSelector::PseudoClass) { |
|
2165 // Handle :not up front. |
|
2166 if (sel->pseudoType() == CSSSelector::PseudoNot) { |
|
2167 // check the simple selector |
|
2168 for (CSSSelector* subSel = sel->simpleSelector(); subSel; subSel = subSel->tagHistory()) { |
|
2169 // :not cannot nest. I don't really know why this is a |
|
2170 // restriction in CSS3, but it is, so let's honor it. |
|
2171 // the parser enforces that this never occurs |
|
2172 ASSERT(!subSel->simpleSelector()); |
|
2173 |
|
2174 if (!checkOneSelector(subSel, e, selectorAttrs, dynamicPseudo, true, elementStyle, elementParentStyle)) |
|
2175 return true; |
|
2176 } |
|
2177 } else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) { |
|
2178 // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each |
|
2179 // (since there are no elements involved). |
|
2180 return checkScrollbarPseudoClass(sel, dynamicPseudo); |
|
2181 } else if (dynamicPseudo == SELECTION) { |
|
2182 if (sel->pseudoType() == CSSSelector::PseudoWindowInactive) |
|
2183 return !m_document->page()->focusController()->isActive(); |
|
2184 } |
|
2185 |
|
2186 // Normal element pseudo class checking. |
|
2187 switch (sel->pseudoType()) { |
|
2188 // Pseudo classes: |
|
2189 case CSSSelector::PseudoNot: |
|
2190 break; // Already handled up above. |
|
2191 case CSSSelector::PseudoEmpty: { |
|
2192 bool result = true; |
|
2193 for (Node* n = e->firstChild(); n; n = n->nextSibling()) { |
|
2194 if (n->isElementNode()) { |
|
2195 result = false; |
|
2196 break; |
|
2197 } else if (n->isTextNode()) { |
|
2198 Text* textNode = static_cast<Text*>(n); |
|
2199 if (!textNode->data().isEmpty()) { |
|
2200 result = false; |
|
2201 break; |
|
2202 } |
|
2203 } |
|
2204 } |
|
2205 if (!m_collectRulesOnly) { |
|
2206 if (elementStyle) |
|
2207 elementStyle->setEmptyState(result); |
|
2208 else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique())) |
|
2209 e->renderStyle()->setEmptyState(result); |
|
2210 } |
|
2211 return result; |
|
2212 } |
|
2213 case CSSSelector::PseudoFirstChild: { |
|
2214 // first-child matches the first child that is an element |
|
2215 if (e->parentNode() && e->parentNode()->isElementNode()) { |
|
2216 bool result = false; |
|
2217 Node* n = e->previousSibling(); |
|
2218 while (n && !n->isElementNode()) |
|
2219 n = n->previousSibling(); |
|
2220 if (!n) |
|
2221 result = true; |
|
2222 if (!m_collectRulesOnly) { |
|
2223 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); |
|
2224 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); |
|
2225 if (parentStyle) |
|
2226 parentStyle->setChildrenAffectedByFirstChildRules(); |
|
2227 if (result && childStyle) |
|
2228 childStyle->setFirstChildState(); |
|
2229 } |
|
2230 return result; |
|
2231 } |
|
2232 break; |
|
2233 } |
|
2234 case CSSSelector::PseudoFirstOfType: { |
|
2235 // first-of-type matches the first element of its type |
|
2236 if (e->parentNode() && e->parentNode()->isElementNode()) { |
|
2237 bool result = false; |
|
2238 const QualifiedName& type = e->tagQName(); |
|
2239 Node* n = e->previousSibling(); |
|
2240 while (n) { |
|
2241 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) |
|
2242 break; |
|
2243 n = n->previousSibling(); |
|
2244 } |
|
2245 if (!n) |
|
2246 result = true; |
|
2247 if (!m_collectRulesOnly) { |
|
2248 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); |
|
2249 if (parentStyle) |
|
2250 parentStyle->setChildrenAffectedByForwardPositionalRules(); |
|
2251 } |
|
2252 return result; |
|
2253 } |
|
2254 break; |
|
2255 } |
|
2256 case CSSSelector::PseudoLastChild: { |
|
2257 // last-child matches the last child that is an element |
|
2258 if (Element* parentElement = e->parentElement()) { |
|
2259 bool result = false; |
|
2260 if (parentElement->isFinishedParsingChildren()) { |
|
2261 Node* n = e->nextSibling(); |
|
2262 while (n && !n->isElementNode()) |
|
2263 n = n->nextSibling(); |
|
2264 if (!n) |
|
2265 result = true; |
|
2266 } |
|
2267 if (!m_collectRulesOnly) { |
|
2268 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); |
|
2269 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); |
|
2270 if (parentStyle) |
|
2271 parentStyle->setChildrenAffectedByLastChildRules(); |
|
2272 if (result && childStyle) |
|
2273 childStyle->setLastChildState(); |
|
2274 } |
|
2275 return result; |
|
2276 } |
|
2277 break; |
|
2278 } |
|
2279 case CSSSelector::PseudoLastOfType: { |
|
2280 // last-of-type matches the last element of its type |
|
2281 if (Element* parentElement = e->parentElement()) { |
|
2282 if (!m_collectRulesOnly) { |
|
2283 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); |
|
2284 if (parentStyle) |
|
2285 parentStyle->setChildrenAffectedByBackwardPositionalRules(); |
|
2286 } |
|
2287 if (!parentElement->isFinishedParsingChildren()) |
|
2288 return false; |
|
2289 bool result = false; |
|
2290 const QualifiedName& type = e->tagQName(); |
|
2291 Node* n = e->nextSibling(); |
|
2292 while (n) { |
|
2293 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) |
|
2294 break; |
|
2295 n = n->nextSibling(); |
|
2296 } |
|
2297 if (!n) |
|
2298 result = true; |
|
2299 return result; |
|
2300 } |
|
2301 break; |
|
2302 } |
|
2303 case CSSSelector::PseudoOnlyChild: { |
|
2304 if (Element* parentElement = e->parentElement()) { |
|
2305 bool firstChild = false; |
|
2306 bool lastChild = false; |
|
2307 |
|
2308 Node* n = e->previousSibling(); |
|
2309 while (n && !n->isElementNode()) |
|
2310 n = n->previousSibling(); |
|
2311 if (!n) |
|
2312 firstChild = true; |
|
2313 if (firstChild && parentElement->isFinishedParsingChildren()) { |
|
2314 n = e->nextSibling(); |
|
2315 while (n && !n->isElementNode()) |
|
2316 n = n->nextSibling(); |
|
2317 if (!n) |
|
2318 lastChild = true; |
|
2319 } |
|
2320 if (!m_collectRulesOnly) { |
|
2321 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); |
|
2322 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); |
|
2323 if (parentStyle) { |
|
2324 parentStyle->setChildrenAffectedByFirstChildRules(); |
|
2325 parentStyle->setChildrenAffectedByLastChildRules(); |
|
2326 } |
|
2327 if (firstChild && childStyle) |
|
2328 childStyle->setFirstChildState(); |
|
2329 if (lastChild && childStyle) |
|
2330 childStyle->setLastChildState(); |
|
2331 } |
|
2332 return firstChild && lastChild; |
|
2333 } |
|
2334 break; |
|
2335 } |
|
2336 case CSSSelector::PseudoOnlyOfType: { |
|
2337 // FIXME: This selector is very slow. |
|
2338 if (Element* parentElement = e->parentElement()) { |
|
2339 if (!m_collectRulesOnly) { |
|
2340 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); |
|
2341 if (parentStyle) { |
|
2342 parentStyle->setChildrenAffectedByForwardPositionalRules(); |
|
2343 parentStyle->setChildrenAffectedByBackwardPositionalRules(); |
|
2344 } |
|
2345 } |
|
2346 if (!parentElement->isFinishedParsingChildren()) |
|
2347 return false; |
|
2348 bool firstChild = false; |
|
2349 bool lastChild = false; |
|
2350 const QualifiedName& type = e->tagQName(); |
|
2351 Node* n = e->previousSibling(); |
|
2352 while (n) { |
|
2353 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) |
|
2354 break; |
|
2355 n = n->previousSibling(); |
|
2356 } |
|
2357 if (!n) |
|
2358 firstChild = true; |
|
2359 if (firstChild) { |
|
2360 n = e->nextSibling(); |
|
2361 while (n) { |
|
2362 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) |
|
2363 break; |
|
2364 n = n->nextSibling(); |
|
2365 } |
|
2366 if (!n) |
|
2367 lastChild = true; |
|
2368 } |
|
2369 return firstChild && lastChild; |
|
2370 } |
|
2371 break; |
|
2372 } |
|
2373 case CSSSelector::PseudoNthChild: { |
|
2374 if (!sel->parseNth()) |
|
2375 break; |
|
2376 if (Element* parentElement = e->parentElement()) { |
|
2377 int count = 1; |
|
2378 Node* n = e->previousSibling(); |
|
2379 while (n) { |
|
2380 if (n->isElementNode()) { |
|
2381 RenderStyle* s = n->renderStyle(); |
|
2382 unsigned index = s ? s->childIndex() : 0; |
|
2383 if (index) { |
|
2384 count += index; |
|
2385 break; |
|
2386 } |
|
2387 count++; |
|
2388 } |
|
2389 n = n->previousSibling(); |
|
2390 } |
|
2391 |
|
2392 if (!m_collectRulesOnly) { |
|
2393 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); |
|
2394 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); |
|
2395 if (childStyle) |
|
2396 childStyle->setChildIndex(count); |
|
2397 if (parentStyle) |
|
2398 parentStyle->setChildrenAffectedByForwardPositionalRules(); |
|
2399 } |
|
2400 |
|
2401 if (sel->matchNth(count)) |
|
2402 return true; |
|
2403 } |
|
2404 break; |
|
2405 } |
|
2406 case CSSSelector::PseudoNthOfType: { |
|
2407 if (!sel->parseNth()) |
|
2408 break; |
|
2409 if (Element* parentElement = e->parentElement()) { |
|
2410 int count = 1; |
|
2411 const QualifiedName& type = e->tagQName(); |
|
2412 Node* n = e->previousSibling(); |
|
2413 while (n) { |
|
2414 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) |
|
2415 count++; |
|
2416 n = n->previousSibling(); |
|
2417 } |
|
2418 |
|
2419 if (!m_collectRulesOnly) { |
|
2420 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); |
|
2421 if (parentStyle) |
|
2422 parentStyle->setChildrenAffectedByForwardPositionalRules(); |
|
2423 } |
|
2424 |
|
2425 if (sel->matchNth(count)) |
|
2426 return true; |
|
2427 } |
|
2428 break; |
|
2429 } |
|
2430 case CSSSelector::PseudoNthLastChild: { |
|
2431 if (!sel->parseNth()) |
|
2432 break; |
|
2433 if (Element* parentElement = e->parentElement()) { |
|
2434 if (!m_collectRulesOnly) { |
|
2435 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); |
|
2436 if (parentStyle) |
|
2437 parentStyle->setChildrenAffectedByBackwardPositionalRules(); |
|
2438 } |
|
2439 if (!parentElement->isFinishedParsingChildren()) |
|
2440 return false; |
|
2441 int count = 1; |
|
2442 Node* n = e->nextSibling(); |
|
2443 while (n) { |
|
2444 if (n->isElementNode()) |
|
2445 count++; |
|
2446 n = n->nextSibling(); |
|
2447 } |
|
2448 if (sel->matchNth(count)) |
|
2449 return true; |
|
2450 } |
|
2451 break; |
|
2452 } |
|
2453 case CSSSelector::PseudoNthLastOfType: { |
|
2454 if (!sel->parseNth()) |
|
2455 break; |
|
2456 if (Element* parentElement = e->parentElement()) { |
|
2457 if (!m_collectRulesOnly) { |
|
2458 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); |
|
2459 if (parentStyle) |
|
2460 parentStyle->setChildrenAffectedByBackwardPositionalRules(); |
|
2461 } |
|
2462 if (!parentElement->isFinishedParsingChildren()) |
|
2463 return false; |
|
2464 int count = 1; |
|
2465 const QualifiedName& type = e->tagQName(); |
|
2466 Node* n = e->nextSibling(); |
|
2467 while (n) { |
|
2468 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) |
|
2469 count++; |
|
2470 n = n->nextSibling(); |
|
2471 } |
|
2472 if (sel->matchNth(count)) |
|
2473 return true; |
|
2474 } |
|
2475 break; |
|
2476 } |
|
2477 case CSSSelector::PseudoTarget: |
|
2478 if (e == e->document()->cssTarget()) |
|
2479 return true; |
|
2480 break; |
|
2481 case CSSSelector::PseudoAnyLink: |
|
2482 if (e && e->isLink()) |
|
2483 return true; |
|
2484 break; |
|
2485 case CSSSelector::PseudoAutofill: { |
|
2486 if (!e || !e->isFormControlElement()) |
|
2487 break; |
|
2488 if (InputElement* inputElement = toInputElement(e)) |
|
2489 return inputElement->isAutofilled(); |
|
2490 break; |
|
2491 } |
|
2492 case CSSSelector::PseudoLink: |
|
2493 if (e && e->isLink()) |
|
2494 return !m_matchVisitedPseudoClass; |
|
2495 break; |
|
2496 case CSSSelector::PseudoVisited: |
|
2497 if (e && e->isLink()) |
|
2498 return m_matchVisitedPseudoClass; |
|
2499 break; |
|
2500 case CSSSelector::PseudoDrag: { |
|
2501 if (elementStyle) |
|
2502 elementStyle->setAffectedByDragRules(true); |
|
2503 else if (e->renderStyle()) |
|
2504 e->renderStyle()->setAffectedByDragRules(true); |
|
2505 if (e->renderer() && e->renderer()->isDragging()) |
|
2506 return true; |
|
2507 break; |
|
2508 } |
|
2509 case CSSSelector::PseudoFocus: |
|
2510 if (e && e->focused() && e->document()->frame()->selection()->isFocusedAndActive()) |
|
2511 return true; |
|
2512 break; |
|
2513 case CSSSelector::PseudoHover: { |
|
2514 // If we're in quirks mode, then hover should never match anchors with no |
|
2515 // href and *:hover should not match anything. This is important for sites like wsj.com. |
|
2516 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) { |
|
2517 if (elementStyle) |
|
2518 elementStyle->setAffectedByHoverRules(true); |
|
2519 else if (e->renderStyle()) |
|
2520 e->renderStyle()->setAffectedByHoverRules(true); |
|
2521 if (e->hovered()) |
|
2522 return true; |
|
2523 } |
|
2524 break; |
|
2525 } |
|
2526 case CSSSelector::PseudoActive: |
|
2527 // If we're in quirks mode, then :active should never match anchors with no |
|
2528 // href and *:active should not match anything. |
|
2529 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) { |
|
2530 if (elementStyle) |
|
2531 elementStyle->setAffectedByActiveRules(true); |
|
2532 else if (e->renderStyle()) |
|
2533 e->renderStyle()->setAffectedByActiveRules(true); |
|
2534 if (e->active()) |
|
2535 return true; |
|
2536 } |
|
2537 break; |
|
2538 case CSSSelector::PseudoEnabled: |
|
2539 if (e && e->isFormControlElement()) |
|
2540 return e->isEnabledFormControl(); |
|
2541 break; |
|
2542 case CSSSelector::PseudoFullPageMedia: |
|
2543 return e && e->document() && e->document()->isMediaDocument(); |
|
2544 break; |
|
2545 case CSSSelector::PseudoDefault: |
|
2546 return e && e->isDefaultButtonForForm(); |
|
2547 case CSSSelector::PseudoDisabled: |
|
2548 if (e && e->isFormControlElement()) |
|
2549 return !e->isEnabledFormControl(); |
|
2550 break; |
|
2551 case CSSSelector::PseudoReadOnly: { |
|
2552 if (!e || !e->isFormControlElement()) |
|
2553 return false; |
|
2554 return e->isTextFormControl() && e->isReadOnlyFormControl(); |
|
2555 } |
|
2556 case CSSSelector::PseudoReadWrite: { |
|
2557 if (!e || !e->isFormControlElement()) |
|
2558 return false; |
|
2559 return e->isTextFormControl() && !e->isReadOnlyFormControl(); |
|
2560 } |
|
2561 case CSSSelector::PseudoOptional: |
|
2562 return e && e->isOptionalFormControl(); |
|
2563 case CSSSelector::PseudoRequired: |
|
2564 return e && e->isRequiredFormControl(); |
|
2565 case CSSSelector::PseudoValid: { |
|
2566 if (!e) |
|
2567 return false; |
|
2568 e->document()->setContainsValidityStyleRules(); |
|
2569 return e->willValidate() && e->isValidFormControlElement(); |
|
2570 } case CSSSelector::PseudoInvalid: { |
|
2571 if (!e) |
|
2572 return false; |
|
2573 e->document()->setContainsValidityStyleRules(); |
|
2574 return e->willValidate() && !e->isValidFormControlElement(); |
|
2575 } case CSSSelector::PseudoChecked: { |
|
2576 if (!e || !e->isFormControlElement()) |
|
2577 break; |
|
2578 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that |
|
2579 // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just |
|
2580 // obey the CSS spec here in the test for matching the pseudo. |
|
2581 InputElement* inputElement = toInputElement(e); |
|
2582 if (inputElement && inputElement->isChecked() && !inputElement->isIndeterminate()) |
|
2583 return true; |
|
2584 break; |
|
2585 } |
|
2586 case CSSSelector::PseudoIndeterminate: { |
|
2587 if (!e || !e->isFormControlElement()) |
|
2588 break; |
|
2589 InputElement* inputElement = toInputElement(e); |
|
2590 if (inputElement && inputElement->isIndeterminate()) |
|
2591 return true; |
|
2592 break; |
|
2593 } |
|
2594 case CSSSelector::PseudoRoot: |
|
2595 if (e == e->document()->documentElement()) |
|
2596 return true; |
|
2597 break; |
|
2598 case CSSSelector::PseudoLang: { |
|
2599 Node* n = e; |
|
2600 AtomicString value; |
|
2601 // The language property is inherited, so we iterate over the parents |
|
2602 // to find the first language. |
|
2603 while (n && value.isNull()) { |
|
2604 if (n->isElementNode()) { |
|
2605 // Spec: xml:lang takes precedence -- http://www.w3.org/TR/xhtml1/#C_7 |
|
2606 value = static_cast<Element*>(n)->fastGetAttribute(XMLNames::langAttr); |
|
2607 if (value.isNull()) |
|
2608 value = static_cast<Element*>(n)->fastGetAttribute(langAttr); |
|
2609 } else if (n->isDocumentNode()) |
|
2610 // checking the MIME content-language |
|
2611 value = static_cast<Document*>(n)->contentLanguage(); |
|
2612 |
|
2613 n = n->parent(); |
|
2614 } |
|
2615 const AtomicString& argument = sel->argument(); |
|
2616 if (value.isNull() || !value.startsWith(argument, false)) |
|
2617 break; |
|
2618 if (value.length() != argument.length() && value[argument.length()] != '-') |
|
2619 break; |
|
2620 return true; |
|
2621 } |
|
2622 case CSSSelector::PseudoUnknown: |
|
2623 case CSSSelector::PseudoNotParsed: |
|
2624 default: |
|
2625 ASSERT_NOT_REACHED(); |
|
2626 break; |
|
2627 } |
|
2628 return false; |
|
2629 } |
|
2630 if (sel->m_match == CSSSelector::PseudoElement) { |
|
2631 if (!elementStyle && !m_collectRulesOnly) |
|
2632 return false; |
|
2633 |
|
2634 PseudoId pseudoId = CSSSelector::pseudoId(sel->pseudoType()); |
|
2635 if (pseudoId == FIRST_LETTER) { |
|
2636 if (Document* document = e->document()) |
|
2637 document->setUsesFirstLetterRules(true); |
|
2638 } |
|
2639 if (pseudoId != NOPSEUDO) { |
|
2640 dynamicPseudo = pseudoId; |
|
2641 return true; |
|
2642 } |
|
2643 ASSERT_NOT_REACHED(); |
|
2644 return false; |
|
2645 } |
|
2646 // ### add the rest of the checks... |
|
2647 return true; |
|
2648 } |
|
2649 |
|
2650 bool CSSStyleSelector::SelectorChecker::checkScrollbarPseudoClass(CSSSelector* sel, PseudoId&) const |
|
2651 { |
|
2652 RenderScrollbar* scrollbar = RenderScrollbar::scrollbarForStyleResolve(); |
|
2653 ScrollbarPart part = RenderScrollbar::partForStyleResolve(); |
|
2654 |
|
2655 // FIXME: This is a temporary hack for resizers and scrollbar corners. Eventually :window-inactive should become a real |
|
2656 // pseudo class and just apply to everything. |
|
2657 if (sel->pseudoType() == CSSSelector::PseudoWindowInactive) |
|
2658 return !m_document->page()->focusController()->isActive(); |
|
2659 |
|
2660 if (!scrollbar) |
|
2661 return false; |
|
2662 |
|
2663 ASSERT(sel->m_match == CSSSelector::PseudoClass); |
|
2664 switch (sel->pseudoType()) { |
|
2665 case CSSSelector::PseudoEnabled: |
|
2666 return scrollbar->enabled(); |
|
2667 case CSSSelector::PseudoDisabled: |
|
2668 return !scrollbar->enabled(); |
|
2669 case CSSSelector::PseudoHover: { |
|
2670 ScrollbarPart hoveredPart = scrollbar->hoveredPart(); |
|
2671 if (part == ScrollbarBGPart) |
|
2672 return hoveredPart != NoPart; |
|
2673 if (part == TrackBGPart) |
|
2674 return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart; |
|
2675 return part == hoveredPart; |
|
2676 } |
|
2677 case CSSSelector::PseudoActive: { |
|
2678 ScrollbarPart pressedPart = scrollbar->pressedPart(); |
|
2679 if (part == ScrollbarBGPart) |
|
2680 return pressedPart != NoPart; |
|
2681 if (part == TrackBGPart) |
|
2682 return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart; |
|
2683 return part == pressedPart; |
|
2684 } |
|
2685 case CSSSelector::PseudoHorizontal: |
|
2686 return scrollbar->orientation() == HorizontalScrollbar; |
|
2687 case CSSSelector::PseudoVertical: |
|
2688 return scrollbar->orientation() == VerticalScrollbar; |
|
2689 case CSSSelector::PseudoDecrement: |
|
2690 return part == BackButtonStartPart || part == BackButtonEndPart || part == BackTrackPart; |
|
2691 case CSSSelector::PseudoIncrement: |
|
2692 return part == ForwardButtonStartPart || part == ForwardButtonEndPart || part == ForwardTrackPart; |
|
2693 case CSSSelector::PseudoStart: |
|
2694 return part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart; |
|
2695 case CSSSelector::PseudoEnd: |
|
2696 return part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart; |
|
2697 case CSSSelector::PseudoDoubleButton: { |
|
2698 ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement(); |
|
2699 if (part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart) |
|
2700 return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth; |
|
2701 if (part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart) |
|
2702 return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth; |
|
2703 return false; |
|
2704 } |
|
2705 case CSSSelector::PseudoSingleButton: { |
|
2706 ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement(); |
|
2707 if (part == BackButtonStartPart || part == ForwardButtonEndPart || part == BackTrackPart || part == ForwardTrackPart) |
|
2708 return buttonsPlacement == ScrollbarButtonsSingle; |
|
2709 return false; |
|
2710 } |
|
2711 case CSSSelector::PseudoNoButton: { |
|
2712 ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement(); |
|
2713 if (part == BackTrackPart) |
|
2714 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd; |
|
2715 if (part == ForwardTrackPart) |
|
2716 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart; |
|
2717 return false; |
|
2718 } |
|
2719 case CSSSelector::PseudoCornerPresent: |
|
2720 return scrollbar->client()->scrollbarCornerPresent(); |
|
2721 default: |
|
2722 return false; |
|
2723 } |
|
2724 } |
|
2725 |
|
2726 void CSSStyleSelector::addVariables(CSSVariablesRule* variables) |
|
2727 { |
|
2728 CSSVariablesDeclaration* decl = variables->variables(); |
|
2729 if (!decl) |
|
2730 return; |
|
2731 unsigned size = decl->length(); |
|
2732 for (unsigned i = 0; i < size; ++i) { |
|
2733 String name = decl->item(i); |
|
2734 m_variablesMap.set(name, variables); |
|
2735 } |
|
2736 } |
|
2737 |
|
2738 CSSValue* CSSStyleSelector::resolveVariableDependentValue(CSSVariableDependentValue*) |
|
2739 { |
|
2740 return 0; |
|
2741 } |
|
2742 |
|
2743 // ----------------------------------------------------------------- |
|
2744 |
|
2745 CSSRuleSet::CSSRuleSet() |
|
2746 { |
|
2747 m_universalRules = 0; |
|
2748 m_pageRules = 0; |
|
2749 m_ruleCount = 0; |
|
2750 m_pageRuleCount = 0; |
|
2751 } |
|
2752 |
|
2753 CSSRuleSet::~CSSRuleSet() |
|
2754 { |
|
2755 deleteAllValues(m_idRules); |
|
2756 deleteAllValues(m_classRules); |
|
2757 deleteAllValues(m_tagRules); |
|
2758 |
|
2759 delete m_universalRules; |
|
2760 delete m_pageRules; |
|
2761 } |
|
2762 |
|
2763 |
|
2764 void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, |
|
2765 CSSStyleRule* rule, CSSSelector* sel) |
|
2766 { |
|
2767 if (!key) return; |
|
2768 CSSRuleDataList* rules = map.get(key); |
|
2769 if (!rules) { |
|
2770 rules = new CSSRuleDataList(m_ruleCount++, rule, sel); |
|
2771 map.set(key, rules); |
|
2772 } else |
|
2773 rules->append(m_ruleCount++, rule, sel); |
|
2774 } |
|
2775 |
|
2776 void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel) |
|
2777 { |
|
2778 if (sel->m_match == CSSSelector::Id) { |
|
2779 addToRuleSet(sel->m_value.impl(), m_idRules, rule, sel); |
|
2780 return; |
|
2781 } |
|
2782 if (sel->m_match == CSSSelector::Class) { |
|
2783 addToRuleSet(sel->m_value.impl(), m_classRules, rule, sel); |
|
2784 return; |
|
2785 } |
|
2786 |
|
2787 const AtomicString& localName = sel->m_tag.localName(); |
|
2788 if (localName != starAtom) { |
|
2789 addToRuleSet(localName.impl(), m_tagRules, rule, sel); |
|
2790 return; |
|
2791 } |
|
2792 |
|
2793 // Just put it in the universal rule set. |
|
2794 if (!m_universalRules) |
|
2795 m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel); |
|
2796 else |
|
2797 m_universalRules->append(m_ruleCount++, rule, sel); |
|
2798 } |
|
2799 |
|
2800 void CSSRuleSet::addPageRule(CSSStyleRule* rule, CSSSelector* sel) |
|
2801 { |
|
2802 if (!m_pageRules) |
|
2803 m_pageRules = new CSSRuleDataList(m_pageRuleCount++, rule, sel); |
|
2804 else |
|
2805 m_pageRules->append(m_pageRuleCount++, rule, sel); |
|
2806 } |
|
2807 |
|
2808 void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector) |
|
2809 { |
|
2810 if (!sheet) |
|
2811 return; |
|
2812 |
|
2813 // No media implies "all", but if a media list exists it must |
|
2814 // contain our current medium |
|
2815 if (sheet->media() && !medium.eval(sheet->media(), styleSelector)) |
|
2816 return; // the style sheet doesn't apply |
|
2817 |
|
2818 int len = sheet->length(); |
|
2819 |
|
2820 for (int i = 0; i < len; i++) { |
|
2821 StyleBase* item = sheet->item(i); |
|
2822 if (item->isStyleRule()) { |
|
2823 addStyleRule(item); |
|
2824 } |
|
2825 else if (item->isImportRule()) { |
|
2826 CSSImportRule* import = static_cast<CSSImportRule*>(item); |
|
2827 if (!import->media() || medium.eval(import->media(), styleSelector)) |
|
2828 addRulesFromSheet(import->styleSheet(), medium, styleSelector); |
|
2829 } |
|
2830 else if (item->isMediaRule()) { |
|
2831 CSSMediaRule* r = static_cast<CSSMediaRule*>(item); |
|
2832 CSSRuleList* rules = r->cssRules(); |
|
2833 |
|
2834 if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) { |
|
2835 // Traverse child elements of the @media rule. |
|
2836 for (unsigned j = 0; j < rules->length(); j++) { |
|
2837 CSSRule *childItem = rules->item(j); |
|
2838 if (childItem->isStyleRule()) { |
|
2839 // It is a StyleRule, so append it to our list |
|
2840 addStyleRule(childItem); |
|
2841 } else if (childItem->isFontFaceRule() && styleSelector) { |
|
2842 // Add this font face to our set. |
|
2843 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem); |
|
2844 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule); |
|
2845 } else if (childItem->isKeyframesRule() && styleSelector) { |
|
2846 // Add this keyframe rule to our set. |
|
2847 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem)); |
|
2848 } |
|
2849 } // for rules |
|
2850 } // if rules |
|
2851 } else if (item->isFontFaceRule() && styleSelector) { |
|
2852 // Add this font face to our set. |
|
2853 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(item); |
|
2854 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule); |
|
2855 } else if (item->isVariablesRule()) { |
|
2856 // Evaluate the media query and make sure it matches. |
|
2857 CSSVariablesRule* variables = static_cast<CSSVariablesRule*>(item); |
|
2858 if (!variables->media() || medium.eval(variables->media(), styleSelector)) |
|
2859 styleSelector->addVariables(variables); |
|
2860 } else if (item->isKeyframesRule()) |
|
2861 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(item)); |
|
2862 } |
|
2863 } |
|
2864 |
|
2865 void CSSRuleSet::addStyleRule(StyleBase* item) |
|
2866 { |
|
2867 if (item->isPageRule()) { |
|
2868 CSSPageRule* pageRule = static_cast<CSSPageRule*>(item); |
|
2869 addPageRule(pageRule, pageRule->selectorList().first()); |
|
2870 } else { |
|
2871 CSSStyleRule* rule = static_cast<CSSStyleRule*>(item); |
|
2872 for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s)) |
|
2873 addRule(rule, s); |
|
2874 } |
|
2875 } |
|
2876 |
|
2877 // ------------------------------------------------------------------------------------- |
|
2878 // this is mostly boring stuff on how to apply a certain rule to the renderstyle... |
|
2879 |
|
2880 static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0) |
|
2881 { |
|
2882 // This function is tolerant of a null style value. The only place style is used is in |
|
2883 // length measurements, like 'ems' and 'px'. And in those cases style is only used |
|
2884 // when the units are EMS or EXS. So we will just fail in those cases. |
|
2885 Length l; |
|
2886 if (!primitiveValue) { |
|
2887 if (ok) |
|
2888 *ok = false; |
|
2889 } else { |
|
2890 int type = primitiveValue->primitiveType(); |
|
2891 |
|
2892 if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) { |
|
2893 if (ok) |
|
2894 *ok = false; |
|
2895 } else if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
2896 l = Length(primitiveValue->computeLengthIntForLength(style, rootStyle, multiplier), Fixed); |
|
2897 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
2898 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
2899 else if (type == CSSPrimitiveValue::CSS_NUMBER) |
|
2900 l = Length(primitiveValue->getDoubleValue() * 100.0, Percent); |
|
2901 else if (ok) |
|
2902 *ok = false; |
|
2903 } |
|
2904 return l; |
|
2905 } |
|
2906 |
|
2907 template <bool applyFirst> |
|
2908 void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex) |
|
2909 { |
|
2910 if (startIndex == -1) |
|
2911 return; |
|
2912 |
|
2913 for (int i = startIndex; i <= endIndex; i++) { |
|
2914 CSSMutableStyleDeclaration* decl = m_matchedDecls[i]; |
|
2915 CSSMutableStyleDeclaration::const_iterator end = decl->end(); |
|
2916 for (CSSMutableStyleDeclaration::const_iterator it = decl->begin(); it != end; ++it) { |
|
2917 const CSSProperty& current = *it; |
|
2918 if (isImportant == current.isImportant()) { |
|
2919 int property = current.id(); |
|
2920 |
|
2921 if (applyFirst) { |
|
2922 COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property); |
|
2923 COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 11, CSS_zoom_is_end_of_first_prop_range); |
|
2924 COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom); |
|
2925 |
|
2926 // give special priority to font-xxx, color properties, etc |
|
2927 if (property <= CSSPropertyLineHeight) { |
|
2928 // we apply line-height later |
|
2929 if (property == CSSPropertyLineHeight) |
|
2930 m_lineHeightValue = current.value(); |
|
2931 else |
|
2932 applyProperty(current.id(), current.value()); |
|
2933 } |
|
2934 } else { |
|
2935 if (property > CSSPropertyLineHeight) |
|
2936 applyProperty(current.id(), current.value()); |
|
2937 } |
|
2938 } |
|
2939 } |
|
2940 } |
|
2941 } |
|
2942 |
|
2943 void CSSStyleSelector::matchPageRules(CSSRuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName) |
|
2944 { |
|
2945 m_matchedRules.clear(); |
|
2946 |
|
2947 if (!rules) |
|
2948 return; |
|
2949 |
|
2950 matchPageRulesForList(rules->getPageRules(), isLeftPage, isFirstPage, pageName); |
|
2951 |
|
2952 // If we didn't match any rules, we're done. |
|
2953 if (m_matchedRules.isEmpty()) |
|
2954 return; |
|
2955 |
|
2956 // Sort the set of matched rules. |
|
2957 sortMatchedRules(0, m_matchedRules.size()); |
|
2958 |
|
2959 // Now transfer the set of matched rules over to our list of decls. |
|
2960 for (unsigned i = 0; i < m_matchedRules.size(); i++) |
|
2961 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration()); |
|
2962 } |
|
2963 |
|
2964 void CSSStyleSelector::matchPageRulesForList(CSSRuleDataList* rules, bool isLeftPage, bool isFirstPage, const String& pageName) |
|
2965 { |
|
2966 if (!rules) |
|
2967 return; |
|
2968 |
|
2969 for (CSSRuleData* d = rules->first(); d; d = d->next()) { |
|
2970 CSSStyleRule* rule = d->rule(); |
|
2971 const AtomicString& selectorLocalName = d->selector()->m_tag.localName(); |
|
2972 if (selectorLocalName != starAtom && selectorLocalName != pageName) |
|
2973 continue; |
|
2974 CSSSelector::PseudoType pseudoType = d->selector()->pseudoType(); |
|
2975 if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage) |
|
2976 || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage) |
|
2977 || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage)) |
|
2978 continue; |
|
2979 |
|
2980 // If the rule has no properties to apply, then ignore it. |
|
2981 CSSMutableStyleDeclaration* decl = rule->declaration(); |
|
2982 if (!decl || !decl->length()) |
|
2983 continue; |
|
2984 |
|
2985 // Add this rule to our list of matched rules. |
|
2986 addMatchedRule(d); |
|
2987 } |
|
2988 } |
|
2989 |
|
2990 bool CSSStyleSelector::isLeftPage(int pageIndex) const |
|
2991 { |
|
2992 bool isFirstPageLeft = false; |
|
2993 if (m_rootElementStyle->direction() == RTL) |
|
2994 isFirstPageLeft = true; |
|
2995 |
|
2996 return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2; |
|
2997 } |
|
2998 |
|
2999 bool CSSStyleSelector::isFirstPage(int pageIndex) const |
|
3000 { |
|
3001 // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page. |
|
3002 return (!pageIndex); |
|
3003 } |
|
3004 |
|
3005 String CSSStyleSelector::pageName(int /* pageIndex */) const |
|
3006 { |
|
3007 // FIXME: Implement page index to page name mapping. |
|
3008 return ""; |
|
3009 } |
|
3010 |
|
3011 static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isReset) |
|
3012 { |
|
3013 CounterDirectiveMap& map = style->accessCounterDirectives(); |
|
3014 typedef CounterDirectiveMap::iterator Iterator; |
|
3015 |
|
3016 Iterator end = map.end(); |
|
3017 for (Iterator it = map.begin(); it != end; ++it) |
|
3018 if (isReset) |
|
3019 it->second.m_reset = false; |
|
3020 else |
|
3021 it->second.m_increment = false; |
|
3022 |
|
3023 int length = list ? list->length() : 0; |
|
3024 for (int i = 0; i < length; ++i) { |
|
3025 Pair* pair = static_cast<CSSPrimitiveValue*>(list->itemWithoutBoundsCheck(i))->getPairValue(); |
|
3026 AtomicString identifier = static_cast<CSSPrimitiveValue*>(pair->first())->getStringValue(); |
|
3027 // FIXME: What about overflow? |
|
3028 int value = static_cast<CSSPrimitiveValue*>(pair->second())->getIntValue(); |
|
3029 CounterDirectives& directives = map.add(identifier.impl(), CounterDirectives()).first->second; |
|
3030 if (isReset) { |
|
3031 directives.m_reset = true; |
|
3032 directives.m_resetValue = value; |
|
3033 } else { |
|
3034 if (directives.m_increment) |
|
3035 directives.m_incrementValue += value; |
|
3036 else { |
|
3037 directives.m_increment = true; |
|
3038 directives.m_incrementValue = value; |
|
3039 } |
|
3040 } |
|
3041 } |
|
3042 } |
|
3043 |
|
3044 void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue *value, RenderStyle* style) |
|
3045 { |
|
3046 initElement(0); |
|
3047 initForStyleResolve(0, style); |
|
3048 m_style = style; |
|
3049 applyProperty(id, value); |
|
3050 } |
|
3051 |
|
3052 inline bool isValidVisitedLinkProperty(int id) |
|
3053 { |
|
3054 switch(static_cast<CSSPropertyID>(id)) { |
|
3055 case CSSPropertyBackgroundColor: |
|
3056 case CSSPropertyBorderLeftColor: |
|
3057 case CSSPropertyBorderRightColor: |
|
3058 case CSSPropertyBorderTopColor: |
|
3059 case CSSPropertyBorderBottomColor: |
|
3060 case CSSPropertyColor: |
|
3061 case CSSPropertyOutlineColor: |
|
3062 case CSSPropertyWebkitColumnRuleColor: |
|
3063 case CSSPropertyWebkitTextFillColor: |
|
3064 case CSSPropertyWebkitTextStrokeColor: |
|
3065 // Also allow shorthands so that inherit/initial still work. |
|
3066 case CSSPropertyBackground: |
|
3067 case CSSPropertyBorderLeft: |
|
3068 case CSSPropertyBorderRight: |
|
3069 case CSSPropertyBorderTop: |
|
3070 case CSSPropertyBorderBottom: |
|
3071 case CSSPropertyOutline: |
|
3072 case CSSPropertyWebkitColumnRule: |
|
3073 #if ENABLE(SVG) |
|
3074 case CSSPropertyFill: |
|
3075 case CSSPropertyStroke: |
|
3076 #endif |
|
3077 return true; |
|
3078 default: |
|
3079 break; |
|
3080 } |
|
3081 |
|
3082 return false; |
|
3083 } |
|
3084 |
|
3085 void CSSStyleSelector::applyProperty(int id, CSSValue *value) |
|
3086 { |
|
3087 CSSPrimitiveValue* primitiveValue = 0; |
|
3088 if (value->isPrimitiveValue()) |
|
3089 primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
3090 |
|
3091 float zoomFactor = m_style->effectiveZoom(); |
|
3092 |
|
3093 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead |
|
3094 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*() |
|
3095 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that. |
|
3096 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...) |
|
3097 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like |
|
3098 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale, |
|
3099 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific |
|
3100 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size). |
|
3101 bool useSVGZoomRules = m_element && m_element->isSVGElement(); |
|
3102 |
|
3103 Length l; |
|
3104 bool apply = false; |
|
3105 |
|
3106 unsigned short valueType = value->cssValueType(); |
|
3107 |
|
3108 bool isInherit = m_parentNode && valueType == CSSValue::CSS_INHERIT; |
|
3109 bool isInitial = valueType == CSSValue::CSS_INITIAL || (!m_parentNode && valueType == CSSValue::CSS_INHERIT); |
|
3110 |
|
3111 id = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction()); |
|
3112 |
|
3113 if (m_checker.m_matchVisitedPseudoClass && !isValidVisitedLinkProperty(id)) { |
|
3114 // Limit the properties that can be applied to only the ones honored by :visited. |
|
3115 return; |
|
3116 } |
|
3117 |
|
3118 // What follows is a list that maps the CSS properties into their corresponding front-end |
|
3119 // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and |
|
3120 // are only hit when mapping "inherit" or "initial" into front-end values. |
|
3121 switch (static_cast<CSSPropertyID>(id)) { |
|
3122 // ident only properties |
|
3123 case CSSPropertyBackgroundAttachment: |
|
3124 HANDLE_BACKGROUND_VALUE(attachment, Attachment, value) |
|
3125 return; |
|
3126 case CSSPropertyBackgroundClip: |
|
3127 case CSSPropertyWebkitBackgroundClip: |
|
3128 HANDLE_BACKGROUND_VALUE(clip, Clip, value) |
|
3129 return; |
|
3130 case CSSPropertyWebkitBackgroundComposite: |
|
3131 HANDLE_BACKGROUND_VALUE(composite, Composite, value) |
|
3132 return; |
|
3133 case CSSPropertyBackgroundOrigin: |
|
3134 case CSSPropertyWebkitBackgroundOrigin: |
|
3135 HANDLE_BACKGROUND_VALUE(origin, Origin, value) |
|
3136 return; |
|
3137 case CSSPropertyBackgroundSize: |
|
3138 case CSSPropertyWebkitBackgroundSize: |
|
3139 HANDLE_BACKGROUND_VALUE(size, Size, value) |
|
3140 return; |
|
3141 case CSSPropertyWebkitMaskAttachment: |
|
3142 HANDLE_MASK_VALUE(attachment, Attachment, value) |
|
3143 return; |
|
3144 case CSSPropertyWebkitMaskClip: |
|
3145 HANDLE_MASK_VALUE(clip, Clip, value) |
|
3146 return; |
|
3147 case CSSPropertyWebkitMaskComposite: |
|
3148 HANDLE_MASK_VALUE(composite, Composite, value) |
|
3149 return; |
|
3150 case CSSPropertyWebkitMaskOrigin: |
|
3151 HANDLE_MASK_VALUE(origin, Origin, value) |
|
3152 return; |
|
3153 case CSSPropertyWebkitMaskSize: |
|
3154 HANDLE_MASK_VALUE(size, Size, value) |
|
3155 return; |
|
3156 case CSSPropertyBorderCollapse: |
|
3157 HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse) |
|
3158 if (!primitiveValue) |
|
3159 return; |
|
3160 switch (primitiveValue->getIdent()) { |
|
3161 case CSSValueCollapse: |
|
3162 m_style->setBorderCollapse(true); |
|
3163 break; |
|
3164 case CSSValueSeparate: |
|
3165 m_style->setBorderCollapse(false); |
|
3166 break; |
|
3167 default: |
|
3168 return; |
|
3169 } |
|
3170 return; |
|
3171 case CSSPropertyBorderTopStyle: |
|
3172 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle) |
|
3173 return; |
|
3174 case CSSPropertyBorderRightStyle: |
|
3175 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle) |
|
3176 return; |
|
3177 case CSSPropertyBorderBottomStyle: |
|
3178 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle) |
|
3179 return; |
|
3180 case CSSPropertyBorderLeftStyle: |
|
3181 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle) |
|
3182 return; |
|
3183 case CSSPropertyOutlineStyle: |
|
3184 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle) |
|
3185 if (primitiveValue) { |
|
3186 if (primitiveValue->getIdent() == CSSValueAuto) |
|
3187 m_style->setOutlineStyle(DOTTED, true); |
|
3188 else |
|
3189 m_style->setOutlineStyle(*primitiveValue); |
|
3190 } |
|
3191 return; |
|
3192 case CSSPropertyCaptionSide: |
|
3193 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(captionSide, CaptionSide) |
|
3194 return; |
|
3195 case CSSPropertyClear: |
|
3196 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(clear, Clear) |
|
3197 return; |
|
3198 case CSSPropertyDirection: |
|
3199 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(direction, Direction) |
|
3200 return; |
|
3201 case CSSPropertyDisplay: |
|
3202 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(display, Display) |
|
3203 #if ENABLE(WCSS) |
|
3204 if (primitiveValue) { |
|
3205 if (primitiveValue->getIdent() == CSSValueWapMarquee) { |
|
3206 // Initialize WAP Marquee style |
|
3207 m_style->setOverflowX(OMARQUEE); |
|
3208 m_style->setOverflowY(OMARQUEE); |
|
3209 m_style->setWhiteSpace(NOWRAP); |
|
3210 m_style->setMarqueeDirection(MLEFT); |
|
3211 m_style->setMarqueeSpeed(85); // Normal speed |
|
3212 m_style->setMarqueeLoopCount(1); |
|
3213 m_style->setMarqueeBehavior(MSCROLL); |
|
3214 |
|
3215 if (m_parentStyle) |
|
3216 m_style->setDisplay(m_parentStyle->display()); |
|
3217 else |
|
3218 m_style->setDisplay(*primitiveValue); |
|
3219 } else |
|
3220 m_style->setDisplay(*primitiveValue); |
|
3221 } |
|
3222 #endif |
|
3223 return; |
|
3224 case CSSPropertyEmptyCells: |
|
3225 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(emptyCells, EmptyCells) |
|
3226 return; |
|
3227 case CSSPropertyFloat: |
|
3228 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(floating, Floating) |
|
3229 return; |
|
3230 case CSSPropertyFontStyle: |
|
3231 { |
|
3232 FontDescription fontDescription = m_style->fontDescription(); |
|
3233 if (isInherit) |
|
3234 fontDescription.setItalic(m_parentStyle->fontDescription().italic()); |
|
3235 else if (isInitial) |
|
3236 fontDescription.setItalic(false); |
|
3237 else { |
|
3238 if (!primitiveValue) |
|
3239 return; |
|
3240 switch (primitiveValue->getIdent()) { |
|
3241 case CSSValueOblique: |
|
3242 // FIXME: oblique is the same as italic for the moment... |
|
3243 case CSSValueItalic: |
|
3244 fontDescription.setItalic(true); |
|
3245 break; |
|
3246 case CSSValueNormal: |
|
3247 fontDescription.setItalic(false); |
|
3248 break; |
|
3249 default: |
|
3250 return; |
|
3251 } |
|
3252 } |
|
3253 if (m_style->setFontDescription(fontDescription)) |
|
3254 m_fontDirty = true; |
|
3255 return; |
|
3256 } |
|
3257 |
|
3258 case CSSPropertyFontVariant: |
|
3259 { |
|
3260 FontDescription fontDescription = m_style->fontDescription(); |
|
3261 if (isInherit) |
|
3262 fontDescription.setSmallCaps(m_parentStyle->fontDescription().smallCaps()); |
|
3263 else if (isInitial) |
|
3264 fontDescription.setSmallCaps(false); |
|
3265 else { |
|
3266 if (!primitiveValue) |
|
3267 return; |
|
3268 int id = primitiveValue->getIdent(); |
|
3269 if (id == CSSValueNormal) |
|
3270 fontDescription.setSmallCaps(false); |
|
3271 else if (id == CSSValueSmallCaps) |
|
3272 fontDescription.setSmallCaps(true); |
|
3273 else |
|
3274 return; |
|
3275 } |
|
3276 if (m_style->setFontDescription(fontDescription)) |
|
3277 m_fontDirty = true; |
|
3278 return; |
|
3279 } |
|
3280 |
|
3281 case CSSPropertyFontWeight: |
|
3282 { |
|
3283 FontDescription fontDescription = m_style->fontDescription(); |
|
3284 if (isInherit) |
|
3285 fontDescription.setWeight(m_parentStyle->fontDescription().weight()); |
|
3286 else if (isInitial) |
|
3287 fontDescription.setWeight(FontWeightNormal); |
|
3288 else { |
|
3289 if (!primitiveValue) |
|
3290 return; |
|
3291 if (primitiveValue->getIdent()) { |
|
3292 switch (primitiveValue->getIdent()) { |
|
3293 case CSSValueBolder: |
|
3294 fontDescription.setWeight(fontDescription.bolderWeight()); |
|
3295 break; |
|
3296 case CSSValueLighter: |
|
3297 fontDescription.setWeight(fontDescription.lighterWeight()); |
|
3298 break; |
|
3299 case CSSValueBold: |
|
3300 case CSSValue700: |
|
3301 fontDescription.setWeight(FontWeightBold); |
|
3302 break; |
|
3303 case CSSValueNormal: |
|
3304 case CSSValue400: |
|
3305 fontDescription.setWeight(FontWeightNormal); |
|
3306 break; |
|
3307 case CSSValue900: |
|
3308 fontDescription.setWeight(FontWeight900); |
|
3309 break; |
|
3310 case CSSValue800: |
|
3311 fontDescription.setWeight(FontWeight800); |
|
3312 break; |
|
3313 case CSSValue600: |
|
3314 fontDescription.setWeight(FontWeight600); |
|
3315 break; |
|
3316 case CSSValue500: |
|
3317 fontDescription.setWeight(FontWeight500); |
|
3318 break; |
|
3319 case CSSValue300: |
|
3320 fontDescription.setWeight(FontWeight300); |
|
3321 break; |
|
3322 case CSSValue200: |
|
3323 fontDescription.setWeight(FontWeight200); |
|
3324 break; |
|
3325 case CSSValue100: |
|
3326 fontDescription.setWeight(FontWeight100); |
|
3327 break; |
|
3328 default: |
|
3329 return; |
|
3330 } |
|
3331 } else |
|
3332 ASSERT_NOT_REACHED(); |
|
3333 } |
|
3334 if (m_style->setFontDescription(fontDescription)) |
|
3335 m_fontDirty = true; |
|
3336 return; |
|
3337 } |
|
3338 |
|
3339 case CSSPropertyListStylePosition: |
|
3340 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(listStylePosition, ListStylePosition) |
|
3341 return; |
|
3342 case CSSPropertyListStyleType: |
|
3343 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(listStyleType, ListStyleType) |
|
3344 return; |
|
3345 case CSSPropertyOverflow: |
|
3346 { |
|
3347 if (isInherit) { |
|
3348 m_style->setOverflowX(m_parentStyle->overflowX()); |
|
3349 m_style->setOverflowY(m_parentStyle->overflowY()); |
|
3350 return; |
|
3351 } |
|
3352 |
|
3353 if (isInitial) { |
|
3354 m_style->setOverflowX(RenderStyle::initialOverflowX()); |
|
3355 m_style->setOverflowY(RenderStyle::initialOverflowY()); |
|
3356 return; |
|
3357 } |
|
3358 |
|
3359 EOverflow o = *primitiveValue; |
|
3360 |
|
3361 m_style->setOverflowX(o); |
|
3362 m_style->setOverflowY(o); |
|
3363 return; |
|
3364 } |
|
3365 |
|
3366 case CSSPropertyOverflowX: |
|
3367 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(overflowX, OverflowX) |
|
3368 return; |
|
3369 case CSSPropertyOverflowY: |
|
3370 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(overflowY, OverflowY) |
|
3371 return; |
|
3372 case CSSPropertyPageBreakBefore: |
|
3373 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak) |
|
3374 return; |
|
3375 case CSSPropertyPageBreakAfter: |
|
3376 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak) |
|
3377 return; |
|
3378 case CSSPropertyPageBreakInside: { |
|
3379 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak) |
|
3380 if (!primitiveValue) |
|
3381 return; |
|
3382 EPageBreak pageBreak = *primitiveValue; |
|
3383 if (pageBreak != PBALWAYS) |
|
3384 m_style->setPageBreakInside(pageBreak); |
|
3385 return; |
|
3386 } |
|
3387 |
|
3388 case CSSPropertyPosition: |
|
3389 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(position, Position) |
|
3390 return; |
|
3391 case CSSPropertyTableLayout: { |
|
3392 HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout) |
|
3393 |
|
3394 ETableLayout l = *primitiveValue; |
|
3395 if (l == TAUTO) |
|
3396 l = RenderStyle::initialTableLayout(); |
|
3397 |
|
3398 m_style->setTableLayout(l); |
|
3399 return; |
|
3400 } |
|
3401 |
|
3402 case CSSPropertyUnicodeBidi: |
|
3403 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(unicodeBidi, UnicodeBidi) |
|
3404 return; |
|
3405 case CSSPropertyTextTransform: |
|
3406 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textTransform, TextTransform) |
|
3407 return; |
|
3408 case CSSPropertyVisibility: |
|
3409 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(visibility, Visibility) |
|
3410 return; |
|
3411 case CSSPropertyWhiteSpace: |
|
3412 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(whiteSpace, WhiteSpace) |
|
3413 return; |
|
3414 |
|
3415 case CSSPropertyBackgroundPosition: |
|
3416 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(xPosition, XPosition); |
|
3417 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(yPosition, YPosition); |
|
3418 return; |
|
3419 case CSSPropertyBackgroundPositionX: { |
|
3420 HANDLE_BACKGROUND_VALUE(xPosition, XPosition, value) |
|
3421 return; |
|
3422 } |
|
3423 case CSSPropertyBackgroundPositionY: { |
|
3424 HANDLE_BACKGROUND_VALUE(yPosition, YPosition, value) |
|
3425 return; |
|
3426 } |
|
3427 case CSSPropertyWebkitMaskPosition: |
|
3428 HANDLE_MASK_INHERIT_AND_INITIAL(xPosition, XPosition); |
|
3429 HANDLE_MASK_INHERIT_AND_INITIAL(yPosition, YPosition); |
|
3430 return; |
|
3431 case CSSPropertyWebkitMaskPositionX: { |
|
3432 HANDLE_MASK_VALUE(xPosition, XPosition, value) |
|
3433 return; |
|
3434 } |
|
3435 case CSSPropertyWebkitMaskPositionY: { |
|
3436 HANDLE_MASK_VALUE(yPosition, YPosition, value) |
|
3437 return; |
|
3438 } |
|
3439 case CSSPropertyBackgroundRepeat: |
|
3440 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(repeatX, RepeatX); |
|
3441 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(repeatY, RepeatY); |
|
3442 return; |
|
3443 case CSSPropertyBackgroundRepeatX: |
|
3444 HANDLE_BACKGROUND_VALUE(repeatX, RepeatX, value) |
|
3445 return; |
|
3446 case CSSPropertyBackgroundRepeatY: |
|
3447 HANDLE_BACKGROUND_VALUE(repeatY, RepeatY, value) |
|
3448 return; |
|
3449 case CSSPropertyWebkitMaskRepeat: |
|
3450 HANDLE_MASK_INHERIT_AND_INITIAL(repeatX, RepeatX); |
|
3451 HANDLE_MASK_INHERIT_AND_INITIAL(repeatY, RepeatY); |
|
3452 return; |
|
3453 case CSSPropertyWebkitMaskRepeatX: |
|
3454 HANDLE_MASK_VALUE(repeatX, RepeatX, value) |
|
3455 return; |
|
3456 case CSSPropertyWebkitMaskRepeatY: |
|
3457 HANDLE_MASK_VALUE(repeatY, RepeatY, value) |
|
3458 return; |
|
3459 case CSSPropertyBorderSpacing: { |
|
3460 if (isInherit) { |
|
3461 m_style->setHorizontalBorderSpacing(m_parentStyle->horizontalBorderSpacing()); |
|
3462 m_style->setVerticalBorderSpacing(m_parentStyle->verticalBorderSpacing()); |
|
3463 } |
|
3464 else if (isInitial) { |
|
3465 m_style->setHorizontalBorderSpacing(0); |
|
3466 m_style->setVerticalBorderSpacing(0); |
|
3467 } |
|
3468 return; |
|
3469 } |
|
3470 case CSSPropertyWebkitBorderHorizontalSpacing: { |
|
3471 HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing) |
|
3472 if (!primitiveValue) |
|
3473 return; |
|
3474 short spacing = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor); |
|
3475 m_style->setHorizontalBorderSpacing(spacing); |
|
3476 return; |
|
3477 } |
|
3478 case CSSPropertyWebkitBorderVerticalSpacing: { |
|
3479 HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing) |
|
3480 if (!primitiveValue) |
|
3481 return; |
|
3482 short spacing = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor); |
|
3483 m_style->setVerticalBorderSpacing(spacing); |
|
3484 return; |
|
3485 } |
|
3486 case CSSPropertyCursor: |
|
3487 if (isInherit) { |
|
3488 m_style->setCursor(m_parentStyle->cursor()); |
|
3489 m_style->setCursorList(m_parentStyle->cursors()); |
|
3490 return; |
|
3491 } |
|
3492 m_style->clearCursorList(); |
|
3493 if (isInitial) { |
|
3494 m_style->setCursor(RenderStyle::initialCursor()); |
|
3495 return; |
|
3496 } |
|
3497 if (value->isValueList()) { |
|
3498 CSSValueList* list = static_cast<CSSValueList*>(value); |
|
3499 int len = list->length(); |
|
3500 m_style->setCursor(CURSOR_AUTO); |
|
3501 for (int i = 0; i < len; i++) { |
|
3502 CSSValue* item = list->itemWithoutBoundsCheck(i); |
|
3503 if (!item->isPrimitiveValue()) |
|
3504 continue; |
|
3505 primitiveValue = static_cast<CSSPrimitiveValue*>(item); |
|
3506 int type = primitiveValue->primitiveType(); |
|
3507 if (type == CSSPrimitiveValue::CSS_URI) { |
|
3508 CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue); |
|
3509 if (image->updateIfSVGCursorIsUsed(m_element)) // Elements with SVG cursors are not allowed to share style. |
|
3510 m_style->setUnique(); |
|
3511 // FIXME: Temporary clumsiness to pass off a CachedImage to an API that will eventually convert to using |
|
3512 // StyleImage. |
|
3513 RefPtr<StyleCachedImage> styleCachedImage(image->cachedImage(m_element->document()->docLoader())); |
|
3514 if (styleCachedImage) |
|
3515 m_style->addCursor(styleCachedImage->cachedImage(), image->hotSpot()); |
|
3516 } else if (type == CSSPrimitiveValue::CSS_IDENT) |
|
3517 m_style->setCursor(*primitiveValue); |
|
3518 } |
|
3519 } else if (primitiveValue) { |
|
3520 int type = primitiveValue->primitiveType(); |
|
3521 if (type == CSSPrimitiveValue::CSS_IDENT && m_style->cursor() != ECursor(*primitiveValue)) |
|
3522 m_style->setCursor(*primitiveValue); |
|
3523 } |
|
3524 return; |
|
3525 // colors || inherit |
|
3526 case CSSPropertyColor: |
|
3527 // If the 'currentColor' keyword is set on the 'color' property itself, |
|
3528 // it is treated as 'color:inherit' at parse time |
|
3529 if (primitiveValue && primitiveValue->getIdent() == CSSValueCurrentcolor) |
|
3530 isInherit = true; |
|
3531 case CSSPropertyBackgroundColor: |
|
3532 case CSSPropertyBorderTopColor: |
|
3533 case CSSPropertyBorderRightColor: |
|
3534 case CSSPropertyBorderBottomColor: |
|
3535 case CSSPropertyBorderLeftColor: |
|
3536 case CSSPropertyOutlineColor: |
|
3537 case CSSPropertyWebkitColumnRuleColor: |
|
3538 case CSSPropertyWebkitTextStrokeColor: |
|
3539 case CSSPropertyWebkitTextFillColor: { |
|
3540 Color col; |
|
3541 if (isInherit) { |
|
3542 HANDLE_INHERIT_COND(CSSPropertyBackgroundColor, backgroundColor, BackgroundColor) |
|
3543 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderTopColor, borderTopColor, color, BorderTopColor) |
|
3544 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderBottomColor, borderBottomColor, color, BorderBottomColor) |
|
3545 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderRightColor, borderRightColor, color, BorderRightColor) |
|
3546 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderLeftColor, borderLeftColor, color, BorderLeftColor) |
|
3547 HANDLE_INHERIT_COND(CSSPropertyColor, color, Color) |
|
3548 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyOutlineColor, outlineColor, color, OutlineColor) |
|
3549 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitColumnRuleColor, columnRuleColor, color, ColumnRuleColor) |
|
3550 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitTextStrokeColor, textStrokeColor, color, TextStrokeColor) |
|
3551 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitTextFillColor, textFillColor, color, TextFillColor) |
|
3552 return; |
|
3553 } |
|
3554 if (isInitial) { |
|
3555 // The border/outline colors will just map to the invalid color |col| above. This will have the |
|
3556 // effect of forcing the use of the currentColor when it comes time to draw the borders (and of |
|
3557 // not painting the background since the color won't be valid). |
|
3558 if (id == CSSPropertyColor) |
|
3559 col = RenderStyle::initialColor(); |
|
3560 } else { |
|
3561 if (!primitiveValue) |
|
3562 return; |
|
3563 col = getColorFromPrimitiveValue(primitiveValue); |
|
3564 } |
|
3565 |
|
3566 switch (id) { |
|
3567 case CSSPropertyBackgroundColor: |
|
3568 m_style->setBackgroundColor(col); |
|
3569 break; |
|
3570 case CSSPropertyBorderTopColor: |
|
3571 m_style->setBorderTopColor(col); |
|
3572 break; |
|
3573 case CSSPropertyBorderRightColor: |
|
3574 m_style->setBorderRightColor(col); |
|
3575 break; |
|
3576 case CSSPropertyBorderBottomColor: |
|
3577 m_style->setBorderBottomColor(col); |
|
3578 break; |
|
3579 case CSSPropertyBorderLeftColor: |
|
3580 m_style->setBorderLeftColor(col); |
|
3581 break; |
|
3582 case CSSPropertyColor: |
|
3583 m_style->setColor(col); |
|
3584 break; |
|
3585 case CSSPropertyOutlineColor: |
|
3586 m_style->setOutlineColor(col); |
|
3587 break; |
|
3588 case CSSPropertyWebkitColumnRuleColor: |
|
3589 m_style->setColumnRuleColor(col); |
|
3590 break; |
|
3591 case CSSPropertyWebkitTextStrokeColor: |
|
3592 m_style->setTextStrokeColor(col); |
|
3593 break; |
|
3594 case CSSPropertyWebkitTextFillColor: |
|
3595 m_style->setTextFillColor(col); |
|
3596 break; |
|
3597 } |
|
3598 |
|
3599 return; |
|
3600 } |
|
3601 |
|
3602 // uri || inherit |
|
3603 case CSSPropertyBackgroundImage: |
|
3604 HANDLE_BACKGROUND_VALUE(image, Image, value) |
|
3605 return; |
|
3606 case CSSPropertyWebkitMaskImage: |
|
3607 HANDLE_MASK_VALUE(image, Image, value) |
|
3608 return; |
|
3609 case CSSPropertyListStyleImage: |
|
3610 { |
|
3611 HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage) |
|
3612 m_style->setListStyleImage(styleImage(value)); |
|
3613 return; |
|
3614 } |
|
3615 |
|
3616 // length |
|
3617 case CSSPropertyBorderTopWidth: |
|
3618 case CSSPropertyBorderRightWidth: |
|
3619 case CSSPropertyBorderBottomWidth: |
|
3620 case CSSPropertyBorderLeftWidth: |
|
3621 case CSSPropertyOutlineWidth: |
|
3622 case CSSPropertyWebkitColumnRuleWidth: |
|
3623 { |
|
3624 if (isInherit) { |
|
3625 HANDLE_INHERIT_COND(CSSPropertyBorderTopWidth, borderTopWidth, BorderTopWidth) |
|
3626 HANDLE_INHERIT_COND(CSSPropertyBorderRightWidth, borderRightWidth, BorderRightWidth) |
|
3627 HANDLE_INHERIT_COND(CSSPropertyBorderBottomWidth, borderBottomWidth, BorderBottomWidth) |
|
3628 HANDLE_INHERIT_COND(CSSPropertyBorderLeftWidth, borderLeftWidth, BorderLeftWidth) |
|
3629 HANDLE_INHERIT_COND(CSSPropertyOutlineWidth, outlineWidth, OutlineWidth) |
|
3630 HANDLE_INHERIT_COND(CSSPropertyWebkitColumnRuleWidth, columnRuleWidth, ColumnRuleWidth) |
|
3631 return; |
|
3632 } |
|
3633 else if (isInitial) { |
|
3634 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopWidth, BorderTopWidth, BorderWidth) |
|
3635 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderRightWidth, BorderRightWidth, BorderWidth) |
|
3636 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomWidth, BorderBottomWidth, BorderWidth) |
|
3637 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderLeftWidth, BorderLeftWidth, BorderWidth) |
|
3638 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyOutlineWidth, OutlineWidth, BorderWidth) |
|
3639 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitColumnRuleWidth, ColumnRuleWidth, BorderWidth) |
|
3640 return; |
|
3641 } |
|
3642 |
|
3643 if (!primitiveValue) |
|
3644 return; |
|
3645 short width = 3; |
|
3646 switch (primitiveValue->getIdent()) { |
|
3647 case CSSValueThin: |
|
3648 width = 1; |
|
3649 break; |
|
3650 case CSSValueMedium: |
|
3651 width = 3; |
|
3652 break; |
|
3653 case CSSValueThick: |
|
3654 width = 5; |
|
3655 break; |
|
3656 case CSSValueInvalid: |
|
3657 width = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor); |
|
3658 break; |
|
3659 default: |
|
3660 return; |
|
3661 } |
|
3662 |
|
3663 if (width < 0) return; |
|
3664 switch (id) { |
|
3665 case CSSPropertyBorderTopWidth: |
|
3666 m_style->setBorderTopWidth(width); |
|
3667 break; |
|
3668 case CSSPropertyBorderRightWidth: |
|
3669 m_style->setBorderRightWidth(width); |
|
3670 break; |
|
3671 case CSSPropertyBorderBottomWidth: |
|
3672 m_style->setBorderBottomWidth(width); |
|
3673 break; |
|
3674 case CSSPropertyBorderLeftWidth: |
|
3675 m_style->setBorderLeftWidth(width); |
|
3676 break; |
|
3677 case CSSPropertyOutlineWidth: |
|
3678 m_style->setOutlineWidth(width); |
|
3679 break; |
|
3680 case CSSPropertyWebkitColumnRuleWidth: |
|
3681 m_style->setColumnRuleWidth(width); |
|
3682 break; |
|
3683 default: |
|
3684 return; |
|
3685 } |
|
3686 return; |
|
3687 } |
|
3688 |
|
3689 case CSSPropertyWebkitFontSmoothing: { |
|
3690 FontDescription fontDescription = m_style->fontDescription(); |
|
3691 if (isInherit) |
|
3692 fontDescription.setFontSmoothing(m_parentStyle->fontDescription().fontSmoothing()); |
|
3693 else if (isInitial) |
|
3694 fontDescription.setFontSmoothing(AutoSmoothing); |
|
3695 else { |
|
3696 if (!primitiveValue) |
|
3697 return; |
|
3698 int id = primitiveValue->getIdent(); |
|
3699 FontSmoothingMode smoothing; |
|
3700 switch (id) { |
|
3701 case CSSValueAuto: |
|
3702 smoothing = AutoSmoothing; |
|
3703 break; |
|
3704 case CSSValueNone: |
|
3705 smoothing = NoSmoothing; |
|
3706 break; |
|
3707 case CSSValueAntialiased: |
|
3708 smoothing = Antialiased; |
|
3709 break; |
|
3710 case CSSValueSubpixelAntialiased: |
|
3711 smoothing = SubpixelAntialiased; |
|
3712 break; |
|
3713 default: |
|
3714 ASSERT_NOT_REACHED(); |
|
3715 smoothing = AutoSmoothing; |
|
3716 } |
|
3717 fontDescription.setFontSmoothing(smoothing); |
|
3718 } |
|
3719 if (m_style->setFontDescription(fontDescription)) |
|
3720 m_fontDirty = true; |
|
3721 return; |
|
3722 } |
|
3723 |
|
3724 case CSSPropertyLetterSpacing: |
|
3725 case CSSPropertyWordSpacing: |
|
3726 { |
|
3727 |
|
3728 if (isInherit) { |
|
3729 HANDLE_INHERIT_COND(CSSPropertyLetterSpacing, letterSpacing, LetterSpacing) |
|
3730 HANDLE_INHERIT_COND(CSSPropertyWordSpacing, wordSpacing, WordSpacing) |
|
3731 return; |
|
3732 } |
|
3733 else if (isInitial) { |
|
3734 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLetterSpacing, LetterSpacing, LetterWordSpacing) |
|
3735 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWordSpacing, WordSpacing, LetterWordSpacing) |
|
3736 return; |
|
3737 } |
|
3738 |
|
3739 int width = 0; |
|
3740 if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal) { |
|
3741 width = 0; |
|
3742 } else { |
|
3743 if (!primitiveValue) |
|
3744 return; |
|
3745 width = primitiveValue->computeLengthInt(style(), m_rootElementStyle, useSVGZoomRules ? 1.0f : zoomFactor); |
|
3746 } |
|
3747 switch (id) { |
|
3748 case CSSPropertyLetterSpacing: |
|
3749 m_style->setLetterSpacing(width); |
|
3750 break; |
|
3751 case CSSPropertyWordSpacing: |
|
3752 m_style->setWordSpacing(width); |
|
3753 break; |
|
3754 // ### needs the definitions in renderstyle |
|
3755 default: break; |
|
3756 } |
|
3757 return; |
|
3758 } |
|
3759 |
|
3760 case CSSPropertyWordBreak: |
|
3761 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordBreak, WordBreak) |
|
3762 return; |
|
3763 case CSSPropertyWordWrap: |
|
3764 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordWrap, WordWrap) |
|
3765 return; |
|
3766 case CSSPropertyWebkitNbspMode: |
|
3767 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(nbspMode, NBSPMode) |
|
3768 return; |
|
3769 case CSSPropertyWebkitLineBreak: |
|
3770 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(khtmlLineBreak, KHTMLLineBreak) |
|
3771 return; |
|
3772 case CSSPropertyWebkitMatchNearestMailBlockquoteColor: |
|
3773 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor) |
|
3774 return; |
|
3775 |
|
3776 case CSSPropertyResize: |
|
3777 { |
|
3778 HANDLE_INHERIT_AND_INITIAL(resize, Resize) |
|
3779 |
|
3780 if (!primitiveValue->getIdent()) |
|
3781 return; |
|
3782 |
|
3783 EResize r = RESIZE_NONE; |
|
3784 if (primitiveValue->getIdent() == CSSValueAuto) { |
|
3785 if (Settings* settings = m_checker.m_document->settings()) |
|
3786 r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE; |
|
3787 } else |
|
3788 r = *primitiveValue; |
|
3789 |
|
3790 m_style->setResize(r); |
|
3791 return; |
|
3792 } |
|
3793 |
|
3794 // length, percent |
|
3795 case CSSPropertyMaxWidth: |
|
3796 // +none +inherit |
|
3797 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) |
|
3798 apply = true; |
|
3799 case CSSPropertyTop: |
|
3800 case CSSPropertyLeft: |
|
3801 case CSSPropertyRight: |
|
3802 case CSSPropertyBottom: |
|
3803 case CSSPropertyWidth: |
|
3804 case CSSPropertyMinWidth: |
|
3805 case CSSPropertyMarginTop: |
|
3806 case CSSPropertyMarginRight: |
|
3807 case CSSPropertyMarginBottom: |
|
3808 case CSSPropertyMarginLeft: |
|
3809 // +inherit +auto |
|
3810 if (id == CSSPropertyWidth || id == CSSPropertyMinWidth || id == CSSPropertyMaxWidth) { |
|
3811 if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) { |
|
3812 l = Length(Intrinsic); |
|
3813 apply = true; |
|
3814 } |
|
3815 else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) { |
|
3816 l = Length(MinIntrinsic); |
|
3817 apply = true; |
|
3818 } |
|
3819 } |
|
3820 if (id != CSSPropertyMaxWidth && primitiveValue && primitiveValue->getIdent() == CSSValueAuto) |
|
3821 apply = true; |
|
3822 case CSSPropertyPaddingTop: |
|
3823 case CSSPropertyPaddingRight: |
|
3824 case CSSPropertyPaddingBottom: |
|
3825 case CSSPropertyPaddingLeft: |
|
3826 case CSSPropertyTextIndent: |
|
3827 // +inherit |
|
3828 { |
|
3829 if (isInherit) { |
|
3830 HANDLE_INHERIT_COND(CSSPropertyMaxWidth, maxWidth, MaxWidth) |
|
3831 HANDLE_INHERIT_COND(CSSPropertyBottom, bottom, Bottom) |
|
3832 HANDLE_INHERIT_COND(CSSPropertyTop, top, Top) |
|
3833 HANDLE_INHERIT_COND(CSSPropertyLeft, left, Left) |
|
3834 HANDLE_INHERIT_COND(CSSPropertyRight, right, Right) |
|
3835 HANDLE_INHERIT_COND(CSSPropertyWidth, width, Width) |
|
3836 HANDLE_INHERIT_COND(CSSPropertyMinWidth, minWidth, MinWidth) |
|
3837 HANDLE_INHERIT_COND(CSSPropertyPaddingTop, paddingTop, PaddingTop) |
|
3838 HANDLE_INHERIT_COND(CSSPropertyPaddingRight, paddingRight, PaddingRight) |
|
3839 HANDLE_INHERIT_COND(CSSPropertyPaddingBottom, paddingBottom, PaddingBottom) |
|
3840 HANDLE_INHERIT_COND(CSSPropertyPaddingLeft, paddingLeft, PaddingLeft) |
|
3841 HANDLE_INHERIT_COND(CSSPropertyMarginTop, marginTop, MarginTop) |
|
3842 HANDLE_INHERIT_COND(CSSPropertyMarginRight, marginRight, MarginRight) |
|
3843 HANDLE_INHERIT_COND(CSSPropertyMarginBottom, marginBottom, MarginBottom) |
|
3844 HANDLE_INHERIT_COND(CSSPropertyMarginLeft, marginLeft, MarginLeft) |
|
3845 HANDLE_INHERIT_COND(CSSPropertyTextIndent, textIndent, TextIndent) |
|
3846 return; |
|
3847 } |
|
3848 else if (isInitial) { |
|
3849 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxWidth, MaxWidth, MaxSize) |
|
3850 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBottom, Bottom, Offset) |
|
3851 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyTop, Top, Offset) |
|
3852 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLeft, Left, Offset) |
|
3853 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyRight, Right, Offset) |
|
3854 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWidth, Width, Size) |
|
3855 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinWidth, MinWidth, MinSize) |
|
3856 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingTop, PaddingTop, Padding) |
|
3857 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingRight, PaddingRight, Padding) |
|
3858 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingBottom, PaddingBottom, Padding) |
|
3859 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingLeft, PaddingLeft, Padding) |
|
3860 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginTop, MarginTop, Margin) |
|
3861 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginRight, MarginRight, Margin) |
|
3862 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginBottom, MarginBottom, Margin) |
|
3863 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginLeft, MarginLeft, Margin) |
|
3864 HANDLE_INITIAL_COND(CSSPropertyTextIndent, TextIndent) |
|
3865 return; |
|
3866 } |
|
3867 |
|
3868 if (primitiveValue && !apply) { |
|
3869 int type = primitiveValue->primitiveType(); |
|
3870 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
3871 // Handle our quirky margin units if we have them. |
|
3872 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed, |
|
3873 primitiveValue->isQuirkValue()); |
|
3874 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
3875 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
3876 else |
|
3877 return; |
|
3878 apply = true; |
|
3879 } |
|
3880 if (!apply) return; |
|
3881 switch (id) { |
|
3882 case CSSPropertyMaxWidth: |
|
3883 m_style->setMaxWidth(l); |
|
3884 break; |
|
3885 case CSSPropertyBottom: |
|
3886 m_style->setBottom(l); |
|
3887 break; |
|
3888 case CSSPropertyTop: |
|
3889 m_style->setTop(l); |
|
3890 break; |
|
3891 case CSSPropertyLeft: |
|
3892 m_style->setLeft(l); |
|
3893 break; |
|
3894 case CSSPropertyRight: |
|
3895 m_style->setRight(l); |
|
3896 break; |
|
3897 case CSSPropertyWidth: |
|
3898 m_style->setWidth(l); |
|
3899 break; |
|
3900 case CSSPropertyMinWidth: |
|
3901 m_style->setMinWidth(l); |
|
3902 break; |
|
3903 case CSSPropertyPaddingTop: |
|
3904 m_style->setPaddingTop(l); |
|
3905 break; |
|
3906 case CSSPropertyPaddingRight: |
|
3907 m_style->setPaddingRight(l); |
|
3908 break; |
|
3909 case CSSPropertyPaddingBottom: |
|
3910 m_style->setPaddingBottom(l); |
|
3911 break; |
|
3912 case CSSPropertyPaddingLeft: |
|
3913 m_style->setPaddingLeft(l); |
|
3914 break; |
|
3915 case CSSPropertyMarginTop: |
|
3916 m_style->setMarginTop(l); |
|
3917 break; |
|
3918 case CSSPropertyMarginRight: |
|
3919 m_style->setMarginRight(l); |
|
3920 break; |
|
3921 case CSSPropertyMarginBottom: |
|
3922 m_style->setMarginBottom(l); |
|
3923 break; |
|
3924 case CSSPropertyMarginLeft: |
|
3925 m_style->setMarginLeft(l); |
|
3926 break; |
|
3927 case CSSPropertyTextIndent: |
|
3928 m_style->setTextIndent(l); |
|
3929 break; |
|
3930 default: |
|
3931 break; |
|
3932 } |
|
3933 return; |
|
3934 } |
|
3935 |
|
3936 case CSSPropertyMaxHeight: |
|
3937 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) { |
|
3938 l = Length(undefinedLength, Fixed); |
|
3939 apply = true; |
|
3940 } |
|
3941 case CSSPropertyHeight: |
|
3942 case CSSPropertyMinHeight: |
|
3943 if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) { |
|
3944 l = Length(Intrinsic); |
|
3945 apply = true; |
|
3946 } else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) { |
|
3947 l = Length(MinIntrinsic); |
|
3948 apply = true; |
|
3949 } else if (id != CSSPropertyMaxHeight && primitiveValue && primitiveValue->getIdent() == CSSValueAuto) |
|
3950 apply = true; |
|
3951 if (isInherit) { |
|
3952 HANDLE_INHERIT_COND(CSSPropertyMaxHeight, maxHeight, MaxHeight) |
|
3953 HANDLE_INHERIT_COND(CSSPropertyHeight, height, Height) |
|
3954 HANDLE_INHERIT_COND(CSSPropertyMinHeight, minHeight, MinHeight) |
|
3955 return; |
|
3956 } |
|
3957 if (isInitial) { |
|
3958 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxHeight, MaxHeight, MaxSize) |
|
3959 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyHeight, Height, Size) |
|
3960 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinHeight, MinHeight, MinSize) |
|
3961 return; |
|
3962 } |
|
3963 |
|
3964 if (primitiveValue && !apply) { |
|
3965 unsigned short type = primitiveValue->primitiveType(); |
|
3966 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
3967 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); |
|
3968 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
3969 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
3970 else |
|
3971 return; |
|
3972 apply = true; |
|
3973 } |
|
3974 if (apply) |
|
3975 switch (id) { |
|
3976 case CSSPropertyMaxHeight: |
|
3977 m_style->setMaxHeight(l); |
|
3978 break; |
|
3979 case CSSPropertyHeight: |
|
3980 m_style->setHeight(l); |
|
3981 break; |
|
3982 case CSSPropertyMinHeight: |
|
3983 m_style->setMinHeight(l); |
|
3984 break; |
|
3985 } |
|
3986 return; |
|
3987 |
|
3988 case CSSPropertyVerticalAlign: |
|
3989 HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign) |
|
3990 if (!primitiveValue) |
|
3991 return; |
|
3992 if (primitiveValue->getIdent()) { |
|
3993 EVerticalAlign align; |
|
3994 |
|
3995 switch (primitiveValue->getIdent()) { |
|
3996 case CSSValueTop: |
|
3997 align = TOP; break; |
|
3998 case CSSValueBottom: |
|
3999 align = BOTTOM; break; |
|
4000 case CSSValueMiddle: |
|
4001 align = MIDDLE; break; |
|
4002 case CSSValueBaseline: |
|
4003 align = BASELINE; break; |
|
4004 case CSSValueTextBottom: |
|
4005 align = TEXT_BOTTOM; break; |
|
4006 case CSSValueTextTop: |
|
4007 align = TEXT_TOP; break; |
|
4008 case CSSValueSub: |
|
4009 align = SUB; break; |
|
4010 case CSSValueSuper: |
|
4011 align = SUPER; break; |
|
4012 case CSSValueWebkitBaselineMiddle: |
|
4013 align = BASELINE_MIDDLE; break; |
|
4014 default: |
|
4015 return; |
|
4016 } |
|
4017 m_style->setVerticalAlign(align); |
|
4018 return; |
|
4019 } else { |
|
4020 int type = primitiveValue->primitiveType(); |
|
4021 Length l; |
|
4022 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
4023 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); |
|
4024 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
4025 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
4026 |
|
4027 m_style->setVerticalAlign(LENGTH); |
|
4028 m_style->setVerticalAlignLength(l); |
|
4029 } |
|
4030 return; |
|
4031 |
|
4032 case CSSPropertyFontSize: |
|
4033 { |
|
4034 FontDescription fontDescription = m_style->fontDescription(); |
|
4035 fontDescription.setKeywordSize(0); |
|
4036 float oldSize = 0; |
|
4037 float size = 0; |
|
4038 |
|
4039 bool parentIsAbsoluteSize = false; |
|
4040 if (m_parentNode) { |
|
4041 oldSize = m_parentStyle->fontDescription().specifiedSize(); |
|
4042 parentIsAbsoluteSize = m_parentStyle->fontDescription().isAbsoluteSize(); |
|
4043 } |
|
4044 |
|
4045 if (isInherit) { |
|
4046 size = oldSize; |
|
4047 if (m_parentNode) |
|
4048 fontDescription.setKeywordSize(m_parentStyle->fontDescription().keywordSize()); |
|
4049 } else if (isInitial) { |
|
4050 size = fontSizeForKeyword(m_checker.m_document, CSSValueMedium, fontDescription.useFixedDefaultSize()); |
|
4051 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); |
|
4052 } else if (primitiveValue->getIdent()) { |
|
4053 // Keywords are being used. |
|
4054 switch (primitiveValue->getIdent()) { |
|
4055 case CSSValueXxSmall: |
|
4056 case CSSValueXSmall: |
|
4057 case CSSValueSmall: |
|
4058 case CSSValueMedium: |
|
4059 case CSSValueLarge: |
|
4060 case CSSValueXLarge: |
|
4061 case CSSValueXxLarge: |
|
4062 case CSSValueWebkitXxxLarge: |
|
4063 size = fontSizeForKeyword(m_checker.m_document, primitiveValue->getIdent(), fontDescription.useFixedDefaultSize()); |
|
4064 fontDescription.setKeywordSize(primitiveValue->getIdent() - CSSValueXxSmall + 1); |
|
4065 break; |
|
4066 case CSSValueLarger: |
|
4067 size = largerFontSize(oldSize, m_style->htmlHacks()); |
|
4068 break; |
|
4069 case CSSValueSmaller: |
|
4070 size = smallerFontSize(oldSize, m_style->htmlHacks()); |
|
4071 break; |
|
4072 default: |
|
4073 return; |
|
4074 } |
|
4075 |
|
4076 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize && |
|
4077 (primitiveValue->getIdent() == CSSValueLarger || |
|
4078 primitiveValue->getIdent() == CSSValueSmaller)); |
|
4079 } else { |
|
4080 int type = primitiveValue->primitiveType(); |
|
4081 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize || |
|
4082 (type != CSSPrimitiveValue::CSS_PERCENTAGE && |
|
4083 type != CSSPrimitiveValue::CSS_EMS && |
|
4084 type != CSSPrimitiveValue::CSS_EXS && |
|
4085 type != CSSPrimitiveValue::CSS_REMS)); |
|
4086 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
4087 size = primitiveValue->computeLengthFloat(m_parentStyle, m_rootElementStyle, true); |
|
4088 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
4089 size = (primitiveValue->getFloatValue() * oldSize) / 100.0f; |
|
4090 else |
|
4091 return; |
|
4092 } |
|
4093 |
|
4094 if (size < 0) |
|
4095 return; |
|
4096 |
|
4097 setFontSize(fontDescription, size); |
|
4098 if (m_style->setFontDescription(fontDescription)) |
|
4099 m_fontDirty = true; |
|
4100 return; |
|
4101 } |
|
4102 |
|
4103 case CSSPropertyZIndex: { |
|
4104 if (isInherit) { |
|
4105 if (m_parentStyle->hasAutoZIndex()) |
|
4106 m_style->setHasAutoZIndex(); |
|
4107 else |
|
4108 m_style->setZIndex(m_parentStyle->zIndex()); |
|
4109 return; |
|
4110 } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) { |
|
4111 m_style->setHasAutoZIndex(); |
|
4112 return; |
|
4113 } |
|
4114 |
|
4115 // FIXME: Should clamp all sorts of other integer properties too. |
|
4116 const double minIntAsDouble = INT_MIN; |
|
4117 const double maxIntAsDouble = INT_MAX; |
|
4118 m_style->setZIndex(static_cast<int>(max(minIntAsDouble, min(primitiveValue->getDoubleValue(), maxIntAsDouble)))); |
|
4119 return; |
|
4120 } |
|
4121 case CSSPropertyWidows: |
|
4122 { |
|
4123 HANDLE_INHERIT_AND_INITIAL(widows, Widows) |
|
4124 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
4125 return; |
|
4126 m_style->setWidows(primitiveValue->getIntValue()); |
|
4127 return; |
|
4128 } |
|
4129 |
|
4130 case CSSPropertyOrphans: |
|
4131 { |
|
4132 HANDLE_INHERIT_AND_INITIAL(orphans, Orphans) |
|
4133 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
4134 return; |
|
4135 m_style->setOrphans(primitiveValue->getIntValue()); |
|
4136 return; |
|
4137 } |
|
4138 |
|
4139 // length, percent, number |
|
4140 case CSSPropertyLineHeight: |
|
4141 { |
|
4142 HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight) |
|
4143 if (!primitiveValue) |
|
4144 return; |
|
4145 Length lineHeight; |
|
4146 int type = primitiveValue->primitiveType(); |
|
4147 if (primitiveValue->getIdent() == CSSValueNormal) |
|
4148 lineHeight = Length(-100.0, Percent); |
|
4149 else if (CSSPrimitiveValue::isUnitTypeLength(type)) { |
|
4150 double multiplier = zoomFactor; |
|
4151 if (m_style->textSizeAdjust()) { |
|
4152 if (FrameView* view = m_checker.m_document->view()) { |
|
4153 if (view->shouldApplyTextZoom()) |
|
4154 multiplier *= view->textZoomFactor(); |
|
4155 } |
|
4156 } |
|
4157 lineHeight = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, multiplier), Fixed); |
|
4158 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
4159 lineHeight = Length((m_style->fontSize() * primitiveValue->getIntValue()) / 100, Fixed); |
|
4160 else if (type == CSSPrimitiveValue::CSS_NUMBER) |
|
4161 lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent); |
|
4162 else |
|
4163 return; |
|
4164 m_style->setLineHeight(lineHeight); |
|
4165 return; |
|
4166 } |
|
4167 |
|
4168 // string |
|
4169 case CSSPropertyTextAlign: |
|
4170 { |
|
4171 HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign) |
|
4172 if (!primitiveValue) |
|
4173 return; |
|
4174 int id = primitiveValue->getIdent(); |
|
4175 if (id == CSSValueStart) |
|
4176 m_style->setTextAlign(m_style->direction() == LTR ? LEFT : RIGHT); |
|
4177 else if (id == CSSValueEnd) |
|
4178 m_style->setTextAlign(m_style->direction() == LTR ? RIGHT : LEFT); |
|
4179 else |
|
4180 m_style->setTextAlign(*primitiveValue); |
|
4181 return; |
|
4182 } |
|
4183 |
|
4184 // rect |
|
4185 case CSSPropertyClip: |
|
4186 { |
|
4187 Length top; |
|
4188 Length right; |
|
4189 Length bottom; |
|
4190 Length left; |
|
4191 bool hasClip = true; |
|
4192 if (isInherit) { |
|
4193 if (m_parentStyle->hasClip()) { |
|
4194 top = m_parentStyle->clipTop(); |
|
4195 right = m_parentStyle->clipRight(); |
|
4196 bottom = m_parentStyle->clipBottom(); |
|
4197 left = m_parentStyle->clipLeft(); |
|
4198 } else { |
|
4199 hasClip = false; |
|
4200 top = right = bottom = left = Length(); |
|
4201 } |
|
4202 } else if (isInitial) { |
|
4203 hasClip = false; |
|
4204 top = right = bottom = left = Length(); |
|
4205 } else if (!primitiveValue) { |
|
4206 return; |
|
4207 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) { |
|
4208 Rect* rect = primitiveValue->getRectValue(); |
|
4209 if (!rect) |
|
4210 return; |
|
4211 top = convertToLength(rect->top(), style(), m_rootElementStyle, zoomFactor); |
|
4212 right = convertToLength(rect->right(), style(), m_rootElementStyle, zoomFactor); |
|
4213 bottom = convertToLength(rect->bottom(), style(), m_rootElementStyle, zoomFactor); |
|
4214 left = convertToLength(rect->left(), style(), m_rootElementStyle, zoomFactor); |
|
4215 } else if (primitiveValue->getIdent() != CSSValueAuto) { |
|
4216 return; |
|
4217 } |
|
4218 m_style->setClip(top, right, bottom, left); |
|
4219 m_style->setHasClip(hasClip); |
|
4220 |
|
4221 // rect, ident |
|
4222 return; |
|
4223 } |
|
4224 |
|
4225 // lists |
|
4226 case CSSPropertyContent: |
|
4227 // list of string, uri, counter, attr, i |
|
4228 { |
|
4229 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This |
|
4230 // note is a reminder that eventually "inherit" needs to be supported. |
|
4231 |
|
4232 if (isInitial) { |
|
4233 m_style->clearContent(); |
|
4234 return; |
|
4235 } |
|
4236 |
|
4237 if (!value->isValueList()) |
|
4238 return; |
|
4239 |
|
4240 CSSValueList* list = static_cast<CSSValueList*>(value); |
|
4241 int len = list->length(); |
|
4242 |
|
4243 bool didSet = false; |
|
4244 for (int i = 0; i < len; i++) { |
|
4245 CSSValue* item = list->itemWithoutBoundsCheck(i); |
|
4246 if (item->isImageGeneratorValue()) { |
|
4247 m_style->setContent(static_cast<CSSImageGeneratorValue*>(item)->generatedImage(), didSet); |
|
4248 didSet = true; |
|
4249 } |
|
4250 |
|
4251 if (!item->isPrimitiveValue()) |
|
4252 continue; |
|
4253 |
|
4254 CSSPrimitiveValue* val = static_cast<CSSPrimitiveValue*>(item); |
|
4255 switch (val->primitiveType()) { |
|
4256 case CSSPrimitiveValue::CSS_STRING: |
|
4257 m_style->setContent(val->getStringValue().impl(), didSet); |
|
4258 didSet = true; |
|
4259 break; |
|
4260 case CSSPrimitiveValue::CSS_ATTR: { |
|
4261 // FIXME: Can a namespace be specified for an attr(foo)? |
|
4262 if (m_style->styleType() == NOPSEUDO) |
|
4263 m_style->setUnique(); |
|
4264 else |
|
4265 m_parentStyle->setUnique(); |
|
4266 QualifiedName attr(nullAtom, val->getStringValue().impl(), nullAtom); |
|
4267 m_style->setContent(m_element->getAttribute(attr).impl(), didSet); |
|
4268 didSet = true; |
|
4269 // register the fact that the attribute value affects the style |
|
4270 m_selectorAttrs.add(attr.localName().impl()); |
|
4271 break; |
|
4272 } |
|
4273 case CSSPrimitiveValue::CSS_URI: { |
|
4274 CSSImageValue* image = static_cast<CSSImageValue*>(val); |
|
4275 m_style->setContent(image->cachedImage(m_element->document()->docLoader()), didSet); |
|
4276 didSet = true; |
|
4277 break; |
|
4278 } |
|
4279 case CSSPrimitiveValue::CSS_COUNTER: { |
|
4280 Counter* counterValue = val->getCounterValue(); |
|
4281 CounterContent* counter = new CounterContent(counterValue->identifier(), |
|
4282 (EListStyleType)counterValue->listStyleNumber(), counterValue->separator()); |
|
4283 m_style->setContent(counter, didSet); |
|
4284 didSet = true; |
|
4285 } |
|
4286 } |
|
4287 } |
|
4288 if (!didSet) |
|
4289 m_style->clearContent(); |
|
4290 return; |
|
4291 } |
|
4292 |
|
4293 case CSSPropertyCounterIncrement: |
|
4294 applyCounterList(style(), value->isValueList() ? static_cast<CSSValueList*>(value) : 0, false); |
|
4295 return; |
|
4296 case CSSPropertyCounterReset: |
|
4297 applyCounterList(style(), value->isValueList() ? static_cast<CSSValueList*>(value) : 0, true); |
|
4298 return; |
|
4299 |
|
4300 case CSSPropertyFontFamily: { |
|
4301 // list of strings and ids |
|
4302 if (isInherit) { |
|
4303 FontDescription parentFontDescription = m_parentStyle->fontDescription(); |
|
4304 FontDescription fontDescription = m_style->fontDescription(); |
|
4305 fontDescription.setGenericFamily(parentFontDescription.genericFamily()); |
|
4306 fontDescription.setFamily(parentFontDescription.firstFamily()); |
|
4307 if (m_style->setFontDescription(fontDescription)) |
|
4308 m_fontDirty = true; |
|
4309 return; |
|
4310 } else if (isInitial) { |
|
4311 FontDescription initialDesc = FontDescription(); |
|
4312 FontDescription fontDescription = m_style->fontDescription(); |
|
4313 // We need to adjust the size to account for the generic family change from monospace |
|
4314 // to non-monospace. |
|
4315 if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize()) |
|
4316 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + fontDescription.keywordSize() - 1, false)); |
|
4317 fontDescription.setGenericFamily(initialDesc.genericFamily()); |
|
4318 if (!initialDesc.firstFamily().familyIsEmpty()) |
|
4319 fontDescription.setFamily(initialDesc.firstFamily()); |
|
4320 if (m_style->setFontDescription(fontDescription)) |
|
4321 m_fontDirty = true; |
|
4322 return; |
|
4323 } |
|
4324 |
|
4325 if (!value->isValueList()) |
|
4326 return; |
|
4327 FontDescription fontDescription = m_style->fontDescription(); |
|
4328 CSSValueList* list = static_cast<CSSValueList*>(value); |
|
4329 int len = list->length(); |
|
4330 FontFamily& firstFamily = fontDescription.firstFamily(); |
|
4331 FontFamily* currFamily = 0; |
|
4332 |
|
4333 // Before mapping in a new font-family property, we should reset the generic family. |
|
4334 bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize(); |
|
4335 fontDescription.setGenericFamily(FontDescription::NoFamily); |
|
4336 |
|
4337 for (int i = 0; i < len; i++) { |
|
4338 CSSValue* item = list->itemWithoutBoundsCheck(i); |
|
4339 if (!item->isPrimitiveValue()) |
|
4340 continue; |
|
4341 CSSPrimitiveValue* val = static_cast<CSSPrimitiveValue*>(item); |
|
4342 AtomicString face; |
|
4343 Settings* settings = m_checker.m_document->settings(); |
|
4344 if (val->primitiveType() == CSSPrimitiveValue::CSS_STRING) |
|
4345 face = static_cast<FontFamilyValue*>(val)->familyName(); |
|
4346 else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) { |
|
4347 switch (val->getIdent()) { |
|
4348 case CSSValueWebkitBody: |
|
4349 face = settings->standardFontFamily(); |
|
4350 break; |
|
4351 case CSSValueSerif: |
|
4352 face = "-webkit-serif"; |
|
4353 fontDescription.setGenericFamily(FontDescription::SerifFamily); |
|
4354 break; |
|
4355 case CSSValueSansSerif: |
|
4356 face = "-webkit-sans-serif"; |
|
4357 fontDescription.setGenericFamily(FontDescription::SansSerifFamily); |
|
4358 break; |
|
4359 case CSSValueCursive: |
|
4360 face = "-webkit-cursive"; |
|
4361 fontDescription.setGenericFamily(FontDescription::CursiveFamily); |
|
4362 break; |
|
4363 case CSSValueFantasy: |
|
4364 face = "-webkit-fantasy"; |
|
4365 fontDescription.setGenericFamily(FontDescription::FantasyFamily); |
|
4366 break; |
|
4367 case CSSValueMonospace: |
|
4368 face = "-webkit-monospace"; |
|
4369 fontDescription.setGenericFamily(FontDescription::MonospaceFamily); |
|
4370 break; |
|
4371 } |
|
4372 } |
|
4373 |
|
4374 if (!face.isEmpty()) { |
|
4375 if (!currFamily) { |
|
4376 // Filling in the first family. |
|
4377 firstFamily.setFamily(face); |
|
4378 firstFamily.appendFamily(0); // Remove any inherited family-fallback list. |
|
4379 currFamily = &firstFamily; |
|
4380 } else { |
|
4381 RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create(); |
|
4382 newFamily->setFamily(face); |
|
4383 currFamily->appendFamily(newFamily); |
|
4384 currFamily = newFamily.get(); |
|
4385 } |
|
4386 } |
|
4387 } |
|
4388 |
|
4389 // We can't call useFixedDefaultSize() until all new font families have been added |
|
4390 // If currFamily is non-zero then we set at least one family on this description. |
|
4391 if (currFamily) { |
|
4392 if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize) |
|
4393 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize)); |
|
4394 |
|
4395 if (m_style->setFontDescription(fontDescription)) |
|
4396 m_fontDirty = true; |
|
4397 } |
|
4398 return; |
|
4399 } |
|
4400 case CSSPropertyTextDecoration: { |
|
4401 // list of ident |
|
4402 HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration) |
|
4403 int t = RenderStyle::initialTextDecoration(); |
|
4404 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) { |
|
4405 // do nothing |
|
4406 } else { |
|
4407 if (!value->isValueList()) return; |
|
4408 CSSValueList *list = static_cast<CSSValueList*>(value); |
|
4409 int len = list->length(); |
|
4410 for (int i = 0; i < len; i++) |
|
4411 { |
|
4412 CSSValue *item = list->itemWithoutBoundsCheck(i); |
|
4413 if (!item->isPrimitiveValue()) continue; |
|
4414 primitiveValue = static_cast<CSSPrimitiveValue*>(item); |
|
4415 switch (primitiveValue->getIdent()) { |
|
4416 case CSSValueNone: |
|
4417 t = TDNONE; break; |
|
4418 case CSSValueUnderline: |
|
4419 t |= UNDERLINE; break; |
|
4420 case CSSValueOverline: |
|
4421 t |= OVERLINE; break; |
|
4422 case CSSValueLineThrough: |
|
4423 t |= LINE_THROUGH; break; |
|
4424 case CSSValueBlink: |
|
4425 t |= BLINK; break; |
|
4426 default: |
|
4427 return; |
|
4428 } |
|
4429 } |
|
4430 } |
|
4431 |
|
4432 m_style->setTextDecoration(t); |
|
4433 return; |
|
4434 } |
|
4435 |
|
4436 case CSSPropertyZoom: |
|
4437 { |
|
4438 // Reset the zoom in effect before we do anything. This allows the setZoom method to accurately compute a new |
|
4439 // zoom in effect. |
|
4440 m_style->setEffectiveZoom(m_parentStyle ? m_parentStyle->effectiveZoom() : RenderStyle::initialZoom()); |
|
4441 |
|
4442 // Now we can handle inherit and initial. |
|
4443 HANDLE_INHERIT_AND_INITIAL(zoom, Zoom) |
|
4444 |
|
4445 // Handle normal/reset, numbers and percentages. |
|
4446 int type = primitiveValue->primitiveType(); |
|
4447 if (primitiveValue->getIdent() == CSSValueNormal) |
|
4448 m_style->setZoom(RenderStyle::initialZoom()); |
|
4449 else if (primitiveValue->getIdent() == CSSValueReset) { |
|
4450 m_style->setEffectiveZoom(RenderStyle::initialZoom()); |
|
4451 m_style->setZoom(RenderStyle::initialZoom()); |
|
4452 } else if (primitiveValue->getIdent() == CSSValueDocument) { |
|
4453 float docZoom = m_checker.m_document->renderer()->style()->zoom(); |
|
4454 m_style->setEffectiveZoom(docZoom); |
|
4455 m_style->setZoom(docZoom); |
|
4456 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) { |
|
4457 if (primitiveValue->getFloatValue()) |
|
4458 m_style->setZoom(primitiveValue->getFloatValue() / 100.0f); |
|
4459 } else if (type == CSSPrimitiveValue::CSS_NUMBER) { |
|
4460 if (primitiveValue->getFloatValue()) |
|
4461 m_style->setZoom(primitiveValue->getFloatValue()); |
|
4462 } |
|
4463 |
|
4464 m_fontDirty = true; |
|
4465 return; |
|
4466 } |
|
4467 // shorthand properties |
|
4468 case CSSPropertyBackground: |
|
4469 if (isInitial) { |
|
4470 m_style->clearBackgroundLayers(); |
|
4471 m_style->setBackgroundColor(Color()); |
|
4472 } |
|
4473 else if (isInherit) { |
|
4474 m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers()); |
|
4475 m_style->setBackgroundColor(m_parentStyle->backgroundColor()); |
|
4476 } |
|
4477 return; |
|
4478 case CSSPropertyWebkitMask: |
|
4479 if (isInitial) |
|
4480 m_style->clearMaskLayers(); |
|
4481 else if (isInherit) |
|
4482 m_style->inheritMaskLayers(*m_parentStyle->maskLayers()); |
|
4483 return; |
|
4484 |
|
4485 case CSSPropertyBorder: |
|
4486 case CSSPropertyBorderStyle: |
|
4487 case CSSPropertyBorderWidth: |
|
4488 case CSSPropertyBorderColor: |
|
4489 if (id == CSSPropertyBorder || id == CSSPropertyBorderColor) |
|
4490 { |
|
4491 if (isInherit) { |
|
4492 m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color()); |
|
4493 m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color()); |
|
4494 m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color()); |
|
4495 m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor(): m_parentStyle->color()); |
|
4496 } |
|
4497 else if (isInitial) { |
|
4498 m_style->setBorderTopColor(Color()); // Reset to invalid color so currentColor is used instead. |
|
4499 m_style->setBorderBottomColor(Color()); |
|
4500 m_style->setBorderLeftColor(Color()); |
|
4501 m_style->setBorderRightColor(Color()); |
|
4502 } |
|
4503 } |
|
4504 if (id == CSSPropertyBorder || id == CSSPropertyBorderStyle) |
|
4505 { |
|
4506 if (isInherit) { |
|
4507 m_style->setBorderTopStyle(m_parentStyle->borderTopStyle()); |
|
4508 m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle()); |
|
4509 m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle()); |
|
4510 m_style->setBorderRightStyle(m_parentStyle->borderRightStyle()); |
|
4511 } |
|
4512 else if (isInitial) { |
|
4513 m_style->setBorderTopStyle(RenderStyle::initialBorderStyle()); |
|
4514 m_style->setBorderBottomStyle(RenderStyle::initialBorderStyle()); |
|
4515 m_style->setBorderLeftStyle(RenderStyle::initialBorderStyle()); |
|
4516 m_style->setBorderRightStyle(RenderStyle::initialBorderStyle()); |
|
4517 } |
|
4518 } |
|
4519 if (id == CSSPropertyBorder || id == CSSPropertyBorderWidth) |
|
4520 { |
|
4521 if (isInherit) { |
|
4522 m_style->setBorderTopWidth(m_parentStyle->borderTopWidth()); |
|
4523 m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth()); |
|
4524 m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth()); |
|
4525 m_style->setBorderRightWidth(m_parentStyle->borderRightWidth()); |
|
4526 } |
|
4527 else if (isInitial) { |
|
4528 m_style->setBorderTopWidth(RenderStyle::initialBorderWidth()); |
|
4529 m_style->setBorderBottomWidth(RenderStyle::initialBorderWidth()); |
|
4530 m_style->setBorderLeftWidth(RenderStyle::initialBorderWidth()); |
|
4531 m_style->setBorderRightWidth(RenderStyle::initialBorderWidth()); |
|
4532 } |
|
4533 } |
|
4534 return; |
|
4535 case CSSPropertyBorderTop: |
|
4536 if (isInherit) { |
|
4537 m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color()); |
|
4538 m_style->setBorderTopStyle(m_parentStyle->borderTopStyle()); |
|
4539 m_style->setBorderTopWidth(m_parentStyle->borderTopWidth()); |
|
4540 } |
|
4541 else if (isInitial) |
|
4542 m_style->resetBorderTop(); |
|
4543 return; |
|
4544 case CSSPropertyBorderRight: |
|
4545 if (isInherit) { |
|
4546 m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor() : m_parentStyle->color()); |
|
4547 m_style->setBorderRightStyle(m_parentStyle->borderRightStyle()); |
|
4548 m_style->setBorderRightWidth(m_parentStyle->borderRightWidth()); |
|
4549 } |
|
4550 else if (isInitial) |
|
4551 m_style->resetBorderRight(); |
|
4552 return; |
|
4553 case CSSPropertyBorderBottom: |
|
4554 if (isInherit) { |
|
4555 m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color()); |
|
4556 m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle()); |
|
4557 m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth()); |
|
4558 } |
|
4559 else if (isInitial) |
|
4560 m_style->resetBorderBottom(); |
|
4561 return; |
|
4562 case CSSPropertyBorderLeft: |
|
4563 if (isInherit) { |
|
4564 m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color()); |
|
4565 m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle()); |
|
4566 m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth()); |
|
4567 } |
|
4568 else if (isInitial) |
|
4569 m_style->resetBorderLeft(); |
|
4570 return; |
|
4571 case CSSPropertyMargin: |
|
4572 if (isInherit) { |
|
4573 m_style->setMarginTop(m_parentStyle->marginTop()); |
|
4574 m_style->setMarginBottom(m_parentStyle->marginBottom()); |
|
4575 m_style->setMarginLeft(m_parentStyle->marginLeft()); |
|
4576 m_style->setMarginRight(m_parentStyle->marginRight()); |
|
4577 } |
|
4578 else if (isInitial) |
|
4579 m_style->resetMargin(); |
|
4580 return; |
|
4581 case CSSPropertyPadding: |
|
4582 if (isInherit) { |
|
4583 m_style->setPaddingTop(m_parentStyle->paddingTop()); |
|
4584 m_style->setPaddingBottom(m_parentStyle->paddingBottom()); |
|
4585 m_style->setPaddingLeft(m_parentStyle->paddingLeft()); |
|
4586 m_style->setPaddingRight(m_parentStyle->paddingRight()); |
|
4587 } |
|
4588 else if (isInitial) |
|
4589 m_style->resetPadding(); |
|
4590 return; |
|
4591 case CSSPropertyFont: |
|
4592 if (isInherit) { |
|
4593 FontDescription fontDescription = m_parentStyle->fontDescription(); |
|
4594 m_style->setLineHeight(m_parentStyle->lineHeight()); |
|
4595 m_lineHeightValue = 0; |
|
4596 if (m_style->setFontDescription(fontDescription)) |
|
4597 m_fontDirty = true; |
|
4598 } else if (isInitial) { |
|
4599 Settings* settings = m_checker.m_document->settings(); |
|
4600 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings |
|
4601 if (!settings) |
|
4602 return; |
|
4603 FontDescription fontDescription; |
|
4604 fontDescription.setGenericFamily(FontDescription::StandardFamily); |
|
4605 fontDescription.setRenderingMode(settings->fontRenderingMode()); |
|
4606 fontDescription.setUsePrinterFont(m_checker.m_document->printing()); |
|
4607 const AtomicString& standardFontFamily = m_checker.m_document->settings()->standardFontFamily(); |
|
4608 if (!standardFontFamily.isEmpty()) { |
|
4609 fontDescription.firstFamily().setFamily(standardFontFamily); |
|
4610 fontDescription.firstFamily().appendFamily(0); |
|
4611 } |
|
4612 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); |
|
4613 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueMedium, false)); |
|
4614 m_style->setLineHeight(RenderStyle::initialLineHeight()); |
|
4615 m_lineHeightValue = 0; |
|
4616 if (m_style->setFontDescription(fontDescription)) |
|
4617 m_fontDirty = true; |
|
4618 } else if (primitiveValue) { |
|
4619 m_style->setLineHeight(RenderStyle::initialLineHeight()); |
|
4620 m_lineHeightValue = 0; |
|
4621 |
|
4622 FontDescription fontDescription; |
|
4623 RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription); |
|
4624 |
|
4625 // Double-check and see if the theme did anything. If not, don't bother updating the font. |
|
4626 if (fontDescription.isAbsoluteSize()) { |
|
4627 // Make sure the rendering mode and printer font settings are updated. |
|
4628 Settings* settings = m_checker.m_document->settings(); |
|
4629 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings |
|
4630 if (!settings) |
|
4631 return; |
|
4632 fontDescription.setRenderingMode(settings->fontRenderingMode()); |
|
4633 fontDescription.setUsePrinterFont(m_checker.m_document->printing()); |
|
4634 |
|
4635 // Handle the zoom factor. |
|
4636 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules)); |
|
4637 if (m_style->setFontDescription(fontDescription)) |
|
4638 m_fontDirty = true; |
|
4639 } |
|
4640 } else if (value->isFontValue()) { |
|
4641 FontValue *font = static_cast<FontValue*>(value); |
|
4642 if (!font->style || !font->variant || !font->weight || |
|
4643 !font->size || !font->lineHeight || !font->family) |
|
4644 return; |
|
4645 applyProperty(CSSPropertyFontStyle, font->style.get()); |
|
4646 applyProperty(CSSPropertyFontVariant, font->variant.get()); |
|
4647 applyProperty(CSSPropertyFontWeight, font->weight.get()); |
|
4648 applyProperty(CSSPropertyFontSize, font->size.get()); |
|
4649 |
|
4650 m_lineHeightValue = font->lineHeight.get(); |
|
4651 |
|
4652 applyProperty(CSSPropertyFontFamily, font->family.get()); |
|
4653 } |
|
4654 return; |
|
4655 |
|
4656 case CSSPropertyListStyle: |
|
4657 if (isInherit) { |
|
4658 m_style->setListStyleType(m_parentStyle->listStyleType()); |
|
4659 m_style->setListStyleImage(m_parentStyle->listStyleImage()); |
|
4660 m_style->setListStylePosition(m_parentStyle->listStylePosition()); |
|
4661 } |
|
4662 else if (isInitial) { |
|
4663 m_style->setListStyleType(RenderStyle::initialListStyleType()); |
|
4664 m_style->setListStyleImage(RenderStyle::initialListStyleImage()); |
|
4665 m_style->setListStylePosition(RenderStyle::initialListStylePosition()); |
|
4666 } |
|
4667 return; |
|
4668 case CSSPropertyOutline: |
|
4669 if (isInherit) { |
|
4670 m_style->setOutlineWidth(m_parentStyle->outlineWidth()); |
|
4671 m_style->setOutlineColor(m_parentStyle->outlineColor().isValid() ? m_parentStyle->outlineColor() : m_parentStyle->color()); |
|
4672 m_style->setOutlineStyle(m_parentStyle->outlineStyle()); |
|
4673 } |
|
4674 else if (isInitial) |
|
4675 m_style->resetOutline(); |
|
4676 return; |
|
4677 |
|
4678 // CSS3 Properties |
|
4679 case CSSPropertyWebkitAppearance: { |
|
4680 HANDLE_INHERIT_AND_INITIAL(appearance, Appearance) |
|
4681 if (!primitiveValue) |
|
4682 return; |
|
4683 m_style->setAppearance(*primitiveValue); |
|
4684 return; |
|
4685 } |
|
4686 case CSSPropertyWebkitBinding: { |
|
4687 #if ENABLE(XBL) |
|
4688 if (isInitial || (primitiveValue && primitiveValue->getIdent() == CSSValueNone)) { |
|
4689 m_style->deleteBindingURIs(); |
|
4690 return; |
|
4691 } |
|
4692 else if (isInherit) { |
|
4693 if (m_parentStyle->bindingURIs()) |
|
4694 m_style->inheritBindingURIs(m_parentStyle->bindingURIs()); |
|
4695 else |
|
4696 m_style->deleteBindingURIs(); |
|
4697 return; |
|
4698 } |
|
4699 |
|
4700 if (!value->isValueList()) return; |
|
4701 CSSValueList* list = static_cast<CSSValueList*>(value); |
|
4702 bool firstBinding = true; |
|
4703 for (unsigned int i = 0; i < list->length(); i++) { |
|
4704 CSSValue *item = list->itemWithoutBoundsCheck(i); |
|
4705 CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item); |
|
4706 if (val->primitiveType() == CSSPrimitiveValue::CSS_URI) { |
|
4707 if (firstBinding) { |
|
4708 firstBinding = false; |
|
4709 m_style->deleteBindingURIs(); |
|
4710 } |
|
4711 m_style->addBindingURI(val->getStringValue()); |
|
4712 } |
|
4713 } |
|
4714 #endif |
|
4715 return; |
|
4716 } |
|
4717 |
|
4718 case CSSPropertyWebkitBorderImage: |
|
4719 case CSSPropertyWebkitMaskBoxImage: { |
|
4720 if (isInherit) { |
|
4721 HANDLE_INHERIT_COND(CSSPropertyWebkitBorderImage, borderImage, BorderImage) |
|
4722 HANDLE_INHERIT_COND(CSSPropertyWebkitMaskBoxImage, maskBoxImage, MaskBoxImage) |
|
4723 return; |
|
4724 } else if (isInitial) { |
|
4725 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderImage, BorderImage, NinePieceImage) |
|
4726 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitMaskBoxImage, MaskBoxImage, NinePieceImage) |
|
4727 return; |
|
4728 } |
|
4729 |
|
4730 NinePieceImage image; |
|
4731 mapNinePieceImage(value, image); |
|
4732 |
|
4733 if (id == CSSPropertyWebkitBorderImage) |
|
4734 m_style->setBorderImage(image); |
|
4735 else |
|
4736 m_style->setMaskBoxImage(image); |
|
4737 return; |
|
4738 } |
|
4739 |
|
4740 case CSSPropertyBorderRadius: |
|
4741 case CSSPropertyWebkitBorderRadius: |
|
4742 if (isInherit) { |
|
4743 m_style->setBorderTopLeftRadius(m_parentStyle->borderTopLeftRadius()); |
|
4744 m_style->setBorderTopRightRadius(m_parentStyle->borderTopRightRadius()); |
|
4745 m_style->setBorderBottomLeftRadius(m_parentStyle->borderBottomLeftRadius()); |
|
4746 m_style->setBorderBottomRightRadius(m_parentStyle->borderBottomRightRadius()); |
|
4747 return; |
|
4748 } |
|
4749 if (isInitial) { |
|
4750 m_style->resetBorderRadius(); |
|
4751 return; |
|
4752 } |
|
4753 // Fall through |
|
4754 case CSSPropertyBorderTopLeftRadius: |
|
4755 case CSSPropertyBorderTopRightRadius: |
|
4756 case CSSPropertyBorderBottomLeftRadius: |
|
4757 case CSSPropertyBorderBottomRightRadius: { |
|
4758 if (isInherit) { |
|
4759 HANDLE_INHERIT_COND(CSSPropertyBorderTopLeftRadius, borderTopLeftRadius, BorderTopLeftRadius) |
|
4760 HANDLE_INHERIT_COND(CSSPropertyBorderTopRightRadius, borderTopRightRadius, BorderTopRightRadius) |
|
4761 HANDLE_INHERIT_COND(CSSPropertyBorderBottomLeftRadius, borderBottomLeftRadius, BorderBottomLeftRadius) |
|
4762 HANDLE_INHERIT_COND(CSSPropertyBorderBottomRightRadius, borderBottomRightRadius, BorderBottomRightRadius) |
|
4763 return; |
|
4764 } |
|
4765 |
|
4766 if (isInitial) { |
|
4767 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopLeftRadius, BorderTopLeftRadius, BorderRadius) |
|
4768 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopRightRadius, BorderTopRightRadius, BorderRadius) |
|
4769 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomLeftRadius, BorderBottomLeftRadius, BorderRadius) |
|
4770 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomRightRadius, BorderBottomRightRadius, BorderRadius) |
|
4771 return; |
|
4772 } |
|
4773 |
|
4774 if (!primitiveValue) |
|
4775 return; |
|
4776 |
|
4777 Pair* pair = primitiveValue->getPairValue(); |
|
4778 if (!pair) |
|
4779 return; |
|
4780 |
|
4781 int width = pair->first()->computeLengthInt(style(), m_rootElementStyle, zoomFactor); |
|
4782 int height = pair->second()->computeLengthInt(style(), m_rootElementStyle, zoomFactor); |
|
4783 if (width < 0 || height < 0) |
|
4784 return; |
|
4785 |
|
4786 if (width == 0) |
|
4787 height = 0; // Null out the other value. |
|
4788 else if (height == 0) |
|
4789 width = 0; // Null out the other value. |
|
4790 |
|
4791 IntSize size(width, height); |
|
4792 switch (id) { |
|
4793 case CSSPropertyBorderTopLeftRadius: |
|
4794 m_style->setBorderTopLeftRadius(size); |
|
4795 break; |
|
4796 case CSSPropertyBorderTopRightRadius: |
|
4797 m_style->setBorderTopRightRadius(size); |
|
4798 break; |
|
4799 case CSSPropertyBorderBottomLeftRadius: |
|
4800 m_style->setBorderBottomLeftRadius(size); |
|
4801 break; |
|
4802 case CSSPropertyBorderBottomRightRadius: |
|
4803 m_style->setBorderBottomRightRadius(size); |
|
4804 break; |
|
4805 default: |
|
4806 m_style->setBorderRadius(size); |
|
4807 break; |
|
4808 } |
|
4809 return; |
|
4810 } |
|
4811 |
|
4812 case CSSPropertyOutlineOffset: |
|
4813 HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset) |
|
4814 m_style->setOutlineOffset(primitiveValue->computeLengthInt(style(), m_rootElementStyle, zoomFactor)); |
|
4815 return; |
|
4816 case CSSPropertyTextRendering: { |
|
4817 FontDescription fontDescription = m_style->fontDescription(); |
|
4818 if (isInherit) |
|
4819 fontDescription.setTextRenderingMode(m_parentStyle->fontDescription().textRenderingMode()); |
|
4820 else if (isInitial) |
|
4821 fontDescription.setTextRenderingMode(AutoTextRendering); |
|
4822 else { |
|
4823 if (!primitiveValue) |
|
4824 return; |
|
4825 fontDescription.setTextRenderingMode(*primitiveValue); |
|
4826 } |
|
4827 if (m_style->setFontDescription(fontDescription)) |
|
4828 m_fontDirty = true; |
|
4829 return; |
|
4830 } |
|
4831 case CSSPropertyTextShadow: |
|
4832 case CSSPropertyWebkitBoxShadow: { |
|
4833 if (isInherit) { |
|
4834 if (id == CSSPropertyTextShadow) |
|
4835 return m_style->setTextShadow(m_parentStyle->textShadow() ? new ShadowData(*m_parentStyle->textShadow()) : 0); |
|
4836 return m_style->setBoxShadow(m_parentStyle->boxShadow() ? new ShadowData(*m_parentStyle->boxShadow()) : 0); |
|
4837 } |
|
4838 if (isInitial || primitiveValue) // initial | none |
|
4839 return id == CSSPropertyTextShadow ? m_style->setTextShadow(0) : m_style->setBoxShadow(0); |
|
4840 |
|
4841 if (!value->isValueList()) |
|
4842 return; |
|
4843 |
|
4844 CSSValueList *list = static_cast<CSSValueList*>(value); |
|
4845 int len = list->length(); |
|
4846 for (int i = 0; i < len; i++) { |
|
4847 ShadowValue* item = static_cast<ShadowValue*>(list->itemWithoutBoundsCheck(i)); |
|
4848 int x = item->x->computeLengthInt(style(), m_rootElementStyle, zoomFactor); |
|
4849 int y = item->y->computeLengthInt(style(), m_rootElementStyle, zoomFactor); |
|
4850 int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0; |
|
4851 int spread = item->spread ? item->spread->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0; |
|
4852 ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal; |
|
4853 Color color; |
|
4854 if (item->color) |
|
4855 color = getColorFromPrimitiveValue(item->color.get()); |
|
4856 ShadowData* shadowData = new ShadowData(x, y, blur, spread, shadowStyle, color.isValid() ? color : Color::transparent); |
|
4857 if (id == CSSPropertyTextShadow) |
|
4858 m_style->setTextShadow(shadowData, i != 0); |
|
4859 else |
|
4860 m_style->setBoxShadow(shadowData, i != 0); |
|
4861 } |
|
4862 return; |
|
4863 } |
|
4864 case CSSPropertyWebkitBoxReflect: { |
|
4865 HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect) |
|
4866 if (primitiveValue) { |
|
4867 m_style->setBoxReflect(RenderStyle::initialBoxReflect()); |
|
4868 return; |
|
4869 } |
|
4870 CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value); |
|
4871 RefPtr<StyleReflection> reflection = StyleReflection::create(); |
|
4872 reflection->setDirection(reflectValue->direction()); |
|
4873 if (reflectValue->offset()) { |
|
4874 int type = reflectValue->offset()->primitiveType(); |
|
4875 if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
4876 reflection->setOffset(Length(reflectValue->offset()->getDoubleValue(), Percent)); |
|
4877 else |
|
4878 reflection->setOffset(Length(reflectValue->offset()->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed)); |
|
4879 } |
|
4880 NinePieceImage mask; |
|
4881 mapNinePieceImage(reflectValue->mask(), mask); |
|
4882 reflection->setMask(mask); |
|
4883 |
|
4884 m_style->setBoxReflect(reflection.release()); |
|
4885 return; |
|
4886 } |
|
4887 case CSSPropertyOpacity: |
|
4888 HANDLE_INHERIT_AND_INITIAL(opacity, Opacity) |
|
4889 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
4890 return; // Error case. |
|
4891 // Clamp opacity to the range 0-1 |
|
4892 m_style->setOpacity(min(1.0f, max(0.0f, primitiveValue->getFloatValue()))); |
|
4893 return; |
|
4894 case CSSPropertyWebkitBoxAlign: |
|
4895 { |
|
4896 HANDLE_INHERIT_AND_INITIAL(boxAlign, BoxAlign) |
|
4897 if (!primitiveValue) |
|
4898 return; |
|
4899 EBoxAlignment boxAlignment = *primitiveValue; |
|
4900 if (boxAlignment != BJUSTIFY) |
|
4901 m_style->setBoxAlign(boxAlignment); |
|
4902 return; |
|
4903 } |
|
4904 case CSSPropertySrc: // Only used in @font-face rules. |
|
4905 return; |
|
4906 case CSSPropertyUnicodeRange: // Only used in @font-face rules. |
|
4907 return; |
|
4908 case CSSPropertyWebkitBackfaceVisibility: |
|
4909 HANDLE_INHERIT_AND_INITIAL(backfaceVisibility, BackfaceVisibility) |
|
4910 if (primitiveValue) |
|
4911 m_style->setBackfaceVisibility((primitiveValue->getIdent() == CSSValueVisible) ? BackfaceVisibilityVisible : BackfaceVisibilityHidden); |
|
4912 return; |
|
4913 case CSSPropertyWebkitBoxDirection: |
|
4914 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxDirection, BoxDirection) |
|
4915 return; |
|
4916 case CSSPropertyWebkitBoxLines: |
|
4917 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxLines, BoxLines) |
|
4918 return; |
|
4919 case CSSPropertyWebkitBoxOrient: |
|
4920 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrient, BoxOrient) |
|
4921 return; |
|
4922 case CSSPropertyWebkitBoxPack: |
|
4923 { |
|
4924 HANDLE_INHERIT_AND_INITIAL(boxPack, BoxPack) |
|
4925 if (!primitiveValue) |
|
4926 return; |
|
4927 EBoxAlignment boxPack = *primitiveValue; |
|
4928 if (boxPack != BSTRETCH && boxPack != BBASELINE) |
|
4929 m_style->setBoxPack(boxPack); |
|
4930 return; |
|
4931 } |
|
4932 case CSSPropertyWebkitBoxFlex: |
|
4933 HANDLE_INHERIT_AND_INITIAL(boxFlex, BoxFlex) |
|
4934 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
4935 return; // Error case. |
|
4936 m_style->setBoxFlex(primitiveValue->getFloatValue()); |
|
4937 return; |
|
4938 case CSSPropertyWebkitBoxFlexGroup: |
|
4939 HANDLE_INHERIT_AND_INITIAL(boxFlexGroup, BoxFlexGroup) |
|
4940 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
4941 return; // Error case. |
|
4942 m_style->setBoxFlexGroup((unsigned int)(primitiveValue->getDoubleValue())); |
|
4943 return; |
|
4944 case CSSPropertyWebkitBoxOrdinalGroup: |
|
4945 HANDLE_INHERIT_AND_INITIAL(boxOrdinalGroup, BoxOrdinalGroup) |
|
4946 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
4947 return; // Error case. |
|
4948 m_style->setBoxOrdinalGroup((unsigned int)(primitiveValue->getDoubleValue())); |
|
4949 return; |
|
4950 case CSSPropertyWebkitBoxSizing: |
|
4951 HANDLE_INHERIT_AND_INITIAL(boxSizing, BoxSizing) |
|
4952 if (!primitiveValue) |
|
4953 return; |
|
4954 if (primitiveValue->getIdent() == CSSValueContentBox) |
|
4955 m_style->setBoxSizing(CONTENT_BOX); |
|
4956 else |
|
4957 m_style->setBoxSizing(BORDER_BOX); |
|
4958 return; |
|
4959 case CSSPropertyWebkitColumnCount: { |
|
4960 if (isInherit) { |
|
4961 if (m_parentStyle->hasAutoColumnCount()) |
|
4962 m_style->setHasAutoColumnCount(); |
|
4963 else |
|
4964 m_style->setColumnCount(m_parentStyle->columnCount()); |
|
4965 return; |
|
4966 } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) { |
|
4967 m_style->setHasAutoColumnCount(); |
|
4968 return; |
|
4969 } |
|
4970 m_style->setColumnCount(static_cast<unsigned short>(primitiveValue->getDoubleValue())); |
|
4971 return; |
|
4972 } |
|
4973 case CSSPropertyWebkitColumnGap: { |
|
4974 if (isInherit) { |
|
4975 if (m_parentStyle->hasNormalColumnGap()) |
|
4976 m_style->setHasNormalColumnGap(); |
|
4977 else |
|
4978 m_style->setColumnGap(m_parentStyle->columnGap()); |
|
4979 return; |
|
4980 } else if (isInitial || primitiveValue->getIdent() == CSSValueNormal) { |
|
4981 m_style->setHasNormalColumnGap(); |
|
4982 return; |
|
4983 } |
|
4984 m_style->setColumnGap(primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor)); |
|
4985 return; |
|
4986 } |
|
4987 case CSSPropertyWebkitColumnSpan: { |
|
4988 HANDLE_INHERIT_AND_INITIAL(columnSpan, ColumnSpan) |
|
4989 m_style->setColumnSpan(primitiveValue->getIdent() == CSSValueAll); |
|
4990 return; |
|
4991 } |
|
4992 case CSSPropertyWebkitColumnWidth: { |
|
4993 if (isInherit) { |
|
4994 if (m_parentStyle->hasAutoColumnWidth()) |
|
4995 m_style->setHasAutoColumnWidth(); |
|
4996 else |
|
4997 m_style->setColumnWidth(m_parentStyle->columnWidth()); |
|
4998 return; |
|
4999 } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) { |
|
5000 m_style->setHasAutoColumnWidth(); |
|
5001 return; |
|
5002 } |
|
5003 m_style->setColumnWidth(primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor)); |
|
5004 return; |
|
5005 } |
|
5006 case CSSPropertyWebkitColumnRuleStyle: |
|
5007 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle) |
|
5008 return; |
|
5009 case CSSPropertyWebkitColumnBreakBefore: |
|
5010 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak) |
|
5011 return; |
|
5012 case CSSPropertyWebkitColumnBreakAfter: |
|
5013 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak) |
|
5014 return; |
|
5015 case CSSPropertyWebkitColumnBreakInside: { |
|
5016 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak) |
|
5017 EPageBreak pb = *primitiveValue; |
|
5018 if (pb != PBALWAYS) |
|
5019 m_style->setColumnBreakInside(pb); |
|
5020 return; |
|
5021 } |
|
5022 case CSSPropertyWebkitColumnRule: |
|
5023 if (isInherit) { |
|
5024 m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color()); |
|
5025 m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle()); |
|
5026 m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth()); |
|
5027 } |
|
5028 else if (isInitial) |
|
5029 m_style->resetColumnRule(); |
|
5030 return; |
|
5031 case CSSPropertyWebkitColumns: |
|
5032 if (isInherit) { |
|
5033 if (m_parentStyle->hasAutoColumnWidth()) |
|
5034 m_style->setHasAutoColumnWidth(); |
|
5035 else |
|
5036 m_style->setColumnWidth(m_parentStyle->columnWidth()); |
|
5037 m_style->setColumnCount(m_parentStyle->columnCount()); |
|
5038 } else if (isInitial) { |
|
5039 m_style->setHasAutoColumnWidth(); |
|
5040 m_style->setColumnCount(RenderStyle::initialColumnCount()); |
|
5041 } |
|
5042 return; |
|
5043 case CSSPropertyWebkitMarquee: |
|
5044 if (valueType != CSSValue::CSS_INHERIT || !m_parentNode) return; |
|
5045 m_style->setMarqueeDirection(m_parentStyle->marqueeDirection()); |
|
5046 m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement()); |
|
5047 m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed()); |
|
5048 m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount()); |
|
5049 m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior()); |
|
5050 return; |
|
5051 #if ENABLE(WCSS) |
|
5052 case CSSPropertyWapMarqueeLoop: |
|
5053 #endif |
|
5054 case CSSPropertyWebkitMarqueeRepetition: { |
|
5055 HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount) |
|
5056 if (!primitiveValue) |
|
5057 return; |
|
5058 if (primitiveValue->getIdent() == CSSValueInfinite) |
|
5059 m_style->setMarqueeLoopCount(-1); // -1 means repeat forever. |
|
5060 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) |
|
5061 m_style->setMarqueeLoopCount(primitiveValue->getIntValue()); |
|
5062 return; |
|
5063 } |
|
5064 #if ENABLE(WCSS) |
|
5065 case CSSPropertyWapMarqueeSpeed: |
|
5066 #endif |
|
5067 case CSSPropertyWebkitMarqueeSpeed: { |
|
5068 HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed) |
|
5069 if (!primitiveValue) |
|
5070 return; |
|
5071 if (primitiveValue->getIdent()) { |
|
5072 switch (primitiveValue->getIdent()) { |
|
5073 case CSSValueSlow: |
|
5074 m_style->setMarqueeSpeed(500); // 500 msec. |
|
5075 break; |
|
5076 case CSSValueNormal: |
|
5077 m_style->setMarqueeSpeed(85); // 85msec. The WinIE default. |
|
5078 break; |
|
5079 case CSSValueFast: |
|
5080 m_style->setMarqueeSpeed(10); // 10msec. Super fast. |
|
5081 break; |
|
5082 } |
|
5083 } |
|
5084 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) |
|
5085 m_style->setMarqueeSpeed(1000 * primitiveValue->getIntValue()); |
|
5086 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) |
|
5087 m_style->setMarqueeSpeed(primitiveValue->getIntValue()); |
|
5088 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support. |
|
5089 m_style->setMarqueeSpeed(primitiveValue->getIntValue()); |
|
5090 return; |
|
5091 } |
|
5092 case CSSPropertyWebkitMarqueeIncrement: { |
|
5093 HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement) |
|
5094 if (!primitiveValue) |
|
5095 return; |
|
5096 if (primitiveValue->getIdent()) { |
|
5097 switch (primitiveValue->getIdent()) { |
|
5098 case CSSValueSmall: |
|
5099 m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px. |
|
5100 break; |
|
5101 case CSSValueNormal: |
|
5102 m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default. |
|
5103 break; |
|
5104 case CSSValueLarge: |
|
5105 m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px. |
|
5106 break; |
|
5107 } |
|
5108 } |
|
5109 else { |
|
5110 bool ok = true; |
|
5111 Length l = convertToLength(primitiveValue, style(), m_rootElementStyle, 1, &ok); |
|
5112 if (ok) |
|
5113 m_style->setMarqueeIncrement(l); |
|
5114 } |
|
5115 return; |
|
5116 } |
|
5117 #if ENABLE(WCSS) |
|
5118 case CSSPropertyWapMarqueeStyle: |
|
5119 #endif |
|
5120 case CSSPropertyWebkitMarqueeStyle: |
|
5121 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeBehavior, MarqueeBehavior) |
|
5122 return; |
|
5123 #if ENABLE(WCSS) |
|
5124 case CSSPropertyWapMarqueeDir: |
|
5125 HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection) |
|
5126 if (primitiveValue && primitiveValue->getIdent()) { |
|
5127 switch (primitiveValue->getIdent()) { |
|
5128 case CSSValueLtr: |
|
5129 m_style->setMarqueeDirection(MRIGHT); |
|
5130 break; |
|
5131 case CSSValueRtl: |
|
5132 m_style->setMarqueeDirection(MLEFT); |
|
5133 break; |
|
5134 default: |
|
5135 m_style->setMarqueeDirection(*primitiveValue); |
|
5136 break; |
|
5137 } |
|
5138 } |
|
5139 return; |
|
5140 #endif |
|
5141 case CSSPropertyWebkitMarqueeDirection: |
|
5142 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeDirection, MarqueeDirection) |
|
5143 return; |
|
5144 case CSSPropertyWebkitUserDrag: |
|
5145 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userDrag, UserDrag) |
|
5146 return; |
|
5147 case CSSPropertyWebkitUserModify: |
|
5148 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userModify, UserModify) |
|
5149 return; |
|
5150 case CSSPropertyWebkitUserSelect: |
|
5151 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userSelect, UserSelect) |
|
5152 return; |
|
5153 |
|
5154 case CSSPropertyTextOverflow: { |
|
5155 // This property is supported by WinIE, and so we leave off the "-webkit-" in order to |
|
5156 // work with WinIE-specific pages that use the property. |
|
5157 HANDLE_INHERIT_AND_INITIAL(textOverflow, TextOverflow) |
|
5158 if (!primitiveValue || !primitiveValue->getIdent()) |
|
5159 return; |
|
5160 m_style->setTextOverflow(primitiveValue->getIdent() == CSSValueEllipsis); |
|
5161 return; |
|
5162 } |
|
5163 case CSSPropertyWebkitMarginCollapse: { |
|
5164 if (isInherit) { |
|
5165 m_style->setMarginTopCollapse(m_parentStyle->marginTopCollapse()); |
|
5166 m_style->setMarginBottomCollapse(m_parentStyle->marginBottomCollapse()); |
|
5167 } |
|
5168 else if (isInitial) { |
|
5169 m_style->setMarginTopCollapse(MCOLLAPSE); |
|
5170 m_style->setMarginBottomCollapse(MCOLLAPSE); |
|
5171 } |
|
5172 return; |
|
5173 } |
|
5174 |
|
5175 case CSSPropertyWebkitMarginTopCollapse: |
|
5176 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marginTopCollapse, MarginTopCollapse) |
|
5177 return; |
|
5178 case CSSPropertyWebkitMarginBottomCollapse: |
|
5179 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marginBottomCollapse, MarginBottomCollapse) |
|
5180 return; |
|
5181 case CSSPropertyWebkitLineClamp: { |
|
5182 HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp) |
|
5183 if (!primitiveValue) |
|
5184 return; |
|
5185 int type = primitiveValue->primitiveType(); |
|
5186 if (type == CSSPrimitiveValue::CSS_NUMBER) |
|
5187 m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), LineClampLineCount)); |
|
5188 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
5189 m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE), LineClampPercentage)); |
|
5190 return; |
|
5191 } |
|
5192 case CSSPropertyWebkitHighlight: { |
|
5193 HANDLE_INHERIT_AND_INITIAL(highlight, Highlight); |
|
5194 if (primitiveValue->getIdent() == CSSValueNone) |
|
5195 m_style->setHighlight(nullAtom); |
|
5196 else |
|
5197 m_style->setHighlight(primitiveValue->getStringValue()); |
|
5198 return; |
|
5199 } |
|
5200 case CSSPropertyWebkitHyphens: { |
|
5201 HANDLE_INHERIT_AND_INITIAL(hyphens, Hyphens); |
|
5202 m_style->setHyphens(*primitiveValue); |
|
5203 return; |
|
5204 } |
|
5205 case CSSPropertyWebkitHyphenateCharacter: { |
|
5206 HANDLE_INHERIT_AND_INITIAL(hyphenateCharacter, HyphenateCharacter); |
|
5207 if (primitiveValue->getIdent() == CSSValueAuto) |
|
5208 m_style->setHyphenateCharacter(nullAtom); |
|
5209 else |
|
5210 m_style->setHyphenateCharacter(primitiveValue->getStringValue()); |
|
5211 return; |
|
5212 } |
|
5213 case CSSPropertyWebkitBorderFit: { |
|
5214 HANDLE_INHERIT_AND_INITIAL(borderFit, BorderFit); |
|
5215 if (primitiveValue->getIdent() == CSSValueBorder) |
|
5216 m_style->setBorderFit(BorderFitBorder); |
|
5217 else |
|
5218 m_style->setBorderFit(BorderFitLines); |
|
5219 return; |
|
5220 } |
|
5221 case CSSPropertyWebkitTextSizeAdjust: { |
|
5222 HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust) |
|
5223 if (!primitiveValue || !primitiveValue->getIdent()) return; |
|
5224 m_style->setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto); |
|
5225 m_fontDirty = true; |
|
5226 return; |
|
5227 } |
|
5228 case CSSPropertyWebkitTextSecurity: |
|
5229 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textSecurity, TextSecurity) |
|
5230 return; |
|
5231 |
|
5232 #if ENABLE(DASHBOARD_SUPPORT) |
|
5233 case CSSPropertyWebkitDashboardRegion: { |
|
5234 HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions) |
|
5235 if (!primitiveValue) |
|
5236 return; |
|
5237 |
|
5238 if (primitiveValue->getIdent() == CSSValueNone) { |
|
5239 m_style->setDashboardRegions(RenderStyle::noneDashboardRegions()); |
|
5240 return; |
|
5241 } |
|
5242 |
|
5243 DashboardRegion *region = primitiveValue->getDashboardRegionValue(); |
|
5244 if (!region) |
|
5245 return; |
|
5246 |
|
5247 DashboardRegion *first = region; |
|
5248 while (region) { |
|
5249 Length top = convertToLength(region->top(), style(), m_rootElementStyle); |
|
5250 Length right = convertToLength(region->right(), style(), m_rootElementStyle); |
|
5251 Length bottom = convertToLength(region->bottom(), style(), m_rootElementStyle); |
|
5252 Length left = convertToLength(region->left(), style(), m_rootElementStyle); |
|
5253 if (region->m_isCircle) |
|
5254 m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true); |
|
5255 else if (region->m_isRectangle) |
|
5256 m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true); |
|
5257 region = region->m_next.get(); |
|
5258 } |
|
5259 |
|
5260 m_element->document()->setHasDashboardRegions(true); |
|
5261 |
|
5262 return; |
|
5263 } |
|
5264 #endif |
|
5265 case CSSPropertyWebkitRtlOrdering: |
|
5266 HANDLE_INHERIT_AND_INITIAL(visuallyOrdered, VisuallyOrdered) |
|
5267 if (!primitiveValue || !primitiveValue->getIdent()) |
|
5268 return; |
|
5269 m_style->setVisuallyOrdered(primitiveValue->getIdent() == CSSValueVisual); |
|
5270 return; |
|
5271 case CSSPropertyWebkitTextStrokeWidth: { |
|
5272 HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth) |
|
5273 float width = 0; |
|
5274 switch (primitiveValue->getIdent()) { |
|
5275 case CSSValueThin: |
|
5276 case CSSValueMedium: |
|
5277 case CSSValueThick: { |
|
5278 double result = 1.0 / 48; |
|
5279 if (primitiveValue->getIdent() == CSSValueMedium) |
|
5280 result *= 3; |
|
5281 else if (primitiveValue->getIdent() == CSSValueThick) |
|
5282 result *= 5; |
|
5283 width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLengthFloat(style(), m_rootElementStyle, zoomFactor); |
|
5284 break; |
|
5285 } |
|
5286 default: |
|
5287 width = primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor); |
|
5288 break; |
|
5289 } |
|
5290 m_style->setTextStrokeWidth(width); |
|
5291 return; |
|
5292 } |
|
5293 case CSSPropertyWebkitTransform: { |
|
5294 HANDLE_INHERIT_AND_INITIAL(transform, Transform); |
|
5295 TransformOperations operations; |
|
5296 createTransformOperations(value, style(), m_rootElementStyle, operations); |
|
5297 m_style->setTransform(operations); |
|
5298 return; |
|
5299 } |
|
5300 case CSSPropertyWebkitTransformOrigin: |
|
5301 HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX) |
|
5302 HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY) |
|
5303 HANDLE_INHERIT_AND_INITIAL(transformOriginZ, TransformOriginZ) |
|
5304 return; |
|
5305 case CSSPropertyWebkitTransformOriginX: { |
|
5306 HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX) |
|
5307 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5308 Length l; |
|
5309 int type = primitiveValue->primitiveType(); |
|
5310 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
5311 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); |
|
5312 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
5313 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
5314 else |
|
5315 return; |
|
5316 m_style->setTransformOriginX(l); |
|
5317 break; |
|
5318 } |
|
5319 case CSSPropertyWebkitTransformOriginY: { |
|
5320 HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY) |
|
5321 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5322 Length l; |
|
5323 int type = primitiveValue->primitiveType(); |
|
5324 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
5325 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); |
|
5326 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
5327 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
5328 else |
|
5329 return; |
|
5330 m_style->setTransformOriginY(l); |
|
5331 break; |
|
5332 } |
|
5333 case CSSPropertyWebkitTransformOriginZ: { |
|
5334 HANDLE_INHERIT_AND_INITIAL(transformOriginZ, TransformOriginZ) |
|
5335 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5336 float f; |
|
5337 int type = primitiveValue->primitiveType(); |
|
5338 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
5339 f = static_cast<float>(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle)); |
|
5340 else |
|
5341 return; |
|
5342 m_style->setTransformOriginZ(f); |
|
5343 break; |
|
5344 } |
|
5345 case CSSPropertyWebkitTransformStyle: |
|
5346 HANDLE_INHERIT_AND_INITIAL(transformStyle3D, TransformStyle3D) |
|
5347 if (primitiveValue) |
|
5348 m_style->setTransformStyle3D((primitiveValue->getIdent() == CSSValuePreserve3d) ? TransformStyle3DPreserve3D : TransformStyle3DFlat); |
|
5349 return; |
|
5350 case CSSPropertyWebkitPerspective: { |
|
5351 HANDLE_INHERIT_AND_INITIAL(perspective, Perspective) |
|
5352 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) { |
|
5353 m_style->setPerspective(0); |
|
5354 return; |
|
5355 } |
|
5356 |
|
5357 float perspectiveValue; |
|
5358 int type = primitiveValue->primitiveType(); |
|
5359 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
5360 perspectiveValue = static_cast<float>(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor)); |
|
5361 else if (type == CSSPrimitiveValue::CSS_NUMBER) { |
|
5362 // For backward compatibility, treat valueless numbers as px. |
|
5363 perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLengthFloat(style(), m_rootElementStyle, zoomFactor); |
|
5364 } else |
|
5365 return; |
|
5366 |
|
5367 if (perspectiveValue >= 0.0f) |
|
5368 m_style->setPerspective(perspectiveValue); |
|
5369 return; |
|
5370 } |
|
5371 case CSSPropertyWebkitPerspectiveOrigin: |
|
5372 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginX, PerspectiveOriginX) |
|
5373 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginY, PerspectiveOriginY) |
|
5374 return; |
|
5375 case CSSPropertyWebkitPerspectiveOriginX: { |
|
5376 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginX, PerspectiveOriginX) |
|
5377 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5378 Length l; |
|
5379 int type = primitiveValue->primitiveType(); |
|
5380 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
5381 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); |
|
5382 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
5383 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
5384 else |
|
5385 return; |
|
5386 m_style->setPerspectiveOriginX(l); |
|
5387 return; |
|
5388 } |
|
5389 case CSSPropertyWebkitPerspectiveOriginY: { |
|
5390 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginY, PerspectiveOriginY) |
|
5391 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5392 Length l; |
|
5393 int type = primitiveValue->primitiveType(); |
|
5394 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
5395 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); |
|
5396 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
5397 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
5398 else |
|
5399 return; |
|
5400 m_style->setPerspectiveOriginY(l); |
|
5401 return; |
|
5402 } |
|
5403 case CSSPropertyWebkitAnimation: |
|
5404 if (isInitial) |
|
5405 m_style->clearAnimations(); |
|
5406 else if (isInherit) |
|
5407 m_style->inheritAnimations(m_parentStyle->animations()); |
|
5408 return; |
|
5409 case CSSPropertyWebkitAnimationDelay: |
|
5410 HANDLE_ANIMATION_VALUE(delay, Delay, value) |
|
5411 return; |
|
5412 case CSSPropertyWebkitAnimationDirection: |
|
5413 HANDLE_ANIMATION_VALUE(direction, Direction, value) |
|
5414 return; |
|
5415 case CSSPropertyWebkitAnimationDuration: |
|
5416 HANDLE_ANIMATION_VALUE(duration, Duration, value) |
|
5417 return; |
|
5418 case CSSPropertyWebkitAnimationFillMode: |
|
5419 HANDLE_ANIMATION_VALUE(fillMode, FillMode, value) |
|
5420 return; |
|
5421 case CSSPropertyWebkitAnimationIterationCount: |
|
5422 HANDLE_ANIMATION_VALUE(iterationCount, IterationCount, value) |
|
5423 return; |
|
5424 case CSSPropertyWebkitAnimationName: |
|
5425 HANDLE_ANIMATION_VALUE(name, Name, value) |
|
5426 return; |
|
5427 case CSSPropertyWebkitAnimationPlayState: |
|
5428 HANDLE_ANIMATION_VALUE(playState, PlayState, value) |
|
5429 return; |
|
5430 case CSSPropertyWebkitAnimationTimingFunction: |
|
5431 HANDLE_ANIMATION_VALUE(timingFunction, TimingFunction, value) |
|
5432 return; |
|
5433 case CSSPropertyWebkitTransition: |
|
5434 if (isInitial) |
|
5435 m_style->clearTransitions(); |
|
5436 else if (isInherit) |
|
5437 m_style->inheritTransitions(m_parentStyle->transitions()); |
|
5438 return; |
|
5439 case CSSPropertyWebkitTransitionDelay: |
|
5440 HANDLE_TRANSITION_VALUE(delay, Delay, value) |
|
5441 return; |
|
5442 case CSSPropertyWebkitTransitionDuration: |
|
5443 HANDLE_TRANSITION_VALUE(duration, Duration, value) |
|
5444 return; |
|
5445 case CSSPropertyWebkitTransitionProperty: |
|
5446 HANDLE_TRANSITION_VALUE(property, Property, value) |
|
5447 return; |
|
5448 case CSSPropertyWebkitTransitionTimingFunction: |
|
5449 HANDLE_TRANSITION_VALUE(timingFunction, TimingFunction, value) |
|
5450 return; |
|
5451 #if 0 // :HACK: |
|
5452 case CSSPropertyWebkitHapticTapType: { |
|
5453 HANDLE_INHERIT_AND_INITIAL(hapticTapType, HapticTapType) |
|
5454 m_style->setHapticTapType(*primitiveValue); |
|
5455 return; |
|
5456 } |
|
5457 case CSSPropertyWebkitHapticTapStrength: { |
|
5458 HANDLE_INHERIT_AND_INITIAL(hapticTapStrength, HapticTapStrength) |
|
5459 m_style->setHapticTapStrength(*primitiveValue); |
|
5460 return; |
|
5461 } |
|
5462 case CSSPropertyWebkitHapticTap: { |
|
5463 if (isInherit) { |
|
5464 m_style->setHapticTapType(m_parentStyle->hapticTapType()); |
|
5465 m_style->setHapticTapStrength(m_parentStyle->hapticTapStrength()); |
|
5466 } else if (isInitial) { |
|
5467 m_style->setHapticTapType(RenderStyle::initialHapticTapType()); |
|
5468 m_style->setHapticTapStrength(RenderStyle::initialHapticTapStrength()); |
|
5469 } |
|
5470 return; |
|
5471 } |
|
5472 #endif // ENABLE(HAPTICS) |
|
5473 case CSSPropertyPointerEvents: |
|
5474 { |
|
5475 #if ENABLE(DASHBOARD_SUPPORT) |
|
5476 // <rdar://problem/6561077> Work around the Stocks widget's misuse of the |
|
5477 // pointer-events property by not applying it in Dashboard. |
|
5478 Settings* settings = m_checker.m_document->settings(); |
|
5479 if (settings && settings->usesDashboardBackwardCompatibilityMode()) |
|
5480 return; |
|
5481 #endif |
|
5482 HANDLE_INHERIT_AND_INITIAL(pointerEvents, PointerEvents) |
|
5483 if (!primitiveValue) |
|
5484 return; |
|
5485 m_style->setPointerEvents(*primitiveValue); |
|
5486 return; |
|
5487 } |
|
5488 case CSSPropertyWebkitColorCorrection: |
|
5489 if (isInherit) |
|
5490 m_style->setColorSpace(m_parentStyle->colorSpace()); |
|
5491 else if (isInitial) |
|
5492 m_style->setColorSpace(DeviceColorSpace); |
|
5493 else { |
|
5494 if (!primitiveValue) |
|
5495 return; |
|
5496 m_style->setColorSpace(*primitiveValue); |
|
5497 } |
|
5498 return; |
|
5499 case CSSPropertySize: |
|
5500 applyPageSizeProperty(value); |
|
5501 return; |
|
5502 case CSSPropertyInvalid: |
|
5503 return; |
|
5504 |
|
5505 // Directional properties are resolved by resolveDirectionAwareProperty() before the switch. |
|
5506 case CSSPropertyWebkitBorderEnd: |
|
5507 case CSSPropertyWebkitBorderEndColor: |
|
5508 case CSSPropertyWebkitBorderEndStyle: |
|
5509 case CSSPropertyWebkitBorderEndWidth: |
|
5510 case CSSPropertyWebkitBorderStart: |
|
5511 case CSSPropertyWebkitBorderStartColor: |
|
5512 case CSSPropertyWebkitBorderStartStyle: |
|
5513 case CSSPropertyWebkitBorderStartWidth: |
|
5514 case CSSPropertyWebkitMarginEnd: |
|
5515 case CSSPropertyWebkitMarginStart: |
|
5516 case CSSPropertyWebkitPaddingEnd: |
|
5517 case CSSPropertyWebkitPaddingStart: |
|
5518 ASSERT_NOT_REACHED(); |
|
5519 break; |
|
5520 |
|
5521 case CSSPropertyFontStretch: |
|
5522 case CSSPropertyPage: |
|
5523 case CSSPropertyQuotes: |
|
5524 case CSSPropertyTextLineThrough: |
|
5525 case CSSPropertyTextLineThroughColor: |
|
5526 case CSSPropertyTextLineThroughMode: |
|
5527 case CSSPropertyTextLineThroughStyle: |
|
5528 case CSSPropertyTextLineThroughWidth: |
|
5529 case CSSPropertyTextOverline: |
|
5530 case CSSPropertyTextOverlineColor: |
|
5531 case CSSPropertyTextOverlineMode: |
|
5532 case CSSPropertyTextOverlineStyle: |
|
5533 case CSSPropertyTextOverlineWidth: |
|
5534 case CSSPropertyTextUnderline: |
|
5535 case CSSPropertyTextUnderlineColor: |
|
5536 case CSSPropertyTextUnderlineMode: |
|
5537 case CSSPropertyTextUnderlineStyle: |
|
5538 case CSSPropertyTextUnderlineWidth: |
|
5539 case CSSPropertyWebkitFontSizeDelta: |
|
5540 case CSSPropertyWebkitTextDecorationsInEffect: |
|
5541 case CSSPropertyWebkitTextStroke: |
|
5542 case CSSPropertyWebkitVariableDeclarationBlock: |
|
5543 return; |
|
5544 #if ENABLE(WCSS) |
|
5545 case CSSPropertyWapInputFormat: |
|
5546 if (primitiveValue && m_element->hasTagName(WebCore::inputTag)) { |
|
5547 String mask = primitiveValue->getStringValue(); |
|
5548 static_cast<HTMLInputElement*>(m_element)->setWapInputFormat(mask); |
|
5549 } |
|
5550 return; |
|
5551 |
|
5552 case CSSPropertyWapInputRequired: |
|
5553 if (primitiveValue && m_element->isFormControlElement()) { |
|
5554 HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(m_element); |
|
5555 bool required = primitiveValue->getStringValue() == "true"; |
|
5556 element->setRequired(required); |
|
5557 } |
|
5558 return; |
|
5559 #endif |
|
5560 |
|
5561 #if ENABLE(SVG) |
|
5562 default: |
|
5563 // Try the SVG properties |
|
5564 applySVGProperty(id, value); |
|
5565 #endif |
|
5566 } |
|
5567 } |
|
5568 |
|
5569 void CSSStyleSelector::applyPageSizeProperty(CSSValue* value) |
|
5570 { |
|
5571 m_style->resetPageSizeType(); |
|
5572 if (!value->isValueList()) |
|
5573 return; |
|
5574 CSSValueList* valueList = static_cast<CSSValueList*>(value); |
|
5575 Length width; |
|
5576 Length height; |
|
5577 PageSizeType pageSizeType = PAGE_SIZE_AUTO; |
|
5578 switch (valueList->length()) { |
|
5579 case 2: { |
|
5580 // <length>{2} | <page-size> <orientation> |
|
5581 pageSizeType = PAGE_SIZE_RESOLVED; |
|
5582 if (!valueList->item(0)->isPrimitiveValue() || !valueList->item(1)->isPrimitiveValue()) |
|
5583 return; |
|
5584 CSSPrimitiveValue* primitiveValue0 = static_cast<CSSPrimitiveValue*>(valueList->item(0)); |
|
5585 CSSPrimitiveValue* primitiveValue1 = static_cast<CSSPrimitiveValue*>(valueList->item(1)); |
|
5586 int type0 = primitiveValue0->primitiveType(); |
|
5587 int type1 = primitiveValue1->primitiveType(); |
|
5588 if (CSSPrimitiveValue::isUnitTypeLength(type0)) { |
|
5589 // <length>{2} |
|
5590 if (!CSSPrimitiveValue::isUnitTypeLength(type1)) |
|
5591 return; |
|
5592 width = Length(primitiveValue0->computeLengthIntForLength(style(), m_rootElementStyle), Fixed); |
|
5593 height = Length(primitiveValue1->computeLengthIntForLength(style(), m_rootElementStyle), Fixed); |
|
5594 } else { |
|
5595 // <page-size> <orientation> |
|
5596 // The value order is guaranteed. See CSSParser::parseSizeParameter. |
|
5597 if (!pageSizeFromName(primitiveValue0, primitiveValue1, width, height)) |
|
5598 return; |
|
5599 } |
|
5600 break; |
|
5601 } |
|
5602 case 1: { |
|
5603 // <length> | auto | <page-size> | [ portrait | landscape] |
|
5604 if (!valueList->item(0)->isPrimitiveValue()) |
|
5605 return; |
|
5606 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(valueList->item(0)); |
|
5607 int type = primitiveValue->primitiveType(); |
|
5608 if (CSSPrimitiveValue::isUnitTypeLength(type)) { |
|
5609 // <length> |
|
5610 pageSizeType = PAGE_SIZE_RESOLVED; |
|
5611 width = height = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle), Fixed); |
|
5612 } else { |
|
5613 if (type != CSSPrimitiveValue::CSS_IDENT) |
|
5614 return; |
|
5615 switch (primitiveValue->getIdent()) { |
|
5616 case CSSValueAuto: |
|
5617 pageSizeType = PAGE_SIZE_AUTO; |
|
5618 break; |
|
5619 case CSSValuePortrait: |
|
5620 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT; |
|
5621 break; |
|
5622 case CSSValueLandscape: |
|
5623 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE; |
|
5624 break; |
|
5625 default: |
|
5626 // <page-size> |
|
5627 pageSizeType = PAGE_SIZE_RESOLVED; |
|
5628 if (!pageSizeFromName(primitiveValue, 0, width, height)) |
|
5629 return; |
|
5630 } |
|
5631 } |
|
5632 break; |
|
5633 } |
|
5634 default: |
|
5635 return; |
|
5636 } |
|
5637 m_style->setPageSizeType(pageSizeType); |
|
5638 m_style->setPageSize(LengthSize(width, height)); |
|
5639 return; |
|
5640 } |
|
5641 |
|
5642 bool CSSStyleSelector::pageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height) |
|
5643 { |
|
5644 static const Length a5Width = mmLength(148), a5Height = mmLength(210); |
|
5645 static const Length a4Width = mmLength(210), a4Height = mmLength(297); |
|
5646 static const Length a3Width = mmLength(297), a3Height = mmLength(420); |
|
5647 static const Length b5Width = mmLength(176), b5Height = mmLength(250); |
|
5648 static const Length b4Width = mmLength(250), b4Height = mmLength(353); |
|
5649 static const Length letterWidth = inchLength(8.5), letterHeight = inchLength(11); |
|
5650 static const Length legalWidth = inchLength(8.5), legalHeight = inchLength(14); |
|
5651 static const Length ledgerWidth = inchLength(11), ledgerHeight = inchLength(17); |
|
5652 |
|
5653 if (!pageSizeName || pageSizeName->primitiveType() != CSSPrimitiveValue::CSS_IDENT) |
|
5654 return false; |
|
5655 |
|
5656 switch (pageSizeName->getIdent()) { |
|
5657 case CSSValueA5: |
|
5658 width = a5Width; |
|
5659 height = a5Height; |
|
5660 break; |
|
5661 case CSSValueA4: |
|
5662 width = a4Width; |
|
5663 height = a4Height; |
|
5664 break; |
|
5665 case CSSValueA3: |
|
5666 width = a3Width; |
|
5667 height = a3Height; |
|
5668 break; |
|
5669 case CSSValueB5: |
|
5670 width = b5Width; |
|
5671 height = b5Height; |
|
5672 break; |
|
5673 case CSSValueB4: |
|
5674 width = b4Width; |
|
5675 height = b4Height; |
|
5676 break; |
|
5677 case CSSValueLetter: |
|
5678 width = letterWidth; |
|
5679 height = letterHeight; |
|
5680 break; |
|
5681 case CSSValueLegal: |
|
5682 width = legalWidth; |
|
5683 height = legalHeight; |
|
5684 break; |
|
5685 case CSSValueLedger: |
|
5686 width = ledgerWidth; |
|
5687 height = ledgerHeight; |
|
5688 break; |
|
5689 default: |
|
5690 return false; |
|
5691 } |
|
5692 |
|
5693 if (pageOrientation) { |
|
5694 if (pageOrientation->primitiveType() != CSSPrimitiveValue::CSS_IDENT) |
|
5695 return false; |
|
5696 switch (pageOrientation->getIdent()) { |
|
5697 case CSSValueLandscape: |
|
5698 std::swap(width, height); |
|
5699 break; |
|
5700 case CSSValuePortrait: |
|
5701 // Nothing to do. |
|
5702 break; |
|
5703 default: |
|
5704 return false; |
|
5705 } |
|
5706 } |
|
5707 return true; |
|
5708 } |
|
5709 |
|
5710 Length CSSStyleSelector::mmLength(double mm) |
|
5711 { |
|
5712 return Length(CSSPrimitiveValue::create(mm, CSSPrimitiveValue::CSS_MM)->computeLengthIntForLength(style(), m_rootElementStyle), Fixed); |
|
5713 } |
|
5714 |
|
5715 Length CSSStyleSelector::inchLength(double inch) |
|
5716 { |
|
5717 return Length(CSSPrimitiveValue::create(inch, CSSPrimitiveValue::CSS_IN)->computeLengthIntForLength(style(), m_rootElementStyle), Fixed); |
|
5718 } |
|
5719 |
|
5720 void CSSStyleSelector::mapFillAttachment(FillLayer* layer, CSSValue* value) |
|
5721 { |
|
5722 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5723 layer->setAttachment(FillLayer::initialFillAttachment(layer->type())); |
|
5724 return; |
|
5725 } |
|
5726 |
|
5727 if (!value->isPrimitiveValue()) |
|
5728 return; |
|
5729 |
|
5730 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5731 switch (primitiveValue->getIdent()) { |
|
5732 case CSSValueFixed: |
|
5733 layer->setAttachment(FixedBackgroundAttachment); |
|
5734 break; |
|
5735 case CSSValueScroll: |
|
5736 layer->setAttachment(ScrollBackgroundAttachment); |
|
5737 break; |
|
5738 case CSSValueLocal: |
|
5739 layer->setAttachment(LocalBackgroundAttachment); |
|
5740 break; |
|
5741 default: |
|
5742 return; |
|
5743 } |
|
5744 } |
|
5745 |
|
5746 void CSSStyleSelector::mapFillClip(FillLayer* layer, CSSValue* value) |
|
5747 { |
|
5748 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5749 layer->setClip(FillLayer::initialFillClip(layer->type())); |
|
5750 return; |
|
5751 } |
|
5752 |
|
5753 if (!value->isPrimitiveValue()) |
|
5754 return; |
|
5755 |
|
5756 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5757 layer->setClip(*primitiveValue); |
|
5758 } |
|
5759 |
|
5760 void CSSStyleSelector::mapFillComposite(FillLayer* layer, CSSValue* value) |
|
5761 { |
|
5762 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5763 layer->setComposite(FillLayer::initialFillComposite(layer->type())); |
|
5764 return; |
|
5765 } |
|
5766 |
|
5767 if (!value->isPrimitiveValue()) |
|
5768 return; |
|
5769 |
|
5770 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5771 layer->setComposite(*primitiveValue); |
|
5772 } |
|
5773 |
|
5774 void CSSStyleSelector::mapFillOrigin(FillLayer* layer, CSSValue* value) |
|
5775 { |
|
5776 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5777 layer->setOrigin(FillLayer::initialFillOrigin(layer->type())); |
|
5778 return; |
|
5779 } |
|
5780 |
|
5781 if (!value->isPrimitiveValue()) |
|
5782 return; |
|
5783 |
|
5784 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5785 layer->setOrigin(*primitiveValue); |
|
5786 } |
|
5787 |
|
5788 StyleImage* CSSStyleSelector::styleImage(CSSValue* value) |
|
5789 { |
|
5790 if (value->isImageValue()) |
|
5791 return static_cast<CSSImageValue*>(value)->cachedImage(m_element->document()->docLoader()); |
|
5792 if (value->isImageGeneratorValue()) |
|
5793 return static_cast<CSSImageGeneratorValue*>(value)->generatedImage(); |
|
5794 return 0; |
|
5795 } |
|
5796 |
|
5797 void CSSStyleSelector::mapFillImage(FillLayer* layer, CSSValue* value) |
|
5798 { |
|
5799 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5800 layer->setImage(FillLayer::initialFillImage(layer->type())); |
|
5801 return; |
|
5802 } |
|
5803 |
|
5804 layer->setImage(styleImage(value)); |
|
5805 } |
|
5806 |
|
5807 void CSSStyleSelector::mapFillRepeatX(FillLayer* layer, CSSValue* value) |
|
5808 { |
|
5809 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5810 layer->setRepeatX(FillLayer::initialFillRepeatX(layer->type())); |
|
5811 return; |
|
5812 } |
|
5813 |
|
5814 if (!value->isPrimitiveValue()) |
|
5815 return; |
|
5816 |
|
5817 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5818 layer->setRepeatX(*primitiveValue); |
|
5819 } |
|
5820 |
|
5821 void CSSStyleSelector::mapFillRepeatY(FillLayer* layer, CSSValue* value) |
|
5822 { |
|
5823 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5824 layer->setRepeatY(FillLayer::initialFillRepeatY(layer->type())); |
|
5825 return; |
|
5826 } |
|
5827 |
|
5828 if (!value->isPrimitiveValue()) |
|
5829 return; |
|
5830 |
|
5831 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5832 layer->setRepeatY(*primitiveValue); |
|
5833 } |
|
5834 |
|
5835 void CSSStyleSelector::mapFillSize(FillLayer* layer, CSSValue* value) |
|
5836 { |
|
5837 if (!value->isPrimitiveValue()) { |
|
5838 layer->setSizeType(SizeNone); |
|
5839 return; |
|
5840 } |
|
5841 |
|
5842 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5843 if (primitiveValue->getIdent() == CSSValueContain) |
|
5844 layer->setSizeType(Contain); |
|
5845 else if (primitiveValue->getIdent() == CSSValueCover) |
|
5846 layer->setSizeType(Cover); |
|
5847 else |
|
5848 layer->setSizeType(SizeLength); |
|
5849 |
|
5850 LengthSize b = FillLayer::initialFillSizeLength(layer->type()); |
|
5851 |
|
5852 if (value->cssValueType() == CSSValue::CSS_INITIAL || primitiveValue->getIdent() == CSSValueContain |
|
5853 || primitiveValue->getIdent() == CSSValueCover) { |
|
5854 layer->setSizeLength(b); |
|
5855 return; |
|
5856 } |
|
5857 |
|
5858 Pair* pair = primitiveValue->getPairValue(); |
|
5859 if (!pair) |
|
5860 return; |
|
5861 |
|
5862 CSSPrimitiveValue* first = static_cast<CSSPrimitiveValue*>(pair->first()); |
|
5863 CSSPrimitiveValue* second = static_cast<CSSPrimitiveValue*>(pair->second()); |
|
5864 |
|
5865 if (!first || !second) |
|
5866 return; |
|
5867 |
|
5868 Length firstLength, secondLength; |
|
5869 int firstType = first->primitiveType(); |
|
5870 int secondType = second->primitiveType(); |
|
5871 |
|
5872 float zoomFactor = m_style->effectiveZoom(); |
|
5873 |
|
5874 if (firstType == CSSPrimitiveValue::CSS_UNKNOWN) |
|
5875 firstLength = Length(Auto); |
|
5876 else if (CSSPrimitiveValue::isUnitTypeLength(firstType)) |
|
5877 firstLength = Length(first->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); |
|
5878 else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
5879 firstLength = Length(first->getDoubleValue(), Percent); |
|
5880 else |
|
5881 return; |
|
5882 |
|
5883 if (secondType == CSSPrimitiveValue::CSS_UNKNOWN) |
|
5884 secondLength = Length(Auto); |
|
5885 else if (CSSPrimitiveValue::isUnitTypeLength(secondType)) |
|
5886 secondLength = Length(second->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); |
|
5887 else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
5888 secondLength = Length(second->getDoubleValue(), Percent); |
|
5889 else |
|
5890 return; |
|
5891 |
|
5892 b.setWidth(firstLength); |
|
5893 b.setHeight(secondLength); |
|
5894 layer->setSizeLength(b); |
|
5895 } |
|
5896 |
|
5897 void CSSStyleSelector::mapFillXPosition(FillLayer* layer, CSSValue* value) |
|
5898 { |
|
5899 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5900 layer->setXPosition(FillLayer::initialFillXPosition(layer->type())); |
|
5901 return; |
|
5902 } |
|
5903 |
|
5904 if (!value->isPrimitiveValue()) |
|
5905 return; |
|
5906 |
|
5907 float zoomFactor = m_style->effectiveZoom(); |
|
5908 |
|
5909 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5910 Length l; |
|
5911 int type = primitiveValue->primitiveType(); |
|
5912 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
5913 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); |
|
5914 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
5915 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
5916 else |
|
5917 return; |
|
5918 layer->setXPosition(l); |
|
5919 } |
|
5920 |
|
5921 void CSSStyleSelector::mapFillYPosition(FillLayer* layer, CSSValue* value) |
|
5922 { |
|
5923 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5924 layer->setYPosition(FillLayer::initialFillYPosition(layer->type())); |
|
5925 return; |
|
5926 } |
|
5927 |
|
5928 if (!value->isPrimitiveValue()) |
|
5929 return; |
|
5930 |
|
5931 float zoomFactor = m_style->effectiveZoom(); |
|
5932 |
|
5933 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5934 Length l; |
|
5935 int type = primitiveValue->primitiveType(); |
|
5936 if (CSSPrimitiveValue::isUnitTypeLength(type)) |
|
5937 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); |
|
5938 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
5939 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
5940 else |
|
5941 return; |
|
5942 layer->setYPosition(l); |
|
5943 } |
|
5944 |
|
5945 void CSSStyleSelector::mapAnimationDelay(Animation* animation, CSSValue* value) |
|
5946 { |
|
5947 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5948 animation->setDelay(Animation::initialAnimationDelay()); |
|
5949 return; |
|
5950 } |
|
5951 |
|
5952 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5953 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) |
|
5954 animation->setDelay(primitiveValue->getFloatValue()); |
|
5955 else |
|
5956 animation->setDelay(primitiveValue->getFloatValue()/1000.0f); |
|
5957 } |
|
5958 |
|
5959 void CSSStyleSelector::mapAnimationDirection(Animation* layer, CSSValue* value) |
|
5960 { |
|
5961 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5962 layer->setDirection(Animation::initialAnimationDirection()); |
|
5963 return; |
|
5964 } |
|
5965 |
|
5966 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5967 layer->setDirection(primitiveValue->getIdent() == CSSValueAlternate ? Animation::AnimationDirectionAlternate : Animation::AnimationDirectionNormal); |
|
5968 } |
|
5969 |
|
5970 void CSSStyleSelector::mapAnimationDuration(Animation* animation, CSSValue* value) |
|
5971 { |
|
5972 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5973 animation->setDuration(Animation::initialAnimationDuration()); |
|
5974 return; |
|
5975 } |
|
5976 |
|
5977 if (!value->isPrimitiveValue()) |
|
5978 return; |
|
5979 |
|
5980 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5981 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) |
|
5982 animation->setDuration(primitiveValue->getFloatValue()); |
|
5983 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) |
|
5984 animation->setDuration(primitiveValue->getFloatValue()/1000.0f); |
|
5985 } |
|
5986 |
|
5987 void CSSStyleSelector::mapAnimationFillMode(Animation* layer, CSSValue* value) |
|
5988 { |
|
5989 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
5990 layer->setFillMode(Animation::initialAnimationFillMode()); |
|
5991 return; |
|
5992 } |
|
5993 |
|
5994 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
5995 switch (primitiveValue->getIdent()) { |
|
5996 case CSSValueNone: |
|
5997 layer->setFillMode(AnimationFillModeNone); |
|
5998 break; |
|
5999 case CSSValueForwards: |
|
6000 layer->setFillMode(AnimationFillModeForwards); |
|
6001 break; |
|
6002 case CSSValueBackwards: |
|
6003 layer->setFillMode(AnimationFillModeBackwards); |
|
6004 break; |
|
6005 case CSSValueBoth: |
|
6006 layer->setFillMode(AnimationFillModeBoth); |
|
6007 break; |
|
6008 } |
|
6009 } |
|
6010 |
|
6011 void CSSStyleSelector::mapAnimationIterationCount(Animation* animation, CSSValue* value) |
|
6012 { |
|
6013 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
6014 animation->setIterationCount(Animation::initialAnimationIterationCount()); |
|
6015 return; |
|
6016 } |
|
6017 |
|
6018 if (!value->isPrimitiveValue()) |
|
6019 return; |
|
6020 |
|
6021 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
6022 if (primitiveValue->getIdent() == CSSValueInfinite) |
|
6023 animation->setIterationCount(-1); |
|
6024 else |
|
6025 animation->setIterationCount(int(primitiveValue->getFloatValue())); |
|
6026 } |
|
6027 |
|
6028 void CSSStyleSelector::mapAnimationName(Animation* layer, CSSValue* value) |
|
6029 { |
|
6030 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
6031 layer->setName(Animation::initialAnimationName()); |
|
6032 return; |
|
6033 } |
|
6034 |
|
6035 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
6036 |
|
6037 if (primitiveValue->getIdent() == CSSValueNone) |
|
6038 layer->setIsNoneAnimation(true); |
|
6039 else |
|
6040 layer->setName(primitiveValue->getStringValue()); |
|
6041 } |
|
6042 |
|
6043 void CSSStyleSelector::mapAnimationPlayState(Animation* layer, CSSValue* value) |
|
6044 { |
|
6045 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
6046 layer->setPlayState(Animation::initialAnimationPlayState()); |
|
6047 return; |
|
6048 } |
|
6049 |
|
6050 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
6051 EAnimPlayState playState = (primitiveValue->getIdent() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying; |
|
6052 layer->setPlayState(playState); |
|
6053 } |
|
6054 |
|
6055 void CSSStyleSelector::mapAnimationProperty(Animation* animation, CSSValue* value) |
|
6056 { |
|
6057 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
6058 animation->setProperty(Animation::initialAnimationProperty()); |
|
6059 return; |
|
6060 } |
|
6061 |
|
6062 if (!value->isPrimitiveValue()) |
|
6063 return; |
|
6064 |
|
6065 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
6066 if (primitiveValue->getIdent() == CSSValueAll) |
|
6067 animation->setProperty(cAnimateAll); |
|
6068 else if (primitiveValue->getIdent() == CSSValueNone) |
|
6069 animation->setProperty(cAnimateNone); |
|
6070 else |
|
6071 animation->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent())); |
|
6072 } |
|
6073 |
|
6074 void CSSStyleSelector::mapAnimationTimingFunction(Animation* animation, CSSValue* value) |
|
6075 { |
|
6076 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
6077 animation->setTimingFunction(Animation::initialAnimationTimingFunction()); |
|
6078 return; |
|
6079 } |
|
6080 |
|
6081 if (value->isPrimitiveValue()) { |
|
6082 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
6083 switch (primitiveValue->getIdent()) { |
|
6084 case CSSValueLinear: |
|
6085 animation->setTimingFunction(TimingFunction(LinearTimingFunction, 0.0, 0.0, 1.0, 1.0)); |
|
6086 break; |
|
6087 case CSSValueEase: |
|
6088 animation->setTimingFunction(TimingFunction()); |
|
6089 break; |
|
6090 case CSSValueEaseIn: |
|
6091 animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, 0.42, 0.0, 1.0, 1.0)); |
|
6092 break; |
|
6093 case CSSValueEaseOut: |
|
6094 animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, 0.0, 0.0, 0.58, 1.0)); |
|
6095 break; |
|
6096 case CSSValueEaseInOut: |
|
6097 animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, 0.42, 0.0, 0.58, 1.0)); |
|
6098 break; |
|
6099 } |
|
6100 return; |
|
6101 } |
|
6102 |
|
6103 if (value->isTimingFunctionValue()) { |
|
6104 CSSTimingFunctionValue* timingFunction = static_cast<CSSTimingFunctionValue*>(value); |
|
6105 animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, timingFunction->x1(), timingFunction->y1(), timingFunction->x2(), timingFunction->y2())); |
|
6106 } |
|
6107 } |
|
6108 |
|
6109 void CSSStyleSelector::mapNinePieceImage(CSSValue* value, NinePieceImage& image) |
|
6110 { |
|
6111 // If we're a primitive value, then we are "none" and don't need to alter the empty image at all. |
|
6112 if (!value || value->isPrimitiveValue()) |
|
6113 return; |
|
6114 |
|
6115 // Retrieve the border image value. |
|
6116 CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value); |
|
6117 |
|
6118 // Set the image (this kicks off the load). |
|
6119 image.setImage(styleImage(borderImage->imageValue())); |
|
6120 |
|
6121 // Set up a length box to represent our image slices. |
|
6122 LengthBox l; |
|
6123 Rect* r = borderImage->m_imageSliceRect.get(); |
|
6124 if (r->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
6125 l.m_top = Length(r->top()->getDoubleValue(), Percent); |
|
6126 else |
|
6127 l.m_top = Length(r->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); |
|
6128 if (r->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
6129 l.m_bottom = Length(r->bottom()->getDoubleValue(), Percent); |
|
6130 else |
|
6131 l.m_bottom = Length((int)r->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); |
|
6132 if (r->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
6133 l.m_left = Length(r->left()->getDoubleValue(), Percent); |
|
6134 else |
|
6135 l.m_left = Length(r->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); |
|
6136 if (r->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
6137 l.m_right = Length(r->right()->getDoubleValue(), Percent); |
|
6138 else |
|
6139 l.m_right = Length(r->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); |
|
6140 image.setSlices(l); |
|
6141 |
|
6142 // Set the appropriate rules for stretch/round/repeat of the slices |
|
6143 ENinePieceImageRule horizontalRule; |
|
6144 switch (borderImage->m_horizontalSizeRule) { |
|
6145 case CSSValueStretch: |
|
6146 horizontalRule = StretchImageRule; |
|
6147 break; |
|
6148 case CSSValueRound: |
|
6149 horizontalRule = RoundImageRule; |
|
6150 break; |
|
6151 default: // CSSValueRepeat |
|
6152 horizontalRule = RepeatImageRule; |
|
6153 break; |
|
6154 } |
|
6155 image.setHorizontalRule(horizontalRule); |
|
6156 |
|
6157 ENinePieceImageRule verticalRule; |
|
6158 switch (borderImage->m_verticalSizeRule) { |
|
6159 case CSSValueStretch: |
|
6160 verticalRule = StretchImageRule; |
|
6161 break; |
|
6162 case CSSValueRound: |
|
6163 verticalRule = RoundImageRule; |
|
6164 break; |
|
6165 default: // CSSValueRepeat |
|
6166 verticalRule = RepeatImageRule; |
|
6167 break; |
|
6168 } |
|
6169 image.setVerticalRule(verticalRule); |
|
6170 } |
|
6171 |
|
6172 void CSSStyleSelector::checkForTextSizeAdjust() |
|
6173 { |
|
6174 if (m_style->textSizeAdjust()) |
|
6175 return; |
|
6176 |
|
6177 FontDescription newFontDescription(m_style->fontDescription()); |
|
6178 newFontDescription.setComputedSize(newFontDescription.specifiedSize()); |
|
6179 m_style->setFontDescription(newFontDescription); |
|
6180 } |
|
6181 |
|
6182 void CSSStyleSelector::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle) |
|
6183 { |
|
6184 if (style->effectiveZoom() == parentStyle->effectiveZoom()) |
|
6185 return; |
|
6186 |
|
6187 const FontDescription& childFont = style->fontDescription(); |
|
6188 FontDescription newFontDescription(childFont); |
|
6189 setFontSize(newFontDescription, childFont.specifiedSize()); |
|
6190 style->setFontDescription(newFontDescription); |
|
6191 } |
|
6192 |
|
6193 void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle) |
|
6194 { |
|
6195 const FontDescription& childFont = style->fontDescription(); |
|
6196 |
|
6197 if (childFont.isAbsoluteSize() || !parentStyle) |
|
6198 return; |
|
6199 |
|
6200 const FontDescription& parentFont = parentStyle->fontDescription(); |
|
6201 if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize()) |
|
6202 return; |
|
6203 |
|
6204 // For now, lump all families but monospace together. |
|
6205 if (childFont.genericFamily() != FontDescription::MonospaceFamily && |
|
6206 parentFont.genericFamily() != FontDescription::MonospaceFamily) |
|
6207 return; |
|
6208 |
|
6209 // We know the parent is monospace or the child is monospace, and that font |
|
6210 // size was unspecified. We want to scale our font size as appropriate. |
|
6211 // If the font uses a keyword size, then we refetch from the table rather than |
|
6212 // multiplying by our scale factor. |
|
6213 float size; |
|
6214 if (childFont.keywordSize()) |
|
6215 size = fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + childFont.keywordSize() - 1, childFont.useFixedDefaultSize()); |
|
6216 else { |
|
6217 Settings* settings = m_checker.m_document->settings(); |
|
6218 float fixedScaleFactor = settings |
|
6219 ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize() |
|
6220 : 1; |
|
6221 size = parentFont.useFixedDefaultSize() ? |
|
6222 childFont.specifiedSize() / fixedScaleFactor : |
|
6223 childFont.specifiedSize() * fixedScaleFactor; |
|
6224 } |
|
6225 |
|
6226 FontDescription newFontDescription(childFont); |
|
6227 setFontSize(newFontDescription, size); |
|
6228 style->setFontDescription(newFontDescription); |
|
6229 } |
|
6230 |
|
6231 void CSSStyleSelector::setFontSize(FontDescription& fontDescription, float size) |
|
6232 { |
|
6233 fontDescription.setSpecifiedSize(size); |
|
6234 |
|
6235 bool useSVGZoomRules = m_element && m_element->isSVGElement(); |
|
6236 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules)); |
|
6237 } |
|
6238 |
|
6239 float CSSStyleSelector::getComputedSizeFromSpecifiedSize(Document* document, RenderStyle* style, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules) |
|
6240 { |
|
6241 float zoomFactor = 1.0f; |
|
6242 if (!useSVGZoomRules) { |
|
6243 zoomFactor = style->effectiveZoom(); |
|
6244 if (document->view() && document->view()->shouldApplyTextZoom()) |
|
6245 zoomFactor *= document->view()->textZoomFactor(); |
|
6246 } |
|
6247 |
|
6248 // We support two types of minimum font size. The first is a hard override that applies to |
|
6249 // all fonts. This is "minSize." The second type of minimum font size is a "smart minimum" |
|
6250 // that is applied only when the Web page can't know what size it really asked for, e.g., |
|
6251 // when it uses logical sizes like "small" or expresses the font-size as a percentage of |
|
6252 // the user's default font setting. |
|
6253 |
|
6254 // With the smart minimum, we never want to get smaller than the minimum font size to keep fonts readable. |
|
6255 // However we always allow the page to set an explicit pixel size that is smaller, |
|
6256 // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum). |
|
6257 |
|
6258 Settings* settings = document->settings(); |
|
6259 if (!settings) |
|
6260 return 1.0f; |
|
6261 |
|
6262 int minSize = settings->minimumFontSize(); |
|
6263 int minLogicalSize = settings->minimumLogicalFontSize(); |
|
6264 float zoomedSize = specifiedSize * zoomFactor; |
|
6265 |
|
6266 // Apply the hard minimum first. We only apply the hard minimum if after zooming we're still too small. |
|
6267 if (zoomedSize < minSize) |
|
6268 zoomedSize = minSize; |
|
6269 |
|
6270 // Now apply the "smart minimum." This minimum is also only applied if we're still too small |
|
6271 // after zooming. The font size must either be relative to the user default or the original size |
|
6272 // must have been acceptable. In other words, we only apply the smart minimum whenever we're positive |
|
6273 // doing so won't disrupt the layout. |
|
6274 if (zoomedSize < minLogicalSize && (specifiedSize >= minLogicalSize || !isAbsoluteSize)) |
|
6275 zoomedSize = minLogicalSize; |
|
6276 |
|
6277 // Also clamp to a reasonable maximum to prevent insane font sizes from causing crashes on various |
|
6278 // platforms (I'm looking at you, Windows.) |
|
6279 return min(1000000.0f, max(zoomedSize, 1.0f)); |
|
6280 } |
|
6281 |
|
6282 const int fontSizeTableMax = 16; |
|
6283 const int fontSizeTableMin = 9; |
|
6284 const int totalKeywords = 8; |
|
6285 |
|
6286 // WinIE/Nav4 table for font sizes. Designed to match the legacy font mapping system of HTML. |
|
6287 static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] = |
|
6288 { |
|
6289 { 9, 9, 9, 9, 11, 14, 18, 28 }, |
|
6290 { 9, 9, 9, 10, 12, 15, 20, 31 }, |
|
6291 { 9, 9, 9, 11, 13, 17, 22, 34 }, |
|
6292 { 9, 9, 10, 12, 14, 18, 24, 37 }, |
|
6293 { 9, 9, 10, 13, 16, 20, 26, 40 }, // fixed font default (13) |
|
6294 { 9, 9, 11, 14, 17, 21, 28, 42 }, |
|
6295 { 9, 10, 12, 15, 17, 23, 30, 45 }, |
|
6296 { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16) |
|
6297 }; |
|
6298 // HTML 1 2 3 4 5 6 7 |
|
6299 // CSS xxs xs s m l xl xxl |
|
6300 // | |
|
6301 // user pref |
|
6302 |
|
6303 // Strict mode table matches MacIE and Mozilla's settings exactly. |
|
6304 static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] = |
|
6305 { |
|
6306 { 9, 9, 9, 9, 11, 14, 18, 27 }, |
|
6307 { 9, 9, 9, 10, 12, 15, 20, 30 }, |
|
6308 { 9, 9, 10, 11, 13, 17, 22, 33 }, |
|
6309 { 9, 9, 10, 12, 14, 18, 24, 36 }, |
|
6310 { 9, 10, 12, 13, 16, 20, 26, 39 }, // fixed font default (13) |
|
6311 { 9, 10, 12, 14, 17, 21, 28, 42 }, |
|
6312 { 9, 10, 13, 15, 18, 23, 30, 45 }, |
|
6313 { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16) |
|
6314 }; |
|
6315 // HTML 1 2 3 4 5 6 7 |
|
6316 // CSS xxs xs s m l xl xxl |
|
6317 // | |
|
6318 // user pref |
|
6319 |
|
6320 // For values outside the range of the table, we use Todd Fahrner's suggested scale |
|
6321 // factors for each keyword value. |
|
6322 static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f }; |
|
6323 |
|
6324 float CSSStyleSelector::fontSizeForKeyword(Document* document, int keyword, bool fixed) |
|
6325 { |
|
6326 Settings* settings = document->settings(); |
|
6327 if (!settings) |
|
6328 return 1.0f; |
|
6329 |
|
6330 bool quirksMode = document->inCompatMode(); |
|
6331 int mediumSize = fixed ? settings->defaultFixedFontSize() : settings->defaultFontSize(); |
|
6332 if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) { |
|
6333 // Look up the entry in the table. |
|
6334 int row = mediumSize - fontSizeTableMin; |
|
6335 int col = (keyword - CSSValueXxSmall); |
|
6336 return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[row][col]; |
|
6337 } |
|
6338 |
|
6339 // Value is outside the range of the table. Apply the scale factor instead. |
|
6340 float minLogicalSize = max(settings->minimumLogicalFontSize(), 1); |
|
6341 return max(fontSizeFactors[keyword - CSSValueXxSmall]*mediumSize, minLogicalSize); |
|
6342 } |
|
6343 |
|
6344 float CSSStyleSelector::largerFontSize(float size, bool) const |
|
6345 { |
|
6346 // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale up to |
|
6347 // the next size level. |
|
6348 return size * 1.2f; |
|
6349 } |
|
6350 |
|
6351 float CSSStyleSelector::smallerFontSize(float size, bool) const |
|
6352 { |
|
6353 // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to |
|
6354 // the next size level. |
|
6355 return size / 1.2f; |
|
6356 } |
|
6357 |
|
6358 static Color colorForCSSValue(int cssValueId) |
|
6359 { |
|
6360 struct ColorValue { |
|
6361 int cssValueId; |
|
6362 RGBA32 color; |
|
6363 }; |
|
6364 |
|
6365 static const ColorValue colorValues[] = { |
|
6366 { CSSValueAqua, 0xFF00FFFF }, |
|
6367 { CSSValueBlack, 0xFF000000 }, |
|
6368 { CSSValueBlue, 0xFF0000FF }, |
|
6369 { CSSValueFuchsia, 0xFFFF00FF }, |
|
6370 { CSSValueGray, 0xFF808080 }, |
|
6371 { CSSValueGreen, 0xFF008000 }, |
|
6372 { CSSValueGrey, 0xFF808080 }, |
|
6373 { CSSValueLime, 0xFF00FF00 }, |
|
6374 { CSSValueMaroon, 0xFF800000 }, |
|
6375 { CSSValueNavy, 0xFF000080 }, |
|
6376 { CSSValueOlive, 0xFF808000 }, |
|
6377 { CSSValueOrange, 0xFFFFA500 }, |
|
6378 { CSSValuePurple, 0xFF800080 }, |
|
6379 { CSSValueRed, 0xFFFF0000 }, |
|
6380 { CSSValueSilver, 0xFFC0C0C0 }, |
|
6381 { CSSValueTeal, 0xFF008080 }, |
|
6382 { CSSValueTransparent, 0x00000000 }, |
|
6383 { CSSValueWhite, 0xFFFFFFFF }, |
|
6384 { CSSValueYellow, 0xFFFFFF00 }, |
|
6385 { 0, 0 } |
|
6386 }; |
|
6387 |
|
6388 for (const ColorValue* col = colorValues; col->cssValueId; ++col) { |
|
6389 if (col->cssValueId == cssValueId) |
|
6390 return col->color; |
|
6391 } |
|
6392 return RenderTheme::defaultTheme()->systemColor(cssValueId); |
|
6393 } |
|
6394 |
|
6395 Color CSSStyleSelector::getColorFromPrimitiveValue(CSSPrimitiveValue* primitiveValue) |
|
6396 { |
|
6397 Color col; |
|
6398 int ident = primitiveValue->getIdent(); |
|
6399 if (ident) { |
|
6400 if (ident == CSSValueWebkitText) |
|
6401 col = m_element->document()->textColor(); |
|
6402 else if (ident == CSSValueWebkitLink) |
|
6403 col = m_element->isLink() && m_checker.m_matchVisitedPseudoClass ? m_element->document()->visitedLinkColor() : m_element->document()->linkColor(); |
|
6404 else if (ident == CSSValueWebkitActivelink) |
|
6405 col = m_element->document()->activeLinkColor(); |
|
6406 else if (ident == CSSValueWebkitFocusRingColor) |
|
6407 col = RenderTheme::focusRingColor(); |
|
6408 else if (ident == CSSValueCurrentcolor) |
|
6409 col = m_style->color(); |
|
6410 else |
|
6411 col = colorForCSSValue(ident); |
|
6412 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR) |
|
6413 col.setRGB(primitiveValue->getRGBA32Value()); |
|
6414 return col; |
|
6415 } |
|
6416 |
|
6417 bool CSSStyleSelector::hasSelectorForAttribute(const AtomicString &attrname) |
|
6418 { |
|
6419 return m_selectorAttrs.contains(attrname.impl()); |
|
6420 } |
|
6421 |
|
6422 void CSSStyleSelector::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result) |
|
6423 { |
|
6424 m_viewportDependentMediaQueryResults.append(new MediaQueryResult(*expr, result)); |
|
6425 } |
|
6426 |
|
6427 bool CSSStyleSelector::affectedByViewportChange() const |
|
6428 { |
|
6429 unsigned s = m_viewportDependentMediaQueryResults.size(); |
|
6430 for (unsigned i = 0; i < s; i++) { |
|
6431 if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result) |
|
6432 return true; |
|
6433 } |
|
6434 return false; |
|
6435 } |
|
6436 |
|
6437 void CSSStyleSelector::SelectorChecker::allVisitedStateChanged() |
|
6438 { |
|
6439 if (m_linksCheckedForVisitedState.isEmpty()) |
|
6440 return; |
|
6441 for (Node* node = m_document; node; node = node->traverseNextNode()) { |
|
6442 if (node->isLink()) |
|
6443 node->setNeedsStyleRecalc(); |
|
6444 } |
|
6445 } |
|
6446 |
|
6447 void CSSStyleSelector::SelectorChecker::visitedStateChanged(LinkHash visitedHash) |
|
6448 { |
|
6449 if (!m_linksCheckedForVisitedState.contains(visitedHash)) |
|
6450 return; |
|
6451 for (Node* node = m_document; node; node = node->traverseNextNode()) { |
|
6452 const AtomicString* attr = linkAttribute(node); |
|
6453 if (attr && visitedLinkHash(m_document->baseURL(), *attr) == visitedHash) |
|
6454 node->setNeedsStyleRecalc(); |
|
6455 } |
|
6456 } |
|
6457 |
|
6458 static TransformOperation::OperationType getTransformOperationType(WebKitCSSTransformValue::TransformOperationType type) |
|
6459 { |
|
6460 switch (type) { |
|
6461 case WebKitCSSTransformValue::ScaleTransformOperation: return TransformOperation::SCALE; |
|
6462 case WebKitCSSTransformValue::ScaleXTransformOperation: return TransformOperation::SCALE_X; |
|
6463 case WebKitCSSTransformValue::ScaleYTransformOperation: return TransformOperation::SCALE_Y; |
|
6464 case WebKitCSSTransformValue::ScaleZTransformOperation: return TransformOperation::SCALE_Z; |
|
6465 case WebKitCSSTransformValue::Scale3DTransformOperation: return TransformOperation::SCALE_3D; |
|
6466 case WebKitCSSTransformValue::TranslateTransformOperation: return TransformOperation::TRANSLATE; |
|
6467 case WebKitCSSTransformValue::TranslateXTransformOperation: return TransformOperation::TRANSLATE_X; |
|
6468 case WebKitCSSTransformValue::TranslateYTransformOperation: return TransformOperation::TRANSLATE_Y; |
|
6469 case WebKitCSSTransformValue::TranslateZTransformOperation: return TransformOperation::TRANSLATE_Z; |
|
6470 case WebKitCSSTransformValue::Translate3DTransformOperation: return TransformOperation::TRANSLATE_3D; |
|
6471 case WebKitCSSTransformValue::RotateTransformOperation: return TransformOperation::ROTATE; |
|
6472 case WebKitCSSTransformValue::RotateXTransformOperation: return TransformOperation::ROTATE_X; |
|
6473 case WebKitCSSTransformValue::RotateYTransformOperation: return TransformOperation::ROTATE_Y; |
|
6474 case WebKitCSSTransformValue::RotateZTransformOperation: return TransformOperation::ROTATE_Z; |
|
6475 case WebKitCSSTransformValue::Rotate3DTransformOperation: return TransformOperation::ROTATE_3D; |
|
6476 case WebKitCSSTransformValue::SkewTransformOperation: return TransformOperation::SKEW; |
|
6477 case WebKitCSSTransformValue::SkewXTransformOperation: return TransformOperation::SKEW_X; |
|
6478 case WebKitCSSTransformValue::SkewYTransformOperation: return TransformOperation::SKEW_Y; |
|
6479 case WebKitCSSTransformValue::MatrixTransformOperation: return TransformOperation::MATRIX; |
|
6480 case WebKitCSSTransformValue::Matrix3DTransformOperation: return TransformOperation::MATRIX_3D; |
|
6481 case WebKitCSSTransformValue::PerspectiveTransformOperation: return TransformOperation::PERSPECTIVE; |
|
6482 case WebKitCSSTransformValue::UnknownTransformOperation: return TransformOperation::NONE; |
|
6483 } |
|
6484 return TransformOperation::NONE; |
|
6485 } |
|
6486 |
|
6487 bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* style, RenderStyle* rootStyle, TransformOperations& outOperations) |
|
6488 { |
|
6489 float zoomFactor = style ? style->effectiveZoom() : 1; |
|
6490 |
|
6491 TransformOperations operations; |
|
6492 if (inValue && !inValue->isPrimitiveValue()) { |
|
6493 CSSValueList* list = static_cast<CSSValueList*>(inValue); |
|
6494 unsigned size = list->length(); |
|
6495 for (unsigned i = 0; i < size; i++) { |
|
6496 WebKitCSSTransformValue* val = static_cast<WebKitCSSTransformValue*>(list->itemWithoutBoundsCheck(i)); |
|
6497 |
|
6498 CSSPrimitiveValue* firstValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(0)); |
|
6499 |
|
6500 switch (val->operationType()) { |
|
6501 case WebKitCSSTransformValue::ScaleTransformOperation: |
|
6502 case WebKitCSSTransformValue::ScaleXTransformOperation: |
|
6503 case WebKitCSSTransformValue::ScaleYTransformOperation: { |
|
6504 double sx = 1.0; |
|
6505 double sy = 1.0; |
|
6506 if (val->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation) |
|
6507 sy = firstValue->getDoubleValue(); |
|
6508 else { |
|
6509 sx = firstValue->getDoubleValue(); |
|
6510 if (val->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) { |
|
6511 if (val->length() > 1) { |
|
6512 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1)); |
|
6513 sy = secondValue->getDoubleValue(); |
|
6514 } else |
|
6515 sy = sx; |
|
6516 } |
|
6517 } |
|
6518 operations.operations().append(ScaleTransformOperation::create(sx, sy, 1.0, getTransformOperationType(val->operationType()))); |
|
6519 break; |
|
6520 } |
|
6521 case WebKitCSSTransformValue::ScaleZTransformOperation: |
|
6522 case WebKitCSSTransformValue::Scale3DTransformOperation: { |
|
6523 double sx = 1.0; |
|
6524 double sy = 1.0; |
|
6525 double sz = 1.0; |
|
6526 if (val->operationType() == WebKitCSSTransformValue::ScaleZTransformOperation) |
|
6527 sz = firstValue->getDoubleValue(); |
|
6528 else if (val->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation) |
|
6529 sy = firstValue->getDoubleValue(); |
|
6530 else { |
|
6531 sx = firstValue->getDoubleValue(); |
|
6532 if (val->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) { |
|
6533 if (val->length() > 2) { |
|
6534 CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(2)); |
|
6535 sz = thirdValue->getDoubleValue(); |
|
6536 } |
|
6537 if (val->length() > 1) { |
|
6538 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1)); |
|
6539 sy = secondValue->getDoubleValue(); |
|
6540 } else |
|
6541 sy = sx; |
|
6542 } |
|
6543 } |
|
6544 operations.operations().append(ScaleTransformOperation::create(sx, sy, sz, getTransformOperationType(val->operationType()))); |
|
6545 break; |
|
6546 } |
|
6547 case WebKitCSSTransformValue::TranslateTransformOperation: |
|
6548 case WebKitCSSTransformValue::TranslateXTransformOperation: |
|
6549 case WebKitCSSTransformValue::TranslateYTransformOperation: { |
|
6550 bool ok = true; |
|
6551 Length tx = Length(0, Fixed); |
|
6552 Length ty = Length(0, Fixed); |
|
6553 if (val->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation) |
|
6554 ty = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok); |
|
6555 else { |
|
6556 tx = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok); |
|
6557 if (val->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) { |
|
6558 if (val->length() > 1) { |
|
6559 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1)); |
|
6560 ty = convertToLength(secondValue, style, rootStyle, zoomFactor, &ok); |
|
6561 } |
|
6562 } |
|
6563 } |
|
6564 |
|
6565 if (!ok) |
|
6566 return false; |
|
6567 |
|
6568 operations.operations().append(TranslateTransformOperation::create(tx, ty, Length(0, Fixed), getTransformOperationType(val->operationType()))); |
|
6569 break; |
|
6570 } |
|
6571 case WebKitCSSTransformValue::TranslateZTransformOperation: |
|
6572 case WebKitCSSTransformValue::Translate3DTransformOperation: { |
|
6573 bool ok = true; |
|
6574 Length tx = Length(0, Fixed); |
|
6575 Length ty = Length(0, Fixed); |
|
6576 Length tz = Length(0, Fixed); |
|
6577 if (val->operationType() == WebKitCSSTransformValue::TranslateZTransformOperation) |
|
6578 tz = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok); |
|
6579 else if (val->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation) |
|
6580 ty = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok); |
|
6581 else { |
|
6582 tx = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok); |
|
6583 if (val->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) { |
|
6584 if (val->length() > 2) { |
|
6585 CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(2)); |
|
6586 tz = convertToLength(thirdValue, style, rootStyle, zoomFactor, &ok); |
|
6587 } |
|
6588 if (val->length() > 1) { |
|
6589 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1)); |
|
6590 ty = convertToLength(secondValue, style, rootStyle, zoomFactor, &ok); |
|
6591 } |
|
6592 } |
|
6593 } |
|
6594 |
|
6595 if (!ok) |
|
6596 return false; |
|
6597 |
|
6598 operations.operations().append(TranslateTransformOperation::create(tx, ty, tz, getTransformOperationType(val->operationType()))); |
|
6599 break; |
|
6600 } |
|
6601 case WebKitCSSTransformValue::RotateTransformOperation: { |
|
6602 double angle = firstValue->getDoubleValue(); |
|
6603 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) |
|
6604 angle = rad2deg(angle); |
|
6605 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) |
|
6606 angle = grad2deg(angle); |
|
6607 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN) |
|
6608 angle = turn2deg(angle); |
|
6609 |
|
6610 operations.operations().append(RotateTransformOperation::create(0, 0, 1, angle, getTransformOperationType(val->operationType()))); |
|
6611 break; |
|
6612 } |
|
6613 case WebKitCSSTransformValue::RotateXTransformOperation: |
|
6614 case WebKitCSSTransformValue::RotateYTransformOperation: |
|
6615 case WebKitCSSTransformValue::RotateZTransformOperation: { |
|
6616 double x = 0; |
|
6617 double y = 0; |
|
6618 double z = 0; |
|
6619 double angle = firstValue->getDoubleValue(); |
|
6620 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) |
|
6621 angle = rad2deg(angle); |
|
6622 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) |
|
6623 angle = grad2deg(angle); |
|
6624 |
|
6625 if (val->operationType() == WebKitCSSTransformValue::RotateXTransformOperation) |
|
6626 x = 1; |
|
6627 else if (val->operationType() == WebKitCSSTransformValue::RotateYTransformOperation) |
|
6628 y = 1; |
|
6629 else |
|
6630 z = 1; |
|
6631 operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(val->operationType()))); |
|
6632 break; |
|
6633 } |
|
6634 case WebKitCSSTransformValue::Rotate3DTransformOperation: { |
|
6635 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1)); |
|
6636 CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(2)); |
|
6637 CSSPrimitiveValue* fourthValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(3)); |
|
6638 double x = firstValue->getDoubleValue(); |
|
6639 double y = secondValue->getDoubleValue(); |
|
6640 double z = thirdValue->getDoubleValue(); |
|
6641 double angle = fourthValue->getDoubleValue(); |
|
6642 if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) |
|
6643 angle = rad2deg(angle); |
|
6644 else if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) |
|
6645 angle = grad2deg(angle); |
|
6646 operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(val->operationType()))); |
|
6647 break; |
|
6648 } |
|
6649 case WebKitCSSTransformValue::SkewTransformOperation: |
|
6650 case WebKitCSSTransformValue::SkewXTransformOperation: |
|
6651 case WebKitCSSTransformValue::SkewYTransformOperation: { |
|
6652 double angleX = 0; |
|
6653 double angleY = 0; |
|
6654 double angle = firstValue->getDoubleValue(); |
|
6655 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) |
|
6656 angle = rad2deg(angle); |
|
6657 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) |
|
6658 angle = grad2deg(angle); |
|
6659 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN) |
|
6660 angle = turn2deg(angle); |
|
6661 if (val->operationType() == WebKitCSSTransformValue::SkewYTransformOperation) |
|
6662 angleY = angle; |
|
6663 else { |
|
6664 angleX = angle; |
|
6665 if (val->operationType() == WebKitCSSTransformValue::SkewTransformOperation) { |
|
6666 if (val->length() > 1) { |
|
6667 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1)); |
|
6668 angleY = secondValue->getDoubleValue(); |
|
6669 if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) |
|
6670 angleY = rad2deg(angleY); |
|
6671 else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) |
|
6672 angleY = grad2deg(angleY); |
|
6673 else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_TURN) |
|
6674 angleY = turn2deg(angleY); |
|
6675 } |
|
6676 } |
|
6677 } |
|
6678 operations.operations().append(SkewTransformOperation::create(angleX, angleY, getTransformOperationType(val->operationType()))); |
|
6679 break; |
|
6680 } |
|
6681 case WebKitCSSTransformValue::MatrixTransformOperation: { |
|
6682 double a = firstValue->getDoubleValue(); |
|
6683 double b = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1))->getDoubleValue(); |
|
6684 double c = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(2))->getDoubleValue(); |
|
6685 double d = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(3))->getDoubleValue(); |
|
6686 double e = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(4))->getDoubleValue(); |
|
6687 double f = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(5))->getDoubleValue(); |
|
6688 operations.operations().append(MatrixTransformOperation::create(a, b, c, d, e, f)); |
|
6689 break; |
|
6690 } |
|
6691 case WebKitCSSTransformValue::Matrix3DTransformOperation: { |
|
6692 TransformationMatrix matrix(static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(0))->getDoubleValue(), |
|
6693 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1))->getDoubleValue(), |
|
6694 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(2))->getDoubleValue(), |
|
6695 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(3))->getDoubleValue(), |
|
6696 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(4))->getDoubleValue(), |
|
6697 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(5))->getDoubleValue(), |
|
6698 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(6))->getDoubleValue(), |
|
6699 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(7))->getDoubleValue(), |
|
6700 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(8))->getDoubleValue(), |
|
6701 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(9))->getDoubleValue(), |
|
6702 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(10))->getDoubleValue(), |
|
6703 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(11))->getDoubleValue(), |
|
6704 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(12))->getDoubleValue(), |
|
6705 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(13))->getDoubleValue(), |
|
6706 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(14))->getDoubleValue(), |
|
6707 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(15))->getDoubleValue()); |
|
6708 operations.operations().append(Matrix3DTransformOperation::create(matrix)); |
|
6709 break; |
|
6710 } |
|
6711 case WebKitCSSTransformValue::PerspectiveTransformOperation: { |
|
6712 double p = firstValue->getDoubleValue(); |
|
6713 if (p < 0.0) |
|
6714 return false; |
|
6715 operations.operations().append(PerspectiveTransformOperation::create(p)); |
|
6716 break; |
|
6717 } |
|
6718 case WebKitCSSTransformValue::UnknownTransformOperation: |
|
6719 ASSERT_NOT_REACHED(); |
|
6720 break; |
|
6721 } |
|
6722 } |
|
6723 } |
|
6724 outOperations = operations; |
|
6725 return true; |
|
6726 } |
|
6727 |
|
6728 } // namespace WebCore |