1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qdrawutil.h"
5#include "qbitmap.h"
6#include "qpixmapcache.h"
7#include "qpainter.h"
8#include "qpainterstateguard.h"
9#include "qpalette.h"
10#include "qstylehelper_p.h"
11#include <private/qpaintengineex_p.h>
12#include <qvarlengtharray.h>
13#include <qmath.h>
14#include <private/qhexstring_p.h>
15
16QT_BEGIN_NAMESPACE
17
18/*!
19 \headerfile <qdrawutil.h>
20 \inmodule QtWidgets
21 \title Drawing Utility Functions
22
23 \sa QPainter
24*/
25
26/*!
27 \fn void qDrawShadeLine(QPainter *painter, int x1, int y1, int x2, int y2,
28 const QPalette &palette, bool sunken,
29 int lineWidth, int midLineWidth)
30 \relates <qdrawutil.h>
31
32 Draws a horizontal (\a y1 == \a y2) or vertical (\a x1 == \a x2)
33 shaded line using the given \a painter. Note that nothing is
34 drawn if \a y1 != \a y2 and \a x1 != \a x2 (i.e. the line is
35 neither horizontal nor vertical).
36
37 The provided \a palette specifies the shading colors (\l
38 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
39 {QPalette::mid()}{middle} colors). The given \a lineWidth
40 specifies the line width for each of the lines; it is not the
41 total line width. The given \a midLineWidth specifies the width of
42 a middle line drawn in the QPalette::mid() color.
43
44 The line appears sunken if \a sunken is true, otherwise raised.
45
46 \warning This function does not look at QWidget::style() or
47 QApplication::style(). Use the drawing functions in QStyle to
48 make widgets that follow the current GUI style.
49
50
51 Alternatively you can use a QFrame widget and apply the
52 QFrame::setFrameStyle() function to display a shaded line:
53
54 \snippet code/src_gui_painting_qdrawutil.cpp 0
55
56 \sa qDrawShadeRect(), qDrawShadePanel(), QStyle
57*/
58
59void qDrawShadeLine(QPainter *p, int x1, int y1, int x2, int y2,
60 const QPalette &pal, bool sunken,
61 int lineWidth, int midLineWidth)
62{
63 if (Q_UNLIKELY(!p || lineWidth < 0 || midLineWidth < 0)) {
64 qWarning(msg: "qDrawShadeLine: Invalid parameters");
65 return;
66 }
67 QPainterStateGuard painterGuard(p);
68 const qreal devicePixelRatio = QStyleHelper::getDpr(painter: p);
69 if (!qFuzzyCompare(p1: devicePixelRatio, p2: qreal(1))) {
70 const qreal inverseScale = qreal(1) / devicePixelRatio;
71 p->scale(sx: inverseScale, sy: inverseScale);
72 x1 = qRound(d: devicePixelRatio * x1);
73 y1 = qRound(d: devicePixelRatio * y1);
74 x2 = qRound(d: devicePixelRatio * x2);
75 y2 = qRound(d: devicePixelRatio * y2);
76 lineWidth = qRound(d: devicePixelRatio * lineWidth);
77 midLineWidth = qRound(d: devicePixelRatio * midLineWidth);
78 p->translate(dx: 0.5, dy: 0.5);
79 }
80 int tlw = lineWidth*2 + midLineWidth; // total line width
81 if (sunken)
82 p->setPen(pal.color(cr: QPalette::Dark));
83 else
84 p->setPen(pal.light().color());
85 QPolygon a;
86 int i;
87 if (y1 == y2) { // horizontal line
88 int y = y1 - tlw/2;
89 if (x1 > x2) { // swap x1 and x2
90 int t = x1;
91 x1 = x2;
92 x2 = t;
93 }
94 x2--;
95 for (i=0; i<lineWidth; i++) { // draw top shadow
96 a.setPoints(nPoints: 3, firstx: x1+i, firsty: y+tlw-1-i,
97 x1+i, y+i,
98 x2-i, y+i);
99 p->drawPolyline(polyline: a);
100 }
101 if (midLineWidth > 0) {
102 p->setPen(pal.mid().color());
103 for (i=0; i<midLineWidth; i++) // draw lines in the middle
104 p->drawLine(x1: x1+lineWidth, y1: y+lineWidth+i,
105 x2: x2-lineWidth, y2: y+lineWidth+i);
106 }
107 if (sunken)
108 p->setPen(pal.light().color());
109 else
110 p->setPen(pal.dark().color());
111 for (i=0; i<lineWidth; i++) { // draw bottom shadow
112 a.setPoints(nPoints: 3, firstx: x1+i, firsty: y+tlw-i-1,
113 x2-i, y+tlw-i-1,
114 x2-i, y+i+1);
115 p->drawPolyline(polyline: a);
116 }
117 }
118 else if (x1 == x2) { // vertical line
119 int x = x1 - tlw/2;
120 if (y1 > y2) { // swap y1 and y2
121 int t = y1;
122 y1 = y2;
123 y2 = t;
124 }
125 y2--;
126 for (i=0; i<lineWidth; i++) { // draw left shadow
127 a.setPoints(nPoints: 3, firstx: x+i, firsty: y2,
128 x+i, y1+i,
129 x+tlw-1, y1+i);
130 p->drawPolyline(polyline: a);
131 }
132 if (midLineWidth > 0) {
133 p->setPen(pal.mid().color());
134 for (i=0; i<midLineWidth; i++) // draw lines in the middle
135 p->drawLine(x1: x+lineWidth+i, y1: y1+lineWidth, x2: x+lineWidth+i, y2);
136 }
137 if (sunken)
138 p->setPen(pal.light().color());
139 else
140 p->setPen(pal.dark().color());
141 for (i=0; i<lineWidth; i++) { // draw right shadow
142 a.setPoints(nPoints: 3, firstx: x+lineWidth, firsty: y2-i,
143 x+tlw-i-1, y2-i,
144 x+tlw-i-1, y1+lineWidth);
145 p->drawPolyline(polyline: a);
146 }
147 }
148}
149
150/*!
151 \fn void qDrawShadeRect(QPainter *painter, int x, int y, int width, int height,
152 const QPalette &palette, bool sunken,
153 int lineWidth, int midLineWidth,
154 const QBrush *fill)
155 \relates <qdrawutil.h>
156
157 Draws the shaded rectangle beginning at (\a x, \a y) with the
158 given \a width and \a height using the provided \a painter.
159
160 The provide \a palette specifies the shading colors (\l
161 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
162 {QPalette::mid()}{middle} colors. The given \a lineWidth
163 specifies the line width for each of the lines; it is not the
164 total line width. The \a midLineWidth specifies the width of a
165 middle line drawn in the QPalette::mid() color. The rectangle's
166 interior is filled with the \a fill brush unless \a fill is \nullptr.
167
168 The rectangle appears sunken if \a sunken is true, otherwise
169 raised.
170
171 \warning This function does not look at QWidget::style() or
172 QApplication::style(). Use the drawing functions in QStyle to make
173 widgets that follow the current GUI style.
174
175 Alternatively you can use a QFrame widget and apply the
176 QFrame::setFrameStyle() function to display a shaded rectangle:
177
178 \snippet code/src_gui_painting_qdrawutil.cpp 1
179
180 \sa qDrawShadeLine(), qDrawShadePanel(), qDrawPlainRect(), QStyle
181*/
182
183void qDrawShadeRect(QPainter *p, int x, int y, int w, int h,
184 const QPalette &pal, bool sunken,
185 int lineWidth, int midLineWidth,
186 const QBrush *fill)
187{
188 if (w == 0 || h == 0)
189 return;
190 if (Q_UNLIKELY(w < 0 || h < 0 || lineWidth < 0 || midLineWidth < 0)) {
191 qWarning(msg: "qDrawShadeRect: Invalid parameters");
192 return;
193 }
194
195 QPainterStateGuard painterGuard(p);
196 const qreal devicePixelRatio = QStyleHelper::getDpr(painter: p);
197 if (!qFuzzyCompare(p1: devicePixelRatio, p2: qreal(1))) {
198 const qreal inverseScale = qreal(1) / devicePixelRatio;
199 p->scale(sx: inverseScale, sy: inverseScale);
200 x = qRound(d: devicePixelRatio * x);
201 y = qRound(d: devicePixelRatio * y);
202 w = devicePixelRatio * w;
203 h = devicePixelRatio * h;
204 lineWidth = qRound(d: devicePixelRatio * lineWidth);
205 midLineWidth = qRound(d: devicePixelRatio * midLineWidth);
206 p->translate(dx: 0.5, dy: 0.5);
207 }
208 if (sunken)
209 p->setPen(pal.dark().color());
210 else
211 p->setPen(pal.light().color());
212 int x1=x, y1=y, x2=x+w-1, y2=y+h-1;
213
214 if (lineWidth == 1 && midLineWidth == 0) {// standard shade rectangle
215 p->drawRect(x: x1, y: y1, w: w-2, h: h-2);
216 if (sunken)
217 p->setPen(pal.light().color());
218 else
219 p->setPen(pal.dark().color());
220 QLineF lines[4] = { QLineF(x1+1, y1+1, x2-2, y1+1),
221 QLineF(x1+1, y1+2, x1+1, y2-2),
222 QLineF(x1, y2, x2, y2),
223 QLineF(x2,y1, x2,y2-1) };
224 p->drawLines(lines, lineCount: 4); // draw bottom/right lines
225 } else { // more complicated
226 int m = lineWidth+midLineWidth;
227 int i, j=0, k=m;
228 for (i=0; i<lineWidth; i++) { // draw top shadow
229 QLineF lines[4] = { QLineF(x1+i, y2-i, x1+i, y1+i),
230 QLineF(x1+i, y1+i, x2-i, y1+i),
231 QLineF(x1+k, y2-k, x2-k, y2-k),
232 QLineF(x2-k, y2-k, x2-k, y1+k) };
233 p->drawLines(lines, lineCount: 4);
234 k++;
235 }
236 p->setPen(pal.mid().color());
237 j = lineWidth*2;
238 for (i=0; i<midLineWidth; i++) { // draw lines in the middle
239 p->drawRect(x: x1+lineWidth+i, y: y1+lineWidth+i, w: w-j-1, h: h-j-1);
240 j += 2;
241 }
242 if (sunken)
243 p->setPen(pal.light().color());
244 else
245 p->setPen(pal.dark().color());
246 k = m;
247 for (i=0; i<lineWidth; i++) { // draw bottom shadow
248 QLineF lines[4] = { QLineF(x1+1+i, y2-i, x2-i, y2-i),
249 QLineF(x2-i, y2-i, x2-i, y1+i+1),
250 QLineF(x1+k, y2-k, x1+k, y1+k),
251 QLineF(x1+k, y1+k, x2-k, y1+k) };
252 p->drawLines(lines, lineCount: 4);
253 k++;
254 }
255 }
256 if (fill) {
257 int tlw = lineWidth + midLineWidth;
258 p->setPen(Qt::NoPen);
259 p->setBrush(*fill);
260 p->drawRect(x: x+tlw, y: y+tlw, w: w-2*tlw, h: h-2*tlw);
261 }
262}
263
264/*!
265 \fn void qDrawShadePanel(QPainter *painter, int x, int y, int width, int height,
266 const QPalette &palette, bool sunken,
267 int lineWidth, const QBrush *fill)
268 \relates <qdrawutil.h>
269
270 Draws the shaded panel beginning at (\a x, \a y) with the given \a
271 width and \a height using the provided \a painter and the given \a
272 lineWidth.
273
274 The given \a palette specifies the shading colors (\l
275 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
276 {QPalette::mid()}{middle} colors). The panel's interior is filled
277 with the \a fill brush unless \a fill is \nullptr.
278
279 The panel appears sunken if \a sunken is true, otherwise raised.
280
281 \warning This function does not look at QWidget::style() or
282 QApplication::style(). Use the drawing functions in QStyle to make
283 widgets that follow the current GUI style.
284
285 Alternatively you can use a QFrame widget and apply the
286 QFrame::setFrameStyle() function to display a shaded panel:
287
288 \snippet code/src_gui_painting_qdrawutil.cpp 2
289
290 \sa qDrawWinPanel(), qDrawShadeLine(), qDrawShadeRect(), QStyle
291*/
292
293void qDrawShadePanel(QPainter *p, int x, int y, int w, int h,
294 const QPalette &pal, bool sunken,
295 int lineWidth, const QBrush *fill)
296{
297 if (w == 0 || h == 0)
298 return;
299 if (Q_UNLIKELY(w < 0 || h < 0 || lineWidth < 0)) {
300 qWarning(msg: "qDrawShadePanel: Invalid parameters");
301 }
302
303 QPainterStateGuard painterGuard(p);
304 const qreal devicePixelRatio = QStyleHelper::getDpr(painter: p);
305 bool isTranslated = false;
306 if (!qFuzzyCompare(p1: devicePixelRatio, p2: qreal(1))) {
307 const qreal inverseScale = qreal(1) / devicePixelRatio;
308 p->scale(sx: inverseScale, sy: inverseScale);
309 x = qRound(d: devicePixelRatio * x);
310 y = qRound(d: devicePixelRatio * y);
311 w = devicePixelRatio * w;
312 h = devicePixelRatio * h;
313 lineWidth = qRound(d: devicePixelRatio * lineWidth);
314 p->translate(dx: 0.5, dy: 0.5);
315 isTranslated = true;
316 }
317
318 QColor shade = pal.dark().color();
319 QColor light = pal.light().color();
320 if (fill) {
321 if (fill->color() == shade)
322 shade = pal.shadow().color();
323 if (fill->color() == light)
324 light = pal.midlight().color();
325 }
326 QList<QLineF> lines;
327 lines.reserve(asize: 2*lineWidth);
328
329 if (sunken)
330 p->setPen(shade);
331 else
332 p->setPen(light);
333 int x1, y1, x2, y2;
334 int i;
335 x1 = x;
336 y1 = y2 = y;
337 x2 = x+w-2;
338 for (i=0; i<lineWidth; i++) { // top shadow
339 lines << QLineF(x1, y1++, x2--, y2++);
340 }
341 x2 = x1;
342 y1 = y+h-2;
343 for (i=0; i<lineWidth; i++) { // left shado
344 lines << QLineF(x1++, y1, x2++, y2--);
345 }
346 p->drawLines(lines);
347 lines.clear();
348 if (sunken)
349 p->setPen(light);
350 else
351 p->setPen(shade);
352 x1 = x;
353 y1 = y2 = y+h-1;
354 x2 = x+w-1;
355 for (i=0; i<lineWidth; i++) { // bottom shadow
356 lines << QLineF(x1++, y1--, x2, y2--);
357 }
358 x1 = x2;
359 y1 = y;
360 y2 = y+h-lineWidth-1;
361 for (i=0; i<lineWidth; i++) { // right shadow
362 lines << QLineF(x1--, y1++, x2--, y2);
363 }
364 p->drawLines(lines);
365 if (fill) { // fill with fill color
366 if (isTranslated)
367 p->translate(dx: -0.5, dy: -0.5);
368 p->fillRect(x: x+lineWidth, y: y+lineWidth, w: w-lineWidth*2, h: h-lineWidth*2, b: *fill);
369 }
370}
371
372/*!
373 \internal
374 This function draws a rectangle with two pixel line width.
375 It is called from qDrawWinButton() and qDrawWinPanel().
376
377 c1..c4 and fill are used:
378
379 1 1 1 1 1 2
380 1 3 3 3 4 2
381 1 3 F F 4 2
382 1 3 F F 4 2
383 1 4 4 4 4 2
384 2 2 2 2 2 2
385*/
386
387static void qDrawWinShades(QPainter *p,
388 int x, int y, int w, int h,
389 const QColor &c1, const QColor &c2,
390 const QColor &c3, const QColor &c4,
391 const QBrush *fill)
392{
393 if (w < 2 || h < 2) // can't do anything with that
394 return;
395
396 QPainterStateGuard painterGuard(p);
397 const qreal devicePixelRatio = QStyleHelper::getDpr(painter: p);
398 bool isTranslated = false;
399 if (!qFuzzyCompare(p1: devicePixelRatio, p2: qreal(1))) {
400 const qreal inverseScale = qreal(1) / devicePixelRatio;
401 p->scale(sx: inverseScale, sy: inverseScale);
402 x = qRound(d: devicePixelRatio * x);
403 y = qRound(d: devicePixelRatio * y);
404 w = devicePixelRatio * w;
405 h = devicePixelRatio * h;
406 p->translate(dx: 0.5, dy: 0.5);
407 isTranslated = true;
408 }
409
410 QPoint a[3] = { QPoint(x, y+h-2), QPoint(x, y), QPoint(x+w-2, y) };
411 p->setPen(c1);
412 p->drawPolyline(points: a, pointCount: 3);
413 QPoint b[3] = { QPoint(x, y+h-1), QPoint(x+w-1, y+h-1), QPoint(x+w-1, y) };
414 p->setPen(c2);
415 p->drawPolyline(points: b, pointCount: 3);
416 if (w > 4 && h > 4) {
417 QPoint c[3] = { QPoint(x+1, y+h-3), QPoint(x+1, y+1), QPoint(x+w-3, y+1) };
418 p->setPen(c3);
419 p->drawPolyline(points: c, pointCount: 3);
420 QPoint d[3] = { QPoint(x+1, y+h-2), QPoint(x+w-2, y+h-2), QPoint(x+w-2, y+1) };
421 p->setPen(c4);
422 p->drawPolyline(points: d, pointCount: 3);
423 if (fill) {
424 if (isTranslated)
425 p->translate(dx: -0.5, dy: -0.5);
426 p->fillRect(QRect(x+2, y+2, w-4, h-4), *fill);
427 }
428 }
429}
430
431
432/*!
433 \fn void qDrawWinButton(QPainter *painter, int x, int y, int width, int height,
434 const QPalette &palette, bool sunken,
435 const QBrush *fill)
436 \relates <qdrawutil.h>
437
438 Draws the Windows-style button specified by the given point (\a x,
439 \a y}, \a width and \a height using the provided \a painter with a
440 line width of 2 pixels. The button's interior is filled with the
441 \a{fill} brush unless \a fill is \nullptr.
442
443 The given \a palette specifies the shading colors (\l
444 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
445 {QPalette::mid()}{middle} colors).
446
447 The button appears sunken if \a sunken is true, otherwise raised.
448
449 \warning This function does not look at QWidget::style() or
450 QApplication::style()-> Use the drawing functions in QStyle to make
451 widgets that follow the current GUI style.
452
453 \sa qDrawWinPanel(), QStyle
454*/
455
456void qDrawWinButton(QPainter *p, int x, int y, int w, int h,
457 const QPalette &pal, bool sunken,
458 const QBrush *fill)
459{
460 if (sunken)
461 qDrawWinShades(p, x, y, w, h,
462 c1: pal.shadow().color(), c2: pal.light().color(), c3: pal.dark().color(),
463 c4: pal.button().color(), fill);
464 else
465 qDrawWinShades(p, x, y, w, h,
466 c1: pal.light().color(), c2: pal.shadow().color(), c3: pal.button().color(),
467 c4: pal.dark().color(), fill);
468}
469
470/*!
471 \fn void qDrawWinPanel(QPainter *painter, int x, int y, int width, int height,
472 const QPalette &palette, bool sunken,
473 const QBrush *fill)
474 \relates <qdrawutil.h>
475
476 Draws the Windows-style panel specified by the given point(\a x,
477 \a y), \a width and \a height using the provided \a painter with a
478 line width of 2 pixels. The button's interior is filled with the
479 \a fill brush unless \a fill is \nullptr.
480
481 The given \a palette specifies the shading colors. The panel
482 appears sunken if \a sunken is true, otherwise raised.
483
484 \warning This function does not look at QWidget::style() or
485 QApplication::style(). Use the drawing functions in QStyle to make
486 widgets that follow the current GUI style.
487
488 Alternatively you can use a QFrame widget and apply the
489 QFrame::setFrameStyle() function to display a shaded panel:
490
491 \snippet code/src_gui_painting_qdrawutil.cpp 3
492
493 \sa qDrawShadePanel(), qDrawWinButton(), QStyle
494*/
495
496void qDrawWinPanel(QPainter *p, int x, int y, int w, int h,
497 const QPalette &pal, bool sunken,
498 const QBrush *fill)
499{
500 if (sunken)
501 qDrawWinShades(p, x, y, w, h,
502 c1: pal.dark().color(), c2: pal.light().color(), c3: pal.shadow().color(),
503 c4: pal.midlight().color(), fill);
504 else
505 qDrawWinShades(p, x, y, w, h,
506 c1: pal.light().color(), c2: pal.shadow().color(), c3: pal.midlight().color(),
507 c4: pal.dark().color(), fill);
508}
509
510/*!
511 \fn void qDrawPlainRect(QPainter *painter, int x, int y, int width, int height, const QColor &lineColor,
512 int lineWidth, const QBrush *fill)
513 \relates <qdrawutil.h>
514
515 Draws the plain rectangle beginning at (\a x, \a y) with the given
516 \a width and \a height, using the specified \a painter, \a lineColor
517 and \a lineWidth. The rectangle's interior is filled with the \a
518 fill brush unless \a fill is \nullptr.
519
520 \warning This function does not look at QWidget::style() or
521 QApplication::style(). Use the drawing functions in QStyle to make
522 widgets that follow the current GUI style.
523
524 Alternatively you can use a QFrame widget and apply the
525 QFrame::setFrameStyle() function to display a plain rectangle:
526
527 \snippet code/src_gui_painting_qdrawutil.cpp 4
528
529 \sa qDrawShadeRect(), QStyle
530*/
531
532void qDrawPlainRect(QPainter *p, int x, int y, int w, int h, const QColor &c,
533 int lineWidth, const QBrush *fill)
534{
535 if (w == 0 || h == 0)
536 return;
537 if (Q_UNLIKELY(w < 0 || h < 0 || lineWidth < 0)) {
538 qWarning(msg: "qDrawPlainRect: Invalid parameters");
539 return;
540 }
541
542 QPainterStateGuard painterGuard(p);
543 if (lineWidth == 0 && !fill)
544 return;
545 if (lineWidth > 0)
546 p->setPen(QPen(c, lineWidth, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin));
547 p->setBrush(fill ? *fill : Qt::NoBrush);
548 const QRectF r(x, y, w, h);
549 const auto lw2 = lineWidth / 2.;
550 const QRectF rect = r.marginsRemoved(margins: QMarginsF(lw2, lw2, lw2, lw2));
551 p->drawRect(rect);
552}
553
554/*!
555 \fn void qDrawPlainRoundedRect(QPainter *painter, int x, int y,
556 int width, int height, qreal rx, qreal ry,
557 const QColor &lineColor, int lineWidth,
558 const QBrush *fill)
559 \since 6.7
560 \relates <qdrawutil.h>
561
562 Draws the plain rounded rectangle beginning at (\a x, \a y)
563 with the given \a width and \a height,
564 using the horizontal \a rx and vertical radius \a ry,
565 specified \a painter, \a lineColor and \a lineWidth.
566 The rectangle's interior is filled with the \a
567 fill brush unless \a fill is \nullptr.
568
569 \warning This function does not look at QWidget::style() or
570 QApplication::style(). Use the drawing functions in QStyle to make
571 widgets that follow the current GUI style.
572
573 Alternatively you can use a QFrame widget and apply the
574 QFrame::setFrameStyle() function to display a plain rectangle:
575
576 \snippet code/src_gui_painting_qdrawutil.cpp 4
577
578 \sa qDrawShadeRect(), QStyle
579*/
580
581// ### Qt7: Pass QPen instead of QColor for frame drawing
582void qDrawPlainRoundedRect(QPainter *p, int x, int y, int w, int h,
583 qreal rx, qreal ry, const QColor &c,
584 int lineWidth, const QBrush *fill)
585{
586 if (w == 0 || h == 0)
587 return;
588 if (Q_UNLIKELY(w < 0 || h < 0 || lineWidth < 0)) {
589 qWarning(msg: "qDrawPlainRect: Invalid parameters");
590 return;
591 }
592
593 QPainterStateGuard painterGuard(p);
594 if (lineWidth == 0 && !fill)
595 return;
596 if (lineWidth > 0)
597 p->setPen(QPen(c, lineWidth));
598 p->setBrush(fill ? *fill : Qt::NoBrush);
599 const QRectF r(x, y, w, h);
600 const auto lw2 = lineWidth / 2.;
601 const QRectF rect = r.marginsRemoved(margins: QMarginsF(lw2, lw2, lw2, lw2));
602 p->drawRoundedRect(rect, xRadius: rx, yRadius: ry);
603}
604
605/*****************************************************************************
606 Overloaded functions.
607 *****************************************************************************/
608
609/*!
610 \fn void qDrawShadeLine(QPainter *painter, const QPoint &p1, const QPoint &p2,
611 const QPalette &palette, bool sunken, int lineWidth, int midLineWidth)
612 \relates <qdrawutil.h>
613 \overload
614
615 Draws a horizontal or vertical shaded line between \a p1 and \a p2
616 using the given \a painter. Note that nothing is drawn if the line
617 between the points would be neither horizontal nor vertical.
618
619 The provided \a palette specifies the shading colors (\l
620 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
621 {QPalette::mid()}{middle} colors). The given \a lineWidth
622 specifies the line width for each of the lines; it is not the
623 total line width. The given \a midLineWidth specifies the width of
624 a middle line drawn in the QPalette::mid() color.
625
626 The line appears sunken if \a sunken is true, otherwise raised.
627
628 \warning This function does not look at QWidget::style() or
629 QApplication::style(). Use the drawing functions in QStyle to
630 make widgets that follow the current GUI style.
631
632
633 Alternatively you can use a QFrame widget and apply the
634 QFrame::setFrameStyle() function to display a shaded line:
635
636 \snippet code/src_gui_painting_qdrawutil.cpp 5
637
638 \sa qDrawShadeRect(), qDrawShadePanel(), QStyle
639*/
640
641void qDrawShadeLine(QPainter *p, const QPoint &p1, const QPoint &p2,
642 const QPalette &pal, bool sunken,
643 int lineWidth, int midLineWidth)
644{
645 qDrawShadeLine(p, x1: p1.x(), y1: p1.y(), x2: p2.x(), y2: p2.y(), pal, sunken,
646 lineWidth, midLineWidth);
647}
648
649/*!
650 \fn void qDrawShadeRect(QPainter *painter, const QRect &rect, const QPalette &palette,
651 bool sunken, int lineWidth, int midLineWidth, const QBrush *fill)
652 \relates <qdrawutil.h>
653 \overload
654
655 Draws the shaded rectangle specified by \a rect using the given \a painter.
656
657 The provide \a palette specifies the shading colors (\l
658 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
659 {QPalette::mid()}{middle} colors. The given \a lineWidth
660 specifies the line width for each of the lines; it is not the
661 total line width. The \a midLineWidth specifies the width of a
662 middle line drawn in the QPalette::mid() color. The rectangle's
663 interior is filled with the \a fill brush unless \a fill is \nullptr.
664
665 The rectangle appears sunken if \a sunken is true, otherwise
666 raised.
667
668 \warning This function does not look at QWidget::style() or
669 QApplication::style(). Use the drawing functions in QStyle to make
670 widgets that follow the current GUI style.
671
672 Alternatively you can use a QFrame widget and apply the
673 QFrame::setFrameStyle() function to display a shaded rectangle:
674
675 \snippet code/src_gui_painting_qdrawutil.cpp 6
676
677 \sa qDrawShadeLine(), qDrawShadePanel(), qDrawPlainRect(), QStyle
678*/
679
680void qDrawShadeRect(QPainter *p, const QRect &r,
681 const QPalette &pal, bool sunken,
682 int lineWidth, int midLineWidth,
683 const QBrush *fill)
684{
685 qDrawShadeRect(p, x: r.x(), y: r.y(), w: r.width(), h: r.height(), pal, sunken,
686 lineWidth, midLineWidth, fill);
687}
688
689/*!
690 \fn void qDrawShadePanel(QPainter *painter, const QRect &rect, const QPalette &palette,
691 bool sunken, int lineWidth, const QBrush *fill)
692 \relates <qdrawutil.h>
693 \overload
694
695 Draws the shaded panel at the rectangle specified by \a rect using the
696 given \a painter and the given \a lineWidth.
697
698 The given \a palette specifies the shading colors (\l
699 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
700 {QPalette::mid()}{middle} colors). The panel's interior is filled
701 with the \a fill brush unless \a fill is \nullptr.
702
703 The panel appears sunken if \a sunken is true, otherwise raised.
704
705 \warning This function does not look at QWidget::style() or
706 QApplication::style(). Use the drawing functions in QStyle to make
707 widgets that follow the current GUI style.
708
709 Alternatively you can use a QFrame widget and apply the
710 QFrame::setFrameStyle() function to display a shaded panel:
711
712 \snippet code/src_gui_painting_qdrawutil.cpp 7
713
714 \sa qDrawWinPanel(), qDrawShadeLine(), qDrawShadeRect(), QStyle
715*/
716
717void qDrawShadePanel(QPainter *p, const QRect &r,
718 const QPalette &pal, bool sunken,
719 int lineWidth, const QBrush *fill)
720{
721 qDrawShadePanel(p, x: r.x(), y: r.y(), w: r.width(), h: r.height(), pal, sunken,
722 lineWidth, fill);
723}
724
725/*!
726 \fn void qDrawWinButton(QPainter *painter, const QRect &rect, const QPalette &palette,
727 bool sunken, const QBrush *fill)
728 \relates <qdrawutil.h>
729 \overload
730
731 Draws the Windows-style button at the rectangle specified by \a rect using
732 the given \a painter with a line width of 2 pixels. The button's interior
733 is filled with the \a{fill} brush unless \a fill is \nullptr.
734
735 The given \a palette specifies the shading colors (\l
736 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
737 {QPalette::mid()}{middle} colors).
738
739 The button appears sunken if \a sunken is true, otherwise raised.
740
741 \warning This function does not look at QWidget::style() or
742 QApplication::style()-> Use the drawing functions in QStyle to make
743 widgets that follow the current GUI style.
744
745 \sa qDrawWinPanel(), QStyle
746*/
747
748void qDrawWinButton(QPainter *p, const QRect &r,
749 const QPalette &pal, bool sunken, const QBrush *fill)
750{
751 qDrawWinButton(p, x: r.x(), y: r.y(), w: r.width(), h: r.height(), pal, sunken, fill);
752}
753
754/*!
755 \fn void qDrawWinPanel(QPainter *painter, const QRect &rect, const QPalette &palette,
756 bool sunken, const QBrush *fill)
757 \relates <qdrawutil.h>
758 \overload
759
760 Draws the Windows-style panel at the rectangle specified by \a rect using
761 the given \a painter with a line width of 2 pixels. The button's interior
762 is filled with the \a fill brush unless \a fill is \nullptr.
763
764 The given \a palette specifies the shading colors. The panel
765 appears sunken if \a sunken is true, otherwise raised.
766
767 \warning This function does not look at QWidget::style() or
768 QApplication::style(). Use the drawing functions in QStyle to make
769 widgets that follow the current GUI style.
770
771 Alternatively you can use a QFrame widget and apply the
772 QFrame::setFrameStyle() function to display a shaded panel:
773
774 \snippet code/src_gui_painting_qdrawutil.cpp 8
775
776 \sa qDrawShadePanel(), qDrawWinButton(), QStyle
777*/
778
779void qDrawWinPanel(QPainter *p, const QRect &r,
780 const QPalette &pal, bool sunken, const QBrush *fill)
781{
782 qDrawWinPanel(p, x: r.x(), y: r.y(), w: r.width(), h: r.height(), pal, sunken, fill);
783}
784
785/*!
786 \fn void qDrawPlainRect(QPainter *painter, const QRect &rect, const QColor &lineColor, int lineWidth, const QBrush *fill)
787 \relates <qdrawutil.h>
788 \overload
789
790 Draws the plain rectangle specified by \a rect using the given \a painter,
791 \a lineColor and \a lineWidth. The rectangle's interior is filled with the
792 \a fill brush unless \a fill is \nullptr.
793
794 \warning This function does not look at QWidget::style() or
795 QApplication::style(). Use the drawing functions in QStyle to make
796 widgets that follow the current GUI style.
797
798 Alternatively you can use a QFrame widget and apply the
799 QFrame::setFrameStyle() function to display a plain rectangle:
800
801 \snippet code/src_gui_painting_qdrawutil.cpp 9
802
803 \sa qDrawShadeRect(), QStyle
804*/
805
806void qDrawPlainRect(QPainter *p, const QRect &r, const QColor &c,
807 int lineWidth, const QBrush *fill)
808{
809 qDrawPlainRect(p, x: r.x(), y: r.y(), w: r.width(), h: r.height(), c,
810 lineWidth, fill);
811}
812
813/*!
814 \fn void qDrawPlainRoundedRect(QPainter *painter, const QRect &rect,
815 qreal rx, qreal ry,
816 const QColor &lineColor, int lineWidth,
817 const QBrush *fill)
818 \since 6.7
819 \relates <qdrawutil.h>
820 \overload
821
822 Draws the plain rectangle specified by \a rect using
823 the horizontal \a rx and vertical radius \a ry,
824 the given \a painter, \a lineColor and \a lineWidth.
825 The rectangle's interior is filled with the
826 \a fill brush unless \a fill is \nullptr.
827
828 \warning This function does not look at QWidget::style() or
829 QApplication::style(). Use the drawing functions in QStyle to make
830 widgets that follow the current GUI style.
831
832 Alternatively you can use a QFrame widget and apply the
833 QFrame::setFrameStyle() function to display a plain rectangle:
834
835 \snippet code/src_gui_painting_qdrawutil.cpp 9
836
837 \sa qDrawShadeRect(), QStyle
838*/
839
840/*!
841 \class QTileRules
842 \since 4.6
843
844 \inmodule QtWidgets
845
846 \brief The QTileRules class provides the rules used to draw a
847 pixmap or image split into nine segments.
848
849 Spliiting is similar to \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}.
850
851 \sa Qt::TileRule, QMargins
852*/
853
854/*! \fn QTileRules::QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule)
855 Constructs a QTileRules with the given \a horizontalRule and
856 \a verticalRule.
857 */
858
859/*! \fn QTileRules::QTileRules(Qt::TileRule rule)
860 Constructs a QTileRules with the given \a rule used for both
861 the horizontal rule and the vertical rule.
862 */
863
864/*!
865 \fn void qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap)
866 \relates <qdrawutil.h>
867 \since 4.6
868
869 \brief The qDrawBorderPixmap function is for drawing a pixmap into
870 the margins of a rectangle.
871
872 Draws the given \a pixmap into the given \a target rectangle, using the
873 given \a painter. The pixmap will be split into nine segments and drawn
874 according to the \a margins structure.
875*/
876
877typedef QVarLengthArray<QPainter::PixmapFragment, 16> QPixmapFragmentsArray;
878
879/*!
880 \relates <qdrawutil.h>
881 \since 4.6
882
883 Draws the indicated \a sourceRect rectangle from the given \a pixmap into
884 the given \a targetRect rectangle, using the given \a painter. The pixmap
885 will be split into nine segments according to the given \a targetMargins
886 and \a sourceMargins structures. Finally, the pixmap will be drawn
887 according to the given \a rules.
888
889 This function is used to draw a scaled pixmap, similar to
890 \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}
891
892 \sa Qt::TileRule, QTileRules, QMargins
893*/
894
895void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins,
896 const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins,
897 const QTileRules &rules
898#ifndef Q_QDOC
899 , QDrawBorderPixmap::DrawingHints hints
900#endif
901 )
902{
903 QPainter::PixmapFragment d;
904 d.opacity = 1.0;
905 d.rotation = 0.0;
906
907 QPixmapFragmentsArray opaqueData;
908 QPixmapFragmentsArray translucentData;
909
910 // source center
911 const int sourceCenterTop = sourceRect.top() + sourceMargins.top();
912 const int sourceCenterLeft = sourceRect.left() + sourceMargins.left();
913 const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1;
914 const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1;
915 const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft;
916 const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop;
917 // target center
918 const int targetCenterTop = targetRect.top() + targetMargins.top();
919 const int targetCenterLeft = targetRect.left() + targetMargins.left();
920 const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1;
921 const int targetCenterRight = targetRect.right() - targetMargins.right() + 1;
922 const int targetCenterWidth = targetCenterRight - targetCenterLeft;
923 const int targetCenterHeight = targetCenterBottom - targetCenterTop;
924
925 QVarLengthArray<qreal, 16> xTarget; // x-coordinates of target rectangles
926 QVarLengthArray<qreal, 16> yTarget; // y-coordinates of target rectangles
927
928 int columns = 3;
929 int rows = 3;
930 if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0)
931 columns = qMax(a: 3, b: 2 + qCeil(v: targetCenterWidth / qreal(sourceCenterWidth)));
932 if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0)
933 rows = qMax(a: 3, b: 2 + qCeil(v: targetCenterHeight / qreal(sourceCenterHeight)));
934
935 xTarget.resize(sz: columns + 1);
936 yTarget.resize(sz: rows + 1);
937
938 bool oldAA = painter->testRenderHint(hint: QPainter::Antialiasing);
939 if (painter->paintEngine()->type() != QPaintEngine::OpenGL
940 && painter->paintEngine()->type() != QPaintEngine::OpenGL2
941 && oldAA && painter->combinedTransform().type() != QTransform::TxNone) {
942 painter->setRenderHint(hint: QPainter::Antialiasing, on: false);
943 }
944
945 xTarget[0] = targetRect.left();
946 xTarget[1] = targetCenterLeft;
947 xTarget[columns - 1] = targetCenterRight;
948 xTarget[columns] = targetRect.left() + targetRect.width();
949
950 yTarget[0] = targetRect.top();
951 yTarget[1] = targetCenterTop;
952 yTarget[rows - 1] = targetCenterBottom;
953 yTarget[rows] = targetRect.top() + targetRect.height();
954
955 qreal dx = targetCenterWidth;
956 qreal dy = targetCenterHeight;
957
958 switch (rules.horizontal) {
959 case Qt::StretchTile:
960 dx = targetCenterWidth;
961 break;
962 case Qt::RepeatTile:
963 dx = sourceCenterWidth;
964 break;
965 case Qt::RoundTile:
966 dx = targetCenterWidth / qreal(columns - 2);
967 break;
968 }
969
970 for (int i = 2; i < columns - 1; ++i)
971 xTarget[i] = xTarget[i - 1] + dx;
972
973 switch (rules.vertical) {
974 case Qt::StretchTile:
975 dy = targetCenterHeight;
976 break;
977 case Qt::RepeatTile:
978 dy = sourceCenterHeight;
979 break;
980 case Qt::RoundTile:
981 dy = targetCenterHeight / qreal(rows - 2);
982 break;
983 }
984
985 for (int i = 2; i < rows - 1; ++i)
986 yTarget[i] = yTarget[i - 1] + dy;
987
988 // corners
989 if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left
990 d.x = (0.5 * (xTarget[1] + xTarget[0]));
991 d.y = (0.5 * (yTarget[1] + yTarget[0]));
992 d.sourceLeft = sourceRect.left();
993 d.sourceTop = sourceRect.top();
994 d.width = sourceMargins.left();
995 d.height = sourceMargins.top();
996 d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
997 d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
998 if (hints & QDrawBorderPixmap::OpaqueTopLeft)
999 opaqueData.append(t: d);
1000 else
1001 translucentData.append(t: d);
1002 }
1003 if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right
1004 d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
1005 d.y = (0.5 * (yTarget[1] + yTarget[0]));
1006 d.sourceLeft = sourceCenterRight;
1007 d.sourceTop = sourceRect.top();
1008 d.width = sourceMargins.right();
1009 d.height = sourceMargins.top();
1010 d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
1011 d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
1012 if (hints & QDrawBorderPixmap::OpaqueTopRight)
1013 opaqueData.append(t: d);
1014 else
1015 translucentData.append(t: d);
1016 }
1017 if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left
1018 d.x = (0.5 * (xTarget[1] + xTarget[0]));
1019 d.y =(0.5 * (yTarget[rows] + yTarget[rows - 1]));
1020 d.sourceLeft = sourceRect.left();
1021 d.sourceTop = sourceCenterBottom;
1022 d.width = sourceMargins.left();
1023 d.height = sourceMargins.bottom();
1024 d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
1025 d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
1026 if (hints & QDrawBorderPixmap::OpaqueBottomLeft)
1027 opaqueData.append(t: d);
1028 else
1029 translucentData.append(t: d);
1030 }
1031 if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right
1032 d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
1033 d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
1034 d.sourceLeft = sourceCenterRight;
1035 d.sourceTop = sourceCenterBottom;
1036 d.width = sourceMargins.right();
1037 d.height = sourceMargins.bottom();
1038 d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
1039 d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
1040 if (hints & QDrawBorderPixmap::OpaqueBottomRight)
1041 opaqueData.append(t: d);
1042 else
1043 translucentData.append(t: d);
1044 }
1045
1046 // horizontal edges
1047 if (targetCenterWidth > 0 && sourceCenterWidth > 0) {
1048 if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
1049 QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
1050 d.sourceLeft = sourceCenterLeft;
1051 d.sourceTop = sourceRect.top();
1052 d.width = sourceCenterWidth;
1053 d.height = sourceMargins.top();
1054 d.y = (0.5 * (yTarget[1] + yTarget[0]));
1055 d.scaleX = dx / d.width;
1056 d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
1057 for (int i = 1; i < columns - 1; ++i) {
1058 d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
1059 data.append(t: d);
1060 }
1061 if (rules.horizontal == Qt::RepeatTile)
1062 data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
1063 }
1064 if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
1065 QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
1066 d.sourceLeft = sourceCenterLeft;
1067 d.sourceTop = sourceCenterBottom;
1068 d.width = sourceCenterWidth;
1069 d.height = sourceMargins.bottom();
1070 d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
1071 d.scaleX = dx / d.width;
1072 d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
1073 for (int i = 1; i < columns - 1; ++i) {
1074 d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
1075 data.append(t: d);
1076 }
1077 if (rules.horizontal == Qt::RepeatTile)
1078 data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
1079 }
1080 }
1081
1082 // vertical edges
1083 if (targetCenterHeight > 0 && sourceCenterHeight > 0) {
1084 if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
1085 QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
1086 d.sourceLeft = sourceRect.left();
1087 d.sourceTop = sourceCenterTop;
1088 d.width = sourceMargins.left();
1089 d.height = sourceCenterHeight;
1090 d.x = (0.5 * (xTarget[1] + xTarget[0]));
1091 d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
1092 d.scaleY = dy / d.height;
1093 for (int i = 1; i < rows - 1; ++i) {
1094 d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
1095 data.append(t: d);
1096 }
1097 if (rules.vertical == Qt::RepeatTile)
1098 data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
1099 }
1100 if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
1101 QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
1102 d.sourceLeft = sourceCenterRight;
1103 d.sourceTop = sourceCenterTop;
1104 d.width = sourceMargins.right();
1105 d.height = sourceCenterHeight;
1106 d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
1107 d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
1108 d.scaleY = dy / d.height;
1109 for (int i = 1; i < rows - 1; ++i) {
1110 d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
1111 data.append(t: d);
1112 }
1113 if (rules.vertical == Qt::RepeatTile)
1114 data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
1115 }
1116 }
1117
1118 // center
1119 if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
1120 QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
1121 d.sourceLeft = sourceCenterLeft;
1122 d.sourceTop = sourceCenterTop;
1123 d.width = sourceCenterWidth;
1124 d.height = sourceCenterHeight;
1125 d.scaleX = dx / d.width;
1126 d.scaleY = dy / d.height;
1127
1128 qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX;
1129 qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY;
1130
1131 for (int j = 1; j < rows - 1; ++j) {
1132 d.y = (0.5 * (yTarget[j + 1] + yTarget[j]));
1133 for (int i = 1; i < columns - 1; ++i) {
1134 d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
1135 data.append(t: d);
1136 }
1137 if (rules.horizontal == Qt::RepeatTile)
1138 data[data.size() - 1].width = repeatWidth;
1139 }
1140 if (rules.vertical == Qt::RepeatTile) {
1141 for (int i = 1; i < columns - 1; ++i)
1142 data[data.size() - i].height = repeatHeight;
1143 }
1144 }
1145
1146 if (opaqueData.size())
1147 painter->drawPixmapFragments(fragments: opaqueData.data(), fragmentCount: opaqueData.size(), pixmap, hints: QPainter::OpaqueHint);
1148 if (translucentData.size())
1149 painter->drawPixmapFragments(fragments: translucentData.data(), fragmentCount: translucentData.size(), pixmap);
1150
1151 if (oldAA)
1152 painter->setRenderHint(hint: QPainter::Antialiasing, on: true);
1153}
1154
1155QT_END_NAMESPACE
1156

source code of qtbase/src/widgets/styles/qdrawutil.cpp