Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qcssparser.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qcssparser_p.h"
5
6#include <QtCore/qmap.h>
7#include <qdebug.h>
8#include <qicon.h>
9#include <qcolor.h>
10#include <qfont.h>
11#include <qfileinfo.h>
12#include <qfontmetrics.h>
13#include <qbrush.h>
14#include <qimagereader.h>
15#include <qtextformat.h>
16
17#include <algorithm>
18
19#ifndef QT_NO_CSSPARSER
20
22
23using namespace Qt::StringLiterals;
24
28
29#include "qcssscanner.cpp"
30
31using namespace QCss;
32
34{
35 const char name[28];
37};
38
39// This array is sorted alphabetically.
41 { "-qt-background-role", QtBackgroundRole },
42 { "-qt-block-indent", QtBlockIndent },
43 { "-qt-fg-texture-cachekey", QtForegroundTextureCacheKey },
44 { "-qt-foreground", QtForeground },
45 { "-qt-line-height-type", QtLineHeightType },
46 { "-qt-list-indent", QtListIndent },
47 { "-qt-list-number-prefix", QtListNumberPrefix },
48 { "-qt-list-number-suffix", QtListNumberSuffix },
49 { "-qt-paragraph-type", QtParagraphType },
50 { "-qt-stroke-color", QtStrokeColor },
51 { "-qt-stroke-dasharray", QtStrokeDashArray },
52 { "-qt-stroke-dashoffset", QtStrokeDashOffset },
53 { "-qt-stroke-linecap", QtStrokeLineCap },
54 { "-qt-stroke-linejoin", QtStrokeLineJoin },
55 { "-qt-stroke-miterlimit", QtStrokeMiterLimit },
56 { "-qt-stroke-width", QtStrokeWidth },
57 { "-qt-style-features", QtStyleFeatures },
58 { "-qt-table-type", QtTableType },
59 { "-qt-user-state", QtUserState },
60 { "accent-color", QtAccent },
61 { "alternate-background-color", QtAlternateBackground },
62 { "background", Background },
63 { "background-attachment", BackgroundAttachment },
64 { "background-clip", BackgroundClip },
65 { "background-color", BackgroundColor },
66 { "background-image", BackgroundImage },
67 { "background-origin", BackgroundOrigin },
68 { "background-position", BackgroundPosition },
69 { "background-repeat", BackgroundRepeat },
70 { "border", Border },
71 { "border-bottom", BorderBottom },
72 { "border-bottom-color", BorderBottomColor },
73 { "border-bottom-left-radius", BorderBottomLeftRadius },
74 { "border-bottom-right-radius", BorderBottomRightRadius },
75 { "border-bottom-style", BorderBottomStyle },
76 { "border-bottom-width", BorderBottomWidth },
77 { "border-collapse", BorderCollapse },
78 { "border-color", BorderColor },
79 { "border-image", BorderImage },
80 { "border-left", BorderLeft },
81 { "border-left-color", BorderLeftColor },
82 { "border-left-style", BorderLeftStyle },
83 { "border-left-width", BorderLeftWidth },
84 { "border-radius", BorderRadius },
85 { "border-right", BorderRight },
86 { "border-right-color", BorderRightColor },
87 { "border-right-style", BorderRightStyle },
88 { "border-right-width", BorderRightWidth },
89 { "border-style", BorderStyles },
90 { "border-top", BorderTop },
91 { "border-top-color", BorderTopColor },
92 { "border-top-left-radius", BorderTopLeftRadius },
93 { "border-top-right-radius", BorderTopRightRadius },
94 { "border-top-style", BorderTopStyle },
95 { "border-top-width", BorderTopWidth },
96 { "border-width", BorderWidth },
97 { "bottom", Bottom },
98 { "color", Color },
99 { "float", Float },
100 { "font", Font },
101 { "font-family", FontFamily },
102 { "font-kerning", FontKerning },
103 { "font-size", FontSize },
104 { "font-style", FontStyle },
105 { "font-variant", FontVariant },
106 { "font-weight", FontWeight },
107 { "height", Height },
108 { "icon", QtIcon },
109 { "image", QtImage },
110 { "image-position", QtImageAlignment },
111 { "left", Left },
112 { "letter-spacing", LetterSpacing },
113 { "line-height", LineHeight },
114 { "list-style", ListStyle },
115 { "list-style-type", ListStyleType },
116 { "margin" , Margin },
117 { "margin-bottom", MarginBottom },
118 { "margin-left", MarginLeft },
119 { "margin-right", MarginRight },
120 { "margin-top", MarginTop },
121 { "max-height", MaximumHeight },
122 { "max-width", MaximumWidth },
123 { "min-height", MinimumHeight },
124 { "min-width", MinimumWidth },
125 { "outline", Outline },
126 { "outline-bottom-left-radius", OutlineBottomLeftRadius },
127 { "outline-bottom-right-radius", OutlineBottomRightRadius },
128 { "outline-color", OutlineColor },
129 { "outline-offset", OutlineOffset },
130 { "outline-radius", OutlineRadius },
131 { "outline-style", OutlineStyle },
132 { "outline-top-left-radius", OutlineTopLeftRadius },
133 { "outline-top-right-radius", OutlineTopRightRadius },
134 { "outline-width", OutlineWidth },
135 { "padding", Padding },
136 { "padding-bottom", PaddingBottom },
137 { "padding-left", PaddingLeft },
138 { "padding-right", PaddingRight },
139 { "padding-top", PaddingTop },
140 { "page-break-after", PageBreakAfter },
141 { "page-break-before", PageBreakBefore },
142 { "placeholder-text-color", QtPlaceHolderTextColor },
143 { "position", Position },
144 { "right", Right },
145 { "selection-background-color", QtSelectionBackground },
146 { "selection-color", QtSelectionForeground },
147 { "spacing", QtSpacing },
148 { "subcontrol-origin", QtOrigin },
149 { "subcontrol-position", QtPosition },
150 { "text-align", TextAlignment },
151 { "text-decoration", TextDecoration },
152 { "text-decoration-color", TextDecorationColor },
153 { "text-indent", TextIndent },
154 { "text-transform", TextTransform },
155 { "text-underline-style", TextUnderlineStyle },
156 { "top", Top },
157 { "vertical-align", VerticalAlignment },
158 { "white-space", Whitespace },
159 { "width", Width },
160 { "word-spacing", WordSpacing }
161};
162
164 { "active", Value_Active },
165 { "alternate-base", Value_AlternateBase },
166 { "always", Value_Always },
167 { "auto", Value_Auto },
168 { "base", Value_Base },
169 { "beveljoin", Value_BevelJoin},
170 { "bold", Value_Bold },
171 { "bottom", Value_Bottom },
172 { "bright-text", Value_BrightText },
173 { "button", Value_Button },
174 { "button-text", Value_ButtonText },
175 { "center", Value_Center },
176 { "circle", Value_Circle },
177 { "dark", Value_Dark },
178 { "dashed", Value_Dashed },
179 { "decimal", Value_Decimal },
180 { "disabled", Value_Disabled },
181 { "disc", Value_Disc },
182 { "dot-dash", Value_DotDash },
183 { "dot-dot-dash", Value_DotDotDash },
184 { "dotted", Value_Dotted },
185 { "double", Value_Double },
186 { "flatcap", Value_FlatCap},
187 { "groove", Value_Groove },
188 { "highlight", Value_Highlight },
189 { "highlighted-text", Value_HighlightedText },
190 { "inset", Value_Inset },
191 { "italic", Value_Italic },
192 { "large", Value_Large },
193 { "left", Value_Left },
194 { "light", Value_Light },
195 { "line-through", Value_LineThrough },
196 { "link", Value_Link },
197 { "link-visited", Value_LinkVisited },
198 { "lower-alpha", Value_LowerAlpha },
199 { "lower-roman", Value_LowerRoman },
200 { "lowercase", Value_Lowercase },
201 { "medium", Value_Medium },
202 { "mid", Value_Mid },
203 { "middle", Value_Middle },
204 { "midlight", Value_Midlight },
205 { "miterjoin", Value_MiterJoin},
206 { "native", Value_Native },
207 { "none", Value_None },
208 { "normal", Value_Normal },
209 { "nowrap", Value_NoWrap },
210 { "oblique", Value_Oblique },
211 { "off", Value_Off },
212 { "on", Value_On },
213 { "outset", Value_Outset },
214 { "overline", Value_Overline },
215 { "pre", Value_Pre },
216 { "pre-line", Value_PreLine },
217 { "pre-wrap", Value_PreWrap },
218 { "ridge", Value_Ridge },
219 { "right", Value_Right },
220 { "roundcap", Value_RoundCap},
221 { "roundjoin", Value_RoundJoin},
222 { "selected", Value_Selected },
223 { "shadow", Value_Shadow },
224 { "small" , Value_Small },
225 { "small-caps", Value_SmallCaps },
226 { "solid", Value_Solid },
227 { "square", Value_Square },
228 { "squarecap", Value_SquareCap},
229 { "sub", Value_Sub },
230 { "super", Value_Super },
231 { "svgmiterjoin", Value_SvgMiterJoin},
232 { "text", Value_Text },
233 { "top", Value_Top },
234 { "transparent", Value_Transparent },
235 { "underline", Value_Underline },
236 { "upper-alpha", Value_UpperAlpha },
237 { "upper-roman", Value_UpperRoman },
238 { "uppercase", Value_Uppercase },
239 { "wave", Value_Wave },
240 { "window", Value_Window },
241 { "window-text", Value_WindowText },
242 { "x-large", Value_XLarge },
243 { "xx-large", Value_XXLarge }
244};
245
246//Map id to strings as they appears in the 'values' array above
247static const short indexOfId[NumKnownValues] = { 0, 44, 51, 45, 52, 53, 60, 37, 28, 78, 79, 27, 46, 6, 71, 50,
248 31, 65, 66, 29, 55, 69, 7, 11, 42, 62, 20, 14, 18, 19, 21, 23, 54, 26, 49, 75, 39, 3, 2, 43, 70, 17, 12,
249 63, 15, 34, 72, 35, 73, 61, 74, 36, 64, 22, 56, 41, 5, 57, 67, 77, 9, 30, 40, 13, 38, 68, 8, 10, 4, 76,
250 59, 24, 25, 32, 33, 1, 16, 0, 58, 48, 47 };
251
253{
254 if (type == KnownIdentifier) {
256 } else {
257 return variant.toString();
258 }
259}
260
261static const QCssKnownValue pseudos[NumPseudos - 1] = {
262 { "active", PseudoClass_Active },
263 { "adjoins-item", PseudoClass_Item },
264 { "alternate", PseudoClass_Alternate },
265 { "bottom", PseudoClass_Bottom },
266 { "checked", PseudoClass_Checked },
267 { "closable", PseudoClass_Closable },
268 { "closed", PseudoClass_Closed },
269 { "default", PseudoClass_Default },
270 { "disabled", PseudoClass_Disabled },
271 { "edit-focus", PseudoClass_EditFocus },
272 { "editable", PseudoClass_Editable },
273 { "enabled", PseudoClass_Enabled },
274 { "exclusive", PseudoClass_Exclusive },
275 { "first", PseudoClass_First },
276 { "flat", PseudoClass_Flat },
277 { "floatable", PseudoClass_Floatable },
278 { "focus", PseudoClass_Focus },
279 { "has-children", PseudoClass_Children },
280 { "has-siblings", PseudoClass_Sibling },
281 { "horizontal", PseudoClass_Horizontal },
282 { "hover", PseudoClass_Hover },
283 { "indeterminate" , PseudoClass_Indeterminate },
284 { "last", PseudoClass_Last },
285 { "left", PseudoClass_Left },
286 { "maximized", PseudoClass_Maximized },
287 { "middle", PseudoClass_Middle },
288 { "minimized", PseudoClass_Minimized },
289 { "movable", PseudoClass_Movable },
290 { "next-selected", PseudoClass_NextSelected },
291 { "no-frame", PseudoClass_Frameless },
292 { "non-exclusive", PseudoClass_NonExclusive },
293 { "off", PseudoClass_Unchecked },
294 { "on", PseudoClass_Checked },
295 { "only-one", PseudoClass_OnlyOne },
296 { "open", PseudoClass_Open },
297 { "pressed", PseudoClass_Pressed },
298 { "previous-selected", PseudoClass_PreviousSelected },
299 { "read-only", PseudoClass_ReadOnly },
300 { "right", PseudoClass_Right },
301 { "selected", PseudoClass_Selected },
302 { "top", PseudoClass_Top },
303 { "unchecked" , PseudoClass_Unchecked },
304 { "vertical", PseudoClass_Vertical },
305 { "window", PseudoClass_Window }
306};
307
309 { "border", Origin_Border },
310 { "content", Origin_Content },
311 { "margin", Origin_Margin }, // not in css
312 { "padding", Origin_Padding }
313};
314
316 { "no-repeat", Repeat_None },
317 { "repeat-x", Repeat_X },
318 { "repeat-xy", Repeat_XY },
319 { "repeat-y", Repeat_Y }
320};
321
323 { "repeat", TileMode_Repeat },
324 { "round", TileMode_Round },
325 { "stretch", TileMode_Stretch },
326};
327
329 { "absolute", PositionMode_Absolute },
330 { "fixed", PositionMode_Fixed },
331 { "relative", PositionMode_Relative },
332 { "static", PositionMode_Static }
333};
334
336 { "fixed", Attachment_Fixed },
337 { "scroll", Attachment_Scroll }
338};
339
341 { "background-color", StyleFeature_BackgroundColor },
342 { "background-gradient", StyleFeature_BackgroundGradient },
343 { "none", StyleFeature_None }
344};
345
346static bool operator<(const QString &name, const QCssKnownValue &prop)
347{
349}
350
351static bool operator<(const QCssKnownValue &prop, const QString &name)
352{
354}
355
356static quint64 findKnownValue(const QString &name, const QCssKnownValue *start, int numValues)
357{
358 const QCssKnownValue *end = start + numValues - 1;
359 const QCssKnownValue *prop = std::lower_bound(start, end, name);
360 if ((prop == end) || (name < *prop))
361 return 0;
362 return prop->id;
363}
364
365static inline bool isInheritable(Property propertyId)
366{
367 switch (propertyId) {
368 case Font:
369 case FontKerning:
370 case FontFamily:
371 case FontSize:
372 case FontStyle:
373 case FontWeight:
374 case TextIndent:
375 case Whitespace:
376 case ListStyleType:
377 case ListStyle:
378 case TextAlignment:
379 case FontVariant:
380 case TextTransform:
381 case LineHeight:
382 case LetterSpacing:
383 case WordSpacing:
384 return true;
385 default:
386 break;
387 }
388 return false;
389}
390
392// Value Extractor
393ValueExtractor::ValueExtractor(const QList<Declaration> &decls, const QPalette &pal)
394: declarations(decls), adjustment(0), fontExtracted(false), pal(pal)
395{
396}
397
398LengthData ValueExtractor::lengthValue(const Value& v)
399{
400 const QString str = v.variant.toString();
404 if (s.endsWith(u"px", Qt::CaseInsensitive))
405 data.unit = LengthData::Px;
406 else if (s.endsWith(u"ex", Qt::CaseInsensitive))
407 data.unit = LengthData::Ex;
408 else if (s.endsWith(u"em", Qt::CaseInsensitive))
409 data.unit = LengthData::Em;
410
411 if (data.unit != LengthData::None)
412 s.chop(2);
413 else if (v.type == Value::Percentage)
415
416 data.number = s.toDouble();
417 return data;
418}
419
420static int lengthValueFromData(const LengthData& data, const QFont& f)
421{
422 const int scale = (data.unit == LengthData::Ex ? QFontMetrics(f).xHeight()
423 : data.unit == LengthData::Em ? QFontMetrics(f).height() : 1);
424 // raised lower limit due to the implementation of qRound()
425 return qRound(qBound(double(INT_MIN) + 0.1, scale * data.number, double(INT_MAX)));
426}
427
429{
430 const LengthData data = lengthValue(decl.d->values.at(0));
431 if (data.unit == LengthData::Percent)
433
435}
436
437int ValueExtractor::lengthValue(const Declaration &decl)
438{
439 if (decl.d->parsed.isValid())
440 return lengthValueFromData(qvariant_cast<LengthData>(decl.d->parsed), f);
441 if (decl.d->values.size() < 1)
442 return 0;
443 LengthData data = lengthValue(decl.d->values.at(0));
444 decl.d->parsed = QVariant::fromValue<LengthData>(data);
445 return lengthValueFromData(data,f);
446}
447
449{
450 if (decl.d->parsed.isValid()) {
451 QList<QVariant> v = decl.d->parsed.toList();
452 Q_ASSERT(v.size() == 4);
453 for (int i = 0; i < 4; i++)
454 m[i] = lengthValueFromData(qvariant_cast<LengthData>(v.at(i)), f);
455 return;
456 }
457
458 LengthData datas[4];
459 int i;
460 for (i = 0; i < qMin(decl.d->values.size(), 4); i++)
461 datas[i] = lengthValue(decl.d->values[i]);
462
463 if (i == 0) {
465 datas[0] = datas[1] = datas[2] = datas[3] = zero;
466 } else if (i == 1) {
467 datas[3] = datas[2] = datas[1] = datas[0];
468 } else if (i == 2) {
469 datas[2] = datas[0];
470 datas[3] = datas[1];
471 } else if (i == 3) {
472 datas[3] = datas[1];
473 }
474
475 QList<QVariant> v;
476 v.reserve(4);
477 for (i = 0; i < 4; i++) {
478 v += QVariant::fromValue<LengthData>(datas[i]);
479 m[i] = lengthValueFromData(datas[i], f);
480 }
481 decl.d->parsed = v;
482}
483
484bool ValueExtractor::extractGeometry(int *w, int *h, int *minw, int *minh, int *maxw, int *maxh)
485{
486 extractFont();
487 bool hit = false;
488 for (int i = 0; i < declarations.size(); i++) {
489 const Declaration &decl = declarations.at(i);
490 switch (decl.d->propertyId) {
491 case Width: *w = lengthValue(decl); break;
492 case Height: *h = lengthValue(decl); break;
493 case MinimumWidth: *minw = lengthValue(decl); break;
494 case MinimumHeight: *minh = lengthValue(decl); break;
495 case MaximumWidth: *maxw = lengthValue(decl); break;
496 case MaximumHeight: *maxh = lengthValue(decl); break;
497 default: continue;
498 }
499 hit = true;
500 }
501
502 return hit;
503}
504
506 Qt::Alignment *position, QCss::PositionMode *mode, Qt::Alignment *textAlignment)
507{
508 extractFont();
509 bool hit = false;
510 for (int i = 0; i < declarations.size(); i++) {
511 const Declaration &decl = declarations.at(i);
512 switch (decl.d->propertyId) {
513 case Left: *left = lengthValue(decl); break;
514 case Top: *top = lengthValue(decl); break;
515 case Right: *right = lengthValue(decl); break;
516 case Bottom: *bottom = lengthValue(decl); break;
517 case QtOrigin: *origin = decl.originValue(); break;
518 case QtPosition: *position = decl.alignmentValue(); break;
519 case TextAlignment: *textAlignment = decl.alignmentValue(); break;
520 case Position: *mode = decl.positionValue(); break;
521 default: continue;
522 }
523 hit = true;
524 }
525
526 return hit;
527}
528
529bool ValueExtractor::extractBox(int *margins, int *paddings, int *spacing)
530{
531 extractFont();
532 bool hit = false;
533 for (int i = 0; i < declarations.size(); i++) {
534 const Declaration &decl = declarations.at(i);
535 switch (decl.d->propertyId) {
536 case PaddingLeft: paddings[LeftEdge] = lengthValue(decl); break;
537 case PaddingRight: paddings[RightEdge] = lengthValue(decl); break;
538 case PaddingTop: paddings[TopEdge] = lengthValue(decl); break;
539 case PaddingBottom: paddings[BottomEdge] = lengthValue(decl); break;
540 case Padding: lengthValues(decl, paddings); break;
541
542 case MarginLeft: margins[LeftEdge] = lengthValue(decl); break;
543 case MarginRight: margins[RightEdge] = lengthValue(decl); break;
544 case MarginTop: margins[TopEdge] = lengthValue(decl); break;
545 case MarginBottom: margins[BottomEdge] = lengthValue(decl); break;
546 case Margin: lengthValues(decl, margins); break;
547 case QtSpacing: if (spacing) *spacing = lengthValue(decl); break;
548
549 default: continue;
550 }
551 hit = true;
552 }
553
554 return hit;
555}
556
558{
559 int features = StyleFeature_None;
560 for (int i = 0; i < declarations.size(); i++) {
561 const Declaration &decl = declarations.at(i);
562 if (decl.d->propertyId == QtStyleFeatures)
563 features = decl.styleFeaturesValue();
564 }
565 return features;
566}
567
568QSize ValueExtractor::sizeValue(const Declaration &decl)
569{
570 if (decl.d->parsed.isValid()) {
571 QList<QVariant> v = decl.d->parsed.toList();
572 return QSize(lengthValueFromData(qvariant_cast<LengthData>(v.at(0)), f),
573 lengthValueFromData(qvariant_cast<LengthData>(v.at(1)), f));
574 }
575
576 LengthData x[2] = { {0, LengthData::None }, {0, LengthData::None} };
577 if (decl.d->values.size() > 0)
578 x[0] = lengthValue(decl.d->values.at(0));
579 if (decl.d->values.size() > 1)
580 x[1] = lengthValue(decl.d->values.at(1));
581 else
582 x[1] = x[0];
583 QList<QVariant> v;
584 v << QVariant::fromValue<LengthData>(x[0]) << QVariant::fromValue<LengthData>(x[1]);
585 decl.d->parsed = v;
587}
588
589void ValueExtractor::sizeValues(const Declaration &decl, QSize *radii)
590{
591 radii[0] = sizeValue(decl);
592 for (int i = 1; i < 4; i++)
593 radii[i] = radii[0];
594}
595
597 QSize *radii)
598{
599 extractFont();
600 bool hit = false;
601 for (int i = 0; i < declarations.size(); i++) {
602 const Declaration &decl = declarations.at(i);
603 switch (decl.d->propertyId) {
604 case BorderLeftWidth: borders[LeftEdge] = lengthValue(decl); break;
605 case BorderRightWidth: borders[RightEdge] = lengthValue(decl); break;
606 case BorderTopWidth: borders[TopEdge] = lengthValue(decl); break;
607 case BorderBottomWidth: borders[BottomEdge] = lengthValue(decl); break;
608 case BorderWidth: lengthValues(decl, borders); break;
609
610 case BorderLeftColor: colors[LeftEdge] = decl.brushValue(pal); break;
611 case BorderRightColor: colors[RightEdge] = decl.brushValue(pal); break;
612 case BorderTopColor: colors[TopEdge] = decl.brushValue(pal); break;
613 case BorderBottomColor: colors[BottomEdge] = decl.brushValue(pal); break;
614 case BorderColor: decl.brushValues(colors, pal); break;
615
616 case BorderTopStyle: styles[TopEdge] = decl.styleValue(); break;
617 case BorderBottomStyle: styles[BottomEdge] = decl.styleValue(); break;
618 case BorderLeftStyle: styles[LeftEdge] = decl.styleValue(); break;
619 case BorderRightStyle: styles[RightEdge] = decl.styleValue(); break;
620 case BorderStyles: decl.styleValues(styles); break;
621
622 case BorderTopLeftRadius: radii[0] = sizeValue(decl); break;
623 case BorderTopRightRadius: radii[1] = sizeValue(decl); break;
624 case BorderBottomLeftRadius: radii[2] = sizeValue(decl); break;
625 case BorderBottomRightRadius: radii[3] = sizeValue(decl); break;
626 case BorderRadius: sizeValues(decl, radii); break;
627
628 case BorderLeft:
629 borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]);
630 break;
631 case BorderTop:
632 borderValue(decl, &borders[TopEdge], &styles[TopEdge], &colors[TopEdge]);
633 break;
634 case BorderRight:
635 borderValue(decl, &borders[RightEdge], &styles[RightEdge], &colors[RightEdge]);
636 break;
637 case BorderBottom:
638 borderValue(decl, &borders[BottomEdge], &styles[BottomEdge], &colors[BottomEdge]);
639 break;
640 case Border:
641 borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]);
642 borders[TopEdge] = borders[RightEdge] = borders[BottomEdge] = borders[LeftEdge];
643 styles[TopEdge] = styles[RightEdge] = styles[BottomEdge] = styles[LeftEdge];
645 break;
646
647 default: continue;
648 }
649 hit = true;
650 }
651
652 return hit;
653}
654
656 QSize *radii, int *offsets)
657{
658 extractFont();
659 bool hit = false;
660 for (int i = 0; i < declarations.size(); i++) {
661 const Declaration &decl = declarations.at(i);
662 switch (decl.d->propertyId) {
663 case OutlineWidth: lengthValues(decl, borders); break;
664 case OutlineColor: decl.brushValues(colors, pal); break;
665 case OutlineStyle: decl.styleValues(styles); break;
666
667 case OutlineTopLeftRadius: radii[0] = sizeValue(decl); break;
668 case OutlineTopRightRadius: radii[1] = sizeValue(decl); break;
669 case OutlineBottomLeftRadius: radii[2] = sizeValue(decl); break;
670 case OutlineBottomRightRadius: radii[3] = sizeValue(decl); break;
671 case OutlineRadius: sizeValues(decl, radii); break;
672 case OutlineOffset: lengthValues(decl, offsets); break;
673
674 case Outline:
675 borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]);
676 borders[TopEdge] = borders[RightEdge] = borders[BottomEdge] = borders[LeftEdge];
677 styles[TopEdge] = styles[RightEdge] = styles[BottomEdge] = styles[LeftEdge];
679 break;
680
681 default: continue;
682 }
683 hit = true;
684 }
685
686 return hit;
687}
688
689static Qt::Alignment parseAlignment(const QCss::Value *values, int count)
690{
691 Qt::Alignment a[2] = { { }, { } };
692 for (int i = 0; i < qMin(2, count); i++) {
694 break;
695 switch (values[i].variant.toInt()) {
696 case Value_Left: a[i] = Qt::AlignLeft; break;
697 case Value_Right: a[i] = Qt::AlignRight; break;
698 case Value_Top: a[i] = Qt::AlignTop; break;
699 case Value_Bottom: a[i] = Qt::AlignBottom; break;
700 case Value_Center: a[i] = Qt::AlignCenter; break;
701 default: break;
702 }
703 }
704
705 if (a[0] == Qt::AlignCenter && a[1] != 0 && a[1] != Qt::AlignCenter)
707 if ((a[1] == 0 || a[1] == Qt::AlignCenter) && a[0] != Qt::AlignCenter)
709 return a[0] | a[1];
710}
711
713{
714 if (v.type == Value::Identifier || v.type == Value::String) {
715 v.variant.convert(QMetaType::fromType<QColor>());
716 v.type = Value::Color;
717 }
718
719 if (v.type == Value::Color)
720 return qvariant_cast<QColor>(v.variant);
721
722 if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_Transparent)
723 return QColor(Qt::transparent);
724
725 if (v.type != Value::Function)
726 return ColorData();
727
728 QStringList lst = v.variant.toStringList();
729 if (lst.size() != 2)
730 return ColorData();
731
732 const QString &identifier = lst.at(0);
733 if ((identifier.compare("palette"_L1, Qt::CaseInsensitive)) == 0) {
734 int role = findKnownValue(lst.at(1).trimmed(), values, NumKnownValues);
735 if (role >= Value_FirstColorRole && role <= Value_LastColorRole)
737
738 return ColorData();
739 }
740
741 const bool rgb = identifier.startsWith("rgb"_L1);
742 const bool hsv = !rgb && identifier.startsWith("hsv"_L1);
743 const bool hsl = !rgb && !hsv && identifier.startsWith("hsl"_L1);
744
745 if (!rgb && !hsv && !hsl)
746 return ColorData();
747
748 const bool hasAlpha = identifier.size() == 4 && identifier.at(3) == u'a';
749 if (identifier.size() > 3 && !hasAlpha)
750 return ColorData();
751
752 Parser p(lst.at(1));
753 if (!p.testExpr())
754 return ColorData();
755
756 QList<QCss::Value> colorDigits;
757 if (!p.parseExpr(&colorDigits))
758 return ColorData();
759 const int tokenCount = colorDigits.size();
760
761 for (int i = 0; i < qMin(tokenCount, 7); i += 2) {
762 if (colorDigits.at(i).type == Value::Percentage) {
763 const qreal maxRange = (rgb || i != 0) ? 255. : 359.;
764 colorDigits[i].variant = colorDigits.at(i).variant.toReal() * (maxRange / 100.);
765 colorDigits[i].type = Value::Number;
766 } else if (colorDigits.at(i).type != Value::Number) {
767 return ColorData();
768 }
769 }
770
771
772 if (tokenCount < 5)
773 return ColorData();
774
775 if (hasAlpha && tokenCount != 7) {
776 qWarning("QCssParser::parseColorValue: Specified color with alpha value but no alpha given: '%s'", qPrintable(lst.join(u' ')));
777 return ColorData();
778 }
779 if (!hasAlpha && tokenCount != 5) {
780 qWarning("QCssParser::parseColorValue: Specified color without alpha value but alpha given: '%s'", qPrintable(lst.join(u' ')));
781 return ColorData();
782 }
783
784 int v1 = colorDigits.at(0).variant.toInt();
785 int v2 = colorDigits.at(2).variant.toInt();
786 int v3 = colorDigits.at(4).variant.toInt();
787 int alpha = 255;
788 if (tokenCount == 7) {
789 int alphaValue = colorDigits.at(6).variant.toInt();
790 if (alphaValue <= 1)
791 alpha = colorDigits.at(6).variant.toReal() * 255.;
792 else
793 alpha = alphaValue;
794 }
795
796 if (rgb)
797 return QColor::fromRgb(v1, v2, v3, alpha);
798 if (hsv)
799 return QColor::fromHsv(v1, v2, v3, alpha);
800 return QColor::fromHsl(v1, v2, v3, alpha);
801}
802
803static QColor colorFromData(const ColorData& c, const QPalette &pal)
804{
805 if (c.type == ColorData::Color) {
806 return c.color;
807 } else if (c.type == ColorData::Role) {
808 return pal.color(c.role);
809 }
810 return QColor();
811}
812
814{
816 if (c.type == ColorData::Color) {
817 return QBrush(c.color);
818 } else if (c.type == ColorData::Role) {
819 return c.role;
820 }
821
822 if (v.type != Value::Function)
823 return BrushData();
824
825 QStringList lst = v.variant.toStringList();
826 if (lst.size() != 2)
827 return BrushData();
828
829 QStringList gradFuncs;
830 gradFuncs << "qlineargradient"_L1 << "qradialgradient"_L1 << "qconicalgradient"_L1 << "qgradient"_L1;
831 int gradType = -1;
832
833 if ((gradType = gradFuncs.indexOf(lst.at(0).toLower())) == -1)
834 return BrushData();
835
836 QHash<QString, qreal> vars;
837 QList<QGradientStop> stops;
838
839 int spread = -1;
840 QStringList spreads;
841 spreads << "pad"_L1 << "reflect"_L1 << "repeat"_L1;
842
843 int coordinateMode = -1;
844 QStringList coordinateModes;
845 coordinateModes << "logical"_L1 << "stretchtodevice"_L1 << "objectbounding"_L1 << "object"_L1;
846
847 bool dependsOnThePalette = false;
848 Parser parser(lst.at(1));
849 while (parser.hasNext()) {
850 parser.skipSpace();
851 if (!parser.test(IDENT))
852 return BrushData();
853 QString attr = parser.lexem();
854 parser.skipSpace();
855 if (!parser.test(COLON))
856 return BrushData();
857 parser.skipSpace();
858 if (attr.compare("stop"_L1, Qt::CaseInsensitive) == 0) {
859 QCss::Value stop, color;
860 parser.next();
861 if (!parser.parseTerm(&stop)) return BrushData();
862 parser.skipSpace();
863 parser.next();
864 if (!parser.parseTerm(&color)) return BrushData();
866 if (cd.type == ColorData::Role)
867 dependsOnThePalette = true;
868 stops.append(QGradientStop(stop.variant.toReal(), colorFromData(cd, pal)));
869 } else {
870 parser.next();
872 (void)parser.parseTerm(&value);
873 if (attr.compare("spread"_L1, Qt::CaseInsensitive) == 0)
874 spread = spreads.indexOf(value.variant.toString());
875 else if (attr.compare("coordinatemode"_L1, Qt::CaseInsensitive) == 0)
876 coordinateMode = coordinateModes.indexOf(value.variant.toString());
877 else
878 vars[attr] = value.variant.toReal();
879 }
880 parser.skipSpace();
881 (void)parser.test(COMMA);
882 }
883
884 if (gradType == 0) {
885 QLinearGradient lg(vars.value("x1"_L1), vars.value("y1"_L1),
886 vars.value("x2"_L1), vars.value("y2"_L1));
888 lg.setStops(stops);
889 if (spread != -1)
890 lg.setSpread(QGradient::Spread(spread));
891 BrushData bd = QBrush(lg);
892 if (dependsOnThePalette)
894 return bd;
895 }
896
897 if (gradType == 1) {
898 QRadialGradient rg(vars.value("cx"_L1), vars.value("cy"_L1),
899 vars.value("radius"_L1), vars.value("fx"_L1),
900 vars.value("fy"_L1));
902 rg.setStops(stops);
903 if (spread != -1)
904 rg.setSpread(QGradient::Spread(spread));
905 BrushData bd = QBrush(rg);
906 if (dependsOnThePalette)
908 return bd;
909 }
910
911 if (gradType == 2) {
912 QConicalGradient cg(vars.value("cx"_L1), vars.value("cy"_L1), vars.value("angle"_L1));
914 cg.setStops(stops);
915 if (spread != -1)
916 cg.setSpread(QGradient::Spread(spread));
917 BrushData bd = QBrush(cg);
918 if (dependsOnThePalette)
920 return bd;
921 }
922
923 return BrushData();
924}
925
926static QBrush brushFromData(const BrushData& c, const QPalette &pal)
927{
928 if (c.type == BrushData::Role) {
929 return pal.color(c.role);
930 } else {
931 return c.brush;
932 }
933}
934
936{
937 if (v.type == Value::KnownIdentifier) {
938 switch (v.variant.toInt()) {
939 case Value_None:
940 return BorderStyle_None;
941 case Value_Dotted:
942 return BorderStyle_Dotted;
943 case Value_Dashed:
944 return BorderStyle_Dashed;
945 case Value_Solid:
946 return BorderStyle_Solid;
947 case Value_Double:
948 return BorderStyle_Double;
949 case Value_DotDash:
950 return BorderStyle_DotDash;
951 case Value_DotDotDash:
953 case Value_Groove:
954 return BorderStyle_Groove;
955 case Value_Ridge:
956 return BorderStyle_Ridge;
957 case Value_Inset:
958 return BorderStyle_Inset;
959 case Value_Outset:
960 return BorderStyle_Outset;
961 case Value_Native:
962 return BorderStyle_Native;
963 default:
964 break;
965 }
966 }
967
968 return BorderStyle_Unknown;
969}
970
971void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::BorderStyle *style, QBrush *color)
972{
973 if (decl.d->parsed.isValid()) {
974 BorderData data = qvariant_cast<BorderData>(decl.d->parsed);
975 *width = lengthValueFromData(data.width, f);
976 *style = data.style;
977 *color = data.color.type != BrushData::Invalid ? brushFromData(data.color, pal) : QBrush(QColor());
978 return;
979 }
980
981 *width = 0;
982 *style = BorderStyle_None;
983 *color = QColor();
984
985 if (decl.d->values.isEmpty())
986 return;
987
989 data.width.number = 0;
990 data.width.unit = LengthData::None;
991 data.style = BorderStyle_None;
992
993 int i = 0;
994 if (decl.d->values.at(i).type == Value::Length || decl.d->values.at(i).type == Value::Number) {
995 data.width = lengthValue(decl.d->values.at(i));
996 *width = lengthValueFromData(data.width, f);
997 if (++i >= decl.d->values.size()) {
998 decl.d->parsed = QVariant::fromValue<BorderData>(data);
999 return;
1000 }
1001 }
1002
1003 data.style = parseStyleValue(decl.d->values.at(i));
1004 if (data.style != BorderStyle_Unknown) {
1005 *style = data.style;
1006 if (++i >= decl.d->values.size()) {
1007 decl.d->parsed = QVariant::fromValue<BorderData>(data);
1008 return;
1009 }
1010 } else {
1011 data.style = BorderStyle_None;
1012 }
1013
1014 data.color = parseBrushValue(decl.d->values.at(i), pal);
1015 if (data.color.type != BrushData::Invalid) {
1016 *color = brushFromData(data.color, pal);
1017 if (data.color.type != BrushData::DependsOnThePalette)
1018 decl.d->parsed = QVariant::fromValue<BorderData>(data);
1019 }
1020}
1021
1022static void parseShorthandBackgroundProperty(const QList<QCss::Value> &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal)
1023{
1024 *brush = BrushData();
1025 *image = QString();
1026 *repeat = Repeat_XY;
1028
1029 for (int i = 0; i < values.size(); ++i) {
1030 const QCss::Value &v = values.at(i);
1031 if (v.type == Value::Uri) {
1032 *image = v.variant.toString();
1033 continue;
1034 } else if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_None) {
1035 *image = QString();
1036 continue;
1037 } else if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_Transparent) {
1039 }
1040
1041 Repeat repeatAttempt = static_cast<Repeat>(findKnownValue(v.variant.toString(),
1043 if (repeatAttempt != Repeat_Unknown) {
1044 *repeat = repeatAttempt;
1045 continue;
1046 }
1047
1048 if (v.type == Value::KnownIdentifier) {
1049 const int start = i;
1050 int count = 1;
1051 if (i < values.size() - 1
1052 && values.at(i + 1).type == Value::KnownIdentifier) {
1053 ++i;
1054 ++count;
1055 }
1056 Qt::Alignment a = parseAlignment(values.constData() + start, count);
1057 if (int(a) != 0) {
1058 *alignment = a;
1059 continue;
1060 }
1061 i -= count - 1;
1062 }
1063
1064 *brush = parseBrushValue(v, pal);
1065 }
1066}
1067
1069 Qt::Alignment *alignment, Origin *origin, Attachment *attachment,
1070 Origin *clip)
1071{
1072 bool hit = false;
1073 for (int i = 0; i < declarations.size(); ++i) {
1074 const Declaration &decl = declarations.at(i);
1075 if (decl.d->values.isEmpty())
1076 continue;
1077 const QCss::Value &val = decl.d->values.at(0);
1078 switch (decl.d->propertyId) {
1079 case BackgroundColor:
1080 *brush = decl.brushValue();
1081 break;
1082 case BackgroundImage:
1083 if (val.type == Value::Uri)
1084 *image = val.variant.toString();
1085 break;
1086 case BackgroundRepeat:
1087 if (decl.d->parsed.isValid()) {
1088 *repeat = static_cast<Repeat>(decl.d->parsed.toInt());
1089 } else {
1090 *repeat = static_cast<Repeat>(findKnownValue(val.variant.toString(),
1092 decl.d->parsed = *repeat;
1093 }
1094 break;
1095 case BackgroundPosition:
1096 *alignment = decl.alignmentValue();
1097 break;
1098 case BackgroundOrigin:
1099 *origin = decl.originValue();
1100 break;
1101 case BackgroundClip:
1102 *clip = decl.originValue();
1103 break;
1104 case Background:
1105 if (decl.d->parsed.isValid()) {
1106 BackgroundData data = qvariant_cast<BackgroundData>(decl.d->parsed);
1107 *brush = brushFromData(data.brush, pal);
1108 *image = data.image;
1109 *repeat = data.repeat;
1110 *alignment = data.alignment;
1111 } else {
1112 BrushData brushData;
1113 parseShorthandBackgroundProperty(decl.d->values, &brushData, image, repeat, alignment, pal);
1114 *brush = brushFromData(brushData, pal);
1115 if (brushData.type != BrushData::DependsOnThePalette) {
1116 BackgroundData data = { brushData, *image, *repeat, *alignment };
1117 decl.d->parsed = QVariant::fromValue<BackgroundData>(data);
1118 }
1119 }
1120 break;
1122 *attachment = decl.attachmentValue();
1123 break;
1124 default: continue;
1125 }
1126 hit = true;
1127 }
1128 return hit;
1129}
1130
1131static bool setFontSizeFromValue(QCss::Value value, QFont *font, int *fontSizeAdjustment)
1132{
1133 if (value.type == Value::KnownIdentifier) {
1134 bool valid = true;
1135 switch (value.variant.toInt()) {
1136 case Value_Small: *fontSizeAdjustment = -1; break;
1137 case Value_Medium: *fontSizeAdjustment = 0; break;
1138 case Value_Large: *fontSizeAdjustment = 1; break;
1139 case Value_XLarge: *fontSizeAdjustment = 2; break;
1140 case Value_XXLarge: *fontSizeAdjustment = 3; break;
1141 default: valid = false; break;
1142 }
1143 return valid;
1144 }
1145 if (value.type != Value::Length)
1146 return false;
1147
1148 bool valid = false;
1149 QString s = value.variant.toString();
1150 if (s.endsWith("pt"_L1, Qt::CaseInsensitive)) {
1151 s.chop(2);
1152 value.variant = s;
1153 if (value.variant.convert(QMetaType::fromType<qreal>())) {
1154 font->setPointSizeF(qBound(qreal(0), value.variant.toReal(), qreal(1 << 24) - 1));
1155 valid = true;
1156 }
1157 } else if (s.endsWith("px"_L1, Qt::CaseInsensitive)) {
1158 s.chop(2);
1159 value.variant = s;
1160 if (value.variant.convert(QMetaType::fromType<int>())) {
1161 font->setPixelSize(qBound(0, value.variant.toInt(), (1 << 24) - 1));
1162 valid = true;
1163 }
1164 }
1165 return valid;
1166}
1167
1169{
1170 if (value.type != Value::KnownIdentifier)
1171 return false ;
1172 switch (value.variant.toInt()) {
1173 case Value_Normal: font->setStyle(QFont::StyleNormal); return true;
1174 case Value_Italic: font->setStyle(QFont::StyleItalic); return true;
1175 case Value_Oblique: font->setStyle(QFont::StyleOblique); return true;
1176 default: break;
1177 }
1178 return false;
1179}
1180
1182{
1183 if (value.type != Value::KnownIdentifier)
1184 return false ;
1185 switch (value.variant.toInt()) {
1186 case Value_Normal: font->setKerning(true); return true;
1187 case Value_None: font->setKerning(false); return true;
1188 case Value_Auto: return true;
1189 default: break;
1190 }
1191 return false;
1192}
1193
1195{
1196 if (value.type == Value::KnownIdentifier) {
1197 switch (value.variant.toInt()) {
1198 case Value_Normal: font->setWeight(QFont::Normal); return true;
1199 case Value_Bold: font->setWeight(QFont::Bold); return true;
1200 default: break;
1201 }
1202 return false;
1203 }
1204 if (value.type != Value::Number)
1205 return false;
1206 // .toInt() would call qRound64() and might overflow the long long there
1207 font->setWeight(QFont::Weight(qRound(qBound(0.0, value.variant.toDouble(), 1001.0))));
1208 return true;
1209}
1210
1216static bool setFontFamilyFromValues(const QList<QCss::Value> &values, QFont *font, int start = 0)
1217{
1218 QString family;
1219 QStringList families;
1220 bool shouldAddSpace = false;
1221 for (int i = start; i < values.size(); ++i) {
1222 const QCss::Value &v = values.at(i);
1223 if (v.type == Value::TermOperatorComma) {
1224 families << family;
1225 family.clear();
1226 shouldAddSpace = false;
1227 continue;
1228 }
1229 const QString str = v.variant.toString();
1230 if (str.isEmpty())
1231 break;
1232 if (shouldAddSpace)
1233 family += u' ';
1234 family += str;
1235 shouldAddSpace = true;
1236 }
1237 if (!family.isEmpty())
1238 families << family;
1239 if (families.isEmpty())
1240 return false;
1241 font->setFamilies(families);
1242 return true;
1243}
1244
1245static void setTextDecorationFromValues(const QList<QCss::Value> &values, QFont *font)
1246{
1247 for (int i = 0; i < values.size(); ++i) {
1248 if (values.at(i).type != Value::KnownIdentifier)
1249 continue;
1250 switch (values.at(i).variant.toInt()) {
1251 case Value_Underline: font->setUnderline(true); break;
1252 case Value_Overline: font->setOverline(true); break;
1253 case Value_LineThrough: font->setStrikeOut(true); break;
1254 case Value_None:
1255 font->setUnderline(false);
1256 font->setOverline(false);
1257 font->setStrikeOut(false);
1258 break;
1259 default: break;
1260 }
1261 }
1262}
1263
1265{
1266 QString s = value.variant.toString();
1267 qreal val;
1268 bool ok = false;
1269 if (s.endsWith("em"_L1, Qt::CaseInsensitive)) {
1270 s.chop(2);
1271 val = s.toDouble(&ok);
1272 if (ok)
1274 } else if (s.endsWith("px"_L1, Qt::CaseInsensitive)) {
1275 s.chop(2);
1276 val = s.toDouble(&ok);
1277 if (ok)
1279 }
1280}
1281
1283{
1284 QString s = value.variant.toString();
1285 if (s.endsWith("px"_L1, Qt::CaseInsensitive)) {
1286 s.chop(2);
1287 qreal val;
1288 bool ok = false;
1289 val = s.toDouble(&ok);
1290 if (ok)
1292 }
1293}
1294
1295static void parseShorthandFontProperty(const QList<QCss::Value> &values, QFont *font, int *fontSizeAdjustment)
1296{
1299 *fontSizeAdjustment = -255;
1300
1301 int i = 0;
1302 while (i < values.size()) {
1305 ++i;
1306 else
1307 break;
1308 }
1309
1310 if (i < values.size()) {
1311 setFontSizeFromValue(values.at(i), font, fontSizeAdjustment);
1312 ++i;
1313 }
1314
1315 if (i < values.size()) {
1317 }
1318}
1319
1321{
1322 if (value.type == Value::KnownIdentifier) {
1323 switch (value.variant.toInt()) {
1326 default: break;
1327 }
1328 }
1329}
1330
1332{
1333 if (value.type == Value::KnownIdentifier) {
1334 switch (value.variant.toInt()) {
1338 default: break;
1339 }
1340 }
1341}
1342
1343bool ValueExtractor::extractFont(QFont *font, int *fontSizeAdjustment)
1344{
1345 if (fontExtracted) {
1346 *font = f;
1347 *fontSizeAdjustment = adjustment;
1348 return fontExtracted == 1;
1349 }
1350
1351 bool hit = false;
1352 for (int i = 0; i < declarations.size(); ++i) {
1353 const Declaration &decl = declarations.at(i);
1354 if (decl.d->values.isEmpty())
1355 continue;
1356 const QCss::Value &val = decl.d->values.at(0);
1357 switch (decl.d->propertyId) {
1358 case FontSize: setFontSizeFromValue(val, font, fontSizeAdjustment); break;
1359 case FontStyle: setFontStyleFromValue(val, font); break;
1360 case FontWeight: setFontWeightFromValue(val, font); break;
1361 case FontFamily: setFontFamilyFromValues(decl.d->values, font); break;
1362 case FontKerning: setFontKerningFromValue(val, font); break;
1363 case TextDecoration: setTextDecorationFromValues(decl.d->values, font); break;
1364 case Font: parseShorthandFontProperty(decl.d->values, font, fontSizeAdjustment); break;
1365 case FontVariant: setFontVariantFromValue(val, font); break;
1366 case TextTransform: setTextTransformFromValue(val, font); break;
1367 case LetterSpacing: setLetterSpacingFromValue(val, font); break;
1368 case WordSpacing: setWordSpacingFromValue(val, font); break;
1369 default: continue;
1370 }
1371 hit = true;
1372 }
1373
1374 f = *font;
1375 adjustment = *fontSizeAdjustment;
1376 fontExtracted = hit ? 1 : 2;
1377 return hit;
1378}
1379
1381 QBrush *selectedForeground,
1382 QBrush *selectedBackground,
1383 QBrush *alternateBackground,
1384 QBrush *placeHolderTextForeground,
1385 QBrush *accent)
1386{
1387 bool hit = false;
1388 for (int i = 0; i < declarations.size(); ++i) {
1389 const Declaration &decl = declarations.at(i);
1390 switch (decl.d->propertyId) {
1391 case Color: *foreground = decl.brushValue(pal); break;
1392 case QtSelectionForeground: *selectedForeground = decl.brushValue(pal); break;
1393 case QtSelectionBackground: *selectedBackground = decl.brushValue(pal); break;
1394 case QtAlternateBackground: *alternateBackground = decl.brushValue(pal); break;
1395 case QtPlaceHolderTextColor: *placeHolderTextForeground = decl.brushValue(pal); break;
1396 case QtAccent: *accent = decl.brushValue(pal); break;
1397 default: continue;
1398 }
1399 hit = true;
1400 }
1401 return hit;
1402}
1403
1404void ValueExtractor::extractFont()
1405{
1406 if (fontExtracted)
1407 return;
1408 int dummy = -255;
1409 extractFont(&f, &dummy);
1410}
1411
1413{
1414 bool hit = false;
1415 for (int i = 0; i < declarations.size(); ++i) {
1416 const Declaration &decl = declarations.at(i);
1417 switch (decl.d->propertyId) {
1418 case QtImage:
1419 *icon = decl.iconValue();
1420 if (decl.d->values.size() > 0 && decl.d->values.at(0).type == Value::Uri) {
1421 // try to pull just the size from the image...
1422 QImageReader imageReader(decl.d->values.at(0).variant.toString());
1423 if ((*size = imageReader.size()).isNull()) {
1424 // but we'll have to load the whole image if the
1425 // format doesn't support just reading the size
1426 *size = imageReader.read().size();
1427 }
1428 }
1429 break;
1430 case QtImageAlignment: *a = decl.alignmentValue(); break;
1431 default: continue;
1432 }
1433 hit = true;
1434 }
1435 return hit;
1436}
1437
1439{
1440 // Find last declaration that specifies an icon
1441 const auto declaration = std::find_if(
1442 declarations.rbegin(), declarations.rend(),
1443 [](const Declaration &decl) { return decl.d->propertyId == QtIcon; });
1444 if (declaration == declarations.rend())
1445 return false;
1446
1447 *icon = declaration->iconValue();
1448
1449 // If the value contains a URI, try to get the size of the icon
1450 if (declaration->d->values.isEmpty())
1451 return true;
1452
1453 const auto &propertyValue = declaration->d->values.constFirst();
1454 if (propertyValue.type != Value::Uri)
1455 return true;
1456
1457 // First try to read just the size from the image without loading it
1458 const QString url(propertyValue.variant.toString());
1459 QImageReader imageReader(url);
1460 *size = imageReader.size();
1461 if (!size->isNull())
1462 return true;
1463
1464 // Get the size by loading the image instead
1465 *size = imageReader.read().size();
1466 return true;
1467}
1468
1470// Declaration
1472{
1473 if (d->values.size() != 1)
1474 return QColor();
1475
1476 if (d->parsed.isValid()) {
1477 switch (d->parsed.typeId()) {
1478 case qMetaTypeId<QColor>():
1479 return qvariant_cast<QColor>(d->parsed);
1480 case qMetaTypeId<int>():
1481 return pal.color((QPalette::ColorRole)(d->parsed.toInt()));
1482 case qMetaTypeId<QList<QVariant>>():
1483 if (d->parsed.toList().size() == 1) {
1484 auto parsedList = d->parsed.toList();
1485 const auto &value = parsedList.at(0);
1486 return qvariant_cast<QColor>(value);
1487 }
1488 break;
1489 }
1490 }
1491
1492 ColorData color = parseColorValue(d->values.at(0));
1493 if (color.type == ColorData::Role) {
1494 d->parsed = QVariant::fromValue<int>(color.role);
1495 return pal.color((QPalette::ColorRole)(color.role));
1496 } else {
1497 d->parsed = QVariant::fromValue<QColor>(color.color);
1498 return color.color;
1499 }
1500}
1501
1503{
1504 if (d->values.size() != 1)
1505 return QBrush();
1506
1507 if (d->parsed.isValid()) {
1508 if (d->parsed.userType() == QMetaType::QBrush)
1509 return qvariant_cast<QBrush>(d->parsed);
1510 if (d->parsed.userType() == QMetaType::Int)
1511 return pal.color((QPalette::ColorRole)(d->parsed.toInt()));
1512 }
1513
1514 BrushData data = parseBrushValue(d->values.at(0), pal);
1515
1516 if (data.type == BrushData::Role) {
1517 d->parsed = QVariant::fromValue<int>(data.role);
1518 return pal.color((QPalette::ColorRole)(data.role));
1519 } else {
1521 d->parsed = QVariant::fromValue<QBrush>(data.brush);
1522 return data.brush;
1523 }
1524}
1525
1527{
1528 int needParse = 0x1f; // bits 0..3 say if we should parse the corresponding value.
1529 // the bit 4 say we need to update d->parsed
1530 int i = 0;
1531 if (d->parsed.isValid()) {
1532 needParse = 0;
1533 Q_ASSERT(d->parsed.metaType() == QMetaType::fromType<QList<QVariant>>());
1534 QList<QVariant> v = d->parsed.toList();
1535 for (i = 0; i < qMin(v.size(), 4); i++) {
1536 if (v.at(i).userType() == QMetaType::QBrush) {
1537 c[i] = qvariant_cast<QBrush>(v.at(i));
1538 } else if (v.at(i).userType() == QMetaType::Int) {
1539 c[i] = pal.color((QPalette::ColorRole)(v.at(i).toInt()));
1540 } else {
1541 needParse |= (1<<i);
1542 }
1543 }
1544 }
1545 if (needParse != 0) {
1546 QList<QVariant> v;
1547 for (i = 0; i < qMin(d->values.size(), 4); i++) {
1548 if (!(needParse & (1<<i)))
1549 continue;
1550 BrushData data = parseBrushValue(d->values.at(i), pal);
1551 if (data.type == BrushData::Role) {
1552 v += QVariant::fromValue<int>(data.role);
1553 c[i] = pal.color((QPalette::ColorRole)(data.role));
1554 } else {
1556 v += QVariant::fromValue<QBrush>(data.brush);
1557 } else {
1558 v += QVariant();
1559 }
1560 c[i] = data.brush;
1561 }
1562 }
1563 if (needParse & 0x10)
1564 d->parsed = v;
1565 }
1566 if (i == 0) c[0] = c[1] = c[2] = c[3] = QBrush();
1567 else if (i == 1) c[3] = c[2] = c[1] = c[0];
1568 else if (i == 2) c[2] = c[0], c[3] = c[1];
1569 else if (i == 3) c[3] = c[1];
1570}
1571
1572bool Declaration::realValue(qreal *real, const char *unit) const
1573{
1574 if (d->values.size() != 1)
1575 return false;
1576 const Value &v = d->values.at(0);
1577 if (unit && v.type != Value::Length)
1578 return false;
1579 const QString str = v.variant.toString();
1580 QStringView s(str);
1581 if (unit) {
1582 const QLatin1StringView unitStr(unit);
1583 if (!s.endsWith(unitStr, Qt::CaseInsensitive))
1584 return false;
1585 s.chop(unitStr.size());
1586 }
1587 bool ok = false;
1588 qreal val = s.toDouble(&ok);
1589 if (ok)
1590 *real = val;
1591 return ok;
1592}
1593
1594static bool intValueHelper(const QCss::Value &v, int *i, const char *unit)
1595{
1596 if (unit && v.type != Value::Length)
1597 return false;
1598 const QString str = v.variant.toString();
1599 QStringView s(str);
1600 if (unit) {
1601 const QLatin1StringView unitStr(unit);
1602 if (!s.endsWith(unitStr, Qt::CaseInsensitive))
1603 return false;
1604 s.chop(unitStr.size());
1605 }
1606 bool ok = false;
1607 int val = s.toInt(&ok);
1608 if (ok)
1609 *i = val;
1610 return ok;
1611}
1612
1613bool Declaration::intValue(int *i, const char *unit) const
1614{
1615 if (d->values.size() != 1)
1616 return false;
1617 return intValueHelper(d->values.at(0), i, unit);
1618}
1619
1621{
1622 if (d->parsed.isValid())
1623 return qvariant_cast<QSize>(d->parsed);
1624
1625 int x[2] = { 0, 0 };
1626 const int count = d->values.size();
1627 for (int i = 0; i < count; ++i) {
1628 if (i > 1) {
1629 qWarning("QCssParser::sizeValue: Too many values provided");
1630 break;
1631 }
1632 const auto &value = d->values.at(i);
1633 const QString valueString = value.variant.toString();
1634 if (valueString.endsWith(u"pt", Qt::CaseInsensitive)) {
1635 intValueHelper(value, &x[i], "pt");
1636 // according to https://www.w3.org/TR/css3-values/#absolute-lengths
1637 // 1pt = 1/72th of 1 inch, and 1px = 1/96th of 1 inch
1638 x[i] = (x[i] * 72) / 96;
1639 } else {
1640 // by default we use 'px'
1641 intValueHelper(value, &x[i], "px");
1642 }
1643 }
1644 if (count == 1)
1645 x[1] = x[0];
1646 QSize size(x[0], x[1]);
1647 d->parsed = QVariant::fromValue<QSize>(size);
1648 return size;
1649}
1650
1652{
1653 if (d->values.size() != 1)
1654 return QRect();
1655
1656 if (d->parsed.isValid())
1657 return qvariant_cast<QRect>(d->parsed);
1658
1659 const QCss::Value &v = d->values.at(0);
1660 if (v.type != Value::Function)
1661 return QRect();
1662 const QStringList func = v.variant.toStringList();
1663 if (func.size() != 2 || func.at(0).compare("rect"_L1) != 0)
1664 return QRect();
1665 const auto args = QStringView{func[1]}.split(u' ', Qt::SkipEmptyParts);
1666 if (args.size() != 4)
1667 return QRect();
1668 QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt());
1669 d->parsed = QVariant::fromValue<QRect>(rect);
1670 return rect;
1671}
1672
1674{
1675 int i;
1676 if (d->parsed.isValid()) {
1677 QList<QVariant> v = d->parsed.toList();
1678 for (i = 0; i < qMin(d->values.size(), 4); i++) {
1679 if (v.at(i).userType() == QMetaType::QColor) {
1680 c[i] = qvariant_cast<QColor>(v.at(i));
1681 } else {
1682 c[i] = pal.color((QPalette::ColorRole)(v.at(i).toInt()));
1683 }
1684 }
1685 } else {
1686 QList<QVariant> v;
1687 for (i = 0; i < qMin(d->values.size(), 4); i++) {
1688 ColorData color = parseColorValue(d->values.at(i));
1689 if (color.type == ColorData::Role) {
1690 v += QVariant::fromValue<int>(color.role);
1691 c[i] = pal.color((QPalette::ColorRole)(color.role));
1692 } else {
1693 v += QVariant::fromValue<QColor>(color.color);
1694 c[i] = color.color;
1695 }
1696 }
1697 d->parsed = v;
1698 }
1699
1700 if (i == 0) c[0] = c[1] = c[2] = c[3] = QColor();
1701 else if (i == 1) c[3] = c[2] = c[1] = c[0];
1702 else if (i == 2) c[2] = c[0], c[3] = c[1];
1703 else if (i == 3) c[3] = c[1];
1704}
1705
1707{
1708 if (d->values.size() != 1)
1709 return BorderStyle_None;
1710 return parseStyleValue(d->values.at(0));
1711}
1712
1714{
1715 int i;
1716 for (i = 0; i < qMin(d->values.size(), 4); i++)
1717 s[i] = parseStyleValue(d->values.at(i));
1718 if (i == 0) s[0] = s[1] = s[2] = s[3] = BorderStyle_None;
1719 else if (i == 1) s[3] = s[2] = s[1] = s[0];
1720 else if (i == 2) s[2] = s[0], s[3] = s[1];
1721 else if (i == 3) s[3] = s[1];
1722}
1723
1725{
1726 if (d->parsed.isValid())
1727 return static_cast<Repeat>(d->parsed.toInt());
1728 if (d->values.size() != 1)
1729 return Repeat_Unknown;
1730 int v = findKnownValue(d->values.at(0).variant.toString(),
1732 d->parsed = v;
1733 return static_cast<Repeat>(v);
1734}
1735
1737{
1738 if (d->parsed.isValid())
1739 return static_cast<Origin>(d->parsed.toInt());
1740 if (d->values.size() != 1)
1741 return Origin_Unknown;
1742 int v = findKnownValue(d->values.at(0).variant.toString(),
1744 d->parsed = v;
1745 return static_cast<Origin>(v);
1746}
1747
1749{
1750 if (d->parsed.isValid())
1751 return static_cast<PositionMode>(d->parsed.toInt());
1752 if (d->values.size() != 1)
1753 return PositionMode_Unknown;
1754 int v = findKnownValue(d->values.at(0).variant.toString(),
1756 d->parsed = v;
1757 return static_cast<PositionMode>(v);
1758}
1759
1761{
1762 if (d->parsed.isValid())
1763 return static_cast<Attachment>(d->parsed.toInt());
1764 if (d->values.size() != 1)
1765 return Attachment_Unknown;
1766 int v = findKnownValue(d->values.at(0).variant.toString(),
1768 d->parsed = v;
1769 return static_cast<Attachment>(v);
1770}
1771
1773{
1774 Q_ASSERT(d->propertyId == QtStyleFeatures);
1775 if (d->parsed.isValid())
1776 return d->parsed.toInt();
1777 int features = StyleFeature_None;
1778 for (int i = 0; i < d->values.size(); i++) {
1779 features |= static_cast<int>(findKnownValue(d->values.value(i).variant.toString(),
1781 }
1782 d->parsed = features;
1783 return features;
1784}
1785
1787{
1788 if (d->values.isEmpty() || d->values.at(0).type != Value::Uri)
1789 return QString();
1790 return d->values.at(0).variant.toString();
1791}
1792
1793Qt::Alignment Declaration::alignmentValue() const
1794{
1795 if (d->parsed.isValid())
1796 return Qt::Alignment(d->parsed.toInt());
1797 if (d->values.isEmpty() || d->values.size() > 2)
1798 return Qt::AlignLeft | Qt::AlignTop;
1799
1800 Qt::Alignment v = parseAlignment(d->values.constData(), d->values.size());
1801 d->parsed = int(v);
1802 return v;
1803}
1804
1806 TileMode *h, TileMode *v) const
1807{
1808 const DeclarationData *d = this->d.data(); // make it const and shadow d
1809 *image = uriValue();
1810 for (int i = 0; i < 4; i++)
1811 cuts[i] = -1;
1812 *h = *v = TileMode_Stretch;
1813
1814 if (d->values.size() < 2)
1815 return;
1816
1817 if (d->values.at(1).type == Value::Number) { // cuts!
1818 int i;
1819 for (i = 0; i < qMin(d->values.size()-1, 4); i++) {
1820 const Value& v = d->values.at(i+1);
1821 if (v.type != Value::Number)
1822 break;
1823 cuts[i] = v.variant.toString().toInt();
1824 }
1825 if (i == 0) cuts[0] = cuts[1] = cuts[2] = cuts[3] = 0;
1826 else if (i == 1) cuts[3] = cuts[2] = cuts[1] = cuts[0];
1827 else if (i == 2) cuts[2] = cuts[0], cuts[3] = cuts[1];
1828 else if (i == 3) cuts[3] = cuts[1];
1829 }
1830
1831 if (d->values.last().type == Value::Identifier) {
1832 *v = static_cast<TileMode>(findKnownValue(d->values.last().variant.toString(),
1834 }
1835 if (d->values[d->values.size() - 2].type == Value::Identifier) {
1836 *h = static_cast<TileMode>
1837 (findKnownValue(d->values[d->values.size()-2].variant.toString(),
1839 } else
1840 *h = *v;
1841}
1842
1844{
1845 if (d->values.size() != 1)
1846 return false;
1847 else
1848 return d->values.at(0).toString() == "collapse"_L1;
1849}
1850
1851QList<qreal> Declaration::dashArray() const
1852{
1853 if (d->propertyId != Property::QtStrokeDashArray || d->values.empty())
1854 return QList<qreal>();
1855
1856 bool isValid = true;
1857 QList<qreal> dashes;
1858 for (int i = 0; i < d->values.size(); i++) {
1859 Value v = d->values[i];
1860 // Separators must be at odd indices and Numbers at even indices.
1861 bool isValidSeparator = (i & 1) && v.type == Value::TermOperatorComma;
1862 bool isValidNumber = !(i & 1) && v.type == Value::Number;
1863 if (!isValidNumber && !isValidSeparator) {
1864 isValid = false;
1865 break;
1866 } else if (isValidNumber) {
1867 bool ok;
1868 dashes.append(v.variant.toReal(&ok));
1869 if (!ok) {
1870 isValid = false;
1871 break;
1872 }
1873 }
1874 }
1875
1876 isValid &= !(dashes.size() & 1);
1877 return isValid ? dashes : QList<qreal>();
1878}
1879
1881{
1882 if (d->parsed.isValid())
1883 return qvariant_cast<QIcon>(d->parsed);
1884
1885 QIcon icon;
1886 for (int i = 0; i < d->values.size();) {
1887 const Value &value = d->values.at(i++);
1888 if (value.type != Value::Uri)
1889 break;
1890 QString uri = value.variant.toString();
1893 for (int j = 0; j < 2; j++) {
1894 if (i != d->values.size() && d->values.at(i).type == Value::KnownIdentifier) {
1895 switch (d->values.at(i).variant.toInt()) {
1896 case Value_Disabled: mode = QIcon::Disabled; break;
1897 case Value_Active: mode = QIcon::Active; break;
1898 case Value_Selected: mode = QIcon::Selected; break;
1899 case Value_Normal: mode = QIcon::Normal; break;
1900 case Value_On: state = QIcon::On; break;
1901 case Value_Off: state = QIcon::Off; break;
1902 default: break;
1903 }
1904 ++i;
1905 } else {
1906 break;
1907 }
1908 }
1909
1910 // QIcon is soo broken
1911 if (icon.isNull())
1912 icon = QIcon(uri);
1913 else
1914 icon.addPixmap(uri, mode, state);
1915
1916 if (i == d->values.size())
1917 break;
1918
1919 if (d->values.at(i).type == Value::TermOperatorComma)
1920 i++;
1921 }
1922
1923 d->parsed = QVariant::fromValue<QIcon>(icon);
1924 return icon;
1925}
1926
1928// Selector
1930{
1931 int val = 0;
1932 for (int i = 0; i < basicSelectors.size(); ++i) {
1933 const BasicSelector &sel = basicSelectors.at(i);
1934 if (!sel.elementName.isEmpty())
1935 val += 1;
1936
1937 val += (sel.pseudos.size() + sel.attributeSelectors.size()) * 0x10;
1938 val += sel.ids.size() * 0x100;
1939 }
1940 return val;
1941}
1942
1944{
1945 const BasicSelector& bs = basicSelectors.last();
1946 if (!bs.pseudos.isEmpty() && bs.pseudos.at(0).type == PseudoClass_Unknown)
1947 return bs.pseudos.at(0).name;
1948 return QString();
1949}
1950
1952{
1953 const BasicSelector& bs = basicSelectors.last();
1954 if (bs.pseudos.isEmpty())
1957 for (int i = !pseudoElement().isEmpty(); i < bs.pseudos.size(); i++) {
1958 const Pseudo &pseudo = bs.pseudos.at(i);
1959 if (pseudo.type == PseudoClass_Unknown)
1960 return PseudoClass_Unknown;
1961 if (!pseudo.negated)
1962 pc |= pseudo.type;
1963 else if (negated)
1964 *negated |= pseudo.type;
1965 }
1966 return pc;
1967}
1968
1970// StyleSheet
1972{
1973 QList<StyleRule> universals;
1974 for (int i = 0; i < styleRules.size(); ++i) {
1975 const StyleRule &rule = styleRules.at(i);
1976 QList<Selector> universalsSelectors;
1977 for (int j = 0; j < rule.selectors.size(); ++j) {
1978 const Selector& selector = rule.selectors.at(j);
1979
1980 if (selector.basicSelectors.isEmpty())
1981 continue;
1982
1983 if (selector.basicSelectors.at(0).relationToNext == BasicSelector::NoRelation) {
1984 if (selector.basicSelectors.size() != 1)
1985 continue;
1986 } else if (selector.basicSelectors.size() <= 1) {
1987 continue;
1988 }
1989
1990 const BasicSelector &sel = selector.basicSelectors.at(selector.basicSelectors.size() - 1);
1991
1992 if (!sel.ids.isEmpty()) {
1993 StyleRule nr;
1994 nr.selectors += selector;
1995 nr.declarations = rule.declarations;
1996 nr.order = i;
1997 idIndex.insert(sel.ids.at(0), nr);
1998 } else if (!sel.elementName.isEmpty()) {
1999 StyleRule nr;
2000 nr.selectors += selector;
2001 nr.declarations = rule.declarations;
2002 nr.order = i;
2003 QString name = sel.elementName;
2004 if (nameCaseSensitivity == Qt::CaseInsensitive)
2005 name = std::move(name).toLower();
2006 nameIndex.insert(name, nr);
2007 } else {
2008 universalsSelectors += selector;
2009 }
2010 }
2011 if (!universalsSelectors.isEmpty()) {
2012 StyleRule nr;
2013 nr.selectors = universalsSelectors;
2014 nr.declarations = rule.declarations;
2015 nr.order = i;
2016 universals << nr;
2017 }
2018 }
2019 styleRules = universals;
2020}
2021
2023// StyleSelector
2027
2028bool StyleSelector::nodeNameEquals(NodePtr node, const QString& nodeName) const
2029{
2030 return nodeNames(node).contains(nodeName, nameCaseSensitivity);
2031}
2032
2037
2038bool StyleSelector::selectorMatches(const Selector &selector, NodePtr node)
2039{
2040 if (selector.basicSelectors.isEmpty())
2041 return false;
2042
2043 if (selector.basicSelectors.at(0).relationToNext == BasicSelector::NoRelation) {
2044 if (selector.basicSelectors.size() != 1)
2045 return false;
2046 return basicSelectorMatches(selector.basicSelectors.at(0), node);
2047 }
2048 if (selector.basicSelectors.size() <= 1)
2049 return false;
2050
2051 int i = selector.basicSelectors.size() - 1;
2052 node = duplicateNode(node);
2053 bool match = true;
2054
2055 BasicSelector sel = selector.basicSelectors.at(i);
2056 do {
2057 match = basicSelectorMatches(sel, node);
2058 if (!match) {
2059 if (i == selector.basicSelectors.size() - 1) // first element must always match!
2060 break;
2061 if (sel.relationToNext != BasicSelector::MatchNextSelectorIfAncestor &&
2063 break;
2064 }
2065
2066 if (match || (sel.relationToNext != BasicSelector::MatchNextSelectorIfAncestor &&
2068 --i;
2069
2070 if (i < 0)
2071 break;
2072
2073 sel = selector.basicSelectors.at(i);
2074 if (sel.relationToNext == BasicSelector::MatchNextSelectorIfAncestor
2075 || sel.relationToNext == BasicSelector::MatchNextSelectorIfParent) {
2076
2077 NodePtr nextParent = parentNode(node);
2078 freeNode(node);
2079 node = nextParent;
2080 } else if (sel.relationToNext == BasicSelector::MatchNextSelectorIfDirectAdjecent
2081 || sel.relationToNext == BasicSelector::MatchNextSelectorIfIndirectAdjecent) {
2082 NodePtr previousSibling = previousSiblingNode(node);
2083 freeNode(node);
2084 node = previousSibling;
2085 }
2086 if (isNullNode(node)) {
2087 match = false;
2088 break;
2089 }
2090 } while (i >= 0 && (match || sel.relationToNext == BasicSelector::MatchNextSelectorIfAncestor
2091 || sel.relationToNext == BasicSelector::MatchNextSelectorIfIndirectAdjecent));
2092
2093 freeNode(node);
2094
2095 return match;
2096}
2097
2098bool StyleSelector::basicSelectorMatches(const BasicSelector &sel, NodePtr node)
2099{
2100 if (!sel.attributeSelectors.isEmpty()) {
2101 if (!hasAttributes(node))
2102 return false;
2103
2104 for (int i = 0; i < sel.attributeSelectors.size(); ++i) {
2105 const QCss::AttributeSelector &a = sel.attributeSelectors.at(i);
2106
2107 const QString attrValue = attributeValue(node, a);
2108 if (attrValue.isNull())
2109 return false;
2110
2111 switch (a.valueMatchCriterium) {
2113 break;
2115 if (attrValue != a.value)
2116 return false;
2117 break;
2119 const auto lst = QStringView{attrValue}.tokenize(u' ');
2120 bool found = false;
2121 for (auto s : lst) {
2122 if (s == a.value) {
2123 found = true;
2124 break;
2125 }
2126 }
2127 if (!found)
2128 return false;
2129 break;
2130 }
2132 const QString dashPrefix = a.value + u'-';
2133 if (attrValue != a.value && !attrValue.startsWith(dashPrefix))
2134 return false;
2135 break;
2136 }
2138 if (!attrValue.startsWith(a.value))
2139 return false;
2140 break;
2142 if (!attrValue.endsWith(a.value))
2143 return false;
2144 break;
2146 if (!attrValue.contains(a.value))
2147 return false;
2148 break;
2149 }
2150 }
2151 }
2152
2153 if (!sel.elementName.isEmpty()
2154 && !nodeNameEquals(node, sel.elementName))
2155 return false;
2156
2157 if (!sel.ids.isEmpty()
2158 && sel.ids != nodeIds(node))
2159 return false;
2160
2161 return true;
2162}
2163
2164void StyleSelector::matchRule(NodePtr node, const StyleRule &rule, StyleSheetOrigin origin,
2165 int depth, QMultiMap<uint, StyleRule> *weightedRules)
2166{
2167 for (int j = 0; j < rule.selectors.size(); ++j) {
2168 const Selector& selector = rule.selectors.at(j);
2169 if (selectorMatches(selector, node)) {
2170 uint weight = rule.order
2171 + selector.specificity() *0x100
2172 + (uint(origin) + depth)*0x100000;
2173 StyleRule newRule = rule;
2174 if (rule.selectors.size() > 1) {
2175 newRule.selectors.resize(1);
2176 newRule.selectors[0] = selector;
2177 }
2178 //We might have rules with the same weight if they came from a rule with several selectors
2179 weightedRules->insert(weight, newRule);
2180 }
2181 }
2182}
2183
2184// Returns style rules that are in ascending order of specificity
2185// Each of the StyleRule returned will contain exactly one Selector
2187{
2188 QList<StyleRule> rules;
2189 if (styleSheets.isEmpty())
2190 return rules;
2191
2192 QMultiMap<uint, StyleRule> weightedRules; // (spec, rule) that will be sorted below
2193
2194 //prune using indexed stylesheet
2195 for (int sheetIdx = 0; sheetIdx < styleSheets.size(); ++sheetIdx) {
2196 const StyleSheet &styleSheet = styleSheets.at(sheetIdx);
2197 for (int i = 0; i < styleSheet.styleRules.size(); ++i) {
2198 matchRule(node, styleSheet.styleRules.at(i), styleSheet.origin, styleSheet.depth, &weightedRules);
2199 }
2200
2201 if (!styleSheet.idIndex.isEmpty()) {
2202 QStringList ids = nodeIds(node);
2203 for (int i = 0; i < ids.size(); i++) {
2204 const QString &key = ids.at(i);
2206 while (it != styleSheet.idIndex.constEnd() && it.key() == key) {
2207 matchRule(node, it.value(), styleSheet.origin, styleSheet.depth, &weightedRules);
2208 ++it;
2209 }
2210 }
2211 }
2212 if (!styleSheet.nameIndex.isEmpty()) {
2213 QStringList names = nodeNames(node);
2214 for (int i = 0; i < names.size(); i++) {
2215 QString name = names.at(i);
2217 name = std::move(name).toLower();
2219 while (it != styleSheet.nameIndex.constEnd() && it.key() == name) {
2220 matchRule(node, it.value(), styleSheet.origin, styleSheet.depth, &weightedRules);
2221 ++it;
2222 }
2223 }
2224 }
2225 if (!medium.isEmpty()) {
2226 for (int i = 0; i < styleSheet.mediaRules.size(); ++i) {
2227 if (styleSheet.mediaRules.at(i).media.contains(medium, Qt::CaseInsensitive)) {
2228 for (int j = 0; j < styleSheet.mediaRules.at(i).styleRules.size(); ++j) {
2229 matchRule(node, styleSheet.mediaRules.at(i).styleRules.at(j), styleSheet.origin,
2230 styleSheet.depth, &weightedRules);
2231 }
2232 }
2233 }
2234 }
2235 }
2236
2237 rules.reserve(weightedRules.size());
2239 for ( ; it != weightedRules.constEnd() ; ++it)
2240 rules += *it;
2241
2242 return rules;
2243}
2244
2245// for qtexthtmlparser which requires just the declarations with Enabled state
2246// and without pseudo elements
2247QList<Declaration> StyleSelector::declarationsForNode(NodePtr node, const char *extraPseudo)
2248{
2249 QList<Declaration> decls;
2250 QList<StyleRule> rules = styleRulesForNode(node);
2251 for (int i = 0; i < rules.size(); i++) {
2252 const Selector& selector = rules.at(i).selectors.at(0);
2253 const QString pseudoElement = selector.pseudoElement();
2254
2255 if (extraPseudo && pseudoElement == QLatin1StringView(extraPseudo)) {
2256 decls += rules.at(i).declarations;
2257 continue;
2258 }
2259
2260 if (!pseudoElement.isEmpty()) // skip rules with pseudo elements
2261 continue;
2262 quint64 pseudoClass = selector.pseudoClass();
2263 if (pseudoClass == PseudoClass_Enabled || pseudoClass == PseudoClass_Unspecified)
2264 decls += rules.at(i).declarations;
2265 }
2266 return decls;
2267}
2268
2269static inline bool isHexDigit(const char c)
2270{
2271 return (c >= '0' && c <= '9')
2272 || (c >= 'a' && c <= 'f')
2273 || (c >= 'A' && c <= 'F')
2274 ;
2275}
2276
2277QString Scanner::preprocess(const QString &input, bool *hasEscapeSequences)
2278{
2280
2281 if (hasEscapeSequences)
2282 *hasEscapeSequences = false;
2283
2284 int i = 0;
2285 while (i < output.size()) {
2286 if (output.at(i) == u'\\') {
2287
2288 ++i;
2289 // test for unicode hex escape
2290 int hexCount = 0;
2291 const int hexStart = i;
2292 while (i < output.size()
2293 && isHexDigit(output.at(i).toLatin1())
2294 && hexCount < 7) {
2295 ++hexCount;
2296 ++i;
2297 }
2298 if (hexCount == 0) {
2299 if (hasEscapeSequences)
2300 *hasEscapeSequences = true;
2301 continue;
2302 }
2303
2304 hexCount = qMin(hexCount, 6);
2305 bool ok = false;
2306 const char16_t code = QStringView{output}.mid(hexStart, hexCount).toUShort(&ok, 16);
2307 if (ok) {
2308 output.replace(hexStart - 1, hexCount + 1, code);
2309 i = hexStart;
2310 } else {
2311 i = hexStart;
2312 }
2313 } else {
2314 ++i;
2315 }
2316 }
2317 return output;
2318}
2319
2321{
2322 while (pos < input.size() - 1) {
2323 if (input.at(pos) == u'*' && input.at(pos + 1) == u'/') {
2324 pos += 2;
2325 break;
2326 }
2327 ++pos;
2328 }
2329 return S;
2330}
2331
2332void Scanner::scan(const QString &preprocessedInput, QList<Symbol> *symbols)
2333{
2334 QCssScanner_Generated scanner(preprocessedInput);
2335 Symbol sym;
2336 int tok = scanner.lex();
2337 while (tok != -1) {
2338 sym.token = static_cast<QCss::TokenType>(tok);
2339 sym.text = scanner.input;
2340 sym.start = scanner.lexemStart;
2341 sym.len = scanner.lexemLength;
2342 symbols->append(sym);
2343 tok = scanner.lex();
2344 }
2345}
2346
2348{
2350 if (len > 0)
2351 result.reserve(len);
2352 for (int i = 0; i < len; ++i) {
2353 if (text.at(start + i) == u'\\' && i < len - 1)
2354 ++i;
2355 result += text.at(start + i);
2356 }
2357 return result;
2358}
2359
2360Parser::Parser(const QString &css, bool isFile)
2361{
2362 init(css, isFile);
2363}
2364
2366{
2367 index = 0;
2368 errorIndex = -1;
2369 hasEscapeSequences = false;
2370}
2371
2372void Parser::init(const QString &css, bool isFile)
2373{
2374 QString styleSheet = css;
2375 if (isFile) {
2376 QFile file(css);
2377 if (file.open(QFile::ReadOnly)) {
2378 sourcePath = QFileInfo(styleSheet).absolutePath() + u'/';
2380 styleSheet = stream.readAll();
2381 } else {
2382 qWarning() << "QCss::Parser - Failed to load file " << css;
2383 styleSheet.clear();
2384 }
2385 } else {
2386 sourcePath.clear();
2387 }
2388
2389 hasEscapeSequences = false;
2390 symbols.clear();
2391 symbols.reserve(8);
2393 index = 0;
2394 errorIndex = -1;
2395}
2396
2397bool Parser::parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity)
2398{
2399 if (testTokenAndEndsWith(ATKEYWORD_SYM, "charset"_L1)) {
2400 while (test(S) || test(CDO) || test(CDC)) {}
2401 if (!next(STRING)) return false;
2402 if (!next(SEMICOLON)) return false;
2403 }
2404
2405 while (test(S) || test(CDO) || test(CDC)) {}
2406
2407 while (testImport()) {
2409 if (!parseImport(&rule)) return false;
2410 styleSheet->importRules.append(rule);
2411 while (test(S) || test(CDO) || test(CDC)) {}
2412 }
2413
2414 do {
2415 if (testMedia()) {
2417 if (!parseMedia(&rule)) return false;
2418 styleSheet->mediaRules.append(rule);
2419 } else if (testPage()) {
2420 PageRule rule;
2421 if (!parsePage(&rule)) return false;
2422 styleSheet->pageRules.append(rule);
2423 } else if (testRuleset()) {
2425 if (!parseRuleset(&rule)) return false;
2426 styleSheet->styleRules.append(rule);
2427 } else if (test(ATKEYWORD_SYM)) {
2428 if (!until(RBRACE)) return false;
2429 } else if (hasNext()) {
2430 return false;
2431 }
2432 while (test(S) || test(CDO) || test(CDC)) {}
2433 } while (hasNext());
2434 styleSheet->buildIndexes(nameCaseSensitivity);
2435 return true;
2436}
2437
2439{
2440 if (errorIndex == -1) return Symbol();
2441 return symbols.at(errorIndex);
2442}
2443
2445{
2446 if (!str->startsWith(u'\'') && !str->startsWith(u'\"'))
2447 return;
2448 str->remove(0, 1);
2449 str->chop(1);
2450}
2451
2453{
2454 skipSpace();
2455
2456 if (test(STRING)) {
2457 importRule->href = lexem();
2458 } else {
2459 if (!testAndParseUri(&importRule->href)) return false;
2460 }
2461 removeOptionalQuotes(&importRule->href);
2462
2463 skipSpace();
2464
2465 if (testMedium()) {
2466 if (!parseMedium(&importRule->media)) return false;
2467
2468 while (test(COMMA)) {
2469 skipSpace();
2470 if (!parseNextMedium(&importRule->media)) return false;
2471 }
2472 }
2473
2474 if (!next(SEMICOLON)) return false;
2475
2476 skipSpace();
2477 return true;
2478}
2479
2481{
2482 do {
2483 skipSpace();
2484 if (!parseNextMedium(&mediaRule->media)) return false;
2485 } while (test(COMMA));
2486
2487 if (!next(LBRACE)) return false;
2488 skipSpace();
2489
2490 while (testRuleset()) {
2492 if (!parseRuleset(&rule)) return false;
2493 mediaRule->styleRules.append(rule);
2494 }
2495
2496 if (!next(RBRACE)) return false;
2497 skipSpace();
2498 return true;
2499}
2500
2502{
2503 media->append(lexem());
2504 skipSpace();
2505 return true;
2506}
2507
2509{
2510 skipSpace();
2511
2512 if (testPseudoPage())
2513 if (!parsePseudoPage(&pageRule->selector)) return false;
2514
2515 skipSpace();
2516 if (!next(LBRACE)) return false;
2517
2518 do {
2519 skipSpace();
2520 Declaration decl;
2521 if (!parseNextDeclaration(&decl)) return false;
2522 if (!decl.isEmpty())
2523 pageRule->declarations.append(decl);
2524 } while (test(SEMICOLON));
2525
2526 if (!next(RBRACE)) return false;
2527 skipSpace();
2528 return true;
2529}
2530
2532{
2533 if (!next(IDENT)) return false;
2534 *selector = lexem();
2535 return true;
2536}
2537
2539{
2540 if (!hasNext()) return true;
2541 switch (next()) {
2542 case SLASH: value->type = Value::TermOperatorSlash; skipSpace(); break;
2543 case COMMA: value->type = Value::TermOperatorComma; skipSpace(); break;
2544 default: prev(); break;
2545 }
2546 return true;
2547}
2548
2550{
2551 *relation = BasicSelector::NoRelation;
2552 if (lookup() == S) {
2554 skipSpace();
2555 } else {
2556 prev();
2557 }
2558 if (test(PLUS)) {
2560 } else if (test(GREATER)) {
2562 } else if (test(TILDE)) {
2564 }
2565 skipSpace();
2566 return true;
2567}
2568
2570{
2571 decl->d->property = lexem();
2572 decl->d->propertyId = static_cast<Property>(findKnownValue(decl->d->property, properties, NumProperties));
2573 decl->d->inheritable = isInheritable(decl->d->propertyId);
2574 skipSpace();
2575 return true;
2576}
2577
2579{
2580 Selector sel;
2581 if (!parseSelector(&sel)) return false;
2582 styleRule->selectors.append(sel);
2583
2584 while (test(COMMA)) {
2585 skipSpace();
2586 Selector sel;
2587 if (!parseNextSelector(&sel)) return false;
2588 styleRule->selectors.append(sel);
2589 }
2590
2591 skipSpace();
2592 if (!next(LBRACE)) return false;
2593 const int declarationStart = index;
2594
2595 do {
2596 skipSpace();
2597 Declaration decl;
2598 const int rewind = index;
2599 if (!parseNextDeclaration(&decl)) {
2600 index = rewind;
2601 const bool foundSemicolon = until(SEMICOLON);
2602 const int semicolonIndex = index;
2603
2604 index = declarationStart;
2605 const bool foundRBrace = until(RBRACE);
2606
2607 if (foundSemicolon && semicolonIndex < index) {
2608 decl = Declaration();
2609 index = semicolonIndex - 1;
2610 } else {
2611 skipSpace();
2612 return foundRBrace;
2613 }
2614 }
2615 if (!decl.isEmpty())
2616 styleRule->declarations.append(decl);
2617 } while (test(SEMICOLON));
2618
2619 if (!next(RBRACE)) return false;
2620 skipSpace();
2621 return true;
2622}
2623
2625{
2626 BasicSelector basicSel;
2627 if (!parseSimpleSelector(&basicSel)) return false;
2628 while (testCombinator()) {
2629 if (!parseCombinator(&basicSel.relationToNext)) return false;
2630
2631 if (!testSimpleSelector()) break;
2632 sel->basicSelectors.append(basicSel);
2633
2634 basicSel = BasicSelector();
2635 if (!parseSimpleSelector(&basicSel)) return false;
2636 }
2637 sel->basicSelectors.append(basicSel);
2638 return true;
2639}
2640
2642{
2643 int minCount = 0;
2644 if (lookupElementName()) {
2645 if (!parseElementName(&basicSel->elementName)) return false;
2646 } else {
2647 prev();
2648 minCount = 1;
2649 }
2650 bool onceMore;
2651 int count = 0;
2652 do {
2653 onceMore = false;
2654 if (test(HASH)) {
2655 QString theid = lexem();
2656 // chop off leading #
2657 theid.remove(0, 1);
2658 basicSel->ids.append(theid);
2659 onceMore = true;
2660 } else if (testClass()) {
2661 onceMore = true;
2663 a.name = "class"_L1;
2664 a.valueMatchCriterium = AttributeSelector::MatchIncludes;
2665 if (!parseClass(&a.value)) return false;
2666 basicSel->attributeSelectors.append(a);
2667 } else if (testAttrib()) {
2668 onceMore = true;
2670 if (!parseAttrib(&a)) return false;
2671 basicSel->attributeSelectors.append(a);
2672 } else if (testPseudo()) {
2673 onceMore = true;
2674 Pseudo ps;
2675 if (!parsePseudo(&ps)) return false;
2676 basicSel->pseudos.append(ps);
2677 }
2678 if (onceMore) ++count;
2679 } while (onceMore);
2680 return count >= minCount;
2681}
2682
2684{
2685 if (!next(IDENT)) return false;
2686 *name = lexem();
2687 return true;
2688}
2689
2691{
2692 switch (lookup()) {
2693 case STAR: name->clear(); break;
2694 case IDENT: *name = lexem(); break;
2695 default: return false;
2696 }
2697 return true;
2698}
2699
2701{
2702 skipSpace();
2703 if (!next(IDENT)) return false;
2704 attr->name = lexem();
2705 skipSpace();
2706
2707 if (test(EQUAL)) {
2709 } else if (test(INCLUDES)) {
2711 } else if (test(DASHMATCH)) {
2713 } else if (test(BEGINSWITH)) {
2715 } else if (test(ENDSWITH)) {
2717 } else if (test(CONTAINS)) {
2719 } else {
2720 return next(RBRACKET);
2721 }
2722
2723 skipSpace();
2724
2725 if (!test(IDENT) && !test(STRING)) return false;
2726 attr->value = unquotedLexem();
2727
2728 skipSpace();
2729 return next(RBRACKET);
2730}
2731
2733{
2734 (void)test(COLON);
2735 pseudo->negated = test(EXCLAMATION_SYM);
2736 if (test(IDENT)) {
2737 pseudo->name = lexem();
2738 pseudo->type = static_cast<quint64>(findKnownValue(pseudo->name, pseudos, NumPseudos));
2739 return true;
2740 }
2741 if (!next(FUNCTION)) return false;
2742 pseudo->function = lexem();
2743 // chop off trailing parenthesis
2744 pseudo->function.chop(1);
2745 skipSpace();
2746 if (!test(IDENT)) return false;
2747 pseudo->name = lexem();
2748 skipSpace();
2749 return next(RPAREN);
2750}
2751
2753{
2754 if (!testProperty())
2755 return true; // not an error!
2756 if (!parseProperty(decl)) return false;
2757 if (!next(COLON)) return false;
2758 skipSpace();
2759 if (!parseNextExpr(&decl->d->values)) return false;
2760 if (testPrio())
2761 if (!parsePrio(decl)) return false;
2762 return true;
2763}
2764
2766{
2767 const int rewind = index;
2768 if (!test(EXCLAMATION_SYM)) return false;
2769 skipSpace();
2770 if (!test(IDENT)) {
2771 index = rewind;
2772 return false;
2773 }
2774 if (lexem().compare("important"_L1, Qt::CaseInsensitive) != 0) {
2775 index = rewind;
2776 return false;
2777 }
2778 return true;
2779}
2780
2782{
2783 declaration->d->important = true;
2784 skipSpace();
2785 return true;
2786}
2787
2788bool Parser::parseExpr(QList<Value> *values)
2789{
2790 Value val;
2791 if (!parseTerm(&val)) return false;
2792 values->append(val);
2793 bool onceMore;
2794 do {
2795 onceMore = false;
2796 val = Value();
2797 if (!parseNextOperator(&val)) return false;
2798 if (val.type != QCss::Value::Unknown)
2799 values->append(val);
2800 if (testTerm()) {
2801 onceMore = true;
2802 val = Value();
2803 if (!parseTerm(&val)) return false;
2804 values->append(val);
2805 }
2806 } while (onceMore);
2807 return true;
2808}
2809
2811{
2812 return test(PLUS) || test(MINUS)
2813 || test(NUMBER)
2814 || test(PERCENTAGE)
2815 || test(LENGTH)
2816 || test(STRING)
2817 || test(IDENT)
2818 || testHexColor()
2819 || testFunction();
2820}
2821
2823{
2824 QString str = lexem();
2825 bool haveUnary = false;
2826 if (lookup() == PLUS || lookup() == MINUS) {
2827 haveUnary = true;
2828 if (!hasNext()) return false;
2829 next();
2830 str += lexem();
2831 }
2832
2833 value->variant = str;
2834 value->type = QCss::Value::String;
2835 switch (lookup()) {
2836 case NUMBER:
2837 value->type = Value::Number;
2838 value->variant.convert(QMetaType::fromType<double>());
2839 break;
2840 case PERCENTAGE:
2841 value->type = Value::Percentage;
2842 str.chop(1); // strip off %
2843 value->variant = str;
2844 break;
2845 case LENGTH:
2846 value->type = Value::Length;
2847 break;
2848
2849 case STRING:
2850 if (haveUnary) return false;
2851 value->type = Value::String;
2852 str.chop(1);
2853 str.remove(0, 1);
2854 value->variant = str;
2855 break;
2856 case IDENT: {
2857 if (haveUnary) return false;
2858 value->type = Value::Identifier;
2859 const int theid = findKnownValue(str, values, NumKnownValues);
2860 if (theid != 0) {
2862 value->variant = theid;
2863 }
2864 break;
2865 }
2866 default: {
2867 if (haveUnary) return false;
2868 prev();
2869 if (testHexColor()) {
2870 QColor col;
2871 if (!parseHexColor(&col)) return false;
2872 value->type = Value::Color;
2873 value->variant = col;
2874 } else if (testFunction()) {
2875 QString name, args;
2876 if (!parseFunction(&name, &args)) return false;
2877 if (name == "url"_L1) {
2878 value->type = Value::Uri;
2882 }
2883 value->variant = args;
2884 } else {
2885 value->type = Value::Function;
2886 value->variant = QStringList() << name << args;
2887 }
2888 } else {
2889 return recordError();
2890 }
2891 return true;
2892 }
2893 }
2894 skipSpace();
2895 return true;
2896}
2897
2899{
2900 *name = lexem();
2901 name->chop(1);
2902 // until(RPAREN) needs FUNCTION token at index-1 to work properly
2903 int start = index;
2904 skipSpace();
2905 std::swap(start, index);
2906 if (!until(RPAREN)) return false;
2907 for (int i = start; i < index - 1; ++i)
2908 args->append(symbols.at(i).lexem());
2909 /*
2910 if (!nextExpr(&arguments)) return false;
2911 if (!next(RPAREN)) return false;
2912 */
2913 skipSpace();
2914 return true;
2915}
2916
2918{
2919 *col = QColor::fromString(lexem());
2920 if (!col->isValid()) {
2921 qWarning("QCssParser::parseHexColor: Unknown color name '%s'",lexem().toLatin1().constData());
2922 return false;
2923 }
2924 skipSpace();
2925 return true;
2926}
2927
2929{
2930 const int rewind = index;
2931 if (!testFunction()) return false;
2932
2933 QString name, args;
2934 if (!parseFunction(&name, &args)) {
2935 index = rewind;
2936 return false;
2937 }
2938 if (name.compare("url"_L1, Qt::CaseInsensitive) != 0) {
2939 index = rewind;
2940 return false;
2941 }
2942 *uri = args;
2944 return true;
2945}
2946
2948{
2949 return testElementName()
2950 || (test(HASH))
2951 || testClass()
2952 || testAttrib()
2953 || testPseudo();
2954}
2955
2957{
2958 if (hasNext() && next() == t)
2959 return true;
2960 return recordError();
2961}
2962
2964{
2965 if (index >= symbols.size())
2966 return false;
2967 if (symbols.at(index).token == t) {
2968 ++index;
2969 return true;
2970 }
2971 return false;
2972}
2973
2975{
2976 QString s = lexem();
2977 if (lookup() == STRING) {
2978 s.chop(1);
2979 s.remove(0, 1);
2980 }
2981 return s;
2982}
2983
2985{
2986 QString lexem;
2987 while (hasNext() && next() != t)
2988 lexem += symbol().lexem();
2989 return lexem;
2990}
2991
2993{
2994 int braceCount = 0;
2995 int brackCount = 0;
2996 int parenCount = 0;
2997 if (index) {
2998 switch(symbols.at(index-1).token) {
2999 case LBRACE: ++braceCount; break;
3000 case LBRACKET: ++brackCount; break;
3001 case FUNCTION:
3002 case LPAREN: ++parenCount; break;
3003 default: ;
3004 }
3005 }
3006 while (index < symbols.size()) {
3008 switch (t) {
3009 case LBRACE: ++braceCount; break;
3010 case RBRACE: --braceCount; break;
3011 case LBRACKET: ++brackCount; break;
3012 case RBRACKET: --brackCount; break;
3013 case FUNCTION:
3014 case LPAREN: ++parenCount; break;
3015 case RPAREN: --parenCount; break;
3016 default: break;
3017 }
3018 if ((t == target || (target2 != NONE && t == target2))
3019 && braceCount <= 0
3020 && brackCount <= 0
3021 && parenCount <= 0)
3022 return true;
3023
3024 if (braceCount < 0 || brackCount < 0 || parenCount < 0) {
3025 --index;
3026 break;
3027 }
3028 }
3029 return false;
3030}
3031
3033{
3034 if (!test(t)) return false;
3035 if (!lexem().endsWith(str, Qt::CaseInsensitive)) {
3036 prev();
3037 return false;
3038 }
3039 return true;
3040}
3041
3043#endif // QT_NO_CSSPARSER
\inmodule QtGui
Definition qbrush.h:30
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
static QColor fromRgb(QRgb rgb) noexcept
Static convenience function that returns a QColor constructed from the given QRgb value rgb.
Definition qcolor.cpp:2369
static QColor fromString(QAnyStringView name) noexcept
Definition qcolor.cpp:980
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,...
Definition qcolor.cpp:2499
static QColor fromHsl(int h, int s, int l, int a=255)
Definition qcolor.cpp:2562
bool isValid() const noexcept
Returns true if the color is valid; otherwise returns false.
Definition qcolor.h:285
\inmodule QtGui
Definition qbrush.h:446
bool testPseudoPage()
bool hasNext() const
bool parsePseudoPage(QString *selector)
bool parseFunction(QString *name, QString *args)
bool testFunction()
bool until(TokenType target, TokenType target2=NONE)
bool testAttrib()
TokenType lookup() const
bool test(TokenType t)
bool parseSelector(Selector *sel)
bool parseSimpleSelector(BasicSelector *basicSel)
bool parseRuleset(StyleRule *styleRule)
bool parsePage(PageRule *pageRule)
void init(const QString &css, bool file=false)
bool testTokenAndEndsWith(TokenType t, QLatin1StringView str)
bool parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity=Qt::CaseSensitive)
bool testSimpleSelector()
bool parseCombinator(BasicSelector::Relation *relation)
bool parseNextOperator(Value *value)
bool parseNextMedium(QStringList *media)
bool parseMedium(QStringList *media)
const Symbol & symbol() const
QString unquotedLexem() const
bool testPseudo()
bool parsePseudo(Pseudo *pseudo)
Symbol errorSymbol()
QString lexem() const
bool parseClass(QString *name)
bool parseProperty(Declaration *decl)
bool testRuleset()
bool parseMedia(MediaRule *mediaRule)
bool parseNextExpr(QList< Value > *values)
bool parseNextSelector(Selector *sel)
bool testImport()
bool parseAttrib(AttributeSelector *attr)
bool parseTerm(Value *value)
bool recordError()
QString lexemUntil(TokenType t)
QString sourcePath
bool testHexColor()
bool parseNextDeclaration(Declaration *declaration)
bool lookupElementName() const
bool testCombinator()
bool testMedium()
TokenType next()
bool testElementName()
bool testAndParseUri(QString *uri)
bool hasEscapeSequences
bool parseExpr(QList< Value > *values)
bool parseElementName(QString *name)
QList< Symbol > symbols
bool testProperty()
bool parseHexColor(QColor *col)
bool parsePrio(Declaration *declaration)
bool parseImport(ImportRule *importRule)
static QString preprocess(const QString &input, bool *hasEscapeSequences=nullptr)
static void scan(const QString &preprocessedInput, QList< Symbol > *symbols)
virtual NodePtr parentNode(NodePtr node) const =0
virtual QStringList nodeNames(NodePtr node) const =0
virtual bool nodeNameEquals(NodePtr node, const QString &nodeName) const
virtual NodePtr previousSiblingNode(NodePtr node) const =0
virtual void freeNode(NodePtr node) const =0
virtual bool hasAttributes(NodePtr node) const =0
virtual bool isNullNode(NodePtr node) const =0
QList< StyleSheet > styleSheets
virtual NodePtr duplicateNode(NodePtr node) const =0
virtual QString attributeValue(NodePtr node, const QCss::AttributeSelector &aSelector) const =0
Qt::CaseSensitivity nameCaseSensitivity
virtual QStringList nodeIds(NodePtr node) const
QList< StyleRule > styleRulesForNode(NodePtr node)
QList< Declaration > declarationsForNode(NodePtr node, const char *extraPseudo=nullptr)
QString absolutePath() const
Returns the absolute path of the file system entry this QFileInfo refers to, excluding the entry's na...
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
\reentrant \inmodule QtGui
int height() const
Returns the height of the font.
int xHeight() const
Returns the 'x' height of the font.
\reentrant
Definition qfont.h:22
void setStyle(Style style)
Sets the style of the font to style.
Definition qfont.cpp:1116
void setOverline(bool)
If enable is true, sets overline on; otherwise sets overline off.
Definition qfont.cpp:1288
void setStrikeOut(bool)
If enable is true, sets strikeout on; otherwise sets strikeout off.
Definition qfont.cpp:1315
@ AllLowercase
Definition qfont.h:100
@ AllUppercase
Definition qfont.h:99
@ MixedCase
Definition qfont.h:98
@ SmallCaps
Definition qfont.h:101
void setFamilies(const QStringList &)
Definition qfont.cpp:2721
void setCapitalization(Capitalization)
Definition qfont.cpp:1725
void setWordSpacing(qreal spacing)
Definition qfont.cpp:1690
@ AbsoluteSpacing
Definition qfont.h:108
@ PercentageSpacing
Definition qfont.h:107
void setLetterSpacing(SpacingType type, qreal spacing)
Definition qfont.cpp:1638
void setKerning(bool)
Enables kerning for this font if enable is true; otherwise disables it.
Definition qfont.cpp:1375
void setPixelSize(int)
Sets the font size to pixelSize pixels, with a maxiumum size of an unsigned 16-bit integer.
Definition qfont.cpp:1049
void setUnderline(bool)
If enable is true, sets underline on; otherwise sets underline off.
Definition qfont.cpp:1262
void setPointSizeF(qreal)
Sets the point size to pointSize.
Definition qfont.cpp:1010
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
Definition qfont.h:63
@ Bold
Definition qfont.h:70
@ Normal
Definition qfont.h:67
void setWeight(Weight weight)
Sets the weight of the font to weight, using the scale defined by \l QFont::Weight enumeration.
Definition qfont.cpp:1205
@ StyleItalic
Definition qfont.h:78
@ StyleNormal
Definition qfont.h:77
@ StyleOblique
Definition qfont.h:79
void setSpread(Spread spread)
Specifies the spread method that should be used for this gradient.
Definition qbrush.h:390
void setCoordinateMode(CoordinateMode mode)
Definition qbrush.cpp:1683
void setStops(const QGradientStops &stops)
Replaces the current set of stop points with the given stopPoints.
Definition qbrush.cpp:1608
CoordinateMode
Definition qbrush.h:153
@ ObjectBoundingMode
Definition qbrush.h:156
Spread
Specifies how the area outside the gradient area should be filled.
Definition qbrush.h:146
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
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:1060
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition qicon.cpp:1019
Mode
This enum type describes the mode for which a pixmap is intended to be used.
Definition qicon.h:22
@ Disabled
Definition qicon.h:22
@ Selected
Definition qicon.h:22
@ Normal
Definition qicon.h:22
@ Active
Definition qicon.h:22
State
This enum describes the state for which a pixmap is intended to be used.
Definition qicon.h:23
@ Off
Definition qicon.h:23
@ On
Definition qicon.h:23
The QImageReader class provides a format independent interface for reading images from files or other...
\inmodule QtGui
Definition qbrush.h:394
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void prepend(rvalue_ref t)
Definition qlist.h:473
void reserve(qsizetype size)
Definition qlist.h:753
void append(parameter_type t)
Definition qlist.h:458
void clear()
Definition qlist.h:434
static constexpr QMetaType fromType()
Definition qmetatype.h:2642
\inmodule QtCore
Definition qhash.h:1840
The QPalette class contains color groups for each widget state.
Definition qpalette.h:19
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:67
\inmodule QtGui
Definition qbrush.h:412
\inmodule QtCore\reentrant
Definition qrect.h:30
const_iterator constBegin() const noexcept
Definition qset.h:139
const_iterator constEnd() const noexcept
Definition qset.h:143
\inmodule QtCore
Definition qsize.h:25
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
constexpr auto tokenize(Needle &&needle, Flags...flags) const noexcept(noexcept(qTokenize(std::declval< const QStringView & >(), std::forward< Needle >(needle), flags...))) -> decltype(qTokenize(*this, std::forward< Needle >(needle), flags...))
Q_CORE_EXPORT QList< QStringView > split(QStringView sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the view into substring views wherever sep occurs, and returns the list of those string views.
Definition qstring.cpp:8249
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
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:5455
void chop(qsizetype n)
Removes n characters from the end of the string.
Definition qstring.cpp:6340
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
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:5506
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6664
QString toLower() const &
Definition qstring.h:435
QString & append(QChar c)
Definition qstring.cpp:3252
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition qstring.cpp:3466
\reentrant
Definition qtextformat.h:45
\inmodule QtCore
\inmodule QtCore
Definition qvariant.h:65
qreal toReal(bool *ok=nullptr) const
Returns the variant as a qreal if the variant has userType() \l QMetaType::Double,...
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
QString str
[2]
qreal spacing
QSet< QString >::iterator it
rect
[4]
uint alignment
else opt state
[0]
const quint64 PseudoClass_Unknown
const quint64 PseudoClass_Floatable
const quint64 PseudoClass_Movable
@ BottomEdge
@ RightEdge
const int NumPseudos
const quint64 PseudoClass_Children
const quint64 PseudoClass_Disabled
const quint64 PseudoClass_Sibling
const quint64 PseudoClass_ReadOnly
const quint64 PseudoClass_Closed
const quint64 PseudoClass_Maximized
const quint64 PseudoClass_Default
@ Repeat_XY
@ Repeat_Unknown
@ Repeat_None
@ NumKnownRepeats
const quint64 PseudoClass_Bottom
const quint64 PseudoClass_EditFocus
const quint64 PseudoClass_Focus
const quint64 PseudoClass_Enabled
const quint64 PseudoClass_Editable
const quint64 PseudoClass_Vertical
const quint64 PseudoClass_Flat
const quint64 PseudoClass_NonExclusive
@ Origin_Padding
@ Origin_Content
@ NumKnownOrigins
@ Origin_Unknown
@ Origin_Margin
@ Origin_Border
@ ATKEYWORD_SYM
@ DASHMATCH
@ PERCENTAGE
@ BEGINSWITH
@ SEMICOLON
@ EXCLAMATION_SYM
const quint64 PseudoClass_Pressed
const quint64 PseudoClass_Item
const quint64 PseudoClass_Alternate
const quint64 PseudoClass_PreviousSelected
const quint64 PseudoClass_Closable
const quint64 PseudoClass_Horizontal
const quint64 PseudoClass_Active
const quint64 PseudoClass_NextSelected
@ StyleFeature_BackgroundGradient
@ NumKnownStyleFeatures
@ StyleFeature_BackgroundColor
@ StyleFeature_None
const quint64 PseudoClass_Open
const quint64 PseudoClass_Frameless
const quint64 PseudoClass_Checked
const quint64 PseudoClass_Selected
@ Attachment_Fixed
@ NumKnownAttachments
@ Attachment_Scroll
@ Attachment_Unknown
const quint64 PseudoClass_Right
@ Value_Disc
@ Value_Bottom
@ Value_Wave
@ Value_UpperRoman
@ Value_Oblique
@ Value_Selected
@ Value_XXLarge
@ Value_Decimal
@ Value_PreWrap
@ Value_Link
@ Value_Active
@ Value_Button
@ Value_Left
@ Value_Circle
@ Value_Medium
@ Value_Midlight
@ Value_SvgMiterJoin
@ Value_Pre
@ Value_SquareCap
@ Value_Normal
@ Value_LineThrough
@ Value_DotDotDash
@ Value_Square
@ Value_Small
@ Value_Groove
@ Value_Transparent
@ Value_LowerAlpha
@ Value_Off
@ Value_Solid
@ Value_Disabled
@ Value_Light
@ Value_Super
@ Value_NoWrap
@ Value_LastColorRole
@ Value_Base
@ Value_Outset
@ NumKnownValues
@ Value_Shadow
@ Value_Native
@ Value_ButtonText
@ Value_RoundJoin
@ Value_FirstColorRole
@ Value_LowerRoman
@ Value_Top
@ Value_None
@ Value_Highlight
@ Value_Bold
@ Value_Dark
@ Value_Center
@ Value_Right
@ Value_Sub
@ Value_Text
@ Value_PreLine
@ Value_HighlightedText
@ Value_WindowText
@ Value_FlatCap
@ Value_Underline
@ Value_DotDash
@ Value_Uppercase
@ Value_Auto
@ Value_Inset
@ Value_Large
@ Value_XLarge
@ Value_MiterJoin
@ Value_SmallCaps
@ Value_RoundCap
@ Value_Double
@ Value_AlternateBase
@ Value_BevelJoin
@ Value_Mid
@ Value_Overline
@ Value_Ridge
@ Value_UpperAlpha
@ Value_Dashed
@ Value_BrightText
@ Value_Always
@ Value_LinkVisited
@ Value_Dotted
@ Value_Middle
@ Value_Window
@ Value_Lowercase
@ Value_Italic
@ BorderImage
@ BorderTopLeftRadius
@ BackgroundColor
@ Whitespace
@ OutlineTopLeftRadius
@ MarginLeft
@ QtAlternateBackground
@ QtStrokeMiterLimit
@ BorderTopColor
@ QtPlaceHolderTextColor
@ MarginRight
@ BorderBottomLeftRadius
@ QtStrokeDashArray
@ QtTableType
@ BorderBottom
@ Padding
@ QtStyleFeatures
@ BorderTopStyle
@ OutlineBottomRightRadius
@ FontKerning
@ NumProperties
@ BorderRightWidth
@ QtStrokeColor
@ PaddingRight
@ QtStrokeDashOffset
@ BackgroundOrigin
@ BorderBottomColor
@ MarginTop
@ TextUnderlineStyle
@ QtListIndent
@ PaddingLeft
@ PaddingTop
@ QtForeground
@ QtSpacing
@ BorderLeftColor
@ OutlineTopRightRadius
@ BorderRightColor
@ QtSelectionForeground
@ PaddingBottom
@ LetterSpacing
@ BorderBottomRightRadius
@ QtListNumberPrefix
@ OutlineWidth
@ PageBreakAfter
@ BorderRight
@ OutlineColor
@ OutlineBottomLeftRadius
@ FontWeight
@ QtBackgroundRole
@ QtForegroundTextureCacheKey
@ TextIndent
@ QtPosition
@ BorderColor
@ MarginBottom
@ MaximumWidth
@ QtUserState
@ OutlineStyle
@ BorderLeftWidth
@ BorderCollapse
@ QtBlockIndent
@ BackgroundPosition
@ WordSpacing
@ QtStrokeWidth
@ BackgroundImage
@ BorderRightStyle
@ FontStyle
@ TextTransform
@ FontFamily
@ FontVariant
@ BorderWidth
@ VerticalAlignment
@ LineHeight
@ QtParagraphType
@ QtSelectionBackground
@ BorderStyles
@ BorderLeft
@ TextDecoration
@ BorderTopRightRadius
@ ListStyleType
@ OutlineOffset
@ BorderRadius
@ ListStyle
@ QtStrokeLineJoin
@ BorderBottomWidth
@ Background
@ BorderTopWidth
@ OutlineRadius
@ MinimumWidth
@ BackgroundAttachment
@ TextAlignment
@ BackgroundClip
@ TextDecorationColor
@ QtListNumberSuffix
@ QtImageAlignment
@ BorderBottomStyle
@ BorderTop
@ FontSize
@ PageBreakBefore
@ QtLineHeightType
@ BackgroundRepeat
@ BorderLeftStyle
@ MinimumHeight
@ MaximumHeight
@ QtStrokeLineCap
const quint64 PseudoClass_Window
const quint64 PseudoClass_Minimized
@ TileMode_Repeat
@ NumKnownTileModes
@ TileMode_Round
@ TileMode_Stretch
StyleSheetOrigin
const quint64 PseudoClass_Unspecified
const quint64 PseudoClass_Unchecked
const quint64 PseudoClass_First
const quint64 PseudoClass_Indeterminate
const quint64 PseudoClass_Middle
@ PositionMode_Absolute
@ PositionMode_Relative
@ PositionMode_Unknown
@ PositionMode_Static
@ PositionMode_Fixed
@ NumKnownPositionModes
const quint64 PseudoClass_Top
const quint64 PseudoClass_Hover
@ BorderStyle_Dotted
@ BorderStyle_Solid
@ BorderStyle_Double
@ BorderStyle_DotDash
@ BorderStyle_Ridge
@ BorderStyle_Unknown
@ BorderStyle_Dashed
@ BorderStyle_Outset
@ BorderStyle_Groove
@ BorderStyle_Native
@ BorderStyle_None
@ BorderStyle_DotDotDash
@ BorderStyle_Inset
const quint64 PseudoClass_Left
const quint64 PseudoClass_Last
const quint64 PseudoClass_OnlyOne
const quint64 PseudoClass_Exclusive
Combined button and popup list for selecting options.
@ AlignRight
Definition qnamespace.h:146
@ AlignBottom
Definition qnamespace.h:154
@ AlignVCenter
Definition qnamespace.h:155
@ AlignTop
Definition qnamespace.h:153
@ AlignHCenter
Definition qnamespace.h:148
@ AlignCenter
Definition qnamespace.h:163
@ AlignLeft
Definition qnamespace.h:144
@ transparent
Definition qnamespace.h:47
CaseSensitivity
@ CaseInsensitive
@ SkipEmptyParts
Definition qnamespace.h:128
Definition brush.cpp:5
Definition image.cpp:4
QPair< qreal, QColor > QGradientStop
Definition qbrush.h:131
#define rgb(r, g, b)
Definition qcolor.cpp:124
QList< QString > QStringList
Constructs a string list that contains the given string, str.
static void setTextDecorationFromValues(const QList< QCss::Value > &values, QFont *font)
static void removeOptionalQuotes(QString *str)
static bool setFontFamilyFromValues(const QList< QCss::Value > &values, QFont *font, int start=0)
static bool setFontWeightFromValue(const QCss::Value &value, QFont *font)
static const QCssKnownValue origins[NumKnownOrigins - 1]
static int lengthValueFromData(const LengthData &data, const QFont &f)
static void setTextTransformFromValue(const QCss::Value &value, QFont *font)
static bool setFontSizeFromValue(QCss::Value value, QFont *font, int *fontSizeAdjustment)
static const QCssKnownValue pseudos[NumPseudos - 1]
static bool setFontStyleFromValue(const QCss::Value &value, QFont *font)
static ColorData parseColorValue(QCss::Value v)
static BorderStyle parseStyleValue(const QCss::Value &v)
static const QCssKnownValue styleFeatures[NumKnownStyleFeatures - 1]
static void setFontVariantFromValue(const QCss::Value &value, QFont *font)
static bool intValueHelper(const QCss::Value &v, int *i, const char *unit)
static quint64 findKnownValue(const QString &name, const QCssKnownValue *start, int numValues)
static const QCssKnownValue positions[NumKnownPositionModes - 1]
static Qt::Alignment parseAlignment(const QCss::Value *values, int count)
static void setLetterSpacingFromValue(const QCss::Value &value, QFont *font)
static BrushData parseBrushValue(const QCss::Value &v, const QPalette &pal)
static const QCssKnownValue properties[NumProperties - 1]
static bool isHexDigit(const char c)
static bool isInheritable(Property propertyId)
static bool setFontKerningFromValue(const QCss::Value &value, QFont *font)
static void parseShorthandBackgroundProperty(const QList< QCss::Value > &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal)
static void parseShorthandFontProperty(const QList< QCss::Value > &values, QFont *font, int *fontSizeAdjustment)
static const QCssKnownValue tileModes[NumKnownTileModes - 1]
static QBrush brushFromData(const BrushData &c, const QPalette &pal)
static const short indexOfId[NumKnownValues]
static void setWordSpacingFromValue(const QCss::Value &value, QFont *font)
static const QCssKnownValue repeats[NumKnownRepeats - 1]
static QColor colorFromData(const ColorData &c, const QPalette &pal)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char * rule
static bool isValidNumber(QChar c)
Definition qdbusutil.cpp:35
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#define qWarning
Definition qlogging.h:166
#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
Definition qmetatype.h:1384
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
GLint GLfloat GLfloat GLfloat v2
GLenum GLsizei GLsizei GLint * values
[15]
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum mode
const GLfloat * m
GLuint64 key
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei const GLuint * ids
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLdouble GLdouble right
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLuint GLuint GLfloat weight
GLint GLsizei width
GLuint color
[2]
GLint left
GLenum type
GLint GLint bottom
GLenum target
GLint GLfloat GLfloat v1
GLsizei const GLenum * attachments
GLuint start
GLint GLfloat GLfloat GLfloat GLfloat v3
GLenum attachment
GLuint name
GLfloat GLfloat GLfloat GLfloat h
GLdouble s
[6]
Definition qopenglext.h:235
GLenum func
Definition qopenglext.h:663
const GLubyte * c
GLuint GLfloat * val
GLuint GLuint * names
GLuint GLsizei const GLuint const GLintptr * offsets
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT GLuint GLuint GLenum GLenum GLuint GLenum GLuint GLenum target2
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLenum GLsizei len
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
GLenum GLenum GLenum GLenum GLenum scale
GLenum GLenum GLenum input
static QGradient::CoordinateMode coordinateMode(const QBrush &brush)
Definition qpainter.cpp:80
static bool hasAlpha(const QImage &image)
static QT_BEGIN_NAMESPACE bool isRelative(const QString &path)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static QT_BEGIN_NAMESPACE const QRgb colors[][14]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static bool operator<(const QSettingsIniKey &k1, const QSettingsIniKey &k2)
#define qPrintable(string)
Definition qstring.h:1531
#define zero
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
static int compare(quint64 a, quint64 b)
unsigned long long quint64
Definition qtypes.h:61
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
static int toInt(const QChar &qc, int R)
QT_BEGIN_NAMESPACE typedef uchar * output
QFile file
[0]
QFileSelector selector
[1]
QUrl url("example.com")
[constructor-url-reference]
QVariant variant
[1]
QJSValueList args
const char name[28]
ValueMatchType valueMatchCriterium
enum QCss::BrushData::@369 type
enum QCss::ColorData::@368 type
void colorValues(QColor *c, const QPalette &=QPalette()) const
int styleFeaturesValue() const
Attachment attachmentValue() const
Origin originValue() const
QIcon iconValue() const
void styleValues(BorderStyle *s) const
Qt::Alignment alignmentValue() const
bool realValue(qreal *r, const char *unit=nullptr) const
QExplicitlySharedDataPointer< DeclarationData > d
QColor colorValue(const QPalette &=QPalette()) const
void borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const
void brushValues(QBrush *c, const QPalette &=QPalette()) const
bool intValue(int *i, const char *unit=nullptr) const
QList< qreal > dashArray() const
QRect rectValue() const
BorderStyle styleValue() const
Repeat repeatValue() const
PositionMode positionValue() const
bool borderCollapseValue() const
QBrush brushValue(const QPalette &=QPalette()) const
bool isEmpty() const
QString uriValue() const
QSize sizeValue() const
enum QCss::LengthData::@370 unit
int specificity() const
QList< BasicSelector > basicSelectors
QString pseudoElement() const
quint64 pseudoClass(quint64 *negated=nullptr) const
QList< Selector > selectors
QList< StyleRule > styleRules
QList< MediaRule > mediaRules
Q_GUI_EXPORT void buildIndexes(Qt::CaseSensitivity nameCaseSensitivity=Qt::CaseSensitive)
QMultiHash< QString, StyleRule > idIndex
QMultiHash< QString, StyleRule > nameIndex
StyleSheetOrigin origin
QList< ImportRule > importRules
QList< PageRule > pageRules
TokenType token
Q_GUI_EXPORT QString lexem() const
bool extractPalette(QBrush *foreground, QBrush *selectedForeground, QBrush *selectedBackground, QBrush *alternateBackground, QBrush *placeHolderTextForeground, QBrush *accent)
bool extractIcon(QIcon *icon, QSize *size)
bool extractPosition(int *l, int *t, int *r, int *b, QCss::Origin *, Qt::Alignment *, QCss::PositionMode *, Qt::Alignment *)
bool extractGeometry(int *w, int *h, int *minw, int *minh, int *maxw, int *maxh)
bool extractBox(int *margins, int *paddings, int *spacing=nullptr)
bool extractFont(QFont *font, int *fontSizeAdjustment)
void lengthValues(const Declaration &decl, int *m)
ValueExtractor(const QList< Declaration > &declarations, const QPalette &=QPalette())
bool extractBorder(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii)
QTextLength textLength(const Declaration &decl)
bool extractImage(QIcon *icon, Qt::Alignment *a, QSize *size)
bool extractOutline(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii, int *offsets)
bool extractBackground(QBrush *, QString *, Repeat *, Qt::Alignment *, QCss::Origin *, QCss::Attachment *, QCss::Origin *)
QVariant variant
Q_GUI_EXPORT QString toString() const
Token token
Definition symbols.h:59
QByteArray lexem() const
Definition symbols.h:60