diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /dom/html/HTMLCanvasElement.h | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | uxp-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz |
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/html/HTMLCanvasElement.h')
-rw-r--r-- | dom/html/HTMLCanvasElement.h | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/dom/html/HTMLCanvasElement.h b/dom/html/HTMLCanvasElement.h new file mode 100644 index 0000000000..81c141d3cc --- /dev/null +++ b/dom/html/HTMLCanvasElement.h @@ -0,0 +1,452 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#if !defined(mozilla_dom_HTMLCanvasElement_h) +#define mozilla_dom_HTMLCanvasElement_h + +#include "mozilla/Attributes.h" +#include "mozilla/WeakPtr.h" +#include "nsIDOMEventListener.h" +#include "nsIDOMHTMLCanvasElement.h" +#include "nsIObserver.h" +#include "nsGenericHTMLElement.h" +#include "nsGkAtoms.h" +#include "nsSize.h" +#include "nsError.h" + +#include "mozilla/dom/CanvasRenderingContextHelper.h" +#include "mozilla/gfx/Rect.h" +#include "mozilla/layers/LayersTypes.h" + +class nsICanvasRenderingContextInternal; +class nsITimerCallback; + +namespace mozilla { + +class WebGLContext; + +namespace layers { +class AsyncCanvasRenderer; +class CanvasLayer; +class Image; +class Layer; +class LayerManager; +class SharedSurfaceTextureClient; +} // namespace layers +namespace gfx { +class SourceSurface; +class VRLayerChild; +} // namespace gfx + +namespace dom { +class BlobCallback; +class CanvasCaptureMediaStream; +class File; +class HTMLCanvasPrintState; +class OffscreenCanvas; +class PrintCallback; +class RequestedFrameRefreshObserver; + +// Listen visibilitychange and memory-pressure event and inform +// context when event is fired. +class HTMLCanvasElementObserver final : public nsIObserver + , public nsIDOMEventListener +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + NS_DECL_NSIDOMEVENTLISTENER + + explicit HTMLCanvasElementObserver(HTMLCanvasElement* aElement); + void Destroy(); + + void RegisterVisibilityChangeEvent(); + void UnregisterVisibilityChangeEvent(); + + void RegisterMemoryPressureEvent(); + void UnregisterMemoryPressureEvent(); + +private: + ~HTMLCanvasElementObserver(); + + HTMLCanvasElement* mElement; +}; + +/* + * FrameCaptureListener is used by captureStream() as a way of getting video + * frames from the canvas. On a refresh driver tick after something has been + * drawn to the canvas since the last such tick, all registered + * FrameCaptureListeners whose `mFrameCaptureRequested` equals `true`, + * will be given a copy of the just-painted canvas. + * All FrameCaptureListeners get the same copy. + */ +class FrameCaptureListener : public SupportsWeakPtr<FrameCaptureListener> +{ +public: + MOZ_DECLARE_WEAKREFERENCE_TYPENAME(FrameCaptureListener) + + FrameCaptureListener() + : mFrameCaptureRequested(false) {} + + /* + * Called when a frame capture is desired on next paint. + */ + void RequestFrameCapture() { mFrameCaptureRequested = true; } + + /* + * Indicates to the canvas whether or not this listener has requested a frame. + */ + bool FrameCaptureRequested() const { return mFrameCaptureRequested; } + + /* + * Interface through which new video frames will be provided while + * `mFrameCaptureRequested` is `true`. + */ + virtual void NewFrame(already_AddRefed<layers::Image> aImage) = 0; + +protected: + virtual ~FrameCaptureListener() {} + + bool mFrameCaptureRequested; +}; + +class HTMLCanvasElement final : public nsGenericHTMLElement, + public nsIDOMHTMLCanvasElement, + public CanvasRenderingContextHelper +{ + enum { + DEFAULT_CANVAS_WIDTH = 300, + DEFAULT_CANVAS_HEIGHT = 150 + }; + + typedef layers::AsyncCanvasRenderer AsyncCanvasRenderer; + typedef layers::CanvasLayer CanvasLayer; + typedef layers::Layer Layer; + typedef layers::LayerManager LayerManager; + +public: + explicit HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo); + + NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLCanvasElement, canvas) + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + // nsIDOMHTMLCanvasElement + NS_DECL_NSIDOMHTMLCANVASELEMENT + + // CC + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLCanvasElement, + nsGenericHTMLElement) + + // WebIDL + uint32_t Height() + { + return GetUnsignedIntAttr(nsGkAtoms::height, DEFAULT_CANVAS_HEIGHT); + } + void SetHeight(uint32_t aHeight, ErrorResult& aRv) + { + if (mOffscreenCanvas) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + SetUnsignedIntAttr(nsGkAtoms::height, aHeight, DEFAULT_CANVAS_HEIGHT, aRv); + } + uint32_t Width() + { + return GetUnsignedIntAttr(nsGkAtoms::width, DEFAULT_CANVAS_WIDTH); + } + void SetWidth(uint32_t aWidth, ErrorResult& aRv) + { + if (mOffscreenCanvas) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + SetUnsignedIntAttr(nsGkAtoms::width, aWidth, DEFAULT_CANVAS_WIDTH, aRv); + } + + virtual already_AddRefed<nsISupports> + GetContext(JSContext* aCx, const nsAString& aContextId, + JS::Handle<JS::Value> aContextOptions, + ErrorResult& aRv) override; + + void ToDataURL(JSContext* aCx, const nsAString& aType, + JS::Handle<JS::Value> aParams, + nsAString& aDataURL, ErrorResult& aRv) + { + aRv = ToDataURL(aType, aParams, aCx, aDataURL); + } + + void ToBlob(JSContext* aCx, + BlobCallback& aCallback, + const nsAString& aType, + JS::Handle<JS::Value> aParams, + ErrorResult& aRv); + + OffscreenCanvas* TransferControlToOffscreen(ErrorResult& aRv); + + bool MozOpaque() const + { + return GetBoolAttr(nsGkAtoms::moz_opaque); + } + void SetMozOpaque(bool aValue, ErrorResult& aRv) + { + if (mOffscreenCanvas) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + SetHTMLBoolAttr(nsGkAtoms::moz_opaque, aValue, aRv); + } + already_AddRefed<File> MozGetAsFile(const nsAString& aName, + const nsAString& aType, + ErrorResult& aRv); + already_AddRefed<nsISupports> MozGetIPCContext(const nsAString& aContextId, + ErrorResult& aRv) + { + nsCOMPtr<nsISupports> context; + aRv = MozGetIPCContext(aContextId, getter_AddRefs(context)); + return context.forget(); + } + PrintCallback* GetMozPrintCallback() const; + void SetMozPrintCallback(PrintCallback* aCallback); + + already_AddRefed<CanvasCaptureMediaStream> + CaptureStream(const Optional<double>& aFrameRate, ErrorResult& aRv); + + /** + * Get the size in pixels of this canvas element + */ + nsIntSize GetSize(); + + /** + * Determine whether the canvas is write-only. + */ + bool IsWriteOnly(); + + /** + * Force the canvas to be write-only. + */ + void SetWriteOnly(); + + /** + * Notify that some canvas content has changed and the window may + * need to be updated. aDamageRect is in canvas coordinates. + */ + void InvalidateCanvasContent(const mozilla::gfx::Rect* aDamageRect); + /* + * Notify that we need to repaint the entire canvas, including updating of + * the layer tree. + */ + void InvalidateCanvas(); + + /* + * Get the number of contexts in this canvas, and request a context at + * an index. + */ + int32_t CountContexts (); + nsICanvasRenderingContextInternal *GetContextAtIndex (int32_t index); + + /* + * Returns true if the canvas context content is guaranteed to be opaque + * across its entire area. + */ + bool GetIsOpaque(); + virtual bool GetOpaqueAttr() override; + + virtual already_AddRefed<gfx::SourceSurface> GetSurfaceSnapshot(bool* aPremultAlpha = nullptr); + + /* + * Register a FrameCaptureListener with this canvas. + * The canvas hooks into the RefreshDriver while there are + * FrameCaptureListeners registered. + * The registered FrameCaptureListeners are stored as WeakPtrs, thus it's the + * caller's responsibility to keep them alive. Once a registered + * FrameCaptureListener is destroyed it will be automatically deregistered. + */ + nsresult RegisterFrameCaptureListener(FrameCaptureListener* aListener); + + /* + * Returns true when there is at least one registered FrameCaptureListener + * that has requested a frame capture. + */ + bool IsFrameCaptureRequested() const; + + /* + * Processes destroyed FrameCaptureListeners and removes them if necessary. + * Should there be none left, the FrameRefreshObserver will be unregistered. + */ + void ProcessDestroyedFrameListeners(); + + /* + * Called by the RefreshDriver hook when a frame has been captured. + * Makes a copy of the provided surface and hands it to all + * FrameCaptureListeners having requested frame capture. + */ + void SetFrameCapture(already_AddRefed<gfx::SourceSurface> aSurface); + + virtual bool ParseAttribute(int32_t aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) override; + nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, int32_t aModType) const override; + + // SetAttr override. C++ is stupid, so have to override both + // overloaded methods. + nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, + const nsAString& aValue, bool aNotify) + { + return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); + } + virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + bool aNotify) override; + + virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName, + bool aNotify) override; + + virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; + nsresult CopyInnerTo(mozilla::dom::Element* aDest); + + virtual nsresult PreHandleEvent(mozilla::EventChainPreVisitor& aVisitor) override; + + /* + * Helpers called by various users of Canvas + */ + + already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder, + Layer *aOldLayer, + LayerManager *aManager); + // Should return true if the canvas layer should always be marked inactive. + // We should return true here if we can't do accelerated compositing with + // a non-BasicCanvasLayer. + bool ShouldForceInactiveLayer(LayerManager *aManager); + + // Call this whenever we need future changes to the canvas + // to trigger fresh invalidation requests. This needs to be called + // whenever we render the canvas contents to the screen, or whenever we + // take a snapshot of the canvas that needs to be "live" (e.g. -moz-element). + void MarkContextClean(); + + // Call this after capturing a frame, so we can avoid unnecessary surface + // copies for future frames when no drawing has occurred. + void MarkContextCleanForFrameCapture(); + + // Starts returning false when something is drawn. + bool IsContextCleanForFrameCapture(); + + nsresult GetContext(const nsAString& aContextId, nsISupports** aContext); + + layers::LayersBackend GetCompositorBackendType() const; + + void OnVisibilityChange(); + + void OnMemoryPressure(); + + static void SetAttrFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer); + static void InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer); + + void StartVRPresentation(); + void StopVRPresentation(); + already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame(); + +protected: + virtual ~HTMLCanvasElement(); + + virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; + + virtual nsIntSize GetWidthHeight() override; + + virtual already_AddRefed<nsICanvasRenderingContextInternal> + CreateContext(CanvasContextType aContextType) override; + + nsresult ExtractData(nsAString& aType, + const nsAString& aOptions, + nsIInputStream** aStream); + nsresult ToDataURLImpl(JSContext* aCx, + const nsAString& aMimeType, + const JS::Value& aEncoderOptions, + nsAString& aDataURL); + nsresult MozGetAsBlobImpl(const nsAString& aName, + const nsAString& aType, + nsISupports** aResult); + void CallPrintCallback(); + + AsyncCanvasRenderer* GetAsyncCanvasRenderer(); + + bool mResetLayer; + RefPtr<HTMLCanvasElement> mOriginalCanvas; + RefPtr<PrintCallback> mPrintCallback; + RefPtr<HTMLCanvasPrintState> mPrintState; + nsTArray<WeakPtr<FrameCaptureListener>> mRequestedFrameListeners; + RefPtr<RequestedFrameRefreshObserver> mRequestedFrameRefreshObserver; + RefPtr<AsyncCanvasRenderer> mAsyncCanvasRenderer; + RefPtr<OffscreenCanvas> mOffscreenCanvas; + RefPtr<HTMLCanvasElementObserver> mContextObserver; + bool mVRPresentationActive; + +public: + // Record whether this canvas should be write-only or not. + // We set this when script paints an image from a different origin. + // We also transitively set it when script paints a canvas which + // is itself write-only. + bool mWriteOnly; + + bool IsPrintCallbackDone(); + + void HandlePrintCallback(nsPresContext::nsPresContextType aType); + + nsresult DispatchPrintCallback(nsITimerCallback* aCallback); + + void ResetPrintCallback(); + + HTMLCanvasElement* GetOriginalCanvas(); + + CanvasContextType GetCurrentContextType() { + return mCurrentContextType; + } +}; + +class HTMLCanvasPrintState final : public nsWrapperCache +{ +public: + HTMLCanvasPrintState(HTMLCanvasElement* aCanvas, + nsICanvasRenderingContextInternal* aContext, + nsITimerCallback* aCallback); + + nsISupports* Context() const; + + void Done(); + + void NotifyDone(); + + bool mIsDone; + + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(HTMLCanvasPrintState) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(HTMLCanvasPrintState) + + virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override; + + HTMLCanvasElement* GetParentObject() + { + return mCanvas; + } + +private: + ~HTMLCanvasPrintState(); + bool mPendingNotify; + +protected: + RefPtr<HTMLCanvasElement> mCanvas; + nsCOMPtr<nsICanvasRenderingContextInternal> mContext; + nsCOMPtr<nsITimerCallback> mCallback; +}; + +} // namespace dom +} // namespace mozilla + +#endif /* mozilla_dom_HTMLCanvasElement_h */ |