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 }