Fixing warnings on GCC... (I)
[qt-netbsd.git] / src / gui / painting / qdrawutil.cpp
blob1182b9a13c7f56a8e451ce0b804100a6c8df13a5
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
38 ** $QT_END_LICENSE$
40 ****************************************************************************/
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>
52 QT_BEGIN_NAMESPACE
54 /*!
55 \headerfile <qdrawutil.h>
56 \title Drawing Utility Functions
58 \sa QPainter
61 /*!
62 \fn void qDrawShadeLine(QPainter *painter, int x1, int y1, int x2, int y2,
63 const QPalette &palette, bool sunken,
64 int lineWidth, int midLineWidth)
65 \relates <qdrawutil.h>
67 Draws a horizontal (\a y1 == \a y2) or vertical (\a x1 == \a x2)
68 shaded line using the given \a painter. Note that nothing is
69 drawn if \a y1 != \a y2 and \a x1 != \a x2 (i.e. the line is
70 neither horizontal nor vertical).
72 The provided \a palette specifies the shading colors (\l
73 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
74 {QPalette::mid()}{middle} colors). The given \a lineWidth
75 specifies the line width for each of the lines; it is not the
76 total line width. The given \a midLineWidth specifies the width of
77 a middle line drawn in the QPalette::mid() color.
79 The line appears sunken if \a sunken is true, otherwise raised.
81 \warning This function does not look at QWidget::style() or
82 QApplication::style(). Use the drawing functions in QStyle to
83 make widgets that follow the current GUI style.
86 Alternatively you can use a QFrame widget and apply the
87 QFrame::setFrameStyle() function to display a shaded line:
89 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 0
91 \sa qDrawShadeRect(), qDrawShadePanel(), QStyle
94 void qDrawShadeLine(QPainter *p, int x1, int y1, int x2, int y2,
95 const QPalette &pal, bool sunken,
96 int lineWidth, int midLineWidth)
98 if (!(p && lineWidth >= 0 && midLineWidth >= 0)) {
99 qWarning("qDrawShadeLine: Invalid parameters");
100 return;
102 int tlw = lineWidth*2 + midLineWidth; // total line width
103 QPen oldPen = p->pen(); // save pen
104 if (sunken)
105 p->setPen(pal.color(QPalette::Dark));
106 else
107 p->setPen(pal.light().color());
108 QPolygon a;
109 int i;
110 if (y1 == y2) { // horizontal line
111 int y = y1 - tlw/2;
112 if (x1 > x2) { // swap x1 and x2
113 int t = x1;
114 x1 = x2;
115 x2 = t;
117 x2--;
118 for (i=0; i<lineWidth; i++) { // draw top shadow
119 a.setPoints(3, x1+i, y+tlw-1-i,
120 x1+i, y+i,
121 x2-i, y+i);
122 p->drawPolyline(a);
124 if (midLineWidth > 0) {
125 p->setPen(pal.mid().color());
126 for (i=0; i<midLineWidth; i++) // draw lines in the middle
127 p->drawLine(x1+lineWidth, y+lineWidth+i,
128 x2-lineWidth, y+lineWidth+i);
130 if (sunken)
131 p->setPen(pal.light().color());
132 else
133 p->setPen(pal.dark().color());
134 for (i=0; i<lineWidth; i++) { // draw bottom shadow
135 a.setPoints(3, x1+i, y+tlw-i-1,
136 x2-i, y+tlw-i-1,
137 x2-i, y+i+1);
138 p->drawPolyline(a);
141 else if (x1 == x2) { // vertical line
142 int x = x1 - tlw/2;
143 if (y1 > y2) { // swap y1 and y2
144 int t = y1;
145 y1 = y2;
146 y2 = t;
148 y2--;
149 for (i=0; i<lineWidth; i++) { // draw left shadow
150 a.setPoints(3, x+i, y2,
151 x+i, y1+i,
152 x+tlw-1, y1+i);
153 p->drawPolyline(a);
155 if (midLineWidth > 0) {
156 p->setPen(pal.mid().color());
157 for (i=0; i<midLineWidth; i++) // draw lines in the middle
158 p->drawLine(x+lineWidth+i, y1+lineWidth, x+lineWidth+i, y2);
160 if (sunken)
161 p->setPen(pal.light().color());
162 else
163 p->setPen(pal.dark().color());
164 for (i=0; i<lineWidth; i++) { // draw right shadow
165 a.setPoints(3, x+lineWidth, y2-i,
166 x+tlw-i-1, y2-i,
167 x+tlw-i-1, y1+lineWidth);
168 p->drawPolyline(a);
171 p->setPen(oldPen);
175 \fn void qDrawShadeRect(QPainter *painter, int x, int y, int width, int height,
176 const QPalette &palette, bool sunken,
177 int lineWidth, int midLineWidth,
178 const QBrush *fill)
179 \relates <qdrawutil.h>
181 Draws the shaded rectangle beginning at (\a x, \a y) with the
182 given \a width and \a height using the provided \a painter.
184 The provide \a palette specifies the shading colors (\l
185 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
186 {QPalette::mid()}{middle} colors. The given \a lineWidth
187 specifies the line width for each of the lines; it is not the
188 total line width. The \a midLineWidth specifies the width of a
189 middle line drawn in the QPalette::mid() color. The rectangle's
190 interior is filled with the \a fill brush unless \a fill is 0.
192 The rectangle appears sunken if \a sunken is true, otherwise
193 raised.
195 \warning This function does not look at QWidget::style() or
196 QApplication::style(). Use the drawing functions in QStyle to make
197 widgets that follow the current GUI style.
199 Alternatively you can use a QFrame widget and apply the
200 QFrame::setFrameStyle() function to display a shaded rectangle:
202 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 1
204 \sa qDrawShadeLine(), qDrawShadePanel(), qDrawPlainRect(), QStyle
207 void qDrawShadeRect(QPainter *p, int x, int y, int w, int h,
208 const QPalette &pal, bool sunken,
209 int lineWidth, int midLineWidth,
210 const QBrush *fill)
212 if (w == 0 || h == 0)
213 return;
214 if (! (w > 0 && h > 0 && lineWidth >= 0 && midLineWidth >= 0)) {
215 qWarning("qDrawShadeRect: Invalid parameters");
216 return;
218 QPen oldPen = p->pen();
219 if (sunken)
220 p->setPen(pal.dark().color());
221 else
222 p->setPen(pal.light().color());
223 int x1=x, y1=y, x2=x+w-1, y2=y+h-1;
225 if (lineWidth == 1 && midLineWidth == 0) {// standard shade rectangle
226 p->drawRect(x1, y1, w-2, h-2);
227 if (sunken)
228 p->setPen(pal.light().color());
229 else
230 p->setPen(pal.dark().color());
231 QLineF lines[4] = { QLineF(x1+1, y1+1, x2-2, y1+1),
232 QLineF(x1+1, y1+2, x1+1, y2-2),
233 QLineF(x1, y2, x2, y2),
234 QLineF(x2,y1, x2,y2-1) };
235 p->drawLines(lines, 4); // draw bottom/right lines
236 } else { // more complicated
237 int m = lineWidth+midLineWidth;
238 int i, j=0, k=m;
239 for (i=0; i<lineWidth; i++) { // draw top shadow
240 QLineF lines[4] = { QLineF(x1+i, y2-i, x1+i, y1+i),
241 QLineF(x1+i, y1+i, x2-i, y1+i),
242 QLineF(x1+k, y2-k, x2-k, y2-k),
243 QLineF(x2-k, y2-k, x2-k, y1+k) };
244 p->drawLines(lines, 4);
245 k++;
247 p->setPen(pal.mid().color());
248 j = lineWidth*2;
249 for (i=0; i<midLineWidth; i++) { // draw lines in the middle
250 p->drawRect(x1+lineWidth+i, y1+lineWidth+i, w-j-1, h-j-1);
251 j += 2;
253 if (sunken)
254 p->setPen(pal.light().color());
255 else
256 p->setPen(pal.dark().color());
257 k = m;
258 for (i=0; i<lineWidth; i++) { // draw bottom shadow
259 QLineF lines[4] = { QLineF(x1+1+i, y2-i, x2-i, y2-i),
260 QLineF(x2-i, y2-i, x2-i, y1+i+1),
261 QLineF(x1+k, y2-k, x1+k, y1+k),
262 QLineF(x1+k, y1+k, x2-k, y1+k) };
263 p->drawLines(lines, 4);
264 k++;
267 if (fill) {
268 QBrush oldBrush = p->brush();
269 int tlw = lineWidth + midLineWidth;
270 p->setPen(Qt::NoPen);
271 p->setBrush(*fill);
272 p->drawRect(x+tlw, y+tlw, w-2*tlw, h-2*tlw);
273 p->setBrush(oldBrush);
275 p->setPen(oldPen); // restore pen
280 \fn void qDrawShadePanel(QPainter *painter, int x, int y, int width, int height,
281 const QPalette &palette, bool sunken,
282 int lineWidth, const QBrush *fill)
283 \relates <qdrawutil.h>
285 Draws the shaded panel beginning at (\a x, \a y) with the given \a
286 width and \a height using the provided \a painter and the given \a
287 lineWidth.
289 The given \a palette specifies the shading colors (\l
290 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
291 {QPalette::mid()}{middle} colors). The panel's interior is filled
292 with the \a fill brush unless \a fill is 0.
294 The panel appears sunken if \a sunken is true, otherwise raised.
296 \warning This function does not look at QWidget::style() or
297 QApplication::style(). Use the drawing functions in QStyle to make
298 widgets that follow the current GUI style.
300 Alternatively you can use a QFrame widget and apply the
301 QFrame::setFrameStyle() function to display a shaded panel:
303 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 2
305 \sa qDrawWinPanel(), qDrawShadeLine(), qDrawShadeRect(), QStyle
308 void qDrawShadePanel(QPainter *p, int x, int y, int w, int h,
309 const QPalette &pal, bool sunken,
310 int lineWidth, const QBrush *fill)
312 if (w == 0 || h == 0)
313 return;
314 if (!(w > 0 && h > 0 && lineWidth >= 0)) {
315 qWarning("qDrawShadePanel: Invalid parameters");
317 QColor shade = pal.dark().color();
318 QColor light = pal.light().color();
319 if (fill) {
320 if (fill->color() == shade)
321 shade = pal.shadow().color();
322 if (fill->color() == light)
323 light = pal.midlight().color();
325 QPen oldPen = p->pen(); // save pen
326 QVector<QLineF> lines;
327 lines.reserve(2*lineWidth);
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++);
341 x2 = x1;
342 y1 = y+h-2;
343 for (i=0; i<lineWidth; i++) { // left shado
344 lines << QLineF(x1++, y1, x2++, y2--);
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--);
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);
364 p->drawLines(lines);
365 if (fill) // fill with fill color
366 p->fillRect(x+lineWidth, y+lineWidth, w-lineWidth*2, h-lineWidth*2, *fill);
367 p->setPen(oldPen); // restore pen
372 \internal
373 This function draws a rectangle with two pixel line width.
374 It is called from qDrawWinButton() and qDrawWinPanel().
376 c1..c4 and fill are used:
378 1 1 1 1 1 2
379 1 3 3 3 4 2
380 1 3 F F 4 2
381 1 3 F F 4 2
382 1 4 4 4 4 2
383 2 2 2 2 2 2
386 static void qDrawWinShades(QPainter *p,
387 int x, int y, int w, int h,
388 const QColor &c1, const QColor &c2,
389 const QColor &c3, const QColor &c4,
390 const QBrush *fill)
392 if (w < 2 || h < 2) // can't do anything with that
393 return;
394 QPen oldPen = p->pen();
395 QPoint a[3] = { QPoint(x, y+h-2), QPoint(x, y), QPoint(x+w-2, y) };
396 p->setPen(c1);
397 p->drawPolyline(a, 3);
398 QPoint b[3] = { QPoint(x, y+h-1), QPoint(x+w-1, y+h-1), QPoint(x+w-1, y) };
399 p->setPen(c2);
400 p->drawPolyline(b, 3);
401 if (w > 4 && h > 4) {
402 QPoint c[3] = { QPoint(x+1, y+h-3), QPoint(x+1, y+1), QPoint(x+w-3, y+1) };
403 p->setPen(c3);
404 p->drawPolyline(c, 3);
405 QPoint d[3] = { QPoint(x+1, y+h-2), QPoint(x+w-2, y+h-2), QPoint(x+w-2, y+1) };
406 p->setPen(c4);
407 p->drawPolyline(d, 3);
408 if (fill)
409 p->fillRect(QRect(x+2, y+2, w-4, h-4), *fill);
411 p->setPen(oldPen);
416 \fn void qDrawWinButton(QPainter *painter, int x, int y, int width, int height,
417 const QPalette &palette, bool sunken,
418 const QBrush *fill)
419 \relates <qdrawutil.h>
421 Draws the Windows-style button specified by the given point (\a x,
422 \a y}, \a width and \a height using the provided \a painter with a
423 line width of 2 pixels. The button's interior is filled with the
424 \a{fill} brush unless \a fill is 0.
426 The given \a palette specifies the shading colors (\l
427 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
428 {QPalette::mid()}{middle} colors).
430 The button appears sunken if \a sunken is true, otherwise raised.
432 \warning This function does not look at QWidget::style() or
433 QApplication::style()-> Use the drawing functions in QStyle to make
434 widgets that follow the current GUI style.
436 \sa qDrawWinPanel(), QStyle
439 void qDrawWinButton(QPainter *p, int x, int y, int w, int h,
440 const QPalette &pal, bool sunken,
441 const QBrush *fill)
443 if (sunken)
444 qDrawWinShades(p, x, y, w, h,
445 pal.shadow().color(), pal.light().color(), pal.dark().color(),
446 pal.button().color(), fill);
447 else
448 qDrawWinShades(p, x, y, w, h,
449 pal.light().color(), pal.shadow().color(), pal.button().color(),
450 pal.dark().color(), fill);
454 \fn void qDrawWinPanel(QPainter *painter, int x, int y, int width, int height,
455 const QPalette &palette, bool sunken,
456 const QBrush *fill)
457 \relates <qdrawutil.h>
459 Draws the Windows-style panel specified by the given point(\a x,
460 \a y), \a width and \a height using the provided \a painter with a
461 line width of 2 pixels. The button's interior is filled with the
462 \a fill brush unless \a fill is 0.
464 The given \a palette specifies the shading colors. The panel
465 appears sunken if \a sunken is true, otherwise raised.
467 \warning This function does not look at QWidget::style() or
468 QApplication::style(). Use the drawing functions in QStyle to make
469 widgets that follow the current GUI style.
471 Alternatively you can use a QFrame widget and apply the
472 QFrame::setFrameStyle() function to display a shaded panel:
474 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 3
476 \sa qDrawShadePanel(), qDrawWinButton(), QStyle
479 void qDrawWinPanel(QPainter *p, int x, int y, int w, int h,
480 const QPalette &pal, bool sunken,
481 const QBrush *fill)
483 if (sunken)
484 qDrawWinShades(p, x, y, w, h,
485 pal.dark().color(), pal.light().color(), pal.shadow().color(),
486 pal.midlight().color(), fill);
487 else
488 qDrawWinShades(p, x, y, w, h,
489 pal.light().color(), pal.shadow().color(), pal.midlight().color(),
490 pal.dark().color(), fill);
494 \fn void qDrawPlainRect(QPainter *painter, int x, int y, int width, int height, const QColor &lineColor,
495 int lineWidth, const QBrush *fill)
496 \relates <qdrawutil.h>
498 Draws the plain rectangle beginning at (\a x, \a y) with the given
499 \a width and \a height, using the specified \a painter, \a lineColor
500 and \a lineWidth. The rectangle's interior is filled with the \a
501 fill brush unless \a fill is 0.
503 \warning This function does not look at QWidget::style() or
504 QApplication::style(). Use the drawing functions in QStyle to make
505 widgets that follow the current GUI style.
507 Alternatively you can use a QFrame widget and apply the
508 QFrame::setFrameStyle() function to display a plain rectangle:
510 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 4
512 \sa qDrawShadeRect(), QStyle
515 void qDrawPlainRect(QPainter *p, int x, int y, int w, int h, const QColor &c,
516 int lineWidth, const QBrush *fill)
518 if (w == 0 || h == 0)
519 return;
520 if (!(w > 0 && h > 0 && lineWidth >= 0)) {
521 qWarning("qDrawPlainRect: Invalid parameters");
523 QPen oldPen = p->pen();
524 QBrush oldBrush = p->brush();
525 p->setPen(c);
526 p->setBrush(Qt::NoBrush);
527 for (int i=0; i<lineWidth; i++)
528 p->drawRect(x+i, y+i, w-i*2 - 1, h-i*2 - 1);
529 if (fill) { // fill with fill color
530 p->setPen(Qt::NoPen);
531 p->setBrush(*fill);
532 p->drawRect(x+lineWidth, y+lineWidth, w-lineWidth*2, h-lineWidth*2);
534 p->setPen(oldPen);
535 p->setBrush(oldBrush);
538 /*****************************************************************************
539 Overloaded functions.
540 *****************************************************************************/
543 \fn void qDrawShadeLine(QPainter *painter, const QPoint &p1, const QPoint &p2,
544 const QPalette &palette, bool sunken, int lineWidth, int midLineWidth)
545 \relates <qdrawutil.h>
546 \overload
548 Draws a horizontal or vertical shaded line between \a p1 and \a p2
549 using the given \a painter. Note that nothing is drawn if the line
550 between the points would be neither horizontal nor vertical.
552 The provided \a palette specifies the shading colors (\l
553 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
554 {QPalette::mid()}{middle} colors). The given \a lineWidth
555 specifies the line width for each of the lines; it is not the
556 total line width. The given \a midLineWidth specifies the width of
557 a middle line drawn in the QPalette::mid() color.
559 The line appears sunken if \a sunken is true, otherwise raised.
561 \warning This function does not look at QWidget::style() or
562 QApplication::style(). Use the drawing functions in QStyle to
563 make widgets that follow the current GUI style.
566 Alternatively you can use a QFrame widget and apply the
567 QFrame::setFrameStyle() function to display a shaded line:
569 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 5
571 \sa qDrawShadeRect(), qDrawShadePanel(), QStyle
574 void qDrawShadeLine(QPainter *p, const QPoint &p1, const QPoint &p2,
575 const QPalette &pal, bool sunken,
576 int lineWidth, int midLineWidth)
578 qDrawShadeLine(p, p1.x(), p1.y(), p2.x(), p2.y(), pal, sunken,
579 lineWidth, midLineWidth);
583 \fn void qDrawShadeRect(QPainter *painter, const QRect &rect, const QPalette &palette,
584 bool sunken, int lineWidth, int midLineWidth, const QBrush *fill)
585 \relates <qdrawutil.h>
586 \overload
588 Draws the shaded rectangle specified by \a rect using the given \a painter.
590 The provide \a palette specifies the shading colors (\l
591 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
592 {QPalette::mid()}{middle} colors. The given \a lineWidth
593 specifies the line width for each of the lines; it is not the
594 total line width. The \a midLineWidth specifies the width of a
595 middle line drawn in the QPalette::mid() color. The rectangle's
596 interior is filled with the \a fill brush unless \a fill is 0.
598 The rectangle appears sunken if \a sunken is true, otherwise
599 raised.
601 \warning This function does not look at QWidget::style() or
602 QApplication::style(). Use the drawing functions in QStyle to make
603 widgets that follow the current GUI style.
605 Alternatively you can use a QFrame widget and apply the
606 QFrame::setFrameStyle() function to display a shaded rectangle:
608 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 6
610 \sa qDrawShadeLine(), qDrawShadePanel(), qDrawPlainRect(), QStyle
613 void qDrawShadeRect(QPainter *p, const QRect &r,
614 const QPalette &pal, bool sunken,
615 int lineWidth, int midLineWidth,
616 const QBrush *fill)
618 qDrawShadeRect(p, r.x(), r.y(), r.width(), r.height(), pal, sunken,
619 lineWidth, midLineWidth, fill);
623 \fn void qDrawShadePanel(QPainter *painter, const QRect &rect, const QPalette &palette,
624 bool sunken, int lineWidth, const QBrush *fill)
625 \relates <qdrawutil.h>
626 \overload
628 Draws the shaded panel at the rectangle specified by \a rect using the
629 given \a painter and the given \a lineWidth.
631 The given \a palette specifies the shading colors (\l
632 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
633 {QPalette::mid()}{middle} colors). The panel's interior is filled
634 with the \a fill brush unless \a fill is 0.
636 The panel appears sunken if \a sunken is true, otherwise raised.
638 \warning This function does not look at QWidget::style() or
639 QApplication::style(). Use the drawing functions in QStyle to make
640 widgets that follow the current GUI style.
642 Alternatively you can use a QFrame widget and apply the
643 QFrame::setFrameStyle() function to display a shaded panel:
645 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 7
647 \sa qDrawWinPanel(), qDrawShadeLine(), qDrawShadeRect(), QStyle
650 void qDrawShadePanel(QPainter *p, const QRect &r,
651 const QPalette &pal, bool sunken,
652 int lineWidth, const QBrush *fill)
654 qDrawShadePanel(p, r.x(), r.y(), r.width(), r.height(), pal, sunken,
655 lineWidth, fill);
659 \fn void qDrawWinButton(QPainter *painter, const QRect &rect, const QPalette &palette,
660 bool sunken, const QBrush *fill)
661 \relates <qdrawutil.h>
662 \overload
664 Draws the Windows-style button at the rectangle specified by \a rect using
665 the given \a painter with a line width of 2 pixels. The button's interior
666 is filled with the \a{fill} brush unless \a fill is 0.
668 The given \a palette specifies the shading colors (\l
669 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
670 {QPalette::mid()}{middle} colors).
672 The button appears sunken if \a sunken is true, otherwise raised.
674 \warning This function does not look at QWidget::style() or
675 QApplication::style()-> Use the drawing functions in QStyle to make
676 widgets that follow the current GUI style.
678 \sa qDrawWinPanel(), QStyle
681 void qDrawWinButton(QPainter *p, const QRect &r,
682 const QPalette &pal, bool sunken, const QBrush *fill)
684 qDrawWinButton(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, fill);
688 \fn void qDrawWinPanel(QPainter *painter, const QRect &rect, const QPalette &palette,
689 bool sunken, const QBrush *fill)
690 \overload
692 Draws the Windows-style panel at the rectangle specified by \a rect using
693 the given \a painter with a line width of 2 pixels. The button's interior
694 is filled with the \a fill brush unless \a fill is 0.
696 The given \a palette specifies the shading colors. The panel
697 appears sunken if \a sunken is true, otherwise raised.
699 \warning This function does not look at QWidget::style() or
700 QApplication::style(). Use the drawing functions in QStyle to make
701 widgets that follow the current GUI style.
703 Alternatively you can use a QFrame widget and apply the
704 QFrame::setFrameStyle() function to display a shaded panel:
706 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 8
708 \sa qDrawShadePanel(), qDrawWinButton(), QStyle
711 void qDrawWinPanel(QPainter *p, const QRect &r,
712 const QPalette &pal, bool sunken, const QBrush *fill)
714 qDrawWinPanel(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, fill);
718 \fn void qDrawPlainRect(QPainter *painter, const QRect &rect, const QColor &lineColor, int lineWidth, const QBrush *fill)
719 \relates <qdrawutil.h>
720 \overload
722 Draws the plain rectangle specified by \a rect using the given \a painter,
723 \a lineColor and \a lineWidth. The rectangle's interior is filled with the
724 \a fill brush unless \a fill is 0.
726 \warning This function does not look at QWidget::style() or
727 QApplication::style(). Use the drawing functions in QStyle to make
728 widgets that follow the current GUI style.
730 Alternatively you can use a QFrame widget and apply the
731 QFrame::setFrameStyle() function to display a plain rectangle:
733 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 9
735 \sa qDrawShadeRect(), QStyle
738 void qDrawPlainRect(QPainter *p, const QRect &r, const QColor &c,
739 int lineWidth, const QBrush *fill)
741 qDrawPlainRect(p, r.x(), r.y(), r.width(), r.height(), c,
742 lineWidth, fill);
745 #ifdef QT3_SUPPORT
746 static void qDrawWinArrow(QPainter *p, Qt::ArrowType type, bool down,
747 int x, int y, int w, int h,
748 const QPalette &pal, bool enabled)
750 QPolygon a; // arrow polygon
751 switch (type) {
752 case Qt::UpArrow:
753 a.setPoints(7, -3,1, 3,1, -2,0, 2,0, -1,-1, 1,-1, 0,-2);
754 break;
755 case Qt::DownArrow:
756 a.setPoints(7, -3,-1, 3,-1, -2,0, 2,0, -1,1, 1,1, 0,2);
757 break;
758 case Qt::LeftArrow:
759 a.setPoints(7, 1,-3, 1,3, 0,-2, 0,2, -1,-1, -1,1, -2,0);
760 break;
761 case Qt::RightArrow:
762 a.setPoints(7, -1,-3, -1,3, 0,-2, 0,2, 1,-1, 1,1, 2,0);
763 break;
764 default:
765 break;
767 if (a.isEmpty())
768 return;
770 if (down) {
771 x++;
772 y++;
775 QPen savePen = p->pen(); // save current pen
776 if (down)
777 p->setBrushOrigin(p->brushOrigin() + QPoint(1,1));
778 p->fillRect(x, y, w, h, pal.brush(QPalette::Button));
779 if (down)
780 p->setBrushOrigin(p->brushOrigin() - QPoint(1,1));
781 if (enabled) {
782 a.translate(x+w/2, y+h/2);
783 p->setPen(pal.foreground().color());
784 p->drawLine(a.at(0), a.at(1));
785 p->drawLine(a.at(2), a.at(2));
786 p->drawPoint(a[6]);
787 } else {
788 a.translate(x+w/2+1, y+h/2+1);
789 p->setPen(pal.light().color());
790 p->drawLine(a.at(0), a.at(1));
791 p->drawLine(a.at(2), a.at(2));
792 p->drawPoint(a[6]);
793 a.translate(-1, -1);
794 p->setPen(pal.mid().color());
795 p->drawLine(a.at(0), a.at(1));
796 p->drawLine(a.at(2), a.at(2));
797 p->drawPoint(a[6]);
799 p->setPen(savePen); // restore pen
801 #endif // QT3_SUPPORT
803 #if defined(Q_CC_MSVC)
804 #pragma warning(disable: 4244)
805 #endif
807 #ifdef QT3_SUPPORT
808 #ifndef QT_NO_STYLE_MOTIF
809 // motif arrows look the same whether they are used or not
810 // is this correct?
811 static void qDrawMotifArrow(QPainter *p, Qt::ArrowType type, bool down,
812 int x, int y, int w, int h,
813 const QPalette &pal, bool)
815 QPolygon bFill; // fill polygon
816 QPolygon bTop; // top shadow.
817 QPolygon bBot; // bottom shadow.
818 QPolygon bLeft; // left shadow.
819 QTransform matrix; // xform matrix
820 bool vertical = type == Qt::UpArrow || type == Qt::DownArrow;
821 bool horizontal = !vertical;
822 int dim = w < h ? w : h;
823 int colspec = 0x0000; // color specification array
825 if (dim < 2) // too small arrow
826 return;
828 if (dim > 3) {
829 if (dim > 6)
830 bFill.resize(dim & 1 ? 3 : 4);
831 bTop.resize((dim/2)*2);
832 bBot.resize(dim & 1 ? dim + 1 : dim);
833 bLeft.resize(dim > 4 ? 4 : 2);
834 bLeft.putPoints(0, 2, 0,0, 0,dim-1);
835 if (dim > 4)
836 bLeft.putPoints(2, 2, 1,2, 1,dim-3);
837 bTop.putPoints(0, 4, 1,0, 1,1, 2,1, 3,1);
838 bBot.putPoints(0, 4, 1,dim-1, 1,dim-2, 2,dim-2, 3,dim-2);
840 for(int i=0; i<dim/2-2 ; i++) {
841 bTop.putPoints(i*2+4, 2, 2+i*2,2+i, 5+i*2, 2+i);
842 bBot.putPoints(i*2+4, 2, 2+i*2,dim-3-i, 5+i*2,dim-3-i);
844 if (dim & 1) // odd number size: extra line
845 bBot.putPoints(dim-1, 2, dim-3,dim/2, dim-1,dim/2);
846 if (dim > 6) { // dim>6: must fill interior
847 bFill.putPoints(0, 2, 1,dim-3, 1,2);
848 if (dim & 1) // if size is an odd number
849 bFill.setPoint(2, dim - 3, dim / 2);
850 else
851 bFill.putPoints(2, 2, dim-4,dim/2-1, dim-4,dim/2);
854 else {
855 if (dim == 3) { // 3x3 arrow pattern
856 bLeft.setPoints(4, 0,0, 0,2, 1,1, 1,1);
857 bTop .setPoints(2, 1,0, 1,0);
858 bBot .setPoints(2, 1,2, 2,1);
860 else { // 2x2 arrow pattern
861 bLeft.setPoints(2, 0,0, 0,1);
862 bTop .setPoints(2, 1,0, 1,0);
863 bBot .setPoints(2, 1,1, 1,1);
867 if (type == Qt::UpArrow || type == Qt::LeftArrow) {
868 matrix.translate(x, y);
869 if (vertical) {
870 matrix.translate(0, h - 1);
871 matrix.rotate(-90);
872 } else {
873 matrix.translate(w - 1, h - 1);
874 matrix.rotate(180);
876 if (down)
877 colspec = horizontal ? 0x2334 : 0x2343;
878 else
879 colspec = horizontal ? 0x1443 : 0x1434;
881 else if (type == Qt::DownArrow || type == Qt::RightArrow) {
882 matrix.translate(x, y);
883 if (vertical) {
884 matrix.translate(w-1, 0);
885 matrix.rotate(90);
887 if (down)
888 colspec = horizontal ? 0x2443 : 0x2434;
889 else
890 colspec = horizontal ? 0x1334 : 0x1343;
893 const QColor *cols[5];
894 cols[0] = 0;
895 cols[1] = &pal.button().color();
896 cols[2] = &pal.mid().color();
897 cols[3] = &pal.light().color();
898 cols[4] = &pal.dark().color();
899 #define CMID *cols[(colspec>>12) & 0xf]
900 #define CLEFT *cols[(colspec>>8) & 0xf]
901 #define CTOP *cols[(colspec>>4) & 0xf]
902 #define CBOT *cols[colspec & 0xf]
904 QPen savePen = p->pen(); // save current pen
905 QBrush saveBrush = p->brush(); // save current brush
906 QTransform wxm = p->transform();
907 QPen pen(Qt::NoPen);
908 const QBrush &brush = pal.brush(QPalette::Button);
910 p->setPen(pen);
911 p->setBrush(brush);
912 p->setTransform(matrix, true); // set transformation matrix
913 p->drawPolygon(bFill); // fill arrow
914 p->setBrush(Qt::NoBrush); // don't fill
916 p->setPen(CLEFT);
917 p->drawLines(bLeft);
918 p->setPen(CTOP);
919 p->drawLines(bTop);
920 p->setPen(CBOT);
921 p->drawLines(bBot);
923 p->setTransform(wxm);
924 p->setBrush(saveBrush); // restore brush
925 p->setPen(savePen); // restore pen
927 #undef CMID
928 #undef CLEFT
929 #undef CTOP
930 #undef CBOT
932 #endif // QT_NO_STYLE_MOTIF
934 QRect qItemRect(QPainter *p, Qt::GUIStyle gs,
935 int x, int y, int w, int h,
936 int flags,
937 bool enabled,
938 const QPixmap *pixmap,
939 const QString& text, int len)
941 QRect result;
943 if (pixmap) {
944 if ((flags & Qt::AlignVCenter) == Qt::AlignVCenter)
945 y += h/2 - pixmap->height()/2;
946 else if ((flags & Qt::AlignBottom) == Qt::AlignBottom)
947 y += h - pixmap->height();
948 if ((flags & Qt::AlignRight) == Qt::AlignRight)
949 x += w - pixmap->width();
950 else if ((flags & Qt::AlignHCenter) == Qt::AlignHCenter)
951 x += w/2 - pixmap->width()/2;
952 else if ((flags & Qt::AlignLeft) != Qt::AlignLeft && QApplication::isRightToLeft())
953 x += w - pixmap->width();
954 result = QRect(x, y, pixmap->width(), pixmap->height());
955 } else if (!text.isNull() && p) {
956 result = p->boundingRect(QRect(x, y, w, h), flags, text.left(len));
957 if (gs == Qt::WindowsStyle && !enabled) {
958 result.setWidth(result.width()+1);
959 result.setHeight(result.height()+1);
961 } else {
962 result = QRect(x, y, w, h);
965 return result;
968 void qDrawArrow(QPainter *p, Qt::ArrowType type, Qt::GUIStyle style, bool down,
969 int x, int y, int w, int h,
970 const QPalette &pal, bool enabled)
972 switch (style) {
973 case Qt::WindowsStyle:
974 qDrawWinArrow(p, type, down, x, y, w, h, pal, enabled);
975 break;
976 #ifndef QT_NO_STYLE_MOTIF
977 case Qt::MotifStyle:
978 qDrawMotifArrow(p, type, down, x, y, w, h, pal, enabled);
979 break;
980 #endif
981 default:
982 qWarning("qDrawArrow: Requested unsupported GUI style");
986 void qDrawItem(QPainter *p, Qt::GUIStyle gs,
987 int x, int y, int w, int h,
988 int flags,
989 const QPalette &pal, bool enabled,
990 const QPixmap *pixmap,
991 const QString& text, int len , const QColor* penColor)
993 p->setPen(penColor?*penColor:pal.foreground().color());
994 if (pixmap) {
995 QPixmap pm(*pixmap);
996 bool clip = (flags & Qt::TextDontClip) == 0;
997 if (clip) {
998 if (pm.width() < w && pm.height() < h)
999 clip = false;
1000 else
1001 p->setClipRect(x, y, w, h);
1003 if ((flags & Qt::AlignVCenter) == Qt::AlignVCenter)
1004 y += h/2 - pm.height()/2;
1005 else if ((flags & Qt::AlignBottom) == Qt::AlignBottom)
1006 y += h - pm.height();
1007 if ((flags & Qt::AlignRight) == Qt::AlignRight)
1008 x += w - pm.width();
1009 else if ((flags & Qt::AlignHCenter) == Qt::AlignHCenter)
1010 x += w/2 - pm.width()/2;
1011 else if (((flags & Qt::AlignLeft) != Qt::AlignLeft) && QApplication::isRightToLeft()) // Qt::AlignAuto && rightToLeft
1012 x += w - pm.width();
1014 if (!enabled) {
1015 if (pm.hasAlphaChannel()) { // pixmap with a mask
1016 pm = pm.mask();
1017 } else if (pm.depth() == 1) { // monochrome pixmap, no mask
1019 #ifndef QT_NO_IMAGE_HEURISTIC_MASK
1020 } else { // color pixmap, no mask
1021 QString k = QString::fromLatin1("$qt-drawitem-%1").arg(pm.cacheKey());
1022 if (!QPixmapCache::find(k, pm)) {
1023 pm = pm.createHeuristicMask();
1024 pm.setMask((QBitmap&)pm);
1025 QPixmapCache::insert(k, pm);
1027 #endif
1029 if (gs == Qt::WindowsStyle) {
1030 p->setPen(pal.light().color());
1031 p->drawPixmap(x+1, y+1, pm);
1032 p->setPen(pal.text().color());
1035 p->drawPixmap(x, y, pm);
1036 if (clip)
1037 p->setClipping(false);
1038 } else if (!text.isNull()) {
1039 if (gs == Qt::WindowsStyle && !enabled) {
1040 p->setPen(pal.light().color());
1041 p->drawText(x+1, y+1, w, h, flags, text.left(len));
1042 p->setPen(pal.text().color());
1044 p->drawText(x, y, w, h, flags, text.left(len));
1048 #endif
1051 \class QTileRules
1052 \since 4.6
1054 Holds the rules used to draw a pixmap or image split into nine segments,
1055 similar to \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}.
1057 \sa Qt::TileRule, QMargins
1060 /*! \fn QTileRules::QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule)
1061 Constructs a QTileRules with the given \a horizontalRule and
1062 \a verticalRule.
1065 /*! \fn QTileRules::QTileRules(Qt::TileRule rule)
1066 Constructs a QTileRules with the given \a rule used for both
1067 the horizontal rule and the vertical rule.
1071 \fn void qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap)
1072 \relates <qdrawutil.h>
1073 \since 4.6
1074 \overload
1076 \brief The qDrawBorderPixmap function is for drawing a pixmap into
1077 the margins of a rectangle.
1079 Draws the given \a pixmap into the given \a target rectangle, using the
1080 given \a painter. The pixmap will be split into nine segments and drawn
1081 according to the \a margins structure.
1084 typedef QVarLengthArray<QDrawPixmaps::Data, 16> QDrawPixmapsDataArray;
1087 \since 4.6
1089 Draws the indicated \a sourceRect rectangle from the given \a pixmap into
1090 the given \a targetRect rectangle, using the given \a painter. The pixmap
1091 will be split into nine segments according to the given \a targetMargins
1092 and \a sourceMargins structures. Finally, the pixmap will be drawn
1093 according to the given \a rules.
1095 This function is used to draw a scaled pixmap, similar to
1096 \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}
1098 \sa Qt::TileRule, QTileRules, QMargins
1101 void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins,
1102 const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins,
1103 const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints)
1105 QDrawPixmaps::Data d;
1106 d.opacity = 1.0;
1107 d.rotation = 0.0;
1109 QDrawPixmapsDataArray opaqueData;
1110 QDrawPixmapsDataArray translucentData;
1112 // source center
1113 const int sourceCenterTop = sourceRect.top() + sourceMargins.top();
1114 const int sourceCenterLeft = sourceRect.left() + sourceMargins.left();
1115 const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1;
1116 const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1;
1117 const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft;
1118 const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop;
1119 // target center
1120 const int targetCenterTop = targetRect.top() + targetMargins.top();
1121 const int targetCenterLeft = targetRect.left() + targetMargins.left();
1122 const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1;
1123 const int targetCenterRight = targetRect.right() - targetMargins.right() + 1;
1124 const int targetCenterWidth = targetCenterRight - targetCenterLeft;
1125 const int targetCenterHeight = targetCenterBottom - targetCenterTop;
1127 QVarLengthArray<qreal, 16> xTarget; // x-coordinates of target rectangles
1128 QVarLengthArray<qreal, 16> yTarget; // y-coordinates of target rectangles
1130 int columns = 3;
1131 int rows = 3;
1132 if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0)
1133 columns = qMax(3, 2 + qCeil(targetCenterWidth / qreal(sourceCenterWidth)));
1134 if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0)
1135 rows = qMax(3, 2 + qCeil(targetCenterHeight / qreal(sourceCenterHeight)));
1137 xTarget.resize(columns + 1);
1138 yTarget.resize(rows + 1);
1140 xTarget[0] = targetRect.left();
1141 xTarget[1] = targetCenterLeft;
1142 xTarget[columns - 1] = targetCenterRight;
1143 xTarget[columns] = targetRect.left() + targetRect.width();
1145 yTarget[0] = targetRect.top();
1146 yTarget[1] = targetCenterTop;
1147 yTarget[rows - 1] = targetCenterBottom;
1148 yTarget[rows] = targetRect.top() + targetRect.height();
1150 qreal dx = targetCenterWidth;
1151 qreal dy = targetCenterHeight;
1153 switch (rules.horizontal) {
1154 case Qt::StretchTile:
1155 dx = targetCenterWidth;
1156 break;
1157 case Qt::RepeatTile:
1158 dx = sourceCenterWidth;
1159 break;
1160 case Qt::RoundTile:
1161 dx = targetCenterWidth / qreal(columns - 2);
1162 break;
1165 for (int i = 2; i < columns - 1; ++i)
1166 xTarget[i] = xTarget[i - 1] + dx;
1168 switch (rules.vertical) {
1169 case Qt::StretchTile:
1170 dy = targetCenterHeight;
1171 break;
1172 case Qt::RepeatTile:
1173 dy = sourceCenterHeight;
1174 break;
1175 case Qt::RoundTile:
1176 dy = targetCenterHeight / qreal(rows - 2);
1177 break;
1180 for (int i = 2; i < rows - 1; ++i)
1181 yTarget[i] = yTarget[i - 1] + dy;
1183 // corners
1184 if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left
1185 d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
1186 d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
1187 d.source = QRectF(sourceRect.left(), sourceRect.top(), sourceMargins.left(), sourceMargins.top());
1188 d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
1189 d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
1190 if (hints & QDrawBorderPixmap::OpaqueTopLeft)
1191 opaqueData.append(d);
1192 else
1193 translucentData.append(d);
1195 if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right
1196 d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
1197 d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
1198 d.source = QRectF(sourceCenterRight, sourceRect.top(), sourceMargins.right(), sourceMargins.top());
1199 d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
1200 d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
1201 if (hints & QDrawBorderPixmap::OpaqueTopRight)
1202 opaqueData.append(d);
1203 else
1204 translucentData.append(d);
1206 if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left
1207 d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
1208 d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
1209 d.source = QRectF(sourceRect.left(), sourceCenterBottom, sourceMargins.left(), sourceMargins.bottom());
1210 d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
1211 d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
1212 if (hints & QDrawBorderPixmap::OpaqueBottomLeft)
1213 opaqueData.append(d);
1214 else
1215 translucentData.append(d);
1217 if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right
1218 d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
1219 d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
1220 d.source = QRectF(sourceCenterRight, sourceCenterBottom, sourceMargins.right(), sourceMargins.bottom());
1221 d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
1222 d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
1223 if (hints & QDrawBorderPixmap::OpaqueBottomRight)
1224 opaqueData.append(d);
1225 else
1226 translucentData.append(d);
1229 // horizontal edges
1230 if (targetCenterWidth > 0 && sourceCenterWidth > 0) {
1231 if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
1232 QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
1233 d.source = QRectF(sourceCenterLeft, sourceRect.top(), sourceCenterWidth, sourceMargins.top());
1234 d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
1235 d.scaleX = dx / d.source.width();
1236 d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
1237 for (int i = 1; i < columns - 1; ++i) {
1238 d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
1239 data.append(d);
1241 if (rules.horizontal == Qt::RepeatTile)
1242 data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
1244 if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
1245 QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
1246 d.source = QRectF(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom());;
1247 d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
1248 d.scaleX = dx / d.source.width();
1249 d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
1250 for (int i = 1; i < columns - 1; ++i) {
1251 d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
1252 data.append(d);
1254 if (rules.horizontal == Qt::RepeatTile)
1255 data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
1259 // vertical edges
1260 if (targetCenterHeight > 0 && sourceCenterHeight > 0) {
1261 if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
1262 QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
1263 d.source = QRectF(sourceRect.left(), sourceCenterTop, sourceMargins.left(), sourceCenterHeight);
1264 d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
1265 d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
1266 d.scaleY = dy / d.source.height();
1267 for (int i = 1; i < rows - 1; ++i) {
1268 d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
1269 data.append(d);
1271 if (rules.vertical == Qt::RepeatTile)
1272 data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
1274 if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
1275 QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
1276 d.source = QRectF(sourceCenterRight, sourceCenterTop, sourceMargins.right(), sourceCenterHeight);
1277 d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
1278 d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
1279 d.scaleY = dy / d.source.height();
1280 for (int i = 1; i < rows - 1; ++i) {
1281 d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
1282 data.append(d);
1284 if (rules.vertical == Qt::RepeatTile)
1285 data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
1289 // center
1290 if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
1291 QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
1292 d.source = QRectF(sourceCenterLeft, sourceCenterTop, sourceCenterWidth, sourceCenterHeight);
1293 d.scaleX = dx / d.source.width();
1294 d.scaleY = dy / d.source.height();
1296 qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX;
1297 qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY;
1299 for (int j = 1; j < rows - 1; ++j) {
1300 d.point.setY(0.5 * (yTarget[j + 1] + yTarget[j]));
1301 for (int i = 1; i < columns - 1; ++i) {
1302 d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
1303 data.append(d);
1305 if (rules.horizontal == Qt::RepeatTile)
1306 data[data.size() - 1].source.setWidth(repeatWidth);
1308 if (rules.vertical == Qt::RepeatTile) {
1309 for (int i = 1; i < columns - 1; ++i)
1310 data[data.size() - i].source.setHeight(repeatHeight);
1314 if (opaqueData.size())
1315 qDrawPixmaps(painter, opaqueData.data(), opaqueData.size(), pixmap, QDrawPixmaps::OpaqueHint);
1316 if (translucentData.size())
1317 qDrawPixmaps(painter, translucentData.data(), translucentData.size(), pixmap);
1321 \class QDrawPixmaps::Data
1322 \since 4.6
1323 \internal
1325 This structure is used with the qDrawPixmaps() function.
1327 QPointF point: Specifies the center of the target rectangle.
1328 QRectF source: Specifies the source rectangle in the pixmap passed into the qDrawPixmaps() call.
1329 qreal scaleX: Specifies the horizontal scale of the target rectangle.
1330 qreal scaleY: Specifies the vertical scale of the target rectangle.
1331 qreal rotation: Specifies the rotation of the target rectangle in degrees.
1332 The target rectangle is rotated after scaling.
1333 qreal opacity: Specifies the opacity of the rectangle.
1337 \enum QDrawPixmaps::DrawingHint
1338 \internal
1342 \internal
1343 \since 4.6
1345 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap, at multiple positions
1346 with different scale, rotation and opacity on \a painter. \a drawingData is an array of \a
1347 dataCount elements specifying the parameters used to draw each pixmap instance.
1348 This can be used for example to implement a particle system.
1350 void qDrawPixmaps(QPainter *painter, const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
1352 QPaintEngine *engine = painter->paintEngine();
1353 if (!engine)
1354 return;
1356 if (engine->isExtended()) {
1357 static_cast<QPaintEngineEx *>(engine)->drawPixmaps(drawingData, dataCount, pixmap, hints);
1358 } else {
1359 qreal oldOpacity = painter->opacity();
1360 QTransform oldTransform = painter->transform();
1362 for (int i = 0; i < dataCount; ++i) {
1363 QTransform transform = oldTransform;
1364 transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
1365 transform.rotate(drawingData[i].rotation);
1366 painter->setOpacity(oldOpacity * drawingData[i].opacity);
1367 painter->setTransform(transform);
1369 qreal w = drawingData[i].scaleX * drawingData[i].source.width();
1370 qreal h = drawingData[i].scaleY * drawingData[i].source.height();
1371 painter->drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, drawingData[i].source);
1374 painter->setOpacity(oldOpacity);
1375 painter->setTransform(oldTransform);
1379 QT_END_NAMESPACE