1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_ImageBitmap_h
8 #define mozilla_dom_ImageBitmap_h
10 #include "mozilla/Attributes.h"
11 #include "mozilla/SurfaceFromElementResult.h"
12 #include "mozilla/dom/ImageBitmapBinding.h"
13 #include "mozilla/dom/ImageBitmapSource.h"
14 #include "mozilla/dom/TypedArray.h"
15 #include "mozilla/gfx/Rect.h"
16 #include "mozilla/Maybe.h"
17 #include "mozilla/UniquePtr.h"
18 #include "ImageData.h"
19 #include "gfxTypes.h" // for gfxAlphaType
20 #include "nsCycleCollectionParticipant.h"
23 struct JSStructuredCloneReader
;
24 struct JSStructuredCloneWriter
;
26 class nsIGlobalObject
;
33 class DataSourceSurface
;
43 class OffscreenCanvas
;
45 class ArrayBufferViewOrArrayBuffer
;
46 class CanvasRenderingContext2D
;
47 class CreateImageBitmapFromBlob
;
48 class CreateImageBitmapFromBlobTask
;
49 class CreateImageBitmapFromBlobWorkerTask
;
50 class ImageBitmapShutdownObserver
;
52 class HTMLCanvasElement
;
53 class HTMLImageElement
;
54 class HTMLVideoElement
;
58 class PostMessageEvent
; // For StructuredClone between windows.
59 class SVGImageElement
;
61 class SendShutdownToWorkerThread
;
63 struct ImageBitmapCloneData final
{
64 RefPtr
<gfx::DataSourceSurface
> mSurface
;
65 gfx::IntRect mPictureRect
;
66 gfxAlphaType mAlphaType
;
71 * ImageBitmap is an opaque handler to several kinds of image-like objects from
72 * HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, ImageData to
73 * CanvasRenderingContext2D and Image Blob.
75 * An ImageBitmap could be painted to a canvas element.
77 * Generally, an ImageBitmap only keeps a reference to its source object's
78 * buffer, but if the source object is an ImageData, an Blob or a
79 * HTMLCanvasElement with WebGL rendering context, the ImageBitmap copy the
80 * source object's buffer.
82 class ImageBitmap final
: public nsISupports
, public nsWrapperCache
{
84 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
85 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ImageBitmap
)
87 nsCOMPtr
<nsIGlobalObject
> GetParentObject() const { return mParent
; }
89 virtual JSObject
* WrapObject(JSContext
* aCx
,
90 JS::Handle
<JSObject
*> aGivenProto
) override
;
92 uint32_t Width() const { return mPictureRect
.Width(); }
94 uint32_t Height() const { return mPictureRect
.Height(); }
98 SurfaceFromElementResult
SurfaceFrom(uint32_t aSurfaceFlags
);
101 * The PrepareForDrawTarget() might return null if the mPictureRect does not
102 * intersect with the size of mData.
104 already_AddRefed
<gfx::SourceSurface
> PrepareForDrawTarget(
105 gfx::DrawTarget
* aTarget
);
108 * Transfer ownership of buffer to caller. So this function call
109 * Close() implicitly.
111 already_AddRefed
<layers::Image
> TransferAsImage();
113 // This method returns null if the image has been already closed.
114 UniquePtr
<ImageBitmapCloneData
> ToCloneData() const;
116 static already_AddRefed
<ImageBitmap
> CreateFromSourceSurface(
117 nsIGlobalObject
* aGlobal
, gfx::SourceSurface
* aSource
, ErrorResult
& aRv
);
119 static already_AddRefed
<ImageBitmap
> CreateFromCloneData(
120 nsIGlobalObject
* aGlobal
, ImageBitmapCloneData
* aData
);
122 static already_AddRefed
<ImageBitmap
> CreateFromOffscreenCanvas(
123 nsIGlobalObject
* aGlobal
, OffscreenCanvas
& aOffscreenCanvas
,
126 static already_AddRefed
<Promise
> Create(nsIGlobalObject
* aGlobal
,
127 const ImageBitmapSource
& aSrc
,
128 const Maybe
<gfx::IntRect
>& aCropRect
,
129 const ImageBitmapOptions
& aOptions
,
132 static JSObject
* ReadStructuredClone(
133 JSContext
* aCx
, JSStructuredCloneReader
* aReader
,
134 nsIGlobalObject
* aParent
,
135 const nsTArray
<RefPtr
<gfx::DataSourceSurface
>>& aClonedSurfaces
,
138 static void WriteStructuredClone(
139 JSStructuredCloneWriter
* aWriter
,
140 nsTArray
<RefPtr
<gfx::DataSourceSurface
>>& aClonedSurfaces
,
141 ImageBitmap
* aImageBitmap
, ErrorResult
& aRv
);
143 friend CreateImageBitmapFromBlob
;
144 friend CreateImageBitmapFromBlobTask
;
145 friend CreateImageBitmapFromBlobWorkerTask
;
146 friend ImageBitmapShutdownObserver
;
148 size_t GetAllocatedSize() const;
152 bool IsWriteOnly() const { return mWriteOnly
; }
153 bool IsClosed() const { return !mData
; };
157 * The default value of aIsPremultipliedAlpha is TRUE because that the
158 * data stored in HTMLImageElement, HTMLVideoElement, HTMLCanvasElement,
159 * CanvasRenderingContext2D are alpha-premultiplied in default.
161 * Actually, if one HTMLCanvasElement's rendering context is WebGLContext, it
162 * is possible to get un-premultipliedAlpha data out. But, we do not do it in
163 * the CreateInternal(from HTMLCanvasElement) method.
165 * It is also possible to decode an image which is encoded with alpha channel
166 * to be non-premultipliedAlpha. This could be applied in
167 * 1) the CreateInternal(from HTMLImageElement) method (which might trigger
168 * re-decoding if the original decoded data is alpha-premultiplied) and
169 * 2) while decoding a blob. But we do not do it in both code path too.
171 * ImageData's underlying data is triggered as non-premultipliedAlpha, so set
172 * the aIsPremultipliedAlpha to be false in the
173 * CreateInternal(from ImageData) method.
175 ImageBitmap(nsIGlobalObject
* aGlobal
, layers::Image
* aData
, bool aWriteOnly
,
176 gfxAlphaType aAlphaType
= gfxAlphaType::Premult
);
178 virtual ~ImageBitmap();
180 void SetPictureRect(const gfx::IntRect
& aRect
, ErrorResult
& aRv
);
182 static already_AddRefed
<ImageBitmap
> CreateImageBitmapInternal(
183 nsIGlobalObject
* aGlobal
, gfx::SourceSurface
* aSurface
,
184 const Maybe
<gfx::IntRect
>& aCropRect
, const ImageBitmapOptions
& aOptions
,
185 const bool aWriteOnly
, const bool aAllocatedImageData
,
186 const bool aMustCopy
, const gfxAlphaType aAlphaType
, ErrorResult
& aRv
);
188 static already_AddRefed
<ImageBitmap
> CreateInternal(
189 nsIGlobalObject
* aGlobal
, HTMLImageElement
& aImageEl
,
190 const Maybe
<gfx::IntRect
>& aCropRect
, const ImageBitmapOptions
& aOptions
,
193 static already_AddRefed
<ImageBitmap
> CreateInternal(
194 nsIGlobalObject
* aGlobal
, SVGImageElement
& aImageEl
,
195 const Maybe
<gfx::IntRect
>& aCropRect
, const ImageBitmapOptions
& aOptions
,
198 static already_AddRefed
<ImageBitmap
> CreateInternal(
199 nsIGlobalObject
* aGlobal
, HTMLVideoElement
& aVideoEl
,
200 const Maybe
<gfx::IntRect
>& aCropRect
, const ImageBitmapOptions
& aOptions
,
203 static already_AddRefed
<ImageBitmap
> CreateInternal(
204 nsIGlobalObject
* aGlobal
, HTMLCanvasElement
& aCanvasEl
,
205 const Maybe
<gfx::IntRect
>& aCropRect
, const ImageBitmapOptions
& aOptions
,
208 static already_AddRefed
<ImageBitmap
> CreateInternal(
209 nsIGlobalObject
* aGlobal
, OffscreenCanvas
& aOffscreenCanvas
,
210 const Maybe
<gfx::IntRect
>& aCropRect
, const ImageBitmapOptions
& aOptions
,
213 static already_AddRefed
<ImageBitmap
> CreateInternal(
214 nsIGlobalObject
* aGlobal
, ImageData
& aImageData
,
215 const Maybe
<gfx::IntRect
>& aCropRect
, const ImageBitmapOptions
& aOptions
,
218 static already_AddRefed
<ImageBitmap
> CreateInternal(
219 nsIGlobalObject
* aGlobal
, CanvasRenderingContext2D
& aCanvasCtx
,
220 const Maybe
<gfx::IntRect
>& aCropRect
, const ImageBitmapOptions
& aOptions
,
223 static already_AddRefed
<ImageBitmap
> CreateInternal(
224 nsIGlobalObject
* aGlobal
, ImageBitmap
& aImageBitmap
,
225 const Maybe
<gfx::IntRect
>& aCropRect
, const ImageBitmapOptions
& aOptions
,
228 static already_AddRefed
<ImageBitmap
> CreateInternal(
229 nsIGlobalObject
* aGlobal
, VideoFrame
& aVideoFrame
,
230 const Maybe
<gfx::IntRect
>& aCropRect
, const ImageBitmapOptions
& aOptions
,
233 nsCOMPtr
<nsIGlobalObject
> mParent
;
236 * The mData is the data buffer of an ImageBitmap, so the mData must not be
239 * The mSurface is a cache for drawing the ImageBitmap onto a
240 * HTMLCanvasElement. The mSurface is null while the ImageBitmap is created
241 * and then will be initialized while the PrepareForDrawTarget() method is
244 * The mSurface might just be a reference to the same data buffer of the mData
245 * if the are of mPictureRect is just the same as the mData's size. Or, it is
246 * a independent data buffer which is copied and cropped form the mData's data
249 RefPtr
<layers::Image
> mData
;
250 RefPtr
<gfx::SourceSurface
> mSurface
;
253 * The mPictureRect is the size of the source image in default, however, if
254 * users specify the cropping area while creating an ImageBitmap, then this
255 * mPictureRect is the cropping area.
257 * Note that if the CreateInternal() copies and crops data from the source
258 * image, then this mPictureRect is just the size of the final mData.
260 * The mPictureRect will be used at PrepareForDrawTarget() while user is going
261 * to draw this ImageBitmap into a HTMLCanvasElement.
263 gfx::IntRect mPictureRect
;
265 gfxAlphaType mAlphaType
;
267 RefPtr
<SendShutdownToWorkerThread
> mShutdownRunnable
;
270 * Whether this object allocated allocated and owns the image data.
272 bool mAllocatedImageData
;
275 * Write-Only flag is set to true if this image has been generated from a
276 * cross-origin source. This is the opposite of what is called 'origin-clean'
283 } // namespace mozilla
285 #endif // mozilla_dom_ImageBitmap_h