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 TypedOMCSSImageValue; |
54 | class CachedImage; |
55 | class CanvasBase; |
56 | class CanvasGradient; |
57 | class CanvasPattern; |
58 | class DOMMatrix; |
59 | class FloatRect; |
60 | class GraphicsContext; |
61 | class HTMLImageElement; |
62 | class HTMLVideoElement; |
63 | class ImageBitmap; |
64 | class ImageData; |
65 | class Path2D; |
66 | class RenderStyle; |
67 | class RenderObject; |
68 | class TextMetrics; |
69 | |
70 | struct DOMMatrix2DInit; |
71 | |
72 | #if ENABLE(VIDEO) && ENABLE(CSS_TYPED_OM) |
73 | using CanvasImageSource = Variant<RefPtr<HTMLImageElement>, RefPtr<HTMLVideoElement>, RefPtr<HTMLCanvasElement>, RefPtr<ImageBitmap>, RefPtr<TypedOMCSSImageValue>>; |
74 | #elif ENABLE(VIDEO) |
75 | using CanvasImageSource = Variant<RefPtr<HTMLImageElement>, RefPtr<HTMLVideoElement>, RefPtr<HTMLCanvasElement>, RefPtr<ImageBitmap>>; |
76 | #else |
77 | using CanvasImageSource = Variant<RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>, RefPtr<ImageBitmap>>; |
78 | #endif |
79 | |
80 | class CanvasRenderingContext2DBase : public CanvasRenderingContext, public CanvasPath { |
81 | WTF_MAKE_ISO_ALLOCATED(CanvasRenderingContext2DBase); |
82 | public: |
83 | CanvasRenderingContext2DBase(CanvasBase&, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode); |
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 | |
285 | protected: |
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 | void prepareGradientForDashboard(CanvasGradient&) const; |
370 | |
371 | ExceptionOr<RefPtr<ImageData>> getImageData(ImageBuffer::CoordinateSystem, float sx, float sy, float sw, float sh) const; |
372 | void putImageData(ImageData&, ImageBuffer::CoordinateSystem, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); |
373 | |
374 | bool isAccelerated() const override; |
375 | |
376 | bool hasInvertibleTransform() const override { return state().hasInvertibleTransform; } |
377 | |
378 | #if ENABLE(ACCELERATED_2D_CANVAS) |
379 | PlatformLayer* platformLayer() const override; |
380 | #endif |
381 | |
382 | void clearPathForDashboardBackwardCompatibilityMode(); |
383 | |
384 | static const unsigned MaxSaveCount = 1024 * 16; |
385 | Vector<State, 1> m_stateStack; |
386 | unsigned m_unrealizedSaveCount { 0 }; |
387 | bool m_usesCSSCompatibilityParseMode; |
388 | #if ENABLE(DASHBOARD_SUPPORT) |
389 | bool m_usesDashboardCompatibilityMode; |
390 | #endif |
391 | bool m_usesDisplayListDrawing { false }; |
392 | bool m_tracksDisplayListReplay { false }; |
393 | mutable std::unique_ptr<struct DisplayListDrawingContext> m_recordingContext; |
394 | }; |
395 | |
396 | } // namespace WebCore |
397 | |
398 | |