Warning, file /graphics/krita/plugins/paintops/tangentnormal/kis_tangent_normal_paintop.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * SPDX-FileCopyrightText: 2015 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_tangent_normal_paintop.h" 0008 0009 #include <QRect> 0010 0011 #include <KoColorSpaceRegistry.h> 0012 #include <KoColor.h> 0013 0014 #include <kis_brush.h> 0015 #include <kis_paint_device.h> 0016 #include <kis_painter.h> 0017 #include <kis_node.h> 0018 #include <kis_brush_based_paintop_settings.h> 0019 #include <kis_fixed_paint_device.h> 0020 #include <kis_image.h> 0021 #include <kis_lod_transform.h> 0022 #include <kis_paintop_plugin_utils.h> 0023 0024 0025 KisTangentNormalPaintOp::KisTangentNormalPaintOp(const KisPaintOpSettingsSP settings, KisPainter* painter, KisNodeSP node, KisImageSP image) 0026 : KisBrushBasedPaintOp(settings, painter) 0027 , m_tangentTiltOption(settings.data()) 0028 , m_opacityOption(settings.data(), node) 0029 , m_flowOption(settings.data()) 0030 , m_sizeOption(settings.data()) 0031 , m_spacingOption(settings.data()) 0032 , m_softnessOption(settings.data()) 0033 , m_sharpnessOption(settings.data()) 0034 , m_scatterOption(settings.data()) 0035 , m_rotationOption(settings.data()) 0036 , m_rateOption(settings.data()) 0037 , m_tempDev(painter->device()->createCompositionSourceDevice()) 0038 0039 { 0040 Q_UNUSED(image); 0041 //Init, read settings, etc// 0042 m_airbrushData.read(settings.data()); 0043 0044 m_dabCache->setSharpnessPostprocessing(&m_sharpnessOption); 0045 m_rotationOption.applyFanCornersInfo(this); 0046 } 0047 0048 KisTangentNormalPaintOp::~KisTangentNormalPaintOp() 0049 { 0050 //destroy things here// 0051 } 0052 0053 KisSpacingInformation KisTangentNormalPaintOp::paintAt(const KisPaintInformation& info) 0054 { 0055 /* 0056 * For the color, the precision of tilt is only 60x60, and the precision of direction and rotation are 360 and 360*90. 0057 * You can't get more precise than 8bit. Therefore, we will check if the current space is RGB, 0058 * if so we request a profile with that space and 8bit bit depth, if not, just sRGB 0059 */ 0060 KoColor currentColor = painter()->paintColor(); 0061 QString currentSpace = currentColor.colorSpace()->colorModelId().id(); 0062 const KoColorSpace* rgbColorSpace = KoColorSpaceRegistry::instance()->rgb8(); 0063 if (currentSpace != "RGBA") { 0064 rgbColorSpace = KoColorSpaceRegistry::instance()->rgb8(); 0065 } else { 0066 rgbColorSpace = currentColor.colorSpace(); 0067 } 0068 QVector <float> channelValues(4); 0069 qreal r, g, b; 0070 0071 if (currentColor.colorSpace()->colorDepthId().id()=="F16" || currentColor.colorSpace()->colorDepthId().id()=="F32"){ 0072 channelValues[0] = 0.5;//red 0073 channelValues[1] = 0.5;//green 0074 channelValues[2] = 1.0;//blue 0075 channelValues[3] = 1.0;//alpha, leave alone. 0076 0077 0078 m_tangentTiltOption.apply(info, &r, &g, &b); 0079 0080 channelValues[0] = r;//red 0081 channelValues[1] = g;//green 0082 channelValues[2] = b;//blue 0083 } else { 0084 channelValues[0] = 1.0;//blue 0085 channelValues[1] = 0.5;//green 0086 channelValues[2] = 0.5;//red 0087 channelValues[3] = 1.0;//alpha, leave alone. 0088 0089 m_tangentTiltOption.apply(info, &r, &g, &b); 0090 0091 channelValues[0] = b;//blue 0092 channelValues[1] = g;//green 0093 channelValues[2] = r;//red 0094 } 0095 0096 quint8 data[MAX_PIXEL_SIZE]; 0097 rgbColorSpace->fromNormalisedChannelsValue(data, channelValues); 0098 KoColor color(data, rgbColorSpace);//Should be default RGB(0.5,0.5,1.0) 0099 //draw stuff here, return kisspacinginformation. 0100 KisBrushSP brush = m_brush; 0101 0102 if (!painter()->device() || !brush || !brush->canPaintFor(info)) { 0103 return KisSpacingInformation(1.0); 0104 } 0105 0106 qreal scale = m_sizeOption.apply(info); 0107 scale *= KisLodTransform::lodToScale(painter()->device()); 0108 qreal rotation = m_rotationOption.apply(info); 0109 if (checkSizeTooSmall(scale)) return KisSpacingInformation(); 0110 KisDabShape shape(scale, 1.0, rotation); 0111 0112 0113 QPointF cursorPos = 0114 m_scatterOption.apply(info, 0115 brush->maskWidth(shape, 0, 0, info), 0116 brush->maskHeight(shape, 0, 0, info)); 0117 0118 m_maskDab = 0119 m_dabCache->fetchDab(rgbColorSpace, color, cursorPos, 0120 shape, 0121 info, m_softnessOption.apply(info), 0122 &m_dstDabRect); 0123 0124 if (m_dstDabRect.isEmpty()) return KisSpacingInformation(1.0); 0125 0126 QRect dabRect = m_maskDab->bounds(); 0127 0128 // sanity check 0129 Q_ASSERT(m_dstDabRect.size() == dabRect.size()); 0130 Q_UNUSED(dabRect); 0131 0132 quint8 oldOpacity = painter()->opacity(); 0133 QString oldCompositeOpId = painter()->compositeOpId(); 0134 0135 0136 m_opacityOption.apply(painter(), info); 0137 //paint with the default color? Copied this from color smudge.// 0138 //painter()->setCompositeOp(COMPOSITE_COPY); 0139 //painter()->fill(0, 0, m_dstDabRect.width(), m_dstDabRect.height(), color); 0140 painter()->bltFixed(m_dstDabRect.topLeft(), m_maskDab, m_maskDab->bounds()); 0141 painter()->renderMirrorMaskSafe(m_dstDabRect, m_maskDab, !m_dabCache->needSeparateOriginal()); 0142 0143 // restore original opacity and composite mode values 0144 painter()->setOpacity(oldOpacity); 0145 painter()->setCompositeOpId(oldCompositeOpId); 0146 0147 return computeSpacing(info, scale, rotation); 0148 } 0149 0150 KisSpacingInformation KisTangentNormalPaintOp::updateSpacingImpl(const KisPaintInformation &info) const 0151 { 0152 qreal scale = m_sizeOption.apply(info) * KisLodTransform::lodToScale(painter()->device()); 0153 qreal rotation = m_rotationOption.apply(info); 0154 return computeSpacing(info, scale, rotation); 0155 } 0156 0157 KisTimingInformation KisTangentNormalPaintOp::updateTimingImpl(const KisPaintInformation &info) const 0158 { 0159 return KisPaintOpPluginUtils::effectiveTiming(&m_airbrushData, &m_rateOption, info); 0160 } 0161 0162 KisSpacingInformation KisTangentNormalPaintOp::computeSpacing(const KisPaintInformation &info, 0163 qreal scale, qreal rotation) const 0164 { 0165 return effectiveSpacing(scale, rotation, &m_airbrushData, &m_spacingOption, info); 0166 } 0167 0168 void KisTangentNormalPaintOp::paintLine(const KisPaintInformation& pi1, const KisPaintInformation& pi2, KisDistanceInformation *currentDistance) 0169 { 0170 if (m_sharpnessOption.isChecked() && m_brush && (m_brush->width() == 1) && (m_brush->height() == 1)) { 0171 0172 if (!m_lineCacheDevice) { 0173 m_lineCacheDevice = m_tempDev; 0174 } 0175 else { 0176 m_lineCacheDevice->clear(); 0177 } 0178 0179 KisPainter p(m_lineCacheDevice); 0180 KoColor currentColor = painter()->paintColor(); 0181 QString currentSpace = currentColor.colorSpace()->colorModelId().id(); 0182 const KoColorSpace* rgbColorSpace = KoColorSpaceRegistry::instance()->rgb8(); 0183 if (currentSpace != "RGBA") { 0184 rgbColorSpace = KoColorSpaceRegistry::instance()->rgb8(); 0185 } else { 0186 rgbColorSpace = currentColor.colorSpace(); 0187 } 0188 QVector <float> channelValues(4); 0189 qreal r, g, b; 0190 0191 if (currentColor.colorSpace()->colorDepthId().id()=="F16" || currentColor.colorSpace()->colorDepthId().id()=="F32"){ 0192 channelValues[0] = 0.5;//red 0193 channelValues[1] = 0.5;//green 0194 channelValues[2] = 1.0;//blue 0195 channelValues[3] = 1.0;//alpha, leave alone. 0196 0197 0198 m_tangentTiltOption.apply(pi2, &r, &g, &b); 0199 0200 channelValues[0] = r;//red 0201 channelValues[1] = g;//green 0202 channelValues[2] = b;//blue 0203 } else { 0204 channelValues[0] = 1.0;//blue 0205 channelValues[1] = 0.5;//green 0206 channelValues[2] = 0.5;//red 0207 channelValues[3] = 1.0;//alpha, leave alone. 0208 0209 m_tangentTiltOption.apply(pi2, &r, &g, &b); 0210 0211 channelValues[0] = b;//blue 0212 channelValues[1] = g;//green 0213 channelValues[2] = r;//red 0214 } 0215 0216 quint8 data[4]; 0217 rgbColorSpace->fromNormalisedChannelsValue(data, channelValues); 0218 KoColor color(data, rgbColorSpace); 0219 p.setPaintColor(color); 0220 p.drawDDALine(pi1.pos(), pi2.pos()); 0221 0222 QRect rc = m_lineCacheDevice->extent(); 0223 painter()->bitBlt(rc.x(), rc.y(), m_lineCacheDevice, rc.x(), rc.y(), rc.width(), rc.height()); 0224 painter()->renderMirrorMask(rc, m_lineCacheDevice); 0225 } 0226 else { 0227 KisPaintOp::paintLine(pi1, pi2, currentDistance); 0228 } 0229 }