File indexing completed on 2024-05-12 15:56:10
0001 /* 0002 * SPDX-FileCopyrightText: 1999 Matthias Elter <me@kde.org> 0003 * SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org> 0004 * SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 #ifndef KIS_BRUSH_ 0009 #define KIS_BRUSH_ 0010 0011 #include <QImage> 0012 0013 #include <KoResource.h> 0014 0015 #include <kis_types.h> 0016 #include <kis_shared.h> 0017 #include <kis_dab_shape.h> 0018 #include <kritabrush_export.h> 0019 0020 class QString; 0021 class KoColor; 0022 class KoColorSpace; 0023 0024 class KisPaintInformation; 0025 class KisPaintopLodLimitations; 0026 class KoAbstractGradient; 0027 class KisOptimizedBrushOutline; 0028 typedef QSharedPointer<KoAbstractGradient> KoAbstractGradientSP; 0029 0030 enum enumBrushType { 0031 INVALID, 0032 MASK, 0033 IMAGE, 0034 PIPE_MASK, 0035 PIPE_IMAGE 0036 }; 0037 0038 enum enumBrushApplication { 0039 ALPHAMASK, 0040 IMAGESTAMP, 0041 LIGHTNESSMAP, 0042 GRADIENTMAP 0043 }; 0044 0045 static const qreal DEFAULT_SOFTNESS_FACTOR = 1.0; 0046 static const qreal DEFAULT_LIGHTNESS_STRENGTH = 1.0; 0047 0048 class KisBrush; 0049 typedef QSharedPointer<KisBrush> KisBrushSP; 0050 0051 /** 0052 * KisBrush is the base class for brush resources. A brush resource 0053 * defines one or more images that are used to potato-stamp along 0054 * the drawn path. The brush type defines how this brush is used -- 0055 * the important difference is between masks (which take the current 0056 * painting color) and images (which do not). It is up to the paintop 0057 * to make use of this feature. 0058 * 0059 * Brushes must be serializable to an xml representation and provide 0060 * a factory class that can recreate or retrieve the brush based on 0061 * this representation. 0062 * 0063 * XXX: This api is still a big mess -- it needs a good refactoring. 0064 * And the whole KoResource architecture is way over-designed. 0065 */ 0066 class BRUSH_EXPORT KisBrush : public KoResource 0067 { 0068 public: 0069 class ColoringInformation 0070 { 0071 public: 0072 virtual ~ColoringInformation(); 0073 virtual const quint8* color() const = 0; 0074 virtual void nextColumn() = 0; 0075 virtual void nextRow() = 0; 0076 }; 0077 0078 protected: 0079 0080 class PlainColoringInformation : public ColoringInformation 0081 { 0082 public: 0083 PlainColoringInformation(const quint8* color); 0084 ~PlainColoringInformation() override; 0085 const quint8* color() const override ; 0086 void nextColumn() override; 0087 void nextRow() override; 0088 private: 0089 const quint8* m_color; 0090 }; 0091 0092 class PaintDeviceColoringInformation : public ColoringInformation 0093 { 0094 0095 public: 0096 0097 PaintDeviceColoringInformation(const KisPaintDeviceSP source, int width); 0098 ~PaintDeviceColoringInformation() override; 0099 const quint8* color() const override ; 0100 void nextColumn() override; 0101 void nextRow() override; 0102 0103 private: 0104 0105 const KisPaintDeviceSP m_source; 0106 KisHLineConstIteratorSP m_iterator; 0107 }; 0108 0109 public: 0110 0111 KisBrush(); 0112 KisBrush(const QString& filename); 0113 ~KisBrush() override; 0114 0115 KisBrush(const KisBrush &rhs); 0116 KisBrush &operator=(const KisBrush &rhs) = delete; 0117 0118 virtual qreal userEffectiveSize() const = 0; 0119 virtual void setUserEffectiveSize(qreal value) = 0; 0120 0121 QPair<QString, QString> resourceType() const override { 0122 return QPair<QString, QString>(ResourceType::Brushes, ""); 0123 } 0124 0125 /** 0126 * @brief brushImage the image the brush tip can paint with. Not all brush types have a single 0127 * image. 0128 * @return a valid QImage. 0129 */ 0130 virtual QImage brushTipImage() const; 0131 0132 /** 0133 * Is a pait device of the brush that shoudl be used for generation 0134 * of the brush outline. Usually, it is the same device returned 0135 * by brushTipImage(), but might be different in some types 0136 * of brushes, like in KisAutoBrush. 0137 */ 0138 virtual KisFixedPaintDeviceSP outlineSourceImage() const; 0139 0140 0141 /** 0142 * Change the spacing of the brush. 0143 * @param spacing a spacing of 1.0 means that strokes will be separated from one time the size 0144 * of the brush. 0145 */ 0146 virtual void setSpacing(double spacing); 0147 0148 /** 0149 * @return the spacing between two strokes for this brush 0150 */ 0151 double spacing() const; 0152 0153 void setAutoSpacing(bool active, qreal coeff); 0154 0155 bool autoSpacingActive() const; 0156 qreal autoSpacingCoeff() const; 0157 0158 0159 /** 0160 * @return the width (for scale == 1.0) 0161 */ 0162 qint32 width() const; 0163 0164 /** 0165 * @return the height (for scale == 1.0) 0166 */ 0167 qint32 height() const; 0168 0169 /** 0170 * @return the width of the mask for the given scale and angle 0171 */ 0172 virtual qint32 maskWidth(KisDabShape const&, qreal subPixelX, qreal subPixelY, const KisPaintInformation& info) const; 0173 0174 /** 0175 * @return the height of the mask for the given scale and angle 0176 */ 0177 virtual qint32 maskHeight(KisDabShape const&, qreal subPixelX, qreal subPixelY, const KisPaintInformation& info) const; 0178 0179 /** 0180 * @return the logical size of the brush, that is the size measured 0181 * in floating point value. 0182 * 0183 * This value should not be used for calculating future dab sizes 0184 * because it doesn't take any rounding into account. The only use 0185 * of this metric is calculation of brush-size derivatives like 0186 * hotspots and spacing. 0187 */ 0188 virtual QSizeF characteristicSize(KisDabShape const&) const; 0189 0190 /** 0191 * @return the angle of the mask adding the given angle 0192 */ 0193 double maskAngle(double angle = 0) const; 0194 0195 /** 0196 * @return the currently selected index of the brush 0197 * if the brush consists of multiple images 0198 * 0199 * @see prepareForSeqNo() 0200 */ 0201 virtual quint32 brushIndex() const; 0202 0203 /** 0204 * The brush type defines how the brush is used. 0205 */ 0206 virtual enumBrushType brushType() const; 0207 0208 QPointF hotSpot(KisDabShape const&, const KisPaintInformation& info) const; 0209 0210 /** 0211 * Returns true if this brush can return something useful for the info. This is used 0212 * by Pipe Brushes that can't paint sometimes 0213 **/ 0214 virtual bool canPaintFor(const KisPaintInformation& /*info*/); 0215 0216 0217 /** 0218 * Is called by the paint op when a paintop starts a stroke. The 0219 * point is that we store brushes a server while the paint ops are 0220 * are recreated all the time. Is means that upon a stroke start 0221 * the brushes may need to clear its state. 0222 */ 0223 virtual void notifyStrokeStarted(); 0224 0225 /** 0226 * Is called by the paint op before it is going to clone the brush into 0227 * multiple instances to pass to different threads. During this call the 0228 * brush is free to prepare some structures that may be shared by all the 0229 * clones without excessive recalculation. 0230 */ 0231 virtual void notifyBrushIsGoingToBeClonedForStroke(); 0232 0233 /** 0234 * Is called by the multithreaded queue to prepare a specific brush 0235 * tip for the particular seqNo. 0236 * 0237 * NOTE: one should use always call prepareForSeqNo() before using the brush 0238 * 0239 * Currently, this is used by pipe'd brushes to implement 0240 * incremental and random parasites 0241 */ 0242 virtual void prepareForSeqNo(const KisPaintInformation& info, int seqNo); 0243 0244 /** 0245 * Return a fixed paint device that contains a correctly scaled image dab. 0246 */ 0247 virtual KisFixedPaintDeviceSP paintDevice(const KoColorSpace * colorSpace, 0248 KisDabShape const&, 0249 const KisPaintInformation& info, 0250 double subPixelX = 0, double subPixelY = 0) const; 0251 0252 /** 0253 * clear dst fill it with a mask colored with KoColor 0254 */ 0255 void mask(KisFixedPaintDeviceSP dst, 0256 const KoColor& color, 0257 KisDabShape const& shape, 0258 const KisPaintInformation& info, 0259 double subPixelX = 0, double subPixelY = 0, 0260 qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR, qreal lightnessStrength = DEFAULT_LIGHTNESS_STRENGTH) const; 0261 0262 /** 0263 * clear dst and fill it with a mask colored with the corresponding colors of src 0264 */ 0265 void mask(KisFixedPaintDeviceSP dst, 0266 const KisPaintDeviceSP src, 0267 KisDabShape const& shape, 0268 const KisPaintInformation& info, 0269 double subPixelX = 0, double subPixelY = 0, 0270 qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR, qreal lightnessStrength = DEFAULT_LIGHTNESS_STRENGTH) const; 0271 0272 0273 virtual enumBrushApplication brushApplication() const; 0274 0275 virtual void setBrushApplication(enumBrushApplication brushApplication); 0276 0277 virtual bool preserveLightness() const; 0278 0279 virtual bool applyingGradient() const; 0280 0281 virtual void setGradient(KoAbstractGradientSP gradient); 0282 0283 0284 /** 0285 * Create a mask and either mask dst (that is, change all alpha values of the 0286 * existing pixels to those of the mask) or, if coloringInfo is present, clear 0287 * dst and fill dst with pixels according to coloringInfo, masked according to the 0288 * generated mask. 0289 * 0290 * @param dst the destination that will be draw on the image, and this function 0291 * will edit its alpha channel 0292 * @param coloringInfo coloring information that will be copied on the dab, it can be null 0293 * @param shape a shape applied on the alpha mask 0294 * @param info the painting information (this is only and should only be used by 0295 * KisImagePipeBrush and only to be backward compatible with the Gimp, 0296 * KisImagePipeBrush is ignoring scale and angle information) 0297 * @param subPixelX sub position of the brush (contained between 0.0 and 1.0) 0298 * @param subPixelY sub position of the brush (contained between 0.0 and 1.0) 0299 * @param softnessFactor softness factor of the brush 0300 * 0301 * @return a mask computed from the grey-level values of the 0302 * pixels in the brush. 0303 */ 0304 virtual void generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, 0305 ColoringInformation* coloringInfo, 0306 KisDabShape const&, 0307 const KisPaintInformation& info, 0308 double subPixelX, double subPixelY, 0309 qreal softnessFactor, qreal lightnessStrength) const; 0310 0311 void generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, 0312 ColoringInformation* coloringInfo, 0313 KisDabShape const&, 0314 const KisPaintInformation& info, 0315 double subPixelX = 0, double subPixelY = 0, 0316 qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR) const; 0317 0318 0319 /** 0320 * Serialize this brush to XML. 0321 */ 0322 virtual void toXML(QDomDocument& , QDomElement&) const; 0323 0324 static KisBrushSP fromXML(const QDomElement& element, KisResourcesInterfaceSP resourcesInterface); 0325 0326 static KoResourceLoadResult fromXMLLoadResult(const QDomElement& element, KisResourcesInterfaceSP resourcesInterface); 0327 0328 virtual KisOptimizedBrushOutline outline(bool forcePreciseOutline = false) const; 0329 0330 virtual void setScale(qreal _scale); 0331 qreal scale() const; 0332 virtual void setAngle(qreal _angle); 0333 qreal angle() const; 0334 0335 void clearBrushPyramid(); 0336 0337 virtual void lodLimitations(KisPaintopLodLimitations *l) const; 0338 0339 virtual bool supportsCaching() const; 0340 0341 virtual void coldInitBrush(); 0342 0343 static const QString brushTypeMetaDataKey; 0344 0345 protected: 0346 0347 void setWidth(qint32 width); 0348 0349 void setHeight(qint32 height); 0350 0351 void setHotSpot(QPointF); 0352 0353 /** 0354 * XXX 0355 */ 0356 virtual void setBrushType(enumBrushType type); 0357 0358 public: 0359 0360 /** 0361 * The image is used to represent the brush in the gui, and may also, depending on the brush type 0362 * be used to define the actual brush instance. 0363 */ 0364 virtual void setBrushTipImage(const QImage& image); 0365 0366 /** 0367 * Returns true if the brush has a bunch of pixels almost 0368 * fully transparent in the very center. If the brush is pierced, 0369 * then dulling mode may not work correctly due to empty samples. 0370 * 0371 * WARNING: this method is relatively expensive since it iterates 0372 * up to 100 pixels of the brush. 0373 */ 0374 virtual bool isPiercedApprox() const; 0375 0376 protected: 0377 0378 void resetOutlineCache(); 0379 void generateOutlineCache(); 0380 bool outlineCacheIsValid() const; 0381 0382 void predefinedBrushToXML(const QString &type, QDomElement& e) const; 0383 0384 private: 0385 0386 struct Private; 0387 Private* const d; 0388 0389 }; 0390 0391 Q_DECLARE_METATYPE(KisBrushSP) 0392 0393 #endif // KIS_BRUSH_ 0394