[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [calligra] krita: assistants: Cache rendering
From: Geoffry Song <goffrie () gmail ! com>
Date: 2011-12-07 3:23:34
Message-ID: 20111207032334.084E3A60A9 () git ! kde ! org
[Download RAW message or body]
Git commit eb82fab9a76582b318902667665df3d8c61a95b6 by Geoffry Song.
Committed on 07/12/2011 at 04:15.
Pushed by geoffrysong into branch 'master'.
assistants: Cache rendering
This significantly improves performance using the QPainter backend,
as KisPaintingAssistant::drawPath is very expensive.
This also adds some caching to PerspectiveAssistant.
CCBUG: 280086
M +21 -0 krita/plugins/assistants/RulerAssistant/Ellipse.cc
M +1 -0 krita/plugins/assistants/RulerAssistant/Ellipse.h
M +11 -6 krita/plugins/assistants/RulerAssistant/EllipseAssistant.cc
M +3 -1 krita/plugins/assistants/RulerAssistant/EllipseAssistant.h
M +59 -32 krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.cc
M +11 -1 krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.h
M +2 -5 krita/plugins/assistants/RulerAssistant/RulerAssistant.cc
M +2 -1 krita/plugins/assistants/RulerAssistant/RulerAssistant.h
M +1 -5 krita/plugins/assistants/RulerAssistant/SplineAssistant.cc
M +2 -1 krita/plugins/assistants/RulerAssistant/SplineAssistant.h
M +4 -1 krita/plugins/assistants/RulerAssistant/kis_ruler_assistant_tool.cc
M +73 -0 krita/ui/kis_painting_assistant.cc
M +6 -1 krita/ui/kis_painting_assistant.h
M +0 -2 krita/ui/kis_painting_assistants_manager.cc
http://commits.kde.org/calligra/eb82fab9a76582b318902667665df3d8c61a95b6
diff --git a/krita/plugins/assistants/RulerAssistant/Ellipse.cc \
b/krita/plugins/assistants/RulerAssistant/Ellipse.cc index 5bc7517..5042dbf 100644
--- a/krita/plugins/assistants/RulerAssistant/Ellipse.cc
+++ b/krita/plugins/assistants/RulerAssistant/Ellipse.cc
@@ -66,6 +66,27 @@ QPointF Ellipse::project(const QPointF& pt) const
/* return inverse.map(closest(matrix.map(pt)));*/
}
+inline QPointF rotate90(const QPointF& p) {
+ return QPointF(p.y(), -p.x());
+}
+
+QRectF Ellipse::boundingRect() const
+{
+ const QPointF centre = (p1 + p2) * 0.5;
+ const QPointF d = rotate90((p2 - p1) * 0.5 * b / a);
+ const QPointF pts[4] = {
+ p1 + d,
+ p1 - d,
+ p2 + d,
+ p2 - d
+ };
+ QRectF ret;
+ for (int i = 0; i < 4; ++i) {
+ ret = ret.united(QRectF(pts[i], QSizeF(0.0001, 0.0001)));
+ }
+ return ret;
+}
+
inline qreal sqrlength(const QPointF& vec)
{
return vec.x() * vec.x() + vec.y() * vec.y();
diff --git a/krita/plugins/assistants/RulerAssistant/Ellipse.h \
b/krita/plugins/assistants/RulerAssistant/Ellipse.h index 95142cb..b64e6bc 100644
--- a/krita/plugins/assistants/RulerAssistant/Ellipse.h
+++ b/krita/plugins/assistants/RulerAssistant/Ellipse.h
@@ -29,6 +29,7 @@ public:
~Ellipse();
QPointF project(const QPointF&) const; // find a close point on the ellipse
+ QRectF boundingRect() const; // find an axis-aligned box bounding this ellipse \
(inexact)
bool set(const QPointF& m1, const QPointF& m2, const QPointF& p); // set all \
points
diff --git a/krita/plugins/assistants/RulerAssistant/EllipseAssistant.cc \
b/krita/plugins/assistants/RulerAssistant/EllipseAssistant.cc index 7c88f41..45851f1 \
100644
--- a/krita/plugins/assistants/RulerAssistant/EllipseAssistant.cc
+++ b/krita/plugins/assistants/RulerAssistant/EllipseAssistant.cc
@@ -46,26 +46,22 @@ QPointF EllipseAssistant::adjustPosition(const QPointF& pt, const \
QPointF& /*str return project(pt);
}
-void EllipseAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const \
KisCoordinatesConverter *converter) +void EllipseAssistant::drawCache(QPainter& gc, \
const KisCoordinatesConverter *converter) {
- Q_UNUSED(updateRect);
if (handles().size() < 2) return;
QTransform initialTransform = converter->documentToWidgetTransform();
if (handles().size() == 2) {
// just draw the axis
- gc.save();
gc.setTransform(initialTransform);
QPainterPath path;
path.moveTo(*handles()[0]);
path.lineTo(*handles()[1]);
drawPath(gc, path);
- gc.restore();
return;
}
if (e.set(*handles()[0], *handles()[1], *handles()[2])) {
// valid ellipse
- gc.save();
gc.setTransform(initialTransform);
gc.setTransform(e.getInverse(), true);
QPainterPath path;
@@ -74,7 +70,16 @@ void EllipseAssistant::drawAssistant(QPainter& gc, const QRectF& \
updateRect, con // Draw the ellipse
path.addEllipse(QPointF(0, 0), e.semiMajor(), e.semiMinor());
drawPath(gc, path);
- gc.restore();
+ }
+}
+
+QRect EllipseAssistant::boundingRect() const
+{
+ if (handles().size() != 3) return KisPaintingAssistant::boundingRect();
+ if (e.set(*handles()[0], *handles()[1], *handles()[2])) {
+ return e.boundingRect().adjusted(-2, -2, 2, 2).toAlignedRect();
+ } else {
+ return QRect();
}
}
diff --git a/krita/plugins/assistants/RulerAssistant/EllipseAssistant.h \
b/krita/plugins/assistants/RulerAssistant/EllipseAssistant.h index 3e55788..f6fd83b \
100644
--- a/krita/plugins/assistants/RulerAssistant/EllipseAssistant.h
+++ b/krita/plugins/assistants/RulerAssistant/EllipseAssistant.h
@@ -28,9 +28,11 @@ class EllipseAssistant : public KisPaintingAssistant
public:
EllipseAssistant();
virtual QPointF adjustPosition(const QPointF& point, const QPointF& \
strokeBegin);
- void drawAssistant(QPainter& gc, const QRectF& updateRect, const \
KisCoordinatesConverter *converter); virtual QPointF buttonPosition() const;
virtual int numHandles() const { return 3; }
+protected:
+ virtual QRect boundingRect() const;
+ virtual void drawCache(QPainter& gc, const KisCoordinatesConverter *converter);
private:
QPointF project(const QPointF& pt) const;
mutable Ellipse e;
diff --git a/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.cc \
b/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.cc index \
36eef16..bd313a7 100644
--- a/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.cc
+++ b/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.cc
@@ -52,7 +52,8 @@ QPointF PerspectiveAssistant::project(const QPointF& pt, const \
QPointF& strokeBe Q_ASSERT(handles().size() == 4);
if (snapLine.isNull()) {
QPolygonF poly;
- if (!quad(poly)) return nullPoint;
+ QTransform transform;
+ if (!getTransform(poly, transform)) return nullPoint;
// avoid problems with multiple assistants: only snap if starting in the \
grid
if (!poly.containsPoint(strokeBegin, Qt::OddEvenFill)) return nullPoint;
@@ -65,8 +66,6 @@ QPointF PerspectiveAssistant::project(const QPointF& pt, const \
QPointF& strokeBe }
// construct transformation
- QTransform transform;
- if (!QTransform::squareToQuad(poly, transform)) return nullPoint; // \
shouldn't happen bool invertible;
const QTransform inverse = transform.inverted(&invertible);
if (!invertible) return nullPoint; // shouldn't happen
@@ -152,9 +151,8 @@ inline qreal inverseMaxLocalScale(const QTransform& transform)
qreal PerspectiveAssistant::distance(const QPointF& pt) const
{
QPolygonF poly;
- if (!quad(poly)) return 1.0;
QTransform transform;
- if (!QTransform::squareToQuad(poly, transform)) return 1.0;
+ if (!getTransform(poly, transform)) return 1.0;
bool invertible;
QTransform inverse = transform.inverted(&invertible);
if (!invertible) return 1.0;
@@ -166,24 +164,41 @@ qreal PerspectiveAssistant::distance(const QPointF& pt) const
}
// draw a vanishing point marker
-inline QPainterPath drawX(QPainter& gc, const QPointF& pt)
+inline QPainterPath drawX(const QPointF& pt)
{
- Q_UNUSED(gc);
QPainterPath path;
path.moveTo(QPointF(pt.x() - 5.0, pt.y() - 5.0)); path.lineTo(QPointF(pt.x() + \
5.0, pt.y() + 5.0));
path.moveTo(QPointF(pt.x() - 5.0, pt.y() + 5.0)); path.lineTo(QPointF(pt.x() + \
5.0, pt.y() - 5.0)); return path;
}
-void PerspectiveAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, \
const KisCoordinatesConverter *converter) +void \
PerspectiveAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const \
KisCoordinatesConverter* converter, bool cached) {
- Q_UNUSED(updateRect);
-
+ gc.save();
+ gc.resetTransform();
QTransform initialTransform = converter->documentToWidgetTransform();
QPolygonF poly;
- gc.save();
- gc.setTransform(initialTransform);
- if (!quad(poly)) {
+ QTransform transform; // unused, but computed for caching purposes
+ if (getTransform(poly, transform)) {
+ // draw vanishing points
+ QPointF intersection(0, 0);
+ if (QLineF(poly[0], poly[1]).intersect(QLineF(poly[2], poly[3]), \
&intersection) != QLineF::NoIntersection) { + drawPath(gc, \
drawX(initialTransform.map(intersection))); + }
+ if (QLineF(poly[1], poly[2]).intersect(QLineF(poly[3], poly[0]), \
&intersection) != QLineF::NoIntersection) { + drawPath(gc, \
drawX(initialTransform.map(intersection))); + }
+ }
+ gc.restore();
+ KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached);
+}
+
+void PerspectiveAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter \
*converter) +{
+ gc.setTransform(converter->documentToWidgetTransform());
+ QPolygonF poly;
+ QTransform transform;
+ if (!getTransform(poly, transform)) {
// color red for an invalid transform, but not for an incomplete one
if(handles().size() == 4)
{
@@ -194,17 +209,8 @@ void PerspectiveAssistant::drawAssistant(QPainter& gc, const \
QRectF& updateRect, path.addPolygon(poly);
drawPath(gc, path);
}
- gc.restore();
} else {
gc.setPen(QColor(0, 0, 0, 125));
-
- QTransform transform;
- if (!QTransform::squareToQuad(poly, transform)) {
- qWarning("Failed to create perspective mapping");
- // bail out
- gc.restore();
- return;
- }
gc.setTransform(transform, true);
QPainterPath path;
for (int y = 0; y <= 8; ++y)
@@ -218,16 +224,6 @@ void PerspectiveAssistant::drawAssistant(QPainter& gc, const \
QRectF& updateRect, path.lineTo(QPointF(x * 0.125, 1.0));
}
drawPath(gc, path);
- gc.restore();
-
- // draw vanishing points
- QPointF intersection(0, 0);
- if (QLineF(poly[0], poly[1]).intersect(QLineF(poly[2], poly[3]), \
&intersection) != QLineF::NoIntersection) {
- drawPath(gc, drawX(gc, initialTransform.map(intersection)));
- }
- if (QLineF(poly[1], poly[2]).intersect(QLineF(poly[3], poly[0]), \
&intersection) != QLineF::NoIntersection) {
- drawPath(gc, drawX(gc, initialTransform.map(intersection)));
- }
}
}
@@ -294,6 +290,37 @@ bool PerspectiveAssistant::quad(QPolygonF& poly) const
return true;
}
+bool PerspectiveAssistant::getTransform(QPolygonF& poly, QTransform& transform) \
const +{
+ if (cachedPolygon.size() != 0 && handles().size() == 4) {
+ for (int i = 0; i <= 4; ++i) {
+ if (i == 4) {
+ poly = cachedPolygon;
+ transform = cachedTransform;
+ return cacheValid;
+ }
+ if (cachedPoints[i] != *handles()[i]) break;
+ }
+ }
+ cachedPolygon.clear();
+ cacheValid = false;
+ if (!quad(poly)) {
+ cachedPolygon = poly;
+ return false;
+ }
+ if (!QTransform::squareToQuad(poly, transform)) {
+ qWarning("Failed to create perspective mapping");
+ return false;
+ }
+ for (int i = 0; i < 4; ++i) {
+ cachedPoints[i] = *handles()[i];
+ }
+ cachedPolygon = poly;
+ cachedTransform = transform;
+ cacheValid = true;
+ return true;
+}
+
PerspectiveAssistantFactory::PerspectiveAssistantFactory()
{
}
diff --git a/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.h \
b/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.h index \
19fea0e..c064d0b 100644
--- a/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.h
+++ b/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.h
@@ -24,6 +24,7 @@
#include <QObject>
#include <QPolygonF>
#include <QLineF>
+#include <QTransform>
class PerspectiveAssistant : public KisPaintingAssistant, public \
KisAbstractPerspectiveGrid {
@@ -31,19 +32,28 @@ public:
PerspectiveAssistant();
virtual QPointF adjustPosition(const QPointF& point, const QPointF& \
strokeBegin); virtual void endStroke();
- void drawAssistant(QPainter& gc, const QRectF& updateRect, const \
KisCoordinatesConverter *converter); virtual QPointF buttonPosition() const;
virtual int numHandles() const { return 4; }
+ virtual void drawAssistant(QPainter& gc, const QRectF& updateRect, const \
KisCoordinatesConverter* converter, bool cached = true);
virtual bool contains(const QPointF& point) const;
virtual qreal distance(const QPointF& point) const;
+protected:
+ virtual void drawCache(QPainter& gc, const KisCoordinatesConverter *converter);
private:
QPointF project(const QPointF& pt, const QPointF& strokeBegin);
// creates the convex hull, returns false if it's not a quadrilateral
bool quad(QPolygonF& out) const;
+ // finds the transform from perspective coordinates (a unit square) to the \
document + bool getTransform(QPolygonF& polyOut, QTransform& transformOut) const;
// which direction to snap to (in transformed coordinates)
QLineF snapLine;
+ // cached information
+ mutable QTransform cachedTransform;
+ mutable QPolygonF cachedPolygon;
+ mutable QPointF cachedPoints[4];
+ mutable bool cacheValid;
};
class PerspectiveAssistantFactory : public KisPaintingAssistantFactory
diff --git a/krita/plugins/assistants/RulerAssistant/RulerAssistant.cc \
b/krita/plugins/assistants/RulerAssistant/RulerAssistant.cc index 7cf6e25..4357a2b \
100644
--- a/krita/plugins/assistants/RulerAssistant/RulerAssistant.cc
+++ b/krita/plugins/assistants/RulerAssistant/RulerAssistant.cc
@@ -72,24 +72,21 @@ inline double norm2(const QPointF& p)
return sqrt(p.x() * p.x() + p.y() * p.y());
}
-void RulerAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const \
KisCoordinatesConverter *converter) +void RulerAssistant::drawCache(QPainter& gc, \
const KisCoordinatesConverter *converter) {
- Q_UNUSED(updateRect);
if (handles().size() < 2) return;
QTransform initialTransform = converter->documentToWidgetTransform();
- // Draw the gradient
+ // Draw the line
QPointF p1 = *handles()[0];
QPointF p2 = *handles()[1];
- gc.save();
gc.setTransform(initialTransform);
QPainterPath path;
path.moveTo(p1);
path.lineTo(p2);
drawPath(gc, path);
- gc.restore();
}
QPointF RulerAssistant::buttonPosition() const
diff --git a/krita/plugins/assistants/RulerAssistant/RulerAssistant.h \
b/krita/plugins/assistants/RulerAssistant/RulerAssistant.h index b5ce3b2..2dd0307 \
100644
--- a/krita/plugins/assistants/RulerAssistant/RulerAssistant.h
+++ b/krita/plugins/assistants/RulerAssistant/RulerAssistant.h
@@ -27,9 +27,10 @@ class RulerAssistant : public KisPaintingAssistant
public:
RulerAssistant();
virtual QPointF adjustPosition(const QPointF& point, const QPointF& \
strokeBegin);
- void drawAssistant(QPainter& gc, const QRectF& updateRect, const \
KisCoordinatesConverter *converter); virtual QPointF buttonPosition() const;
virtual int numHandles() const { return 2; }
+protected:
+ virtual void drawCache(QPainter& gc, const KisCoordinatesConverter *converter);
private:
QPointF project(const QPointF& pt) const;
};
diff --git a/krita/plugins/assistants/RulerAssistant/SplineAssistant.cc \
b/krita/plugins/assistants/RulerAssistant/SplineAssistant.cc index fee1f1d..7a1a2bb \
100644
--- a/krita/plugins/assistants/RulerAssistant/SplineAssistant.cc
+++ b/krita/plugins/assistants/RulerAssistant/SplineAssistant.cc
@@ -87,9 +87,8 @@ QPointF SplineAssistant::adjustPosition(const QPointF& pt, const \
QPointF& /*stro return project(pt);
}
-void SplineAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const \
KisCoordinatesConverter *converter) +void SplineAssistant::drawCache(QPainter& gc, \
const KisCoordinatesConverter *converter) {
- Q_UNUSED(updateRect);
if (handles().size() < 2) return;
QTransform initialTransform = converter->documentToWidgetTransform();
@@ -100,7 +99,6 @@ void SplineAssistant::drawAssistant(QPainter& gc, const QRectF& \
updateRect, cons pts[2] = (handles().size() >= 3) ? (*handles()[2]) : \
(*handles()[0]);
pts[3] = (handles().size() >= 4) ? (*handles()[3]) : (handles().size() >= 3) ? \
(*handles()[2]) : (*handles()[1]);
- gc.save();
gc.setTransform(initialTransform);
gc.setPen(QColor(0, 0, 0, 75));
// Draw control lines
@@ -112,8 +110,6 @@ void SplineAssistant::drawAssistant(QPainter& gc, const QRectF& \
updateRect, cons path.moveTo(pts[0]);
path.cubicTo(pts[2], pts[3], pts[1]);
drawPath(gc, path);
-
- gc.restore();
}
QPointF SplineAssistant::buttonPosition() const
diff --git a/krita/plugins/assistants/RulerAssistant/SplineAssistant.h \
b/krita/plugins/assistants/RulerAssistant/SplineAssistant.h index 8ed81f4..76fdfe4 \
100644
--- a/krita/plugins/assistants/RulerAssistant/SplineAssistant.h
+++ b/krita/plugins/assistants/RulerAssistant/SplineAssistant.h
@@ -27,9 +27,10 @@ class SplineAssistant : public KisPaintingAssistant
public:
SplineAssistant();
virtual QPointF adjustPosition(const QPointF& point, const QPointF& \
strokeBegin);
- void drawAssistant(QPainter& gc, const QRectF& updateRect, const \
KisCoordinatesConverter *converter); virtual QPointF buttonPosition() const;
virtual int numHandles() const { return 4; }
+protected:
+ virtual void drawCache(QPainter& gc, const KisCoordinatesConverter *converter);
private:
QPointF project(const QPointF& pt) const;
};
diff --git a/krita/plugins/assistants/RulerAssistant/kis_ruler_assistant_tool.cc \
b/krita/plugins/assistants/RulerAssistant/kis_ruler_assistant_tool.cc index \
d450a84..b2f9d31 100644
--- a/krita/plugins/assistants/RulerAssistant/kis_ruler_assistant_tool.cc
+++ b/krita/plugins/assistants/RulerAssistant/kis_ruler_assistant_tool.cc
@@ -114,6 +114,7 @@ void KisRulerAssistantTool::mousePressEvent(KoPointerEvent \
*event) }
if (m_handleDrag) {
if (event->modifiers() & Qt::ShiftModifier) {
+ m_handleDrag->uncache();
m_handleDrag = m_handleDrag->split()[0];
m_handles = m_canvas->view()->paintingAssistantManager()->handles();
}
@@ -187,6 +188,7 @@ void KisRulerAssistantTool::mouseMoveEvent(KoPointerEvent *event)
} else if(MOVE_CONDITION(event, KisTool::PAINT_MODE)) {
if (m_handleDrag) {
*m_handleDrag = event->point;
+ m_handleDrag->uncache();
m_handleCombine = 0;
if (!(event->modifiers() & Qt::ShiftModifier)) {
@@ -227,6 +229,7 @@ void KisRulerAssistantTool::mouseReleaseEvent(KoPointerEvent \
*event) if (m_handleDrag) {
if (!(event->modifiers() & Qt::ShiftModifier) && m_handleCombine) {
m_handleCombine->mergeWith(m_handleDrag);
+ m_handleCombine->uncache();
m_handles = m_canvas->view()->paintingAssistantManager()->handles();
}
m_handleDrag = m_handleCombine = 0;
@@ -248,7 +251,7 @@ void KisRulerAssistantTool::paint(QPainter& _gc, const \
KoViewConverter &_convert QColor handlesColor(0, 0, 0, 125);
if (m_newAssistant) {
- m_newAssistant->drawAssistant(_gc, QRectF(QPointF(0, 0), \
QSizeF(m_canvas->image()->size())), m_canvas->coordinatesConverter()); + \
m_newAssistant->drawAssistant(_gc, QRectF(QPointF(0, 0), \
QSizeF(m_canvas->image()->size())), m_canvas->coordinatesConverter(), \
false);
foreach(const KisPaintingAssistantHandleSP handle, \
m_newAssistant->handles()) { QPainterPath path;
path.addEllipse(QRectF(_converter.documentToView(*handle) - QPointF(6, \
6), QSizeF(12, 12)));
diff --git a/krita/ui/kis_painting_assistant.cc b/krita/ui/kis_painting_assistant.cc
index db46c4c..a42beb9 100644
--- a/krita/ui/kis_painting_assistant.cc
+++ b/krita/ui/kis_painting_assistant.cc
@@ -18,11 +18,13 @@
*/
#include "kis_painting_assistant.h"
+#include "kis_coordinates_converter.h"
#include "kis_debug.h"
#include <kglobal.h>
#include <QPen>
#include <QPainter>
+#include <QPixmapCache>
struct KisPaintingAssistantHandle::Private {
QList<KisPaintingAssistant*> assistants;
@@ -92,11 +94,28 @@ QList<KisPaintingAssistantHandleSP> \
KisPaintingAssistantHandle::split() return newHandles;
}
+void KisPaintingAssistantHandle::uncache()
+{
+ foreach(KisPaintingAssistant* assistant, d->assistants) {
+ assistant->uncache();
+ }
+}
+
struct KisPaintingAssistant::Private {
QString id;
QString name;
QList<KisPaintingAssistantHandleSP> handles;
+ QPixmapCache::Key cached;
+ QRect cachedRect; // relative to boundingRect().topLeft()
+ struct TranslationInvariantTransform {
+ qreal m11, m12, m21, m22;
+ TranslationInvariantTransform() { }
+ TranslationInvariantTransform(const QTransform& t) : m11(t.m11()), \
m12(t.m12()), m21(t.m21()), m22(t.m22()) { } + bool operator==(const \
TranslationInvariantTransform& b) { + return m11 == b.m11 && m12 == b.m12 \
&& m21 == b.m21 && m22 == b.m22; + }
+ } cachedTransform;
};
KisPaintingAssistant::KisPaintingAssistant(const QString& id, const QString& name) : \
d(new Private) @@ -162,6 +181,60 @@ void \
KisPaintingAssistant::addHandle(KisPaintingAssistantHandleSP handle) \
handle->registerAssistant(this); }
+void KisPaintingAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, \
const KisCoordinatesConverter* converter, bool useCache) +{
+ Q_UNUSED(updateRect);
+
+ if (!useCache) {
+ gc.save();
+ drawCache(gc, converter);
+ gc.restore();
+ return;
+ }
+ const QRect bound = boundingRect();
+ if (bound.isEmpty()) return;
+ const QTransform transform = converter->documentToWidgetTransform();
+ const QRect widgetBound = transform.mapRect(bound);
+
+ const QRect paintRect = transform.mapRect(bound).intersected(gc.viewport());
+ if (paintRect.isEmpty()) return;
+
+ QPixmap cached;
+ if (!(QPixmapCache::find(d->cached, &cached) &&
+ d->cachedTransform == transform &&
+ d->cachedRect.translated(widgetBound.topLeft()).contains(paintRect))) {
+ const QRect cacheRect = gc.viewport().adjusted(-100, -100, 100, \
100).intersected(widgetBound); + Q_ASSERT(!cacheRect.isEmpty());
+ if (cached.isNull() || cached.size() != cacheRect.size()) {
+ cached = QPixmap(cacheRect.size());
+ }
+ cached.fill(Qt::transparent);
+ QPainter painter(&cached);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setWindow(cacheRect);
+ drawCache(painter, converter);
+ painter.end();
+ d->cachedTransform = transform;
+ d->cachedRect = cacheRect.translated(-widgetBound.topLeft());
+ d->cached = QPixmapCache::insert(cached);
+ }
+ gc.drawPixmap(paintRect, cached, paintRect.translated(-widgetBound.topLeft() - \
d->cachedRect.topLeft())); +}
+
+void KisPaintingAssistant::uncache()
+{
+ d->cached = QPixmapCache::Key();
+}
+
+QRect KisPaintingAssistant::boundingRect() const
+{
+ QRectF r;
+ foreach (KisPaintingAssistantHandleSP h, handles()) {
+ r = r.united(QRectF(*h, QSizeF(1,1)));
+ }
+ return r.adjusted(-2, -2, 2, 2).toAlignedRect();
+}
+
const QList<KisPaintingAssistantHandleSP>& KisPaintingAssistant::handles() const
{
return d->handles;
diff --git a/krita/ui/kis_painting_assistant.h b/krita/ui/kis_painting_assistant.h
index 16189bf..34757b4 100644
--- a/krita/ui/kis_painting_assistant.h
+++ b/krita/ui/kis_painting_assistant.h
@@ -21,6 +21,7 @@
#include <QString>
#include <QPointF>
+#include <QRect>
#include <krita_export.h>
#include <kis_shared.h>
@@ -52,6 +53,7 @@ public:
~KisPaintingAssistantHandle();
void mergeWith(KisPaintingAssistantHandleSP);
QList<KisPaintingAssistantHandleSP> split();
+ void uncache();
KisPaintingAssistantHandle& operator=(const QPointF&);
private:
void registerAssistant(KisPaintingAssistant*);
@@ -80,11 +82,12 @@ public:
*/
virtual QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) \
= 0; virtual void endStroke() { }
- virtual void drawAssistant(QPainter& gc, const QRectF& updateRect, const \
KisCoordinatesConverter *converter) = 0; virtual QPointF buttonPosition() const = 0;
virtual int numHandles() const = 0;
void replaceHandle(KisPaintingAssistantHandleSP _handle, \
KisPaintingAssistantHandleSP _with); void addHandle(KisPaintingAssistantHandleSP \
handle); + virtual void drawAssistant(QPainter& gc, const QRectF& updateRect, \
const KisCoordinatesConverter *converter, bool cached = true); + void uncache();
const QList<KisPaintingAssistantHandleSP>& handles() const;
QList<KisPaintingAssistantHandleSP> handles();
public:
@@ -93,6 +96,8 @@ public:
*/
static void drawPath(QPainter& painter, const QPainterPath& path);
protected:
+ virtual QRect boundingRect() const;
+ virtual void drawCache(QPainter& gc, const KisCoordinatesConverter *converter) = \
0; void initHandles(QList<KisPaintingAssistantHandleSP> _handles);
private:
struct Private;
diff --git a/krita/ui/kis_painting_assistants_manager.cc \
b/krita/ui/kis_painting_assistants_manager.cc index aaa3cad..7a59ae4 100644
--- a/krita/ui/kis_painting_assistants_manager.cc
+++ b/krita/ui/kis_painting_assistants_manager.cc
@@ -116,9 +116,7 @@ void KisPaintingAssistantsManager::setup(KActionCollection * \
collection) void KisPaintingAssistantsManager::drawDecoration(QPainter& gc, const \
QRectF& updateRect, const KisCoordinatesConverter *converter) {
foreach(KisPaintingAssistant* assistant, d->assistants) {
- gc.save();
assistant->drawAssistant(gc, updateRect, converter);
- gc.restore();
}
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic