1412 lines
40 KiB
C++
1412 lines
40 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/qt/graphics.cpp
|
|
// Purpose: Graphics context methods for the Qt platform
|
|
// Author: Jay Nabonne
|
|
// Created: 2018-12-13
|
|
// Copyright: (c) Jay Nabonne
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#if defined(__BORLANDC__)
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_GRAPHICS_CONTEXT
|
|
|
|
#include <QApplication>
|
|
#include <QDesktopWidget>
|
|
#include <QPainter>
|
|
#include <QPicture>
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/bitmap.h"
|
|
#include "wx/icon.h"
|
|
#include "wx/dcclient.h"
|
|
#include "wx/dcmemory.h"
|
|
#include "wx/dcprint.h"
|
|
#include "wx/window.h"
|
|
#endif
|
|
|
|
#include "wx/graphics.h"
|
|
#include "wx/scopedptr.h"
|
|
#include "wx/tokenzr.h"
|
|
|
|
#include "wx/private/graphics.h"
|
|
|
|
namespace
|
|
{
|
|
|
|
// Ensure that the given painter is active by calling begin() if it isn't. If
|
|
// it already is, don't do anything.
|
|
class EnsurePainterIsActive
|
|
{
|
|
public:
|
|
explicit EnsurePainterIsActive(QPainter* painter)
|
|
: m_painter(painter),
|
|
m_wasActive(painter->isActive())
|
|
{
|
|
if ( !m_wasActive )
|
|
m_painter->begin(&m_picture);
|
|
}
|
|
|
|
~EnsurePainterIsActive()
|
|
{
|
|
if ( !m_wasActive )
|
|
m_painter->end();
|
|
}
|
|
|
|
private:
|
|
QPainter* m_painter;
|
|
QPicture m_picture;
|
|
bool m_wasActive;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(EnsurePainterIsActive);
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
class WXDLLIMPEXP_CORE wxQtBrushData : public wxGraphicsObjectRefData
|
|
{
|
|
public:
|
|
wxQtBrushData(wxGraphicsRenderer* renderer)
|
|
: wxGraphicsObjectRefData(renderer)
|
|
{
|
|
}
|
|
|
|
wxQtBrushData(wxGraphicsRenderer* renderer, const wxBrush& wxbrush)
|
|
: wxGraphicsObjectRefData(renderer),
|
|
m_brush(wxbrush.GetHandle())
|
|
{
|
|
}
|
|
|
|
void CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
|
|
wxDouble x2, wxDouble y2,
|
|
const wxGraphicsGradientStops& stops)
|
|
{
|
|
QLinearGradient gradient(x1, y1, x2, y2);
|
|
SetStops(gradient, stops);
|
|
m_brush = QBrush(gradient);
|
|
}
|
|
|
|
void CreateRadialGradientBrush(wxDouble startX, wxDouble startY,
|
|
wxDouble endX, wxDouble endY,
|
|
wxDouble radius,
|
|
const wxGraphicsGradientStops& stops)
|
|
{
|
|
QRadialGradient gradient(QPointF(endX, endY), radius, QPointF(startX, startY));
|
|
SetStops(gradient, stops);
|
|
m_brush = QBrush(gradient);
|
|
}
|
|
|
|
const QBrush& getBrush() const
|
|
{
|
|
return m_brush;
|
|
}
|
|
|
|
private:
|
|
static void
|
|
SetStops(QGradient& gradient, const wxGraphicsGradientStops& stops)
|
|
{
|
|
QGradientStops qstops;
|
|
for ( size_t i = 0; i < stops.GetCount(); ++i )
|
|
{
|
|
const wxGraphicsGradientStop stop = stops.Item(i);
|
|
qstops.append(QGradientStop(stop.GetPosition(),
|
|
stop.GetColour().GetQColor()));
|
|
}
|
|
|
|
gradient.setStops(qstops);
|
|
}
|
|
|
|
QBrush m_brush;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxQtBrushData);
|
|
};
|
|
|
|
class WXDLLIMPEXP_CORE wxQtPenData : public wxGraphicsObjectRefData
|
|
{
|
|
public:
|
|
wxQtPenData(wxGraphicsRenderer* renderer, const wxGraphicsPenInfo& info)
|
|
: wxGraphicsObjectRefData(renderer),
|
|
m_pen(CreatePenFromInfo(info))
|
|
{
|
|
}
|
|
|
|
const QPen& GetPen() const
|
|
{
|
|
return m_pen;
|
|
}
|
|
|
|
private:
|
|
static QPen CreatePenFromInfo(const wxGraphicsPenInfo& info)
|
|
{
|
|
wxPen wxpen(info.GetColour(), info.GetWidth(), info.GetStyle());
|
|
wxpen.SetDashes(info.GetDashCount(), info.GetDash());
|
|
wxpen.SetJoin(info.GetJoin());
|
|
wxpen.SetCap(info.GetCap());
|
|
switch ( info.GetStyle() )
|
|
{
|
|
case wxPENSTYLE_STIPPLE:
|
|
case wxPENSTYLE_STIPPLE_MASK:
|
|
case wxPENSTYLE_STIPPLE_MASK_OPAQUE:
|
|
{
|
|
wxpen.SetStipple(info.GetStipple());
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return wxpen.GetHandle();
|
|
}
|
|
QPen m_pen;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxQtPenData);
|
|
};
|
|
|
|
class WXDLLIMPEXP_CORE wxQtBitmapData : public wxGraphicsBitmapData
|
|
{
|
|
public:
|
|
wxQtBitmapData(wxGraphicsRenderer* renderer, QPixmap* pixmap)
|
|
: wxGraphicsBitmapData(renderer),
|
|
m_pixmap(pixmap)
|
|
{
|
|
}
|
|
|
|
wxQtBitmapData(wxGraphicsRenderer* renderer, const wxBitmap& bmp)
|
|
: wxGraphicsBitmapData(renderer),
|
|
m_pixmap(bmp.GetHandle())
|
|
{
|
|
}
|
|
|
|
QPixmap* GetPixmap() const
|
|
{
|
|
return m_pixmap;
|
|
}
|
|
|
|
virtual void* GetNativeBitmap() const wxOVERRIDE
|
|
{
|
|
return m_pixmap;
|
|
}
|
|
|
|
static const QPixmap* GetPixmapFromBitmap(const wxGraphicsBitmap& bitmap)
|
|
{
|
|
const wxQtBitmapData* const
|
|
data = static_cast<const wxQtBitmapData*>(bitmap.GetBitmapData());
|
|
return data->GetPixmap();
|
|
}
|
|
|
|
|
|
#if wxUSE_IMAGE
|
|
wxImage DoConvertToImage() const
|
|
{
|
|
wxBitmap bitmap(*m_pixmap);
|
|
return bitmap.ConvertToImage();
|
|
}
|
|
#endif // wxUSE_IMAGE
|
|
|
|
private:
|
|
QPixmap* m_pixmap;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxQtBitmapData);
|
|
};
|
|
|
|
|
|
class WXDLLIMPEXP_CORE wxQtMatrixData : public wxGraphicsMatrixData
|
|
{
|
|
public:
|
|
explicit wxQtMatrixData(wxGraphicsRenderer* renderer)
|
|
: wxGraphicsMatrixData(renderer),
|
|
m_transform(new QTransform)
|
|
{
|
|
}
|
|
|
|
wxQtMatrixData(wxGraphicsRenderer* renderer, const QTransform& transform)
|
|
: wxGraphicsMatrixData(renderer),
|
|
m_transform(new QTransform(transform))
|
|
{
|
|
}
|
|
|
|
virtual ~wxQtMatrixData()
|
|
{
|
|
delete m_transform;
|
|
}
|
|
|
|
virtual wxGraphicsObjectRefData* Clone() const wxOVERRIDE
|
|
{
|
|
wxQtMatrixData* newMatrix = new wxQtMatrixData(m_renderer);
|
|
*newMatrix->m_transform = *m_transform;
|
|
return newMatrix;
|
|
}
|
|
|
|
// concatenates the matrix
|
|
virtual void Concat(const wxGraphicsMatrixData *t) wxOVERRIDE
|
|
{
|
|
const wxQtMatrixData* rhs = static_cast<const wxQtMatrixData*>(t);
|
|
*m_transform = *rhs->m_transform* (*m_transform);
|
|
}
|
|
|
|
// sets the matrix to the respective values
|
|
virtual void Set(wxDouble a = 1.0, wxDouble b = 0.0,
|
|
wxDouble c = 0.0, wxDouble d = 1.0,
|
|
wxDouble tx = 0.0, wxDouble ty = 0.0) wxOVERRIDE
|
|
{
|
|
m_transform->setMatrix(a, b, 0.0,
|
|
c, d, 0.0,
|
|
tx, ty, 1.0);
|
|
}
|
|
|
|
// gets the component values of the matrix
|
|
virtual void Get(wxDouble* a, wxDouble* b,
|
|
wxDouble* c, wxDouble* d,
|
|
wxDouble* tx, wxDouble* ty) const wxOVERRIDE
|
|
{
|
|
if ( a )
|
|
*a = m_transform->m11();
|
|
if ( b )
|
|
*b = m_transform->m12();
|
|
if ( c )
|
|
*c = m_transform->m21();
|
|
if ( d )
|
|
*d = m_transform->m22();
|
|
if ( tx )
|
|
*tx = m_transform->m31();
|
|
if ( ty )
|
|
*ty = m_transform->m32();
|
|
}
|
|
|
|
// makes this the inverse matrix
|
|
virtual void Invert() wxOVERRIDE
|
|
{
|
|
bool invertible = false;
|
|
const QTransform invTransform = m_transform->inverted(&invertible);
|
|
if ( invertible )
|
|
{
|
|
*m_transform = invTransform;
|
|
}
|
|
}
|
|
|
|
// returns true if the elements of the transformation matrix are equal ?
|
|
virtual bool IsEqual(const wxGraphicsMatrixData* t) const wxOVERRIDE
|
|
{
|
|
const wxQtMatrixData* rhs = static_cast<const wxQtMatrixData*>(t);
|
|
return *m_transform == *rhs->m_transform;
|
|
}
|
|
|
|
// return true if this is the identity matrix
|
|
virtual bool IsIdentity() const wxOVERRIDE
|
|
{
|
|
return m_transform->isIdentity();
|
|
}
|
|
|
|
//
|
|
// transformation
|
|
//
|
|
|
|
// add the translation to this matrix
|
|
virtual void Translate(wxDouble dx, wxDouble dy) wxOVERRIDE
|
|
{
|
|
m_transform->translate(dx, dy);
|
|
}
|
|
|
|
// add the scale to this matrix
|
|
virtual void Scale(wxDouble xScale, wxDouble yScale) wxOVERRIDE
|
|
{
|
|
m_transform->scale(xScale, yScale);
|
|
}
|
|
|
|
// add the rotation to this matrix (radians)
|
|
virtual void Rotate(wxDouble angle) wxOVERRIDE
|
|
{
|
|
m_transform->rotateRadians(angle);
|
|
}
|
|
|
|
//
|
|
// apply the transforms
|
|
//
|
|
|
|
// applies that matrix to the point
|
|
virtual void TransformPoint(wxDouble *x, wxDouble *y) const wxOVERRIDE
|
|
{
|
|
qreal transformed_x, transformed_y;
|
|
m_transform->map(static_cast<qreal>(*x), static_cast<qreal>(*y),
|
|
&transformed_x, &transformed_y);
|
|
*x = transformed_x;
|
|
*y = transformed_y;
|
|
}
|
|
|
|
// applies the matrix except for translations
|
|
virtual void TransformDistance(wxDouble *dx, wxDouble *dy) const wxOVERRIDE
|
|
{
|
|
const QTransform untransTransform(
|
|
m_transform->m11(),
|
|
m_transform->m12(),
|
|
m_transform->m13(),
|
|
m_transform->m21(),
|
|
m_transform->m22(),
|
|
m_transform->m23(),
|
|
0.0,
|
|
0.0,
|
|
1.0);
|
|
|
|
qreal transformed_x, transformed_y;
|
|
untransTransform.map(static_cast<qreal>(*dx), static_cast<qreal>(*dy),
|
|
&transformed_x, &transformed_y);
|
|
|
|
*dx = transformed_x;
|
|
*dy = transformed_y;
|
|
}
|
|
|
|
// returns the native representation
|
|
virtual void* GetNativeMatrix() const wxOVERRIDE
|
|
{
|
|
return static_cast<void*>(m_transform);
|
|
}
|
|
|
|
const QTransform& GetQTransform() const
|
|
{
|
|
return *m_transform;
|
|
}
|
|
private:
|
|
QTransform* m_transform;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxQtMatrixData);
|
|
};
|
|
|
|
class wxQtFontData : public wxGraphicsObjectRefData
|
|
{
|
|
public:
|
|
wxQtFontData(wxGraphicsRenderer* renderer,
|
|
const wxFont& font,
|
|
const wxColour& col)
|
|
: wxGraphicsObjectRefData(renderer),
|
|
m_font(font.GetHandle()),
|
|
m_color(col.GetQColor())
|
|
{
|
|
}
|
|
|
|
wxQtFontData(
|
|
wxGraphicsRenderer* renderer,
|
|
double sizeInPixels,
|
|
const wxString& facename,
|
|
int flags,
|
|
const wxColour& col)
|
|
: wxGraphicsObjectRefData(renderer),
|
|
m_color(col.GetQColor())
|
|
{
|
|
m_font.setFamily(QString(facename));
|
|
m_font.setPixelSize(static_cast<int>(sizeInPixels));
|
|
if ( flags & wxFONTFLAG_LIGHT )
|
|
m_font.setWeight(QFont::Light);
|
|
if ( flags & wxFONTFLAG_BOLD )
|
|
m_font.setWeight(QFont::Bold);
|
|
if ( flags & (wxFONTFLAG_ITALIC | wxFONTFLAG_SLANT) )
|
|
m_font.setItalic(true);
|
|
if ( flags & wxFONTFLAG_ANTIALIASED )
|
|
m_font.setStyleStrategy(QFont::PreferAntialias);
|
|
if ( flags & wxFONTFLAG_NOT_ANTIALIASED )
|
|
m_font.setStyleStrategy(QFont::NoAntialias);
|
|
if ( flags & wxFONTFLAG_UNDERLINED )
|
|
m_font.setUnderline(true);
|
|
if ( flags & wxFONTFLAG_STRIKETHROUGH )
|
|
m_font.setStrikeOut(true);
|
|
}
|
|
|
|
const QFont& GetFont() const
|
|
{
|
|
return m_font;
|
|
}
|
|
|
|
const QColor& GetColor() const
|
|
{
|
|
return m_color;
|
|
}
|
|
|
|
private:
|
|
QFont m_font;
|
|
QColor m_color;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxQtFontData);
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// wxQtGraphicsPathData
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class WXDLLIMPEXP_CORE wxQtGraphicsPathData : public wxGraphicsPathData
|
|
{
|
|
public:
|
|
wxQtGraphicsPathData(wxGraphicsRenderer* renderer)
|
|
: wxGraphicsPathData(renderer),
|
|
m_path(new QPainterPath()),
|
|
m_current_subpath_start(-1)
|
|
{
|
|
}
|
|
|
|
~wxQtGraphicsPathData()
|
|
{
|
|
delete m_path;
|
|
}
|
|
|
|
virtual wxGraphicsObjectRefData *Clone() const wxOVERRIDE
|
|
{
|
|
return new wxQtGraphicsPathData(*this);
|
|
}
|
|
|
|
//
|
|
// These are the path primitives from which everything else can be
|
|
// constructed.
|
|
//
|
|
|
|
// begins a new subpath at (x,y)
|
|
virtual void MoveToPoint(wxDouble x, wxDouble y) wxOVERRIDE
|
|
{
|
|
m_path->moveTo(x, y);
|
|
m_current_subpath_start = m_path->elementCount() - 1;
|
|
}
|
|
|
|
// adds a straight line from the current point to (x,y)
|
|
// if there is no current path, it is equivalent to a moveTo.
|
|
virtual void AddLineToPoint(wxDouble x, wxDouble y) wxOVERRIDE
|
|
{
|
|
if ( !HasCurrentSubpath() )
|
|
MoveToPoint(x, y);
|
|
else
|
|
m_path->lineTo(x, y);
|
|
}
|
|
|
|
// adds a cubic Bezier curve from the current point, using two control
|
|
// points and an end point
|
|
virtual void
|
|
AddCurveToPoint(wxDouble cx1, wxDouble cy1,
|
|
wxDouble cx2, wxDouble cy2,
|
|
wxDouble x, wxDouble y) wxOVERRIDE
|
|
{
|
|
if ( !HasCurrentSubpath() )
|
|
MoveToPoint(cx1, cy1);
|
|
m_path->cubicTo(QPointF(cx1, cy1), QPointF(cx2, cy2), QPointF(x, y));
|
|
}
|
|
|
|
// adds an arc of a circle centering at (x,y) with radius (r) from
|
|
// startAngle to endAngle
|
|
virtual void
|
|
AddArc(wxDouble x, wxDouble y, wxDouble r,
|
|
wxDouble startAngle, wxDouble endAngle,
|
|
bool clockwise) wxOVERRIDE
|
|
{
|
|
const bool fixupFirst = !HasCurrentSubpath();
|
|
if ( fixupFirst )
|
|
MoveToPoint(x, y);
|
|
|
|
qreal arcLength;
|
|
if ( clockwise )
|
|
{
|
|
if ( endAngle < startAngle )
|
|
endAngle += 2* M_PI;
|
|
arcLength = -wxRadToDeg(endAngle - startAngle);
|
|
}
|
|
else
|
|
{
|
|
if ( endAngle > startAngle )
|
|
endAngle -= 2* M_PI;
|
|
arcLength = -wxRadToDeg(endAngle - startAngle);
|
|
}
|
|
m_path->arcTo(x-r, y-r, r*2, r*2, -wxRadToDeg(startAngle), arcLength);
|
|
if ( fixupFirst )
|
|
{
|
|
QPainterPath::Element
|
|
element = m_path->elementAt(m_current_subpath_start+1);
|
|
m_path->setElementPositionAt(m_current_subpath_start,
|
|
element.x, element.y);
|
|
}
|
|
}
|
|
|
|
// gets the last point of the current path, (0,0) if not yet set
|
|
virtual void GetCurrentPoint(wxDouble* x, wxDouble* y) const wxOVERRIDE
|
|
{
|
|
QPointF position = m_path->currentPosition();
|
|
*x = position.x();
|
|
*y = position.y();
|
|
}
|
|
|
|
// adds another path
|
|
virtual void AddPath(const wxGraphicsPathData* path) wxOVERRIDE
|
|
{
|
|
const wxQtGraphicsPathData*
|
|
pathAdded = static_cast<const wxQtGraphicsPathData*>(path);
|
|
m_path->addPath(*pathAdded->m_path);
|
|
}
|
|
|
|
// closes the current sub-path
|
|
virtual void CloseSubpath() wxOVERRIDE
|
|
{
|
|
// Current position must be end of last path after close, not (0,0) as
|
|
// Qt sets.
|
|
if ( !HasCurrentSubpath() )
|
|
return;
|
|
|
|
const QPainterPath::Element
|
|
firstElement = m_path->elementAt(m_current_subpath_start);
|
|
|
|
m_path->closeSubpath();
|
|
MoveToPoint(firstElement.x, firstElement.y);
|
|
}
|
|
|
|
//
|
|
// These are convenience functions which - if not available natively will
|
|
// be assembled using the primitives from above
|
|
//
|
|
|
|
// appends a circle as a new closed subpath
|
|
virtual void AddCircle(wxDouble x, wxDouble y, wxDouble r) wxOVERRIDE
|
|
{
|
|
m_path->addEllipse(x - r, y - r, r*2, r*2);
|
|
}
|
|
|
|
// appends an ellipse as a new closed subpath fitting the passed rectangle
|
|
virtual void
|
|
AddEllipse(wxDouble x, wxDouble y, wxDouble w, wxDouble h) wxOVERRIDE
|
|
{
|
|
m_path->addEllipse(x, y, w, h);
|
|
}
|
|
|
|
// returns the native path
|
|
virtual void* GetNativePath() const wxOVERRIDE
|
|
{
|
|
return static_cast<void*>(m_path);
|
|
}
|
|
|
|
// give the native path returned by GetNativePath() back (there might be
|
|
// some deallocations necessary)
|
|
virtual void UnGetNativePath(void *) const wxOVERRIDE
|
|
{
|
|
}
|
|
|
|
// transforms each point of this path by the matrix
|
|
virtual void Transform(const wxGraphicsMatrixData* matrix) wxOVERRIDE
|
|
{
|
|
const wxQtMatrixData*
|
|
qmatrix = static_cast<const wxQtMatrixData*>(matrix);
|
|
*m_path = qmatrix->GetQTransform().map(*m_path);
|
|
}
|
|
|
|
// gets the bounding box enclosing all points (possibly including control
|
|
// points)
|
|
virtual void
|
|
GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const wxOVERRIDE
|
|
{
|
|
QRectF boundingRect = m_path->controlPointRect();
|
|
|
|
if ( !boundingRect.isValid() )
|
|
boundingRect = QRectF();
|
|
|
|
if ( x ) *x = boundingRect.left();
|
|
if ( y ) *y = boundingRect.top();
|
|
if ( w ) *w = boundingRect.width();
|
|
if ( h ) *h = boundingRect.height();
|
|
}
|
|
|
|
virtual bool
|
|
Contains(wxDouble x, wxDouble y,
|
|
wxPolygonFillMode /*fillStyle = wxWINDING_RULE*/) const wxOVERRIDE
|
|
{
|
|
return m_path->contains(QPointF(x, y));
|
|
}
|
|
|
|
private:
|
|
// for Clone
|
|
wxQtGraphicsPathData(const wxQtGraphicsPathData& rhs)
|
|
: wxGraphicsPathData(rhs.GetRenderer()),
|
|
m_path(new QPainterPath(*rhs.m_path)),
|
|
m_current_subpath_start(rhs.m_current_subpath_start)
|
|
{
|
|
}
|
|
|
|
bool HasCurrentSubpath() const
|
|
{
|
|
return m_current_subpath_start != -1;
|
|
}
|
|
|
|
QPainterPath* m_path;
|
|
int m_current_subpath_start;
|
|
|
|
wxQtGraphicsPathData& operator=(const wxQtGraphicsPathData&);
|
|
};
|
|
|
|
class WXDLLIMPEXP_CORE wxQtGraphicsContext : public wxGraphicsContext
|
|
{
|
|
void InitFromDC(const wxDC& dc)
|
|
{
|
|
m_qtPainter = static_cast<QPainter*>(dc.GetHandle());
|
|
|
|
const wxSize sz = dc.GetSize();
|
|
m_width = sz.x;
|
|
m_height = sz.y;
|
|
}
|
|
|
|
protected:
|
|
// Use the specified painter and take ownership of it, i.e. it will be
|
|
// destroyed in this class dtor.
|
|
void AttachPainter(QPainter* painter)
|
|
{
|
|
m_qtPainter = painter;
|
|
|
|
// Ensure that it will be destroyed when this object is.
|
|
m_ownedPainter.reset(m_qtPainter);
|
|
}
|
|
|
|
wxQtGraphicsContext(wxGraphicsRenderer* renderer)
|
|
: wxGraphicsContext(renderer),
|
|
m_qtPainter(NULL)
|
|
{
|
|
}
|
|
|
|
public:
|
|
wxQtGraphicsContext(wxGraphicsRenderer* renderer, QPaintDevice* device)
|
|
: wxGraphicsContext(renderer)
|
|
{
|
|
AttachPainter(new QPainter(device));
|
|
|
|
m_width = device->width();
|
|
m_height = device->height();
|
|
}
|
|
|
|
wxQtGraphicsContext(wxGraphicsRenderer* renderer, const wxWindowDC& dc)
|
|
: wxGraphicsContext(renderer)
|
|
{
|
|
InitFromDC(dc);
|
|
}
|
|
|
|
wxQtGraphicsContext(wxGraphicsRenderer* renderer, const wxMemoryDC& dc)
|
|
: wxGraphicsContext(renderer)
|
|
{
|
|
InitFromDC(dc);
|
|
}
|
|
|
|
#if wxUSE_PRINTING_ARCHITECTURE
|
|
wxQtGraphicsContext(wxGraphicsRenderer* renderer, const wxPrinterDC& dc)
|
|
: wxGraphicsContext(renderer)
|
|
{
|
|
InitFromDC(dc);
|
|
}
|
|
|
|
#endif
|
|
|
|
wxQtGraphicsContext(wxGraphicsRenderer* renderer, wxWindow *window)
|
|
: wxGraphicsContext(renderer)
|
|
{
|
|
m_qtPainter = static_cast<QPainter*>(window->QtGetPainter());
|
|
|
|
const wxSize sz = window->GetClientSize();
|
|
m_width = sz.x;
|
|
m_height = sz.y;
|
|
}
|
|
|
|
virtual bool ShouldOffset() const wxOVERRIDE
|
|
{
|
|
return false;
|
|
}
|
|
|
|
virtual void Clip(const wxRegion& region) wxOVERRIDE
|
|
{
|
|
m_qtPainter->setClipRegion(region.GetHandle());
|
|
}
|
|
|
|
// clips drawings to the rect
|
|
virtual void Clip(wxDouble x, wxDouble y, wxDouble w, wxDouble h) wxOVERRIDE
|
|
{
|
|
m_qtPainter->setClipRect(x, y, w, h);
|
|
}
|
|
|
|
// resets the clipping to original extent
|
|
virtual void ResetClip() wxOVERRIDE
|
|
{
|
|
m_qtPainter->setClipping(false);
|
|
}
|
|
|
|
// returns bounding box of the clipping region
|
|
virtual void
|
|
GetClipBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble* h) wxOVERRIDE
|
|
{
|
|
const QRectF box = m_qtPainter->clipBoundingRect();
|
|
if ( x )
|
|
*x = box.left();
|
|
if ( y )
|
|
*y = box.top();
|
|
if ( w )
|
|
*w = box.width();
|
|
if ( h )
|
|
*h = box.height();
|
|
}
|
|
|
|
virtual void* GetNativeContext() wxOVERRIDE
|
|
{
|
|
return static_cast<void*>(m_qtPainter);
|
|
}
|
|
|
|
virtual bool SetAntialiasMode(wxAntialiasMode antialias) wxOVERRIDE
|
|
{
|
|
bool enableAA = false;
|
|
switch ( antialias )
|
|
{
|
|
case wxANTIALIAS_DEFAULT:
|
|
enableAA = true;
|
|
break;
|
|
|
|
case wxANTIALIAS_NONE:
|
|
enableAA = false;
|
|
break;
|
|
}
|
|
|
|
m_qtPainter->setRenderHints(QPainter::Antialiasing |
|
|
QPainter::TextAntialiasing,
|
|
enableAA);
|
|
|
|
m_antialias = antialias;
|
|
return true;
|
|
}
|
|
|
|
virtual bool
|
|
SetInterpolationQuality(wxInterpolationQuality interpolation) wxOVERRIDE
|
|
{
|
|
m_qtPainter->setRenderHint(QPainter::SmoothPixmapTransform,
|
|
interpolation == wxINTERPOLATION_BEST);
|
|
m_interpolation = interpolation;
|
|
return true;
|
|
}
|
|
|
|
virtual bool SetCompositionMode(wxCompositionMode composition) wxOVERRIDE
|
|
{
|
|
QPainter::CompositionMode q_composition_mode;
|
|
switch ( composition )
|
|
{
|
|
case wxCOMPOSITION_CLEAR:
|
|
q_composition_mode = QPainter::CompositionMode_Clear;
|
|
break;
|
|
case wxCOMPOSITION_SOURCE:
|
|
q_composition_mode = QPainter::CompositionMode_Source;
|
|
break;
|
|
case wxCOMPOSITION_OVER:
|
|
q_composition_mode = QPainter::CompositionMode_SourceOver;
|
|
break;
|
|
case wxCOMPOSITION_IN:
|
|
q_composition_mode = QPainter::CompositionMode_SourceIn;
|
|
break;
|
|
case wxCOMPOSITION_OUT:
|
|
q_composition_mode = QPainter::CompositionMode_SourceOut;
|
|
break;
|
|
case wxCOMPOSITION_ATOP:
|
|
q_composition_mode = QPainter::CompositionMode_SourceAtop;
|
|
break;
|
|
case wxCOMPOSITION_DEST:
|
|
q_composition_mode = QPainter::CompositionMode_Destination;
|
|
break;
|
|
case wxCOMPOSITION_DEST_OVER:
|
|
q_composition_mode = QPainter::CompositionMode_DestinationOver;
|
|
break;
|
|
case wxCOMPOSITION_DEST_IN:
|
|
q_composition_mode = QPainter::CompositionMode_DestinationIn;
|
|
break;
|
|
case wxCOMPOSITION_DEST_OUT:
|
|
q_composition_mode = QPainter::CompositionMode_DestinationOut;
|
|
break;
|
|
case wxCOMPOSITION_DEST_ATOP:
|
|
q_composition_mode = QPainter::CompositionMode_DestinationAtop;
|
|
break;
|
|
case wxCOMPOSITION_XOR:
|
|
q_composition_mode = QPainter::CompositionMode_Xor;
|
|
break;
|
|
case wxCOMPOSITION_ADD:
|
|
q_composition_mode = QPainter::CompositionMode_Plus;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
m_qtPainter->setCompositionMode(q_composition_mode);
|
|
m_composition = composition;
|
|
return true;
|
|
}
|
|
|
|
virtual void BeginLayer(wxDouble /*opacity*/) wxOVERRIDE
|
|
{
|
|
wxFAIL_MSG("BeginLayer not implemented");
|
|
}
|
|
|
|
virtual void EndLayer() wxOVERRIDE
|
|
{
|
|
wxFAIL_MSG("EndLayer not implemented");
|
|
}
|
|
|
|
virtual void StrokePath(const wxGraphicsPath& p) wxOVERRIDE
|
|
{
|
|
if ( m_pen.IsNull() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
const QPainterPath*
|
|
pathData = static_cast<QPainterPath*>(p.GetNativePath());
|
|
const QPen&
|
|
pen = static_cast<wxQtPenData*>(m_pen.GetRefData())->GetPen();
|
|
m_qtPainter->strokePath(*pathData, pen);
|
|
}
|
|
|
|
virtual void
|
|
FillPath(const wxGraphicsPath& p,
|
|
wxPolygonFillMode /*fillStyle = wxWINDING_RULE*/) wxOVERRIDE
|
|
{
|
|
if ( m_brush.IsNull() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
const QPainterPath*
|
|
pathData = static_cast<QPainterPath*>(p.GetNativePath());
|
|
const QBrush&
|
|
brush = static_cast<wxQtBrushData*>(m_brush.GetRefData())->getBrush();
|
|
m_qtPainter->fillPath(*pathData, brush);
|
|
}
|
|
|
|
virtual void
|
|
ClearRectangle(wxDouble x, wxDouble y, wxDouble w, wxDouble h) wxOVERRIDE
|
|
{
|
|
m_qtPainter->fillRect(x, y, w, h, QBrush(QColor(0, 0, 0, 0)));
|
|
}
|
|
|
|
virtual void Translate(wxDouble dx, wxDouble dy) wxOVERRIDE
|
|
{
|
|
m_qtPainter->translate(dx, dy);
|
|
}
|
|
|
|
virtual void Scale(wxDouble xScale, wxDouble yScale) wxOVERRIDE
|
|
{
|
|
m_qtPainter->scale(xScale, yScale);
|
|
}
|
|
|
|
virtual void Rotate(wxDouble angle) wxOVERRIDE
|
|
{
|
|
// wx angle is in radians. Qt angle is in degrees.
|
|
m_qtPainter->rotate(wxRadToDeg(angle));
|
|
}
|
|
|
|
// concatenates this transform with the current transform of this context
|
|
virtual void ConcatTransform(const wxGraphicsMatrix& matrix) wxOVERRIDE
|
|
{
|
|
wxGraphicsMatrix currentMatrix = GetTransform();
|
|
currentMatrix.Concat(matrix);
|
|
SetTransform(currentMatrix);
|
|
}
|
|
|
|
// sets the transform of this context
|
|
virtual void SetTransform(const wxGraphicsMatrix& matrix) wxOVERRIDE
|
|
{
|
|
const wxQtMatrixData*
|
|
qmatrix = static_cast<const wxQtMatrixData*>(matrix.GetRefData());
|
|
m_qtPainter->setTransform(qmatrix->GetQTransform());
|
|
}
|
|
|
|
// gets the matrix of this context
|
|
virtual wxGraphicsMatrix GetTransform() const wxOVERRIDE
|
|
{
|
|
const QTransform& transform = m_qtPainter->transform();
|
|
wxGraphicsMatrix m;
|
|
m.SetRefData(new wxQtMatrixData(GetRenderer(), transform));
|
|
return m;
|
|
}
|
|
|
|
virtual void
|
|
DrawBitmap(const wxGraphicsBitmap& bmp,
|
|
wxDouble x, wxDouble y, wxDouble w, wxDouble h) wxOVERRIDE
|
|
{
|
|
const QPixmap* pixmap = wxQtBitmapData::GetPixmapFromBitmap(bmp);
|
|
m_qtPainter->drawPixmap(x, y, w, h, *pixmap);
|
|
}
|
|
|
|
virtual void
|
|
DrawBitmap(const wxBitmap& bmp,
|
|
wxDouble x, wxDouble y, wxDouble w, wxDouble h) wxOVERRIDE
|
|
{
|
|
DoDrawBitmap(bmp, x, y, w, h, true);
|
|
}
|
|
|
|
virtual void
|
|
DrawIcon(const wxIcon& icon,
|
|
wxDouble x, wxDouble y, wxDouble w, wxDouble h) wxOVERRIDE
|
|
{
|
|
DoDrawBitmap(icon, x, y, w, h, true);
|
|
}
|
|
|
|
virtual void PushState() wxOVERRIDE
|
|
{
|
|
m_qtPainter->save();
|
|
}
|
|
|
|
virtual void PopState() wxOVERRIDE
|
|
{
|
|
m_qtPainter->restore();
|
|
}
|
|
|
|
virtual void Flush() wxOVERRIDE
|
|
{
|
|
}
|
|
|
|
virtual void GetTextExtent(const wxString& str,
|
|
wxDouble *width,
|
|
wxDouble *height,
|
|
wxDouble *descent,
|
|
wxDouble *externalLeading) const wxOVERRIDE
|
|
{
|
|
wxCHECK_RET( !m_font.IsNull(),
|
|
"wxQtContext::GetTextExtent - no valid font set" );
|
|
|
|
EnsurePainterIsActive active(m_qtPainter);
|
|
|
|
const wxQtFontData*
|
|
fontData = static_cast<wxQtFontData*>(m_font.GetRefData());
|
|
m_qtPainter->setFont(fontData->GetFont());
|
|
|
|
const QFontMetrics metrics = m_qtPainter->fontMetrics();
|
|
const QRect boundingRect = metrics.boundingRect(QString(str));
|
|
|
|
if ( width )
|
|
*width = boundingRect.width();
|
|
if ( height )
|
|
*height = boundingRect.height();
|
|
if ( descent )
|
|
*descent = metrics.descent();
|
|
if ( externalLeading )
|
|
*externalLeading = metrics.leading() - (metrics.ascent() + metrics.descent());
|
|
}
|
|
|
|
virtual void
|
|
GetPartialTextExtents(const wxString& text,
|
|
wxArrayDouble& widths) const wxOVERRIDE
|
|
{
|
|
wxCHECK_RET( !m_font.IsNull(),
|
|
"wxQtContext::GetPartialTextExtents - no valid font set" );
|
|
|
|
EnsurePainterIsActive active(m_qtPainter);
|
|
|
|
const wxQtFontData*
|
|
fontData = static_cast<wxQtFontData*>(m_font.GetRefData());
|
|
m_qtPainter->setFont(fontData->GetFont());
|
|
|
|
const QFontMetrics metrics = m_qtPainter->fontMetrics();
|
|
|
|
const size_t textLength = text.length();
|
|
|
|
widths.clear();
|
|
widths.insert(widths.end(), textLength, 0);
|
|
|
|
for ( size_t i = 0; i < textLength; ++i )
|
|
{
|
|
const wxString subString = text.substr(0, i+1);
|
|
const QRect
|
|
boundingRect = metrics.boundingRect(QString(subString));
|
|
widths[i] = boundingRect.width();
|
|
}
|
|
}
|
|
|
|
protected:
|
|
virtual void
|
|
DoDrawText(const wxString& str, wxDouble x, wxDouble y) wxOVERRIDE
|
|
{
|
|
wxCHECK_RET( !m_font.IsNull(),
|
|
"wxQtContext::DrawText - no valid font set" );
|
|
|
|
const wxQtFontData*
|
|
fontData = static_cast<wxQtFontData*>(m_font.GetRefData());
|
|
|
|
m_qtPainter->setFont(fontData->GetFont());
|
|
m_qtPainter->setPen(QPen(fontData->GetColor()));
|
|
|
|
QFontMetrics metrics = m_qtPainter->fontMetrics();
|
|
|
|
wxStringTokenizer tokenizer(str, "\n");
|
|
while ( tokenizer.HasMoreTokens() )
|
|
{
|
|
const wxString line = tokenizer.GetNextToken();
|
|
m_qtPainter->drawText(x, y + metrics.ascent(), QString(line));
|
|
y += metrics.lineSpacing();
|
|
}
|
|
}
|
|
|
|
void
|
|
DoDrawBitmap(const wxBitmap& bmp,
|
|
wxDouble x, wxDouble y,
|
|
wxDouble w, wxDouble h, bool useMask) const
|
|
{
|
|
QPixmap pix = *bmp.GetHandle();
|
|
|
|
if (useMask && bmp.GetMask() && bmp.GetMask()->GetHandle())
|
|
pix.setMask(*bmp.GetMask()->GetHandle());
|
|
|
|
m_qtPainter->drawPixmap(x, y, w, h, pix);
|
|
}
|
|
|
|
QPainter* m_qtPainter;
|
|
|
|
private:
|
|
// This pointer may be empty if we don't own m_qtPainter.
|
|
wxScopedPtr<QPainter> m_ownedPainter;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxQtGraphicsContext);
|
|
};
|
|
|
|
class wxQtMeasuringContext : public wxQtGraphicsContext
|
|
{
|
|
public:
|
|
wxQtMeasuringContext(wxGraphicsRenderer* renderer)
|
|
: wxQtGraphicsContext(renderer)
|
|
{
|
|
AttachPainter(new QPainter());
|
|
}
|
|
};
|
|
|
|
class wxQtImageContext : public wxQtGraphicsContext
|
|
{
|
|
public:
|
|
wxQtImageContext(wxGraphicsRenderer* renderer, wxImage& image) :
|
|
wxQtGraphicsContext(renderer),
|
|
m_image(image)
|
|
{
|
|
const wxBitmap wxbitmap(image);
|
|
m_pixmap = *wxbitmap.GetHandle();
|
|
AttachPainter(new QPainter(&m_pixmap));
|
|
}
|
|
|
|
~wxQtImageContext()
|
|
{
|
|
wxQtBitmapData bitmap(GetRenderer(), &m_pixmap);
|
|
m_image = bitmap.DoConvertToImage();
|
|
}
|
|
|
|
private:
|
|
QPixmap m_pixmap;
|
|
wxImage& m_image;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// wxQtGraphicsRenderer declaration
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class WXDLLIMPEXP_CORE wxQtGraphicsRenderer : public wxGraphicsRenderer
|
|
{
|
|
public:
|
|
wxQtGraphicsRenderer() {}
|
|
|
|
virtual ~wxQtGraphicsRenderer() {}
|
|
|
|
// Context
|
|
|
|
virtual wxGraphicsContext* CreateContext(const wxWindowDC& dc) wxOVERRIDE;
|
|
virtual wxGraphicsContext* CreateContext(const wxMemoryDC& dc) wxOVERRIDE;
|
|
#if wxUSE_PRINTING_ARCHITECTURE
|
|
virtual wxGraphicsContext* CreateContext(const wxPrinterDC& dc) wxOVERRIDE;
|
|
#endif
|
|
|
|
virtual wxGraphicsContext* CreateContextFromNativeContext(void* context) wxOVERRIDE;
|
|
|
|
virtual wxGraphicsContext* CreateContextFromNativeWindow(void* window) wxOVERRIDE;
|
|
|
|
#if wxUSE_IMAGE
|
|
virtual wxGraphicsContext* CreateContextFromImage(wxImage& image) wxOVERRIDE;
|
|
#endif // wxUSE_IMAGE
|
|
|
|
virtual wxGraphicsContext* CreateContext(wxWindow* window) wxOVERRIDE;
|
|
|
|
virtual wxGraphicsContext* CreateMeasuringContext() wxOVERRIDE;
|
|
|
|
// Path
|
|
|
|
virtual wxGraphicsPath CreatePath() wxOVERRIDE;
|
|
|
|
// Matrix
|
|
|
|
virtual wxGraphicsMatrix CreateMatrix(wxDouble a = 1.0, wxDouble b = 0.0,
|
|
wxDouble c = 0.0, wxDouble d = 1.0,
|
|
wxDouble tx = 0.0, wxDouble ty = 0.0) wxOVERRIDE;
|
|
|
|
virtual wxGraphicsPen CreatePen(const wxGraphicsPenInfo& info) wxOVERRIDE;
|
|
|
|
virtual wxGraphicsBrush CreateBrush(const wxBrush& brush) wxOVERRIDE;
|
|
|
|
virtual wxGraphicsBrush
|
|
CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
|
|
wxDouble x2, wxDouble y2,
|
|
const wxGraphicsGradientStops& stops,
|
|
const wxGraphicsMatrix& matrix=wxNullGraphicsMatrix) wxOVERRIDE;
|
|
|
|
virtual wxGraphicsBrush
|
|
CreateRadialGradientBrush(wxDouble startX, wxDouble startY,
|
|
wxDouble endX, wxDouble endY,
|
|
wxDouble radius,
|
|
const wxGraphicsGradientStops& stops,
|
|
const wxGraphicsMatrix& matrix=wxNullGraphicsMatrix) wxOVERRIDE;
|
|
|
|
// sets the font
|
|
virtual wxGraphicsFont CreateFont(const wxFont& font,
|
|
const wxColour& col = *wxBLACK) wxOVERRIDE;
|
|
virtual wxGraphicsFont CreateFont(double sizeInPixels,
|
|
const wxString& facename,
|
|
int flags = wxFONTFLAG_DEFAULT,
|
|
const wxColour& col = *wxBLACK) wxOVERRIDE;
|
|
|
|
// create a native bitmap representation
|
|
virtual wxGraphicsBitmap CreateBitmap(const wxBitmap& bitmap) wxOVERRIDE;
|
|
#if wxUSE_IMAGE
|
|
virtual wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image) wxOVERRIDE;
|
|
virtual wxImage CreateImageFromBitmap(const wxGraphicsBitmap& bmp) wxOVERRIDE;
|
|
#endif // wxUSE_IMAGE
|
|
|
|
// create a graphics bitmap from a native bitmap
|
|
virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap(void* bitmap) wxOVERRIDE;
|
|
|
|
// create a subimage from a native image representation
|
|
virtual wxGraphicsBitmap CreateSubBitmap(const wxGraphicsBitmap& bitmap,
|
|
wxDouble x, wxDouble y,
|
|
wxDouble w, wxDouble h) wxOVERRIDE;
|
|
|
|
virtual wxString GetName() const wxOVERRIDE;
|
|
virtual void GetVersion(int *major,
|
|
int *minor,
|
|
int *micro) const wxOVERRIDE;
|
|
|
|
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxQtGraphicsRenderer);
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// wxQtGraphicsRenderer implementation
|
|
//-----------------------------------------------------------------------------
|
|
|
|
wxIMPLEMENT_DYNAMIC_CLASS(wxQtGraphicsRenderer, wxGraphicsRenderer);
|
|
|
|
wxGraphicsContext* wxQtGraphicsRenderer::CreateContext(const wxWindowDC& dc)
|
|
{
|
|
return new wxQtGraphicsContext(this, dc);
|
|
}
|
|
|
|
wxGraphicsContext* wxQtGraphicsRenderer::CreateContext(const wxMemoryDC& dc)
|
|
{
|
|
return new wxQtGraphicsContext(this, dc);
|
|
}
|
|
|
|
#if wxUSE_PRINTING_ARCHITECTURE
|
|
wxGraphicsContext* wxQtGraphicsRenderer::CreateContext(const wxPrinterDC& dc)
|
|
{
|
|
return new wxQtGraphicsContext(this, dc);
|
|
}
|
|
#endif
|
|
|
|
wxGraphicsContext*
|
|
wxQtGraphicsRenderer::CreateContextFromNativeContext(void* context)
|
|
{
|
|
return new wxQtGraphicsContext(this, static_cast<QPaintDevice*>(context));
|
|
}
|
|
|
|
wxGraphicsContext*
|
|
wxQtGraphicsRenderer::CreateContextFromNativeWindow(void* window)
|
|
{
|
|
return new wxQtGraphicsContext(this, static_cast<QWidget*>(window));
|
|
}
|
|
|
|
#if wxUSE_IMAGE
|
|
wxGraphicsContext* wxQtGraphicsRenderer::CreateContextFromImage(wxImage& image)
|
|
{
|
|
return new wxQtImageContext(this, image);
|
|
}
|
|
#endif // wxUSE_IMAGE
|
|
|
|
wxGraphicsContext* wxQtGraphicsRenderer::CreateMeasuringContext()
|
|
{
|
|
return new wxQtMeasuringContext(this);
|
|
}
|
|
|
|
wxGraphicsContext* wxQtGraphicsRenderer::CreateContext(wxWindow* window)
|
|
{
|
|
return new wxQtGraphicsContext(this, window);
|
|
}
|
|
|
|
// Path
|
|
|
|
wxGraphicsPath wxQtGraphicsRenderer::CreatePath()
|
|
{
|
|
wxGraphicsPath path;
|
|
path.SetRefData(new wxQtGraphicsPathData(this));
|
|
return path;
|
|
}
|
|
|
|
// Matrix
|
|
|
|
wxGraphicsMatrix wxQtGraphicsRenderer::CreateMatrix(wxDouble a, wxDouble b,
|
|
wxDouble c, wxDouble d,
|
|
wxDouble tx, wxDouble ty)
|
|
|
|
{
|
|
wxGraphicsMatrix m;
|
|
wxQtMatrixData* data = new wxQtMatrixData(this);
|
|
data->Set(a, b, c, d, tx, ty);
|
|
m.SetRefData(data);
|
|
return m;
|
|
}
|
|
|
|
wxGraphicsPen wxQtGraphicsRenderer::CreatePen(const wxGraphicsPenInfo& info)
|
|
{
|
|
wxGraphicsPen p;
|
|
if ( info.GetStyle() != wxPENSTYLE_TRANSPARENT )
|
|
{
|
|
p.SetRefData(new wxQtPenData(this, info));
|
|
}
|
|
return p;
|
|
}
|
|
|
|
wxGraphicsBrush wxQtGraphicsRenderer::CreateBrush(const wxBrush& brush)
|
|
{
|
|
wxGraphicsBrush p;
|
|
if ( brush.IsOk() && brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT )
|
|
{
|
|
p.SetRefData(new wxQtBrushData(this, brush));
|
|
}
|
|
return p;
|
|
}
|
|
|
|
wxGraphicsBrush wxQtGraphicsRenderer::CreateLinearGradientBrush(
|
|
wxDouble x1, wxDouble y1,
|
|
wxDouble x2, wxDouble y2,
|
|
const wxGraphicsGradientStops& stops,
|
|
const wxGraphicsMatrix& WXUNUSED(matrix))
|
|
{
|
|
wxGraphicsBrush p;
|
|
wxQtBrushData* d = new wxQtBrushData(this);
|
|
d->CreateLinearGradientBrush(x1, y1, x2, y2, stops);
|
|
p.SetRefData(d);
|
|
return p;
|
|
}
|
|
|
|
wxGraphicsBrush wxQtGraphicsRenderer::CreateRadialGradientBrush(
|
|
wxDouble startX, wxDouble startY,
|
|
wxDouble endX, wxDouble endY, wxDouble r,
|
|
const wxGraphicsGradientStops& stops,
|
|
const wxGraphicsMatrix& WXUNUSED(matrix))
|
|
{
|
|
wxGraphicsBrush p;
|
|
wxQtBrushData* d = new wxQtBrushData(this);
|
|
d->CreateRadialGradientBrush(startX, startY, endX, endY, r, stops);
|
|
p.SetRefData(d);
|
|
return p;
|
|
}
|
|
|
|
wxGraphicsFont
|
|
wxQtGraphicsRenderer::CreateFont(const wxFont& font, const wxColour& col)
|
|
{
|
|
wxGraphicsFont p;
|
|
if ( font.IsOk() )
|
|
{
|
|
p.SetRefData(new wxQtFontData(this, font, col));
|
|
}
|
|
return p;
|
|
}
|
|
|
|
wxGraphicsFont wxQtGraphicsRenderer::CreateFont(
|
|
double sizeInPixels,
|
|
const wxString& facename,
|
|
int flags,
|
|
const wxColour& col)
|
|
{
|
|
wxGraphicsFont font;
|
|
font.SetRefData(new wxQtFontData(this, sizeInPixels, facename, flags, col));
|
|
return font;
|
|
}
|
|
|
|
wxGraphicsBitmap wxQtGraphicsRenderer::CreateBitmap(const wxBitmap& bmp)
|
|
{
|
|
wxGraphicsBitmap p;
|
|
if ( bmp.IsOk() )
|
|
{
|
|
p.SetRefData(new wxQtBitmapData(this, bmp));
|
|
}
|
|
return p;
|
|
}
|
|
|
|
#if wxUSE_IMAGE
|
|
|
|
wxGraphicsBitmap
|
|
wxQtGraphicsRenderer::CreateBitmapFromImage(const wxImage& image)
|
|
{
|
|
wxGraphicsBitmap bmp;
|
|
if ( image.IsOk() )
|
|
{
|
|
bmp.SetRefData(new wxQtBitmapData(this, image));
|
|
}
|
|
return bmp;
|
|
}
|
|
|
|
wxImage wxQtGraphicsRenderer::CreateImageFromBitmap(const wxGraphicsBitmap& bmp)
|
|
{
|
|
const wxQtBitmapData* const
|
|
data = static_cast<const wxQtBitmapData*>(bmp.GetBitmapData());
|
|
return data->DoConvertToImage();
|
|
}
|
|
#endif // wxUSE_IMAGE
|
|
|
|
wxGraphicsBitmap
|
|
wxQtGraphicsRenderer::CreateBitmapFromNativeBitmap(void* bitmap)
|
|
{
|
|
wxGraphicsBitmap p;
|
|
if ( bitmap != NULL )
|
|
{
|
|
p.SetRefData(new wxQtBitmapData(this, (QPixmap*)bitmap));
|
|
}
|
|
return p;
|
|
}
|
|
|
|
wxGraphicsBitmap
|
|
wxQtGraphicsRenderer::CreateSubBitmap(const wxGraphicsBitmap& bitmap,
|
|
wxDouble x, wxDouble y,
|
|
wxDouble w, wxDouble h)
|
|
{
|
|
wxCHECK_MSG(!bitmap.IsNull(), wxNullGraphicsBitmap, wxS("Invalid bitmap"));
|
|
|
|
const QPixmap* sourcePixmap = wxQtBitmapData::GetPixmapFromBitmap(bitmap);
|
|
wxCHECK_MSG(sourcePixmap, wxNullGraphicsBitmap, wxS("Invalid bitmap"));
|
|
|
|
const int srcWidth = sourcePixmap->width();
|
|
const int srcHeight = sourcePixmap->height();
|
|
const int dstWidth = wxRound(w);
|
|
const int dstHeight = wxRound(h);
|
|
|
|
wxCHECK_MSG(x >= 0.0 && y >= 0.0 && dstWidth > 0 && dstHeight > 0 &&
|
|
x + dstWidth <= srcWidth && y + dstHeight <= srcHeight,
|
|
wxNullGraphicsBitmap, wxS("Invalid bitmap region"));
|
|
|
|
QPixmap* subPixmap = new QPixmap(sourcePixmap->copy(x, y, w, h));
|
|
|
|
wxGraphicsBitmap bmpRes;
|
|
bmpRes.SetRefData(new wxQtBitmapData(this, subPixmap));
|
|
return bmpRes;
|
|
}
|
|
|
|
wxString wxQtGraphicsRenderer::GetName() const
|
|
{
|
|
return "qt";
|
|
}
|
|
|
|
void wxQtGraphicsRenderer::GetVersion(int *major, int *minor, int *micro) const
|
|
{
|
|
if ( major ) *major = QT_VERSION_MAJOR;
|
|
if ( minor ) *minor = QT_VERSION_MINOR;
|
|
if ( micro ) *micro = QT_VERSION_PATCH;
|
|
}
|
|
|
|
static wxQtGraphicsRenderer gs_qtGraphicsRenderer;
|
|
|
|
wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer()
|
|
{
|
|
return &gs_qtGraphicsRenderer;
|
|
}
|
|
|
|
#endif // wxUSE_GRAPHICS_CONTEXT
|