Make sure rasterColourOp is always initialized, even if none of the switch cases matches, to avoid warnings about possibly uninitialized variable. See https://github.com/wxWidgets/wxWidgets/pull/1048
824 lines
23 KiB
C++
824 lines
23 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/qt/dc.cpp
|
|
// Author: Peter Most, Javier Torres, Mariano Reingart
|
|
// Copyright: (c) 2009 wxWidgets dev team
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#include <QtGui/QBitmap>
|
|
#include <QtGui/QPen>
|
|
#include <QtGui/QPainter>
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/icon.h"
|
|
#include "wx/log.h"
|
|
#endif // WX_PRECOMP
|
|
|
|
#include "wx/dc.h"
|
|
#include "wx/qt/dc.h"
|
|
#include "wx/qt/private/converter.h"
|
|
#include "wx/qt/private/utils.h"
|
|
|
|
#include <QtGui/QScreen>
|
|
#include <QtWidgets/QApplication>
|
|
|
|
static void SetPenColour( QPainter *qtPainter, QColor col )
|
|
{
|
|
QPen p = qtPainter->pen();
|
|
p.setColor( col );
|
|
qtPainter->setPen( p );
|
|
}
|
|
|
|
static void SetBrushColour( QPainter *qtPainter, QColor col )
|
|
{
|
|
QBrush b = qtPainter->brush();
|
|
b.setColor( col );
|
|
qtPainter->setBrush( b );
|
|
}
|
|
|
|
wxQtDCImpl::wxQtDCImpl( wxDC *owner )
|
|
: wxDCImpl( owner )
|
|
{
|
|
m_clippingRegion = new wxRegion;
|
|
m_qtImage = NULL;
|
|
m_rasterColourOp = wxQtNONE;
|
|
m_qtPenColor = new QColor;
|
|
m_qtBrushColor = new QColor;
|
|
m_ok = true;
|
|
}
|
|
|
|
wxQtDCImpl::~wxQtDCImpl()
|
|
{
|
|
if ( m_qtPainter )
|
|
{
|
|
if( m_qtPainter->isActive() )
|
|
{
|
|
m_qtPainter->end();
|
|
}
|
|
delete m_qtPainter;
|
|
}
|
|
|
|
delete m_clippingRegion;
|
|
delete m_qtPenColor;
|
|
delete m_qtBrushColor;
|
|
}
|
|
|
|
void wxQtDCImpl::QtPreparePainter( )
|
|
{
|
|
//Do here all QPainter initialization (called after each begin())
|
|
if ( m_qtPainter == NULL )
|
|
{
|
|
wxLogDebug(wxT("wxQtDCImpl::QtPreparePainter is NULL!!!"));
|
|
}
|
|
else if ( m_qtPainter->isActive() )
|
|
{
|
|
m_qtPainter->setPen( wxPen().GetHandle() );
|
|
m_qtPainter->setBrush( wxBrush().GetHandle() );
|
|
m_qtPainter->setFont( wxFont().GetHandle() );
|
|
|
|
if (m_clipping)
|
|
{
|
|
wxRegionIterator ri(*m_clippingRegion);
|
|
bool append = false;
|
|
while (ri.HaveRects())
|
|
{
|
|
wxRect r = ri.GetRect();
|
|
m_qtPainter->setClipRect( r.x, r.y, r.width, r.height,
|
|
append ? Qt::IntersectClip : Qt::ReplaceClip );
|
|
append = true;
|
|
ri++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// wxLogDebug(wxT("wxQtDCImpl::QtPreparePainter not active!"));
|
|
}
|
|
}
|
|
|
|
bool wxQtDCImpl::CanDrawBitmap() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool wxQtDCImpl::CanGetTextExtent() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void wxQtDCImpl::DoGetSize(int *width, int *height) const
|
|
{
|
|
if (width) *width = m_qtPainter->device()->width();
|
|
if (height) *height = m_qtPainter->device()->height();
|
|
}
|
|
|
|
void wxQtDCImpl::DoGetSizeMM(int* width, int* height) const
|
|
{
|
|
if (width) *width = m_qtPainter->device()->widthMM();
|
|
if (height) *height = m_qtPainter->device()->heightMM();
|
|
}
|
|
|
|
int wxQtDCImpl::GetDepth() const
|
|
{
|
|
return m_qtPainter->device()->depth();
|
|
}
|
|
|
|
wxSize wxQtDCImpl::GetPPI() const
|
|
{
|
|
QScreen *srn = QApplication::screens().at(0);
|
|
if (!srn)
|
|
return wxSize(m_qtPainter->device()->logicalDpiX(), m_qtPainter->device()->logicalDpiY());
|
|
qreal dotsPerInch = srn->logicalDotsPerInch();
|
|
return wxSize(round(dotsPerInch), round(dotsPerInch));
|
|
}
|
|
|
|
void wxQtDCImpl::SetFont(const wxFont& font)
|
|
{
|
|
m_font = font;
|
|
|
|
if (m_qtPainter->isActive())
|
|
m_qtPainter->setFont(font.GetHandle());
|
|
}
|
|
|
|
void wxQtDCImpl::SetPen(const wxPen& pen)
|
|
{
|
|
m_pen = pen;
|
|
|
|
m_qtPainter->setPen(pen.GetHandle());
|
|
|
|
ApplyRasterColourOp();
|
|
}
|
|
|
|
void wxQtDCImpl::SetBrush(const wxBrush& brush)
|
|
{
|
|
m_brush = brush;
|
|
|
|
if (brush.GetStyle() == wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE)
|
|
{
|
|
// Use a monochrome mask: use foreground color for the mask
|
|
QBrush b(brush.GetHandle());
|
|
b.setColor(m_textForegroundColour.GetQColor());
|
|
b.setTexture(b.texture().mask());
|
|
m_qtPainter->setBrush(b);
|
|
}
|
|
else if (brush.GetStyle() == wxBRUSHSTYLE_STIPPLE)
|
|
{
|
|
//Don't use the mask
|
|
QBrush b(brush.GetHandle());
|
|
|
|
QPixmap p = b.texture();
|
|
p.setMask(QBitmap());
|
|
b.setTexture(p);
|
|
|
|
m_qtPainter->setBrush(b);
|
|
}
|
|
else
|
|
{
|
|
m_qtPainter->setBrush(brush.GetHandle());
|
|
}
|
|
|
|
ApplyRasterColourOp();
|
|
}
|
|
|
|
void wxQtDCImpl::SetBackground(const wxBrush& brush)
|
|
{
|
|
m_backgroundBrush = brush;
|
|
|
|
if (m_qtPainter->isActive())
|
|
m_qtPainter->setBackground(brush.GetHandle());
|
|
}
|
|
|
|
void wxQtDCImpl::SetBackgroundMode(int mode)
|
|
{
|
|
/* Do not change QPainter, as wx uses this background mode
|
|
* only for drawing text, where Qt uses it for everything.
|
|
* Always let QPainter mode to transparent, and change it
|
|
* when needed */
|
|
m_backgroundMode = mode;
|
|
}
|
|
|
|
#include <QtGui/QPen>
|
|
#include <QtGui/QPainter>
|
|
#include <QtGui/QScreen>
|
|
#include <QtWidgets/QApplication>
|
|
|
|
#if wxUSE_PALETTE
|
|
void wxQtDCImpl::SetPalette(const wxPalette& WXUNUSED(palette))
|
|
{
|
|
wxMISSING_IMPLEMENTATION(__FUNCTION__);
|
|
}
|
|
#endif // wxUSE_PALETTE
|
|
|
|
void wxQtDCImpl::SetLogicalFunction(wxRasterOperationMode function)
|
|
{
|
|
m_logicalFunction = function;
|
|
|
|
wxQtRasterColourOp rasterColourOp = wxQtNONE;
|
|
switch ( function )
|
|
{
|
|
case wxCLEAR: // 0
|
|
m_qtPainter->setCompositionMode( QPainter::CompositionMode_SourceOver );
|
|
rasterColourOp = wxQtBLACK;
|
|
break;
|
|
case wxXOR: // src XOR dst
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_SourceXorDestination );
|
|
break;
|
|
case wxINVERT: // NOT dst => dst XOR WHITE
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_SourceXorDestination );
|
|
rasterColourOp = wxQtWHITE;
|
|
break;
|
|
case wxOR_REVERSE: // src OR (NOT dst) => (NOT (NOT src)) OR (NOT dst)
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_NotSourceOrNotDestination );
|
|
rasterColourOp = wxQtINVERT;
|
|
break;
|
|
case wxAND_REVERSE: // src AND (NOT dst)
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_SourceAndNotDestination );
|
|
break;
|
|
case wxCOPY: // src
|
|
m_qtPainter->setCompositionMode( QPainter::CompositionMode_SourceOver );
|
|
break;
|
|
case wxAND: // src AND dst
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_SourceAndDestination );
|
|
break;
|
|
case wxAND_INVERT: // (NOT src) AND dst
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_NotSourceAndDestination );
|
|
break;
|
|
case wxNO_OP: // dst
|
|
m_qtPainter->setCompositionMode( QPainter::CompositionMode_DestinationOver );
|
|
break;
|
|
case wxNOR: // (NOT src) AND (NOT dst)
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_NotSourceAndNotDestination );
|
|
break;
|
|
case wxEQUIV: // (NOT src) XOR dst
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_NotSourceXorDestination );
|
|
break;
|
|
case wxSRC_INVERT: // (NOT src)
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_NotSource );
|
|
break;
|
|
case wxOR_INVERT: // (NOT src) OR dst
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_SourceOrDestination );
|
|
rasterColourOp = wxQtINVERT;
|
|
break;
|
|
case wxNAND: // (NOT src) OR (NOT dst)
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_NotSourceOrNotDestination );
|
|
break;
|
|
case wxOR: // src OR dst
|
|
m_qtPainter->setCompositionMode( QPainter::RasterOp_SourceOrDestination );
|
|
break;
|
|
case wxSET: // 1
|
|
m_qtPainter->setCompositionMode( QPainter::CompositionMode_SourceOver );
|
|
rasterColourOp = wxQtWHITE;
|
|
break;
|
|
}
|
|
|
|
if ( rasterColourOp != m_rasterColourOp )
|
|
{
|
|
// Source colour mode changed
|
|
m_rasterColourOp = rasterColourOp;
|
|
|
|
// Restore original colours and apply new mode
|
|
SetPenColour( m_qtPainter, *m_qtPenColor );
|
|
SetBrushColour( m_qtPainter, *m_qtPenColor );
|
|
|
|
ApplyRasterColourOp();
|
|
}
|
|
}
|
|
|
|
void wxQtDCImpl::ApplyRasterColourOp()
|
|
{
|
|
// Save colours
|
|
*m_qtPenColor = m_qtPainter->pen().color();
|
|
*m_qtBrushColor = m_qtPainter->brush().color();
|
|
|
|
// Apply op
|
|
switch ( m_rasterColourOp )
|
|
{
|
|
case wxQtWHITE:
|
|
SetPenColour( m_qtPainter, QColor( Qt::white ) );
|
|
SetBrushColour( m_qtPainter, QColor( Qt::white ) );
|
|
break;
|
|
case wxQtBLACK:
|
|
SetPenColour( m_qtPainter, QColor( Qt::black ) );
|
|
SetBrushColour( m_qtPainter, QColor( Qt::black ) );
|
|
break;
|
|
case wxQtINVERT:
|
|
SetPenColour( m_qtPainter, QColor( ~m_qtPenColor->rgb() ) );
|
|
SetBrushColour( m_qtPainter, QColor( ~m_qtBrushColor->rgb() ) );
|
|
break;
|
|
case wxQtNONE:
|
|
// No op
|
|
break;
|
|
}
|
|
}
|
|
|
|
wxCoord wxQtDCImpl::GetCharHeight() const
|
|
{
|
|
QFontMetrics metrics(m_qtPainter->font());
|
|
return wxCoord( metrics.height() );
|
|
}
|
|
|
|
wxCoord wxQtDCImpl::GetCharWidth() const
|
|
{
|
|
//FIXME: Returning max width, instead of average
|
|
QFontMetrics metrics(m_qtPainter->font());
|
|
return wxCoord( metrics.maxWidth() );
|
|
}
|
|
|
|
void wxQtDCImpl::DoGetTextExtent(const wxString& string,
|
|
wxCoord *x, wxCoord *y,
|
|
wxCoord *descent,
|
|
wxCoord *externalLeading,
|
|
const wxFont *theFont ) const
|
|
{
|
|
QFont f;
|
|
if (theFont != NULL)
|
|
f = theFont->GetHandle();
|
|
else
|
|
f = m_font.GetHandle();
|
|
|
|
QFontMetrics metrics(f);
|
|
if (x != NULL || y != NULL)
|
|
{
|
|
// note that boundingRect doesn't return "advance width" for spaces
|
|
if (x != NULL)
|
|
*x = metrics.width( wxQtConvertString(string) );
|
|
if (y != NULL)
|
|
*y = metrics.height();
|
|
}
|
|
|
|
if (descent != NULL)
|
|
*descent = metrics.descent();
|
|
|
|
if (externalLeading != NULL)
|
|
*externalLeading = metrics.leading();
|
|
}
|
|
|
|
void wxQtDCImpl::Clear()
|
|
{
|
|
int width, height;
|
|
DoGetSize(&width, &height);
|
|
|
|
m_qtPainter->eraseRect(QRect(0, 0, width, height));
|
|
}
|
|
|
|
void wxQtDCImpl::DoSetClippingRegion(wxCoord x, wxCoord y,
|
|
wxCoord width, wxCoord height)
|
|
{
|
|
// Special case: Empty region -> DestroyClippingRegion()
|
|
if ( width == 0 && height == 0 )
|
|
{
|
|
DestroyClippingRegion();
|
|
}
|
|
else
|
|
{
|
|
if (m_qtPainter->isActive())
|
|
{
|
|
// Set QPainter clipping (intersection if not the first one)
|
|
m_qtPainter->setClipRect( x, y, width, height,
|
|
m_clipping ? Qt::IntersectClip : Qt::ReplaceClip );
|
|
}
|
|
|
|
// Set internal state for getters
|
|
/* Note: Qt states that QPainter::clipRegion() may be slow, so we
|
|
* keep the region manually, which should be faster */
|
|
if ( m_clipping )
|
|
m_clippingRegion->Union( wxRect( x, y, width, height ) );
|
|
else
|
|
m_clippingRegion->Intersect( wxRect( x, y, width, height ) );
|
|
|
|
wxRect clipRect = m_clippingRegion->GetBox();
|
|
|
|
m_clipX1 = clipRect.GetLeft();
|
|
m_clipX2 = clipRect.GetRight();
|
|
m_clipY1 = clipRect.GetTop();
|
|
m_clipY2 = clipRect.GetBottom();
|
|
m_clipping = true;
|
|
}
|
|
}
|
|
|
|
void wxQtDCImpl::DoSetDeviceClippingRegion(const wxRegion& region)
|
|
{
|
|
if ( region.IsEmpty() )
|
|
{
|
|
DestroyClippingRegion();
|
|
}
|
|
else
|
|
{
|
|
QRegion qregion = region.GetHandle();
|
|
// Save current origin / scale (logical coordinates)
|
|
QTransform qtrans = m_qtPainter->worldTransform();
|
|
// Reset transofrmation to match device coordinates
|
|
m_qtPainter->setWorldTransform( QTransform() );
|
|
// Set QPainter clipping (intersection if not the first one)
|
|
m_qtPainter->setClipRegion( qregion,
|
|
m_clipping ? Qt::IntersectClip : Qt::ReplaceClip );
|
|
|
|
// Restore the transformation (translation / scale):
|
|
m_qtPainter->setWorldTransform( qtrans );
|
|
|
|
// Set internal state for getters
|
|
/* Note: Qt states that QPainter::clipRegion() may be slow, so we
|
|
* keep the region manually, which should be faster */
|
|
if ( m_clipping )
|
|
m_clippingRegion->Union( region );
|
|
else
|
|
m_clippingRegion->Intersect( region );
|
|
|
|
wxRect clipRect = m_clippingRegion->GetBox();
|
|
|
|
m_clipX1 = clipRect.GetLeft();
|
|
m_clipX2 = clipRect.GetRight();
|
|
m_clipY1 = clipRect.GetTop();
|
|
m_clipY2 = clipRect.GetBottom();
|
|
m_clipping = true;
|
|
}
|
|
}
|
|
|
|
void wxQtDCImpl::DestroyClippingRegion()
|
|
{
|
|
wxDCImpl::DestroyClippingRegion();
|
|
m_clippingRegion->Clear();
|
|
|
|
if (m_qtPainter->isActive())
|
|
m_qtPainter->setClipping( false );
|
|
}
|
|
|
|
bool wxQtDCImpl::DoFloodFill(wxCoord x, wxCoord y, const wxColour& col,
|
|
wxFloodFillStyle style )
|
|
{
|
|
#if wxUSE_IMAGE
|
|
extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
|
|
const wxColour & col, wxFloodFillStyle style);
|
|
|
|
return wxDoFloodFill( GetOwner(), x, y, col, style);
|
|
#else
|
|
wxUnusedVar(x);
|
|
wxUnusedVar(y);
|
|
wxUnusedVar(col);
|
|
wxUnusedVar(style);
|
|
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool wxQtDCImpl::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
|
|
{
|
|
wxCHECK_MSG( m_qtPainter->isActive(), false, "Invalid wxDC" );
|
|
|
|
if ( col )
|
|
{
|
|
wxCHECK_MSG( m_qtImage != NULL, false, "This DC doesn't support GetPixel()" );
|
|
|
|
QColor pixel = m_qtImage->pixel( x, y );
|
|
col->Set( pixel.red(), pixel.green(), pixel.blue(), pixel.alpha() );
|
|
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawPoint(wxCoord x, wxCoord y)
|
|
{
|
|
m_qtPainter->drawPoint(x, y);
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
|
|
{
|
|
m_qtPainter->drawLine(x1, y1, x2, y2);
|
|
}
|
|
|
|
|
|
void wxQtDCImpl::DoDrawArc(wxCoord x1, wxCoord y1,
|
|
wxCoord x2, wxCoord y2,
|
|
wxCoord xc, wxCoord yc)
|
|
{
|
|
// Calculate the rectangle that contains the circle
|
|
QLineF l1( xc, yc, x1, y1 );
|
|
QLineF l2( xc, yc, x2, y2 );
|
|
QPointF center( xc, yc );
|
|
|
|
qreal penWidth = m_qtPainter->pen().width();
|
|
qreal lenRadius = l1.length() - penWidth / 2;
|
|
QPointF centerToCorner( lenRadius, lenRadius );
|
|
|
|
QRect rectangle = QRectF( center - centerToCorner, center + centerToCorner ).toRect();
|
|
|
|
// Calculate the angles
|
|
int startAngle = (int)( l1.angle() * 16 );
|
|
int endAngle = (int)( l2.angle() * 16 );
|
|
int spanAngle = endAngle - startAngle;
|
|
if ( spanAngle < 0 )
|
|
{
|
|
spanAngle = -spanAngle;
|
|
}
|
|
|
|
if ( spanAngle == 0 )
|
|
m_qtPainter->drawEllipse( rectangle );
|
|
else
|
|
m_qtPainter->drawPie( rectangle, startAngle, spanAngle );
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawEllipticArc(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
|
|
double sa, double ea)
|
|
{
|
|
int penWidth = m_qtPainter->pen().width();
|
|
x += penWidth / 2;
|
|
y += penWidth / 2;
|
|
w -= penWidth;
|
|
h -= penWidth;
|
|
|
|
double spanAngle = sa - ea;
|
|
if (spanAngle < -180)
|
|
spanAngle += 360;
|
|
if (spanAngle > 180)
|
|
spanAngle -= 360;
|
|
|
|
if ( spanAngle == 0 )
|
|
m_qtPainter->drawEllipse( x, y, w, h );
|
|
else
|
|
m_qtPainter->drawPie( x, y, w, h, (int)( sa * 16 ), (int)( ( ea - sa ) * 16 ) );
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
|
|
{
|
|
int penWidth = m_qtPainter->pen().width();
|
|
x += penWidth / 2;
|
|
y += penWidth / 2;
|
|
width -= penWidth;
|
|
height -= penWidth;
|
|
|
|
m_qtPainter->drawRect( x, y, width, height );
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
|
|
wxCoord width, wxCoord height,
|
|
double radius)
|
|
{
|
|
int penWidth = m_qtPainter->pen().width();
|
|
x += penWidth / 2;
|
|
y += penWidth / 2;
|
|
width -= penWidth;
|
|
height -= penWidth;
|
|
|
|
m_qtPainter->drawRoundedRect( x, y, width, height, radius, radius );
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawEllipse(wxCoord x, wxCoord y,
|
|
wxCoord width, wxCoord height)
|
|
{
|
|
QBrush savedBrush;
|
|
int penWidth = m_qtPainter->pen().width();
|
|
x += penWidth / 2;
|
|
y += penWidth / 2;
|
|
width -= penWidth;
|
|
height -= penWidth;
|
|
|
|
if ( m_pen.IsNonTransparent() )
|
|
{
|
|
// Save pen/brush
|
|
savedBrush = m_qtPainter->brush();
|
|
// Fill with text background color ("no fill" like in wxGTK):
|
|
m_qtPainter->setBrush(QBrush(m_textBackgroundColour.GetQColor()));
|
|
}
|
|
|
|
// Draw
|
|
m_qtPainter->drawEllipse( x, y, width, height );
|
|
|
|
if ( m_pen.IsNonTransparent() )
|
|
{
|
|
//Restore saved settings
|
|
m_qtPainter->setBrush(savedBrush);
|
|
}
|
|
}
|
|
|
|
void wxQtDCImpl::DoCrossHair(wxCoord x, wxCoord y)
|
|
{
|
|
int w, h;
|
|
DoGetSize( &w, &h );
|
|
|
|
// Map width and height back (inverted transform)
|
|
QTransform inv = m_qtPainter->transform().inverted();
|
|
int left, top, right, bottom;
|
|
inv.map( w, h, &right, &bottom );
|
|
inv.map( 0, 0, &left, &top );
|
|
|
|
m_qtPainter->drawLine( left, y, right, y );
|
|
m_qtPainter->drawLine( x, top, x, bottom );
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawIcon(const wxIcon& icon, wxCoord x, wxCoord y)
|
|
{
|
|
DoDrawBitmap( icon, x, y, true );
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y,
|
|
bool useMask )
|
|
{
|
|
QPixmap pix = *bmp.GetHandle();
|
|
if (pix.depth() == 1) {
|
|
//Monochrome bitmap, draw using text fore/background
|
|
|
|
//Save pen/brush
|
|
QBrush savedBrush = m_qtPainter->background();
|
|
QPen savedPen = m_qtPainter->pen();
|
|
|
|
//Use text colors
|
|
m_qtPainter->setBackground(QBrush(m_textBackgroundColour.GetQColor()));
|
|
m_qtPainter->setPen(QPen(m_textForegroundColour.GetQColor()));
|
|
|
|
//Draw
|
|
m_qtPainter->drawPixmap(x, y, pix);
|
|
|
|
//Restore saved settings
|
|
m_qtPainter->setBackground(savedBrush);
|
|
m_qtPainter->setPen(savedPen);
|
|
}
|
|
else
|
|
{
|
|
if ( useMask && bmp.GetMask() && bmp.GetMask()->GetHandle() )
|
|
pix.setMask(*bmp.GetMask()->GetHandle());
|
|
m_qtPainter->drawPixmap(x, y, pix);
|
|
}
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawText(const wxString& text, wxCoord x, wxCoord y)
|
|
{
|
|
QPen savedPen = m_qtPainter->pen();
|
|
m_qtPainter->setPen(QPen(m_textForegroundColour.GetQColor()));
|
|
|
|
// Disable logical function
|
|
QPainter::CompositionMode savedOp = m_qtPainter->compositionMode();
|
|
m_qtPainter->setCompositionMode( QPainter::CompositionMode_SourceOver );
|
|
|
|
if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
|
|
{
|
|
m_qtPainter->setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
//Save pen/brush
|
|
QBrush savedBrush = m_qtPainter->background();
|
|
|
|
//Use text colors
|
|
m_qtPainter->setBackground(QBrush(m_textBackgroundColour.GetQColor()));
|
|
|
|
//Draw
|
|
m_qtPainter->drawText(x, y, 1, 1, Qt::TextDontClip, wxQtConvertString(text));
|
|
|
|
//Restore saved settings
|
|
m_qtPainter->setBackground(savedBrush);
|
|
|
|
|
|
m_qtPainter->setBackgroundMode(Qt::TransparentMode);
|
|
}
|
|
else
|
|
m_qtPainter->drawText(x, y, 1, 1, Qt::TextDontClip, wxQtConvertString(text));
|
|
|
|
m_qtPainter->setPen(savedPen);
|
|
m_qtPainter->setCompositionMode( savedOp );
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawRotatedText(const wxString& text,
|
|
wxCoord x, wxCoord y, double angle)
|
|
{
|
|
if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
|
|
m_qtPainter->setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
//Move and rotate (reverse angle direction in Qt and wx)
|
|
m_qtPainter->translate(x, y);
|
|
m_qtPainter->rotate(-angle);
|
|
|
|
QPen savedPen = m_qtPainter->pen();
|
|
m_qtPainter->setPen(QPen(m_textForegroundColour.GetQColor()));
|
|
|
|
// Disable logical function
|
|
QPainter::CompositionMode savedOp = m_qtPainter->compositionMode();
|
|
m_qtPainter->setCompositionMode( QPainter::CompositionMode_SourceOver );
|
|
|
|
if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
|
|
{
|
|
m_qtPainter->setBackgroundMode(Qt::OpaqueMode);
|
|
|
|
//Save pen/brush
|
|
QBrush savedBrush = m_qtPainter->background();
|
|
|
|
//Use text colors
|
|
m_qtPainter->setBackground(QBrush(m_textBackgroundColour.GetQColor()));
|
|
|
|
//Draw
|
|
m_qtPainter->drawText(x, y, 1, 1, Qt::TextDontClip, wxQtConvertString(text));
|
|
|
|
//Restore saved settings
|
|
m_qtPainter->setBackground(savedBrush);
|
|
|
|
m_qtPainter->setBackgroundMode(Qt::TransparentMode);
|
|
}
|
|
else
|
|
m_qtPainter->drawText(x, y, 1, 1, Qt::TextDontClip, wxQtConvertString(text));
|
|
|
|
//Reset to default
|
|
ComputeScaleAndOrigin();
|
|
m_qtPainter->setPen(savedPen);
|
|
m_qtPainter->setCompositionMode( savedOp );
|
|
}
|
|
|
|
bool wxQtDCImpl::DoBlit(wxCoord xdest, wxCoord ydest,
|
|
wxCoord width, wxCoord height,
|
|
wxDC *source,
|
|
wxCoord xsrc, wxCoord ysrc,
|
|
wxRasterOperationMode rop,
|
|
bool useMask,
|
|
wxCoord WXUNUSED(xsrcMask),
|
|
wxCoord WXUNUSED(ysrcMask) )
|
|
{
|
|
wxQtDCImpl *implSource = (wxQtDCImpl*)source->GetImpl();
|
|
|
|
QImage *qtSource = implSource->GetQImage();
|
|
|
|
// Not a CHECK on purpose
|
|
if ( !qtSource )
|
|
return false;
|
|
|
|
QImage qtSourceConverted = *qtSource;
|
|
if ( !useMask )
|
|
qtSourceConverted = qtSourceConverted.convertToFormat( QImage::Format_RGB32 );
|
|
|
|
// Change logical function
|
|
wxRasterOperationMode savedMode = GetLogicalFunction();
|
|
SetLogicalFunction( rop );
|
|
|
|
m_qtPainter->drawImage( QRect( xdest, ydest, width, height ),
|
|
qtSourceConverted,
|
|
QRect( xsrc, ysrc, width, height ) );
|
|
|
|
SetLogicalFunction( savedMode );
|
|
|
|
return true;
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawLines(int n, const wxPoint points[],
|
|
wxCoord xoffset, wxCoord yoffset )
|
|
{
|
|
if (n > 0)
|
|
{
|
|
QPainterPath path(wxQtConvertPoint(points[0]));
|
|
for (int i = 1; i < n; i++)
|
|
{
|
|
path.lineTo(wxQtConvertPoint(points[i]));
|
|
}
|
|
|
|
m_qtPainter->translate(xoffset, yoffset);
|
|
|
|
QBrush savebrush = m_qtPainter->brush();
|
|
m_qtPainter->setBrush(Qt::NoBrush);
|
|
m_qtPainter->drawPath(path);
|
|
m_qtPainter->setBrush(savebrush);
|
|
|
|
// Reset transform
|
|
ComputeScaleAndOrigin();
|
|
}
|
|
}
|
|
|
|
void wxQtDCImpl::DoDrawPolygon(int n, const wxPoint points[],
|
|
wxCoord xoffset, wxCoord yoffset,
|
|
wxPolygonFillMode fillStyle )
|
|
{
|
|
QPolygon qtPoints;
|
|
for (int i = 0; i < n; i++) {
|
|
qtPoints << wxQtConvertPoint(points[i]);
|
|
}
|
|
|
|
Qt::FillRule fill = (fillStyle == wxWINDING_RULE) ? Qt::WindingFill : Qt::OddEvenFill;
|
|
|
|
m_qtPainter->translate(xoffset, yoffset);
|
|
m_qtPainter->drawPolygon(qtPoints, fill);
|
|
// Reset transform
|
|
ComputeScaleAndOrigin();
|
|
}
|
|
|
|
void wxQtDCImpl::ComputeScaleAndOrigin()
|
|
{
|
|
QTransform t;
|
|
|
|
// First apply device origin
|
|
t.translate( m_deviceOriginX + m_deviceLocalOriginX,
|
|
m_deviceOriginY + m_deviceLocalOriginY );
|
|
|
|
// Second, scale
|
|
m_scaleX = m_logicalScaleX * m_userScaleX;
|
|
m_scaleY = m_logicalScaleY * m_userScaleY;
|
|
t.scale( m_scaleX * m_signX, m_scaleY * m_signY );
|
|
|
|
// Finally, logical origin
|
|
t.translate( m_logicalOriginX, m_logicalOriginY );
|
|
|
|
// Apply transform to QPainter, overwriting the previous one
|
|
m_qtPainter->setWorldTransform(t, false);
|
|
}
|