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