Commit 71e2e229 authored by Lukáš Tvrdý's avatar Lukáš Tvrdý

Implement support for drawing the QPainterPath.

We have already support for filling QPainterPath.

Now we can paint nicer anti-aliased lines with various styles and cap styles:
e.g. see http://doc.trolltech.com/latest/qpen.html#pen-style

Drawback: it is much slower compared to drawThickLine

svn path=/trunk/koffice/; revision=1150131
parent d1306b8d
......@@ -19,6 +19,7 @@
#include <qtest_kde.h>
#include <QImage>
#include <QDebug>
#include "kis_painter_benchmark.h"
#include "kis_benchmark_values.h"
......@@ -41,6 +42,7 @@
#define CYCLES 20
static const int LINE_COUNT = 100;
void KisPainterBenchmark::initTestCase()
{
......@@ -48,6 +50,13 @@ void KisPainterBenchmark::initTestCase()
m_color = KoColor(m_colorSpace);
m_color.fromQColor(Qt::red);
srand48(0);
for (int i = 0; i < LINE_COUNT ;i++){
m_points.append( QPointF(drand48() * TEST_IMAGE_WIDTH, drand48() * TEST_IMAGE_HEIGHT) );
m_points.append( QPointF(drand48() * TEST_IMAGE_WIDTH, drand48() * TEST_IMAGE_HEIGHT) );
}
}
void KisPainterBenchmark::cleanupTestCase()
......@@ -172,6 +181,59 @@ void KisPainterBenchmark::benchmarkFixedBitBltSelection()
}
void KisPainterBenchmark::benchmarkDrawThickLine()
{
KisPaintDeviceSP dev = new KisPaintDevice(m_colorSpace);
KoColor color(m_colorSpace);
color.fromQColor(Qt::white);
dev->clear();
dev->fill(0,0,TEST_IMAGE_WIDTH,TEST_IMAGE_HEIGHT,color.data());
color.fromQColor(Qt::black);
KisPainter painter(dev);
painter.setPaintColor(color);
QBENCHMARK{
for (int i = 0; i < LINE_COUNT; i++){
painter.drawThickLine(m_points[i*2],m_points[i*2+1],10,10);
}
}
//dev->convertToQImage(m_colorSpace->profile()).save("drawThickLine.png");
}
void KisPainterBenchmark::benchmarkDrawQtLine()
{
KisPaintDeviceSP dev = new KisPaintDevice(m_colorSpace);
KoColor color(m_colorSpace);
color.fromQColor(Qt::white);
dev->clear();
dev->fill(0,0,TEST_IMAGE_WIDTH,TEST_IMAGE_HEIGHT,color.data());
color.fromQColor(Qt::black);
KisPainter painter(dev);
painter.setPaintColor(color);
painter.setFillStyle(KisPainter::FillStyleForegroundColor);
QPen pen;
pen.setWidth(10);
pen.setColor(Qt::white);
pen.setCapStyle(Qt::RoundCap);
QBENCHMARK{
for (int i = 0; i < LINE_COUNT; i++){
QPainterPath path;
path.moveTo(m_points[i*2]);
path.lineTo(m_points[i*2 + 1]);
painter.drawPainterPath(path, pen);
}
}
//dev->convertToQImage(m_colorSpace->profile(),0,0,TEST_IMAGE_WIDTH,TEST_IMAGE_HEIGHT).save("drawQtLine.png");
}
QTEST_KDEMAIN(KisPainterBenchmark, NoGUI)
......
......@@ -35,6 +35,7 @@ class KisPainterBenchmark : public QObject
private:
const KoColorSpace * m_colorSpace;
KoColor m_color;
QVector<QPointF> m_points;
private slots:
void initTestCase();
......@@ -45,7 +46,9 @@ private slots:
void benchmarkBitBltSelection();
void benchmarkFixedBitBlt();
void benchmarkFixedBitBltSelection();
void benchmarkDrawThickLine();
void benchmarkDrawQtLine();
};
......
......@@ -965,6 +965,89 @@ void KisPainter::fillPainterPath(const QPainterPath& path)
bitBlt(r.x(), r.y(), d->polygon, r.x(), r.y(), r.width(), r.height());
}
void KisPainter::drawPainterPath(const QPainterPath& path, const QPen& pen)
{
// we are drawing mask, it has to be white
// color of the path is given by paintColor()
Q_ASSERT(pen.color() == Qt::white);
if (!d->fillPainter) {
d->polygon = new KisPaintDevice(d->device->colorSpace());
d->fillPainter = new KisFillPainter(d->polygon);
} else {
d->polygon->clear();
}
Q_CHECK_PTR(d->polygon);
QRectF boundingRect = path.boundingRect();
QRect fillRect;
fillRect.setLeft((qint32)floor(boundingRect.left()));
fillRect.setRight((qint32)ceil(boundingRect.right()));
fillRect.setTop((qint32)floor(boundingRect.top()));
fillRect.setBottom((qint32)ceil(boundingRect.bottom()));
// take width of the pen into account
int penWidth = qRound(pen.widthF());
fillRect.adjust(-penWidth, -penWidth, penWidth, penWidth);
// Expand the rectangle to allow for anti-aliasing.
fillRect.adjust(-1, -1, 1, 1);
// Clip to the image bounds.
if (d->bounds.isValid()) {
fillRect &= d->bounds;
}
d->fillPainter->fillRect(fillRect, paintColor(), OPACITY_OPAQUE_U8);
if (d->polygonMaskImage.isNull() || (d->maskPainter == 0)) {
d->polygonMaskImage = QImage(d->maskImageWidth, d->maskImageHeight, QImage::Format_ARGB32_Premultiplied);
d->maskPainter = new QPainter(&d->polygonMaskImage);
d->maskPainter->setRenderHint(QPainter::Antialiasing, antiAliasPolygonFill());
}
// Break the mask up into chunks so we don't have to allocate a potentially very large QImage.
const QColor black(Qt::black);
QPen oldPen = d->maskPainter->pen();
d->maskPainter->setPen(pen);
for (qint32 x = fillRect.x(); x < fillRect.x() + fillRect.width(); x += d->maskImageWidth) {
for (qint32 y = fillRect.y(); y < fillRect.y() + fillRect.height(); y += d->maskImageHeight) {
d->polygonMaskImage.fill(black.rgb());
d->maskPainter->translate(-x, -y);
d->maskPainter->drawPath(path);
d->maskPainter->translate(x, y);
qint32 rectWidth = qMin(fillRect.x() + fillRect.width() - x, d->maskImageWidth);
qint32 rectHeight = qMin(fillRect.y() + fillRect.height() - y, d->maskImageHeight);
KisHLineIterator lineIt = d->polygon->createHLineIterator(x, y, rectWidth);
quint8 tmp;
for (int row = y; row < y + rectHeight; row++) {
QRgb* line = reinterpret_cast<QRgb*>(d->polygonMaskImage.scanLine(row - y));
while (!lineIt.isDone()) {
tmp = qRed(line[lineIt.x() - x]);
d->polygon->colorSpace()->applyAlphaU8Mask(lineIt.rawData(),
&tmp, 1);
++lineIt;
}
lineIt.nextRow();
}
}
}
d->maskPainter->setPen(oldPen);
QRect r = d->polygon->extent();
bitBlt(r.x(), r.y(), d->polygon, r.x(), r.y(), r.width(), r.height());
}
void KisPainter::drawLine(const QPointF & start, const QPointF & end)
{
drawThickLine(start, end, 1, 1);
......
......@@ -29,6 +29,7 @@
#include "kis_types.h"
#include <krita_export.h>
class QPen;
class QRegion;
class QUndoCommand;
class QRect;
......@@ -311,6 +312,11 @@ public:
*/
void fillPainterPath(const QPainterPath& path);
/**
* Draw the path using the Pen
*/
void drawPainterPath(const QPainterPath& path, const QPen& pen);
/**
* paint an unstroked one-pixel wide line from specified start position to the
* specified end position.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment