content/canvas/src/CanvasRenderingContext2D.h

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     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/. */
     5 #ifndef CanvasRenderingContext2D_h
     6 #define CanvasRenderingContext2D_h
     8 #include "mozilla/Attributes.h"
     9 #include <vector>
    10 #include "nsIDOMCanvasRenderingContext2D.h"
    11 #include "nsICanvasRenderingContextInternal.h"
    12 #include "mozilla/RefPtr.h"
    13 #include "nsColor.h"
    14 #include "mozilla/dom/HTMLCanvasElement.h"
    15 #include "mozilla/dom/HTMLVideoElement.h"
    16 #include "CanvasUtils.h"
    17 #include "gfxFont.h"
    18 #include "mozilla/ErrorResult.h"
    19 #include "mozilla/dom/CanvasGradient.h"
    20 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
    21 #include "mozilla/dom/CanvasPattern.h"
    22 #include "mozilla/gfx/Rect.h"
    23 #include "mozilla/gfx/2D.h"
    24 #include "gfx2DGlue.h"
    25 #include "imgIEncoder.h"
    26 #include "nsLayoutUtils.h"
    27 #include "mozilla/EnumeratedArray.h"
    29 class nsGlobalWindow;
    30 class nsXULElement;
    32 namespace mozilla {
    33 namespace gfx {
    34 class SourceSurface;
    35 class SurfaceStream;
    36 }
    38 namespace dom {
    39 class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
    40 class ImageData;
    41 class StringOrCanvasGradientOrCanvasPattern;
    42 class OwningStringOrCanvasGradientOrCanvasPattern;
    43 class TextMetrics;
    45 extern const mozilla::gfx::Float SIGMA_MAX;
    47 template<typename T> class Optional;
    49 class CanvasPath MOZ_FINAL :
    50   public nsWrapperCache
    51 {
    52 public:
    53   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPath)
    54   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPath)
    56   nsCOMPtr<nsISupports> GetParentObject() { return mParent; }
    58   JSObject* WrapObject(JSContext* aCx);
    60   static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
    61                                                   ErrorResult& rv);
    62   static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
    63                                                   CanvasPath& aCanvasPath,
    64                                                   ErrorResult& rv);
    65   static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
    66                                                   const nsAString& aPathString,
    67                                                   ErrorResult& rv);
    69   void ClosePath();
    70   void MoveTo(double x, double y);
    71   void LineTo(double x, double y);
    72   void QuadraticCurveTo(double cpx, double cpy, double x, double y);
    73   void BezierCurveTo(double cp1x, double cp1y,
    74                      double cp2x, double cp2y,
    75                      double x, double y);
    76   void ArcTo(double x1, double y1, double x2, double y2, double radius,
    77              ErrorResult& error);
    78   void Rect(double x, double y, double w, double h);
    79   void Arc(double x, double y, double radius,
    80            double startAngle, double endAngle, bool anticlockwise,
    81            ErrorResult& error);
    83   void LineTo(const gfx::Point& aPoint);
    84   void BezierTo(const gfx::Point& aCP1,
    85                 const gfx::Point& aCP2,
    86                 const gfx::Point& aCP3);
    88   mozilla::RefPtr<mozilla::gfx::Path> GetPath(const CanvasWindingRule& winding,
    89                                               const mozilla::RefPtr<mozilla::gfx::DrawTarget>& mTarget) const;
    91   explicit CanvasPath(nsISupports* aParent);
    92   CanvasPath(nsISupports* aParent, RefPtr<gfx::PathBuilder> mPathBuilder);
    93   virtual ~CanvasPath() {}
    95 private:
    97   nsCOMPtr<nsISupports> mParent;
    98   static gfx::Float ToFloat(double aValue) { return gfx::Float(aValue); }
   100   mutable RefPtr<gfx::Path> mPath;
   101   mutable RefPtr<gfx::PathBuilder> mPathBuilder;
   103   void EnsurePathBuilder() const;
   104 };
   106 struct CanvasBidiProcessor;
   107 class CanvasRenderingContext2DUserData;
   109 /**
   110  ** CanvasRenderingContext2D
   111  **/
   112 class CanvasRenderingContext2D :
   113   public nsICanvasRenderingContextInternal,
   114   public nsWrapperCache
   115 {
   116 typedef HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
   117   HTMLImageOrCanvasOrVideoElement;
   119 public:
   120   CanvasRenderingContext2D();
   121   virtual ~CanvasRenderingContext2D();
   123   virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
   125   HTMLCanvasElement* GetCanvas() const
   126   {
   127     // corresponds to changes to the old bindings made in bug 745025
   128     return mCanvasElement->GetOriginalCanvas();
   129   }
   131   void Save();
   132   void Restore();
   133   void Scale(double x, double y, mozilla::ErrorResult& error);
   134   void Rotate(double angle, mozilla::ErrorResult& error);
   135   void Translate(double x, double y, mozilla::ErrorResult& error);
   136   void Transform(double m11, double m12, double m21, double m22, double dx,
   137                  double dy, mozilla::ErrorResult& error);
   138   void SetTransform(double m11, double m12, double m21, double m22, double dx,
   139                     double dy, mozilla::ErrorResult& error);
   141   double GlobalAlpha()
   142   {
   143     return CurrentState().globalAlpha;
   144   }
   146   // Useful for silencing cast warnings
   147   static mozilla::gfx::Float ToFloat(double aValue) { return mozilla::gfx::Float(aValue); }
   149   void SetGlobalAlpha(double globalAlpha)
   150   {
   151     if (globalAlpha >= 0.0 && globalAlpha <= 1.0) {
   152       CurrentState().globalAlpha = ToFloat(globalAlpha);
   153     }
   154   }
   156   void GetGlobalCompositeOperation(nsAString& op, mozilla::ErrorResult& error);
   157   void SetGlobalCompositeOperation(const nsAString& op,
   158                                    mozilla::ErrorResult& error);
   160   void GetStrokeStyle(OwningStringOrCanvasGradientOrCanvasPattern& value)
   161   {
   162     GetStyleAsUnion(value, Style::STROKE);
   163   }
   165   void SetStrokeStyle(const StringOrCanvasGradientOrCanvasPattern& value)
   166   {
   167     SetStyleFromUnion(value, Style::STROKE);
   168   }
   170   void GetFillStyle(OwningStringOrCanvasGradientOrCanvasPattern& value)
   171   {
   172     GetStyleAsUnion(value, Style::FILL);
   173   }
   175   void SetFillStyle(const StringOrCanvasGradientOrCanvasPattern& value)
   176   {
   177     SetStyleFromUnion(value, Style::FILL);
   178   }
   180   already_AddRefed<CanvasGradient>
   181     CreateLinearGradient(double x0, double y0, double x1, double y1);
   182   already_AddRefed<CanvasGradient>
   183     CreateRadialGradient(double x0, double y0, double r0, double x1, double y1,
   184                          double r1, ErrorResult& aError);
   185   already_AddRefed<CanvasPattern>
   186     CreatePattern(const HTMLImageOrCanvasOrVideoElement& element,
   187                   const nsAString& repeat, ErrorResult& error);
   189   double ShadowOffsetX()
   190   {
   191     return CurrentState().shadowOffset.x;
   192   }
   194   void SetShadowOffsetX(double shadowOffsetX)
   195   {
   196     CurrentState().shadowOffset.x = ToFloat(shadowOffsetX);
   197   }
   199   double ShadowOffsetY()
   200   {
   201     return CurrentState().shadowOffset.y;
   202   }
   204   void SetShadowOffsetY(double shadowOffsetY)
   205   {
   206     CurrentState().shadowOffset.y = ToFloat(shadowOffsetY);
   207   }
   209   double ShadowBlur()
   210   {
   211     return CurrentState().shadowBlur;
   212   }
   214   void SetShadowBlur(double shadowBlur)
   215   {
   216     if (shadowBlur >= 0.0) {
   217       CurrentState().shadowBlur = ToFloat(shadowBlur);
   218     }
   219   }
   221   void GetShadowColor(nsAString& shadowColor)
   222   {
   223     StyleColorToString(CurrentState().shadowColor, shadowColor);
   224   }
   226   void SetShadowColor(const nsAString& shadowColor);
   227   void ClearRect(double x, double y, double w, double h);
   228   void FillRect(double x, double y, double w, double h);
   229   void StrokeRect(double x, double y, double w, double h);
   230   void BeginPath();
   231   void Fill(const CanvasWindingRule& winding);
   232   void Fill(const CanvasPath& path, const CanvasWindingRule& winding);
   233   void Stroke();
   234   void Stroke(const CanvasPath& path);
   235   void DrawFocusIfNeeded(mozilla::dom::Element& element);
   236   bool DrawCustomFocusRing(mozilla::dom::Element& element);
   237   void Clip(const CanvasWindingRule& winding);
   238   void Clip(const CanvasPath& path, const CanvasWindingRule& winding);
   239   bool IsPointInPath(JSContext* cx, double x, double y,
   240                      const CanvasWindingRule& winding);
   241   bool IsPointInPath(JSContext* cx, const CanvasPath& path, double x, double y,
   242                      const CanvasWindingRule& winding);
   243   bool IsPointInStroke(JSContext* cx, double x, double y);
   244   bool IsPointInStroke(JSContext* cx, const CanvasPath& path,
   245                        double x, double y);
   246   void FillText(const nsAString& text, double x, double y,
   247                 const Optional<double>& maxWidth,
   248                 mozilla::ErrorResult& error);
   249   void StrokeText(const nsAString& text, double x, double y,
   250                   const Optional<double>& maxWidth,
   251                   mozilla::ErrorResult& error);
   252   TextMetrics*
   253     MeasureText(const nsAString& rawText, mozilla::ErrorResult& error);
   255   void AddHitRegion(const HitRegionOptions& options, mozilla::ErrorResult& error);
   256   void RemoveHitRegion(const nsAString& id);
   258   void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
   259                  double dx, double dy, mozilla::ErrorResult& error)
   260   {
   261     DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, 0.0, 0.0, 0, error);
   262   }
   264   void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
   265                  double dx, double dy, double dw, double dh,
   266                  mozilla::ErrorResult& error)
   267   {
   268     DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, dw, dh, 2, error);
   269   }
   271   void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
   272                  double sx, double sy, double sw, double sh, double dx,
   273                  double dy, double dw, double dh, mozilla::ErrorResult& error)
   274   {
   275     DrawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, 6, error);
   276   }
   278   already_AddRefed<ImageData>
   279     CreateImageData(JSContext* cx, double sw, double sh,
   280                     mozilla::ErrorResult& error);
   281   already_AddRefed<ImageData>
   282     CreateImageData(JSContext* cx, ImageData& imagedata,
   283                     mozilla::ErrorResult& error);
   284   already_AddRefed<ImageData>
   285     GetImageData(JSContext* cx, double sx, double sy, double sw, double sh,
   286                  mozilla::ErrorResult& error);
   287   void PutImageData(ImageData& imageData,
   288                     double dx, double dy, mozilla::ErrorResult& error);
   289   void PutImageData(ImageData& imageData,
   290                     double dx, double dy, double dirtyX, double dirtyY,
   291                     double dirtyWidth, double dirtyHeight,
   292                     mozilla::ErrorResult& error);
   294   double LineWidth()
   295   {
   296     return CurrentState().lineWidth;
   297   }
   299   void SetLineWidth(double width)
   300   {
   301     if (width > 0.0) {
   302       CurrentState().lineWidth = ToFloat(width);
   303     }
   304   }
   305   void GetLineCap(nsAString& linecap);
   306   void SetLineCap(const nsAString& linecap);
   307   void GetLineJoin(nsAString& linejoin, mozilla::ErrorResult& error);
   308   void SetLineJoin(const nsAString& linejoin);
   310   double MiterLimit()
   311   {
   312     return CurrentState().miterLimit;
   313   }
   315   void SetMiterLimit(double miter)
   316   {
   317     if (miter > 0.0) {
   318       CurrentState().miterLimit = ToFloat(miter);
   319     }
   320   }
   322   void GetFont(nsAString& font)
   323   {
   324     font = GetFont();
   325   }
   327   void SetFont(const nsAString& font, mozilla::ErrorResult& error);
   328   void GetTextAlign(nsAString& textAlign);
   329   void SetTextAlign(const nsAString& textAlign);
   330   void GetTextBaseline(nsAString& textBaseline);
   331   void SetTextBaseline(const nsAString& textBaseline);
   333   void ClosePath()
   334   {
   335     EnsureWritablePath();
   337     if (mPathBuilder) {
   338       mPathBuilder->Close();
   339     } else {
   340       mDSPathBuilder->Close();
   341     }
   342   }
   344   void MoveTo(double x, double y)
   345   {
   346     EnsureWritablePath();
   348     if (mPathBuilder) {
   349       mPathBuilder->MoveTo(mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
   350     } else {
   351       mDSPathBuilder->MoveTo(mTarget->GetTransform() *
   352                              mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
   353     }
   354   }
   356   void LineTo(double x, double y)
   357   {
   358     EnsureWritablePath();
   360     LineTo(mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
   361   }
   363   void QuadraticCurveTo(double cpx, double cpy, double x, double y)
   364   {
   365     EnsureWritablePath();
   367     if (mPathBuilder) {
   368       mPathBuilder->QuadraticBezierTo(mozilla::gfx::Point(ToFloat(cpx), ToFloat(cpy)),
   369                                       mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
   370     } else {
   371       mozilla::gfx::Matrix transform = mTarget->GetTransform();
   372       mDSPathBuilder->QuadraticBezierTo(transform *
   373                                         mozilla::gfx::Point(ToFloat(cpx), ToFloat(cpy)),
   374                                         transform *
   375                                         mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
   376     }
   377   }
   379   void BezierCurveTo(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y)
   380   {
   381     EnsureWritablePath();
   383     BezierTo(mozilla::gfx::Point(ToFloat(cp1x), ToFloat(cp1y)),
   384              mozilla::gfx::Point(ToFloat(cp2x), ToFloat(cp2y)),
   385              mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
   386   }
   388   void ArcTo(double x1, double y1, double x2, double y2, double radius,
   389              mozilla::ErrorResult& error);
   390   void Rect(double x, double y, double w, double h);
   391   void Arc(double x, double y, double radius, double startAngle,
   392            double endAngle, bool anticlockwise, mozilla::ErrorResult& error);
   394   void GetMozCurrentTransform(JSContext* cx,
   395 			      JS::MutableHandle<JSObject*> result,
   396 			      mozilla::ErrorResult& error) const;
   397   void SetMozCurrentTransform(JSContext* cx,
   398                               JS::Handle<JSObject*> currentTransform,
   399                               mozilla::ErrorResult& error);
   400   void GetMozCurrentTransformInverse(JSContext* cx,
   401 				     JS::MutableHandle<JSObject*> result,
   402 				     mozilla::ErrorResult& error) const;
   403   void SetMozCurrentTransformInverse(JSContext* cx,
   404                                      JS::Handle<JSObject*> currentTransform,
   405                                      mozilla::ErrorResult& error);
   406   void GetFillRule(nsAString& fillRule);
   407   void SetFillRule(const nsAString& fillRule);
   408   void GetMozDash(JSContext* cx, JS::MutableHandle<JS::Value> retval,
   409 		  mozilla::ErrorResult& error);
   410   void SetMozDash(JSContext* cx, const JS::Value& mozDash,
   411                   mozilla::ErrorResult& error);
   413   void SetLineDash(const Sequence<double>& mSegments);
   414   void GetLineDash(nsTArray<double>& mSegments) const;
   416   void SetLineDashOffset(double mOffset);
   417   double LineDashOffset() const;
   419   double MozDashOffset()
   420   {
   421     return CurrentState().dashOffset;
   422   }
   423   void SetMozDashOffset(double mozDashOffset);
   425   void GetMozTextStyle(nsAString& mozTextStyle)
   426   {
   427     GetFont(mozTextStyle);
   428   }
   430   void SetMozTextStyle(const nsAString& mozTextStyle,
   431                        mozilla::ErrorResult& error)
   432   {
   433     SetFont(mozTextStyle, error);
   434   }
   436   bool ImageSmoothingEnabled()
   437   {
   438     return CurrentState().imageSmoothingEnabled;
   439   }
   441   void SetImageSmoothingEnabled(bool imageSmoothingEnabled)
   442   {
   443     if (imageSmoothingEnabled != CurrentState().imageSmoothingEnabled) {
   444       CurrentState().imageSmoothingEnabled = imageSmoothingEnabled;
   445     }
   446   }
   448   void DrawWindow(nsGlobalWindow& window, double x, double y, double w, double h,
   449                   const nsAString& bgColor, uint32_t flags,
   450                   mozilla::ErrorResult& error);
   451   void AsyncDrawXULElement(nsXULElement& elem, double x, double y, double w,
   452                            double h, const nsAString& bgColor, uint32_t flags,
   453                            mozilla::ErrorResult& error);
   455   void Demote();
   457   nsresult Redraw();
   459 #ifdef DEBUG
   460     virtual int32_t GetWidth() const MOZ_OVERRIDE;
   461     virtual int32_t GetHeight() const MOZ_OVERRIDE;
   462 #endif
   463   // nsICanvasRenderingContextInternal
   464   NS_IMETHOD SetDimensions(int32_t width, int32_t height) MOZ_OVERRIDE;
   465   NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, int32_t width, int32_t height) MOZ_OVERRIDE;
   467   NS_IMETHOD GetInputStream(const char* aMimeType,
   468                             const char16_t* aEncoderOptions,
   469                             nsIInputStream **aStream) MOZ_OVERRIDE;
   471   mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetSurfaceSnapshot(bool* aPremultAlpha = nullptr) MOZ_OVERRIDE
   472   {
   473     EnsureTarget();
   474     if (aPremultAlpha) {
   475       *aPremultAlpha = true;
   476     }
   477     return mTarget->Snapshot();
   478   }
   480   NS_IMETHOD SetIsOpaque(bool isOpaque) MOZ_OVERRIDE;
   481   bool GetIsOpaque() MOZ_OVERRIDE { return mOpaque; }
   482   NS_IMETHOD Reset() MOZ_OVERRIDE;
   483   already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
   484                                                CanvasLayer *aOldLayer,
   485                                                LayerManager *aManager) MOZ_OVERRIDE;
   486   virtual bool ShouldForceInactiveLayer(LayerManager *aManager) MOZ_OVERRIDE;
   487   void MarkContextClean() MOZ_OVERRIDE;
   488   NS_IMETHOD SetIsIPC(bool isIPC) MOZ_OVERRIDE;
   489   // this rect is in canvas device space
   490   void Redraw(const mozilla::gfx::Rect &r);
   491   NS_IMETHOD Redraw(const gfxRect &r) MOZ_OVERRIDE { Redraw(ToRect(r)); return NS_OK; }
   492   NS_IMETHOD SetContextOptions(JSContext* aCx, JS::Handle<JS::Value> aOptions) MOZ_OVERRIDE;
   494   // this rect is in mTarget's current user space
   495   void RedrawUser(const gfxRect &r);
   497   // nsISupports interface + CC
   498   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   500   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(CanvasRenderingContext2D)
   502   MOZ_BEGIN_NESTED_ENUM_CLASS(CanvasMultiGetterType, uint8_t)
   503     STRING = 0,
   504     PATTERN = 1,
   505     GRADIENT = 2
   506   MOZ_END_NESTED_ENUM_CLASS(CanvasMultiGetterType)
   508   MOZ_BEGIN_NESTED_ENUM_CLASS(Style, uint8_t)
   509     STROKE = 0,
   510     FILL,
   511     MAX
   512   MOZ_END_NESTED_ENUM_CLASS(Style)
   514   nsINode* GetParentObject()
   515   {
   516     return mCanvasElement;
   517   }
   519   void LineTo(const mozilla::gfx::Point& aPoint)
   520   {
   521     if (mPathBuilder) {
   522       mPathBuilder->LineTo(aPoint);
   523     } else {
   524       mDSPathBuilder->LineTo(mTarget->GetTransform() * aPoint);
   525     }
   526   }
   528   void BezierTo(const mozilla::gfx::Point& aCP1,
   529                 const mozilla::gfx::Point& aCP2,
   530                 const mozilla::gfx::Point& aCP3)
   531   {
   532     if (mPathBuilder) {
   533       mPathBuilder->BezierTo(aCP1, aCP2, aCP3);
   534     } else {
   535       mozilla::gfx::Matrix transform = mTarget->GetTransform();
   536       mDSPathBuilder->BezierTo(transform * aCP1,
   537                                 transform * aCP2,
   538                                 transform * aCP3);
   539     }
   540   }
   542   friend class CanvasRenderingContext2DUserData;
   544   virtual void GetImageBuffer(uint8_t** aImageBuffer, int32_t* aFormat);
   546 protected:
   547   nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
   548                              uint32_t aWidth, uint32_t aHeight,
   549                              JSObject** aRetval);
   551   nsresult PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h,
   552                                  dom::Uint8ClampedArray* aArray,
   553                                  bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
   554                                  int32_t dirtyWidth, int32_t dirtyHeight);
   556   /**
   557    * Internal method to complete initialisation, expects mTarget to have been set
   558    */
   559   nsresult Initialize(int32_t width, int32_t height);
   561   nsresult InitializeWithTarget(mozilla::gfx::DrawTarget *surface,
   562                                 int32_t width, int32_t height);
   564   /**
   565     * The number of living nsCanvasRenderingContexts.  When this goes down to
   566     * 0, we free the premultiply and unpremultiply tables, if they exist.
   567     */
   568   static uint32_t sNumLivingContexts;
   570   /**
   571     * Lookup table used to speed up GetImageData().
   572     */
   573   static uint8_t (*sUnpremultiplyTable)[256];
   575   /**
   576     * Lookup table used to speed up PutImageData().
   577     */
   578   static uint8_t (*sPremultiplyTable)[256];
   580   static mozilla::gfx::DrawTarget* sErrorTarget;
   582   // Some helpers.  Doesn't modify a color on failure.
   583   void SetStyleFromUnion(const StringOrCanvasGradientOrCanvasPattern& value,
   584                          Style whichStyle);
   585   void SetStyleFromString(const nsAString& str, Style whichStyle);
   587   void SetStyleFromGradient(CanvasGradient& gradient, Style whichStyle)
   588   {
   589     CurrentState().SetGradientStyle(whichStyle, &gradient);
   590   }
   592   void SetStyleFromPattern(CanvasPattern& pattern, Style whichStyle)
   593   {
   594     CurrentState().SetPatternStyle(whichStyle, &pattern);
   595   }
   597   void GetStyleAsUnion(OwningStringOrCanvasGradientOrCanvasPattern& aValue,
   598                        Style aWhichStyle);
   600   // Returns whether a color was successfully parsed.
   601   bool ParseColor(const nsAString& aString, nscolor* aColor);
   603   static void StyleColorToString(const nscolor& aColor, nsAString& aStr);
   605   /**
   606    * Creates the error target, if it doesn't exist
   607    */
   608   static void EnsureErrorTarget();
   610   /* This function ensures there is a writable pathbuilder available, this
   611    * pathbuilder may be working in user space or in device space or
   612    * device space.
   613    * After calling this function mPathTransformWillUpdate will be false
   614    */
   615   void EnsureWritablePath();
   617   // Ensures a path in UserSpace is available.
   618   void EnsureUserSpacePath(const CanvasWindingRule& winding = CanvasWindingRule::Nonzero);
   620   /**
   621    * Needs to be called before updating the transform. This makes a call to
   622    * EnsureTarget() so you don't have to.
   623    */
   624   void TransformWillUpdate();
   626   // Report the fillRule has changed.
   627   void FillRuleChanged();
   629    /**
   630    * Create the backing surfacing, if it doesn't exist. If there is an error
   631    * in creating the target then it will put sErrorTarget in place. If there
   632    * is in turn an error in creating the sErrorTarget then they would both
   633    * be null so IsTargetValid() would still return null.
   634    */
   635   void EnsureTarget();
   637   /*
   638    * Disposes an old target and prepares to lazily create a new target.
   639    */
   640   void ClearTarget();
   642   /**
   643    * Check if the target is valid after calling EnsureTarget.
   644    */
   645   bool IsTargetValid() { return mTarget != sErrorTarget && mTarget != nullptr; }
   647   /**
   648     * Returns the surface format this canvas should be allocated using. Takes
   649     * into account mOpaque, platform requirements, etc.
   650     */
   651   mozilla::gfx::SurfaceFormat GetSurfaceFormat() const;
   653   void DrawImage(const HTMLImageOrCanvasOrVideoElement &imgElt,
   654                  double sx, double sy, double sw, double sh,
   655                  double dx, double dy, double dw, double dh, 
   656                  uint8_t optional_argc, mozilla::ErrorResult& error);
   658   void DrawDirectlyToCanvas(const nsLayoutUtils::DirectDrawInfo& image,
   659                             mozilla::gfx::Rect* bounds, double dx, double dy,
   660                             double dw, double dh, double sx, double sy,
   661                             double sw, double sh, gfxIntSize imgSize);
   663   nsString& GetFont()
   664   {
   665     /* will initilize the value if not set, else does nothing */
   666     GetCurrentFontStyle();
   668     return CurrentState().font;
   669   }
   671   static std::vector<CanvasRenderingContext2D*>& DemotableContexts();
   672   static void DemoteOldestContextIfNecessary();
   674   static void AddDemotableContext(CanvasRenderingContext2D* context);
   675   static void RemoveDemotableContext(CanvasRenderingContext2D* context);
   677   // Do not use GL
   678   bool mForceSoftware;
   680   // Member vars
   681   int32_t mWidth, mHeight;
   683   // This is true when the canvas is valid, but of zero size, this requires
   684   // specific behavior on some operations.
   685   bool mZero;
   687   bool mOpaque;
   689   // This is true when the next time our layer is retrieved we need to
   690   // recreate it (i.e. our backing surface changed)
   691   bool mResetLayer;
   692   // This is needed for drawing in drawAsyncXULElement
   693   bool mIPC;
   695   nsTArray<CanvasRenderingContext2DUserData*> mUserDatas;
   697   // If mCanvasElement is not provided, then a docshell is
   698   nsCOMPtr<nsIDocShell> mDocShell;
   700   // This is created lazily so it is necessary to call EnsureTarget before
   701   // accessing it. In the event of an error it will be equal to
   702   // sErrorTarget.
   703   mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget;
   705   RefPtr<gfx::SurfaceStream> mStream;
   707   /**
   708     * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
   709     * Redraw is called, reset to false when Render is called.
   710     */
   711   bool mIsEntireFrameInvalid;
   712   /**
   713     * When this is set, the first call to Redraw(gfxRect) should set
   714     * mIsEntireFrameInvalid since we expect it will be followed by
   715     * many more Redraw calls.
   716     */
   717   bool mPredictManyRedrawCalls;
   719   // This is stored after GetThebesSurface has been called once to avoid
   720   // excessive ThebesSurface initialization overhead.
   721   nsRefPtr<gfxASurface> mThebesSurface;
   723   /**
   724     * We also have a device space pathbuilder. The reason for this is as
   725     * follows, when a path is being built, but the transform changes, we
   726     * can no longer keep a single path in userspace, considering there's
   727     * several 'user spaces' now. We therefore transform the current path
   728     * into device space, and add all operations to this path in device
   729     * space.
   730     *
   731     * When then finally executing a render, the Azure drawing API expects
   732     * the path to be in userspace. We could then set an identity transform
   733     * on the DrawTarget and do all drawing in device space. This is
   734     * undesirable because it requires transforming patterns, gradients,
   735     * clips, etc. into device space and it would not work for stroking.
   736     * What we do instead is convert the path back to user space when it is
   737     * drawn, and draw it with the current transform. This makes all drawing
   738     * occur correctly.
   739     *
   740     * There's never both a device space path builder and a user space path
   741     * builder present at the same time. There is also never a path and a
   742     * path builder present at the same time. When writing proceeds on an
   743     * existing path the Path is cleared and a new builder is created.
   744     *
   745     * mPath is always in user-space.
   746     */
   747   mozilla::RefPtr<mozilla::gfx::Path> mPath;
   748   mozilla::RefPtr<mozilla::gfx::PathBuilder> mDSPathBuilder;
   749   mozilla::RefPtr<mozilla::gfx::PathBuilder> mPathBuilder;
   750   bool mPathTransformWillUpdate;
   751   mozilla::gfx::Matrix mPathToDS;
   753   /**
   754     * Number of times we've invalidated before calling redraw
   755     */
   756   uint32_t mInvalidateCount;
   757   static const uint32_t kCanvasMaxInvalidateCount = 100;
   759   /**
   760     * State information for hit regions
   761     */
   763   struct RegionInfo : public nsStringHashKey
   764   {
   765     RegionInfo(const nsAString& aKey) :
   766       nsStringHashKey(&aKey)
   767     {
   768     }
   769     RegionInfo(const nsAString *aKey) :
   770       nsStringHashKey(aKey)
   771     {
   772     }
   774     nsRefPtr<Element> mElement;
   775   };
   777 #ifdef ACCESSIBILITY
   778   static PLDHashOperator RemoveHitRegionProperty(RegionInfo* aEntry, void* aData);
   779 #endif
   780   nsTHashtable<RegionInfo> mHitRegionsOptions;
   782   /**
   783     * Returns true if a shadow should be drawn along with a
   784     * drawing operation.
   785     */
   786   bool NeedToDrawShadow()
   787   {
   788     const ContextState& state = CurrentState();
   790     // The spec says we should not draw shadows if the operator is OVER.
   791     // If it's over and the alpha value is zero, nothing needs to be drawn.
   792     return NS_GET_A(state.shadowColor) != 0 && 
   793       (state.shadowBlur != 0 || state.shadowOffset.x != 0 || state.shadowOffset.y != 0);
   794   }
   796   mozilla::gfx::CompositionOp UsedOperation()
   797   {
   798     if (NeedToDrawShadow()) {
   799       // In this case the shadow rendering will use the operator.
   800       return mozilla::gfx::CompositionOp::OP_OVER;
   801     }
   803     return CurrentState().op;
   804   }
   806   /**
   807     * Gets the pres shell from either the canvas element or the doc shell
   808     */
   809   nsIPresShell *GetPresShell() {
   810     if (mCanvasElement) {
   811       return mCanvasElement->OwnerDoc()->GetShell();
   812     }
   813     if (mDocShell) {
   814       return mDocShell->GetPresShell();
   815     }
   816     return nullptr;
   817   }
   819   // text
   821 public: // These enums are public only to accomodate non-C++11 legacy path of
   822         // MOZ_FINISH_NESTED_ENUM_CLASS. Can move back to protected as soon
   823         // as that legacy path is dropped.
   824   MOZ_BEGIN_NESTED_ENUM_CLASS(TextAlign, uint8_t)
   825     START,
   826     END,
   827     LEFT,
   828     RIGHT,
   829     CENTER
   830   MOZ_END_NESTED_ENUM_CLASS(TextAlign)
   832   MOZ_BEGIN_NESTED_ENUM_CLASS(TextBaseline, uint8_t)
   833     TOP,
   834     HANGING,
   835     MIDDLE,
   836     ALPHABETIC,
   837     IDEOGRAPHIC,
   838     BOTTOM
   839   MOZ_END_NESTED_ENUM_CLASS(TextBaseline)
   841   MOZ_BEGIN_NESTED_ENUM_CLASS(TextDrawOperation, uint8_t)
   842     FILL,
   843     STROKE,
   844     MEASURE
   845   MOZ_END_NESTED_ENUM_CLASS(TextDrawOperation)
   847 protected:
   848   gfxFontGroup *GetCurrentFontStyle();
   850   /*
   851     * Implementation of the fillText, strokeText, and measure functions with
   852     * the operation abstracted to a flag.
   853     */
   854   nsresult DrawOrMeasureText(const nsAString& text,
   855                              float x,
   856                              float y,
   857                              const Optional<double>& maxWidth,
   858                              TextDrawOperation op,
   859                              float* aWidth);
   861   // state stack handling
   862   class ContextState {
   863   public:
   864     ContextState() : textAlign(TextAlign::START),
   865                      textBaseline(TextBaseline::ALPHABETIC),
   866                      lineWidth(1.0f),
   867                      miterLimit(10.0f),
   868                      globalAlpha(1.0f),
   869                      shadowBlur(0.0),
   870                      dashOffset(0.0f),
   871                      op(mozilla::gfx::CompositionOp::OP_OVER),
   872                      fillRule(mozilla::gfx::FillRule::FILL_WINDING),
   873                      lineCap(mozilla::gfx::CapStyle::BUTT),
   874                      lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL),
   875                      imageSmoothingEnabled(true)
   876     { }
   878     ContextState(const ContextState& other)
   879         : fontGroup(other.fontGroup),
   880           gradientStyles(other.gradientStyles),
   881           patternStyles(other.patternStyles),
   882           colorStyles(other.colorStyles),
   883           font(other.font),
   884           textAlign(other.textAlign),
   885           textBaseline(other.textBaseline),
   886           shadowColor(other.shadowColor),
   887           transform(other.transform),
   888           shadowOffset(other.shadowOffset),
   889           lineWidth(other.lineWidth),
   890           miterLimit(other.miterLimit),
   891           globalAlpha(other.globalAlpha),
   892           shadowBlur(other.shadowBlur),
   893           dash(other.dash),
   894           dashOffset(other.dashOffset),
   895           op(other.op),
   896           fillRule(other.fillRule),
   897           lineCap(other.lineCap),
   898           lineJoin(other.lineJoin),
   899           imageSmoothingEnabled(other.imageSmoothingEnabled)
   900     { }
   902     void SetColorStyle(Style whichStyle, nscolor color)
   903     {
   904       colorStyles[whichStyle] = color;
   905       gradientStyles[whichStyle] = nullptr;
   906       patternStyles[whichStyle] = nullptr;
   907     }
   909     void SetPatternStyle(Style whichStyle, CanvasPattern* pat)
   910     {
   911       gradientStyles[whichStyle] = nullptr;
   912       patternStyles[whichStyle] = pat;
   913     }
   915     void SetGradientStyle(Style whichStyle, CanvasGradient* grad)
   916     {
   917       gradientStyles[whichStyle] = grad;
   918       patternStyles[whichStyle] = nullptr;
   919     }
   921     /**
   922       * returns true iff the given style is a solid color.
   923       */
   924     bool StyleIsColor(Style whichStyle) const
   925     {
   926       return !(patternStyles[whichStyle] || gradientStyles[whichStyle]);
   927     }
   930     std::vector<mozilla::RefPtr<mozilla::gfx::Path> > clipsPushed;
   932     nsRefPtr<gfxFontGroup> fontGroup;
   933     EnumeratedArray<Style, Style::MAX, nsRefPtr<CanvasGradient>> gradientStyles;
   934     EnumeratedArray<Style, Style::MAX, nsRefPtr<CanvasPattern>> patternStyles;
   935     EnumeratedArray<Style, Style::MAX, nscolor> colorStyles;
   937     nsString font;
   938     TextAlign textAlign;
   939     TextBaseline textBaseline;
   941     nscolor shadowColor;
   943     mozilla::gfx::Matrix transform;
   944     mozilla::gfx::Point shadowOffset;
   945     mozilla::gfx::Float lineWidth;
   946     mozilla::gfx::Float miterLimit;
   947     mozilla::gfx::Float globalAlpha;
   948     mozilla::gfx::Float shadowBlur;
   949     FallibleTArray<mozilla::gfx::Float> dash;
   950     mozilla::gfx::Float dashOffset;
   952     mozilla::gfx::CompositionOp op;
   953     mozilla::gfx::FillRule fillRule;
   954     mozilla::gfx::CapStyle lineCap;
   955     mozilla::gfx::JoinStyle lineJoin;
   957     bool imageSmoothingEnabled;
   958   };
   960   nsAutoTArray<ContextState, 3> mStyleStack;
   962   inline ContextState& CurrentState() {
   963     return mStyleStack[mStyleStack.Length() - 1];
   964   }
   966   inline const ContextState& CurrentState() const {
   967     return mStyleStack[mStyleStack.Length() - 1];
   968   }
   970   friend class CanvasGeneralPattern;
   971   friend class AdjustedTarget;
   973   // other helpers
   974   void GetAppUnitsValues(int32_t *perDevPixel, int32_t *perCSSPixel)
   975   {
   976     // If we don't have a canvas element, we just return something generic.
   977     int32_t devPixel = 60;
   978     int32_t cssPixel = 60;
   980     nsIPresShell *ps = GetPresShell();
   981     nsPresContext *pc;
   983     if (!ps) goto FINISH;
   984     pc = ps->GetPresContext();
   985     if (!pc) goto FINISH;
   986     devPixel = pc->AppUnitsPerDevPixel();
   987     cssPixel = pc->AppUnitsPerCSSPixel();
   989   FINISH:
   990     if (perDevPixel)
   991       *perDevPixel = devPixel;
   992     if (perCSSPixel)
   993       *perCSSPixel = cssPixel;
   994   }
   996   friend struct CanvasBidiProcessor;
   997 };
   999 MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::CanvasMultiGetterType)
  1000 MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::Style)
  1001 MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextAlign)
  1002 MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextBaseline)
  1003 MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextDrawOperation)
  1008 #endif /* CanvasRenderingContext2D_h */

mercurial