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