[krita] /: Fix "openGL lag at zoom 2000 + rotation"
Dmitry Kazakov
dimula73 at gmail.com
Fri Mar 25 12:09:44 UTC 2016
Git commit 08fd3aa8e554557728f60f8571e51364070c09e8 by Dmitry Kazakov.
Committed on 25/03/2016 at 12:08.
Pushed by dkazakov into branch 'master'.
Fix "openGL lag at zoom 2000 + rotation"
The problem was not related to the openGL actualy. It was caused
by the implementation of QPainter::clipRegion() which generated
20k+ rectangles from a rotated rect when rotation angle was near to
a 0 or 90deg.
WARNING for the future:
Never use QPainter::clipRegion(). Use KisPaintingUtils::safeClipRegion()
instead. It workarounds the issue returning a bit bigger rect.
Fixes T1446
BUG:355104
CC:kimageshop at kde.org
M +3 -1 libs/flake/KoShapeContainer.cpp
M +3 -1 libs/flake/KoShapeManager.cpp
M +0 -3 libs/flake/tools/KoCreateShapeStrategy.cpp
M +0 -2 libs/flake/tools/KoShapeRubberSelectStrategy.cpp
M +1 -0 libs/global/CMakeLists.txt
A +51 -0 libs/global/kis_painting_tweaks.cpp [License: GPL (v2+)]
A +45 -0 libs/global/kis_painting_tweaks.h [License: GPL (v2+)]
M +4 -1 plugins/flake/textshape/TextShape.cpp
M +2 -1 plugins/flake/textshape/textlayout/KoTextLayoutArea_paint.cpp
M +3 -1 plugins/flake/vectorshape/VectorShape.cpp
http://commits.kde.org/krita/08fd3aa8e554557728f60f8571e51364070c09e8
diff --git a/libs/flake/KoShapeContainer.cpp b/libs/flake/KoShapeContainer.cpp
index 74cdb23..411098c 100644
--- a/libs/flake/KoShapeContainer.cpp
+++ b/libs/flake/KoShapeContainer.cpp
@@ -29,6 +29,8 @@
#include <QPainter>
#include <QPainterPath>
+#include "kis_painting_tweaks.h"
+
KoShapeContainerPrivate::KoShapeContainerPrivate(KoShapeContainer *q)
: KoShapePrivate(q),
model(0)
@@ -173,7 +175,7 @@ void KoShapeContainer::paint(QPainter &painter, const KoViewConverter &converter
m.scale(zoomX, zoomY);
painter.setClipPath(m.map(outline()), Qt::IntersectClip);
- QRectF toPaintRect = converter.viewToDocument(painter.clipRegion().boundingRect());
+ QRectF toPaintRect = converter.viewToDocument(KisPaintingTweaks::safeClipBoundingRect(painter));
toPaintRect = transform().mapRect(toPaintRect);
// We'll use this clipRect to see if our child shapes lie within it.
// Because shape->boundingRect() uses absoluteTransformation(0) we'll
diff --git a/libs/flake/KoShapeManager.cpp b/libs/flake/KoShapeManager.cpp
index f44d4be..6f861f1 100644
--- a/libs/flake/KoShapeManager.cpp
+++ b/libs/flake/KoShapeManager.cpp
@@ -48,6 +48,8 @@
#include <QTimer>
#include <FlakeDebug.h>
+#include "kis_painting_tweaks.h"
+
void KoShapeManager::Private::updateTree()
{
@@ -227,7 +229,7 @@ void KoShapeManager::paint(QPainter &painter, const KoViewConverter &converter,
QList<KoShape*> unsortedShapes;
if (painter.hasClipping()) {
- QRectF rect = converter.viewToDocument(painter.clipRegion().boundingRect());
+ QRectF rect = converter.viewToDocument(KisPaintingTweaks::safeClipBoundingRect(painter));
unsortedShapes = d->tree.intersects(rect);
} else {
unsortedShapes = shapes();
diff --git a/libs/flake/tools/KoCreateShapeStrategy.cpp b/libs/flake/tools/KoCreateShapeStrategy.cpp
index 7e6ef1a..054a56b 100644
--- a/libs/flake/tools/KoCreateShapeStrategy.cpp
+++ b/libs/flake/tools/KoCreateShapeStrategy.cpp
@@ -119,9 +119,6 @@ void KoCreateShapeStrategy::paint(QPainter &painter, const KoViewConverter &conv
matrix.scale(xscale, yscale);
painter.translate(paintRect.left(), paintRect.top());
- if (painter.hasClipping())
- paintRect = paintRect.intersect(painter.clipRegion().boundingRect());
-
painter.setTransform(matrix, true);
painter.drawPath(m_outline);
painter.restore();
diff --git a/libs/flake/tools/KoShapeRubberSelectStrategy.cpp b/libs/flake/tools/KoShapeRubberSelectStrategy.cpp
index 8240593..0b0a0e8 100644
--- a/libs/flake/tools/KoShapeRubberSelectStrategy.cpp
+++ b/libs/flake/tools/KoShapeRubberSelectStrategy.cpp
@@ -52,8 +52,6 @@ void KoShapeRubberSelectStrategy::paint(QPainter &painter, const KoViewConverter
QRectF paintRect = converter.documentToView(d->selectedRect());
paintRect = paintRect.normalized();
paintRect.adjust(0., -0.5, 0.5, 0.);
- if (painter.hasClipping())
- paintRect = paintRect.intersect(painter.clipRegion().boundingRect());
painter.drawRect(paintRect);
}
diff --git a/libs/global/CMakeLists.txt b/libs/global/CMakeLists.txt
index efb0d98..42a33fe 100644
--- a/libs/global/CMakeLists.txt
+++ b/libs/global/CMakeLists.txt
@@ -12,6 +12,7 @@ set(kritaglobal_LIB_SRCS
kis_memory_leak_tracker.cpp
kis_shared.cpp
kis_dom_utils.cpp
+ kis_painting_tweaks.cpp
)
add_library(kritaglobal SHARED ${kritaglobal_LIB_SRCS} )
diff --git a/libs/global/kis_painting_tweaks.cpp b/libs/global/kis_painting_tweaks.cpp
new file mode 100644
index 0000000..1c59e1a
--- /dev/null
+++ b/libs/global/kis_painting_tweaks.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016 Dmitry Kazakov <dimula73 at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_painting_tweaks.h"
+
+#include <QRegion>
+#include <QPainter>
+#include <QTransform>
+
+#include "kis_debug.h"
+
+
+namespace KisPaintingTweaks {
+
+QRegion safeClipRegion(const QPainter &painter)
+{
+ const QTransform t = painter.transform();
+
+ QRegion region = t.type() <= QTransform::TxScale ?
+ painter.clipRegion() :
+ QRegion(painter.clipBoundingRect().toAlignedRect());
+
+ if (region.rectCount() > 1000) {
+ qWarning() << "WARNING: KisPaintingTweaks::safeClipRegion: too many rectangles in the region!" << ppVar(region.rectCount());
+ region = QRegion(painter.clipBoundingRect().toAlignedRect());
+ }
+
+ return region;
+}
+
+QRect safeClipBoundingRect(const QPainter &painter)
+{
+ return painter.clipBoundingRect().toAlignedRect();
+}
+
+}
diff --git a/libs/global/kis_painting_tweaks.h b/libs/global/kis_painting_tweaks.h
new file mode 100644
index 0000000..274cbad
--- /dev/null
+++ b/libs/global/kis_painting_tweaks.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016 Dmitry Kazakov <dimula73 at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KIS_PAINTING_TWEAKS_H
+#define __KIS_PAINTING_TWEAKS_H
+
+#include "kritaglobal_export.h"
+
+class QPainter;
+class QRegion;
+class QRect;
+
+namespace KisPaintingTweaks {
+
+ /**
+ * This is a workaround for QPainter::clipRegion() bug. When zoom
+ * is about 2000% and rotation is in a range[-5;5] degrees, the
+ * generated region will have about 20k+ regtangles inside. Their
+ * processing will be really slow. These functions fworkarounds
+ * the issue.
+ */
+ KRITAGLOBAL_EXPORT QRegion safeClipRegion(const QPainter &painter);
+
+ /**
+ * \see safeClipRegion()
+ */
+ KRITAGLOBAL_EXPORT QRect safeClipBoundingRect(const QPainter &painter);
+}
+
+#endif /* __KIS_PAINTING_TWEAKS_H */
diff --git a/plugins/flake/textshape/TextShape.cpp b/plugins/flake/textshape/TextShape.cpp
index 65b5ac3..7fdda74 100644
--- a/plugins/flake/textshape/TextShape.cpp
+++ b/plugins/flake/textshape/TextShape.cpp
@@ -63,6 +63,9 @@
#include <QDebug>
+#include "kis_painting_tweaks.h"
+
+
TextShape::TextShape(KoInlineTextObjectManager *inlineTextObjectManager, KoTextRangeManager *textRangeManager)
: KoShapeContainer(new KoTextShapeContainerModel())
, KoFrameShape(KoXmlNS::draw, "text-box")
@@ -137,7 +140,7 @@ void TextShape::paintComponent(QPainter &painter, const KoViewConverter &convert
KoTextPage *page = m_pageProvider->page(this);
if (page) {
// this is used to not trigger repaints if layout during the painting is done
- m_paintRegion = painter.clipRegion();
+ m_paintRegion = KisPaintingTweaks::safeClipRegion(painter);
if (!m_textShapeData->rootArea()->page() || page->pageNumber() != m_textShapeData->rootArea()->page()->pageNumber()) {
m_textShapeData->rootArea()->setPage(page); // takes over ownership of the page
} else {
diff --git a/plugins/flake/textshape/textlayout/KoTextLayoutArea_paint.cpp b/plugins/flake/textshape/textlayout/KoTextLayoutArea_paint.cpp
index 5d6860c..dbe749e 100644
--- a/plugins/flake/textshape/textlayout/KoTextLayoutArea_paint.cpp
+++ b/plugins/flake/textshape/textlayout/KoTextLayoutArea_paint.cpp
@@ -65,6 +65,7 @@
#include <QTextLayout>
#include <QTextCursor>
#include <QTime>
+#include "kis_painting_tweaks.h"
extern int qt_defaultDpiY();
Q_DECLARE_METATYPE(QTextDocument *)
@@ -91,7 +92,7 @@ void KoTextLayoutArea::paint(QPainter *painter, const KoTextDocumentLayout::Pain
painter->translate(0, d->verticalAlignOffset);
painter->setPen(context.textContext.palette.color(QPalette::Text)); // for text that has no color.
- const QRegion clipRegion = painter->clipRegion(); // fetch after painter->translate so the clipRegion is correct
+ const QRegion clipRegion = KisPaintingTweaks::safeClipRegion(*painter); // fetch after painter->translate so the clipRegion is correct
KoTextBlockBorderData *lastBorder = 0;
QRectF lastBorderRect;
diff --git a/plugins/flake/vectorshape/VectorShape.cpp b/plugins/flake/vectorshape/VectorShape.cpp
index 6e227df..2a80a5c 100644
--- a/plugins/flake/vectorshape/VectorShape.cpp
+++ b/plugins/flake/vectorshape/VectorShape.cpp
@@ -57,6 +57,8 @@
#include "SvmParser.h"
#include "SvmPainterBackend.h"
+#include "kis_painting_tweaks.h"
+
// Comment out to get uncached painting, which is good for debugging
//#define VECTORSHAPE_PAINT_UNCACHED
@@ -247,7 +249,7 @@ void VectorShape::paint(QPainter &painter, const KoViewConverter &converter, KoS
QImage *cache = render(converter, asynchronous, useCache);
if (cache) { // paint cached image
Q_ASSERT(!cache->isNull());
- QVector<QRect> clipRects = painter.clipRegion().rects();
+ QVector<QRect> clipRects = KisPaintingTweaks::safeClipRegion(painter).rects();
foreach (const QRect &rc, clipRects) {
painter.drawImage(rc.topLeft(), *cache, rc);
}
More information about the kimageshop
mailing list