Merge branch 'wxqt-gfx-1' of https://github.com/dsa-t/wxWidgets
Improve wxQtDCImpl to better match Cairo rendering and enable anti-aliasing. See #24328.
This commit is contained in:
commit
bf971fb0a8
3 changed files with 136 additions and 45 deletions
149
src/qt/dc.cpp
149
src/qt/dc.cpp
|
|
@ -42,6 +42,49 @@ static void SetBrushColour( QPainter *qtPainter, QColor col )
|
|||
qtPainter->setBrush( b );
|
||||
}
|
||||
|
||||
class QtDCOffsetHelper
|
||||
{
|
||||
public:
|
||||
QtDCOffsetHelper(QPainter *qpainter)
|
||||
{
|
||||
m_shouldOffset = ShouldOffset(qpainter->pen());
|
||||
if (!m_shouldOffset)
|
||||
return;
|
||||
|
||||
m_qp = qpainter;
|
||||
m_offset = 0.5;
|
||||
|
||||
m_qp->translate(m_offset, m_offset);
|
||||
}
|
||||
|
||||
~QtDCOffsetHelper()
|
||||
{
|
||||
if (m_shouldOffset)
|
||||
m_qp->translate(-m_offset, -m_offset);
|
||||
}
|
||||
|
||||
bool ShouldOffset(const QPen &pen) const
|
||||
{
|
||||
if (pen.style() == Qt::NoPen)
|
||||
return false;
|
||||
|
||||
double width = pen.widthF();
|
||||
|
||||
// always offset for 1-pixel width
|
||||
if (width <= 0)
|
||||
return true;
|
||||
|
||||
// offset if pen width is odd integer
|
||||
const int w = int(width);
|
||||
return (w & 1) && wxIsSameDouble(width, w);
|
||||
}
|
||||
|
||||
private:
|
||||
QPainter *m_qp;
|
||||
double m_offset;
|
||||
bool m_shouldOffset;
|
||||
};
|
||||
|
||||
wxIMPLEMENT_CLASS(wxQtDCImpl,wxDCImpl);
|
||||
|
||||
wxQtDCImpl::wxQtDCImpl( wxDC *owner )
|
||||
|
|
@ -83,6 +126,12 @@ void wxQtDCImpl::QtPreparePainter( )
|
|||
m_qtPainter->setBrush( wxBrush().GetHandle() );
|
||||
m_qtPainter->setFont( wxFont().GetHandle() );
|
||||
|
||||
if (m_qtPainter->device()->depth() > 1)
|
||||
{
|
||||
m_qtPainter->setRenderHints(QPainter::Antialiasing,
|
||||
true);
|
||||
}
|
||||
|
||||
if (m_clipping)
|
||||
{
|
||||
m_qtPainter->setClipRegion( m_clippingRegion.GetHandle() );
|
||||
|
|
@ -560,11 +609,15 @@ bool wxQtDCImpl::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
|
|||
|
||||
void wxQtDCImpl::DoDrawPoint(wxCoord x, wxCoord y)
|
||||
{
|
||||
QtDCOffsetHelper helper( m_qtPainter );
|
||||
|
||||
m_qtPainter->drawPoint(x, y);
|
||||
}
|
||||
|
||||
void wxQtDCImpl::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
|
||||
{
|
||||
QtDCOffsetHelper helper( m_qtPainter );
|
||||
|
||||
m_qtPainter->drawLine(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
|
|
@ -578,8 +631,7 @@ void wxQtDCImpl::DoDrawArc(wxCoord x1, wxCoord y1,
|
|||
QLineF l2( xc, yc, x2, y2 );
|
||||
QPointF center( xc, yc );
|
||||
|
||||
qreal penWidth = m_qtPainter->pen().width();
|
||||
qreal lenRadius = l1.length() - penWidth / 2;
|
||||
qreal lenRadius = l1.length();
|
||||
QPointF centerToCorner( lenRadius, lenRadius );
|
||||
|
||||
QRect rectangle = QRectF( center - centerToCorner, center + centerToCorner ).toRect();
|
||||
|
|
@ -587,46 +639,64 @@ void wxQtDCImpl::DoDrawArc(wxCoord x1, wxCoord y1,
|
|||
// Calculate the angles
|
||||
int startAngle = (int)(l1.angle() * 16);
|
||||
int endAngle = (int)(l2.angle() * 16);
|
||||
|
||||
while(endAngle < startAngle)
|
||||
endAngle += 360 * 16;
|
||||
|
||||
int spanAngle = endAngle - startAngle;
|
||||
if ( spanAngle < 0 )
|
||||
{
|
||||
spanAngle = -spanAngle;
|
||||
}
|
||||
|
||||
QtDCOffsetHelper helper( m_qtPainter );
|
||||
|
||||
if ( spanAngle == 0 )
|
||||
m_qtPainter->drawEllipse( rectangle );
|
||||
else
|
||||
else if (m_qtPainter->brush().style() != Qt::NoBrush)
|
||||
m_qtPainter->drawPie( rectangle, startAngle, spanAngle );
|
||||
else
|
||||
m_qtPainter->drawArc( 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;
|
||||
int startAngle = (int)( sa * 16 );
|
||||
int endAngle = (int)( ea * 16 );
|
||||
|
||||
double spanAngle = sa - ea;
|
||||
if (spanAngle < -180)
|
||||
spanAngle += 360;
|
||||
if (spanAngle > 180)
|
||||
spanAngle -= 360;
|
||||
while(endAngle < startAngle)
|
||||
endAngle += 360 * 16;
|
||||
|
||||
int spanAngle = endAngle - startAngle;
|
||||
|
||||
QRect rectangle(x, y, w, h);
|
||||
|
||||
QtDCOffsetHelper helper( m_qtPainter );
|
||||
|
||||
if (spanAngle == 0)
|
||||
m_qtPainter->drawEllipse( x, y, w, h );
|
||||
{
|
||||
m_qtPainter->drawEllipse( rectangle );
|
||||
}
|
||||
else
|
||||
m_qtPainter->drawPie( x, y, w, h, (int)( sa * 16 ), (int)( ( ea - sa ) * 16 ) );
|
||||
{
|
||||
if (m_qtPainter->brush().style() != Qt::NoBrush)
|
||||
{
|
||||
QPen savedPen = m_qtPainter->pen();
|
||||
m_qtPainter->setPen( QPen( Qt::NoPen ) );
|
||||
m_qtPainter->drawPie( rectangle, startAngle, spanAngle );
|
||||
m_qtPainter->setPen( savedPen );
|
||||
}
|
||||
|
||||
m_qtPainter->drawArc( rectangle, startAngle, spanAngle );
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (m_qtPainter->pen().style() != Qt::NoPen)
|
||||
{
|
||||
width -= 1;
|
||||
height -= 1;
|
||||
}
|
||||
|
||||
QtDCOffsetHelper helper( m_qtPainter );
|
||||
|
||||
m_qtPainter->drawRect( x, y, width, height );
|
||||
}
|
||||
|
|
@ -635,11 +705,13 @@ 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;
|
||||
if (m_qtPainter->pen().style() != Qt::NoPen)
|
||||
{
|
||||
width -= 1;
|
||||
height -= 1;
|
||||
}
|
||||
|
||||
QtDCOffsetHelper helper( m_qtPainter );
|
||||
|
||||
m_qtPainter->drawRoundedRect( x, y, width, height, radius, radius );
|
||||
}
|
||||
|
|
@ -647,11 +719,7 @@ void wxQtDCImpl::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
|
|||
void wxQtDCImpl::DoDrawEllipse(wxCoord x, wxCoord y,
|
||||
wxCoord width, wxCoord height)
|
||||
{
|
||||
const int penWidth = m_qtPainter->pen().width();
|
||||
x += penWidth / 2;
|
||||
y += penWidth / 2;
|
||||
width -= penWidth;
|
||||
height -= penWidth;
|
||||
QtDCOffsetHelper helper( m_qtPainter );
|
||||
|
||||
m_qtPainter->drawEllipse( x, y, width, height );
|
||||
}
|
||||
|
|
@ -667,6 +735,8 @@ void wxQtDCImpl::DoCrossHair(wxCoord x, wxCoord y)
|
|||
inv.map( w, h, &right, &bottom );
|
||||
inv.map( 0, 0, &left, &top );
|
||||
|
||||
QtDCOffsetHelper helper( m_qtPainter );
|
||||
|
||||
m_qtPainter->drawLine( left, y, right, y );
|
||||
m_qtPainter->drawLine( x, top, x, bottom );
|
||||
}
|
||||
|
|
@ -838,12 +908,16 @@ void wxQtDCImpl::DoDrawLines(int n, const wxPoint points[],
|
|||
path.lineTo(wxQtConvertPoint(points[i]));
|
||||
}
|
||||
|
||||
{
|
||||
QtDCOffsetHelper helper(m_qtPainter);
|
||||
|
||||
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();
|
||||
|
|
@ -854,15 +928,20 @@ void wxQtDCImpl::DoDrawPolygon(int n, const wxPoint points[],
|
|||
wxCoord xoffset, wxCoord yoffset,
|
||||
wxPolygonFillMode fillStyle )
|
||||
{
|
||||
Qt::FillRule fill = (fillStyle == wxWINDING_RULE) ? Qt::WindingFill : Qt::OddEvenFill;
|
||||
|
||||
QPolygon qtPoints;
|
||||
for (int i = 0; i < n; i++) {
|
||||
qtPoints << wxQtConvertPoint(points[i]);
|
||||
}
|
||||
|
||||
Qt::FillRule fill = (fillStyle == wxWINDING_RULE) ? Qt::WindingFill : Qt::OddEvenFill;
|
||||
{
|
||||
QtDCOffsetHelper helper(m_qtPainter);
|
||||
|
||||
m_qtPainter->translate(xoffset, yoffset);
|
||||
m_qtPainter->drawPolygon(qtPoints, fill);
|
||||
}
|
||||
|
||||
// Reset transform
|
||||
ComputeScaleAndOrigin();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,12 @@ void wxMemoryDCImpl::DoSelect( const wxBitmap& bitmap )
|
|||
// start drawing on the intermediary device:
|
||||
m_ok = m_qtPainter->begin( m_qtPixmap );
|
||||
|
||||
if (m_qtPainter->device()->depth() > 1)
|
||||
{
|
||||
m_qtPainter->setRenderHints(QPainter::Antialiasing,
|
||||
true);
|
||||
}
|
||||
|
||||
SetPen(m_pen);
|
||||
SetBrush(m_brush);
|
||||
SetFont(m_font);
|
||||
|
|
|
|||
|
|
@ -1385,6 +1385,12 @@ bool wxWindowQt::QtHandlePaintEvent ( QWidget *handler, QPaintEvent *event )
|
|||
// itself otherwise.
|
||||
const bool ok = m_qtPainter->begin( widget );
|
||||
|
||||
if (m_qtPainter->device()->depth() > 1)
|
||||
{
|
||||
m_qtPainter->setRenderHints(QPainter::Antialiasing,
|
||||
true);
|
||||
}
|
||||
|
||||
if ( ok )
|
||||
{
|
||||
bool handled;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue