1/*
2 * Copyright (C) 2006, 2007, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef CanvasRenderingContext2D_h
27#define CanvasRenderingContext2D_h
28
29#include "AffineTransform.h"
30#include "CanvasPathMethods.h"
31#include "CanvasRenderingContext.h"
32#include "CanvasStyle.h"
33#include "Color.h"
34#include "ColorSpace.h"
35#include "FloatSize.h"
36#include "Font.h"
37#include "GraphicsTypes.h"
38#include "ImageBuffer.h"
39#include "Path.h"
40#include "PlatformLayer.h"
41#include <wtf/Vector.h>
42#include <wtf/text/WTFString.h>
43
44namespace WebCore {
45
46class CanvasGradient;
47class CanvasPattern;
48class DOMPath;
49class FloatRect;
50class GraphicsContext;
51class HTMLCanvasElement;
52class HTMLImageElement;
53class HTMLVideoElement;
54class ImageData;
55class TextMetrics;
56
57typedef int ExceptionCode;
58
59class CanvasRenderingContext2D : public CanvasRenderingContext, public CanvasPathMethods {
60public:
61    CanvasRenderingContext2D(HTMLCanvasElement*, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode);
62    virtual ~CanvasRenderingContext2D();
63
64    const CanvasStyle& strokeStyle() const { return state().m_strokeStyle; }
65    void setStrokeStyle(CanvasStyle);
66
67    const CanvasStyle& fillStyle() const { return state().m_fillStyle; }
68    void setFillStyle(CanvasStyle);
69
70    float lineWidth() const;
71    void setLineWidth(float);
72
73    String lineCap() const;
74    void setLineCap(const String&);
75
76    String lineJoin() const;
77    void setLineJoin(const String&);
78
79    float miterLimit() const;
80    void setMiterLimit(float);
81
82    const Vector<float>& getLineDash() const;
83    void setLineDash(const Vector<float>&);
84    void setWebkitLineDash(const Vector<float>&);
85
86    float lineDashOffset() const;
87    void setLineDashOffset(float);
88    float webkitLineDashOffset() const;
89    void setWebkitLineDashOffset(float);
90
91    float shadowOffsetX() const;
92    void setShadowOffsetX(float);
93
94    float shadowOffsetY() const;
95    void setShadowOffsetY(float);
96
97    float shadowBlur() const;
98    void setShadowBlur(float);
99
100    String shadowColor() const;
101    void setShadowColor(const String&);
102
103    float globalAlpha() const;
104    void setGlobalAlpha(float);
105
106    String globalCompositeOperation() const;
107    void setGlobalCompositeOperation(const String&);
108
109    void save() { ++m_unrealizedSaveCount; }
110    void restore();
111
112    void scale(float sx, float sy);
113    void rotate(float angleInRadians);
114    void translate(float tx, float ty);
115    void transform(float m11, float m12, float m21, float m22, float dx, float dy);
116    void setTransform(float m11, float m12, float m21, float m22, float dx, float dy);
117
118    void setStrokeColor(const String& color);
119    void setStrokeColor(float grayLevel);
120    void setStrokeColor(const String& color, float alpha);
121    void setStrokeColor(float grayLevel, float alpha);
122    void setStrokeColor(float r, float g, float b, float a);
123    void setStrokeColor(float c, float m, float y, float k, float a);
124
125    void setFillColor(const String& color);
126    void setFillColor(float grayLevel);
127    void setFillColor(const String& color, float alpha);
128    void setFillColor(float grayLevel, float alpha);
129    void setFillColor(float r, float g, float b, float a);
130    void setFillColor(float c, float m, float y, float k, float a);
131
132    void beginPath();
133
134    void fill(const String& winding = "nonzero");
135    void stroke();
136    void clip(const String& winding = "nonzero");
137
138    void fill(DOMPath*, const String& winding = "nonzero");
139    void stroke(DOMPath*);
140    void clip(DOMPath*, const String& winding = "nonzero");
141
142    bool isPointInPath(const float x, const float y, const String& winding = "nonzero");
143    bool isPointInStroke(const float x, const float y);
144
145    bool isPointInPath(DOMPath*, const float x, const float y, const String& winding = "nonzero");
146    bool isPointInStroke(DOMPath*, const float x, const float y);
147
148    void clearRect(float x, float y, float width, float height);
149    void fillRect(float x, float y, float width, float height);
150    void strokeRect(float x, float y, float width, float height);
151
152    void setShadow(float width, float height, float blur);
153    void setShadow(float width, float height, float blur, const String& color);
154    void setShadow(float width, float height, float blur, float grayLevel);
155    void setShadow(float width, float height, float blur, const String& color, float alpha);
156    void setShadow(float width, float height, float blur, float grayLevel, float alpha);
157    void setShadow(float width, float height, float blur, float r, float g, float b, float a);
158    void setShadow(float width, float height, float blur, float c, float m, float y, float k, float a);
159
160    void clearShadow();
161
162    void drawImage(HTMLImageElement*, float x, float y, ExceptionCode&);
163    void drawImage(HTMLImageElement*, float x, float y, float width, float height, ExceptionCode&);
164    void drawImage(HTMLImageElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&);
165    void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&);
166    void drawImage(HTMLCanvasElement*, float x, float y, ExceptionCode&);
167    void drawImage(HTMLCanvasElement*, float x, float y, float width, float height, ExceptionCode&);
168    void drawImage(HTMLCanvasElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&);
169    void drawImage(HTMLCanvasElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&);
170    void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const BlendMode&, ExceptionCode&);
171#if ENABLE(VIDEO)
172    void drawImage(HTMLVideoElement*, float x, float y, ExceptionCode&);
173    void drawImage(HTMLVideoElement*, float x, float y, float width, float height, ExceptionCode&);
174    void drawImage(HTMLVideoElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&);
175    void drawImage(HTMLVideoElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&);
176#endif
177
178    void drawImageFromRect(HTMLImageElement*, float sx = 0, float sy = 0, float sw = 0, float sh = 0,
179                           float dx = 0, float dy = 0, float dw = 0, float dh = 0, const String& compositeOperation = emptyString());
180
181    void setAlpha(float);
182
183    void setCompositeOperation(const String&);
184
185    PassRefPtr<CanvasGradient> createLinearGradient(float x0, float y0, float x1, float y1, ExceptionCode&);
186    PassRefPtr<CanvasGradient> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionCode&);
187    PassRefPtr<CanvasPattern> createPattern(HTMLImageElement*, const String& repetitionType, ExceptionCode&);
188    PassRefPtr<CanvasPattern> createPattern(HTMLCanvasElement*, const String& repetitionType, ExceptionCode&);
189
190    PassRefPtr<ImageData> createImageData(PassRefPtr<ImageData>, ExceptionCode&) const;
191    PassRefPtr<ImageData> createImageData(float width, float height, ExceptionCode&) const;
192    PassRefPtr<ImageData> getImageData(float sx, float sy, float sw, float sh, ExceptionCode&) const;
193    PassRefPtr<ImageData> webkitGetImageDataHD(float sx, float sy, float sw, float sh, ExceptionCode&) const;
194    void putImageData(ImageData*, float dx, float dy, ExceptionCode&);
195    void putImageData(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode&);
196    void webkitPutImageDataHD(ImageData*, float dx, float dy, ExceptionCode&);
197    void webkitPutImageDataHD(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode&);
198
199    void drawFocusIfNeeded(Element*);
200
201    float webkitBackingStorePixelRatio() const { return canvas()->deviceScaleFactor(); }
202
203    void reset();
204
205    String font() const;
206    void setFont(const String&);
207
208    String textAlign() const;
209    void setTextAlign(const String&);
210
211    String textBaseline() const;
212    void setTextBaseline(const String&);
213
214    void fillText(const String& text, float x, float y);
215    void fillText(const String& text, float x, float y, float maxWidth);
216    void strokeText(const String& text, float x, float y);
217    void strokeText(const String& text, float x, float y, float maxWidth);
218    PassRefPtr<TextMetrics> measureText(const String& text);
219
220    LineCap getLineCap() const { return state().m_lineCap; }
221    LineJoin getLineJoin() const { return state().m_lineJoin; }
222
223    bool webkitImageSmoothingEnabled() const;
224    void setWebkitImageSmoothingEnabled(bool);
225
226private:
227    struct State : FontSelectorClient {
228        State();
229        virtual ~State();
230
231        State(const State&);
232        State& operator=(const State&);
233
234        virtual void fontsNeedUpdate(FontSelector*) override;
235
236        String m_unparsedStrokeColor;
237        String m_unparsedFillColor;
238        CanvasStyle m_strokeStyle;
239        CanvasStyle m_fillStyle;
240        float m_lineWidth;
241        LineCap m_lineCap;
242        LineJoin m_lineJoin;
243        float m_miterLimit;
244        FloatSize m_shadowOffset;
245        float m_shadowBlur;
246        RGBA32 m_shadowColor;
247        float m_globalAlpha;
248        CompositeOperator m_globalComposite;
249        BlendMode m_globalBlend;
250        AffineTransform m_transform;
251        bool m_hasInvertibleTransform;
252        Vector<float> m_lineDash;
253        float m_lineDashOffset;
254        bool m_imageSmoothingEnabled;
255
256        // Text state.
257        TextAlign m_textAlign;
258        TextBaseline m_textBaseline;
259
260        String m_unparsedFont;
261        Font m_font;
262        bool m_realizedFont;
263    };
264
265    enum CanvasDidDrawOption {
266        CanvasDidDrawApplyNone = 0,
267        CanvasDidDrawApplyTransform = 1,
268        CanvasDidDrawApplyShadow = 1 << 1,
269        CanvasDidDrawApplyClip = 1 << 2,
270        CanvasDidDrawApplyAll = 0xffffffff
271    };
272
273    State& modifiableState() { ASSERT(!m_unrealizedSaveCount); return m_stateStack.last(); }
274    const State& state() const { return m_stateStack.last(); }
275
276    void applyLineDash() const;
277    void setShadow(const FloatSize& offset, float blur, RGBA32 color);
278    void applyShadow();
279    bool shouldDrawShadows() const;
280
281    void didDraw(const FloatRect&, unsigned options = CanvasDidDrawApplyAll);
282    void didDrawEntireCanvas();
283
284    GraphicsContext* drawingContext() const;
285
286    void unwindStateStack();
287    void realizeSaves()
288    {
289        if (m_unrealizedSaveCount)
290            realizeSavesLoop();
291    }
292    void realizeSavesLoop();
293
294    void applyStrokePattern();
295    void applyFillPattern();
296
297    void drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth = 0, bool useMaxWidth = false);
298
299    const Font& accessFont();
300
301#if ENABLE(DASHBOARD_SUPPORT)
302    void clearPathForDashboardBackwardCompatibilityMode();
303#endif
304
305    void beginCompositeLayer();
306    void endCompositeLayer();
307
308    void fillInternal(const Path&, const String& winding);
309    void strokeInternal(const Path&);
310    void clipInternal(const Path&, const String& winding);
311
312    bool isPointInPathInternal(const Path&, float x, float y, const String& winding);
313    bool isPointInStrokeInternal(const Path&, float x, float y);
314
315    void clearCanvas();
316    Path transformAreaToDevice(const Path&) const;
317    Path transformAreaToDevice(const FloatRect&) const;
318    bool rectContainsCanvas(const FloatRect&) const;
319
320    template<class T> IntRect calculateCompositingBufferRect(const T&, IntSize*);
321    std::unique_ptr<ImageBuffer> createCompositingBuffer(const IntRect&);
322    void compositeBuffer(ImageBuffer*, const IntRect&, CompositeOperator);
323
324    void inflateStrokeRect(FloatRect&) const;
325
326    template<class T> void fullCanvasCompositedDrawImage(T*, ColorSpace, const FloatRect&, const FloatRect&, CompositeOperator);
327
328    void prepareGradientForDashboard(CanvasGradient* gradient) const;
329
330    PassRefPtr<ImageData> getImageData(ImageBuffer::CoordinateSystem, float sx, float sy, float sw, float sh, ExceptionCode&) const;
331    void putImageData(ImageData*, ImageBuffer::CoordinateSystem, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode&);
332
333    virtual bool is2d() const override { return true; }
334    virtual bool isAccelerated() const override;
335
336    virtual bool hasInvertibleTransform() const override { return state().m_hasInvertibleTransform; }
337
338#if ENABLE(ACCELERATED_2D_CANVAS)
339    virtual PlatformLayer* platformLayer() const override;
340#endif
341
342    Vector<State, 1> m_stateStack;
343    unsigned m_unrealizedSaveCount;
344    bool m_usesCSSCompatibilityParseMode;
345#if ENABLE(DASHBOARD_SUPPORT)
346    bool m_usesDashboardCompatibilityMode;
347#endif
348};
349
350} // namespace WebCore
351
352#endif
353