1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdrawutil.h"
43 #include "qbitmap.h"
44 #include "qpixmapcache.h"
45 #include "qapplication.h"
46 #include "qpainter.h"
47 #include "qpalette.h"
48 #include <private/qpaintengineex_p.h>
49 #include <qvarlengtharray.h>
50 #include <qmath.h>
51 #include <private/qstylehelper_p.h>
52
53 QT_BEGIN_NAMESPACE
54
55 /*!
56 \headerfile <qdrawutil.h>
57 \title Drawing Utility Functions
58
59 \sa QPainter
60 */
61
62 /*!
63 \fn void qDrawShadeLine(QPainter *painter, int x1, int y1, int x2, int y2,
64 const QPalette &palette, bool sunken,
65 int lineWidth, int midLineWidth)
66 \relates <qdrawutil.h>
67
68 Draws a horizontal (\a y1 == \a y2) or vertical (\a x1 == \a x2)
69 shaded line using the given \a painter. Note that nothing is
70 drawn if \a y1 != \a y2 and \a x1 != \a x2 (i.e. the line is
71 neither horizontal nor vertical).
72
73 The provided \a palette specifies the shading colors (\l
74 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
75 {QPalette::mid()}{middle} colors). The given \a lineWidth
76 specifies the line width for each of the lines; it is not the
77 total line width. The given \a midLineWidth specifies the width of
78 a middle line drawn in the QPalette::mid() color.
79
80 The line appears sunken if \a sunken is true, otherwise raised.
81
82 \warning This function does not look at QWidget::style() or
83 QApplication::style(). Use the drawing functions in QStyle to
84 make widgets that follow the current GUI style.
85
86
87 Alternatively you can use a QFrame widget and apply the
88 QFrame::setFrameStyle() function to display a shaded line:
89
90 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 0
91
92 \sa qDrawShadeRect(), qDrawShadePanel(), QStyle
93 */
94
qDrawShadeLine(QPainter * p,int x1,int y1,int x2,int y2,const QPalette & pal,bool sunken,int lineWidth,int midLineWidth)95 void qDrawShadeLine(QPainter *p, int x1, int y1, int x2, int y2,
96 const QPalette &pal, bool sunken,
97 int lineWidth, int midLineWidth)
98 {
99 if (!(p && lineWidth >= 0 && midLineWidth >= 0)) {
100 qWarning("qDrawShadeLine: Invalid parameters");
101 return;
102 }
103 int tlw = lineWidth*2 + midLineWidth; // total line width
104 QPen oldPen = p->pen(); // save pen
105 if (sunken)
106 p->setPen(pal.color(QPalette::Dark));
107 else
108 p->setPen(pal.light().color());
109 QPolygon a;
110 int i;
111 if (y1 == y2) { // horizontal line
112 int y = y1 - tlw/2;
113 if (x1 > x2) { // swap x1 and x2
114 int t = x1;
115 x1 = x2;
116 x2 = t;
117 }
118 x2--;
119 for (i=0; i<lineWidth; i++) { // draw top shadow
120 a.setPoints(3, x1+i, y+tlw-1-i,
121 x1+i, y+i,
122 x2-i, y+i);
123 p->drawPolyline(a);
124 }
125 if (midLineWidth > 0) {
126 p->setPen(pal.mid().color());
127 for (i=0; i<midLineWidth; i++) // draw lines in the middle
128 p->drawLine(x1+lineWidth, y+lineWidth+i,
129 x2-lineWidth, y+lineWidth+i);
130 }
131 if (sunken)
132 p->setPen(pal.light().color());
133 else
134 p->setPen(pal.dark().color());
135 for (i=0; i<lineWidth; i++) { // draw bottom shadow
136 a.setPoints(3, x1+i, y+tlw-i-1,
137 x2-i, y+tlw-i-1,
138 x2-i, y+i+1);
139 p->drawPolyline(a);
140 }
141 }
142 else if (x1 == x2) { // vertical line
143 int x = x1 - tlw/2;
144 if (y1 > y2) { // swap y1 and y2
145 int t = y1;
146 y1 = y2;
147 y2 = t;
148 }
149 y2--;
150 for (i=0; i<lineWidth; i++) { // draw left shadow
151 a.setPoints(3, x+i, y2,
152 x+i, y1+i,
153 x+tlw-1, y1+i);
154 p->drawPolyline(a);
155 }
156 if (midLineWidth > 0) {
157 p->setPen(pal.mid().color());
158 for (i=0; i<midLineWidth; i++) // draw lines in the middle
159 p->drawLine(x+lineWidth+i, y1+lineWidth, x+lineWidth+i, y2);
160 }
161 if (sunken)
162 p->setPen(pal.light().color());
163 else
164 p->setPen(pal.dark().color());
165 for (i=0; i<lineWidth; i++) { // draw right shadow
166 a.setPoints(3, x+lineWidth, y2-i,
167 x+tlw-i-1, y2-i,
168 x+tlw-i-1, y1+lineWidth);
169 p->drawPolyline(a);
170 }
171 }
172 p->setPen(oldPen);
173 }
174
175 /*!
176 \fn void qDrawShadeRect(QPainter *painter, int x, int y, int width, int height,
177 const QPalette &palette, bool sunken,
178 int lineWidth, int midLineWidth,
179 const QBrush *fill)
180 \relates <qdrawutil.h>
181
182 Draws the shaded rectangle beginning at (\a x, \a y) with the
183 given \a width and \a height using the provided \a painter.
184
185 The provide \a palette specifies the shading colors (\l
186 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
187 {QPalette::mid()}{middle} colors. The given \a lineWidth
188 specifies the line width for each of the lines; it is not the
189 total line width. The \a midLineWidth specifies the width of a
190 middle line drawn in the QPalette::mid() color. The rectangle's
191 interior is filled with the \a fill brush unless \a fill is 0.
192
193 The rectangle appears sunken if \a sunken is true, otherwise
194 raised.
195
196 \warning This function does not look at QWidget::style() or
197 QApplication::style(). Use the drawing functions in QStyle to make
198 widgets that follow the current GUI style.
199
200 Alternatively you can use a QFrame widget and apply the
201 QFrame::setFrameStyle() function to display a shaded rectangle:
202
203 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 1
204
205 \sa qDrawShadeLine(), qDrawShadePanel(), qDrawPlainRect(), QStyle
206 */
207
qDrawShadeRect(QPainter * p,int x,int y,int w,int h,const QPalette & pal,bool sunken,int lineWidth,int midLineWidth,const QBrush * fill)208 void qDrawShadeRect(QPainter *p, int x, int y, int w, int h,
209 const QPalette &pal, bool sunken,
210 int lineWidth, int midLineWidth,
211 const QBrush *fill)
212 {
213 if (w == 0 || h == 0)
214 return;
215 if (! (w > 0 && h > 0 && lineWidth >= 0 && midLineWidth >= 0)) {
216 qWarning("qDrawShadeRect: Invalid parameters");
217 return;
218 }
219 QPen oldPen = p->pen();
220 if (sunken)
221 p->setPen(pal.dark().color());
222 else
223 p->setPen(pal.light().color());
224 int x1=x, y1=y, x2=x+w-1, y2=y+h-1;
225
226 if (lineWidth == 1 && midLineWidth == 0) {// standard shade rectangle
227 p->drawRect(x1, y1, w-2, h-2);
228 if (sunken)
229 p->setPen(pal.light().color());
230 else
231 p->setPen(pal.dark().color());
232 QLineF lines[4] = { QLineF(x1+1, y1+1, x2-2, y1+1),
233 QLineF(x1+1, y1+2, x1+1, y2-2),
234 QLineF(x1, y2, x2, y2),
235 QLineF(x2,y1, x2,y2-1) };
236 p->drawLines(lines, 4); // draw bottom/right lines
237 } else { // more complicated
238 int m = lineWidth+midLineWidth;
239 int i, j=0, k=m;
240 for (i=0; i<lineWidth; i++) { // draw top shadow
241 QLineF lines[4] = { QLineF(x1+i, y2-i, x1+i, y1+i),
242 QLineF(x1+i, y1+i, x2-i, y1+i),
243 QLineF(x1+k, y2-k, x2-k, y2-k),
244 QLineF(x2-k, y2-k, x2-k, y1+k) };
245 p->drawLines(lines, 4);
246 k++;
247 }
248 p->setPen(pal.mid().color());
249 j = lineWidth*2;
250 for (i=0; i<midLineWidth; i++) { // draw lines in the middle
251 p->drawRect(x1+lineWidth+i, y1+lineWidth+i, w-j-1, h-j-1);
252 j += 2;
253 }
254 if (sunken)
255 p->setPen(pal.light().color());
256 else
257 p->setPen(pal.dark().color());
258 k = m;
259 for (i=0; i<lineWidth; i++) { // draw bottom shadow
260 QLineF lines[4] = { QLineF(x1+1+i, y2-i, x2-i, y2-i),
261 QLineF(x2-i, y2-i, x2-i, y1+i+1),
262 QLineF(x1+k, y2-k, x1+k, y1+k),
263 QLineF(x1+k, y1+k, x2-k, y1+k) };
264 p->drawLines(lines, 4);
265 k++;
266 }
267 }
268 if (fill) {
269 QBrush oldBrush = p->brush();
270 int tlw = lineWidth + midLineWidth;
271 p->setPen(Qt::NoPen);
272 p->setBrush(*fill);
273 p->drawRect(x+tlw, y+tlw, w-2*tlw, h-2*tlw);
274 p->setBrush(oldBrush);
275 }
276 p->setPen(oldPen); // restore pen
277 }
278
279
280 /*!
281 \fn void qDrawShadePanel(QPainter *painter, int x, int y, int width, int height,
282 const QPalette &palette, bool sunken,
283 int lineWidth, const QBrush *fill)
284 \relates <qdrawutil.h>
285
286 Draws the shaded panel beginning at (\a x, \a y) with the given \a
287 width and \a height using the provided \a painter and the given \a
288 lineWidth.
289
290 The given \a palette specifies the shading colors (\l
291 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
292 {QPalette::mid()}{middle} colors). The panel's interior is filled
293 with the \a fill brush unless \a fill is 0.
294
295 The panel appears sunken if \a sunken is true, otherwise raised.
296
297 \warning This function does not look at QWidget::style() or
298 QApplication::style(). Use the drawing functions in QStyle to make
299 widgets that follow the current GUI style.
300
301 Alternatively you can use a QFrame widget and apply the
302 QFrame::setFrameStyle() function to display a shaded panel:
303
304 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 2
305
306 \sa qDrawWinPanel(), qDrawShadeLine(), qDrawShadeRect(), QStyle
307 */
308
qDrawShadePanel(QPainter * p,int x,int y,int w,int h,const QPalette & pal,bool sunken,int lineWidth,const QBrush * fill)309 void qDrawShadePanel(QPainter *p, int x, int y, int w, int h,
310 const QPalette &pal, bool sunken,
311 int lineWidth, const QBrush *fill)
312 {
313 if (w == 0 || h == 0)
314 return;
315 if (!(w > 0 && h > 0 && lineWidth >= 0)) {
316 qWarning("qDrawShadePanel: Invalid parameters");
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 QPen oldPen = p->pen(); // save pen
327 QVector<QLineF> lines;
328 lines.reserve(2*lineWidth);
329
330 if (sunken)
331 p->setPen(shade);
332 else
333 p->setPen(light);
334 int x1, y1, x2, y2;
335 int i;
336 x1 = x;
337 y1 = y2 = y;
338 x2 = x+w-2;
339 for (i=0; i<lineWidth; i++) { // top shadow
340 lines << QLineF(x1, y1++, x2--, y2++);
341 }
342 x2 = x1;
343 y1 = y+h-2;
344 for (i=0; i<lineWidth; i++) { // left shado
345 lines << QLineF(x1++, y1, x2++, y2--);
346 }
347 p->drawLines(lines);
348 lines.clear();
349 if (sunken)
350 p->setPen(light);
351 else
352 p->setPen(shade);
353 x1 = x;
354 y1 = y2 = y+h-1;
355 x2 = x+w-1;
356 for (i=0; i<lineWidth; i++) { // bottom shadow
357 lines << QLineF(x1++, y1--, x2, y2--);
358 }
359 x1 = x2;
360 y1 = y;
361 y2 = y+h-lineWidth-1;
362 for (i=0; i<lineWidth; i++) { // right shadow
363 lines << QLineF(x1--, y1++, x2--, y2);
364 }
365 p->drawLines(lines);
366 if (fill) // fill with fill color
367 p->fillRect(x+lineWidth, y+lineWidth, w-lineWidth*2, h-lineWidth*2, *fill);
368 p->setPen(oldPen); // restore pen
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
qDrawWinShades(QPainter * p,int x,int y,int w,int h,const QColor & c1,const QColor & c2,const QColor & c3,const QColor & c4,const QBrush * fill)387 static 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 QPen oldPen = p->pen();
396 QPoint a[3] = { QPoint(x, y+h-2), QPoint(x, y), QPoint(x+w-2, y) };
397 p->setPen(c1);
398 p->drawPolyline(a, 3);
399 QPoint b[3] = { QPoint(x, y+h-1), QPoint(x+w-1, y+h-1), QPoint(x+w-1, y) };
400 p->setPen(c2);
401 p->drawPolyline(b, 3);
402 if (w > 4 && h > 4) {
403 QPoint c[3] = { QPoint(x+1, y+h-3), QPoint(x+1, y+1), QPoint(x+w-3, y+1) };
404 p->setPen(c3);
405 p->drawPolyline(c, 3);
406 QPoint d[3] = { QPoint(x+1, y+h-2), QPoint(x+w-2, y+h-2), QPoint(x+w-2, y+1) };
407 p->setPen(c4);
408 p->drawPolyline(d, 3);
409 if (fill)
410 p->fillRect(QRect(x+2, y+2, w-4, h-4), *fill);
411 }
412 p->setPen(oldPen);
413 }
414
415
416 /*!
417 \fn void qDrawWinButton(QPainter *painter, int x, int y, int width, int height,
418 const QPalette &palette, bool sunken,
419 const QBrush *fill)
420 \relates <qdrawutil.h>
421
422 Draws the Windows-style button specified by the given point (\a x,
423 \a y}, \a width and \a height using the provided \a painter with a
424 line width of 2 pixels. The button's interior is filled with the
425 \a{fill} brush unless \a fill is 0.
426
427 The given \a palette specifies the shading colors (\l
428 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
429 {QPalette::mid()}{middle} colors).
430
431 The button appears sunken if \a sunken is true, otherwise raised.
432
433 \warning This function does not look at QWidget::style() or
434 QApplication::style()-> Use the drawing functions in QStyle to make
435 widgets that follow the current GUI style.
436
437 \sa qDrawWinPanel(), QStyle
438 */
439
qDrawWinButton(QPainter * p,int x,int y,int w,int h,const QPalette & pal,bool sunken,const QBrush * fill)440 void qDrawWinButton(QPainter *p, int x, int y, int w, int h,
441 const QPalette &pal, bool sunken,
442 const QBrush *fill)
443 {
444 if (sunken)
445 qDrawWinShades(p, x, y, w, h,
446 pal.shadow().color(), pal.light().color(), pal.dark().color(),
447 pal.button().color(), fill);
448 else
449 qDrawWinShades(p, x, y, w, h,
450 pal.light().color(), pal.shadow().color(), pal.button().color(),
451 pal.dark().color(), fill);
452 }
453
454 /*!
455 \fn void qDrawWinPanel(QPainter *painter, int x, int y, int width, int height,
456 const QPalette &palette, bool sunken,
457 const QBrush *fill)
458 \relates <qdrawutil.h>
459
460 Draws the Windows-style panel specified by the given point(\a x,
461 \a y), \a width and \a height using the provided \a painter with a
462 line width of 2 pixels. The button's interior is filled with the
463 \a fill brush unless \a fill is 0.
464
465 The given \a palette specifies the shading colors. The panel
466 appears sunken if \a sunken is true, otherwise raised.
467
468 \warning This function does not look at QWidget::style() or
469 QApplication::style(). Use the drawing functions in QStyle to make
470 widgets that follow the current GUI style.
471
472 Alternatively you can use a QFrame widget and apply the
473 QFrame::setFrameStyle() function to display a shaded panel:
474
475 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 3
476
477 \sa qDrawShadePanel(), qDrawWinButton(), QStyle
478 */
479
qDrawWinPanel(QPainter * p,int x,int y,int w,int h,const QPalette & pal,bool sunken,const QBrush * fill)480 void qDrawWinPanel(QPainter *p, int x, int y, int w, int h,
481 const QPalette &pal, bool sunken,
482 const QBrush *fill)
483 {
484 if (sunken)
485 qDrawWinShades(p, x, y, w, h,
486 pal.dark().color(), pal.light().color(), pal.shadow().color(),
487 pal.midlight().color(), fill);
488 else
489 qDrawWinShades(p, x, y, w, h,
490 pal.light().color(), pal.shadow().color(), pal.midlight().color(),
491 pal.dark().color(), fill);
492 }
493
494 /*!
495 \fn void qDrawPlainRect(QPainter *painter, int x, int y, int width, int height, const QColor &lineColor,
496 int lineWidth, const QBrush *fill)
497 \relates <qdrawutil.h>
498
499 Draws the plain rectangle beginning at (\a x, \a y) with the given
500 \a width and \a height, using the specified \a painter, \a lineColor
501 and \a lineWidth. The rectangle's interior is filled with the \a
502 fill brush unless \a fill is 0.
503
504 \warning This function does not look at QWidget::style() or
505 QApplication::style(). Use the drawing functions in QStyle to make
506 widgets that follow the current GUI style.
507
508 Alternatively you can use a QFrame widget and apply the
509 QFrame::setFrameStyle() function to display a plain rectangle:
510
511 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 4
512
513 \sa qDrawShadeRect(), QStyle
514 */
515
qDrawPlainRect(QPainter * p,int x,int y,int w,int h,const QColor & c,int lineWidth,const QBrush * fill)516 void qDrawPlainRect(QPainter *p, int x, int y, int w, int h, const QColor &c,
517 int lineWidth, const QBrush *fill)
518 {
519 if (w == 0 || h == 0)
520 return;
521 if (!(w > 0 && h > 0 && lineWidth >= 0)) {
522 qWarning("qDrawPlainRect: Invalid parameters");
523 }
524 QPen oldPen = p->pen();
525 QBrush oldBrush = p->brush();
526 p->setPen(c);
527 p->setBrush(Qt::NoBrush);
528 for (int i=0; i<lineWidth; i++)
529 p->drawRect(x+i, y+i, w-i*2 - 1, h-i*2 - 1);
530 if (fill) { // fill with fill color
531 p->setPen(Qt::NoPen);
532 p->setBrush(*fill);
533 p->drawRect(x+lineWidth, y+lineWidth, w-lineWidth*2, h-lineWidth*2);
534 }
535 p->setPen(oldPen);
536 p->setBrush(oldBrush);
537 }
538
539 /*****************************************************************************
540 Overloaded functions.
541 *****************************************************************************/
542
543 /*!
544 \fn void qDrawShadeLine(QPainter *painter, const QPoint &p1, const QPoint &p2,
545 const QPalette &palette, bool sunken, int lineWidth, int midLineWidth)
546 \relates <qdrawutil.h>
547 \overload
548
549 Draws a horizontal or vertical shaded line between \a p1 and \a p2
550 using the given \a painter. Note that nothing is drawn if the line
551 between the points would be neither horizontal nor vertical.
552
553 The provided \a palette specifies the shading colors (\l
554 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
555 {QPalette::mid()}{middle} colors). The given \a lineWidth
556 specifies the line width for each of the lines; it is not the
557 total line width. The given \a midLineWidth specifies the width of
558 a middle line drawn in the QPalette::mid() color.
559
560 The line appears sunken if \a sunken is true, otherwise raised.
561
562 \warning This function does not look at QWidget::style() or
563 QApplication::style(). Use the drawing functions in QStyle to
564 make widgets that follow the current GUI style.
565
566
567 Alternatively you can use a QFrame widget and apply the
568 QFrame::setFrameStyle() function to display a shaded line:
569
570 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 5
571
572 \sa qDrawShadeRect(), qDrawShadePanel(), QStyle
573 */
574
qDrawShadeLine(QPainter * p,const QPoint & p1,const QPoint & p2,const QPalette & pal,bool sunken,int lineWidth,int midLineWidth)575 void qDrawShadeLine(QPainter *p, const QPoint &p1, const QPoint &p2,
576 const QPalette &pal, bool sunken,
577 int lineWidth, int midLineWidth)
578 {
579 qDrawShadeLine(p, p1.x(), p1.y(), p2.x(), p2.y(), pal, sunken,
580 lineWidth, midLineWidth);
581 }
582
583 /*!
584 \fn void qDrawShadeRect(QPainter *painter, const QRect &rect, const QPalette &palette,
585 bool sunken, int lineWidth, int midLineWidth, const QBrush *fill)
586 \relates <qdrawutil.h>
587 \overload
588
589 Draws the shaded rectangle specified by \a rect using the given \a painter.
590
591 The provide \a palette specifies the shading colors (\l
592 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
593 {QPalette::mid()}{middle} colors. The given \a lineWidth
594 specifies the line width for each of the lines; it is not the
595 total line width. The \a midLineWidth specifies the width of a
596 middle line drawn in the QPalette::mid() color. The rectangle's
597 interior is filled with the \a fill brush unless \a fill is 0.
598
599 The rectangle appears sunken if \a sunken is true, otherwise
600 raised.
601
602 \warning This function does not look at QWidget::style() or
603 QApplication::style(). Use the drawing functions in QStyle to make
604 widgets that follow the current GUI style.
605
606 Alternatively you can use a QFrame widget and apply the
607 QFrame::setFrameStyle() function to display a shaded rectangle:
608
609 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 6
610
611 \sa qDrawShadeLine(), qDrawShadePanel(), qDrawPlainRect(), QStyle
612 */
613
qDrawShadeRect(QPainter * p,const QRect & r,const QPalette & pal,bool sunken,int lineWidth,int midLineWidth,const QBrush * fill)614 void qDrawShadeRect(QPainter *p, const QRect &r,
615 const QPalette &pal, bool sunken,
616 int lineWidth, int midLineWidth,
617 const QBrush *fill)
618 {
619 qDrawShadeRect(p, r.x(), r.y(), r.width(), r.height(), pal, sunken,
620 lineWidth, midLineWidth, fill);
621 }
622
623 /*!
624 \fn void qDrawShadePanel(QPainter *painter, const QRect &rect, const QPalette &palette,
625 bool sunken, int lineWidth, const QBrush *fill)
626 \relates <qdrawutil.h>
627 \overload
628
629 Draws the shaded panel at the rectangle specified by \a rect using the
630 given \a painter and the given \a lineWidth.
631
632 The given \a palette specifies the shading colors (\l
633 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
634 {QPalette::mid()}{middle} colors). The panel's interior is filled
635 with the \a fill brush unless \a fill is 0.
636
637 The panel appears sunken if \a sunken is true, otherwise raised.
638
639 \warning This function does not look at QWidget::style() or
640 QApplication::style(). Use the drawing functions in QStyle to make
641 widgets that follow the current GUI style.
642
643 Alternatively you can use a QFrame widget and apply the
644 QFrame::setFrameStyle() function to display a shaded panel:
645
646 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 7
647
648 \sa qDrawWinPanel(), qDrawShadeLine(), qDrawShadeRect(), QStyle
649 */
650
qDrawShadePanel(QPainter * p,const QRect & r,const QPalette & pal,bool sunken,int lineWidth,const QBrush * fill)651 void qDrawShadePanel(QPainter *p, const QRect &r,
652 const QPalette &pal, bool sunken,
653 int lineWidth, const QBrush *fill)
654 {
655 qDrawShadePanel(p, r.x(), r.y(), r.width(), r.height(), pal, sunken,
656 lineWidth, fill);
657 }
658
659 /*!
660 \fn void qDrawWinButton(QPainter *painter, const QRect &rect, const QPalette &palette,
661 bool sunken, const QBrush *fill)
662 \relates <qdrawutil.h>
663 \overload
664
665 Draws the Windows-style button at the rectangle specified by \a rect using
666 the given \a painter with a line width of 2 pixels. The button's interior
667 is filled with the \a{fill} brush unless \a fill is 0.
668
669 The given \a palette specifies the shading colors (\l
670 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
671 {QPalette::mid()}{middle} colors).
672
673 The button appears sunken if \a sunken is true, otherwise raised.
674
675 \warning This function does not look at QWidget::style() or
676 QApplication::style()-> Use the drawing functions in QStyle to make
677 widgets that follow the current GUI style.
678
679 \sa qDrawWinPanel(), QStyle
680 */
681
qDrawWinButton(QPainter * p,const QRect & r,const QPalette & pal,bool sunken,const QBrush * fill)682 void qDrawWinButton(QPainter *p, const QRect &r,
683 const QPalette &pal, bool sunken, const QBrush *fill)
684 {
685 qDrawWinButton(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, fill);
686 }
687
688 /*!
689 \fn void qDrawWinPanel(QPainter *painter, const QRect &rect, const QPalette &palette,
690 bool sunken, const QBrush *fill)
691 \overload
692
693 Draws the Windows-style panel at the rectangle specified by \a rect using
694 the given \a painter with a line width of 2 pixels. The button's interior
695 is filled with the \a fill brush unless \a fill is 0.
696
697 The given \a palette specifies the shading colors. The panel
698 appears sunken if \a sunken is true, otherwise raised.
699
700 \warning This function does not look at QWidget::style() or
701 QApplication::style(). Use the drawing functions in QStyle to make
702 widgets that follow the current GUI style.
703
704 Alternatively you can use a QFrame widget and apply the
705 QFrame::setFrameStyle() function to display a shaded panel:
706
707 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 8
708
709 \sa qDrawShadePanel(), qDrawWinButton(), QStyle
710 */
711
qDrawWinPanel(QPainter * p,const QRect & r,const QPalette & pal,bool sunken,const QBrush * fill)712 void qDrawWinPanel(QPainter *p, const QRect &r,
713 const QPalette &pal, bool sunken, const QBrush *fill)
714 {
715 qDrawWinPanel(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, fill);
716 }
717
718 /*!
719 \fn void qDrawPlainRect(QPainter *painter, const QRect &rect, const QColor &lineColor, int lineWidth, const QBrush *fill)
720 \relates <qdrawutil.h>
721 \overload
722
723 Draws the plain rectangle specified by \a rect using the given \a painter,
724 \a lineColor and \a lineWidth. The rectangle's interior is filled with the
725 \a fill brush unless \a fill is 0.
726
727 \warning This function does not look at QWidget::style() or
728 QApplication::style(). Use the drawing functions in QStyle to make
729 widgets that follow the current GUI style.
730
731 Alternatively you can use a QFrame widget and apply the
732 QFrame::setFrameStyle() function to display a plain rectangle:
733
734 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 9
735
736 \sa qDrawShadeRect(), QStyle
737 */
738
qDrawPlainRect(QPainter * p,const QRect & r,const QColor & c,int lineWidth,const QBrush * fill)739 void qDrawPlainRect(QPainter *p, const QRect &r, const QColor &c,
740 int lineWidth, const QBrush *fill)
741 {
742 qDrawPlainRect(p, r.x(), r.y(), r.width(), r.height(), c,
743 lineWidth, fill);
744 }
745
746 #ifdef QT3_SUPPORT
qDrawWinArrow(QPainter * p,Qt::ArrowType type,bool down,int x,int y,int w,int h,const QPalette & pal,bool enabled)747 static void qDrawWinArrow(QPainter *p, Qt::ArrowType type, bool down,
748 int x, int y, int w, int h,
749 const QPalette &pal, bool enabled)
750 {
751 QPolygon a; // arrow polygon
752 switch (type) {
753 case Qt::UpArrow:
754 a.setPoints(7, -3,1, 3,1, -2,0, 2,0, -1,-1, 1,-1, 0,-2);
755 break;
756 case Qt::DownArrow:
757 a.setPoints(7, -3,-1, 3,-1, -2,0, 2,0, -1,1, 1,1, 0,2);
758 break;
759 case Qt::LeftArrow:
760 a.setPoints(7, 1,-3, 1,3, 0,-2, 0,2, -1,-1, -1,1, -2,0);
761 break;
762 case Qt::RightArrow:
763 a.setPoints(7, -1,-3, -1,3, 0,-2, 0,2, 1,-1, 1,1, 2,0);
764 break;
765 default:
766 break;
767 }
768 if (a.isEmpty())
769 return;
770
771 if (down) {
772 x++;
773 y++;
774 }
775
776 QPen savePen = p->pen(); // save current pen
777 if (down)
778 p->setBrushOrigin(p->brushOrigin() + QPoint(1,1));
779 p->fillRect(x, y, w, h, pal.brush(QPalette::Button));
780 if (down)
781 p->setBrushOrigin(p->brushOrigin() - QPoint(1,1));
782 if (enabled) {
783 a.translate(x+w/2, y+h/2);
784 p->setPen(pal.foreground().color());
785 p->drawLine(a.at(0), a.at(1));
786 p->drawLine(a.at(2), a.at(2));
787 p->drawPoint(a[6]);
788 } else {
789 a.translate(x+w/2+1, y+h/2+1);
790 p->setPen(pal.light().color());
791 p->drawLine(a.at(0), a.at(1));
792 p->drawLine(a.at(2), a.at(2));
793 p->drawPoint(a[6]);
794 a.translate(-1, -1);
795 p->setPen(pal.mid().color());
796 p->drawLine(a.at(0), a.at(1));
797 p->drawLine(a.at(2), a.at(2));
798 p->drawPoint(a[6]);
799 }
800 p->setPen(savePen); // restore pen
801 }
802 #endif // QT3_SUPPORT
803
804 #if defined(Q_CC_MSVC)
805 #pragma warning(disable: 4244)
806 #endif
807
808 #ifdef QT3_SUPPORT
809 #ifndef QT_NO_STYLE_MOTIF
810 // motif arrows look the same whether they are used or not
811 // is this correct?
qDrawMotifArrow(QPainter * p,Qt::ArrowType type,bool down,int x,int y,int w,int h,const QPalette & pal,bool)812 static void qDrawMotifArrow(QPainter *p, Qt::ArrowType type, bool down,
813 int x, int y, int w, int h,
814 const QPalette &pal, bool)
815 {
816 QPolygon bFill; // fill polygon
817 QPolygon bTop; // top shadow.
818 QPolygon bBot; // bottom shadow.
819 QPolygon bLeft; // left shadow.
820 QTransform matrix; // xform matrix
821 bool vertical = type == Qt::UpArrow || type == Qt::DownArrow;
822 bool horizontal = !vertical;
823 int dim = w < h ? w : h;
824 int colspec = 0x0000; // color specification array
825
826 if (dim < 2) // too small arrow
827 return;
828
829 if (dim > 3) {
830 if (dim > 6)
831 bFill.resize(dim & 1 ? 3 : 4);
832 bTop.resize((dim/2)*2);
833 bBot.resize(dim & 1 ? dim + 1 : dim);
834 bLeft.resize(dim > 4 ? 4 : 2);
835 bLeft.putPoints(0, 2, 0,0, 0,dim-1);
836 if (dim > 4)
837 bLeft.putPoints(2, 2, 1,2, 1,dim-3);
838 bTop.putPoints(0, 4, 1,0, 1,1, 2,1, 3,1);
839 bBot.putPoints(0, 4, 1,dim-1, 1,dim-2, 2,dim-2, 3,dim-2);
840
841 for(int i=0; i<dim/2-2 ; i++) {
842 bTop.putPoints(i*2+4, 2, 2+i*2,2+i, 5+i*2, 2+i);
843 bBot.putPoints(i*2+4, 2, 2+i*2,dim-3-i, 5+i*2,dim-3-i);
844 }
845 if (dim & 1) // odd number size: extra line
846 bBot.putPoints(dim-1, 2, dim-3,dim/2, dim-1,dim/2);
847 if (dim > 6) { // dim>6: must fill interior
848 bFill.putPoints(0, 2, 1,dim-3, 1,2);
849 if (dim & 1) // if size is an odd number
850 bFill.setPoint(2, dim - 3, dim / 2);
851 else
852 bFill.putPoints(2, 2, dim-4,dim/2-1, dim-4,dim/2);
853 }
854 }
855 else {
856 if (dim == 3) { // 3x3 arrow pattern
857 bLeft.setPoints(4, 0,0, 0,2, 1,1, 1,1);
858 bTop .setPoints(2, 1,0, 1,0);
859 bBot .setPoints(2, 1,2, 2,1);
860 }
861 else { // 2x2 arrow pattern
862 bLeft.setPoints(2, 0,0, 0,1);
863 bTop .setPoints(2, 1,0, 1,0);
864 bBot .setPoints(2, 1,1, 1,1);
865 }
866 }
867
868 if (type == Qt::UpArrow || type == Qt::LeftArrow) {
869 matrix.translate(x, y);
870 if (vertical) {
871 matrix.translate(0, h - 1);
872 matrix.rotate(-90);
873 } else {
874 matrix.translate(w - 1, h - 1);
875 matrix.rotate(180);
876 }
877 if (down)
878 colspec = horizontal ? 0x2334 : 0x2343;
879 else
880 colspec = horizontal ? 0x1443 : 0x1434;
881 }
882 else if (type == Qt::DownArrow || type == Qt::RightArrow) {
883 matrix.translate(x, y);
884 if (vertical) {
885 matrix.translate(w-1, 0);
886 matrix.rotate(90);
887 }
888 if (down)
889 colspec = horizontal ? 0x2443 : 0x2434;
890 else
891 colspec = horizontal ? 0x1334 : 0x1343;
892 }
893
894 const QColor *cols[5];
895 cols[0] = 0;
896 cols[1] = &pal.button().color();
897 cols[2] = &pal.mid().color();
898 cols[3] = &pal.light().color();
899 cols[4] = &pal.dark().color();
900 #define CMID *cols[(colspec>>12) & 0xf]
901 #define CLEFT *cols[(colspec>>8) & 0xf]
902 #define CTOP *cols[(colspec>>4) & 0xf]
903 #define CBOT *cols[colspec & 0xf]
904
905 QPen savePen = p->pen(); // save current pen
906 QBrush saveBrush = p->brush(); // save current brush
907 QTransform wxm = p->transform();
908 QPen pen(Qt::NoPen);
909 const QBrush &brush = pal.brush(QPalette::Button);
910
911 p->setPen(pen);
912 p->setBrush(brush);
913 p->setTransform(matrix, true); // set transformation matrix
914 p->drawPolygon(bFill); // fill arrow
915 p->setBrush(Qt::NoBrush); // don't fill
916
917 p->setPen(CLEFT);
918 p->drawLines(bLeft);
919 p->setPen(CTOP);
920 p->drawLines(bTop);
921 p->setPen(CBOT);
922 p->drawLines(bBot);
923
924 p->setTransform(wxm);
925 p->setBrush(saveBrush); // restore brush
926 p->setPen(savePen); // restore pen
927
928 #undef CMID
929 #undef CLEFT
930 #undef CTOP
931 #undef CBOT
932 }
933 #endif // QT_NO_STYLE_MOTIF
934
qItemRect(QPainter * p,Qt::GUIStyle gs,int x,int y,int w,int h,int flags,bool enabled,const QPixmap * pixmap,const QString & text,int len)935 QRect qItemRect(QPainter *p, Qt::GUIStyle gs,
936 int x, int y, int w, int h,
937 int flags,
938 bool enabled,
939 const QPixmap *pixmap,
940 const QString& text, int len)
941 {
942 QRect result;
943
944 if (pixmap) {
945 if ((flags & Qt::AlignVCenter) == Qt::AlignVCenter)
946 y += h/2 - pixmap->height()/2;
947 else if ((flags & Qt::AlignBottom) == Qt::AlignBottom)
948 y += h - pixmap->height();
949 if ((flags & Qt::AlignRight) == Qt::AlignRight)
950 x += w - pixmap->width();
951 else if ((flags & Qt::AlignHCenter) == Qt::AlignHCenter)
952 x += w/2 - pixmap->width()/2;
953 else if ((flags & Qt::AlignLeft) != Qt::AlignLeft && QApplication::isRightToLeft())
954 x += w - pixmap->width();
955 result = QRect(x, y, pixmap->width(), pixmap->height());
956 } else if (!text.isNull() && p) {
957 result = p->boundingRect(QRect(x, y, w, h), flags, text.left(len));
958 if (gs == Qt::WindowsStyle && !enabled) {
959 result.setWidth(result.width()+1);
960 result.setHeight(result.height()+1);
961 }
962 } else {
963 result = QRect(x, y, w, h);
964 }
965
966 return result;
967 }
968
qDrawArrow(QPainter * p,Qt::ArrowType type,Qt::GUIStyle style,bool down,int x,int y,int w,int h,const QPalette & pal,bool enabled)969 void qDrawArrow(QPainter *p, Qt::ArrowType type, Qt::GUIStyle style, bool down,
970 int x, int y, int w, int h,
971 const QPalette &pal, bool enabled)
972 {
973 switch (style) {
974 case Qt::WindowsStyle:
975 qDrawWinArrow(p, type, down, x, y, w, h, pal, enabled);
976 break;
977 #ifndef QT_NO_STYLE_MOTIF
978 case Qt::MotifStyle:
979 qDrawMotifArrow(p, type, down, x, y, w, h, pal, enabled);
980 break;
981 #endif
982 default:
983 qWarning("qDrawArrow: Requested unsupported GUI style");
984 }
985 }
986
qDrawItem(QPainter * p,Qt::GUIStyle gs,int x,int y,int w,int h,int flags,const QPalette & pal,bool enabled,const QPixmap * pixmap,const QString & text,int len,const QColor * penColor)987 void qDrawItem(QPainter *p, Qt::GUIStyle gs,
988 int x, int y, int w, int h,
989 int flags,
990 const QPalette &pal, bool enabled,
991 const QPixmap *pixmap,
992 const QString& text, int len , const QColor* penColor)
993 {
994 p->setPen(penColor?*penColor:pal.foreground().color());
995 if (pixmap) {
996 QPixmap pm(*pixmap);
997 bool clip = (flags & Qt::TextDontClip) == 0;
998 if (clip) {
999 if (pm.width() < w && pm.height() < h)
1000 clip = false;
1001 else
1002 p->setClipRect(x, y, w, h);
1003 }
1004 if ((flags & Qt::AlignVCenter) == Qt::AlignVCenter)
1005 y += h/2 - pm.height()/2;
1006 else if ((flags & Qt::AlignBottom) == Qt::AlignBottom)
1007 y += h - pm.height();
1008 if ((flags & Qt::AlignRight) == Qt::AlignRight)
1009 x += w - pm.width();
1010 else if ((flags & Qt::AlignHCenter) == Qt::AlignHCenter)
1011 x += w/2 - pm.width()/2;
1012 else if (((flags & Qt::AlignLeft) != Qt::AlignLeft) && QApplication::isRightToLeft()) // Qt::AlignAuto && rightToLeft
1013 x += w - pm.width();
1014
1015 if (!enabled) {
1016 if (pm.hasAlphaChannel()) { // pixmap with a mask
1017 pm = pm.mask();
1018 } else if (pm.depth() == 1) { // monochrome pixmap, no mask
1019 ;
1020 #ifndef QT_NO_IMAGE_HEURISTIC_MASK
1021 } else { // color pixmap, no mask
1022 QString k = QLatin1Literal("$qt-drawitem")
1023 % HexString<qint64>(pm.cacheKey());
1024
1025 if (!QPixmapCache::find(k, pm)) {
1026 pm = pm.createHeuristicMask();
1027 pm.setMask((QBitmap&)pm);
1028 QPixmapCache::insert(k, pm);
1029 }
1030 #endif
1031 }
1032 if (gs == Qt::WindowsStyle) {
1033 p->setPen(pal.light().color());
1034 p->drawPixmap(x+1, y+1, pm);
1035 p->setPen(pal.text().color());
1036 }
1037 }
1038 p->drawPixmap(x, y, pm);
1039 if (clip)
1040 p->setClipping(false);
1041 } else if (!text.isNull()) {
1042 if (gs == Qt::WindowsStyle && !enabled) {
1043 p->setPen(pal.light().color());
1044 p->drawText(x+1, y+1, w, h, flags, text.left(len));
1045 p->setPen(pal.text().color());
1046 }
1047 p->drawText(x, y, w, h, flags, text.left(len));
1048 }
1049 }
1050
1051 #endif
1052
1053 /*!
1054 \class QTileRules
1055 \since 4.6
1056
1057 Holds the rules used to draw a pixmap or image split into nine segments,
1058 similar to \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}.
1059
1060 \sa Qt::TileRule, QMargins
1061 */
1062
1063 /*! \fn QTileRules::QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule)
1064 Constructs a QTileRules with the given \a horizontalRule and
1065 \a verticalRule.
1066 */
1067
1068 /*! \fn QTileRules::QTileRules(Qt::TileRule rule)
1069 Constructs a QTileRules with the given \a rule used for both
1070 the horizontal rule and the vertical rule.
1071 */
1072
1073 /*!
1074 \fn void qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap)
1075 \relates <qdrawutil.h>
1076 \since 4.6
1077 \overload
1078
1079 \brief The qDrawBorderPixmap function is for drawing a pixmap into
1080 the margins of a rectangle.
1081
1082 Draws the given \a pixmap into the given \a target rectangle, using the
1083 given \a painter. The pixmap will be split into nine segments and drawn
1084 according to the \a margins structure.
1085 */
1086
1087 typedef QVarLengthArray<QRectF, 16> QRectFArray;
1088
1089 /*!
1090 \since 4.6
1091
1092 Draws the indicated \a sourceRect rectangle from the given \a pixmap into
1093 the given \a targetRect rectangle, using the given \a painter. The pixmap
1094 will be split into nine segments according to the given \a targetMargins
1095 and \a sourceMargins structures. Finally, the pixmap will be drawn
1096 according to the given \a rules.
1097
1098 This function is used to draw a scaled pixmap, similar to
1099 \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}
1100
1101 \sa Qt::TileRule, QTileRules, QMargins
1102 */
1103
qDrawBorderPixmap(QPainter * painter,const QRect & targetRect,const QMargins & targetMargins,const QPixmap & pixmap,const QRect & sourceRect,const QMargins & sourceMargins,const QTileRules & rules,QDrawBorderPixmap::DrawingHints hints)1104 void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins,
1105 const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins,
1106 const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints)
1107 {
1108 if (!painter->isActive()) {
1109 qWarning("qDrawBorderPixmap: Painter not active");
1110 return;
1111 }
1112
1113 QRectFArray sourceData[2];
1114 QRectFArray targetData[2];
1115
1116 // source center
1117 const int sourceCenterTop = sourceRect.top() + sourceMargins.top();
1118 const int sourceCenterLeft = sourceRect.left() + sourceMargins.left();
1119 const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1;
1120 const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1;
1121 const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft;
1122 const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop;
1123 // target center
1124 const int targetCenterTop = targetRect.top() + targetMargins.top();
1125 const int targetCenterLeft = targetRect.left() + targetMargins.left();
1126 const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1;
1127 const int targetCenterRight = targetRect.right() - targetMargins.right() + 1;
1128 const int targetCenterWidth = targetCenterRight - targetCenterLeft;
1129 const int targetCenterHeight = targetCenterBottom - targetCenterTop;
1130
1131 QVarLengthArray<qreal, 16> xTarget; // x-coordinates of target rectangles
1132 QVarLengthArray<qreal, 16> yTarget; // y-coordinates of target rectangles
1133
1134 int columns = 3;
1135 int rows = 3;
1136 if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0)
1137 columns = qMax(3, 2 + qCeil(targetCenterWidth / qreal(sourceCenterWidth)));
1138 if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0)
1139 rows = qMax(3, 2 + qCeil(targetCenterHeight / qreal(sourceCenterHeight)));
1140
1141 xTarget.resize(columns + 1);
1142 yTarget.resize(rows + 1);
1143
1144 bool oldAA = painter->testRenderHint(QPainter::Antialiasing);
1145 if (painter->paintEngine()->type() != QPaintEngine::OpenGL
1146 && painter->paintEngine()->type() != QPaintEngine::OpenGL2
1147 && oldAA && painter->combinedTransform().type() != QTransform::TxNone) {
1148 painter->setRenderHint(QPainter::Antialiasing, false);
1149 }
1150
1151 xTarget[0] = targetRect.left();
1152 xTarget[1] = targetCenterLeft;
1153 xTarget[columns - 1] = targetCenterRight;
1154 xTarget[columns] = targetRect.left() + targetRect.width();
1155
1156 yTarget[0] = targetRect.top();
1157 yTarget[1] = targetCenterTop;
1158 yTarget[rows - 1] = targetCenterBottom;
1159 yTarget[rows] = targetRect.top() + targetRect.height();
1160
1161 qreal dx = targetCenterWidth;
1162 qreal dy = targetCenterHeight;
1163
1164 switch (rules.horizontal) {
1165 case Qt::StretchTile:
1166 dx = targetCenterWidth;
1167 break;
1168 case Qt::RepeatTile:
1169 dx = sourceCenterWidth;
1170 break;
1171 case Qt::RoundTile:
1172 dx = targetCenterWidth / qreal(columns - 2);
1173 break;
1174 }
1175
1176 for (int i = 2; i < columns - 1; ++i)
1177 xTarget[i] = xTarget[i - 1] + dx;
1178
1179 switch (rules.vertical) {
1180 case Qt::StretchTile:
1181 dy = targetCenterHeight;
1182 break;
1183 case Qt::RepeatTile:
1184 dy = sourceCenterHeight;
1185 break;
1186 case Qt::RoundTile:
1187 dy = targetCenterHeight / qreal(rows - 2);
1188 break;
1189 }
1190
1191 for (int i = 2; i < rows - 1; ++i)
1192 yTarget[i] = yTarget[i - 1] + dy;
1193
1194 // corners
1195 if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left
1196 int index = bool(hints & QDrawBorderPixmap::OpaqueTopLeft);
1197 sourceData[index].append(QRectF(sourceRect.topLeft(), QSizeF(sourceMargins.left(), sourceMargins.top())));
1198 targetData[index].append(QRectF(QPointF(xTarget[0], yTarget[0]), QPointF(xTarget[1], yTarget[1])));
1199 }
1200 if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right
1201 int index = bool(hints & QDrawBorderPixmap::OpaqueTopRight);
1202 sourceData[index].append(QRectF(QPointF(sourceCenterRight, sourceRect.top()), QSizeF(sourceMargins.right(), sourceMargins.top())));
1203 targetData[index].append(QRectF(QPointF(xTarget[columns-1], yTarget[0]), QPointF(xTarget[columns], yTarget[1])));
1204 }
1205 if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left
1206 int index = bool(hints & QDrawBorderPixmap::OpaqueBottomLeft);
1207 sourceData[index].append(QRectF(QPointF(sourceRect.left(), sourceCenterBottom), QSizeF(sourceMargins.left(), sourceMargins.bottom())));
1208 targetData[index].append(QRectF(QPointF(xTarget[0], yTarget[rows - 1]), QPointF(xTarget[1], yTarget[rows])));
1209 }
1210 if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right
1211 int index = bool(hints & QDrawBorderPixmap::OpaqueBottomRight);
1212 sourceData[index].append(QRectF(QPointF(sourceCenterRight, sourceCenterBottom), QSizeF(sourceMargins.right(), sourceMargins.bottom())));
1213 targetData[index].append(QRectF(QPointF(xTarget[columns - 1], yTarget[rows - 1]), QPointF(xTarget[columns], yTarget[rows])));
1214 }
1215
1216 // horizontal edges
1217 if (targetCenterWidth > 0 && sourceCenterWidth > 0) {
1218 if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
1219 int index = bool(hints & QDrawBorderPixmap::OpaqueTop);
1220 for (int i = 1; i < columns - 1; ++i) {
1221 if (rules.horizontal == Qt::RepeatTile && i == columns - 2) {
1222 sourceData[index].append(QRectF(QPointF(sourceCenterLeft, sourceRect.top()), QSizeF(xTarget[i + 1] - xTarget[i], sourceMargins.top())));
1223 } else {
1224 sourceData[index].append(QRectF(QPointF(sourceCenterLeft, sourceRect.top()), QSizeF(sourceCenterWidth, sourceMargins.top())));
1225 }
1226 targetData[index].append(QRectF(QPointF(xTarget[i], yTarget[0]), QPointF(xTarget[i + 1], yTarget[1])));
1227 }
1228 }
1229 if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
1230 int index = bool(hints & QDrawBorderPixmap::OpaqueBottom);
1231 for (int i = 1; i < columns - 1; ++i) {
1232 if (rules.horizontal == Qt::RepeatTile && i == columns - 2) {
1233 sourceData[index].append(QRectF(QPointF(sourceCenterLeft, sourceCenterBottom), QSizeF(xTarget[i + 1] - xTarget[i], sourceMargins.bottom())));
1234 } else {
1235 sourceData[index].append(QRectF(QPointF(sourceCenterLeft, sourceCenterBottom), QSizeF(sourceCenterWidth, sourceMargins.bottom())));
1236 }
1237 targetData[index].append(QRectF(QPointF(xTarget[i], yTarget[rows - 1]), QPointF(xTarget[i + 1], yTarget[rows])));
1238 }
1239 }
1240 }
1241
1242 // vertical edges
1243 if (targetCenterHeight > 0 && sourceCenterHeight > 0) {
1244 if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
1245 int index = bool(hints & QDrawBorderPixmap::OpaqueLeft);
1246 for (int i = 1; i < rows - 1; ++i) {
1247 if (rules.vertical == Qt::RepeatTile && i == rows - 2) {
1248 sourceData[index].append(QRectF(QPointF(sourceRect.left(), sourceCenterTop), QSizeF(sourceMargins.left(), yTarget[i + 1] - yTarget[i])));
1249 } else {
1250 sourceData[index].append(QRectF(QPointF(sourceRect.left(), sourceCenterTop), QSizeF(sourceMargins.left(), sourceCenterHeight)));
1251 }
1252 targetData[index].append(QRectF(QPointF(xTarget[0], yTarget[i]), QPointF(xTarget[1], yTarget[i + 1])));
1253 }
1254 }
1255 if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
1256 int index = bool(hints & QDrawBorderPixmap::OpaqueRight);
1257 for (int i = 1; i < rows - 1; ++i) {
1258 if (rules.vertical == Qt::RepeatTile && i == rows - 2) {
1259 sourceData[index].append(QRectF(QPointF(sourceCenterRight, sourceCenterTop), QSizeF(sourceMargins.right(), yTarget[i + 1] - yTarget[i])));
1260 } else {
1261 sourceData[index].append(QRectF(QPointF(sourceCenterRight, sourceCenterTop), QSizeF(sourceMargins.right(), sourceCenterHeight)));
1262 }
1263 targetData[index].append(QRectF(QPointF(xTarget[columns - 1], yTarget[i]), QPointF(xTarget[columns], yTarget[i + 1])));
1264 }
1265 }
1266 }
1267
1268 // center
1269 if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
1270 int index = bool(hints & QDrawBorderPixmap::OpaqueCenter);
1271 for (int j = 1; j < rows - 1; ++j) {
1272 qreal sourceHeight = (rules.vertical == Qt::RepeatTile && j == rows - 2) ? yTarget[j + 1] - yTarget[j] : sourceCenterHeight;
1273 for (int i = 1; i < columns - 1; ++i) {
1274 qreal sourceWidth = (rules.horizontal == Qt::RepeatTile && i == columns - 2) ? xTarget[i + 1] - xTarget[i] : sourceCenterWidth;
1275 sourceData[index].append(QRectF(QPointF(sourceCenterLeft, sourceCenterTop), QSizeF(sourceWidth, sourceHeight)));
1276 targetData[index].append(QRectF(QPointF(xTarget[i], yTarget[j]), QPointF(xTarget[i + 1], yTarget[j + 1])));
1277 }
1278 }
1279 }
1280
1281 for (int i = 0; i < 2; ++i) {
1282 if (sourceData[i].size())
1283 painter->drawPixmapFragments(targetData[i].data(), sourceData[i].data(), sourceData[i].size(), pixmap, i == 1 ? QPainter::OpaqueHint : QPainter::PixmapFragmentHint(0));
1284 }
1285
1286 if (oldAA)
1287 painter->setRenderHint(QPainter::Antialiasing, true);
1288 }
1289
1290 QT_END_NAMESPACE
1291