Coverage Report

Created: 2018-09-25 14:53

/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 */