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