qcssparser.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/text/qcssparser.cpp
Switch to Source codePreprocessed file
LineSourceCount
1-
2-
3-
4-
5-
6-
7-
8-
9-
10using namespace QCss;-
11-
12struct QCssKnownValue-
13{-
14 const char name[28];-
15 quint64 id;-
16};-
17-
18static const QCssKnownValue properties[NumProperties - 1] = {-
19 { "-qt-background-role", QtBackgroundRole },-
20 { "-qt-block-indent", QtBlockIndent },-
21 { "-qt-line-height-type", QtLineHeightType },-
22 { "-qt-list-indent", QtListIndent },-
23 { "-qt-list-number-prefix", QtListNumberPrefix },-
24 { "-qt-list-number-suffix", QtListNumberSuffix },-
25 { "-qt-paragraph-type", QtParagraphType },-
26 { "-qt-style-features", QtStyleFeatures },-
27 { "-qt-table-type", QtTableType },-
28 { "-qt-user-state", QtUserState },-
29 { "alternate-background-color", QtAlternateBackground },-
30 { "background", Background },-
31 { "background-attachment", BackgroundAttachment },-
32 { "background-clip", BackgroundClip },-
33 { "background-color", BackgroundColor },-
34 { "background-image", BackgroundImage },-
35 { "background-origin", BackgroundOrigin },-
36 { "background-position", BackgroundPosition },-
37 { "background-repeat", BackgroundRepeat },-
38 { "border", Border },-
39 { "border-bottom", BorderBottom },-
40 { "border-bottom-color", BorderBottomColor },-
41 { "border-bottom-left-radius", BorderBottomLeftRadius },-
42 { "border-bottom-right-radius", BorderBottomRightRadius },-
43 { "border-bottom-style", BorderBottomStyle },-
44 { "border-bottom-width", BorderBottomWidth },-
45 { "border-color", BorderColor },-
46 { "border-image", BorderImage },-
47 { "border-left", BorderLeft },-
48 { "border-left-color", BorderLeftColor },-
49 { "border-left-style", BorderLeftStyle },-
50 { "border-left-width", BorderLeftWidth },-
51 { "border-radius", BorderRadius },-
52 { "border-right", BorderRight },-
53 { "border-right-color", BorderRightColor },-
54 { "border-right-style", BorderRightStyle },-
55 { "border-right-width", BorderRightWidth },-
56 { "border-style", BorderStyles },-
57 { "border-top", BorderTop },-
58 { "border-top-color", BorderTopColor },-
59 { "border-top-left-radius", BorderTopLeftRadius },-
60 { "border-top-right-radius", BorderTopRightRadius },-
61 { "border-top-style", BorderTopStyle },-
62 { "border-top-width", BorderTopWidth },-
63 { "border-width", BorderWidth },-
64 { "bottom", Bottom },-
65 { "color", Color },-
66 { "float", Float },-
67 { "font", Font },-
68 { "font-family", FontFamily },-
69 { "font-size", FontSize },-
70 { "font-style", FontStyle },-
71 { "font-variant", FontVariant },-
72 { "font-weight", FontWeight },-
73 { "height", Height },-
74 { "image", QtImage },-
75 { "image-position", QtImageAlignment },-
76 { "left", Left },-
77 { "line-height", LineHeight },-
78 { "list-style", ListStyle },-
79 { "list-style-type", ListStyleType },-
80 { "margin" , Margin },-
81 { "margin-bottom", MarginBottom },-
82 { "margin-left", MarginLeft },-
83 { "margin-right", MarginRight },-
84 { "margin-top", MarginTop },-
85 { "max-height", MaximumHeight },-
86 { "max-width", MaximumWidth },-
87 { "min-height", MinimumHeight },-
88 { "min-width", MinimumWidth },-
89 { "outline", Outline },-
90 { "outline-bottom-left-radius", OutlineBottomLeftRadius },-
91 { "outline-bottom-right-radius", OutlineBottomRightRadius },-
92 { "outline-color", OutlineColor },-
93 { "outline-offset", OutlineOffset },-
94 { "outline-radius", OutlineRadius },-
95 { "outline-style", OutlineStyle },-
96 { "outline-top-left-radius", OutlineTopLeftRadius },-
97 { "outline-top-right-radius", OutlineTopRightRadius },-
98 { "outline-width", OutlineWidth },-
99 { "padding", Padding },-
100 { "padding-bottom", PaddingBottom },-
101 { "padding-left", PaddingLeft },-
102 { "padding-right", PaddingRight },-
103 { "padding-top", PaddingTop },-
104 { "page-break-after", PageBreakAfter },-
105 { "page-break-before", PageBreakBefore },-
106 { "position", Position },-
107 { "right", Right },-
108 { "selection-background-color", QtSelectionBackground },-
109 { "selection-color", QtSelectionForeground },-
110 { "spacing", QtSpacing },-
111 { "subcontrol-origin", QtOrigin },-
112 { "subcontrol-position", QtPosition },-
113 { "text-align", TextAlignment },-
114 { "text-decoration", TextDecoration },-
115 { "text-indent", TextIndent },-
116 { "text-transform", TextTransform },-
117 { "text-underline-style", TextUnderlineStyle },-
118 { "top", Top },-
119 { "vertical-align", VerticalAlignment },-
120 { "white-space", Whitespace },-
121 { "width", Width }-
122};-
123-
124static const QCssKnownValue values[NumKnownValues - 1] = {-
125 { "active", Value_Active },-
126 { "alternate-base", Value_AlternateBase },-
127 { "always", Value_Always },-
128 { "auto", Value_Auto },-
129 { "base", Value_Base },-
130 { "bold", Value_Bold },-
131 { "bottom", Value_Bottom },-
132 { "bright-text", Value_BrightText },-
133 { "button", Value_Button },-
134 { "button-text", Value_ButtonText },-
135 { "center", Value_Center },-
136 { "circle", Value_Circle },-
137 { "dark", Value_Dark },-
138 { "dashed", Value_Dashed },-
139 { "decimal", Value_Decimal },-
140 { "disabled", Value_Disabled },-
141 { "disc", Value_Disc },-
142 { "dot-dash", Value_DotDash },-
143 { "dot-dot-dash", Value_DotDotDash },-
144 { "dotted", Value_Dotted },-
145 { "double", Value_Double },-
146 { "groove", Value_Groove },-
147 { "highlight", Value_Highlight },-
148 { "highlighted-text", Value_HighlightedText },-
149 { "inset", Value_Inset },-
150 { "italic", Value_Italic },-
151 { "large", Value_Large },-
152 { "left", Value_Left },-
153 { "light", Value_Light },-
154 { "line-through", Value_LineThrough },-
155 { "link", Value_Link },-
156 { "link-visited", Value_LinkVisited },-
157 { "lower-alpha", Value_LowerAlpha },-
158 { "lower-roman", Value_LowerRoman },-
159 { "lowercase", Value_Lowercase },-
160 { "medium", Value_Medium },-
161 { "mid", Value_Mid },-
162 { "middle", Value_Middle },-
163 { "midlight", Value_Midlight },-
164 { "native", Value_Native },-
165 { "none", Value_None },-
166 { "normal", Value_Normal },-
167 { "nowrap", Value_NoWrap },-
168 { "oblique", Value_Oblique },-
169 { "off", Value_Off },-
170 { "on", Value_On },-
171 { "outset", Value_Outset },-
172 { "overline", Value_Overline },-
173 { "pre", Value_Pre },-
174 { "pre-wrap", Value_PreWrap },-
175 { "ridge", Value_Ridge },-
176 { "right", Value_Right },-
177 { "selected", Value_Selected },-
178 { "shadow", Value_Shadow },-
179 { "small" , Value_Small },-
180 { "small-caps", Value_SmallCaps },-
181 { "solid", Value_Solid },-
182 { "square", Value_Square },-
183 { "sub", Value_Sub },-
184 { "super", Value_Super },-
185 { "text", Value_Text },-
186 { "top", Value_Top },-
187 { "transparent", Value_Transparent },-
188 { "underline", Value_Underline },-
189 { "upper-alpha", Value_UpperAlpha },-
190 { "upper-roman", Value_UpperRoman },-
191 { "uppercase", Value_Uppercase },-
192 { "wave", Value_Wave },-
193 { "window", Value_Window },-
194 { "window-text", Value_WindowText },-
195 { "x-large", Value_XLarge },-
196 { "xx-large", Value_XXLarge }-
197};-
198-
199-
200static const short indexOfId[NumKnownValues] = { 0, 41, 48, 42, 49, 54, 35, 26, 70, 71, 25, 43, 5, 63, 47,-
201 29, 58, 59, 27, 51, 61, 6, 10, 39, 56, 19, 13, 17, 18, 20, 21, 50, 24, 46, 67, 37, 3, 2, 40, 62, 16,-
202 11, 57, 14, 32, 64, 33, 65, 55, 66, 34, 69, 8, 28, 38, 12, 36, 60, 7, 9, 4, 68, 53, 22, 23, 30, 31,-
203 1, 15, 0, 52, 45, 44 };-
204-
205QString Value::toString() const-
206{-
207 if (type == KnownIdentifier) {-
208 return QLatin1String(values[indexOfId[variant.toInt()]].name);-
209 } else {-
210 return variant.toString();-
211 }-
212}-
213-
214static const QCssKnownValue pseudos[NumPseudos - 1] = {-
215 { "active", PseudoClass_Active },-
216 { "adjoins-item", PseudoClass_Item },-
217 { "alternate", PseudoClass_Alternate },-
218 { "bottom", PseudoClass_Bottom },-
219 { "checked", PseudoClass_Checked },-
220 { "closable", PseudoClass_Closable },-
221 { "closed", PseudoClass_Closed },-
222 { "default", PseudoClass_Default },-
223 { "disabled", PseudoClass_Disabled },-
224 { "edit-focus", PseudoClass_EditFocus },-
225 { "editable", PseudoClass_Editable },-
226 { "enabled", PseudoClass_Enabled },-
227 { "exclusive", PseudoClass_Exclusive },-
228 { "first", PseudoClass_First },-
229 { "flat", PseudoClass_Flat },-
230 { "floatable", PseudoClass_Floatable },-
231 { "focus", PseudoClass_Focus },-
232 { "has-children", PseudoClass_Children },-
233 { "has-siblings", PseudoClass_Sibling },-
234 { "horizontal", PseudoClass_Horizontal },-
235 { "hover", PseudoClass_Hover },-
236 { "indeterminate" , PseudoClass_Indeterminate },-
237 { "last", PseudoClass_Last },-
238 { "left", PseudoClass_Left },-
239 { "maximized", PseudoClass_Maximized },-
240 { "middle", PseudoClass_Middle },-
241 { "minimized", PseudoClass_Minimized },-
242 { "movable", PseudoClass_Movable },-
243 { "next-selected", PseudoClass_NextSelected },-
244 { "no-frame", PseudoClass_Frameless },-
245 { "non-exclusive", PseudoClass_NonExclusive },-
246 { "off", PseudoClass_Unchecked },-
247 { "on", PseudoClass_Checked },-
248 { "only-one", PseudoClass_OnlyOne },-
249 { "open", PseudoClass_Open },-
250 { "pressed", PseudoClass_Pressed },-
251 { "previous-selected", PseudoClass_PreviousSelected },-
252 { "read-only", PseudoClass_ReadOnly },-
253 { "right", PseudoClass_Right },-
254 { "selected", PseudoClass_Selected },-
255 { "top", PseudoClass_Top },-
256 { "unchecked" , PseudoClass_Unchecked },-
257 { "vertical", PseudoClass_Vertical },-
258 { "window", PseudoClass_Window }-
259};-
260-
261static const QCssKnownValue origins[NumKnownOrigins - 1] = {-
262 { "border", Origin_Border },-
263 { "content", Origin_Content },-
264 { "margin", Origin_Margin },-
265 { "padding", Origin_Padding }-
266};-
267-
268static const QCssKnownValue repeats[NumKnownRepeats - 1] = {-
269 { "no-repeat", Repeat_None },-
270 { "repeat-x", Repeat_X },-
271 { "repeat-xy", Repeat_XY },-
272 { "repeat-y", Repeat_Y }-
273};-
274-
275static const QCssKnownValue tileModes[NumKnownTileModes - 1] = {-
276 { "repeat", TileMode_Repeat },-
277 { "round", TileMode_Round },-
278 { "stretch", TileMode_Stretch },-
279};-
280-
281static const QCssKnownValue positions[NumKnownPositionModes - 1] = {-
282 { "absolute", PositionMode_Absolute },-
283 { "fixed", PositionMode_Fixed },-
284 { "relative", PositionMode_Relative },-
285 { "static", PositionMode_Static }-
286};-
287-
288static const QCssKnownValue attachments[NumKnownAttachments - 1] = {-
289 { "fixed", Attachment_Fixed },-
290 { "scroll", Attachment_Scroll }-
291};-
292-
293static const QCssKnownValue styleFeatures[NumKnownStyleFeatures - 1] = {-
294 { "background-color", StyleFeature_BackgroundColor },-
295 { "background-gradient", StyleFeature_BackgroundGradient },-
296 { "none", StyleFeature_None }-
297};-
298static bool operator<(const QString &name, const QCssKnownValue &prop)-
299{-
300 return QString::compare(name, QLatin1String(prop.name), Qt::CaseInsensitive) < 0;-
301}-
302-
303static bool operator<(const QCssKnownValue &prop, const QString &name)-
304{-
305 return QString::compare(QLatin1String(prop.name), name, Qt::CaseInsensitive) < 0;-
306}-
307-
308static quint64 findKnownValue(const QString &name, const QCssKnownValue *start, int numValues)-
309{-
310 const QCssKnownValue *end = &start[numValues - 1];-
311 const QCssKnownValue *prop = std::lower_bound(start, end, name);-
312 if ((prop == end) || (name < *prop))-
313 return 0;-
314 return prop->id;-
315}-
316-
317static inline bool isInheritable(Property propertyId)-
318{-
319 switch (propertyId) {-
320 case Font:-
321 case FontFamily:-
322 case FontSize:-
323 case FontStyle:-
324 case FontWeight:-
325 case TextIndent:-
326 case Whitespace:-
327 case ListStyleType:-
328 case ListStyle:-
329 case TextAlignment:-
330 case FontVariant:-
331 case TextTransform:-
332 case LineHeight:-
333 return true;-
334 default:-
335 break;-
336 }-
337 return false;-
338}-
339-
340-
341-
342ValueExtractor::ValueExtractor(const QVector<Declaration> &decls, const QPalette &pal)-
343: declarations(decls), adjustment(0), fontExtracted(false), pal(pal)-
344{-
345}-
346-
347LengthData ValueExtractor::lengthValue(const Value& v)-
348{-
349 QString s = v.variant.toString();-
350 s.reserve(s.length());-
351 LengthData data;-
352 data.unit = LengthData::None;-
353 if (s.endsWith(QLatin1String("px"), Qt::CaseInsensitive))-
354 data.unit = LengthData::Px;-
355 else if (s.endsWith(QLatin1String("ex"), Qt::CaseInsensitive))-
356 data.unit = LengthData::Ex;-
357 else if (s.endsWith(QLatin1String("em"), Qt::CaseInsensitive))-
358 data.unit = LengthData::Em;-
359-
360 if (data.unit != LengthData::None)-
361 s.chop(2);-
362-
363 data.number = s.toDouble();-
364 return data;-
365}-
366-
367static int lengthValueFromData(const LengthData& data, const QFont& f)-
368{-
369 if (data.unit == LengthData::Ex)-
370 return qRound(QFontMetrics(f).xHeight() * data.number);-
371 else if (data.unit == LengthData::Em)-
372 return qRound(QFontMetrics(f).height() * data.number);-
373 return qRound(data.number);-
374}-
375-
376int ValueExtractor::lengthValue(const Declaration &decl)-
377{-
378 if (decl.d->parsed.isValid())-
379 return lengthValueFromData(qvariant_cast<LengthData>(decl.d->parsed), f);-
380 if (decl.d->values.count() < 1)-
381 return 0;-
382 LengthData data = lengthValue(decl.d->values.at(0));-
383 decl.d->parsed = QVariant::fromValue<LengthData>(data);-
384 return lengthValueFromData(data,f);-
385}-
386-
387void ValueExtractor::lengthValues(const Declaration &decl, int *m)-
388{-
389 if (decl.d->parsed.isValid()) {-
390 QList<QVariant> v = decl.d->parsed.toList();-
391 for (int i = 0; i < 4; i++)-
392 m[i] = lengthValueFromData(qvariant_cast<LengthData>(v.at(i)), f);-
393 return;-
394 }-
395-
396 LengthData datas[4];-
397 int i;-
398 for (i = 0; i < qMin(decl.d->values.count(), 4); i++)-
399 datas[i] = lengthValue(decl.d->values[i]);-
400-
401 if (i == 0) {-
402 LengthData zero = {0.0, LengthData::None};-
403 datas[0] = datas[1] = datas[2] = datas[3] = zero;-
404 } else if (i == 1) {-
405 datas[3] = datas[2] = datas[1] = datas[0];-
406 } else if (i == 2) {-
407 datas[2] = datas[0];-
408 datas[3] = datas[1];-
409 } else if (i == 3) {-
410 datas[3] = datas[1];-
411 }-
412-
413 QList<QVariant> v;-
414 v.reserve(4);-
415 for (i = 0; i < 4; i++) {-
416 v += QVariant::fromValue<LengthData>(datas[i]);-
417 m[i] = lengthValueFromData(datas[i], f);-
418 }-
419 decl.d->parsed = v;-
420}-
421-
422bool ValueExtractor::extractGeometry(int *w, int *h, int *minw, int *minh, int *maxw, int *maxh)-
423{-
424 extractFont();-
425 bool hit = false;-
426 for (int i = 0; i < declarations.count(); i++) {-
427 const Declaration &decl = declarations.at(i);-
428 switch (decl.d->propertyId) {-
429 case Width: *w = lengthValue(decl); break;-
430 case Height: *h = lengthValue(decl); break;-
431 case MinimumWidth: *minw = lengthValue(decl); break;-
432 case MinimumHeight: *minh = lengthValue(decl); break;-
433 case MaximumWidth: *maxw = lengthValue(decl); break;-
434 case MaximumHeight: *maxh = lengthValue(decl); break;-
435 default: continue;-
436 }-
437 hit = true;-
438 }-
439-
440 return hit;-
441}-
442-
443bool ValueExtractor::extractPosition(int *left, int *top, int *right, int *bottom, QCss::Origin *origin,-
444 Qt::Alignment *position, QCss::PositionMode *mode, Qt::Alignment *textAlignment)-
445{-
446 extractFont();-
447 bool hit = false;-
448 for (int i = 0; i < declarations.count(); i++) {-
449 const Declaration &decl = declarations.at(i);-
450 switch (decl.d->propertyId) {-
451 case Left: *left = lengthValue(decl); break;-
452 case Top: *top = lengthValue(decl); break;-
453 case Right: *right = lengthValue(decl); break;-
454 case Bottom: *bottom = lengthValue(decl); break;-
455 case QtOrigin: *origin = decl.originValue(); break;-
456 case QtPosition: *position = decl.alignmentValue(); break;-
457 case TextAlignment: *textAlignment = decl.alignmentValue(); break;-
458 case Position: *mode = decl.positionValue(); break;-
459 default: continue;-
460 }-
461 hit = true;-
462 }-
463-
464 return hit;-
465}-
466-
467bool ValueExtractor::extractBox(int *margins, int *paddings, int *spacing)-
468{-
469 extractFont();-
470 bool hit = false;-
471 for (int i = 0; i < declarations.count(); i++) {-
472 const Declaration &decl = declarations.at(i);-
473 switch (decl.d->propertyId) {-
474 case PaddingLeft: paddings[LeftEdge] = lengthValue(decl); break;-
475 case PaddingRight: paddings[RightEdge] = lengthValue(decl); break;-
476 case PaddingTop: paddings[TopEdge] = lengthValue(decl); break;-
477 case PaddingBottom: paddings[BottomEdge] = lengthValue(decl); break;-
478 case Padding: lengthValues(decl, paddings); break;-
479-
480 case MarginLeft: margins[LeftEdge] = lengthValue(decl); break;-
481 case MarginRight: margins[RightEdge] = lengthValue(decl); break;-
482 case MarginTop: margins[TopEdge] = lengthValue(decl); break;-
483 case MarginBottom: margins[BottomEdge] = lengthValue(decl); break;-
484 case Margin: lengthValues(decl, margins); break;-
485 case QtSpacing: if (spacing) *spacing = lengthValue(decl); break;-
486-
487 default: continue;-
488 }-
489 hit = true;-
490 }-
491-
492 return hit;-
493}-
494-
495int ValueExtractor::extractStyleFeatures()-
496{-
497 int features = StyleFeature_None;-
498 for (int i = 0; i < declarations.count(); i++) {-
499 const Declaration &decl = declarations.at(i);-
500 if (decl.d->propertyId == QtStyleFeatures)-
501 features = decl.styleFeaturesValue();-
502 }-
503 return features;-
504}-
505-
506QSize ValueExtractor::sizeValue(const Declaration &decl)-
507{-
508 if (decl.d->parsed.isValid()) {-
509 QList<QVariant> v = decl.d->parsed.toList();-
510 return QSize(lengthValueFromData(qvariant_cast<LengthData>(v.at(0)), f),-
511 lengthValueFromData(qvariant_cast<LengthData>(v.at(1)), f));-
512 }-
513-
514 LengthData x[2] = { {0, LengthData::None }, {0, LengthData::None} };-
515 if (decl.d->values.count() > 0)-
516 x[0] = lengthValue(decl.d->values.at(0));-
517 if (decl.d->values.count() > 1)-
518 x[1] = lengthValue(decl.d->values.at(1));-
519 else-
520 x[1] = x[0];-
521 QList<QVariant> v;-
522 v << QVariant::fromValue<LengthData>(x[0]) << QVariant::fromValue<LengthData>(x[1]);-
523 decl.d->parsed = v;-
524 return QSize(lengthValueFromData(x[0], f), lengthValueFromData(x[1], f));-
525}-
526-
527void ValueExtractor::sizeValues(const Declaration &decl, QSize *radii)-
528{-
529 radii[0] = sizeValue(decl);-
530 for (int i = 1; i < 4; i++)-
531 radii[i] = radii[0];-
532}-
533-
534bool ValueExtractor::extractBorder(int *borders, QBrush *colors, BorderStyle *styles,-
535 QSize *radii)-
536{-
537 extractFont();-
538 bool hit = false;-
539 for (int i = 0; i < declarations.count(); i++) {-
540 const Declaration &decl = declarations.at(i);-
541 switch (decl.d->propertyId) {-
542 case BorderLeftWidth: borders[LeftEdge] = lengthValue(decl); break;-
543 case BorderRightWidth: borders[RightEdge] = lengthValue(decl); break;-
544 case BorderTopWidth: borders[TopEdge] = lengthValue(decl); break;-
545 case BorderBottomWidth: borders[BottomEdge] = lengthValue(decl); break;-
546 case BorderWidth: lengthValues(decl, borders); break;-
547-
548 case BorderLeftColor: colors[LeftEdge] = decl.brushValue(pal); break;-
549 case BorderRightColor: colors[RightEdge] = decl.brushValue(pal); break;-
550 case BorderTopColor: colors[TopEdge] = decl.brushValue(pal); break;-
551 case BorderBottomColor: colors[BottomEdge] = decl.brushValue(pal); break;-
552 case BorderColor: decl.brushValues(colors, pal); break;-
553-
554 case BorderTopStyle: styles[TopEdge] = decl.styleValue(); break;-
555 case BorderBottomStyle: styles[BottomEdge] = decl.styleValue(); break;-
556 case BorderLeftStyle: styles[LeftEdge] = decl.styleValue(); break;-
557 case BorderRightStyle: styles[RightEdge] = decl.styleValue(); break;-
558 case BorderStyles: decl.styleValues(styles); break;-
559-
560-
561 case BorderTopLeftRadius: radii[0] = sizeValue(decl); break;-
562-
563-
564-
565 case BorderTopRightRadius: radii[1] = sizeValue(decl); break;-
566 case BorderBottomLeftRadius: radii[2] = sizeValue(decl); break;-
567 case BorderBottomRightRadius: radii[3] = sizeValue(decl); break;-
568 case BorderRadius: sizeValues(decl, radii); break;-
569-
570 case BorderLeft:-
571 borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]);-
572 break;-
573 case BorderTop:-
574 borderValue(decl, &borders[TopEdge], &styles[TopEdge], &colors[TopEdge]);-
575 break;-
576 case BorderRight:-
577 borderValue(decl, &borders[RightEdge], &styles[RightEdge], &colors[RightEdge]);-
578 break;-
579 case BorderBottom:-
580 borderValue(decl, &borders[BottomEdge], &styles[BottomEdge], &colors[BottomEdge]);-
581 break;-
582 case Border:-
583 borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]);-
584 borders[TopEdge] = borders[RightEdge] = borders[BottomEdge] = borders[LeftEdge];-
585 styles[TopEdge] = styles[RightEdge] = styles[BottomEdge] = styles[LeftEdge];-
586 colors[TopEdge] = colors[RightEdge] = colors[BottomEdge] = colors[LeftEdge];-
587 break;-
588-
589 default: continue;-
590 }-
591 hit = true;-
592 }-
593-
594 return hit;-
595}-
596-
597bool ValueExtractor::extractOutline(int *borders, QBrush *colors, BorderStyle *styles,-
598 QSize *radii, int *offsets)-
599{-
600 extractFont();-
601 bool hit = false;-
602 for (int i = 0; i < declarations.count(); i++) {-
603 const Declaration &decl = declarations.at(i);-
604 switch (decl.d->propertyId) {-
605 case OutlineWidth: lengthValues(decl, borders); break;-
606 case OutlineColor: decl.brushValues(colors, pal); break;-
607 case OutlineStyle: decl.styleValues(styles); break;-
608-
609 case OutlineTopLeftRadius: radii[0] = sizeValue(decl); break;-
610 case OutlineTopRightRadius: radii[1] = sizeValue(decl); break;-
611 case OutlineBottomLeftRadius: radii[2] = sizeValue(decl); break;-
612 case OutlineBottomRightRadius: radii[3] = sizeValue(decl); break;-
613 case OutlineRadius: sizeValues(decl, radii); break;-
614 case OutlineOffset: lengthValues(decl, offsets); break;-
615-
616 case Outline:-
617 borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]);-
618 borders[TopEdge] = borders[RightEdge] = borders[BottomEdge] = borders[LeftEdge];-
619 styles[TopEdge] = styles[RightEdge] = styles[BottomEdge] = styles[LeftEdge];-
620 colors[TopEdge] = colors[RightEdge] = colors[BottomEdge] = colors[LeftEdge];-
621 break;-
622-
623 default: continue;-
624 }-
625 hit = true;-
626 }-
627-
628 return hit;-
629}-
630-
631static Qt::Alignment parseAlignment(const QCss::Value *values, int count)-
632{-
633 Qt::Alignment a[2] = { 0, 0 };-
634 for (int i = 0; i < qMin(2, count); i++) {-
635 if (values[i].type != Value::KnownIdentifier)-
636 break;-
637 switch (values[i].variant.toInt()) {-
638 case Value_Left: a[i] = Qt::AlignLeft; break;-
639 case Value_Right: a[i] = Qt::AlignRight; break;-
640 case Value_Top: a[i] = Qt::AlignTop; break;-
641 case Value_Bottom: a[i] = Qt::AlignBottom; break;-
642 case Value_Center: a[i] = Qt::AlignCenter; break;-
643 default: break;-
644 }-
645 }-
646-
647 if (a[0] == Qt::AlignCenter && a[1] != 0 && a[1] != Qt::AlignCenter)-
648 a[0] = (a[1] == Qt::AlignLeft || a[1] == Qt::AlignRight) ? Qt::AlignVCenter : Qt::AlignHCenter;-
649 if ((a[1] == 0 || a[1] == Qt::AlignCenter) && a[0] != Qt::AlignCenter)-
650 a[1] = (a[0] == Qt::AlignLeft || a[0] == Qt::AlignRight) ? Qt::AlignVCenter : Qt::AlignHCenter;-
651 return a[0] | a[1];-
652}-
653-
654static ColorData parseColorValue(QCss::Value v)-
655{-
656 if (v.type == Value::Identifier || v.type == Value::String) {-
657 v.variant.convert(QVariant::Color);-
658 v.type = Value::Color;-
659 }-
660-
661 if (v.type == Value::Color)-
662 return qvariant_cast<QColor>(v.variant);-
663-
664 if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_Transparent)-
665 return QColor(Qt::transparent);-
666-
667 if (v.type != Value::Function)-
668 return ColorData();-
669-
670 QStringList lst = v.variant.toStringList();-
671 if (lst.count() != 2)-
672 return ColorData();-
673-
674 if ((lst.at(0).compare(QLatin1String("palette"), Qt::CaseInsensitive)) == 0) {-
675 int role = findKnownValue(lst.at(1).trimmed(), values, NumKnownValues);-
676 if (role >= Value_FirstColorRole && role <= Value_LastColorRole)-
677 return (QPalette::ColorRole)(role-Value_FirstColorRole);-
678-
679 return ColorData();-
680 }-
681-
682 bool rgb = lst.at(0).startsWith(QLatin1String("rgb"));-
683 bool rgba = lst.at(0).startsWith(QLatin1String("rgba"));-
684-
685 Parser p(lst.at(1));-
686 if (!p.testExpr())-
687 return ColorData();-
688-
689 QVector<QCss::Value> colorDigits;-
690 if (!p.parseExpr(&colorDigits))-
691 return ColorData();-
692 const int tokenCount = colorDigits.count();-
693-
694 for (int i = 0; i < qMin(tokenCount, 7); i += 2) {-
695 if (colorDigits.at(i).type == Value::Percentage) {-
696 colorDigits[i].variant = colorDigits.at(i).variant.toReal() * (255. / 100.);-
697 colorDigits[i].type = Value::Number;-
698 } else if (colorDigits.at(i).type != Value::Number) {-
699 return ColorData();-
700 }-
701 }-
702-
703-
704 if (tokenCount < 5)-
705 return ColorData();-
706-
707 int v1 = colorDigits.at(0).variant.toInt();-
708 int v2 = colorDigits.at(2).variant.toInt();-
709 int v3 = colorDigits.at(4).variant.toInt();-
710 int alpha = 255;-
711 if (tokenCount >= 7) {-
712 int alphaValue = colorDigits.at(6).variant.toInt();-
713 if (rgba && alphaValue <= 1)-
714 alpha = colorDigits.at(6).variant.toReal() * 255.;-
715 else-
716 alpha = alphaValue;-
717 }-
718-
719 return rgb ? QColor::fromRgb(v1, v2, v3, alpha)-
720 : QColor::fromHsv(v1, v2, v3, alpha);-
721}-
722-
723static QColor colorFromData(const ColorData& c, const QPalette &pal)-
724{-
725 if (c.type == ColorData::Color) {-
726 return c.color;-
727 } else if (c.type == ColorData::Role) {-
728 return pal.color(c.role);-
729 }-
730 return QColor();-
731}-
732-
733static BrushData parseBrushValue(const QCss::Value &v, const QPalette &pal)-
734{-
735 ColorData c = parseColorValue(v);-
736 if (c.type == ColorData::Color) {-
737 return QBrush(c.color);-
738 } else if (c.type == ColorData::Role) {-
739 return c.role;-
740 }-
741-
742 if (v.type != Value::Function)-
743 return BrushData();-
744-
745 QStringList lst = v.variant.toStringList();-
746 if (lst.count() != 2)-
747 return BrushData();-
748-
749 QStringList gradFuncs;-
750 gradFuncs << QLatin1String("qlineargradient") << QLatin1String("qradialgradient") << QLatin1String("qconicalgradient") << QLatin1String("qgradient");-
751 int gradType = -1;-
752-
753 if ((gradType = gradFuncs.indexOf(lst.at(0).toLower())) == -1)-
754 return BrushData();-
755-
756 QHash<QString, qreal> vars;-
757 QVector<QGradientStop> stops;-
758-
759 int spread = -1;-
760 QStringList spreads;-
761 spreads << QLatin1String("pad") << QLatin1String("reflect") << QLatin1String("repeat");-
762-
763 bool dependsOnThePalette = false;-
764 Parser parser(lst.at(1));-
765 while (parser.hasNext()) {-
766 parser.skipSpace();-
767 if (!parser.test(IDENT))-
768 return BrushData();-
769 QString attr = parser.lexem();-
770 parser.skipSpace();-
771 if (!parser.test(COLON))-
772 return BrushData();-
773 parser.skipSpace();-
774 if (attr.compare(QLatin1String("stop"), Qt::CaseInsensitive) == 0) {-
775 QCss::Value stop, color;-
776 parser.next();-
777 if (!parser.parseTerm(&stop)) return BrushData();-
778 parser.skipSpace();-
779 parser.next();-
780 if (!parser.parseTerm(&color)) return BrushData();-
781 ColorData cd = parseColorValue(color);-
782 if(cd.type == ColorData::Role)-
783 dependsOnThePalette = true;-
784 stops.append(QGradientStop(stop.variant.toReal(), colorFromData(cd, pal)));-
785 } else {-
786 parser.next();-
787 QCss::Value value;-
788 (void)parser.parseTerm(&value);-
789 if (attr.compare(QLatin1String("spread"), Qt::CaseInsensitive) == 0) {-
790 spread = spreads.indexOf(value.variant.toString());-
791 } else {-
792 vars[attr] = value.variant.toReal();-
793 }-
794 }-
795 parser.skipSpace();-
796 (void)parser.test(COMMA);-
797 }-
798-
799 if (gradType == 0) {-
800 QLinearGradient lg(vars.value(QLatin1String("x1")), vars.value(QLatin1String("y1")),-
801 vars.value(QLatin1String("x2")), vars.value(QLatin1String("y2")));-
802 lg.setCoordinateMode(QGradient::ObjectBoundingMode);-
803 lg.setStops(stops);-
804 if (spread != -1)-
805 lg.setSpread(QGradient::Spread(spread));-
806 BrushData bd = QBrush(lg);-
807 if (dependsOnThePalette)-
808 bd.type = BrushData::DependsOnThePalette;-
809 return bd;-
810 }-
811-
812 if (gradType == 1) {-
813 QRadialGradient rg(vars.value(QLatin1String("cx")), vars.value(QLatin1String("cy")),-
814 vars.value(QLatin1String("radius")), vars.value(QLatin1String("fx")),-
815 vars.value(QLatin1String("fy")));-
816 rg.setCoordinateMode(QGradient::ObjectBoundingMode);-
817 rg.setStops(stops);-
818 if (spread != -1)-
819 rg.setSpread(QGradient::Spread(spread));-
820 BrushData bd = QBrush(rg);-
821 if (dependsOnThePalette)-
822 bd.type = BrushData::DependsOnThePalette;-
823 return bd;-
824 }-
825-
826 if (gradType == 2) {-
827 QConicalGradient cg(vars.value(QLatin1String("cx")), vars.value(QLatin1String("cy")),-
828 vars.value(QLatin1String("angle")));-
829 cg.setCoordinateMode(QGradient::ObjectBoundingMode);-
830 cg.setStops(stops);-
831 if (spread != -1)-
832 cg.setSpread(QGradient::Spread(spread));-
833 BrushData bd = QBrush(cg);-
834 if (dependsOnThePalette)-
835 bd.type = BrushData::DependsOnThePalette;-
836 return bd;-
837 }-
838-
839 return BrushData();-
840}-
841-
842static QBrush brushFromData(const BrushData& c, const QPalette &pal)-
843{-
844 if (c.type == BrushData::Role) {-
845 return pal.color(c.role);-
846 } else {-
847 return c.brush;-
848 }-
849}-
850-
851static BorderStyle parseStyleValue(QCss::Value v)-
852{-
853 if (v.type == Value::KnownIdentifier) {-
854 switch (v.variant.toInt()) {-
855 case Value_None:-
856 return BorderStyle_None;-
857 case Value_Dotted:-
858 return BorderStyle_Dotted;-
859 case Value_Dashed:-
860 return BorderStyle_Dashed;-
861 case Value_Solid:-
862 return BorderStyle_Solid;-
863 case Value_Double:-
864 return BorderStyle_Double;-
865 case Value_DotDash:-
866 return BorderStyle_DotDash;-
867 case Value_DotDotDash:-
868 return BorderStyle_DotDotDash;-
869 case Value_Groove:-
870 return BorderStyle_Groove;-
871 case Value_Ridge:-
872 return BorderStyle_Ridge;-
873 case Value_Inset:-
874 return BorderStyle_Inset;-
875 case Value_Outset:-
876 return BorderStyle_Outset;-
877 case Value_Native:-
878 return BorderStyle_Native;-
879 default:-
880 break;-
881 }-
882 }-
883-
884 return BorderStyle_Unknown;-
885}-
886-
887void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::BorderStyle *style, QBrush *color)-
888{-
889 if (decl.d->parsed.isValid()) {-
890 BorderData data = qvariant_cast<BorderData>(decl.d->parsed);-
891 *width = lengthValueFromData(data.width, f);-
892 *style = data.style;-
893 *color = data.color.type != BrushData::Invalid ? brushFromData(data.color, pal) : QBrush(QColor());-
894 return;-
895 }-
896-
897 *width = 0;-
898 *style = BorderStyle_None;-
899 *color = QColor();-
900-
901 if (decl.d->values.isEmpty())-
902 return;-
903-
904 BorderData data;-
905 data.width.number = 0;-
906 data.width.unit = LengthData::None;-
907 data.style = BorderStyle_None;-
908-
909 int i = 0;-
910 if (decl.d->values.at(i).type == Value::Length || decl.d->values.at(i).type == Value::Number) {-
911 data.width = lengthValue(decl.d->values.at(i));-
912 *width = lengthValueFromData(data.width, f);-
913 if (++i >= decl.d->values.count()) {-
914 decl.d->parsed = QVariant::fromValue<BorderData>(data);-
915 return;-
916 }-
917 }-
918-
919 data.style = parseStyleValue(decl.d->values.at(i));-
920 if (data.style != BorderStyle_Unknown) {-
921 *style = data.style;-
922 if (++i >= decl.d->values.count()) {-
923 decl.d->parsed = QVariant::fromValue<BorderData>(data);-
924 return;-
925 }-
926 } else {-
927 data.style = BorderStyle_None;-
928 }-
929-
930 data.color = parseBrushValue(decl.d->values.at(i), pal);-
931 *color = brushFromData(data.color, pal);-
932 if (data.color.type != BrushData::DependsOnThePalette)-
933 decl.d->parsed = QVariant::fromValue<BorderData>(data);-
934}-
935-
936static void parseShorthandBackgroundProperty(const QVector<QCss::Value> &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal)-
937{-
938 *brush = BrushData();-
939 *image = QString();-
940 *repeat = Repeat_XY;-
941 *alignment = Qt::AlignTop | Qt::AlignLeft;-
942-
943 for (int i = 0; i < values.count(); ++i) {-
944 const QCss::Value &v = values.at(i);-
945 if (v.type == Value::Uri) {-
946 *image = v.variant.toString();-
947 continue;-
948 } else if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_None) {-
949 *image = QString();-
950 continue;-
951 } else if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_Transparent) {-
952 *brush = QBrush(Qt::transparent);-
953 }-
954-
955 Repeat repeatAttempt = static_cast<Repeat>(findKnownValue(v.variant.toString(),-
956 repeats, NumKnownRepeats));-
957 if (repeatAttempt != Repeat_Unknown) {-
958 *repeat = repeatAttempt;-
959 continue;-
960 }-
961-
962 if (v.type == Value::KnownIdentifier) {-
963 const int start = i;-
964 int count = 1;-
965 if (i < values.count() - 1-
966 && values.at(i + 1).type == Value::KnownIdentifier) {-
967 ++i;-
968 ++count;-
969 }-
970 Qt::Alignment a = parseAlignment(values.constData() + start, count);-
971 if (int(a) != 0) {-
972 *alignment = a;-
973 continue;-
974 }-
975 i -= count - 1;-
976 }-
977-
978 *brush = parseBrushValue(v, pal);-
979 }-
980}-
981-
982bool ValueExtractor::extractBackground(QBrush *brush, QString *image, Repeat *repeat,-
983 Qt::Alignment *alignment, Origin *origin, Attachment *attachment,-
984 Origin *clip)-
985{-
986 bool hit = false;-
987 for (int i = 0; i < declarations.count(); ++i) {-
988 const Declaration &decl = declarations.at(i);-
989 if (decl.d->values.isEmpty())-
990 continue;-
991 const QCss::Value &val = decl.d->values.at(0);-
992 switch (decl.d->propertyId) {-
993 case BackgroundColor:-
994 *brush = decl.brushValue();-
995 break;-
996 case BackgroundImage:-
997 if (val.type == Value::Uri)-
998 *image = val.variant.toString();-
999 break;-
1000 case BackgroundRepeat:-
1001 if (decl.d->parsed.isValid()) {-
1002 *repeat = static_cast<Repeat>(decl.d->parsed.toInt());-
1003 } else {-
1004 *repeat = static_cast<Repeat>(findKnownValue(val.variant.toString(),-
1005 repeats, NumKnownRepeats));-
1006 decl.d->parsed = *repeat;-
1007 }-
1008 break;-
1009 case BackgroundPosition:-
1010 *alignment = decl.alignmentValue();-
1011 break;-
1012 case BackgroundOrigin:-
1013 *origin = decl.originValue();-
1014 break;-
1015 case BackgroundClip:-
1016 *clip = decl.originValue();-
1017 break;-
1018 case Background:-
1019 if (decl.d->parsed.isValid()) {-
1020 BackgroundData data = qvariant_cast<BackgroundData>(decl.d->parsed);-
1021 *brush = brushFromData(data.brush, pal);-
1022 *image = data.image;-
1023 *repeat = data.repeat;-
1024 *alignment = data.alignment;-
1025 } else {-
1026 BrushData brushData;-
1027 parseShorthandBackgroundProperty(decl.d->values, &brushData, image, repeat, alignment, pal);-
1028 *brush = brushFromData(brushData, pal);-
1029 if (brushData.type != BrushData::DependsOnThePalette) {-
1030 BackgroundData data = { brushData, *image, *repeat, *alignment };-
1031 decl.d->parsed = QVariant::fromValue<BackgroundData>(data);-
1032 }-
1033 }-
1034 break;-
1035 case BackgroundAttachment:-
1036 *attachment = decl.attachmentValue();-
1037 break;-
1038 default: continue;-
1039 }-
1040 hit = true;-
1041 }-
1042 return hit;-
1043}-
1044-
1045static bool setFontSizeFromValue(QCss::Value value, QFont *font, int *fontSizeAdjustment)-
1046{-
1047 if (value.type == Value::KnownIdentifier) {-
1048 bool valid = true;-
1049 switch (value.variant.toInt()) {-
1050 case Value_Small: *fontSizeAdjustment = -1; break;-
1051 case Value_Medium: *fontSizeAdjustment = 0; break;-
1052 case Value_Large: *fontSizeAdjustment = 1; break;-
1053 case Value_XLarge: *fontSizeAdjustment = 2; break;-
1054 case Value_XXLarge: *fontSizeAdjustment = 3; break;-
1055 default: valid = false; break;-
1056 }-
1057 return valid;-
1058 }-
1059 if (value.type != Value::Length)-
1060 return false;-
1061-
1062 bool valid = false;-
1063 QString s = value.variant.toString();-
1064 if (s.endsWith(QLatin1String("pt"), Qt::CaseInsensitive)) {-
1065 s.chop(2);-
1066 value.variant = s;-
1067 if (value.variant.convert((QVariant::Type)qMetaTypeId<qreal>())) {-
1068 font->setPointSizeF(value.variant.toReal());-
1069 valid = true;-
1070 }-
1071 } else if (s.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) {-
1072 s.chop(2);-
1073 value.variant = s;-
1074 if (value.variant.convert(QVariant::Int)) {-
1075 font->setPixelSize(value.variant.toInt());-
1076 valid = true;-
1077 }-
1078 }-
1079 return valid;-
1080}-
1081-
1082static bool setFontStyleFromValue(const QCss::Value &value, QFont *font)-
1083{-
1084 if (value.type != Value::KnownIdentifier)-
1085 return false ;-
1086 switch (value.variant.toInt()) {-
1087 case Value_Normal: font->setStyle(QFont::StyleNormal); return true;-
1088 case Value_Italic: font->setStyle(QFont::StyleItalic); return true;-
1089 case Value_Oblique: font->setStyle(QFont::StyleOblique); return true;-
1090 default: break;-
1091 }-
1092 return false;-
1093}-
1094-
1095static bool setFontWeightFromValue(const QCss::Value &value, QFont *font)-
1096{-
1097 if (value.type == Value::KnownIdentifier) {-
1098 switch (value.variant.toInt()) {-
1099 case Value_Normal: font->setWeight(QFont::Normal); return true;-
1100 case Value_Bold: font->setWeight(QFont::Bold); return true;-
1101 default: break;-
1102 }-
1103 return false;-
1104 }-
1105 if (value.type != Value::Number)-
1106 return false;-
1107 font->setWeight(qMin(value.variant.toInt() / 8, 99));-
1108 return true;-
1109}-
1110-
1111-
1112-
1113-
1114-
1115-
1116static bool setFontFamilyFromValues(const QVector<QCss::Value> &values, QFont *font, int start = 0)-
1117{-
1118 QString family;-
1119 bool shouldAddSpace = false;-
1120 for (int i = start; i < values.count(); ++i) {-
1121 const QCss::Value &v = values.at(i);-
1122 if (v.type == Value::TermOperatorComma) {-
1123 family += QLatin1Char(',');-
1124 shouldAddSpace = false;-
1125 continue;-
1126 }-
1127 const QString str = v.variant.toString();-
1128 if (str.isEmpty())-
1129 break;-
1130 if (shouldAddSpace)-
1131 family += QLatin1Char(' ');-
1132 family += str;-
1133 shouldAddSpace = true;-
1134 }-
1135 if (family.isEmpty())-
1136 return false;-
1137 font->setFamily(family);-
1138 return true;-
1139}-
1140-
1141static void setTextDecorationFromValues(const QVector<QCss::Value> &values, QFont *font)-
1142{-
1143 for (int i = 0; i < values.count(); ++i) {-
1144 if (values.at(i).type != Value::KnownIdentifier)-
1145 continue;-
1146 switch (values.at(i).variant.toInt()) {-
1147 case Value_Underline: font->setUnderline(true); break;-
1148 case Value_Overline: font->setOverline(true); break;-
1149 case Value_LineThrough: font->setStrikeOut(true); break;-
1150 case Value_None:-
1151 font->setUnderline(false);-
1152 font->setOverline(false);-
1153 font->setStrikeOut(false);-
1154 break;-
1155 default: break;-
1156 }-
1157 }-
1158}-
1159-
1160static void parseShorthandFontProperty(const QVector<QCss::Value> &values, QFont *font, int *fontSizeAdjustment)-
1161{-
1162 font->setStyle(QFont::StyleNormal);-
1163 font->setWeight(QFont::Normal);-
1164 *fontSizeAdjustment = -255;-
1165-
1166 int i = 0;-
1167 while (i < values.count()) {-
1168 if (setFontStyleFromValue(values.at(i), font)-
1169 || setFontWeightFromValue(values.at(i), font))-
1170 ++i;-
1171 else-
1172 break;-
1173 }-
1174-
1175 if (i < values.count()) {-
1176 setFontSizeFromValue(values.at(i), font, fontSizeAdjustment);-
1177 ++i;-
1178 }-
1179-
1180 if (i < values.count()) {-
1181 setFontFamilyFromValues(values, font, i);-
1182 }-
1183}-
1184-
1185static void setFontVariantFromValue(const QCss::Value &value, QFont *font)-
1186{-
1187 if (value.type == Value::KnownIdentifier) {-
1188 switch (value.variant.toInt()) {-
1189 case Value_Normal: font->setCapitalization(QFont::MixedCase); break;-
1190 case Value_SmallCaps: font->setCapitalization(QFont::SmallCaps); break;-
1191 default: break;-
1192 }-
1193 }-
1194}-
1195-
1196static void setTextTransformFromValue(const QCss::Value &value, QFont *font)-
1197{-
1198 if (value.type == Value::KnownIdentifier) {-
1199 switch (value.variant.toInt()) {-
1200 case Value_None: font->setCapitalization(QFont::MixedCase); break;-
1201 case Value_Uppercase: font->setCapitalization(QFont::AllUppercase); break;-
1202 case Value_Lowercase: font->setCapitalization(QFont::AllLowercase); break;-
1203 default: break;-
1204 }-
1205 }-
1206}-
1207-
1208bool ValueExtractor::extractFont(QFont *font, int *fontSizeAdjustment)-
1209{-
1210 if (fontExtracted) {-
1211 *font = f;-
1212 *fontSizeAdjustment = adjustment;-
1213 return fontExtracted == 1;-
1214 }-
1215-
1216 bool hit = false;-
1217 for (int i = 0; i < declarations.count(); ++i) {-
1218 const Declaration &decl = declarations.at(i);-
1219 if (decl.d->values.isEmpty())-
1220 continue;-
1221 const QCss::Value &val = decl.d->values.at(0);-
1222 switch (decl.d->propertyId) {-
1223 case FontSize: setFontSizeFromValue(val, font, fontSizeAdjustment); break;-
1224 case FontStyle: setFontStyleFromValue(val, font); break;-
1225 case FontWeight: setFontWeightFromValue(val, font); break;-
1226 case FontFamily: setFontFamilyFromValues(decl.d->values, font); break;-
1227 case TextDecoration: setTextDecorationFromValues(decl.d->values, font); break;-
1228 case Font: parseShorthandFontProperty(decl.d->values, font, fontSizeAdjustment); break;-
1229 case FontVariant: setFontVariantFromValue(val, font); break;-
1230 case TextTransform: setTextTransformFromValue(val, font); break;-
1231 default: continue;-
1232 }-
1233 hit = true;-
1234 }-
1235-
1236 f = *font;-
1237 adjustment = *fontSizeAdjustment;-
1238 fontExtracted = hit ? 1 : 2;-
1239 return hit;-
1240}-
1241-
1242bool ValueExtractor::extractPalette(QBrush *fg, QBrush *sfg, QBrush *sbg, QBrush *abg)-
1243{-
1244 bool hit = false;-
1245 for (int i = 0; i < declarations.count(); ++i) {-
1246 const Declaration &decl = declarations.at(i);-
1247 switch (decl.d->propertyId) {-
1248 case Color: *fg = decl.brushValue(pal); break;-
1249 case QtSelectionForeground: *sfg = decl.brushValue(pal); break;-
1250 case QtSelectionBackground: *sbg = decl.brushValue(pal); break;-
1251 case QtAlternateBackground: *abg = decl.brushValue(pal); break;-
1252 default: continue;-
1253 }-
1254 hit = true;-
1255 }-
1256 return hit;-
1257}-
1258-
1259void ValueExtractor::extractFont()-
1260{-
1261 if (fontExtracted)-
1262 return;-
1263 int dummy = -255;-
1264 extractFont(&f, &dummy);-
1265}-
1266-
1267bool ValueExtractor::extractImage(QIcon *icon, Qt::Alignment *a, QSize *size)-
1268{-
1269 bool hit = false;-
1270 for (int i = 0; i < declarations.count(); ++i) {-
1271 const Declaration &decl = declarations.at(i);-
1272 switch (decl.d->propertyId) {-
1273 case QtImage:-
1274 *icon = decl.iconValue();-
1275 if (decl.d->values.count() > 0 && decl.d->values.at(0).type == Value::Uri) {-
1276-
1277 QImageReader imageReader(decl.d->values.at(0).variant.toString());-
1278 if ((*size = imageReader.size()).isNull()) {-
1279-
1280-
1281 *size = imageReader.read().size();-
1282 }-
1283 }-
1284 break;-
1285 case QtImageAlignment: *a = decl.alignmentValue(); break;-
1286 default: continue;-
1287 }-
1288 hit = true;-
1289 }-
1290 return hit;-
1291}-
1292-
1293-
1294-
1295QColor Declaration::colorValue(const QPalette &pal) const-
1296{-
1297 if (d->values.count() != 1)-
1298 return QColor();-
1299-
1300 if (d->parsed.isValid()) {-
1301 if (d->parsed.type() == QVariant::Color)-
1302 return qvariant_cast<QColor>(d->parsed);-
1303 if (d->parsed.type() == QVariant::Int)-
1304 return pal.color((QPalette::ColorRole)(d->parsed.toInt()));-
1305 }-
1306-
1307 ColorData color = parseColorValue(d->values.at(0));-
1308 if(color.type == ColorData::Role) {-
1309 d->parsed = QVariant::fromValue<int>(color.role);-
1310 return pal.color((QPalette::ColorRole)(color.role));-
1311 } else {-
1312 d->parsed = QVariant::fromValue<QColor>(color.color);-
1313 return color.color;-
1314 }-
1315}-
1316-
1317QBrush Declaration::brushValue(const QPalette &pal) const-
1318{-
1319 if (d->values.count() != 1)-
1320 return QBrush();-
1321-
1322 if (d->parsed.isValid()) {-
1323 if (d->parsed.type() == QVariant::Brush)-
1324 return qvariant_cast<QBrush>(d->parsed);-
1325 if (d->parsed.type() == QVariant::Int)-
1326 return pal.color((QPalette::ColorRole)(d->parsed.toInt()));-
1327 }-
1328-
1329 BrushData data = parseBrushValue(d->values.at(0), pal);-
1330-
1331 if(data.type == BrushData::Role) {-
1332 d->parsed = QVariant::fromValue<int>(data.role);-
1333 return pal.color((QPalette::ColorRole)(data.role));-
1334 } else {-
1335 if (data.type != BrushData::DependsOnThePalette)-
1336 d->parsed = QVariant::fromValue<QBrush>(data.brush);-
1337 return data.brush;-
1338 }-
1339}-
1340-
1341void Declaration::brushValues(QBrush *c, const QPalette &pal) const-
1342{-
1343 int needParse = 0x1f;-
1344-
1345 int i = 0;-
1346 if (d->parsed.isValid()) {-
1347 needParse = 0;-
1348 QList<QVariant> v = d->parsed.toList();-
1349 for (i = 0; i < qMin(v.count(), 4); i++) {-
1350 if (v.at(i).type() == QVariant::Brush) {-
1351 c[i] = qvariant_cast<QBrush>(v.at(i));-
1352 } else if (v.at(i).type() == QVariant::Int) {-
1353 c[i] = pal.color((QPalette::ColorRole)(v.at(i).toInt()));-
1354 } else {-
1355 needParse |= (1<<i);-
1356 }-
1357 }-
1358 }-
1359 if (needParse != 0) {-
1360 QList<QVariant> v;-
1361 for (i = 0; i < qMin(d->values.count(), 4); i++) {-
1362 if (!(needParse & (1<<i)))-
1363 continue;-
1364 BrushData data = parseBrushValue(d->values.at(i), pal);-
1365 if(data.type == BrushData::Role) {-
1366 v += QVariant::fromValue<int>(data.role);-
1367 c[i] = pal.color((QPalette::ColorRole)(data.role));-
1368 } else {-
1369 if (data.type != BrushData::DependsOnThePalette) {-
1370 v += QVariant::fromValue<QBrush>(data.brush);-
1371 } else {-
1372 v += QVariant();-
1373 }-
1374 c[i] = data.brush;-
1375 }-
1376 }-
1377 if (needParse & 0x10)-
1378 d->parsed = v;-
1379 }-
1380 if (i == 0) c[0] = c[1] = c[2] = c[3] = QBrush();-
1381 else if (i == 1) c[3] = c[2] = c[1] = c[0];-
1382 else if (i == 2) c[2] = c[0], c[3] = c[1];-
1383 else if (i == 3) c[3] = c[1];-
1384}-
1385-
1386bool Declaration::realValue(qreal *real, const char *unit) const-
1387{-
1388 if (d->values.count() != 1)-
1389 return false;-
1390 const Value &v = d->values.at(0);-
1391 if (unit && v.type != Value::Length)-
1392 return false;-
1393 QString s = v.variant.toString();-
1394 if (unit) {-
1395 if (!s.endsWith(QLatin1String(unit), Qt::CaseInsensitive))-
1396 return false;-
1397 s.chop(qstrlen(unit));-
1398 }-
1399 bool ok = false;-
1400 qreal val = s.toDouble(&ok);-
1401 if (ok)-
1402 *real = val;-
1403 return ok;-
1404}-
1405-
1406static bool intValueHelper(const QCss::Value &v, int *i, const char *unit)-
1407{-
1408 if (unit && v.type != Value::Length)-
1409 return false;-
1410 QString s = v.variant.toString();-
1411 if (unit) {-
1412 if (!s.endsWith(QLatin1String(unit), Qt::CaseInsensitive))-
1413 return false;-
1414 s.chop(qstrlen(unit));-
1415 }-
1416 bool ok = false;-
1417 int val = s.toInt(&ok);-
1418 if (ok)-
1419 *i = val;-
1420 return ok;-
1421}-
1422-
1423bool Declaration::intValue(int *i, const char *unit) const-
1424{-
1425 if (d->values.count() != 1)-
1426 return false;-
1427 return intValueHelper(d->values.at(0), i, unit);-
1428}-
1429-
1430QSize Declaration::sizeValue() const-
1431{-
1432 if (d->parsed.isValid())-
1433 return qvariant_cast<QSize>(d->parsed);-
1434-
1435 int x[2] = { 0, 0 };-
1436 if (d->values.count() > 0)-
1437 intValueHelper(d->values.at(0), &x[0], "px");-
1438 if (d->values.count() > 1)-
1439 intValueHelper(d->values.at(1), &x[1], "px");-
1440 else-
1441 x[1] = x[0];-
1442 QSize size(x[0], x[1]);-
1443 d->parsed = QVariant::fromValue<QSize>(size);-
1444 return size;-
1445}-
1446-
1447QRect Declaration::rectValue() const-
1448{-
1449 if (d->values.count() != 1
d->values.count() != 1Description
TRUEnever evaluated
FALSEnever evaluated
)
0
1450 return
never executed: return QRect();
QRect();
never executed: return QRect();
0
1451-
1452 if (d->parsed.isValid()
d->parsed.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
1453 return
never executed: return qvariant_cast<QRect>(d->parsed);
qvariant_cast<QRect>(d->parsed);
never executed: return qvariant_cast<QRect>(d->parsed);
0
1454-
1455 const QCss::Value &v = d->values.at(0);-
1456 if (v.type != Value::Function
v.type != Value::FunctionDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
1457 return
never executed: return QRect();
QRect();
never executed: return QRect();
0
1458 const QStringList func = v.variant.toStringList();-
1459 if (func.count() != 2
func.count() != 2Description
TRUEnever evaluated
FALSEnever evaluated
|| func.at(0).compare(QLatin1String("rect")) != 0
func.at(0).com...("rect")) != 0Description
TRUEnever evaluated
FALSEnever evaluated
)
0
1460 return
never executed: return QRect();
QRect();
never executed: return QRect();
0
1461 QStringListconst auto args = func[1].splitsplitRef(QLatin1Char(' '), QString::SkipEmptyParts);-
1462 if (args.count() != 4
args.count() != 4Description
TRUEnever evaluated
FALSEnever evaluated
)
0
1463 return
never executed: return QRect();
QRect();
never executed: return QRect();
0
1464 QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt());-
1465 d->parsed = QVariant::fromValue<QRect>(rect);-
1466 return
never executed: return rect;
rect;
never executed: return rect;
0
1467}-
1468-
1469void Declaration::colorValues(QColor *c, const QPalette &pal) const-
1470{-
1471 int i;-
1472 if (d->parsed.isValid()) {-
1473 QList<QVariant> v = d->parsed.toList();-
1474 for (i = 0; i < qMin(d->values.count(), 4); i++) {-
1475 if (v.at(i).type() == QVariant::Color) {-
1476 c[i] = qvariant_cast<QColor>(v.at(i));-
1477 } else {-
1478 c[i] = pal.color((QPalette::ColorRole)(v.at(i).toInt()));-
1479 }-
1480 }-
1481 } else {-
1482 QList<QVariant> v;-
1483 for (i = 0; i < qMin(d->values.count(), 4); i++) {-
1484 ColorData color = parseColorValue(d->values.at(i));-
1485 if(color.type == ColorData::Role) {-
1486 v += QVariant::fromValue<int>(color.role);-
1487 c[i] = pal.color((QPalette::ColorRole)(color.role));-
1488 } else {-
1489 v += QVariant::fromValue<QColor>(color.color);-
1490 c[i] = color.color;-
1491 }-
1492 }-
1493 d->parsed = v;-
1494 }-
1495-
1496 if (i == 0) c[0] = c[1] = c[2] = c[3] = QColor();-
1497 else if (i == 1) c[3] = c[2] = c[1] = c[0];-
1498 else if (i == 2) c[2] = c[0], c[3] = c[1];-
1499 else if (i == 3) c[3] = c[1];-
1500}-
1501-
1502BorderStyle Declaration::styleValue() const-
1503{-
1504 if (d->values.count() != 1)-
1505 return BorderStyle_None;-
1506 return parseStyleValue(d->values.at(0));-
1507}-
1508-
1509void Declaration::styleValues(BorderStyle *s) const-
1510{-
1511 int i;-
1512 for (i = 0; i < qMin(d->values.count(), 4); i++)-
1513 s[i] = parseStyleValue(d->values.at(i));-
1514 if (i == 0) s[0] = s[1] = s[2] = s[3] = BorderStyle_None;-
1515 else if (i == 1) s[3] = s[2] = s[1] = s[0];-
1516 else if (i == 2) s[2] = s[0], s[3] = s[1];-
1517 else if (i == 3) s[3] = s[1];-
1518}-
1519-
1520Repeat Declaration::repeatValue() const-
1521{-
1522 if (d->parsed.isValid())-
1523 return static_cast<Repeat>(d->parsed.toInt());-
1524 if (d->values.count() != 1)-
1525 return Repeat_Unknown;-
1526 int v = findKnownValue(d->values.at(0).variant.toString(),-
1527 repeats, NumKnownRepeats);-
1528 d->parsed = v;-
1529 return static_cast<Repeat>(v);-
1530}-
1531-
1532Origin Declaration::originValue() const-
1533{-
1534 if (d->parsed.isValid())-
1535 return static_cast<Origin>(d->parsed.toInt());-
1536 if (d->values.count() != 1)-
1537 return Origin_Unknown;-
1538 int v = findKnownValue(d->values.at(0).variant.toString(),-
1539 origins, NumKnownOrigins);-
1540 d->parsed = v;-
1541 return static_cast<Origin>(v);-
1542}-
1543-
1544PositionMode Declaration::positionValue() const-
1545{-
1546 if (d->parsed.isValid())-
1547 return static_cast<PositionMode>(d->parsed.toInt());-
1548 if (d->values.count() != 1)-
1549 return PositionMode_Unknown;-
1550 int v = findKnownValue(d->values.at(0).variant.toString(),-
1551 positions, NumKnownPositionModes);-
1552 d->parsed = v;-
1553 return static_cast<PositionMode>(v);-
1554}-
1555-
1556Attachment Declaration::attachmentValue() const-
1557{-
1558 if (d->parsed.isValid())-
1559 return static_cast<Attachment>(d->parsed.toInt());-
1560 if (d->values.count() != 1)-
1561 return Attachment_Unknown;-
1562 int v = findKnownValue(d->values.at(0).variant.toString(),-
1563 attachments, NumKnownAttachments);-
1564 d->parsed = v;-
1565 return static_cast<Attachment>(v);-
1566}-
1567-
1568int Declaration::styleFeaturesValue() const-
1569{-
1570 ((!(d->propertyId == QtStyleFeatures)) ? qt_assert("d->propertyId == QtStyleFeatures",__FILE__,16201627) : qt_noop());-
1571 if (d->parsed.isValid())-
1572 return d->parsed.toInt();-
1573 int features = StyleFeature_None;-
1574 for (int i = 0; i < d->values.count(); i++) {-
1575 features |= static_cast<int>(findKnownValue(d->values.value(i).variant.toString(),-
1576 styleFeatures, NumKnownStyleFeatures));-
1577 }-
1578 d->parsed = features;-
1579 return features;-
1580}-
1581-
1582QString Declaration::uriValue() const-
1583{-
1584 if (d->values.isEmpty() || d->values.at(0).type != Value::Uri)-
1585 return QString();-
1586 return d->values.at(0).variant.toString();-
1587}-
1588-
1589Qt::Alignment Declaration::alignmentValue() const-
1590{-
1591 if (d->parsed.isValid())-
1592 return Qt::Alignment(d->parsed.toInt());-
1593 if (d->values.isEmpty() || d->values.count() > 2)-
1594 return Qt::AlignLeft | Qt::AlignTop;-
1595-
1596 Qt::Alignment v = parseAlignment(d->values.constData(), d->values.count());-
1597 d->parsed = int(v);-
1598 return v;-
1599}-
1600-
1601void Declaration::borderImageValue(QString *image, int *cuts,-
1602 TileMode *h, TileMode *v) const-
1603{-
1604 const DeclarationData *d = this->d.data();-
1605 *image = uriValue();-
1606 for (int i = 0; i < 4
i < 4Description
TRUEnever evaluated
FALSEnever evaluated
; i++)
0
1607 cuts[i] = -1;
never executed: cuts[i] = -1;
0
1608 *h = *v = TileMode_Stretch;-
1609-
1610 if (d->values.count() < 2
d->values.count() < 2Description
TRUEnever evaluated
FALSEnever evaluated
)
0
1611 return;
never executed: return;
0
1612-
1613 if (d->values.at(1).type == Value::Number
d->values.at(1... Value::NumberDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
1614 int i;-
1615 for (i = 0; i < qMin(d->values.count()-1, 4)
i < qMin(d->va....count()-1, 4)Description
TRUEnever evaluated
FALSEnever evaluated
; i++) {
0
1616 const Value& v = d->values.at(i+1);-
1617 if (v.type != Value::Number
v.type != Value::NumberDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
1618 break;
never executed: break;
0
1619 cuts[i] = v.variant.toString().toInt();-
1620 }
never executed: end of block
0
1621 if (i == 0
i == 0Description
TRUEnever evaluated
FALSEnever evaluated
) cuts[0] = cuts[1] = cuts[2] = cuts[3] = 0;
never executed: cuts[0] = cuts[1] = cuts[2] = cuts[3] = 0;
0
1622 else if (i == 1
i == 1Description
TRUEnever evaluated
FALSEnever evaluated
) cuts[3] = cuts[2] = cuts[1] = cuts[0];
never executed: cuts[3] = cuts[2] = cuts[1] = cuts[0];
0
1623 else if (i == 2
i == 2Description
TRUEnever evaluated
FALSEnever evaluated
) cuts[2] = cuts[0], cuts[3] = cuts[1];
never executed: cuts[2] = cuts[0], cuts[3] = cuts[1];
0
1624 else if (i == 3
i == 3Description
TRUEnever evaluated
FALSEnever evaluated
) cuts[3] = cuts[1];
never executed: cuts[3] = cuts[1];
0
1625 }
never executed: end of block
0
1626-
1627 if (d->values.last().type == Value::Identifier
d->values.last...ue::IdentifierDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
1628 *v = static_cast<TileMode>(findKnownValue(d->values.last().variant.toString(),-
1629 tileModes, NumKnownTileModes));-
1630 }
never executed: end of block
0
1631 if (d->values[d->values.count() - 2].type == Value::Identifier
d->values[d->v...ue::IdentifierDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
1632 *h = static_cast<TileMode>-
1633 (findKnownValue(d->values[d->values.count()-2].variant.toString(),-
1634 tileModes, NumKnownTileModes));-
1635 }
never executed: end of block
else
0
1636 *
never executed: *h = *v;
h = *v;
never executed: *h = *v;
0
1637}-
1638-
1639QIcon Declaration::iconValue() const-
1640{-
1641 if (d->parsed.isValid())-
1642 return qvariant_cast<QIcon>(d->parsed);-
1643-
1644 QIcon icon;-
1645 for (int i = 0; i < d->values.count();) {-
1646 const Value &value = d->values.at(i++);-
1647 if (value.type != Value::Uri)-
1648 break;-
1649 QString uri = value.variant.toString();-
1650 QIcon::Mode mode = QIcon::Normal;-
1651 QIcon::State state = QIcon::Off;-
1652 for (int j = 0; j < 2; j++) {-
1653 if (i != d->values.count() && d->values.at(i).type == Value::KnownIdentifier) {-
1654 switch (d->values.at(i).variant.toInt()) {-
1655 case Value_Disabled: mode = QIcon::Disabled; break;-
1656 case Value_Active: mode = QIcon::Active; break;-
1657 case Value_Selected: mode = QIcon::Selected; break;-
1658 case Value_Normal: mode = QIcon::Normal; break;-
1659 case Value_On: state = QIcon::On; break;-
1660 case Value_Off: state = QIcon::Off; break;-
1661 default: break;-
1662 }-
1663 ++i;-
1664 } else {-
1665 break;-
1666 }-
1667 }-
1668-
1669-
1670 if (icon.isNull())-
1671 icon = QIcon(uri);-
1672 else-
1673 icon.addPixmap(uri, mode, state);-
1674-
1675 if (i == d->values.count())-
1676 break;-
1677-
1678 if (d->values.at(i).type == Value::TermOperatorComma)-
1679 i++;-
1680 }-
1681-
1682 d->parsed = QVariant::fromValue<QIcon>(icon);-
1683 return icon;-
1684}-
1685-
1686-
1687-
1688int Selector::specificity() const-
1689{-
1690 int val = 0;-
1691 for (int i = 0; i < basicSelectors.count(); ++i) {-
1692 const BasicSelector &sel = basicSelectors.at(i);-
1693 if (!sel.elementName.isEmpty())-
1694 val += 1;-
1695-
1696 val += (sel.pseudos.count() + sel.attributeSelectors.count()) * 0x10;-
1697 val += sel.ids.count() * 0x100;-
1698 }-
1699 return val;-
1700}-
1701-
1702QString Selector::pseudoElement() const-
1703{-
1704 const BasicSelector& bs = basicSelectors.last();-
1705 if (!bs.pseudos.isEmpty() && bs.pseudos.at(0).type == PseudoClass_Unknown)-
1706 return bs.pseudos.at(0).name;-
1707 return QString();-
1708}-
1709-
1710quint64 Selector::pseudoClass(quint64 *negated) const-
1711{-
1712 const BasicSelector& bs = basicSelectors.last();-
1713 if (bs.pseudos.isEmpty())-
1714 return PseudoClass_Unspecified;-
1715 quint64 pc = PseudoClass_Unknown;-
1716 for (int i = !pseudoElement().isEmpty(); i < bs.pseudos.count(); i++) {-
1717 const Pseudo &pseudo = bs.pseudos.at(i);-
1718 if (pseudo.type == PseudoClass_Unknown)-
1719 return PseudoClass_Unknown;-
1720 if (!pseudo.negated)-
1721 pc |= pseudo.type;-
1722 else if (negated)-
1723 *negated |= pseudo.type;-
1724 }-
1725 return pc;-
1726}-
1727-
1728-
1729-
1730void StyleSheet::buildIndexes(Qt::CaseSensitivity nameCaseSensitivity)-
1731{-
1732 QVector<StyleRule> universals;-
1733 for (int i = 0; i < styleRules.count(); ++i) {-
1734 const StyleRule &rule = styleRules.at(i);-
1735 QVector<Selector> universalsSelectors;-
1736 for (int j = 0; j < rule.selectors.count(); ++j) {-
1737 const Selector& selector = rule.selectors.at(j);-
1738-
1739 if (selector.basicSelectors.isEmpty())-
1740 continue;-
1741-
1742 if (selector.basicSelectors.at(0).relationToNext == BasicSelector::NoRelation) {-
1743 if (selector.basicSelectors.count() != 1)-
1744 continue;-
1745 } else if (selector.basicSelectors.count() <= 1) {-
1746 continue;-
1747 }-
1748-
1749 const BasicSelector &sel = selector.basicSelectors.at(selector.basicSelectors.count() - 1);-
1750-
1751 if (!sel.ids.isEmpty()) {-
1752 StyleRule nr;-
1753 nr.selectors += selector;-
1754 nr.declarations = rule.declarations;-
1755 nr.order = i;-
1756 idIndex.insert(sel.ids.at(0), nr);-
1757 } else if (!sel.elementName.isEmpty()) {-
1758 StyleRule nr;-
1759 nr.selectors += selector;-
1760 nr.declarations = rule.declarations;-
1761 nr.order = i;-
1762 QString name = sel.elementName;-
1763 if (nameCaseSensitivity == Qt::CaseInsensitive)-
1764 name=name.toLower();-
1765 nameIndex.insert(name, nr);-
1766 } else {-
1767 universalsSelectors += selector;-
1768 }-
1769 }-
1770 if (!universalsSelectors.isEmpty()) {-
1771 StyleRule nr;-
1772 nr.selectors = universalsSelectors;-
1773 nr.declarations = rule.declarations;-
1774 nr.order = i;-
1775 universals << nr;-
1776 }-
1777 }-
1778 styleRules = universals;-
1779}-
1780-
1781-
1782-
1783StyleSelector::~StyleSelector()-
1784{-
1785}-
1786-
1787bool StyleSelector::nodeNameEquals(NodePtr node, const QString& nodeName) const-
1788{-
1789 return nodeNames(node).contains(nodeName, nameCaseSensitivity);-
1790}-
1791-
1792QStringList StyleSelector::nodeIds(NodePtr node) const-
1793{-
1794 return QStringList(attribute(node, QLatin1String("id")));-
1795}-
1796-
1797bool StyleSelector::selectorMatches(const Selector &selector, NodePtr node)-
1798{-
1799 if (selector.basicSelectors.isEmpty())-
1800 return false;-
1801-
1802 if (selector.basicSelectors.at(0).relationToNext == BasicSelector::NoRelation) {-
1803 if (selector.basicSelectors.count() != 1)-
1804 return false;-
1805 return basicSelectorMatches(selector.basicSelectors.at(0), node);-
1806 }-
1807 if (selector.basicSelectors.count() <= 1)-
1808 return false;-
1809-
1810 int i = selector.basicSelectors.count() - 1;-
1811 node = duplicateNode(node);-
1812 bool match = true;-
1813-
1814 BasicSelector sel = selector.basicSelectors.at(i);-
1815 do {-
1816 match = basicSelectorMatches(sel, node);-
1817 if (!match) {-
1818 if (sel.relationToNext == BasicSelector::MatchNextSelectorIfParent-
1819 || i == selector.basicSelectors.count() - 1)-
1820 break;-
1821 }-
1822-
1823 if (match || sel.relationToNext != BasicSelector::MatchNextSelectorIfAncestor)-
1824 --i;-
1825-
1826 if (i < 0)-
1827 break;-
1828-
1829 sel = selector.basicSelectors.at(i);-
1830 if (sel.relationToNext == BasicSelector::MatchNextSelectorIfAncestor-
1831 || sel.relationToNext == BasicSelector::MatchNextSelectorIfParent) {-
1832-
1833 NodePtr nextParent = parentNode(node);-
1834 freeNode(node);-
1835 node = nextParent;-
1836 } else if (sel.relationToNext == BasicSelector::MatchNextSelectorIfPreceeds) {-
1837 NodePtr previousSibling = previousSiblingNode(node);-
1838 freeNode(node);-
1839 node = previousSibling;-
1840 }-
1841 if (isNullNode(node)) {-
1842 match = false;-
1843 break;-
1844 }-
1845 } while (i >= 0 && (match || sel.relationToNext == BasicSelector::MatchNextSelectorIfAncestor));-
1846-
1847 freeNode(node);-
1848-
1849 return match;-
1850}-
1851-
1852bool StyleSelector::basicSelectorMatches(const BasicSelector &sel, NodePtr node)-
1853{-
1854 if (!sel.attributeSelectors.isEmpty()
!sel.attribute...tors.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
1855 if (!hasAttributes(node)
!hasAttributes(node)Description
TRUEnever evaluated
FALSEnever evaluated
)
0
1856 return
never executed: return false;
false;
never executed: return false;
0
1857-
1858 for (int i = 0; i < sel.attributeSelectors.count()
i < sel.attrib...ectors.count()Description
TRUEnever evaluated
FALSEnever evaluated
; ++i) {
0
1859 const QCss::AttributeSelector &a = sel.attributeSelectors.at(i);-
1860-
1861 const QString attrValue = attribute(node, a.name);-
1862 if (attrValue.isNull()
attrValue.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
1863 return
never executed: return false;
false;
never executed: return false;
0
1864-
1865 if (a.valueMatchCriterium == QCss::AttributeSelector::MatchContains
a.valueMatchCr...:MatchContainsDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
1866 QStringListconst auto lst = attrValue.splitsplitRef(QLatin1Char(' '));-
1867 if (!lst.contains(aQStringRef(&a.value))))
!lst.contains(...Ref(&a.value))Description
TRUEnever evaluated
FALSEnever evaluated
)
0
1868 return
never executed: return false;
false;
never executed: return false;
0
1869 }
never executed: end of block
else if (
0
1870 (a.valueMatchCriterium == QCss::AttributeSelector::MatchEqual
a.valueMatchCr...or::MatchEqualDescription
TRUEnever evaluated
FALSEnever evaluated
0
1871 && attrValue != a.value
attrValue != a.valueDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
1872 ||-
1873 (a.valueMatchCriterium == QCss::AttributeSelector::MatchBeginsWith
a.valueMatchCr...atchBeginsWithDescription
TRUEnever evaluated
FALSEnever evaluated
0
1874 && !attrValue.startsWith(a.value)
!attrValue.startsWith(a.value)Description
TRUEnever evaluated
FALSEnever evaluated
)
0
1875 )-
1876 return
never executed: return false;
false;
never executed: return false;
0
1877 }
never executed: end of block
0
1878 }
never executed: end of block
0
1879-
1880 if (!sel.elementName.isEmpty()
!sel.elementName.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1881 && !nodeNameEquals(node, sel.elementName)
!nodeNameEqual...l.elementName)Description
TRUEnever evaluated
FALSEnever evaluated
)
0
1882 return
never executed: return false;
false;
never executed: return false;
0
1883-
1884 if (!sel.ids.isEmpty()
!sel.ids.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1885 && sel.ids != nodeIds(node)
sel.ids != nodeIds(node)Description
TRUEnever evaluated
FALSEnever evaluated
)
0
1886 return
never executed: return false;
false;
never executed: return false;
0
1887-
1888 return
never executed: return true;
true;
never executed: return true;
0
1889}-
1890-
1891void StyleSelector::matchRule(NodePtr node, const StyleRule &rule, StyleSheetOrigin origin,-
1892 int depth, QMap<uint, StyleRule> *weightedRules)-
1893{-
1894 for (int j = 0; j < rule.selectors.count(); ++j) {-
1895 const Selector& selector = rule.selectors.at(j);-
1896 if (selectorMatches(selector, node)) {-
1897 uint weight = rule.order-
1898 + selector.specificity() *0x100-
1899 + (uint(origin) + depth)*0x100000;-
1900 StyleRule newRule = rule;-
1901 if(rule.selectors.count() > 1) {-
1902 newRule.selectors.resize(1);-
1903 newRule.selectors[0] = selector;-
1904 }-
1905-
1906 weightedRules->insertMulti(weight, newRule);-
1907 }-
1908 }-
1909}-
1910-
1911-
1912-
1913QVector<StyleRule> StyleSelector::styleRulesForNode(NodePtr node)-
1914{-
1915 QVector<StyleRule> rules;-
1916 if (styleSheets.isEmpty())-
1917 return rules;-
1918-
1919 QMap<uint, StyleRule> weightedRules;-
1920-
1921-
1922 for (int sheetIdx = 0; sheetIdx < styleSheets.count(); ++sheetIdx) {-
1923 const StyleSheet &styleSheet = styleSheets.at(sheetIdx);-
1924 for (int i = 0; i < styleSheet.styleRules.count(); ++i) {-
1925 matchRule(node, styleSheet.styleRules.at(i), styleSheet.origin, styleSheet.depth, &weightedRules);-
1926 }-
1927-
1928 if (!styleSheet.idIndex.isEmpty()) {-
1929 QStringList ids = nodeIds(node);-
1930 for (int i = 0; i < ids.count(); i++) {-
1931 const QString &key = ids.at(i);-
1932 QMultiHash<QString, StyleRule>::const_iterator it = styleSheet.idIndex.constFind(key);-
1933 while (it != styleSheet.idIndex.constEnd() && it.key() == key) {-
1934 matchRule(node, it.value(), styleSheet.origin, styleSheet.depth, &weightedRules);-
1935 ++it;-
1936 }-
1937 }-
1938 }-
1939 if (!styleSheet.nameIndex.isEmpty()) {-
1940 QStringList names = nodeNames(node);-
1941 for (int i = 0; i < names.count(); i++) {-
1942 QString name = names.at(i);-
1943 if (nameCaseSensitivity == Qt::CaseInsensitive)-
1944 name = name.toLower();-
1945 QMultiHash<QString, StyleRule>::const_iterator it = styleSheet.nameIndex.constFind(name);-
1946 while (it != styleSheet.nameIndex.constEnd() && it.key() == name) {-
1947 matchRule(node, it.value(), styleSheet.origin, styleSheet.depth, &weightedRules);-
1948 ++it;-
1949 }-
1950 }-
1951 }-
1952 if (!medium.isEmpty()) {-
1953 for (int i = 0; i < styleSheet.mediaRules.count(); ++i) {-
1954 if (styleSheet.mediaRules.at(i).media.contains(medium, Qt::CaseInsensitive)) {-
1955 for (int j = 0; j < styleSheet.mediaRules.at(i).styleRules.count(); ++j) {-
1956 matchRule(node, styleSheet.mediaRules.at(i).styleRules.at(j), styleSheet.origin,-
1957 styleSheet.depth, &weightedRules);-
1958 }-
1959 }-
1960 }-
1961 }-
1962 }-
1963-
1964 rules.reserve(weightedRules.count());-
1965 QMap<uint, StyleRule>::const_iterator it = weightedRules.constBegin();-
1966 for ( ; it != weightedRules.constEnd() ; ++it)-
1967 rules += *it;-
1968-
1969 return rules;-
1970}-
1971-
1972-
1973-
1974QVector<Declaration> StyleSelector::declarationsForNode(NodePtr node, const char *extraPseudo)-
1975{-
1976 QVector<Declaration> decls;-
1977 QVector<StyleRule> rules = styleRulesForNode(node);-
1978 for (int i = 0; i < rules.count(); i++) {-
1979 const Selector& selector = rules.at(i).selectors.at(0);-
1980 const QString pseudoElement = selector.pseudoElement();-
1981-
1982 if (extraPseudo && pseudoElement == QLatin1String(extraPseudo)) {-
1983 decls += rules.at(i).declarations;-
1984 continue;-
1985 }-
1986-
1987 if (!pseudoElement.isEmpty())-
1988 continue;-
1989 quint64 pseudoClass = selector.pseudoClass();-
1990 if (pseudoClass == PseudoClass_Enabled || pseudoClass == PseudoClass_Unspecified)-
1991 decls += rules.at(i).declarations;-
1992 }-
1993 return decls;-
1994}-
1995-
1996static inline bool isHexDigit(const char c)-
1997{-
1998 return (c >= '0' && c <= '9')-
1999 || (c >= 'a' && c <= 'f')-
2000 || (c >= 'A' && c <= 'F')-
2001 ;-
2002}-
2003-
2004QString Scanner::preprocess(const QString &input, bool *hasEscapeSequences)-
2005{-
2006 QString output = input;-
2007-
2008 if (hasEscapeSequences)-
2009 *hasEscapeSequences = false;-
2010-
2011 int i = 0;-
2012 while (i < output.size()) {-
2013 if (output.at(i) == QLatin1Char('\\')) {-
2014-
2015 ++i;-
2016-
2017 int hexCount = 0;-
2018 const int hexStart = i;-
2019 while (i < output.size()-
2020 && isHexDigit(output.at(i).toLatin1())-
2021 && hexCount < 7) {-
2022 ++hexCount;-
2023 ++i;-
2024 }-
2025 if (hexCount == 0) {-
2026 if (hasEscapeSequences)-
2027 *hasEscapeSequences = true;-
2028 continue;-
2029 }-
2030-
2031 hexCount = qMin(hexCount, 6);-
2032 bool ok = false;-
2033 ushort code = output.mid(hexStart, hexCount).toUShort(&ok, 16);-
2034 if (ok) {-
2035 output.replace(hexStart - 1, hexCount + 1, QChar(code));-
2036 i = hexStart;-
2037 } else {-
2038 i = hexStart;-
2039 }-
2040 } else {-
2041 ++i;-
2042 }-
2043 }-
2044 return output;-
2045}-
2046-
2047int QCssScanner_Generated::handleCommentStart()-
2048{-
2049 while (pos < input.size() - 1) {-
2050 if (input.at(pos) == QLatin1Char('*')-
2051 && input.at(pos + 1) == QLatin1Char('/')) {-
2052 pos += 2;-
2053 break;-
2054 }-
2055 ++pos;-
2056 }-
2057 return S;-
2058}-
2059-
2060void Scanner::scan(const QString &preprocessedInput, QVector<Symbol> *symbols)-
2061{-
2062 QCssScanner_Generated scanner(preprocessedInput);-
2063 Symbol sym;-
2064 int tok = scanner.lex();-
2065 while (tok != -1) {-
2066 sym.token = static_cast<QCss::TokenType>(tok);-
2067 sym.text = scanner.input;-
2068 sym.start = scanner.lexemStart;-
2069 sym.len = scanner.lexemLength;-
2070 symbols->append(sym);-
2071 tok = scanner.lex();-
2072 }-
2073}-
2074-
2075QString Symbol::lexem() const-
2076{-
2077 QString result;-
2078 if (len > 0)-
2079 result.reserve(len);-
2080 for (int i = 0; i < len; ++i) {-
2081 if (text.at(start + i) == QLatin1Char('\\') && i < len - 1)-
2082 ++i;-
2083 result += text.at(start + i);-
2084 }-
2085 return result;-
2086}-
2087-
2088Parser::Parser(const QString &css, bool isFile)-
2089{-
2090 init(css, isFile);-
2091}-
2092-
2093Parser::Parser()-
2094{-
2095 index = 0;-
2096 errorIndex = -1;-
2097 hasEscapeSequences = false;-
2098}-
2099-
2100void Parser::init(const QString &css, bool isFile)-
2101{-
2102 QString styleSheet = css;-
2103 if (isFile
isFileDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
2104 QFile file(css);-
2105 if (file.open(QFile::ReadOnly)
file.open(QFile::ReadOnly)Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
2106 sourcePath = QFileInfo(styleSheet).absolutePath() + QLatin1Char('/');-
2107 QTextStream stream(&file);-
2108 styleSheet = stream.readAll();-
2109 }
never executed: end of block
else {
0
2110 QMessageLogger(__FILE__, 21602167, __PRETTY_FUNCTION__).warning() << "QCss::Parser - Failed to load file " << css;-
2111 styleSheet.clear();-
2112 }
never executed: end of block
0
2113 } else {-
2114 sourcePath.clear();-
2115 }
never executed: end of block
0
2116-
2117 hasEscapeSequences = false;-
2118 symbols.resize(0);clear();-
2119 symbols.reserve(8);-
2120 Scanner::scan(Scanner::preprocess(styleSheet, &hasEscapeSequences), &symbols);-
2121 index = 0;-
2122 errorIndex = -1;-
2123}
never executed: end of block
0
2124-
2125bool Parser::parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity)-
2126{-
2127 if (testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("charset"))) {-
2128 while (test(S) || test(CDO) || test(CDC)) {}-
2129 if (!next(STRING)) return false;-
2130 if (!next(SEMICOLON)) return false;-
2131 }-
2132-
2133 while (test(S) || test(CDO) || test(CDC)) {}-
2134-
2135 while (testImport()) {-
2136 ImportRule rule;-
2137 if (!parseImport(&rule)) return false;-
2138 styleSheet->importRules.append(rule);-
2139 while (test(S) || test(CDO) || test(CDC)) {}-
2140 }-
2141-
2142 do {-
2143 if (testMedia()) {-
2144 MediaRule rule;-
2145 if (!parseMedia(&rule)) return false;-
2146 styleSheet->mediaRules.append(rule);-
2147 } else if (testPage()) {-
2148 PageRule rule;-
2149 if (!parsePage(&rule)) return false;-
2150 styleSheet->pageRules.append(rule);-
2151 } else if (testRuleset()) {-
2152 StyleRule rule;-
2153 if (!parseRuleset(&rule)) return false;-
2154 styleSheet->styleRules.append(rule);-
2155 } else if (test(ATKEYWORD_SYM)) {-
2156 if (!until(RBRACE)) return false;-
2157 } else if (hasNext()) {-
2158 return false;-
2159 }-
2160 while (test(S) || test(CDO) || test(CDC)) {}-
2161 } while (hasNext());-
2162 styleSheet->buildIndexes(nameCaseSensitivity);-
2163 return true;-
2164}-
2165-
2166Symbol Parser::errorSymbol()-
2167{-
2168 if (errorIndex == -1) return Symbol();-
2169 return symbols.at(errorIndex);-
2170}-
2171-
2172static inline void removeOptionalQuotes(QString *str)-
2173{-
2174 if (!str->startsWith(QLatin1Char('\''))-
2175 && !str->startsWith(QLatin1Char('\"')))-
2176 return;-
2177 str->remove(0, 1);-
2178 str->chop(1);-
2179}-
2180-
2181bool Parser::parseImport(ImportRule *importRule)-
2182{-
2183 skipSpace();-
2184-
2185 if (test(STRING)) {-
2186 importRule->href = lexem();-
2187 } else {-
2188 if (!testAndParseUri(&importRule->href)) return false;-
2189 }-
2190 removeOptionalQuotes(&importRule->href);-
2191-
2192 skipSpace();-
2193-
2194 if (testMedium()) {-
2195 if (!parseMedium(&importRule->media)) return false;-
2196-
2197 while (test(COMMA)) {-
2198 skipSpace();-
2199 if (!parseNextMedium(&importRule->media)) return false;-
2200 }-
2201 }-
2202-
2203 if (!next(SEMICOLON)) return false;-
2204-
2205 skipSpace();-
2206 return true;-
2207}-
2208-
2209bool Parser::parseMedia(MediaRule *mediaRule)-
2210{-
2211 do {-
2212 skipSpace();-
2213 if (!parseNextMedium(&mediaRule->media)) return false;-
2214 } while (test(COMMA));-
2215-
2216 if (!next(LBRACE)) return false;-
2217 skipSpace();-
2218-
2219 while (testRuleset()) {-
2220 StyleRule rule;-
2221 if (!parseRuleset(&rule)) return false;-
2222 mediaRule->styleRules.append(rule);-
2223 }-
2224-
2225 if (!next(RBRACE)) return false;-
2226 skipSpace();-
2227 return true;-
2228}-
2229-
2230bool Parser::parseMedium(QStringList *media)-
2231{-
2232 media->append(lexem());-
2233 skipSpace();-
2234 return true;-
2235}-
2236-
2237bool Parser::parsePage(PageRule *pageRule)-
2238{-
2239 skipSpace();-
2240-
2241 if (testPseudoPage())-
2242 if (!parsePseudoPage(&pageRule->selector)) return false;-
2243-
2244 skipSpace();-
2245 if (!next(LBRACE)) return false;-
2246-
2247 do {-
2248 skipSpace();-
2249 Declaration decl;-
2250 if (!parseNextDeclaration(&decl)) return false;-
2251 if (!decl.isEmpty())-
2252 pageRule->declarations.append(decl);-
2253 } while (test(SEMICOLON));-
2254-
2255 if (!next(RBRACE)) return false;-
2256 skipSpace();-
2257 return true;-
2258}-
2259-
2260bool Parser::parsePseudoPage(QString *selector)-
2261{-
2262 if (!next(IDENT)) return false;-
2263 *selector = lexem();-
2264 return true;-
2265}-
2266-
2267bool Parser::parseNextOperator(Value *value)-
2268{-
2269 if (!hasNext()) return true;-
2270 switch (next()) {-
2271 case SLASH: value->type = Value::TermOperatorSlash; skipSpace(); break;-
2272 case COMMA: value->type = Value::TermOperatorComma; skipSpace(); break;-
2273 default: prev(); break;-
2274 }-
2275 return true;-
2276}-
2277-
2278bool Parser::parseCombinator(BasicSelector::Relation *relation)-
2279{-
2280 *relation = BasicSelector::NoRelation;-
2281 if (lookup() == S) {-
2282 *relation = BasicSelector::MatchNextSelectorIfAncestor;-
2283 skipSpace();-
2284 } else {-
2285 prev();-
2286 }-
2287 if (test(PLUS)) {-
2288 *relation = BasicSelector::MatchNextSelectorIfPreceeds;-
2289 } else if (test(GREATER)) {-
2290 *relation = BasicSelector::MatchNextSelectorIfParent;-
2291 }-
2292 skipSpace();-
2293 return true;-
2294}-
2295-
2296bool Parser::parseProperty(Declaration *decl)-
2297{-
2298 decl->d->property = lexem();-
2299 decl->d->propertyId = static_cast<Property>(findKnownValue(decl->d->property, properties, NumProperties));-
2300 decl->d->inheritable = isInheritable(decl->d->propertyId);-
2301 skipSpace();-
2302 return true;-
2303}-
2304-
2305bool Parser::parseRuleset(StyleRule *styleRule)-
2306{-
2307 Selector sel;-
2308 if (!parseSelector(&sel)) return false;-
2309 styleRule->selectors.append(sel);-
2310-
2311 while (test(COMMA)) {-
2312 skipSpace();-
2313 Selector sel;-
2314 if (!parseNextSelector(&sel)) return false;-
2315 styleRule->selectors.append(sel);-
2316 }-
2317-
2318 skipSpace();-
2319 if (!next(LBRACE)) return false;-
2320 const int declarationStart = index;-
2321-
2322 do {-
2323 skipSpace();-
2324 Declaration decl;-
2325 const int rewind = index;-
2326 if (!parseNextDeclaration(&decl)) {-
2327 index = rewind;-
2328 const bool foundSemicolon = until(SEMICOLON);-
2329 const int semicolonIndex = index;-
2330-
2331 index = declarationStart;-
2332 const bool foundRBrace = until(RBRACE);-
2333-
2334 if (foundSemicolon && semicolonIndex < index) {-
2335 decl = Declaration();-
2336 index = semicolonIndex - 1;-
2337 } else {-
2338 skipSpace();-
2339 return foundRBrace;-
2340 }-
2341 }-
2342 if (!decl.isEmpty())-
2343 styleRule->declarations.append(decl);-
2344 } while (test(SEMICOLON));-
2345-
2346 if (!next(RBRACE)) return false;-
2347 skipSpace();-
2348 return true;-
2349}-
2350-
2351bool Parser::parseSelector(Selector *sel)-
2352{-
2353 BasicSelector basicSel;-
2354 if (!parseSimpleSelector(&basicSel)) return false;-
2355 while (testCombinator()) {-
2356 if (!parseCombinator(&basicSel.relationToNext)) return false;-
2357-
2358 if (!testSimpleSelector()) break;-
2359 sel->basicSelectors.append(basicSel);-
2360-
2361 basicSel = BasicSelector();-
2362 if (!parseSimpleSelector(&basicSel)) return false;-
2363 }-
2364 sel->basicSelectors.append(basicSel);-
2365 return true;-
2366}-
2367-
2368bool Parser::parseSimpleSelector(BasicSelector *basicSel)-
2369{-
2370 int minCount = 0;-
2371 if (lookupElementName()) {-
2372 if (!parseElementName(&basicSel->elementName)) return false;-
2373 } else {-
2374 prev();-
2375 minCount = 1;-
2376 }-
2377 bool onceMore;-
2378 int count = 0;-
2379 do {-
2380 onceMore = false;-
2381 if (test(HASH)) {-
2382 QString theid = lexem();-
2383-
2384 theid.remove(0, 1);-
2385 basicSel->ids.append(theid);-
2386 onceMore = true;-
2387 } else if (testClass()) {-
2388 onceMore = true;-
2389 AttributeSelector a;-
2390 a.name = QLatin1String("class");-
2391 a.valueMatchCriterium = AttributeSelector::MatchContains;-
2392 if (!parseClass(&a.value)) return false;-
2393 basicSel->attributeSelectors.append(a);-
2394 } else if (testAttrib()) {-
2395 onceMore = true;-
2396 AttributeSelector a;-
2397 if (!parseAttrib(&a)) return false;-
2398 basicSel->attributeSelectors.append(a);-
2399 } else if (testPseudo()) {-
2400 onceMore = true;-
2401 Pseudo ps;-
2402 if (!parsePseudo(&ps)) return false;-
2403 basicSel->pseudos.append(ps);-
2404 }-
2405 if (onceMore) ++count;-
2406 } while (onceMore);-
2407 return count >= minCount;-
2408}-
2409-
2410bool Parser::parseClass(QString *name)-
2411{-
2412 if (!next(IDENT)) return false;-
2413 *name = lexem();-
2414 return true;-
2415}-
2416-
2417bool Parser::parseElementName(QString *name)-
2418{-
2419 switch (lookup()) {-
2420 case STAR: name->clear(); break;-
2421 case IDENT: *name = lexem(); break;-
2422 default: return false;-
2423 }-
2424 return true;-
2425}-
2426-
2427bool Parser::parseAttrib(AttributeSelector *attr)-
2428{-
2429 skipSpace();-
2430 if (!next(IDENT)) return false;-
2431 attr->name = lexem();-
2432 skipSpace();-
2433-
2434 if (test(EQUAL)) {-
2435 attr->valueMatchCriterium = AttributeSelector::MatchEqual;-
2436 } else if (test(INCLUDES)) {-
2437 attr->valueMatchCriterium = AttributeSelector::MatchContains;-
2438 } else if (test(DASHMATCH)) {-
2439 attr->valueMatchCriterium = AttributeSelector::MatchBeginsWith;-
2440 } else {-
2441 return next(RBRACKET);-
2442 }-
2443-
2444 skipSpace();-
2445-
2446 if (!test(IDENT) && !test(STRING)) return false;-
2447 attr->value = unquotedLexem();-
2448-
2449 skipSpace();-
2450 return next(RBRACKET);-
2451}-
2452-
2453bool Parser::parsePseudo(Pseudo *pseudo)-
2454{-
2455 (void)test(COLON);-
2456 pseudo->negated = test(EXCLAMATION_SYM);-
2457 if (test(IDENT)) {-
2458 pseudo->name = lexem();-
2459 pseudo->type = static_cast<quint64>(findKnownValue(pseudo->name, pseudos, NumPseudos));-
2460 return true;-
2461 }-
2462 if (!next(FUNCTION)) return false;-
2463 pseudo->function = lexem();-
2464-
2465 pseudo->function.chop(1);-
2466 skipSpace();-
2467 if (!test(IDENT)) return false;-
2468 pseudo->name = lexem();-
2469 skipSpace();-
2470 return next(RPAREN);-
2471}-
2472-
2473bool Parser::parseNextDeclaration(Declaration *decl)-
2474{-
2475 if (!testProperty())-
2476 return true;-
2477 if (!parseProperty(decl)) return false;-
2478 if (!next(COLON)) return false;-
2479 skipSpace();-
2480 if (!parseNextExpr(&decl->d->values)) return false;-
2481 if (testPrio())-
2482 if (!parsePrio(decl)) return false;-
2483 return true;-
2484}-
2485-
2486bool Parser::testPrio()-
2487{-
2488 const int rewind = index;-
2489 if (!test(EXCLAMATION_SYM)) return false;-
2490 skipSpace();-
2491 if (!test(IDENT)) {-
2492 index = rewind;-
2493 return false;-
2494 }-
2495 if (lexem().compare(QLatin1String("important"), Qt::CaseInsensitive) != 0) {-
2496 index = rewind;-
2497 return false;-
2498 }-
2499 return true;-
2500}-
2501-
2502bool Parser::parsePrio(Declaration *declaration)-
2503{-
2504 declaration->d->important = true;-
2505 skipSpace();-
2506 return true;-
2507}-
2508-
2509bool Parser::parseExpr(QVector<Value> *values)-
2510{-
2511 Value val;-
2512 if (!parseTerm(&val)) return false;-
2513 values->append(val);-
2514 bool onceMore;-
2515 do {-
2516 onceMore = false;-
2517 val = Value();-
2518 if (!parseNextOperator(&val)) return false;-
2519 if (val.type != QCss::Value::Unknown)-
2520 values->append(val);-
2521 if (testTerm()) {-
2522 onceMore = true;-
2523 val = Value();-
2524 if (!parseTerm(&val)) return false;-
2525 values->append(val);-
2526 }-
2527 } while (onceMore);-
2528 return true;-
2529}-
2530-
2531bool Parser::testTerm()-
2532{-
2533 return test(PLUS) || test(MINUS)-
2534 || test(NUMBER)-
2535 || test(PERCENTAGE)-
2536 || test(LENGTH)-
2537 || test(STRING)-
2538 || test(IDENT)-
2539 || testHexColor()-
2540 || testFunction();-
2541}-
2542-
2543bool Parser::parseTerm(Value *value)-
2544{-
2545 QString str = lexem();-
2546 bool haveUnary = false;-
2547 if (lookup() == PLUS || lookup() == MINUS) {-
2548 haveUnary = true;-
2549 if (!hasNext()) return false;-
2550 next();-
2551 str += lexem();-
2552 }-
2553-
2554 value->variant = str;-
2555 value->type = QCss::Value::String;-
2556 switch (lookup()) {-
2557 case NUMBER:-
2558 value->type = Value::Number;-
2559 value->variant.convert(QVariant::Double);-
2560 break;-
2561 case PERCENTAGE:-
2562 value->type = Value::Percentage;-
2563 str.chop(1);-
2564 value->variant = str;-
2565 break;-
2566 case LENGTH:-
2567 value->type = Value::Length;-
2568 break;-
2569-
2570 case STRING:-
2571 if (haveUnary) return false;-
2572 value->type = Value::String;-
2573 str.chop(1);-
2574 str.remove(0, 1);-
2575 value->variant = str;-
2576 break;-
2577 case IDENT: {-
2578 if (haveUnary) return false;-
2579 value->type = Value::Identifier;-
2580 const int theid = findKnownValue(str, values, NumKnownValues);-
2581 if (theid != 0) {-
2582 value->type = Value::KnownIdentifier;-
2583 value->variant = theid;-
2584 }-
2585 break;-
2586 }-
2587 default: {-
2588 if (haveUnary) return false;-
2589 prev();-
2590 if (testHexColor()) {-
2591 QColor col;-
2592 if (!parseHexColor(&col)) return false;-
2593 value->type = Value::Color;-
2594 value->variant = col;-
2595 } else if (testFunction()) {-
2596 QString name, args;-
2597 if (!parseFunction(&name, &args)) return false;-
2598 if (name == QLatin1String("url")) {-
2599 value->type = Value::Uri;-
2600 removeOptionalQuotes(&args);-
2601 if (QFileInfo(args).isRelative() && !sourcePath.isEmpty()) {-
2602 args.prepend(sourcePath);-
2603 }-
2604 value->variant = args;-
2605 } else {-
2606 value->type = Value::Function;-
2607 value->variant = QStringList() << name << args;-
2608 }-
2609 } else {-
2610 return recordError();-
2611 }-
2612 return true;-
2613 }-
2614 }-
2615 skipSpace();-
2616 return true;-
2617}-
2618-
2619bool Parser::parseFunction(QString *name, QString *args)-
2620{-
2621 *name = lexem();-
2622 name->chop(1);-
2623 skipSpace();-
2624 const int start = index;-
2625 if (!until(RPAREN)) return false;-
2626 for (int i = start; i < index - 1; ++i)-
2627 args->append(symbols.at(i).lexem());-
2628-
2629-
2630-
2631-
2632 skipSpace();-
2633 return true;-
2634}-
2635-
2636bool Parser::parseHexColor(QColor *col)-
2637{-
2638 col->setNamedColor(lexem());-
2639 if (!col->isValid()) {-
2640 QMessageLogger(__FILE__, 26902697, __PRETTY_FUNCTION__).warning("QCssParser::parseHexColor: Unknown color name '%s'",lexem().toLatin1().constData());-
2641 return false;-
2642 }-
2643 skipSpace();-
2644 return true;-
2645}-
2646-
2647bool Parser::testAndParseUri(QString *uri)-
2648{-
2649 const int rewind = index;-
2650 if (!testFunction()) return false;-
2651-
2652 QString name, args;-
2653 if (!parseFunction(&name, &args)) {-
2654 index = rewind;-
2655 return false;-
2656 }-
2657 if (name.toLower() != QLatin1String("url")) {-
2658 index = rewind;-
2659 return false;-
2660 }-
2661 *uri = args;-
2662 removeOptionalQuotes(uri);-
2663 return true;-
2664}-
2665-
2666bool Parser::testSimpleSelector()-
2667{-
2668 return testElementName()-
2669 || (test(HASH))-
2670 || testClass()-
2671 || testAttrib()-
2672 || testPseudo();-
2673}-
2674-
2675bool Parser::next(QCss::TokenType t)-
2676{-
2677 if (hasNext() && next() == t)-
2678 return true;-
2679 return recordError();-
2680}-
2681-
2682bool Parser::test(QCss::TokenType t)-
2683{-
2684 if (index >= symbols.count())-
2685 return false;-
2686 if (symbols.at(index).token == t) {-
2687 ++index;-
2688 return true;-
2689 }-
2690 return false;-
2691}-
2692-
2693QString Parser::unquotedLexem() const-
2694{-
2695 QString s = lexem();-
2696 if (lookup() == STRING) {-
2697 s.chop(1);-
2698 s.remove(0, 1);-
2699 }-
2700 return s;-
2701}-
2702-
2703QString Parser::lexemUntil(QCss::TokenType t)-
2704{-
2705 QString lexem;-
2706 while (hasNext() && next() != t)-
2707 lexem += symbol().lexem();-
2708 return lexem;-
2709}-
2710-
2711bool Parser::until(QCss::TokenType target, QCss::TokenType target2)-
2712{-
2713 int braceCount = 0;-
2714 int brackCount = 0;-
2715 int parenCount = 0;-
2716 if (index) {-
2717 switch(symbols.at(index-1).token) {-
2718 case LBRACE: ++braceCount; break;-
2719 case LBRACKET: ++brackCount; break;-
2720 case FUNCTION:-
2721 case LPAREN: ++parenCount; break;-
2722 default: ;-
2723 }-
2724 }-
2725 while (index < symbols.size()) {-
2726 QCss::TokenType t = symbols.at(index++).token;-
2727 switch (t) {-
2728 case LBRACE: ++braceCount; break;-
2729 case RBRACE: --braceCount; break;-
2730 case LBRACKET: ++brackCount; break;-
2731 case RBRACKET: --brackCount; break;-
2732 case FUNCTION:-
2733 case LPAREN: ++parenCount; break;-
2734 case RPAREN: --parenCount; break;-
2735 default: break;-
2736 }-
2737 if ((t == target || (target2 != NONE && t == target2))-
2738 && braceCount <= 0-
2739 && brackCount <= 0-
2740 && parenCount <= 0)-
2741 return true;-
2742-
2743 if (braceCount < 0 || brackCount < 0 || parenCount < 0) {-
2744 --index;-
2745 break;-
2746 }-
2747 }-
2748 return false;-
2749}-
2750-
2751bool Parser::testTokenAndEndsWith(QCss::TokenType t, QLatin1String str)-
2752{-
2753 if (!test(t)) return false;-
2754 if (!lexem().endsWith(str, Qt::CaseInsensitive)) {-
2755 prev();-
2756 return false;-
2757 }-
2758 return true;-
2759}-
2760-
2761-
Switch to Source codePreprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9