tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CanvasRenderingContext2D.h (43798B)


      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 "FilterDescription.h"
      9 #include "gfx2DGlue.h"
     10 #include "gfxFontConstants.h"
     11 #include "gfxTextRun.h"
     12 #include "gfxUtils.h"
     13 #include "mozilla/Attributes.h"
     14 #include "mozilla/EnumeratedArray.h"
     15 #include "mozilla/Maybe.h"
     16 #include "mozilla/MruCache.h"
     17 #include "mozilla/RefPtr.h"
     18 #include "mozilla/SurfaceFromElementResult.h"
     19 #include "mozilla/ThreadLocal.h"
     20 #include "mozilla/UniquePtr.h"
     21 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
     22 #include "mozilla/dom/HTMLCanvasElement.h"
     23 #include "mozilla/gfx/2D.h"
     24 #include "mozilla/gfx/Rect.h"
     25 #include "mozilla/intl/Bidi.h"
     26 #include "nsColor.h"
     27 #include "nsICanvasRenderingContextInternal.h"
     28 #include "nsIFrame.h"
     29 #include "nsRFPService.h"
     30 
     31 class gfxFontGroup;
     32 class nsGlobalWindowInner;
     33 class nsXULElement;
     34 
     35 namespace mozilla {
     36 class ErrorResult;
     37 class ISVGFilterObserverList;
     38 class PresShell;
     39 
     40 namespace gl {
     41 class SourceSurface;
     42 }  // namespace gl
     43 
     44 namespace layers {
     45 class PersistentBufferProvider;
     46 enum class LayersBackend : int8_t;
     47 }  // namespace layers
     48 
     49 namespace dom {
     50 class
     51    HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrOffscreenCanvasOrImageBitmapOrVideoFrame;
     52 using CanvasImageSource =
     53    HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrOffscreenCanvasOrImageBitmapOrVideoFrame;
     54 class ImageBitmap;
     55 class ImageData;
     56 class UTF8StringOrCanvasGradientOrCanvasPattern;
     57 class OwningUTF8StringOrCanvasGradientOrCanvasPattern;
     58 class TextMetrics;
     59 class CanvasGradient;
     60 class CanvasPath;
     61 class CanvasPattern;
     62 
     63 extern const mozilla::gfx::Float SIGMA_MAX;
     64 
     65 template <typename T>
     66 class Optional;
     67 
     68 struct CanvasBidiProcessor;
     69 class CanvasDrawObserver;
     70 class CanvasShutdownObserver;
     71 
     72 class DOMMatrix;
     73 class DOMMatrixReadOnly;
     74 struct DOMMatrix2DInit;
     75 
     76 /**
     77 ** CanvasRenderingContext2D
     78 **/
     79 class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
     80                                 public nsWrapperCache {
     81 protected:
     82  virtual ~CanvasRenderingContext2D();
     83 
     84 public:
     85  explicit CanvasRenderingContext2D(layers::LayersBackend aCompositorBackend);
     86 
     87  virtual JSObject* WrapObject(JSContext* aCx,
     88                               JS::Handle<JSObject*> aGivenProto) override;
     89 
     90  HTMLCanvasElement* GetCanvas() const {
     91    if (!mCanvasElement || mCanvasElement->IsInNativeAnonymousSubtree()) {
     92      return nullptr;
     93    }
     94 
     95    // corresponds to changes to the old bindings made in bug 745025
     96    return mCanvasElement->GetOriginalCanvas();
     97  }
     98 
     99  void GetContextAttributes(CanvasRenderingContext2DSettings& aSettings) const;
    100 
    101  void GetDebugInfo(bool aEnsureTarget,
    102                    CanvasRenderingContext2DDebugInfo& aDebugInfo,
    103                    ErrorResult& aError);
    104 
    105  void OnMemoryPressure() override;
    106  void OnBeforePaintTransaction() override;
    107  void OnDidPaintTransaction() override;
    108  layers::PersistentBufferProvider* GetBufferProvider() override;
    109 
    110  Maybe<layers::SurfaceDescriptor> GetFrontBuffer(
    111      WebGLFramebufferJS*, const bool webvr = false) override;
    112 
    113  already_AddRefed<layers::FwdTransactionTracker> UseCompositableForwarder(
    114      layers::CompositableForwarder* aForwarder) override;
    115 
    116  mozilla::gfx::Matrix GetCurrentTransform() const;
    117  bool HasAnyClips() const;
    118 
    119  void Save();
    120  void Restore();
    121 
    122  void Reset() {
    123    // reset the rendering context to its default state
    124    // Userland polyfill is `c2d.width = c2d.width;`
    125    SetDimensions(GetWidth(), GetHeight());
    126  }
    127 
    128  void Scale(double aX, double aY, mozilla::ErrorResult& aError);
    129  void Rotate(double aAngle, mozilla::ErrorResult& aError);
    130  void Translate(double aX, double aY, mozilla::ErrorResult& aError);
    131  void Transform(double aM11, double aM12, double aM21, double aM22, double aDx,
    132                 double aDy, mozilla::ErrorResult& aError);
    133  already_AddRefed<DOMMatrix> GetTransform(mozilla::ErrorResult& aError);
    134  void SetTransform(double aM11, double aM12, double aM21, double aM22,
    135                    double aDx, double aDy, mozilla::ErrorResult& aError);
    136  void SetTransform(const DOMMatrix2DInit& aInit, mozilla::ErrorResult& aError);
    137  void ResetTransform(mozilla::ErrorResult& aError);
    138 
    139  double GlobalAlpha() { return CurrentState().globalAlpha; }
    140 
    141  // Useful for silencing cast warnings
    142  static mozilla::gfx::Float ToFloat(double aValue) {
    143    return mozilla::gfx::Float(aValue);
    144  }
    145 
    146  void SetGlobalAlpha(double aGlobalAlpha) {
    147    if (aGlobalAlpha >= 0.0 && aGlobalAlpha <= 1.0) {
    148      CurrentState().globalAlpha = ToFloat(aGlobalAlpha);
    149    }
    150  }
    151 
    152  enum class ResolveCurrentColor : bool { No, Yes };
    153  Maybe<nscolor> ParseColor(const nsACString&,
    154                            ResolveCurrentColor = ResolveCurrentColor::Yes);
    155 
    156  void GetGlobalCompositeOperation(nsAString& aOp,
    157                                   mozilla::ErrorResult& aError);
    158  void SetGlobalCompositeOperation(const nsAString& aOp,
    159                                   mozilla::ErrorResult& aError);
    160 
    161  void GetStrokeStyle(OwningUTF8StringOrCanvasGradientOrCanvasPattern& aValue) {
    162    GetStyleAsUnion(aValue, Style::STROKE);
    163  }
    164 
    165  void SetStrokeStyle(const UTF8StringOrCanvasGradientOrCanvasPattern& aValue) {
    166    SetStyleFromUnion(aValue, Style::STROKE);
    167  }
    168 
    169  void GetFillStyle(OwningUTF8StringOrCanvasGradientOrCanvasPattern& aValue) {
    170    GetStyleAsUnion(aValue, Style::FILL);
    171  }
    172 
    173  void SetFillStyle(const UTF8StringOrCanvasGradientOrCanvasPattern& aValue) {
    174    SetStyleFromUnion(aValue, Style::FILL);
    175  }
    176 
    177  already_AddRefed<CanvasGradient> CreateLinearGradient(double aX0, double aY0,
    178                                                        double aX1, double aY1);
    179  already_AddRefed<CanvasGradient> CreateRadialGradient(double aX0, double aY0,
    180                                                        double aR0, double aX1,
    181                                                        double aY1, double aR1,
    182                                                        ErrorResult& aError);
    183  already_AddRefed<CanvasGradient> CreateConicGradient(double aAngle,
    184                                                       double aCx, double aCy);
    185  already_AddRefed<CanvasPattern> CreatePattern(
    186      const CanvasImageSource& aElement, const nsAString& aRepeat,
    187      ErrorResult& aError);
    188 
    189  double ShadowOffsetX() { return CurrentState().shadowOffset.x; }
    190 
    191  void SetShadowOffsetX(double aShadowOffsetX) {
    192    CurrentState().shadowOffset.x = ToFloat(aShadowOffsetX);
    193  }
    194 
    195  double ShadowOffsetY() { return CurrentState().shadowOffset.y; }
    196 
    197  void SetShadowOffsetY(double aShadowOffsetY) {
    198    CurrentState().shadowOffset.y = ToFloat(aShadowOffsetY);
    199  }
    200 
    201  double ShadowBlur() { return CurrentState().shadowBlur; }
    202 
    203  void SetShadowBlur(double aShadowBlur) {
    204    if (aShadowBlur >= 0.0) {
    205      CurrentState().shadowBlur = ToFloat(aShadowBlur);
    206    }
    207  }
    208 
    209  void GetShadowColor(nsACString& aShadowColor) {
    210    StyleColorToString(CurrentState().shadowColor, aShadowColor);
    211  }
    212 
    213  void GetFilter(nsACString& aFilter) { aFilter = CurrentState().filterString; }
    214 
    215  void SetShadowColor(const nsACString& aShadowColor);
    216  void SetFilter(const nsACString& aFilter, mozilla::ErrorResult& aError);
    217  void ClearRect(double aX, double aY, double aW, double aH);
    218  void FillRect(double aX, double aY, double aW, double aH);
    219  void StrokeRect(double aX, double aY, double aW, double aH);
    220  void BeginPath();
    221  void Fill(const CanvasWindingRule& aWinding);
    222  void Fill(const CanvasPath& aPath, const CanvasWindingRule& aWinding);
    223  void Stroke();
    224  void Stroke(const CanvasPath& aPath);
    225  void DrawFocusIfNeeded(mozilla::dom::Element& aElement, ErrorResult& aRv);
    226  bool DrawCustomFocusRing(mozilla::dom::Element& aElement);
    227  void Clip(const CanvasWindingRule& aWinding);
    228  void Clip(const CanvasPath& aPath, const CanvasWindingRule& aWinding);
    229  bool IsPointInPath(JSContext* aCx, double aX, double aY,
    230                     const CanvasWindingRule& aWinding,
    231                     nsIPrincipal& aSubjectPrincipal);
    232  bool IsPointInPath(JSContext* aCx, const CanvasPath& aPath, double aX,
    233                     double aY, const CanvasWindingRule& aWinding,
    234                     nsIPrincipal&);
    235  bool IsPointInStroke(JSContext* aCx, double aX, double aY,
    236                       nsIPrincipal& aSubjectPrincipal);
    237  bool IsPointInStroke(JSContext* aCx, const CanvasPath& aPath, double aX,
    238                       double aY, nsIPrincipal&);
    239  void FillText(const nsAString& aText, double aX, double aY,
    240                const Optional<double>& aMaxWidth,
    241                mozilla::ErrorResult& aError);
    242  void StrokeText(const nsAString& aText, double aX, double aY,
    243                  const Optional<double>& aMaxWidth,
    244                  mozilla::ErrorResult& aError);
    245  UniquePtr<TextMetrics> MeasureText(const nsAString& aRawText,
    246                                     mozilla::ErrorResult& aError);
    247 
    248  void DrawImage(const CanvasImageSource& aImage, double aDx, double aDy,
    249                 mozilla::ErrorResult& aError) {
    250    DrawImage(aImage, 0.0, 0.0, 0.0, 0.0, aDx, aDy, 0.0, 0.0, 0, aError);
    251  }
    252 
    253  void DrawImage(const CanvasImageSource& aImage, double aDx, double aDy,
    254                 double aDw, double aDh, mozilla::ErrorResult& aError) {
    255    DrawImage(aImage, 0.0, 0.0, 0.0, 0.0, aDx, aDy, aDw, aDh, 2, aError);
    256  }
    257 
    258  void DrawImage(const CanvasImageSource& aImage, double aSx, double aSy,
    259                 double aSw, double aSh, double aDx, double aDy, double aDw,
    260                 double aDh, mozilla::ErrorResult& aError) {
    261    DrawImage(aImage, aSx, aSy, aSw, aSh, aDx, aDy, aDw, aDh, 6, aError);
    262  }
    263 
    264  already_AddRefed<ImageData> CreateImageData(JSContext*, int32_t aSw,
    265                                              int32_t aSh, ErrorResult&);
    266  already_AddRefed<ImageData> CreateImageData(JSContext*, ImageData&,
    267                                              ErrorResult&);
    268  already_AddRefed<ImageData> GetImageData(JSContext*, int32_t aSx, int32_t aSy,
    269                                           int32_t aSw, int32_t aSh,
    270                                           nsIPrincipal& aSubjectPrincipal,
    271                                           ErrorResult&);
    272  void PutImageData(ImageData&, int32_t aDx, int32_t aDy, ErrorResult&);
    273  void PutImageData(ImageData&, int32_t aDx, int32_t aDy, int32_t aDirtyX,
    274                    int32_t aDirtyY, int32_t aDirtyWidth, int32_t aDirtyHeight,
    275                    ErrorResult&);
    276 
    277  double LineWidth() { return CurrentState().lineWidth; }
    278 
    279  void SetLineWidth(double aWidth) {
    280    if (aWidth > 0.0) {
    281      CurrentState().lineWidth = ToFloat(aWidth);
    282    }
    283  }
    284 
    285  CanvasLineCap LineCap() { return CurrentState().lineCap; }
    286  void SetLineCap(const CanvasLineCap& aLinecapStyle) {
    287    CurrentState().lineCap = aLinecapStyle;
    288  }
    289 
    290  CanvasLineJoin LineJoin() { return CurrentState().lineJoin; }
    291  void SetLineJoin(const CanvasLineJoin& aLinejoinStyle) {
    292    CurrentState().lineJoin = aLinejoinStyle;
    293  }
    294 
    295  double MiterLimit() { return CurrentState().miterLimit; }
    296 
    297  void SetMiterLimit(double aMiter) {
    298    if (aMiter > 0.0) {
    299      CurrentState().miterLimit = ToFloat(aMiter);
    300    }
    301  }
    302 
    303  void GetFont(nsACString& aFont) { aFont = GetFont(); }
    304 
    305  void SetFont(const nsACString& aFont, ErrorResult& aError);
    306 
    307  CanvasTextAlign TextAlign() { return CurrentState().textAlign; }
    308  void SetTextAlign(const CanvasTextAlign& aTextAlign) {
    309    CurrentState().textAlign = aTextAlign;
    310  }
    311 
    312  CanvasTextBaseline TextBaseline() { return CurrentState().textBaseline; }
    313  void SetTextBaseline(const CanvasTextBaseline& aTextBaseline) {
    314    CurrentState().textBaseline = aTextBaseline;
    315  }
    316 
    317  CanvasDirection Direction() { return CurrentState().textDirection; }
    318  void SetDirection(const CanvasDirection& aDirection) {
    319    CurrentState().textDirection = aDirection;
    320  }
    321 
    322  CanvasFontKerning FontKerning() { return CurrentState().fontKerning; }
    323  void SetFontKerning(const CanvasFontKerning& aFontKerning) {
    324    if (CurrentState().fontKerning != aFontKerning) {
    325      CurrentState().fontKerning = aFontKerning;
    326      CurrentState().fontGroup = nullptr;
    327    }
    328  }
    329 
    330  CanvasFontStretch FontStretch() { return CurrentState().fontStretch; }
    331  void SetFontStretch(const CanvasFontStretch& aFontStretch) {
    332    if (CurrentState().fontStretch != aFontStretch) {
    333      CurrentState().fontStretch = aFontStretch;
    334      CurrentState().fontGroup = nullptr;
    335    }
    336  }
    337 
    338  CanvasFontVariantCaps FontVariantCaps() {
    339    return CurrentState().fontVariantCaps;
    340  }
    341  void SetFontVariantCaps(const CanvasFontVariantCaps& aFontVariantCaps) {
    342    if (CurrentState().fontVariantCaps != aFontVariantCaps) {
    343      CurrentState().fontVariantCaps = aFontVariantCaps;
    344      CurrentState().fontGroup = nullptr;
    345    }
    346  }
    347 
    348  CanvasTextRendering TextRendering() { return CurrentState().textRendering; }
    349  void SetTextRendering(const CanvasTextRendering& aTextRendering) {
    350    CurrentState().textRendering = aTextRendering;
    351  }
    352 
    353  void GetLetterSpacing(nsACString& aLetterSpacing);
    354  void SetLetterSpacing(const nsACString& aLetterSpacing);
    355  void GetWordSpacing(nsACString& aWordSpacing);
    356  void SetWordSpacing(const nsACString& aWordSpacing);
    357 
    358  void EnsureCapped() {
    359    if (mPathPruned) {
    360      mPathBuilder->LineTo(mPathBuilder->CurrentPoint());
    361      mPathPruned = false;
    362    }
    363  }
    364 
    365  void EnsureActivePath() {
    366    if (mPathPruned && !mPathBuilder->IsActive()) {
    367      mPathBuilder->MoveTo(mPathBuilder->CurrentPoint());
    368      mPathPruned = false;
    369    }
    370  }
    371 
    372  void ClosePath() {
    373    if (!EnsureWritablePath()) {
    374      return;
    375    }
    376 
    377    mPathBuilder->Close();
    378    mPathPruned = false;
    379  }
    380 
    381  void MoveTo(double aX, double aY) {
    382    if (!EnsureWritablePath()) {
    383      return;
    384    }
    385 
    386    mozilla::gfx::Point pos(ToFloat(aX), ToFloat(aY));
    387    if (!pos.IsFinite()) {
    388      return;
    389    }
    390 
    391    EnsureCapped();
    392    mPathBuilder->MoveTo(pos);
    393  }
    394 
    395  void LineTo(double aX, double aY) {
    396    if (!EnsureWritablePath()) {
    397      return;
    398    }
    399 
    400    LineTo(mozilla::gfx::Point(ToFloat(aX), ToFloat(aY)));
    401  }
    402 
    403  void QuadraticCurveTo(double aCpx, double aCpy, double aX, double aY) {
    404    if (!EnsureWritablePath()) {
    405      return;
    406    }
    407 
    408    mozilla::gfx::Point cp1(ToFloat(aCpx), ToFloat(aCpy));
    409    mozilla::gfx::Point cp2(ToFloat(aX), ToFloat(aY));
    410    if (!cp1.IsFinite() || !cp2.IsFinite()) {
    411      return;
    412    }
    413 
    414    if (cp1 == mPathBuilder->CurrentPoint() && cp1 == cp2) {
    415      mPathPruned = true;
    416      return;
    417    }
    418    EnsureActivePath();
    419    mPathBuilder->QuadraticBezierTo(cp1, cp2);
    420    mPathPruned = false;
    421  }
    422 
    423  void BezierCurveTo(double aCp1x, double aCp1y, double aCp2x, double aCp2y,
    424                     double aX, double aY) {
    425    if (!EnsureWritablePath()) {
    426      return;
    427    }
    428 
    429    BezierTo(mozilla::gfx::Point(ToFloat(aCp1x), ToFloat(aCp1y)),
    430             mozilla::gfx::Point(ToFloat(aCp2x), ToFloat(aCp2y)),
    431             mozilla::gfx::Point(ToFloat(aX), ToFloat(aY)));
    432  }
    433 
    434  void ArcTo(double aX1, double aY1, double aX2, double aY2, double aRadius,
    435             mozilla::ErrorResult& aError);
    436  void Rect(double aX, double aY, double aW, double aH);
    437  void RoundRect(
    438      double aX, double aY, double aW, double aH,
    439      const UnrestrictedDoubleOrDOMPointInitOrUnrestrictedDoubleOrDOMPointInitSequence&
    440          aRadii,
    441      ErrorResult& aError);
    442  void Arc(double aX, double aY, double aRadius, double aStartAngle,
    443           double aEndAngle, bool aAnticlockwise, mozilla::ErrorResult& aError);
    444  void Ellipse(double aX, double aY, double aRadiusX, double aRadiusY,
    445               double aRotation, double aStartAngle, double aEndAngle,
    446               bool aAnticlockwise, ErrorResult& aError);
    447 
    448  void GetFillRule(nsAString& aFillRule);
    449  void SetFillRule(const nsAString& aFillRule);
    450 
    451  void SetLineDash(const Sequence<double>& aSegments,
    452                   mozilla::ErrorResult& aRv);
    453  void GetLineDash(nsTArray<double>& aSegments) const;
    454 
    455  void SetLineDashOffset(double aOffset);
    456  double LineDashOffset() const;
    457 
    458  bool ImageSmoothingEnabled() { return CurrentState().imageSmoothingEnabled; }
    459 
    460  void SetImageSmoothingEnabled(bool aImageSmoothingEnabled) {
    461    if (aImageSmoothingEnabled != CurrentState().imageSmoothingEnabled) {
    462      CurrentState().imageSmoothingEnabled = aImageSmoothingEnabled;
    463    }
    464  }
    465 
    466  CanvasContextProperties ContextProperties() const {
    467    return mContextProperties;
    468  }
    469 
    470  void SetContextProperties(const CanvasContextProperties& aValue) {
    471    mContextProperties = aValue;
    472  }
    473 
    474  void DrawWindow(nsGlobalWindowInner& aWindow, double aX, double aY, double aW,
    475                  double aH, const nsACString& aBgColor, uint32_t aFlags,
    476                  nsIPrincipal& aSubjectPrincipal,
    477                  mozilla::ErrorResult& aError);
    478 
    479  // Eventually this should be deprecated. Keeping for now to keep the binding
    480  // functional.
    481  void Demote();
    482 
    483  nsresult Redraw();
    484 
    485  gfx::IntSize GetSize() const { return gfx::IntSize(mWidth, mHeight); }
    486  int32_t GetWidth() override { return GetSize().width; }
    487  int32_t GetHeight() override { return GetSize().height; }
    488 
    489  // nsICanvasRenderingContextInternal
    490  /**
    491   * Gets the pres shell from either the canvas element or the doc shell
    492   */
    493  PresShell* GetPresShell() final;
    494  nsresult Initialize() override;
    495  NS_IMETHOD SetDimensions(int32_t aWidth, int32_t aHeight) override;
    496  NS_IMETHOD InitializeWithDrawTarget(
    497      nsIDocShell* aShell, NotNull<gfx::DrawTarget*> aTarget) override;
    498 
    499  NS_IMETHOD GetInputStream(
    500      const char* aMimeType, const nsAString& aEncoderOptions,
    501      mozilla::CanvasUtils::ImageExtraction aExtractionBehavior,
    502      const nsACString& aRandomizationKey, nsIInputStream** aStream) override;
    503 
    504  already_AddRefed<mozilla::gfx::SourceSurface> GetOptimizedSnapshot(
    505      mozilla::gfx::DrawTarget* aTarget, gfxAlphaType* aOutAlphaType) override;
    506 
    507  already_AddRefed<mozilla::gfx::SourceSurface> GetSurfaceSnapshot(
    508      gfxAlphaType* aOutAlphaType = nullptr) override {
    509    return GetOptimizedSnapshot(nullptr, aOutAlphaType);
    510  }
    511 
    512  virtual void SetOpaqueValueFromOpaqueAttr(bool aOpaqueAttrValue) override;
    513  bool GetIsOpaque() override { return mOpaque; }
    514  void ResetBitmap(bool aFreeBuffer);
    515  void ResetBitmap() override { ResetBitmap(true); }
    516 
    517  bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
    518                                 WebRenderCanvasData* aCanvasData) override;
    519 
    520  bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
    521                                CanvasRenderer* aRenderer) override;
    522  void MarkContextClean() override;
    523  void MarkContextCleanForFrameCapture() override {
    524    mFrameCaptureState = FrameCaptureState::CLEAN;
    525  }
    526  Watchable<FrameCaptureState>* GetFrameCaptureState() override {
    527    return &mFrameCaptureState;
    528  }
    529  // this rect is in canvas device space
    530  void Redraw(const mozilla::gfx::Rect& aR);
    531  NS_IMETHOD Redraw(const gfxRect& aR) override {
    532    Redraw(ToRect(aR));
    533    return NS_OK;
    534  }
    535  NS_IMETHOD SetContextOptions(JSContext* aCx, JS::Handle<JS::Value> aOptions,
    536                               ErrorResult& aRvForDictionaryInit) override;
    537 
    538  /**
    539   * An abstract base class to be implemented by callers wanting to be notified
    540   * that a refresh has occurred. Callers must ensure an observer is removed
    541   * before it is destroyed.
    542   */
    543  virtual void DidRefresh() override;
    544 
    545  // this rect is in mTarget's current user space
    546  void RedrawUser(const gfxRect& aR);
    547 
    548  // nsISupports interface + CC
    549  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    550 
    551  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS(
    552      CanvasRenderingContext2D)
    553 
    554  enum class CanvasMultiGetterType : uint8_t {
    555    STRING = 0,
    556    PATTERN = 1,
    557    GRADIENT = 2
    558  };
    559 
    560  enum class Style : uint8_t { STROKE = 0, FILL, MAX };
    561 
    562  void LineTo(const mozilla::gfx::Point& aPoint) {
    563    mFeatureUsage |= CanvasFeatureUsage::LineTo;
    564 
    565    if (!aPoint.IsFinite()) {
    566      return;
    567    }
    568    if (mPathBuilder->CurrentPoint() == aPoint) {
    569      mPathPruned = true;
    570      return;
    571    }
    572    EnsureActivePath();
    573    mPathBuilder->LineTo(aPoint);
    574    mPathPruned = false;
    575  }
    576 
    577  void BezierTo(const mozilla::gfx::Point& aCP1,
    578                const mozilla::gfx::Point& aCP2,
    579                const mozilla::gfx::Point& aCP3) {
    580    if (!aCP1.IsFinite() || !aCP2.IsFinite() || !aCP3.IsFinite()) {
    581      return;
    582    }
    583 
    584    if (aCP1 == mPathBuilder->CurrentPoint() && aCP1 == aCP2 && aCP1 == aCP3) {
    585      mPathPruned = true;
    586      return;
    587    }
    588    EnsureActivePath();
    589    mPathBuilder->BezierTo(aCP1, aCP2, aCP3);
    590    mPathPruned = false;
    591  }
    592 
    593  virtual UniquePtr<uint8_t[]> GetImageBuffer(
    594      mozilla::CanvasUtils::ImageExtraction aExtractionBehavior,
    595      int32_t* out_format, gfx::IntSize* out_imageSize) override;
    596 
    597  void OnShutdown();
    598 
    599  bool IsContextLost() const { return mIsContextLost; }
    600  void OnRemoteCanvasLost();
    601  void OnRemoteCanvasRestored();
    602 
    603  /**
    604   * Update CurrentState().filter with the filter description for
    605   * CurrentState().filterChain.
    606   * Flushes the PresShell if aFlushIsNeeded is true, so the world can change
    607   * if you call this function.
    608   */
    609  MOZ_CAN_RUN_SCRIPT_BOUNDARY void UpdateFilter(bool aFlushIfNeeded);
    610 
    611  CanvasFeatureUsage FeatureUsage() const { return mFeatureUsage; }
    612 
    613 protected:
    614  /**
    615   * Helper to parse a value for the letterSpacing or wordSpacing attribute.
    616   * If successful, returns the result in aValue, and the whitespace-normalized
    617   * value string in aNormalized; if unsuccessful these are left untouched.
    618   */
    619  void ParseSpacing(const nsACString& aSpacing, float* aValue,
    620                    nsACString& aNormalized);
    621 
    622  already_AddRefed<const ComputedStyle> ResolveStyleForProperty(
    623      NonCustomCSSPropertyId aProperty, const nsACString& aValue);
    624 
    625  nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
    626                             uint32_t aWidth, uint32_t aHeight,
    627                             nsIPrincipal& aSubjectPrincipal,
    628                             JSObject** aRetval);
    629 
    630  void PutImageData_explicit(int32_t aX, int32_t aY, ImageData&,
    631                             bool aHasDirtyRect, int32_t aDirtyX,
    632                             int32_t aDirtyY, int32_t aDirtyWidth,
    633                             int32_t aDirtyHeight, ErrorResult&);
    634 
    635  bool CopyBufferProvider(layers::PersistentBufferProvider& aOld,
    636                          gfx::DrawTarget& aTarget, gfx::IntRect aCopyRect);
    637 
    638  /**
    639   * Internal method to complete initialisation, expects mTarget to have been
    640   * set
    641   */
    642  nsresult Initialize(int32_t aWidth, int32_t aHeight);
    643 
    644  nsresult InitializeWithTarget(mozilla::gfx::DrawTarget* aSurface,
    645                                int32_t aWidth, int32_t aHeight);
    646 
    647  /**
    648   * The number of living nsCanvasRenderingContexts.  When this goes down to
    649   * 0, we free the premultiply and unpremultiply tables, if they exist.
    650   */
    651  static MOZ_THREAD_LOCAL(uintptr_t) sNumLivingContexts;
    652 
    653  static MOZ_THREAD_LOCAL(mozilla::gfx::DrawTarget*) sErrorTarget;
    654 
    655  void SetTransformInternal(const mozilla::gfx::Matrix& aTransform);
    656 
    657  // Some helpers.  Doesn't modify a color on failure.
    658  void SetStyleFromUnion(
    659      const UTF8StringOrCanvasGradientOrCanvasPattern& aValue,
    660      Style aWhichStyle);
    661  void SetStyleFromString(const nsACString& aStr, Style aWhichStyle);
    662 
    663  void SetStyleFromGradient(CanvasGradient& aGradient, Style aWhichStyle) {
    664    CurrentState().SetGradientStyle(aWhichStyle, &aGradient);
    665  }
    666 
    667  void SetStyleFromPattern(CanvasPattern& aPattern, Style aWhichStyle) {
    668    CurrentState().SetPatternStyle(aWhichStyle, &aPattern);
    669  }
    670 
    671  void GetStyleAsUnion(OwningUTF8StringOrCanvasGradientOrCanvasPattern& aValue,
    672                       Style aWhichStyle);
    673 
    674  static void StyleColorToString(const nscolor& aColor, nsACString& aStr);
    675 
    676  // Returns whether a filter was successfully parsed.
    677  bool ParseFilter(const nsACString& aString,
    678                   StyleOwnedSlice<StyleFilter>& aFilterChain,
    679                   ErrorResult& aError);
    680 
    681  // Returns whether the font was successfully updated.
    682  bool SetFontInternal(const nsACString& aFont, mozilla::ErrorResult& aError);
    683 
    684  // Helper for SetFontInternal in the case where we have no PresShell.
    685  bool SetFontInternalDisconnected(const nsACString& aFont,
    686                                   mozilla::ErrorResult& aError);
    687 
    688  // Update the resolved values for letterSpacing and wordSpacing, if present,
    689  // following a potential change to font-relative dimensions.
    690  void UpdateSpacing();
    691 
    692  // Clears the target and updates mOpaque based on mOpaqueAttrValue and
    693  // mContextAttributesHasAlpha.
    694  void UpdateIsOpaque();
    695 
    696  // Shared implementation for Stroke() and Stroke(CanvasPath) methods.
    697  void StrokeImpl(const mozilla::gfx::Path& aPath);
    698 
    699  // Shared implementation for Fill() methods.
    700  void FillImpl(const mozilla::gfx::Path& aPath);
    701 
    702  /**
    703   * Creates the error target, if it doesn't exist
    704   */
    705  static void EnsureErrorTarget();
    706 
    707  /* This function ensures there is a writable pathbuilder available
    708   */
    709  bool EnsureWritablePath();
    710 
    711  // Ensures there is a valid BufferProvider for creating a PathBuilder.
    712  bool EnsureBufferProvider();
    713 
    714  // Ensures a path in UserSpace is available.
    715  void EnsureUserSpacePath(
    716      const CanvasWindingRule& aWinding = CanvasWindingRule::Nonzero);
    717 
    718  // Ensures both target and a path in UserSpace is available.
    719  void EnsureTargetAndUserSpacePath(
    720      const CanvasWindingRule& aWinding = CanvasWindingRule::Nonzero) {
    721    EnsureTarget();
    722    EnsureUserSpacePath(aWinding);
    723  }
    724 
    725  /**
    726   * Needs to be called before updating the transform. This makes a call to
    727   * EnsureTarget() so you don't have to.
    728   */
    729  void TransformCurrentPath(const mozilla::gfx::Matrix& aTransform);
    730 
    731  // Report the fillRule has changed.
    732  void FillRuleChanged();
    733 
    734  /**
    735   * Check if the target is in an error state. Functions that may need to
    736   * access the transform or clip state with or without a target should call
    737   * this first to verify that it's okay to access this state, as error targets
    738   * should ignore it instead.
    739   */
    740  bool HasErrorState(ErrorResult& aError, bool aInitProvider = true);
    741  bool HasErrorState() {
    742    IgnoredErrorResult error;
    743    return HasErrorState(error);
    744  }
    745 
    746  /**
    747   * Create the backing surfacing, if it doesn't exist. If there is an error
    748   * in creating the target then it will put sErrorTarget in place. If there
    749   * is in turn an error in creating the sErrorTarget then they would both
    750   * be null so IsTargetValid() would still return null.
    751   *
    752   * Returns true on success.
    753   */
    754  bool EnsureTarget(ErrorResult& aError,
    755                    const gfx::Rect* aCoveredRect = nullptr,
    756                    bool aWillClear = false, bool aSkipTransform = false);
    757 
    758  bool EnsureTarget(const gfx::Rect* aCoveredRect = nullptr,
    759                    bool aWillClear = false, bool aSkipTransform = false) {
    760    IgnoredErrorResult error;
    761    return EnsureTarget(error, aCoveredRect, aWillClear, aSkipTransform);
    762  }
    763 
    764  // Attempt to borrow a new target from an existing buffer provider.
    765  bool BorrowTarget(const gfx::IntRect& aPersistedRect, bool aNeedsClear);
    766 
    767  void RestoreClipsAndTransformToTarget();
    768 
    769  bool TryAcceleratedTarget(
    770      RefPtr<gfx::DrawTarget>& aOutDT,
    771      RefPtr<layers::PersistentBufferProvider>& aOutProvider);
    772 
    773  bool TrySharedTarget(RefPtr<gfx::DrawTarget>& aOutDT,
    774                       RefPtr<layers::PersistentBufferProvider>& aOutProvider);
    775 
    776  bool TryBasicTarget(RefPtr<gfx::DrawTarget>& aOutDT,
    777                      RefPtr<layers::PersistentBufferProvider>& aOutProvider,
    778                      ErrorResult& aError);
    779 
    780  void RegisterAllocation();
    781 
    782  void SetInitialState();
    783 
    784  void SetErrorState();
    785 
    786  /**
    787   * This method is run at the end of the event-loop spin where
    788   * ScheduleStableStateCallback was called.
    789   *
    790   * We use it to unlock resources that need to be locked while drawing.
    791   */
    792  void OnStableState();
    793 
    794  /**
    795   * Cf. OnStableState.
    796   */
    797  void ScheduleStableStateCallback();
    798 
    799  /**
    800   * Disposes an old target and prepares to lazily create a new target.
    801   *
    802   * Parameters are the new dimensions to be used, or if either is negative,
    803   * existing dimensions will be left unchanged.
    804   */
    805  void ClearTarget(int32_t aWidth = -1, int32_t aHeight = -1);
    806 
    807  /*
    808   * Returns the target to the buffer provider. i.e. this will queue a frame for
    809   * rendering.
    810   */
    811  void ReturnTarget(bool aForceReset = false);
    812 
    813  /**
    814   * Check if the target is valid after calling EnsureTarget.
    815   */
    816  bool IsTargetValid() const {
    817    return !!mTarget && mTarget != sErrorTarget.get() && !mIsContextLost;
    818  }
    819 
    820  /**
    821   * Returns the surface format this canvas should be allocated using. Takes
    822   * into account mOpaque, platform requirements, etc.
    823   */
    824  mozilla::gfx::SurfaceFormat GetSurfaceFormat() const;
    825 
    826  /**
    827   * Returns true if we know for sure that the pattern for a given style is
    828   * opaque. Usefull to know if we can discard the content below in certain
    829   * situations. Optionally checks if the pattern is a color pattern.
    830   */
    831  bool PatternIsOpaque(Style aStyle, bool* aIsColor = nullptr) const;
    832 
    833  SurfaceFromElementResult CachedSurfaceFromElement(Element* aElement);
    834 
    835  void DrawImage(const CanvasImageSource& aImgElt, double aSx, double aSy,
    836                 double aSw, double aSh, double aDx, double aDy, double aDw,
    837                 double aDh, uint8_t aOptional_argc,
    838                 mozilla::ErrorResult& aError);
    839 
    840  void DrawDirectlyToCanvas(const DirectDrawInfo& aImage,
    841                            mozilla::gfx::Rect* aBounds,
    842                            mozilla::gfx::Rect aDest, mozilla::gfx::Rect aSrc,
    843                            gfx::IntSize aImgSize);
    844 
    845  nsCString& GetFont() {
    846    // will initialize the value if not set, else does nothing
    847    GetCurrentFontStyle();
    848 
    849    return CurrentState().font;
    850  }
    851 
    852  bool UseSoftwareRendering() const;
    853 
    854  // Member vars
    855  int32_t mWidth, mHeight;
    856 
    857  // This is true when the canvas is valid, but of zero size, this requires
    858  // specific behavior on some operations.
    859  bool mZero;
    860 
    861  // The two ways to set the opaqueness of the canvas.
    862  // mOpaqueAttrValue: Whether the <canvas> element has the moz-opaque attribute
    863  // set. Can change during the lifetime of the context. Non-standard, should
    864  // hopefully go away soon.
    865  // mContextAttributesHasAlpha: The standard way of setting canvas opaqueness.
    866  // Set at context initialization time and never changes.
    867  bool mOpaqueAttrValue;
    868  bool mContextAttributesHasAlpha;
    869 
    870  // Determines the context's opaqueness. Is computed from mOpaqueAttrValue and
    871  // mContextAttributesHasAlpha in UpdateIsOpaque().
    872  bool mOpaque;
    873 
    874  // This is true when the next time our layer is retrieved we need to
    875  // recreate it (i.e. our backing surface changed)
    876  bool mResetLayer;
    877  // This is needed for drawing in drawAsyncXULElement
    878  bool mIPC;
    879 
    880  bool mHasPendingStableStateCallback;
    881 
    882  // If mCanvasElement is not provided, then a docshell is
    883  nsCOMPtr<nsIDocShell> mDocShell;
    884 
    885  // This is created lazily so it is necessary to call EnsureTarget before
    886  // accessing it. In the event of an error it will be equal to
    887  // sErrorTarget.
    888  RefPtr<mozilla::gfx::DrawTarget> mTarget;
    889 
    890  RefPtr<mozilla::layers::PersistentBufferProvider> mBufferProvider;
    891  // Whether the target's buffer must be cleared before drawing.
    892  bool mBufferNeedsClear = false;
    893  // Whether the current state contains clips or transforms not set on target.
    894  bool mTargetNeedsClipsAndTransforms = false;
    895 
    896  // Whether we should try to create an accelerated buffer provider.
    897  bool mAllowAcceleration = true;
    898  // Whether the application expects to use operations that perform poorly with
    899  // acceleration.
    900  bool mWillReadFrequently = false;
    901  // Whether to force software rendering
    902  bool mForceSoftwareRendering = false;
    903  // Whether or not we have already shutdown.
    904  bool mHasShutdown = false;
    905  // Whether or not remote canvas is currently unavailable.
    906  bool mIsContextLost = false;
    907  // Whether or not we can restore the context after restoration.
    908  bool mAllowContextRestore = true;
    909  // Which context properties apply to an SVG when calling drawImage.
    910  CanvasContextProperties mContextProperties = CanvasContextProperties::None;
    911 
    912  bool AddShutdownObserver();
    913  void RemoveShutdownObserver();
    914  bool AlreadyShutDown() const { return mHasShutdown; }
    915 
    916  /**
    917   * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
    918   * Redraw is called, reset to false when Render is called.
    919   */
    920  bool mIsEntireFrameInvalid;
    921  /**
    922   * When this is set, the first call to Redraw(gfxRect) should set
    923   * mIsEntireFrameInvalid since we expect it will be followed by
    924   * many more Redraw calls.
    925   */
    926  bool mPredictManyRedrawCalls;
    927 
    928  /**
    929   * Flag to avoid unnecessary surface copies to FrameCaptureListeners in the
    930   * case when the canvas is not currently being drawn into and not rendered
    931   * but canvas capturing is still ongoing.
    932   */
    933  Watchable<FrameCaptureState> mFrameCaptureState;
    934 
    935  /**
    936   * We also have a device space pathbuilder. The reason for this is as
    937   * follows, when a path is being built, but the transform changes, we
    938   * can no longer keep a single path in userspace, considering there's
    939   * several 'user spaces' now. We therefore transform the current path
    940   * into device space, and add all operations to this path in device
    941   * space.
    942   *
    943   * When then finally executing a render, the Azure drawing API expects
    944   * the path to be in userspace. We could then set an identity transform
    945   * on the DrawTarget and do all drawing in device space. This is
    946   * undesirable because it requires transforming patterns, gradients,
    947   * clips, etc. into device space and it would not work for stroking.
    948   * What we do instead is convert the path back to user space when it is
    949   * drawn, and draw it with the current transform. This makes all drawing
    950   * occur correctly.
    951   *
    952   * There's never both a device space path builder and a user space path
    953   * builder present at the same time. There is also never a path and a
    954   * path builder present at the same time. When writing proceeds on an
    955   * existing path the Path is cleared and a new builder is created.
    956   *
    957   * mPath is always in user-space.
    958   */
    959  RefPtr<mozilla::gfx::Path> mPath;
    960  RefPtr<mozilla::gfx::PathBuilder> mPathBuilder;
    961  mozilla::gfx::BackendType mPathType = mozilla::gfx::BackendType::NONE;
    962  bool mPathPruned = false;
    963  mozilla::gfx::Matrix mPathTransform;
    964  bool mPathTransformDirty = false;
    965 
    966  void FlushPathTransform();
    967 
    968  /**
    969   * Number of times we've invalidated before calling redraw
    970   */
    971  uint32_t mInvalidateCount;
    972  static const uint32_t kCanvasMaxInvalidateCount = 100;
    973 
    974  mozilla::intl::Bidi mBidiEngine;
    975 
    976  /**
    977   * Returns true if a shadow should be drawn along with a
    978   * drawing operation.
    979   */
    980  bool NeedToDrawShadow() {
    981    const ContextState& state = CurrentState();
    982 
    983    // The spec says we should not draw shadows if the operator is OVER.
    984    // If it's over and the alpha value is zero, nothing needs to be drawn.
    985    return NS_GET_A(state.shadowColor) != 0 &&
    986           (state.shadowBlur != 0.f || state.shadowOffset.x != 0.f ||
    987            state.shadowOffset.y != 0.f);
    988  }
    989 
    990  /**
    991   * Returns true if the result of a drawing operation should be
    992   * drawn with a filter.
    993   */
    994  bool NeedToApplyFilter() {
    995    return EnsureUpdatedFilter().mPrimitives.Length() > 0;
    996  }
    997 
    998  /**
    999   * Calls UpdateFilter if the canvas's WriteOnly state has changed between the
   1000   * last call to UpdateFilter and now.
   1001   */
   1002  const gfx::FilterDescription& EnsureUpdatedFilter() {
   1003    bool isWriteOnly = mCanvasElement && mCanvasElement->IsWriteOnly();
   1004    if (CurrentState().filterSourceGraphicTainted != isWriteOnly) {
   1005      UpdateFilter(/* aFlushIfNeeded = */ true);
   1006      EnsureTarget();
   1007    }
   1008    MOZ_ASSERT(CurrentState().filterSourceGraphicTainted == isWriteOnly);
   1009    return CurrentState().filter;
   1010  }
   1011 
   1012  bool NeedToCalculateBounds() {
   1013    return NeedToDrawShadow() || NeedToApplyFilter();
   1014  }
   1015 
   1016  // text
   1017 
   1018 public:
   1019  gfxFontGroup* GetCurrentFontStyle();
   1020 
   1021 protected:
   1022  enum class TextDrawOperation : uint8_t { FILL, STROKE, MEASURE };
   1023 
   1024  /**
   1025   * Implementation of the fillText, strokeText, and measure functions with
   1026   * the operation abstracted to a flag.
   1027   * Returns a TextMetrics object _only_ if the operation is measure;
   1028   * drawing operations (fill or stroke) always return nullptr.
   1029   */
   1030  UniquePtr<TextMetrics> DrawOrMeasureText(const nsAString& aText, float aX,
   1031                                           float aY,
   1032                                           const Optional<double>& aMaxWidth,
   1033                                           TextDrawOperation aOp,
   1034                                           ErrorResult& aError);
   1035 
   1036  // A clip or a transform, recorded and restored in order.
   1037  struct ClipState {
   1038    explicit ClipState(mozilla::gfx::Path* aClip) : clip(aClip) {}
   1039 
   1040    explicit ClipState(const mozilla::gfx::Matrix& aTransform)
   1041        : transform(aTransform) {}
   1042 
   1043    bool IsClip() const { return !!clip; }
   1044 
   1045    RefPtr<mozilla::gfx::Path> clip;
   1046    mozilla::gfx::Matrix transform;
   1047  };
   1048 
   1049  // state stack handling
   1050  class ContextState {
   1051   public:
   1052    ContextState();
   1053    ContextState(const ContextState& aOther);
   1054    ~ContextState();
   1055 
   1056    void SetColorStyle(Style aWhichStyle, nscolor aColor);
   1057    void SetPatternStyle(Style aWhichStyle, CanvasPattern* aPat);
   1058    void SetGradientStyle(Style aWhichStyle, CanvasGradient* aGrad);
   1059 
   1060    /**
   1061     * returns true iff the given style is a solid color.
   1062     */
   1063    bool StyleIsColor(Style aWhichStyle) const {
   1064      return !(patternStyles[aWhichStyle] || gradientStyles[aWhichStyle]);
   1065    }
   1066 
   1067    int32_t ShadowBlurRadius() const {
   1068      static const gfxFloat GAUSSIAN_SCALE_FACTOR =
   1069          (3 * sqrt(2 * M_PI) / 4) * 1.5;
   1070      return (int32_t)floor(ShadowBlurSigma() * GAUSSIAN_SCALE_FACTOR + 0.5);
   1071    }
   1072 
   1073    mozilla::gfx::Float ShadowBlurSigma() const {
   1074      return std::min(SIGMA_MAX, shadowBlur / 2.0f);
   1075    }
   1076 
   1077    ElementOrArray<ClipState> clipsAndTransforms;
   1078 
   1079    RefPtr<gfxFontGroup> fontGroup;
   1080    nsFont fontFont;
   1081    RefPtr<const ComputedStyle>
   1082        fontComputedStyle;  // NOTE: Only non-null if connected.
   1083 
   1084    EnumeratedArray<Style, RefPtr<CanvasGradient>, size_t(Style::MAX)>
   1085        gradientStyles;
   1086    EnumeratedArray<Style, RefPtr<CanvasPattern>, size_t(Style::MAX)>
   1087        patternStyles;
   1088    EnumeratedArray<Style, nscolor, size_t(Style::MAX)> colorStyles;
   1089 
   1090    nsCString font;
   1091    CanvasTextAlign textAlign = CanvasTextAlign::Start;
   1092    CanvasTextBaseline textBaseline = CanvasTextBaseline::Alphabetic;
   1093    CanvasDirection textDirection = CanvasDirection::Inherit;
   1094    CanvasFontKerning fontKerning = CanvasFontKerning::Auto;
   1095    CanvasFontStretch fontStretch = CanvasFontStretch::Normal;
   1096    CanvasFontVariantCaps fontVariantCaps = CanvasFontVariantCaps::Normal;
   1097    CanvasTextRendering textRendering = CanvasTextRendering::Auto;
   1098 
   1099    gfx::Float letterSpacing = 0.0f;
   1100    gfx::Float wordSpacing = 0.0f;
   1101    nsCString letterSpacingStr;
   1102    nsCString wordSpacingStr;
   1103 
   1104    nscolor shadowColor = 0;
   1105 
   1106    mozilla::gfx::Matrix transform;
   1107    mozilla::gfx::Point shadowOffset;
   1108    mozilla::gfx::Float lineWidth = 1.0f;
   1109    mozilla::gfx::Float miterLimit = 10.0f;
   1110    mozilla::gfx::Float globalAlpha = 1.0f;
   1111    mozilla::gfx::Float shadowBlur = 0.0f;
   1112 
   1113    nsTArray<mozilla::gfx::Float> dash;
   1114    mozilla::gfx::Float dashOffset = 0.0f;
   1115 
   1116    mozilla::gfx::CompositionOp op = mozilla::gfx::CompositionOp::OP_OVER;
   1117    mozilla::gfx::FillRule fillRule = mozilla::gfx::FillRule::FILL_WINDING;
   1118    CanvasLineCap lineCap = CanvasLineCap::Butt;
   1119    CanvasLineJoin lineJoin = CanvasLineJoin::Miter;
   1120 
   1121    nsCString filterString{"none"};
   1122    StyleOwnedSlice<StyleFilter> filterChain;
   1123    // RAII object that we obtain when we start to observer SVG filter elements
   1124    // for rendering changes.  When released we stop observing the SVG elements.
   1125    nsCOMPtr<ISVGFilterObserverList> autoSVGFiltersObserver;
   1126    mozilla::gfx::FilterDescription filter;
   1127    nsTArray<RefPtr<mozilla::gfx::SourceSurface>> filterAdditionalImages;
   1128 
   1129    // This keeps track of whether the canvas was "tainted" or not when
   1130    // we last used a filter. This is a security measure, whereby the
   1131    // canvas is flipped to write-only if a cross-origin image is drawn to it.
   1132    // This is to stop bad actors from reading back data they shouldn't have
   1133    // access to.
   1134    //
   1135    // This also limits what filters we can apply to the context; in particular
   1136    // feDisplacementMap is restricted.
   1137    //
   1138    // We keep track of this to ensure that if this gets out of sync with the
   1139    // tainted state of the canvas itself, we update our filters accordingly.
   1140    bool filterSourceGraphicTainted = false;
   1141    bool imageSmoothingEnabled = true;
   1142  };
   1143 
   1144  AutoTArray<ContextState, 3> mStyleStack;
   1145 
   1146  inline ContextState& CurrentState() {
   1147    return mStyleStack[mStyleStack.Length() - 1];
   1148  }
   1149 
   1150  inline const ContextState& CurrentState() const {
   1151    return mStyleStack[mStyleStack.Length() - 1];
   1152  }
   1153 
   1154  inline const ContextState& PreviousState() const {
   1155    return mStyleStack[mStyleStack.Length() - 2];
   1156  }
   1157 
   1158  struct FontStyleCacheKey {
   1159    FontStyleCacheKey() = default;
   1160    FontStyleCacheKey(const nsACString& aFont, uint64_t aGeneration)
   1161        : mFont(aFont), mGeneration(aGeneration) {}
   1162    nsCString mFont;
   1163    uint64_t mGeneration = 0;
   1164  };
   1165 
   1166  struct FontStyleData {
   1167    FontStyleCacheKey mKey;
   1168    nsCString mUsedFont;
   1169    RefPtr<const ComputedStyle> mStyle;
   1170  };
   1171 
   1172  class FontStyleCache
   1173      : public MruCache<FontStyleCacheKey, FontStyleData, FontStyleCache> {
   1174   public:
   1175    static HashNumber Hash(const FontStyleCacheKey& aKey) {
   1176      HashNumber hash = HashString(aKey.mFont);
   1177      return AddToHash(hash, aKey.mGeneration);
   1178    }
   1179    static bool Match(const FontStyleCacheKey& aKey,
   1180                      const FontStyleData& aVal) {
   1181      return aVal.mKey.mGeneration == aKey.mGeneration &&
   1182             aVal.mKey.mFont == aKey.mFont;
   1183    }
   1184  };
   1185 
   1186  FontStyleCache mFontStyleCache;
   1187  const ComputedStyle* GetCurrentFontComputedStyle() {
   1188    GetCurrentFontStyle();
   1189    return CurrentState().fontComputedStyle;
   1190  }
   1191 
   1192  struct ColorStyleCacheEntry {
   1193    nsCString mKey;
   1194    Maybe<nscolor> mColor;
   1195    bool mWasCurrentColor = false;
   1196  };
   1197  class ColorStyleCache
   1198      : public MruCache<nsACString, ColorStyleCacheEntry, ColorStyleCache> {
   1199   public:
   1200    static HashNumber Hash(const nsACString& aKey) { return HashString(aKey); }
   1201    static bool Match(const nsACString& aKey,
   1202                      const ColorStyleCacheEntry& aVal) {
   1203      return aVal.mKey == aKey;
   1204    }
   1205  };
   1206  ColorStyleCache mColorStyleCache;
   1207 
   1208  ColorStyleCacheEntry ParseColorSlow(const nsACString&);
   1209 
   1210  mozilla::gfx::PaletteCache mPaletteCache;
   1211 
   1212  friend class CanvasGeneralPattern;
   1213  friend class AdjustedTarget;
   1214  friend class AdjustedTargetForShadow;
   1215  friend class AdjustedTargetForFilter;
   1216 
   1217  // other helpers
   1218  void GetAppUnitsValues(int32_t* aPerDevPixel, int32_t* aPerCSSPixel);
   1219 
   1220  friend struct CanvasBidiProcessor;
   1221  friend class CanvasDrawObserver;
   1222  friend class ImageBitmap;
   1223 
   1224  void SetWriteOnly();
   1225 
   1226  bool IsWriteOnly() const { return mWriteOnly; }
   1227 
   1228  bool mWriteOnly;
   1229 
   1230  uint8_t mFillTextCalls = 0;
   1231  // Flags used by the fingerprinting detection heuristic
   1232  CanvasFeatureUsage mFeatureUsage = CanvasFeatureUsage::None;
   1233 
   1234  virtual void AddZoneWaitingForGC();
   1235  virtual void AddAssociatedMemory();
   1236  virtual void RemoveAssociatedMemory();
   1237 };
   1238 
   1239 size_t BindingJSObjectMallocBytes(CanvasRenderingContext2D* aContext);
   1240 
   1241 }  // namespace dom
   1242 }  // namespace mozilla
   1243 
   1244 #endif /* CanvasRenderingContext2D_h */