File indexing completed on 2024-05-12 15:56:39
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 0013 #include "kis_assert.h" 0014 0015 struct Q_DECL_HIDDEN KoClipMaskPainter::Private 0016 { 0017 QPainter *globalPainter; 0018 0019 QImage shapeImage; 0020 QImage maskImage; 0021 0022 QPainter shapePainter; 0023 QPainter maskPainter; 0024 0025 QRect alignedGlobalClipRect; 0026 }; 0027 0028 KoClipMaskPainter::KoClipMaskPainter(QPainter *painter, const QRectF &globalClipRect) 0029 : m_d(new Private) 0030 { 0031 m_d->globalPainter = painter; 0032 m_d->alignedGlobalClipRect = globalClipRect.toAlignedRect(); 0033 0034 m_d->shapeImage = QImage(m_d->alignedGlobalClipRect.size(), QImage::Format_ARGB32); 0035 m_d->maskImage = QImage(m_d->alignedGlobalClipRect.size(), QImage::Format_ARGB32); 0036 0037 m_d->shapeImage.fill(0); 0038 m_d->maskImage.fill(0); 0039 0040 QTransform moveToBufferTransform = 0041 QTransform::fromTranslate(-m_d->alignedGlobalClipRect.x(), 0042 -m_d->alignedGlobalClipRect.y()); 0043 0044 m_d->shapePainter.begin(&m_d->shapeImage); 0045 m_d->shapePainter.setTransform(moveToBufferTransform); 0046 m_d->shapePainter.setTransform(painter->transform(), true); 0047 if (painter->hasClipping()) { 0048 m_d->shapePainter.setClipPath(painter->clipPath()); 0049 } 0050 m_d->shapePainter.setOpacity(painter->opacity()); 0051 m_d->shapePainter.setBrush(painter->brush()); 0052 m_d->shapePainter.setPen(painter->pen()); 0053 0054 m_d->maskPainter.begin(&m_d->maskImage); 0055 m_d->maskPainter.setTransform(moveToBufferTransform); 0056 m_d->maskPainter.setTransform(painter->transform(), true); 0057 if (painter->hasClipping()) { 0058 m_d->maskPainter.setClipPath(painter->clipPath()); 0059 } 0060 m_d->maskPainter.setOpacity(painter->opacity()); 0061 m_d->maskPainter.setBrush(painter->brush()); 0062 m_d->maskPainter.setPen(painter->pen()); 0063 } 0064 0065 KoClipMaskPainter::~KoClipMaskPainter() 0066 { 0067 } 0068 0069 QPainter *KoClipMaskPainter::shapePainter() 0070 { 0071 return &m_d->shapePainter; 0072 } 0073 0074 QPainter *KoClipMaskPainter::maskPainter() 0075 { 0076 return &m_d->maskPainter; 0077 } 0078 0079 void KoClipMaskPainter::renderOnGlobalPainter() 0080 { 0081 KIS_ASSERT_RECOVER_RETURN(m_d->maskImage.size() == m_d->shapeImage.size()); 0082 0083 for (int y = 0; y < m_d->maskImage.height(); y++) { 0084 QRgb *shapeData = reinterpret_cast<QRgb*>(m_d->shapeImage.scanLine(y)); 0085 QRgb *maskData = reinterpret_cast<QRgb*>(m_d->maskImage.scanLine(y)); 0086 0087 for (int x = 0; x < m_d->maskImage.width(); x++) { 0088 0089 const qreal normCoeff = 1.0 / 255.0 * 255.0; 0090 0091 qreal maskValue = qreal(qAlpha(*maskData)) * 0092 (0.2125 * qRed(*maskData) + 0093 0.7154 * qGreen(*maskData) + 0094 0.0721 * qBlue(*maskData)); 0095 0096 int alpha = qRound(maskValue * qAlpha(*shapeData) * normCoeff); 0097 0098 *shapeData = (alpha << 24) | (*shapeData & 0x00ffffff); 0099 0100 shapeData++; 0101 maskData++; 0102 } 0103 } 0104 0105 KIS_ASSERT_RECOVER_RETURN(m_d->shapeImage.size() == m_d->alignedGlobalClipRect.size()); 0106 QPainterPath globalClipPath; 0107 0108 if (m_d->globalPainter->hasClipping()) { 0109 globalClipPath = m_d->globalPainter->transform().map(m_d->globalPainter->clipPath()); 0110 } 0111 0112 m_d->globalPainter->save(); 0113 0114 m_d->globalPainter->setTransform(QTransform()); 0115 0116 if (!globalClipPath.isEmpty()) { 0117 m_d->globalPainter->setClipPath(globalClipPath); 0118 } 0119 0120 m_d->globalPainter->drawImage(m_d->alignedGlobalClipRect.topLeft(), m_d->shapeImage); 0121 m_d->globalPainter->restore(); 0122 } 0123