File indexing completed on 2024-05-19 04:26:19

0001 /*
0002  *  SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_layer_projection_plane.h"
0008 
0009 #include <QBitArray>
0010 #include <KoColorSpace.h>
0011 #include <KoChannelInfo.h>
0012 #include <KoCompositeOpRegistry.h>
0013 #include "kis_painter.h"
0014 #include "kis_projection_leaf.h"
0015 #include "kis_cached_paint_device.h"
0016 #include "kis_sequential_iterator.h"
0017 
0018 
0019 struct KisLayerProjectionPlane::Private
0020 {
0021     KisLayer *layer;
0022     KisCachedPaintDevice cachedDevice;
0023 };
0024 
0025 
0026 KisLayerProjectionPlane::KisLayerProjectionPlane(KisLayer *layer)
0027     : m_d(new Private)
0028 {
0029     m_d->layer = layer;
0030 }
0031 
0032 KisLayerProjectionPlane::~KisLayerProjectionPlane()
0033 {
0034 }
0035 
0036 QRect KisLayerProjectionPlane::recalculate(const QRect& rect, KisNodeSP filthyNode)
0037 {
0038     return m_d->layer->updateProjection(rect, filthyNode);
0039 }
0040 
0041 void KisLayerProjectionPlane::applyImpl(KisPainter *painter, const QRect &rect, KritaUtils::ThresholdMode thresholdMode)
0042 {
0043     KisPaintDeviceSP device = m_d->layer->projection();
0044     if (!device) return;
0045 
0046     QRect needRect = rect;
0047 
0048     if (m_d->layer->compositeOpId() != COMPOSITE_COPY &&
0049         m_d->layer->compositeOpId() != COMPOSITE_DESTINATION_IN  &&
0050         m_d->layer->compositeOpId() != COMPOSITE_DESTINATION_ATOP) {
0051 
0052         needRect &= device->extent();
0053     }
0054 
0055     if(needRect.isEmpty()) return;
0056 
0057     const QBitArray channelFlags = m_d->layer->projectionLeaf()->channelFlags();
0058 
0059     QScopedPointer<KisCachedPaintDevice::Guard> d1;
0060 
0061     if (thresholdMode != KritaUtils::ThresholdNone) {
0062         d1.reset(new KisCachedPaintDevice::Guard(device, m_d->cachedDevice));
0063         KisPaintDeviceSP tmp = d1->device();
0064         tmp->makeCloneFromRough(device, needRect);
0065 
0066         KritaUtils::thresholdOpacity(tmp, needRect, thresholdMode);
0067 
0068         device = tmp;
0069     }
0070 
0071     painter->setChannelFlags(channelFlags);
0072     painter->setCompositeOpId(m_d->layer->compositeOpId());
0073     painter->setOpacity(m_d->layer->projectionLeaf()->opacity());
0074     painter->bitBlt(needRect.topLeft(), device, needRect);
0075 }
0076 
0077 void KisLayerProjectionPlane::apply(KisPainter *painter, const QRect &rect)
0078 {
0079     applyImpl(painter, rect, KritaUtils::ThresholdNone);
0080 }
0081 
0082 void KisLayerProjectionPlane::applyMaxOutAlpha(KisPainter *painter, const QRect &rect, KritaUtils::ThresholdMode thresholdMode)
0083 {
0084     applyImpl(painter, rect, thresholdMode);
0085 }
0086 
0087 KisPaintDeviceList KisLayerProjectionPlane::getLodCapableDevices() const
0088 {
0089     return KisPaintDeviceList() << m_d->layer->projection();
0090 }
0091 
0092 QRect KisLayerProjectionPlane::needRect(const QRect &rect, KisLayer::PositionToFilthy pos) const
0093 {
0094     return m_d->layer->needRect(rect, pos);
0095 }
0096 
0097 QRect KisLayerProjectionPlane::changeRect(const QRect &rect, KisLayer::PositionToFilthy pos) const
0098 {
0099     return m_d->layer->changeRect(rect, pos);
0100 }
0101 
0102 QRect KisLayerProjectionPlane::accessRect(const QRect &rect, KisLayer::PositionToFilthy pos) const
0103 {
0104     return m_d->layer->accessRect(rect, pos);
0105 }
0106 
0107 QRect KisLayerProjectionPlane::needRectForOriginal(const QRect &rect) const
0108 {
0109     return m_d->layer->needRectForOriginal(rect);
0110 }
0111 
0112 QRect KisLayerProjectionPlane::tightUserVisibleBounds() const
0113 {
0114     return m_d->layer->tightUserVisibleBounds();
0115 }
0116