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
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
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
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 innerRadiusTL,
483 !m_gradient_is_vertical ? innerRadiusBL : innerRadiusTR
484 }, {
485 !m_gradient_is_vertical ? innerRadiusTR : innerRadiusBL,
486 innerRadiusBR
487 }};
488
489 const float outerRadius[][2] = {{
490 outerRadiusTL,
491 !m_gradient_is_vertical ? outerRadiusBL : outerRadiusTR
492 }, {
493 !m_gradient_is_vertical ? outerRadiusTR : outerRadiusBL,
494 outerRadiusBR
495 }};
496
497 const int segments[][2] = {{
498 segmentsTL,
499 !m_gradient_is_vertical ? segmentsBL : segmentsTR
500 }, {
501 !m_gradient_is_vertical ? segmentsTR : segmentsBL,
502 segmentsBR
503 }};
504
505 const float cosStep[][2] = {{
506 cosStepTL,
507 !m_gradient_is_vertical ? cosStepBL : cosStepTR
508 }, {
509 !m_gradient_is_vertical ? cosStepTR : cosStepBL,
510 cosStepBR
511 }};
512
513 const float sinStep[][2] = {{
514 sinStepTL,
515 !m_gradient_is_vertical ? sinStepBL : sinStepTR
516 }, {
517 !m_gradient_is_vertical ? sinStepTR : sinStepBL,
518 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 if (t < stops.first().first)
528 return colorToColor4ub(stops.first().second);
529 while (i < stops.size()) {
530 const QGradientStop &prev = stops.at(i - 1);
531 const QGradientStop &next = stops.at(i);
532 if (prev.first <= t && next.first > t) {
533 t = (t - prev.first) / (next.first - prev.first);
534 return colorToColor4ub(prev.second) * (1. - t) + colorToColor4ub(next.second) * t; }
535 i++;
536 }
537 return colorToColor4ub(stops.last().second);
538 };
539
540 for (int part = 0; part < 2; ++part) {
541 // cosine of the angle of the current segment, starting at 1 for part 0 and 0 for part 1
542 float cosSegmentAngleLeft = 1. - part;
543 // sine of the angle of the current segment
544 float sinSegmentAngleLeft = part;
545
546 float cosSegmentAngleRight = 1. - part;
547 float sinSegmentAngleRight = part;
548
549 bool advanceLeft = true;
550
551 // We draw both the left part and the right part of the rectangle at the same time.
552 // We also draw a vertex on the left side for every vertex on the right side. This
553 // syncronisation is required to make sure that all gradient stops can be inserted.
554 for (int iLeft = 0, iRight = 0; iLeft <= segments[part][0] || iRight <= segments[part][1]; ) {
555
556 float xLeft, yLeft,
557 xRight, yRight;
558
559 float outerXLeft, outerYLeft,
560 outerXRight, outerYRight;
561
562 float sinAngleLeft, cosAngleLeft,
563 sinAngleRight, cosAngleRight;
564
565 // calculate inner x-coordinates
566 xLeft = innerXCenter[part][0] - innerRadius[part][0] * cosSegmentAngleLeft;
567 xRight = innerXCenter[part][1] - innerRadius[part][1] * cosSegmentAngleRight;
568
569 // calcuate inner y-coordinates
570 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinSegmentAngleLeft;
571 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinSegmentAngleRight;
572
573 // Synchronize left and right hand x-coordinates. This is required to
574 // make sure that we can insert all gradient stops that require exactly two triangles at
575 // every x-coordinate. Take the smaller of both x-coordinates and then find the matching
576 // y-coordinates.
577 if ((iLeft <= segments[part][0] && xLeft <= xRight) || iRight > segments[part][1]) {
578 advanceLeft = true;
579 } else {
580 advanceLeft = false;
581 }
582
583 // Inner: Find the matching y-coordinates for the x-coordinate found above.
584 // Outer: Also set the sine and cosine to make sure that outer vertices are
585 // drawn correctly.
586 if (innerRadius[part][0] == innerRadius[part][1]) {
587 // Special case of equal radii. Optimize to avoid performance regression:
588 // Left and right is always equal and we can just copy the angles and
589 // mirror the coordinates.
590 if (advanceLeft) {
591 if (outerRadius[part][0] == 0) {
592 sinAngleLeft = 1.;
593 cosAngleLeft = part ? -1. : 1.;
594 } else {
595 sinAngleLeft = sinSegmentAngleLeft;
596 cosAngleLeft = cosSegmentAngleLeft;
597 }
598 if (outerRadius[part][1] == 0) {
599 sinAngleRight = 1.;
600 cosAngleRight = part ? -1. : 1.;
601 } else {
602 sinAngleRight = sinSegmentAngleLeft;
603 cosAngleRight = cosSegmentAngleLeft;
604 }
605 xRight = xLeft;
606 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinAngleRight;
607 } else {
608 if (outerRadius[part][0] == 0) {
609 sinAngleLeft = 1.;
610 cosAngleLeft = part ? -1. : 1.;
611 } else {
612 sinAngleLeft = sinSegmentAngleRight;
613 cosAngleLeft = cosSegmentAngleRight;
614 }
615 if (outerRadius[part][1] == 0) {
616 sinAngleRight = 1.;
617 cosAngleRight = part ? -1. : 1.;
618 } else {
619 sinAngleRight = sinSegmentAngleRight;
620 cosAngleRight = cosSegmentAngleRight;
621 }
622 xLeft = xRight;
623 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinAngleLeft;
624 }
625 } else if (advanceLeft) {
626 if (outerRadius[part][0] == 0) {
627 sinAngleLeft = 1.;
628 cosAngleLeft = part ? -1. : 1.;
629 } else {
630 sinAngleLeft = sinSegmentAngleLeft;
631 cosAngleLeft = cosSegmentAngleLeft;
632 }
633 if (outerRadius[part][1] == 0) {
634 // Outer: If the outer radius is zero we can return both sin and cos = 1
635 // to form a nice corner. Inner: Accept the x-coordinate from the other
636 // side and match the y-coordinate
637 sinAngleRight = 1.;
638 cosAngleRight = part ? -1. : 1.;
639 xRight = xLeft;
640 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinAngleRight;
641 } else if (xLeft >= innerXCenter[0][1] && xLeft <= innerXCenter[1][1]) {
642 // Outer: If we are on the straight line between the inner centers, we can
643 // just return sin = 1 and cos = 0. Inner: Accept the x-coordinate from the
644 // other side and match the y-coordinate
645 sinAngleRight = 1.;
646 cosAngleRight = 0.;
647 xRight = xLeft;
648 yRight = innerYCenter[part][1] + innerRadius[part][1] * sinAngleRight;
649 } else {
650 // Inner: If we are on the rounded part of the oposite side, we have to find a vertex
651 // on that curve that matches the x-coordinate we selected.
652 // We always select the smaller x-coordinate and can therefore use a linear
653 // interpolation between the last point on this side and the point on this side
654 // that was not accepted because it was too large.
655 if (xRight != innerXPrev) {
656 float t = (xLeft - innerXPrev) / (xRight - innerXPrev);
657 yRight = innerYRightPrev * (1. - t) + yRight * t;
658 xRight = xLeft;
659 }
660 // Outer: With the coordinates from the interpolation we can calculate the sine
661 // and cosine of the respective angle quickly.
662 sinAngleRight = (yRight - innerYCenter[part][1]) / innerRadius[part][1];
663 cosAngleRight = -(xRight - innerXCenter[part][1]) / innerRadius[part][1];
664 }
665 } else {
666 // same as above but for the other side.
667 if (outerRadius[part][1] == 0) {
668 sinAngleRight = 1.;
669 cosAngleRight = part ? -1. : 1.;
670 } else {
671 sinAngleRight = sinSegmentAngleRight;
672 cosAngleRight = cosSegmentAngleRight;
673 }
674 if (outerRadius[part][0] == 0) {
675 sinAngleLeft = 1.;
676 cosAngleLeft = part ? -1. : 1.;
677 xLeft = xRight;
678 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinAngleLeft;
679 } else if (xRight >= innerXCenter[0][0] && xRight <= innerXCenter[1][0]) {
680 sinAngleLeft = 1.;
681 cosAngleLeft = 0.;
682 xLeft = xRight;
683 yLeft = innerYCenter[part][0] - innerRadius[part][0] * sinAngleLeft;
684 } else {
685 if (xLeft != innerXPrev) {
686 float t = (xRight - innerXPrev) / (xLeft - innerXPrev);
687 yLeft = innerYLeftPrev * (1. - t) + yLeft * t;
688 xLeft = xRight;
689 }
690 sinAngleLeft = -(yLeft - innerYCenter[part][0]) / innerRadius[part][0];
691 cosAngleLeft = -(xLeft - innerXCenter[part][0]) / innerRadius[part][0];
692 }
693 }
694
695 gradientPos = (xLeft - gradientStart) / gradientLength;
696
697 // calculate the matching outer coordinates
698 outerXLeft = outerXCenter[part][0] - outerRadius[part][0] * cosAngleLeft;
699 outerYLeft = outerYCenter[part][0] - outerRadius[part][0] * sinAngleLeft;
700 outerXRight = outerXCenter[part][1] - outerRadius[part][1] * cosAngleRight;
701 outerYRight = outerYCenter[part][1] + outerRadius[part][1] * sinAngleRight;
702
703 // insert gradient stops as required
704 while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) {
705 float gradientX;
706 float gradientYLeft;
707 float gradientYRight;
708
709 // Insert vertices at gradient stops
710 gradientX = gradientStart + stops.at(nextGradientStop).first * gradientLength;
711 // bilinear interpolation of known vertices
712 float t = (gradientX - innerXPrev) / (xLeft - innerXPrev);
713 gradientYLeft = innerYLeftPrev * (1. - t) + t * yLeft;
714 gradientYRight = innerYRightPrev * (1. - t) + t * yRight;
715
716 fillColor = fillColorFromX(gradientX);
717
718 if (hasFill) {
719 indices[fillHead++] = index;
720 indices[fillHead++] = index + 1;
721 }
722
723 if (penWidth) {
724 --borderHead;
725 indices[borderHead] = indices[borderHead + 2];
726 indices[--borderHead] = index + 2;
727 indices[borderTail++] = index + 3;
728 indices[borderTail] = indices[borderTail - 2];
729 ++borderTail;
730 }
731
732 if (m_antialiasing) {
733 indices[--innerAAHead] = index + 2;
734 indices[--innerAAHead] = index;
735 indices[innerAATail++] = index + 1;
736 indices[innerAATail++] = index + 3;
737
738 bool lower = stops.at(nextGradientStop).first > 0.5f;
739 float dp = lower ? qMin(0.0f, gradientLength - gradientX - delta) : qMax(0.0f, delta - gradientX);
740 smoothVertices[index++].set(gradientX, gradientYRight, fillColor, dp, secondaryLength - gradientYRight - delta, m_gradient_is_vertical);
741 smoothVertices[index++].set(gradientX, gradientYLeft, fillColor, dp, delta - gradientYLeft, m_gradient_is_vertical);
742 if (penWidth) {
743 smoothVertices[index++].set(gradientX, gradientYRight, borderColor, -0.49f * penWidth * cosAngleRight, 0.49f * penWidth * sinAngleRight, m_gradient_is_vertical);
744 smoothVertices[index++].set(gradientX, gradientYLeft, borderColor, -0.49f * penWidth * cosAngleLeft, -0.49f * penWidth * sinAngleLeft, m_gradient_is_vertical);
745 } else {
746 dp = lower ? delta : -delta;
747 smoothVertices[index++].set(gradientX, gradientYRight, transparent, dp, delta, m_gradient_is_vertical);
748 smoothVertices[index++].set(gradientX, gradientYLeft, transparent, dp, -delta, m_gradient_is_vertical);
749 }
750 } else {
751 vertices[index++].set(gradientX, gradientYRight, fillColor, m_gradient_is_vertical);
752 vertices[index++].set(gradientX, gradientYLeft, fillColor, m_gradient_is_vertical);
753 if (penWidth) {
754 vertices[index++].set(gradientX, gradientYRight, borderColor, m_gradient_is_vertical);
755 vertices[index++].set(gradientX, gradientYLeft, borderColor, m_gradient_is_vertical);
756 }
757 }
758
759 innerXPrev = gradientX;
760 innerYLeftPrev = gradientYLeft;
761 innerYRightPrev = gradientYRight;
762
763 nextGradientStop++;
764 }
765
766 if (!stops.isEmpty()) {
767 fillColor = fillColorFromX(xLeft);
768 }
769
770 if (hasFill) {
771 indices[fillHead++] = index;
772 indices[fillHead++] = index + 1;
773 }
774
775 if (penWidth) {
776 indices[--borderHead] = index + 4;
777 indices[--borderHead] = index + 2;
778 indices[borderTail++] = index + 3;
779 indices[borderTail++] = index + 5;
780 }
781
782 if (m_antialiasing) {
783 indices[--innerAAHead] = index + 2;
784 indices[--innerAAHead] = index;
785 indices[innerAATail++] = index + 1;
786 indices[innerAATail++] = index + 3;
787
788 float dp = part ? qMin(0.0f, gradientLength - xRight - delta) : qMax(0.0f, delta - xRight);
789 smoothVertices[index++].set(xRight, yRight, fillColor, dp, secondaryLength - yRight - delta, m_gradient_is_vertical);
790 smoothVertices[index++].set(xLeft, yLeft, fillColor, dp, delta - yLeft, m_gradient_is_vertical);
791
792 dp = part ? delta : -delta;
793 if (penWidth) {
794 smoothVertices[index++].set(xRight, yRight, borderColor, -0.49f * penWidth * cosAngleRight, 0.49f * penWidth * sinAngleRight, m_gradient_is_vertical);
795 smoothVertices[index++].set(xLeft, yLeft, borderColor, -0.49f * penWidth * cosAngleLeft, -0.49f * penWidth * sinAngleLeft, m_gradient_is_vertical);
796 smoothVertices[index++].set(outerXRight, outerYRight, borderColor, 0.49f * penWidth * cosAngleRight, -0.49f * penWidth * sinAngleRight, m_gradient_is_vertical);
797 smoothVertices[index++].set(outerXLeft, outerYLeft, borderColor, 0.49f * penWidth * cosAngleLeft, 0.49f * penWidth * sinAngleLeft, m_gradient_is_vertical);
798 smoothVertices[index++].set(outerXRight, outerYRight, transparent, dp, delta, m_gradient_is_vertical);
799 smoothVertices[index++].set(outerXLeft, outerYLeft, transparent, dp, -delta, m_gradient_is_vertical);
800
801 indices[--outerAAHead] = index - 2;
802 indices[--outerAAHead] = index - 4;
803 indices[outerAATail++] = index - 3;
804 indices[outerAATail++] = index - 1;
805 } else {
806 smoothVertices[index++].set(xRight, yRight, transparent, dp, delta, m_gradient_is_vertical);
807 smoothVertices[index++].set(xLeft, yLeft, transparent, dp, -delta, m_gradient_is_vertical);
808 }
809 } else {
810 vertices[index++].set(xRight, yRight, fillColor, m_gradient_is_vertical);
811 vertices[index++].set(xLeft, yLeft, fillColor, m_gradient_is_vertical);
812 if (penWidth) {
813 vertices[index++].set(xRight, yRight, borderColor, m_gradient_is_vertical);
814 vertices[index++].set(xLeft, yLeft, borderColor, m_gradient_is_vertical);
815 vertices[index++].set(outerXRight, outerYRight, borderColor, m_gradient_is_vertical);
816 vertices[index++].set(outerXLeft, outerYLeft, borderColor, m_gradient_is_vertical);
817 }
818 }
819
820 innerXPrev = xLeft;
821 innerYLeftPrev = yLeft;
822 innerYRightPrev = yRight;
823
824 // Advance the point. This corresponds to a rotation of the respective segment
825 if (advanceLeft) {
826 iLeft++;
827 qreal tmp = cosSegmentAngleLeft;
828 cosSegmentAngleLeft = cosSegmentAngleLeft * cosStep[part][0] - sinSegmentAngleLeft * sinStep[part][0];
829 sinSegmentAngleLeft = sinSegmentAngleLeft * cosStep[part][0] + tmp * sinStep[part][0];
830 } else {
831 iRight++;
832 qreal tmp = cosSegmentAngleRight;
833 cosSegmentAngleRight = cosSegmentAngleRight * cosStep[part][1] - sinSegmentAngleRight * sinStep[part][1];
834 sinSegmentAngleRight = sinSegmentAngleRight * cosStep[part][1] + tmp * sinStep[part][1];
835 }
836 }
837 }
838
839 Q_ASSERT(index == vertexCount);
840
841 // Close the triangle strips.
842 if (m_antialiasing) {
843 indices[--innerAAHead] = indices[innerAATail - 1];
844 indices[--innerAAHead] = indices[innerAATail - 2];
845 Q_ASSERT(innerAATail <= indexCount);
846 }
847 if (penWidth) {
848 indices[--borderHead] = indices[borderTail - 1];
849 indices[--borderHead] = indices[borderTail - 2];
850 Q_ASSERT(borderTail <= indexCount);
851 }
852 if (m_antialiasing && penWidth) {
853 indices[--outerAAHead] = indices[outerAATail - 1];
854 indices[--outerAAHead] = indices[outerAATail - 2];
855 Q_ASSERT(outerAATail == indexCount);
856 }
857 } else {
858 // Straight corners.
859 QRectF innerRect = m_rect;
860 QRectF outerRect = m_rect;
861
862 if (penWidth)
863 innerRect.adjust(1.0f * penWidth, 1.0f * penWidth, -1.0f * penWidth, -1.0f * penWidth);
864
865 float delta = qMin(width, height) * 0.5f;
866 int innerVertexCount = 4 + gradientIntersections * 2;
867 int outerVertexCount = 4;
868 int vertexCount = innerVertexCount;
869 if (m_antialiasing || penWidth)
870 vertexCount += innerVertexCount;
871 if (penWidth)
872 vertexCount += outerVertexCount;
873 if (m_antialiasing && penWidth)
874 vertexCount += outerVertexCount;
875
876 int fillIndexCount = innerVertexCount;
877 int innerAAIndexCount = innerVertexCount * 2 + 2;
878 int borderIndexCount = innerVertexCount * 2 + 2;
879 int outerAAIndexCount = outerVertexCount * 2 + 2;
880 int indexCount = 0;
881 int fillHead = 0;
882 int innerAAHead = 0;
883 int innerAATail = 0;
884 int borderHead = 0;
885 int borderTail = 0;
886 int outerAAHead = 0;
887 int outerAATail = 0;
888 bool hasFill = m_color.alpha() > 0 || !stops.isEmpty();
889 if (hasFill)
890 indexCount += fillIndexCount;
891 if (m_antialiasing) {
892 innerAATail = innerAAHead = indexCount + (innerAAIndexCount >> 1) + 1;
893 indexCount += innerAAIndexCount;
894 }
895 if (penWidth) {
896 borderTail = borderHead = indexCount + (borderIndexCount >> 1) + 1;
897 indexCount += borderIndexCount;
898 }
899 if (m_antialiasing && penWidth) {
900 outerAATail = outerAAHead = indexCount + (outerAAIndexCount >> 1) + 1;
901 indexCount += outerAAIndexCount;
902 }
903
904 g->allocate(vertexCount, indexCount);
905 vertices = reinterpret_cast<Vertex *>(g->vertexData());
906 memset(vertices, 0, vertexCount * vertexStride);
907 quint16 *indices = g->indexDataAsUShort();
908 quint16 index = 0;
909
910 float innerStart = (m_gradient_is_vertical ? innerRect.top() : innerRect.left());
911 float innerEnd = (m_gradient_is_vertical ? innerRect.bottom() : innerRect.right());
912 float outerStart = (m_gradient_is_vertical ? outerRect.top() : outerRect.left());
913 float outerEnd = (m_gradient_is_vertical ? outerRect.bottom() : outerRect.right());
914
915 float innerSecondaryStart = (m_gradient_is_vertical ? innerRect.left() : innerRect.top());
916 float innerSecondaryEnd = (m_gradient_is_vertical ? innerRect.right() : innerRect.bottom());
917 float outerSecondaryStart = (m_gradient_is_vertical ? outerRect.left() : outerRect.top());
918 float outerSecondaryEnd = (m_gradient_is_vertical ? outerRect.right() : outerRect.bottom());
919
920 for (int part = -1; part <= 1; part += 2) {
921 float innerEdge = (part == 1 ? innerEnd : innerStart);
922 float outerEdge = (part == 1 ? outerEnd : outerStart);
923 gradientPos = (innerEdge - innerStart + penWidth) / gradientLength;
924
925 while (nextGradientStop <= lastGradientStop && stops.at(nextGradientStop).first <= gradientPos) {
926 // Insert vertices at gradient stops.
927 float gp = (innerStart - penWidth) + stops.at(nextGradientStop).first * gradientLength;
928
929 fillColor = colorToColor4ub(stops.at(nextGradientStop).second);
930
931 if (hasFill) {
932 indices[fillHead++] = index;
933 indices[fillHead++] = index + 1;
934 }
935
936 if (penWidth) {
937 --borderHead;
938 indices[borderHead] = indices[borderHead + 2];
939 indices[--borderHead] = index + 2;
940 indices[borderTail++] = index + 3;
941 indices[borderTail] = indices[borderTail - 2];
942 ++borderTail;
943 }
944
945 if (m_antialiasing) {
946 indices[--innerAAHead] = index + 2;
947 indices[--innerAAHead] = index;
948 indices[innerAATail++] = index + 1;
949 indices[innerAATail++] = index + 3;
950
951 bool lower = stops.at(nextGradientStop).first > 0.5f;
952 float dp = lower ? qMin(0.0f, gradientLength - gp - delta) : qMax(0.0f, delta - gp);
953 smoothVertices[index++].set(gp, innerSecondaryEnd, fillColor, dp, secondaryLength - innerSecondaryEnd - delta, m_gradient_is_vertical);
954 smoothVertices[index++].set(gp, innerSecondaryStart, fillColor, dp, delta - innerSecondaryStart, m_gradient_is_vertical);
955 if (penWidth) {
956 smoothVertices[index++].set(gp, innerSecondaryEnd, borderColor, (lower ? 0.49f : -0.49f) * penWidth, 0.49f * penWidth, m_gradient_is_vertical);
957 smoothVertices[index++].set(gp, innerSecondaryStart, borderColor, (lower ? 0.49f : -0.49f) * penWidth, -0.49f * penWidth, m_gradient_is_vertical);
958 } else {
959 smoothVertices[index++].set(gp, innerSecondaryEnd, transparent, lower ? delta : -delta, delta, m_gradient_is_vertical);
960 smoothVertices[index++].set(gp, innerSecondaryStart, transparent, lower ? delta : -delta, -delta, m_gradient_is_vertical);
961 }
962 } else {
963 vertices[index++].set(gp, innerSecondaryEnd, fillColor, m_gradient_is_vertical);
964 vertices[index++].set(gp, innerSecondaryStart, fillColor, m_gradient_is_vertical);
965 if (penWidth) {
966 vertices[index++].set(gp, innerSecondaryEnd, borderColor, m_gradient_is_vertical);
967 vertices[index++].set(gp, innerSecondaryStart, borderColor, m_gradient_is_vertical);
968 }
969 }
970 ++nextGradientStop;
971 }
972
973 if (!stops.isEmpty()) {
974 if (nextGradientStop == 0) {
975 fillColor = colorToColor4ub(stops.at(0).second);
976 } else if (nextGradientStop == stops.size()) {
977 fillColor = colorToColor4ub(stops.last().second);
978 } else {
979 const QGradientStop &prev = stops.at(nextGradientStop - 1);
980 const QGradientStop &next = stops.at(nextGradientStop);
981 float t = (gradientPos - prev.first) / (next.first - prev.first);
982 fillColor = colorToColor4ub(prev.second) * (1 - t) + colorToColor4ub(next.second) * t;
983 }
984 }
985
986 if (hasFill) {
987 indices[fillHead++] = index;
988 indices[fillHead++] = index + 1;
989 }
990
991 if (penWidth) {
992 indices[--borderHead] = index + 4;
993 indices[--borderHead] = index + 2;
994 indices[borderTail++] = index + 3;
995 indices[borderTail++] = index + 5;
996 }
997
998 if (m_antialiasing) {
999 indices[--innerAAHead] = index + 2;
1000 indices[--innerAAHead] = index;
1001 indices[innerAATail++] = index + 1;
1002 indices[innerAATail++] = index + 3;
1003
1004 float dp = part == 1 ? qMin(0.0f, gradientLength - innerEdge - delta) : qMax(0.0f, delta - innerEdge);
1005 smoothVertices[index++].set(innerEdge, innerSecondaryEnd, fillColor, dp, secondaryLength - innerSecondaryEnd - delta, m_gradient_is_vertical);
1006 smoothVertices[index++].set(innerEdge, innerSecondaryStart, fillColor, dp, delta - innerSecondaryStart, m_gradient_is_vertical);
1007
1008 if (penWidth) {
1009 smoothVertices[index++].set(innerEdge, innerSecondaryEnd, borderColor, 0.49f * penWidth * part, 0.49f * penWidth, m_gradient_is_vertical);
1010 smoothVertices[index++].set(innerEdge, innerSecondaryStart, borderColor, 0.49f * penWidth * part, -0.49f * penWidth, m_gradient_is_vertical);
1011 smoothVertices[index++].set(outerEdge, outerSecondaryEnd, borderColor, -0.49f * penWidth * part, -0.49f * penWidth, m_gradient_is_vertical);
1012 smoothVertices[index++].set(outerEdge, outerSecondaryStart, borderColor, -0.49f * penWidth * part, 0.49f * penWidth, m_gradient_is_vertical);
1013 smoothVertices[index++].set(outerEdge, outerSecondaryEnd, transparent, delta * part, delta, m_gradient_is_vertical);
1014 smoothVertices[index++].set(outerEdge, outerSecondaryStart, transparent, delta * part, -delta, m_gradient_is_vertical);
1015
1016 indices[--outerAAHead] = index - 2;
1017 indices[--outerAAHead] = index - 4;
1018 indices[outerAATail++] = index - 3;
1019 indices[outerAATail++] = index - 1;
1020 } else {
1021 smoothVertices[index++].set(innerEdge, innerSecondaryEnd, transparent, delta * part, delta, m_gradient_is_vertical);
1022 smoothVertices[index++].set(innerEdge, innerSecondaryStart, transparent, delta * part, -delta, m_gradient_is_vertical);
1023 }
1024 } else {
1025 vertices[index++].set(innerEdge, innerSecondaryEnd, fillColor, m_gradient_is_vertical);
1026 vertices[index++].set(innerEdge, innerSecondaryStart, fillColor, m_gradient_is_vertical);
1027 if (penWidth) {
1028 vertices[index++].set(innerEdge, innerSecondaryEnd, borderColor, m_gradient_is_vertical);
1029 vertices[index++].set(innerEdge, innerSecondaryStart, borderColor, m_gradient_is_vertical);
1030 vertices[index++].set(outerEdge, outerSecondaryEnd, borderColor, m_gradient_is_vertical);
1031 vertices[index++].set(outerEdge, outerSecondaryStart, borderColor, m_gradient_is_vertical);
1032 }
1033 }
1034 }
1035 Q_ASSERT(index == vertexCount);
1036
1037 // Close the triangle strips.
1038 if (m_antialiasing) {
1039 indices[--innerAAHead] = indices[innerAATail - 1];
1040 indices[--innerAAHead] = indices[innerAATail - 2];
1041 Q_ASSERT(innerAATail <= indexCount);
1042 }
1043 if (penWidth) {
1044 indices[--borderHead] = indices[borderTail - 1];
1045 indices[--borderHead] = indices[borderTail - 2];
1046 Q_ASSERT(borderTail <= indexCount);
1047 }
1048 if (m_antialiasing && penWidth) {
1049 indices[--outerAAHead] = indices[outerAATail - 1];
1050 indices[--outerAAHead] = indices[outerAATail - 2];
1051 Q_ASSERT(outerAATail == indexCount);
1052 }
1053 }
1054}
1055
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:397
const_pointer constData() const noexcept
Definition qlist.h:433
bool isEmpty() const noexcept
Definition qlist.h:401
T & first()
Definition qlist.h:645
T & last()
Definition qlist.h:648
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr qreal bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:500
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:732
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:729
constexpr qreal left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:497
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:805
constexpr qreal top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:498
constexpr qreal right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:499
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:764
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:624
void setFlag(Flag, bool=true)
Sets the flag f on this node if enabled is true; otherwise clears the flag.
Definition qsgnode.cpp:586
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:327
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 GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei width
GLuint color
[2]
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:641
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define gp
unsigned char uchar
Definition qtypes.h:32
unsigned short quint16
Definition qtypes.h:48
double qreal
Definition qtypes.h:187
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