Implement new TextMetrics, returned by canvas measureText()
[WebKit-https.git] / Source / WebCore / html / canvas / CanvasRenderingContext2D.h
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 #pragma once
27
28 #include "AffineTransform.h"
29 #include "CanvasPath.h"
30 #include "CanvasRenderingContext.h"
31 #include "CanvasStyle.h"
32 #include "Color.h"
33 #include "FloatSize.h"
34 #include "FontCascade.h"
35 #include "FontSelectorClient.h"
36 #include "GraphicsContext.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
44 namespace WebCore {
45
46 class CanvasGradient;
47 class CanvasPattern;
48 class DOMMatrix;
49 class DOMPath;
50 class FloatRect;
51 class GraphicsContext;
52 class HTMLCanvasElement;
53 class HTMLImageElement;
54 class HTMLVideoElement;
55 class ImageData;
56 class TextMetrics;
57
58 struct DOMMatrixInit;
59
60 #if ENABLE(VIDEO)
61 using CanvasImageSource = Variant<RefPtr<HTMLImageElement>, RefPtr<HTMLVideoElement>, RefPtr<HTMLCanvasElement>>;
62 #else
63 using CanvasImageSource = Variant<RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>>;
64 #endif
65
66 class CanvasRenderingContext2D final : public CanvasRenderingContext, public CanvasPath {
67 public:
68     CanvasRenderingContext2D(HTMLCanvasElement&, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode);
69     virtual ~CanvasRenderingContext2D();
70
71     float lineWidth() const;
72     void setLineWidth(float);
73
74     String lineCap() const;
75     void setLineCap(const String&);
76
77     String lineJoin() const;
78     void setLineJoin(const String&);
79
80     float miterLimit() const;
81     void setMiterLimit(float);
82
83     const Vector<float>& getLineDash() const;
84     void setLineDash(const Vector<float>&);
85     const Vector<float>& webkitLineDash() const { return getLineDash(); }
86     void setWebkitLineDash(const Vector<float>&);
87
88     float lineDashOffset() const;
89     void setLineDashOffset(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     // This is a no-op in a direct-2d canvas.
113     void commit() { }
114
115     void scale(float sx, float sy);
116     void rotate(float angleInRadians);
117     void translate(float tx, float ty);
118     void transform(float m11, float m12, float m21, float m22, float dx, float dy);
119
120     Ref<DOMMatrix> getTransform() const;
121     void setTransform(float m11, float m12, float m21, float m22, float dx, float dy);
122     ExceptionOr<void> setTransform(DOMMatrixInit&&);
123     void resetTransform();
124
125     void setStrokeColor(const String& color, std::optional<float> alpha = std::nullopt);
126     void setStrokeColor(float grayLevel, float alpha = 1.0);
127     void setStrokeColor(float r, float g, float b, float a);
128     void setStrokeColor(float c, float m, float y, float k, float a);
129
130     void setFillColor(const String& color, std::optional<float> alpha = std::nullopt);
131     void setFillColor(float grayLevel, float alpha = 1.0f);
132     void setFillColor(float r, float g, float b, float a);
133     void setFillColor(float c, float m, float y, float k, float a);
134
135     void beginPath();
136
137     enum class WindingRule { Nonzero, Evenodd };
138     static String stringForWindingRule(WindingRule);
139
140     void fill(WindingRule = WindingRule::Nonzero);
141     void stroke();
142     void clip(WindingRule = WindingRule::Nonzero);
143
144     void fill(DOMPath&, WindingRule = WindingRule::Nonzero);
145     void stroke(DOMPath&);
146     void clip(DOMPath&, WindingRule = WindingRule::Nonzero);
147
148     bool isPointInPath(float x, float y, WindingRule = WindingRule::Nonzero);
149     bool isPointInStroke(float x, float y);
150
151     bool isPointInPath(DOMPath&, float x, float y, WindingRule = WindingRule::Nonzero);
152     bool isPointInStroke(DOMPath&, float x, float y);
153
154     void clearRect(float x, float y, float width, float height);
155     void fillRect(float x, float y, float width, float height);
156     void strokeRect(float x, float y, float width, float height);
157
158     void setShadow(float width, float height, float blur, const String& color = String(), std::optional<float> alpha = std::nullopt);
159     void setShadow(float width, float height, float blur, float grayLevel, float alpha = 1.0);
160     void setShadow(float width, float height, float blur, float r, float g, float b, float a);
161     void setShadow(float width, float height, float blur, float c, float m, float y, float k, float a);
162
163     void clearShadow();
164
165     ExceptionOr<void> drawImage(CanvasImageSource&&, float dx, float dy);
166     ExceptionOr<void> drawImage(CanvasImageSource&&, float dx, float dy, float dw, float dh);
167     ExceptionOr<void> drawImage(CanvasImageSource&&, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh);
168
169     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());
170
171     void setAlpha(float);
172
173     void setCompositeOperation(const String&);
174
175     using Style = Variant<String, RefPtr<CanvasGradient>, RefPtr<CanvasPattern>>;
176     Style strokeStyle() const;
177     void setStrokeStyle(Style&&);
178     Style fillStyle() const;
179     void setFillStyle(Style&&);
180
181     ExceptionOr<Ref<CanvasGradient>> createLinearGradient(float x0, float y0, float x1, float y1);
182     ExceptionOr<Ref<CanvasGradient>> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1);
183     ExceptionOr<RefPtr<CanvasPattern>> createPattern(CanvasImageSource&&, const String& repetition);
184
185     ExceptionOr<RefPtr<ImageData>> createImageData(ImageData*) const;
186     ExceptionOr<RefPtr<ImageData>> createImageData(float width, float height) const;
187     ExceptionOr<RefPtr<ImageData>> getImageData(float sx, float sy, float sw, float sh) const;
188     ExceptionOr<RefPtr<ImageData>> webkitGetImageDataHD(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     void webkitPutImageDataHD(ImageData&, float dx, float dy);
192     void webkitPutImageDataHD(ImageData&, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight);
193
194     void drawFocusIfNeeded(Element&);
195     void drawFocusIfNeeded(DOMPath&, Element&);
196
197     float webkitBackingStorePixelRatio() const { return 1; }
198
199     void reset();
200
201     String font() const;
202     void setFont(const String&);
203
204     String textAlign() const;
205     void setTextAlign(const String&);
206
207     String textBaseline() const;
208     void setTextBaseline(const String&);
209
210     String direction() const;
211     void setDirection(const String&);
212
213     void fillText(const String& text, float x, float y, std::optional<float> maxWidth = std::nullopt);
214     void strokeText(const String& text, float x, float y, std::optional<float> maxWidth = std::nullopt);
215     Ref<TextMetrics> measureText(const String& text);
216
217     LineCap getLineCap() const { return state().lineCap; }
218     LineJoin getLineJoin() const { return state().lineJoin; }
219
220     bool imageSmoothingEnabled() const;
221     void setImageSmoothingEnabled(bool);
222
223     enum class ImageSmoothingQuality { Low, Medium, High };
224     static String stringForImageSmoothingQuality(ImageSmoothingQuality);
225
226     ImageSmoothingQuality imageSmoothingQuality() const;
227     void setImageSmoothingQuality(ImageSmoothingQuality);
228
229     bool usesDisplayListDrawing() const { return m_usesDisplayListDrawing; };
230     void setUsesDisplayListDrawing(bool flag) { m_usesDisplayListDrawing = flag; };
231
232     bool tracksDisplayListReplay() const { return m_tracksDisplayListReplay; }
233     void setTracksDisplayListReplay(bool);
234
235     String displayListAsText(DisplayList::AsTextFlags) const;
236     String replayDisplayListAsText(DisplayList::AsTextFlags) const;
237
238     enum class Direction {
239         Inherit,
240         RTL,
241         LTR
242     };
243
244     class FontProxy : public FontSelectorClient {
245     public:
246         FontProxy() = default;
247         virtual ~FontProxy();
248         FontProxy(const FontProxy&);
249         FontProxy& operator=(const FontProxy&);
250
251         bool realized() const { return m_font.fontSelector(); }
252         void initialize(FontSelector&, const RenderStyle&);
253         const FontMetrics& fontMetrics() const;
254         const FontCascadeDescription& fontDescription() const;
255         float width(const TextRun&, GlyphOverflow* = 0) const;
256         void drawBidiText(GraphicsContext&, const TextRun&, const FloatPoint&, FontCascade::CustomFontNotReadyAction) const;
257
258     private:
259         void update(FontSelector&);
260         void fontsNeedUpdate(FontSelector&) override;
261
262         FontCascade m_font;
263     };
264
265     struct State final {
266         State();
267
268         State(const State&);
269         State& operator=(const State&);
270
271         String unparsedStrokeColor;
272         String unparsedFillColor;
273         CanvasStyle strokeStyle;
274         CanvasStyle fillStyle;
275         float lineWidth;
276         LineCap lineCap;
277         LineJoin lineJoin;
278         float miterLimit;
279         FloatSize shadowOffset;
280         float shadowBlur;
281         Color shadowColor;
282         float globalAlpha;
283         CompositeOperator globalComposite;
284         BlendMode globalBlend;
285         AffineTransform transform;
286         bool hasInvertibleTransform;
287         Vector<float> lineDash;
288         float lineDashOffset;
289         bool imageSmoothingEnabled;
290         ImageSmoothingQuality imageSmoothingQuality;
291
292         // Text state.
293         TextAlign textAlign;
294         TextBaseline textBaseline;
295         Direction direction;
296
297         String unparsedFont;
298         FontProxy font;
299     };
300
301     const State& state() const { return m_stateStack.last(); }
302
303 private:
304     enum CanvasDidDrawOption {
305         CanvasDidDrawApplyNone = 0,
306         CanvasDidDrawApplyTransform = 1,
307         CanvasDidDrawApplyShadow = 1 << 1,
308         CanvasDidDrawApplyClip = 1 << 2,
309         CanvasDidDrawApplyAll = 0xffffffff
310     };
311
312     State& modifiableState() { ASSERT(!m_unrealizedSaveCount || m_stateStack.size() >= MaxSaveCount); return m_stateStack.last(); }
313
314     void applyLineDash() const;
315     void setShadow(const FloatSize& offset, float blur, const Color&);
316     void applyShadow();
317     bool shouldDrawShadows() const;
318
319     void didDraw(const FloatRect&, unsigned options = CanvasDidDrawApplyAll);
320     void didDrawEntireCanvas();
321
322     void paintRenderingResultsToCanvas() override;
323
324     GraphicsContext* drawingContext() const;
325
326     void unwindStateStack();
327     void realizeSaves();
328     void realizeSavesLoop();
329
330     void applyStrokePattern();
331     void applyFillPattern();
332
333     void setStrokeStyle(CanvasStyle);
334     void setFillStyle(CanvasStyle);
335
336     ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLImageElement&, bool repeatX, bool repeatY);
337     ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLCanvasElement&, bool repeatX, bool repeatY);
338 #if ENABLE(VIDEO)
339     ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLVideoElement&, bool repeatX, bool repeatY);
340 #endif
341
342     ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect);
343     ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const BlendMode&);
344     ExceptionOr<void> drawImage(HTMLCanvasElement&, const FloatRect& srcRect, const FloatRect& dstRect);
345 #if ENABLE(VIDEO)
346     ExceptionOr<void> drawImage(HTMLVideoElement&, const FloatRect& srcRect, const FloatRect& dstRect);
347 #endif
348
349     void drawTextInternal(const String& text, float x, float y, bool fill, std::optional<float> maxWidth = std::nullopt);
350
351     // The relationship between FontCascade and CanvasRenderingContext2D::FontProxy must hold certain invariants.
352     // Therefore, all font operations must pass through the State.
353     const FontProxy& fontProxy();
354
355     void clearPathForDashboardBackwardCompatibilityMode();
356
357     void beginCompositeLayer();
358     void endCompositeLayer();
359
360     void fillInternal(const Path&, WindingRule);
361     void strokeInternal(const Path&);
362     void clipInternal(const Path&, WindingRule);
363
364     bool isPointInPathInternal(const Path&, float x, float y, WindingRule);
365     bool isPointInStrokeInternal(const Path&, float x, float y);
366
367     void drawFocusIfNeededInternal(const Path&, Element&);
368
369     void clearCanvas();
370     Path transformAreaToDevice(const Path&) const;
371     Path transformAreaToDevice(const FloatRect&) const;
372     bool rectContainsCanvas(const FloatRect&) const;
373
374     template<class T> IntRect calculateCompositingBufferRect(const T&, IntSize*);
375     std::unique_ptr<ImageBuffer> createCompositingBuffer(const IntRect&);
376     void compositeBuffer(ImageBuffer&, const IntRect&, CompositeOperator);
377
378     void inflateStrokeRect(FloatRect&) const;
379
380     template<class T> void fullCanvasCompositedDrawImage(T&, const FloatRect&, const FloatRect&, CompositeOperator);
381
382     void prepareGradientForDashboard(CanvasGradient& gradient) const;
383
384     ExceptionOr<RefPtr<ImageData>> getImageData(ImageBuffer::CoordinateSystem, float sx, float sy, float sw, float sh) const;
385     void putImageData(ImageData&, ImageBuffer::CoordinateSystem, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight);
386
387     bool is2d() const override { return true; }
388     bool isAccelerated() const override;
389
390     bool hasInvertibleTransform() const override { return state().hasInvertibleTransform; }
391     TextDirection toTextDirection(Direction, const RenderStyle** computedStyle = nullptr) const;
392
393     FloatPoint textOffset(float width, TextDirection);
394
395 #if ENABLE(ACCELERATED_2D_CANVAS)
396     PlatformLayer* platformLayer() const override;
397 #endif
398
399     static const unsigned MaxSaveCount = 1024 * 16;
400     Vector<State, 1> m_stateStack;
401     unsigned m_unrealizedSaveCount { 0 };
402     bool m_usesCSSCompatibilityParseMode;
403 #if ENABLE(DASHBOARD_SUPPORT)
404     bool m_usesDashboardCompatibilityMode;
405 #endif
406     bool m_usesDisplayListDrawing { false };
407     bool m_tracksDisplayListReplay { false };
408     mutable std::unique_ptr<struct DisplayListDrawingContext> m_recordingContext;
409 };
410
411 } // namespace WebCore
412
413 SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(WebCore::CanvasRenderingContext2D, is2d())