/work/obj-fuzz/dist/include/mozilla/dom/CanvasRenderingContext2D.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
3 | | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #ifndef CanvasRenderingContext2D_h |
6 | | #define CanvasRenderingContext2D_h |
7 | | |
8 | | #include "mozilla/Attributes.h" |
9 | | #include <vector> |
10 | | #include "nsICanvasRenderingContextInternal.h" |
11 | | #include "mozilla/RefPtr.h" |
12 | | #include "nsColor.h" |
13 | | #include "mozilla/dom/HTMLCanvasElement.h" |
14 | | #include "mozilla/dom/HTMLVideoElement.h" |
15 | | #include "gfxTextRun.h" |
16 | | #include "mozilla/ErrorResult.h" |
17 | | #include "mozilla/dom/BasicRenderingContext2D.h" |
18 | | #include "mozilla/dom/CanvasGradient.h" |
19 | | #include "mozilla/dom/CanvasRenderingContext2DBinding.h" |
20 | | #include "mozilla/dom/CanvasPattern.h" |
21 | | #include "mozilla/gfx/Rect.h" |
22 | | #include "mozilla/gfx/2D.h" |
23 | | #include "mozilla/UniquePtr.h" |
24 | | #include "gfx2DGlue.h" |
25 | | #include "imgIEncoder.h" |
26 | | #include "nsLayoutUtils.h" |
27 | | #include "mozilla/EnumeratedArray.h" |
28 | | #include "FilterSupport.h" |
29 | | #include "SVGObserverUtils.h" |
30 | | #include "Layers.h" |
31 | | #include "nsBidi.h" |
32 | | |
33 | | class nsGlobalWindowInner; |
34 | | class nsXULElement; |
35 | | |
36 | | namespace mozilla { |
37 | | namespace gl { |
38 | | class SourceSurface; |
39 | | } // namespace gl |
40 | | |
41 | | namespace dom { |
42 | | class HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap; |
43 | | typedef HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap CanvasImageSource; |
44 | | class ImageData; |
45 | | class StringOrCanvasGradientOrCanvasPattern; |
46 | | class OwningStringOrCanvasGradientOrCanvasPattern; |
47 | | class TextMetrics; |
48 | | class SVGFilterObserverListForCanvas; |
49 | | class CanvasPath; |
50 | | |
51 | | extern const mozilla::gfx::Float SIGMA_MAX; |
52 | | |
53 | | template<typename T> class Optional; |
54 | | |
55 | | struct CanvasBidiProcessor; |
56 | | class CanvasRenderingContext2DUserData; |
57 | | class CanvasDrawObserver; |
58 | | class CanvasShutdownObserver; |
59 | | |
60 | | /** |
61 | | ** CanvasRenderingContext2D |
62 | | **/ |
63 | | class CanvasRenderingContext2D final : |
64 | | public nsICanvasRenderingContextInternal, |
65 | | public nsWrapperCache, |
66 | | public BasicRenderingContext2D |
67 | | { |
68 | | virtual ~CanvasRenderingContext2D(); |
69 | | |
70 | | public: |
71 | | explicit CanvasRenderingContext2D(layers::LayersBackend aCompositorBackend); |
72 | | |
73 | | virtual JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override; |
74 | | |
75 | | HTMLCanvasElement* GetCanvas() const |
76 | 0 | { |
77 | 0 | if (!mCanvasElement || mCanvasElement->IsInNativeAnonymousSubtree()) { |
78 | 0 | return nullptr; |
79 | 0 | } |
80 | 0 | |
81 | 0 | // corresponds to changes to the old bindings made in bug 745025 |
82 | 0 | return mCanvasElement->GetOriginalCanvas(); |
83 | 0 | } |
84 | | |
85 | | void Save() override; |
86 | | void Restore() override; |
87 | | void Scale(double aX, double aY, mozilla::ErrorResult& aError) override; |
88 | | void Rotate(double aAngle, mozilla::ErrorResult& aError) override; |
89 | | void Translate(double aX, double aY, mozilla::ErrorResult& aError) override; |
90 | | void Transform(double aM11, double aM12, double aM21, double aM22, |
91 | | double aDx, double aDy, mozilla::ErrorResult& aError) override; |
92 | | void SetTransform(double aM11, double aM12, double aM21, double aM22, |
93 | | double aDx, double aDy, mozilla::ErrorResult& aError) override; |
94 | | void ResetTransform(mozilla::ErrorResult& aError) override; |
95 | | |
96 | | double GlobalAlpha() override |
97 | 0 | { |
98 | 0 | return CurrentState().globalAlpha; |
99 | 0 | } |
100 | | |
101 | | // Useful for silencing cast warnings |
102 | 0 | static mozilla::gfx::Float ToFloat(double aValue) { return mozilla::gfx::Float(aValue); } |
103 | | |
104 | | void SetGlobalAlpha(double aGlobalAlpha) override |
105 | 0 | { |
106 | 0 | if (aGlobalAlpha >= 0.0 && aGlobalAlpha <= 1.0) { |
107 | 0 | CurrentState().globalAlpha = ToFloat(aGlobalAlpha); |
108 | 0 | } |
109 | 0 | } |
110 | | |
111 | | void GetGlobalCompositeOperation(nsAString& aOp, |
112 | | mozilla::ErrorResult& aError) override; |
113 | | void SetGlobalCompositeOperation(const nsAString& aOp, |
114 | | mozilla::ErrorResult& aError) override; |
115 | | |
116 | | void |
117 | | GetStrokeStyle(OwningStringOrCanvasGradientOrCanvasPattern& aValue) override |
118 | 0 | { |
119 | 0 | GetStyleAsUnion(aValue, Style::STROKE); |
120 | 0 | } |
121 | | |
122 | | void |
123 | | SetStrokeStyle(const StringOrCanvasGradientOrCanvasPattern& aValue) override |
124 | 0 | { |
125 | 0 | SetStyleFromUnion(aValue, Style::STROKE); |
126 | 0 | } |
127 | | |
128 | | void |
129 | | GetFillStyle(OwningStringOrCanvasGradientOrCanvasPattern& aValue) override |
130 | 0 | { |
131 | 0 | GetStyleAsUnion(aValue, Style::FILL); |
132 | 0 | } |
133 | | |
134 | | void |
135 | | SetFillStyle(const StringOrCanvasGradientOrCanvasPattern& aValue) override |
136 | 0 | { |
137 | 0 | SetStyleFromUnion(aValue, Style::FILL); |
138 | 0 | } |
139 | | |
140 | | already_AddRefed<CanvasGradient> |
141 | | CreateLinearGradient(double aX0, double aY0, double aX1, double aY1) override; |
142 | | already_AddRefed<CanvasGradient> |
143 | | CreateRadialGradient(double aX0, double aY0, double aR0, |
144 | | double aX1, double aY1, double aR1, |
145 | | ErrorResult& aError) override; |
146 | | already_AddRefed<CanvasPattern> |
147 | | CreatePattern(const CanvasImageSource& aElement, |
148 | | const nsAString& aRepeat, ErrorResult& aError) override; |
149 | | |
150 | | double ShadowOffsetX() override |
151 | 0 | { |
152 | 0 | return CurrentState().shadowOffset.x; |
153 | 0 | } |
154 | | |
155 | | void SetShadowOffsetX(double aShadowOffsetX) override |
156 | 0 | { |
157 | 0 | CurrentState().shadowOffset.x = ToFloat(aShadowOffsetX); |
158 | 0 | } |
159 | | |
160 | | double ShadowOffsetY() override |
161 | 0 | { |
162 | 0 | return CurrentState().shadowOffset.y; |
163 | 0 | } |
164 | | |
165 | | void SetShadowOffsetY(double aShadowOffsetY) override |
166 | 0 | { |
167 | 0 | CurrentState().shadowOffset.y = ToFloat(aShadowOffsetY); |
168 | 0 | } |
169 | | |
170 | | double ShadowBlur() override |
171 | 0 | { |
172 | 0 | return CurrentState().shadowBlur; |
173 | 0 | } |
174 | | |
175 | | void SetShadowBlur(double aShadowBlur) override |
176 | 0 | { |
177 | 0 | if (aShadowBlur >= 0.0) { |
178 | 0 | CurrentState().shadowBlur = ToFloat(aShadowBlur); |
179 | 0 | } |
180 | 0 | } |
181 | | |
182 | | void GetShadowColor(nsAString& aShadowColor) override |
183 | 0 | { |
184 | 0 | StyleColorToString(CurrentState().shadowColor, aShadowColor); |
185 | 0 | } |
186 | | |
187 | | void GetFilter(nsAString& aFilter) |
188 | 0 | { |
189 | 0 | aFilter = CurrentState().filterString; |
190 | 0 | } |
191 | | |
192 | | void SetShadowColor(const nsAString& aShadowColor) override; |
193 | | void SetFilter(const nsAString& aFilter, mozilla::ErrorResult& aError); |
194 | | void ClearRect(double aX, double aY, double aW, double aH) override; |
195 | | void FillRect(double aX, double aY, double aW, double aH) override; |
196 | | void StrokeRect(double aX, double aY, double aW, double aH) override; |
197 | | void BeginPath(); |
198 | | void Fill(const CanvasWindingRule& aWinding); |
199 | | void Fill(const CanvasPath& aPath, const CanvasWindingRule& aWinding); |
200 | | void Stroke(); |
201 | | void Stroke(const CanvasPath& aPath); |
202 | | void DrawFocusIfNeeded(mozilla::dom::Element& aElement, ErrorResult& aRv); |
203 | | bool DrawCustomFocusRing(mozilla::dom::Element& aElement); |
204 | | void Clip(const CanvasWindingRule& aWinding); |
205 | | void Clip(const CanvasPath& aPath, const CanvasWindingRule& aWinding); |
206 | | bool IsPointInPath(JSContext* aCx, double aX, double aY, |
207 | | const CanvasWindingRule& aWinding, |
208 | | nsIPrincipal& aSubjectPrincipal); |
209 | | bool IsPointInPath(JSContext* aCx, const CanvasPath& aPath, |
210 | | double aX, double aY, |
211 | | const CanvasWindingRule& aWinding, nsIPrincipal&); |
212 | | bool IsPointInStroke(JSContext* aCx, double aX, double aY, |
213 | | nsIPrincipal& aSubjectPrincipal); |
214 | | bool IsPointInStroke(JSContext* aCx, const CanvasPath& aPath, |
215 | | double aX, double aY, nsIPrincipal&); |
216 | | void FillText(const nsAString& aText, double aX, double aY, |
217 | | const Optional<double>& aMaxWidth, |
218 | | mozilla::ErrorResult& aError); |
219 | | void StrokeText(const nsAString& aText, double aX, double aY, |
220 | | const Optional<double>& aMaxWidth, |
221 | | mozilla::ErrorResult& aError); |
222 | | TextMetrics* |
223 | | MeasureText(const nsAString& aRawText, mozilla::ErrorResult& aError); |
224 | | |
225 | | void AddHitRegion(const HitRegionOptions& aOptions, mozilla::ErrorResult& aError); |
226 | | void RemoveHitRegion(const nsAString& aId); |
227 | | void ClearHitRegions(); |
228 | | |
229 | | void DrawImage(const CanvasImageSource& aImage, double aDx, double aDy, |
230 | | mozilla::ErrorResult& aError) override |
231 | 0 | { |
232 | 0 | DrawImage(aImage, 0.0, 0.0, 0.0, 0.0, aDx, aDy, 0.0, 0.0, 0, aError); |
233 | 0 | } |
234 | | |
235 | | void DrawImage(const CanvasImageSource& aImage, double aDx, double aDy, |
236 | | double aDw, double aDh, mozilla::ErrorResult& aError) override |
237 | 0 | { |
238 | 0 | DrawImage(aImage, 0.0, 0.0, 0.0, 0.0, aDx, aDy, aDw, aDh, 2, aError); |
239 | 0 | } |
240 | | |
241 | | void DrawImage(const CanvasImageSource& aImage, |
242 | | double aSx, double aSy, double aSw, double aSh, |
243 | | double aDx, double aDy, double aDw, double aDh, |
244 | | mozilla::ErrorResult& aError) override |
245 | 0 | { |
246 | 0 | DrawImage(aImage, aSx, aSy, aSw, aSh, aDx, aDy, aDw, aDh, 6, aError); |
247 | 0 | } |
248 | | |
249 | | already_AddRefed<ImageData> |
250 | | CreateImageData(JSContext* aCx, double aSw, double aSh, |
251 | | mozilla::ErrorResult& aError); |
252 | | already_AddRefed<ImageData> |
253 | | CreateImageData(JSContext* aCx, ImageData& aImagedata, |
254 | | mozilla::ErrorResult& aError); |
255 | | already_AddRefed<ImageData> |
256 | | GetImageData(JSContext* aCx, double aSx, double aSy, double aSw, double aSh, |
257 | | nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aError); |
258 | | void PutImageData(ImageData& aImageData, |
259 | | double aDx, double aDy, mozilla::ErrorResult& aError); |
260 | | void PutImageData(ImageData& aImageData, |
261 | | double aDx, double aDy, double aDirtyX, double aDirtyY, |
262 | | double aDirtyWidth, double aDirtyHeight, |
263 | | mozilla::ErrorResult& aError); |
264 | | |
265 | | double LineWidth() override |
266 | 0 | { |
267 | 0 | return CurrentState().lineWidth; |
268 | 0 | } |
269 | | |
270 | | void SetLineWidth(double aWidth) override |
271 | 0 | { |
272 | 0 | if (aWidth > 0.0) { |
273 | 0 | CurrentState().lineWidth = ToFloat(aWidth); |
274 | 0 | } |
275 | 0 | } |
276 | | void GetLineCap(nsAString& aLinecapStyle) override; |
277 | | void SetLineCap(const nsAString& aLinecapStyle) override; |
278 | | void GetLineJoin(nsAString& aLinejoinStyle, |
279 | | mozilla::ErrorResult& aError) override; |
280 | | void SetLineJoin(const nsAString& aLinejoinStyle) override; |
281 | | |
282 | | double MiterLimit() override |
283 | 0 | { |
284 | 0 | return CurrentState().miterLimit; |
285 | 0 | } |
286 | | |
287 | | void SetMiterLimit(double aMiter) override |
288 | 0 | { |
289 | 0 | if (aMiter > 0.0) { |
290 | 0 | CurrentState().miterLimit = ToFloat(aMiter); |
291 | 0 | } |
292 | 0 | } |
293 | | |
294 | | void GetFont(nsAString& aFont) |
295 | 0 | { |
296 | 0 | aFont = GetFont(); |
297 | 0 | } |
298 | | |
299 | | void SetFont(const nsAString& aFont, mozilla::ErrorResult& aError); |
300 | | void GetTextAlign(nsAString& aTextAlign); |
301 | | void SetTextAlign(const nsAString& aTextAlign); |
302 | | void GetTextBaseline(nsAString& aTextBaseline); |
303 | | void SetTextBaseline(const nsAString& aTextBaseline); |
304 | | |
305 | | void ClosePath() override |
306 | 0 | { |
307 | 0 | EnsureWritablePath(); |
308 | 0 |
|
309 | 0 | if (mPathBuilder) { |
310 | 0 | mPathBuilder->Close(); |
311 | 0 | } else { |
312 | 0 | mDSPathBuilder->Close(); |
313 | 0 | } |
314 | 0 | } |
315 | | |
316 | | void MoveTo(double aX, double aY) override |
317 | 0 | { |
318 | 0 | EnsureWritablePath(); |
319 | 0 |
|
320 | 0 | if (mPathBuilder) { |
321 | 0 | mPathBuilder->MoveTo(mozilla::gfx::Point(ToFloat(aX), ToFloat(aY))); |
322 | 0 | } else { |
323 | 0 | mDSPathBuilder->MoveTo(mTarget->GetTransform().TransformPoint( |
324 | 0 | mozilla::gfx::Point(ToFloat(aX), ToFloat(aY)))); |
325 | 0 | } |
326 | 0 | } |
327 | | |
328 | | void LineTo(double aX, double aY) override |
329 | 0 | { |
330 | 0 | EnsureWritablePath(); |
331 | 0 |
|
332 | 0 | LineTo(mozilla::gfx::Point(ToFloat(aX), ToFloat(aY))); |
333 | 0 | } |
334 | | |
335 | | void QuadraticCurveTo(double aCpx, double aCpy, double aX, double aY) override |
336 | 0 | { |
337 | 0 | EnsureWritablePath(); |
338 | 0 |
|
339 | 0 | if (mPathBuilder) { |
340 | 0 | mPathBuilder->QuadraticBezierTo(mozilla::gfx::Point(ToFloat(aCpx), ToFloat(aCpy)), |
341 | 0 | mozilla::gfx::Point(ToFloat(aX), ToFloat(aY))); |
342 | 0 | } else { |
343 | 0 | mozilla::gfx::Matrix transform = mTarget->GetTransform(); |
344 | 0 | mDSPathBuilder->QuadraticBezierTo(transform.TransformPoint( |
345 | 0 | mozilla::gfx::Point(ToFloat(aCpx), ToFloat(aCpy))), |
346 | 0 | transform.TransformPoint( |
347 | 0 | mozilla::gfx::Point(ToFloat(aX), ToFloat(aY)))); |
348 | 0 | } |
349 | 0 | } |
350 | | |
351 | | void BezierCurveTo(double aCp1x, double aCp1y, double aCp2x, double aCp2y, |
352 | | double aX, double aY) override |
353 | 0 | { |
354 | 0 | EnsureWritablePath(); |
355 | 0 |
|
356 | 0 | BezierTo(mozilla::gfx::Point(ToFloat(aCp1x), ToFloat(aCp1y)), |
357 | 0 | mozilla::gfx::Point(ToFloat(aCp2x), ToFloat(aCp2y)), |
358 | 0 | mozilla::gfx::Point(ToFloat(aX), ToFloat(aY))); |
359 | 0 | } |
360 | | |
361 | | void ArcTo(double aX1, double aY1, double aX2, double aY2, |
362 | | double aRadius, mozilla::ErrorResult& aError) override; |
363 | | void Rect(double aX, double aY, double aW, double aH) override; |
364 | | void Arc(double aX, double aY, double aRadius, double aStartAngle, |
365 | | double aEndAngle, bool aAnticlockwise, |
366 | | mozilla::ErrorResult& aError) override; |
367 | | void Ellipse(double aX, double aY, double aRadiusX, double aRadiusY, |
368 | | double aRotation, double aStartAngle, double aEndAngle, |
369 | | bool aAnticlockwise, ErrorResult& aError) override; |
370 | | |
371 | | void GetMozCurrentTransform(JSContext* aCx, |
372 | | JS::MutableHandle<JSObject*> aResult, |
373 | | mozilla::ErrorResult& aError); |
374 | | void SetMozCurrentTransform(JSContext* aCx, |
375 | | JS::Handle<JSObject*> aCurrentTransform, |
376 | | mozilla::ErrorResult& aError); |
377 | | void GetMozCurrentTransformInverse(JSContext* aCx, |
378 | | JS::MutableHandle<JSObject*> aResult, |
379 | | mozilla::ErrorResult& aError); |
380 | | void SetMozCurrentTransformInverse(JSContext* aCx, |
381 | | JS::Handle<JSObject*> aCurrentTransform, |
382 | | mozilla::ErrorResult& aError); |
383 | | void GetFillRule(nsAString& aFillRule); |
384 | | void SetFillRule(const nsAString& aFillRule); |
385 | | |
386 | | void SetLineDash(const Sequence<double>& aSegments, |
387 | | mozilla::ErrorResult& aRv) override; |
388 | | void GetLineDash(nsTArray<double>& aSegments) const override; |
389 | | |
390 | | void SetLineDashOffset(double aOffset) override; |
391 | | double LineDashOffset() const override; |
392 | | |
393 | | void GetMozTextStyle(nsAString& aMozTextStyle) |
394 | 0 | { |
395 | 0 | GetFont(aMozTextStyle); |
396 | 0 | } |
397 | | |
398 | | void SetMozTextStyle(const nsAString& aMozTextStyle, |
399 | | mozilla::ErrorResult& aError) |
400 | 0 | { |
401 | 0 | SetFont(aMozTextStyle, aError); |
402 | 0 | } |
403 | | |
404 | | bool ImageSmoothingEnabled() override |
405 | 0 | { |
406 | 0 | return CurrentState().imageSmoothingEnabled; |
407 | 0 | } |
408 | | |
409 | | void SetImageSmoothingEnabled(bool aImageSmoothingEnabled) override |
410 | 0 | { |
411 | 0 | if (aImageSmoothingEnabled != CurrentState().imageSmoothingEnabled) { |
412 | 0 | CurrentState().imageSmoothingEnabled = aImageSmoothingEnabled; |
413 | 0 | } |
414 | 0 | } |
415 | | |
416 | | void DrawWindow(nsGlobalWindowInner& aWindow, double aX, double aY, |
417 | | double aW, double aH, |
418 | | const nsAString& aBgColor, uint32_t aFlags, |
419 | | mozilla::ErrorResult& aError); |
420 | | |
421 | | enum RenderingMode { |
422 | | SoftwareBackendMode, |
423 | | OpenGLBackendMode, |
424 | | DefaultBackendMode |
425 | | }; |
426 | | |
427 | | bool SwitchRenderingMode(RenderingMode aRenderingMode); |
428 | | |
429 | | // Eventually this should be deprecated. Keeping for now to keep the binding functional. |
430 | | void Demote(); |
431 | | |
432 | | nsresult Redraw(); |
433 | | |
434 | 0 | gfx::IntSize GetSize() const { return gfx::IntSize(mWidth, mHeight); } |
435 | 0 | virtual int32_t GetWidth() override { return GetSize().width; } |
436 | 0 | virtual int32_t GetHeight() override { return GetSize().height; } |
437 | | |
438 | | // nsICanvasRenderingContextInternal |
439 | | /** |
440 | | * Gets the pres shell from either the canvas element or the doc shell |
441 | | */ |
442 | 0 | nsIPresShell* GetPresShell() final { |
443 | 0 | if (mCanvasElement) { |
444 | 0 | return mCanvasElement->OwnerDoc()->GetShell(); |
445 | 0 | } |
446 | 0 | if (mDocShell) { |
447 | 0 | return mDocShell->GetPresShell(); |
448 | 0 | } |
449 | 0 | return nullptr; |
450 | 0 | } |
451 | | NS_IMETHOD SetDimensions(int32_t aWidth, int32_t aHeight) override; |
452 | | NS_IMETHOD InitializeWithDrawTarget(nsIDocShell* aShell, |
453 | | NotNull<gfx::DrawTarget*> aTarget) override; |
454 | | |
455 | | NS_IMETHOD GetInputStream(const char* aMimeType, |
456 | | const char16_t* aEncoderOptions, |
457 | | nsIInputStream** aStream) override; |
458 | | |
459 | | already_AddRefed<mozilla::gfx::SourceSurface> |
460 | | GetSurfaceSnapshot(gfxAlphaType* aOutAlphaType = nullptr) override |
461 | 0 | { |
462 | 0 | EnsureTarget(); |
463 | 0 | if (aOutAlphaType) { |
464 | 0 | *aOutAlphaType = (mOpaque ? gfxAlphaType::Opaque : gfxAlphaType::Premult); |
465 | 0 | } |
466 | 0 | return mTarget->Snapshot(); |
467 | 0 | } |
468 | | |
469 | | virtual void SetOpaqueValueFromOpaqueAttr(bool aOpaqueAttrValue) override; |
470 | 0 | bool GetIsOpaque() override { return mOpaque; } |
471 | | NS_IMETHOD Reset() override; |
472 | | already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder, |
473 | | Layer* aOldLayer, |
474 | | LayerManager* aManager) override; |
475 | | |
476 | | bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder, |
477 | | WebRenderCanvasData* aCanvasData) override; |
478 | | |
479 | | bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder, |
480 | | CanvasRenderer* aRenderer) override; |
481 | | virtual bool ShouldForceInactiveLayer(LayerManager* aManager) override; |
482 | | void MarkContextClean() override; |
483 | | void MarkContextCleanForFrameCapture() override; |
484 | | bool IsContextCleanForFrameCapture() override; |
485 | | NS_IMETHOD SetIsIPC(bool aIsIPC) override; |
486 | | // this rect is in canvas device space |
487 | | void Redraw(const mozilla::gfx::Rect& aR); |
488 | 0 | NS_IMETHOD Redraw(const gfxRect& aR) override { Redraw(ToRect(aR)); return NS_OK; } |
489 | | NS_IMETHOD SetContextOptions(JSContext* aCx, |
490 | | JS::Handle<JS::Value> aOptions, |
491 | | ErrorResult& aRvForDictionaryInit) override; |
492 | | |
493 | | /** |
494 | | * An abstract base class to be implemented by callers wanting to be notified |
495 | | * that a refresh has occurred. Callers must ensure an observer is removed |
496 | | * before it is destroyed. |
497 | | */ |
498 | | virtual void DidRefresh() override; |
499 | | |
500 | | // this rect is in mTarget's current user space |
501 | | void RedrawUser(const gfxRect& aR); |
502 | | |
503 | | // nsISupports interface + CC |
504 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
505 | | |
506 | | NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(CanvasRenderingContext2D) |
507 | | |
508 | | enum class CanvasMultiGetterType : uint8_t { |
509 | | STRING = 0, |
510 | | PATTERN = 1, |
511 | | GRADIENT = 2 |
512 | | }; |
513 | | |
514 | | enum class Style : uint8_t { |
515 | | STROKE = 0, |
516 | | FILL, |
517 | | MAX |
518 | | }; |
519 | | |
520 | | nsINode* GetParentObject() |
521 | 0 | { |
522 | 0 | return mCanvasElement; |
523 | 0 | } |
524 | | |
525 | | void LineTo(const mozilla::gfx::Point& aPoint) |
526 | 0 | { |
527 | 0 | if (mPathBuilder) { |
528 | 0 | mPathBuilder->LineTo(aPoint); |
529 | 0 | } else { |
530 | 0 | mDSPathBuilder->LineTo(mTarget->GetTransform().TransformPoint(aPoint)); |
531 | 0 | } |
532 | 0 | } |
533 | | |
534 | | void BezierTo(const mozilla::gfx::Point& aCP1, |
535 | | const mozilla::gfx::Point& aCP2, |
536 | | const mozilla::gfx::Point& aCP3) |
537 | 0 | { |
538 | 0 | if (mPathBuilder) { |
539 | 0 | mPathBuilder->BezierTo(aCP1, aCP2, aCP3); |
540 | 0 | } else { |
541 | 0 | mozilla::gfx::Matrix transform = mTarget->GetTransform(); |
542 | 0 | mDSPathBuilder->BezierTo(transform.TransformPoint(aCP1), |
543 | 0 | transform.TransformPoint(aCP2), |
544 | 0 | transform.TransformPoint(aCP3)); |
545 | 0 | } |
546 | 0 | } |
547 | | |
548 | | friend class CanvasRenderingContext2DUserData; |
549 | | |
550 | | virtual UniquePtr<uint8_t[]> GetImageBuffer(int32_t* aFormat) override; |
551 | | |
552 | | |
553 | | // Given a point, return hit region ID if it exists |
554 | | nsString GetHitRegion(const mozilla::gfx::Point& aPoint) override; |
555 | | |
556 | | |
557 | | // return true and fills in the bound rect if element has a hit region. |
558 | | bool GetHitRegionRect(Element* aElement, nsRect& aRect) override; |
559 | | |
560 | | void OnShutdown(); |
561 | | |
562 | | // Check the global setup, as well as the compositor type: |
563 | | bool AllowOpenGLCanvas() const; |
564 | | |
565 | | protected: |
566 | | nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY, |
567 | | uint32_t aWidth, uint32_t aHeight, |
568 | | nsIPrincipal& aSubjectPrincipal, |
569 | | JSObject** aRetval); |
570 | | |
571 | | nsresult PutImageData_explicit(int32_t aX, int32_t aY, uint32_t aW, uint32_t aH, |
572 | | dom::Uint8ClampedArray* aArray, |
573 | | bool aHasDirtyRect, int32_t aDirtyX, int32_t aDirtyY, |
574 | | int32_t aDirtyWidth, int32_t aDirtyHeight); |
575 | | |
576 | | bool CopyBufferProvider(layers::PersistentBufferProvider& aOld, |
577 | | gfx::DrawTarget& aTarget, |
578 | | gfx::IntRect aCopyRect); |
579 | | |
580 | | /** |
581 | | * Internal method to complete initialisation, expects mTarget to have been set |
582 | | */ |
583 | | nsresult Initialize(int32_t aWidth, int32_t aHeight); |
584 | | |
585 | | nsresult InitializeWithTarget(mozilla::gfx::DrawTarget* aSurface, |
586 | | int32_t aWidth, int32_t aHeight); |
587 | | |
588 | | /** |
589 | | * The number of living nsCanvasRenderingContexts. When this goes down to |
590 | | * 0, we free the premultiply and unpremultiply tables, if they exist. |
591 | | */ |
592 | | static uintptr_t sNumLivingContexts; |
593 | | |
594 | | static mozilla::gfx::DrawTarget* sErrorTarget; |
595 | | |
596 | | void SetTransformInternal(const mozilla::gfx::Matrix& aTransform); |
597 | | |
598 | | // Some helpers. Doesn't modify a color on failure. |
599 | | void SetStyleFromUnion(const StringOrCanvasGradientOrCanvasPattern& aValue, |
600 | | Style aWhichStyle); |
601 | | void SetStyleFromString(const nsAString& aStr, Style aWhichStyle); |
602 | | |
603 | | void SetStyleFromGradient(CanvasGradient& aGradient, Style aWhichStyle) |
604 | 0 | { |
605 | 0 | CurrentState().SetGradientStyle(aWhichStyle, &aGradient); |
606 | 0 | } |
607 | | |
608 | | void SetStyleFromPattern(CanvasPattern& aPattern, Style aWhichStyle) |
609 | 0 | { |
610 | 0 | CurrentState().SetPatternStyle(aWhichStyle, &aPattern); |
611 | 0 | } |
612 | | |
613 | | void GetStyleAsUnion(OwningStringOrCanvasGradientOrCanvasPattern& aValue, |
614 | | Style aWhichStyle); |
615 | | |
616 | | // Returns whether a color was successfully parsed. |
617 | | bool ParseColor(const nsAString& aString, nscolor* aColor); |
618 | | |
619 | | static void StyleColorToString(const nscolor& aColor, nsAString& aStr); |
620 | | |
621 | | // Returns whether a filter was successfully parsed. |
622 | | bool ParseFilter(const nsAString& aString, |
623 | | nsTArray<nsStyleFilter>& aFilterChain, |
624 | | ErrorResult& aError); |
625 | | |
626 | | // Returns whether the font was successfully updated. |
627 | | bool SetFontInternal(const nsAString& aFont, mozilla::ErrorResult& aError); |
628 | | |
629 | | // Clears the target and updates mOpaque based on mOpaqueAttrValue and |
630 | | // mContextAttributesHasAlpha. |
631 | | void UpdateIsOpaque(); |
632 | | |
633 | | /** |
634 | | * Creates the error target, if it doesn't exist |
635 | | */ |
636 | | static void EnsureErrorTarget(); |
637 | | |
638 | | /* This function ensures there is a writable pathbuilder available, this |
639 | | * pathbuilder may be working in user space or in device space or |
640 | | * device space. |
641 | | * After calling this function mPathTransformWillUpdate will be false |
642 | | */ |
643 | | void EnsureWritablePath(); |
644 | | |
645 | | // Ensures a path in UserSpace is available. |
646 | | void EnsureUserSpacePath(const CanvasWindingRule& aWinding = CanvasWindingRule::Nonzero); |
647 | | |
648 | | /** |
649 | | * Needs to be called before updating the transform. This makes a call to |
650 | | * EnsureTarget() so you don't have to. |
651 | | */ |
652 | | void TransformWillUpdate(); |
653 | | |
654 | | // Report the fillRule has changed. |
655 | | void FillRuleChanged(); |
656 | | |
657 | | /** |
658 | | * Create the backing surfacing, if it doesn't exist. If there is an error |
659 | | * in creating the target then it will put sErrorTarget in place. If there |
660 | | * is in turn an error in creating the sErrorTarget then they would both |
661 | | * be null so IsTargetValid() would still return null. |
662 | | * |
663 | | * Returns the actual rendering mode being used by the created target. |
664 | | */ |
665 | | RenderingMode EnsureTarget(const gfx::Rect* aCoveredRect = nullptr, |
666 | | RenderingMode aRenderMode = RenderingMode::DefaultBackendMode); |
667 | | |
668 | | void RestoreClipsAndTransformToTarget(); |
669 | | |
670 | | bool TrySkiaGLTarget(RefPtr<gfx::DrawTarget>& aOutDT, |
671 | | RefPtr<layers::PersistentBufferProvider>& aOutProvider); |
672 | | |
673 | | bool TrySharedTarget(RefPtr<gfx::DrawTarget>& aOutDT, |
674 | | RefPtr<layers::PersistentBufferProvider>& aOutProvider); |
675 | | |
676 | | bool TryBasicTarget(RefPtr<gfx::DrawTarget>& aOutDT, |
677 | | RefPtr<layers::PersistentBufferProvider>& aOutProvider); |
678 | | |
679 | | void RegisterAllocation(); |
680 | | |
681 | | void SetInitialState(); |
682 | | |
683 | | void SetErrorState(); |
684 | | |
685 | | /** |
686 | | * This method is run at the end of the event-loop spin where |
687 | | * ScheduleStableStateCallback was called. |
688 | | * |
689 | | * We use it to unlock resources that need to be locked while drawing. |
690 | | */ |
691 | | void OnStableState(); |
692 | | |
693 | | /** |
694 | | * Cf. OnStableState. |
695 | | */ |
696 | | void ScheduleStableStateCallback(); |
697 | | |
698 | | /** |
699 | | * Disposes an old target and prepares to lazily create a new target. |
700 | | * |
701 | | * Parameters are the new dimensions to be used, or if either is negative, |
702 | | * existing dimensions will be left unchanged. |
703 | | */ |
704 | | void ClearTarget(int32_t aWidth = -1, int32_t aHeight = -1); |
705 | | |
706 | | /* |
707 | | * Returns the target to the buffer provider. i.e. this will queue a frame for |
708 | | * rendering. |
709 | | */ |
710 | | void ReturnTarget(bool aForceReset = false); |
711 | | |
712 | | /** |
713 | | * Check if the target is valid after calling EnsureTarget. |
714 | | */ |
715 | 0 | bool IsTargetValid() const { |
716 | 0 | return !!mTarget && mTarget != sErrorTarget; |
717 | 0 | } |
718 | | |
719 | | /** |
720 | | * Returns the surface format this canvas should be allocated using. Takes |
721 | | * into account mOpaque, platform requirements, etc. |
722 | | */ |
723 | | mozilla::gfx::SurfaceFormat GetSurfaceFormat() const; |
724 | | |
725 | | /** |
726 | | * Returns true if we know for sure that the pattern for a given style is opaque. |
727 | | * Usefull to know if we can discard the content below in certain situations. |
728 | | */ |
729 | | bool PatternIsOpaque(Style aStyle) const; |
730 | | |
731 | | /** |
732 | | * Update CurrentState().filter with the filter description for |
733 | | * CurrentState().filterChain. |
734 | | * Flushes the PresShell, so the world can change if you call this function. |
735 | | */ |
736 | | void UpdateFilter(); |
737 | | |
738 | | nsLayoutUtils::SurfaceFromElementResult |
739 | | CachedSurfaceFromElement(Element* aElement); |
740 | | |
741 | | void DrawImage(const CanvasImageSource& aImgElt, |
742 | | double aSx, double aSy, double aSw, double aSh, |
743 | | double aDx, double aDy, double aDw, double aDh, |
744 | | uint8_t aOptional_argc, mozilla::ErrorResult& aError); |
745 | | |
746 | | void DrawDirectlyToCanvas(const nsLayoutUtils::DirectDrawInfo& aImage, |
747 | | mozilla::gfx::Rect* aBounds, |
748 | | mozilla::gfx::Rect aDest, |
749 | | mozilla::gfx::Rect aSrc, |
750 | | gfx::IntSize aImgSize); |
751 | | |
752 | | nsString& GetFont() |
753 | 0 | { |
754 | 0 | /* will initilize the value if not set, else does nothing */ |
755 | 0 | GetCurrentFontStyle(); |
756 | 0 |
|
757 | 0 | return CurrentState().font; |
758 | 0 | } |
759 | | |
760 | | // This function maintains a list of raw pointers to cycle-collected |
761 | | // objects. We need to ensure that no entries persist beyond unlink, |
762 | | // since the objects are logically destructed at that point. |
763 | | static std::vector<CanvasRenderingContext2D*>& DemotableContexts(); |
764 | | static void DemoteOldestContextIfNecessary(); |
765 | | |
766 | | static void AddDemotableContext(CanvasRenderingContext2D* aContext); |
767 | | static void RemoveDemotableContext(CanvasRenderingContext2D* aContext); |
768 | | |
769 | | RenderingMode mRenderingMode; |
770 | | |
771 | | layers::LayersBackend mCompositorBackend; |
772 | | |
773 | | // Member vars |
774 | | int32_t mWidth, mHeight; |
775 | | |
776 | | // This is true when the canvas is valid, but of zero size, this requires |
777 | | // specific behavior on some operations. |
778 | | bool mZero; |
779 | | |
780 | | // The two ways to set the opaqueness of the canvas. |
781 | | // mOpaqueAttrValue: Whether the <canvas> element has the moz-opaque attribute |
782 | | // set. Can change during the lifetime of the context. Non-standard, should |
783 | | // hopefully go away soon. |
784 | | // mContextAttributesHasAlpha: The standard way of setting canvas opaqueness. |
785 | | // Set at context initialization time and never changes. |
786 | | bool mOpaqueAttrValue; |
787 | | bool mContextAttributesHasAlpha; |
788 | | |
789 | | // Determines the context's opaqueness. Is computed from mOpaqueAttrValue and |
790 | | // mContextAttributesHasAlpha in UpdateIsOpaque(). |
791 | | bool mOpaque; |
792 | | |
793 | | // This is true when the next time our layer is retrieved we need to |
794 | | // recreate it (i.e. our backing surface changed) |
795 | | bool mResetLayer; |
796 | | // This is needed for drawing in drawAsyncXULElement |
797 | | bool mIPC; |
798 | | // True if the current DrawTarget is using skia-gl, used so we can avoid |
799 | | // requesting the DT from mBufferProvider to check. |
800 | | bool mIsSkiaGL; |
801 | | |
802 | | bool mHasPendingStableStateCallback; |
803 | | |
804 | | nsTArray<CanvasRenderingContext2DUserData*> mUserDatas; |
805 | | |
806 | | // If mCanvasElement is not provided, then a docshell is |
807 | | nsCOMPtr<nsIDocShell> mDocShell; |
808 | | |
809 | | // This is created lazily so it is necessary to call EnsureTarget before |
810 | | // accessing it. In the event of an error it will be equal to |
811 | | // sErrorTarget. |
812 | | RefPtr<mozilla::gfx::DrawTarget> mTarget; |
813 | | |
814 | | RefPtr<mozilla::layers::PersistentBufferProvider> mBufferProvider; |
815 | | |
816 | | uint32_t SkiaGLTex() const; |
817 | | |
818 | | // This observes our draw calls at the beginning of the canvas |
819 | | // lifetime and switches to software or GPU mode depending on |
820 | | // what it thinks is best |
821 | | CanvasDrawObserver* mDrawObserver; |
822 | | void RemoveDrawObserver(); |
823 | | |
824 | | RefPtr<CanvasShutdownObserver> mShutdownObserver; |
825 | | void RemoveShutdownObserver(); |
826 | 0 | bool AlreadyShutDown() const { return !mShutdownObserver; } |
827 | | |
828 | | /** |
829 | | * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever |
830 | | * Redraw is called, reset to false when Render is called. |
831 | | */ |
832 | | bool mIsEntireFrameInvalid; |
833 | | /** |
834 | | * When this is set, the first call to Redraw(gfxRect) should set |
835 | | * mIsEntireFrameInvalid since we expect it will be followed by |
836 | | * many more Redraw calls. |
837 | | */ |
838 | | bool mPredictManyRedrawCalls; |
839 | | |
840 | | /** |
841 | | * Flag to avoid unnecessary surface copies to FrameCaptureListeners in the |
842 | | * case when the canvas is not currently being drawn into and not rendered |
843 | | * but canvas capturing is still ongoing. |
844 | | */ |
845 | | bool mIsCapturedFrameInvalid; |
846 | | |
847 | | /** |
848 | | * We also have a device space pathbuilder. The reason for this is as |
849 | | * follows, when a path is being built, but the transform changes, we |
850 | | * can no longer keep a single path in userspace, considering there's |
851 | | * several 'user spaces' now. We therefore transform the current path |
852 | | * into device space, and add all operations to this path in device |
853 | | * space. |
854 | | * |
855 | | * When then finally executing a render, the Azure drawing API expects |
856 | | * the path to be in userspace. We could then set an identity transform |
857 | | * on the DrawTarget and do all drawing in device space. This is |
858 | | * undesirable because it requires transforming patterns, gradients, |
859 | | * clips, etc. into device space and it would not work for stroking. |
860 | | * What we do instead is convert the path back to user space when it is |
861 | | * drawn, and draw it with the current transform. This makes all drawing |
862 | | * occur correctly. |
863 | | * |
864 | | * There's never both a device space path builder and a user space path |
865 | | * builder present at the same time. There is also never a path and a |
866 | | * path builder present at the same time. When writing proceeds on an |
867 | | * existing path the Path is cleared and a new builder is created. |
868 | | * |
869 | | * mPath is always in user-space. |
870 | | */ |
871 | | RefPtr<mozilla::gfx::Path> mPath; |
872 | | RefPtr<mozilla::gfx::PathBuilder> mDSPathBuilder; |
873 | | RefPtr<mozilla::gfx::PathBuilder> mPathBuilder; |
874 | | bool mPathTransformWillUpdate; |
875 | | mozilla::gfx::Matrix mPathToDS; |
876 | | |
877 | | /** |
878 | | * Number of times we've invalidated before calling redraw |
879 | | */ |
880 | | uint32_t mInvalidateCount; |
881 | | static const uint32_t kCanvasMaxInvalidateCount = 100; |
882 | | |
883 | | /** |
884 | | * State information for hit regions |
885 | | */ |
886 | | struct RegionInfo |
887 | | { |
888 | | nsString mId; |
889 | | // fallback element for a11y |
890 | | RefPtr<Element> mElement; |
891 | | // Path of the hit region in the 2d context coordinate space (not user space) |
892 | | RefPtr<gfx::Path> mPath; |
893 | | }; |
894 | | |
895 | | nsTArray<RegionInfo> mHitRegionsOptions; |
896 | | |
897 | | nsBidi mBidiEngine; |
898 | | |
899 | | /** |
900 | | * Returns true if a shadow should be drawn along with a |
901 | | * drawing operation. |
902 | | */ |
903 | | bool NeedToDrawShadow() |
904 | 0 | { |
905 | 0 | const ContextState& state = CurrentState(); |
906 | 0 |
|
907 | 0 | // The spec says we should not draw shadows if the operator is OVER. |
908 | 0 | // If it's over and the alpha value is zero, nothing needs to be drawn. |
909 | 0 | return NS_GET_A(state.shadowColor) != 0 && |
910 | 0 | (state.shadowBlur != 0.f || state.shadowOffset.x != 0.f || state.shadowOffset.y != 0.f); |
911 | 0 | } |
912 | | |
913 | | /** |
914 | | * Returns true if the result of a drawing operation should be |
915 | | * drawn with a filter. |
916 | | */ |
917 | | bool NeedToApplyFilter() |
918 | 0 | { |
919 | 0 | return EnsureUpdatedFilter().mPrimitives.Length() > 0; |
920 | 0 | } |
921 | | |
922 | | /** |
923 | | * Calls UpdateFilter if the canvas's WriteOnly state has changed between the |
924 | | * last call to UpdateFilter and now. |
925 | | */ |
926 | 0 | const gfx::FilterDescription& EnsureUpdatedFilter() { |
927 | 0 | bool isWriteOnly = mCanvasElement && mCanvasElement->IsWriteOnly(); |
928 | 0 | if (CurrentState().filterSourceGraphicTainted != isWriteOnly) { |
929 | 0 | UpdateFilter(); |
930 | 0 | EnsureTarget(); |
931 | 0 | } |
932 | 0 | MOZ_ASSERT(CurrentState().filterSourceGraphicTainted == isWriteOnly); |
933 | 0 | return CurrentState().filter; |
934 | 0 | } |
935 | | |
936 | | bool NeedToCalculateBounds() |
937 | 0 | { |
938 | 0 | return NeedToDrawShadow() || NeedToApplyFilter(); |
939 | 0 | } |
940 | | |
941 | | mozilla::gfx::CompositionOp UsedOperation() |
942 | 0 | { |
943 | 0 | if (NeedToDrawShadow() || NeedToApplyFilter()) { |
944 | 0 | // In this case the shadow or filter rendering will use the operator. |
945 | 0 | return mozilla::gfx::CompositionOp::OP_OVER; |
946 | 0 | } |
947 | 0 | |
948 | 0 | return CurrentState().op; |
949 | 0 | } |
950 | | |
951 | | // text |
952 | | |
953 | | protected: |
954 | | enum class TextAlign : uint8_t { |
955 | | START, |
956 | | END, |
957 | | LEFT, |
958 | | RIGHT, |
959 | | CENTER |
960 | | }; |
961 | | |
962 | | enum class TextBaseline : uint8_t { |
963 | | TOP, |
964 | | HANGING, |
965 | | MIDDLE, |
966 | | ALPHABETIC, |
967 | | IDEOGRAPHIC, |
968 | | BOTTOM |
969 | | }; |
970 | | |
971 | | enum class TextDrawOperation : uint8_t { |
972 | | FILL, |
973 | | STROKE, |
974 | | MEASURE |
975 | | }; |
976 | | |
977 | | protected: |
978 | | gfxFontGroup *GetCurrentFontStyle(); |
979 | | |
980 | | /** |
981 | | * Implementation of the fillText, strokeText, and measure functions with |
982 | | * the operation abstracted to a flag. |
983 | | */ |
984 | | nsresult DrawOrMeasureText(const nsAString& aText, |
985 | | float aX, |
986 | | float aY, |
987 | | const Optional<double>& aMaxWidth, |
988 | | TextDrawOperation aOp, |
989 | | float* aWidth); |
990 | | |
991 | | bool CheckSizeForSkiaGL(mozilla::gfx::IntSize aSize); |
992 | | |
993 | | // A clip or a transform, recorded and restored in order. |
994 | | struct ClipState { |
995 | | explicit ClipState(mozilla::gfx::Path* aClip) |
996 | | : clip(aClip) |
997 | 0 | {} |
998 | | |
999 | | explicit ClipState(const mozilla::gfx::Matrix& aTransform) |
1000 | | : transform(aTransform) |
1001 | 0 | {} |
1002 | | |
1003 | 0 | bool IsClip() const { return !!clip; } |
1004 | | |
1005 | | RefPtr<mozilla::gfx::Path> clip; |
1006 | | mozilla::gfx::Matrix transform; |
1007 | | }; |
1008 | | |
1009 | | // state stack handling |
1010 | | class ContextState { |
1011 | | public: |
1012 | | ContextState() : textAlign(TextAlign::START), |
1013 | | textBaseline(TextBaseline::ALPHABETIC), |
1014 | | shadowColor(0), |
1015 | | lineWidth(1.0f), |
1016 | | miterLimit(10.0f), |
1017 | | globalAlpha(1.0f), |
1018 | | shadowBlur(0.0), |
1019 | | dashOffset(0.0f), |
1020 | | op(mozilla::gfx::CompositionOp::OP_OVER), |
1021 | | fillRule(mozilla::gfx::FillRule::FILL_WINDING), |
1022 | | lineCap(mozilla::gfx::CapStyle::BUTT), |
1023 | | lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL), |
1024 | | filterString(u"none"), |
1025 | | filterSourceGraphicTainted(false), |
1026 | | imageSmoothingEnabled(true), |
1027 | | fontExplicitLanguage(false) |
1028 | 0 | { } |
1029 | | |
1030 | | ContextState(const ContextState& aOther) |
1031 | | : fontGroup(aOther.fontGroup), |
1032 | | fontLanguage(aOther.fontLanguage), |
1033 | | fontFont(aOther.fontFont), |
1034 | | gradientStyles(aOther.gradientStyles), |
1035 | | patternStyles(aOther.patternStyles), |
1036 | | colorStyles(aOther.colorStyles), |
1037 | | font(aOther.font), |
1038 | | textAlign(aOther.textAlign), |
1039 | | textBaseline(aOther.textBaseline), |
1040 | | shadowColor(aOther.shadowColor), |
1041 | | transform(aOther.transform), |
1042 | | shadowOffset(aOther.shadowOffset), |
1043 | | lineWidth(aOther.lineWidth), |
1044 | | miterLimit(aOther.miterLimit), |
1045 | | globalAlpha(aOther.globalAlpha), |
1046 | | shadowBlur(aOther.shadowBlur), |
1047 | | dash(aOther.dash), |
1048 | | dashOffset(aOther.dashOffset), |
1049 | | op(aOther.op), |
1050 | | fillRule(aOther.fillRule), |
1051 | | lineCap(aOther.lineCap), |
1052 | | lineJoin(aOther.lineJoin), |
1053 | | filterString(aOther.filterString), |
1054 | | filterChain(aOther.filterChain), |
1055 | | filterObserverList(aOther.filterObserverList), |
1056 | | filter(aOther.filter), |
1057 | | filterAdditionalImages(aOther.filterAdditionalImages), |
1058 | | filterSourceGraphicTainted(aOther.filterSourceGraphicTainted), |
1059 | | imageSmoothingEnabled(aOther.imageSmoothingEnabled), |
1060 | | fontExplicitLanguage(aOther.fontExplicitLanguage) |
1061 | 0 | { } |
1062 | | |
1063 | | void SetColorStyle(Style aWhichStyle, nscolor aColor) |
1064 | 0 | { |
1065 | 0 | colorStyles[aWhichStyle] = aColor; |
1066 | 0 | gradientStyles[aWhichStyle] = nullptr; |
1067 | 0 | patternStyles[aWhichStyle] = nullptr; |
1068 | 0 | } |
1069 | | |
1070 | | void SetPatternStyle(Style aWhichStyle, CanvasPattern* aPat) |
1071 | 0 | { |
1072 | 0 | gradientStyles[aWhichStyle] = nullptr; |
1073 | 0 | patternStyles[aWhichStyle] = aPat; |
1074 | 0 | } |
1075 | | |
1076 | | void SetGradientStyle(Style aWhichStyle, CanvasGradient* aGrad) |
1077 | 0 | { |
1078 | 0 | gradientStyles[aWhichStyle] = aGrad; |
1079 | 0 | patternStyles[aWhichStyle] = nullptr; |
1080 | 0 | } |
1081 | | |
1082 | | /** |
1083 | | * returns true iff the given style is a solid color. |
1084 | | */ |
1085 | | bool StyleIsColor(Style aWhichStyle) const |
1086 | 0 | { |
1087 | 0 | return !(patternStyles[aWhichStyle] || gradientStyles[aWhichStyle]); |
1088 | 0 | } |
1089 | | |
1090 | | int32_t ShadowBlurRadius() const |
1091 | 0 | { |
1092 | 0 | static const gfxFloat GAUSSIAN_SCALE_FACTOR = (3 * sqrt(2 * M_PI) / 4) * 1.5; |
1093 | 0 | return (int32_t)floor(ShadowBlurSigma() * GAUSSIAN_SCALE_FACTOR + 0.5); |
1094 | 0 | } |
1095 | | |
1096 | | mozilla::gfx::Float ShadowBlurSigma() const |
1097 | 0 | { |
1098 | 0 | return std::min(SIGMA_MAX, shadowBlur / 2.0f); |
1099 | 0 | } |
1100 | | |
1101 | | nsTArray<ClipState> clipsAndTransforms; |
1102 | | |
1103 | | RefPtr<gfxFontGroup> fontGroup; |
1104 | | RefPtr<nsAtom> fontLanguage; |
1105 | | nsFont fontFont; |
1106 | | |
1107 | | EnumeratedArray<Style, Style::MAX, RefPtr<CanvasGradient>> gradientStyles; |
1108 | | EnumeratedArray<Style, Style::MAX, RefPtr<CanvasPattern>> patternStyles; |
1109 | | EnumeratedArray<Style, Style::MAX, nscolor> colorStyles; |
1110 | | |
1111 | | nsString font; |
1112 | | TextAlign textAlign; |
1113 | | TextBaseline textBaseline; |
1114 | | |
1115 | | nscolor shadowColor; |
1116 | | |
1117 | | mozilla::gfx::Matrix transform; |
1118 | | mozilla::gfx::Point shadowOffset; |
1119 | | mozilla::gfx::Float lineWidth; |
1120 | | mozilla::gfx::Float miterLimit; |
1121 | | mozilla::gfx::Float globalAlpha; |
1122 | | mozilla::gfx::Float shadowBlur; |
1123 | | nsTArray<mozilla::gfx::Float> dash; |
1124 | | mozilla::gfx::Float dashOffset; |
1125 | | |
1126 | | mozilla::gfx::CompositionOp op; |
1127 | | mozilla::gfx::FillRule fillRule; |
1128 | | mozilla::gfx::CapStyle lineCap; |
1129 | | mozilla::gfx::JoinStyle lineJoin; |
1130 | | |
1131 | | nsString filterString; |
1132 | | nsTArray<nsStyleFilter> filterChain; |
1133 | | RefPtr<SVGFilterObserverList> filterObserverList; |
1134 | | mozilla::gfx::FilterDescription filter; |
1135 | | nsTArray<RefPtr<mozilla::gfx::SourceSurface>> filterAdditionalImages; |
1136 | | |
1137 | | // This keeps track of whether the canvas was "tainted" or not when |
1138 | | // we last used a filter. This is a security measure, whereby the |
1139 | | // canvas is flipped to write-only if a cross-origin image is drawn to it. |
1140 | | // This is to stop bad actors from reading back data they shouldn't have |
1141 | | // access to. |
1142 | | // |
1143 | | // This also limits what filters we can apply to the context; in particular |
1144 | | // feDisplacementMap is restricted. |
1145 | | // |
1146 | | // We keep track of this to ensure that if this gets out of sync with the |
1147 | | // tainted state of the canvas itself, we update our filters accordingly. |
1148 | | bool filterSourceGraphicTainted; |
1149 | | |
1150 | | bool imageSmoothingEnabled; |
1151 | | bool fontExplicitLanguage; |
1152 | | }; |
1153 | | |
1154 | | AutoTArray<ContextState, 3> mStyleStack; |
1155 | | |
1156 | 0 | inline ContextState& CurrentState() { |
1157 | 0 | return mStyleStack[mStyleStack.Length() - 1]; |
1158 | 0 | } |
1159 | | |
1160 | 0 | inline const ContextState& CurrentState() const { |
1161 | 0 | return mStyleStack[mStyleStack.Length() - 1]; |
1162 | 0 | } |
1163 | | |
1164 | | friend class CanvasGeneralPattern; |
1165 | | friend class SVGFilterObserverListForCanvas; |
1166 | | friend class AdjustedTarget; |
1167 | | friend class AdjustedTargetForShadow; |
1168 | | friend class AdjustedTargetForFilter; |
1169 | | |
1170 | | // other helpers |
1171 | | void GetAppUnitsValues(int32_t* aPerDevPixel, int32_t* aPerCSSPixel) |
1172 | 0 | { |
1173 | 0 | // If we don't have a canvas element, we just return something generic. |
1174 | 0 | int32_t devPixel = 60; |
1175 | 0 | int32_t cssPixel = 60; |
1176 | 0 |
|
1177 | 0 | nsIPresShell *ps = GetPresShell(); |
1178 | 0 | nsPresContext *pc; |
1179 | 0 |
|
1180 | 0 | if (!ps) goto FINISH; |
1181 | 0 | pc = ps->GetPresContext(); |
1182 | 0 | if (!pc) goto FINISH; |
1183 | 0 | devPixel = pc->AppUnitsPerDevPixel(); |
1184 | 0 | cssPixel = AppUnitsPerCSSPixel(); |
1185 | 0 |
|
1186 | 0 | FINISH: |
1187 | 0 | if (aPerDevPixel) |
1188 | 0 | *aPerDevPixel = devPixel; |
1189 | 0 | if (aPerCSSPixel) |
1190 | 0 | *aPerCSSPixel = cssPixel; |
1191 | 0 | } |
1192 | | |
1193 | | friend struct CanvasBidiProcessor; |
1194 | | friend class CanvasDrawObserver; |
1195 | | }; |
1196 | | |
1197 | | size_t BindingJSObjectMallocBytes(CanvasRenderingContext2D* aContext); |
1198 | | |
1199 | | } // namespace dom |
1200 | | } // namespace mozilla |
1201 | | |
1202 | | #endif /* CanvasRenderingContext2D_h */ |