Changeset 8127 in ntrip for trunk/BNC/qwt/qwt_symbol.cpp


Ignore:
Timestamp:
May 10, 2017, 3:20:54 PM (7 years ago)
Author:
stoecker
Message:

update qwt and qwtpolar, many QT5 fixes (unfinished)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/qwt/qwt_symbol.cpp

    r4271 r8127  
    1010#include "qwt_symbol.h"
    1111#include "qwt_painter.h"
     12#include "qwt_graphic.h"
    1213#include <qapplication.h>
    1314#include <qpainter.h>
     15#include <qpainterpath.h>
     16#include <qpixmap.h>
     17#include <qpaintengine.h>
    1418#include <qmath.h>
     19#ifndef QWT_NO_SVG
     20#include <qsvgrenderer.h>
     21#endif
    1522
    1623namespace QwtTriangle
     
    2330        Down
    2431    };
     32}
     33
     34static QwtGraphic qwtPathGraphic( const QPainterPath &path,
     35    const QPen &pen, const QBrush& brush )
     36{
     37    QwtGraphic graphic;
     38    graphic.setRenderHint( QwtGraphic::RenderPensUnscaled );
     39
     40    QPainter painter( &graphic );
     41    painter.setPen( pen );
     42    painter.setBrush( brush );
     43    painter.drawPath( path );
     44    painter.end();
     45
     46    return graphic;
     47}
     48
     49static inline QRectF qwtScaledBoundingRect(
     50    const QwtGraphic &graphic, const QSizeF size )
     51{
     52    QSizeF scaledSize = size;
     53    if ( scaledSize.isEmpty() )
     54        scaledSize = graphic.defaultSize();
     55       
     56    const QSizeF sz = graphic.controlPointRect().size();
     57
     58    double sx = 1.0;
     59    if ( sz.width() > 0.0 )
     60        sx = scaledSize.width() / sz.width();
     61   
     62    double sy = 1.0;
     63    if ( sz.height() > 0.0 )
     64        sy = scaledSize.height() / sz.height();
     65
     66    return graphic.scaledBoundingRect( sx, sy );
     67}
     68
     69static inline void qwtDrawPixmapSymbols( QPainter *painter,
     70    const QPointF *points, int numPoints, const QwtSymbol &symbol )
     71{
     72    QSize size = symbol.size();
     73    if ( size.isEmpty() )
     74        size = symbol.pixmap().size();
     75
     76    const QTransform transform = painter->transform();
     77    if ( transform.isScaling() )
     78    {
     79        const QRect r( 0, 0, size.width(), size.height() );
     80        size = transform.mapRect( r ).size();
     81    }
     82
     83    QPixmap pm = symbol.pixmap();
     84    if ( pm.size() != size )
     85        pm = pm.scaled( size );
     86   
     87    QPointF pinPoint( 0.5 * size.width(), 0.5 * size.height() );
     88    if ( symbol.isPinPointEnabled() )
     89        pinPoint = symbol.pinPoint();
     90
     91    painter->resetTransform();
     92
     93    for ( int i = 0; i < numPoints; i++ )
     94    {
     95        const QPointF pos = transform.map( points[i] ) - pinPoint;
     96
     97        QwtPainter::drawPixmap( painter,
     98            QRect( pos.toPoint(), pm.size() ), pm );
     99    }
     100}
     101
     102#ifndef QWT_NO_SVG
     103
     104static inline void qwtDrawSvgSymbols( QPainter *painter,
     105    const QPointF *points, int numPoints,
     106    QSvgRenderer *renderer, const QwtSymbol &symbol )
     107{
     108    if ( renderer == NULL || !renderer->isValid() )
     109        return;
     110
     111    const QRectF viewBox = renderer->viewBoxF();
     112    if ( viewBox.isEmpty() )
     113        return;
     114
     115    QSizeF sz = symbol.size();
     116    if ( !sz.isValid() )
     117        sz = viewBox.size();
     118
     119    const double sx = sz.width() / viewBox.width();
     120    const double sy = sz.height() / viewBox.height();
     121
     122    QPointF pinPoint = viewBox.center();
     123    if ( symbol.isPinPointEnabled() )
     124        pinPoint = symbol.pinPoint();
     125
     126    const double dx = sx * ( pinPoint.x() - viewBox.left() );
     127    const double dy = sy * ( pinPoint.y() - viewBox.top() );
     128
     129    for ( int i = 0; i < numPoints; i++ )
     130    {
     131        const double x = points[i].x() - dx;
     132        const double y = points[i].y() - dy;
     133
     134        renderer->render( painter,
     135            QRectF( x, y, sz.width(), sz.height() ) );
     136    }
     137}
     138
     139#endif
     140
     141static inline void qwtDrawGraphicSymbols( QPainter *painter,
     142    const QPointF *points, int numPoints, const QwtGraphic &graphic,
     143    const QwtSymbol &symbol )
     144{
     145    const QRectF pointRect = graphic.controlPointRect();
     146    if ( pointRect.isEmpty() )
     147        return;
     148
     149    double sx = 1.0;
     150    double sy = 1.0;
     151
     152    const QSize sz = symbol.size();
     153    if ( sz.isValid() )
     154    {
     155        sx = sz.width() / pointRect.width();
     156        sy = sz.height() / pointRect.height();
     157    }
     158
     159    QPointF pinPoint = pointRect.center();
     160    if ( symbol.isPinPointEnabled() )
     161        pinPoint = symbol.pinPoint();
     162
     163    const QTransform transform = painter->transform();
     164
     165    for ( int i = 0; i < numPoints; i++ )
     166    {
     167        QTransform tr = transform;
     168        tr.translate( points[i].x(), points[i].y() );
     169        tr.scale( sx, sy );
     170        tr.translate( -pinPoint.x(), -pinPoint.y() );
     171
     172        painter->setTransform( tr );
     173
     174        graphic.render( painter );
     175    }
     176
     177    painter->setTransform( transform );
    25178}
    26179
     
    623776        size( sz ),
    624777        brush( br ),
    625         pen( pn )
    626     {
    627     }
    628 
    629     bool operator==( const PrivateData &other ) const
    630     {
    631         return ( style == other.style )
    632             && ( size == other.size )
    633             && ( brush == other.brush )
    634             && ( pen == other.pen );
    635     }
    636 
     778        pen( pn ),
     779        isPinPointEnabled( false )
     780    {
     781        cache.policy = QwtSymbol::AutoCache;
     782#ifndef QWT_NO_SVG
     783        svg.renderer = NULL;
     784#endif
     785    }
     786
     787    ~PrivateData()
     788    {
     789#ifndef QWT_NO_SVG
     790        delete svg.renderer;
     791#endif
     792    }
    637793
    638794    Style style;
     
    640796    QBrush brush;
    641797    QPen pen;
     798
     799    bool isPinPointEnabled;
     800    QPointF pinPoint;
     801
     802    struct Path
     803    {
     804        QPainterPath path;
     805        QwtGraphic graphic;
     806
     807    } path;
     808
     809    struct Pixmap
     810    {
     811        QPixmap pixmap;
     812
     813    } pixmap;
     814
     815    struct Graphic
     816    {
     817        QwtGraphic graphic;
     818
     819    } graphic;
     820
     821#ifndef QWT_NO_SVG
     822    struct SVG
     823    {
     824        QSvgRenderer *renderer;
     825    } svg;
     826#endif
     827
     828    struct PaintCache
     829    {
     830        QwtSymbol::CachePolicy policy;
     831        QPixmap pixmap;
     832
     833    } cache;
    642834};
    643835
     
    652844{
    653845    d_data = new PrivateData( style, QBrush( Qt::gray ),
    654         QPen( Qt::black ), QSize( 0.0, 0.0 ) );
     846        QPen( Qt::black, 0 ), QSize() );
    655847}
    656848
     
    671863
    672864/*!
    673   \brief Copy constructor
    674 
    675   \param other Symbol
     865  \brief Constructor
     866
     867  The symbol gets initialized by a painter path. The style is
     868  set to QwtSymbol::Path, the size is set to empty ( the path
     869  is displayed unscaled ).
     870
     871  \param path painter path
     872  \param brush brush to fill the interior
     873  \param pen outline pen
     874
     875  \sa setPath(), setBrush(), setPen(), setSize()
    676876*/
    677 QwtSymbol::QwtSymbol( const QwtSymbol &other )
    678 {
    679     d_data = new PrivateData( other.style(), other.brush(),
    680         other.pen(), other.size() );
    681 };
     877
     878QwtSymbol::QwtSymbol( const QPainterPath &path,
     879    const QBrush &brush, const QPen &pen )
     880{
     881    d_data = new PrivateData( QwtSymbol::Path, brush, pen, QSize() );
     882    setPath( path );
     883}
    682884
    683885//! Destructor
     
    687889}
    688890
    689 //! \brief Assignment operator
    690 QwtSymbol &QwtSymbol::operator=( const QwtSymbol &other )
    691 {
    692     *d_data = *other.d_data;
    693     return *this;
    694 }
    695 
    696 //! \brief Compare two symbols
    697 bool QwtSymbol::operator==( const QwtSymbol &other ) const
    698 {
    699     return *d_data == *other.d_data;
    700 }
    701 
    702 //! \brief Compare two symbols
    703 bool QwtSymbol::operator!=( const QwtSymbol &other ) const
    704 {
    705     return !( *d_data == *other.d_data );
    706 }
     891/*!
     892  Change the cache policy
     893
     894  The default policy is AutoCache
     895
     896  \param policy Cache policy
     897  \sa CachePolicy, cachePolicy()
     898*/
     899void QwtSymbol::setCachePolicy(
     900    QwtSymbol::CachePolicy policy )
     901{
     902    if ( d_data->cache.policy != policy )
     903    {
     904        d_data->cache.policy = policy;
     905        invalidateCache();
     906    }
     907}
     908
     909/*!
     910  \return Cache policy
     911  \sa CachePolicy, setCachePolicy()
     912*/
     913QwtSymbol::CachePolicy QwtSymbol::cachePolicy() const
     914{
     915    return d_data->cache.policy;
     916}
     917
     918/*!
     919  \brief Set a painter path as symbol
     920
     921  The symbol is represented by a painter path, where the
     922  origin ( 0, 0 ) of the path coordinate system is mapped to
     923  the position of the symbol.
     924
     925  When the symbol has valid size the painter path gets scaled
     926  to fit into the size. Otherwise the symbol size depends on
     927  the bounding rectangle of the path.
     928
     929  The following code defines a symbol drawing an arrow:
     930
     931  \verbatim
     932#include <qwt_symbol.h>
     933
     934QwtSymbol *symbol = new QwtSymbol();
     935
     936QPen pen( Qt::black, 2 );
     937pen.setJoinStyle( Qt::MiterJoin );
     938
     939symbol->setPen( pen );
     940symbol->setBrush( Qt::red );
     941
     942QPainterPath path;
     943path.moveTo( 0, 8 );
     944path.lineTo( 0, 5 );
     945path.lineTo( -3, 5 );
     946path.lineTo( 0, 0 );
     947path.lineTo( 3, 5 );
     948path.lineTo( 0, 5 );
     949
     950QTransform transform;
     951transform.rotate( -30.0 );
     952path = transform.map( path );
     953
     954symbol->setPath( path );
     955symbol->setPinPoint( QPointF( 0.0, 0.0 ) );
     956
     957setSize( 10, 14 );
     958\endverbatim
     959
     960  \param path Painter path
     961
     962  \note The style is implicitely set to QwtSymbol::Path.
     963  \sa path(), setSize()
     964 */
     965void QwtSymbol::setPath( const QPainterPath &path )
     966{
     967    d_data->style = QwtSymbol::Path;
     968    d_data->path.path = path;
     969    d_data->path.graphic.reset();
     970}
     971
     972/*!
     973   \return Painter path for displaying the symbol
     974   \sa setPath()
     975*/
     976const QPainterPath &QwtSymbol::path() const
     977{
     978    return d_data->path.path;
     979}
     980
     981/*!
     982  Set a pixmap as symbol
     983
     984  \param pixmap Pixmap
     985
     986  \sa pixmap(), setGraphic()
     987
     988  \note the style() is set to QwtSymbol::Pixmap
     989  \note brush() and pen() have no effect
     990 */
     991void QwtSymbol::setPixmap( const QPixmap &pixmap )
     992{
     993    d_data->style = QwtSymbol::Pixmap;
     994    d_data->pixmap.pixmap = pixmap;
     995}
     996
     997/*!
     998  \return Assigned pixmap
     999  \sa setPixmap()
     1000 */
     1001const QPixmap &QwtSymbol::pixmap() const
     1002{
     1003    return d_data->pixmap.pixmap;
     1004}
     1005
     1006/*!
     1007  Set a graphic as symbol
     1008
     1009  \param graphic Graphic
     1010
     1011  \sa graphic(), setPixmap()
     1012
     1013  \note the style() is set to QwtSymbol::Graphic
     1014  \note brush() and pen() have no effect
     1015 */
     1016void QwtSymbol::setGraphic( const QwtGraphic &graphic )
     1017{
     1018    d_data->style = QwtSymbol::Graphic;
     1019    d_data->graphic.graphic = graphic;
     1020}
     1021
     1022/*!
     1023  \return Assigned graphic
     1024  \sa setGraphic()
     1025 */
     1026const QwtGraphic &QwtSymbol::graphic() const
     1027{
     1028    return d_data->graphic.graphic;
     1029}
     1030
     1031#ifndef QWT_NO_SVG
     1032
     1033/*!
     1034  Set a SVG icon as symbol
     1035
     1036  \param svgDocument SVG icon
     1037
     1038  \sa setGraphic(), setPixmap()
     1039
     1040  \note the style() is set to QwtSymbol::SvgDocument
     1041  \note brush() and pen() have no effect
     1042 */
     1043void QwtSymbol::setSvgDocument( const QByteArray &svgDocument )
     1044{
     1045    d_data->style = QwtSymbol::SvgDocument;
     1046    if ( d_data->svg.renderer == NULL )
     1047        d_data->svg.renderer = new QSvgRenderer();
     1048
     1049    d_data->svg.renderer->load( svgDocument );
     1050}
     1051
     1052#endif
    7071053
    7081054/*!
     
    7121058  and the 'w' parameter is greater than or equal to 0,
    7131059  the symbol size will be set to (w,w).
     1060
    7141061  \param width Width
    7151062  \param height Height (defaults to -1)
     
    7221069        height = width;
    7231070
    724     d_data->size = QSize( width, height );
     1071    setSize( QSize( width, height ) );
    7251072}
    7261073
     
    7331080void QwtSymbol::setSize( const QSize &size )
    7341081{
    735     if ( size.isValid() )
     1082    if ( size.isValid() && size != d_data->size )
     1083    {
    7361084        d_data->size = size;
     1085        invalidateCache();
     1086    }
    7371087}
    7381088
     
    7561106void QwtSymbol::setBrush( const QBrush &brush )
    7571107{
    758     d_data->brush = brush;
     1108    if ( brush != d_data->brush )
     1109    {
     1110        d_data->brush = brush;
     1111        invalidateCache();
     1112
     1113        if ( d_data->style == QwtSymbol::Path )
     1114            d_data->path.graphic.reset();
     1115    }
    7591116}
    7601117
     
    7691126
    7701127/*!
     1128  Build and assign a pen
     1129
     1130  In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 )
     1131  what makes it non cosmetic ( see QPen::isCosmetic() ).
     1132  This method has been introduced to hide this incompatibility.
     1133
     1134  \param color Pen color
     1135  \param width Pen width
     1136  \param style Pen style
     1137
     1138  \sa pen(), brush()
     1139 */
     1140void QwtSymbol::setPen( const QColor &color,
     1141    qreal width, Qt::PenStyle style )
     1142{
     1143    setPen( QPen( color, width, style ) );
     1144}
     1145
     1146/*!
    7711147  Assign a pen
    7721148
     
    7781154void QwtSymbol::setPen( const QPen &pen )
    7791155{
    780     d_data->pen = pen;
     1156    if ( pen != d_data->pen )
     1157    {
     1158        d_data->pen = pen;
     1159        invalidateCache();
     1160
     1161        if ( d_data->style == QwtSymbol::Path )
     1162            d_data->path.graphic.reset();
     1163    }
    7811164}
    7821165
     
    8151198        case QwtSymbol::Hexagon:
    8161199        {
    817             d_data->brush.setColor( color );
     1200            if ( d_data->brush.color() != color )
     1201            {
     1202                d_data->brush.setColor( color );
     1203                invalidateCache();
     1204            }
    8181205            break;
    8191206        }
     
    8241211        case QwtSymbol::Star1:
    8251212        {
    826             d_data->pen.setColor( color );
     1213            if ( d_data->pen.color() != color )
     1214            {
     1215                d_data->pen.setColor( color );
     1216                invalidateCache();
     1217            }
    8271218            break;
    8281219        }
    8291220        default:
    8301221        {
     1222            if ( d_data->brush.color() != color ||
     1223                d_data->pen.color() != color )
     1224            {
     1225                invalidateCache();
     1226            }
     1227
    8311228            d_data->brush.setColor( color );
    8321229            d_data->pen.setColor( color );
     
    8361233
    8371234/*!
    838   Draw an array of symbols
     1235  \brief Set and enable a pin point
     1236
     1237  The position of a complex symbol is not always aligned to its center
     1238  ( f.e an arrow, where the peak points to a position ). The pin point
     1239  defines the position inside of a Pixmap, Graphic, SvgDocument
     1240  or PainterPath symbol where the represented point has to
     1241  be aligned to.
     1242 
     1243  \param pos Position
     1244  \param enable En/Disable the pin point alignment
     1245
     1246  \sa pinPoint(), setPinPointEnabled()
     1247 */
     1248void QwtSymbol::setPinPoint( const QPointF &pos, bool enable )
     1249{
     1250    if ( d_data->pinPoint != pos )
     1251    {
     1252        d_data->pinPoint = pos;
     1253        if ( d_data->isPinPointEnabled )
     1254        {
     1255            invalidateCache();
     1256        }
     1257    }
     1258
     1259    setPinPointEnabled( enable );
     1260}
     1261
     1262/*!
     1263  \return Pin point
     1264  \sa setPinPoint(), setPinPointEnabled()
     1265 */
     1266QPointF QwtSymbol::pinPoint() const
     1267{
     1268    return d_data->pinPoint;
     1269}
     1270
     1271/*!
     1272  En/Disable the pin point alignment
     1273
     1274  \param on Enabled, when on is true
     1275  \sa setPinPoint(), isPinPointEnabled()
     1276 */
     1277void QwtSymbol::setPinPointEnabled( bool on )
     1278{
     1279    if ( d_data->isPinPointEnabled != on )
     1280    {
     1281        d_data->isPinPointEnabled = on;
     1282        invalidateCache();
     1283    }
     1284}
     1285
     1286/*!
     1287  \return True, when the pin point translation is enabled
     1288  \sa setPinPoint(), setPinPointEnabled()
     1289 */
     1290bool QwtSymbol::isPinPointEnabled() const
     1291{
     1292    return d_data->isPinPointEnabled;
     1293}
     1294
     1295/*!
     1296  Render an array of symbols
    8391297
    8401298  Painting several symbols is more effective than drawing symbols
     
    8521310        return;
    8531311
    854     painter->save();
    855 
     1312    bool useCache = false;
     1313
     1314    // Don't use the pixmap, when the paint device
     1315    // could generate scalable vectors
     1316
     1317    if ( QwtPainter::roundingAlignment( painter ) &&
     1318        !painter->transform().isScaling() )
     1319    {
     1320        if ( d_data->cache.policy == QwtSymbol::Cache )
     1321        {
     1322            useCache = true;
     1323        }
     1324        else if ( d_data->cache.policy == QwtSymbol::AutoCache )
     1325        {
     1326            if ( painter->paintEngine()->type() == QPaintEngine::Raster )
     1327            {
     1328                useCache = true;
     1329            }
     1330            else
     1331            {
     1332                switch( d_data->style )
     1333                {
     1334                    case QwtSymbol::XCross:
     1335                    case QwtSymbol::HLine:
     1336                    case QwtSymbol::VLine:
     1337                    case QwtSymbol::Cross:
     1338                        break;
     1339
     1340                    case QwtSymbol::Pixmap:
     1341                    {
     1342                        if ( !d_data->size.isEmpty() &&
     1343                            d_data->size != d_data->pixmap.pixmap.size() )
     1344                        {
     1345                            useCache = true;
     1346                        }
     1347                        break;
     1348                    }                       
     1349                    default:
     1350                        useCache = true;
     1351                }
     1352            }
     1353        }
     1354    }
     1355
     1356    if ( useCache )
     1357    {
     1358        const QRect br = boundingRect();
     1359
     1360        const QRect rect( 0, 0, br.width(), br.height() );
     1361       
     1362        if ( d_data->cache.pixmap.isNull() )
     1363        {
     1364            d_data->cache.pixmap = QwtPainter::backingStore( NULL, br.size() );
     1365            d_data->cache.pixmap.fill( Qt::transparent );
     1366
     1367            QPainter p( &d_data->cache.pixmap );
     1368            p.setRenderHints( painter->renderHints() );
     1369            p.translate( -br.topLeft() );
     1370
     1371            const QPointF pos;
     1372            renderSymbols( &p, &pos, 1 );
     1373        }
     1374
     1375        const int dx = br.left();
     1376        const int dy = br.top();
     1377
     1378        for ( int i = 0; i < numPoints; i++ )
     1379        {
     1380            const int left = qRound( points[i].x() ) + dx;
     1381            const int top = qRound( points[i].y() ) + dy;
     1382
     1383            painter->drawPixmap( left, top, d_data->cache.pixmap );
     1384        }
     1385    }
     1386    else
     1387    {
     1388        painter->save();
     1389        renderSymbols( painter, points, numPoints );
     1390        painter->restore();
     1391    }
     1392}
     1393
     1394/*!
     1395  \brief Draw the symbol into a rectangle
     1396
     1397  The symbol is painted centered and scaled into the target rectangle.
     1398  It is always painted uncached and the pin point is ignored.
     1399
     1400  This method is primarily intended for drawing a symbol to
     1401  the legend.
     1402
     1403  \param painter Painter
     1404  \param rect Target rectangle for the symbol
     1405*/
     1406void QwtSymbol::drawSymbol( QPainter *painter, const QRectF &rect ) const
     1407{
     1408    if ( d_data->style == QwtSymbol::NoSymbol )
     1409        return;
     1410
     1411    if ( d_data->style == QwtSymbol::Graphic )
     1412    {
     1413        d_data->graphic.graphic.render(
     1414            painter, rect, Qt::KeepAspectRatio );
     1415    }
     1416    else if ( d_data->style == QwtSymbol::Path )
     1417    {
     1418        if ( d_data->path.graphic.isNull() )
     1419        {
     1420            d_data->path.graphic = qwtPathGraphic(
     1421                d_data->path.path, d_data->pen, d_data->brush );
     1422        }
     1423
     1424        d_data->path.graphic.render(
     1425            painter, rect, Qt::KeepAspectRatio );
     1426        return;
     1427    }
     1428    else if ( d_data->style == QwtSymbol::SvgDocument )
     1429    {
     1430#ifndef QWT_NO_SVG
     1431        if ( d_data->svg.renderer )
     1432        {
     1433            QRectF scaledRect;
     1434
     1435            QSizeF sz = d_data->svg.renderer->viewBoxF().size();
     1436            if ( !sz.isEmpty() )
     1437            {
     1438                sz.scale( rect.size(), Qt::KeepAspectRatio );
     1439                scaledRect.setSize( sz );
     1440                scaledRect.moveCenter( rect.center() );
     1441            }
     1442            else
     1443            {
     1444                scaledRect = rect;
     1445            }
     1446
     1447            d_data->svg.renderer->render(
     1448                painter, scaledRect );
     1449        }
     1450#endif
     1451    }
     1452    else
     1453    {
     1454        const QRect br = boundingRect();
     1455
     1456        // scale the symbol size to fit into rect.
     1457
     1458        const double ratio = qMin( rect.width() / br.width(),
     1459            rect.height() / br.height() );
     1460
     1461        painter->save();
     1462
     1463        painter->translate( rect.center() );
     1464        painter->scale( ratio, ratio );
     1465
     1466        const bool isPinPointEnabled = d_data->isPinPointEnabled;
     1467        d_data->isPinPointEnabled = false;
     1468
     1469        const QPointF pos;
     1470        renderSymbols( painter, &pos, 1 );
     1471   
     1472        d_data->isPinPointEnabled = isPinPointEnabled;
     1473
     1474        painter->restore();
     1475    }
     1476}
     1477
     1478/*!
     1479  Render the symbol to series of points
     1480
     1481  \param painter Qt painter
     1482  \param points Positions of the symbols
     1483  \param numPoints Number of points
     1484 */
     1485void QwtSymbol::renderSymbols( QPainter *painter,
     1486    const QPointF *points, int numPoints ) const
     1487{
    8561488    switch ( d_data->style )
    8571489    {
     
    9341566            break;
    9351567        }
     1568        case QwtSymbol::Path:
     1569        {
     1570            if ( d_data->path.graphic.isNull() )
     1571            {
     1572                d_data->path.graphic = qwtPathGraphic( d_data->path.path,
     1573                    d_data->pen, d_data->brush );
     1574            }
     1575
     1576            qwtDrawGraphicSymbols( painter, points, numPoints,
     1577                d_data->path.graphic, *this );
     1578            break;
     1579        }
     1580        case QwtSymbol::Pixmap:
     1581        {
     1582            qwtDrawPixmapSymbols( painter, points, numPoints, *this );
     1583            break;
     1584        }
     1585        case QwtSymbol::Graphic:
     1586        {
     1587            qwtDrawGraphicSymbols( painter, points, numPoints,
     1588                d_data->graphic.graphic, *this );
     1589            break;
     1590        }
     1591        case QwtSymbol::SvgDocument:
     1592        {
     1593#ifndef QWT_NO_SVG
     1594            qwtDrawSvgSymbols( painter, points, numPoints,
     1595                d_data->svg.renderer, *this );
     1596#endif
     1597            break;
     1598        }
    9361599        default:;
    9371600    }
    938     painter->restore();
    939 }
    940 
    941 //!  \return Size of the bounding rectangle of a symbol
    942 QSize QwtSymbol::boundingSize() const
    943 {
    944     QSize size;
     1601}
     1602
     1603/*!
     1604  Calculate the bounding rectangle for a symbol
     1605  at position (0,0).
     1606
     1607  \return Bounding rectangle
     1608 */
     1609QRect QwtSymbol::boundingRect() const
     1610{
     1611    QRectF rect;
     1612
     1613    bool pinPointTranslation = false;
    9451614
    9461615    switch ( d_data->style )
     
    9541623                pw = qMax( d_data->pen.widthF(), qreal( 1.0 ) );
    9551624
    956             size = d_data->size + QSize( pw, pw );
     1625            rect.setSize( d_data->size + QSizeF( pw, pw ) );
     1626            rect.moveCenter( QPointF( 0.0, 0.0 ) );
    9571627
    9581628            break;
     
    9721642                pw = qMax( d_data->pen.widthF(), qreal( 1.0 ) );
    9731643
    974             size = d_data->size + QSize( 2 * pw, 2 * pw );
    975             break;
    976         }
     1644            rect.setSize( d_data->size + QSizeF( 2 * pw, 2 * pw ) );
     1645            rect.moveCenter( QPointF( 0.0, 0.0 ) );
     1646            break;
     1647        }
     1648        case QwtSymbol::Path:
     1649        {
     1650            if ( d_data->path.graphic.isNull() )
     1651            {
     1652                d_data->path.graphic = qwtPathGraphic(
     1653                    d_data->path.path, d_data->pen, d_data->brush );
     1654            }
     1655
     1656            rect = qwtScaledBoundingRect(
     1657                d_data->path.graphic, d_data->size );
     1658            pinPointTranslation = true;
     1659
     1660            break;
     1661        }
     1662        case QwtSymbol::Pixmap:
     1663        {
     1664            if ( d_data->size.isEmpty() )
     1665                rect.setSize( d_data->pixmap.pixmap.size() );
     1666            else
     1667                rect.setSize( d_data->size );
     1668           
     1669            pinPointTranslation = true;
     1670
     1671            break;
     1672        }
     1673        case QwtSymbol::Graphic:
     1674        {
     1675            rect = qwtScaledBoundingRect(
     1676                d_data->graphic.graphic, d_data->size );
     1677            pinPointTranslation = true;
     1678
     1679            break;
     1680        }
     1681#ifndef QWT_NO_SVG
     1682        case QwtSymbol::SvgDocument:
     1683        {
     1684            if ( d_data->svg.renderer )
     1685                rect = d_data->svg.renderer->viewBoxF();
     1686
     1687            if ( d_data->size.isValid() && !rect.isEmpty() )
     1688            {
     1689                QSizeF sz = rect.size();
     1690
     1691                const double sx = d_data->size.width() / sz.width();
     1692                const double sy = d_data->size.height() / sz.height();
     1693
     1694                QTransform transform;
     1695                transform.scale( sx, sy );
     1696
     1697                rect = transform.mapRect( rect );
     1698            }
     1699            pinPointTranslation = true;
     1700            break;
     1701        }
     1702#endif
    9771703        default:
    9781704        {
    979             size = d_data->size;
    980         }
    981     }
    982 
    983     return size + QSize( 1, 1 ); // for antialiasing
     1705            rect.setSize( d_data->size );
     1706            rect.moveCenter( QPointF( 0.0, 0.0 ) );
     1707        }
     1708    }
     1709
     1710    if ( pinPointTranslation )
     1711    {
     1712        QPointF pinPoint( 0.0, 0.0 );
     1713        if ( d_data->isPinPointEnabled )
     1714            pinPoint = rect.center() - d_data->pinPoint;
     1715
     1716        rect.moveCenter( pinPoint );
     1717    }
     1718
     1719    QRect r;
     1720    r.setLeft( qFloor( rect.left() ) );
     1721    r.setTop( qFloor( rect.top() ) );
     1722    r.setRight( qCeil( rect.right() ) );
     1723    r.setBottom( qCeil( rect.bottom() ) );
     1724
     1725    if ( d_data->style != QwtSymbol::Pixmap )
     1726        r.adjust( -1, -1, 1, 1 ); // for antialiasing
     1727
     1728    return r;
     1729}
     1730
     1731/*!
     1732  Invalidate the cached symbol pixmap
     1733
     1734  The symbol invalidates its cache, whenever an attribute is changed
     1735  that has an effect ob how to display a symbol. In case of derived
     1736  classes with individual styles ( >= QwtSymbol::UserStyle ) it
     1737  might be necessary to call invalidateCache() for attributes
     1738  that are relevant for this style.
     1739
     1740  \sa CachePolicy, setCachePolicy(), drawSymbols()
     1741 */
     1742void QwtSymbol::invalidateCache()
     1743{
     1744    if ( !d_data->cache.pixmap.isNull() )
     1745        d_data->cache.pixmap = QPixmap();
    9841746}
    9851747
     
    9921754void QwtSymbol::setStyle( QwtSymbol::Style style )
    9931755{
    994     d_data->style = style;
     1756    if ( d_data->style != style )
     1757    {
     1758        d_data->style = style;
     1759        invalidateCache();
     1760    }
    9951761}
    9961762
Note: See TracChangeset for help on using the changeset viewer.