Replace 'i < len-1 && func(i+1)' by 'i+1 < len && func(i+1)'
[profile/ivi/qtbase.git] / src / gui / painting / qdrawutil.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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?
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
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
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
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<QPainter::PixmapFragment, 16> QPixmapFragmentsArray;
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
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     QPainter::PixmapFragment d;
1109     d.opacity = 1.0;
1110     d.rotation = 0.0;
1111
1112     QPixmapFragmentsArray opaqueData;
1113     QPixmapFragmentsArray translucentData;
1114
1115     // source center
1116     const int sourceCenterTop = sourceRect.top() + sourceMargins.top();
1117     const int sourceCenterLeft = sourceRect.left() + sourceMargins.left();
1118     const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1;
1119     const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1;
1120     const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft;
1121     const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop;
1122     // target center
1123     const int targetCenterTop = targetRect.top() + targetMargins.top();
1124     const int targetCenterLeft = targetRect.left() + targetMargins.left();
1125     const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1;
1126     const int targetCenterRight = targetRect.right() - targetMargins.right() + 1;
1127     const int targetCenterWidth = targetCenterRight - targetCenterLeft;
1128     const int targetCenterHeight = targetCenterBottom - targetCenterTop;
1129
1130     QVarLengthArray<qreal, 16> xTarget; // x-coordinates of target rectangles
1131     QVarLengthArray<qreal, 16> yTarget; // y-coordinates of target rectangles
1132
1133     int columns = 3;
1134     int rows = 3;
1135     if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0)
1136         columns = qMax(3, 2 + qCeil(targetCenterWidth / qreal(sourceCenterWidth)));
1137     if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0)
1138         rows = qMax(3, 2 + qCeil(targetCenterHeight / qreal(sourceCenterHeight)));
1139
1140     xTarget.resize(columns + 1);
1141     yTarget.resize(rows + 1);
1142
1143     bool oldAA = painter->testRenderHint(QPainter::Antialiasing);
1144     if (painter->paintEngine()->type() != QPaintEngine::OpenGL
1145         && painter->paintEngine()->type() != QPaintEngine::OpenGL2
1146         && oldAA && painter->combinedTransform().type() != QTransform::TxNone) {
1147         painter->setRenderHint(QPainter::Antialiasing, false);
1148     }
1149
1150     xTarget[0] = targetRect.left();
1151     xTarget[1] = targetCenterLeft;
1152     xTarget[columns - 1] = targetCenterRight;
1153     xTarget[columns] = targetRect.left() + targetRect.width();
1154
1155     yTarget[0] = targetRect.top();
1156     yTarget[1] = targetCenterTop;
1157     yTarget[rows - 1] = targetCenterBottom;
1158     yTarget[rows] = targetRect.top() + targetRect.height();
1159
1160     qreal dx = targetCenterWidth;
1161     qreal dy = targetCenterHeight;
1162
1163     switch (rules.horizontal) {
1164     case Qt::StretchTile:
1165         dx = targetCenterWidth;
1166         break;
1167     case Qt::RepeatTile:
1168         dx = sourceCenterWidth;
1169         break;
1170     case Qt::RoundTile:
1171         dx = targetCenterWidth / qreal(columns - 2);
1172         break;
1173     }
1174
1175     for (int i = 2; i < columns - 1; ++i)
1176         xTarget[i] = xTarget[i - 1] + dx;
1177
1178     switch (rules.vertical) {
1179     case Qt::StretchTile:
1180         dy = targetCenterHeight;
1181         break;
1182     case Qt::RepeatTile:
1183         dy = sourceCenterHeight;
1184         break;
1185     case Qt::RoundTile:
1186         dy = targetCenterHeight / qreal(rows - 2);
1187         break;
1188     }
1189
1190     for (int i = 2; i < rows - 1; ++i)
1191         yTarget[i] = yTarget[i - 1] + dy;
1192
1193     // corners
1194     if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left
1195         d.x = (0.5 * (xTarget[1] + xTarget[0]));
1196         d.y = (0.5 * (yTarget[1] + yTarget[0]));
1197         d.sourceLeft = sourceRect.left();
1198         d.sourceTop = sourceRect.top();
1199         d.width = sourceMargins.left();
1200         d.height = sourceMargins.top();
1201         d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
1202         d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
1203         if (hints & QDrawBorderPixmap::OpaqueTopLeft)
1204             opaqueData.append(d);
1205         else
1206             translucentData.append(d);
1207     }
1208     if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right
1209         d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
1210         d.y = (0.5 * (yTarget[1] + yTarget[0]));
1211         d.sourceLeft = sourceCenterRight;
1212         d.sourceTop = sourceRect.top();
1213         d.width = sourceMargins.right();
1214         d.height = sourceMargins.top();
1215         d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
1216         d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
1217         if (hints & QDrawBorderPixmap::OpaqueTopRight)
1218             opaqueData.append(d);
1219         else
1220             translucentData.append(d);
1221     }
1222     if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left
1223         d.x = (0.5 * (xTarget[1] + xTarget[0]));
1224         d.y =(0.5 * (yTarget[rows] + yTarget[rows - 1]));
1225         d.sourceLeft = sourceRect.left();
1226         d.sourceTop = sourceCenterBottom;
1227         d.width = sourceMargins.left();
1228         d.height = sourceMargins.bottom();
1229         d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
1230         d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
1231         if (hints & QDrawBorderPixmap::OpaqueBottomLeft)
1232             opaqueData.append(d);
1233         else
1234             translucentData.append(d);
1235     }
1236     if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right
1237         d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
1238         d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
1239         d.sourceLeft = sourceCenterRight;
1240         d.sourceTop = sourceCenterBottom;
1241         d.width = sourceMargins.right();
1242         d.height = sourceMargins.bottom();
1243         d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
1244         d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
1245         if (hints & QDrawBorderPixmap::OpaqueBottomRight)
1246             opaqueData.append(d);
1247         else
1248             translucentData.append(d);
1249     }
1250
1251     // horizontal edges
1252     if (targetCenterWidth > 0 && sourceCenterWidth > 0) {
1253         if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
1254             QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
1255             d.sourceLeft = sourceCenterLeft;
1256             d.sourceTop = sourceRect.top();
1257             d.width = sourceCenterWidth;
1258             d.height = sourceMargins.top();
1259             d.y = (0.5 * (yTarget[1] + yTarget[0]));
1260             d.scaleX = dx / d.width;
1261             d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
1262             for (int i = 1; i < columns - 1; ++i) {
1263                 d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
1264                 data.append(d);
1265             }
1266             if (rules.horizontal == Qt::RepeatTile)
1267                 data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
1268         }
1269         if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
1270             QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
1271             d.sourceLeft = sourceCenterLeft;
1272             d.sourceTop = sourceCenterBottom;
1273             d.width = sourceCenterWidth;
1274             d.height = sourceMargins.bottom();
1275             d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
1276             d.scaleX = dx / d.width;
1277             d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
1278             for (int i = 1; i < columns - 1; ++i) {
1279                 d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
1280                 data.append(d);
1281             }
1282             if (rules.horizontal == Qt::RepeatTile)
1283                 data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
1284         }
1285     }
1286
1287     // vertical edges
1288     if (targetCenterHeight > 0 && sourceCenterHeight > 0) {
1289         if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
1290             QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
1291             d.sourceLeft = sourceRect.left();
1292             d.sourceTop = sourceCenterTop;
1293             d.width = sourceMargins.left();
1294             d.height = sourceCenterHeight;
1295             d.x = (0.5 * (xTarget[1] + xTarget[0]));
1296             d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
1297             d.scaleY = dy / d.height;
1298             for (int i = 1; i < rows - 1; ++i) {
1299                 d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
1300                 data.append(d);
1301             }
1302             if (rules.vertical == Qt::RepeatTile)
1303                 data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
1304         }
1305         if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
1306             QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
1307             d.sourceLeft = sourceCenterRight;
1308             d.sourceTop = sourceCenterTop;
1309             d.width = sourceMargins.right();
1310             d.height = sourceCenterHeight;
1311             d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
1312             d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
1313             d.scaleY = dy / d.height;
1314             for (int i = 1; i < rows - 1; ++i) {
1315                 d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
1316                 data.append(d);
1317             }
1318             if (rules.vertical == Qt::RepeatTile)
1319                 data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
1320         }
1321     }
1322
1323     // center
1324     if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
1325         QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
1326         d.sourceLeft = sourceCenterLeft;
1327         d.sourceTop = sourceCenterTop;
1328         d.width = sourceCenterWidth;
1329         d.height = sourceCenterHeight;
1330         d.scaleX = dx / d.width;
1331         d.scaleY = dy / d.height;
1332
1333         qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX;
1334         qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY;
1335
1336         for (int j = 1; j < rows - 1; ++j) {
1337             d.y = (0.5 * (yTarget[j + 1] + yTarget[j]));
1338             for (int i = 1; i < columns - 1; ++i) {
1339                 d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
1340                 data.append(d);
1341             }
1342             if (rules.horizontal == Qt::RepeatTile)
1343                 data[data.size() - 1].width = repeatWidth;
1344         }
1345         if (rules.vertical == Qt::RepeatTile) {
1346             for (int i = 1; i < columns - 1; ++i)
1347                 data[data.size() - i].height = repeatHeight;
1348         }
1349     }
1350
1351     if (opaqueData.size())
1352         painter->drawPixmapFragments(opaqueData.data(), opaqueData.size(), pixmap, QPainter::OpaqueHint);
1353     if (translucentData.size())
1354         painter->drawPixmapFragments(translucentData.data(), translucentData.size(), pixmap);
1355
1356     if (oldAA)
1357         painter->setRenderHint(QPainter::Antialiasing, true);
1358 }
1359
1360 QT_END_NAMESPACE