Bumping manifests a=b2g-bump
[gecko.git] / dom / canvas / CanvasRenderingContext2D.h
blobbb695d9d7106a801bf98f96b1cc35b10b8405a25
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 gl {
34 class SourceSurface;
35 class SurfaceStream;
38 namespace dom {
39 class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
40 class ImageData;
41 class StringOrCanvasGradientOrCanvasPattern;
42 class OwningStringOrCanvasGradientOrCanvasPattern;
43 class TextMetrics;
44 class SVGMatrix;
46 extern const mozilla::gfx::Float SIGMA_MAX;
48 template<typename T> class Optional;
50 class CanvasPath MOZ_FINAL :
51 public nsWrapperCache
53 public:
54 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPath)
55 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPath)
57 nsCOMPtr<nsISupports> GetParentObject() { return mParent; }
59 JSObject* WrapObject(JSContext* aCx);
61 static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
62 ErrorResult& rv);
63 static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
64 CanvasPath& aCanvasPath,
65 ErrorResult& rv);
66 static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
67 const nsAString& aPathString,
68 ErrorResult& rv);
70 void ClosePath();
71 void MoveTo(double x, double y);
72 void LineTo(double x, double y);
73 void QuadraticCurveTo(double cpx, double cpy, double x, double y);
74 void BezierCurveTo(double cp1x, double cp1y,
75 double cp2x, double cp2y,
76 double x, double y);
77 void ArcTo(double x1, double y1, double x2, double y2, double radius,
78 ErrorResult& error);
79 void Rect(double x, double y, double w, double h);
80 void Arc(double x, double y, double radius,
81 double startAngle, double endAngle, bool anticlockwise,
82 ErrorResult& error);
84 void LineTo(const gfx::Point& aPoint);
85 void BezierTo(const gfx::Point& aCP1,
86 const gfx::Point& aCP2,
87 const gfx::Point& aCP3);
89 TemporaryRef<gfx::Path> GetPath(const CanvasWindingRule& aWinding,
90 const gfx::DrawTarget* aTarget) const;
92 explicit CanvasPath(nsISupports* aParent);
93 // TemporaryRef arg because the return value from Path::CopyToBuilder() is
94 // passed directly and we can't drop the only ref to have a raw pointer.
95 CanvasPath(nsISupports* aParent,
96 TemporaryRef<gfx::PathBuilder> aPathBuilder);
98 void AddPath(CanvasPath& aCanvasPath,
99 const Optional<NonNull<SVGMatrix>>& aMatrix);
101 private:
102 virtual ~CanvasPath() {}
104 nsCOMPtr<nsISupports> mParent;
105 static gfx::Float ToFloat(double aValue) { return gfx::Float(aValue); }
107 mutable RefPtr<gfx::Path> mPath;
108 mutable RefPtr<gfx::PathBuilder> mPathBuilder;
110 void EnsurePathBuilder() const;
113 struct CanvasBidiProcessor;
114 class CanvasRenderingContext2DUserData;
117 ** CanvasRenderingContext2D
119 class CanvasRenderingContext2D MOZ_FINAL :
120 public nsICanvasRenderingContextInternal,
121 public nsWrapperCache
123 typedef HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
124 HTMLImageOrCanvasOrVideoElement;
126 virtual ~CanvasRenderingContext2D();
128 public:
129 CanvasRenderingContext2D();
131 virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
133 HTMLCanvasElement* GetCanvas() const
135 // corresponds to changes to the old bindings made in bug 745025
136 return mCanvasElement->GetOriginalCanvas();
139 void Save();
140 void Restore();
141 void Scale(double x, double y, mozilla::ErrorResult& error);
142 void Rotate(double angle, mozilla::ErrorResult& error);
143 void Translate(double x, double y, mozilla::ErrorResult& error);
144 void Transform(double m11, double m12, double m21, double m22, double dx,
145 double dy, mozilla::ErrorResult& error);
146 void SetTransform(double m11, double m12, double m21, double m22, double dx,
147 double dy, mozilla::ErrorResult& error);
149 double GlobalAlpha()
151 return CurrentState().globalAlpha;
154 // Useful for silencing cast warnings
155 static mozilla::gfx::Float ToFloat(double aValue) { return mozilla::gfx::Float(aValue); }
157 void SetGlobalAlpha(double globalAlpha)
159 if (globalAlpha >= 0.0 && globalAlpha <= 1.0) {
160 CurrentState().globalAlpha = ToFloat(globalAlpha);
164 void GetGlobalCompositeOperation(nsAString& op, mozilla::ErrorResult& error);
165 void SetGlobalCompositeOperation(const nsAString& op,
166 mozilla::ErrorResult& error);
168 void GetStrokeStyle(OwningStringOrCanvasGradientOrCanvasPattern& value)
170 GetStyleAsUnion(value, Style::STROKE);
173 void SetStrokeStyle(const StringOrCanvasGradientOrCanvasPattern& value)
175 SetStyleFromUnion(value, Style::STROKE);
178 void GetFillStyle(OwningStringOrCanvasGradientOrCanvasPattern& value)
180 GetStyleAsUnion(value, Style::FILL);
183 void SetFillStyle(const StringOrCanvasGradientOrCanvasPattern& value)
185 SetStyleFromUnion(value, Style::FILL);
188 already_AddRefed<CanvasGradient>
189 CreateLinearGradient(double x0, double y0, double x1, double y1);
190 already_AddRefed<CanvasGradient>
191 CreateRadialGradient(double x0, double y0, double r0, double x1, double y1,
192 double r1, ErrorResult& aError);
193 already_AddRefed<CanvasPattern>
194 CreatePattern(const HTMLImageOrCanvasOrVideoElement& element,
195 const nsAString& repeat, ErrorResult& error);
197 double ShadowOffsetX()
199 return CurrentState().shadowOffset.x;
202 void SetShadowOffsetX(double shadowOffsetX)
204 CurrentState().shadowOffset.x = ToFloat(shadowOffsetX);
207 double ShadowOffsetY()
209 return CurrentState().shadowOffset.y;
212 void SetShadowOffsetY(double shadowOffsetY)
214 CurrentState().shadowOffset.y = ToFloat(shadowOffsetY);
217 double ShadowBlur()
219 return CurrentState().shadowBlur;
222 void SetShadowBlur(double shadowBlur)
224 if (shadowBlur >= 0.0) {
225 CurrentState().shadowBlur = ToFloat(shadowBlur);
229 void GetShadowColor(nsAString& shadowColor)
231 StyleColorToString(CurrentState().shadowColor, shadowColor);
234 void SetShadowColor(const nsAString& shadowColor);
235 void ClearRect(double x, double y, double w, double h);
236 void FillRect(double x, double y, double w, double h);
237 void StrokeRect(double x, double y, double w, double h);
238 void BeginPath();
239 void Fill(const CanvasWindingRule& winding);
240 void Fill(const CanvasPath& path, const CanvasWindingRule& winding);
241 void Stroke();
242 void Stroke(const CanvasPath& path);
243 void DrawFocusIfNeeded(mozilla::dom::Element& element);
244 bool DrawCustomFocusRing(mozilla::dom::Element& element);
245 void Clip(const CanvasWindingRule& winding);
246 void Clip(const CanvasPath& path, const CanvasWindingRule& winding);
247 bool IsPointInPath(double x, double y, const CanvasWindingRule& winding);
248 bool IsPointInPath(const CanvasPath& path, double x, double y, const CanvasWindingRule& winding);
249 bool IsPointInStroke(double x, double y);
250 bool IsPointInStroke(const CanvasPath& path, double x, double y);
251 void FillText(const nsAString& text, double x, double y,
252 const Optional<double>& maxWidth,
253 mozilla::ErrorResult& error);
254 void StrokeText(const nsAString& text, double x, double y,
255 const Optional<double>& maxWidth,
256 mozilla::ErrorResult& error);
257 TextMetrics*
258 MeasureText(const nsAString& rawText, mozilla::ErrorResult& error);
260 void AddHitRegion(const HitRegionOptions& options, mozilla::ErrorResult& error);
261 void RemoveHitRegion(const nsAString& id);
263 void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
264 double dx, double dy, mozilla::ErrorResult& error)
266 DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, 0.0, 0.0, 0, error);
269 void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
270 double dx, double dy, double dw, double dh,
271 mozilla::ErrorResult& error)
273 DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, dw, dh, 2, error);
276 void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
277 double sx, double sy, double sw, double sh, double dx,
278 double dy, double dw, double dh, mozilla::ErrorResult& error)
280 DrawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, 6, error);
283 already_AddRefed<ImageData>
284 CreateImageData(JSContext* cx, double sw, double sh,
285 mozilla::ErrorResult& error);
286 already_AddRefed<ImageData>
287 CreateImageData(JSContext* cx, ImageData& imagedata,
288 mozilla::ErrorResult& error);
289 already_AddRefed<ImageData>
290 GetImageData(JSContext* cx, double sx, double sy, double sw, double sh,
291 mozilla::ErrorResult& error);
292 void PutImageData(ImageData& imageData,
293 double dx, double dy, mozilla::ErrorResult& error);
294 void PutImageData(ImageData& imageData,
295 double dx, double dy, double dirtyX, double dirtyY,
296 double dirtyWidth, double dirtyHeight,
297 mozilla::ErrorResult& error);
299 double LineWidth()
301 return CurrentState().lineWidth;
304 void SetLineWidth(double width)
306 if (width > 0.0) {
307 CurrentState().lineWidth = ToFloat(width);
310 void GetLineCap(nsAString& linecap);
311 void SetLineCap(const nsAString& linecap);
312 void GetLineJoin(nsAString& linejoin, mozilla::ErrorResult& error);
313 void SetLineJoin(const nsAString& linejoin);
315 double MiterLimit()
317 return CurrentState().miterLimit;
320 void SetMiterLimit(double miter)
322 if (miter > 0.0) {
323 CurrentState().miterLimit = ToFloat(miter);
327 void GetFont(nsAString& font)
329 font = GetFont();
332 void SetFont(const nsAString& font, mozilla::ErrorResult& error);
333 void GetTextAlign(nsAString& textAlign);
334 void SetTextAlign(const nsAString& textAlign);
335 void GetTextBaseline(nsAString& textBaseline);
336 void SetTextBaseline(const nsAString& textBaseline);
338 void ClosePath()
340 EnsureWritablePath();
342 if (mPathBuilder) {
343 mPathBuilder->Close();
344 } else {
345 mDSPathBuilder->Close();
349 void MoveTo(double x, double y)
351 EnsureWritablePath();
353 if (mPathBuilder) {
354 mPathBuilder->MoveTo(mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
355 } else {
356 mDSPathBuilder->MoveTo(mTarget->GetTransform() *
357 mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
361 void LineTo(double x, double y)
363 EnsureWritablePath();
365 LineTo(mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
368 void QuadraticCurveTo(double cpx, double cpy, double x, double y)
370 EnsureWritablePath();
372 if (mPathBuilder) {
373 mPathBuilder->QuadraticBezierTo(mozilla::gfx::Point(ToFloat(cpx), ToFloat(cpy)),
374 mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
375 } else {
376 mozilla::gfx::Matrix transform = mTarget->GetTransform();
377 mDSPathBuilder->QuadraticBezierTo(transform *
378 mozilla::gfx::Point(ToFloat(cpx), ToFloat(cpy)),
379 transform *
380 mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
384 void BezierCurveTo(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y)
386 EnsureWritablePath();
388 BezierTo(mozilla::gfx::Point(ToFloat(cp1x), ToFloat(cp1y)),
389 mozilla::gfx::Point(ToFloat(cp2x), ToFloat(cp2y)),
390 mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
393 void ArcTo(double x1, double y1, double x2, double y2, double radius,
394 mozilla::ErrorResult& error);
395 void Rect(double x, double y, double w, double h);
396 void Arc(double x, double y, double radius, double startAngle,
397 double endAngle, bool anticlockwise, mozilla::ErrorResult& error);
399 void GetMozCurrentTransform(JSContext* cx,
400 JS::MutableHandle<JSObject*> result,
401 mozilla::ErrorResult& error) const;
402 void SetMozCurrentTransform(JSContext* cx,
403 JS::Handle<JSObject*> currentTransform,
404 mozilla::ErrorResult& error);
405 void GetMozCurrentTransformInverse(JSContext* cx,
406 JS::MutableHandle<JSObject*> result,
407 mozilla::ErrorResult& error) const;
408 void SetMozCurrentTransformInverse(JSContext* cx,
409 JS::Handle<JSObject*> currentTransform,
410 mozilla::ErrorResult& error);
411 void GetFillRule(nsAString& fillRule);
412 void SetFillRule(const nsAString& fillRule);
413 void GetMozDash(JSContext* cx, JS::MutableHandle<JS::Value> retval,
414 mozilla::ErrorResult& error);
415 void SetMozDash(JSContext* cx, const JS::Value& mozDash,
416 mozilla::ErrorResult& error);
418 void SetLineDash(const Sequence<double>& mSegments);
419 void GetLineDash(nsTArray<double>& mSegments) const;
421 void SetLineDashOffset(double mOffset);
422 double LineDashOffset() const;
424 double MozDashOffset()
426 return CurrentState().dashOffset;
428 void SetMozDashOffset(double mozDashOffset);
430 void GetMozTextStyle(nsAString& mozTextStyle)
432 GetFont(mozTextStyle);
435 void SetMozTextStyle(const nsAString& mozTextStyle,
436 mozilla::ErrorResult& error)
438 SetFont(mozTextStyle, error);
441 bool ImageSmoothingEnabled()
443 return CurrentState().imageSmoothingEnabled;
446 void SetImageSmoothingEnabled(bool imageSmoothingEnabled)
448 if (imageSmoothingEnabled != CurrentState().imageSmoothingEnabled) {
449 CurrentState().imageSmoothingEnabled = imageSmoothingEnabled;
453 void DrawWindow(nsGlobalWindow& window, double x, double y, double w, double h,
454 const nsAString& bgColor, uint32_t flags,
455 mozilla::ErrorResult& error);
456 void AsyncDrawXULElement(nsXULElement& elem, double x, double y, double w,
457 double h, const nsAString& bgColor, uint32_t flags,
458 mozilla::ErrorResult& error);
460 void Demote();
462 nsresult Redraw();
464 #ifdef DEBUG
465 virtual int32_t GetWidth() const MOZ_OVERRIDE;
466 virtual int32_t GetHeight() const MOZ_OVERRIDE;
467 #endif
468 // nsICanvasRenderingContextInternal
469 NS_IMETHOD SetDimensions(int32_t width, int32_t height) MOZ_OVERRIDE;
470 NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, int32_t width, int32_t height) MOZ_OVERRIDE;
472 NS_IMETHOD GetInputStream(const char* aMimeType,
473 const char16_t* aEncoderOptions,
474 nsIInputStream **aStream) MOZ_OVERRIDE;
476 mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetSurfaceSnapshot(bool* aPremultAlpha = nullptr) MOZ_OVERRIDE
478 EnsureTarget();
479 if (aPremultAlpha) {
480 *aPremultAlpha = true;
482 return mTarget->Snapshot();
485 NS_IMETHOD SetIsOpaque(bool isOpaque) MOZ_OVERRIDE;
486 bool GetIsOpaque() MOZ_OVERRIDE { return mOpaque; }
487 NS_IMETHOD Reset() MOZ_OVERRIDE;
488 already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
489 CanvasLayer *aOldLayer,
490 LayerManager *aManager) MOZ_OVERRIDE;
491 virtual bool ShouldForceInactiveLayer(LayerManager *aManager) MOZ_OVERRIDE;
492 void MarkContextClean() MOZ_OVERRIDE;
493 NS_IMETHOD SetIsIPC(bool isIPC) MOZ_OVERRIDE;
494 // this rect is in canvas device space
495 void Redraw(const mozilla::gfx::Rect &r);
496 NS_IMETHOD Redraw(const gfxRect &r) MOZ_OVERRIDE { Redraw(ToRect(r)); return NS_OK; }
497 NS_IMETHOD SetContextOptions(JSContext* aCx, JS::Handle<JS::Value> aOptions) MOZ_OVERRIDE;
499 // this rect is in mTarget's current user space
500 void RedrawUser(const gfxRect &r);
502 // nsISupports interface + CC
503 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
505 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(CanvasRenderingContext2D)
507 MOZ_BEGIN_NESTED_ENUM_CLASS(CanvasMultiGetterType, uint8_t)
508 STRING = 0,
509 PATTERN = 1,
510 GRADIENT = 2
511 MOZ_END_NESTED_ENUM_CLASS(CanvasMultiGetterType)
513 MOZ_BEGIN_NESTED_ENUM_CLASS(Style, uint8_t)
514 STROKE = 0,
515 FILL,
517 MOZ_END_NESTED_ENUM_CLASS(Style)
519 nsINode* GetParentObject()
521 return mCanvasElement;
524 void LineTo(const mozilla::gfx::Point& aPoint)
526 if (mPathBuilder) {
527 mPathBuilder->LineTo(aPoint);
528 } else {
529 mDSPathBuilder->LineTo(mTarget->GetTransform() * aPoint);
533 void BezierTo(const mozilla::gfx::Point& aCP1,
534 const mozilla::gfx::Point& aCP2,
535 const mozilla::gfx::Point& aCP3)
537 if (mPathBuilder) {
538 mPathBuilder->BezierTo(aCP1, aCP2, aCP3);
539 } else {
540 mozilla::gfx::Matrix transform = mTarget->GetTransform();
541 mDSPathBuilder->BezierTo(transform * aCP1,
542 transform * aCP2,
543 transform * aCP3);
547 friend class CanvasRenderingContext2DUserData;
549 virtual void GetImageBuffer(uint8_t** aImageBuffer, int32_t* aFormat);
552 // Given a point, return hit region ID if it exists
553 nsString GetHitRegion(const mozilla::gfx::Point& aPoint);
556 // return true and fills in the bound rect if element has a hit region.
557 bool GetHitRegionRect(Element* aElement, nsRect& aRect);
559 protected:
560 nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
561 uint32_t aWidth, uint32_t aHeight,
562 JSObject** aRetval);
564 nsresult PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h,
565 dom::Uint8ClampedArray* aArray,
566 bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
567 int32_t dirtyWidth, int32_t dirtyHeight);
570 * Internal method to complete initialisation, expects mTarget to have been set
572 nsresult Initialize(int32_t width, int32_t height);
574 nsresult InitializeWithTarget(mozilla::gfx::DrawTarget *surface,
575 int32_t width, int32_t height);
578 * The number of living nsCanvasRenderingContexts. When this goes down to
579 * 0, we free the premultiply and unpremultiply tables, if they exist.
581 static uint32_t sNumLivingContexts;
584 * Lookup table used to speed up GetImageData().
586 static uint8_t (*sUnpremultiplyTable)[256];
589 * Lookup table used to speed up PutImageData().
591 static uint8_t (*sPremultiplyTable)[256];
593 static mozilla::gfx::DrawTarget* sErrorTarget;
595 // Some helpers. Doesn't modify a color on failure.
596 void SetStyleFromUnion(const StringOrCanvasGradientOrCanvasPattern& value,
597 Style whichStyle);
598 void SetStyleFromString(const nsAString& str, Style whichStyle);
600 void SetStyleFromGradient(CanvasGradient& gradient, Style whichStyle)
602 CurrentState().SetGradientStyle(whichStyle, &gradient);
605 void SetStyleFromPattern(CanvasPattern& pattern, Style whichStyle)
607 CurrentState().SetPatternStyle(whichStyle, &pattern);
610 void GetStyleAsUnion(OwningStringOrCanvasGradientOrCanvasPattern& aValue,
611 Style aWhichStyle);
613 // Returns whether a color was successfully parsed.
614 bool ParseColor(const nsAString& aString, nscolor* aColor);
616 static void StyleColorToString(const nscolor& aColor, nsAString& aStr);
619 * Creates the error target, if it doesn't exist
621 static void EnsureErrorTarget();
623 /* This function ensures there is a writable pathbuilder available, this
624 * pathbuilder may be working in user space or in device space or
625 * device space.
626 * After calling this function mPathTransformWillUpdate will be false
628 void EnsureWritablePath();
630 // Ensures a path in UserSpace is available.
631 void EnsureUserSpacePath(const CanvasWindingRule& winding = CanvasWindingRule::Nonzero);
634 * Needs to be called before updating the transform. This makes a call to
635 * EnsureTarget() so you don't have to.
637 void TransformWillUpdate();
639 // Report the fillRule has changed.
640 void FillRuleChanged();
643 * Create the backing surfacing, if it doesn't exist. If there is an error
644 * in creating the target then it will put sErrorTarget in place. If there
645 * is in turn an error in creating the sErrorTarget then they would both
646 * be null so IsTargetValid() would still return null.
648 void EnsureTarget();
651 * Disposes an old target and prepares to lazily create a new target.
653 void ClearTarget();
656 * Check if the target is valid after calling EnsureTarget.
658 bool IsTargetValid() { return mTarget != sErrorTarget && mTarget != nullptr; }
661 * Returns the surface format this canvas should be allocated using. Takes
662 * into account mOpaque, platform requirements, etc.
664 mozilla::gfx::SurfaceFormat GetSurfaceFormat() const;
666 nsLayoutUtils::SurfaceFromElementResult
667 CachedSurfaceFromElement(Element* aElement);
669 void DrawImage(const HTMLImageOrCanvasOrVideoElement &imgElt,
670 double sx, double sy, double sw, double sh,
671 double dx, double dy, double dw, double dh,
672 uint8_t optional_argc, mozilla::ErrorResult& error);
674 void DrawDirectlyToCanvas(const nsLayoutUtils::DirectDrawInfo& image,
675 mozilla::gfx::Rect* bounds,
676 mozilla::gfx::Rect dest,
677 mozilla::gfx::Rect src,
678 gfxIntSize imgSize);
680 nsString& GetFont()
682 /* will initilize the value if not set, else does nothing */
683 GetCurrentFontStyle();
685 return CurrentState().font;
688 static std::vector<CanvasRenderingContext2D*>& DemotableContexts();
689 static void DemoteOldestContextIfNecessary();
691 static void AddDemotableContext(CanvasRenderingContext2D* context);
692 static void RemoveDemotableContext(CanvasRenderingContext2D* context);
694 // Do not use GL
695 bool mForceSoftware;
697 // Member vars
698 int32_t mWidth, mHeight;
700 // This is true when the canvas is valid, but of zero size, this requires
701 // specific behavior on some operations.
702 bool mZero;
704 bool mOpaque;
706 // This is true when the next time our layer is retrieved we need to
707 // recreate it (i.e. our backing surface changed)
708 bool mResetLayer;
709 // This is needed for drawing in drawAsyncXULElement
710 bool mIPC;
712 nsTArray<CanvasRenderingContext2DUserData*> mUserDatas;
714 // If mCanvasElement is not provided, then a docshell is
715 nsCOMPtr<nsIDocShell> mDocShell;
717 // This is created lazily so it is necessary to call EnsureTarget before
718 // accessing it. In the event of an error it will be equal to
719 // sErrorTarget.
720 mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget;
722 RefPtr<gl::SurfaceStream> mStream;
725 * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
726 * Redraw is called, reset to false when Render is called.
728 bool mIsEntireFrameInvalid;
730 * When this is set, the first call to Redraw(gfxRect) should set
731 * mIsEntireFrameInvalid since we expect it will be followed by
732 * many more Redraw calls.
734 bool mPredictManyRedrawCalls;
736 // This is stored after GetThebesSurface has been called once to avoid
737 // excessive ThebesSurface initialization overhead.
738 nsRefPtr<gfxASurface> mThebesSurface;
741 * We also have a device space pathbuilder. The reason for this is as
742 * follows, when a path is being built, but the transform changes, we
743 * can no longer keep a single path in userspace, considering there's
744 * several 'user spaces' now. We therefore transform the current path
745 * into device space, and add all operations to this path in device
746 * space.
748 * When then finally executing a render, the Azure drawing API expects
749 * the path to be in userspace. We could then set an identity transform
750 * on the DrawTarget and do all drawing in device space. This is
751 * undesirable because it requires transforming patterns, gradients,
752 * clips, etc. into device space and it would not work for stroking.
753 * What we do instead is convert the path back to user space when it is
754 * drawn, and draw it with the current transform. This makes all drawing
755 * occur correctly.
757 * There's never both a device space path builder and a user space path
758 * builder present at the same time. There is also never a path and a
759 * path builder present at the same time. When writing proceeds on an
760 * existing path the Path is cleared and a new builder is created.
762 * mPath is always in user-space.
764 mozilla::RefPtr<mozilla::gfx::Path> mPath;
765 mozilla::RefPtr<mozilla::gfx::PathBuilder> mDSPathBuilder;
766 mozilla::RefPtr<mozilla::gfx::PathBuilder> mPathBuilder;
767 bool mPathTransformWillUpdate;
768 mozilla::gfx::Matrix mPathToDS;
771 * Number of times we've invalidated before calling redraw
773 uint32_t mInvalidateCount;
774 static const uint32_t kCanvasMaxInvalidateCount = 100;
777 * State information for hit regions
779 struct RegionInfo
781 nsString mId;
782 // fallback element for a11y
783 nsRefPtr<Element> mElement;
784 // Path of the hit region in the 2d context coordinate space (not user space)
785 RefPtr<gfx::Path> mPath;
788 nsTArray<RegionInfo> mHitRegionsOptions;
791 * Returns true if a shadow should be drawn along with a
792 * drawing operation.
794 bool NeedToDrawShadow()
796 const ContextState& state = CurrentState();
798 // The spec says we should not draw shadows if the operator is OVER.
799 // If it's over and the alpha value is zero, nothing needs to be drawn.
800 return NS_GET_A(state.shadowColor) != 0 &&
801 (state.shadowBlur != 0.f || state.shadowOffset.x != 0.f || state.shadowOffset.y != 0.f);
804 mozilla::gfx::CompositionOp UsedOperation()
806 if (NeedToDrawShadow()) {
807 // In this case the shadow rendering will use the operator.
808 return mozilla::gfx::CompositionOp::OP_OVER;
811 return CurrentState().op;
815 * Gets the pres shell from either the canvas element or the doc shell
817 nsIPresShell *GetPresShell() {
818 if (mCanvasElement) {
819 return mCanvasElement->OwnerDoc()->GetShell();
821 if (mDocShell) {
822 return mDocShell->GetPresShell();
824 return nullptr;
827 // text
829 public: // These enums are public only to accomodate non-C++11 legacy path of
830 // MOZ_FINISH_NESTED_ENUM_CLASS. Can move back to protected as soon
831 // as that legacy path is dropped.
832 MOZ_BEGIN_NESTED_ENUM_CLASS(TextAlign, uint8_t)
833 START,
834 END,
835 LEFT,
836 RIGHT,
837 CENTER
838 MOZ_END_NESTED_ENUM_CLASS(TextAlign)
840 MOZ_BEGIN_NESTED_ENUM_CLASS(TextBaseline, uint8_t)
841 TOP,
842 HANGING,
843 MIDDLE,
844 ALPHABETIC,
845 IDEOGRAPHIC,
846 BOTTOM
847 MOZ_END_NESTED_ENUM_CLASS(TextBaseline)
849 MOZ_BEGIN_NESTED_ENUM_CLASS(TextDrawOperation, uint8_t)
850 FILL,
851 STROKE,
852 MEASURE
853 MOZ_END_NESTED_ENUM_CLASS(TextDrawOperation)
855 protected:
856 gfxFontGroup *GetCurrentFontStyle();
859 * Implementation of the fillText, strokeText, and measure functions with
860 * the operation abstracted to a flag.
862 nsresult DrawOrMeasureText(const nsAString& text,
863 float x,
864 float y,
865 const Optional<double>& maxWidth,
866 TextDrawOperation op,
867 float* aWidth);
869 bool CheckSizeForSkiaGL(mozilla::gfx::IntSize size);
871 // state stack handling
872 class ContextState {
873 public:
874 ContextState() : textAlign(TextAlign::START),
875 textBaseline(TextBaseline::ALPHABETIC),
876 lineWidth(1.0f),
877 miterLimit(10.0f),
878 globalAlpha(1.0f),
879 shadowBlur(0.0),
880 dashOffset(0.0f),
881 op(mozilla::gfx::CompositionOp::OP_OVER),
882 fillRule(mozilla::gfx::FillRule::FILL_WINDING),
883 lineCap(mozilla::gfx::CapStyle::BUTT),
884 lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL),
885 imageSmoothingEnabled(true)
888 ContextState(const ContextState& other)
889 : fontGroup(other.fontGroup),
890 gradientStyles(other.gradientStyles),
891 patternStyles(other.patternStyles),
892 colorStyles(other.colorStyles),
893 font(other.font),
894 textAlign(other.textAlign),
895 textBaseline(other.textBaseline),
896 shadowColor(other.shadowColor),
897 transform(other.transform),
898 shadowOffset(other.shadowOffset),
899 lineWidth(other.lineWidth),
900 miterLimit(other.miterLimit),
901 globalAlpha(other.globalAlpha),
902 shadowBlur(other.shadowBlur),
903 dash(other.dash),
904 dashOffset(other.dashOffset),
905 op(other.op),
906 fillRule(other.fillRule),
907 lineCap(other.lineCap),
908 lineJoin(other.lineJoin),
909 imageSmoothingEnabled(other.imageSmoothingEnabled)
912 void SetColorStyle(Style whichStyle, nscolor color)
914 colorStyles[whichStyle] = color;
915 gradientStyles[whichStyle] = nullptr;
916 patternStyles[whichStyle] = nullptr;
919 void SetPatternStyle(Style whichStyle, CanvasPattern* pat)
921 gradientStyles[whichStyle] = nullptr;
922 patternStyles[whichStyle] = pat;
925 void SetGradientStyle(Style whichStyle, CanvasGradient* grad)
927 gradientStyles[whichStyle] = grad;
928 patternStyles[whichStyle] = nullptr;
932 * returns true iff the given style is a solid color.
934 bool StyleIsColor(Style whichStyle) const
936 return !(patternStyles[whichStyle] || gradientStyles[whichStyle]);
940 std::vector<mozilla::RefPtr<mozilla::gfx::Path> > clipsPushed;
942 nsRefPtr<gfxFontGroup> fontGroup;
943 EnumeratedArray<Style, Style::MAX, nsRefPtr<CanvasGradient>> gradientStyles;
944 EnumeratedArray<Style, Style::MAX, nsRefPtr<CanvasPattern>> patternStyles;
945 EnumeratedArray<Style, Style::MAX, nscolor> colorStyles;
947 nsString font;
948 TextAlign textAlign;
949 TextBaseline textBaseline;
951 nscolor shadowColor;
953 mozilla::gfx::Matrix transform;
954 mozilla::gfx::Point shadowOffset;
955 mozilla::gfx::Float lineWidth;
956 mozilla::gfx::Float miterLimit;
957 mozilla::gfx::Float globalAlpha;
958 mozilla::gfx::Float shadowBlur;
959 FallibleTArray<mozilla::gfx::Float> dash;
960 mozilla::gfx::Float dashOffset;
962 mozilla::gfx::CompositionOp op;
963 mozilla::gfx::FillRule fillRule;
964 mozilla::gfx::CapStyle lineCap;
965 mozilla::gfx::JoinStyle lineJoin;
967 bool imageSmoothingEnabled;
970 nsAutoTArray<ContextState, 3> mStyleStack;
972 inline ContextState& CurrentState() {
973 return mStyleStack[mStyleStack.Length() - 1];
976 inline const ContextState& CurrentState() const {
977 return mStyleStack[mStyleStack.Length() - 1];
980 friend class CanvasGeneralPattern;
981 friend class AdjustedTarget;
983 // other helpers
984 void GetAppUnitsValues(int32_t *perDevPixel, int32_t *perCSSPixel)
986 // If we don't have a canvas element, we just return something generic.
987 int32_t devPixel = 60;
988 int32_t cssPixel = 60;
990 nsIPresShell *ps = GetPresShell();
991 nsPresContext *pc;
993 if (!ps) goto FINISH;
994 pc = ps->GetPresContext();
995 if (!pc) goto FINISH;
996 devPixel = pc->AppUnitsPerDevPixel();
997 cssPixel = pc->AppUnitsPerCSSPixel();
999 FINISH:
1000 if (perDevPixel)
1001 *perDevPixel = devPixel;
1002 if (perCSSPixel)
1003 *perCSSPixel = cssPixel;
1006 friend struct CanvasBidiProcessor;
1009 MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::CanvasMultiGetterType)
1010 MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::Style)
1011 MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextAlign)
1012 MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextBaseline)
1013 MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextDrawOperation)
1018 #endif /* CanvasRenderingContext2D_h */