summaryrefslogtreecommitdiffstats
path: root/krita/core/kis_brush.h
blob: 7de2c8b72c2b1531f9bc97de15d736126844c564 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
 *  Copyright (c) 1999 Matthias Elter  <me@kde.org>
 *  Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
 *  Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
#ifndef KIS_BRUSH_
#define KIS_BRUSH_

#include <qcstring.h>
#include <qstring.h>
#include <qsize.h>
#include <qimage.h>
#include <qvaluevector.h>

#include <kio/job.h>

#include "kis_resource.h"
#include "kis_types.h"
#include "kis_point.h"
#include "kis_alpha_mask.h"
#include "koffice_export.h"
#include "kis_boundary.h"
#include "kis_paintop.h"

class QPoint;
class QPixmap;
class KisBoundary;
class KisColorSpace;
class QIODevice;

enum enumBrushType {
    INVALID,
    MASK,
    IMAGE,
    PIPE_MASK,
    PIPE_IMAGE,
    AIRBRUSH
};

class KRITACORE_EXPORT KisBrush : public KisResource {
    typedef KisResource super;
    Q_OBJECT

public:
    /// Construct brush to load filename later as brush
    KisBrush(const QString& filename);
    /// Load brush from the specified data, at position dataPos, and set the filename
    KisBrush(const QString& filename,
         const QByteArray & data,
         Q_UINT32 & dataPos);
    /// Load brush from the specified paint device, in the specified region
    KisBrush(KisPaintDevice* image, int x, int y, int w, int h);
    /// Load brush as a copy from the specified QImage (handy when you need to copy a brush!)
    KisBrush(const QImage& image, const QString& name = QString(""));

    virtual ~KisBrush();

    virtual bool load();
    /// synchronous, doesn't emit any signal (none defined!)
    virtual bool save();
    virtual QImage img();
    virtual bool saveToDevice(QIODevice* dev) const;

    /**
       @return a mask computed from the grey-level values of the
       pixels in the brush.
    */
    virtual KisAlphaMaskSP mask(const KisPaintInformation& info,
                                double subPixelX = 0, double subPixelY = 0) const;
    // XXX: return non-tiled simple buffer
    virtual KisPaintDeviceSP image(KisColorSpace * colorSpace, const KisPaintInformation& info,
                             double subPixelX = 0, double subPixelY = 0) const;

    void setHotSpot(KisPoint);
    KisPoint hotSpot(const KisPaintInformation& info = KisPaintInformation()) const;

    void setSpacing(double s) { m_spacing = s; }
    double spacing() const { return m_spacing; }
    double xSpacing(double pressure = PRESSURE_DEFAULT) const;
    double ySpacing(double pressure = PRESSURE_DEFAULT) const;

    // Dimensions in pixels of the mask/image at a given pressure.
    Q_INT32 maskWidth(const KisPaintInformation& info) const;
    Q_INT32 maskHeight(const KisPaintInformation& info) const;

    virtual void setUseColorAsMask(bool useColorAsMask) { m_useColorAsMask = useColorAsMask; }
    virtual bool useColorAsMask() const { return m_useColorAsMask; }
    virtual bool hasColor() const;

    virtual void makeMaskImage();
    Q_INT32 width() const;
    Q_INT32 height() const;

    virtual enumBrushType brushType() const;

    //QImage outline(double pressure = PRESSURE_DEFAULT);
    virtual KisBoundary boundary();

    /**
     * Returns true if this brush can return something useful for the info. This is used
     * by Pipe Brushes that can't paint sometimes
     **/
    virtual bool canPaintFor(const KisPaintInformation& /*info*/) { return true; }

    virtual KisBrush* clone() const;

protected:
    void setWidth(Q_INT32 w);
    void setHeight(Q_INT32 h);
    void setImage(const QImage& img);
    void setBrushType(enumBrushType type) { m_brushType = type; };
    static double scaleForPressure(double pressure);

private:
    class ScaledBrush {
    public:
        ScaledBrush();
        ScaledBrush(KisAlphaMaskSP scaledMask, const QImage& scaledImage, double scale, double xScale, double yScale);

        double scale() const { return m_scale; }
        double xScale() const { return m_xScale; }
        double yScale() const { return m_yScale; }
        KisAlphaMaskSP mask() const { return m_mask; }
        QImage image() const { return m_image; }

    private:
        KisAlphaMaskSP m_mask;
        QImage m_image;
        double m_scale;
        double m_xScale;
        double m_yScale;
    };


    bool init();
    bool initFromPaintDev(KisPaintDevice* image, int x, int y, int w, int h);
    void createScaledBrushes() const;

    KisAlphaMaskSP scaleMask(const ScaledBrush *srcBrush, double scale, double subPixelX, double subPixelY) const;
    QImage scaleImage(const ScaledBrush *srcBrush, double scale, double subPixelX, double subPixelY) const;

    static QImage scaleImage(const QImage& srcImage, int width, int height);
    static QImage interpolate(const QImage& image1, const QImage& image2, double t);

    static KisAlphaMaskSP scaleSinglePixelMask(double scale, Q_UINT8 maskValue, double subPixelX, double subPixelY);
    static QImage scaleSinglePixelImage(double scale, QRgb pixel, double subPixelX, double subPixelY);

    // Find the scaled brush(es) nearest to the given scale.
    void findScaledBrushes(double scale, const ScaledBrush **aboveBrush, const ScaledBrush **belowBrush) const;

    // Initialize our boundary
    void generateBoundary();

    QByteArray m_data;
    bool m_ownData;
    KisPoint m_hotSpot;
    double m_spacing;
    bool m_useColorAsMask;
    bool m_hasColor;
    QImage m_img;
    mutable QValueVector<ScaledBrush> m_scaledBrushes;

    Q_INT32 m_width;
    Q_INT32 m_height;

    Q_UINT32 m_header_size;  /*  header_size = sizeof (BrushHeader) + brush name  */
    Q_UINT32 m_version;      /*  brush file version #  */
    Q_UINT32 m_bytes;        /*  depth of brush in bytes */
    Q_UINT32 m_magic_number; /*  GIMP brush magic number  */

    enumBrushType m_brushType;

    KisBoundary* m_boundary;

};
#endif // KIS_BRUSH_