Skip to content
qwt_painter.cpp 34.6 KiB
Newer Older
pixhawk's avatar
pixhawk committed
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

Bryant's avatar
Bryant committed
#include "qwt_painter.h"
#include "qwt_math.h"
#include "qwt_clipper.h"
#include "qwt_color_map.h"
#include "qwt_scale_map.h"
pixhawk's avatar
pixhawk committed
#include <qwindowdefs.h>
#include <qwidget.h>
Bryant's avatar
Bryant committed
#include <qframe.h>
pixhawk's avatar
pixhawk committed
#include <qrect.h>
#include <qpainter.h>
#include <qpalette.h>
#include <qpaintdevice.h>
#include <qpixmap.h>
#include <qstyle.h>
#include <qtextdocument.h>
#include <qabstracttextdocumentlayout.h>
#include <qstyleoption.h>
#include <qpaintengine.h>
Bryant's avatar
Bryant committed
#include <qapplication.h>
#include <qdesktopwidget.h>
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
#if QT_VERSION >= 0x050000
#include <qwindow.h>
#endif
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
#if QT_VERSION < 0x050000 
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
#ifdef Q_WS_X11
#include <qx11info_x11.h>
pixhawk's avatar
pixhawk committed
#endif

#endif

Bryant's avatar
Bryant committed
bool QwtPainter::d_polylineSplitting = true;
bool QwtPainter::d_roundingAlignment = true;
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
static inline bool qwtIsClippingNeeded( 
    const QPainter *painter, QRectF &clipRect )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    bool doClipping = false;
    const QPaintEngine *pe = painter->paintEngine();
    if ( pe && pe->type() == QPaintEngine::SVG )
    {
        // The SVG paint engine ignores any clipping,
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
        if ( painter->hasClipping() )
        {
            doClipping = true;
            clipRect = painter->clipRegion().boundingRect();
        }
    }
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    return doClipping;
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
template <class T>
static inline void qwtDrawPolyline( QPainter *painter,
    const T *points, int pointCount, bool polylineSplitting )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    bool doSplit = false;
    if ( polylineSplitting )
    {
        const QPaintEngine *pe = painter->paintEngine();
        if ( pe && pe->type() == QPaintEngine::Raster )
        {
            /*
                The raster paint engine seems to use some algo with O(n*n).
                ( Qt 4.3 is better than Qt 4.2, but remains unacceptable)
                To work around this problem, we have to split the polygon into
                smaller pieces.
             */
            doSplit = true;
        }
    }
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    if ( doSplit )
    {
        const int splitSize = 20;
        for ( int i = 0; i < pointCount; i += splitSize )
        {
            const int n = qMin( splitSize + 1, pointCount - i );
            painter->drawPolyline( points + i, n );
        }
pixhawk's avatar
pixhawk committed
    }
Bryant's avatar
Bryant committed
    else
        painter->drawPolyline( points, pointCount );
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
static inline void qwtUnscaleFont( QPainter *painter )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( painter->font().pixelSize() >= 0 )
        return;
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    static QSize screenResolution;
    if ( !screenResolution.isValid() )
    {
        QDesktopWidget *desktop = QApplication::desktop();
        if ( desktop )
        {
            screenResolution.setWidth( desktop->logicalDpiX() );
            screenResolution.setHeight( desktop->logicalDpiY() );
        }
    }
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    const QPaintDevice *pd = painter->device();
    if ( pd->logicalDpiX() != screenResolution.width() ||
        pd->logicalDpiY() != screenResolution.height() )
    {
        QFont pixelFont( painter->font(), QApplication::desktop() );
        pixelFont.setPixelSize( QFontInfo( pixelFont ).pixelSize() );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
        painter->setFont( pixelFont );
    }
pixhawk's avatar
pixhawk committed
}

/*!
Bryant's avatar
Bryant committed
  Check is the application is running with the X11 graphics system
  that has some special capabilities that can be used for incremental
  painting to a widget.
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
  \return True, when the graphics system is X11
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
bool QwtPainter::isX11GraphicsSystem()
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    static int onX11 = -1;
    if ( onX11 < 0 )
    {
        QPixmap pm( 1, 1 );
        QPainter painter( &pm );

        onX11 = ( painter.paintEngine()->type() == QPaintEngine::X11 ) ? 1 : 0;
    }

    return onX11 == 1;
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
  Check if the painter is using a paint engine, that aligns
  coordinates to integers. Today these are all paint engines
  beside QPaintEngine::Pdf and QPaintEngine::SVG.

  If we have an integer based paint engine it is also
  checked if the painter has a transformation matrix,
  that rotates or scales.

  \param  painter Painter
  \return true, when the painter is aligning

  \sa setRoundingAlignment()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
bool QwtPainter::isAligning( QPainter *painter )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( painter && painter->isActive() )
    {
        switch ( painter->paintEngine()->type() )
        {
            case QPaintEngine::Pdf:
            case QPaintEngine::SVG:
                return false;

            default:;
        }

        const QTransform tr = painter->transform();
        if ( tr.isRotating() || tr.isScaling() )
        {
            // we might have to check translations too
            return false;
        }
    }

    return true;
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
  Enable whether coordinates should be rounded, before they are painted
  to a paint engine that floors to integer values. For other paint engines
  this ( PDF, SVG ), this flag has no effect.
  QwtPainter stores this flag only, the rounding itself is done in 
  the painting code ( f.e the plot items ).

  The default setting is true. 

  \sa roundingAlignment(), isAligning()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtPainter::setRoundingAlignment( bool enable )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    d_roundingAlignment = enable;
pixhawk's avatar
pixhawk committed
}

/*!
Loading
Loading full blame...