src/gui/painting/qbrush.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
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 "qbrush.h"
       
    43 #include "qpixmap.h"
       
    44 #include "qbitmap.h"
       
    45 #include "qpixmapcache.h"
       
    46 #include "qdatastream.h"
       
    47 #include "qvariant.h"
       
    48 #include "qline.h"
       
    49 #include "qdebug.h"
       
    50 #include <QtCore/qcoreapplication.h>
       
    51 
       
    52 QT_BEGIN_NAMESPACE
       
    53 
       
    54 const uchar *qt_patternForBrush(int brushStyle, bool invert)
       
    55 {
       
    56     Q_ASSERT(brushStyle > Qt::SolidPattern && brushStyle < Qt::LinearGradientPattern);
       
    57     if(invert) {
       
    58         static const uchar dense1_pat[] = { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff };
       
    59         static const uchar dense2_pat[] = { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff };
       
    60         static const uchar dense3_pat[] = { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee };
       
    61         static const uchar dense4_pat[] = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 };
       
    62         static const uchar dense5_pat[] = { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 };
       
    63         static const uchar dense6_pat[] = { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 };
       
    64         static const uchar dense7_pat[] = { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 };
       
    65         static const uchar hor_pat[]    = { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 };
       
    66         static const uchar ver_pat[]    = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 };
       
    67         static const uchar cross_pat[]  = { 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0x10 };
       
    68         static const uchar bdiag_pat[]  = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
       
    69         static const uchar fdiag_pat[]  = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
       
    70         static const uchar dcross_pat[] = { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 };
       
    71         static const uchar *const pat_tbl[] = {
       
    72             dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat,
       
    73             dense6_pat, dense7_pat,
       
    74             hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat };
       
    75         return pat_tbl[brushStyle - Qt::Dense1Pattern];
       
    76     }
       
    77     static const uchar dense1_pat[] = { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 };
       
    78     static const uchar dense2_pat[] = { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 };
       
    79     static const uchar dense3_pat[] = { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 };
       
    80     static const uchar dense4_pat[] = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa };
       
    81     static const uchar dense5_pat[] = { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee };
       
    82     static const uchar dense6_pat[] = { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff };
       
    83     static const uchar dense7_pat[] = { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff };
       
    84     static const uchar hor_pat[]    = { 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff };
       
    85     static const uchar ver_pat[]    = { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef };
       
    86     static const uchar cross_pat[]  = { 0xef, 0xef, 0xef, 0x00, 0xef, 0xef, 0xef, 0xef };
       
    87     static const uchar bdiag_pat[]  = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
       
    88     static const uchar fdiag_pat[]  = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
       
    89     static const uchar dcross_pat[] = { 0x7e, 0xbd, 0xdb, 0xe7, 0xe7, 0xdb, 0xbd, 0x7e };
       
    90     static const uchar *const pat_tbl[] = {
       
    91         dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat,
       
    92         dense6_pat, dense7_pat,
       
    93         hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat };
       
    94     return pat_tbl[brushStyle - Qt::Dense1Pattern];
       
    95 }
       
    96 
       
    97 QPixmap qt_pixmapForBrush(int brushStyle, bool invert)
       
    98 {
       
    99     QPixmap pm;
       
   100     QString key = QLatin1String("$qt-brush$") + QString::number(brushStyle)
       
   101                   + QString::number((int)invert);
       
   102     if (!QPixmapCache::find(key, pm)) {
       
   103         pm = QBitmap::fromData(QSize(8, 8), qt_patternForBrush(brushStyle, invert),
       
   104                                QImage::Format_MonoLSB);
       
   105         QPixmapCache::insert(key, pm);
       
   106     }
       
   107 
       
   108     return pm;
       
   109 }
       
   110 
       
   111 class QBrushPatternImageCache
       
   112 {
       
   113 public:
       
   114     QBrushPatternImageCache()
       
   115         : m_initialized(false)
       
   116     {
       
   117         init();
       
   118     }
       
   119 
       
   120     void init()
       
   121     {
       
   122         for (int style = Qt::Dense1Pattern; style <= Qt::DiagCrossPattern; ++style) {
       
   123             int i = style - Qt::Dense1Pattern;
       
   124             m_images[i][0] = QImage(qt_patternForBrush(style, 0), 8, 8, 1, QImage::Format_MonoLSB);
       
   125             m_images[i][1] = QImage(qt_patternForBrush(style, 1), 8, 8, 1, QImage::Format_MonoLSB);
       
   126         }
       
   127         m_initialized = true;
       
   128     }
       
   129 
       
   130     QImage getImage(int brushStyle, bool invert) const
       
   131     {
       
   132         Q_ASSERT(brushStyle >= Qt::Dense1Pattern && brushStyle <= Qt::DiagCrossPattern);
       
   133         if (!m_initialized)
       
   134             const_cast<QBrushPatternImageCache*>(this)->init();
       
   135         return m_images[brushStyle - Qt::Dense1Pattern][invert];
       
   136     }
       
   137 
       
   138     void cleanup() {
       
   139         for (int style = Qt::Dense1Pattern; style <= Qt::DiagCrossPattern; ++style) {
       
   140             int i = style - Qt::Dense1Pattern;
       
   141             m_images[i][0] = QImage();
       
   142             m_images[i][1] = QImage();
       
   143         }
       
   144         m_initialized = false;
       
   145     }
       
   146 
       
   147 private:
       
   148     QImage m_images[Qt::DiagCrossPattern - Qt::Dense1Pattern + 1][2];
       
   149     bool m_initialized;
       
   150 };
       
   151 
       
   152 static void qt_cleanup_brush_pattern_image_cache();
       
   153 Q_GLOBAL_STATIC_WITH_INITIALIZER(QBrushPatternImageCache, qt_brushPatternImageCache,
       
   154                                  {
       
   155                                      qAddPostRoutine(qt_cleanup_brush_pattern_image_cache);
       
   156                                  })
       
   157 
       
   158 static void qt_cleanup_brush_pattern_image_cache()
       
   159 {
       
   160     qt_brushPatternImageCache()->cleanup();
       
   161 }
       
   162 
       
   163 Q_GUI_EXPORT
       
   164 QImage qt_imageForBrush(int brushStyle, bool invert)
       
   165 {
       
   166     return qt_brushPatternImageCache()->getImage(brushStyle, invert);
       
   167 }
       
   168 
       
   169 struct QTexturedBrushData : public QBrushData
       
   170 {
       
   171     QTexturedBrushData() {
       
   172         m_has_pixmap_texture = false;
       
   173         m_pixmap = 0;
       
   174     }
       
   175     ~QTexturedBrushData() {
       
   176         delete m_pixmap;
       
   177     }
       
   178 
       
   179     void setPixmap(const QPixmap &pm) {
       
   180         delete m_pixmap;
       
   181 
       
   182         if (pm.isNull()) {
       
   183             m_pixmap = 0;
       
   184             m_has_pixmap_texture = false;
       
   185         } else {
       
   186             m_pixmap = new QPixmap(pm);
       
   187             m_has_pixmap_texture = true;
       
   188         }
       
   189 
       
   190         m_image = QImage();
       
   191     }
       
   192 
       
   193     void setImage(const QImage &image) {
       
   194         m_image = image;
       
   195         delete m_pixmap;
       
   196         m_pixmap = 0;
       
   197         m_has_pixmap_texture = false;
       
   198     }
       
   199 
       
   200     QPixmap &pixmap() {
       
   201         if (!m_pixmap) {
       
   202             m_pixmap = new QPixmap(QPixmap::fromImage(m_image));
       
   203         }
       
   204         return *m_pixmap;
       
   205     }
       
   206 
       
   207     QImage &image() {
       
   208         if (m_image.isNull() && m_pixmap)
       
   209             m_image = m_pixmap->toImage();
       
   210         return m_image;
       
   211     }
       
   212 
       
   213     QPixmap *m_pixmap;
       
   214     QImage m_image;
       
   215     bool m_has_pixmap_texture;
       
   216 };
       
   217 
       
   218 // returns true if the brush has a pixmap (or bitmap) set as the
       
   219 // brush texture, false otherwise
       
   220 bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush)
       
   221 {
       
   222     if (brush.style() != Qt::TexturePattern)
       
   223         return false;
       
   224     QTexturedBrushData *tx_data = static_cast<QTexturedBrushData *>(brush.d.data());
       
   225     return tx_data->m_has_pixmap_texture;
       
   226 }
       
   227 
       
   228 struct QGradientBrushData : public QBrushData
       
   229 {
       
   230     QGradient gradient;
       
   231 };
       
   232 
       
   233 struct QBrushDataPointerDeleter
       
   234 {
       
   235     static inline void deleteData(QBrushData *d)
       
   236     {
       
   237         switch (d->style) {
       
   238         case Qt::TexturePattern:
       
   239             delete static_cast<QTexturedBrushData*>(d);
       
   240             break;
       
   241         case Qt::LinearGradientPattern:
       
   242         case Qt::RadialGradientPattern:
       
   243         case Qt::ConicalGradientPattern:
       
   244             delete static_cast<QGradientBrushData*>(d);
       
   245             break;
       
   246         default:
       
   247             delete d;
       
   248         }
       
   249     }
       
   250 
       
   251     static inline void cleanup(QBrushData *d)
       
   252     {
       
   253         if (d && !d->ref.deref()) {
       
   254             deleteData(d);
       
   255         }
       
   256     }
       
   257 };
       
   258 
       
   259 /*!
       
   260     \class QBrush
       
   261     \ingroup painting
       
   262     \ingroup shared
       
   263 
       
   264     \brief The QBrush class defines the fill pattern of shapes drawn
       
   265     by QPainter.
       
   266 
       
   267     A brush has a style, a color, a gradient and a texture.
       
   268 
       
   269     The brush style() defines the fill pattern using the
       
   270     Qt::BrushStyle enum. The default brush style is Qt::NoBrush
       
   271     (depending on how you construct a brush). This style tells the
       
   272     painter to not fill shapes. The standard style for filling is
       
   273     Qt::SolidPattern. The style can be set when the brush is created
       
   274     using the appropriate constructor, and in addition the setStyle()
       
   275     function provides means for altering the style once the brush is
       
   276     constructed.
       
   277 
       
   278     \image brush-styles.png Brush Styles
       
   279 
       
   280     The brush color() defines the color of the fill pattern. The color
       
   281     can either be one of Qt's predefined colors, Qt::GlobalColor, or
       
   282     any other custom QColor. The currently set color can be retrieved
       
   283     and altered using the color() and setColor() functions,
       
   284     respectively.
       
   285 
       
   286     The gradient() defines the gradient fill used when the current
       
   287     style is either Qt::LinearGradientPattern,
       
   288     Qt::RadialGradientPattern or Qt::ConicalGradientPattern. Gradient
       
   289     brushes are created by giving a QGradient as a constructor
       
   290     argument when creating the QBrush. Qt provides three different
       
   291     gradients: QLinearGradient, QConicalGradient, and QRadialGradient
       
   292     - all of which inherit QGradient.
       
   293 
       
   294     \snippet doc/src/snippets/brush/gradientcreationsnippet.cpp 0
       
   295 
       
   296     The texture() defines the pixmap used when the current style is
       
   297     Qt::TexturePattern.  You can create a brush with a texture by
       
   298     providing the pixmap when the brush is created or by using
       
   299     setTexture().
       
   300 
       
   301     Note that applying setTexture() makes style() ==
       
   302     Qt::TexturePattern, regardless of previous style
       
   303     settings. Also, calling setColor() will not make a difference if
       
   304     the style is a gradient. The same is the case if the style is
       
   305     Qt::TexturePattern style unless the current texture is a QBitmap.
       
   306 
       
   307     The isOpaque() function returns true if the brush is fully opaque
       
   308     otherwise false. A brush is considered opaque if:
       
   309 
       
   310     \list
       
   311     \o The alpha component of the color() is 255.
       
   312     \o Its texture() does not have an alpha channel and is not a QBitmap.
       
   313     \o The colors in the gradient() all have an alpha component that is 255.
       
   314     \endlist
       
   315 
       
   316     \table 100%
       
   317     \row
       
   318     \o \inlineimage brush-outline.png Outlines
       
   319     \o
       
   320 
       
   321     To specify the style and color of lines and outlines, use the
       
   322     QPainter's \l {QPen}{pen} combined with Qt::PenStyle and
       
   323     Qt::GlobalColor:
       
   324 
       
   325     \snippet doc/src/snippets/code/src_gui_painting_qbrush.cpp 0
       
   326 
       
   327     Note that, by default, QPainter renders the outline (using the
       
   328     currently set pen) when drawing shapes. Use \l {Qt::NoPen}{\c
       
   329     painter.setPen(Qt::NoPen)} to disable this behavior.
       
   330 
       
   331     \endtable
       
   332 
       
   333     For more information about painting in general, see \l{The Paint
       
   334     System} documentation.
       
   335 
       
   336     \sa Qt::BrushStyle, QPainter, QColor
       
   337 */
       
   338 
       
   339 #ifndef QT_NO_THREAD
       
   340 // Special deleter that only deletes if the ref-count goes to zero
       
   341 template <>
       
   342 class QGlobalStaticDeleter<QBrushData>
       
   343 {
       
   344 public:
       
   345     QGlobalStatic<QBrushData> &globalStatic;
       
   346     QGlobalStaticDeleter(QGlobalStatic<QBrushData> &_globalStatic)
       
   347         : globalStatic(_globalStatic)
       
   348     { }
       
   349 
       
   350     inline ~QGlobalStaticDeleter()
       
   351     {
       
   352         if (!globalStatic.pointer->ref.deref())
       
   353             delete globalStatic.pointer;
       
   354         globalStatic.pointer = 0;
       
   355         globalStatic.destroyed = true;
       
   356     }
       
   357 };
       
   358 #endif
       
   359 
       
   360 Q_GLOBAL_STATIC_WITH_INITIALIZER(QBrushData, nullBrushInstance,
       
   361                                  {
       
   362                                      x->ref = 1;
       
   363                                      x->style = Qt::BrushStyle(0);
       
   364                                      x->color = Qt::black;
       
   365                                  })
       
   366 
       
   367 static bool qbrush_check_type(Qt::BrushStyle style) {
       
   368     switch (style) {
       
   369     case Qt::TexturePattern:
       
   370          qWarning("QBrush: Incorrect use of TexturePattern");
       
   371          break;
       
   372     case Qt::LinearGradientPattern:
       
   373     case Qt::RadialGradientPattern:
       
   374     case Qt::ConicalGradientPattern:
       
   375         qWarning("QBrush: Wrong use of a gradient pattern");
       
   376         break;
       
   377     default:
       
   378         return true;
       
   379     }
       
   380     return false;
       
   381 }
       
   382 
       
   383 /*!
       
   384   \internal
       
   385   Initializes the brush.
       
   386 */
       
   387 
       
   388 void QBrush::init(const QColor &color, Qt::BrushStyle style)
       
   389 {
       
   390     switch(style) {
       
   391     case Qt::NoBrush:
       
   392         d.reset(nullBrushInstance());
       
   393         d->ref.ref();
       
   394         if (d->color != color) setColor(color);
       
   395         return;
       
   396     case Qt::TexturePattern:
       
   397         d.reset(new QTexturedBrushData);
       
   398         break;
       
   399     case Qt::LinearGradientPattern:
       
   400     case Qt::RadialGradientPattern:
       
   401     case Qt::ConicalGradientPattern:
       
   402         d.reset(new QGradientBrushData);
       
   403         break;
       
   404     default:
       
   405         d.reset(new QBrushData);
       
   406         break;
       
   407     }
       
   408     d->ref = 1;
       
   409     d->style = style;
       
   410     d->color = color;
       
   411 }
       
   412 
       
   413 /*!
       
   414     Constructs a default black brush with the style Qt::NoBrush
       
   415     (i.e. this brush will not fill shapes).
       
   416 */
       
   417 
       
   418 QBrush::QBrush()
       
   419     : d(nullBrushInstance())
       
   420 {
       
   421     Q_ASSERT(d);
       
   422     d->ref.ref();
       
   423 }
       
   424 
       
   425 /*!
       
   426     Constructs a brush with a black color and a texture set to the
       
   427     given \a pixmap. The style is set to Qt::TexturePattern.
       
   428 
       
   429     \sa setTexture()
       
   430 */
       
   431 
       
   432 QBrush::QBrush(const QPixmap &pixmap)
       
   433 {
       
   434     init(Qt::black, Qt::TexturePattern);
       
   435     setTexture(pixmap);
       
   436 }
       
   437 
       
   438 
       
   439 /*!
       
   440     Constructs a brush with a black color and a texture set to the
       
   441     given \a image. The style is set to Qt::TexturePattern.
       
   442 
       
   443     \sa setTextureImage()
       
   444 */
       
   445 
       
   446 QBrush::QBrush(const QImage &image)
       
   447 {
       
   448     init(Qt::black, Qt::TexturePattern);
       
   449     setTextureImage(image);
       
   450 }
       
   451 
       
   452 /*!
       
   453     Constructs a black brush with the given \a style.
       
   454 
       
   455     \sa setStyle()
       
   456 */
       
   457 
       
   458 QBrush::QBrush(Qt::BrushStyle style)
       
   459 {
       
   460     if (qbrush_check_type(style))
       
   461         init(Qt::black, style);
       
   462     else {
       
   463         d.reset(nullBrushInstance());
       
   464         d->ref.ref();
       
   465     }
       
   466 }
       
   467 
       
   468 /*!
       
   469     Constructs a brush with the given \a color and \a style.
       
   470 
       
   471     \sa setColor(), setStyle()
       
   472 */
       
   473 
       
   474 QBrush::QBrush(const QColor &color, Qt::BrushStyle style)
       
   475 {
       
   476     if (qbrush_check_type(style))
       
   477         init(color, style);
       
   478     else {
       
   479         d.reset(nullBrushInstance());
       
   480         d->ref.ref();
       
   481     }
       
   482 }
       
   483 
       
   484 /*!
       
   485     \fn QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style)
       
   486 
       
   487     Constructs a brush with the given \a color and \a style.
       
   488 
       
   489     \sa setColor(), setStyle()
       
   490 */
       
   491 QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style)
       
   492 {
       
   493     if (qbrush_check_type(style))
       
   494         init(color, style);
       
   495     else {
       
   496         d.reset(nullBrushInstance());
       
   497         d->ref.ref();
       
   498     }
       
   499 }
       
   500 
       
   501 /*!
       
   502     Constructs a brush with the given \a color and the custom pattern
       
   503     stored in \a pixmap.
       
   504 
       
   505     The style is set to Qt::TexturePattern. The color will only have
       
   506     an effect for QBitmaps.
       
   507 
       
   508     \sa setColor(), setPixmap()
       
   509 */
       
   510 
       
   511 QBrush::QBrush(const QColor &color, const QPixmap &pixmap)
       
   512 {
       
   513     init(color, Qt::TexturePattern);
       
   514     setTexture(pixmap);
       
   515 }
       
   516 
       
   517 /*!
       
   518 
       
   519     Constructs a brush with the given \a color and the custom pattern
       
   520     stored in \a pixmap.
       
   521 
       
   522     The style is set to Qt::TexturePattern. The color will only have
       
   523     an effect for QBitmaps.
       
   524 
       
   525     \sa setColor(), setPixmap()
       
   526 */
       
   527 QBrush::QBrush(Qt::GlobalColor color, const QPixmap &pixmap)
       
   528 {
       
   529     init(color, Qt::TexturePattern);
       
   530     setTexture(pixmap);
       
   531 }
       
   532 
       
   533 /*!
       
   534     Constructs a copy of \a other.
       
   535 */
       
   536 
       
   537 QBrush::QBrush(const QBrush &other)
       
   538     : d(other.d.data())
       
   539 {
       
   540     d->ref.ref();
       
   541 }
       
   542 
       
   543 /*!
       
   544     Constructs a brush based on the given \a gradient.
       
   545 
       
   546     The brush style is set to the corresponding gradient style (either
       
   547     Qt::LinearGradientPattern, Qt::RadialGradientPattern or
       
   548     Qt::ConicalGradientPattern).
       
   549 */
       
   550 QBrush::QBrush(const QGradient &gradient)
       
   551 {
       
   552     Q_ASSERT_X(gradient.type() != QGradient::NoGradient, "QBrush::QBrush",
       
   553                "QGradient should not be used directly, use the linear, radial\n"
       
   554                "or conical gradients instead");
       
   555 
       
   556     const Qt::BrushStyle enum_table[] = {
       
   557         Qt::LinearGradientPattern,
       
   558         Qt::RadialGradientPattern,
       
   559         Qt::ConicalGradientPattern
       
   560     };
       
   561 
       
   562     init(QColor(), enum_table[gradient.type()]);
       
   563     QGradientBrushData *grad = static_cast<QGradientBrushData *>(d.data());
       
   564     grad->gradient = gradient;
       
   565 }
       
   566 
       
   567 /*!
       
   568     Destroys the brush.
       
   569 */
       
   570 
       
   571 QBrush::~QBrush()
       
   572 {
       
   573 }
       
   574 
       
   575 void QBrush::cleanUp(QBrushData *x)
       
   576 {
       
   577     QBrushDataPointerDeleter::deleteData(x);
       
   578 }
       
   579 
       
   580 
       
   581 void QBrush::detach(Qt::BrushStyle newStyle)
       
   582 {
       
   583     if (newStyle == d->style && d->ref == 1)
       
   584         return;
       
   585 
       
   586     QScopedPointer<QBrushData> x;
       
   587     switch(newStyle) {
       
   588     case Qt::TexturePattern: {
       
   589         QTexturedBrushData *tbd = new QTexturedBrushData;
       
   590         if (d->style == Qt::TexturePattern) {
       
   591             QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
       
   592             if (data->m_has_pixmap_texture)
       
   593                 tbd->setPixmap(data->pixmap());
       
   594             else
       
   595                 tbd->setImage(data->image());
       
   596         }
       
   597         x.reset(tbd);
       
   598         break;
       
   599         }
       
   600     case Qt::LinearGradientPattern:
       
   601     case Qt::RadialGradientPattern:
       
   602     case Qt::ConicalGradientPattern:
       
   603         x.reset(new QGradientBrushData);
       
   604         static_cast<QGradientBrushData *>(x.data())->gradient =
       
   605             static_cast<QGradientBrushData *>(d.data())->gradient;
       
   606         break;
       
   607     default:
       
   608         x.reset(new QBrushData);
       
   609         break;
       
   610     }
       
   611     x->ref = 1;
       
   612     x->style = newStyle;
       
   613     x->color = d->color;
       
   614     x->transform = d->transform;
       
   615     d.reset(x.take());
       
   616 }
       
   617 
       
   618 
       
   619 /*!
       
   620     \fn QBrush &QBrush::operator=(const QBrush &brush)
       
   621 
       
   622     Assigns the given \a brush to \e this brush and returns a
       
   623     reference to \e this brush.
       
   624 */
       
   625 
       
   626 QBrush &QBrush::operator=(const QBrush &b)
       
   627 {
       
   628     if (d == b.d)
       
   629         return *this;
       
   630 
       
   631     b.d->ref.ref();
       
   632     d.reset(b.d.data());
       
   633     return *this;
       
   634 }
       
   635 
       
   636 /*!
       
   637    Returns the brush as a QVariant
       
   638 */
       
   639 QBrush::operator QVariant() const
       
   640 {
       
   641     return QVariant(QVariant::Brush, this);
       
   642 }
       
   643 
       
   644 /*!
       
   645     \fn Qt::BrushStyle QBrush::style() const
       
   646 
       
   647     Returns the brush style.
       
   648 
       
   649     \sa setStyle()
       
   650 */
       
   651 
       
   652 /*!
       
   653     Sets the brush style to \a style.
       
   654 
       
   655     \sa style()
       
   656 */
       
   657 
       
   658 void QBrush::setStyle(Qt::BrushStyle style)
       
   659 {
       
   660     if (d->style == style)
       
   661         return;
       
   662 
       
   663     if (qbrush_check_type(style)) {
       
   664         detach(style);
       
   665         d->style = style;
       
   666     }
       
   667 }
       
   668 
       
   669 
       
   670 /*!
       
   671     \fn const QColor &QBrush::color() const
       
   672 
       
   673     Returns the brush color.
       
   674 
       
   675     \sa setColor()
       
   676 */
       
   677 
       
   678 /*!
       
   679     \fn void QBrush::setColor(const QColor &color)
       
   680 
       
   681     Sets the brush color to the given \a color.
       
   682 
       
   683     Note that calling setColor() will not make a difference if the
       
   684     style is a gradient. The same is the case if the style is
       
   685     Qt::TexturePattern style unless the current texture is a QBitmap.
       
   686 
       
   687     \sa color()
       
   688 */
       
   689 
       
   690 void QBrush::setColor(const QColor &c)
       
   691 {
       
   692     detach(d->style);
       
   693     d->color = c;
       
   694 }
       
   695 
       
   696 /*!
       
   697     \fn void QBrush::setColor(Qt::GlobalColor color)
       
   698     \overload
       
   699 
       
   700     Sets the brush color to the given \a color.
       
   701 */
       
   702 
       
   703 
       
   704 #ifdef QT3_SUPPORT
       
   705 
       
   706 /*!
       
   707     \fn void QBrush::setPixmap(const QPixmap &pixmap)
       
   708 
       
   709     \compat
       
   710 
       
   711     Sets a custom pattern for this brush.
       
   712 
       
   713     Use setTexture() instead.
       
   714 */
       
   715 
       
   716 /*!
       
   717     \fn QPixmap *QBrush::pixmap() const
       
   718 
       
   719     Returns a pointer to the custom brush pattern.
       
   720 
       
   721     Use texture() instead.
       
   722 */
       
   723 QPixmap *QBrush::pixmap() const
       
   724 {
       
   725     if (d->style != Qt::TexturePattern)
       
   726         return 0;
       
   727     QTexturedBrushData *data  = static_cast<QTexturedBrushData*>(d.data());
       
   728     QPixmap &pixmap = data->pixmap();
       
   729     return pixmap.isNull() ? 0 : &pixmap;
       
   730 }
       
   731 #endif
       
   732 
       
   733 /*!
       
   734     \fn QPixmap QBrush::texture() const
       
   735 
       
   736     Returns the custom brush pattern, or a null pixmap if no custom brush pattern
       
   737     has been set.
       
   738 
       
   739     \sa setTexture()
       
   740 */
       
   741 QPixmap QBrush::texture() const
       
   742 {
       
   743     return d->style == Qt::TexturePattern
       
   744                      ? (static_cast<QTexturedBrushData *>(d.data()))->pixmap()
       
   745                      : QPixmap();
       
   746 }
       
   747 
       
   748 /*!
       
   749     Sets the brush pixmap to \a pixmap. The style is set to
       
   750     Qt::TexturePattern.
       
   751 
       
   752     The current brush color will only have an effect for monochrome
       
   753     pixmaps, i.e. for QPixmap::depth() == 1 (\l {QBitmap}{QBitmaps}).
       
   754 
       
   755     \sa texture()
       
   756 */
       
   757 
       
   758 void QBrush::setTexture(const QPixmap &pixmap)
       
   759 {
       
   760     if (!pixmap.isNull()) {
       
   761         detach(Qt::TexturePattern);
       
   762         QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
       
   763         data->setPixmap(pixmap);
       
   764     } else {
       
   765         detach(Qt::NoBrush);
       
   766     }
       
   767 }
       
   768 
       
   769 
       
   770 /*!
       
   771     \since 4.2
       
   772 
       
   773     Returns the custom brush pattern, or a null image if no custom
       
   774     brush pattern has been set.
       
   775 
       
   776     If the texture was set as a QPixmap it will be converted to a
       
   777     QImage.
       
   778 
       
   779     \sa setTextureImage()
       
   780 */
       
   781 
       
   782 QImage QBrush::textureImage() const
       
   783 {
       
   784     return d->style == Qt::TexturePattern
       
   785                      ? (static_cast<QTexturedBrushData *>(d.data()))->image()
       
   786                      : QImage();
       
   787 }
       
   788 
       
   789 
       
   790 /*!
       
   791     \since 4.2
       
   792 
       
   793     Sets the brush image to \a image. The style is set to
       
   794     Qt::TexturePattern.
       
   795 
       
   796     Note the current brush color will \e not have any affect on
       
   797     monochrome images, as opposed to calling setTexture() with a
       
   798     QBitmap. If you want to change the color of monochrome image
       
   799     brushes, either convert the image to QBitmap with \c
       
   800     QBitmap::fromImage() and set the resulting QBitmap as a texture,
       
   801     or change the entries in the color table for the image.
       
   802 
       
   803     \sa textureImage(), setTexture()
       
   804 */
       
   805 
       
   806 void QBrush::setTextureImage(const QImage &image)
       
   807 {
       
   808     if (!image.isNull()) {
       
   809         detach(Qt::TexturePattern);
       
   810         QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
       
   811         data->setImage(image);
       
   812     } else {
       
   813         detach(Qt::NoBrush);
       
   814     }
       
   815 }
       
   816 
       
   817 
       
   818 /*!
       
   819     Returns the gradient describing this brush.
       
   820 */
       
   821 const QGradient *QBrush::gradient() const
       
   822 {
       
   823     if (d->style == Qt::LinearGradientPattern
       
   824         || d->style == Qt::RadialGradientPattern
       
   825         || d->style == Qt::ConicalGradientPattern) {
       
   826         return &static_cast<const QGradientBrushData *>(d.data())->gradient;
       
   827     }
       
   828     return 0;
       
   829 }
       
   830 
       
   831 
       
   832 /*!
       
   833     Returns true if the brush is fully opaque otherwise false. A brush
       
   834     is considered opaque if:
       
   835 
       
   836     \list
       
   837     \i The alpha component of the color() is 255.
       
   838     \i Its texture() does not have an alpha channel and is not a QBitmap.
       
   839     \i The colors in the gradient() all have an alpha component that is 255.
       
   840     \endlist
       
   841 */
       
   842 
       
   843 bool QBrush::isOpaque() const
       
   844 {
       
   845     bool opaqueColor = d->color.alpha() == 255;
       
   846 
       
   847     // Test awfully simple case first
       
   848     if (d->style == Qt::SolidPattern)
       
   849         return opaqueColor;
       
   850 
       
   851     if (d->style == Qt::LinearGradientPattern
       
   852         || d->style == Qt::RadialGradientPattern
       
   853         || d->style == Qt::ConicalGradientPattern) {
       
   854         QGradientStops stops = gradient()->stops();
       
   855         for (int i=0; i<stops.size(); ++i)
       
   856             if (stops.at(i).second.alpha() != 255)
       
   857                 return false;
       
   858         return true;
       
   859     } else if (d->style == Qt::TexturePattern) {
       
   860         return qHasPixmapTexture(*this)
       
   861             ? !texture().hasAlphaChannel() && !texture().isQBitmap()
       
   862             : !textureImage().hasAlphaChannel();
       
   863     }
       
   864 
       
   865     return false;
       
   866 }
       
   867 
       
   868 
       
   869 /*!
       
   870     \since 4.2
       
   871 
       
   872     Sets \a matrix as an explicit transformation matrix on the
       
   873     current brush. The brush transformation matrix is merged with
       
   874     QPainter transformation matrix to produce the final result.
       
   875 
       
   876     \sa matrix()
       
   877 */
       
   878 void QBrush::setMatrix(const QMatrix &matrix)
       
   879 {
       
   880     setTransform(QTransform(matrix));
       
   881 }
       
   882 
       
   883 /*!
       
   884     \since 4.3
       
   885 
       
   886     Sets \a matrix as an explicit transformation matrix on the
       
   887     current brush. The brush transformation matrix is merged with
       
   888     QPainter transformation matrix to produce the final result.
       
   889 
       
   890     \sa transform()
       
   891 */
       
   892 void QBrush::setTransform(const QTransform &matrix)
       
   893 {
       
   894     detach(d->style);
       
   895     d->transform = matrix;
       
   896 }
       
   897 
       
   898 
       
   899 /*!
       
   900     \fn void QBrush::matrix() const
       
   901     \since 4.2
       
   902 
       
   903     Returns the current transformation matrix for the brush.
       
   904 
       
   905     \sa setMatrix()
       
   906 */
       
   907 
       
   908 /*!
       
   909     \fn bool QBrush::operator!=(const QBrush &brush) const
       
   910 
       
   911     Returns true if the brush is different from the given \a brush;
       
   912     otherwise returns false.
       
   913 
       
   914     Two brushes are different if they have different styles, colors or
       
   915     pixmaps.
       
   916 
       
   917     \sa operator==()
       
   918 */
       
   919 
       
   920 /*!
       
   921     \fn bool QBrush::operator==(const QBrush &brush) const
       
   922 
       
   923     Returns true if the brush is equal to the given \a brush;
       
   924     otherwise returns false.
       
   925 
       
   926     Two brushes are equal if they have equal styles, colors and
       
   927     pixmaps.
       
   928 
       
   929     \sa operator!=()
       
   930 */
       
   931 
       
   932 bool QBrush::operator==(const QBrush &b) const
       
   933 {
       
   934     if (b.d == d)
       
   935         return true;
       
   936     if (b.d->style == d->style && b.d->color == d->color) {
       
   937         switch (d->style) {
       
   938         case Qt::TexturePattern: {
       
   939             QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap();
       
   940             QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap();
       
   941             return ((us.isNull() && them.isNull()) || us.cacheKey() == them.cacheKey());
       
   942         }
       
   943         case Qt::LinearGradientPattern:
       
   944         case Qt::RadialGradientPattern:
       
   945         case Qt::ConicalGradientPattern:
       
   946             {
       
   947                 QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data());
       
   948                 QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data());
       
   949                 return d1->gradient == d2->gradient;
       
   950             }
       
   951         default:
       
   952             return true;
       
   953         }
       
   954     }
       
   955     return false;
       
   956 }
       
   957 
       
   958 /*!
       
   959     \fn QBrush::operator const QColor&() const
       
   960 
       
   961     Returns the brush's color.
       
   962 
       
   963     Use color() instead.
       
   964 */
       
   965 
       
   966 #ifndef QT_NO_DEBUG_STREAM
       
   967 /*!
       
   968   \internal
       
   969 */
       
   970 QDebug operator<<(QDebug dbg, const QBrush &b)
       
   971 {
       
   972 #ifndef Q_BROKEN_DEBUG_STREAM
       
   973     dbg.nospace() << "QBrush(" << b.color() << ',' << b.style() << ')';
       
   974     return dbg.space();
       
   975 #else
       
   976     qWarning("This compiler doesn't support streaming QBrush to QDebug");
       
   977     return dbg;
       
   978     Q_UNUSED(b);
       
   979 #endif
       
   980 }
       
   981 #endif
       
   982 
       
   983 /*****************************************************************************
       
   984   QBrush stream functions
       
   985  *****************************************************************************/
       
   986 #ifndef QT_NO_DATASTREAM
       
   987 /*!
       
   988     \fn QDataStream &operator<<(QDataStream &stream, const QBrush &brush)
       
   989     \relates QBrush
       
   990 
       
   991     Writes the given \a brush to the given \a stream and returns a
       
   992     reference to the \a stream.
       
   993 
       
   994     \sa {Format of the QDataStream Operators}
       
   995 */
       
   996 
       
   997 QDataStream &operator<<(QDataStream &s, const QBrush &b)
       
   998 {
       
   999     quint8 style = (quint8) b.style();
       
  1000     bool gradient_style = false;
       
  1001 
       
  1002     if (style == Qt::LinearGradientPattern || style == Qt::RadialGradientPattern
       
  1003         || style == Qt::ConicalGradientPattern)
       
  1004         gradient_style = true;
       
  1005 
       
  1006     if (s.version() < QDataStream::Qt_4_0 && gradient_style)
       
  1007         style = Qt::NoBrush;
       
  1008 
       
  1009     s << style << b.color();
       
  1010     if (b.style() == Qt::TexturePattern) {
       
  1011         s << b.texture();
       
  1012     } else if (s.version() >= QDataStream::Qt_4_0 && gradient_style) {
       
  1013         const QGradient *gradient = b.gradient();
       
  1014         int type_as_int = int(gradient->type());
       
  1015         s << type_as_int;
       
  1016         if (s.version() >= QDataStream::Qt_4_3) {
       
  1017             s << int(gradient->spread());
       
  1018             s << int(gradient->coordinateMode());
       
  1019         }
       
  1020 
       
  1021         if (s.version() >= QDataStream::Qt_4_5)
       
  1022             s << int(gradient->interpolationMode());
       
  1023 
       
  1024         if (sizeof(qreal) == sizeof(double)) {
       
  1025             s << gradient->stops();
       
  1026         } else {
       
  1027             // ensure that we write doubles here instead of streaming the stops
       
  1028             // directly; otherwise, platforms that redefine qreal might generate
       
  1029             // data that cannot be read on other platforms.
       
  1030             QVector<QGradientStop> stops = gradient->stops();
       
  1031             s << quint32(stops.size());
       
  1032             for (int i = 0; i < stops.size(); ++i) {
       
  1033                 const QGradientStop &stop = stops.at(i);
       
  1034                 s << QPair<double, QColor>(double(stop.first), stop.second);
       
  1035             }
       
  1036         }
       
  1037 
       
  1038         if (gradient->type() == QGradient::LinearGradient) {
       
  1039             s << static_cast<const QLinearGradient *>(gradient)->start();
       
  1040             s << static_cast<const QLinearGradient *>(gradient)->finalStop();
       
  1041         } else if (gradient->type() == QGradient::RadialGradient) {
       
  1042             s << static_cast<const QRadialGradient *>(gradient)->center();
       
  1043             s << static_cast<const QRadialGradient *>(gradient)->focalPoint();
       
  1044             s << (double) static_cast<const QRadialGradient *>(gradient)->radius();
       
  1045         } else { // type == Conical
       
  1046             s << static_cast<const QConicalGradient *>(gradient)->center();
       
  1047             s << (double) static_cast<const QConicalGradient *>(gradient)->angle();
       
  1048         }
       
  1049     }
       
  1050     if (s.version() >= QDataStream::Qt_4_3)
       
  1051         s << b.transform();
       
  1052     return s;
       
  1053 }
       
  1054 
       
  1055 /*!
       
  1056     \fn QDataStream &operator>>(QDataStream &stream, QBrush &brush)
       
  1057     \relates QBrush
       
  1058 
       
  1059     Reads the given \a brush from the given \a stream and returns a
       
  1060     reference to the \a stream.
       
  1061 
       
  1062     \sa {Format of the QDataStream Operators}
       
  1063 */
       
  1064 
       
  1065 QDataStream &operator>>(QDataStream &s, QBrush &b)
       
  1066 {
       
  1067     quint8 style;
       
  1068     QColor color;
       
  1069     s >> style;
       
  1070     s >> color;
       
  1071     if (style == Qt::TexturePattern) {
       
  1072         QPixmap pm;
       
  1073         s >> pm;
       
  1074         b = QBrush(color, pm);
       
  1075     } else if (style == Qt::LinearGradientPattern
       
  1076                || style == Qt::RadialGradientPattern
       
  1077                || style == Qt::ConicalGradientPattern) {
       
  1078 
       
  1079         int type_as_int;
       
  1080         QGradient::Type type;
       
  1081         QGradientStops stops;
       
  1082         QGradient::CoordinateMode cmode = QGradient::LogicalMode;
       
  1083         QGradient::Spread spread = QGradient::PadSpread;
       
  1084         QGradient::InterpolationMode imode = QGradient::ColorInterpolation;
       
  1085 
       
  1086         s >> type_as_int;
       
  1087         type = QGradient::Type(type_as_int);
       
  1088         if (s.version() >= QDataStream::Qt_4_3) {
       
  1089             s >> type_as_int;
       
  1090             spread = QGradient::Spread(type_as_int);
       
  1091             s >> type_as_int;
       
  1092             cmode = QGradient::CoordinateMode(type_as_int);
       
  1093         }
       
  1094 
       
  1095         if (s.version() >= QDataStream::Qt_4_5) {
       
  1096             s >> type_as_int;
       
  1097             imode = QGradient::InterpolationMode(type_as_int);
       
  1098         }
       
  1099 
       
  1100         if (sizeof(qreal) == sizeof(double)) {
       
  1101             s >> stops;
       
  1102         } else {
       
  1103             quint32 numStops;
       
  1104             double n;
       
  1105             QColor c;
       
  1106 
       
  1107             s >> numStops;
       
  1108             for (quint32 i = 0; i < numStops; ++i) {
       
  1109                 s >> n >> c;
       
  1110                 stops << QPair<qreal, QColor>(n, c);
       
  1111             }
       
  1112         }
       
  1113 
       
  1114         if (type == QGradient::LinearGradient) {
       
  1115             QPointF p1, p2;
       
  1116             s >> p1;
       
  1117             s >> p2;
       
  1118             QLinearGradient lg(p1, p2);
       
  1119             lg.setStops(stops);
       
  1120             lg.setSpread(spread);
       
  1121             lg.setCoordinateMode(cmode);
       
  1122             lg.setInterpolationMode(imode);
       
  1123             b = QBrush(lg);
       
  1124         } else if (type == QGradient::RadialGradient) {
       
  1125             QPointF center, focal;
       
  1126             double radius;
       
  1127             s >> center;
       
  1128             s >> focal;
       
  1129             s >> radius;
       
  1130             QRadialGradient rg(center, radius, focal);
       
  1131             rg.setStops(stops);
       
  1132             rg.setSpread(spread);
       
  1133             rg.setCoordinateMode(cmode);
       
  1134             rg.setInterpolationMode(imode);
       
  1135             b = QBrush(rg);
       
  1136         } else { // type == QGradient::ConicalGradient
       
  1137             QPointF center;
       
  1138             double angle;
       
  1139             s >> center;
       
  1140             s >> angle;
       
  1141             QConicalGradient cg(center, angle);
       
  1142             cg.setStops(stops);
       
  1143             cg.setSpread(spread);
       
  1144             cg.setCoordinateMode(cmode);
       
  1145             cg.setInterpolationMode(imode);
       
  1146             b = QBrush(cg);
       
  1147         }
       
  1148     } else {
       
  1149         b = QBrush(color, (Qt::BrushStyle)style);
       
  1150     }
       
  1151     if (s.version() >= QDataStream::Qt_4_3) {
       
  1152         QTransform transform;
       
  1153         s >> transform;
       
  1154         b.setTransform(transform);
       
  1155     }
       
  1156     return s;
       
  1157 }
       
  1158 #endif // QT_NO_DATASTREAM
       
  1159 
       
  1160 /*******************************************************************************
       
  1161  * QGradient implementations
       
  1162  */
       
  1163 
       
  1164 
       
  1165 /*!
       
  1166     \class QGradient
       
  1167     \ingroup painting
       
  1168     \ingroup shared
       
  1169 
       
  1170     \brief The QGradient class is used in combination with QBrush to
       
  1171     specify gradient fills.
       
  1172 
       
  1173     Qt currently supports three types of gradient fills:
       
  1174 
       
  1175     \list
       
  1176     \o \e Linear gradients interpolate colors between start and end points.
       
  1177     \o \e Radial gradients interpolate colors between a focal point and end
       
  1178         points on a circle surrounding it.
       
  1179     \o \e Conical gradients interpolate colors around a center point.
       
  1180     \endlist
       
  1181 
       
  1182     A gradient's type can be retrieved using the type() function.
       
  1183     Each of the types is represented by a subclass of QGradient:
       
  1184 
       
  1185     \table
       
  1186     \row
       
  1187     \o \inlineimage qgradient-linear.png
       
  1188     \o \inlineimage qgradient-radial.png
       
  1189     \o \inlineimage qgradient-conical.png
       
  1190     \header
       
  1191     \o QLinearGradient
       
  1192     \o QRadialGradient
       
  1193     \o QConicalGradient
       
  1194     \endtable
       
  1195 
       
  1196     The colors in a gradient is defined using stop points of the
       
  1197     QGradientStop type, i.e. a position and a color.  Use the
       
  1198     setColorAt() function to define a single stop
       
  1199     point. Alternatively, use the setStops() function to define
       
  1200     several stop points in one go. Note that the latter function \e
       
  1201     replaces the current set of stop points.
       
  1202 
       
  1203     It is the gradient's complete set of stop points (accessible
       
  1204     through the stops() function) that describes how the gradient area
       
  1205     should be filled. If no stop points have been specified, a
       
  1206     gradient of black at 0 to white at 1 is used.
       
  1207 
       
  1208     A diagonal linear gradient from black at (100, 100) to white at
       
  1209     (200, 200) could be specified like this:
       
  1210 
       
  1211     \snippet doc/src/snippets/brush/brush.cpp 0
       
  1212 
       
  1213     A gradient can have an arbitrary number of stop points. The
       
  1214     following would create a radial gradient starting with
       
  1215     red in the center, blue and then green on the edges:
       
  1216 
       
  1217     \snippet doc/src/snippets/brush/brush.cpp 1
       
  1218 
       
  1219     It is possible to repeat or reflect the gradient outside its area
       
  1220     by specifiying the \l {QGradient::Spread}{spread method} using the
       
  1221     setSpread() function. The default is to pad the outside area with
       
  1222     the color at the closest stop point. The currently set \l
       
  1223     {QGradient::Spread}{spread method} can be retrieved using the
       
  1224     spread() function. The QGradient::Spread enum defines three
       
  1225     different methods:
       
  1226 
       
  1227     \table
       
  1228     \row
       
  1229     \o \inlineimage qradialgradient-pad.png
       
  1230     \o \inlineimage qradialgradient-repeat.png
       
  1231     \o \inlineimage qradialgradient-reflect.png
       
  1232     \row
       
  1233     \o \l {QGradient::PadSpread}{PadSpread}
       
  1234     \o \l {QGradient::RepeatSpread}{RepeatSpread}
       
  1235     \o \l {QGradient::ReflectSpread}{ReflectSpread}
       
  1236     \endtable
       
  1237 
       
  1238     Note that the setSpread() function only has effect for linear and
       
  1239     radial gradients. The reason is that the conical gradient is
       
  1240     closed by definition, i.e. the \e conical gradient fills the
       
  1241     entire circle from 0 - 360 degrees, while the boundary of a radial
       
  1242     or a linear gradient can be specified through its radius or final
       
  1243     stop points, respectively.
       
  1244 
       
  1245     The gradient coordinates can be specified in logical coordinates,
       
  1246     relative to device coordinates, or relative to object bounding box coordinates.
       
  1247     The \l {QGradient::CoordinateMode}{coordinate mode} can be set using the
       
  1248     setCoordinateMode() function. The default is LogicalMode, where the
       
  1249     gradient coordinates are specified in the same way as the object
       
  1250     coordinates. To retrieve the currently set \l {QGradient::CoordinateMode}
       
  1251     {coordinate mode} use coordinateMode().
       
  1252 
       
  1253 
       
  1254     \sa {demos/gradients}{The Gradients Demo}, QBrush
       
  1255 */
       
  1256 
       
  1257 /*!
       
  1258     \internal
       
  1259 */
       
  1260 QGradient::QGradient()
       
  1261     : m_type(NoGradient), dummy(0)
       
  1262 {
       
  1263 }
       
  1264 
       
  1265 
       
  1266 /*!
       
  1267     \enum QGradient::Type
       
  1268 
       
  1269     Specifies the type of gradient.
       
  1270 
       
  1271     \value LinearGradient  Interpolates colors between start and end points
       
  1272     (QLinearGradient).
       
  1273 
       
  1274     \value RadialGradient Interpolate colors between a focal point and end
       
  1275     points on a circle surrounding it (QRadialGradient).
       
  1276 
       
  1277     \value ConicalGradient Interpolate colors around a center point (QConicalGradient).
       
  1278     \value NoGradient No gradient is used.
       
  1279 
       
  1280     \sa type()
       
  1281 */
       
  1282 
       
  1283 /*!
       
  1284     \enum QGradient::Spread
       
  1285 
       
  1286     Specifies how the area outside the gradient area should be
       
  1287     filled.
       
  1288 
       
  1289     \value PadSpread The area is filled with the closest stop
       
  1290     color. This is the default.
       
  1291 
       
  1292     \value RepeatSpread The gradient  is repeated outside the gradient
       
  1293     area.
       
  1294 
       
  1295     \value ReflectSpread The gradient is reflected outside the
       
  1296     gradient area.
       
  1297 
       
  1298     \sa spread(), setSpread()
       
  1299 */
       
  1300 
       
  1301 /*!
       
  1302     \fn void QGradient::setSpread(Spread method)
       
  1303 
       
  1304     Specifies the spread \a method that should be used for this
       
  1305     gradient.
       
  1306 
       
  1307     Note that this function only has effect for linear and radial
       
  1308     gradients.
       
  1309 
       
  1310     \sa spread()
       
  1311 */
       
  1312 
       
  1313 /*!
       
  1314     \fn QGradient::Spread QGradient::spread() const
       
  1315 
       
  1316     Returns the spread method use by this gradient. The default is
       
  1317     PadSpread.
       
  1318 
       
  1319     \sa setSpread()
       
  1320 */
       
  1321 
       
  1322 /*!
       
  1323     \fn QGradient::Type QGradient::type() const
       
  1324 
       
  1325     Returns the type of gradient.
       
  1326 */
       
  1327 
       
  1328 /*!
       
  1329     \fn void QGradient::setColorAt(qreal position, const QColor &color)
       
  1330 
       
  1331     Creates a stop point at the given \a position with the given \a
       
  1332     color. The given \a position must be in the range 0 to 1.
       
  1333 
       
  1334     \sa setStops(), stops()
       
  1335 */
       
  1336 
       
  1337 void QGradient::setColorAt(qreal pos, const QColor &color)
       
  1338 {
       
  1339     if (pos > 1 || pos < 0) {
       
  1340         qWarning("QGradient::setColorAt: Color position must be specified in the range 0 to 1");
       
  1341         return;
       
  1342     }
       
  1343 
       
  1344     int index = 0;
       
  1345     while (index < m_stops.size() && m_stops.at(index).first < pos) ++index;
       
  1346 
       
  1347     if (index < m_stops.size() && m_stops.at(index).first == pos)
       
  1348         m_stops[index].second = color;
       
  1349     else
       
  1350         m_stops.insert(index, QGradientStop(pos, color));
       
  1351 }
       
  1352 
       
  1353 /*!
       
  1354     \fn void QGradient::setStops(const QGradientStops &stopPoints)
       
  1355 
       
  1356     Replaces the current set of stop points with the given \a
       
  1357     stopPoints. The positions of the points must be in the range 0 to
       
  1358     1, and must be sorted with the lowest point first.
       
  1359 
       
  1360     \sa setColorAt(), stops()
       
  1361 */
       
  1362 void QGradient::setStops(const QGradientStops &stops)
       
  1363 {
       
  1364     m_stops.clear();
       
  1365     for (int i=0; i<stops.size(); ++i)
       
  1366         setColorAt(stops.at(i).first, stops.at(i).second);
       
  1367 }
       
  1368 
       
  1369 
       
  1370 /*!
       
  1371     Returns the stop points for this gradient.
       
  1372 
       
  1373     If no stop points have been specified, a gradient of black at 0 to white
       
  1374     at 1 is used.
       
  1375 
       
  1376     \sa setStops(), setColorAt()
       
  1377 */
       
  1378 QGradientStops QGradient::stops() const
       
  1379 {
       
  1380     if (m_stops.isEmpty()) {
       
  1381         QGradientStops tmp;
       
  1382         tmp << QGradientStop(0, Qt::black) << QGradientStop(1, Qt::white);
       
  1383         return tmp;
       
  1384     }
       
  1385     return m_stops;
       
  1386 }
       
  1387 
       
  1388 #define Q_DUMMY_ACCESSOR union {void *p; uint i;}; p = dummy;
       
  1389 
       
  1390 /*!
       
  1391     \enum QGradient::CoordinateMode
       
  1392     \since 4.4
       
  1393 
       
  1394     This enum specifies how gradient coordinates map to the paint
       
  1395     device on which the gradient is used.
       
  1396 
       
  1397     \value LogicalMode This is the default mode. The gradient coordinates
       
  1398     are specified logical space just like the object coordinates.
       
  1399     \value StretchToDeviceMode In this mode the gradient coordinates
       
  1400     are relative to the bounding rectangle of the paint device,
       
  1401     with (0,0) in the top left corner, and (1,1) in the bottom right
       
  1402     corner of the paint device.
       
  1403     \value ObjectBoundingMode In this mode the gradient coordinates are
       
  1404     relative to the bounding rectangle of the object being drawn, with
       
  1405     (0,0) in the top left corner, and (1,1) in the bottom right corner
       
  1406     of the object's bounding rectangle.
       
  1407 */
       
  1408 
       
  1409 /*!
       
  1410     \since 4.4
       
  1411 
       
  1412     Returns the coordinate mode of this gradient. The default mode is
       
  1413     LogicalMode.
       
  1414 */
       
  1415 QGradient::CoordinateMode QGradient::coordinateMode() const
       
  1416 {
       
  1417     Q_DUMMY_ACCESSOR
       
  1418     return CoordinateMode(i & 0x03);
       
  1419 }
       
  1420 
       
  1421 /*!
       
  1422     \since 4.4
       
  1423 
       
  1424     Sets the coordinate mode of this gradient to \a mode. The default
       
  1425     mode is LogicalMode.
       
  1426 */
       
  1427 void QGradient::setCoordinateMode(CoordinateMode mode)
       
  1428 {
       
  1429     Q_DUMMY_ACCESSOR
       
  1430     i &= ~0x03;
       
  1431     i |= uint(mode);
       
  1432     dummy = p;
       
  1433 }
       
  1434 
       
  1435 /*!
       
  1436     \enum QGradient::InterpolationMode
       
  1437     \since 4.5
       
  1438     \internal
       
  1439 
       
  1440     \value ComponentInterpolation The color components and the alpha component are
       
  1441     independently linearly interpolated.
       
  1442     \value ColorInterpolation The colors are linearly interpolated in
       
  1443     premultiplied color space.
       
  1444 */
       
  1445 
       
  1446 /*!
       
  1447     \since 4.5
       
  1448     \internal
       
  1449 
       
  1450     Returns the interpolation mode of this gradient. The default mode is
       
  1451     ColorInterpolation.
       
  1452 */
       
  1453 QGradient::InterpolationMode QGradient::interpolationMode() const
       
  1454 {
       
  1455     Q_DUMMY_ACCESSOR
       
  1456     return InterpolationMode((i >> 2) & 0x01);
       
  1457 }
       
  1458 
       
  1459 /*!
       
  1460     \since 4.5
       
  1461     \internal
       
  1462 
       
  1463     Sets the interpolation mode of this gradient to \a mode. The default
       
  1464     mode is ColorInterpolation.
       
  1465 */
       
  1466 void QGradient::setInterpolationMode(InterpolationMode mode)
       
  1467 {
       
  1468     Q_DUMMY_ACCESSOR
       
  1469     i &= ~(1 << 2);
       
  1470     i |= (uint(mode) << 2);
       
  1471     dummy = p;
       
  1472 }
       
  1473 
       
  1474 #undef Q_DUMMY_ACCESSOR
       
  1475 
       
  1476 /*!
       
  1477     \fn bool QGradient::operator!=(const QGradient &gradient) const
       
  1478     \since 4.2
       
  1479 
       
  1480     Returns true if the gradient is the same as the other \a gradient
       
  1481     specified; otherwise returns false.
       
  1482 
       
  1483     \sa operator==()
       
  1484 */
       
  1485 
       
  1486 /*!
       
  1487     Returns true if the gradient is the same as the other \a gradient
       
  1488     specified; otherwise returns false.
       
  1489 
       
  1490     \sa operator!=()
       
  1491 */
       
  1492 bool QGradient::operator==(const QGradient &gradient) const
       
  1493 {
       
  1494     if (gradient.m_type != m_type
       
  1495         || gradient.m_spread != m_spread
       
  1496         || gradient.dummy != dummy) return false;
       
  1497 
       
  1498     if (m_type == LinearGradient) {
       
  1499         if (m_data.linear.x1 != gradient.m_data.linear.x1
       
  1500             || m_data.linear.y1 != gradient.m_data.linear.y1
       
  1501             || m_data.linear.x2 != gradient.m_data.linear.x2
       
  1502             || m_data.linear.y2 != gradient.m_data.linear.y2)
       
  1503             return false;
       
  1504     } else if (m_type == RadialGradient) {
       
  1505         if (m_data.radial.cx != gradient.m_data.radial.cx
       
  1506             || m_data.radial.cy != gradient.m_data.radial.cy
       
  1507             || m_data.radial.fx != gradient.m_data.radial.fx
       
  1508             || m_data.radial.fy != gradient.m_data.radial.fy
       
  1509             || m_data.radial.radius != gradient.m_data.radial.radius)
       
  1510             return false;
       
  1511     } else { // m_type == ConicalGradient
       
  1512         if (m_data.conical.cx != gradient.m_data.conical.cx
       
  1513             || m_data.conical.cy != gradient.m_data.conical.cy
       
  1514             || m_data.conical.angle != gradient.m_data.conical.angle)
       
  1515             return false;
       
  1516     }
       
  1517 
       
  1518     return stops() == gradient.stops();
       
  1519 }
       
  1520 
       
  1521 /*!
       
  1522     \internal
       
  1523 */
       
  1524 bool QGradient::operator==(const QGradient &gradient)
       
  1525 {
       
  1526     return const_cast<const QGradient *>(this)->operator==(gradient);
       
  1527 }
       
  1528 
       
  1529 /*!
       
  1530     \class QLinearGradient
       
  1531     \ingroup painting
       
  1532 
       
  1533     \brief The QLinearGradient class is used in combination with QBrush to
       
  1534     specify a linear gradient brush.
       
  1535 
       
  1536     Linear gradients interpolate colors between start and end
       
  1537     points. Outside these points the gradient is either padded,
       
  1538     reflected or repeated depending on the currently set \l
       
  1539     {QGradient::Spread}{spread} method:
       
  1540 
       
  1541     \table
       
  1542     \row
       
  1543     \o \inlineimage qlineargradient-pad.png
       
  1544     \o \inlineimage qlineargradient-reflect.png
       
  1545     \o \inlineimage qlineargradient-repeat.png
       
  1546     \row
       
  1547     \o \l {QGradient::PadSpread}{PadSpread} (default)
       
  1548     \o \l {QGradient::ReflectSpread}{ReflectSpread}
       
  1549     \o \l {QGradient::RepeatSpread}{RepeatSpread}
       
  1550     \endtable
       
  1551 
       
  1552     The colors in a gradient is defined using stop points of the
       
  1553     QGradientStop type, i.e. a position and a color. Use the
       
  1554     QGradient::setColorAt() or the QGradient::setStops() function to
       
  1555     define the stop points. It is the gradient's complete set of stop
       
  1556     points that describes how the gradient area should be filled. If
       
  1557     no stop points have been specified, a gradient of black at 0 to
       
  1558     white at 1 is used.
       
  1559 
       
  1560     In addition to the functions inherited from QGradient, the
       
  1561     QLinearGradient class provides the finalStop() function which
       
  1562     returns the final stop point of the gradient, and the start()
       
  1563     function returning the start point of the gradient.
       
  1564 
       
  1565     \sa QRadialGradient, QConicalGradient, {demos/gradients}{The
       
  1566     Gradients Demo}
       
  1567 */
       
  1568 
       
  1569 
       
  1570 /*!
       
  1571     Constructs a default linear gradient with interpolation area
       
  1572     between (0, 0) and (1, 1).
       
  1573 
       
  1574     \sa QGradient::setColorAt(), setStart(), setFinalStop()
       
  1575 */
       
  1576 
       
  1577 QLinearGradient::QLinearGradient()
       
  1578 {
       
  1579     m_type = LinearGradient;
       
  1580     m_spread = PadSpread;
       
  1581     m_data.linear.x1 = 0;
       
  1582     m_data.linear.y1 = 0;
       
  1583     m_data.linear.x2 = 1;
       
  1584     m_data.linear.y2 = 1;
       
  1585 }
       
  1586 
       
  1587 
       
  1588 /*!
       
  1589     Constructs a linear gradient with interpolation area between the
       
  1590     given \a start point and \a finalStop.
       
  1591 
       
  1592     \note The expected parameter values are in pixels.
       
  1593 
       
  1594     \sa QGradient::setColorAt(), QGradient::setStops()
       
  1595 */
       
  1596 QLinearGradient::QLinearGradient(const QPointF &start, const QPointF &finalStop)
       
  1597 {
       
  1598     m_type = LinearGradient;
       
  1599     m_spread = PadSpread;
       
  1600     m_data.linear.x1 = start.x();
       
  1601     m_data.linear.y1 = start.y();
       
  1602     m_data.linear.x2 = finalStop.x();
       
  1603     m_data.linear.y2 = finalStop.y();
       
  1604 }
       
  1605 
       
  1606 /*!
       
  1607     \fn QLinearGradient::QLinearGradient(qreal x1, qreal y1, qreal x2, qreal y2)
       
  1608 
       
  1609     Constructs a linear gradient with interpolation area between (\a
       
  1610     x1, \a y1) and (\a x2, \a y2).
       
  1611 
       
  1612     \note The expected parameter values are in pixels.
       
  1613 
       
  1614     \sa QGradient::setColorAt(), QGradient::setStops()
       
  1615 */
       
  1616 QLinearGradient::QLinearGradient(qreal xStart, qreal yStart, qreal xFinalStop, qreal yFinalStop)
       
  1617 {
       
  1618     m_type = LinearGradient;
       
  1619     m_spread = PadSpread;
       
  1620     m_data.linear.x1 = xStart;
       
  1621     m_data.linear.y1 = yStart;
       
  1622     m_data.linear.x2 = xFinalStop;
       
  1623     m_data.linear.y2 = yFinalStop;
       
  1624 }
       
  1625 
       
  1626 
       
  1627 /*!
       
  1628     Returns the start point of this linear gradient in logical coordinates.
       
  1629 
       
  1630     \sa QGradient::stops()
       
  1631 */
       
  1632 
       
  1633 QPointF QLinearGradient::start() const
       
  1634 {
       
  1635     Q_ASSERT(m_type == LinearGradient);
       
  1636     return QPointF(m_data.linear.x1, m_data.linear.y1);
       
  1637 }
       
  1638 
       
  1639 /*!
       
  1640     \fn void QLinearGradient::setStart(qreal x, qreal y)
       
  1641     \overload
       
  1642     \since 4.2
       
  1643 
       
  1644     Sets the start point of this linear gradient in logical
       
  1645     coordinates to \a x, \a y.
       
  1646 
       
  1647     \sa start()
       
  1648 */
       
  1649 
       
  1650 /*!
       
  1651     \since 4.2
       
  1652 
       
  1653     Sets the start point of this linear gradient in logical
       
  1654     coordinates to \a start.
       
  1655 
       
  1656     \sa start()
       
  1657 */
       
  1658 
       
  1659 void QLinearGradient::setStart(const QPointF &start)
       
  1660 {
       
  1661     Q_ASSERT(m_type == LinearGradient);
       
  1662     m_data.linear.x1 = start.x();
       
  1663     m_data.linear.y1 = start.y();
       
  1664 }
       
  1665 
       
  1666 
       
  1667 /*!
       
  1668     \fn void QLinearGradient::setFinalStop(qreal x, qreal y)
       
  1669     \overload
       
  1670     \since 4.2
       
  1671 
       
  1672     Sets the final stop point of this linear gradient in logical
       
  1673     coordinates to \a x, \a y.
       
  1674 
       
  1675     \sa start()
       
  1676 */
       
  1677 
       
  1678 /*!
       
  1679     Returns the final stop point of this linear gradient in logical coordinates.
       
  1680 
       
  1681     \sa QGradient::stops()
       
  1682 */
       
  1683 
       
  1684 QPointF QLinearGradient::finalStop() const
       
  1685 {
       
  1686     Q_ASSERT(m_type == LinearGradient);
       
  1687     return QPointF(m_data.linear.x2, m_data.linear.y2);
       
  1688 }
       
  1689 
       
  1690 
       
  1691 /*!
       
  1692     \since 4.2
       
  1693 
       
  1694     Sets the final stop point of this linear gradient in logical
       
  1695     coordinates to \a stop.
       
  1696 
       
  1697     \sa finalStop()
       
  1698 */
       
  1699 
       
  1700 void QLinearGradient::setFinalStop(const QPointF &stop)
       
  1701 {
       
  1702     Q_ASSERT(m_type == LinearGradient);
       
  1703     m_data.linear.x2 = stop.x();
       
  1704     m_data.linear.y2 = stop.y();
       
  1705 }
       
  1706 
       
  1707 
       
  1708 /*!
       
  1709     \class QRadialGradient
       
  1710     \ingroup painting
       
  1711 
       
  1712     \brief The QRadialGradient class is used in combination with QBrush to
       
  1713     specify a radial gradient brush.
       
  1714 
       
  1715     Radial gradients interpolate colors between a focal point and end
       
  1716     points on a circle surrounding it. Outside the end points the
       
  1717     gradient is either padded, reflected or repeated depending on the
       
  1718     currently set \l {QGradient::Spread}{spread} method:
       
  1719 
       
  1720     \table
       
  1721     \row
       
  1722     \o \inlineimage qradialgradient-pad.png
       
  1723     \o \inlineimage qradialgradient-reflect.png
       
  1724     \o \inlineimage qradialgradient-repeat.png
       
  1725     \row
       
  1726     \o \l {QGradient::PadSpread}{PadSpread} (default)
       
  1727     \o \l {QGradient::ReflectSpread}{ReflectSpread}
       
  1728     \o \l {QGradient::RepeatSpread}{RepeatSpread}
       
  1729     \endtable
       
  1730 
       
  1731     The colors in a gradient is defined using stop points of the
       
  1732     QGradientStop type, i.e. a position and a color. Use the
       
  1733     QGradient::setColorAt() or the QGradient::setStops() function to
       
  1734     define the stop points. It is the gradient's complete set of stop
       
  1735     points that describes how the gradient area should be filled.  If
       
  1736     no stop points have been specified, a gradient of black at 0 to
       
  1737     white at 1 is used.
       
  1738 
       
  1739     In addition to the functions inherited from QGradient, the
       
  1740     QRadialGradient class provides the center(), focalPoint() and
       
  1741     radius() functions returning the gradient's center, focal point
       
  1742     and radius respectively.
       
  1743 
       
  1744     \sa QLinearGradient, QConicalGradient, {demos/gradients}{The
       
  1745     Gradients Demo}
       
  1746 */
       
  1747 
       
  1748 static QPointF qt_radial_gradient_adapt_focal_point(const QPointF &center,
       
  1749                                                     qreal radius,
       
  1750                                                     const QPointF &focalPoint)
       
  1751 {
       
  1752     // We have a one pixel buffer zone to avoid numerical instability on the
       
  1753     // circle border
       
  1754     //### this is hacky because technically we should adjust based on current matrix
       
  1755     const qreal compensated_radius = radius - radius * 0.001;
       
  1756     QLineF line(center, focalPoint);
       
  1757     if (line.length() > (compensated_radius))
       
  1758         line.setLength(compensated_radius);
       
  1759     return line.p2();
       
  1760 }
       
  1761 
       
  1762 /*!
       
  1763     Constructs a radial gradient with the given \a center, \a
       
  1764     radius and \a focalPoint.
       
  1765 
       
  1766     \sa QGradient::setColorAt(), QGradient::setStops()
       
  1767 */
       
  1768 
       
  1769 QRadialGradient::QRadialGradient(const QPointF &center, qreal radius, const QPointF &focalPoint)
       
  1770 {
       
  1771     m_type = RadialGradient;
       
  1772     m_spread = PadSpread;
       
  1773     m_data.radial.cx = center.x();
       
  1774     m_data.radial.cy = center.y();
       
  1775     m_data.radial.radius = radius;
       
  1776 
       
  1777     QPointF adapted_focal = qt_radial_gradient_adapt_focal_point(center, radius, focalPoint);
       
  1778     m_data.radial.fx = adapted_focal.x();
       
  1779     m_data.radial.fy = adapted_focal.y();
       
  1780 }
       
  1781 
       
  1782 /*!
       
  1783     Constructs a radial gradient with the given \a center, \a
       
  1784     radius and the focal point in the circle center.
       
  1785 
       
  1786     \sa QGradient::setColorAt(), QGradient::setStops()
       
  1787 */
       
  1788 QRadialGradient::QRadialGradient(const QPointF &center, qreal radius)
       
  1789 {
       
  1790     m_type = RadialGradient;
       
  1791     m_spread = PadSpread;
       
  1792     m_data.radial.cx = center.x();
       
  1793     m_data.radial.cy = center.y();
       
  1794     m_data.radial.radius = radius;
       
  1795     m_data.radial.fx = center.x();
       
  1796     m_data.radial.fy = center.y();
       
  1797 }
       
  1798 
       
  1799 
       
  1800 /*!
       
  1801     Constructs a radial gradient with the given center (\a cx, \a cy),
       
  1802     \a radius and focal point (\a fx, \a fy).
       
  1803 
       
  1804     \sa QGradient::setColorAt(), QGradient::setStops()
       
  1805 */
       
  1806 
       
  1807 QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius, qreal fx, qreal fy)
       
  1808 {
       
  1809     m_type = RadialGradient;
       
  1810     m_spread = PadSpread;
       
  1811     m_data.radial.cx = cx;
       
  1812     m_data.radial.cy = cy;
       
  1813     m_data.radial.radius = radius;
       
  1814 
       
  1815     QPointF adapted_focal = qt_radial_gradient_adapt_focal_point(QPointF(cx, cy),
       
  1816                                                                  radius,
       
  1817                                                                  QPointF(fx, fy));
       
  1818 
       
  1819     m_data.radial.fx = adapted_focal.x();
       
  1820     m_data.radial.fy = adapted_focal.y();
       
  1821 }
       
  1822 
       
  1823 /*!
       
  1824     Constructs a radial gradient with the center at (\a cx, \a cy) and the
       
  1825     specified \a radius. The focal point lies at the center of the circle.
       
  1826 
       
  1827     \sa QGradient::setColorAt(), QGradient::setStops()
       
  1828  */
       
  1829 QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius)
       
  1830 {
       
  1831     m_type = RadialGradient;
       
  1832     m_spread = PadSpread;
       
  1833     m_data.radial.cx = cx;
       
  1834     m_data.radial.cy = cy;
       
  1835     m_data.radial.radius = radius;
       
  1836     m_data.radial.fx = cx;
       
  1837     m_data.radial.fy = cy;
       
  1838 }
       
  1839 
       
  1840 
       
  1841 /*!
       
  1842     Constructs a radial gradient with the center and focal point at
       
  1843     (0, 0) with a radius of 1.
       
  1844 */
       
  1845 QRadialGradient::QRadialGradient()
       
  1846 {
       
  1847     m_type = RadialGradient;
       
  1848     m_spread = PadSpread;
       
  1849     m_data.radial.cx = 0;
       
  1850     m_data.radial.cy = 0;
       
  1851     m_data.radial.radius = 1;
       
  1852     m_data.radial.fx = 0;
       
  1853     m_data.radial.fy = 0;
       
  1854 }
       
  1855 
       
  1856 
       
  1857 /*!
       
  1858     Returns the center of this radial gradient in logical coordinates.
       
  1859 
       
  1860     \sa QGradient::stops()
       
  1861 */
       
  1862 
       
  1863 QPointF QRadialGradient::center() const
       
  1864 {
       
  1865     Q_ASSERT(m_type == RadialGradient);
       
  1866     return QPointF(m_data.radial.cx, m_data.radial.cy);
       
  1867 }
       
  1868 
       
  1869 /*!
       
  1870     \fn void QRadialGradient::setCenter(qreal x, qreal y)
       
  1871     \overload
       
  1872     \since 4.2
       
  1873 
       
  1874     Sets the center of this radial gradient in logical coordinates
       
  1875     to (\a x, \a y).
       
  1876 
       
  1877     \sa center()
       
  1878 */
       
  1879 
       
  1880 /*!
       
  1881     \since 4.2
       
  1882 
       
  1883     Sets the center of this radial gradient in logical coordinates
       
  1884     to \a center.
       
  1885 
       
  1886     \sa center()
       
  1887 */
       
  1888 
       
  1889 void QRadialGradient::setCenter(const QPointF &center)
       
  1890 {
       
  1891     Q_ASSERT(m_type == RadialGradient);
       
  1892     m_data.radial.cx = center.x();
       
  1893     m_data.radial.cy = center.y();
       
  1894 }
       
  1895 
       
  1896 
       
  1897 /*!
       
  1898     Returns the radius of this radial gradient in logical coordinates.
       
  1899 
       
  1900     \sa QGradient::stops()
       
  1901 */
       
  1902 
       
  1903 qreal QRadialGradient::radius() const
       
  1904 {
       
  1905     Q_ASSERT(m_type == RadialGradient);
       
  1906     return m_data.radial.radius;
       
  1907 }
       
  1908 
       
  1909 
       
  1910 /*!
       
  1911     \since 4.2
       
  1912 
       
  1913     Sets the radius of this radial gradient in logical coordinates
       
  1914     to \a radius
       
  1915 */
       
  1916 void QRadialGradient::setRadius(qreal radius)
       
  1917 {
       
  1918     Q_ASSERT(m_type == RadialGradient);
       
  1919     m_data.radial.radius = radius;
       
  1920 }
       
  1921 
       
  1922 
       
  1923 /*!
       
  1924     Returns the focal point of this radial gradient in logical
       
  1925     coordinates.
       
  1926 
       
  1927     \sa QGradient::stops()
       
  1928 */
       
  1929 
       
  1930 QPointF QRadialGradient::focalPoint() const
       
  1931 {
       
  1932     Q_ASSERT(m_type == RadialGradient);
       
  1933     return QPointF(m_data.radial.fx, m_data.radial.fy);
       
  1934 }
       
  1935 
       
  1936 /*!
       
  1937     \fn void QRadialGradient::setFocalPoint(qreal x, qreal y)
       
  1938     \overload
       
  1939     \since 4.2
       
  1940 
       
  1941     Sets the focal point of this radial gradient in logical
       
  1942     coordinates to (\a x, \a y).
       
  1943 
       
  1944     \sa focalPoint()
       
  1945 */
       
  1946 
       
  1947 /*!
       
  1948     \since 4.2
       
  1949 
       
  1950     Sets the focal point of this radial gradient in logical
       
  1951     coordinates to \a focalPoint.
       
  1952 
       
  1953     \sa focalPoint()
       
  1954 */
       
  1955 
       
  1956 void QRadialGradient::setFocalPoint(const QPointF &focalPoint)
       
  1957 {
       
  1958     Q_ASSERT(m_type == RadialGradient);
       
  1959     m_data.radial.fx = focalPoint.x();
       
  1960     m_data.radial.fy = focalPoint.y();
       
  1961 }
       
  1962 
       
  1963 
       
  1964 
       
  1965 /*!
       
  1966     \class QConicalGradient
       
  1967     \ingroup painting
       
  1968 
       
  1969     \brief The QConicalGradient class is used in combination with QBrush to
       
  1970     specify a conical gradient brush.
       
  1971 
       
  1972     Conical gradients interpolate interpolate colors counter-clockwise
       
  1973     around a center point.
       
  1974 
       
  1975     \image qconicalgradient.png
       
  1976 
       
  1977     The colors in a gradient is defined using stop points of the
       
  1978     QGradientStop type, i.e. a position and a color. Use the
       
  1979     QGradient::setColorAt() or the QGradient::setStops() function to
       
  1980     define the stop points. It is the gradient's complete set of stop
       
  1981     points that describes how the gradient area should be filled. If
       
  1982     no stop points have been specified, a gradient of black at 0 to
       
  1983     white at 1 is used.
       
  1984 
       
  1985     In addition to the functions inherited from QGradient, the
       
  1986     QConicalGradient class provides the angle() and center() functions
       
  1987     returning the start angle and center of the gradient.
       
  1988 
       
  1989     Note that the setSpread() function has no effect for conical
       
  1990     gradients. The reason is that the conical gradient is closed by
       
  1991     definition, i.e. the conical gradient fills the entire circle from
       
  1992     0 - 360 degrees, while the boundary of a radial or a linear
       
  1993     gradient can be specified through its radius or final stop points,
       
  1994     respectively.
       
  1995 
       
  1996     \sa QLinearGradient, QRadialGradient, {demos/gradients}{The
       
  1997     Gradients Demo}
       
  1998 */
       
  1999 
       
  2000 
       
  2001 /*!
       
  2002     Constructs a conical gradient with the given \a center, starting
       
  2003     the interpolation at the given \a angle. The \a angle must be
       
  2004     specified in degrees between 0 and 360.
       
  2005 
       
  2006     \sa QGradient::setColorAt(), QGradient::setStops()
       
  2007 */
       
  2008 
       
  2009 QConicalGradient::QConicalGradient(const QPointF &center, qreal angle)
       
  2010 {
       
  2011     m_type = ConicalGradient;
       
  2012     m_spread = PadSpread;
       
  2013     m_data.conical.cx = center.x();
       
  2014     m_data.conical.cy = center.y();
       
  2015     m_data.conical.angle = angle;
       
  2016 }
       
  2017 
       
  2018 
       
  2019 /*!
       
  2020     Constructs a conical gradient with the given center (\a cx, \a
       
  2021     cy), starting the interpolation at the given \a angle. The angle
       
  2022     must be specified in degrees between 0 and 360.
       
  2023 
       
  2024     \sa QGradient::setColorAt(), QGradient::setStops()
       
  2025 */
       
  2026 
       
  2027 QConicalGradient::QConicalGradient(qreal cx, qreal cy, qreal angle)
       
  2028 {
       
  2029     m_type = ConicalGradient;
       
  2030     m_spread = PadSpread;
       
  2031     m_data.conical.cx = cx;
       
  2032     m_data.conical.cy = cy;
       
  2033     m_data.conical.angle = angle;
       
  2034 }
       
  2035 
       
  2036 
       
  2037 /*!
       
  2038     Constructs a conical with center at (0, 0) starting the
       
  2039     interpolation at angle 0.
       
  2040 
       
  2041     \sa QGradient::setColorAt(), setCenter(), setAngle()
       
  2042 */
       
  2043 
       
  2044 QConicalGradient::QConicalGradient()
       
  2045 {
       
  2046     m_type = ConicalGradient;
       
  2047     m_spread = PadSpread;
       
  2048     m_data.conical.cx = 0;
       
  2049     m_data.conical.cy = 0;
       
  2050     m_data.conical.angle = 0;
       
  2051 }
       
  2052 
       
  2053 
       
  2054 /*!
       
  2055     Returns the center of the conical gradient in logical
       
  2056     coordinates.
       
  2057 
       
  2058     \sa stops()
       
  2059 */
       
  2060 
       
  2061 QPointF QConicalGradient::center() const
       
  2062 {
       
  2063     Q_ASSERT(m_type == ConicalGradient);
       
  2064     return QPointF(m_data.conical.cx, m_data.conical.cy);
       
  2065 }
       
  2066 
       
  2067 
       
  2068 /*!
       
  2069     \fn void QConicalGradient::setCenter(qreal x, qreal y)
       
  2070 
       
  2071     \overload
       
  2072 
       
  2073     Sets the center of this conical gradient in logical coordinates to
       
  2074     (\a x, \a y).
       
  2075 
       
  2076     \sa center()
       
  2077 */
       
  2078 
       
  2079 /*!
       
  2080     Sets the center of this conical gradient in logical coordinates to
       
  2081     \a center.
       
  2082 
       
  2083     \sa center()
       
  2084 */
       
  2085 
       
  2086 void QConicalGradient::setCenter(const QPointF &center)
       
  2087 {
       
  2088     Q_ASSERT(m_type == ConicalGradient);
       
  2089     m_data.conical.cx = center.x();
       
  2090     m_data.conical.cy = center.y();
       
  2091 }
       
  2092 
       
  2093 /*!
       
  2094     Returns the start angle of the conical gradient in logical
       
  2095     coordinates.
       
  2096 
       
  2097     \sa stops()
       
  2098 */
       
  2099 
       
  2100 qreal QConicalGradient::angle() const
       
  2101 {
       
  2102     Q_ASSERT(m_type == ConicalGradient);
       
  2103     return m_data.conical.angle;
       
  2104 }
       
  2105 
       
  2106 
       
  2107 /*!
       
  2108     \since 4.2
       
  2109 
       
  2110     Sets \a angle to be the start angle for this conical gradient in
       
  2111     logical coordinates.
       
  2112 
       
  2113     \sa angle()
       
  2114 */
       
  2115 
       
  2116 void QConicalGradient::setAngle(qreal angle)
       
  2117 {
       
  2118     Q_ASSERT(m_type == ConicalGradient);
       
  2119     m_data.conical.angle = angle;
       
  2120 }
       
  2121 
       
  2122 /*!
       
  2123     \typedef QGradientStop
       
  2124     \relates QGradient
       
  2125 
       
  2126     Typedef for QPair<\l qreal, QColor>.
       
  2127 */
       
  2128 
       
  2129 /*!
       
  2130     \typedef QGradientStops
       
  2131     \relates QGradient
       
  2132 
       
  2133     Typedef for QVector<QGradientStop>.
       
  2134 */
       
  2135 
       
  2136 /*!
       
  2137     \typedef QBrush::DataPtr
       
  2138     \internal
       
  2139 */
       
  2140 
       
  2141 /*!
       
  2142     \fn DataPtr &QBrush::data_ptr()
       
  2143     \internal
       
  2144 */
       
  2145 
       
  2146 
       
  2147 /*!
       
  2148     \fn bool QBrush::isDetached() const
       
  2149     \internal
       
  2150 */
       
  2151 
       
  2152 /*!
       
  2153     \fn QTransform QBrush::transform() const
       
  2154     \since 4.3
       
  2155 
       
  2156     Returns the current transformation matrix for the brush.
       
  2157 
       
  2158     \sa setTransform()
       
  2159 */
       
  2160 
       
  2161 QT_END_NAMESPACE