1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the examples of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of The Qt Company Ltd nor the names of its
21 **     contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #ifndef CONTEXT2D_H
42 #define CONTEXT2D_H
43 
44 #include "domimage.h"
45 
46 #include <QPainter>
47 #include <QPainterPath>
48 #include <QString>
49 #include <QStack>
50 #include <QMetaType>
51 #include <QTimerEvent>
52 
53 // [3]
54 class CanvasGradient
55 {
56 public:
CanvasGradient(const QGradient & v)57     CanvasGradient(const QGradient &v)
58         : value(v) {}
CanvasGradient()59     CanvasGradient() {}
60 
61     QGradient value;
62 };
63 // [3]
64 
65 Q_DECLARE_METATYPE(CanvasGradient)
Q_DECLARE_METATYPE(CanvasGradient *)66 Q_DECLARE_METATYPE(CanvasGradient*)
67 
68 class ImageData {
69 };
70 
71 class QContext2DCanvas;
72 
73 //! [0]
74 class Context2D : public QObject
75 {
76     Q_OBJECT
77     // compositing
78     Q_PROPERTY(qreal globalAlpha READ globalAlpha WRITE setGlobalAlpha)
79     Q_PROPERTY(QString globalCompositeOperation READ globalCompositeOperation WRITE setGlobalCompositeOperation)
80     Q_PROPERTY(QVariant strokeStyle READ strokeStyle WRITE setStrokeStyle)
81     Q_PROPERTY(QVariant fillStyle READ fillStyle WRITE setFillStyle)
82     // line caps/joins
83     Q_PROPERTY(qreal lineWidth READ lineWidth WRITE setLineWidth)
84     Q_PROPERTY(QString lineCap READ lineCap WRITE setLineCap)
85     Q_PROPERTY(QString lineJoin READ lineJoin WRITE setLineJoin)
86     Q_PROPERTY(qreal miterLimit READ miterLimit WRITE setMiterLimit)
87     // shadows
88     Q_PROPERTY(qreal shadowOffsetX READ shadowOffsetX WRITE setShadowOffsetX)
89     Q_PROPERTY(qreal shadowOffsetY READ shadowOffsetY WRITE setShadowOffsetY)
90     Q_PROPERTY(qreal shadowBlur READ shadowBlur WRITE setShadowBlur)
91     Q_PROPERTY(QString shadowColor READ shadowColor WRITE setShadowColor)
92 //! [0]
93 
94 public:
95     Context2D(QObject *parent = 0);
96     void setSize(int width, int height);
97     void setSize(const QSize &size);
98     QSize size() const;
99 
100     void clear();
101     void reset();
102 
103     // compositing
104     qreal globalAlpha() const; // (default 1.0)
105     QString globalCompositeOperation() const; // (default over)
106     QVariant strokeStyle() const; // (default black)
107     QVariant fillStyle() const; // (default black)
108 
109     void setGlobalAlpha(qreal alpha);
110     void setGlobalCompositeOperation(const QString &op);
111     void setStrokeStyle(const QVariant &style);
112     void setFillStyle(const QVariant &style);
113 
114     // line caps/joins
115     qreal lineWidth() const; // (default 1)
116     QString lineCap() const; // "butt", "round", "square" (default "butt")
117     QString lineJoin() const; // "round", "bevel", "miter" (default "miter")
118     qreal miterLimit() const; // (default 10)
119 
120     void setLineWidth(qreal w);
121     void setLineCap(const QString &s);
122     void setLineJoin(const QString &s);
123     void setMiterLimit(qreal m);
124 
125     // shadows
126     qreal shadowOffsetX() const; // (default 0)
127     qreal shadowOffsetY() const; // (default 0)
128     qreal shadowBlur() const; // (default 0)
129     QString shadowColor() const; // (default black)
130 
131     void setShadowOffsetX(qreal x);
132     void setShadowOffsetY(qreal y);
133     void setShadowBlur(qreal b);
134     void setShadowColor(const QString &str);
135 
136 //! [1]
137 public slots:
138     void save(); // push state on state stack
139     void restore(); // pop state stack and restore state
140 
141     void scale(qreal x, qreal y);
142     void rotate(qreal angle);
143     void translate(qreal x, qreal y);
144     void transform(qreal m11, qreal m12, qreal m21, qreal m22,
145                    qreal dx, qreal dy);
146     void setTransform(qreal m11, qreal m12, qreal m21, qreal m22,
147                       qreal dx, qreal dy);
148 
149     CanvasGradient createLinearGradient(qreal x0, qreal y0,
150                                         qreal x1, qreal y1);
151     CanvasGradient createRadialGradient(qreal x0, qreal y0,
152                                         qreal r0, qreal x1,
153                                         qreal y1, qreal r1);
154 
155     // rects
156     void clearRect(qreal x, qreal y, qreal w, qreal h);
157     void fillRect(qreal x, qreal y, qreal w, qreal h);
158     void strokeRect(qreal x, qreal y, qreal w, qreal h);
159 
160     // path API
161     void beginPath();
162     void closePath();
163     void moveTo(qreal x, qreal y);
164     void lineTo(qreal x, qreal y);
165     void quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y);
166     void bezierCurveTo(qreal cp1x, qreal cp1y,
167                        qreal cp2x, qreal cp2y, qreal x, qreal y);
168     void arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius);
169     void rect(qreal x, qreal y, qreal w, qreal h);
170     void arc(qreal x, qreal y, qreal radius,
171              qreal startAngle, qreal endAngle,
172              bool anticlockwise);
173     void fill();
174     void stroke();
175     void clip();
176     bool isPointInPath(qreal x, qreal y) const;
177 //! [1]
178 
179     // drawing images
180     void drawImage(DomImage *image, qreal dx, qreal dy);
181     void drawImage(DomImage *image, qreal dx, qreal dy,
182                    qreal dw, qreal dh);
183     void drawImage(DomImage *image, qreal sx, qreal sy,
184                    qreal sw, qreal sh, qreal dx, qreal dy,
185                    qreal dw, qreal dh);
186 
187     // pixel manipulation
188     ImageData getImageData(qreal sx, qreal sy, qreal sw, qreal sh);
189     void putImageData(ImageData image, qreal dx, qreal dy);
190 
191 //! [2]
192 signals:
193     void changed(const QImage &image);
194 //! [2]
195 
196 protected:
197     void timerEvent(QTimerEvent *e);
198 
199 private:
200     void beginPainting();
201     const QImage &endPainting();
202     void scheduleChange();
203 
204     int m_changeTimerId;
205     QImage  m_image;
206     QPainter m_painter;
207     QPainterPath m_path;
208 
209     enum DirtyFlag {
210         DirtyTransformationMatrix = 0x00001,
211         DirtyClippingRegion       = 0x00002,
212         DirtyStrokeStyle          = 0x00004,
213         DirtyFillStyle            = 0x00008,
214         DirtyGlobalAlpha          = 0x00010,
215         DirtyLineWidth            = 0x00020,
216         DirtyLineCap              = 0x00040,
217         DirtyLineJoin             = 0x00080,
218         DirtyMiterLimit           = 0x00100,
219         MDirtyPen                 = DirtyStrokeStyle
220                                   | DirtyLineWidth
221                                   | DirtyLineCap
222                                   | DirtyLineJoin
223                                   | DirtyMiterLimit,
224         DirtyShadowOffsetX        = 0x00200,
225         DirtyShadowOffsetY        = 0x00400,
226         DirtyShadowBlur           = 0x00800,
227         DirtyShadowColor          = 0x01000,
228         DirtyGlobalCompositeOperation = 0x2000,
229         DirtyFont                 = 0x04000,
230         DirtyTextAlign            = 0x08000,
231         DirtyTextBaseline         = 0x10000,
232         AllIsFullOfDirt           = 0xfffff
233     };
234 
235     struct State {
StateState236         State() : flags(0) {}
237         QMatrix matrix;
238         QPainterPath clipPath;
239         QBrush strokeStyle;
240         QBrush fillStyle;
241         qreal globalAlpha;
242         qreal lineWidth;
243         Qt::PenCapStyle lineCap;
244         Qt::PenJoinStyle lineJoin;
245         qreal miterLimit;
246         qreal shadowOffsetX;
247         qreal shadowOffsetY;
248         qreal shadowBlur;
249         QColor shadowColor;
250         QPainter::CompositionMode globalCompositeOperation;
251         QFont font;
252         int textAlign;
253         int textBaseline;
254         int flags;
255     };
256     State m_state;
257     QStack<State> m_stateStack;
258 };
259 
260 #endif
261