src/gui/painting/qdrawutil.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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.
       
    15 **
       
    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.
       
    23 **
       
    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.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    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 
       
    52 QT_BEGIN_NAMESPACE
       
    53 
       
    54 /*!
       
    55     \headerfile <qdrawutil.h>
       
    56     \title Drawing Utility Functions
       
    57 
       
    58     \sa QPainter
       
    59 */
       
    60 
       
    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>
       
    66 
       
    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).
       
    71 
       
    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.
       
    78 
       
    79     The line appears sunken if \a sunken is true, otherwise raised.
       
    80 
       
    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.
       
    84 
       
    85 
       
    86     Alternatively you can use a QFrame widget and apply the
       
    87     QFrame::setFrameStyle() function to display a shaded line:
       
    88 
       
    89     \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 0
       
    90 
       
    91     \sa qDrawShadeRect(), qDrawShadePanel(), QStyle
       
    92 */
       
    93 
       
    94 void qDrawShadeLine(QPainter *p, int x1, int y1, int x2, int y2,
       
    95                      const QPalette &pal, bool sunken,
       
    96                      int lineWidth, int midLineWidth)
       
    97 {
       
    98     if (!(p && lineWidth >= 0 && midLineWidth >= 0))        {
       
    99         qWarning("qDrawShadeLine: Invalid parameters");
       
   100         return;
       
   101     }
       
   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;
       
   116         }
       
   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);
       
   123         }
       
   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);
       
   129         }
       
   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);
       
   139         }
       
   140     }
       
   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;
       
   147         }
       
   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);
       
   154         }
       
   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);
       
   159         }
       
   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);
       
   169         }
       
   170     }
       
   171     p->setPen(oldPen);
       
   172 }
       
   173 
       
   174 /*!
       
   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>
       
   180 
       
   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.
       
   183 
       
   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.
       
   191 
       
   192     The rectangle appears sunken if \a sunken is true, otherwise
       
   193     raised.
       
   194 
       
   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.
       
   198 
       
   199     Alternatively you can use a QFrame widget and apply the
       
   200     QFrame::setFrameStyle() function to display a shaded rectangle:
       
   201 
       
   202     \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 1
       
   203 
       
   204     \sa qDrawShadeLine(), qDrawShadePanel(), qDrawPlainRect(), QStyle
       
   205 */
       
   206 
       
   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)
       
   211 {
       
   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;
       
   217     }
       
   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;
       
   224 
       
   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++;
       
   246         }
       
   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;
       
   252         }
       
   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++;
       
   265         }
       
   266     }
       
   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);
       
   274     }
       
   275     p->setPen(oldPen);                        // restore pen
       
   276 }
       
   277 
       
   278 
       
   279 /*!
       
   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>
       
   284 
       
   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.
       
   288 
       
   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.
       
   293 
       
   294     The panel appears sunken if \a sunken is true, otherwise raised.
       
   295 
       
   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.
       
   299 
       
   300     Alternatively you can use a QFrame widget and apply the
       
   301     QFrame::setFrameStyle() function to display a shaded panel:
       
   302 
       
   303     \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 2
       
   304 
       
   305     \sa qDrawWinPanel(), qDrawShadeLine(), qDrawShadeRect(), QStyle
       
   306 */
       
   307 
       
   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)
       
   311 {
       
   312     if (w == 0 || h == 0)
       
   313         return;
       
   314     if (!(w > 0 && h > 0 && lineWidth >= 0)) {
       
   315         qWarning("qDrawShadePanel: Invalid parameters");
       
   316     }
       
   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();
       
   324     }
       
   325     QPen oldPen = p->pen();                        // save pen
       
   326     QVector<QLineF> lines;
       
   327     lines.reserve(2*lineWidth);
       
   328 
       
   329     if (sunken)
       
   330         p->setPen(shade);
       
   331     else
       
   332         p->setPen(light);
       
   333     int x1, y1, x2, y2;
       
   334     int i;
       
   335     x1 = x;
       
   336     y1 = y2 = y;
       
   337     x2 = x+w-2;
       
   338     for (i=0; i<lineWidth; i++) {                // top shadow
       
   339         lines << QLineF(x1, y1++, x2--, y2++);
       
   340     }
       
   341     x2 = x1;
       
   342     y1 = y+h-2;
       
   343     for (i=0; i<lineWidth; i++) {                // left shado
       
   344         lines << QLineF(x1++, y1, x2++, y2--);
       
   345     }
       
   346     p->drawLines(lines);
       
   347     lines.clear();
       
   348     if (sunken)
       
   349         p->setPen(light);
       
   350     else
       
   351         p->setPen(shade);
       
   352     x1 = x;
       
   353     y1 = y2 = y+h-1;
       
   354     x2 = x+w-1;
       
   355     for (i=0; i<lineWidth; i++) {                // bottom shadow
       
   356         lines << QLineF(x1++, y1--, x2, y2--);
       
   357     }
       
   358     x1 = x2;
       
   359     y1 = y;
       
   360     y2 = y+h-lineWidth-1;
       
   361     for (i=0; i<lineWidth; i++) {                // right shadow
       
   362         lines << QLineF(x1--, y1++, x2--, y2);
       
   363     }
       
   364     p->drawLines(lines);
       
   365     if (fill)                                // fill with fill color
       
   366         p->fillRect(x+lineWidth, y+lineWidth, w-lineWidth*2, h-lineWidth*2, *fill);
       
   367     p->setPen(oldPen);                        // restore pen
       
   368 }
       
   369 
       
   370 
       
   371 /*!
       
   372   \internal
       
   373   This function draws a rectangle with two pixel line width.
       
   374   It is called from qDrawWinButton() and qDrawWinPanel().
       
   375 
       
   376   c1..c4 and fill are used:
       
   377 
       
   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
       
   384 */
       
   385 
       
   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)
       
   391 {
       
   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);
       
   410     }
       
   411     p->setPen(oldPen);
       
   412 }
       
   413 
       
   414 
       
   415 /*!
       
   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>
       
   420 
       
   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.
       
   425 
       
   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).
       
   429 
       
   430     The button appears sunken if \a sunken is true, otherwise raised.
       
   431 
       
   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.
       
   435 
       
   436     \sa qDrawWinPanel(), QStyle
       
   437 */
       
   438 
       
   439 void qDrawWinButton(QPainter *p, int x, int y, int w, int h,
       
   440                      const QPalette &pal, bool sunken,
       
   441                      const QBrush *fill)
       
   442 {
       
   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);
       
   451 }
       
   452 
       
   453 /*!
       
   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>
       
   458 
       
   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.
       
   463 
       
   464     The given \a palette specifies the shading colors.  The panel
       
   465     appears sunken if \a sunken is true, otherwise raised.
       
   466 
       
   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.
       
   470 
       
   471     Alternatively you can use a QFrame widget and apply the
       
   472     QFrame::setFrameStyle() function to display a shaded panel:
       
   473 
       
   474     \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 3
       
   475 
       
   476     \sa qDrawShadePanel(), qDrawWinButton(), QStyle
       
   477 */
       
   478 
       
   479 void qDrawWinPanel(QPainter *p, int x, int y, int w, int h,
       
   480                     const QPalette &pal, bool        sunken,
       
   481                     const QBrush *fill)
       
   482 {
       
   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);
       
   491 }
       
   492 
       
   493 /*!
       
   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>
       
   497 
       
   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.
       
   502 
       
   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.
       
   506 
       
   507     Alternatively you can use a QFrame widget and apply the
       
   508     QFrame::setFrameStyle() function to display a plain rectangle:
       
   509 
       
   510     \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 4
       
   511 
       
   512     \sa qDrawShadeRect(), QStyle
       
   513 */
       
   514 
       
   515 void qDrawPlainRect(QPainter *p, int x, int y, int w, int h, const QColor &c,
       
   516                      int lineWidth, const QBrush *fill)
       
   517 {
       
   518     if (w == 0 || h == 0)
       
   519         return;
       
   520     if (!(w > 0 && h > 0 && lineWidth >= 0)) {
       
   521         qWarning("qDrawPlainRect: Invalid parameters");
       
   522     }
       
   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);
       
   533     }
       
   534     p->setPen(oldPen);
       
   535     p->setBrush(oldBrush);
       
   536 }
       
   537 
       
   538 /*****************************************************************************
       
   539   Overloaded functions.
       
   540  *****************************************************************************/
       
   541 
       
   542 /*!
       
   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
       
   547 
       
   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.
       
   551 
       
   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.
       
   558 
       
   559     The line appears sunken if \a sunken is true, otherwise raised.
       
   560 
       
   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.
       
   564 
       
   565 
       
   566     Alternatively you can use a QFrame widget and apply the
       
   567     QFrame::setFrameStyle() function to display a shaded line:
       
   568 
       
   569     \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 5
       
   570 
       
   571     \sa qDrawShadeRect(), qDrawShadePanel(), QStyle
       
   572 */
       
   573 
       
   574 void qDrawShadeLine(QPainter *p, const QPoint &p1, const QPoint &p2,
       
   575                      const QPalette &pal, bool sunken,
       
   576                      int lineWidth, int midLineWidth)
       
   577 {
       
   578     qDrawShadeLine(p, p1.x(), p1.y(), p2.x(), p2.y(), pal, sunken,
       
   579                     lineWidth, midLineWidth);
       
   580 }
       
   581 
       
   582 /*!
       
   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
       
   587 
       
   588     Draws the shaded rectangle specified by \a rect using the given \a painter.
       
   589 
       
   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.
       
   597 
       
   598     The rectangle appears sunken if \a sunken is true, otherwise
       
   599     raised.
       
   600 
       
   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.
       
   604 
       
   605     Alternatively you can use a QFrame widget and apply the
       
   606     QFrame::setFrameStyle() function to display a shaded rectangle:
       
   607 
       
   608     \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 6
       
   609 
       
   610     \sa qDrawShadeLine(), qDrawShadePanel(), qDrawPlainRect(), QStyle
       
   611 */
       
   612 
       
   613 void qDrawShadeRect(QPainter *p, const QRect &r,
       
   614                      const QPalette &pal, bool sunken,
       
   615                      int lineWidth, int midLineWidth,
       
   616                      const QBrush *fill)
       
   617 {
       
   618     qDrawShadeRect(p, r.x(), r.y(), r.width(), r.height(), pal, sunken,
       
   619                     lineWidth, midLineWidth, fill);
       
   620 }
       
   621 
       
   622 /*!
       
   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
       
   627 
       
   628     Draws the shaded panel at the rectangle specified by \a rect using the
       
   629     given \a painter and the given \a lineWidth.
       
   630 
       
   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.
       
   635 
       
   636     The panel appears sunken if \a sunken is true, otherwise raised.
       
   637 
       
   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.
       
   641 
       
   642     Alternatively you can use a QFrame widget and apply the
       
   643     QFrame::setFrameStyle() function to display a shaded panel:
       
   644 
       
   645     \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 7
       
   646 
       
   647     \sa qDrawWinPanel(), qDrawShadeLine(), qDrawShadeRect(), QStyle
       
   648 */
       
   649 
       
   650 void qDrawShadePanel(QPainter *p, const QRect &r,
       
   651                       const QPalette &pal, bool sunken,
       
   652                       int lineWidth, const QBrush *fill)
       
   653 {
       
   654     qDrawShadePanel(p, r.x(), r.y(), r.width(), r.height(), pal, sunken,
       
   655                      lineWidth, fill);
       
   656 }
       
   657 
       
   658 /*!
       
   659     \fn void qDrawWinButton(QPainter *painter, const QRect &rect, const QPalette &palette,
       
   660              bool sunken, const QBrush *fill)
       
   661     \relates <qdrawutil.h>
       
   662     \overload
       
   663 
       
   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.
       
   667 
       
   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).
       
   671 
       
   672     The button appears sunken if \a sunken is true, otherwise raised.
       
   673 
       
   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.
       
   677 
       
   678     \sa qDrawWinPanel(), QStyle
       
   679 */
       
   680 
       
   681 void qDrawWinButton(QPainter *p, const QRect &r,
       
   682                      const QPalette &pal, bool sunken, const QBrush *fill)
       
   683 {
       
   684     qDrawWinButton(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, fill);
       
   685 }
       
   686 
       
   687 /*!
       
   688     \fn void qDrawWinPanel(QPainter *painter, const QRect &rect, const QPalette &palette,
       
   689              bool sunken, const QBrush *fill)
       
   690     \overload
       
   691 
       
   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.
       
   695 
       
   696     The given \a palette specifies the shading colors.  The panel
       
   697     appears sunken if \a sunken is true, otherwise raised.
       
   698 
       
   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.
       
   702 
       
   703     Alternatively you can use a QFrame widget and apply the
       
   704     QFrame::setFrameStyle() function to display a shaded panel:
       
   705 
       
   706     \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 8
       
   707 
       
   708     \sa qDrawShadePanel(), qDrawWinButton(), QStyle
       
   709 */
       
   710 
       
   711 void qDrawWinPanel(QPainter *p, const QRect &r,
       
   712                     const QPalette &pal, bool sunken, const QBrush *fill)
       
   713 {
       
   714     qDrawWinPanel(p, r.x(), r.y(), r.width(), r.height(), pal, sunken, fill);
       
   715 }
       
   716 
       
   717 /*!
       
   718     \fn void qDrawPlainRect(QPainter *painter, const QRect &rect, const QColor &lineColor, int lineWidth, const QBrush *fill)
       
   719     \relates <qdrawutil.h>
       
   720     \overload
       
   721 
       
   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.
       
   725 
       
   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.
       
   729 
       
   730     Alternatively you can use a QFrame widget and apply the
       
   731     QFrame::setFrameStyle() function to display a plain rectangle:
       
   732 
       
   733     \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 9
       
   734 
       
   735     \sa qDrawShadeRect(), QStyle
       
   736 */
       
   737 
       
   738 void qDrawPlainRect(QPainter *p, const QRect &r, const QColor &c,
       
   739                      int lineWidth, const QBrush *fill)
       
   740 {
       
   741     qDrawPlainRect(p, r.x(), r.y(), r.width(), r.height(), c,
       
   742                     lineWidth, fill);
       
   743 }
       
   744 
       
   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)
       
   749 {
       
   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;
       
   766     }
       
   767     if (a.isEmpty())
       
   768         return;
       
   769 
       
   770     if (down) {
       
   771         x++;
       
   772         y++;
       
   773     }
       
   774 
       
   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]);
       
   798     }
       
   799     p->setPen(savePen);                        // restore pen
       
   800 }
       
   801 #endif // QT3_SUPPORT
       
   802 
       
   803 #if defined(Q_CC_MSVC)
       
   804 #pragma warning(disable: 4244)
       
   805 #endif
       
   806 
       
   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)
       
   814 {
       
   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
       
   824 
       
   825     if (dim < 2)                                // too small arrow
       
   826         return;
       
   827 
       
   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);
       
   839 
       
   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);
       
   843         }
       
   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);
       
   852         }
       
   853     }
       
   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);
       
   859         }
       
   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);
       
   864         }
       
   865     }
       
   866 
       
   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);
       
   875         }
       
   876         if (down)
       
   877             colspec = horizontal ? 0x2334 : 0x2343;
       
   878         else
       
   879             colspec = horizontal ? 0x1443 : 0x1434;
       
   880     }
       
   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);
       
   886         }
       
   887         if (down)
       
   888             colspec = horizontal ? 0x2443 : 0x2434;
       
   889         else
       
   890             colspec = horizontal ? 0x1334 : 0x1343;
       
   891     }
       
   892 
       
   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]
       
   903 
       
   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);
       
   909 
       
   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
       
   915 
       
   916     p->setPen(CLEFT);
       
   917     p->drawLines(bLeft);
       
   918     p->setPen(CTOP);
       
   919     p->drawLines(bTop);
       
   920     p->setPen(CBOT);
       
   921     p->drawLines(bBot);
       
   922 
       
   923     p->setTransform(wxm);
       
   924     p->setBrush(saveBrush);                        // restore brush
       
   925     p->setPen(savePen);                        // restore pen
       
   926 
       
   927 #undef CMID
       
   928 #undef CLEFT
       
   929 #undef CTOP
       
   930 #undef CBOT
       
   931 }
       
   932 #endif // QT_NO_STYLE_MOTIF
       
   933 
       
   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)
       
   940 {
       
   941     QRect result;
       
   942 
       
   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);
       
   960         }
       
   961     } else {
       
   962         result = QRect(x, y, w, h);
       
   963     }
       
   964 
       
   965     return result;
       
   966 }
       
   967 
       
   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)
       
   971 {
       
   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");
       
   983     }
       
   984 }
       
   985 
       
   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)
       
   992 {
       
   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);
       
  1002         }
       
  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();
       
  1013 
       
  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
       
  1018                 ;
       
  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);
       
  1026                 }
       
  1027 #endif
       
  1028             }
       
  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());
       
  1033             }
       
  1034         }
       
  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());
       
  1043         }
       
  1044         p->drawText(x, y, w, h, flags, text.left(len));
       
  1045     }
       
  1046 }
       
  1047 
       
  1048 #endif
       
  1049 
       
  1050 /*!
       
  1051     \class QTileRules
       
  1052     \since 4.6
       
  1053 
       
  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}.
       
  1056 
       
  1057     \sa Qt::TileRule, QMargins
       
  1058 */
       
  1059 
       
  1060 /*! \fn QTileRules::QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule)
       
  1061   Constructs a QTileRules with the given \a horizontalRule and
       
  1062   \a verticalRule.
       
  1063  */
       
  1064 
       
  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.
       
  1068  */
       
  1069 
       
  1070 /*!
       
  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
       
  1075 
       
  1076     \brief The qDrawBorderPixmap function is for drawing a pixmap into
       
  1077     the margins of a rectangle.
       
  1078 
       
  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.
       
  1082 */
       
  1083 
       
  1084 typedef QVarLengthArray<QDrawPixmaps::Data, 16> QDrawPixmapsDataArray;
       
  1085 
       
  1086 /*!
       
  1087     \since 4.6
       
  1088 
       
  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.
       
  1094 
       
  1095     This function is used to draw a scaled pixmap, similar to
       
  1096     \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}
       
  1097 
       
  1098     \sa Qt::TileRule, QTileRules, QMargins
       
  1099 */
       
  1100 
       
  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)
       
  1104 {
       
  1105     QDrawPixmaps::Data d;
       
  1106     d.opacity = 1.0;
       
  1107     d.rotation = 0.0;
       
  1108 
       
  1109     QDrawPixmapsDataArray opaqueData;
       
  1110     QDrawPixmapsDataArray translucentData;
       
  1111 
       
  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;
       
  1126 
       
  1127     QVarLengthArray<qreal, 16> xTarget; // x-coordinates of target rectangles
       
  1128     QVarLengthArray<qreal, 16> yTarget; // y-coordinates of target rectangles
       
  1129 
       
  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)));
       
  1136 
       
  1137     xTarget.resize(columns + 1);
       
  1138     yTarget.resize(rows + 1);
       
  1139 
       
  1140     xTarget[0] = targetRect.left();
       
  1141     xTarget[1] = targetCenterLeft;
       
  1142     xTarget[columns - 1] = targetCenterRight;
       
  1143     xTarget[columns] = targetRect.left() + targetRect.width();
       
  1144 
       
  1145     yTarget[0] = targetRect.top();
       
  1146     yTarget[1] = targetCenterTop;
       
  1147     yTarget[rows - 1] = targetCenterBottom;
       
  1148     yTarget[rows] = targetRect.top() + targetRect.height();
       
  1149 
       
  1150     qreal dx = targetCenterWidth;
       
  1151     qreal dy = targetCenterHeight;
       
  1152 
       
  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;
       
  1163     }
       
  1164 
       
  1165     for (int i = 2; i < columns - 1; ++i)
       
  1166         xTarget[i] = xTarget[i - 1] + dx;
       
  1167 
       
  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;
       
  1178     }
       
  1179 
       
  1180     for (int i = 2; i < rows - 1; ++i)
       
  1181         yTarget[i] = yTarget[i - 1] + dy;
       
  1182 
       
  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);
       
  1194     }
       
  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);
       
  1205     }
       
  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);
       
  1216     }
       
  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);
       
  1227     }
       
  1228 
       
  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);
       
  1240             }
       
  1241             if (rules.horizontal == Qt::RepeatTile)
       
  1242                 data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
       
  1243         }
       
  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);
       
  1253             }
       
  1254             if (rules.horizontal == Qt::RepeatTile)
       
  1255                 data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
       
  1256         }
       
  1257     }
       
  1258 
       
  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);
       
  1270             }
       
  1271             if (rules.vertical == Qt::RepeatTile)
       
  1272                 data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
       
  1273         }
       
  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);
       
  1283             }
       
  1284             if (rules.vertical == Qt::RepeatTile)
       
  1285                 data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
       
  1286         }
       
  1287     }
       
  1288 
       
  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();
       
  1295 
       
  1296         qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX;
       
  1297         qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY;
       
  1298 
       
  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);
       
  1304             }
       
  1305             if (rules.horizontal == Qt::RepeatTile)
       
  1306                 data[data.size() - 1].source.setWidth(repeatWidth);
       
  1307         }
       
  1308         if (rules.vertical == Qt::RepeatTile) {
       
  1309             for (int i = 1; i < columns - 1; ++i)
       
  1310                 data[data.size() - i].source.setHeight(repeatHeight);
       
  1311         }
       
  1312     }
       
  1313 
       
  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);
       
  1318 }
       
  1319 
       
  1320 /*!
       
  1321     \class QDrawPixmaps::Data
       
  1322     \since 4.6
       
  1323     \internal
       
  1324 
       
  1325     This structure is used with the qDrawPixmaps() function.
       
  1326 
       
  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.
       
  1334 */
       
  1335 
       
  1336 /*!
       
  1337     \enum QDrawPixmaps::DrawingHint
       
  1338     \internal
       
  1339 */
       
  1340 
       
  1341 /*!
       
  1342     \internal
       
  1343     \since 4.6
       
  1344 
       
  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.
       
  1349 */
       
  1350 void qDrawPixmaps(QPainter *painter, const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
       
  1351 {
       
  1352     QPaintEngine *engine = painter->paintEngine();
       
  1353     if (!engine)
       
  1354         return;
       
  1355 
       
  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();
       
  1361 
       
  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);
       
  1368 
       
  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);
       
  1372         }
       
  1373 
       
  1374         painter->setOpacity(oldOpacity);
       
  1375         painter->setTransform(oldTransform);
       
  1376     }
       
  1377 }
       
  1378 
       
  1379 QT_END_NAMESPACE