File indexing completed on 2024-05-19 04:24:48

0001 /*
0002  *  SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "KoClipMaskPainter.h"
0008 
0009 #include <QPainter>
0010 #include <QPainterPath>
0011 #include <QRectF>
0012 #include <KoStreamedMath.h>
0013 #include <KoClipMaskApplicatorBase.h>
0014 #include <xsimd/KoClipMaskApplicatorFactoryImpl.h>
0015 
0016 #include "kis_assert.h"
0017 
0018 struct KoClipMaskApplicatorFactory {
0019     static KoClipMaskApplicatorBase* createApplicator() {
0020 #ifndef DISABLE_CLIP_MASK_PAINTER_ON_MACOS
0021         return createOptimizedClass<KoClipMaskApplicatorFactoryImpl>();
0022 #else
0023         return KoClipMaskApplicatorFactoryImpl::create<xsimd::generic>();
0024 #endif
0025     }
0026 };
0027 
0028 struct Q_DECL_HIDDEN KoClipMaskPainter::Private
0029 {
0030     QPainter *globalPainter;
0031 
0032     QImage shapeImage;
0033     QImage maskImage;
0034 
0035     QPainter shapePainter;
0036     QPainter maskPainter;
0037 
0038     QRect alignedGlobalClipRect;
0039 };
0040 
0041 KoClipMaskPainter::KoClipMaskPainter(QPainter *painter, const QRectF &globalClipRect)
0042     : m_d(new Private)
0043 {
0044     m_d->globalPainter = painter;
0045     m_d->alignedGlobalClipRect = globalClipRect.toAlignedRect();
0046 
0047     if (!m_d->alignedGlobalClipRect.isValid()) {
0048         m_d->alignedGlobalClipRect = QRect();
0049     }
0050     m_d->shapeImage = QImage(m_d->alignedGlobalClipRect.size(), QImage::Format_ARGB32);
0051     m_d->maskImage = QImage(m_d->alignedGlobalClipRect.size(), QImage::Format_ARGB32);
0052 
0053     QTransform moveToBufferTransform =
0054         QTransform::fromTranslate(-m_d->alignedGlobalClipRect.x(),
0055                                   -m_d->alignedGlobalClipRect.y());
0056 
0057     m_d->shapePainter.begin(&m_d->shapeImage);
0058 
0059     m_d->shapePainter.save();
0060     m_d->shapePainter.setCompositionMode(QPainter::CompositionMode_Source);
0061     m_d->shapePainter.fillRect(QRect(QPoint(), m_d->alignedGlobalClipRect.size()), Qt::transparent);
0062     m_d->shapePainter.restore();
0063 
0064     m_d->shapePainter.setTransform(moveToBufferTransform);
0065     m_d->shapePainter.setTransform(painter->transform(), true);
0066     if (painter->hasClipping()) {
0067         m_d->shapePainter.setClipPath(painter->clipPath());
0068     }
0069     m_d->shapePainter.setOpacity(painter->opacity());
0070     m_d->shapePainter.setBrush(painter->brush());
0071     m_d->shapePainter.setPen(painter->pen());
0072 
0073     m_d->maskPainter.begin(&m_d->maskImage);
0074 
0075     m_d->maskPainter.save();
0076     m_d->maskPainter.setCompositionMode(QPainter::CompositionMode_Source);
0077     m_d->maskPainter.fillRect(QRect(QPoint(), m_d->alignedGlobalClipRect.size()), Qt::transparent);
0078     m_d->maskPainter.restore();
0079 
0080     m_d->maskPainter.setTransform(moveToBufferTransform);
0081     m_d->maskPainter.setTransform(painter->transform(), true);
0082     if (painter->hasClipping()) {
0083         m_d->maskPainter.setClipPath(painter->clipPath());
0084     }
0085     m_d->maskPainter.setOpacity(painter->opacity());
0086     m_d->maskPainter.setBrush(painter->brush());
0087     m_d->maskPainter.setPen(painter->pen());
0088 
0089 
0090 
0091 }
0092 
0093 KoClipMaskPainter::~KoClipMaskPainter()
0094 {
0095 }
0096 
0097 QPainter *KoClipMaskPainter::shapePainter()
0098 {
0099     return &m_d->shapePainter;
0100 }
0101 
0102 QPainter *KoClipMaskPainter::maskPainter()
0103 {
0104     return &m_d->maskPainter;
0105 }
0106 
0107 void KoClipMaskPainter::renderOnGlobalPainter()
0108 {
0109     KIS_ASSERT_RECOVER_RETURN(m_d->maskImage.size() == m_d->shapeImage.size());
0110 
0111     const int nPixels = m_d->maskImage.height() * m_d->maskImage.width();
0112 
0113     KoClipMaskApplicatorBase *applicator = KoClipMaskApplicatorFactory::createApplicator();
0114     applicator->applyLuminanceMask(m_d->shapeImage.bits(),
0115                                   m_d->maskImage.bits(),
0116                                   nPixels);
0117 
0118     KIS_ASSERT_RECOVER_RETURN(m_d->shapeImage.size() == m_d->alignedGlobalClipRect.size());
0119     QPainterPath globalClipPath;
0120 
0121     if (m_d->globalPainter->hasClipping()) {
0122         globalClipPath = m_d->globalPainter->transform().map(m_d->globalPainter->clipPath());
0123     }
0124 
0125     m_d->globalPainter->save();
0126 
0127     m_d->globalPainter->setTransform(QTransform());
0128 
0129     if (!globalClipPath.isEmpty()) {
0130         m_d->globalPainter->setClipPath(globalClipPath);
0131     }
0132 
0133     m_d->globalPainter->drawImage(m_d->alignedGlobalClipRect.topLeft(), m_d->shapeImage);
0134     m_d->globalPainter->restore();
0135 }