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