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