Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qsgbasicinternalrectanglenode.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
5
6#include <QtCore/qmath.h>
7
9
10namespace
11{
12 struct Color4ub
13 {
14 unsigned char r, g, b, a;
15 };
16
17 Color4ub operator *(Color4ub c, float t) { c.a *= t; c.r *= t; c.g *= t; c.b *= t; return c; }
18 Color4ub operator +(Color4ub a, Color4ub b) { a.a += b.a; a.r += b.r; a.g += b.g; a.b += b.b; return a; }
19
21 {
22 float r, g, b, a;
23 c.getRgbF(&r, &g, &b, &a);
24 Color4ub color = { uchar(qRound(r * a * 255)),
25 uchar(qRound(g * a * 255)),
26 uchar(qRound(b * a * 255)),
27 uchar(qRound(a * 255))
28 };
29 return color;
30 }
31
32 // Same layout as QSGGeometry::ColoredPoint2D, but uses Color4ub for convenience.
33 struct Vertex
34 {
35 float x, y;
37
38 void set(float primary, float secondary, Color4ub ncolor, bool vertical)
39 {
40 if (vertical) {
41 x = secondary; y = primary;
42 } else {
43 x = primary; y = secondary;
44 }
45 color = ncolor;
46 }
47 };
48
49 struct SmoothVertex : public Vertex
50 {
51 float dx, dy;
52
53 void set(float primary, float secondary, Color4ub ncolor, float dPrimary, float dSecondary, bool vertical)
54 {
55 Vertex::set(primary, secondary, ncolor, vertical);
56 if (vertical) {
57 dx = dSecondary; dy = dPrimary;
58 } else {
59 dx = dPrimary; dy = dSecondary;
60 }
61 }
62 };
63
65 {
66 static QSGGeometry::Attribute data[] = {
70 };
71 static QSGGeometry::AttributeSet attrs = { 3, sizeof(SmoothVertex), data };
72 return attrs;
73 }
74}
75
78 , m_aligned(true)
79 , m_antialiasing(false)
80 , m_gradient_is_opaque(true)
81 , m_dirty_geometry(false)
82 , m_gradient_is_vertical(true)
83 , m_geometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0)
84{
86
87#ifdef QSG_RUNTIME_DESCRIPTION
88 qsgnode_set_description(this, QLatin1String("internalrectangle"));
89#endif
90}
91
93{
94 if (rect == m_rect)
95 return;
96 m_rect = rect;
97 m_dirty_geometry = true;
98}
99
101{
102 if (color == m_color)
103 return;
104 m_color = color;
106 m_dirty_geometry = true;
107}
108
110{
111 if (color == m_border_color)
112 return;
114 if (m_pen_width > 0)
115 m_dirty_geometry = true;
116}
117
119{
120 if (width == m_pen_width)
121 return;
123 m_dirty_geometry = true;
124}
125
126
128{
129 if (stops.constData() == m_gradient_stops.constData())
130 return;
131
132 m_gradient_stops = stops;
133
135 for (int i = 0; i < stops.size(); ++i)
136 m_gradient_is_opaque &= stops.at(i).second.alpha() == 0xff;
137 m_dirty_geometry = true;
138}
139
141{
142 if (vertical == m_gradient_is_vertical)
143 return;
144 m_gradient_is_vertical = vertical;
145 m_dirty_geometry = true;
146}
147
148
150{
151 if (radius == m_radius)
152 return;
153 m_radius = radius;
154 m_dirty_geometry = true;
155}
156
158{
159 if (radius == m_topLeftRadius)
160 return;
161 m_topLeftRadius = radius;
162 m_dirty_geometry = true;
163}
165{
166 if (radius == m_topRightRadius)
167 return;
168 m_topRightRadius = radius;
169 m_dirty_geometry = true;
170}
172{
173 if (radius == m_bottomLeftRadius)
174 return;
175 m_bottomLeftRadius = radius;
176 m_dirty_geometry = true;
177}
179{
180 if (radius == m_bottomRightRadius)
181 return;
182 m_bottomRightRadius = radius;
183 m_dirty_geometry = true;
184}
185
187{
189 return;
190
191 if (antialiasing == m_antialiasing)
192 return;
193 m_antialiasing = antialiasing;
194 if (m_antialiasing) {
195 setGeometry(new QSGGeometry(smoothAttributeSet(), 0));
196 setFlag(OwnsGeometry, true);
197 } else {
199 setFlag(OwnsGeometry, false);
200 }
202 m_dirty_geometry = true;
203}
204
206{
207 if (aligned == m_aligned)
208 return;
210 m_dirty_geometry = true;
211}
212
214{
215 if (m_dirty_geometry) {
217 m_dirty_geometry = false;
218
219 QSGNode::DirtyState state = QSGNode::DirtyGeometry;
222 }
223}
224
226{
227 float width = float(m_rect.width());
228 float height = float(m_rect.height());
229 float penWidth = qMin(qMin(width, height) * 0.5f, float(m_pen_width));
230
231 if (m_aligned)
232 penWidth = qRound(penWidth);
233
235 g->setDrawingMode(QSGGeometry::DrawTriangleStrip);
236 int vertexStride = g->sizeOfVertex();
237
238 union {
239 Vertex *vertices;
240 SmoothVertex *smoothVertices;
241 };
242
243 Color4ub fillColor = colorToColor4ub(m_color);
245 Color4ub transparent = { 0, 0, 0, 0 };
246 const QGradientStops &stops = m_gradient_stops;
247
248 float gradientStart = (m_gradient_is_vertical ? m_rect.top() : m_rect.left());
249 float gradientLength = (m_gradient_is_vertical ? height : width);
250 float secondaryLength = (m_gradient_is_vertical ? width : height);
251
252 int nextGradientStop = 0;
253 float gradientPos = penWidth / gradientLength;
254 while (nextGradientStop < stops.size() && stops.at(nextGradientStop).first <= gradientPos)
255 ++nextGradientStop;
256 int lastGradientStop = stops.size() - 1;
257 float lastGradientPos = 1.0f - penWidth / gradientLength;
258 while (lastGradientStop >= nextGradientStop && stops.at(lastGradientStop).first >= lastGradientPos)
259 --lastGradientStop;
260 int gradientIntersections = (lastGradientStop - nextGradientStop + 1);
261
262 if (m_radius > 0
263 || m_topLeftRadius > 0
264 || m_topRightRadius > 0
265 || m_bottomLeftRadius > 0
266 || m_bottomRightRadius > 0) {
267 // Rounded corners.
268
269 // Radius should never exceed half the width or half the height.
270 float radiusTL = qMin(qMin(width, height) * 0.4999f, float(m_topLeftRadius < 0 ? m_radius : m_topLeftRadius));
271 float radiusTR = qMin(qMin(width, height) * 0.4999f, float(m_topRightRadius < 0 ? m_radius : m_topRightRadius));
272 float radiusBL = qMin(qMin(width, height) * 0.4999f, float(m_bottomLeftRadius < 0 ? m_radius : m_bottomLeftRadius));
273 float radiusBR = qMin(qMin(width, height) * 0.4999f, float(m_bottomRightRadius < 0 ? m_radius : m_bottomRightRadius));
274
275 // The code produces some artefacts when radius <= 0.5. A radius of half a pixel
276 // does not make much sense anyway, so we draw a normal corner in such a case.
277 if (radiusTL <= 0.5)
278 radiusTL = 0;
279 if (radiusTR <= 0.5)
280 radiusTR = 0;
281 if (radiusBL <= 0.5)
282 radiusBL = 0;
283 if (radiusBR <= 0.5)
284 radiusBR = 0;
285
286 // We want to keep a minimal inner radius in order to make the inner
287 // x-coordinates of an arc mathematically unique and identifiable.
288 const float innerRadiusTL = qMax(radiusTL - penWidth * 1.0f, 0.01);
289 const float innerRadiusTR = qMax(radiusTR - penWidth * 1.0f, 0.01);
290 const float innerRadiusBL = qMax(radiusBL - penWidth * 1.0f, 0.01);
291 const float innerRadiusBR = qMax(radiusBR - penWidth * 1.0f, 0.01);
292 const float outerRadiusTL = radiusTL;
293 const float outerRadiusTR = radiusTR;
294 const float outerRadiusBL = radiusBL;
295 const float outerRadiusBR = radiusBR;
296 const float delta = qMin(width, height) * 0.5f;
297
298 int segmentsTL = radiusTL == 0 ? 0 : qBound(3, qCeil(radiusTL * (M_PI / 6)), 18);
299 int segmentsTR = radiusTR == 0 ? 0 : qBound(3, qCeil(radiusTR * (M_PI / 6)), 18);
300 int segmentsBL = radiusBL == 0 ? 0 : qBound(3, qCeil(radiusBL * (M_PI / 6)), 18);
301 int segmentsBR = radiusBR == 0 ? 0 : qBound(3, qCeil(radiusBR * (M_PI / 6)), 18);
302
303 // If the radii on opposite sites in genraration direction are the same,
304 // we will set the segments of one side to 0 as these points would be
305 // calculated twice. Also, this optimizes for the case of similar radii
307 if (innerRadiusTL == innerRadiusTR) {
308 if (segmentsTL <= segmentsTR)
309 segmentsTL = 0;
310 else
311 segmentsTR = 0;
312 }
313 if (innerRadiusBL == innerRadiusBR){
314 if (segmentsBL <= segmentsBR)
315 segmentsBL = 0;
316 else
317 segmentsBR = 0;
318 }
319 } else {
320 if (innerRadiusTL == innerRadiusBL) {
321 if (segmentsTL <= segmentsBL)
322 segmentsTL = 0;
323 else
324 segmentsBL = 0;
325 }
326 if (innerRadiusTR == innerRadiusBR) {
327 if (segmentsTR <= segmentsBR)
328 segmentsTR = 0;
329 else
330 segmentsBR = 0;
331 }
332 }
333
334 const int sumSegments = segmentsTL + segmentsTR + segmentsBL + segmentsBR;
335
336 /*
337
338 --+--__
339 --+--__--__
340 | --__--__
341 | seg --__--+
342 --+-__ ment _+ \
343 --+-__--__ - \ \
344 --__--+ se \ \
345 + \ g \ \
346 \ \ m \ \
347 -----------+--+ e \ \ <- gradient line
348 \ \ nt\ \
349 fill +--+----+--+
350 | | | |
351 border
352 inner AA outer AA (AA = antialiasing)
353
354 */
355
356 const int innerVertexCount = (sumSegments + 4) * 2 + gradientIntersections * 2;
357 const int outerVertexCount = (sumSegments + 4) * 2;
358 int vertexCount = innerVertexCount;
359 if (m_antialiasing || penWidth)
360 vertexCount += innerVertexCount;
361 if (penWidth)
362 vertexCount += outerVertexCount;
363 if (m_antialiasing && penWidth)
364 vertexCount += outerVertexCount;
365
366
367 const int fillIndexCount = innerVertexCount;
368 const int innerAAIndexCount = innerVertexCount * 2 + 2;
369 const int borderIndexCount = innerVertexCount * 2 + 2;
370 const int outerAAIndexCount = outerVertexCount * 2 + 2;
371 int indexCount = 0;
372 int fillHead = 0;
373 int innerAAHead = 0;
374 int innerAATail = 0;
375 int borderHead = 0;
376 int borderTail = 0;
377 int outerAAHead = 0;
378 int outerAATail = 0;
379 bool hasFill = m_color.alpha() > 0 || !stops.isEmpty();
380 if (hasFill)
381 indexCount += fillIndexCount;
382 if (m_antialiasing) {
383 innerAATail = innerAAHead = indexCount + (innerAAIndexCount >> 1) + 1;
384 indexCount += innerAAIndexCount;
385 }
386 if (penWidth) {
387 borderTail = borderHead = indexCount + (borderIndexCount >> 1) + 1;
388 indexCount += borderIndexCount;
389 }
390 if (m_antialiasing && penWidth) {
391 outerAATail = outerAAHead = indexCount + (outerAAIndexCount >> 1) + 1;
392 indexCount += outerAAIndexCount;
393 }
394
395 g->allocate(vertexCount, indexCount);
396 vertices = reinterpret_cast<Vertex *>(g->vertexData());
397 memset(vertices, 0, vertexCount * vertexStride);
398 quint16 *indices = g->indexDataAsUShort();
399 quint16 index = 0;
400
401
402 float innerXPrev = 0.; // previous inner primary coordinate, both sides.
403 float innerYLeftPrev = 0.; // previous inner secondary coordinate, left.
404 float innerYRightPrev = 0.; // previous inner secondary coordinate, right.
405
406 const float angleTL = 0.5f * float(M_PI) / segmentsTL;
407 const float cosStepTL = qFastCos(angleTL);
408 const float sinStepTL = qFastSin(angleTL);
409 const float angleTR = 0.5f * float(M_PI) / segmentsTR;
410 const float cosStepTR = qFastCos(angleTR);
411 const float sinStepTR = qFastSin(angleTR);
412 const float angleBL = 0.5f * float(M_PI) / segmentsBL;
413 const float cosStepBL = qFastCos(angleBL);
414 const float sinStepBL = qFastSin(angleBL);
415 const float angleBR = 0.5f * float(M_PI) / segmentsBR;
416 const float cosStepBR = qFastCos(angleBR);
417 const float sinStepBR = qFastSin(angleBR);
418
419 //The x- and y-Axis are transposed, depending on gradient being vertical or horizontal
420 //Lets define some coordinates and radii. The first index is the part, the second index
421 //is the left or right side, as seen when moving from part0 to part1
422
423 // left vertices | right vertices
424 // |
425 // *************|**************
426 // * | | | *
427 // *--o | o--*
428 // * innerX/Y | innerX/Y *
429 // * | *
430 // * | * part 0
431 // * | *
432 // * | *
433 // * | *
434 // -----------------+--------------------> y
435 // * | *
436 // * | *
437 // * | *
438 // * | * part 1
439 // * | *
440 // * innerX/Y | innerX/Y *
441 // *--o | o--*
442 // * | | | *
443 // *************|**************
444 // |
445 // v x
446 //
447 // direction of vertex generation
448
449 const float outerXCenter[][2] = {{
450 float(m_gradient_is_vertical ? m_rect.top() + radiusTL : m_rect.left() + radiusTL),
451 float(m_gradient_is_vertical ? m_rect.top() + radiusTR : m_rect.left() + radiusBL)
452 }, {
453 float(m_gradient_is_vertical ? m_rect.bottom() - radiusBL : m_rect.right() - radiusTR),
454 float(m_gradient_is_vertical ? m_rect.bottom() - radiusBR : m_rect.right() - radiusBR)
455 }};
456
457 const float outerYCenter[][2] = {{
458 float(!m_gradient_is_vertical ? m_rect.top() + outerRadiusTL : m_rect.left() + outerRadiusTL),
459 float(!m_gradient_is_vertical ? m_rect.bottom() - outerRadiusBL : m_rect.right() - outerRadiusTR)
460 }, {
461 float(!m_gradient_is_vertical ? m_rect.top() + outerRadiusTR : m_rect.left() + outerRadiusBL),
462 float(!m_gradient_is_vertical ? m_rect.bottom() - outerRadiusBR : m_rect.right() - outerRadiusBR)
463 }};
464
465 const float innerXCenter[][2] = { {
466 float(m_gradient_is_vertical ? m_rect.top() + innerRadiusTL + penWidth : m_rect.left() + innerRadiusTL + penWidth),
467 float(m_gradient_is_vertical ? m_rect.top() + innerRadiusTR + penWidth: m_rect.left() + innerRadiusBL + penWidth)
468 }, {
469 float(m_gradient_is_vertical ? m_rect.bottom() - innerRadiusBL - penWidth: m_rect.right() - innerRadiusTR - penWidth),
470 float(m_gradient_is_vertical ? m_rect.bottom() - innerRadiusBR - penWidth: m_rect.right() - innerRadiusBR - penWidth)
471 }};
472
473 const float innerYCenter[][2] = { {
474 float(!m_gradient_is_vertical ? m_rect.top() + innerRadiusTL + penWidth : m_rect.left() + innerRadiusTL + penWidth),
475 float(!m_gradient_is_vertical ? m_rect.bottom() - innerRadiusBL - penWidth : m_rect.right() - innerRadiusTR - penWidth)
476 },{
477 float(!m_gradient_is_vertical ? m_rect.top() + innerRadiusTR + penWidth : m_rect.left() + innerRadiusBL + penWidth),
478 float(!m_gradient_is_vertical ? m_rect.bottom() - innerRadiusBR - penWidth : m_rect.right() - innerRadiusBR - penWidth)
479 }};
480
481 const float innerRadius[][2] = {{
482 float(!m_gradient_is_vertical ? innerRadiusTL : innerRadiusTL),
483 float(!m_gradient_is_vertical ? innerRadiusBL : innerRadiusTR)
484 }, {
485 float(!m_gradient_is_vertical ? innerRadiusTR : innerRadiusBL),
486 float(!m_gradient_is_vertical ? innerRadiusBR : innerRadiusBR)
487 }};
488
489 const float outerRadius[][2] = {{
490 float(!m_gradient_is_vertical ? outerRadiusTL : outerRadiusTL),
491 float(!m_gradient_is_vertical ? outerRadiusBL : outerRadiusTR)
492 }, {
493 float(!m_gradient_is_vertical ? outerRadiusTR : outerRadiusBL),
494 float(!m_gradient_is_vertical ? outerRadiusBR : outerRadiusBR)
495 }};
496
497 const int segments[][2] = {{
498 (!m_gradient_is_vertical ? segmentsTL : segmentsTL),
499 (!m_gradient_is_vertical ? segmentsBL : segmentsTR)
500 }, {
501 (!m_gradient_is_vertical ? segmentsTR : segmentsBL),
502 (!m_gradient_is_vertical ? segmentsBR : segmentsBR)
503 }};
504
505 const float cosStep[][2] = {{
506 float(!m_gradient_is_vertical ? cosStepTL : cosStepTL),
507 float(!m_gradient_is_vertical ? cosStepBL : cosStepTR)
508 }, {
509 float(!m_gradient_is_vertical ? cosStepTR : cosStepBL),
510 float(!m_gradient_is_vertical ? cosStepBR : cosStepBR)
511 }};
512
513 const float sinStep[][2] = {{
514 float(!m_gradient_is_vertical ? sinStepTL : sinStepTL),
515 float(!m_gradient_is_vertical ? sinStepBL : sinStepTR)
516 }, {
517 float(!m_gradient_is_vertical ? sinStepTR : sinStepBL),
518 float(!m_gradient_is_vertical ? sinStepBR : sinStepBR)
519 }};
520
521 auto fillColorFromX = [&](float x) {
522
523 float t = (x - gradientStart) / gradientLength;
524 t = qBound(0.0, t, 1.0);
525
526 int i = 1;
527 while (i < stops.size()) {
528 const QGradientStop &prev = stops.at(i - 1);
529 const QGradientStop &next = stops.at(i);
530 if (prev.first <= t && next.first > t) {
531 t = (t - prev.first) / (next.first - prev.first);
532 return colorToColor4ub(prev.second) * (1. - t) + colorToColor4ub(next.second) * t; }
533 i++;
534 }
535 return colorToColor4ub(stops.last().second);
536 };
537
538 for (int part = 0; part < 2; ++part) {
539 // cosine of the angle of the current segment, starting at 1 for part 0 and 0 for part 1
540 float cosSegmentAngleLeft = 1. - part;
541 // sine of the angle of the current segment
542 float sinSegmentAngleLeft = part;
543
544 float cosSegmentAngleRight = 1. - part;
545 float sinSegmentAngleRight = part;
546
547 bool advanceLeft = true;
548
549 // We draw both the left part and the right part of the rectangle at the same time.
550 // We also draw a vertex on the left side for every vertex on the right side. This
551 // syncronisation is required to make sure that all gradient stops can be inserted.
552 for (int iLeft = 0, iRight = 0; iLeft <= segments[part][0] || iRight <= segments[part][1]; ) {
553
554 float xLeft, yLeft,
555 xRight, yRight;
556
557 float outerXLeft, outerYLeft,
558 outerXRight, outerYRight;
559
560 float sinAngleLeft, cosAngleLeft,
561 sinAngleRight, cosAngleRight;
562
563 // calculate inner x-coordinates
564 xLeft = innerXCenter[part][0] - innerRadius[part][0] * cosSegmentAngleLeft;
565 xRight = innerXCenter[part][1] - innerRadius[part][1] * cosSegmentAngleRight;
566
567 // calcuate inner y-coordinates
568 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinSegmentAngleLeft;
569 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinSegmentAngleRight;
570
571 // Synchronize left and right hand x-coordinates. This is required to
572 // make sure that we can insert all gradient stops that require exactly two triangles at
573 // every x-coordinate. Take the smaller of both x-coordinates and then find the matching
574 // y-coordinates.
575 if ((iLeft <= segments[part][0] && xLeft <= xRight) || iRight > segments[part][1]) {
576 advanceLeft = true;
577 } else {
578 advanceLeft = false;
579 }
580
581 // Inner: Find the matching y-coordinates for the x-coordinate found above.
582 // Outer: Also set the sine and cosine to make sure that outer vertices are
583 // drawn correctly.
584 if (innerRadius[part][0] == innerRadius[part][1]) {
585 // Special case of equal radii. Optimize to avoid performance regression:
586 // Left and right is always equal and we can just copy the angles and
587 // mirror the coordinates.
588 if (advanceLeft) {
589 if (outerRadius[part][0] == 0) {
590 sinAngleLeft = 1.;
591 cosAngleLeft = part ? -1. : 1.;
592 } else {
593 sinAngleLeft = sinSegmentAngleLeft;
594 cosAngleLeft = cosSegmentAngleLeft;
595 }
596 if (outerRadius[part][1] == 0) {
597 sinAngleRight = 1.;
598 cosAngleRight = part ? -1. : 1.;
599 } else {
600 sinAngleRight = sinSegmentAngleLeft;
601 cosAngleRight = cosSegmentAngleLeft;
602 }
603 xRight = xLeft;
604 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinAngleRight;
605 } else {
606 if (outerRadius[part][0] == 0) {
607 sinAngleLeft = 1.;
608 cosAngleLeft = part ? -1. : 1.;
609 } else {
610 sinAngleLeft = sinSegmentAngleRight;
611 cosAngleLeft = cosSegmentAngleRight;
612 }
613 if (outerRadius[part][1] == 0) {
614 sinAngleRight = 1.;
615 cosAngleRight = part ? -1. : 1.;
616 } else {
617 sinAngleRight = sinSegmentAngleRight;
618 cosAngleRight = cosSegmentAngleRight;
619 }
620 xLeft = xRight;
621 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinAngleLeft;
622 }
623 } else if (advanceLeft) {
624 if (outerRadius[part][0] == 0) {
625 sinAngleLeft = 1.;
626 cosAngleLeft = part ? -1. : 1.;
627 } else {
628 sinAngleLeft = sinSegmentAngleLeft;
629 cosAngleLeft = cosSegmentAngleLeft;
630 }
631 if (outerRadius[part][1] == 0) {
632 // Outer: If the outer radius is zero we can return both sin and cos = 1
633 // to form a nice corner. Inner: Accept the x-coordinate from the other
634 // side and match the y-coordinate
635 sinAngleRight = 1.;
636 cosAngleRight = part ? -1. : 1.;
637 xRight = xLeft;
638 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinAngleRight;
639 } else if (xLeft >= innerXCenter[0][1] && xLeft <= innerXCenter[1][1]) {
640 // Outer: If we are on the straight line between the inner centers, we can
641 // just return sin = 1 and cos = 0. Inner: Accept the x-coordinate from the
642 // other side and match the y-coordinate
643 sinAngleRight = 1.;
644 cosAngleRight = 0.;
645 xRight = xLeft;
646 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinAngleRight;
647 } else {
648 // Inner: If we are on the rounded part of the oposite side, we have to find a vertex
649 // on that curve that matches the x-coordinate we selected.
650 // We always select the smaller x-coordinate and can therefore use a linear
651 // interpolation between the last point on this side and the point on this side
652 // that was not accepted because it was too large.
653 if (xRight != innerXPrev) {
654 float t = (xLeft - innerXPrev) / (xRight - innerXPrev);
655 yRight = innerYRightPrev * (1. - t) + yRight * t;
656 xRight = xLeft;
657 }
658 // Outer: With the coordinates from the interpolation we can calculate the sine
659 // and cosine of the respective angle quickly.
660 sinAngleRight = (yRight - innerYCenter[part][1]) / innerRadius[part][1];
661 cosAngleRight = -(xRight - innerXCenter[part][1]) / innerRadius[part][1];
662 }
663 } else {
664 // same as above but for the other side.
665 if (outerRadius[part][1] == 0) {
666 sinAngleRight = 1.;
667 cosAngleRight = part ? -1. : 1.;
668 } else {
669 sinAngleRight = sinSegmentAngleRight;
670 cosAngleRight = cosSegmentAngleRight;
671 }
672 if (outerRadius[part][0] == 0) {
673 sinAngleLeft = 1.;
674 cosAngleLeft = part ? -1. : 1.;
675 xLeft = xRight;
676 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinAngleLeft;
677 } else if (xRight >= innerXCenter[0][0] && xRight <= innerXCenter[1][0]) {
678 sinAngleLeft = 1.;
679 cosAngleLeft = 0.;
680 xLeft = xRight;
681 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinAngleLeft;
682 } else {
683 if (xLeft != innerXPrev) {
684 float t = (xRight - innerXPrev) / (xLeft - innerXPrev);
685 yLeft = innerYLeftPrev * (1. - t) + yLeft * t;
686 xLeft = xRight;
687 }
688 sinAngleLeft = -(yLeft - innerYCenter[part][0]) / innerRadius[part][0];
689 cosAngleLeft = -(xLeft - innerXCenter[part][0]) / innerRadius[part][0];
690 }
691 }
692
693 gradientPos = (xLeft - gradientStart) / gradientLength;
694
695 // calculate the matching outer coordinates
696 outerXLeft = outerXCenter[part][0] - outerRadius[part][0] * cosAngleLeft;
697 outerYLeft = outerYCenter[part][0] - outerRadius[part][0] * sinAngleLeft;
698 outerXRight = outerXCenter[part][1] - outerRadius[part][1] * cosAngleRight;
699 outerYRight = outerYCenter[part][1] + outerRadius[part][1] * sinAngleRight;
700
701 // insert gradient stops as required
702 while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) {
703 float gradientX;
704 float gradientYLeft;
705 float gradientYRight;
706
707 // Insert vertices at gradient stops
708 gradientX = gradientStart + stops.at(nextGradientStop).first * gradientLength;
709 // bilinear interpolation of known vertices
710 float t = (gradientX - innerXPrev) / (xLeft - innerXPrev);
711 gradientYLeft = innerYLeftPrev * (1. - t) + t * yLeft;
712 gradientYRight = innerYRightPrev * (1. - t) + t * yRight;
713
714 fillColor = fillColorFromX(gradientX);
715
716 if (hasFill) {
717 indices[fillHead++] = index;
718 indices[fillHead++] = index + 1;
719 }
720
721 if (penWidth) {
722 --borderHead;
723 indices[borderHead] = indices[borderHead + 2];
724 indices[--borderHead] = index + 2;
725 indices[borderTail++] = index + 3;
726 indices[borderTail] = indices[borderTail - 2];
727 ++borderTail;
728 }
729
730 if (m_antialiasing) {
731 indices[--innerAAHead] = index + 2;
732 indices[--innerAAHead] = index;
733 indices[innerAATail++] = index + 1;
734 indices[innerAATail++] = index + 3;
735
736 bool lower = stops.at(nextGradientStop).first > 0.5f;
737 float dp = lower ? qMin(0.0f, gradientLength - gradientX - delta) : qMax(0.0f, delta - gradientX);
738 smoothVertices[index++].set(gradientX, gradientYRight, fillColor, dp, secondaryLength - gradientYRight - delta, m_gradient_is_vertical);
739 smoothVertices[index++].set(gradientX, gradientYLeft, fillColor, dp, delta - gradientYLeft, m_gradient_is_vertical);
740 if (penWidth) {
741 smoothVertices[index++].set(gradientX, gradientYRight, borderColor, -0.49f * penWidth * cosAngleRight, 0.49f * penWidth * sinAngleRight, m_gradient_is_vertical);
742 smoothVertices[index++].set(gradientX, gradientYLeft, borderColor, -0.49f * penWidth * cosAngleLeft, -0.49f * penWidth * sinAngleLeft, m_gradient_is_vertical);
743 } else {
744 dp = lower ? delta : -delta;
745 smoothVertices[index++].set(gradientX, gradientYRight, transparent, dp, delta, m_gradient_is_vertical);
746 smoothVertices[index++].set(gradientX, gradientYLeft, transparent, dp, -delta, m_gradient_is_vertical);
747 }
748 } else {
749 vertices[index++].set(gradientX, gradientYRight, fillColor, m_gradient_is_vertical);
750 vertices[index++].set(gradientX, gradientYLeft, fillColor, m_gradient_is_vertical);
751 if (penWidth) {
752 vertices[index++].set(gradientX, gradientYRight, borderColor, m_gradient_is_vertical);
753 vertices[index++].set(gradientX, gradientYLeft, borderColor, m_gradient_is_vertical);
754 }
755 }
756
757 innerXPrev = gradientX;
758 innerYLeftPrev = gradientYLeft;
759 innerYRightPrev = gradientYRight;
760
761 nextGradientStop++;
762 }
763
764 if (!stops.isEmpty()) {
765 fillColor = fillColorFromX(xLeft);
766 }
767
768 if (hasFill) {
769 indices[fillHead++] = index;
770 indices[fillHead++] = index + 1;
771 }
772
773 if (penWidth) {
774 indices[--borderHead] = index + 4;
775 indices[--borderHead] = index + 2;
776 indices[borderTail++] = index + 3;
777 indices[borderTail++] = index + 5;
778 }
779
780 if (m_antialiasing) {
781 indices[--innerAAHead] = index + 2;
782 indices[--innerAAHead] = index;
783 indices[innerAATail++] = index + 1;
784 indices[innerAATail++] = index + 3;
785
786 float dp = part ? qMin(0.0f, gradientLength - xRight - delta) : qMax(0.0f, delta - xRight);
787 smoothVertices[index++].set(xRight, yRight, fillColor, dp, secondaryLength - yRight - delta, m_gradient_is_vertical);
788 smoothVertices[index++].set(xLeft, yLeft, fillColor, dp, delta - yLeft, m_gradient_is_vertical);
789
790 dp = part ? delta : -delta;
791 if (penWidth) {
792 smoothVertices[index++].set(xRight, yRight, borderColor, -0.49f * penWidth * cosAngleRight, 0.49f * penWidth * sinAngleRight, m_gradient_is_vertical);
793 smoothVertices[index++].set(xLeft, yLeft, borderColor, -0.49f * penWidth * cosAngleLeft, -0.49f * penWidth * sinAngleLeft, m_gradient_is_vertical);
794 smoothVertices[index++].set(outerXRight, outerYRight, borderColor, 0.49f * penWidth * cosAngleRight, -0.49f * penWidth * sinAngleRight, m_gradient_is_vertical);
795 smoothVertices[index++].set(outerXLeft, outerYLeft, borderColor, 0.49f * penWidth * cosAngleLeft, 0.49f * penWidth * sinAngleLeft, m_gradient_is_vertical);
796 smoothVertices[index++].set(outerXRight, outerYRight, transparent, dp, delta, m_gradient_is_vertical);
797 smoothVertices[index++].set(outerXLeft, outerYLeft, transparent, dp, -delta, m_gradient_is_vertical);
798
799 indices[--outerAAHead] = index - 2;
800 indices[--outerAAHead] = index - 4;
801 indices[outerAATail++] = index - 3;
802 indices[outerAATail++] = index - 1;
803 } else {
804 smoothVertices[index++].set(xRight, yRight, transparent, dp, delta, m_gradient_is_vertical);
805 smoothVertices[index++].set(xLeft, yLeft, transparent, dp, -delta, m_gradient_is_vertical);
806 }
807 } else {
808 vertices[index++].set(xRight, yRight, fillColor, m_gradient_is_vertical);
809 vertices[index++].set(xLeft, yLeft, fillColor, m_gradient_is_vertical);
810 if (penWidth) {
811 vertices[index++].set(xRight, yRight, borderColor, m_gradient_is_vertical);
812 vertices[index++].set(xLeft, yLeft, borderColor, m_gradient_is_vertical);
813 vertices[index++].set(outerXRight, outerYRight, borderColor, m_gradient_is_vertical);
814 vertices[index++].set(outerXLeft, outerYLeft, borderColor, m_gradient_is_vertical);
815 }
816 }
817
818 innerXPrev = xLeft;
819 innerYLeftPrev = yLeft;
820 innerYRightPrev = yRight;
821
822 // Advance the point. This corresponds to a rotation of the respective segment
823 if (advanceLeft) {
824 iLeft++;
825 qreal tmp = cosSegmentAngleLeft;
826 cosSegmentAngleLeft = cosSegmentAngleLeft * cosStep[part][0] - sinSegmentAngleLeft * sinStep[part][0];
827 sinSegmentAngleLeft = sinSegmentAngleLeft * cosStep[part][0] + tmp * sinStep[part][0];
828 } else {
829 iRight++;
830 qreal tmp = cosSegmentAngleRight;
831 cosSegmentAngleRight = cosSegmentAngleRight * cosStep[part][1] - sinSegmentAngleRight * sinStep[part][1];
832 sinSegmentAngleRight = sinSegmentAngleRight * cosStep[part][1] + tmp * sinStep[part][1];
833 }
834 }
835 }
836
837 Q_ASSERT(index == vertexCount);
838
839 // Close the triangle strips.
840 if (m_antialiasing) {
841 indices[--innerAAHead] = indices[innerAATail - 1];
842 indices[--innerAAHead] = indices[innerAATail - 2];
843 Q_ASSERT(innerAATail <= indexCount);
844 }
845 if (penWidth) {
846 indices[--borderHead] = indices[borderTail - 1];
847 indices[--borderHead] = indices[borderTail - 2];
848 Q_ASSERT(borderTail <= indexCount);
849 }
850 if (m_antialiasing && penWidth) {
851 indices[--outerAAHead] = indices[outerAATail - 1];
852 indices[--outerAAHead] = indices[outerAATail - 2];
853 Q_ASSERT(outerAATail == indexCount);
854 }
855 } else {
856 // Straight corners.
857 QRectF innerRect = m_rect;
858 QRectF outerRect = m_rect;
859
860 if (penWidth)
861 innerRect.adjust(1.0f * penWidth, 1.0f * penWidth, -1.0f * penWidth, -1.0f * penWidth);
862
863 float delta = qMin(width, height) * 0.5f;
864 int innerVertexCount = 4 + gradientIntersections * 2;
865 int outerVertexCount = 4;
866 int vertexCount = innerVertexCount;
867 if (m_antialiasing || penWidth)
868 vertexCount += innerVertexCount;
869 if (penWidth)
870 vertexCount += outerVertexCount;
871 if (m_antialiasing && penWidth)
872 vertexCount += outerVertexCount;
873
874 int fillIndexCount = innerVertexCount;
875 int innerAAIndexCount = innerVertexCount * 2 + 2;
876 int borderIndexCount = innerVertexCount * 2 + 2;
877 int outerAAIndexCount = outerVertexCount * 2 + 2;
878 int indexCount = 0;
879 int fillHead = 0;
880 int innerAAHead = 0;
881 int innerAATail = 0;
882 int borderHead = 0;
883 int borderTail = 0;
884 int outerAAHead = 0;
885 int outerAATail = 0;
886 bool hasFill = m_color.alpha() > 0 || !stops.isEmpty();
887 if (hasFill)
888 indexCount += fillIndexCount;
889 if (m_antialiasing) {
890 innerAATail = innerAAHead = indexCount + (innerAAIndexCount >> 1) + 1;
891 indexCount += innerAAIndexCount;
892 }
893 if (penWidth) {
894 borderTail = borderHead = indexCount + (borderIndexCount >> 1) + 1;
895 indexCount += borderIndexCount;
896 }
897 if (m_antialiasing && penWidth) {
898 outerAATail = outerAAHead = indexCount + (outerAAIndexCount >> 1) + 1;
899 indexCount += outerAAIndexCount;
900 }
901
902 g->allocate(vertexCount, indexCount);
903 vertices = reinterpret_cast<Vertex *>(g->vertexData());
904 memset(vertices, 0, vertexCount * vertexStride);
905 quint16 *indices = g->indexDataAsUShort();
906 quint16 index = 0;
907
908 float innerStart = (m_gradient_is_vertical ? innerRect.top() : innerRect.left());
909 float innerEnd = (m_gradient_is_vertical ? innerRect.bottom() : innerRect.right());
910 float outerStart = (m_gradient_is_vertical ? outerRect.top() : outerRect.left());
911 float outerEnd = (m_gradient_is_vertical ? outerRect.bottom() : outerRect.right());
912
913 float innerSecondaryStart = (m_gradient_is_vertical ? innerRect.left() : innerRect.top());
914 float innerSecondaryEnd = (m_gradient_is_vertical ? innerRect.right() : innerRect.bottom());
915 float outerSecondaryStart = (m_gradient_is_vertical ? outerRect.left() : outerRect.top());
916 float outerSecondaryEnd = (m_gradient_is_vertical ? outerRect.right() : outerRect.bottom());
917
918 for (int part = -1; part <= 1; part += 2) {
919 float innerEdge = (part == 1 ? innerEnd : innerStart);
920 float outerEdge = (part == 1 ? outerEnd : outerStart);
921 gradientPos = (innerEdge - innerStart + penWidth) / gradientLength;
922
923 while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) {
924 // Insert vertices at gradient stops.
925 float gp = (innerStart - penWidth) + stops.at(nextGradientStop).first * gradientLength;
926
927 fillColor = colorToColor4ub(stops.at(nextGradientStop).second);
928
929 if (hasFill) {
930 indices[fillHead++] = index;
931 indices[fillHead++] = index + 1;
932 }
933
934 if (penWidth) {
935 --borderHead;
936 indices[borderHead] = indices[borderHead + 2];
937 indices[--borderHead] = index + 2;
938 indices[borderTail++] = index + 3;
939 indices[borderTail] = indices[borderTail - 2];
940 ++borderTail;
941 }
942
943 if (m_antialiasing) {
944 indices[--innerAAHead] = index + 2;
945 indices[--innerAAHead] = index;
946 indices[innerAATail++] = index + 1;
947 indices[innerAATail++] = index + 3;
948
949 bool lower = stops.at(nextGradientStop).first > 0.5f;
950 float dp = lower ? qMin(0.0f, gradientLength - gp - delta) : qMax(0.0f, delta - gp);
951 smoothVertices[index++].set(gp, innerSecondaryEnd, fillColor, dp, secondaryLength - innerSecondaryEnd - delta, m_gradient_is_vertical);
952 smoothVertices[index++].set(gp, innerSecondaryStart, fillColor, dp, delta - innerSecondaryStart, m_gradient_is_vertical);
953 if (penWidth) {
954 smoothVertices[index++].set(gp, innerSecondaryEnd, borderColor, (lower ? 0.49f : -0.49f) * penWidth, 0.49f * penWidth, m_gradient_is_vertical);
955 smoothVertices[index++].set(gp, innerSecondaryStart, borderColor, (lower ? 0.49f : -0.49f) * penWidth, -0.49f * penWidth, m_gradient_is_vertical);
956 } else {
957 smoothVertices[index++].set(gp, innerSecondaryEnd, transparent, lower ? delta : -delta, delta, m_gradient_is_vertical);
958 smoothVertices[index++].set(gp, innerSecondaryStart, transparent, lower ? delta : -delta, -delta, m_gradient_is_vertical);
959 }
960 } else {
961 vertices[index++].set(gp, innerSecondaryEnd, fillColor, m_gradient_is_vertical);
962 vertices[index++].set(gp, innerSecondaryStart, fillColor, m_gradient_is_vertical);
963 if (penWidth) {
964 vertices[index++].set(gp, innerSecondaryEnd, borderColor, m_gradient_is_vertical);
965 vertices[index++].set(gp, innerSecondaryStart, borderColor, m_gradient_is_vertical);
966 }
967 }
968 ++nextGradientStop;
969 }
970
971 if (!stops.isEmpty()) {
972 if (nextGradientStop == 0) {
973 fillColor = colorToColor4ub(stops.at(0).second);
974 } else if (nextGradientStop == stops.size()) {
975 fillColor = colorToColor4ub(stops.last().second);
976 } else {
977 const QGradientStop &prev = stops.at(nextGradientStop - 1);
978 const QGradientStop &next = stops.at(nextGradientStop);
979 float t = (gradientPos - prev.first) / (next.first - prev.first);
980 fillColor = colorToColor4ub(prev.second) * (1 - t) + colorToColor4ub(next.second) * t;
981 }
982 }
983
984 if (hasFill) {
985 indices[fillHead++] = index;
986 indices[fillHead++] = index + 1;
987 }
988
989 if (penWidth) {
990 indices[--borderHead] = index + 4;
991 indices[--borderHead] = index + 2;
992 indices[borderTail++] = index + 3;
993 indices[borderTail++] = index + 5;
994 }
995
996 if (m_antialiasing) {
997 indices[--innerAAHead] = index + 2;
998 indices[--innerAAHead] = index;
999 indices[innerAATail++] = index + 1;
1000 indices[innerAATail++] = index + 3;
1001
1002 float dp = part == 1 ? qMin(0.0f, gradientLength - innerEdge - delta) : qMax(0.0f, delta - innerEdge);
1003 smoothVertices[index++].set(innerEdge, innerSecondaryEnd, fillColor, dp, secondaryLength - innerSecondaryEnd - delta, m_gradient_is_vertical);
1004 smoothVertices[index++].set(innerEdge, innerSecondaryStart, fillColor, dp, delta - innerSecondaryStart, m_gradient_is_vertical);
1005
1006 if (penWidth) {
1007 smoothVertices[index++].set(innerEdge, innerSecondaryEnd, borderColor, 0.49f * penWidth * part, 0.49f * penWidth, m_gradient_is_vertical);
1008 smoothVertices[index++].set(innerEdge, innerSecondaryStart, borderColor, 0.49f * penWidth * part, -0.49f * penWidth, m_gradient_is_vertical);
1009 smoothVertices[index++].set(outerEdge, outerSecondaryEnd, borderColor, -0.49f * penWidth * part, -0.49f * penWidth, m_gradient_is_vertical);
1010 smoothVertices[index++].set(outerEdge, outerSecondaryStart, borderColor, -0.49f * penWidth * part, 0.49f * penWidth, m_gradient_is_vertical);
1011 smoothVertices[index++].set(outerEdge, outerSecondaryEnd, transparent, delta * part, delta, m_gradient_is_vertical);
1012 smoothVertices[index++].set(outerEdge, outerSecondaryStart, transparent, delta * part, -delta, m_gradient_is_vertical);
1013
1014 indices[--outerAAHead] = index - 2;
1015 indices[--outerAAHead] = index - 4;
1016 indices[outerAATail++] = index - 3;
1017 indices[outerAATail++] = index - 1;
1018 } else {
1019 smoothVertices[index++].set(innerEdge, innerSecondaryEnd, transparent, delta * part, delta, m_gradient_is_vertical);
1020 smoothVertices[index++].set(innerEdge, innerSecondaryStart, transparent, delta * part, -delta, m_gradient_is_vertical);
1021 }
1022 } else {
1023 vertices[index++].set(innerEdge, innerSecondaryEnd, fillColor, m_gradient_is_vertical);
1024 vertices[index++].set(innerEdge, innerSecondaryStart, fillColor, m_gradient_is_vertical);
1025 if (penWidth) {
1026 vertices[index++].set(innerEdge, innerSecondaryEnd, borderColor, m_gradient_is_vertical);
1027 vertices[index++].set(innerEdge, innerSecondaryStart, borderColor, m_gradient_is_vertical);
1028 vertices[index++].set(outerEdge, outerSecondaryEnd, borderColor, m_gradient_is_vertical);
1029 vertices[index++].set(outerEdge, outerSecondaryStart, borderColor, m_gradient_is_vertical);
1030 }
1031 }
1032 }
1033 Q_ASSERT(index == vertexCount);
1034
1035 // Close the triangle strips.
1036 if (m_antialiasing) {
1037 indices[--innerAAHead] = indices[innerAATail - 1];
1038 indices[--innerAAHead] = indices[innerAATail - 2];
1039 Q_ASSERT(innerAATail <= indexCount);
1040 }
1041 if (penWidth) {
1042 indices[--borderHead] = indices[borderTail - 1];
1043 indices[--borderHead] = indices[borderTail - 2];
1044 Q_ASSERT(borderTail <= indexCount);
1045 }
1046 if (m_antialiasing && penWidth) {
1047 indices[--outerAAHead] = indices[outerAATail - 1];
1048 indices[--outerAAHead] = indices[outerAATail - 2];
1049 Q_ASSERT(outerAATail == indexCount);
1050 }
1051 }
1052}
1053
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
int alpha() const noexcept
Returns the alpha color component of this color.
Definition qcolor.cpp:1466
qsizetype size() const noexcept
Definition qlist.h:386
const_pointer constData() const noexcept
Definition qlist.h:416
bool isEmpty() const noexcept
Definition qlist.h:390
T & last()
Definition qlist.h:631
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr qreal bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:499
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:718
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:715
constexpr qreal left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:496
constexpr void adjust(qreal x1, qreal y1, qreal x2, qreal y2) noexcept
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition qrect.h:791
constexpr qreal top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:497
constexpr qreal right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:498
const QSGGeometry * geometry() const
Returns this node's geometry.
Definition qsgnode.h:160
void setGeometry(QSGGeometry *geometry)
Sets the geometry of this node to geometry.
Definition qsgnode.cpp:762
virtual void updateMaterialAntialiasing()=0
void setBottomLeftRadius(qreal radius) override
void setGradientVertical(bool vertical) override
void setPenColor(const QColor &color) override
void setColor(const QColor &color) override
virtual void updateMaterialBlending(QSGNode::DirtyState *state)=0
void setRect(const QRectF &rect) override
void setAntialiasing(bool antialiasing) override
void setBottomRightRadius(qreal radius) override
void setGradientStops(const QGradientStops &stops) override
The QSGGeometry class provides low-level storage for graphics primitives in the \l{Qt Quick Scene Gra...
Definition qsggeometry.h:15
@ DirtyGeometry
Definition qsgnode.h:74
@ OwnsGeometry
Definition qsgnode.h:57
void markDirty(DirtyState bits)
Notifies all connected renderers that the node has dirty bits.
Definition qsgnode.cpp:622
void setFlag(Flag, bool=true)
Sets the flag f on this node if enabled is true; otherwise clears the flag.
Definition qsgnode.cpp:584
rect
[4]
else opt state
[0]
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
const QSGGeometry::AttributeSet & smoothAttributeSet()
QPair< qreal, QColor > QGradientStop
Definition qbrush.h:131
constexpr timespec operator+(const timespec &t1, const timespec &t2)
constexpr timespec operator*(const timespec &t1, int mul)
static struct AttrInfo attrs[]
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
qreal qFastSin(qreal x)
Definition qmath.h:240
qreal qFastCos(qreal x)
Definition qmath.h:250
int qCeil(T v)
Definition qmath.h:36
#define M_PI
Definition qmath.h:209
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
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint index
[2]
GLboolean r
[2]
GLint GLsizei width
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLboolean GLboolean g
GLsizei GLenum const void * indices
GLint y
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint segments
static QQuickShapeGenericRenderer::Color4ub colorToColor4ub(const QColor &c)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
Int aligned(Int v, Int byteAlign)
void qsgnode_set_description(QSGNode *node, const QString &description)
Definition qsgnode.cpp:639
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define gp
unsigned char uchar
Definition qtypes.h:27
unsigned short quint16
Definition qtypes.h:43
double qreal
Definition qtypes.h:92
The QSGGeometry::AttributeSet describes how the vertices in a QSGGeometry are built up.
Definition qsggeometry.h:73
The QSGGeometry::Attribute describes a single vertex attribute in a QSGGeometry.
Definition qsggeometry.h:58
static Attribute createWithAttributeType(int pos, int tupleSize, int primitiveType, AttributeType attributeType)
Creates a new QSGGeometry::Attribute for attribute register pos with tupleSize.
void set(float primary, float secondary, Color4ub ncolor, float dPrimary, float dSecondary, bool vertical)
void set(float primary, float secondary, Color4ub ncolor, bool vertical)
\qmltype MapCircle \instantiates QDeclarativeCircleMapItem \inqmlmodule QtLocation