ad538cd790b476ec3218a9216a6b56689e0b687d
[WebKit-https.git] / Source / WebCore / html / canvas / CanvasRenderingContext2DBase.h
1 /*
2  * Copyright (C) 2006, 2007, 2009, 2010, 2011, 2012, 2017 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 #pragma once
27
28 #include "AffineTransform.h"
29 #include "CanvasDirection.h"
30 #include "CanvasFillRule.h"
31 #include "CanvasLineCap.h"
32 #include "CanvasLineJoin.h"
33 #include "CanvasPath.h"
34 #include "CanvasRenderingContext.h"
35 #include "CanvasStyle.h"
36 #include "CanvasTextAlign.h"
37 #include "CanvasTextBaseline.h"
38 #include "Color.h"
39 #include "FloatSize.h"
40 #include "FontCascade.h"
41 #include "FontSelectorClient.h"
42 #include "GraphicsContext.h"
43 #include "GraphicsTypes.h"
44 #include "ImageBuffer.h"
45 #include "ImageSmoothingQuality.h"
46 #include "Path.h"
47 #include "PlatformLayer.h"
48 #include <wtf/Vector.h>
49 #include <wtf/text/WTFString.h>
50
51 namespace WebCore {
52
53 class CanvasBase;
54 class CanvasGradient;
55 class CanvasPattern;
56 class DOMMatrix;
57 class FloatRect;
58 class GraphicsContext;
59 class HTMLImageElement;
60 class HTMLVideoElement;
61 class ImageBitmap;
62 class ImageData;
63 class Path2D;
64 class RenderStyle;
65 class TextMetrics;
66
67 struct DOMMatrix2DInit;
68
69 #if ENABLE(VIDEO)
70 using CanvasImageSource = Variant<RefPtr<HTMLImageElement>, RefPtr<HTMLVideoElement>, RefPtr<HTMLCanvasElement>, RefPtr<ImageBitmap>>;
71 #else
72 using CanvasImageSource = Variant<RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>, RefPtr<ImageBitmap>>;
73 #endif
74
75 class CanvasRenderingContext2DBase : public CanvasRenderingContext, public CanvasPath {
76 public:
77     CanvasRenderingContext2DBase(CanvasBase&, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode);
78     virtual ~CanvasRenderingContext2DBase();
79
80     float lineWidth() const;
81     void setLineWidth(float);
82
83     CanvasLineCap lineCap() const;
84     void setLineCap(CanvasLineCap);
85     void setLineCap(const String&);
86
87     CanvasLineJoin lineJoin() const;
88     void setLineJoin(CanvasLineJoin);
89     void setLineJoin(const String&);
90
91     float miterLimit() const;
92     void setMiterLimit(float);
93
94     const Vector<float>& getLineDash() const;
95     void setLineDash(const Vector<float>&);
96     const Vector<float>& webkitLineDash() const { return getLineDash(); }
97     void setWebkitLineDash(const Vector<float>&);
98
99     float lineDashOffset() const;
100     void setLineDashOffset(float);
101
102     float shadowOffsetX() const;
103     void setShadowOffsetX(float);
104
105     float shadowOffsetY() const;
106     void setShadowOffsetY(float);
107
108     float shadowBlur() const;
109     void setShadowBlur(float);
110
111     String shadowColor() const;
112     void setShadowColor(const String&);
113
114     float globalAlpha() const;
115     void setGlobalAlpha(float);
116
117     String globalCompositeOperation() const;
118     void setGlobalCompositeOperation(const String&);
119
120     void save() { ++m_unrealizedSaveCount; }
121     void restore();
122
123     void scale(float sx, float sy);
124     void rotate(float angleInRadians);
125     void translate(float tx, float ty);
126     void transform(float m11, float m12, float m21, float m22, float dx, float dy);
127
128     Ref<DOMMatrix> getTransform() const;
129     void setTransform(float m11, float m12, float m21, float m22, float dx, float dy);
130     ExceptionOr<void> setTransform(DOMMatrix2DInit&&);
131     void resetTransform();
132
133     void setStrokeColor(const String& color, std::optional<float> alpha = std::nullopt);
134     void setStrokeColor(float grayLevel, float alpha = 1.0);
135     void setStrokeColor(float r, float g, float b, float a);
136     void setStrokeColor(float c, float m, float y, float k, float a);
137
138     void setFillColor(const String& color, std::optional<float> alpha = std::nullopt);
139     void setFillColor(float grayLevel, float alpha = 1.0f);
140     void setFillColor(float r, float g, float b, float a);
141     void setFillColor(float c, float m, float y, float k, float a);
142
143     void beginPath();
144
145     void fill(CanvasFillRule = CanvasFillRule::Nonzero);
146     void stroke();
147     void clip(CanvasFillRule = CanvasFillRule::Nonzero);
148
149     void fill(Path2D&, CanvasFillRule = CanvasFillRule::Nonzero);
150     void stroke(Path2D&);
151     void clip(Path2D&, CanvasFillRule = CanvasFillRule::Nonzero);
152
153     bool isPointInPath(float x, float y, CanvasFillRule = CanvasFillRule::Nonzero);
154     bool isPointInStroke(float x, float y);
155
156     bool isPointInPath(Path2D&, float x, float y, CanvasFillRule = CanvasFillRule::Nonzero);
157     bool isPointInStroke(Path2D&, float x, float y);
158
159     void clearRect(float x, float y, float width, float height);
160     void fillRect(float x, float y, float width, float height);
161     void strokeRect(float x, float y, float width, float height);
162
163     void setShadow(float width, float height, float blur, const String& color = String(), std::optional<float> alpha = std::nullopt);
164     void setShadow(float width, float height, float blur, float grayLevel, float alpha = 1.0);
165     void setShadow(float width, float height, float blur, float r, float g, float b, float a);
166     void setShadow(float width, float height, float blur, float c, float m, float y, float k, float a);
167
168     void clearShadow();
169
170     ExceptionOr<void> drawImage(CanvasImageSource&&, float dx, float dy);
171     ExceptionOr<void> drawImage(CanvasImageSource&&, float dx, float dy, float dw, float dh);
172     ExceptionOr<void> drawImage(CanvasImageSource&&, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh);
173
174     void drawImageFromRect(HTMLImageElement&, float sx = 0, float sy = 0, float sw = 0, float sh = 0, float dx = 0, float dy = 0, float dw = 0, float dh = 0, const String& compositeOperation = emptyString());
175
176     using Style = Variant<String, RefPtr<CanvasGradient>, RefPtr<CanvasPattern>>;
177     Style strokeStyle() const;
178     void setStrokeStyle(Style&&);
179     Style fillStyle() const;
180     void setFillStyle(Style&&);
181
182     ExceptionOr<Ref<CanvasGradient>> createLinearGradient(float x0, float y0, float x1, float y1);
183     ExceptionOr<Ref<CanvasGradient>> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1);
184     ExceptionOr<RefPtr<CanvasPattern>> createPattern(CanvasImageSource&&, const String& repetition);
185
186     RefPtr<ImageData> createImageData(ImageData&) const;
187     ExceptionOr<RefPtr<ImageData>> createImageData(float width, float height) const;
188     ExceptionOr<RefPtr<ImageData>> getImageData(float sx, float sy, float sw, float sh) const;
189     void putImageData(ImageData&, float dx, float dy);
190     void putImageData(ImageData&, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight);
191
192     float webkitBackingStorePixelRatio() const { return 1; }
193
194     void reset();
195
196     LineCap getLineCap() const { return state().lineCap; }
197     LineJoin getLineJoin() const { return state().lineJoin; }
198
199     bool imageSmoothingEnabled() const;
200     void setImageSmoothingEnabled(bool);
201
202     ImageSmoothingQuality imageSmoothingQuality() const;
203     void setImageSmoothingQuality(ImageSmoothingQuality);
204
205     void setPath(Path2D&);
206     Ref<Path2D> getPath() const;
207
208     bool usesDisplayListDrawing() const { return m_usesDisplayListDrawing; };
209     void setUsesDisplayListDrawing(bool flag) { m_usesDisplayListDrawing = flag; };
210
211     bool tracksDisplayListReplay() const { return m_tracksDisplayListReplay; }
212     void setTracksDisplayListReplay(bool);
213
214     String displayListAsText(DisplayList::AsTextFlags) const;
215     String replayDisplayListAsText(DisplayList::AsTextFlags) const;
216
217     using Direction = CanvasDirection;
218
219     class FontProxy : public FontSelectorClient {
220     public:
221         FontProxy() = default;
222         virtual ~FontProxy();
223         FontProxy(const FontProxy&);
224         FontProxy& operator=(const FontProxy&);
225
226         bool realized() const { return m_font.fontSelector(); }
227         void initialize(FontSelector&, const RenderStyle&);
228         const FontMetrics& fontMetrics() const;
229         const FontCascadeDescription& fontDescription() const;
230         float width(const TextRun&, GlyphOverflow* = 0) const;
231         void drawBidiText(GraphicsContext&, const TextRun&, const FloatPoint&, FontCascade::CustomFontNotReadyAction) const;
232
233     private:
234         void update(FontSelector&);
235         void fontsNeedUpdate(FontSelector&) override;
236
237         FontCascade m_font;
238     };
239
240     struct State final {
241         State();
242
243         State(const State&);
244         State& operator=(const State&);
245
246         String unparsedStrokeColor;
247         String unparsedFillColor;
248         CanvasStyle strokeStyle;
249         CanvasStyle fillStyle;
250         float lineWidth;
251         LineCap lineCap;
252         LineJoin lineJoin;
253         float miterLimit;
254         FloatSize shadowOffset;
255         float shadowBlur;
256         Color shadowColor;
257         float globalAlpha;
258         CompositeOperator globalComposite;
259         BlendMode globalBlend;
260         AffineTransform transform;
261         bool hasInvertibleTransform;
262         Vector<float> lineDash;
263         float lineDashOffset;
264         bool imageSmoothingEnabled;
265         ImageSmoothingQuality imageSmoothingQuality;
266
267         // Text state.
268         TextAlign textAlign;
269         TextBaseline textBaseline;
270         Direction direction;
271
272         String unparsedFont;
273         FontProxy font;
274     };
275
276     const State& state() const { return m_stateStack.last(); }
277     const Vector<State, 1>& stateStack();
278
279 protected:
280     static const int DefaultFontSize;
281     static const char* const DefaultFontFamily;
282     static const char* const DefaultFont;
283
284     enum CanvasDidDrawOption {
285         CanvasDidDrawApplyNone = 0,
286         CanvasDidDrawApplyTransform = 1,
287         CanvasDidDrawApplyShadow = 1 << 1,
288         CanvasDidDrawApplyClip = 1 << 2,
289         CanvasDidDrawApplyAll = 0xffffffff
290     };
291
292     bool isFullCanvasCompositeMode(CompositeOperator);
293
294     State& modifiableState() { ASSERT(!m_unrealizedSaveCount || m_stateStack.size() >= MaxSaveCount); return m_stateStack.last(); }
295
296     void applyLineDash() const;
297     void setShadow(const FloatSize& offset, float blur, const Color&);
298     void applyShadow();
299     bool shouldDrawShadows() const;
300
301     void didDraw(const FloatRect&, unsigned options = CanvasDidDrawApplyAll);
302     void didDrawEntireCanvas();
303
304     void paintRenderingResultsToCanvas() override;
305
306     GraphicsContext* drawingContext() const;
307
308     void unwindStateStack();
309     void realizeSaves();
310     void realizeSavesLoop();
311
312     void applyStrokePattern();
313     void applyFillPattern();
314
315     void setStrokeStyle(CanvasStyle);
316     void setFillStyle(CanvasStyle);
317
318     ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLImageElement&, bool repeatX, bool repeatY);
319     ExceptionOr<RefPtr<CanvasPattern>> createPattern(CanvasBase&, bool repeatX, bool repeatY);
320 #if ENABLE(VIDEO)
321     ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLVideoElement&, bool repeatX, bool repeatY);
322 #endif
323     ExceptionOr<RefPtr<CanvasPattern>> createPattern(ImageBitmap&, bool repeatX, bool repeatY);
324
325     ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect);
326     ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const BlendMode&);
327     ExceptionOr<void> drawImage(HTMLCanvasElement&, const FloatRect& srcRect, const FloatRect& dstRect);
328 #if ENABLE(VIDEO)
329     ExceptionOr<void> drawImage(HTMLVideoElement&, const FloatRect& srcRect, const FloatRect& dstRect);
330 #endif
331     ExceptionOr<void> drawImage(ImageBitmap&, const FloatRect& srcRect, const FloatRect& dstRect);
332
333     void beginCompositeLayer();
334     void endCompositeLayer();
335
336     void fillInternal(const Path&, CanvasFillRule);
337     void strokeInternal(const Path&);
338     void clipInternal(const Path&, CanvasFillRule);
339
340     bool isPointInPathInternal(const Path&, float x, float y, CanvasFillRule);
341     bool isPointInStrokeInternal(const Path&, float x, float y);
342
343     void clearCanvas();
344     Path transformAreaToDevice(const Path&) const;
345     Path transformAreaToDevice(const FloatRect&) const;
346     bool rectContainsCanvas(const FloatRect&) const;
347
348     template<class T> IntRect calculateCompositingBufferRect(const T&, IntSize*);
349     std::unique_ptr<ImageBuffer> createCompositingBuffer(const IntRect&);
350     void compositeBuffer(ImageBuffer&, const IntRect&, CompositeOperator);
351
352     void inflateStrokeRect(FloatRect&) const;
353
354     template<class T> void fullCanvasCompositedDrawImage(T&, const FloatRect&, const FloatRect&, CompositeOperator);
355
356     void prepareGradientForDashboard(CanvasGradient&) const;
357
358     ExceptionOr<RefPtr<ImageData>> getImageData(ImageBuffer::CoordinateSystem, float sx, float sy, float sw, float sh) const;
359     void putImageData(ImageData&, ImageBuffer::CoordinateSystem, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight);
360
361     bool isAccelerated() const override;
362
363     bool hasInvertibleTransform() const override { return state().hasInvertibleTransform; }
364
365 #if ENABLE(ACCELERATED_2D_CANVAS)
366     PlatformLayer* platformLayer() const override;
367 #endif
368
369     void clearPathForDashboardBackwardCompatibilityMode();
370
371     static const unsigned MaxSaveCount = 1024 * 16;
372     Vector<State, 1> m_stateStack;
373     unsigned m_unrealizedSaveCount { 0 };
374     bool m_usesCSSCompatibilityParseMode;
375 #if ENABLE(DASHBOARD_SUPPORT)
376     bool m_usesDashboardCompatibilityMode;
377 #endif
378     bool m_usesDisplayListDrawing { false };
379     bool m_tracksDisplayListReplay { false };
380     mutable std::unique_ptr<struct DisplayListDrawingContext> m_recordingContext;
381 };
382
383 } // namespace WebCore
384