diff --git a/libs/image/layerstyles/KisLayerStyleKnockoutBlower.cpp b/libs/image/layerstyles/KisLayerStyleKnockoutBlower.cpp index 1583567a0a..48bae193b6 100644 --- a/libs/image/layerstyles/KisLayerStyleKnockoutBlower.cpp +++ b/libs/image/layerstyles/KisLayerStyleKnockoutBlower.cpp @@ -1,72 +1,82 @@ /* * Copyright (c) 2019 Dmitry Kazakov * * 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 "KisLayerStyleKnockoutBlower.h" #include "kis_painter.h" #include "KoCompositeOpRegistry.h" +KisLayerStyleKnockoutBlower::KisLayerStyleKnockoutBlower() +{ +} + +KisLayerStyleKnockoutBlower::KisLayerStyleKnockoutBlower(const KisLayerStyleKnockoutBlower &rhs) + : m_knockoutSelection(rhs.m_knockoutSelection ? new KisSelection(*rhs.m_knockoutSelection) : nullptr) +{ +} + KisSelectionSP KisLayerStyleKnockoutBlower::knockoutSelectionLazy() { { QReadLocker l(&m_lock); if (m_knockoutSelection) { return m_knockoutSelection; } } { QWriteLocker l(&m_lock); if (m_knockoutSelection) { return m_knockoutSelection; } else { m_knockoutSelection = new KisSelection(new KisSelectionEmptyBounds(0)); return m_knockoutSelection; } } } void KisLayerStyleKnockoutBlower::setKnockoutSelection(KisSelectionSP selection) { QWriteLocker l(&m_lock); m_knockoutSelection = selection; } void KisLayerStyleKnockoutBlower::resetKnockoutSelection() { QWriteLocker l(&m_lock); m_knockoutSelection = 0; } void KisLayerStyleKnockoutBlower::apply(KisPainter *painter, KisPaintDeviceSP mergedStyle, const QRect &rect) const { QReadLocker l(&m_lock); KIS_SAFE_ASSERT_RECOVER_NOOP(m_knockoutSelection); painter->setOpacity(OPACITY_OPAQUE_U8); painter->setChannelFlags(QBitArray()); painter->setCompositeOp(COMPOSITE_COPY); painter->setSelection(m_knockoutSelection); painter->bitBlt(rect.topLeft(), mergedStyle, rect); + painter->setSelection(0); } bool KisLayerStyleKnockoutBlower::isEmpty() const { QReadLocker l(&m_lock); return !m_knockoutSelection; } diff --git a/libs/image/layerstyles/KisLayerStyleKnockoutBlower.h b/libs/image/layerstyles/KisLayerStyleKnockoutBlower.h index 50188eff42..d0555d1a7c 100644 --- a/libs/image/layerstyles/KisLayerStyleKnockoutBlower.h +++ b/libs/image/layerstyles/KisLayerStyleKnockoutBlower.h @@ -1,44 +1,47 @@ /* * Copyright (c) 2019 Dmitry Kazakov * * 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 KISLAYERSTYLEKNOCKOUTBLOWER_H #define KISLAYERSTYLEKNOCKOUTBLOWER_H #include "kis_selection.h" #include class KisPainter; class KRITAIMAGE_EXPORT KisLayerStyleKnockoutBlower { public: + KisLayerStyleKnockoutBlower(); + KisLayerStyleKnockoutBlower(const KisLayerStyleKnockoutBlower &rhs); + KisSelectionSP knockoutSelectionLazy(); void setKnockoutSelection(KisSelectionSP selection); void resetKnockoutSelection(); void apply(KisPainter *painter, KisPaintDeviceSP mergedStyle, const QRect &rect) const; bool isEmpty() const; private: mutable QReadWriteLock m_lock; KisSelectionSP m_knockoutSelection; }; #endif // KISLAYERSTYLEKNOCKOUTBLOWER_H diff --git a/libs/image/layerstyles/kis_layer_style_filter_projection_plane.cpp b/libs/image/layerstyles/kis_layer_style_filter_projection_plane.cpp index 97797d7023..cd52f11502 100644 --- a/libs/image/layerstyles/kis_layer_style_filter_projection_plane.cpp +++ b/libs/image/layerstyles/kis_layer_style_filter_projection_plane.cpp @@ -1,165 +1,166 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * 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_layer_style_filter_projection_plane.h" #include "filter/kis_filter.h" #include "filter/kis_filter_configuration.h" #include "filter/kis_filter_registry.h" #include "kis_layer_style_filter.h" #include "kis_layer_style_filter_environment.h" #include "kis_psd_layer_style.h" #include "kis_painter.h" #include "kis_multiple_projection.h" #include "KisLayerStyleKnockoutBlower.h" struct KisLayerStyleFilterProjectionPlane::Private { Private(KisLayer *_sourceLayer) : sourceLayer(_sourceLayer), environment(new KisLayerStyleFilterEnvironment(_sourceLayer)) { KIS_SAFE_ASSERT_RECOVER_NOOP(_sourceLayer); } Private(const Private &rhs, KisLayer *_sourceLayer, KisPSDLayerStyleSP clonedStyle) : sourceLayer(_sourceLayer), filter(rhs.filter ? rhs.filter->clone() : 0), style(clonedStyle), environment(new KisLayerStyleFilterEnvironment(_sourceLayer)), + knockoutBlower(rhs.knockoutBlower), projection(rhs.projection) { KIS_SAFE_ASSERT_RECOVER_NOOP(_sourceLayer); } KisLayer *sourceLayer; QScopedPointer filter; KisPSDLayerStyleSP style; QScopedPointer environment; KisLayerStyleKnockoutBlower knockoutBlower; KisMultipleProjection projection; }; KisLayerStyleFilterProjectionPlane:: KisLayerStyleFilterProjectionPlane(KisLayer *sourceLayer) : m_d(new Private(sourceLayer)) { } KisLayerStyleFilterProjectionPlane::KisLayerStyleFilterProjectionPlane(const KisLayerStyleFilterProjectionPlane &rhs, KisLayer *sourceLayer, KisPSDLayerStyleSP clonedStyle) : m_d(new Private(*rhs.m_d, sourceLayer, clonedStyle)) { } KisLayerStyleFilterProjectionPlane::~KisLayerStyleFilterProjectionPlane() { } void KisLayerStyleFilterProjectionPlane::setStyle(KisLayerStyleFilter *filter, KisPSDLayerStyleSP style) { m_d->filter.reset(filter); m_d->style = style; } QRect KisLayerStyleFilterProjectionPlane::recalculate(const QRect& rect, KisNodeSP filthyNode) { Q_UNUSED(filthyNode); if (!m_d->sourceLayer || !m_d->filter) { warnKrita << "KisLayerStyleFilterProjectionPlane::recalculate(): [BUG] is not initialized"; return QRect(); } m_d->projection.clear(rect); m_d->filter->processDirectly(m_d->sourceLayer->projection(), &m_d->projection, &m_d->knockoutBlower, rect, m_d->style, m_d->environment.data()); return rect; } void KisLayerStyleFilterProjectionPlane::apply(KisPainter *painter, const QRect &rect) { m_d->projection.apply(painter->device(), rect, m_d->environment.data()); } KisPaintDeviceList KisLayerStyleFilterProjectionPlane::getLodCapableDevices() const { return m_d->projection.getLodCapableDevices(); } bool KisLayerStyleFilterProjectionPlane::isEmpty() const { return m_d->projection.isEmpty(); } KisLayerStyleKnockoutBlower *KisLayerStyleFilterProjectionPlane::knockoutBlower() const { return &m_d->knockoutBlower; } QRect KisLayerStyleFilterProjectionPlane::needRect(const QRect &rect, KisLayer::PositionToFilthy pos) const { if (!m_d->sourceLayer || !m_d->filter) { warnKrita << "KisLayerStyleFilterProjectionPlane::needRect(): [BUG] is not initialized"; return rect; } KIS_ASSERT_RECOVER_NOOP(pos == KisLayer::N_ABOVE_FILTHY); return m_d->filter->neededRect(rect, m_d->style, m_d->environment.data()); } QRect KisLayerStyleFilterProjectionPlane::changeRect(const QRect &rect, KisLayer::PositionToFilthy pos) const { if (!m_d->sourceLayer || !m_d->filter) { warnKrita << "KisLayerStyleFilterProjectionPlane::changeRect(): [BUG] is not initialized"; return rect; } KIS_ASSERT_RECOVER_NOOP(pos == KisLayer::N_ABOVE_FILTHY); return m_d->filter->changedRect(rect, m_d->style, m_d->environment.data()); } QRect KisLayerStyleFilterProjectionPlane::accessRect(const QRect &rect, KisLayer::PositionToFilthy pos) const { return needRect(rect, pos); } QRect KisLayerStyleFilterProjectionPlane::needRectForOriginal(const QRect &rect) const { return needRect(rect, KisLayer::N_ABOVE_FILTHY); } QRect KisLayerStyleFilterProjectionPlane::tightUserVisibleBounds() const { KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(m_d->filter, QRect()); KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(m_d->sourceLayer, QRect()); return m_d->filter->changedRect(m_d->sourceLayer->exactBounds(), m_d->style, m_d->environment.data()); }