1 /* 2 * Copyright (c) 1999 Matthias Elter <me@kde.org> 3 * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> 4 * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 #ifndef KIS_BRUSH_ 21 #define KIS_BRUSH_ 22 23 #include <QImage> 24 25 #include <resources/KoResource.h> 26 27 #include <kis_types.h> 28 #include <kis_shared.h> 29 #include <kis_dab_shape.h> 30 #include <kritabrush_export.h> 31 #include <resources/KoAbstractGradient.h> 32 33 class KisQImagemask; 34 typedef KisSharedPtr<KisQImagemask> KisQImagemaskSP; 35 36 class QString; 37 class KoColor; 38 class KoColorSpace; 39 40 class KisPaintInformation; 41 class KisBoundary; 42 class KisPaintopLodLimitations; 43 44 enum enumBrushType { 45 INVALID, 46 MASK, 47 IMAGE, 48 PIPE_MASK, 49 PIPE_IMAGE 50 }; 51 52 enum enumBrushApplication { 53 ALPHAMASK, 54 IMAGESTAMP, 55 LIGHTNESSMAP, 56 GRADIENTMAP 57 }; 58 59 static const qreal DEFAULT_SOFTNESS_FACTOR = 1.0; 60 static const qreal DEFAULT_LIGHTNESS_STRENGTH = 1.0; 61 62 class KisBrush; 63 typedef KisSharedPtr<KisBrush> KisBrushSP; 64 65 /** 66 * KisBrush is the base class for brush resources. A brush resource 67 * defines one or more images that are used to potato-stamp along 68 * the drawn path. The brush type defines how this brush is used -- 69 * the important difference is between masks (which take the current 70 * painting color) and images (which do not). It is up to the paintop 71 * to make use of this feature. 72 * 73 * Brushes must be serializable to an xml representation and provide 74 * a factory class that can recreate or retrieve the brush based on 75 * this representation. 76 * 77 * XXX: This api is still a big mess -- it needs a good refactoring. 78 * And the whole KoResource architecture is way over-designed. 79 */ 80 class BRUSH_EXPORT KisBrush : public KoResource, public KisShared 81 { 82 83 84 public: 85 class ColoringInformation 86 { 87 public: 88 virtual ~ColoringInformation(); 89 virtual const quint8* color() const = 0; 90 virtual void nextColumn() = 0; 91 virtual void nextRow() = 0; 92 }; 93 94 protected: 95 96 class PlainColoringInformation : public ColoringInformation 97 { 98 public: 99 PlainColoringInformation(const quint8* color); 100 ~PlainColoringInformation() override; 101 const quint8* color() const override ; 102 void nextColumn() override; 103 void nextRow() override; 104 private: 105 const quint8* m_color; 106 }; 107 108 class PaintDeviceColoringInformation : public ColoringInformation 109 { 110 111 public: 112 113 PaintDeviceColoringInformation(const KisPaintDeviceSP source, int width); 114 ~PaintDeviceColoringInformation() override; 115 const quint8* color() const override ; 116 void nextColumn() override; 117 void nextRow() override; 118 119 private: 120 121 const KisPaintDeviceSP m_source; 122 KisHLineConstIteratorSP m_iterator; 123 }; 124 125 public: 126 127 KisBrush(); 128 KisBrush(const QString& filename); 129 130 ~KisBrush() override; 131 132 virtual qreal userEffectiveSize() const = 0; 133 virtual void setUserEffectiveSize(qreal value) = 0; 134 load()135 bool load() override { 136 return false; 137 } 138 loadFromDevice(QIODevice *)139 bool loadFromDevice(QIODevice *) override { 140 return false; 141 } 142 143 save()144 bool save() override { 145 return false; 146 } 147 saveToDevice(QIODevice *)148 bool saveToDevice(QIODevice* ) const override { 149 return false; 150 } 151 152 /** 153 * @brief brushImage the image the brush tip can paint with. Not all brush types have a single 154 * image. 155 * @return a valid QImage. 156 */ 157 virtual QImage brushTipImage() const; 158 159 /** 160 * Change the spacing of the brush. 161 * @param spacing a spacing of 1.0 means that strokes will be separated from one time the size 162 * of the brush. 163 */ 164 virtual void setSpacing(double spacing); 165 166 /** 167 * @return the spacing between two strokes for this brush 168 */ 169 double spacing() const; 170 171 void setAutoSpacing(bool active, qreal coeff); 172 173 bool autoSpacingActive() const; 174 qreal autoSpacingCoeff() const; 175 176 177 /** 178 * @return the width (for scale == 1.0) 179 */ 180 qint32 width() const; 181 182 /** 183 * @return the height (for scale == 1.0) 184 */ 185 qint32 height() const; 186 187 /** 188 * @return the width of the mask for the given scale and angle 189 */ 190 virtual qint32 maskWidth(KisDabShape const&, qreal subPixelX, qreal subPixelY, const KisPaintInformation& info) const; 191 192 /** 193 * @return the height of the mask for the given scale and angle 194 */ 195 virtual qint32 maskHeight(KisDabShape const&, qreal subPixelX, qreal subPixelY, const KisPaintInformation& info) const; 196 197 /** 198 * @return the logical size of the brush, that is the size measured 199 * in floating point value. 200 * 201 * This value should not be used for calculating future dab sizes 202 * because it doesn't take any rounding into account. The only use 203 * of this metric is calculation of brush-size derivatives like 204 * hotspots and spacing. 205 */ 206 virtual QSizeF characteristicSize(KisDabShape const&) const; 207 208 /** 209 * @return the angle of the mask adding the given angle 210 */ 211 double maskAngle(double angle = 0) const; 212 213 /** 214 * @return the currently selected index of the brush 215 * if the brush consists of multiple images 216 * 217 * @see prepareForSeqNo() 218 */ 219 virtual quint32 brushIndex() const; 220 221 /** 222 * The brush type defines how the brush is used. 223 */ 224 virtual enumBrushType brushType() const; 225 226 QPointF hotSpot(KisDabShape const&, const KisPaintInformation& info) const; 227 228 /** 229 * Returns true if this brush can return something useful for the info. This is used 230 * by Pipe Brushes that can't paint sometimes 231 **/ 232 virtual bool canPaintFor(const KisPaintInformation& /*info*/); 233 234 235 /** 236 * Is called by the paint op when a paintop starts a stroke. The 237 * point is that we store brushes a server while the paint ops are 238 * are recreated all the time. Is means that upon a stroke start 239 * the brushes may need to clear its state. 240 */ 241 virtual void notifyStrokeStarted(); 242 243 /** 244 * Is called by the multithreaded queue to prepare a specific brush 245 * tip for the particular seqNo. 246 * 247 * NOTE: one should use always call prepareForSeqNo() before using the brush 248 * 249 * Currently, this is used by pipe'd brushes to implement 250 * incremental and random parasites 251 */ 252 virtual void prepareForSeqNo(const KisPaintInformation& info, int seqNo); 253 254 /** 255 * Notify the brush if it can use QtConcurrent's threading capabilities in its 256 * internal routines. By default it is allowed, but some paintops (who do their 257 * own multithreading) may ask the brush to avoid internal threading. 258 */ 259 void setThreadingAllowed(bool value); 260 261 /** 262 * \see setThreadingAllowed() for details 263 */ 264 bool threadingAllowed() const; 265 266 /** 267 * Return a fixed paint device that contains a correctly scaled image dab. 268 */ 269 virtual KisFixedPaintDeviceSP paintDevice(const KoColorSpace * colorSpace, 270 KisDabShape const&, 271 const KisPaintInformation& info, 272 double subPixelX = 0, double subPixelY = 0) const; 273 274 /** 275 * clear dst fill it with a mask colored with KoColor 276 */ 277 void mask(KisFixedPaintDeviceSP dst, 278 const KoColor& color, 279 KisDabShape const& shape, 280 const KisPaintInformation& info, 281 double subPixelX = 0, double subPixelY = 0, 282 qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR, qreal lightnessStrength = DEFAULT_LIGHTNESS_STRENGTH) const; 283 284 /** 285 * clear dst and fill it with a mask colored with the corresponding colors of src 286 */ 287 void mask(KisFixedPaintDeviceSP dst, 288 const KisPaintDeviceSP src, 289 KisDabShape const& shape, 290 const KisPaintInformation& info, 291 double subPixelX = 0, double subPixelY = 0, 292 qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR, qreal lightnessStrength = DEFAULT_LIGHTNESS_STRENGTH) const; 293 294 295 virtual enumBrushApplication brushApplication() const; 296 297 virtual void setBrushApplication(enumBrushApplication brushApplication); 298 299 virtual bool preserveLightness() const; 300 301 virtual bool applyingGradient() const; 302 303 virtual void setGradient(const KoAbstractGradient* gradient); 304 305 306 /** 307 * Create a mask and either mask dst (that is, change all alpha values of the 308 * existing pixels to those of the mask) or, if coloringInfo is present, clear 309 * dst and fill dst with pixels according to coloringInfo, masked according to the 310 * generated mask. 311 * 312 * @param dst the destination that will be draw on the image, and this function 313 * will edit its alpha channel 314 * @param coloringInfo coloring information that will be copied on the dab, it can be null 315 * @param shape a shape applied on the alpha mask 316 * @param info the painting information (this is only and should only be used by 317 * KisImagePipeBrush and only to be backward compatible with the Gimp, 318 * KisImagePipeBrush is ignoring scale and angle information) 319 * @param subPixelX sub position of the brush (contained between 0.0 and 1.0) 320 * @param subPixelY sub position of the brush (contained between 0.0 and 1.0) 321 * @param softnessFactor softness factor of the brush 322 * 323 * @return a mask computed from the grey-level values of the 324 * pixels in the brush. 325 */ 326 virtual void generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, 327 ColoringInformation* coloringInfo, 328 KisDabShape const&, 329 const KisPaintInformation& info, 330 double subPixelX, double subPixelY, 331 qreal softnessFactor, qreal lightnessStrength) const; 332 333 void generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, 334 ColoringInformation* coloringInfo, 335 KisDabShape const&, 336 const KisPaintInformation& info, 337 double subPixelX = 0, double subPixelY = 0, 338 qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR) const; 339 340 341 /** 342 * Serialize this brush to XML. 343 */ 344 virtual void toXML(QDomDocument& , QDomElement&) const; 345 346 static KisBrushSP fromXML(const QDomElement& element); 347 348 virtual const KisBoundary* boundary() const; 349 virtual QPainterPath outline() const; 350 351 virtual void setScale(qreal _scale); 352 qreal scale() const; 353 virtual void setAngle(qreal _angle); 354 qreal angle() const; 355 356 void clearBrushPyramid(); 357 358 virtual void lodLimitations(KisPaintopLodLimitations *l) const; 359 360 virtual KisBrush* clone() const = 0; 361 362 virtual bool supportsCaching() const; 363 364 protected: 365 366 KisBrush(const KisBrush& rhs); 367 368 void setWidth(qint32 width); 369 370 void setHeight(qint32 height); 371 372 void setHotSpot(QPointF); 373 374 /** 375 * XXX 376 */ 377 virtual void setBrushType(enumBrushType type); 378 379 public: 380 381 /** 382 * The image is used to represent the brush in the gui, and may also, depending on the brush type 383 * be used to define the actual brush instance. 384 */ 385 virtual void setBrushTipImage(const QImage& image); 386 387 /** 388 * Returns true if the brush has a bunch of pixels almost 389 * fully transparent in the very center. If the brush is pierced, 390 * then dulling mode may not work correctly due to empty samples. 391 * 392 * WARNING: this method is relatively expensive since it iterates 393 * up to 100 pixels of the brush. 394 */ 395 bool isPiercedApprox() const; 396 397 protected: 398 399 void resetBoundary(); 400 401 void predefinedBrushToXML(const QString &type, QDomElement& e) const; 402 403 private: 404 405 // Initialize our boundary 406 void generateBoundary() const; 407 408 struct Private; 409 Private* const d; 410 411 }; 412 413 414 #endif // KIS_BRUSH_ 415 416