|
1 /** |
|
2 * This file is part of the CSS implementation for KDE. |
|
3 * |
|
4 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
|
5 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) |
|
6 * (C) 2006 Nicholas Shanks (webkit@nickshanks.com) |
|
7 * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. |
|
8 * |
|
9 * This library is free software; you can redistribute it and/or |
|
10 * modify it under the terms of the GNU Library General Public |
|
11 * License as published by the Free Software Foundation; either |
|
12 * version 2 of the License, or (at your option) any later version. |
|
13 * |
|
14 * This library is distributed in the hope that it will be useful, |
|
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
17 * Library General Public License for more details. |
|
18 * |
|
19 * You should have received a copy of the GNU Library General Public License |
|
20 * along with this library; see the file COPYING.LIB. If not, write to |
|
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
22 * Boston, MA 02110-1301, USA. |
|
23 */ |
|
24 |
|
25 #include "config.h" |
|
26 #include "CSSStyleSelector.h" |
|
27 |
|
28 #include "CSSBorderImageValue.h" |
|
29 #include "CSSCursorImageValue.h" |
|
30 #include "CSSImageValue.h" |
|
31 #include "CSSImportRule.h" |
|
32 #include "CSSMediaRule.h" |
|
33 #include "CSSProperty.h" |
|
34 #include "CSSPropertyNames.h" |
|
35 #include "CSSRuleList.h" |
|
36 #include "CSSSelector.h" |
|
37 #include "CSSStyleRule.h" |
|
38 #include "CSSStyleSheet.h" |
|
39 #include "CSSValueKeywords.h" |
|
40 #include "CSSValueList.h" |
|
41 #include "CachedImage.h" |
|
42 #include "Counter.h" |
|
43 #include "DashboardRegion.h" |
|
44 #include "FontFamilyValue.h" |
|
45 #include "FontValue.h" |
|
46 #include "Frame.h" |
|
47 #include "FrameView.h" |
|
48 #include "GlobalHistory.h" |
|
49 #include "HTMLDocument.h" |
|
50 #include "HTMLElement.h" |
|
51 #include "HTMLInputElement.h" |
|
52 #include "HTMLNames.h" |
|
53 #include "MediaList.h" |
|
54 #include "MediaQueryEvaluator.h" |
|
55 #include "Pair.h" |
|
56 #include "Rect.h" |
|
57 #include "RenderTheme.h" |
|
58 #include "Settings.h" |
|
59 #include "ShadowValue.h" |
|
60 #include "StyleSheetList.h" |
|
61 #include "UserAgentStyleSheets.h" |
|
62 #include "loader.h" |
|
63 |
|
64 #if ENABLE(SVG) |
|
65 #include "XLinkNames.h" |
|
66 #include "SVGNames.h" |
|
67 #endif |
|
68 |
|
69 #if PLATFORM(SYMBIAN) |
|
70 #include "Frame.h" |
|
71 #include "WebCoreFrameBridge.h" |
|
72 #endif |
|
73 |
|
74 |
|
75 using namespace std; |
|
76 |
|
77 namespace WebCore { |
|
78 |
|
79 using namespace HTMLNames; |
|
80 |
|
81 // #define STYLE_SHARING_STATS 1 |
|
82 |
|
83 #define HANDLE_INHERIT(prop, Prop) \ |
|
84 if (isInherit) { \ |
|
85 style->set##Prop(parentStyle->prop()); \ |
|
86 return; \ |
|
87 } |
|
88 |
|
89 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ |
|
90 HANDLE_INHERIT(prop, Prop) \ |
|
91 if (isInitial) { \ |
|
92 style->set##Prop(RenderStyle::initial##Prop()); \ |
|
93 return; \ |
|
94 } |
|
95 |
|
96 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \ |
|
97 HANDLE_INHERIT(prop, Prop) \ |
|
98 if (isInitial) { \ |
|
99 style->set##Prop(RenderStyle::initial##Value());\ |
|
100 return;\ |
|
101 } |
|
102 |
|
103 #define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \ |
|
104 if (isInherit) { \ |
|
105 BackgroundLayer* currChild = style->accessBackgroundLayers(); \ |
|
106 BackgroundLayer* prevChild = 0; \ |
|
107 const BackgroundLayer* currParent = parentStyle->backgroundLayers(); \ |
|
108 while (currParent && currParent->is##Prop##Set()) { \ |
|
109 if (!currChild) { \ |
|
110 /* Need to make a new layer.*/ \ |
|
111 currChild = new BackgroundLayer(); \ |
|
112 prevChild->setNext(currChild); \ |
|
113 } \ |
|
114 currChild->set##Prop(currParent->prop()); \ |
|
115 prevChild = currChild; \ |
|
116 currChild = prevChild->next(); \ |
|
117 currParent = currParent->next(); \ |
|
118 } \ |
|
119 \ |
|
120 while (currChild) { \ |
|
121 /* Reset any remaining layers to not have the property set. */ \ |
|
122 currChild->clear##Prop(); \ |
|
123 currChild = currChild->next(); \ |
|
124 } \ |
|
125 return; \ |
|
126 } \ |
|
127 if (isInitial) { \ |
|
128 BackgroundLayer* currChild = style->accessBackgroundLayers(); \ |
|
129 currChild->set##Prop(RenderStyle::initial##Prop()); \ |
|
130 for (currChild = currChild->next(); currChild; currChild = currChild->next()) \ |
|
131 currChild->clear##Prop(); \ |
|
132 return; \ |
|
133 } |
|
134 |
|
135 #define HANDLE_BACKGROUND_VALUE(prop, Prop, value) { \ |
|
136 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \ |
|
137 if (!value->isPrimitiveValue() && !value->isValueList()) \ |
|
138 return; \ |
|
139 BackgroundLayer* currChild = style->accessBackgroundLayers(); \ |
|
140 BackgroundLayer* prevChild = 0; \ |
|
141 if (value->isPrimitiveValue()) { \ |
|
142 map##Prop(currChild, value); \ |
|
143 currChild = currChild->next(); \ |
|
144 } \ |
|
145 else { \ |
|
146 /* Walk each value and put it into a layer, creating new layers as needed. */ \ |
|
147 CSSValueList* valueList = static_cast<CSSValueList*>(value); \ |
|
148 for (unsigned int i = 0; i < valueList->length(); i++) { \ |
|
149 if (!currChild) { \ |
|
150 /* Need to make a new layer to hold this value */ \ |
|
151 currChild = new BackgroundLayer(); \ |
|
152 prevChild->setNext(currChild); \ |
|
153 } \ |
|
154 map##Prop(currChild, valueList->item(i)); \ |
|
155 prevChild = currChild; \ |
|
156 currChild = currChild->next(); \ |
|
157 } \ |
|
158 } \ |
|
159 while (currChild) { \ |
|
160 /* Reset all remaining layers to not have the property set. */ \ |
|
161 currChild->clear##Prop(); \ |
|
162 currChild = currChild->next(); \ |
|
163 } } |
|
164 |
|
165 #define HANDLE_INHERIT_COND(propID, prop, Prop) \ |
|
166 if (id == propID) { \ |
|
167 style->set##Prop(parentStyle->prop()); \ |
|
168 return; \ |
|
169 } |
|
170 |
|
171 #define HANDLE_INITIAL_COND(propID, Prop) \ |
|
172 if (id == propID) { \ |
|
173 style->set##Prop(RenderStyle::initial##Prop()); \ |
|
174 return; \ |
|
175 } |
|
176 |
|
177 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \ |
|
178 if (id == propID) { \ |
|
179 style->set##Prop(RenderStyle::initial##Value()); \ |
|
180 return; \ |
|
181 } |
|
182 |
|
183 class CSSRuleSet |
|
184 { |
|
185 public: |
|
186 CSSRuleSet(); |
|
187 ~CSSRuleSet(); |
|
188 |
|
189 typedef HashMap<AtomicStringImpl*, CSSRuleDataList*> AtomRuleMap; |
|
190 |
|
191 void addRulesFromSheet(CSSStyleSheet* sheet, MediaQueryEvaluator* medium); |
|
192 |
|
193 void addRule(CSSStyleRule* rule, CSSSelector* sel); |
|
194 void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, |
|
195 CSSStyleRule* rule, CSSSelector* sel); |
|
196 |
|
197 CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); } |
|
198 CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); } |
|
199 CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); } |
|
200 CSSRuleDataList* getUniversalRules() { return m_universalRules; } |
|
201 |
|
202 public: |
|
203 AtomRuleMap m_idRules; |
|
204 AtomRuleMap m_classRules; |
|
205 AtomRuleMap m_tagRules; |
|
206 CSSRuleDataList* m_universalRules; |
|
207 |
|
208 unsigned m_ruleCount; |
|
209 }; |
|
210 |
|
211 CSSRuleSet* CSSStyleSelector::defaultStyle = 0; |
|
212 CSSRuleSet* CSSStyleSelector::defaultQuirksStyle = 0; |
|
213 CSSRuleSet* CSSStyleSelector::defaultPrintStyle = 0; |
|
214 CSSRuleSet* CSSStyleSelector::defaultViewSourceStyle = 0; |
|
215 |
|
216 CSSStyleSheet* CSSStyleSelector::defaultSheet = 0; |
|
217 RenderStyle* CSSStyleSelector::styleNotYetAvailable = 0; |
|
218 CSSStyleSheet* CSSStyleSelector::quirksSheet = 0; |
|
219 CSSStyleSheet* CSSStyleSelector::viewSourceSheet = 0; |
|
220 |
|
221 #if ENABLE(SVG) |
|
222 CSSStyleSheet *CSSStyleSelector::svgSheet = 0; |
|
223 #endif |
|
224 |
|
225 static CSSStyleSelector::Encodedurl *currentEncodedURL = 0; |
|
226 static PseudoState pseudoState; |
|
227 |
|
228 CSSStyleSelector::CSSStyleSelector(Document* doc, const String& userStyleSheet, StyleSheetList *styleSheets, bool _strictParsing) |
|
229 { |
|
230 init(); |
|
231 |
|
232 m_document = doc; |
|
233 |
|
234 strictParsing = _strictParsing; |
|
235 if (!defaultStyle) |
|
236 loadDefaultStyle(); |
|
237 |
|
238 m_userStyle = 0; |
|
239 |
|
240 // construct document root element default style. this is needed |
|
241 // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)" |
|
242 // This is here instead of constructor, because when constructor is run, |
|
243 // document doesn't have documentElement |
|
244 // NOTE: this assumes that element that gets passed to styleForElement -call |
|
245 // is always from the document that owns the style selector |
|
246 FrameView* view = m_document->view(); |
|
247 if (view) |
|
248 m_medium = new MediaQueryEvaluator(view->mediaType()); |
|
249 else |
|
250 m_medium = new MediaQueryEvaluator("all"); |
|
251 |
|
252 Element* root = doc->documentElement(); |
|
253 |
|
254 if (root) |
|
255 m_rootDefaultStyle = styleForElement(root, 0, false, true); // dont ref, because the RenderStyle is allocated from global heap |
|
256 |
|
257 if (m_rootDefaultStyle && view) { |
|
258 delete m_medium; |
|
259 m_medium = new MediaQueryEvaluator(view->mediaType(), view->frame()->page(), m_rootDefaultStyle); |
|
260 } |
|
261 |
|
262 // FIXME: This sucks! The user sheet is reparsed every time! |
|
263 if (!userStyleSheet.isEmpty()) { |
|
264 m_userSheet = new CSSStyleSheet(doc); |
|
265 m_userSheet->parseString(userStyleSheet, strictParsing); |
|
266 |
|
267 m_userStyle = new CSSRuleSet(); |
|
268 m_userStyle->addRulesFromSheet(m_userSheet.get(), m_medium); |
|
269 } |
|
270 |
|
271 // add stylesheets from document |
|
272 m_authorStyle = new CSSRuleSet(); |
|
273 |
|
274 DeprecatedPtrListIterator<StyleSheet> it(styleSheets->styleSheets); |
|
275 for (; it.current(); ++it) |
|
276 if (it.current()->isCSSStyleSheet() && !it.current()->disabled()) |
|
277 m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(it.current()), m_medium); |
|
278 |
|
279 } |
|
280 |
|
281 CSSStyleSelector::CSSStyleSelector(CSSStyleSheet *sheet) |
|
282 { |
|
283 init(); |
|
284 |
|
285 if (!defaultStyle) |
|
286 loadDefaultStyle(); |
|
287 FrameView *view = sheet->doc()->view(); |
|
288 |
|
289 if (view) |
|
290 m_medium = new MediaQueryEvaluator(view->mediaType()); |
|
291 else |
|
292 m_medium = new MediaQueryEvaluator("all"); |
|
293 |
|
294 Element* root = sheet->doc()->documentElement(); |
|
295 if (root) |
|
296 m_rootDefaultStyle = styleForElement(root, 0, false, true); |
|
297 |
|
298 if (m_rootDefaultStyle && view) { |
|
299 delete m_medium; |
|
300 m_medium = new MediaQueryEvaluator(view->mediaType(), view->frame()->page(), m_rootDefaultStyle); |
|
301 } |
|
302 |
|
303 m_authorStyle = new CSSRuleSet(); |
|
304 m_authorStyle->addRulesFromSheet(sheet, m_medium); |
|
305 } |
|
306 |
|
307 void CSSStyleSelector::init() |
|
308 { |
|
309 element = 0; |
|
310 m_matchedDecls.clear(); |
|
311 m_ruleList = 0; |
|
312 m_collectRulesOnly = false; |
|
313 m_rootDefaultStyle = 0; |
|
314 m_medium = 0; |
|
315 } |
|
316 |
|
317 void CSSStyleSelector::setEncodedURL(const KURL& url) |
|
318 { |
|
319 KURL u = url; |
|
320 |
|
321 u.setQuery(DeprecatedString::null); |
|
322 u.setRef(DeprecatedString::null); |
|
323 encodedurl.file = u.url(); |
|
324 int pos = encodedurl.file.findRev('/'); |
|
325 encodedurl.path = encodedurl.file; |
|
326 if (pos > 0) { |
|
327 encodedurl.path.truncate(pos); |
|
328 encodedurl.path += '/'; |
|
329 } |
|
330 u.setPath(DeprecatedString::null); |
|
331 encodedurl.host = u.url(); |
|
332 } |
|
333 |
|
334 CSSStyleSelector::~CSSStyleSelector() |
|
335 { |
|
336 delete m_medium; |
|
337 ::delete m_rootDefaultStyle; |
|
338 |
|
339 delete m_authorStyle; |
|
340 delete m_userStyle; |
|
341 } |
|
342 |
|
343 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size) |
|
344 { |
|
345 CSSStyleSheet* const parent = 0; |
|
346 CSSStyleSheet* sheet = new CSSStyleSheet(parent); |
|
347 sheet->ref(); // leak the sheet on purpose since it will be stored in a global variable |
|
348 sheet->parseString(String(characters, size)); |
|
349 return sheet; |
|
350 } |
|
351 |
|
352 template<typename T> CSSStyleSheet* parseUASheet(const T& array) |
|
353 { |
|
354 return parseUASheet((const char*)array, sizeof(array)); |
|
355 |
|
356 } |
|
357 |
|
358 void CSSStyleSelector::loadDefaultStyle() |
|
359 { |
|
360 if (defaultStyle) |
|
361 return; |
|
362 |
|
363 defaultStyle = new CSSRuleSet; |
|
364 defaultPrintStyle = new CSSRuleSet; |
|
365 defaultQuirksStyle = new CSSRuleSet; |
|
366 defaultViewSourceStyle = new CSSRuleSet; |
|
367 |
|
368 MediaQueryEvaluator screenEval("screen"); |
|
369 MediaQueryEvaluator printEval("print"); |
|
370 |
|
371 // Strict-mode rules. |
|
372 defaultSheet = parseUASheet(html4UserAgentStyleSheet); |
|
373 defaultStyle->addRulesFromSheet(defaultSheet, &screenEval); |
|
374 defaultPrintStyle->addRulesFromSheet(defaultSheet, &printEval); |
|
375 |
|
376 #if ENABLE(SVG) |
|
377 // SVG rules. |
|
378 svgSheet = parseUASheet(svgUserAgentStyleSheet); |
|
379 defaultStyle->addRulesFromSheet(svgSheet, &screenEval); |
|
380 defaultPrintStyle->addRulesFromSheet(svgSheet, &printEval); |
|
381 #endif |
|
382 |
|
383 // Quirks-mode rules. |
|
384 quirksSheet = parseUASheet(quirksUserAgentStyleSheet); |
|
385 defaultQuirksStyle->addRulesFromSheet(quirksSheet, &screenEval); |
|
386 |
|
387 // View source rules. |
|
388 viewSourceSheet = parseUASheet(sourceUserAgentStyleSheet); |
|
389 defaultViewSourceStyle->addRulesFromSheet(viewSourceSheet, &screenEval); |
|
390 } |
|
391 |
|
392 void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex) |
|
393 { |
|
394 m_matchedRules.clear(); |
|
395 |
|
396 if (!rules || !element) |
|
397 return; |
|
398 |
|
399 // We need to collect the rules for id, class, tag, and everything else into a buffer and |
|
400 // then sort the buffer. |
|
401 if (element->hasID()) |
|
402 matchRulesForList(rules->getIDRules(element->getIDAttribute().impl()), firstRuleIndex, lastRuleIndex); |
|
403 if (element->hasClass()) { |
|
404 for (const AtomicStringList* singleClass = element->getClassList(); singleClass; singleClass = singleClass->next()) |
|
405 matchRulesForList(rules->getClassRules(singleClass->string().impl()), firstRuleIndex, lastRuleIndex); |
|
406 } |
|
407 matchRulesForList(rules->getTagRules(element->localName().impl()), firstRuleIndex, lastRuleIndex); |
|
408 matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex); |
|
409 |
|
410 // If we didn't match any rules, we're done. |
|
411 if (m_matchedRules.isEmpty()) |
|
412 return; |
|
413 |
|
414 // Sort the set of matched rules. |
|
415 sortMatchedRules(0, m_matchedRules.size()); |
|
416 |
|
417 // Now transfer the set of matched rules over to our list of decls. |
|
418 if (!m_collectRulesOnly) { |
|
419 for (unsigned i = 0; i < m_matchedRules.size(); i++) |
|
420 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration()); |
|
421 } else { |
|
422 for (unsigned i = 0; i < m_matchedRules.size(); i++) { |
|
423 if (!m_ruleList) |
|
424 m_ruleList = new CSSRuleList(); |
|
425 m_ruleList->append(m_matchedRules[i]->rule()); |
|
426 } |
|
427 } |
|
428 } |
|
429 |
|
430 void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex) |
|
431 { |
|
432 if (!rules) |
|
433 return; |
|
434 |
|
435 for (CSSRuleData* d = rules->first(); d; d = d->next()) { |
|
436 CSSStyleRule* rule = d->rule(); |
|
437 const AtomicString& localName = element->localName(); |
|
438 const AtomicString& selectorLocalName = d->selector()->m_tag.localName(); |
|
439 if ((localName == selectorLocalName || selectorLocalName == starAtom) && checkSelector(d->selector(), element)) { |
|
440 // If the rule has no properties to apply, then ignore it. |
|
441 CSSMutableStyleDeclaration* decl = rule->declaration(); |
|
442 if (!decl || !decl->length()) |
|
443 continue; |
|
444 |
|
445 // If we're matching normal rules, set a pseudo bit if |
|
446 // we really just matched a pseudo-element. |
|
447 if (dynamicPseudo != RenderStyle::NOPSEUDO && pseudoStyle == RenderStyle::NOPSEUDO) { |
|
448 if (m_collectRulesOnly) |
|
449 return; |
|
450 style->setHasPseudoStyle(dynamicPseudo); |
|
451 } else { |
|
452 // Update our first/last rule indices in the matched rules array. |
|
453 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size(); |
|
454 if (firstRuleIndex == -1) |
|
455 firstRuleIndex = lastRuleIndex; |
|
456 |
|
457 // Add this rule to our list of matched rules. |
|
458 addMatchedRule(d); |
|
459 } |
|
460 } |
|
461 } |
|
462 } |
|
463 |
|
464 bool operator >(CSSRuleData& r1, CSSRuleData& r2) |
|
465 { |
|
466 int spec1 = r1.selector()->specificity(); |
|
467 int spec2 = r2.selector()->specificity(); |
|
468 return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2; |
|
469 } |
|
470 bool operator <=(CSSRuleData& r1, CSSRuleData& r2) |
|
471 { |
|
472 return !(r1 > r2); |
|
473 } |
|
474 |
|
475 void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end) |
|
476 { |
|
477 if (start >= end || (end - start == 1)) |
|
478 return; // Sanity check. |
|
479 |
|
480 if (end - start <= 6) { |
|
481 // Apply a bubble sort for smaller lists. |
|
482 for (unsigned i = end - 1; i > start; i--) { |
|
483 bool sorted = true; |
|
484 for (unsigned j = start; j < i; j++) { |
|
485 CSSRuleData* elt = m_matchedRules[j]; |
|
486 CSSRuleData* elt2 = m_matchedRules[j + 1]; |
|
487 if (*elt > *elt2) { |
|
488 sorted = false; |
|
489 m_matchedRules[j] = elt2; |
|
490 m_matchedRules[j + 1] = elt; |
|
491 } |
|
492 } |
|
493 if (sorted) |
|
494 return; |
|
495 } |
|
496 return; |
|
497 } |
|
498 |
|
499 // Peform a merge sort for larger lists. |
|
500 unsigned mid = (start + end) / 2; |
|
501 sortMatchedRules(start, mid); |
|
502 sortMatchedRules(mid, end); |
|
503 |
|
504 CSSRuleData* elt = m_matchedRules[mid - 1]; |
|
505 CSSRuleData* elt2 = m_matchedRules[mid]; |
|
506 |
|
507 // Handle the fast common case (of equal specificity). The list may already |
|
508 // be completely sorted. |
|
509 if (*elt <= *elt2) |
|
510 return; |
|
511 |
|
512 // We have to merge sort. Ensure our merge buffer is big enough to hold |
|
513 // all the items. |
|
514 Vector<CSSRuleData*> rulesMergeBuffer; |
|
515 rulesMergeBuffer.reserveCapacity(end - start); |
|
516 |
|
517 unsigned i1 = start; |
|
518 unsigned i2 = mid; |
|
519 |
|
520 elt = m_matchedRules[i1]; |
|
521 elt2 = m_matchedRules[i2]; |
|
522 |
|
523 while (i1 < mid || i2 < end) { |
|
524 if (i1 < mid && (i2 == end || *elt <= *elt2)) { |
|
525 rulesMergeBuffer.append(elt); |
|
526 if (++i1 < mid) |
|
527 elt = m_matchedRules[i1]; |
|
528 } else { |
|
529 rulesMergeBuffer.append(elt2); |
|
530 if (++i2 < end) |
|
531 elt2 = m_matchedRules[i2]; |
|
532 } |
|
533 } |
|
534 |
|
535 for (unsigned i = start; i < end; i++) |
|
536 m_matchedRules[i] = rulesMergeBuffer[i - start]; |
|
537 } |
|
538 |
|
539 void CSSStyleSelector::initElementAndPseudoState(Element* e) |
|
540 { |
|
541 element = e; |
|
542 if (element && element->isStyledElement()) |
|
543 styledElement = static_cast<StyledElement*>(element); |
|
544 else |
|
545 styledElement = 0; |
|
546 currentEncodedURL = &encodedurl; |
|
547 pseudoState = PseudoUnknown; |
|
548 } |
|
549 |
|
550 void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* defaultParent) |
|
551 { |
|
552 // set some variables we will need |
|
553 pseudoStyle = RenderStyle::NOPSEUDO; |
|
554 |
|
555 parentNode = e->parentNode(); |
|
556 |
|
557 #if ENABLE(SVG) |
|
558 if (!parentNode && e->isSVGElement() && e->isShadowNode()) |
|
559 parentNode = e->shadowParentNode(); |
|
560 #endif |
|
561 |
|
562 if (defaultParent) |
|
563 parentStyle = defaultParent; |
|
564 else |
|
565 parentStyle = parentNode ? parentNode->renderStyle() : 0; |
|
566 isXMLDoc = !element->document()->isHTMLDocument(); |
|
567 |
|
568 style = 0; |
|
569 |
|
570 m_matchedDecls.clear(); |
|
571 |
|
572 m_ruleList = 0; |
|
573 |
|
574 fontDirty = false; |
|
575 } |
|
576 |
|
577 // modified version of the one in kurl.cpp |
|
578 static void cleanpath(DeprecatedString &path) |
|
579 { |
|
580 int pos; |
|
581 while ((pos = path.find("/../")) != -1) { |
|
582 int prev = 0; |
|
583 if (pos > 0) |
|
584 prev = path.findRev("/", pos -1); |
|
585 // don't remove the host, i.e. http://foo.org/../foo.html |
|
586 if (prev < 0 || (prev > 3 && path.findRev("://", prev-1) == prev-2)) |
|
587 path.remove(pos, 3); |
|
588 else |
|
589 // matching directory found ? |
|
590 path.remove(prev, pos- prev + 3); |
|
591 } |
|
592 pos = 0; |
|
593 |
|
594 // Don't remove "//" from an anchor identifier. -rjw |
|
595 // Set refPos to -2 to mean "I haven't looked for the anchor yet". |
|
596 // We don't want to waste a function call on the search for the the anchor |
|
597 // in the vast majority of cases where there is no "//" in the path. |
|
598 int refPos = -2; |
|
599 while ((pos = path.find("//", pos)) != -1) { |
|
600 if (refPos == -2) |
|
601 refPos = path.find("#"); |
|
602 if (refPos > 0 && pos >= refPos) |
|
603 break; |
|
604 |
|
605 if (pos == 0 || path[pos-1] != ':') |
|
606 path.remove(pos, 1); |
|
607 else |
|
608 pos += 2; |
|
609 } |
|
610 while ((pos = path.find("/./")) != -1) |
|
611 path.remove(pos, 2); |
|
612 } |
|
613 |
|
614 static void checkPseudoState(Element *e, bool checkVisited = true) |
|
615 { |
|
616 if (!e->isLink()) { |
|
617 pseudoState = PseudoNone; |
|
618 return; |
|
619 } |
|
620 |
|
621 AtomicString attr; |
|
622 if (e->isHTMLElement()) |
|
623 attr = e->getAttribute(hrefAttr); |
|
624 #if ENABLE(SVG) |
|
625 else if (e->isSVGElement()) |
|
626 attr = e->getAttribute(XLinkNames::hrefAttr); |
|
627 #endif |
|
628 if (attr.isNull()) { |
|
629 pseudoState = PseudoNone; |
|
630 return; |
|
631 } |
|
632 |
|
633 if (!checkVisited) { |
|
634 pseudoState = PseudoAnyLink; |
|
635 return; |
|
636 } |
|
637 |
|
638 DeprecatedConstString cu(reinterpret_cast<const DeprecatedChar*>(attr.characters()), attr.length()); |
|
639 DeprecatedString u = cu.string(); |
|
640 if (!u.contains("://")) { |
|
641 if (u[0] == '/') |
|
642 u.prepend(currentEncodedURL->host); |
|
643 else if (u[0] == '#') |
|
644 u.prepend(currentEncodedURL->file); |
|
645 else |
|
646 u.prepend(currentEncodedURL->path); |
|
647 cleanpath(u); |
|
648 } |
|
649 pseudoState = historyContains(u) ? PseudoVisited : PseudoLink; |
|
650 } |
|
651 |
|
652 #ifdef STYLE_SHARING_STATS |
|
653 static int fraction = 0; |
|
654 static int total = 0; |
|
655 #endif |
|
656 |
|
657 static const unsigned cStyleSearchThreshold = 10; |
|
658 |
|
659 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth) |
|
660 { |
|
661 if (parent && parent->isStyledElement()) { |
|
662 StyledElement* p = static_cast<StyledElement*>(parent); |
|
663 if (!p->inlineStyleDecl() && !p->hasID()) { |
|
664 Node* r = p->previousSibling(); |
|
665 unsigned subcount = 0; |
|
666 RenderStyle* st = p->renderStyle(); |
|
667 while (r) { |
|
668 if (r->renderStyle() == st) |
|
669 return r->lastChild(); |
|
670 if (subcount++ == cStyleSearchThreshold) |
|
671 return 0; |
|
672 r = r->previousSibling(); |
|
673 } |
|
674 if (!r && depth < cStyleSearchThreshold) |
|
675 r = locateCousinList(static_cast<Element*>(parent->parentNode()), depth + 1); |
|
676 while (r) { |
|
677 if (r->renderStyle() == st) |
|
678 return r->lastChild(); |
|
679 if (subcount++ == cStyleSearchThreshold) |
|
680 return 0; |
|
681 r = r->previousSibling(); |
|
682 } |
|
683 } |
|
684 } |
|
685 return 0; |
|
686 } |
|
687 |
|
688 bool CSSStyleSelector::canShareStyleWithElement(Node* n) |
|
689 { |
|
690 if (n->isStyledElement()) { |
|
691 StyledElement* s = static_cast<StyledElement*>(n); |
|
692 RenderStyle* style = s->renderStyle(); |
|
693 if (style && !style->unique() && |
|
694 (s->tagQName() == element->tagQName()) && !s->hasID() && |
|
695 (s->hasClass() == element->hasClass()) && !s->inlineStyleDecl() && |
|
696 (s->hasMappedAttributes() == styledElement->hasMappedAttributes()) && |
|
697 (s->isLink() == element->isLink()) && |
|
698 !style->affectedByAttributeSelectors() && |
|
699 (s->hovered() == element->hovered()) && |
|
700 (s->active() == element->active()) && |
|
701 (s->focused() == element->focused()) && |
|
702 (s != s->document()->getCSSTarget() && element != element->document()->getCSSTarget()) && |
|
703 (s->getAttribute(typeAttr) == element->getAttribute(typeAttr)) && |
|
704 (s->getAttribute(readonlyAttr) == element->getAttribute(readonlyAttr))) { |
|
705 bool isControl = s->isControl(); |
|
706 if (isControl != element->isControl()) |
|
707 return false; |
|
708 if (isControl && (s->isEnabled() != element->isEnabled()) || |
|
709 (s->isIndeterminate() != element->isIndeterminate()) || |
|
710 (s->isChecked() != element->isChecked())) |
|
711 return false; |
|
712 |
|
713 bool classesMatch = true; |
|
714 if (s->hasClass()) { |
|
715 const AtomicString& class1 = element->getAttribute(classAttr); |
|
716 const AtomicString& class2 = s->getAttribute(classAttr); |
|
717 classesMatch = (class1 == class2); |
|
718 } |
|
719 |
|
720 if (classesMatch) { |
|
721 bool mappedAttrsMatch = true; |
|
722 if (s->hasMappedAttributes()) |
|
723 mappedAttrsMatch = s->mappedAttributes()->mapsEquivalent(styledElement->mappedAttributes()); |
|
724 if (mappedAttrsMatch) { |
|
725 bool linksMatch = true; |
|
726 if (s->isLink()) { |
|
727 // We need to check to see if the visited state matches. |
|
728 Color linkColor = element->document()->linkColor(); |
|
729 Color visitedColor = element->document()->visitedLinkColor(); |
|
730 if (pseudoState == PseudoUnknown) |
|
731 checkPseudoState(element, style->pseudoState() != PseudoAnyLink || linkColor != visitedColor); |
|
732 linksMatch = (pseudoState == style->pseudoState()); |
|
733 } |
|
734 |
|
735 if (linksMatch) |
|
736 return true; |
|
737 } |
|
738 } |
|
739 } |
|
740 } |
|
741 return false; |
|
742 } |
|
743 |
|
744 RenderStyle* CSSStyleSelector::locateSharedStyle() |
|
745 { |
|
746 if (styledElement && !styledElement->inlineStyleDecl() && !styledElement->hasID() && |
|
747 !styledElement->document()->usesSiblingRules()) { |
|
748 // Check previous siblings. |
|
749 unsigned count = 0; |
|
750 Node* n; |
|
751 for (n = element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()); |
|
752 while (n) { |
|
753 if (canShareStyleWithElement(n)) |
|
754 return n->renderStyle(); |
|
755 if (count++ == cStyleSearchThreshold) |
|
756 return 0; |
|
757 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()); |
|
758 } |
|
759 if (!n) |
|
760 n = locateCousinList(static_cast<Element*>(element->parentNode())); |
|
761 while (n) { |
|
762 if (canShareStyleWithElement(n)) |
|
763 return n->renderStyle(); |
|
764 if (count++ == cStyleSearchThreshold) |
|
765 return 0; |
|
766 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()); |
|
767 } |
|
768 } |
|
769 return 0; |
|
770 } |
|
771 |
|
772 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule) |
|
773 { |
|
774 // First we match rules from the user agent sheet. |
|
775 CSSRuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print") |
|
776 ? defaultPrintStyle : defaultStyle; |
|
777 matchRules(userAgentStyleSheet, firstUARule, lastUARule); |
|
778 |
|
779 // In quirks mode, we match rules from the quirks user agent sheet. |
|
780 if (!strictParsing) |
|
781 matchRules(defaultQuirksStyle, firstUARule, lastUARule); |
|
782 |
|
783 // If we're in view source mode, then we match rules from the view source style sheet. |
|
784 if (m_document->frame() && m_document->frame()->inViewSourceMode()) |
|
785 matchRules(defaultViewSourceStyle, firstUARule, lastUARule); |
|
786 } |
|
787 |
|
788 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where |
|
789 // relative units are interpreted according to document root element style, styled only with UA stylesheet |
|
790 |
|
791 RenderStyle* CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault) |
|
792 { |
|
793 // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer |
|
794 // will vanish if a style recalc happens during loading. |
|
795 if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) { |
|
796 if (!styleNotYetAvailable) { |
|
797 styleNotYetAvailable = ::new RenderStyle; |
|
798 styleNotYetAvailable->ref(); |
|
799 styleNotYetAvailable->setDisplay(NONE); |
|
800 styleNotYetAvailable->font().update(); |
|
801 } |
|
802 styleNotYetAvailable->ref(); |
|
803 e->document()->setHasNodesWithPlaceholderStyle(); |
|
804 return styleNotYetAvailable; |
|
805 } |
|
806 |
|
807 initElementAndPseudoState(e); |
|
808 if (allowSharing) { |
|
809 style = locateSharedStyle(); |
|
810 #ifdef STYLE_SHARING_STATS |
|
811 fraction += style != 0; |
|
812 total++; |
|
813 printf("Sharing %d out of %d\n", fraction, total); |
|
814 #endif |
|
815 if (style) { |
|
816 style->ref(); |
|
817 return style; |
|
818 } |
|
819 } |
|
820 initForStyleResolve(e, defaultParent); |
|
821 |
|
822 if (resolveForRootDefault) { |
|
823 style = ::new RenderStyle(); |
|
824 // don't ref, because we want to delete this, but we cannot unref it |
|
825 } else { |
|
826 style = new (e->document()->renderArena()) RenderStyle(); |
|
827 style->ref(); |
|
828 } |
|
829 if (parentStyle) |
|
830 style->inheritFrom(parentStyle); |
|
831 else |
|
832 parentStyle = style; |
|
833 |
|
834 int firstUARule = -1, lastUARule = -1; |
|
835 int firstUserRule = -1, lastUserRule = -1; |
|
836 int firstAuthorRule = -1, lastAuthorRule = -1; |
|
837 matchUARules(firstUARule, lastUARule); |
|
838 |
|
839 if (!resolveForRootDefault) { |
|
840 // 4. Now we check user sheet rules. |
|
841 matchRules(m_userStyle, firstUserRule, lastUserRule); |
|
842 |
|
843 // 5. Now check author rules, beginning first with presentational attributes |
|
844 // mapped from HTML. |
|
845 if (styledElement) { |
|
846 // Ask if the HTML element has mapped attributes. |
|
847 if (styledElement->hasMappedAttributes()) { |
|
848 // Walk our attribute list and add in each decl. |
|
849 const NamedMappedAttrMap* map = styledElement->mappedAttributes(); |
|
850 for (unsigned i = 0; i < map->length(); i++) { |
|
851 MappedAttribute* attr = map->attributeItem(i); |
|
852 if (attr->decl()) { |
|
853 lastAuthorRule = m_matchedDecls.size(); |
|
854 if (firstAuthorRule == -1) |
|
855 firstAuthorRule = lastAuthorRule; |
|
856 addMatchedDeclaration(attr->decl()); |
|
857 } |
|
858 } |
|
859 } |
|
860 |
|
861 // Now we check additional mapped declarations. |
|
862 // Tables and table cells share an additional mapped rule that must be applied |
|
863 // after all attributes, since their mapped style depends on the values of multiple attributes. |
|
864 CSSMutableStyleDeclaration* attributeDecl = styledElement->additionalAttributeStyleDecl(); |
|
865 if (attributeDecl) { |
|
866 lastAuthorRule = m_matchedDecls.size(); |
|
867 if (firstAuthorRule == -1) |
|
868 firstAuthorRule = lastAuthorRule; |
|
869 addMatchedDeclaration(attributeDecl); |
|
870 } |
|
871 } |
|
872 |
|
873 // 6. Check the rules in author sheets next. |
|
874 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule); |
|
875 |
|
876 // 7. Now check our inline style attribute. |
|
877 if (styledElement) { |
|
878 CSSMutableStyleDeclaration* inlineDecl = styledElement->inlineStyleDecl(); |
|
879 if (inlineDecl) { |
|
880 lastAuthorRule = m_matchedDecls.size(); |
|
881 if (firstAuthorRule == -1) |
|
882 firstAuthorRule = lastAuthorRule; |
|
883 addMatchedDeclaration(inlineDecl); |
|
884 } |
|
885 } |
|
886 } |
|
887 |
|
888 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply |
|
889 // high-priority properties first, i.e., those properties that other properties depend on. |
|
890 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important |
|
891 // and (4) normal important. |
|
892 m_lineHeightValue = 0; |
|
893 applyDeclarations(true, false, 0, m_matchedDecls.size() - 1); |
|
894 if (!resolveForRootDefault) { |
|
895 applyDeclarations(true, true, firstAuthorRule, lastAuthorRule); |
|
896 applyDeclarations(true, true, firstUserRule, lastUserRule); |
|
897 } |
|
898 applyDeclarations(true, true, firstUARule, lastUARule); |
|
899 |
|
900 // If our font got dirtied, go ahead and update it now. |
|
901 if (fontDirty) |
|
902 updateFont(); |
|
903 |
|
904 // Line-height is set when we are sure we decided on the font-size |
|
905 if (m_lineHeightValue) |
|
906 applyProperty(CSS_PROP_LINE_HEIGHT, m_lineHeightValue); |
|
907 |
|
908 // Now do the normal priority UA properties. |
|
909 applyDeclarations(false, false, firstUARule, lastUARule); |
|
910 |
|
911 // Cache our border and background so that we can examine them later. |
|
912 cacheBorderAndBackground(); |
|
913 |
|
914 // Now do the author and user normal priority properties and all the !important properties. |
|
915 if (!resolveForRootDefault) { |
|
916 applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1); |
|
917 applyDeclarations(false, true, firstAuthorRule, lastAuthorRule); |
|
918 applyDeclarations(false, true, firstUserRule, lastUserRule); |
|
919 } |
|
920 applyDeclarations(false, true, firstUARule, lastUARule); |
|
921 |
|
922 // If our font got dirtied by one of the non-essential font props, |
|
923 // go ahead and update it a second time. |
|
924 if (fontDirty) |
|
925 updateFont(); |
|
926 |
|
927 // Clean up our style object's display and text decorations (among other fixups). |
|
928 adjustRenderStyle(style, e); |
|
929 |
|
930 // If we are a link, cache the determined pseudo-state. |
|
931 if (e->isLink()) |
|
932 style->setPseudoState(pseudoState); |
|
933 |
|
934 // If we have first-letter pseudo style, do not share this style |
|
935 if (style->hasPseudoStyle(RenderStyle::FIRST_LETTER)) |
|
936 style->setUnique(); |
|
937 |
|
938 // Now return the style. |
|
939 return style; |
|
940 } |
|
941 |
|
942 RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudo, Element* e, RenderStyle* parentStyle) |
|
943 { |
|
944 if (!e) |
|
945 return 0; |
|
946 |
|
947 initElementAndPseudoState(e); |
|
948 initForStyleResolve(e, parentStyle); |
|
949 pseudoStyle = pseudo; |
|
950 |
|
951 // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking |
|
952 // those rules. |
|
953 |
|
954 // Check UA, user and author rules. |
|
955 int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1; |
|
956 matchUARules(firstUARule, lastUARule); |
|
957 matchRules(m_userStyle, firstUserRule, lastUserRule); |
|
958 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule); |
|
959 |
|
960 if (m_matchedDecls.isEmpty()) |
|
961 return 0; |
|
962 |
|
963 style = new (e->document()->renderArena()) RenderStyle(); |
|
964 style->ref(); |
|
965 if (parentStyle) |
|
966 style->inheritFrom(parentStyle); |
|
967 else |
|
968 parentStyle = style; |
|
969 style->noninherited_flags._styleType = pseudoStyle; |
|
970 |
|
971 m_lineHeightValue = 0; |
|
972 // High-priority properties. |
|
973 applyDeclarations(true, false, 0, m_matchedDecls.size() - 1); |
|
974 applyDeclarations(true, true, firstAuthorRule, lastAuthorRule); |
|
975 applyDeclarations(true, true, firstUserRule, lastUserRule); |
|
976 applyDeclarations(true, true, firstUARule, lastUARule); |
|
977 |
|
978 // If our font got dirtied, go ahead and update it now. |
|
979 if (fontDirty) |
|
980 updateFont(); |
|
981 |
|
982 // Line-height is set when we are sure we decided on the font-size |
|
983 if (m_lineHeightValue) |
|
984 applyProperty(CSS_PROP_LINE_HEIGHT, m_lineHeightValue); |
|
985 |
|
986 // Now do the normal priority properties. |
|
987 applyDeclarations(false, false, firstUARule, lastUARule); |
|
988 |
|
989 // Cache our border and background so that we can examine them later. |
|
990 cacheBorderAndBackground(); |
|
991 |
|
992 applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1); |
|
993 applyDeclarations(false, true, firstAuthorRule, lastAuthorRule); |
|
994 applyDeclarations(false, true, firstUserRule, lastUserRule); |
|
995 applyDeclarations(false, true, firstUARule, lastUARule); |
|
996 |
|
997 // If our font got dirtied by one of the non-essential font props, |
|
998 // go ahead and update it a second time. |
|
999 if (fontDirty) |
|
1000 updateFont(); |
|
1001 // Clean up our style object's display and text decorations (among other fixups). |
|
1002 adjustRenderStyle(style, 0); |
|
1003 |
|
1004 // Now return the style. |
|
1005 return style; |
|
1006 } |
|
1007 |
|
1008 static void addIntrinsicMargins(RenderStyle* style) |
|
1009 { |
|
1010 // Intrinsic margin value. |
|
1011 const int intrinsicMargin = 2; |
|
1012 |
|
1013 // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed. |
|
1014 // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame. |
|
1015 if (style->width().isIntrinsicOrAuto()) { |
|
1016 if (style->marginLeft().quirk()) |
|
1017 style->setMarginLeft(Length(intrinsicMargin, Fixed)); |
|
1018 if (style->marginRight().quirk()) |
|
1019 style->setMarginRight(Length(intrinsicMargin, Fixed)); |
|
1020 } |
|
1021 |
|
1022 if (style->height().isAuto()) { |
|
1023 if (style->marginTop().quirk()) |
|
1024 style->setMarginTop(Length(intrinsicMargin, Fixed)); |
|
1025 if (style->marginBottom().quirk()) |
|
1026 style->setMarginBottom(Length(intrinsicMargin, Fixed)); |
|
1027 } |
|
1028 } |
|
1029 |
|
1030 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, Element *e) |
|
1031 { |
|
1032 // Cache our original display. |
|
1033 style->setOriginalDisplay(style->display()); |
|
1034 |
|
1035 if (style->display() != NONE) { |
|
1036 // If we have a <td> that specifies a float property, in quirks mode we just drop the float |
|
1037 // property. |
|
1038 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force |
|
1039 // these tags to retain their display types. |
|
1040 if (!strictParsing && e) { |
|
1041 if (e->hasTagName(tdTag)) { |
|
1042 style->setDisplay(TABLE_CELL); |
|
1043 style->setFloating(FNONE); |
|
1044 } |
|
1045 else if (e->hasTagName(tableTag)) |
|
1046 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE); |
|
1047 } |
|
1048 |
|
1049 // Tables never support the -webkit-* values for text-align and will reset back to the default. |
|
1050 if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT)) |
|
1051 style->setTextAlign(TAAUTO); |
|
1052 |
|
1053 // Frames and framesets never honor position:relative or position:absolute. This is necessary to |
|
1054 // fix a crash where a site tries to position these objects. They also never honor display. |
|
1055 if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) { |
|
1056 style->setPosition(StaticPosition); |
|
1057 style->setDisplay(BLOCK); |
|
1058 } |
|
1059 |
|
1060 // Table headers with a text-align of auto will change the text-align to center. |
|
1061 if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO) |
|
1062 style->setTextAlign(CENTER); |
|
1063 |
|
1064 // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to |
|
1065 // position or float an inline, compact, or run-in. Cache the original display, since it |
|
1066 // may be needed for positioned elements that have to compute their static normal flow |
|
1067 // positions. We also force inline-level roots to be block-level. |
|
1068 if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX && |
|
1069 (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE || |
|
1070 (e && e->document()->documentElement() == e))) { |
|
1071 if (style->display() == INLINE_TABLE) |
|
1072 style->setDisplay(TABLE); |
|
1073 else if (style->display() == INLINE_BOX) |
|
1074 style->setDisplay(BOX); |
|
1075 else if (style->display() == LIST_ITEM) { |
|
1076 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, |
|
1077 // but only in quirks mode. |
|
1078 if (!strictParsing && style->floating() != FNONE) |
|
1079 style->setDisplay(BLOCK); |
|
1080 } |
|
1081 else |
|
1082 style->setDisplay(BLOCK); |
|
1083 } |
|
1084 |
|
1085 // After performing the display mutation, check table rows. We do not honor position:relative on |
|
1086 // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock() |
|
1087 // on some sites). |
|
1088 if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP || |
|
1089 style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_CELL) && |
|
1090 style->position() == RelativePosition) |
|
1091 style->setPosition(StaticPosition); |
|
1092 } |
|
1093 |
|
1094 // Make sure our z-index value is only applied if the object is positioned, |
|
1095 // relatively positioned, or transparent. |
|
1096 if (style->position() == StaticPosition && style->opacity() == 1.0f) |
|
1097 style->setHasAutoZIndex(); |
|
1098 |
|
1099 // Auto z-index becomes 0 for the root element and transparent objects. This prevents |
|
1100 // cases where objects that should be blended as a single unit end up with a non-transparent |
|
1101 // object wedged in between them. |
|
1102 if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f)) |
|
1103 style->setZIndex(0); |
|
1104 |
|
1105 // Button, legend, input, select and textarea all consider width values of 'auto' to be 'intrinsic'. |
|
1106 // This will be important when we use block flows for all form controls. |
|
1107 if (e && (e->hasTagName(legendTag) || e->hasTagName(buttonTag) || e->hasTagName(inputTag) || |
|
1108 e->hasTagName(selectTag) || e->hasTagName(textareaTag))) { |
|
1109 if (style->width().isAuto()) |
|
1110 style->setWidth(Length(Intrinsic)); |
|
1111 } |
|
1112 |
|
1113 // Finally update our text decorations in effect, but don't allow text-decoration to percolate through |
|
1114 // tables, inline blocks, inline tables, or run-ins. |
|
1115 if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN |
|
1116 || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX) |
|
1117 style->setTextDecorationsInEffect(style->textDecoration()); |
|
1118 else |
|
1119 style->addToTextDecorationsInEffect(style->textDecoration()); |
|
1120 |
|
1121 // If either overflow value is not visible, change to auto. |
|
1122 if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE) |
|
1123 style->setOverflowY(OMARQUEE); |
|
1124 else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE) |
|
1125 style->setOverflowX(OMARQUEE); |
|
1126 else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) |
|
1127 style->setOverflowX(OAUTO); |
|
1128 else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE) |
|
1129 style->setOverflowY(OAUTO); |
|
1130 |
|
1131 // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto. |
|
1132 // FIXME: Eventually table sections will support auto and scroll. |
|
1133 if (style->display() == TABLE || style->display() == INLINE_TABLE || |
|
1134 style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) { |
|
1135 if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) |
|
1136 style->setOverflowX(OVISIBLE); |
|
1137 if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) |
|
1138 style->setOverflowY(OVISIBLE); |
|
1139 } |
|
1140 |
|
1141 // Cull out any useless layers and also repeat patterns into additional layers. |
|
1142 style->adjustBackgroundLayers(); |
|
1143 |
|
1144 // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will |
|
1145 // alter fonts and heights/widths. |
|
1146 if (e && e->isControl() && style->fontSize() >= 11) { |
|
1147 // Don't apply intrinsic margins to image buttons. The designer knows how big the images are, |
|
1148 // so we have to treat all image buttons as though they were explicitly sized. |
|
1149 if (!e->hasTagName(inputTag) || static_cast<HTMLInputElement*>(e)->inputType() != HTMLInputElement::IMAGE) |
|
1150 addIntrinsicMargins(style); |
|
1151 } |
|
1152 |
|
1153 // Let the theme also have a crack at adjusting the style. |
|
1154 if (style->hasAppearance()) |
|
1155 theme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor); |
|
1156 |
|
1157 #if ENABLE(SVG) |
|
1158 if (e && e->isSVGElement()) { |
|
1159 // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty |
|
1160 if (style->overflowY() == OSCROLL) |
|
1161 style->setOverflowY(OHIDDEN); |
|
1162 else if (style->overflowY() == OAUTO) |
|
1163 style->setOverflowY(OVISIBLE); |
|
1164 |
|
1165 if (style->overflowX() == OSCROLL) |
|
1166 style->setOverflowX(OHIDDEN); |
|
1167 else if (style->overflowX() == OAUTO) |
|
1168 style->setOverflowX(OVISIBLE); |
|
1169 |
|
1170 // Only the root <svg> element in an SVG document fragment tree honors css position |
|
1171 if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement())) |
|
1172 style->setPosition(RenderStyle::initialPosition()); |
|
1173 } |
|
1174 #endif |
|
1175 } |
|
1176 |
|
1177 void CSSStyleSelector::updateFont() |
|
1178 { |
|
1179 checkForTextSizeAdjust(); |
|
1180 checkForGenericFamilyChange(style, parentStyle); |
|
1181 style->font().update(); |
|
1182 fontDirty = false; |
|
1183 } |
|
1184 |
|
1185 void CSSStyleSelector::cacheBorderAndBackground() |
|
1186 { |
|
1187 m_hasUAAppearance = style->hasAppearance(); |
|
1188 if (m_hasUAAppearance) { |
|
1189 m_borderData = style->border(); |
|
1190 m_backgroundData = *style->backgroundLayers(); |
|
1191 m_backgroundColor = style->backgroundColor(); |
|
1192 } |
|
1193 } |
|
1194 |
|
1195 RefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly) |
|
1196 { |
|
1197 if (!e || !e->document()->haveStylesheetsLoaded()) |
|
1198 return 0; |
|
1199 |
|
1200 m_collectRulesOnly = true; |
|
1201 |
|
1202 initElementAndPseudoState(e); |
|
1203 initForStyleResolve(e, 0); |
|
1204 |
|
1205 if (!authorOnly) { |
|
1206 int firstUARule = -1, lastUARule = -1; |
|
1207 // First we match rules from the user agent sheet. |
|
1208 matchUARules(firstUARule, lastUARule); |
|
1209 |
|
1210 // Now we check user sheet rules. |
|
1211 int firstUserRule = -1, lastUserRule = -1; |
|
1212 matchRules(m_userStyle, firstUserRule, lastUserRule); |
|
1213 } |
|
1214 |
|
1215 // Check the rules in author sheets. |
|
1216 int firstAuthorRule = -1, lastAuthorRule = -1; |
|
1217 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule); |
|
1218 |
|
1219 m_collectRulesOnly = false; |
|
1220 |
|
1221 return m_ruleList; |
|
1222 } |
|
1223 |
|
1224 RefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, StringImpl* pseudoStyle, bool authorOnly) |
|
1225 { |
|
1226 // FIXME: Implement this. |
|
1227 return 0; |
|
1228 } |
|
1229 |
|
1230 static bool subject; |
|
1231 |
|
1232 bool CSSStyleSelector::checkSelector(CSSSelector* sel, Element *e) |
|
1233 { |
|
1234 dynamicPseudo = RenderStyle::NOPSEUDO; |
|
1235 |
|
1236 Node *n = e; |
|
1237 |
|
1238 // we have the subject part of the selector |
|
1239 subject = true; |
|
1240 |
|
1241 // We track whether or not the rule contains only :hover and :active in a simple selector. If |
|
1242 // so, we can't allow that to apply to every element on the page. We assume the author intended |
|
1243 // to apply the rules only to links. |
|
1244 bool onlyHoverActive = (!sel->hasTag() && |
|
1245 (sel->m_match == CSSSelector::PseudoClass && |
|
1246 (sel->pseudoType() == CSSSelector::PseudoHover || |
|
1247 sel->pseudoType() == CSSSelector::PseudoActive))); |
|
1248 bool affectedByHover = style ? style->affectedByHoverRules() : false; |
|
1249 bool affectedByActive = style ? style->affectedByActiveRules() : false; |
|
1250 bool havePseudo = pseudoStyle != RenderStyle::NOPSEUDO; |
|
1251 |
|
1252 // first selector has to match |
|
1253 if (!checkOneSelector(sel, e)) |
|
1254 return false; |
|
1255 |
|
1256 // check the subselectors |
|
1257 CSSSelector::Relation relation = sel->relation(); |
|
1258 while((sel = sel->m_tagHistory)) { |
|
1259 if (!n->isElementNode()) |
|
1260 return false; |
|
1261 if (relation != CSSSelector::SubSelector) { |
|
1262 subject = false; |
|
1263 if (havePseudo && dynamicPseudo != pseudoStyle) |
|
1264 return false; |
|
1265 } |
|
1266 |
|
1267 switch(relation) |
|
1268 { |
|
1269 case CSSSelector::Descendant: |
|
1270 // FIXME: This match needs to know how to backtrack and be non-deterministic. |
|
1271 do { |
|
1272 n = n->parentNode(); |
|
1273 if (!n || !n->isElementNode()) |
|
1274 return false; |
|
1275 } while (!checkOneSelector(sel, static_cast<Element*>(n))); |
|
1276 break; |
|
1277 case CSSSelector::Child: |
|
1278 { |
|
1279 n = n->parentNode(); |
|
1280 if (!n || !n->isElementNode()) |
|
1281 return false; |
|
1282 if (!checkOneSelector(sel, static_cast<Element*>(n))) |
|
1283 return false; |
|
1284 break; |
|
1285 } |
|
1286 case CSSSelector::DirectAdjacent: |
|
1287 { |
|
1288 n = n->previousSibling(); |
|
1289 while (n && !n->isElementNode()) |
|
1290 n = n->previousSibling(); |
|
1291 if (!n) |
|
1292 return false; |
|
1293 if (!checkOneSelector(sel, static_cast<Element*>(n))) |
|
1294 return false; |
|
1295 break; |
|
1296 } |
|
1297 case CSSSelector::IndirectAdjacent: |
|
1298 // FIXME: This match needs to know how to backtrack and be non-deterministic. |
|
1299 do { |
|
1300 n = n->previousSibling(); |
|
1301 while (n && !n->isElementNode()) |
|
1302 n = n->previousSibling(); |
|
1303 if (!n) |
|
1304 return false; |
|
1305 } while (!checkOneSelector(sel, static_cast<Element*>(n))); |
|
1306 break; |
|
1307 case CSSSelector::SubSelector: |
|
1308 { |
|
1309 if (onlyHoverActive) |
|
1310 onlyHoverActive = (sel->m_match == CSSSelector::PseudoClass && |
|
1311 (sel->pseudoType() == CSSSelector::PseudoHover || |
|
1312 sel->pseudoType() == CSSSelector::PseudoActive)); |
|
1313 |
|
1314 Element *elem = static_cast<Element*>(n); |
|
1315 // a selector is invalid if something follows :first-xxx |
|
1316 if (elem == element && dynamicPseudo != RenderStyle::NOPSEUDO) |
|
1317 return false; |
|
1318 if (!checkOneSelector(sel, elem, true)) |
|
1319 return false; |
|
1320 break; |
|
1321 } |
|
1322 } |
|
1323 relation = sel->relation(); |
|
1324 } |
|
1325 |
|
1326 if (subject && havePseudo && dynamicPseudo != pseudoStyle) |
|
1327 return false; |
|
1328 |
|
1329 // disallow *:hover, *:active, and *:hover:active except for links |
|
1330 if (!strictParsing && onlyHoverActive && subject) { |
|
1331 if (pseudoState == PseudoUnknown) |
|
1332 checkPseudoState(e); |
|
1333 |
|
1334 if (pseudoState == PseudoNone) { |
|
1335 if (!affectedByHover && style->affectedByHoverRules()) |
|
1336 style->setAffectedByHoverRules(false); |
|
1337 if (!affectedByActive && style->affectedByActiveRules()) |
|
1338 style->setAffectedByActiveRules(false); |
|
1339 return false; |
|
1340 } |
|
1341 } |
|
1342 |
|
1343 return true; |
|
1344 } |
|
1345 |
|
1346 bool CSSStyleSelector::checkOneSelector(CSSSelector* sel, Element* e, bool isSubSelector) |
|
1347 { |
|
1348 if(!e) |
|
1349 return false; |
|
1350 |
|
1351 if (sel->hasTag()) { |
|
1352 const AtomicString& localName = e->localName(); |
|
1353 const AtomicString& ns = e->namespaceURI(); |
|
1354 const AtomicString& selLocalName = sel->m_tag.localName(); |
|
1355 const AtomicString& selNS = sel->m_tag.namespaceURI(); |
|
1356 |
|
1357 if ((selLocalName != starAtom && localName != selLocalName) || |
|
1358 (selNS != starAtom && ns != selNS)) |
|
1359 return false; |
|
1360 } |
|
1361 |
|
1362 if (sel->hasAttribute()) { |
|
1363 if (sel->m_match == CSSSelector::Class) { |
|
1364 if (!e->hasClass()) |
|
1365 return false; |
|
1366 for (const AtomicStringList* c = e->getClassList(); c; c = c->next()) |
|
1367 if (c->string() == sel->m_value) |
|
1368 return true; |
|
1369 return false; |
|
1370 } |
|
1371 else if (sel->m_match == CSSSelector::Id) |
|
1372 return e->hasID() && e->getIDAttribute() == sel->m_value; |
|
1373 else if (style && (e != element || !styledElement || (!styledElement->isMappedAttribute(sel->m_attr) && sel->m_attr != typeAttr && sel->m_attr != readonlyAttr))) { |
|
1374 style->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style. |
|
1375 m_selectorAttrs.add(sel->m_attr.localName().impl()); |
|
1376 } |
|
1377 |
|
1378 const AtomicString& value = e->getAttribute(sel->m_attr); |
|
1379 if (value.isNull()) |
|
1380 return false; // attribute is not set |
|
1381 |
|
1382 switch(sel->m_match) { |
|
1383 case CSSSelector::Exact: |
|
1384 if ((isXMLDoc && sel->m_value != value) || (!isXMLDoc && !equalIgnoringCase(sel->m_value, value))) |
|
1385 return false; |
|
1386 break; |
|
1387 case CSSSelector::List: |
|
1388 { |
|
1389 // The selector's value can't contain a space, or it's totally bogus. |
|
1390 if (sel->m_value.contains(' ')) |
|
1391 return false; |
|
1392 |
|
1393 int startSearchAt = 0; |
|
1394 while (true) { |
|
1395 int foundPos = value.find(sel->m_value, startSearchAt, isXMLDoc); |
|
1396 if (foundPos == -1) |
|
1397 return false; |
|
1398 if (foundPos == 0 || value[foundPos-1] == ' ') { |
|
1399 unsigned endStr = foundPos + sel->m_value.length(); |
|
1400 if (endStr == value.length() || value[endStr] == ' ') |
|
1401 break; // We found a match. |
|
1402 } |
|
1403 |
|
1404 // No match. Keep looking. |
|
1405 startSearchAt = foundPos + 1; |
|
1406 } |
|
1407 break; |
|
1408 } |
|
1409 case CSSSelector::Contain: |
|
1410 if (!value.contains(sel->m_value, isXMLDoc)) |
|
1411 return false; |
|
1412 break; |
|
1413 case CSSSelector::Begin: |
|
1414 if (!value.startsWith(sel->m_value, isXMLDoc)) |
|
1415 return false; |
|
1416 break; |
|
1417 case CSSSelector::End: |
|
1418 if (!value.endsWith(sel->m_value, isXMLDoc)) |
|
1419 return false; |
|
1420 break; |
|
1421 case CSSSelector::Hyphen: |
|
1422 if (value.length() < sel->m_value.length()) |
|
1423 return false; |
|
1424 if (!value.startsWith(sel->m_value, isXMLDoc)) |
|
1425 return false; |
|
1426 // It they start the same, check for exact match or following '-': |
|
1427 if (value.length() != sel->m_value.length() && value[sel->m_value.length()] != '-') |
|
1428 return false; |
|
1429 break; |
|
1430 case CSSSelector::PseudoClass: |
|
1431 case CSSSelector::PseudoElement: |
|
1432 default: |
|
1433 break; |
|
1434 } |
|
1435 } |
|
1436 if(sel->m_match == CSSSelector::PseudoClass || sel->m_match == CSSSelector::PseudoElement) |
|
1437 { |
|
1438 // Pseudo elements. We need to check first child here. No dynamic pseudo |
|
1439 // elements for the moment |
|
1440 switch (sel->pseudoType()) { |
|
1441 // Pseudo classes: |
|
1442 case CSSSelector::PseudoEmpty: |
|
1443 if (!e->firstChild()) |
|
1444 return true; |
|
1445 break; |
|
1446 case CSSSelector::PseudoFirstChild: { |
|
1447 // first-child matches the first child that is an element! |
|
1448 if (e->parentNode() && e->parentNode()->isElementNode()) { |
|
1449 Node *n = e->previousSibling(); |
|
1450 while (n && !n->isElementNode()) |
|
1451 n = n->previousSibling(); |
|
1452 if (!n) |
|
1453 return true; |
|
1454 } |
|
1455 break; |
|
1456 } |
|
1457 case CSSSelector::PseudoFirstOfType: { |
|
1458 // first-of-type matches the first element of its type! |
|
1459 if (e->parentNode() && e->parentNode()->isElementNode()) { |
|
1460 const QualifiedName& type = e->tagQName(); |
|
1461 Node *n = e->previousSibling(); |
|
1462 while (n) { |
|
1463 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) |
|
1464 break; |
|
1465 n = n->previousSibling(); |
|
1466 } |
|
1467 if (!n) |
|
1468 return true; |
|
1469 } |
|
1470 break; |
|
1471 } |
|
1472 case CSSSelector::PseudoTarget: |
|
1473 if (e == e->document()->getCSSTarget()) |
|
1474 return true; |
|
1475 break; |
|
1476 case CSSSelector::PseudoAnyLink: |
|
1477 if (pseudoState == PseudoUnknown) |
|
1478 checkPseudoState(e, false); |
|
1479 if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited) |
|
1480 return true; |
|
1481 break; |
|
1482 case CSSSelector::PseudoAutofill: |
|
1483 if (e && e->hasTagName(inputTag)) |
|
1484 return static_cast<HTMLInputElement*>(e)->autofilled(); |
|
1485 break; |
|
1486 case CSSSelector::PseudoLink: |
|
1487 if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink) |
|
1488 checkPseudoState(e); |
|
1489 if (pseudoState == PseudoLink) |
|
1490 return true; |
|
1491 break; |
|
1492 case CSSSelector::PseudoVisited: |
|
1493 if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink) |
|
1494 checkPseudoState(e); |
|
1495 if (pseudoState == PseudoVisited) |
|
1496 return true; |
|
1497 break; |
|
1498 case CSSSelector::PseudoHover: { |
|
1499 // If we're in quirks mode, then hover should never match anchors with no |
|
1500 // href and *:hover should not match anything. This is important for sites like wsj.com. |
|
1501 if (strictParsing || isSubSelector || sel->relation() == CSSSelector::SubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) { |
|
1502 if (element == e && style) |
|
1503 style->setAffectedByHoverRules(true); |
|
1504 if (element != e && e->renderStyle()) |
|
1505 e->renderStyle()->setAffectedByHoverRules(true); |
|
1506 if (e->hovered()) |
|
1507 return true; |
|
1508 } |
|
1509 break; |
|
1510 } |
|
1511 case CSSSelector::PseudoDrag: { |
|
1512 if (element == e && style) |
|
1513 style->setAffectedByDragRules(true); |
|
1514 if (element != e && e->renderStyle()) |
|
1515 e->renderStyle()->setAffectedByDragRules(true); |
|
1516 if (e->renderer() && e->renderer()->isDragging()) |
|
1517 return true; |
|
1518 break; |
|
1519 } |
|
1520 case CSSSelector::PseudoFocus: |
|
1521 if (e && e->focused() && e->document()->frame()->isActive()) |
|
1522 return true; |
|
1523 break; |
|
1524 case CSSSelector::PseudoActive: |
|
1525 // If we're in quirks mode, then :active should never match anchors with no |
|
1526 // href and *:active should not match anything. |
|
1527 if (strictParsing || isSubSelector || sel->relation() == CSSSelector::SubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) { |
|
1528 if (element == e && style) |
|
1529 style->setAffectedByActiveRules(true); |
|
1530 else if (e->renderStyle()) |
|
1531 e->renderStyle()->setAffectedByActiveRules(true); |
|
1532 if (e->active()) |
|
1533 return true; |
|
1534 } |
|
1535 break; |
|
1536 case CSSSelector::PseudoEnabled: |
|
1537 if (e && e->isControl()) |
|
1538 // The UI spec states that you can't match :enabled unless you are an object that can |
|
1539 // "receive focus and be activated." We will limit matching of this pseudo-class to elements |
|
1540 // that are controls. |
|
1541 return e->isEnabled(); |
|
1542 break; |
|
1543 case CSSSelector::PseudoDisabled: |
|
1544 if (e && e->isControl()) |
|
1545 // The UI spec states that you can't match :enabled unless you are an object that can |
|
1546 // "receive focus and be activated." We will limit matching of this pseudo-class to elements |
|
1547 // that are controls. |
|
1548 return !e->isEnabled(); |
|
1549 break; |
|
1550 case CSSSelector::PseudoChecked: |
|
1551 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that |
|
1552 // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just |
|
1553 // obey the CSS spec here in the test for matching the pseudo. |
|
1554 if (e && e->isChecked() && !e->isIndeterminate()) |
|
1555 return true; |
|
1556 break; |
|
1557 case CSSSelector::PseudoIndeterminate: |
|
1558 if (e && e->isIndeterminate()) |
|
1559 return true; |
|
1560 break; |
|
1561 case CSSSelector::PseudoRoot: |
|
1562 if (e == e->document()->documentElement()) |
|
1563 return true; |
|
1564 break; |
|
1565 case CSSSelector::PseudoLang: { |
|
1566 const AtomicString& value = e->getAttribute(langAttr); |
|
1567 if (value.isEmpty() || !value.startsWith(sel->m_argument, false)) |
|
1568 break; |
|
1569 if (value.length() != sel->m_argument.length() && value[sel->m_argument.length()] != '-') |
|
1570 break; |
|
1571 return true; |
|
1572 } |
|
1573 case CSSSelector::PseudoNot: { |
|
1574 // check the simple selector |
|
1575 for (CSSSelector* subSel = sel->m_simpleSelector; subSel; subSel = subSel->m_tagHistory) { |
|
1576 // :not cannot nest. I don't really know why this is a |
|
1577 // restriction in CSS3, but it is, so let's honour it. |
|
1578 if (subSel->m_simpleSelector) |
|
1579 break; |
|
1580 if (!checkOneSelector(subSel, e)) |
|
1581 return true; |
|
1582 } |
|
1583 break; |
|
1584 } |
|
1585 case CSSSelector::PseudoUnknown: |
|
1586 ASSERT_NOT_REACHED(); |
|
1587 break; |
|
1588 |
|
1589 // Pseudo-elements: |
|
1590 case CSSSelector::PseudoFirstLine: |
|
1591 if (subject) { |
|
1592 dynamicPseudo = RenderStyle::FIRST_LINE; |
|
1593 return true; |
|
1594 } |
|
1595 break; |
|
1596 case CSSSelector::PseudoFirstLetter: |
|
1597 if (subject) { |
|
1598 dynamicPseudo = RenderStyle::FIRST_LETTER; |
|
1599 if (Document* doc = e->document()) |
|
1600 doc->setUsesFirstLetterRules(true); |
|
1601 return true; |
|
1602 } |
|
1603 break; |
|
1604 case CSSSelector::PseudoSelection: |
|
1605 dynamicPseudo = RenderStyle::SELECTION; |
|
1606 return true; |
|
1607 case CSSSelector::PseudoBefore: |
|
1608 dynamicPseudo = RenderStyle::BEFORE; |
|
1609 return true; |
|
1610 case CSSSelector::PseudoAfter: |
|
1611 dynamicPseudo = RenderStyle::AFTER; |
|
1612 return true; |
|
1613 case CSSSelector::PseudoFileUploadButton: |
|
1614 dynamicPseudo = RenderStyle::FILE_UPLOAD_BUTTON; |
|
1615 return true; |
|
1616 case CSSSelector::PseudoSliderThumb: |
|
1617 dynamicPseudo = RenderStyle::SLIDER_THUMB; |
|
1618 return true; |
|
1619 case CSSSelector::PseudoSearchCancelButton: |
|
1620 dynamicPseudo = RenderStyle::SEARCH_CANCEL_BUTTON; |
|
1621 return true; |
|
1622 case CSSSelector::PseudoSearchDecoration: |
|
1623 dynamicPseudo = RenderStyle::SEARCH_DECORATION; |
|
1624 return true; |
|
1625 case CSSSelector::PseudoSearchResultsDecoration: |
|
1626 dynamicPseudo = RenderStyle::SEARCH_RESULTS_DECORATION; |
|
1627 return true; |
|
1628 case CSSSelector::PseudoSearchResultsButton: |
|
1629 dynamicPseudo = RenderStyle::SEARCH_RESULTS_BUTTON; |
|
1630 return true; |
|
1631 case CSSSelector::PseudoNotParsed: |
|
1632 ASSERT(false); |
|
1633 break; |
|
1634 } |
|
1635 return false; |
|
1636 } |
|
1637 // ### add the rest of the checks... |
|
1638 return true; |
|
1639 } |
|
1640 |
|
1641 // ----------------------------------------------------------------- |
|
1642 |
|
1643 CSSRuleSet::CSSRuleSet() |
|
1644 { |
|
1645 m_universalRules = 0; |
|
1646 m_ruleCount = 0; |
|
1647 } |
|
1648 |
|
1649 CSSRuleSet::~CSSRuleSet() |
|
1650 { |
|
1651 deleteAllValues(m_idRules); |
|
1652 deleteAllValues(m_classRules); |
|
1653 deleteAllValues(m_tagRules); |
|
1654 |
|
1655 delete m_universalRules; |
|
1656 } |
|
1657 |
|
1658 |
|
1659 void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, |
|
1660 CSSStyleRule* rule, CSSSelector* sel) |
|
1661 { |
|
1662 if (!key) return; |
|
1663 CSSRuleDataList* rules = map.get(key); |
|
1664 if (!rules) { |
|
1665 rules = new CSSRuleDataList(m_ruleCount++, rule, sel); |
|
1666 map.set(key, rules); |
|
1667 } else |
|
1668 rules->append(m_ruleCount++, rule, sel); |
|
1669 } |
|
1670 |
|
1671 void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel) |
|
1672 { |
|
1673 if (sel->m_match == CSSSelector::Id) { |
|
1674 addToRuleSet(sel->m_value.impl(), m_idRules, rule, sel); |
|
1675 return; |
|
1676 } |
|
1677 if (sel->m_match == CSSSelector::Class) { |
|
1678 addToRuleSet(sel->m_value.impl(), m_classRules, rule, sel); |
|
1679 return; |
|
1680 } |
|
1681 |
|
1682 const AtomicString& localName = sel->m_tag.localName(); |
|
1683 if (localName != starAtom) { |
|
1684 addToRuleSet(localName.impl(), m_tagRules, rule, sel); |
|
1685 return; |
|
1686 } |
|
1687 |
|
1688 // Just put it in the universal rule set. |
|
1689 if (!m_universalRules) |
|
1690 m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel); |
|
1691 else |
|
1692 m_universalRules->append(m_ruleCount++, rule, sel); |
|
1693 } |
|
1694 |
|
1695 void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, MediaQueryEvaluator* medium) |
|
1696 { |
|
1697 if (!sheet || !sheet->isCSSStyleSheet()) |
|
1698 return; |
|
1699 |
|
1700 // No media implies "all", but if a media list exists it must |
|
1701 // contain our current medium |
|
1702 if (sheet->media() && !medium->eval(sheet->media())) |
|
1703 return; // the style sheet doesn't apply |
|
1704 |
|
1705 int len = sheet->length(); |
|
1706 |
|
1707 for (int i = 0; i < len; i++) { |
|
1708 StyleBase* item = sheet->item(i); |
|
1709 if (item->isStyleRule()) { |
|
1710 CSSStyleRule* rule = static_cast<CSSStyleRule*>(item); |
|
1711 for (CSSSelector* s = rule->selector(); s; s = s->next()) |
|
1712 addRule(rule, s); |
|
1713 } |
|
1714 else if(item->isImportRule()) { |
|
1715 CSSImportRule* import = static_cast<CSSImportRule*>(item); |
|
1716 if (!import->media() || medium->eval(import->media())) |
|
1717 addRulesFromSheet(import->styleSheet(), medium); |
|
1718 } |
|
1719 else if(item->isMediaRule()) { |
|
1720 CSSMediaRule* r = static_cast<CSSMediaRule*>(item); |
|
1721 CSSRuleList* rules = r->cssRules(); |
|
1722 |
|
1723 if ((!r->media() || medium->eval(r->media())) && rules) { |
|
1724 // Traverse child elements of the @media rule. |
|
1725 for (unsigned j = 0; j < rules->length(); j++) { |
|
1726 CSSRule *childItem = rules->item(j); |
|
1727 if (childItem->isStyleRule()) { |
|
1728 // It is a StyleRule, so append it to our list |
|
1729 CSSStyleRule* rule = static_cast<CSSStyleRule*>(childItem); |
|
1730 for (CSSSelector* s = rule->selector(); s; s = s->next()) |
|
1731 addRule(rule, s); |
|
1732 |
|
1733 } |
|
1734 } // for rules |
|
1735 } // if rules |
|
1736 } |
|
1737 } |
|
1738 } |
|
1739 |
|
1740 // ------------------------------------------------------------------------------------- |
|
1741 // this is mostly boring stuff on how to apply a certain rule to the renderstyle... |
|
1742 |
|
1743 static Length convertToLength(CSSPrimitiveValue *primitiveValue, RenderStyle *style, bool *ok = 0) |
|
1744 { |
|
1745 Length l; |
|
1746 if (!primitiveValue) { |
|
1747 if (ok) |
|
1748 *ok = false; |
|
1749 } else { |
|
1750 int type = primitiveValue->primitiveType(); |
|
1751 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) |
|
1752 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed); |
|
1753 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
1754 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
1755 else if(type == CSSPrimitiveValue::CSS_NUMBER) |
|
1756 l = Length(primitiveValue->getDoubleValue() * 100.0, Percent); |
|
1757 else if (ok) |
|
1758 *ok = false; |
|
1759 } |
|
1760 return l; |
|
1761 } |
|
1762 |
|
1763 void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant, |
|
1764 int startIndex, int endIndex) |
|
1765 { |
|
1766 if (startIndex == -1) return; |
|
1767 for (int i = startIndex; i <= endIndex; i++) { |
|
1768 CSSMutableStyleDeclaration* decl = m_matchedDecls[i]; |
|
1769 DeprecatedValueListConstIterator<CSSProperty> end; |
|
1770 for (DeprecatedValueListConstIterator<CSSProperty> it = decl->valuesIterator(); it != end; ++it) { |
|
1771 const CSSProperty& current = *it; |
|
1772 // give special priority to font-xxx, color properties |
|
1773 if (isImportant == current.isImportant()) { |
|
1774 bool first; |
|
1775 switch(current.id()) { |
|
1776 case CSS_PROP_LINE_HEIGHT: |
|
1777 m_lineHeightValue = current.value(); |
|
1778 first = !applyFirst; // we apply line-height later |
|
1779 break; |
|
1780 case CSS_PROP_COLOR: |
|
1781 case CSS_PROP_DIRECTION: |
|
1782 case CSS_PROP_DISPLAY: |
|
1783 case CSS_PROP_FONT: |
|
1784 case CSS_PROP_FONT_SIZE: |
|
1785 case CSS_PROP_FONT_STYLE: |
|
1786 case CSS_PROP_FONT_FAMILY: |
|
1787 case CSS_PROP_FONT_WEIGHT: |
|
1788 case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST: |
|
1789 case CSS_PROP_FONT_VARIANT: |
|
1790 // these have to be applied first, because other properties use the computed |
|
1791 // values of these porperties. |
|
1792 first = true; |
|
1793 break; |
|
1794 default: |
|
1795 first = false; |
|
1796 break; |
|
1797 } |
|
1798 if (first == applyFirst) |
|
1799 applyProperty(current.id(), current.value()); |
|
1800 } |
|
1801 } |
|
1802 } |
|
1803 } |
|
1804 |
|
1805 static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isReset) |
|
1806 { |
|
1807 CounterDirectiveMap& map = style->accessCounterDirectives(); |
|
1808 typedef CounterDirectiveMap::iterator Iterator; |
|
1809 |
|
1810 Iterator end = map.end(); |
|
1811 for (Iterator it = map.begin(); it != end; ++it) |
|
1812 if (isReset) |
|
1813 it->second.m_reset = false; |
|
1814 else |
|
1815 it->second.m_increment = false; |
|
1816 |
|
1817 int length = list ? list->length() : 0; |
|
1818 for (int i = 0; i < length; ++i) { |
|
1819 Pair* pair = static_cast<CSSPrimitiveValue*>(list->item(i))->getPairValue(); |
|
1820 AtomicString identifier = static_cast<CSSPrimitiveValue*>(pair->first())->getStringValue(); |
|
1821 // FIXME: What about overflow? |
|
1822 int value = static_cast<CSSPrimitiveValue*>(pair->second())->getIntValue(); |
|
1823 CounterDirectives& directives = map.add(identifier.impl(), CounterDirectives()).first->second; |
|
1824 if (isReset) { |
|
1825 directives.m_reset = true; |
|
1826 directives.m_resetValue = value; |
|
1827 } else { |
|
1828 if (directives.m_increment) |
|
1829 directives.m_incrementValue += value; |
|
1830 else { |
|
1831 directives.m_increment = true; |
|
1832 directives.m_incrementValue = value; |
|
1833 } |
|
1834 } |
|
1835 } |
|
1836 } |
|
1837 |
|
1838 void CSSStyleSelector::applyProperty(int id, CSSValue *value) |
|
1839 { |
|
1840 CSSPrimitiveValue *primitiveValue = 0; |
|
1841 if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
1842 |
|
1843 Length l; |
|
1844 bool apply = false; |
|
1845 |
|
1846 unsigned short valueType = value->cssValueType(); |
|
1847 |
|
1848 bool isInherit = parentNode && valueType == CSSValue::CSS_INHERIT; |
|
1849 bool isInitial = valueType == CSSValue::CSS_INITIAL || (!parentNode && valueType == CSSValue::CSS_INHERIT); |
|
1850 |
|
1851 // These properties are used to set the correct margins/padding on RTL lists. |
|
1852 if (id == CSS_PROP__WEBKIT_MARGIN_START) |
|
1853 id = style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT; |
|
1854 else if (id == CSS_PROP__WEBKIT_PADDING_START) |
|
1855 id = style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT; |
|
1856 |
|
1857 // What follows is a list that maps the CSS properties into their corresponding front-end |
|
1858 // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and |
|
1859 // are only hit when mapping "inherit" or "initial" into front-end values. |
|
1860 switch (static_cast<CSSPropertyID>(id)) |
|
1861 { |
|
1862 // ident only properties |
|
1863 case CSS_PROP_BACKGROUND_ATTACHMENT: |
|
1864 HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value) |
|
1865 return; |
|
1866 case CSS_PROP__WEBKIT_BACKGROUND_CLIP: |
|
1867 HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value) |
|
1868 return; |
|
1869 case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE: |
|
1870 HANDLE_BACKGROUND_VALUE(backgroundComposite, BackgroundComposite, value) |
|
1871 return; |
|
1872 case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN: |
|
1873 HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value) |
|
1874 return; |
|
1875 case CSS_PROP_BACKGROUND_REPEAT: |
|
1876 HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value) |
|
1877 return; |
|
1878 case CSS_PROP__WEBKIT_BACKGROUND_SIZE: |
|
1879 HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value) |
|
1880 return; |
|
1881 case CSS_PROP_BORDER_COLLAPSE: |
|
1882 HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse) |
|
1883 if(!primitiveValue) return; |
|
1884 switch(primitiveValue->getIdent()) |
|
1885 { |
|
1886 case CSS_VAL_COLLAPSE: |
|
1887 style->setBorderCollapse(true); |
|
1888 break; |
|
1889 case CSS_VAL_SEPARATE: |
|
1890 style->setBorderCollapse(false); |
|
1891 break; |
|
1892 default: |
|
1893 return; |
|
1894 } |
|
1895 return; |
|
1896 |
|
1897 case CSS_PROP_BORDER_TOP_STYLE: |
|
1898 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle) |
|
1899 if (!primitiveValue) return; |
|
1900 style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE)); |
|
1901 return; |
|
1902 case CSS_PROP_BORDER_RIGHT_STYLE: |
|
1903 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle) |
|
1904 if (!primitiveValue) return; |
|
1905 style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE)); |
|
1906 return; |
|
1907 case CSS_PROP_BORDER_BOTTOM_STYLE: |
|
1908 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle) |
|
1909 if (!primitiveValue) return; |
|
1910 style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE)); |
|
1911 return; |
|
1912 case CSS_PROP_BORDER_LEFT_STYLE: |
|
1913 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle) |
|
1914 if (!primitiveValue) return; |
|
1915 style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE)); |
|
1916 return; |
|
1917 case CSS_PROP_OUTLINE_STYLE: |
|
1918 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle) |
|
1919 if (!primitiveValue) return; |
|
1920 if (primitiveValue->getIdent() == CSS_VAL_AUTO) |
|
1921 style->setOutlineStyle(DOTTED, true); |
|
1922 else |
|
1923 style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE)); |
|
1924 return; |
|
1925 case CSS_PROP_CAPTION_SIDE: |
|
1926 { |
|
1927 HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide) |
|
1928 if(!primitiveValue) return; |
|
1929 ECaptionSide c = RenderStyle::initialCaptionSide(); |
|
1930 switch(primitiveValue->getIdent()) |
|
1931 { |
|
1932 case CSS_VAL_LEFT: |
|
1933 c = CAPLEFT; break; |
|
1934 case CSS_VAL_RIGHT: |
|
1935 c = CAPRIGHT; break; |
|
1936 case CSS_VAL_TOP: |
|
1937 c = CAPTOP; break; |
|
1938 case CSS_VAL_BOTTOM: |
|
1939 c = CAPBOTTOM; break; |
|
1940 default: |
|
1941 return; |
|
1942 } |
|
1943 style->setCaptionSide(c); |
|
1944 return; |
|
1945 } |
|
1946 case CSS_PROP_CLEAR: |
|
1947 { |
|
1948 HANDLE_INHERIT_AND_INITIAL(clear, Clear) |
|
1949 if(!primitiveValue) return; |
|
1950 EClear c; |
|
1951 switch(primitiveValue->getIdent()) |
|
1952 { |
|
1953 case CSS_VAL_NONE: |
|
1954 c = CNONE; break; |
|
1955 case CSS_VAL_LEFT: |
|
1956 c = CLEFT; break; |
|
1957 case CSS_VAL_RIGHT: |
|
1958 c = CRIGHT; break; |
|
1959 case CSS_VAL_BOTH: |
|
1960 c = CBOTH; break; |
|
1961 default: |
|
1962 return; |
|
1963 } |
|
1964 style->setClear(c); |
|
1965 return; |
|
1966 } |
|
1967 case CSS_PROP_DIRECTION: |
|
1968 { |
|
1969 HANDLE_INHERIT_AND_INITIAL(direction, Direction) |
|
1970 if(!primitiveValue) break; |
|
1971 style->setDirection(primitiveValue->getIdent() == CSS_VAL_LTR ? LTR : RTL); |
|
1972 return; |
|
1973 } |
|
1974 case CSS_PROP_DISPLAY: |
|
1975 { |
|
1976 HANDLE_INHERIT_AND_INITIAL(display, Display) |
|
1977 if(!primitiveValue) break; |
|
1978 int id = primitiveValue->getIdent(); |
|
1979 EDisplay d; |
|
1980 if (id == CSS_VAL_NONE) |
|
1981 d = NONE; |
|
1982 else |
|
1983 d = EDisplay(primitiveValue->getIdent() - CSS_VAL_INLINE); |
|
1984 |
|
1985 #if PLATFORM(SYMBIAN) |
|
1986 if( id == CSS_VAL__WAP_MARQUEE ) { |
|
1987 style->setOverflowX(OMARQUEE); |
|
1988 } |
|
1989 #endif |
|
1990 style->setDisplay(d); |
|
1991 |
|
1992 return; |
|
1993 } |
|
1994 |
|
1995 case CSS_PROP_EMPTY_CELLS: |
|
1996 { |
|
1997 HANDLE_INHERIT_AND_INITIAL(emptyCells, EmptyCells) |
|
1998 if (!primitiveValue) break; |
|
1999 int id = primitiveValue->getIdent(); |
|
2000 if (id == CSS_VAL_SHOW) |
|
2001 style->setEmptyCells(SHOW); |
|
2002 else if (id == CSS_VAL_HIDE) |
|
2003 style->setEmptyCells(HIDE); |
|
2004 return; |
|
2005 } |
|
2006 case CSS_PROP_FLOAT: |
|
2007 { |
|
2008 HANDLE_INHERIT_AND_INITIAL(floating, Floating) |
|
2009 if(!primitiveValue) return; |
|
2010 EFloat f; |
|
2011 switch(primitiveValue->getIdent()) |
|
2012 { |
|
2013 case CSS_VAL_LEFT: |
|
2014 f = FLEFT; break; |
|
2015 case CSS_VAL_RIGHT: |
|
2016 f = FRIGHT; break; |
|
2017 case CSS_VAL_NONE: |
|
2018 case CSS_VAL_CENTER: //Non standart CSS-Value |
|
2019 f = FNONE; break; |
|
2020 default: |
|
2021 return; |
|
2022 } |
|
2023 |
|
2024 style->setFloating(f); |
|
2025 return; |
|
2026 } |
|
2027 |
|
2028 case CSS_PROP_FONT_STYLE: |
|
2029 { |
|
2030 FontDescription fontDescription = style->fontDescription(); |
|
2031 if (isInherit) |
|
2032 fontDescription.setItalic(parentStyle->fontDescription().italic()); |
|
2033 else if (isInitial) |
|
2034 fontDescription.setItalic(false); |
|
2035 else { |
|
2036 if (!primitiveValue) return; |
|
2037 switch (primitiveValue->getIdent()) { |
|
2038 case CSS_VAL_OBLIQUE: |
|
2039 // FIXME: oblique is the same as italic for the moment... |
|
2040 case CSS_VAL_ITALIC: |
|
2041 fontDescription.setItalic(true); |
|
2042 break; |
|
2043 case CSS_VAL_NORMAL: |
|
2044 fontDescription.setItalic(false); |
|
2045 break; |
|
2046 default: |
|
2047 return; |
|
2048 } |
|
2049 } |
|
2050 if (style->setFontDescription(fontDescription)) |
|
2051 fontDirty = true; |
|
2052 return; |
|
2053 } |
|
2054 |
|
2055 case CSS_PROP_FONT_VARIANT: |
|
2056 { |
|
2057 FontDescription fontDescription = style->fontDescription(); |
|
2058 if (isInherit) |
|
2059 fontDescription.setSmallCaps(parentStyle->fontDescription().smallCaps()); |
|
2060 else if (isInitial) |
|
2061 fontDescription.setSmallCaps(false); |
|
2062 else { |
|
2063 if (!primitiveValue) return; |
|
2064 int id = primitiveValue->getIdent(); |
|
2065 if (id == CSS_VAL_NORMAL) |
|
2066 fontDescription.setSmallCaps(false); |
|
2067 else if (id == CSS_VAL_SMALL_CAPS) |
|
2068 fontDescription.setSmallCaps(true); |
|
2069 else |
|
2070 return; |
|
2071 } |
|
2072 if (style->setFontDescription(fontDescription)) |
|
2073 fontDirty = true; |
|
2074 return; |
|
2075 } |
|
2076 |
|
2077 case CSS_PROP_FONT_WEIGHT: |
|
2078 { |
|
2079 FontDescription fontDescription = style->fontDescription(); |
|
2080 if (isInherit) |
|
2081 fontDescription.setWeight(parentStyle->fontDescription().weight()); |
|
2082 else if (isInitial) |
|
2083 fontDescription.setWeight(cNormalWeight); |
|
2084 else { |
|
2085 if (!primitiveValue) return; |
|
2086 if (primitiveValue->getIdent()) { |
|
2087 switch (primitiveValue->getIdent()) { |
|
2088 // FIXME: We aren't genuinely supporting specific weight values. |
|
2089 case CSS_VAL_BOLD: |
|
2090 case CSS_VAL_BOLDER: |
|
2091 case CSS_VAL_600: |
|
2092 case CSS_VAL_700: |
|
2093 case CSS_VAL_800: |
|
2094 case CSS_VAL_900: |
|
2095 fontDescription.setWeight(cBoldWeight); |
|
2096 break; |
|
2097 case CSS_VAL_NORMAL: |
|
2098 case CSS_VAL_LIGHTER: |
|
2099 case CSS_VAL_100: |
|
2100 case CSS_VAL_200: |
|
2101 case CSS_VAL_300: |
|
2102 case CSS_VAL_400: |
|
2103 case CSS_VAL_500: |
|
2104 fontDescription.setWeight(cNormalWeight); |
|
2105 break; |
|
2106 default: |
|
2107 return; |
|
2108 } |
|
2109 } |
|
2110 else |
|
2111 { |
|
2112 // ### fix parsing of 100-900 values in parser, apply them here |
|
2113 } |
|
2114 } |
|
2115 if (style->setFontDescription(fontDescription)) |
|
2116 fontDirty = true; |
|
2117 return; |
|
2118 } |
|
2119 |
|
2120 case CSS_PROP_LIST_STYLE_POSITION: |
|
2121 { |
|
2122 HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition) |
|
2123 if (!primitiveValue) return; |
|
2124 if (primitiveValue->getIdent()) |
|
2125 style->setListStylePosition((EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE)); |
|
2126 return; |
|
2127 } |
|
2128 |
|
2129 case CSS_PROP_LIST_STYLE_TYPE: |
|
2130 { |
|
2131 HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType) |
|
2132 if (!primitiveValue) return; |
|
2133 if (primitiveValue->getIdent()) |
|
2134 { |
|
2135 EListStyleType t; |
|
2136 int id = primitiveValue->getIdent(); |
|
2137 if (id == CSS_VAL_NONE) { // important!! |
|
2138 t = LNONE; |
|
2139 } else { |
|
2140 t = EListStyleType(id - CSS_VAL_DISC); |
|
2141 } |
|
2142 style->setListStyleType(t); |
|
2143 } |
|
2144 return; |
|
2145 } |
|
2146 |
|
2147 case CSS_PROP_OVERFLOW: |
|
2148 { |
|
2149 if (isInherit) { |
|
2150 style->setOverflowX(parentStyle->overflowX()); |
|
2151 style->setOverflowY(parentStyle->overflowY()); |
|
2152 return; |
|
2153 } |
|
2154 |
|
2155 if (isInitial) { |
|
2156 style->setOverflowX(RenderStyle::initialOverflowX()); |
|
2157 style->setOverflowY(RenderStyle::initialOverflowY()); |
|
2158 return; |
|
2159 } |
|
2160 |
|
2161 EOverflow o; |
|
2162 switch(primitiveValue->getIdent()) { |
|
2163 case CSS_VAL_VISIBLE: |
|
2164 o = OVISIBLE; break; |
|
2165 case CSS_VAL_HIDDEN: |
|
2166 o = OHIDDEN; break; |
|
2167 case CSS_VAL_SCROLL: |
|
2168 o = OSCROLL; break; |
|
2169 case CSS_VAL_AUTO: |
|
2170 o = OAUTO; break; |
|
2171 case CSS_VAL__WEBKIT_MARQUEE: |
|
2172 o = OMARQUEE; break; |
|
2173 case CSS_VAL_OVERLAY: |
|
2174 o = OOVERLAY; break; |
|
2175 default: |
|
2176 return; |
|
2177 } |
|
2178 style->setOverflowX(o); |
|
2179 style->setOverflowY(o); |
|
2180 return; |
|
2181 } |
|
2182 |
|
2183 case CSS_PROP_OVERFLOW_X: |
|
2184 { |
|
2185 HANDLE_INHERIT_AND_INITIAL(overflowX, OverflowX) |
|
2186 EOverflow o; |
|
2187 switch(primitiveValue->getIdent()) |
|
2188 { |
|
2189 case CSS_VAL_VISIBLE: |
|
2190 o = OVISIBLE; break; |
|
2191 case CSS_VAL_HIDDEN: |
|
2192 o = OHIDDEN; break; |
|
2193 case CSS_VAL_SCROLL: |
|
2194 o = OSCROLL; break; |
|
2195 case CSS_VAL_AUTO: |
|
2196 o = OAUTO; break; |
|
2197 case CSS_VAL__WEBKIT_MARQUEE: |
|
2198 o = OMARQUEE; break; |
|
2199 case CSS_VAL_OVERLAY: |
|
2200 o = OOVERLAY; break; |
|
2201 default: |
|
2202 return; |
|
2203 } |
|
2204 style->setOverflowX(o); |
|
2205 return; |
|
2206 } |
|
2207 |
|
2208 case CSS_PROP_OVERFLOW_Y: |
|
2209 { |
|
2210 HANDLE_INHERIT_AND_INITIAL(overflowY, OverflowY) |
|
2211 EOverflow o; |
|
2212 switch(primitiveValue->getIdent()) |
|
2213 { |
|
2214 case CSS_VAL_VISIBLE: |
|
2215 o = OVISIBLE; break; |
|
2216 case CSS_VAL_HIDDEN: |
|
2217 o = OHIDDEN; break; |
|
2218 case CSS_VAL_SCROLL: |
|
2219 o = OSCROLL; break; |
|
2220 case CSS_VAL_AUTO: |
|
2221 o = OAUTO; break; |
|
2222 case CSS_VAL__WEBKIT_MARQUEE: |
|
2223 o = OMARQUEE; break; |
|
2224 case CSS_VAL_OVERLAY: |
|
2225 o = OOVERLAY; break; |
|
2226 default: |
|
2227 return; |
|
2228 } |
|
2229 style->setOverflowY(o); |
|
2230 return; |
|
2231 } |
|
2232 |
|
2233 case CSS_PROP_PAGE_BREAK_BEFORE: |
|
2234 { |
|
2235 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak) |
|
2236 if (!primitiveValue) return; |
|
2237 switch (primitiveValue->getIdent()) { |
|
2238 case CSS_VAL_AUTO: |
|
2239 style->setPageBreakBefore(PBAUTO); |
|
2240 break; |
|
2241 case CSS_VAL_LEFT: |
|
2242 case CSS_VAL_RIGHT: |
|
2243 case CSS_VAL_ALWAYS: |
|
2244 style->setPageBreakBefore(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always." |
|
2245 break; |
|
2246 case CSS_VAL_AVOID: |
|
2247 style->setPageBreakBefore(PBAVOID); |
|
2248 break; |
|
2249 } |
|
2250 return; |
|
2251 } |
|
2252 |
|
2253 case CSS_PROP_PAGE_BREAK_AFTER: |
|
2254 { |
|
2255 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak) |
|
2256 if (!primitiveValue) return; |
|
2257 switch (primitiveValue->getIdent()) { |
|
2258 case CSS_VAL_AUTO: |
|
2259 style->setPageBreakAfter(PBAUTO); |
|
2260 break; |
|
2261 case CSS_VAL_LEFT: |
|
2262 case CSS_VAL_RIGHT: |
|
2263 case CSS_VAL_ALWAYS: |
|
2264 style->setPageBreakAfter(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always." |
|
2265 break; |
|
2266 case CSS_VAL_AVOID: |
|
2267 style->setPageBreakAfter(PBAVOID); |
|
2268 break; |
|
2269 } |
|
2270 return; |
|
2271 } |
|
2272 |
|
2273 case CSS_PROP_PAGE_BREAK_INSIDE: { |
|
2274 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak) |
|
2275 if (!primitiveValue) return; |
|
2276 if (primitiveValue->getIdent() == CSS_VAL_AUTO) |
|
2277 style->setPageBreakInside(PBAUTO); |
|
2278 else if (primitiveValue->getIdent() == CSS_VAL_AVOID) |
|
2279 style->setPageBreakInside(PBAVOID); |
|
2280 return; |
|
2281 } |
|
2282 |
|
2283 case CSS_PROP_POSITION: |
|
2284 { |
|
2285 HANDLE_INHERIT_AND_INITIAL(position, Position) |
|
2286 if(!primitiveValue) return; |
|
2287 EPosition p; |
|
2288 switch(primitiveValue->getIdent()) |
|
2289 { |
|
2290 case CSS_VAL_STATIC: |
|
2291 p = StaticPosition; |
|
2292 break; |
|
2293 case CSS_VAL_RELATIVE: |
|
2294 p = RelativePosition; |
|
2295 break; |
|
2296 case CSS_VAL_ABSOLUTE: |
|
2297 p = AbsolutePosition; |
|
2298 break; |
|
2299 case CSS_VAL_FIXED: |
|
2300 p = FixedPosition; |
|
2301 break; |
|
2302 default: |
|
2303 return; |
|
2304 } |
|
2305 style->setPosition(p); |
|
2306 return; |
|
2307 } |
|
2308 |
|
2309 case CSS_PROP_TABLE_LAYOUT: { |
|
2310 HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout) |
|
2311 |
|
2312 if (!primitiveValue->getIdent()) |
|
2313 return; |
|
2314 |
|
2315 ETableLayout l = RenderStyle::initialTableLayout(); |
|
2316 switch(primitiveValue->getIdent()) { |
|
2317 case CSS_VAL_FIXED: |
|
2318 l = TFIXED; |
|
2319 // fall through |
|
2320 case CSS_VAL_AUTO: |
|
2321 style->setTableLayout(l); |
|
2322 default: |
|
2323 break; |
|
2324 } |
|
2325 return; |
|
2326 } |
|
2327 |
|
2328 case CSS_PROP_UNICODE_BIDI: { |
|
2329 HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi) |
|
2330 switch (primitiveValue->getIdent()) { |
|
2331 case CSS_VAL_NORMAL: |
|
2332 style->setUnicodeBidi(UBNormal); |
|
2333 break; |
|
2334 case CSS_VAL_EMBED: |
|
2335 style->setUnicodeBidi(Embed); |
|
2336 break; |
|
2337 case CSS_VAL_BIDI_OVERRIDE: |
|
2338 style->setUnicodeBidi(Override); |
|
2339 break; |
|
2340 default: |
|
2341 return; |
|
2342 } |
|
2343 return; |
|
2344 } |
|
2345 case CSS_PROP_TEXT_TRANSFORM: { |
|
2346 HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform) |
|
2347 |
|
2348 if(!primitiveValue->getIdent()) return; |
|
2349 |
|
2350 ETextTransform tt; |
|
2351 switch(primitiveValue->getIdent()) { |
|
2352 case CSS_VAL_CAPITALIZE: tt = CAPITALIZE; break; |
|
2353 case CSS_VAL_UPPERCASE: tt = UPPERCASE; break; |
|
2354 case CSS_VAL_LOWERCASE: tt = LOWERCASE; break; |
|
2355 case CSS_VAL_NONE: |
|
2356 default: tt = TTNONE; break; |
|
2357 } |
|
2358 style->setTextTransform(tt); |
|
2359 return; |
|
2360 } |
|
2361 |
|
2362 case CSS_PROP_VISIBILITY: |
|
2363 { |
|
2364 HANDLE_INHERIT_AND_INITIAL(visibility, Visibility) |
|
2365 |
|
2366 switch(primitiveValue->getIdent()) { |
|
2367 case CSS_VAL_HIDDEN: |
|
2368 style->setVisibility(HIDDEN); |
|
2369 break; |
|
2370 case CSS_VAL_VISIBLE: |
|
2371 style->setVisibility(VISIBLE); |
|
2372 break; |
|
2373 case CSS_VAL_COLLAPSE: |
|
2374 style->setVisibility(COLLAPSE); |
|
2375 default: |
|
2376 break; |
|
2377 } |
|
2378 return; |
|
2379 } |
|
2380 case CSS_PROP_WHITE_SPACE: |
|
2381 HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace) |
|
2382 |
|
2383 if(!primitiveValue->getIdent()) return; |
|
2384 |
|
2385 EWhiteSpace s; |
|
2386 switch(primitiveValue->getIdent()) { |
|
2387 case CSS_VAL__WEBKIT_NOWRAP: |
|
2388 s = KHTML_NOWRAP; |
|
2389 break; |
|
2390 case CSS_VAL_NOWRAP: |
|
2391 s = NOWRAP; |
|
2392 break; |
|
2393 case CSS_VAL_PRE: |
|
2394 s = PRE; |
|
2395 break; |
|
2396 case CSS_VAL_PRE_WRAP: |
|
2397 s = PRE_WRAP; |
|
2398 break; |
|
2399 case CSS_VAL_PRE_LINE: |
|
2400 s = PRE_LINE; |
|
2401 break; |
|
2402 case CSS_VAL_NORMAL: |
|
2403 default: |
|
2404 s = NORMAL; |
|
2405 break; |
|
2406 } |
|
2407 style->setWhiteSpace(s); |
|
2408 return; |
|
2409 |
|
2410 case CSS_PROP_BACKGROUND_POSITION: |
|
2411 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition); |
|
2412 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition); |
|
2413 return; |
|
2414 case CSS_PROP_BACKGROUND_POSITION_X: { |
|
2415 HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value) |
|
2416 return; |
|
2417 } |
|
2418 case CSS_PROP_BACKGROUND_POSITION_Y: { |
|
2419 HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value) |
|
2420 return; |
|
2421 } |
|
2422 case CSS_PROP_BORDER_SPACING: { |
|
2423 if (isInherit) { |
|
2424 style->setHorizontalBorderSpacing(parentStyle->horizontalBorderSpacing()); |
|
2425 style->setVerticalBorderSpacing(parentStyle->verticalBorderSpacing()); |
|
2426 } |
|
2427 else if (isInitial) { |
|
2428 style->setHorizontalBorderSpacing(0); |
|
2429 style->setVerticalBorderSpacing(0); |
|
2430 } |
|
2431 return; |
|
2432 } |
|
2433 case CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING: { |
|
2434 HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing) |
|
2435 if (!primitiveValue) return; |
|
2436 short spacing = primitiveValue->computeLengthShort(style); |
|
2437 style->setHorizontalBorderSpacing(spacing); |
|
2438 return; |
|
2439 } |
|
2440 case CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING: { |
|
2441 HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing) |
|
2442 if (!primitiveValue) return; |
|
2443 short spacing = primitiveValue->computeLengthShort(style); |
|
2444 style->setVerticalBorderSpacing(spacing); |
|
2445 return; |
|
2446 } |
|
2447 case CSS_PROP_CURSOR: |
|
2448 if (isInherit) { |
|
2449 style->setCursor(parentStyle->cursor()); |
|
2450 style->setCursorList(parentStyle->cursors()); |
|
2451 return; |
|
2452 } |
|
2453 style->clearCursorList(); |
|
2454 if (isInitial) { |
|
2455 style->setCursor(RenderStyle::initialCursor()); |
|
2456 return; |
|
2457 } |
|
2458 if (value->isValueList()) { |
|
2459 CSSValueList* list = static_cast<CSSValueList*>(value); |
|
2460 int len = list->length(); |
|
2461 style->setCursor(CURSOR_AUTO); |
|
2462 for (int i = 0; i < len; i++) { |
|
2463 CSSValue* item = list->item(i); |
|
2464 if (!item->isPrimitiveValue()) |
|
2465 continue; |
|
2466 primitiveValue = static_cast<CSSPrimitiveValue*>(item); |
|
2467 int type = primitiveValue->primitiveType(); |
|
2468 if (type == CSSPrimitiveValue::CSS_URI) { |
|
2469 #if ENABLE(SVG) |
|
2470 if (primitiveValue->getStringValue().find("#") == 0) |
|
2471 style->addSVGCursor(primitiveValue->getStringValue().substring(1)); |
|
2472 else |
|
2473 #endif |
|
2474 { |
|
2475 CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue); |
|
2476 style->addCursor(image->image(element->document()->docLoader()), image->hotspot()); |
|
2477 } |
|
2478 } else if (type == CSSPrimitiveValue::CSS_IDENT) { |
|
2479 int ident = primitiveValue->getIdent(); |
|
2480 if (ident == CSS_VAL_COPY) |
|
2481 style->setCursor(CURSOR_COPY); |
|
2482 else if (ident == CSS_VAL_NONE) |
|
2483 style->setCursor(CURSOR_NONE); |
|
2484 else |
|
2485 style->setCursor((ECursor)(ident - CSS_VAL_AUTO)); |
|
2486 } |
|
2487 } |
|
2488 } else if (primitiveValue) { |
|
2489 int type = primitiveValue->primitiveType(); |
|
2490 if (type == CSSPrimitiveValue::CSS_IDENT) { |
|
2491 int ident = primitiveValue->getIdent(); |
|
2492 if (ident == CSS_VAL_COPY) |
|
2493 style->setCursor(CURSOR_COPY); |
|
2494 else if (ident == CSS_VAL_NONE) |
|
2495 style->setCursor(CURSOR_NONE); |
|
2496 else |
|
2497 style->setCursor((ECursor)(ident - CSS_VAL_AUTO)); |
|
2498 } |
|
2499 } |
|
2500 return; |
|
2501 // colors || inherit |
|
2502 case CSS_PROP_BACKGROUND_COLOR: |
|
2503 case CSS_PROP_BORDER_TOP_COLOR: |
|
2504 case CSS_PROP_BORDER_RIGHT_COLOR: |
|
2505 case CSS_PROP_BORDER_BOTTOM_COLOR: |
|
2506 case CSS_PROP_BORDER_LEFT_COLOR: |
|
2507 case CSS_PROP_COLOR: |
|
2508 case CSS_PROP_OUTLINE_COLOR: |
|
2509 case CSS_PROP__WEBKIT_COLUMN_RULE_COLOR: |
|
2510 case CSS_PROP__WEBKIT_TEXT_STROKE_COLOR: |
|
2511 case CSS_PROP__WEBKIT_TEXT_FILL_COLOR: { |
|
2512 Color col; |
|
2513 if (isInherit) { |
|
2514 HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor) |
|
2515 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor) |
|
2516 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor) |
|
2517 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor) |
|
2518 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor) |
|
2519 HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color) |
|
2520 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor) |
|
2521 HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_COLUMN_RULE_COLOR, columnRuleColor, ColumnRuleColor) |
|
2522 HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_TEXT_STROKE_COLOR, textStrokeColor, TextStrokeColor) |
|
2523 HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_TEXT_FILL_COLOR, textFillColor, TextFillColor) |
|
2524 return; |
|
2525 } |
|
2526 if (isInitial) { |
|
2527 // The border/outline colors will just map to the invalid color |col| above. This will have the |
|
2528 // effect of forcing the use of the currentColor when it comes time to draw the borders (and of |
|
2529 // not painting the background since the color won't be valid). |
|
2530 if (id == CSS_PROP_COLOR) |
|
2531 col = RenderStyle::initialColor(); |
|
2532 } else { |
|
2533 if (!primitiveValue) |
|
2534 return; |
|
2535 col = getColorFromPrimitiveValue(primitiveValue); |
|
2536 } |
|
2537 |
|
2538 switch(id) { |
|
2539 case CSS_PROP_BACKGROUND_COLOR: |
|
2540 style->setBackgroundColor(col); break; |
|
2541 case CSS_PROP_BORDER_TOP_COLOR: |
|
2542 style->setBorderTopColor(col); break; |
|
2543 case CSS_PROP_BORDER_RIGHT_COLOR: |
|
2544 style->setBorderRightColor(col); break; |
|
2545 case CSS_PROP_BORDER_BOTTOM_COLOR: |
|
2546 style->setBorderBottomColor(col); break; |
|
2547 case CSS_PROP_BORDER_LEFT_COLOR: |
|
2548 style->setBorderLeftColor(col); break; |
|
2549 case CSS_PROP_COLOR: |
|
2550 style->setColor(col); break; |
|
2551 case CSS_PROP_OUTLINE_COLOR: |
|
2552 style->setOutlineColor(col); break; |
|
2553 case CSS_PROP__WEBKIT_COLUMN_RULE_COLOR: |
|
2554 style->setColumnRuleColor(col); |
|
2555 break; |
|
2556 case CSS_PROP__WEBKIT_TEXT_STROKE_COLOR: |
|
2557 style->setTextStrokeColor(col); |
|
2558 break; |
|
2559 case CSS_PROP__WEBKIT_TEXT_FILL_COLOR: |
|
2560 style->setTextFillColor(col); |
|
2561 break; |
|
2562 } |
|
2563 |
|
2564 return; |
|
2565 } |
|
2566 |
|
2567 // uri || inherit |
|
2568 case CSS_PROP_BACKGROUND_IMAGE: |
|
2569 HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value) |
|
2570 return; |
|
2571 case CSS_PROP_LIST_STYLE_IMAGE: |
|
2572 { |
|
2573 HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage) |
|
2574 if (!primitiveValue) |
|
2575 return; |
|
2576 style->setListStyleImage(static_cast<CSSImageValue*>(primitiveValue)->image(element->document()->docLoader())); |
|
2577 return; |
|
2578 } |
|
2579 |
|
2580 // length |
|
2581 case CSS_PROP_BORDER_TOP_WIDTH: |
|
2582 case CSS_PROP_BORDER_RIGHT_WIDTH: |
|
2583 case CSS_PROP_BORDER_BOTTOM_WIDTH: |
|
2584 case CSS_PROP_BORDER_LEFT_WIDTH: |
|
2585 case CSS_PROP_OUTLINE_WIDTH: |
|
2586 case CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH: |
|
2587 { |
|
2588 if (isInherit) { |
|
2589 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth) |
|
2590 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth) |
|
2591 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth) |
|
2592 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth) |
|
2593 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth) |
|
2594 HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH, columnRuleWidth, ColumnRuleWidth) |
|
2595 return; |
|
2596 } |
|
2597 else if (isInitial) { |
|
2598 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth) |
|
2599 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth) |
|
2600 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth) |
|
2601 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth) |
|
2602 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth) |
|
2603 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH, ColumnRuleWidth, BorderWidth) |
|
2604 return; |
|
2605 } |
|
2606 |
|
2607 if(!primitiveValue) return; |
|
2608 short width = 3; |
|
2609 switch(primitiveValue->getIdent()) |
|
2610 { |
|
2611 case CSS_VAL_THIN: |
|
2612 width = 1; |
|
2613 break; |
|
2614 case CSS_VAL_MEDIUM: |
|
2615 width = 3; |
|
2616 break; |
|
2617 case CSS_VAL_THICK: |
|
2618 width = 5; |
|
2619 break; |
|
2620 case CSS_VAL_INVALID: |
|
2621 width = primitiveValue->computeLengthShort(style); |
|
2622 break; |
|
2623 default: |
|
2624 return; |
|
2625 } |
|
2626 |
|
2627 if(width < 0) return; |
|
2628 switch(id) |
|
2629 { |
|
2630 case CSS_PROP_BORDER_TOP_WIDTH: |
|
2631 style->setBorderTopWidth(width); |
|
2632 break; |
|
2633 case CSS_PROP_BORDER_RIGHT_WIDTH: |
|
2634 style->setBorderRightWidth(width); |
|
2635 break; |
|
2636 case CSS_PROP_BORDER_BOTTOM_WIDTH: |
|
2637 style->setBorderBottomWidth(width); |
|
2638 break; |
|
2639 case CSS_PROP_BORDER_LEFT_WIDTH: |
|
2640 style->setBorderLeftWidth(width); |
|
2641 break; |
|
2642 case CSS_PROP_OUTLINE_WIDTH: |
|
2643 style->setOutlineWidth(width); |
|
2644 break; |
|
2645 case CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH: |
|
2646 style->setColumnRuleWidth(width); |
|
2647 break; |
|
2648 default: |
|
2649 return; |
|
2650 } |
|
2651 return; |
|
2652 } |
|
2653 |
|
2654 case CSS_PROP_LETTER_SPACING: |
|
2655 case CSS_PROP_WORD_SPACING: |
|
2656 { |
|
2657 |
|
2658 if (isInherit) { |
|
2659 HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing) |
|
2660 HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing) |
|
2661 return; |
|
2662 } |
|
2663 else if (isInitial) { |
|
2664 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing) |
|
2665 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing) |
|
2666 return; |
|
2667 } |
|
2668 |
|
2669 int width = 0; |
|
2670 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NORMAL){ |
|
2671 width = 0; |
|
2672 } else { |
|
2673 if(!primitiveValue) return; |
|
2674 width = primitiveValue->computeLengthInt(style); |
|
2675 } |
|
2676 switch(id) |
|
2677 { |
|
2678 case CSS_PROP_LETTER_SPACING: |
|
2679 style->setLetterSpacing(width); |
|
2680 break; |
|
2681 case CSS_PROP_WORD_SPACING: |
|
2682 style->setWordSpacing(width); |
|
2683 break; |
|
2684 // ### needs the definitions in renderstyle |
|
2685 default: break; |
|
2686 } |
|
2687 return; |
|
2688 } |
|
2689 |
|
2690 case CSS_PROP_WORD_BREAK: { |
|
2691 HANDLE_INHERIT_AND_INITIAL(wordBreak, WordBreak) |
|
2692 |
|
2693 EWordBreak b; |
|
2694 switch (primitiveValue->getIdent()) { |
|
2695 case CSS_VAL_BREAK_ALL: |
|
2696 b = BreakAllWordBreak; |
|
2697 break; |
|
2698 case CSS_VAL_BREAK_WORD: |
|
2699 b = BreakWordBreak; |
|
2700 break; |
|
2701 case CSS_VAL_NORMAL: |
|
2702 default: |
|
2703 b = NormalWordBreak; |
|
2704 break; |
|
2705 } |
|
2706 style->setWordBreak(b); |
|
2707 return; |
|
2708 } |
|
2709 |
|
2710 case CSS_PROP_WORD_WRAP: { |
|
2711 HANDLE_INHERIT_AND_INITIAL(wordWrap, WordWrap) |
|
2712 |
|
2713 EWordWrap s; |
|
2714 switch(primitiveValue->getIdent()) { |
|
2715 case CSS_VAL_BREAK_WORD: |
|
2716 s = BreakWordWrap; |
|
2717 break; |
|
2718 case CSS_VAL_NORMAL: |
|
2719 default: |
|
2720 s = NormalWordWrap; |
|
2721 break; |
|
2722 } |
|
2723 |
|
2724 style->setWordWrap(s); |
|
2725 return; |
|
2726 } |
|
2727 |
|
2728 case CSS_PROP__WEBKIT_NBSP_MODE: |
|
2729 { |
|
2730 HANDLE_INHERIT_AND_INITIAL(nbspMode, NBSPMode) |
|
2731 |
|
2732 if (!primitiveValue->getIdent()) return; |
|
2733 |
|
2734 ENBSPMode m; |
|
2735 switch(primitiveValue->getIdent()) { |
|
2736 case CSS_VAL_SPACE: |
|
2737 m = SPACE; |
|
2738 break; |
|
2739 case CSS_VAL_NORMAL: |
|
2740 default: |
|
2741 m = NBNORMAL; |
|
2742 break; |
|
2743 } |
|
2744 style->setNBSPMode(m); |
|
2745 return; |
|
2746 } |
|
2747 |
|
2748 case CSS_PROP__WEBKIT_LINE_BREAK: |
|
2749 { |
|
2750 HANDLE_INHERIT_AND_INITIAL(khtmlLineBreak, KHTMLLineBreak) |
|
2751 |
|
2752 if (!primitiveValue->getIdent()) return; |
|
2753 |
|
2754 EKHTMLLineBreak b; |
|
2755 switch(primitiveValue->getIdent()) { |
|
2756 case CSS_VAL_AFTER_WHITE_SPACE: |
|
2757 b = AFTER_WHITE_SPACE; |
|
2758 break; |
|
2759 case CSS_VAL_NORMAL: |
|
2760 default: |
|
2761 b = LBNORMAL; |
|
2762 break; |
|
2763 } |
|
2764 style->setKHTMLLineBreak(b); |
|
2765 return; |
|
2766 } |
|
2767 |
|
2768 case CSS_PROP__WEBKIT_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR: |
|
2769 { |
|
2770 HANDLE_INHERIT_AND_INITIAL(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor) |
|
2771 |
|
2772 if (!primitiveValue->getIdent()) return; |
|
2773 |
|
2774 EMatchNearestMailBlockquoteColor c; |
|
2775 switch(primitiveValue->getIdent()) { |
|
2776 case CSS_VAL_NORMAL: |
|
2777 c = BCNORMAL; |
|
2778 break; |
|
2779 case CSS_VAL_MATCH: |
|
2780 default: |
|
2781 c = MATCH; |
|
2782 break; |
|
2783 } |
|
2784 style->setMatchNearestMailBlockquoteColor(c); |
|
2785 return; |
|
2786 } |
|
2787 |
|
2788 case CSS_PROP_RESIZE: |
|
2789 { |
|
2790 HANDLE_INHERIT_AND_INITIAL(resize, Resize) |
|
2791 |
|
2792 if (!primitiveValue->getIdent()) return; |
|
2793 |
|
2794 EResize r = RESIZE_NONE; |
|
2795 switch(primitiveValue->getIdent()) { |
|
2796 case CSS_VAL_BOTH: |
|
2797 r = RESIZE_BOTH; |
|
2798 break; |
|
2799 case CSS_VAL_HORIZONTAL: |
|
2800 r = RESIZE_HORIZONTAL; |
|
2801 break; |
|
2802 case CSS_VAL_VERTICAL: |
|
2803 r = RESIZE_VERTICAL; |
|
2804 break; |
|
2805 case CSS_VAL_AUTO: |
|
2806 if (Settings* settings = m_document->settings()) |
|
2807 r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE; |
|
2808 break; |
|
2809 case CSS_VAL_NONE: |
|
2810 default: |
|
2811 r = RESIZE_NONE; |
|
2812 break; |
|
2813 } |
|
2814 style->setResize(r); |
|
2815 return; |
|
2816 } |
|
2817 |
|
2818 // length, percent |
|
2819 case CSS_PROP_MAX_WIDTH: |
|
2820 // +none +inherit |
|
2821 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) |
|
2822 apply = true; |
|
2823 case CSS_PROP_TOP: |
|
2824 case CSS_PROP_LEFT: |
|
2825 case CSS_PROP_RIGHT: |
|
2826 case CSS_PROP_BOTTOM: |
|
2827 case CSS_PROP_WIDTH: |
|
2828 case CSS_PROP_MIN_WIDTH: |
|
2829 case CSS_PROP_MARGIN_TOP: |
|
2830 case CSS_PROP_MARGIN_RIGHT: |
|
2831 case CSS_PROP_MARGIN_BOTTOM: |
|
2832 case CSS_PROP_MARGIN_LEFT: |
|
2833 // +inherit +auto |
|
2834 if (id == CSS_PROP_WIDTH || id == CSS_PROP_MIN_WIDTH || id == CSS_PROP_MAX_WIDTH) { |
|
2835 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) { |
|
2836 l = Length(Intrinsic); |
|
2837 apply = true; |
|
2838 } |
|
2839 else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) { |
|
2840 l = Length(MinIntrinsic); |
|
2841 apply = true; |
|
2842 } |
|
2843 } |
|
2844 if (id != CSS_PROP_MAX_WIDTH && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO) |
|
2845 apply = true; |
|
2846 case CSS_PROP_PADDING_TOP: |
|
2847 case CSS_PROP_PADDING_RIGHT: |
|
2848 case CSS_PROP_PADDING_BOTTOM: |
|
2849 case CSS_PROP_PADDING_LEFT: |
|
2850 case CSS_PROP_TEXT_INDENT: |
|
2851 // +inherit |
|
2852 { |
|
2853 if (isInherit) { |
|
2854 HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth) |
|
2855 HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom) |
|
2856 HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top) |
|
2857 HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left) |
|
2858 HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right) |
|
2859 HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width) |
|
2860 HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth) |
|
2861 HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop) |
|
2862 HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight) |
|
2863 HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom) |
|
2864 HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft) |
|
2865 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop) |
|
2866 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight) |
|
2867 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom) |
|
2868 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft) |
|
2869 HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent) |
|
2870 return; |
|
2871 } |
|
2872 else if (isInitial) { |
|
2873 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize) |
|
2874 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset) |
|
2875 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset) |
|
2876 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset) |
|
2877 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset) |
|
2878 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size) |
|
2879 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize) |
|
2880 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding) |
|
2881 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding) |
|
2882 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding) |
|
2883 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding) |
|
2884 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin) |
|
2885 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin) |
|
2886 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin) |
|
2887 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin) |
|
2888 HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent) |
|
2889 return; |
|
2890 } |
|
2891 |
|
2892 if (primitiveValue && !apply) { |
|
2893 int type = primitiveValue->primitiveType(); |
|
2894 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) |
|
2895 // Handle our quirky margin units if we have them. |
|
2896 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed, |
|
2897 primitiveValue->isQuirkValue()); |
|
2898 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
2899 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
2900 else |
|
2901 return; |
|
2902 if (id == CSS_PROP_PADDING_LEFT || id == CSS_PROP_PADDING_RIGHT || |
|
2903 id == CSS_PROP_PADDING_TOP || id == CSS_PROP_PADDING_BOTTOM) |
|
2904 // Padding can't be negative |
|
2905 apply = !((l.isFixed() || l.isPercent()) && l.calcValue(100) < 0); |
|
2906 else |
|
2907 apply = true; |
|
2908 } |
|
2909 if(!apply) return; |
|
2910 switch(id) |
|
2911 { |
|
2912 case CSS_PROP_MAX_WIDTH: |
|
2913 style->setMaxWidth(l); break; |
|
2914 case CSS_PROP_BOTTOM: |
|
2915 style->setBottom(l); break; |
|
2916 case CSS_PROP_TOP: |
|
2917 style->setTop(l); break; |
|
2918 case CSS_PROP_LEFT: |
|
2919 style->setLeft(l); break; |
|
2920 case CSS_PROP_RIGHT: |
|
2921 style->setRight(l); break; |
|
2922 case CSS_PROP_WIDTH: |
|
2923 style->setWidth(l); break; |
|
2924 case CSS_PROP_MIN_WIDTH: |
|
2925 style->setMinWidth(l); break; |
|
2926 case CSS_PROP_PADDING_TOP: |
|
2927 style->setPaddingTop(l); break; |
|
2928 case CSS_PROP_PADDING_RIGHT: |
|
2929 style->setPaddingRight(l); break; |
|
2930 case CSS_PROP_PADDING_BOTTOM: |
|
2931 style->setPaddingBottom(l); break; |
|
2932 case CSS_PROP_PADDING_LEFT: |
|
2933 style->setPaddingLeft(l); break; |
|
2934 case CSS_PROP_MARGIN_TOP: |
|
2935 style->setMarginTop(l); break; |
|
2936 case CSS_PROP_MARGIN_RIGHT: |
|
2937 style->setMarginRight(l); break; |
|
2938 case CSS_PROP_MARGIN_BOTTOM: |
|
2939 style->setMarginBottom(l); break; |
|
2940 case CSS_PROP_MARGIN_LEFT: |
|
2941 style->setMarginLeft(l); break; |
|
2942 case CSS_PROP_TEXT_INDENT: |
|
2943 style->setTextIndent(l); break; |
|
2944 default: break; |
|
2945 } |
|
2946 return; |
|
2947 } |
|
2948 |
|
2949 case CSS_PROP_MAX_HEIGHT: |
|
2950 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) { |
|
2951 l = Length(undefinedLength, Fixed); |
|
2952 apply = true; |
|
2953 } |
|
2954 case CSS_PROP_HEIGHT: |
|
2955 case CSS_PROP_MIN_HEIGHT: |
|
2956 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) { |
|
2957 l = Length(Intrinsic); |
|
2958 apply = true; |
|
2959 } else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) { |
|
2960 l = Length(MinIntrinsic); |
|
2961 apply = true; |
|
2962 } else if (id != CSS_PROP_MAX_HEIGHT && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO) |
|
2963 apply = true; |
|
2964 if (isInherit) { |
|
2965 HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight) |
|
2966 HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height) |
|
2967 HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight) |
|
2968 return; |
|
2969 } |
|
2970 if (isInitial) { |
|
2971 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize) |
|
2972 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size) |
|
2973 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize) |
|
2974 return; |
|
2975 } |
|
2976 |
|
2977 if (primitiveValue && !apply) { |
|
2978 unsigned short type = primitiveValue->primitiveType(); |
|
2979 if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) |
|
2980 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed); |
|
2981 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
2982 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
2983 else |
|
2984 return; |
|
2985 apply = true; |
|
2986 } |
|
2987 if (apply) |
|
2988 switch (id) { |
|
2989 case CSS_PROP_MAX_HEIGHT: |
|
2990 style->setMaxHeight(l); |
|
2991 break; |
|
2992 case CSS_PROP_HEIGHT: |
|
2993 style->setHeight(l); |
|
2994 break; |
|
2995 case CSS_PROP_MIN_HEIGHT: |
|
2996 style->setMinHeight(l); |
|
2997 break; |
|
2998 } |
|
2999 return; |
|
3000 |
|
3001 case CSS_PROP_VERTICAL_ALIGN: |
|
3002 HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign) |
|
3003 if (!primitiveValue) return; |
|
3004 if (primitiveValue->getIdent()) { |
|
3005 EVerticalAlign align; |
|
3006 |
|
3007 switch(primitiveValue->getIdent()) |
|
3008 { |
|
3009 case CSS_VAL_TOP: |
|
3010 align = TOP; break; |
|
3011 case CSS_VAL_BOTTOM: |
|
3012 align = BOTTOM; break; |
|
3013 case CSS_VAL_MIDDLE: |
|
3014 align = MIDDLE; break; |
|
3015 case CSS_VAL_BASELINE: |
|
3016 align = BASELINE; break; |
|
3017 case CSS_VAL_TEXT_BOTTOM: |
|
3018 align = TEXT_BOTTOM; break; |
|
3019 case CSS_VAL_TEXT_TOP: |
|
3020 align = TEXT_TOP; break; |
|
3021 case CSS_VAL_SUB: |
|
3022 align = SUB; break; |
|
3023 case CSS_VAL_SUPER: |
|
3024 align = SUPER; break; |
|
3025 case CSS_VAL__WEBKIT_BASELINE_MIDDLE: |
|
3026 align = BASELINE_MIDDLE; break; |
|
3027 default: |
|
3028 return; |
|
3029 } |
|
3030 style->setVerticalAlign(align); |
|
3031 return; |
|
3032 } else { |
|
3033 int type = primitiveValue->primitiveType(); |
|
3034 Length l; |
|
3035 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) |
|
3036 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed); |
|
3037 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
3038 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
3039 |
|
3040 style->setVerticalAlign(LENGTH); |
|
3041 style->setVerticalAlignLength(l); |
|
3042 } |
|
3043 return; |
|
3044 |
|
3045 case CSS_PROP_FONT_SIZE: |
|
3046 { |
|
3047 FontDescription fontDescription = style->fontDescription(); |
|
3048 fontDescription.setKeywordSize(0); |
|
3049 bool familyIsFixed = fontDescription.genericFamily() == FontDescription::MonospaceFamily; |
|
3050 float oldSize = 0; |
|
3051 float size = 0; |
|
3052 |
|
3053 bool parentIsAbsoluteSize = false; |
|
3054 if (parentNode) { |
|
3055 oldSize = parentStyle->fontDescription().specifiedSize(); |
|
3056 parentIsAbsoluteSize = parentStyle->fontDescription().isAbsoluteSize(); |
|
3057 } |
|
3058 |
|
3059 if (isInherit) { |
|
3060 size = oldSize; |
|
3061 if (parentNode) |
|
3062 fontDescription.setKeywordSize(parentStyle->fontDescription().keywordSize()); |
|
3063 } else if (isInitial) { |
|
3064 size = fontSizeForKeyword(CSS_VAL_MEDIUM, style->htmlHacks(), familyIsFixed); |
|
3065 fontDescription.setKeywordSize(CSS_VAL_MEDIUM - CSS_VAL_XX_SMALL + 1); |
|
3066 } else if (primitiveValue->getIdent()) { |
|
3067 // Keywords are being used. |
|
3068 switch (primitiveValue->getIdent()) { |
|
3069 case CSS_VAL_XX_SMALL: |
|
3070 case CSS_VAL_X_SMALL: |
|
3071 case CSS_VAL_SMALL: |
|
3072 case CSS_VAL_MEDIUM: |
|
3073 case CSS_VAL_LARGE: |
|
3074 case CSS_VAL_X_LARGE: |
|
3075 case CSS_VAL_XX_LARGE: |
|
3076 case CSS_VAL__WEBKIT_XXX_LARGE: |
|
3077 size = fontSizeForKeyword(primitiveValue->getIdent(), style->htmlHacks(), familyIsFixed); |
|
3078 fontDescription.setKeywordSize(primitiveValue->getIdent() - CSS_VAL_XX_SMALL + 1); |
|
3079 break; |
|
3080 case CSS_VAL_LARGER: |
|
3081 size = largerFontSize(oldSize, style->htmlHacks()); |
|
3082 break; |
|
3083 case CSS_VAL_SMALLER: |
|
3084 size = smallerFontSize(oldSize, style->htmlHacks()); |
|
3085 break; |
|
3086 default: |
|
3087 return; |
|
3088 } |
|
3089 |
|
3090 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize && |
|
3091 (primitiveValue->getIdent() == CSS_VAL_LARGER || |
|
3092 primitiveValue->getIdent() == CSS_VAL_SMALLER)); |
|
3093 } else { |
|
3094 int type = primitiveValue->primitiveType(); |
|
3095 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize || |
|
3096 (type != CSSPrimitiveValue::CSS_PERCENTAGE && |
|
3097 type != CSSPrimitiveValue::CSS_EMS && |
|
3098 type != CSSPrimitiveValue::CSS_EXS)); |
|
3099 if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) |
|
3100 size = primitiveValue->computeLengthFloat(parentStyle, false); |
|
3101 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
3102 size = (primitiveValue->getFloatValue() * oldSize) / 100.0f; |
|
3103 else |
|
3104 return; |
|
3105 } |
|
3106 |
|
3107 if (size < 0) |
|
3108 return; |
|
3109 |
|
3110 setFontSize(fontDescription, size); |
|
3111 if (style->setFontDescription(fontDescription)) |
|
3112 fontDirty = true; |
|
3113 return; |
|
3114 } |
|
3115 |
|
3116 case CSS_PROP_Z_INDEX: { |
|
3117 if (isInherit) { |
|
3118 if (parentStyle->hasAutoZIndex()) |
|
3119 style->setHasAutoZIndex(); |
|
3120 else |
|
3121 style->setZIndex(parentStyle->zIndex()); |
|
3122 return; |
|
3123 } else if (isInitial || primitiveValue->getIdent() == CSS_VAL_AUTO) { |
|
3124 style->setHasAutoZIndex(); |
|
3125 return; |
|
3126 } |
|
3127 |
|
3128 // FIXME: Should clamp all sorts of other integer properties too. |
|
3129 const double minIntAsDouble = INT_MIN; |
|
3130 const double maxIntAsDouble = INT_MAX; |
|
3131 style->setZIndex(static_cast<int>(max(minIntAsDouble, min(primitiveValue->getDoubleValue(), maxIntAsDouble)))); |
|
3132 return; |
|
3133 } |
|
3134 case CSS_PROP_WIDOWS: |
|
3135 { |
|
3136 HANDLE_INHERIT_AND_INITIAL(widows, Widows) |
|
3137 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
3138 return; |
|
3139 style->setWidows(primitiveValue->getIntValue()); |
|
3140 return; |
|
3141 } |
|
3142 |
|
3143 case CSS_PROP_ORPHANS: |
|
3144 { |
|
3145 HANDLE_INHERIT_AND_INITIAL(orphans, Orphans) |
|
3146 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
3147 return; |
|
3148 style->setOrphans(primitiveValue->getIntValue()); |
|
3149 return; |
|
3150 } |
|
3151 |
|
3152 // length, percent, number |
|
3153 case CSS_PROP_LINE_HEIGHT: |
|
3154 { |
|
3155 HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight) |
|
3156 if(!primitiveValue) return; |
|
3157 Length lineHeight; |
|
3158 int type = primitiveValue->primitiveType(); |
|
3159 if (primitiveValue->getIdent() == CSS_VAL_NORMAL) |
|
3160 lineHeight = Length(-100.0, Percent); |
|
3161 else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) { |
|
3162 double multiplier = 1.0; |
|
3163 // Scale for the font zoom factor only for types other than "em" and "ex", since those are |
|
3164 // already based on the font size. |
|
3165 if (type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && style->textSizeAdjust() && m_document->frame()) { |
|
3166 multiplier = m_document->frame()->zoomFactor() / 100.0; |
|
3167 } |
|
3168 lineHeight = Length(primitiveValue->computeLengthIntForLength(style, multiplier), Fixed); |
|
3169 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
3170 lineHeight = Length((style->fontSize() * primitiveValue->getIntValue()) / 100, Fixed); |
|
3171 else if (type == CSSPrimitiveValue::CSS_NUMBER) |
|
3172 lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent); |
|
3173 else |
|
3174 return; |
|
3175 |
|
3176 #if PLATFORM(SYMBIAN) |
|
3177 if (lineHeight.type() == Fixed) |
|
3178 lineHeight.setValue(lineHeight.value()-1); |
|
3179 #endif |
|
3180 style->setLineHeight(lineHeight); |
|
3181 |
|
3182 return; |
|
3183 } |
|
3184 |
|
3185 // string |
|
3186 case CSS_PROP_TEXT_ALIGN: |
|
3187 { |
|
3188 HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign) |
|
3189 if (!primitiveValue) return; |
|
3190 if (primitiveValue->getIdent()) |
|
3191 style->setTextAlign((ETextAlign) (primitiveValue->getIdent() - CSS_VAL__WEBKIT_AUTO)); |
|
3192 return; |
|
3193 } |
|
3194 |
|
3195 // rect |
|
3196 case CSS_PROP_CLIP: |
|
3197 { |
|
3198 Length top; |
|
3199 Length right; |
|
3200 Length bottom; |
|
3201 Length left; |
|
3202 bool hasClip = true; |
|
3203 if (isInherit) { |
|
3204 if (parentStyle->hasClip()) { |
|
3205 top = parentStyle->clipTop(); |
|
3206 right = parentStyle->clipRight(); |
|
3207 bottom = parentStyle->clipBottom(); |
|
3208 left = parentStyle->clipLeft(); |
|
3209 } |
|
3210 else { |
|
3211 hasClip = false; |
|
3212 top = right = bottom = left = Length(); |
|
3213 } |
|
3214 } else if (isInitial) { |
|
3215 hasClip = false; |
|
3216 top = right = bottom = left = Length(); |
|
3217 } else if (!primitiveValue) { |
|
3218 return; |
|
3219 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) { |
|
3220 Rect* rect = primitiveValue->getRectValue(); |
|
3221 if (!rect) |
|
3222 return; |
|
3223 top = convertToLength(rect->top(), style); |
|
3224 right = convertToLength(rect->right(), style); |
|
3225 bottom = convertToLength(rect->bottom(), style); |
|
3226 left = convertToLength(rect->left(), style); |
|
3227 |
|
3228 } else if (primitiveValue->getIdent() != CSS_VAL_AUTO) { |
|
3229 return; |
|
3230 } |
|
3231 style->setClip(top, right, bottom, left); |
|
3232 style->setHasClip(hasClip); |
|
3233 |
|
3234 // rect, ident |
|
3235 return; |
|
3236 } |
|
3237 |
|
3238 // lists |
|
3239 case CSS_PROP_CONTENT: |
|
3240 // list of string, uri, counter, attr, i |
|
3241 { |
|
3242 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This |
|
3243 // note is a reminder that eventually "inherit" needs to be supported. |
|
3244 |
|
3245 if (isInitial) { |
|
3246 style->clearContent(); |
|
3247 return; |
|
3248 } |
|
3249 |
|
3250 if (!value->isValueList()) |
|
3251 return; |
|
3252 |
|
3253 CSSValueList* list = static_cast<CSSValueList*>(value); |
|
3254 int len = list->length(); |
|
3255 |
|
3256 bool didSet = false; |
|
3257 for (int i = 0; i < len; i++) { |
|
3258 CSSValue* item = list->item(i); |
|
3259 if (!item->isPrimitiveValue()) |
|
3260 continue; |
|
3261 |
|
3262 CSSPrimitiveValue* val = static_cast<CSSPrimitiveValue*>(item); |
|
3263 switch (val->primitiveType()) { |
|
3264 case CSSPrimitiveValue::CSS_STRING: |
|
3265 style->setContent(val->getStringValue().impl(), didSet); |
|
3266 didSet = true; |
|
3267 break; |
|
3268 case CSSPrimitiveValue::CSS_ATTR: { |
|
3269 // FIXME: Can a namespace be specified for an attr(foo)? |
|
3270 if (style->styleType() == RenderStyle::NOPSEUDO) |
|
3271 style->setUnique(); |
|
3272 else |
|
3273 parentStyle->setUnique(); |
|
3274 QualifiedName attr(nullAtom, val->getStringValue().impl(), nullAtom); |
|
3275 style->setContent(element->getAttribute(attr).impl(), didSet); |
|
3276 didSet = true; |
|
3277 // register the fact that the attribute value affects the style |
|
3278 m_selectorAttrs.add(attr.localName().impl()); |
|
3279 break; |
|
3280 } |
|
3281 case CSSPrimitiveValue::CSS_URI: { |
|
3282 CSSImageValue *image = static_cast<CSSImageValue*>(val); |
|
3283 style->setContent(image->image(element->document()->docLoader()), didSet); |
|
3284 didSet = true; |
|
3285 break; |
|
3286 } |
|
3287 case CSSPrimitiveValue::CSS_COUNTER: { |
|
3288 Counter* counterValue = val->getCounterValue(); |
|
3289 CounterContent* counter = new CounterContent(counterValue->identifier(), |
|
3290 (EListStyleType)counterValue->listStyleNumber(), counterValue->separator()); |
|
3291 style->setContent(counter, didSet); |
|
3292 didSet = true; |
|
3293 } |
|
3294 } |
|
3295 } |
|
3296 if (!didSet) |
|
3297 style->clearContent(); |
|
3298 return; |
|
3299 } |
|
3300 |
|
3301 case CSS_PROP_COUNTER_INCREMENT: |
|
3302 applyCounterList(style, value->isValueList() ? static_cast<CSSValueList*>(value) : 0, false); |
|
3303 return; |
|
3304 case CSS_PROP_COUNTER_RESET: |
|
3305 applyCounterList(style, value->isValueList() ? static_cast<CSSValueList*>(value) : 0, true); |
|
3306 return; |
|
3307 |
|
3308 case CSS_PROP_FONT_FAMILY: { |
|
3309 // list of strings and ids |
|
3310 if (isInherit) { |
|
3311 FontDescription parentFontDescription = parentStyle->fontDescription(); |
|
3312 FontDescription fontDescription = style->fontDescription(); |
|
3313 fontDescription.setGenericFamily(parentFontDescription.genericFamily()); |
|
3314 fontDescription.setFamily(parentFontDescription.firstFamily()); |
|
3315 if (style->setFontDescription(fontDescription)) |
|
3316 fontDirty = true; |
|
3317 return; |
|
3318 } |
|
3319 else if (isInitial) { |
|
3320 FontDescription initialDesc = FontDescription(); |
|
3321 FontDescription fontDescription = style->fontDescription(); |
|
3322 // We need to adjust the size to account for the generic family change from monospace |
|
3323 // to non-monospace. |
|
3324 if (fontDescription.keywordSize() && fontDescription.genericFamily() == FontDescription::MonospaceFamily) |
|
3325 setFontSize(fontDescription, fontSizeForKeyword(CSS_VAL_XX_SMALL + fontDescription.keywordSize() - 1, style->htmlHacks(), false)); |
|
3326 fontDescription.setGenericFamily(initialDesc.genericFamily()); |
|
3327 fontDescription.setFamily(initialDesc.firstFamily()); |
|
3328 if (style->setFontDescription(fontDescription)) |
|
3329 fontDirty = true; |
|
3330 return; |
|
3331 } |
|
3332 |
|
3333 if (!value->isValueList()) return; |
|
3334 FontDescription fontDescription = style->fontDescription(); |
|
3335 CSSValueList *list = static_cast<CSSValueList*>(value); |
|
3336 int len = list->length(); |
|
3337 FontFamily& firstFamily = fontDescription.firstFamily(); |
|
3338 FontFamily *currFamily = 0; |
|
3339 |
|
3340 // Before mapping in a new font-family property, we should reset the generic family. |
|
3341 bool oldFamilyIsMonospace = fontDescription.genericFamily() == FontDescription::MonospaceFamily; |
|
3342 fontDescription.setGenericFamily(FontDescription::NoFamily); |
|
3343 |
|
3344 for(int i = 0; i < len; i++) { |
|
3345 CSSValue *item = list->item(i); |
|
3346 if(!item->isPrimitiveValue()) continue; |
|
3347 CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item); |
|
3348 AtomicString face; |
|
3349 Settings* settings = m_document->settings(); |
|
3350 if (val->primitiveType() == CSSPrimitiveValue::CSS_STRING) |
|
3351 face = static_cast<FontFamilyValue*>(val)->fontName(); |
|
3352 else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) { |
|
3353 switch (val->getIdent()) { |
|
3354 case CSS_VAL__WEBKIT_BODY: |
|
3355 face = settings->standardFontFamily(); |
|
3356 break; |
|
3357 case CSS_VAL_SERIF: |
|
3358 face = settings->serifFontFamily(); |
|
3359 fontDescription.setGenericFamily(FontDescription::SerifFamily); |
|
3360 break; |
|
3361 case CSS_VAL_SANS_SERIF: |
|
3362 face = settings->sansSerifFontFamily(); |
|
3363 fontDescription.setGenericFamily(FontDescription::SansSerifFamily); |
|
3364 break; |
|
3365 case CSS_VAL_CURSIVE: |
|
3366 face = settings->cursiveFontFamily(); |
|
3367 fontDescription.setGenericFamily(FontDescription::CursiveFamily); |
|
3368 break; |
|
3369 case CSS_VAL_FANTASY: |
|
3370 face = settings->fantasyFontFamily(); |
|
3371 fontDescription.setGenericFamily(FontDescription::FantasyFamily); |
|
3372 break; |
|
3373 case CSS_VAL_MONOSPACE: |
|
3374 face = settings->fixedFontFamily(); |
|
3375 fontDescription.setGenericFamily(FontDescription::MonospaceFamily); |
|
3376 break; |
|
3377 } |
|
3378 } |
|
3379 |
|
3380 if (!face.isEmpty()) { |
|
3381 if (!currFamily) { |
|
3382 // Filling in the first family. |
|
3383 firstFamily.setFamily(face); |
|
3384 currFamily = &firstFamily; |
|
3385 } |
|
3386 else { |
|
3387 FontFamily *newFamily = new FontFamily; |
|
3388 newFamily->setFamily(face); |
|
3389 currFamily->appendFamily(newFamily); |
|
3390 currFamily = newFamily; |
|
3391 } |
|
3392 |
|
3393 if (fontDescription.keywordSize() && (fontDescription.genericFamily() == FontDescription::MonospaceFamily) != oldFamilyIsMonospace) |
|
3394 setFontSize(fontDescription, fontSizeForKeyword(CSS_VAL_XX_SMALL + fontDescription.keywordSize() - 1, style->htmlHacks(), !oldFamilyIsMonospace)); |
|
3395 |
|
3396 if (style->setFontDescription(fontDescription)) |
|
3397 fontDirty = true; |
|
3398 } |
|
3399 } |
|
3400 return; |
|
3401 } |
|
3402 case CSS_PROP_TEXT_DECORATION: { |
|
3403 // list of ident |
|
3404 HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration) |
|
3405 int t = RenderStyle::initialTextDecoration(); |
|
3406 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) { |
|
3407 // do nothing |
|
3408 } else { |
|
3409 if(!value->isValueList()) return; |
|
3410 CSSValueList *list = static_cast<CSSValueList*>(value); |
|
3411 int len = list->length(); |
|
3412 for(int i = 0; i < len; i++) |
|
3413 { |
|
3414 CSSValue *item = list->item(i); |
|
3415 if(!item->isPrimitiveValue()) continue; |
|
3416 primitiveValue = static_cast<CSSPrimitiveValue*>(item); |
|
3417 switch(primitiveValue->getIdent()) |
|
3418 { |
|
3419 case CSS_VAL_NONE: |
|
3420 t = TDNONE; break; |
|
3421 case CSS_VAL_UNDERLINE: |
|
3422 t |= UNDERLINE; break; |
|
3423 case CSS_VAL_OVERLINE: |
|
3424 t |= OVERLINE; break; |
|
3425 case CSS_VAL_LINE_THROUGH: |
|
3426 t |= LINE_THROUGH; break; |
|
3427 case CSS_VAL_BLINK: |
|
3428 t |= BLINK; break; |
|
3429 default: |
|
3430 return; |
|
3431 } |
|
3432 } |
|
3433 } |
|
3434 |
|
3435 style->setTextDecoration(t); |
|
3436 return; |
|
3437 } |
|
3438 |
|
3439 // shorthand properties |
|
3440 case CSS_PROP_BACKGROUND: |
|
3441 if (isInitial) { |
|
3442 style->clearBackgroundLayers(); |
|
3443 style->setBackgroundColor(Color()); |
|
3444 return; |
|
3445 } |
|
3446 else if (isInherit) { |
|
3447 style->inheritBackgroundLayers(*parentStyle->backgroundLayers()); |
|
3448 style->setBackgroundColor(parentStyle->backgroundColor()); |
|
3449 } |
|
3450 return; |
|
3451 case CSS_PROP_BORDER: |
|
3452 case CSS_PROP_BORDER_STYLE: |
|
3453 case CSS_PROP_BORDER_WIDTH: |
|
3454 case CSS_PROP_BORDER_COLOR: |
|
3455 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR) |
|
3456 { |
|
3457 if (isInherit) { |
|
3458 style->setBorderTopColor(parentStyle->borderTopColor()); |
|
3459 style->setBorderBottomColor(parentStyle->borderBottomColor()); |
|
3460 style->setBorderLeftColor(parentStyle->borderLeftColor()); |
|
3461 style->setBorderRightColor(parentStyle->borderRightColor()); |
|
3462 } |
|
3463 else if (isInitial) { |
|
3464 style->setBorderTopColor(Color()); // Reset to invalid color so currentColor is used instead. |
|
3465 style->setBorderBottomColor(Color()); |
|
3466 style->setBorderLeftColor(Color()); |
|
3467 style->setBorderRightColor(Color()); |
|
3468 } |
|
3469 } |
|
3470 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE) |
|
3471 { |
|
3472 if (isInherit) { |
|
3473 style->setBorderTopStyle(parentStyle->borderTopStyle()); |
|
3474 style->setBorderBottomStyle(parentStyle->borderBottomStyle()); |
|
3475 style->setBorderLeftStyle(parentStyle->borderLeftStyle()); |
|
3476 style->setBorderRightStyle(parentStyle->borderRightStyle()); |
|
3477 } |
|
3478 else if (isInitial) { |
|
3479 style->setBorderTopStyle(RenderStyle::initialBorderStyle()); |
|
3480 style->setBorderBottomStyle(RenderStyle::initialBorderStyle()); |
|
3481 style->setBorderLeftStyle(RenderStyle::initialBorderStyle()); |
|
3482 style->setBorderRightStyle(RenderStyle::initialBorderStyle()); |
|
3483 } |
|
3484 } |
|
3485 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_WIDTH) |
|
3486 { |
|
3487 if (isInherit) { |
|
3488 style->setBorderTopWidth(parentStyle->borderTopWidth()); |
|
3489 style->setBorderBottomWidth(parentStyle->borderBottomWidth()); |
|
3490 style->setBorderLeftWidth(parentStyle->borderLeftWidth()); |
|
3491 style->setBorderRightWidth(parentStyle->borderRightWidth()); |
|
3492 } |
|
3493 else if (isInitial) { |
|
3494 style->setBorderTopWidth(RenderStyle::initialBorderWidth()); |
|
3495 style->setBorderBottomWidth(RenderStyle::initialBorderWidth()); |
|
3496 style->setBorderLeftWidth(RenderStyle::initialBorderWidth()); |
|
3497 style->setBorderRightWidth(RenderStyle::initialBorderWidth()); |
|
3498 } |
|
3499 } |
|
3500 return; |
|
3501 case CSS_PROP_BORDER_TOP: |
|
3502 if (isInherit) { |
|
3503 style->setBorderTopColor(parentStyle->borderTopColor()); |
|
3504 style->setBorderTopStyle(parentStyle->borderTopStyle()); |
|
3505 style->setBorderTopWidth(parentStyle->borderTopWidth()); |
|
3506 } |
|
3507 else if (isInitial) |
|
3508 style->resetBorderTop(); |
|
3509 return; |
|
3510 case CSS_PROP_BORDER_RIGHT: |
|
3511 if (isInherit) { |
|
3512 style->setBorderRightColor(parentStyle->borderRightColor()); |
|
3513 style->setBorderRightStyle(parentStyle->borderRightStyle()); |
|
3514 style->setBorderRightWidth(parentStyle->borderRightWidth()); |
|
3515 } |
|
3516 else if (isInitial) |
|
3517 style->resetBorderRight(); |
|
3518 return; |
|
3519 case CSS_PROP_BORDER_BOTTOM: |
|
3520 if (isInherit) { |
|
3521 style->setBorderBottomColor(parentStyle->borderBottomColor()); |
|
3522 style->setBorderBottomStyle(parentStyle->borderBottomStyle()); |
|
3523 style->setBorderBottomWidth(parentStyle->borderBottomWidth()); |
|
3524 } |
|
3525 else if (isInitial) |
|
3526 style->resetBorderBottom(); |
|
3527 return; |
|
3528 case CSS_PROP_BORDER_LEFT: |
|
3529 if (isInherit) { |
|
3530 style->setBorderLeftColor(parentStyle->borderLeftColor()); |
|
3531 style->setBorderLeftStyle(parentStyle->borderLeftStyle()); |
|
3532 style->setBorderLeftWidth(parentStyle->borderLeftWidth()); |
|
3533 } |
|
3534 else if (isInitial) |
|
3535 style->resetBorderLeft(); |
|
3536 return; |
|
3537 case CSS_PROP_MARGIN: |
|
3538 if (isInherit) { |
|
3539 style->setMarginTop(parentStyle->marginTop()); |
|
3540 style->setMarginBottom(parentStyle->marginBottom()); |
|
3541 style->setMarginLeft(parentStyle->marginLeft()); |
|
3542 style->setMarginRight(parentStyle->marginRight()); |
|
3543 } |
|
3544 else if (isInitial) |
|
3545 style->resetMargin(); |
|
3546 return; |
|
3547 case CSS_PROP_PADDING: |
|
3548 if (isInherit) { |
|
3549 style->setPaddingTop(parentStyle->paddingTop()); |
|
3550 style->setPaddingBottom(parentStyle->paddingBottom()); |
|
3551 style->setPaddingLeft(parentStyle->paddingLeft()); |
|
3552 style->setPaddingRight(parentStyle->paddingRight()); |
|
3553 } |
|
3554 else if (isInitial) |
|
3555 style->resetPadding(); |
|
3556 return; |
|
3557 case CSS_PROP_FONT: |
|
3558 if (isInherit) { |
|
3559 FontDescription fontDescription = parentStyle->fontDescription(); |
|
3560 style->setLineHeight(parentStyle->lineHeight()); |
|
3561 m_lineHeightValue = 0; |
|
3562 if (style->setFontDescription(fontDescription)) |
|
3563 fontDirty = true; |
|
3564 } else if (isInitial) { |
|
3565 FontDescription fontDescription; |
|
3566 fontDescription.setGenericFamily(FontDescription::StandardFamily); |
|
3567 style->setLineHeight(RenderStyle::initialLineHeight()); |
|
3568 m_lineHeightValue = 0; |
|
3569 if (style->setFontDescription(fontDescription)) |
|
3570 fontDirty = true; |
|
3571 } else if (primitiveValue) { |
|
3572 style->setLineHeight(RenderStyle::initialLineHeight()); |
|
3573 m_lineHeightValue = 0; |
|
3574 FontDescription fontDescription; |
|
3575 theme()->systemFont(primitiveValue->getIdent(), fontDescription); |
|
3576 // Double-check and see if the theme did anything. If not, don't bother updating the font. |
|
3577 if (fontDescription.isAbsoluteSize()) { |
|
3578 // Handle the zoom factor. |
|
3579 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription.isAbsoluteSize(), fontDescription.specifiedSize())); |
|
3580 if (style->setFontDescription(fontDescription)) |
|
3581 fontDirty = true; |
|
3582 } |
|
3583 } else if (value->isFontValue()) { |
|
3584 FontValue *font = static_cast<FontValue*>(value); |
|
3585 if (!font->style || !font->variant || !font->weight || |
|
3586 !font->size || !font->lineHeight || !font->family) |
|
3587 return; |
|
3588 applyProperty(CSS_PROP_FONT_STYLE, font->style.get()); |
|
3589 applyProperty(CSS_PROP_FONT_VARIANT, font->variant.get()); |
|
3590 applyProperty(CSS_PROP_FONT_WEIGHT, font->weight.get()); |
|
3591 applyProperty(CSS_PROP_FONT_SIZE, font->size.get()); |
|
3592 |
|
3593 m_lineHeightValue = font->lineHeight.get(); |
|
3594 applyProperty(CSS_PROP_FONT_FAMILY, font->family.get()); |
|
3595 } |
|
3596 return; |
|
3597 |
|
3598 case CSS_PROP_LIST_STYLE: |
|
3599 if (isInherit) { |
|
3600 style->setListStyleType(parentStyle->listStyleType()); |
|
3601 style->setListStyleImage(parentStyle->listStyleImage()); |
|
3602 style->setListStylePosition(parentStyle->listStylePosition()); |
|
3603 } |
|
3604 else if (isInitial) { |
|
3605 style->setListStyleType(RenderStyle::initialListStyleType()); |
|
3606 style->setListStyleImage(RenderStyle::initialListStyleImage()); |
|
3607 style->setListStylePosition(RenderStyle::initialListStylePosition()); |
|
3608 } |
|
3609 return; |
|
3610 case CSS_PROP_OUTLINE: |
|
3611 if (isInherit) { |
|
3612 style->setOutlineWidth(parentStyle->outlineWidth()); |
|
3613 style->setOutlineColor(parentStyle->outlineColor()); |
|
3614 style->setOutlineStyle(parentStyle->outlineStyle()); |
|
3615 } |
|
3616 else if (isInitial) |
|
3617 style->resetOutline(); |
|
3618 return; |
|
3619 |
|
3620 // CSS3 Properties |
|
3621 case CSS_PROP__WEBKIT_APPEARANCE: { |
|
3622 HANDLE_INHERIT_AND_INITIAL(appearance, Appearance) |
|
3623 if (!primitiveValue) break; |
|
3624 int id = primitiveValue->getIdent(); |
|
3625 EAppearance appearance; |
|
3626 if (id == CSS_VAL_NONE) |
|
3627 appearance = NoAppearance; |
|
3628 else |
|
3629 appearance = EAppearance(id - CSS_VAL_CHECKBOX + 1); |
|
3630 style->setAppearance(appearance); |
|
3631 return; |
|
3632 } |
|
3633 case CSS_PROP__WEBKIT_BINDING: { |
|
3634 #if ENABLE(XBL) |
|
3635 if (isInitial || (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)) { |
|
3636 style->deleteBindingURIs(); |
|
3637 return; |
|
3638 } |
|
3639 else if (isInherit) { |
|
3640 if (parentStyle->bindingURIs()) |
|
3641 style->inheritBindingURIs(parentStyle->bindingURIs()); |
|
3642 else |
|
3643 style->deleteBindingURIs(); |
|
3644 return; |
|
3645 } |
|
3646 |
|
3647 if (!value->isValueList()) return; |
|
3648 CSSValueList* list = static_cast<CSSValueList*>(value); |
|
3649 bool firstBinding = true; |
|
3650 for (unsigned int i = 0; i < list->length(); i++) { |
|
3651 CSSValue *item = list->item(i); |
|
3652 CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item); |
|
3653 if (val->primitiveType() == CSSPrimitiveValue::CSS_URI) { |
|
3654 if (firstBinding) { |
|
3655 firstBinding = false; |
|
3656 style->deleteBindingURIs(); |
|
3657 } |
|
3658 style->addBindingURI(val->getStringValue()); |
|
3659 } |
|
3660 } |
|
3661 #endif |
|
3662 return; |
|
3663 } |
|
3664 |
|
3665 case CSS_PROP__WEBKIT_BORDER_IMAGE: { |
|
3666 HANDLE_INHERIT_AND_INITIAL(borderImage, BorderImage) |
|
3667 BorderImage image; |
|
3668 if (primitiveValue) { |
|
3669 if (primitiveValue->getIdent() == CSS_VAL_NONE) |
|
3670 style->setBorderImage(image); |
|
3671 } else { |
|
3672 // Retrieve the border image value. |
|
3673 CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value); |
|
3674 |
|
3675 // Set the image (this kicks off the load). |
|
3676 image.m_image = borderImage->m_image->image(element->document()->docLoader()); |
|
3677 |
|
3678 // Set up a length box to represent our image slices. |
|
3679 LengthBox& l = image.m_slices; |
|
3680 Rect* r = borderImage->m_imageSliceRect.get(); |
|
3681 if (r->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
3682 l.top = Length(r->top()->getDoubleValue(), Percent); |
|
3683 else |
|
3684 l.top = Length(r->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); |
|
3685 if (r->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
3686 l.bottom = Length(r->bottom()->getDoubleValue(), Percent); |
|
3687 else |
|
3688 l.bottom = Length((int)r->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); |
|
3689 if (r->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
3690 l.left = Length(r->left()->getDoubleValue(), Percent); |
|
3691 else |
|
3692 l.left = Length(r->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); |
|
3693 if (r->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
3694 l.right = Length(r->right()->getDoubleValue(), Percent); |
|
3695 else |
|
3696 l.right = Length(r->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); |
|
3697 |
|
3698 // Set the appropriate rules for stretch/round/repeat of the slices |
|
3699 switch (borderImage->m_horizontalSizeRule) { |
|
3700 case CSS_VAL_STRETCH: |
|
3701 image.m_horizontalRule = BI_STRETCH; |
|
3702 break; |
|
3703 case CSS_VAL_ROUND: |
|
3704 image.m_horizontalRule = BI_ROUND; |
|
3705 break; |
|
3706 default: // CSS_VAL_REPEAT |
|
3707 image.m_horizontalRule = BI_REPEAT; |
|
3708 break; |
|
3709 } |
|
3710 |
|
3711 switch (borderImage->m_verticalSizeRule) { |
|
3712 case CSS_VAL_STRETCH: |
|
3713 image.m_verticalRule = BI_STRETCH; |
|
3714 break; |
|
3715 case CSS_VAL_ROUND: |
|
3716 image.m_verticalRule = BI_ROUND; |
|
3717 break; |
|
3718 default: // CSS_VAL_REPEAT |
|
3719 image.m_verticalRule = BI_REPEAT; |
|
3720 break; |
|
3721 } |
|
3722 |
|
3723 style->setBorderImage(image); |
|
3724 } |
|
3725 return; |
|
3726 } |
|
3727 |
|
3728 case CSS_PROP__WEBKIT_BORDER_RADIUS: |
|
3729 if (isInherit) { |
|
3730 style->setBorderTopLeftRadius(parentStyle->borderTopLeftRadius()); |
|
3731 style->setBorderTopRightRadius(parentStyle->borderTopRightRadius()); |
|
3732 style->setBorderBottomLeftRadius(parentStyle->borderBottomLeftRadius()); |
|
3733 style->setBorderBottomRightRadius(parentStyle->borderBottomRightRadius()); |
|
3734 return; |
|
3735 } |
|
3736 if (isInitial) { |
|
3737 style->resetBorderRadius(); |
|
3738 return; |
|
3739 } |
|
3740 // Fall through |
|
3741 case CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS: |
|
3742 case CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS: |
|
3743 case CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS: |
|
3744 case CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS: { |
|
3745 if (isInherit) { |
|
3746 HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS, borderTopLeftRadius, BorderTopLeftRadius) |
|
3747 HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS, borderTopRightRadius, BorderTopRightRadius) |
|
3748 HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS, borderBottomLeftRadius, BorderBottomLeftRadius) |
|
3749 HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS, borderBottomRightRadius, BorderBottomRightRadius) |
|
3750 return; |
|
3751 } |
|
3752 |
|
3753 if (isInitial) { |
|
3754 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS, BorderTopLeftRadius, BorderRadius) |
|
3755 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS, BorderTopRightRadius, BorderRadius) |
|
3756 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS, BorderBottomLeftRadius, BorderRadius) |
|
3757 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS, BorderBottomRightRadius, BorderRadius) |
|
3758 return; |
|
3759 } |
|
3760 |
|
3761 if (!primitiveValue) |
|
3762 return; |
|
3763 |
|
3764 Pair* pair = primitiveValue->getPairValue(); |
|
3765 if (!pair) |
|
3766 return; |
|
3767 |
|
3768 int width = pair->first()->computeLengthInt(style); |
|
3769 int height = pair->second()->computeLengthInt(style); |
|
3770 if (width < 0 || height < 0) |
|
3771 return; |
|
3772 |
|
3773 if (width == 0) |
|
3774 height = 0; // Null out the other value. |
|
3775 else if (height == 0) |
|
3776 width = 0; // Null out the other value. |
|
3777 |
|
3778 IntSize size(width, height); |
|
3779 switch (id) { |
|
3780 case CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS: |
|
3781 style->setBorderTopLeftRadius(size); |
|
3782 break; |
|
3783 case CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS: |
|
3784 style->setBorderTopRightRadius(size); |
|
3785 break; |
|
3786 case CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS: |
|
3787 style->setBorderBottomLeftRadius(size); |
|
3788 break; |
|
3789 case CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS: |
|
3790 style->setBorderBottomRightRadius(size); |
|
3791 break; |
|
3792 default: |
|
3793 style->setBorderRadius(size); |
|
3794 break; |
|
3795 } |
|
3796 return; |
|
3797 } |
|
3798 |
|
3799 case CSS_PROP_OUTLINE_OFFSET: |
|
3800 HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset) |
|
3801 style->setOutlineOffset(primitiveValue->computeLengthInt(style)); |
|
3802 return; |
|
3803 |
|
3804 case CSS_PROP_TEXT_SHADOW: |
|
3805 case CSS_PROP__WEBKIT_BOX_SHADOW: { |
|
3806 if (isInherit) { |
|
3807 if (id == CSS_PROP_TEXT_SHADOW) |
|
3808 return style->setTextShadow(parentStyle->textShadow() ? new ShadowData(*parentStyle->textShadow()) : 0); |
|
3809 return style->setBoxShadow(parentStyle->boxShadow() ? new ShadowData(*parentStyle->boxShadow()) : 0); |
|
3810 } |
|
3811 if (isInitial || primitiveValue) // initial | none |
|
3812 return id == CSS_PROP_TEXT_SHADOW ? style->setTextShadow(0) : style->setBoxShadow(0); |
|
3813 |
|
3814 if (!value->isValueList()) |
|
3815 return; |
|
3816 |
|
3817 CSSValueList *list = static_cast<CSSValueList*>(value); |
|
3818 int len = list->length(); |
|
3819 for (int i = 0; i < len; i++) { |
|
3820 ShadowValue* item = static_cast<ShadowValue*>(list->item(i)); |
|
3821 int x = item->x->computeLengthInt(style); |
|
3822 int y = item->y->computeLengthInt(style); |
|
3823 int blur = item->blur ? item->blur->computeLengthInt(style) : 0; |
|
3824 Color color; |
|
3825 if (item->color) |
|
3826 color = getColorFromPrimitiveValue(item->color.get()); |
|
3827 ShadowData* shadowData = new ShadowData(x, y, blur, color.isValid() ? color : Color::transparent); |
|
3828 if (id == CSS_PROP_TEXT_SHADOW) |
|
3829 style->setTextShadow(shadowData, i != 0); |
|
3830 else |
|
3831 style->setBoxShadow(shadowData, i != 0); |
|
3832 } |
|
3833 return; |
|
3834 } |
|
3835 case CSS_PROP_OPACITY: |
|
3836 HANDLE_INHERIT_AND_INITIAL(opacity, Opacity) |
|
3837 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
3838 return; // Error case. |
|
3839 // Clamp opacity to the range 0-1 |
|
3840 style->setOpacity(min(1.0f, max(0.0f, primitiveValue->getFloatValue()))); |
|
3841 return; |
|
3842 case CSS_PROP__WEBKIT_BOX_ALIGN: |
|
3843 HANDLE_INHERIT_AND_INITIAL(boxAlign, BoxAlign) |
|
3844 if (!primitiveValue) return; |
|
3845 switch (primitiveValue->getIdent()) { |
|
3846 case CSS_VAL_STRETCH: |
|
3847 style->setBoxAlign(BSTRETCH); |
|
3848 break; |
|
3849 case CSS_VAL_START: |
|
3850 style->setBoxAlign(BSTART); |
|
3851 break; |
|
3852 case CSS_VAL_END: |
|
3853 style->setBoxAlign(BEND); |
|
3854 break; |
|
3855 case CSS_VAL_CENTER: |
|
3856 style->setBoxAlign(BCENTER); |
|
3857 break; |
|
3858 case CSS_VAL_BASELINE: |
|
3859 style->setBoxAlign(BBASELINE); |
|
3860 break; |
|
3861 default: |
|
3862 return; |
|
3863 } |
|
3864 return; |
|
3865 case CSS_PROP__WEBKIT_BOX_DIRECTION: |
|
3866 HANDLE_INHERIT_AND_INITIAL(boxDirection, BoxDirection) |
|
3867 if (!primitiveValue) return; |
|
3868 if (primitiveValue->getIdent() == CSS_VAL_NORMAL) |
|
3869 style->setBoxDirection(BNORMAL); |
|
3870 else |
|
3871 style->setBoxDirection(BREVERSE); |
|
3872 return; |
|
3873 case CSS_PROP__WEBKIT_BOX_LINES: |
|
3874 HANDLE_INHERIT_AND_INITIAL(boxLines, BoxLines) |
|
3875 if(!primitiveValue) return; |
|
3876 if (primitiveValue->getIdent() == CSS_VAL_SINGLE) |
|
3877 style->setBoxLines(SINGLE); |
|
3878 else |
|
3879 style->setBoxLines(MULTIPLE); |
|
3880 return; |
|
3881 case CSS_PROP__WEBKIT_BOX_ORIENT: |
|
3882 HANDLE_INHERIT_AND_INITIAL(boxOrient, BoxOrient) |
|
3883 if (!primitiveValue) return; |
|
3884 if (primitiveValue->getIdent() == CSS_VAL_HORIZONTAL || |
|
3885 primitiveValue->getIdent() == CSS_VAL_INLINE_AXIS) |
|
3886 style->setBoxOrient(HORIZONTAL); |
|
3887 else |
|
3888 style->setBoxOrient(VERTICAL); |
|
3889 return; |
|
3890 case CSS_PROP__WEBKIT_BOX_PACK: |
|
3891 HANDLE_INHERIT_AND_INITIAL(boxPack, BoxPack) |
|
3892 if (!primitiveValue) return; |
|
3893 switch (primitiveValue->getIdent()) { |
|
3894 case CSS_VAL_START: |
|
3895 style->setBoxPack(BSTART); |
|
3896 break; |
|
3897 case CSS_VAL_END: |
|
3898 style->setBoxPack(BEND); |
|
3899 break; |
|
3900 case CSS_VAL_CENTER: |
|
3901 style->setBoxPack(BCENTER); |
|
3902 break; |
|
3903 case CSS_VAL_JUSTIFY: |
|
3904 style->setBoxPack(BJUSTIFY); |
|
3905 break; |
|
3906 default: |
|
3907 return; |
|
3908 } |
|
3909 return; |
|
3910 case CSS_PROP__WEBKIT_BOX_FLEX: |
|
3911 HANDLE_INHERIT_AND_INITIAL(boxFlex, BoxFlex) |
|
3912 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
3913 return; // Error case. |
|
3914 style->setBoxFlex(primitiveValue->getFloatValue()); |
|
3915 return; |
|
3916 case CSS_PROP__WEBKIT_BOX_FLEX_GROUP: |
|
3917 HANDLE_INHERIT_AND_INITIAL(boxFlexGroup, BoxFlexGroup) |
|
3918 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
3919 return; // Error case. |
|
3920 style->setBoxFlexGroup((unsigned int)(primitiveValue->getDoubleValue())); |
|
3921 return; |
|
3922 case CSS_PROP__WEBKIT_BOX_ORDINAL_GROUP: |
|
3923 HANDLE_INHERIT_AND_INITIAL(boxOrdinalGroup, BoxOrdinalGroup) |
|
3924 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) |
|
3925 return; // Error case. |
|
3926 style->setBoxOrdinalGroup((unsigned int)(primitiveValue->getDoubleValue())); |
|
3927 return; |
|
3928 case CSS_PROP__WEBKIT_BOX_SIZING: |
|
3929 HANDLE_INHERIT_AND_INITIAL(boxSizing, BoxSizing) |
|
3930 if (!primitiveValue) return; |
|
3931 if (primitiveValue->getIdent() == CSS_VAL_CONTENT_BOX) |
|
3932 style->setBoxSizing(CONTENT_BOX); |
|
3933 else |
|
3934 style->setBoxSizing(BORDER_BOX); |
|
3935 return; |
|
3936 case CSS_PROP__WEBKIT_COLUMN_COUNT: { |
|
3937 if (isInherit) { |
|
3938 if (parentStyle->hasAutoColumnCount()) |
|
3939 style->setHasAutoColumnCount(); |
|
3940 else |
|
3941 style->setColumnCount(parentStyle->columnCount()); |
|
3942 return; |
|
3943 } else if (isInitial || primitiveValue->getIdent() == CSS_VAL_AUTO) { |
|
3944 style->setHasAutoColumnCount(); |
|
3945 return; |
|
3946 } |
|
3947 style->setColumnCount(static_cast<unsigned short>(primitiveValue->getDoubleValue())); |
|
3948 return; |
|
3949 } |
|
3950 case CSS_PROP__WEBKIT_COLUMN_GAP: { |
|
3951 if (isInherit) { |
|
3952 if (parentStyle->hasNormalColumnGap()) |
|
3953 style->setHasNormalColumnGap(); |
|
3954 else |
|
3955 style->setColumnGap(parentStyle->columnGap()); |
|
3956 return; |
|
3957 } else if (isInitial || primitiveValue->getIdent() == CSS_VAL_NORMAL) { |
|
3958 style->setHasNormalColumnGap(); |
|
3959 return; |
|
3960 } |
|
3961 style->setColumnGap(primitiveValue->computeLengthFloat(style)); |
|
3962 return; |
|
3963 } |
|
3964 case CSS_PROP__WEBKIT_COLUMN_WIDTH: { |
|
3965 if (isInherit) { |
|
3966 if (parentStyle->hasAutoColumnWidth()) |
|
3967 style->setHasAutoColumnWidth(); |
|
3968 else |
|
3969 style->setColumnWidth(parentStyle->columnWidth()); |
|
3970 return; |
|
3971 } else if (isInitial || primitiveValue->getIdent() == CSS_VAL_AUTO) { |
|
3972 style->setHasAutoColumnWidth(); |
|
3973 return; |
|
3974 } |
|
3975 style->setColumnWidth(primitiveValue->computeLengthFloat(style)); |
|
3976 return; |
|
3977 } |
|
3978 case CSS_PROP__WEBKIT_COLUMN_RULE_STYLE: |
|
3979 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle) |
|
3980 style->setColumnRuleStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE)); |
|
3981 return; |
|
3982 case CSS_PROP__WEBKIT_COLUMN_BREAK_BEFORE: { |
|
3983 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak) |
|
3984 switch (primitiveValue->getIdent()) { |
|
3985 case CSS_VAL_AUTO: |
|
3986 style->setColumnBreakBefore(PBAUTO); |
|
3987 break; |
|
3988 case CSS_VAL_LEFT: |
|
3989 case CSS_VAL_RIGHT: |
|
3990 case CSS_VAL_ALWAYS: |
|
3991 style->setColumnBreakBefore(PBALWAYS); |
|
3992 break; |
|
3993 case CSS_VAL_AVOID: |
|
3994 style->setColumnBreakBefore(PBAVOID); |
|
3995 break; |
|
3996 } |
|
3997 return; |
|
3998 } |
|
3999 case CSS_PROP__WEBKIT_COLUMN_BREAK_AFTER: { |
|
4000 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak) |
|
4001 switch (primitiveValue->getIdent()) { |
|
4002 case CSS_VAL_AUTO: |
|
4003 style->setColumnBreakAfter(PBAUTO); |
|
4004 break; |
|
4005 case CSS_VAL_LEFT: |
|
4006 case CSS_VAL_RIGHT: |
|
4007 case CSS_VAL_ALWAYS: |
|
4008 style->setColumnBreakAfter(PBALWAYS); |
|
4009 break; |
|
4010 case CSS_VAL_AVOID: |
|
4011 style->setColumnBreakAfter(PBAVOID); |
|
4012 break; |
|
4013 } |
|
4014 return; |
|
4015 } |
|
4016 case CSS_PROP__WEBKIT_COLUMN_BREAK_INSIDE: { |
|
4017 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak) |
|
4018 if (primitiveValue->getIdent() == CSS_VAL_AUTO) |
|
4019 style->setColumnBreakInside(PBAUTO); |
|
4020 else if (primitiveValue->getIdent() == CSS_VAL_AVOID) |
|
4021 style->setColumnBreakInside(PBAVOID); |
|
4022 return; |
|
4023 } |
|
4024 case CSS_PROP__WEBKIT_COLUMN_RULE: |
|
4025 if (isInherit) { |
|
4026 style->setColumnRuleColor(parentStyle->columnRuleColor()); |
|
4027 style->setColumnRuleStyle(parentStyle->columnRuleStyle()); |
|
4028 style->setColumnRuleWidth(parentStyle->columnRuleWidth()); |
|
4029 } |
|
4030 else if (isInitial) |
|
4031 style->resetColumnRule(); |
|
4032 return; |
|
4033 case CSS_PROP__WEBKIT_COLUMNS: |
|
4034 if (isInherit) { |
|
4035 if (parentStyle->hasAutoColumnWidth()) |
|
4036 style->setHasAutoColumnWidth(); |
|
4037 else |
|
4038 style->setColumnWidth(parentStyle->columnWidth()); |
|
4039 style->setColumnCount(parentStyle->columnCount()); |
|
4040 } else if (isInitial) { |
|
4041 style->setHasAutoColumnWidth(); |
|
4042 style->setColumnCount(RenderStyle::initialColumnCount()); |
|
4043 } |
|
4044 return; |
|
4045 case CSS_PROP__WEBKIT_MARQUEE: |
|
4046 if (valueType != CSSValue::CSS_INHERIT || !parentNode) return; |
|
4047 style->setMarqueeDirection(parentStyle->marqueeDirection()); |
|
4048 style->setMarqueeIncrement(parentStyle->marqueeIncrement()); |
|
4049 style->setMarqueeSpeed(parentStyle->marqueeSpeed()); |
|
4050 style->setMarqueeLoopCount(parentStyle->marqueeLoopCount()); |
|
4051 style->setMarqueeBehavior(parentStyle->marqueeBehavior()); |
|
4052 return; |
|
4053 #if PLATFORM(SYMBIAN) |
|
4054 case CSS_PROP__WAP_MARQUEE_LOOP: { |
|
4055 HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount) |
|
4056 if (!primitiveValue) { |
|
4057 // invalid value, set loopcount to 1 |
|
4058 style->setMarqueeLoopCount(1); |
|
4059 return; |
|
4060 } |
|
4061 if (primitiveValue->getIdent() == CSS_VAL_INFINITE) |
|
4062 style->setMarqueeLoopCount(1); // 1 loop instead of forever |
|
4063 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) |
|
4064 style->setMarqueeLoopCount(primitiveValue->getIntValue()); |
|
4065 else |
|
4066 style->setMarqueeLoopCount(1); |
|
4067 return; |
|
4068 } |
|
4069 #endif |
|
4070 case CSS_PROP__WEBKIT_MARQUEE_REPETITION: { |
|
4071 HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount) |
|
4072 if (!primitiveValue) return; |
|
4073 if (primitiveValue->getIdent() == CSS_VAL_INFINITE) |
|
4074 style->setMarqueeLoopCount(-1); // -1 means repeat forever. |
|
4075 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) |
|
4076 style->setMarqueeLoopCount(primitiveValue->getIntValue()); |
|
4077 return; |
|
4078 } |
|
4079 #if PLATFORM(SYMBIAN) |
|
4080 case CSS_PROP__WAP_MARQUEE_SPEED: |
|
4081 #endif |
|
4082 case CSS_PROP__WEBKIT_MARQUEE_SPEED: { |
|
4083 HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed) |
|
4084 if (!primitiveValue) return; |
|
4085 if (primitiveValue->getIdent()) { |
|
4086 switch (primitiveValue->getIdent()) |
|
4087 { |
|
4088 case CSS_VAL_SLOW: |
|
4089 style->setMarqueeSpeed(500); // 500 msec. |
|
4090 break; |
|
4091 case CSS_VAL_NORMAL: |
|
4092 style->setMarqueeSpeed(85); // 85msec. The WinIE default. |
|
4093 break; |
|
4094 case CSS_VAL_FAST: |
|
4095 style->setMarqueeSpeed(10); // 10msec. Super fast. |
|
4096 break; |
|
4097 } |
|
4098 } |
|
4099 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) |
|
4100 style->setMarqueeSpeed(1000 * primitiveValue->getIntValue()); |
|
4101 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) |
|
4102 style->setMarqueeSpeed(primitiveValue->getIntValue()); |
|
4103 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support. |
|
4104 style->setMarqueeSpeed(primitiveValue->getIntValue()); |
|
4105 return; |
|
4106 } |
|
4107 case CSS_PROP__WEBKIT_MARQUEE_INCREMENT: { |
|
4108 HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement) |
|
4109 if (!primitiveValue) return; |
|
4110 if (primitiveValue->getIdent()) { |
|
4111 switch (primitiveValue->getIdent()) |
|
4112 { |
|
4113 case CSS_VAL_SMALL: |
|
4114 style->setMarqueeIncrement(Length(1, Fixed)); // 1px. |
|
4115 break; |
|
4116 case CSS_VAL_NORMAL: |
|
4117 style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default. |
|
4118 break; |
|
4119 case CSS_VAL_LARGE: |
|
4120 style->setMarqueeIncrement(Length(36, Fixed)); // 36px. |
|
4121 break; |
|
4122 } |
|
4123 } |
|
4124 else { |
|
4125 bool ok = true; |
|
4126 Length l = convertToLength(primitiveValue, style, &ok); |
|
4127 if (ok) |
|
4128 style->setMarqueeIncrement(l); |
|
4129 } |
|
4130 return; |
|
4131 } |
|
4132 #if PLATFORM(SYMBIAN) |
|
4133 case CSS_PROP__WAP_MARQUEE_STYLE: |
|
4134 #endif |
|
4135 case CSS_PROP__WEBKIT_MARQUEE_STYLE: { |
|
4136 HANDLE_INHERIT_AND_INITIAL(marqueeBehavior, MarqueeBehavior) |
|
4137 if (!primitiveValue || !primitiveValue->getIdent()) return; |
|
4138 switch (primitiveValue->getIdent()) |
|
4139 { |
|
4140 case CSS_VAL_NONE: |
|
4141 style->setMarqueeBehavior(MNONE); |
|
4142 break; |
|
4143 case CSS_VAL_SCROLL: |
|
4144 style->setMarqueeBehavior(MSCROLL); |
|
4145 break; |
|
4146 case CSS_VAL_SLIDE: |
|
4147 style->setMarqueeBehavior(MSLIDE); |
|
4148 break; |
|
4149 case CSS_VAL_ALTERNATE: |
|
4150 style->setMarqueeBehavior(MALTERNATE); |
|
4151 break; |
|
4152 } |
|
4153 return; |
|
4154 } |
|
4155 #if PLATFORM(SYMBIAN) |
|
4156 case CSS_PROP__WAP_MARQUEE_DIR: { |
|
4157 HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection) |
|
4158 if (!primitiveValue || !primitiveValue->getIdent()) return; |
|
4159 switch (primitiveValue->getIdent()) |
|
4160 { |
|
4161 case CSS_VAL_RTL: |
|
4162 style->setMarqueeDirection(MLEFT); |
|
4163 break; |
|
4164 case CSS_VAL_LTR: |
|
4165 style->setMarqueeDirection(MRIGHT); |
|
4166 break; |
|
4167 } |
|
4168 break; |
|
4169 #endif |
|
4170 case CSS_PROP__WEBKIT_MARQUEE_DIRECTION: { |
|
4171 HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection) |
|
4172 if (!primitiveValue || !primitiveValue->getIdent()) return; |
|
4173 switch (primitiveValue->getIdent()) |
|
4174 { |
|
4175 case CSS_VAL_FORWARDS: |
|
4176 style->setMarqueeDirection(MFORWARD); |
|
4177 break; |
|
4178 case CSS_VAL_BACKWARDS: |
|
4179 style->setMarqueeDirection(MBACKWARD); |
|
4180 break; |
|
4181 case CSS_VAL_AUTO: |
|
4182 style->setMarqueeDirection(MAUTO); |
|
4183 break; |
|
4184 case CSS_VAL_AHEAD: |
|
4185 case CSS_VAL_UP: // We don't support vertical languages, so AHEAD just maps to UP. |
|
4186 style->setMarqueeDirection(MUP); |
|
4187 break; |
|
4188 case CSS_VAL_REVERSE: |
|
4189 case CSS_VAL_DOWN: // REVERSE just maps to DOWN, since we don't do vertical text. |
|
4190 style->setMarqueeDirection(MDOWN); |
|
4191 break; |
|
4192 case CSS_VAL_LEFT: |
|
4193 style->setMarqueeDirection(MLEFT); |
|
4194 break; |
|
4195 case CSS_VAL_RIGHT: |
|
4196 style->setMarqueeDirection(MRIGHT); |
|
4197 break; |
|
4198 } |
|
4199 return; |
|
4200 } |
|
4201 case CSS_PROP__WEBKIT_USER_DRAG: { |
|
4202 HANDLE_INHERIT_AND_INITIAL(userDrag, UserDrag) |
|
4203 if (!primitiveValue || !primitiveValue->getIdent()) |
|
4204 return; |
|
4205 switch (primitiveValue->getIdent()) { |
|
4206 case CSS_VAL_AUTO: |
|
4207 style->setUserDrag(DRAG_AUTO); |
|
4208 break; |
|
4209 case CSS_VAL_NONE: |
|
4210 style->setUserDrag(DRAG_NONE); |
|
4211 break; |
|
4212 case CSS_VAL_ELEMENT: |
|
4213 style->setUserDrag(DRAG_ELEMENT); |
|
4214 default: |
|
4215 return; |
|
4216 } |
|
4217 return; |
|
4218 } |
|
4219 case CSS_PROP__WEBKIT_USER_MODIFY: { |
|
4220 HANDLE_INHERIT_AND_INITIAL(userModify, UserModify) |
|
4221 if (!primitiveValue || !primitiveValue->getIdent()) |
|
4222 return; |
|
4223 EUserModify userModify = EUserModify(primitiveValue->getIdent() - CSS_VAL_READ_ONLY); |
|
4224 style->setUserModify(userModify); |
|
4225 return; |
|
4226 } |
|
4227 case CSS_PROP__WEBKIT_USER_SELECT: { |
|
4228 HANDLE_INHERIT_AND_INITIAL(userSelect, UserSelect) |
|
4229 if (!primitiveValue || !primitiveValue->getIdent()) |
|
4230 return; |
|
4231 switch (primitiveValue->getIdent()) { |
|
4232 case CSS_VAL_AUTO: |
|
4233 style->setUserSelect(SELECT_TEXT); |
|
4234 break; |
|
4235 case CSS_VAL_NONE: |
|
4236 style->setUserSelect(SELECT_NONE); |
|
4237 break; |
|
4238 case CSS_VAL_TEXT: |
|
4239 style->setUserSelect(SELECT_TEXT); |
|
4240 default: |
|
4241 return; |
|
4242 } |
|
4243 return; |
|
4244 } |
|
4245 case CSS_PROP_TEXT_OVERFLOW: { |
|
4246 // This property is supported by WinIE, and so we leave off the "-webkit-" in order to |
|
4247 // work with WinIE-specific pages that use the property. |
|
4248 HANDLE_INHERIT_AND_INITIAL(textOverflow, TextOverflow) |
|
4249 if (!primitiveValue || !primitiveValue->getIdent()) |
|
4250 return; |
|
4251 style->setTextOverflow(primitiveValue->getIdent() == CSS_VAL_ELLIPSIS); |
|
4252 return; |
|
4253 } |
|
4254 case CSS_PROP__WEBKIT_MARGIN_COLLAPSE: { |
|
4255 if (isInherit) { |
|
4256 style->setMarginTopCollapse(parentStyle->marginTopCollapse()); |
|
4257 style->setMarginBottomCollapse(parentStyle->marginBottomCollapse()); |
|
4258 } |
|
4259 else if (isInitial) { |
|
4260 style->setMarginTopCollapse(MCOLLAPSE); |
|
4261 style->setMarginBottomCollapse(MCOLLAPSE); |
|
4262 } |
|
4263 return; |
|
4264 } |
|
4265 case CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE: { |
|
4266 HANDLE_INHERIT_AND_INITIAL(marginTopCollapse, MarginTopCollapse) |
|
4267 if (!primitiveValue || !primitiveValue->getIdent()) return; |
|
4268 EMarginCollapse val; |
|
4269 switch (primitiveValue->getIdent()) { |
|
4270 case CSS_VAL_SEPARATE: |
|
4271 val = MSEPARATE; |
|
4272 break; |
|
4273 case CSS_VAL_DISCARD: |
|
4274 val = MDISCARD; |
|
4275 break; |
|
4276 default: |
|
4277 val = MCOLLAPSE; |
|
4278 } |
|
4279 style->setMarginTopCollapse(val); |
|
4280 return; |
|
4281 } |
|
4282 case CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE: { |
|
4283 HANDLE_INHERIT_AND_INITIAL(marginBottomCollapse, MarginBottomCollapse) |
|
4284 if (!primitiveValue || !primitiveValue->getIdent()) return; |
|
4285 EMarginCollapse val; |
|
4286 switch (primitiveValue->getIdent()) { |
|
4287 case CSS_VAL_SEPARATE: |
|
4288 val = MSEPARATE; |
|
4289 break; |
|
4290 case CSS_VAL_DISCARD: |
|
4291 val = MDISCARD; |
|
4292 break; |
|
4293 default: |
|
4294 val = MCOLLAPSE; |
|
4295 } |
|
4296 style->setMarginBottomCollapse(val); |
|
4297 return; |
|
4298 } |
|
4299 |
|
4300 // Apple-specific changes. Do not merge these properties into KHTML. |
|
4301 case CSS_PROP__WEBKIT_LINE_CLAMP: { |
|
4302 HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp) |
|
4303 if (!primitiveValue) return; |
|
4304 style->setLineClamp(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE)); |
|
4305 return; |
|
4306 } |
|
4307 case CSS_PROP__WEBKIT_HIGHLIGHT: { |
|
4308 HANDLE_INHERIT_AND_INITIAL(highlight, Highlight); |
|
4309 if (primitiveValue->getIdent() == CSS_VAL_NONE) |
|
4310 style->setHighlight(nullAtom); |
|
4311 else |
|
4312 style->setHighlight(primitiveValue->getStringValue()); |
|
4313 return; |
|
4314 } |
|
4315 case CSS_PROP__WEBKIT_BORDER_FIT: { |
|
4316 HANDLE_INHERIT_AND_INITIAL(borderFit, BorderFit); |
|
4317 if (primitiveValue->getIdent() == CSS_VAL_BORDER) |
|
4318 style->setBorderFit(BorderFitBorder); |
|
4319 else |
|
4320 style->setBorderFit(BorderFitLines); |
|
4321 return; |
|
4322 } |
|
4323 case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST: { |
|
4324 HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust) |
|
4325 if (!primitiveValue || !primitiveValue->getIdent()) return; |
|
4326 style->setTextSizeAdjust(primitiveValue->getIdent() == CSS_VAL_AUTO); |
|
4327 fontDirty = true; |
|
4328 return; |
|
4329 } |
|
4330 case CSS_PROP__WEBKIT_TEXT_SECURITY: { |
|
4331 HANDLE_INHERIT_AND_INITIAL(textSecurity, TextSecurity) |
|
4332 if (!primitiveValue) |
|
4333 return; |
|
4334 ETextSecurity textSecurity = TSNONE; |
|
4335 switch (primitiveValue->getIdent()) { |
|
4336 case CSS_VAL_DISC: |
|
4337 textSecurity = TSDISC; |
|
4338 break; |
|
4339 case CSS_VAL_CIRCLE: |
|
4340 textSecurity = TSCIRCLE; |
|
4341 break; |
|
4342 case CSS_VAL_SQUARE: |
|
4343 textSecurity= TSSQUARE; |
|
4344 break; |
|
4345 } |
|
4346 style->setTextSecurity(textSecurity); |
|
4347 return; |
|
4348 } |
|
4349 case CSS_PROP__WEBKIT_DASHBOARD_REGION: { |
|
4350 HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions) |
|
4351 if (!primitiveValue) |
|
4352 return; |
|
4353 |
|
4354 if(primitiveValue->getIdent() == CSS_VAL_NONE) { |
|
4355 style->setDashboardRegions(RenderStyle::noneDashboardRegions()); |
|
4356 return; |
|
4357 } |
|
4358 |
|
4359 DashboardRegion *region = primitiveValue->getDashboardRegionValue(); |
|
4360 if (!region) |
|
4361 return; |
|
4362 |
|
4363 DashboardRegion *first = region; |
|
4364 while (region) { |
|
4365 Length top = convertToLength (region->top(), style); |
|
4366 Length right = convertToLength (region->right(), style); |
|
4367 Length bottom = convertToLength (region->bottom(), style); |
|
4368 Length left = convertToLength (region->left(), style); |
|
4369 if (region->m_isCircle) |
|
4370 style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true); |
|
4371 else if (region->m_isRectangle) |
|
4372 style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true); |
|
4373 region = region->m_next.get(); |
|
4374 } |
|
4375 |
|
4376 element->document()->setHasDashboardRegions(true); |
|
4377 |
|
4378 return; |
|
4379 } |
|
4380 case CSS_PROP__WEBKIT_RTL_ORDERING: |
|
4381 HANDLE_INHERIT_AND_INITIAL(visuallyOrdered, VisuallyOrdered) |
|
4382 if (!primitiveValue || !primitiveValue->getIdent()) |
|
4383 return; |
|
4384 style->setVisuallyOrdered(primitiveValue->getIdent() == CSS_VAL_VISUAL); |
|
4385 return; |
|
4386 case CSS_PROP__WEBKIT_TEXT_STROKE_WIDTH: { |
|
4387 HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth) |
|
4388 float width = 0; |
|
4389 switch (primitiveValue->getIdent()) { |
|
4390 case CSS_VAL_THIN: |
|
4391 case CSS_VAL_MEDIUM: |
|
4392 case CSS_VAL_THICK: { |
|
4393 double result = 1.0 / 48; |
|
4394 if (primitiveValue->getIdent() == CSS_VAL_MEDIUM) |
|
4395 result *= 3; |
|
4396 else if (primitiveValue->getIdent() == CSS_VAL_THICK) |
|
4397 result *= 5; |
|
4398 CSSPrimitiveValue val(result, CSSPrimitiveValue::CSS_EMS); |
|
4399 width = val.computeLengthFloat(style); |
|
4400 break; |
|
4401 } |
|
4402 default: |
|
4403 width = primitiveValue->computeLengthFloat(style); |
|
4404 break; |
|
4405 } |
|
4406 style->setTextStrokeWidth(width); |
|
4407 return; |
|
4408 } |
|
4409 #if PLATFORM(SYMBIAN) |
|
4410 case CSS_PROP__WAP_INPUT_FORMAT: { |
|
4411 HANDLE_INHERIT_AND_INITIAL(wapInputFormat, WapInputFormat) |
|
4412 if (!primitiveValue) return; |
|
4413 style->setWapInputFormat(primitiveValue->getStringValue()); |
|
4414 break; |
|
4415 } |
|
4416 case CSS_PROP__WAP_INPUT_REQUIRED: { |
|
4417 HANDLE_INHERIT_AND_INITIAL(wapInputRequired, WapInputRequired) |
|
4418 if (!primitiveValue) return; |
|
4419 style->setWapInputRequired(primitiveValue->getIdent() == CSS_VAL_TRUE ? true : false); |
|
4420 break; |
|
4421 } |
|
4422 } |
|
4423 #endif |
|
4424 case CSS_PROP_INVALID: |
|
4425 return; |
|
4426 case CSS_PROP_FONT_STRETCH: |
|
4427 case CSS_PROP_PAGE: |
|
4428 case CSS_PROP_QUOTES: |
|
4429 case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: |
|
4430 case CSS_PROP_SCROLLBAR_ARROW_COLOR: |
|
4431 case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: |
|
4432 case CSS_PROP_SCROLLBAR_FACE_COLOR: |
|
4433 case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: |
|
4434 case CSS_PROP_SCROLLBAR_SHADOW_COLOR: |
|
4435 case CSS_PROP_SCROLLBAR_TRACK_COLOR: |
|
4436 case CSS_PROP_SIZE: |
|
4437 case CSS_PROP_TEXT_LINE_THROUGH: |
|
4438 case CSS_PROP_TEXT_LINE_THROUGH_COLOR: |
|
4439 case CSS_PROP_TEXT_LINE_THROUGH_MODE: |
|
4440 case CSS_PROP_TEXT_LINE_THROUGH_STYLE: |
|
4441 case CSS_PROP_TEXT_LINE_THROUGH_WIDTH: |
|
4442 case CSS_PROP_TEXT_OVERLINE: |
|
4443 case CSS_PROP_TEXT_OVERLINE_COLOR: |
|
4444 case CSS_PROP_TEXT_OVERLINE_MODE: |
|
4445 case CSS_PROP_TEXT_OVERLINE_STYLE: |
|
4446 case CSS_PROP_TEXT_OVERLINE_WIDTH: |
|
4447 case CSS_PROP_TEXT_UNDERLINE: |
|
4448 case CSS_PROP_TEXT_UNDERLINE_COLOR: |
|
4449 case CSS_PROP_TEXT_UNDERLINE_MODE: |
|
4450 case CSS_PROP_TEXT_UNDERLINE_STYLE: |
|
4451 case CSS_PROP_TEXT_UNDERLINE_WIDTH: |
|
4452 case CSS_PROP__WEBKIT_FONT_SIZE_DELTA: |
|
4453 case CSS_PROP__WEBKIT_MARGIN_START: |
|
4454 case CSS_PROP__WEBKIT_PADDING_START: |
|
4455 case CSS_PROP__WEBKIT_TEXT_DECORATIONS_IN_EFFECT: |
|
4456 case CSS_PROP__WEBKIT_TEXT_STROKE: |
|
4457 return; |
|
4458 } |
|
4459 #if ENABLE(SVG) |
|
4460 // Try the SVG properties |
|
4461 applySVGProperty(id, value); |
|
4462 #endif |
|
4463 } |
|
4464 |
|
4465 void CSSStyleSelector::mapBackgroundAttachment(BackgroundLayer* layer, CSSValue* value) |
|
4466 { |
|
4467 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
4468 layer->setBackgroundAttachment(RenderStyle::initialBackgroundAttachment()); |
|
4469 return; |
|
4470 } |
|
4471 |
|
4472 if (!value->isPrimitiveValue()) return; |
|
4473 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
4474 switch (primitiveValue->getIdent()) { |
|
4475 case CSS_VAL_FIXED: |
|
4476 layer->setBackgroundAttachment(false); |
|
4477 break; |
|
4478 case CSS_VAL_SCROLL: |
|
4479 layer->setBackgroundAttachment(true); |
|
4480 break; |
|
4481 default: |
|
4482 return; |
|
4483 } |
|
4484 } |
|
4485 |
|
4486 void CSSStyleSelector::mapBackgroundClip(BackgroundLayer* layer, CSSValue* value) |
|
4487 { |
|
4488 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
4489 layer->setBackgroundClip(RenderStyle::initialBackgroundClip()); |
|
4490 return; |
|
4491 } |
|
4492 |
|
4493 if (!value->isPrimitiveValue()) return; |
|
4494 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
4495 switch (primitiveValue->getIdent()) { |
|
4496 case CSS_VAL_BORDER: |
|
4497 layer->setBackgroundClip(BGBORDER); |
|
4498 break; |
|
4499 case CSS_VAL_PADDING: |
|
4500 layer->setBackgroundClip(BGPADDING); |
|
4501 break; |
|
4502 default: // CSS_VAL_CONTENT |
|
4503 layer->setBackgroundClip(BGCONTENT); |
|
4504 break; |
|
4505 } |
|
4506 } |
|
4507 |
|
4508 void CSSStyleSelector::mapBackgroundComposite(BackgroundLayer* layer, CSSValue* value) |
|
4509 { |
|
4510 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
4511 layer->setBackgroundComposite(RenderStyle::initialBackgroundComposite()); |
|
4512 return; |
|
4513 } |
|
4514 |
|
4515 if (!value->isPrimitiveValue()) |
|
4516 return; |
|
4517 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
4518 switch(primitiveValue->getIdent()) { |
|
4519 case CSS_VAL_CLEAR: |
|
4520 layer->setBackgroundComposite(CompositeClear); |
|
4521 break; |
|
4522 case CSS_VAL_COPY: |
|
4523 layer->setBackgroundComposite(CompositeCopy); |
|
4524 break; |
|
4525 case CSS_VAL_SOURCE_OVER: |
|
4526 layer->setBackgroundComposite(CompositeSourceOver); |
|
4527 break; |
|
4528 case CSS_VAL_SOURCE_IN: |
|
4529 layer->setBackgroundComposite(CompositeSourceIn); |
|
4530 break; |
|
4531 case CSS_VAL_SOURCE_OUT: |
|
4532 layer->setBackgroundComposite(CompositeSourceOut); |
|
4533 break; |
|
4534 case CSS_VAL_SOURCE_ATOP: |
|
4535 layer->setBackgroundComposite(CompositeSourceAtop); |
|
4536 break; |
|
4537 case CSS_VAL_DESTINATION_OVER: |
|
4538 layer->setBackgroundComposite(CompositeDestinationOver); |
|
4539 break; |
|
4540 case CSS_VAL_DESTINATION_IN: |
|
4541 layer->setBackgroundComposite(CompositeDestinationIn); |
|
4542 break; |
|
4543 case CSS_VAL_DESTINATION_OUT: |
|
4544 layer->setBackgroundComposite(CompositeDestinationOut); |
|
4545 break; |
|
4546 case CSS_VAL_DESTINATION_ATOP: |
|
4547 layer->setBackgroundComposite(CompositeDestinationAtop); |
|
4548 break; |
|
4549 case CSS_VAL_XOR: |
|
4550 layer->setBackgroundComposite(CompositeXOR); |
|
4551 break; |
|
4552 case CSS_VAL_PLUS_DARKER: |
|
4553 layer->setBackgroundComposite(CompositePlusDarker); |
|
4554 break; |
|
4555 case CSS_VAL_HIGHLIGHT: |
|
4556 layer->setBackgroundComposite(CompositeHighlight); |
|
4557 break; |
|
4558 case CSS_VAL_PLUS_LIGHTER: |
|
4559 layer->setBackgroundComposite(CompositePlusLighter); |
|
4560 break; |
|
4561 default: |
|
4562 return; |
|
4563 } |
|
4564 } |
|
4565 |
|
4566 void CSSStyleSelector::mapBackgroundOrigin(BackgroundLayer* layer, CSSValue* value) |
|
4567 { |
|
4568 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
4569 layer->setBackgroundOrigin(RenderStyle::initialBackgroundOrigin()); |
|
4570 return; |
|
4571 } |
|
4572 |
|
4573 if (!value->isPrimitiveValue()) return; |
|
4574 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
4575 switch (primitiveValue->getIdent()) { |
|
4576 case CSS_VAL_BORDER: |
|
4577 layer->setBackgroundOrigin(BGBORDER); |
|
4578 break; |
|
4579 case CSS_VAL_PADDING: |
|
4580 layer->setBackgroundOrigin(BGPADDING); |
|
4581 break; |
|
4582 default: // CSS_VAL_CONTENT |
|
4583 layer->setBackgroundOrigin(BGCONTENT); |
|
4584 break; |
|
4585 } |
|
4586 } |
|
4587 |
|
4588 void CSSStyleSelector::mapBackgroundImage(BackgroundLayer* layer, CSSValue* value) |
|
4589 { |
|
4590 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
4591 layer->setBackgroundImage(RenderStyle::initialBackgroundImage()); |
|
4592 return; |
|
4593 } |
|
4594 |
|
4595 if (!value->isPrimitiveValue()) return; |
|
4596 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
4597 layer->setBackgroundImage(static_cast<CSSImageValue*>(primitiveValue)->image(element->document()->docLoader())); |
|
4598 } |
|
4599 |
|
4600 void CSSStyleSelector::mapBackgroundRepeat(BackgroundLayer* layer, CSSValue* value) |
|
4601 { |
|
4602 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
4603 layer->setBackgroundRepeat(RenderStyle::initialBackgroundRepeat()); |
|
4604 return; |
|
4605 } |
|
4606 |
|
4607 if (!value->isPrimitiveValue()) |
|
4608 return; |
|
4609 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
4610 switch(primitiveValue->getIdent()) { |
|
4611 case CSS_VAL_REPEAT: |
|
4612 layer->setBackgroundRepeat(REPEAT); |
|
4613 break; |
|
4614 case CSS_VAL_REPEAT_X: |
|
4615 layer->setBackgroundRepeat(REPEAT_X); |
|
4616 break; |
|
4617 case CSS_VAL_REPEAT_Y: |
|
4618 layer->setBackgroundRepeat(REPEAT_Y); |
|
4619 break; |
|
4620 case CSS_VAL_NO_REPEAT: |
|
4621 layer->setBackgroundRepeat(NO_REPEAT); |
|
4622 break; |
|
4623 default: |
|
4624 return; |
|
4625 } |
|
4626 } |
|
4627 |
|
4628 void CSSStyleSelector::mapBackgroundSize(BackgroundLayer* layer, CSSValue* value) |
|
4629 { |
|
4630 LengthSize b = RenderStyle::initialBackgroundSize(); |
|
4631 |
|
4632 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
4633 layer->setBackgroundSize(b); |
|
4634 return; |
|
4635 } |
|
4636 |
|
4637 if (!value->isPrimitiveValue()) |
|
4638 return; |
|
4639 |
|
4640 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
4641 Pair* pair = primitiveValue->getPairValue(); |
|
4642 if (!pair) |
|
4643 return; |
|
4644 |
|
4645 CSSPrimitiveValue* first = static_cast<CSSPrimitiveValue*>(pair->first()); |
|
4646 CSSPrimitiveValue* second = static_cast<CSSPrimitiveValue*>(pair->second()); |
|
4647 |
|
4648 if (!first || !second) |
|
4649 return; |
|
4650 |
|
4651 Length firstLength, secondLength; |
|
4652 int firstType = first->primitiveType(); |
|
4653 int secondType = second->primitiveType(); |
|
4654 |
|
4655 if (firstType == CSSPrimitiveValue::CSS_UNKNOWN) |
|
4656 firstLength = Length(Auto); |
|
4657 else if (firstType > CSSPrimitiveValue::CSS_PERCENTAGE && firstType < CSSPrimitiveValue::CSS_DEG) |
|
4658 firstLength = Length(first->computeLengthIntForLength(style), Fixed); |
|
4659 else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
4660 firstLength = Length(first->getDoubleValue(), Percent); |
|
4661 else |
|
4662 return; |
|
4663 |
|
4664 if (secondType == CSSPrimitiveValue::CSS_UNKNOWN) |
|
4665 secondLength = Length(Auto); |
|
4666 else if (secondType > CSSPrimitiveValue::CSS_PERCENTAGE && secondType < CSSPrimitiveValue::CSS_DEG) |
|
4667 secondLength = Length(second->computeLengthIntForLength(style), Fixed); |
|
4668 else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
4669 secondLength = Length(second->getDoubleValue(), Percent); |
|
4670 else |
|
4671 return; |
|
4672 |
|
4673 b.width = firstLength; |
|
4674 b.height = secondLength; |
|
4675 layer->setBackgroundSize(b); |
|
4676 } |
|
4677 |
|
4678 void CSSStyleSelector::mapBackgroundXPosition(BackgroundLayer* layer, CSSValue* value) |
|
4679 { |
|
4680 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
4681 layer->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition()); |
|
4682 return; |
|
4683 } |
|
4684 |
|
4685 if (!value->isPrimitiveValue()) |
|
4686 return; |
|
4687 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
4688 Length l; |
|
4689 int type = primitiveValue->primitiveType(); |
|
4690 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) |
|
4691 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed); |
|
4692 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
4693 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
4694 else |
|
4695 return; |
|
4696 layer->setBackgroundXPosition(l); |
|
4697 } |
|
4698 |
|
4699 void CSSStyleSelector::mapBackgroundYPosition(BackgroundLayer* layer, CSSValue* value) |
|
4700 { |
|
4701 if (value->cssValueType() == CSSValue::CSS_INITIAL) { |
|
4702 layer->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition()); |
|
4703 return; |
|
4704 } |
|
4705 |
|
4706 if (!value->isPrimitiveValue()) |
|
4707 return; |
|
4708 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); |
|
4709 Length l; |
|
4710 int type = primitiveValue->primitiveType(); |
|
4711 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) |
|
4712 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed); |
|
4713 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) |
|
4714 l = Length(primitiveValue->getDoubleValue(), Percent); |
|
4715 else |
|
4716 return; |
|
4717 layer->setBackgroundYPosition(l); |
|
4718 } |
|
4719 |
|
4720 void CSSStyleSelector::checkForTextSizeAdjust() |
|
4721 { |
|
4722 if (style->textSizeAdjust()) |
|
4723 return; |
|
4724 |
|
4725 FontDescription newFontDescription(style->fontDescription()); |
|
4726 newFontDescription.setComputedSize(newFontDescription.specifiedSize()); |
|
4727 style->setFontDescription(newFontDescription); |
|
4728 } |
|
4729 |
|
4730 void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle) |
|
4731 { |
|
4732 const FontDescription& childFont = style->fontDescription(); |
|
4733 |
|
4734 if (childFont.isAbsoluteSize() || !parentStyle) |
|
4735 return; |
|
4736 |
|
4737 const FontDescription& parentFont = parentStyle->fontDescription(); |
|
4738 |
|
4739 if (childFont.genericFamily() == parentFont.genericFamily()) |
|
4740 return; |
|
4741 |
|
4742 // For now, lump all families but monospace together. |
|
4743 if (childFont.genericFamily() != FontDescription::MonospaceFamily && |
|
4744 parentFont.genericFamily() != FontDescription::MonospaceFamily) |
|
4745 return; |
|
4746 |
|
4747 // We know the parent is monospace or the child is monospace, and that font |
|
4748 // size was unspecified. We want to scale our font size as appropriate. |
|
4749 // If the font uses a keyword size, then we refetch from the table rather than |
|
4750 // multiplying by our scale factor. |
|
4751 float size; |
|
4752 if (childFont.keywordSize()) { |
|
4753 size = fontSizeForKeyword(CSS_VAL_XX_SMALL + childFont.keywordSize() - 1, style->htmlHacks(), |
|
4754 childFont.genericFamily() == FontDescription::MonospaceFamily); |
|
4755 } else { |
|
4756 Settings* settings = m_document->settings(); |
|
4757 float fixedScaleFactor = settings |
|
4758 ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize() |
|
4759 : 1; |
|
4760 size = (parentFont.genericFamily() == FontDescription::MonospaceFamily) ? |
|
4761 childFont.specifiedSize()/fixedScaleFactor : |
|
4762 childFont.specifiedSize()*fixedScaleFactor; |
|
4763 } |
|
4764 |
|
4765 FontDescription newFontDescription(childFont); |
|
4766 setFontSize(newFontDescription, size); |
|
4767 style->setFontDescription(newFontDescription); |
|
4768 } |
|
4769 |
|
4770 void CSSStyleSelector::setFontSize(FontDescription& fontDescription, float size) |
|
4771 { |
|
4772 fontDescription.setSpecifiedSize(size); |
|
4773 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription.isAbsoluteSize(), size)); |
|
4774 } |
|
4775 |
|
4776 float CSSStyleSelector::getComputedSizeFromSpecifiedSize(bool isAbsoluteSize, float specifiedSize) |
|
4777 { |
|
4778 // We support two types of minimum font size. The first is a hard override that applies to |
|
4779 // all fonts. This is "minSize." The second type of minimum font size is a "smart minimum" |
|
4780 // that is applied only when the Web page can't know what size it really asked for, e.g., |
|
4781 // when it uses logical sizes like "small" or expresses the font-size as a percentage of |
|
4782 // the user's default font setting. |
|
4783 |
|
4784 // With the smart minimum, we never want to get smaller than the minimum font size to keep fonts readable. |
|
4785 // However we always allow the page to set an explicit pixel size that is smaller, |
|
4786 // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum). |
|
4787 |
|
4788 Settings* settings = m_document->settings(); |
|
4789 if (!settings) |
|
4790 return 1.0f; |
|
4791 |
|
4792 int minSize = settings->minimumFontSize(); |
|
4793 int minLogicalSize = settings->minimumLogicalFontSize(); |
|
4794 |
|
4795 float zoomPercent = m_document->frame() ? m_document->frame()->zoomFactor() / 100.0f : 1.0f; |
|
4796 float zoomedSize = specifiedSize * zoomPercent; |
|
4797 |
|
4798 #if PLATFORM(SYMBIAN) |
|
4799 if( !isAbsoluteSize ) |
|
4800 zoomedSize *= m_document ? m_document->frame()->bridge()->textZoomPercent() / 100.0f : 1.0f; |
|
4801 #endif |
|
4802 |
|
4803 // Apply the hard minimum first. We only apply the hard minimum if after zooming we're still too small. |
|
4804 if (zoomedSize < minSize) |
|
4805 zoomedSize = minSize; |
|
4806 |
|
4807 // Now apply the "smart minimum." This minimum is also only applied if we're still too small |
|
4808 // after zooming. The font size must either be relative to the user default or the original size |
|
4809 // must have been acceptable. In other words, we only apply the smart minimum whenever we're positive |
|
4810 // doing so won't disrupt the layout. |
|
4811 if (zoomedSize < minLogicalSize && (specifiedSize >= minLogicalSize || !isAbsoluteSize)) |
|
4812 zoomedSize = minLogicalSize; |
|
4813 |
|
4814 // Also clamp to a reasonable maximum to prevent insane font sizes from causing crashes on various |
|
4815 // platforms (I'm looking at you, Windows.) |
|
4816 return min(1000000.0f, max(zoomedSize, 1.0f)); |
|
4817 } |
|
4818 |
|
4819 const int fontSizeTableMax = 16; |
|
4820 const int fontSizeTableMin = 9; |
|
4821 const int totalKeywords = 8; |
|
4822 |
|
4823 // WinIE/Nav4 table for font sizes. Designed to match the legacy font mapping system of HTML. |
|
4824 static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] = |
|
4825 { |
|
4826 { 9, 9, 9, 9, 11, 14, 18, 28 }, |
|
4827 { 9, 9, 9, 10, 12, 15, 20, 31 }, |
|
4828 { 9, 9, 9, 11, 13, 17, 22, 34 }, |
|
4829 { 9, 9, 10, 12, 14, 18, 24, 37 }, |
|
4830 { 9, 9, 10, 13, 16, 20, 26, 40 }, // fixed font default (13) |
|
4831 { 9, 9, 11, 14, 17, 21, 28, 42 }, |
|
4832 { 9, 10, 12, 15, 17, 23, 30, 45 }, |
|
4833 { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16) |
|
4834 }; |
|
4835 // HTML 1 2 3 4 5 6 7 |
|
4836 // CSS xxs xs s m l xl xxl |
|
4837 // | |
|
4838 // user pref |
|
4839 |
|
4840 // Strict mode table matches MacIE and Mozilla's settings exactly. |
|
4841 static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] = |
|
4842 { |
|
4843 { 9, 9, 9, 9, 11, 14, 18, 27 }, |
|
4844 { 9, 9, 9, 10, 12, 15, 20, 30 }, |
|
4845 { 9, 9, 10, 11, 13, 17, 22, 33 }, |
|
4846 { 9, 9, 10, 12, 14, 18, 24, 36 }, |
|
4847 { 9, 10, 12, 13, 16, 20, 26, 39 }, // fixed font default (13) |
|
4848 { 9, 10, 12, 14, 17, 21, 28, 42 }, |
|
4849 { 9, 10, 13, 15, 18, 23, 30, 45 }, |
|
4850 { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16) |
|
4851 }; |
|
4852 // HTML 1 2 3 4 5 6 7 |
|
4853 // CSS xxs xs s m l xl xxl |
|
4854 // | |
|
4855 // user pref |
|
4856 |
|
4857 // For values outside the range of the table, we use Todd Fahrner's suggested scale |
|
4858 // factors for each keyword value. |
|
4859 static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f }; |
|
4860 |
|
4861 float CSSStyleSelector::fontSizeForKeyword(int keyword, bool quirksMode, bool fixed) const |
|
4862 { |
|
4863 Settings* settings = m_document->settings(); |
|
4864 if (!settings) |
|
4865 return 1.0f; |
|
4866 |
|
4867 int mediumSize = fixed ? settings->defaultFixedFontSize() : settings->defaultFontSize(); |
|
4868 if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) { |
|
4869 // Look up the entry in the table. |
|
4870 int row = mediumSize - fontSizeTableMin; |
|
4871 int col = (keyword - CSS_VAL_XX_SMALL); |
|
4872 return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[row][col]; |
|
4873 } |
|
4874 |
|
4875 // Value is outside the range of the table. Apply the scale factor instead. |
|
4876 float minLogicalSize = max(settings->minimumLogicalFontSize(), 1); |
|
4877 return max(fontSizeFactors[keyword - CSS_VAL_XX_SMALL]*mediumSize, minLogicalSize); |
|
4878 } |
|
4879 |
|
4880 float CSSStyleSelector::largerFontSize(float size, bool quirksMode) const |
|
4881 { |
|
4882 // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale up to |
|
4883 // the next size level. |
|
4884 return size * 1.2f; |
|
4885 } |
|
4886 |
|
4887 float CSSStyleSelector::smallerFontSize(float size, bool quirksMode) const |
|
4888 { |
|
4889 // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to |
|
4890 // the next size level. |
|
4891 return size / 1.2f; |
|
4892 } |
|
4893 |
|
4894 // color mapping code |
|
4895 struct ColorValue { |
|
4896 int css_value; |
|
4897 RGBA32 color; |
|
4898 }; |
|
4899 |
|
4900 static const ColorValue colorValues[] = { |
|
4901 { CSS_VAL_AQUA, 0xFF00FFFF }, |
|
4902 { CSS_VAL_BLACK, 0xFF000000 }, |
|
4903 { CSS_VAL_BLUE, 0xFF0000FF }, |
|
4904 { CSS_VAL_FUCHSIA, 0xFFFF00FF }, |
|
4905 { CSS_VAL_GRAY, 0xFF808080 }, |
|
4906 { CSS_VAL_GREEN, 0xFF008000 }, |
|
4907 { CSS_VAL_LIME, 0xFF00FF00 }, |
|
4908 { CSS_VAL_MAROON, 0xFF800000 }, |
|
4909 { CSS_VAL_NAVY, 0xFF000080 }, |
|
4910 { CSS_VAL_OLIVE, 0xFF808000 }, |
|
4911 { CSS_VAL_ORANGE, 0xFFFFA500 }, |
|
4912 { CSS_VAL_PURPLE, 0xFF800080 }, |
|
4913 { CSS_VAL_RED, 0xFFFF0000 }, |
|
4914 { CSS_VAL_SILVER, 0xFFC0C0C0 }, |
|
4915 { CSS_VAL_TEAL, 0xFF008080 }, |
|
4916 { CSS_VAL_WHITE, 0xFFFFFFFF }, |
|
4917 { CSS_VAL_YELLOW, 0xFFFFFF00 }, |
|
4918 { CSS_VAL_TRANSPARENT, 0x00000000 }, |
|
4919 { CSS_VAL_GREY, 0xFF808080 }, |
|
4920 { CSS_VAL_ACTIVEBORDER, 0xFFFFFFFF }, |
|
4921 { CSS_VAL_ACTIVECAPTION, 0xFFCCCCCC }, |
|
4922 { CSS_VAL_APPWORKSPACE, 0xFFFFFFFF }, |
|
4923 { CSS_VAL_BUTTONFACE, 0xFFC0C0C0 }, |
|
4924 { CSS_VAL_BUTTONHIGHLIGHT, 0xFFDDDDDD }, |
|
4925 { CSS_VAL_BUTTONSHADOW, 0xFF888888 }, |
|
4926 { CSS_VAL_BUTTONTEXT, 0xFF000000 }, |
|
4927 { CSS_VAL_CAPTIONTEXT, 0xFF000000 }, |
|
4928 { CSS_VAL_GRAYTEXT, 0xFF808080 }, |
|
4929 { CSS_VAL_HIGHLIGHT, 0xFFB5D5FF }, |
|
4930 { CSS_VAL_HIGHLIGHTTEXT, 0xFF000000 }, |
|
4931 { CSS_VAL_INACTIVEBORDER, 0xFFFFFFFF }, |
|
4932 { CSS_VAL_INACTIVECAPTION, 0xFFFFFFFF }, |
|
4933 { CSS_VAL_INACTIVECAPTIONTEXT, 0xFF7F7F7F }, |
|
4934 { CSS_VAL_INFOBACKGROUND, 0xFFFBFCC5 }, |
|
4935 { CSS_VAL_INFOTEXT, 0xFF000000 }, |
|
4936 { CSS_VAL_MENU, 0xFFC0C0C0 }, |
|
4937 { CSS_VAL_MENUTEXT, 0xFF000000 }, |
|
4938 { CSS_VAL_SCROLLBAR, 0xFFFFFFFF }, |
|
4939 { CSS_VAL_TEXT, 0xFF000000 }, |
|
4940 { CSS_VAL_THREEDDARKSHADOW, 0xFF666666 }, |
|
4941 { CSS_VAL_THREEDFACE, 0xFFC0C0C0 }, |
|
4942 { CSS_VAL_THREEDHIGHLIGHT, 0xFFDDDDDD }, |
|
4943 { CSS_VAL_THREEDLIGHTSHADOW, 0xFFC0C0C0 }, |
|
4944 { CSS_VAL_THREEDSHADOW, 0xFF888888 }, |
|
4945 { CSS_VAL_WINDOW, 0xFFFFFFFF }, |
|
4946 { CSS_VAL_WINDOWFRAME, 0xFFCCCCCC }, |
|
4947 { CSS_VAL_WINDOWTEXT, 0xFF000000 }, |
|
4948 { 0, 0 } |
|
4949 }; |
|
4950 |
|
4951 |
|
4952 static Color colorForCSSValue(int css_value) |
|
4953 { |
|
4954 for (const ColorValue* col = colorValues; col->css_value; ++col) |
|
4955 if (col->css_value == css_value) |
|
4956 return col->color; |
|
4957 return Color(); |
|
4958 } |
|
4959 |
|
4960 Color CSSStyleSelector::getColorFromPrimitiveValue(CSSPrimitiveValue* primitiveValue) |
|
4961 { |
|
4962 Color col; |
|
4963 int ident = primitiveValue->getIdent(); |
|
4964 if (ident) { |
|
4965 if (ident == CSS_VAL__WEBKIT_TEXT) |
|
4966 col = element->document()->textColor(); |
|
4967 else if (ident == CSS_VAL__WEBKIT_LINK) { |
|
4968 Color linkColor = element->document()->linkColor(); |
|
4969 Color visitedColor = element->document()->visitedLinkColor(); |
|
4970 if (linkColor == visitedColor) |
|
4971 col = linkColor; |
|
4972 else { |
|
4973 if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink) |
|
4974 checkPseudoState(element); |
|
4975 col = (pseudoState == PseudoLink) ? linkColor : visitedColor; |
|
4976 } |
|
4977 } else if (ident == CSS_VAL__WEBKIT_ACTIVELINK) |
|
4978 col = element->document()->activeLinkColor(); |
|
4979 else if (ident == CSS_VAL__WEBKIT_FOCUS_RING_COLOR) |
|
4980 col = focusRingColor(); |
|
4981 else |
|
4982 col = colorForCSSValue(ident); |
|
4983 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR) |
|
4984 col.setRGB(primitiveValue->getRGBColorValue()); |
|
4985 return col; |
|
4986 } |
|
4987 |
|
4988 bool CSSStyleSelector::hasSelectorForAttribute(const AtomicString &attrname) |
|
4989 { |
|
4990 return m_selectorAttrs.contains(attrname.impl()); |
|
4991 } |
|
4992 |
|
4993 } // namespace WebCore |