Commit 553efe20 authored by Wolthera van Hövell's avatar Wolthera van Hövell 🛍

Merge branch 'master' into krita-testing-wolthera

parents e4b42d28 ffc4d9cf
......@@ -83,7 +83,7 @@ endif()
# define common versions of Krita applications, used to generate kritaversion.h
# update these version for every release:
set(KRITA_VERSION_STRING "3.0.1 Betas")
set(KRITA_VERSION_STRING "3.0.1 Beta")
set(KRITA_STABLE_VERSION_MAJOR 3) # 3 for 3.x, 4 for 4.x, etc.
set(KRITA_STABLE_VERSION_MINOR 0) # 0 for 3.0, 1 for 3.1, etc.
set(KRITA_VERSION_RELEASE 90) # 89 for Alpha, increase for next test releases, set 0 for first Stable, etc.
......
......@@ -128,18 +128,15 @@ QTransform baseBrushTransform(KisDabShape const& shape,
const QRectF &baseBounds)
{
QTransform transform;
if (!qFuzzyCompare(shape.rotation(), 0)) {
QTransform rotationTransform;
rotationTransform.rotateRadians(shape.rotation());
transform.scale(shape.scaleX(), shape.scaleY());
QRectF rotatedBounds = rotationTransform.mapRect(baseBounds);
transform = rotationTransform *
QTransform::fromTranslate(-rotatedBounds.x(), -rotatedBounds.y());
if (!qFuzzyCompare(shape.rotation(), 0)) {
transform = transform * QTransform().rotateRadians(shape.rotation());
QRectF rotatedBounds = transform.mapRect(baseBounds);
transform = transform * QTransform::fromTranslate(-rotatedBounds.x(), -rotatedBounds.y());
}
return transform *
QTransform::fromScale(shape.scaleX(), shape.scaleY()) *
QTransform::fromTranslate(subPixelX, subPixelY);
return transform * QTransform::fromTranslate(subPixelX, subPixelY);
}
void KisQImagePyramid::calculateParams(KisDabShape const& shape,
......@@ -178,7 +175,6 @@ void KisQImagePyramid::calculateParams(KisDabShape shape,
baseBrushTransform(shape,
subPixelX, subPixelY,
baseBounds);
QRect expectedDstRect = roundRect(originalTransform.mapRect(originalBounds));
#if 0 // Only enable when debugging; users shouldn't see this warning
{
......
......@@ -294,6 +294,22 @@ void KisBrushTest::testPyramidLevelRounding()
QCOMPARE(baseLevel, 5);
}
static QSize dabTransformHelper(KisDabShape const& shape)
{
QSize const testSize(150, 150);
qreal const subPixelX = 0.0,
subPixelY = 0.0;
return KisQImagePyramid::imageSize(testSize, shape, subPixelX, subPixelY);
}
void KisBrushTest::testPyramidDabTransform()
{
QCOMPARE(dabTransformHelper(KisDabShape(1.0, 1.0, 0.0)), QSize(150, 150));
QCOMPARE(dabTransformHelper(KisDabShape(1.0, 0.5, 0.0)), QSize(150, 75));
QCOMPARE(dabTransformHelper(KisDabShape(1.0, 1.0, M_PI / 4)), QSize(213, 213));
QCOMPARE(dabTransformHelper(KisDabShape(1.0, 0.5, M_PI / 4)), QSize(160, 160));
}
// see comment in KisQImagePyramid::appendPyramidLevel
void KisBrushTest::testQPainterTransformationBorder()
{
......
......@@ -38,9 +38,10 @@ private Q_SLOTS:
void benchmarkPyramidCreation();
void benchmarkScaling();
void benchmarkRotation();
void benchmarkMaskScaling();
void testPyramidLevelRounding();
void testPyramidDabTransform();
void testQPainterTransformationBorder();
};
......
......@@ -651,8 +651,6 @@ bool KisDocument::exportDocument(const QUrl &_url)
bool KisDocument::saveFile()
{
dbgUI << "doc=" << url().url();
// Save it to be able to restore it after a failed save
const bool wasModified = isModified();
......@@ -676,12 +674,19 @@ bool KisDocument::saveFile()
setFileProgressUpdater(i18n("Saving Document"));
if (!isNativeFormat(outputMimeType)) {
dbgUI << "Saving to format" << outputMimeType << "in" << localFilePath();
QFileInfo fi(localFilePath());
QString tempororaryFileName;
{
QTemporaryFile tf(QDir::tempPath() + "/XXXXXX" + fi.baseName() + "." + fi.completeSuffix());
tf.open();
tempororaryFileName = tf.fileName();
}
Q_ASSERT(!tempororaryFileName.isEmpty());
if (!isNativeFormat(outputMimeType)) {
Private::SafeSavingLocker locker(d);
if (locker.successfullyLocked()) {
status = d->filterManager->exportDocument(localFilePath(), outputMimeType);
status = d->filterManager->exportDocument(tempororaryFileName, outputMimeType);
} else {
status = KisImportExportFilter::UsageError;
}
......@@ -691,11 +696,9 @@ bool KisDocument::saveFile()
dbgFile << "Export status was" << status;
} else {
// Native format => normal save
Q_ASSERT(!localFilePath().isEmpty());
ret = saveNativeFormat(localFilePath());
ret = saveNativeFormat(tempororaryFileName);
}
if (ret) {
if (!d->suppressProgress) {
QPointer<KoUpdater> updater = d->progressUpdater->startSubtask(1, "clear undo stack");
......@@ -705,15 +708,58 @@ bool KisDocument::saveFile()
} else {
d->undoStack->setClean();
}
removeAutoSaveFiles();
QFile tempFile(tempororaryFileName);
QString s = localFilePath();
QFile dstFile(s);
while (QFileInfo(s).exists()) {
s.append("_");
}
bool r;
if (s != localFilePath()) {
r = dstFile.rename(s);
if (!r) {
setErrorMessage(i18n("Could not rename original file to %1: %2", dstFile.fileName(), dstFile. errorString()));
}
}
if (tempFile.exists()) {
r = tempFile.copy(localFilePath());
if (!r) {
setErrorMessage(i18n("Copying the temporary file failed: %1 to %2: %3", tempFile.fileName(), dstFile.fileName(), tempFile.errorString()));
}
else {
r = tempFile.remove();
if (!r) {
setErrorMessage(i18n("Could not remove temporary file %1: %2", tempFile.fileName(), tempFile.errorString()));
}
else if (s != localFilePath()) {
r = dstFile.remove();
if (!r) {
setErrorMessage(i18n("Could not remove saved original file: %1", dstFile.errorString()));
}
}
}
}
else {
setErrorMessage(i18n("The temporary file %1 is gone before we could copy it!", tempFile.fileName()));
}
if (errorMessage().isEmpty()) {
removeAutoSaveFiles();
}
else {
qWarning() << "Error while saving:" << errorMessage();
}
// Restart the autosave timer
// (we don't want to autosave again 2 seconds after a real save)
setAutoSave(d->autoSaveDelay);
}
clearFileProgressUpdater();
QApplication::restoreOverrideCursor();
if (!ret) {
d->mimeType = outputMimeType;
setConfirmNonNativeSave(isExporting(), false);
}
else {
if (!suppressErrorDialog) {
if (errorMessage().isEmpty()) {
......@@ -744,10 +790,9 @@ bool KisDocument::saveFile()
setModified(wasModified);
}
if (ret) {
d->mimeType = outputMimeType;
setConfirmNonNativeSave(isExporting(), false);
}
clearFileProgressUpdater();
QApplication::restoreOverrideCursor();
return ret;
}
......@@ -2125,6 +2170,7 @@ bool KisDocument::saveAs(const QUrl &kurl)
bool KisDocument::save()
{
qDebug() << "Saving!";
d->m_saveOk = false;
if ( d->m_file.isEmpty() ) { // document was created empty
d->prepareSaving();
......
......@@ -19,7 +19,6 @@ Boston, MA 02110-1301, USA.
#include "KisFilterChainLink.h"
#include <QMetaMethod>
#include <QPluginLoader>
#include <QTemporaryFile>
#include <kis_debug.h>
#include "KisFilterEntry.h"
#include "KisImportExportManager.h"
......
......@@ -28,7 +28,6 @@ Boston, MA 02110-1301, USA.
#include "KisFilterVertex.h"
#include <QMetaMethod>
#include <QTemporaryFile>
#include <QPluginLoader>
#include <kis_debug.h>
......
......@@ -21,7 +21,6 @@ Boston, MA 02110-1301, USA.
#include "KisImportExportFilter.h"
#include <QFile>
#include <QTemporaryFile>
#include <kis_debug.h>
#include <QStack>
#include "KisImportExportManager.h"
......
......@@ -20,7 +20,6 @@
#include <QApplication>
#include <QMessageBox>
#include <QTemporaryFile>
#include <klocalizedstring.h>
......
......@@ -573,12 +573,13 @@ void KisPaintopBox::setCurrentPaintopAndReload(const KoID& paintop, KisPaintOpPr
void KisPaintopBox::setCurrentPaintop(const KoID& paintop, KisPaintOpPresetSP preset)
{
m_presetConnections.clear();
if (m_resourceProvider->currentPreset()) {
m_resourceProvider->setPreviousPaintOpPreset(m_resourceProvider->currentPreset());
if (m_optionWidget) {
m_optionWidget->disconnect(this);
m_optionWidget->hide();
}
......@@ -608,11 +609,10 @@ void KisPaintopBox::setCurrentPaintop(const KoID& paintop, KisPaintOpPresetSP pr
Q_ASSERT(m_optionWidget && m_presetSelectorPopupButton);
connect(m_optionWidget, SIGNAL(sigConfigurationUpdated()), this, SLOT(slotGuiChangedCurrentPreset()));
connect(&m_presetUpdateCompressor, SIGNAL(timeout()), this, SLOT(slotUpdateOptionsWidget()));
connect(m_optionWidget, SIGNAL(sigSaveLockedConfig(KisPropertiesConfiguration*)), this, SLOT(slotSaveLockedOptionToPreset(KisPropertiesConfiguration*)));
connect(m_optionWidget, SIGNAL(sigDropLockedConfig(KisPropertiesConfiguration*)), this, SLOT(slotDropLockedOption(KisPropertiesConfiguration*)));
m_presetConnections.addConnection(m_optionWidget, SIGNAL(sigConfigurationUpdated()), this, SLOT(slotGuiChangedCurrentPreset()));
m_presetConnections.addConnection(&m_presetUpdateCompressor, SIGNAL(timeout()), this, SLOT(slotUpdateOptionsWidget()));
m_presetConnections.addConnection(m_optionWidget, SIGNAL(sigSaveLockedConfig(KisPropertiesConfiguration*)), this, SLOT(slotSaveLockedOptionToPreset(KisPropertiesConfiguration*)));
m_presetConnections.addConnection(m_optionWidget, SIGNAL(sigDropLockedConfig(KisPropertiesConfiguration*)), this, SLOT(slotDropLockedOption(KisPropertiesConfiguration*)));
// load the current brush engine icon for the brush editor toolbar button
......@@ -628,8 +628,6 @@ void KisPaintopBox::setCurrentPaintop(const KoID& paintop, KisPaintOpPresetSP pr
dbgKrita << "current paintop " << paintop.name() << " was not set, not supported by colorspace";
}
m_presetConnections.clear();
// preset -> compressor
m_presetConnections.addConnection(
preset->updateProxy(), SIGNAL(sigSettingsChanged()),
......
......@@ -22,6 +22,9 @@
#include <QOpenGLFunctions>
#include <QApplication>
#include <QDesktopWidget>
#include <QPixmapCache>
#include <QDir>
#include <QFile>
#include <QDesktopServices>
......@@ -40,6 +43,7 @@ namespace
{
bool initialized = false;
bool NeedsFenceWorkaround = false;
bool NeedsPixmapCacheWorkaround = false;
int glMajorVersion = 0;
int glMinorVersion = 0;
bool supportsDeprecatedFunctions = false;
......@@ -116,6 +120,32 @@ void KisOpenGL::initializeContext(QOpenGLContext *ctx)
if ((isOnX11 && Renderer.startsWith("AMD")) || cfg.forceOpenGLFenceWorkaround()) {
NeedsFenceWorkaround = true;
}
/**
* NVidia + Qt's openGL don't play well together and one cannot
* draw a pixmap on a widget more than once in one rendering cycle.
*
* It can be workarounded by drawing strictly via QPixmapCache and
* only when the pixmap size in bigger than doubled size of the
* display framebuffer. That is for 8-bit HD display, you should have
* a cache bigger than 16 MiB. Don't ask me why. (DK)
*
* See bug: https://bugs.kde.org/show_bug.cgi?id=361709
*
* TODO: check if this workaround is still needed after merging
* Qt5+openGL3 branch.
*/
if (vendor.toUpper().contains("NVIDIA")) {
NeedsPixmapCacheWorkaround = true;
const QRect screenSize = QApplication::desktop()->screenGeometry();
const int minCacheSize = 20 * 1024;
const int cacheSize = 2048 + 2 * 4 * screenSize.width() * screenSize.height() / 1024; //KiB
QPixmapCache::setCacheLimit(qMax(minCacheSize, cacheSize));
}
}
bool KisOpenGL::supportsGLSL13()
......@@ -136,6 +166,12 @@ bool KisOpenGL::needsFenceWorkaround()
return NeedsFenceWorkaround;
}
bool KisOpenGL::needsPixmapCacheWorkaround()
{
initialize();
return NeedsPixmapCacheWorkaround;
}
void KisOpenGL::setDefaultFormat()
{
QSurfaceFormat format;
......
......@@ -66,6 +66,11 @@ public:
*/
static bool needsFenceWorkaround();
/**
* @see a comment in initializeContext()
*/
static bool needsPixmapCacheWorkaround();
private:
static void setDefaultFormat();
......
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