diff --git a/libs/ui/KisReferenceImage.cpp b/libs/ui/KisReferenceImage.cpp index b19b02fe26..a45c9e4294 100644 --- a/libs/ui/KisReferenceImage.cpp +++ b/libs/ui/KisReferenceImage.cpp @@ -1,283 +1,285 @@ /* * Copyright (C) 2017 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisReferenceImage.h" #include #include #include #include #include #include #include #include #include #include #include struct KisReferenceImage::Private { KisReferenceImage *q; QString src; QImage image; QImage cachedImage; qreal saturation{1.0}; int id{-1}; bool embed{true}; explicit Private(KisReferenceImage *q) : q(q) {} void loadFromFile() { KIS_SAFE_ASSERT_RECOVER_RETURN(src.startsWith("file://")); QString filename = src.mid(7); image.load(filename); } }; KisReferenceImage::SetSaturationCommand::SetSaturationCommand(const QList &shapes, qreal newSaturation, KUndo2Command *parent) : KUndo2Command(kundo2_i18n("Set saturation"), parent) , newSaturation(newSaturation) { images.reserve(shapes.count()); Q_FOREACH(auto *shape, shapes) { auto *reference = dynamic_cast(shape); KIS_SAFE_ASSERT_RECOVER_BREAK(reference); images.append(reference); } Q_FOREACH(auto *image, images) { oldSaturations.append(image->saturation()); } } void KisReferenceImage::SetSaturationCommand::undo() { auto saturationIterator = oldSaturations.begin(); Q_FOREACH(auto *image, images) { image->setSaturation(*saturationIterator); image->update(); saturationIterator++; } } void KisReferenceImage::SetSaturationCommand::redo() { Q_FOREACH(auto *image, images) { image->setSaturation(newSaturation); image->update(); } } KisReferenceImage::KisReferenceImage() : d(new Private(this)) { setKeepAspectRatio(true); } KisReferenceImage::KisReferenceImage(const KisReferenceImage &rhs) : KoTosContainer(new KoTosContainerPrivate(*rhs.d_func(), this)) , d(new Private(*rhs.d)) {} KisReferenceImage::~KisReferenceImage() {} KisReferenceImage * KisReferenceImage::fromFile(const QString &filename, const KisCoordinatesConverter &converter) { KisReferenceImage *reference = new KisReferenceImage(); reference->d->src = QString("file://") + filename; reference->d->loadFromFile(); QRect r = QRect(QPoint(), reference->d->image.size()); QSizeF shapeSize = converter.imageToDocument(r).size(); reference->setSize(shapeSize); return reference; } void KisReferenceImage::paint(QPainter &gc, const KoViewConverter &converter, KoShapePaintingContext &/*paintcontext*/) { + if (!parent()) return; + gc.save(); applyConversion(gc, converter); QSizeF shapeSize = size(); QTransform transform = QTransform::fromScale(shapeSize.width() / d->image.width(), shapeSize.height() / d->image.height()); if (d->cachedImage.isNull()) { if (d->saturation < 1.0) { d->cachedImage = KritaUtils::convertQImageToGrayA(d->image); if (d->saturation > 0.0) { QPainter gc2(&d->cachedImage); gc2.setOpacity(d->saturation); gc2.drawImage(QPoint(), d->image); } } else { d->cachedImage = d->image; } } gc.setRenderHint(QPainter::SmoothPixmapTransform); gc.setClipRect(QRectF(QPointF(), shapeSize), Qt::IntersectClip); gc.setTransform(transform, true); gc.drawImage(QPoint(), d->cachedImage); gc.restore(); } void KisReferenceImage::setSaturation(qreal saturation) { d->saturation = saturation; d->cachedImage = QImage(); } qreal KisReferenceImage::saturation() const { return d->saturation; } void KisReferenceImage::setEmbed(bool embed) { KIS_SAFE_ASSERT_RECOVER_RETURN(embed || d->src.startsWith("file://")); d->embed = embed; } bool KisReferenceImage::embed() { return d->embed; } bool KisReferenceImage::hasLocalFile() { return d->src.startsWith("file://"); } QColor KisReferenceImage::getPixel(QPointF position) { const QSizeF shapeSize = size(); const QTransform scale = QTransform::fromScale(d->image.width() / shapeSize.width(), d->image.height() / shapeSize.height()); const QTransform transform = absoluteTransformation(nullptr).inverted() * scale; const QPointF localPosition = position * transform; return d->image.pixelColor(localPosition.toPoint()); } void KisReferenceImage::saveXml(QDomDocument &document, QDomElement &parentElement, int id) { d->id = id; QDomElement element = document.createElement("referenceimage"); if (d->embed) { d->src = QString("reference_images/%1.png").arg(id); } element.setAttribute("src", d->src); const QSizeF &shapeSize = size(); element.setAttribute("width", KisDomUtils::toString(shapeSize.width())); element.setAttribute("height", KisDomUtils::toString(shapeSize.height())); element.setAttribute("keepAspectRatio", keepAspectRatio() ? "true" : "false"); element.setAttribute("transform", SvgUtil::transformToString(transform())); element.setAttribute("opacity", KisDomUtils::toString(1.0 - transparency())); element.setAttribute("saturation", KisDomUtils::toString(d->saturation)); parentElement.appendChild(element); } KisReferenceImage * KisReferenceImage::fromXml(const QDomElement &elem) { auto *reference = new KisReferenceImage(); const QString &src = elem.attribute("src"); reference->d->src = src; reference->d->embed = !src.startsWith("file://"); qreal width = KisDomUtils::toDouble(elem.attribute("width", "100")); qreal height = KisDomUtils::toDouble(elem.attribute("height", "100")); reference->setSize(QSizeF(width, height)); reference->setKeepAspectRatio(elem.attribute("keepAspectRatio", "true").toLower() == "true"); auto transform = SvgTransformParser(elem.attribute("transform")).transform(); reference->setTransformation(transform); qreal opacity = KisDomUtils::toDouble(elem.attribute("opacity", "1")); reference->setTransparency(1.0 - opacity); qreal saturation = KisDomUtils::toDouble(elem.attribute("opacity", "1")); reference->setSaturation(saturation); return reference; } bool KisReferenceImage::saveImage(KoStore *store) const { if (!d->embed) return true; if (!store->open(d->src)) { return false; } KoStoreDevice storeDev(store); if (!storeDev.open(QIODevice::WriteOnly)) { return false; } if (!d->image.save(&storeDev, "PNG")) { return false; } return store->close(); } bool KisReferenceImage::loadImage(KoStore *store) { if (d->src.startsWith("file://")) { d->loadFromFile(); return true; } if (!store->open(d->src)) { return false; } KoStoreDevice storeDev(store); if (!storeDev.open(QIODevice::ReadOnly)) { return false; } if (!d->image.load(&storeDev, "PNG")) { return false; } return store->close(); } KoShape *KisReferenceImage::cloneShape() const { return new KisReferenceImage(*this); }