1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/canvas/src/CanvasRenderingContext2D.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1008 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#ifndef CanvasRenderingContext2D_h 1.9 +#define CanvasRenderingContext2D_h 1.10 + 1.11 +#include "mozilla/Attributes.h" 1.12 +#include <vector> 1.13 +#include "nsIDOMCanvasRenderingContext2D.h" 1.14 +#include "nsICanvasRenderingContextInternal.h" 1.15 +#include "mozilla/RefPtr.h" 1.16 +#include "nsColor.h" 1.17 +#include "mozilla/dom/HTMLCanvasElement.h" 1.18 +#include "mozilla/dom/HTMLVideoElement.h" 1.19 +#include "CanvasUtils.h" 1.20 +#include "gfxFont.h" 1.21 +#include "mozilla/ErrorResult.h" 1.22 +#include "mozilla/dom/CanvasGradient.h" 1.23 +#include "mozilla/dom/CanvasRenderingContext2DBinding.h" 1.24 +#include "mozilla/dom/CanvasPattern.h" 1.25 +#include "mozilla/gfx/Rect.h" 1.26 +#include "mozilla/gfx/2D.h" 1.27 +#include "gfx2DGlue.h" 1.28 +#include "imgIEncoder.h" 1.29 +#include "nsLayoutUtils.h" 1.30 +#include "mozilla/EnumeratedArray.h" 1.31 + 1.32 +class nsGlobalWindow; 1.33 +class nsXULElement; 1.34 + 1.35 +namespace mozilla { 1.36 +namespace gfx { 1.37 +class SourceSurface; 1.38 +class SurfaceStream; 1.39 +} 1.40 + 1.41 +namespace dom { 1.42 +class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement; 1.43 +class ImageData; 1.44 +class StringOrCanvasGradientOrCanvasPattern; 1.45 +class OwningStringOrCanvasGradientOrCanvasPattern; 1.46 +class TextMetrics; 1.47 + 1.48 +extern const mozilla::gfx::Float SIGMA_MAX; 1.49 + 1.50 +template<typename T> class Optional; 1.51 + 1.52 +class CanvasPath MOZ_FINAL : 1.53 + public nsWrapperCache 1.54 +{ 1.55 +public: 1.56 + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPath) 1.57 + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPath) 1.58 + 1.59 + nsCOMPtr<nsISupports> GetParentObject() { return mParent; } 1.60 + 1.61 + JSObject* WrapObject(JSContext* aCx); 1.62 + 1.63 + static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal, 1.64 + ErrorResult& rv); 1.65 + static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal, 1.66 + CanvasPath& aCanvasPath, 1.67 + ErrorResult& rv); 1.68 + static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal, 1.69 + const nsAString& aPathString, 1.70 + ErrorResult& rv); 1.71 + 1.72 + void ClosePath(); 1.73 + void MoveTo(double x, double y); 1.74 + void LineTo(double x, double y); 1.75 + void QuadraticCurveTo(double cpx, double cpy, double x, double y); 1.76 + void BezierCurveTo(double cp1x, double cp1y, 1.77 + double cp2x, double cp2y, 1.78 + double x, double y); 1.79 + void ArcTo(double x1, double y1, double x2, double y2, double radius, 1.80 + ErrorResult& error); 1.81 + void Rect(double x, double y, double w, double h); 1.82 + void Arc(double x, double y, double radius, 1.83 + double startAngle, double endAngle, bool anticlockwise, 1.84 + ErrorResult& error); 1.85 + 1.86 + void LineTo(const gfx::Point& aPoint); 1.87 + void BezierTo(const gfx::Point& aCP1, 1.88 + const gfx::Point& aCP2, 1.89 + const gfx::Point& aCP3); 1.90 + 1.91 + mozilla::RefPtr<mozilla::gfx::Path> GetPath(const CanvasWindingRule& winding, 1.92 + const mozilla::RefPtr<mozilla::gfx::DrawTarget>& mTarget) const; 1.93 + 1.94 + explicit CanvasPath(nsISupports* aParent); 1.95 + CanvasPath(nsISupports* aParent, RefPtr<gfx::PathBuilder> mPathBuilder); 1.96 + virtual ~CanvasPath() {} 1.97 + 1.98 +private: 1.99 + 1.100 + nsCOMPtr<nsISupports> mParent; 1.101 + static gfx::Float ToFloat(double aValue) { return gfx::Float(aValue); } 1.102 + 1.103 + mutable RefPtr<gfx::Path> mPath; 1.104 + mutable RefPtr<gfx::PathBuilder> mPathBuilder; 1.105 + 1.106 + void EnsurePathBuilder() const; 1.107 +}; 1.108 + 1.109 +struct CanvasBidiProcessor; 1.110 +class CanvasRenderingContext2DUserData; 1.111 + 1.112 +/** 1.113 + ** CanvasRenderingContext2D 1.114 + **/ 1.115 +class CanvasRenderingContext2D : 1.116 + public nsICanvasRenderingContextInternal, 1.117 + public nsWrapperCache 1.118 +{ 1.119 +typedef HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement 1.120 + HTMLImageOrCanvasOrVideoElement; 1.121 + 1.122 +public: 1.123 + CanvasRenderingContext2D(); 1.124 + virtual ~CanvasRenderingContext2D(); 1.125 + 1.126 + virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; 1.127 + 1.128 + HTMLCanvasElement* GetCanvas() const 1.129 + { 1.130 + // corresponds to changes to the old bindings made in bug 745025 1.131 + return mCanvasElement->GetOriginalCanvas(); 1.132 + } 1.133 + 1.134 + void Save(); 1.135 + void Restore(); 1.136 + void Scale(double x, double y, mozilla::ErrorResult& error); 1.137 + void Rotate(double angle, mozilla::ErrorResult& error); 1.138 + void Translate(double x, double y, mozilla::ErrorResult& error); 1.139 + void Transform(double m11, double m12, double m21, double m22, double dx, 1.140 + double dy, mozilla::ErrorResult& error); 1.141 + void SetTransform(double m11, double m12, double m21, double m22, double dx, 1.142 + double dy, mozilla::ErrorResult& error); 1.143 + 1.144 + double GlobalAlpha() 1.145 + { 1.146 + return CurrentState().globalAlpha; 1.147 + } 1.148 + 1.149 + // Useful for silencing cast warnings 1.150 + static mozilla::gfx::Float ToFloat(double aValue) { return mozilla::gfx::Float(aValue); } 1.151 + 1.152 + void SetGlobalAlpha(double globalAlpha) 1.153 + { 1.154 + if (globalAlpha >= 0.0 && globalAlpha <= 1.0) { 1.155 + CurrentState().globalAlpha = ToFloat(globalAlpha); 1.156 + } 1.157 + } 1.158 + 1.159 + void GetGlobalCompositeOperation(nsAString& op, mozilla::ErrorResult& error); 1.160 + void SetGlobalCompositeOperation(const nsAString& op, 1.161 + mozilla::ErrorResult& error); 1.162 + 1.163 + void GetStrokeStyle(OwningStringOrCanvasGradientOrCanvasPattern& value) 1.164 + { 1.165 + GetStyleAsUnion(value, Style::STROKE); 1.166 + } 1.167 + 1.168 + void SetStrokeStyle(const StringOrCanvasGradientOrCanvasPattern& value) 1.169 + { 1.170 + SetStyleFromUnion(value, Style::STROKE); 1.171 + } 1.172 + 1.173 + void GetFillStyle(OwningStringOrCanvasGradientOrCanvasPattern& value) 1.174 + { 1.175 + GetStyleAsUnion(value, Style::FILL); 1.176 + } 1.177 + 1.178 + void SetFillStyle(const StringOrCanvasGradientOrCanvasPattern& value) 1.179 + { 1.180 + SetStyleFromUnion(value, Style::FILL); 1.181 + } 1.182 + 1.183 + already_AddRefed<CanvasGradient> 1.184 + CreateLinearGradient(double x0, double y0, double x1, double y1); 1.185 + already_AddRefed<CanvasGradient> 1.186 + CreateRadialGradient(double x0, double y0, double r0, double x1, double y1, 1.187 + double r1, ErrorResult& aError); 1.188 + already_AddRefed<CanvasPattern> 1.189 + CreatePattern(const HTMLImageOrCanvasOrVideoElement& element, 1.190 + const nsAString& repeat, ErrorResult& error); 1.191 + 1.192 + double ShadowOffsetX() 1.193 + { 1.194 + return CurrentState().shadowOffset.x; 1.195 + } 1.196 + 1.197 + void SetShadowOffsetX(double shadowOffsetX) 1.198 + { 1.199 + CurrentState().shadowOffset.x = ToFloat(shadowOffsetX); 1.200 + } 1.201 + 1.202 + double ShadowOffsetY() 1.203 + { 1.204 + return CurrentState().shadowOffset.y; 1.205 + } 1.206 + 1.207 + void SetShadowOffsetY(double shadowOffsetY) 1.208 + { 1.209 + CurrentState().shadowOffset.y = ToFloat(shadowOffsetY); 1.210 + } 1.211 + 1.212 + double ShadowBlur() 1.213 + { 1.214 + return CurrentState().shadowBlur; 1.215 + } 1.216 + 1.217 + void SetShadowBlur(double shadowBlur) 1.218 + { 1.219 + if (shadowBlur >= 0.0) { 1.220 + CurrentState().shadowBlur = ToFloat(shadowBlur); 1.221 + } 1.222 + } 1.223 + 1.224 + void GetShadowColor(nsAString& shadowColor) 1.225 + { 1.226 + StyleColorToString(CurrentState().shadowColor, shadowColor); 1.227 + } 1.228 + 1.229 + void SetShadowColor(const nsAString& shadowColor); 1.230 + void ClearRect(double x, double y, double w, double h); 1.231 + void FillRect(double x, double y, double w, double h); 1.232 + void StrokeRect(double x, double y, double w, double h); 1.233 + void BeginPath(); 1.234 + void Fill(const CanvasWindingRule& winding); 1.235 + void Fill(const CanvasPath& path, const CanvasWindingRule& winding); 1.236 + void Stroke(); 1.237 + void Stroke(const CanvasPath& path); 1.238 + void DrawFocusIfNeeded(mozilla::dom::Element& element); 1.239 + bool DrawCustomFocusRing(mozilla::dom::Element& element); 1.240 + void Clip(const CanvasWindingRule& winding); 1.241 + void Clip(const CanvasPath& path, const CanvasWindingRule& winding); 1.242 + bool IsPointInPath(JSContext* cx, double x, double y, 1.243 + const CanvasWindingRule& winding); 1.244 + bool IsPointInPath(JSContext* cx, const CanvasPath& path, double x, double y, 1.245 + const CanvasWindingRule& winding); 1.246 + bool IsPointInStroke(JSContext* cx, double x, double y); 1.247 + bool IsPointInStroke(JSContext* cx, const CanvasPath& path, 1.248 + double x, double y); 1.249 + void FillText(const nsAString& text, double x, double y, 1.250 + const Optional<double>& maxWidth, 1.251 + mozilla::ErrorResult& error); 1.252 + void StrokeText(const nsAString& text, double x, double y, 1.253 + const Optional<double>& maxWidth, 1.254 + mozilla::ErrorResult& error); 1.255 + TextMetrics* 1.256 + MeasureText(const nsAString& rawText, mozilla::ErrorResult& error); 1.257 + 1.258 + void AddHitRegion(const HitRegionOptions& options, mozilla::ErrorResult& error); 1.259 + void RemoveHitRegion(const nsAString& id); 1.260 + 1.261 + void DrawImage(const HTMLImageOrCanvasOrVideoElement& image, 1.262 + double dx, double dy, mozilla::ErrorResult& error) 1.263 + { 1.264 + DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, 0.0, 0.0, 0, error); 1.265 + } 1.266 + 1.267 + void DrawImage(const HTMLImageOrCanvasOrVideoElement& image, 1.268 + double dx, double dy, double dw, double dh, 1.269 + mozilla::ErrorResult& error) 1.270 + { 1.271 + DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, dw, dh, 2, error); 1.272 + } 1.273 + 1.274 + void DrawImage(const HTMLImageOrCanvasOrVideoElement& image, 1.275 + double sx, double sy, double sw, double sh, double dx, 1.276 + double dy, double dw, double dh, mozilla::ErrorResult& error) 1.277 + { 1.278 + DrawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, 6, error); 1.279 + } 1.280 + 1.281 + already_AddRefed<ImageData> 1.282 + CreateImageData(JSContext* cx, double sw, double sh, 1.283 + mozilla::ErrorResult& error); 1.284 + already_AddRefed<ImageData> 1.285 + CreateImageData(JSContext* cx, ImageData& imagedata, 1.286 + mozilla::ErrorResult& error); 1.287 + already_AddRefed<ImageData> 1.288 + GetImageData(JSContext* cx, double sx, double sy, double sw, double sh, 1.289 + mozilla::ErrorResult& error); 1.290 + void PutImageData(ImageData& imageData, 1.291 + double dx, double dy, mozilla::ErrorResult& error); 1.292 + void PutImageData(ImageData& imageData, 1.293 + double dx, double dy, double dirtyX, double dirtyY, 1.294 + double dirtyWidth, double dirtyHeight, 1.295 + mozilla::ErrorResult& error); 1.296 + 1.297 + double LineWidth() 1.298 + { 1.299 + return CurrentState().lineWidth; 1.300 + } 1.301 + 1.302 + void SetLineWidth(double width) 1.303 + { 1.304 + if (width > 0.0) { 1.305 + CurrentState().lineWidth = ToFloat(width); 1.306 + } 1.307 + } 1.308 + void GetLineCap(nsAString& linecap); 1.309 + void SetLineCap(const nsAString& linecap); 1.310 + void GetLineJoin(nsAString& linejoin, mozilla::ErrorResult& error); 1.311 + void SetLineJoin(const nsAString& linejoin); 1.312 + 1.313 + double MiterLimit() 1.314 + { 1.315 + return CurrentState().miterLimit; 1.316 + } 1.317 + 1.318 + void SetMiterLimit(double miter) 1.319 + { 1.320 + if (miter > 0.0) { 1.321 + CurrentState().miterLimit = ToFloat(miter); 1.322 + } 1.323 + } 1.324 + 1.325 + void GetFont(nsAString& font) 1.326 + { 1.327 + font = GetFont(); 1.328 + } 1.329 + 1.330 + void SetFont(const nsAString& font, mozilla::ErrorResult& error); 1.331 + void GetTextAlign(nsAString& textAlign); 1.332 + void SetTextAlign(const nsAString& textAlign); 1.333 + void GetTextBaseline(nsAString& textBaseline); 1.334 + void SetTextBaseline(const nsAString& textBaseline); 1.335 + 1.336 + void ClosePath() 1.337 + { 1.338 + EnsureWritablePath(); 1.339 + 1.340 + if (mPathBuilder) { 1.341 + mPathBuilder->Close(); 1.342 + } else { 1.343 + mDSPathBuilder->Close(); 1.344 + } 1.345 + } 1.346 + 1.347 + void MoveTo(double x, double y) 1.348 + { 1.349 + EnsureWritablePath(); 1.350 + 1.351 + if (mPathBuilder) { 1.352 + mPathBuilder->MoveTo(mozilla::gfx::Point(ToFloat(x), ToFloat(y))); 1.353 + } else { 1.354 + mDSPathBuilder->MoveTo(mTarget->GetTransform() * 1.355 + mozilla::gfx::Point(ToFloat(x), ToFloat(y))); 1.356 + } 1.357 + } 1.358 + 1.359 + void LineTo(double x, double y) 1.360 + { 1.361 + EnsureWritablePath(); 1.362 + 1.363 + LineTo(mozilla::gfx::Point(ToFloat(x), ToFloat(y))); 1.364 + } 1.365 + 1.366 + void QuadraticCurveTo(double cpx, double cpy, double x, double y) 1.367 + { 1.368 + EnsureWritablePath(); 1.369 + 1.370 + if (mPathBuilder) { 1.371 + mPathBuilder->QuadraticBezierTo(mozilla::gfx::Point(ToFloat(cpx), ToFloat(cpy)), 1.372 + mozilla::gfx::Point(ToFloat(x), ToFloat(y))); 1.373 + } else { 1.374 + mozilla::gfx::Matrix transform = mTarget->GetTransform(); 1.375 + mDSPathBuilder->QuadraticBezierTo(transform * 1.376 + mozilla::gfx::Point(ToFloat(cpx), ToFloat(cpy)), 1.377 + transform * 1.378 + mozilla::gfx::Point(ToFloat(x), ToFloat(y))); 1.379 + } 1.380 + } 1.381 + 1.382 + void BezierCurveTo(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y) 1.383 + { 1.384 + EnsureWritablePath(); 1.385 + 1.386 + BezierTo(mozilla::gfx::Point(ToFloat(cp1x), ToFloat(cp1y)), 1.387 + mozilla::gfx::Point(ToFloat(cp2x), ToFloat(cp2y)), 1.388 + mozilla::gfx::Point(ToFloat(x), ToFloat(y))); 1.389 + } 1.390 + 1.391 + void ArcTo(double x1, double y1, double x2, double y2, double radius, 1.392 + mozilla::ErrorResult& error); 1.393 + void Rect(double x, double y, double w, double h); 1.394 + void Arc(double x, double y, double radius, double startAngle, 1.395 + double endAngle, bool anticlockwise, mozilla::ErrorResult& error); 1.396 + 1.397 + void GetMozCurrentTransform(JSContext* cx, 1.398 + JS::MutableHandle<JSObject*> result, 1.399 + mozilla::ErrorResult& error) const; 1.400 + void SetMozCurrentTransform(JSContext* cx, 1.401 + JS::Handle<JSObject*> currentTransform, 1.402 + mozilla::ErrorResult& error); 1.403 + void GetMozCurrentTransformInverse(JSContext* cx, 1.404 + JS::MutableHandle<JSObject*> result, 1.405 + mozilla::ErrorResult& error) const; 1.406 + void SetMozCurrentTransformInverse(JSContext* cx, 1.407 + JS::Handle<JSObject*> currentTransform, 1.408 + mozilla::ErrorResult& error); 1.409 + void GetFillRule(nsAString& fillRule); 1.410 + void SetFillRule(const nsAString& fillRule); 1.411 + void GetMozDash(JSContext* cx, JS::MutableHandle<JS::Value> retval, 1.412 + mozilla::ErrorResult& error); 1.413 + void SetMozDash(JSContext* cx, const JS::Value& mozDash, 1.414 + mozilla::ErrorResult& error); 1.415 + 1.416 + void SetLineDash(const Sequence<double>& mSegments); 1.417 + void GetLineDash(nsTArray<double>& mSegments) const; 1.418 + 1.419 + void SetLineDashOffset(double mOffset); 1.420 + double LineDashOffset() const; 1.421 + 1.422 + double MozDashOffset() 1.423 + { 1.424 + return CurrentState().dashOffset; 1.425 + } 1.426 + void SetMozDashOffset(double mozDashOffset); 1.427 + 1.428 + void GetMozTextStyle(nsAString& mozTextStyle) 1.429 + { 1.430 + GetFont(mozTextStyle); 1.431 + } 1.432 + 1.433 + void SetMozTextStyle(const nsAString& mozTextStyle, 1.434 + mozilla::ErrorResult& error) 1.435 + { 1.436 + SetFont(mozTextStyle, error); 1.437 + } 1.438 + 1.439 + bool ImageSmoothingEnabled() 1.440 + { 1.441 + return CurrentState().imageSmoothingEnabled; 1.442 + } 1.443 + 1.444 + void SetImageSmoothingEnabled(bool imageSmoothingEnabled) 1.445 + { 1.446 + if (imageSmoothingEnabled != CurrentState().imageSmoothingEnabled) { 1.447 + CurrentState().imageSmoothingEnabled = imageSmoothingEnabled; 1.448 + } 1.449 + } 1.450 + 1.451 + void DrawWindow(nsGlobalWindow& window, double x, double y, double w, double h, 1.452 + const nsAString& bgColor, uint32_t flags, 1.453 + mozilla::ErrorResult& error); 1.454 + void AsyncDrawXULElement(nsXULElement& elem, double x, double y, double w, 1.455 + double h, const nsAString& bgColor, uint32_t flags, 1.456 + mozilla::ErrorResult& error); 1.457 + 1.458 + void Demote(); 1.459 + 1.460 + nsresult Redraw(); 1.461 + 1.462 +#ifdef DEBUG 1.463 + virtual int32_t GetWidth() const MOZ_OVERRIDE; 1.464 + virtual int32_t GetHeight() const MOZ_OVERRIDE; 1.465 +#endif 1.466 + // nsICanvasRenderingContextInternal 1.467 + NS_IMETHOD SetDimensions(int32_t width, int32_t height) MOZ_OVERRIDE; 1.468 + NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, int32_t width, int32_t height) MOZ_OVERRIDE; 1.469 + 1.470 + NS_IMETHOD GetInputStream(const char* aMimeType, 1.471 + const char16_t* aEncoderOptions, 1.472 + nsIInputStream **aStream) MOZ_OVERRIDE; 1.473 + 1.474 + mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetSurfaceSnapshot(bool* aPremultAlpha = nullptr) MOZ_OVERRIDE 1.475 + { 1.476 + EnsureTarget(); 1.477 + if (aPremultAlpha) { 1.478 + *aPremultAlpha = true; 1.479 + } 1.480 + return mTarget->Snapshot(); 1.481 + } 1.482 + 1.483 + NS_IMETHOD SetIsOpaque(bool isOpaque) MOZ_OVERRIDE; 1.484 + bool GetIsOpaque() MOZ_OVERRIDE { return mOpaque; } 1.485 + NS_IMETHOD Reset() MOZ_OVERRIDE; 1.486 + already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder, 1.487 + CanvasLayer *aOldLayer, 1.488 + LayerManager *aManager) MOZ_OVERRIDE; 1.489 + virtual bool ShouldForceInactiveLayer(LayerManager *aManager) MOZ_OVERRIDE; 1.490 + void MarkContextClean() MOZ_OVERRIDE; 1.491 + NS_IMETHOD SetIsIPC(bool isIPC) MOZ_OVERRIDE; 1.492 + // this rect is in canvas device space 1.493 + void Redraw(const mozilla::gfx::Rect &r); 1.494 + NS_IMETHOD Redraw(const gfxRect &r) MOZ_OVERRIDE { Redraw(ToRect(r)); return NS_OK; } 1.495 + NS_IMETHOD SetContextOptions(JSContext* aCx, JS::Handle<JS::Value> aOptions) MOZ_OVERRIDE; 1.496 + 1.497 + // this rect is in mTarget's current user space 1.498 + void RedrawUser(const gfxRect &r); 1.499 + 1.500 + // nsISupports interface + CC 1.501 + NS_DECL_CYCLE_COLLECTING_ISUPPORTS 1.502 + 1.503 + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(CanvasRenderingContext2D) 1.504 + 1.505 + MOZ_BEGIN_NESTED_ENUM_CLASS(CanvasMultiGetterType, uint8_t) 1.506 + STRING = 0, 1.507 + PATTERN = 1, 1.508 + GRADIENT = 2 1.509 + MOZ_END_NESTED_ENUM_CLASS(CanvasMultiGetterType) 1.510 + 1.511 + MOZ_BEGIN_NESTED_ENUM_CLASS(Style, uint8_t) 1.512 + STROKE = 0, 1.513 + FILL, 1.514 + MAX 1.515 + MOZ_END_NESTED_ENUM_CLASS(Style) 1.516 + 1.517 + nsINode* GetParentObject() 1.518 + { 1.519 + return mCanvasElement; 1.520 + } 1.521 + 1.522 + void LineTo(const mozilla::gfx::Point& aPoint) 1.523 + { 1.524 + if (mPathBuilder) { 1.525 + mPathBuilder->LineTo(aPoint); 1.526 + } else { 1.527 + mDSPathBuilder->LineTo(mTarget->GetTransform() * aPoint); 1.528 + } 1.529 + } 1.530 + 1.531 + void BezierTo(const mozilla::gfx::Point& aCP1, 1.532 + const mozilla::gfx::Point& aCP2, 1.533 + const mozilla::gfx::Point& aCP3) 1.534 + { 1.535 + if (mPathBuilder) { 1.536 + mPathBuilder->BezierTo(aCP1, aCP2, aCP3); 1.537 + } else { 1.538 + mozilla::gfx::Matrix transform = mTarget->GetTransform(); 1.539 + mDSPathBuilder->BezierTo(transform * aCP1, 1.540 + transform * aCP2, 1.541 + transform * aCP3); 1.542 + } 1.543 + } 1.544 + 1.545 + friend class CanvasRenderingContext2DUserData; 1.546 + 1.547 + virtual void GetImageBuffer(uint8_t** aImageBuffer, int32_t* aFormat); 1.548 + 1.549 +protected: 1.550 + nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY, 1.551 + uint32_t aWidth, uint32_t aHeight, 1.552 + JSObject** aRetval); 1.553 + 1.554 + nsresult PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h, 1.555 + dom::Uint8ClampedArray* aArray, 1.556 + bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY, 1.557 + int32_t dirtyWidth, int32_t dirtyHeight); 1.558 + 1.559 + /** 1.560 + * Internal method to complete initialisation, expects mTarget to have been set 1.561 + */ 1.562 + nsresult Initialize(int32_t width, int32_t height); 1.563 + 1.564 + nsresult InitializeWithTarget(mozilla::gfx::DrawTarget *surface, 1.565 + int32_t width, int32_t height); 1.566 + 1.567 + /** 1.568 + * The number of living nsCanvasRenderingContexts. When this goes down to 1.569 + * 0, we free the premultiply and unpremultiply tables, if they exist. 1.570 + */ 1.571 + static uint32_t sNumLivingContexts; 1.572 + 1.573 + /** 1.574 + * Lookup table used to speed up GetImageData(). 1.575 + */ 1.576 + static uint8_t (*sUnpremultiplyTable)[256]; 1.577 + 1.578 + /** 1.579 + * Lookup table used to speed up PutImageData(). 1.580 + */ 1.581 + static uint8_t (*sPremultiplyTable)[256]; 1.582 + 1.583 + static mozilla::gfx::DrawTarget* sErrorTarget; 1.584 + 1.585 + // Some helpers. Doesn't modify a color on failure. 1.586 + void SetStyleFromUnion(const StringOrCanvasGradientOrCanvasPattern& value, 1.587 + Style whichStyle); 1.588 + void SetStyleFromString(const nsAString& str, Style whichStyle); 1.589 + 1.590 + void SetStyleFromGradient(CanvasGradient& gradient, Style whichStyle) 1.591 + { 1.592 + CurrentState().SetGradientStyle(whichStyle, &gradient); 1.593 + } 1.594 + 1.595 + void SetStyleFromPattern(CanvasPattern& pattern, Style whichStyle) 1.596 + { 1.597 + CurrentState().SetPatternStyle(whichStyle, &pattern); 1.598 + } 1.599 + 1.600 + void GetStyleAsUnion(OwningStringOrCanvasGradientOrCanvasPattern& aValue, 1.601 + Style aWhichStyle); 1.602 + 1.603 + // Returns whether a color was successfully parsed. 1.604 + bool ParseColor(const nsAString& aString, nscolor* aColor); 1.605 + 1.606 + static void StyleColorToString(const nscolor& aColor, nsAString& aStr); 1.607 + 1.608 + /** 1.609 + * Creates the error target, if it doesn't exist 1.610 + */ 1.611 + static void EnsureErrorTarget(); 1.612 + 1.613 + /* This function ensures there is a writable pathbuilder available, this 1.614 + * pathbuilder may be working in user space or in device space or 1.615 + * device space. 1.616 + * After calling this function mPathTransformWillUpdate will be false 1.617 + */ 1.618 + void EnsureWritablePath(); 1.619 + 1.620 + // Ensures a path in UserSpace is available. 1.621 + void EnsureUserSpacePath(const CanvasWindingRule& winding = CanvasWindingRule::Nonzero); 1.622 + 1.623 + /** 1.624 + * Needs to be called before updating the transform. This makes a call to 1.625 + * EnsureTarget() so you don't have to. 1.626 + */ 1.627 + void TransformWillUpdate(); 1.628 + 1.629 + // Report the fillRule has changed. 1.630 + void FillRuleChanged(); 1.631 + 1.632 + /** 1.633 + * Create the backing surfacing, if it doesn't exist. If there is an error 1.634 + * in creating the target then it will put sErrorTarget in place. If there 1.635 + * is in turn an error in creating the sErrorTarget then they would both 1.636 + * be null so IsTargetValid() would still return null. 1.637 + */ 1.638 + void EnsureTarget(); 1.639 + 1.640 + /* 1.641 + * Disposes an old target and prepares to lazily create a new target. 1.642 + */ 1.643 + void ClearTarget(); 1.644 + 1.645 + /** 1.646 + * Check if the target is valid after calling EnsureTarget. 1.647 + */ 1.648 + bool IsTargetValid() { return mTarget != sErrorTarget && mTarget != nullptr; } 1.649 + 1.650 + /** 1.651 + * Returns the surface format this canvas should be allocated using. Takes 1.652 + * into account mOpaque, platform requirements, etc. 1.653 + */ 1.654 + mozilla::gfx::SurfaceFormat GetSurfaceFormat() const; 1.655 + 1.656 + void DrawImage(const HTMLImageOrCanvasOrVideoElement &imgElt, 1.657 + double sx, double sy, double sw, double sh, 1.658 + double dx, double dy, double dw, double dh, 1.659 + uint8_t optional_argc, mozilla::ErrorResult& error); 1.660 + 1.661 + void DrawDirectlyToCanvas(const nsLayoutUtils::DirectDrawInfo& image, 1.662 + mozilla::gfx::Rect* bounds, double dx, double dy, 1.663 + double dw, double dh, double sx, double sy, 1.664 + double sw, double sh, gfxIntSize imgSize); 1.665 + 1.666 + nsString& GetFont() 1.667 + { 1.668 + /* will initilize the value if not set, else does nothing */ 1.669 + GetCurrentFontStyle(); 1.670 + 1.671 + return CurrentState().font; 1.672 + } 1.673 + 1.674 + static std::vector<CanvasRenderingContext2D*>& DemotableContexts(); 1.675 + static void DemoteOldestContextIfNecessary(); 1.676 + 1.677 + static void AddDemotableContext(CanvasRenderingContext2D* context); 1.678 + static void RemoveDemotableContext(CanvasRenderingContext2D* context); 1.679 + 1.680 + // Do not use GL 1.681 + bool mForceSoftware; 1.682 + 1.683 + // Member vars 1.684 + int32_t mWidth, mHeight; 1.685 + 1.686 + // This is true when the canvas is valid, but of zero size, this requires 1.687 + // specific behavior on some operations. 1.688 + bool mZero; 1.689 + 1.690 + bool mOpaque; 1.691 + 1.692 + // This is true when the next time our layer is retrieved we need to 1.693 + // recreate it (i.e. our backing surface changed) 1.694 + bool mResetLayer; 1.695 + // This is needed for drawing in drawAsyncXULElement 1.696 + bool mIPC; 1.697 + 1.698 + nsTArray<CanvasRenderingContext2DUserData*> mUserDatas; 1.699 + 1.700 + // If mCanvasElement is not provided, then a docshell is 1.701 + nsCOMPtr<nsIDocShell> mDocShell; 1.702 + 1.703 + // This is created lazily so it is necessary to call EnsureTarget before 1.704 + // accessing it. In the event of an error it will be equal to 1.705 + // sErrorTarget. 1.706 + mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget; 1.707 + 1.708 + RefPtr<gfx::SurfaceStream> mStream; 1.709 + 1.710 + /** 1.711 + * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever 1.712 + * Redraw is called, reset to false when Render is called. 1.713 + */ 1.714 + bool mIsEntireFrameInvalid; 1.715 + /** 1.716 + * When this is set, the first call to Redraw(gfxRect) should set 1.717 + * mIsEntireFrameInvalid since we expect it will be followed by 1.718 + * many more Redraw calls. 1.719 + */ 1.720 + bool mPredictManyRedrawCalls; 1.721 + 1.722 + // This is stored after GetThebesSurface has been called once to avoid 1.723 + // excessive ThebesSurface initialization overhead. 1.724 + nsRefPtr<gfxASurface> mThebesSurface; 1.725 + 1.726 + /** 1.727 + * We also have a device space pathbuilder. The reason for this is as 1.728 + * follows, when a path is being built, but the transform changes, we 1.729 + * can no longer keep a single path in userspace, considering there's 1.730 + * several 'user spaces' now. We therefore transform the current path 1.731 + * into device space, and add all operations to this path in device 1.732 + * space. 1.733 + * 1.734 + * When then finally executing a render, the Azure drawing API expects 1.735 + * the path to be in userspace. We could then set an identity transform 1.736 + * on the DrawTarget and do all drawing in device space. This is 1.737 + * undesirable because it requires transforming patterns, gradients, 1.738 + * clips, etc. into device space and it would not work for stroking. 1.739 + * What we do instead is convert the path back to user space when it is 1.740 + * drawn, and draw it with the current transform. This makes all drawing 1.741 + * occur correctly. 1.742 + * 1.743 + * There's never both a device space path builder and a user space path 1.744 + * builder present at the same time. There is also never a path and a 1.745 + * path builder present at the same time. When writing proceeds on an 1.746 + * existing path the Path is cleared and a new builder is created. 1.747 + * 1.748 + * mPath is always in user-space. 1.749 + */ 1.750 + mozilla::RefPtr<mozilla::gfx::Path> mPath; 1.751 + mozilla::RefPtr<mozilla::gfx::PathBuilder> mDSPathBuilder; 1.752 + mozilla::RefPtr<mozilla::gfx::PathBuilder> mPathBuilder; 1.753 + bool mPathTransformWillUpdate; 1.754 + mozilla::gfx::Matrix mPathToDS; 1.755 + 1.756 + /** 1.757 + * Number of times we've invalidated before calling redraw 1.758 + */ 1.759 + uint32_t mInvalidateCount; 1.760 + static const uint32_t kCanvasMaxInvalidateCount = 100; 1.761 + 1.762 + /** 1.763 + * State information for hit regions 1.764 + */ 1.765 + 1.766 + struct RegionInfo : public nsStringHashKey 1.767 + { 1.768 + RegionInfo(const nsAString& aKey) : 1.769 + nsStringHashKey(&aKey) 1.770 + { 1.771 + } 1.772 + RegionInfo(const nsAString *aKey) : 1.773 + nsStringHashKey(aKey) 1.774 + { 1.775 + } 1.776 + 1.777 + nsRefPtr<Element> mElement; 1.778 + }; 1.779 + 1.780 +#ifdef ACCESSIBILITY 1.781 + static PLDHashOperator RemoveHitRegionProperty(RegionInfo* aEntry, void* aData); 1.782 +#endif 1.783 + nsTHashtable<RegionInfo> mHitRegionsOptions; 1.784 + 1.785 + /** 1.786 + * Returns true if a shadow should be drawn along with a 1.787 + * drawing operation. 1.788 + */ 1.789 + bool NeedToDrawShadow() 1.790 + { 1.791 + const ContextState& state = CurrentState(); 1.792 + 1.793 + // The spec says we should not draw shadows if the operator is OVER. 1.794 + // If it's over and the alpha value is zero, nothing needs to be drawn. 1.795 + return NS_GET_A(state.shadowColor) != 0 && 1.796 + (state.shadowBlur != 0 || state.shadowOffset.x != 0 || state.shadowOffset.y != 0); 1.797 + } 1.798 + 1.799 + mozilla::gfx::CompositionOp UsedOperation() 1.800 + { 1.801 + if (NeedToDrawShadow()) { 1.802 + // In this case the shadow rendering will use the operator. 1.803 + return mozilla::gfx::CompositionOp::OP_OVER; 1.804 + } 1.805 + 1.806 + return CurrentState().op; 1.807 + } 1.808 + 1.809 + /** 1.810 + * Gets the pres shell from either the canvas element or the doc shell 1.811 + */ 1.812 + nsIPresShell *GetPresShell() { 1.813 + if (mCanvasElement) { 1.814 + return mCanvasElement->OwnerDoc()->GetShell(); 1.815 + } 1.816 + if (mDocShell) { 1.817 + return mDocShell->GetPresShell(); 1.818 + } 1.819 + return nullptr; 1.820 + } 1.821 + 1.822 + // text 1.823 + 1.824 +public: // These enums are public only to accomodate non-C++11 legacy path of 1.825 + // MOZ_FINISH_NESTED_ENUM_CLASS. Can move back to protected as soon 1.826 + // as that legacy path is dropped. 1.827 + MOZ_BEGIN_NESTED_ENUM_CLASS(TextAlign, uint8_t) 1.828 + START, 1.829 + END, 1.830 + LEFT, 1.831 + RIGHT, 1.832 + CENTER 1.833 + MOZ_END_NESTED_ENUM_CLASS(TextAlign) 1.834 + 1.835 + MOZ_BEGIN_NESTED_ENUM_CLASS(TextBaseline, uint8_t) 1.836 + TOP, 1.837 + HANGING, 1.838 + MIDDLE, 1.839 + ALPHABETIC, 1.840 + IDEOGRAPHIC, 1.841 + BOTTOM 1.842 + MOZ_END_NESTED_ENUM_CLASS(TextBaseline) 1.843 + 1.844 + MOZ_BEGIN_NESTED_ENUM_CLASS(TextDrawOperation, uint8_t) 1.845 + FILL, 1.846 + STROKE, 1.847 + MEASURE 1.848 + MOZ_END_NESTED_ENUM_CLASS(TextDrawOperation) 1.849 + 1.850 +protected: 1.851 + gfxFontGroup *GetCurrentFontStyle(); 1.852 + 1.853 + /* 1.854 + * Implementation of the fillText, strokeText, and measure functions with 1.855 + * the operation abstracted to a flag. 1.856 + */ 1.857 + nsresult DrawOrMeasureText(const nsAString& text, 1.858 + float x, 1.859 + float y, 1.860 + const Optional<double>& maxWidth, 1.861 + TextDrawOperation op, 1.862 + float* aWidth); 1.863 + 1.864 + // state stack handling 1.865 + class ContextState { 1.866 + public: 1.867 + ContextState() : textAlign(TextAlign::START), 1.868 + textBaseline(TextBaseline::ALPHABETIC), 1.869 + lineWidth(1.0f), 1.870 + miterLimit(10.0f), 1.871 + globalAlpha(1.0f), 1.872 + shadowBlur(0.0), 1.873 + dashOffset(0.0f), 1.874 + op(mozilla::gfx::CompositionOp::OP_OVER), 1.875 + fillRule(mozilla::gfx::FillRule::FILL_WINDING), 1.876 + lineCap(mozilla::gfx::CapStyle::BUTT), 1.877 + lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL), 1.878 + imageSmoothingEnabled(true) 1.879 + { } 1.880 + 1.881 + ContextState(const ContextState& other) 1.882 + : fontGroup(other.fontGroup), 1.883 + gradientStyles(other.gradientStyles), 1.884 + patternStyles(other.patternStyles), 1.885 + colorStyles(other.colorStyles), 1.886 + font(other.font), 1.887 + textAlign(other.textAlign), 1.888 + textBaseline(other.textBaseline), 1.889 + shadowColor(other.shadowColor), 1.890 + transform(other.transform), 1.891 + shadowOffset(other.shadowOffset), 1.892 + lineWidth(other.lineWidth), 1.893 + miterLimit(other.miterLimit), 1.894 + globalAlpha(other.globalAlpha), 1.895 + shadowBlur(other.shadowBlur), 1.896 + dash(other.dash), 1.897 + dashOffset(other.dashOffset), 1.898 + op(other.op), 1.899 + fillRule(other.fillRule), 1.900 + lineCap(other.lineCap), 1.901 + lineJoin(other.lineJoin), 1.902 + imageSmoothingEnabled(other.imageSmoothingEnabled) 1.903 + { } 1.904 + 1.905 + void SetColorStyle(Style whichStyle, nscolor color) 1.906 + { 1.907 + colorStyles[whichStyle] = color; 1.908 + gradientStyles[whichStyle] = nullptr; 1.909 + patternStyles[whichStyle] = nullptr; 1.910 + } 1.911 + 1.912 + void SetPatternStyle(Style whichStyle, CanvasPattern* pat) 1.913 + { 1.914 + gradientStyles[whichStyle] = nullptr; 1.915 + patternStyles[whichStyle] = pat; 1.916 + } 1.917 + 1.918 + void SetGradientStyle(Style whichStyle, CanvasGradient* grad) 1.919 + { 1.920 + gradientStyles[whichStyle] = grad; 1.921 + patternStyles[whichStyle] = nullptr; 1.922 + } 1.923 + 1.924 + /** 1.925 + * returns true iff the given style is a solid color. 1.926 + */ 1.927 + bool StyleIsColor(Style whichStyle) const 1.928 + { 1.929 + return !(patternStyles[whichStyle] || gradientStyles[whichStyle]); 1.930 + } 1.931 + 1.932 + 1.933 + std::vector<mozilla::RefPtr<mozilla::gfx::Path> > clipsPushed; 1.934 + 1.935 + nsRefPtr<gfxFontGroup> fontGroup; 1.936 + EnumeratedArray<Style, Style::MAX, nsRefPtr<CanvasGradient>> gradientStyles; 1.937 + EnumeratedArray<Style, Style::MAX, nsRefPtr<CanvasPattern>> patternStyles; 1.938 + EnumeratedArray<Style, Style::MAX, nscolor> colorStyles; 1.939 + 1.940 + nsString font; 1.941 + TextAlign textAlign; 1.942 + TextBaseline textBaseline; 1.943 + 1.944 + nscolor shadowColor; 1.945 + 1.946 + mozilla::gfx::Matrix transform; 1.947 + mozilla::gfx::Point shadowOffset; 1.948 + mozilla::gfx::Float lineWidth; 1.949 + mozilla::gfx::Float miterLimit; 1.950 + mozilla::gfx::Float globalAlpha; 1.951 + mozilla::gfx::Float shadowBlur; 1.952 + FallibleTArray<mozilla::gfx::Float> dash; 1.953 + mozilla::gfx::Float dashOffset; 1.954 + 1.955 + mozilla::gfx::CompositionOp op; 1.956 + mozilla::gfx::FillRule fillRule; 1.957 + mozilla::gfx::CapStyle lineCap; 1.958 + mozilla::gfx::JoinStyle lineJoin; 1.959 + 1.960 + bool imageSmoothingEnabled; 1.961 + }; 1.962 + 1.963 + nsAutoTArray<ContextState, 3> mStyleStack; 1.964 + 1.965 + inline ContextState& CurrentState() { 1.966 + return mStyleStack[mStyleStack.Length() - 1]; 1.967 + } 1.968 + 1.969 + inline const ContextState& CurrentState() const { 1.970 + return mStyleStack[mStyleStack.Length() - 1]; 1.971 + } 1.972 + 1.973 + friend class CanvasGeneralPattern; 1.974 + friend class AdjustedTarget; 1.975 + 1.976 + // other helpers 1.977 + void GetAppUnitsValues(int32_t *perDevPixel, int32_t *perCSSPixel) 1.978 + { 1.979 + // If we don't have a canvas element, we just return something generic. 1.980 + int32_t devPixel = 60; 1.981 + int32_t cssPixel = 60; 1.982 + 1.983 + nsIPresShell *ps = GetPresShell(); 1.984 + nsPresContext *pc; 1.985 + 1.986 + if (!ps) goto FINISH; 1.987 + pc = ps->GetPresContext(); 1.988 + if (!pc) goto FINISH; 1.989 + devPixel = pc->AppUnitsPerDevPixel(); 1.990 + cssPixel = pc->AppUnitsPerCSSPixel(); 1.991 + 1.992 + FINISH: 1.993 + if (perDevPixel) 1.994 + *perDevPixel = devPixel; 1.995 + if (perCSSPixel) 1.996 + *perCSSPixel = cssPixel; 1.997 + } 1.998 + 1.999 + friend struct CanvasBidiProcessor; 1.1000 +}; 1.1001 + 1.1002 +MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::CanvasMultiGetterType) 1.1003 +MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::Style) 1.1004 +MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextAlign) 1.1005 +MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextBaseline) 1.1006 +MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextDrawOperation) 1.1007 + 1.1008 +} 1.1009 +} 1.1010 + 1.1011 +#endif /* CanvasRenderingContext2D_h */