KisReferenceImagesDecoration.cpp 4.73 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Copyright (C) 2016 Boudewijn Rempt <boud@valdyas.org>
 *
 * 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 "KisReferenceImagesDecoration.h"

22 23 24
#include "KoShapeManager.h"

#include "kis_algebra_2d.h"
25
#include "KisDocument.h"
26
#include "KisReferenceImagesLayer.h"
27 28

struct KisReferenceImagesDecoration::Private {
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
    struct Buffer
    {
        /// Top left corner of the buffer relative to the viewport
        QPointF position;
        QImage image;

        QRectF bounds() const
        {
            return QRectF(position, image.size());
        }
    };

    KisReferenceImagesDecoration *q;

    KisWeakSharedPtr<KisReferenceImagesLayer> layer;
    Buffer buffer;
    QTransform previousTransform;

    explicit Private(KisReferenceImagesDecoration *q)
        : q(q)
    {}

    void updateBufferByImageCoordinates(const QRectF &dirtyImageRect)
    {
        QRectF dirtyWidgetRect = q->view()->viewConverter()->imageToWidget(dirtyImageRect);
        updateBuffer(dirtyWidgetRect, dirtyImageRect);
    }
56

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
    void updateBufferByWidgetCoordinates(const QRectF &dirtyWidgetRect)
    {
        QRectF dirtyImageRect = q->view()->viewConverter()->widgetToImage(dirtyWidgetRect);
        updateBuffer(dirtyWidgetRect, dirtyImageRect);
    }

private:
    void updateBuffer(const QRectF &widgetRect, const QRectF &imageRect)
    {
        KisCoordinatesConverter *viewConverter = q->view()->viewConverter();
        QTransform transform = viewConverter->imageToWidgetTransform();

        if (buffer.image.isNull() || !buffer.bounds().contains(widgetRect)) {
            // TODO: only use enough buffer to cover the BB of the shapes
            buffer.position = QPointF();
            buffer.image = QImage(q->view()->width(), q->view()->height(), QImage::Format_ARGB32);
            buffer.image.fill(Qt::transparent);
        }

        QPainter gc(&buffer.image);
        gc.setTransform(transform);

        gc.save();
        gc.setCompositionMode(QPainter::CompositionMode_Source);
        gc.fillRect(imageRect, Qt::transparent);
        gc.restore();

        gc.setClipRect(imageRect);
85
        layer->paintReferences(gc);
86
    }
87 88 89 90
};

KisReferenceImagesDecoration::KisReferenceImagesDecoration(QPointer<KisView> parent)
    : KisCanvasDecoration("referenceImagesDecoration", parent)
91 92
    , d(new Private(this))
{}
93 94

KisReferenceImagesDecoration::~KisReferenceImagesDecoration()
95
{}
96

97
void KisReferenceImagesDecoration::addReferenceImage(KisReferenceImage *referenceImage)
98
{
99
    KisSharedPtr<KisReferenceImagesLayer> layer = view()->document()->createReferenceImagesLayer();
100 101
    KIS_SAFE_ASSERT_RECOVER_RETURN(layer);

102 103
    KUndo2Command *cmd = layer->addReferenceImage(referenceImage);
    view()->document()->addCommand(cmd);
104 105
}

106
bool KisReferenceImagesDecoration::documentHasReferenceImages() const
107
{
108
    return view()->document()->referenceImagesLayer() != nullptr;
109 110
}

Boudewijn Rempt's avatar
Boudewijn Rempt committed
111
void KisReferenceImagesDecoration::drawDecoration(QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter */*converter*/, KisCanvas2 */*canvas*/)
112
{
113 114 115 116 117 118 119 120 121 122 123
    KisSharedPtr<KisReferenceImagesLayer> layer = d->layer.toStrongRef();
    if (layer.isNull()) {
        layer = d->layer = view()->document()->referenceImagesLayer();
        if (layer.isNull()) return;

        connect(layer.data(), SIGNAL(sigUpdateCanvas(const QRectF&)), this, SLOT(slotReferenceImagesChanged(const QRectF&)));

        d->updateBufferByWidgetCoordinates(updateRect);
    } else {
        QTransform transform = view()->viewConverter()->imageToWidgetTransform();
        if (!KisAlgebra2D::fuzzyMatrixCompare(transform, d->previousTransform, 1e-4)) {
124
            d->previousTransform = transform;
125 126
            d->updateBufferByWidgetCoordinates(QRectF(0, 0, view()->width(), view()->height()));
        }
127
    }
128 129 130 131 132 133 134 135 136 137

    gc.drawImage(d->buffer.position, d->buffer.image);
}

void KisReferenceImagesDecoration::slotReferenceImagesChanged(const QRectF &dirtyRect)
{
    d->updateBufferByImageCoordinates(dirtyRect);

    QRectF documentRect = view()->viewConverter()->imageToDocument(dirtyRect);
    view()->canvasBase()->updateCanvas(documentRect);
138
}