Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsgsoftwareinternalrectanglenode.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// Qt-Security score:significant reason:default
4
6#include <qmath.h>
7
8#include <QtGui/QPainter>
9
11
12QSGSoftwareInternalRectangleNode::QSGSoftwareInternalRectangleNode()
13 : m_penWidth(0)
14 , m_radius(0)
15 , m_topLeftRadius(0)
16 , m_topRightRadius(0)
17 , m_bottomLeftRadius(0)
18 , m_bottomRightRadius(0)
19 , m_devicePixelRatio(1)
20 , m_vertical(true)
21 , m_cornerPixmapIsDirty(true)
22 , m_isTopLeftRadiusSet(false)
23 , m_isTopRightRadiusSet(false)
24 , m_isBottomLeftRadiusSet(false)
25 , m_isBottomRightRadiusSet(false)
26{
27 m_pen.setJoinStyle(Qt::MiterJoin);
28 m_pen.setMiterLimit(0);
29 setMaterial((QSGMaterial*)1);
30 setGeometry((QSGGeometry*)1);
31}
32
34{
35 QRect alignedRect = rect.toAlignedRect();
36 if (m_rect != alignedRect) {
37 m_rect = alignedRect;
38 markDirty(DirtyMaterial);
39 }
40}
41
43{
44 if (m_color != color) {
45 m_color = color;
46 m_cornerPixmapIsDirty = true;
47 markDirty(DirtyMaterial);
48 }
49}
50
52{
53 if (m_penColor != color) {
54 m_penColor = color;
55 m_cornerPixmapIsDirty = true;
56 markDirty(DirtyMaterial);
57 }
58}
59
61{
62 if (m_penWidth != width) {
63 m_penWidth = width;
64 m_cornerPixmapIsDirty = true;
65 markDirty(DirtyMaterial);
66 }
67}
68
69//Move first stop by pos relative to seconds
70static QGradientStop interpolateStop(const QGradientStop &firstStop, const QGradientStop &secondStop, double newPos)
71{
72 double distance = secondStop.first - firstStop.first;
73 double distanceDelta = newPos - firstStop.first;
74 double modifierValue = distanceDelta / distance;
75 const auto firstStopRgbColor = firstStop.second.toRgb();
76 const auto secondStopRgbColor = secondStop.second.toRgb();
77 int redDelta = (secondStopRgbColor.red() - firstStopRgbColor.red()) * modifierValue;
78 int greenDelta = (secondStopRgbColor.green() - firstStopRgbColor.green()) * modifierValue;
79 int blueDelta = (secondStopRgbColor.blue() - firstStopRgbColor.blue()) * modifierValue;
80 int alphaDelta = (secondStopRgbColor.alpha() - firstStopRgbColor.alpha()) * modifierValue;
81
82 QGradientStop newStop;
83 newStop.first = newPos;
84 newStop.second = QColor(firstStopRgbColor.red() + redDelta,
85 firstStopRgbColor.green() + greenDelta,
86 firstStopRgbColor.blue() + blueDelta,
87 firstStopRgbColor.alpha() + alphaDelta);
88
89 return newStop;
90}
91
92void QSGSoftwareInternalRectangleNode::setGradientStops(const QGradientStops &stops)
93{
94 //normalize stops
95 bool needsNormalization = false;
96 for (const QGradientStop &stop : std::as_const(stops)) {
97 if (stop.first < 0.0 || stop.first > 1.0) {
98 needsNormalization = true;
99 break;
100 }
101 }
102
103 if (needsNormalization) {
104 QGradientStops normalizedStops;
105 if (stops.size() == 1) {
106 //If there is only one stop, then the position does not matter
107 //It is just treated as a color
108 QGradientStop stop = stops.at(0);
109 stop.first = 0.0;
110 normalizedStops.append(stop);
111 } else {
112 //Clip stops to only the first below 0.0 and above 1.0
113 int below = -1;
114 int above = -1;
115 QList<int> between;
116 for (int i = 0; i < stops.size(); ++i) {
117 if (stops.at(i).first < 0.0) {
118 below = i;
119 } else if (stops.at(i).first > 1.0) {
120 above = i;
121 break;
122 } else {
123 between.append(i);
124 }
125 }
126
127 //Interpoloate new color values for above and below
128 if (below != -1 ) {
129 //If there are more than one stops left, interpolate
130 if (below + 1 < stops.size()) {
131 normalizedStops.append(interpolateStop(stops.at(below), stops.at(below + 1), 0.0));
132 } else {
133 QGradientStop singleStop;
134 singleStop.first = 0.0;
135 singleStop.second = stops.at(below).second;
136 normalizedStops.append(singleStop);
137 }
138 }
139
140 for (int i = 0; i < between.size(); ++i)
141 normalizedStops.append(stops.at(between.at(i)));
142
143 if (above != -1) {
144 //If there stops before above, interpolate
145 if (above >= 1) {
146 normalizedStops.append(interpolateStop(stops.at(above), stops.at(above - 1), 1.0));
147 } else {
148 QGradientStop singleStop;
149 singleStop.first = 1.0;
150 singleStop.second = stops.at(above).second;
151 normalizedStops.append(singleStop);
152 }
153 }
154 }
155
156 m_stops = normalizedStops;
157
158 } else {
159 m_stops = stops;
160 }
161 m_cornerPixmapIsDirty = true;
162 markDirty(DirtyMaterial);
163}
164
166{
167 if (m_vertical != vertical) {
168 m_vertical = vertical;
169 m_cornerPixmapIsDirty = true;
170 markDirty(DirtyMaterial);
171 }
172}
173
175{
176 if (m_radius == radius)
177 return;
178 m_radius = radius;
179 m_cornerPixmapIsDirty = true;
180 markDirty(DirtyMaterial);
181}
182
184{
185 if (m_isTopLeftRadiusSet && m_topLeftRadius == radius)
186 return;
187 m_isTopLeftRadiusSet = true;
188 m_topLeftRadius = radius;
189 m_cornerPixmapIsDirty = true;
190 markDirty(DirtyMaterial);
191}
192
194{
195 if (m_isTopRightRadiusSet && m_topRightRadius == radius)
196 return;
197 m_isTopRightRadiusSet = true;
198 m_topRightRadius = radius;
199 m_cornerPixmapIsDirty = true;
200 markDirty(DirtyMaterial);
201}
202
204{
205 if (m_isBottomLeftRadiusSet && m_bottomLeftRadius == radius)
206 return;
207 m_isBottomLeftRadiusSet = true;
208 m_bottomLeftRadius = radius;
209 m_cornerPixmapIsDirty = true;
210 markDirty(DirtyMaterial);
211}
212
214{
215 if (m_isBottomRightRadiusSet && m_bottomRightRadius == radius)
216 return;
217 m_isBottomRightRadiusSet = true;
218 m_bottomRightRadius = radius;
219 m_cornerPixmapIsDirty = true;
220 markDirty(DirtyMaterial);
221}
222
224{
225 if (!m_isTopLeftRadiusSet)
226 return;
227 m_isTopLeftRadiusSet = false;
228 m_cornerPixmapIsDirty = true;
229 markDirty(DirtyMaterial);
230}
231
233{
234 if (!m_isTopRightRadiusSet)
235 return;
236 m_isTopRightRadiusSet = false;
237 m_cornerPixmapIsDirty = true;
238 markDirty(DirtyMaterial);
239}
240
242{
243 if (!m_isBottomLeftRadiusSet)
244 return;
245 m_isBottomLeftRadiusSet = false;
246 m_cornerPixmapIsDirty = true;
247 markDirty(DirtyMaterial);
248}
249
251{
252 if (!m_isBottomRightRadiusSet)
253 return;
254 m_isBottomRightRadiusSet = false;
255 m_cornerPixmapIsDirty = true;
256 markDirty(DirtyMaterial);
257}
258
260{
261}
262
264{
265 if (!m_penWidth || m_penColor == Qt::transparent) {
266 m_pen = Qt::NoPen;
267 } else {
268 m_pen = QPen(m_penColor);
269 m_pen.setWidthF(m_penWidth);
270 }
271
272 if (!m_stops.isEmpty()) {
273 QLinearGradient gradient(QPoint(0,0), QPoint(m_vertical ? 0 : m_rect.width(), m_vertical ? m_rect.height() : 0));
274 gradient.setStops(m_stops);
275 m_brush = QBrush(gradient);
276 } else {
277 m_brush = QBrush(m_color);
278 }
279
280 if (m_cornerPixmapIsDirty) {
281 generateCornerPixmap();
282 m_cornerPixmapIsDirty = false;
283 }
284}
285
287{
288 //We can only check for a device pixel ratio change when we know what
289 //paint device is being used.
290 if (!qFuzzyCompare(painter->device()->devicePixelRatio(), m_devicePixelRatio)) {
291 m_devicePixelRatio = painter->device()->devicePixelRatio();
292 generateCornerPixmap();
293 }
294
295 if (painter->transform().isRotating()) {
296 //Rotated rectangles lose the benefits of direct rendering, and have poor rendering
297 //quality when using only blits and fills.
298
299 if (m_radius == 0
300 && m_penWidth == 0
301 && !m_isTopLeftRadiusSet
302 && !m_isTopRightRadiusSet
303 && !m_isBottomLeftRadiusSet
304 && !m_isBottomRightRadiusSet) {
305 //Non-Rounded Rects without borders (fall back to drawRect)
306 //Most common case
307 painter->setPen(Qt::NoPen);
308 painter->setBrush(m_brush);
309 painter->drawRect(m_rect);
310 } else if (!m_isTopLeftRadiusSet
311 && !m_isTopRightRadiusSet
312 && !m_isBottomLeftRadiusSet
313 && !m_isBottomRightRadiusSet) {
314 //Rounded Rects and Rects with Borders
315 //Avoids broken behaviors of QPainter::drawRect/roundedRect
316 QPixmap pixmap = QPixmap(qRound(m_rect.width() * m_devicePixelRatio), qRound(m_rect.height() * m_devicePixelRatio));
317 pixmap.fill(Qt::transparent);
318 pixmap.setDevicePixelRatio(m_devicePixelRatio);
319 QPainter pixmapPainter(&pixmap);
320 paintRectangle(&pixmapPainter, QRect(0, 0, m_rect.width(), m_rect.height()));
321
322 QPainter::RenderHints previousRenderHints = painter->renderHints();
323 painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
324 painter->drawPixmap(m_rect, pixmap);
325 painter->setRenderHints(previousRenderHints);
326 } else {
327 // Corners with different radii. Split implementation to avoid
328 // performance regression of the majority of cases
329 QPixmap pixmap = QPixmap(qRound(m_rect.width() * m_devicePixelRatio), qRound(m_rect.height() * m_devicePixelRatio));
330 pixmap.fill(Qt::transparent);
331 pixmap.setDevicePixelRatio(m_devicePixelRatio);
332 QPainter pixmapPainter(&pixmap);
333 // Slow function relying on paths
334 paintRectangleIndividualCorners(&pixmapPainter, QRect(0, 0, m_rect.width(), m_rect.height()));
335
336 QPainter::RenderHints previousRenderHints = painter->renderHints();
337 painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
338 painter->drawPixmap(m_rect, pixmap);
339 painter->setRenderHints(previousRenderHints);
340
341 }
342
343
344 } else {
345 //Paint directly
346 if (!m_isTopLeftRadiusSet
347 && !m_isTopRightRadiusSet
348 && !m_isBottomLeftRadiusSet
349 && !m_isBottomRightRadiusSet) {
350 paintRectangle(painter, m_rect);
351 } else {
352 paintRectangleIndividualCorners(painter, m_rect);
353 }
354 }
355}
356
358{
359 if (m_radius > 0.0f
360 || m_topLeftRadius > 0.0f
361 || m_topRightRadius > 0.0f
362 || m_bottomRightRadius > 0.0f
363 || m_bottomLeftRadius > 0.0f)
364 return false;
365 if (m_color.alpha() < 255)
366 return false;
367 if (m_penWidth > 0.0f && m_penColor.alpha() < 255)
368 return false;
369 if (m_stops.size() > 0) {
370 for (const QGradientStop &stop : std::as_const(m_stops)) {
371 if (stop.second.alpha() < 255)
372 return false;
373 }
374 }
375
376 return true;
377}
378
380{
381 //TODO: double check that this is correct.
382 return m_rect;
383}
384
385void QSGSoftwareInternalRectangleNode::paintRectangle(QPainter *painter, const QRect &rect)
386{
387 //Radius should never exceeds half of the width or half of the height
388 int radius = qFloor(qMin(qMin(rect.width(), rect.height()) * 0.5, m_radius));
389 QPainter::RenderHints previousRenderHints = painter->renderHints();
390 painter->setRenderHint(QPainter::Antialiasing, false);
391
392 if (m_penWidth > 0) {
393 //Fill border Rects
394
395 //Borders can not be more than half the height/width of a rect
396 double borderWidth = qMin(m_penWidth, rect.width() * 0.5);
397 double borderHeight = qMin(m_penWidth, rect.height() * 0.5);
398
399
400
401 if (borderWidth > radius) {
402 //4 Rects
403 QRectF borderTopOutside(QPointF(rect.x() + radius, rect.y()),
404 QPointF(rect.x() + rect.width() - radius, rect.y() + radius));
405 QRectF borderTopInside(QPointF(rect.x() + borderWidth, rect.y() + radius),
406 QPointF(rect.x() + rect.width() - borderWidth, rect.y() + borderHeight));
407 QRectF borderBottomOutside(QPointF(rect.x() + radius, rect.y() + rect.height() - radius),
408 QPointF(rect.x() + rect.width() - radius, rect.y() + rect.height()));
409 QRectF borderBottomInside(QPointF(rect.x() + borderWidth, rect.y() + rect.height() - borderHeight),
410 QPointF(rect.x() + rect.width() - borderWidth, rect.y() + rect.height() - radius));
411
412 if (borderTopOutside.isValid())
413 painter->fillRect(borderTopOutside, m_penColor);
414 if (borderTopInside.isValid())
415 painter->fillRect(borderTopInside, m_penColor);
416 if (borderBottomOutside.isValid())
417 painter->fillRect(borderBottomOutside, m_penColor);
418 if (borderBottomInside.isValid())
419 painter->fillRect(borderBottomInside, m_penColor);
420
421 } else {
422 //2 Rects
423 QRectF borderTop(QPointF(rect.x() + radius, rect.y()),
424 QPointF(rect.x() + rect.width() - radius, rect.y() + borderHeight));
425 QRectF borderBottom(QPointF(rect.x() + radius, rect.y() + rect.height() - borderHeight),
426 QPointF(rect.x() + rect.width() - radius, rect.y() + rect.height()));
427 if (borderTop.isValid())
428 painter->fillRect(borderTop, m_penColor);
429 if (borderBottom.isValid())
430 painter->fillRect(borderBottom, m_penColor);
431 }
432 QRectF borderLeft(QPointF(rect.x(), rect.y() + radius),
433 QPointF(rect.x() + borderWidth, rect.y() + rect.height() - radius));
434 QRectF borderRight(QPointF(rect.x() + rect.width() - borderWidth, rect.y() + radius),
435 QPointF(rect.x() + rect.width(), rect.y() + rect.height() - radius));
436 if (borderLeft.isValid())
437 painter->fillRect(borderLeft, m_penColor);
438 if (borderRight.isValid())
439 painter->fillRect(borderRight, m_penColor);
440 }
441
442
443 if (radius > 0) {
444
445 if (radius * 2 >= rect.width() && radius * 2 >= rect.height()) {
446 //Blit whole pixmap for circles
447 painter->drawPixmap(rect, m_cornerPixmap, m_cornerPixmap.rect());
448 } else {
449
450 //blit 4 corners to border
451 int scaledRadius = qRound(radius * m_devicePixelRatio);
452 QRectF topLeftCorner(QPointF(rect.x(), rect.y()),
453 QPointF(rect.x() + radius, rect.y() + radius));
454 painter->drawPixmap(topLeftCorner, m_cornerPixmap, QRectF(0, 0, scaledRadius, scaledRadius));
455 QRectF topRightCorner(QPointF(rect.x() + rect.width() - radius, rect.y()),
456 QPointF(rect.x() + rect.width(), rect.y() + radius));
457 painter->drawPixmap(topRightCorner, m_cornerPixmap, QRectF(scaledRadius, 0, scaledRadius, scaledRadius));
458 QRectF bottomLeftCorner(QPointF(rect.x(), rect.y() + rect.height() - radius),
459 QPointF(rect.x() + radius, rect.y() + rect.height()));
460 painter->drawPixmap(bottomLeftCorner, m_cornerPixmap, QRectF(0, scaledRadius, scaledRadius, scaledRadius));
461 QRectF bottomRightCorner(QPointF(rect.x() + rect.width() - radius, rect.y() + rect.height() - radius),
462 QPointF(rect.x() + rect.width(), rect.y() + rect.height()));
463 painter->drawPixmap(bottomRightCorner, m_cornerPixmap, QRectF(scaledRadius, scaledRadius, scaledRadius, scaledRadius));
464
465 }
466
467 }
468
469 QRectF brushRect = QRectF(rect).marginsRemoved(QMarginsF(m_penWidth, m_penWidth, m_penWidth, m_penWidth));
470 if (brushRect.width() < 0)
471 brushRect.setWidth(0);
472 if (brushRect.height() < 0)
473 brushRect.setHeight(0);
474 double innerRectRadius = qMax(0.0, radius - m_penWidth);
475
476 //If not completely transparent or has a gradient
477 if (m_color.alpha() > 0 || !m_stops.empty()) {
478 if (innerRectRadius > 0) {
479 //Rounded Rect
480 if (m_stops.empty()) {
481 //Rounded Rects without gradient need 3 blits
482 QRectF centerRect(QPointF(brushRect.x() + innerRectRadius, brushRect.y()),
483 QPointF(brushRect.x() + brushRect.width() - innerRectRadius, brushRect.y() + brushRect.height()));
484 painter->fillRect(centerRect, m_color);
485 QRectF leftRect(QPointF(brushRect.x(), brushRect.y() + innerRectRadius),
486 QPointF(brushRect.x() + innerRectRadius, brushRect.y() + brushRect.height() - innerRectRadius));
487 painter->fillRect(leftRect, m_color);
488 QRectF rightRect(QPointF(brushRect.x() + brushRect.width() - innerRectRadius, brushRect.y() + innerRectRadius),
489 QPointF(brushRect.x() + brushRect.width(), brushRect.y() + brushRect.height() - innerRectRadius));
490 painter->fillRect(rightRect, m_color);
491 } else {
492 //Rounded Rect with gradient (slow)
493 painter->setPen(Qt::NoPen);
494 painter->setBrush(m_brush);
495 painter->drawRoundedRect(brushRect, innerRectRadius, innerRectRadius);
496 }
497 } else {
498 //non-rounded rects only need 1 blit
499 painter->fillRect(brushRect, m_brush);
500 }
501 }
502
503 painter->setRenderHints(previousRenderHints);
504}
505
506void QSGSoftwareInternalRectangleNode::paintRectangleIndividualCorners(QPainter *painter, const QRect &rect)
507{
508 QPainterPath path;
509
510 const float w = m_penWidth;
511
512 // Radius should never exceeds half of the width or half of the height
513 const float radiusTL = qMin(qMin(rect.width(), rect.height()) * 0.5f,
514 m_isTopLeftRadiusSet ? m_topLeftRadius : m_radius);
515 const float radiusTR = qMin(qMin(rect.width(), rect.height()) * 0.5f,
516 m_isTopRightRadiusSet ? m_topRightRadius : m_radius);
517 const float radiusBL = qMin(qMin(rect.width(), rect.height()) * 0.5f,
518 m_isBottomLeftRadiusSet ? m_bottomLeftRadius : m_radius);
519 const float radiusBR = qMin(qMin(rect.width(), rect.height()) * 0.5f,
520 m_isBottomRightRadiusSet ? m_bottomRightRadius : m_radius);
521
522 const float innerRadiusTL = qMin(qMin(rect.width(), rect.height()) * 0.5f, radiusTL - w);
523 const float innerRadiusTR = qMin(qMin(rect.width(), rect.height()) * 0.5f, radiusTR - w);
524 const float innerRadiusBL = qMin(qMin(rect.width(), rect.height()) * 0.5f, radiusBL - w);
525 const float innerRadiusBR = qMin(qMin(rect.width(), rect.height()) * 0.5f, radiusBR - w);
526
527 QRect rect2 = rect.adjusted(0, 0, 1, 1);
528
529 path.moveTo(rect2.topRight() - QPointF(radiusTR, -w));
530 if (innerRadiusTR > 0.)
531 path.arcTo(QRectF(rect2.topRight() - QPointF(radiusTR + innerRadiusTR, -w), 2. * QSizeF(innerRadiusTR, innerRadiusTR)), 90, -90);
532 else
533 path.lineTo(rect2.topRight() - QPointF(w, -w));
534
535 if (innerRadiusBR > 0.)
536 path.arcTo(QRectF(rect2.bottomRight() - QPointF(radiusBR + innerRadiusBR, radiusBR + innerRadiusBR), 2. * QSizeF(innerRadiusBR, innerRadiusBR)), 0, -90);
537 else
538 path.lineTo(rect2.bottomRight() - QPointF(w, w));
539
540 if (innerRadiusBL > 0.)
541 path.arcTo(QRectF(rect2.bottomLeft() - QPointF(-w, radiusBL + innerRadiusBL), 2. * QSizeF(innerRadiusBL, innerRadiusBL)), -90, -90);
542 else
543 path.lineTo(rect2.bottomLeft() - QPointF(-w, w));
544 if (innerRadiusTL > 0.)
545 path.arcTo(QRectF(rect2.topLeft() + QPointF(w, w), 2. * QSizeF(innerRadiusTL, innerRadiusTL)), -180, -90);
546 else
547 path.lineTo(rect2.topLeft() + QPointF(w, w));
548 path.closeSubpath();
549
550 painter->setPen(Qt::NoPen);
551 painter->setBrush(m_brush);
552 painter->drawPath(path);
553
554 if (w > 0) {
555 path.moveTo(rect2.topRight() - QPointF(radiusTR, 0.));
556 if (radiusTR > 0.)
557 path.arcTo(QRectF(rect2.topRight() - 2. * QPointF(radiusTR, 0.), 2. * QSizeF(radiusTR, radiusTR)), 90, -90);
558 else
559 path.lineTo(rect2.topRight());
560 if (radiusBR > 0.)
561 path.arcTo(QRectF(rect2.bottomRight() - 2. * QPointF(radiusBR, radiusBR), 2. * QSizeF(radiusBR, radiusBR)), 0, -90);
562 else
563 path.lineTo(rect2.bottomRight());
564 if (radiusBL > 0.)
565 path.arcTo(QRectF(rect2.bottomLeft() - 2. * QPointF(0., radiusBL), 2. * QSizeF(radiusBL, radiusBL)), -90, -90);
566 else
567 path.lineTo(rect2.bottomLeft());
568 if (radiusTL > 0.)
569 path.arcTo(QRectF(rect2.topLeft() - 2. * QPointF(0., 0.), 2. * QSizeF(radiusTL, radiusTL)), -180, -90);
570 else
571 path.lineTo(rect2.topLeft());
572 path.closeSubpath();
573
574 painter->setBrush(m_penColor);
575 painter->drawPath(path);
576 }
577}
578
579void QSGSoftwareInternalRectangleNode::generateCornerPixmap()
580{
581 //Generate new corner Pixmap
582 int radius = qFloor(qMin(qMin(m_rect.width(), m_rect.height()) * 0.5, m_radius));
583 const auto width = qRound(radius * 2 * m_devicePixelRatio);
584
585 if (m_cornerPixmap.width() != width)
586 m_cornerPixmap = QPixmap(width, width);
587
588 m_cornerPixmap.setDevicePixelRatio(m_devicePixelRatio);
589 m_cornerPixmap.fill(Qt::transparent);
590
591 if (radius > 0) {
592 QPainter cornerPainter(&m_cornerPixmap);
593 cornerPainter.setRenderHint(QPainter::Antialiasing);
594 cornerPainter.setCompositionMode(QPainter::CompositionMode_Source);
595
596 //Paint outer cicle
597 if (m_penWidth > 0) {
598 cornerPainter.setPen(Qt::NoPen);
599 cornerPainter.setBrush(m_penColor);
600 cornerPainter.drawRoundedRect(QRectF(0, 0, radius * 2, radius *2), radius, radius);
601 }
602
603 //Paint inner circle
604 if (radius > m_penWidth) {
605 cornerPainter.setPen(Qt::NoPen);
606 if (m_stops.isEmpty())
607 cornerPainter.setBrush(m_brush);
608 else
609 cornerPainter.setBrush(Qt::transparent);
610
611 QMarginsF adjustmentMargins(m_penWidth, m_penWidth, m_penWidth, m_penWidth);
612 QRectF cornerCircleRect = QRectF(0, 0, radius * 2, radius * 2).marginsRemoved(adjustmentMargins);
613 cornerPainter.drawRoundedRect(cornerCircleRect, radius, radius);
614 }
615 cornerPainter.end();
616 }
617}
618
619QT_END_NAMESPACE
void setColor(const QColor &color) override
void setGradientStops(const QGradientStops &stops) override
void setPenColor(const QColor &color) override
Combined button and popup list for selecting options.
static QGradientStop interpolateStop(const QGradientStop &firstStop, const QGradientStop &secondStop, double newPos)