ImageBitmap.h (10309B)
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/. */ 6 7 #ifndef mozilla_dom_ImageBitmap_h 8 #define mozilla_dom_ImageBitmap_h 9 10 #include "ImageData.h" 11 #include "gfxTypes.h" // for gfxAlphaType 12 #include "mozilla/Maybe.h" 13 #include "mozilla/SurfaceFromElementResult.h" 14 #include "mozilla/UniquePtr.h" 15 #include "mozilla/dom/ImageBitmapBinding.h" 16 #include "mozilla/dom/ImageBitmapSource.h" 17 #include "mozilla/dom/TypedArray.h" 18 #include "mozilla/gfx/Rect.h" 19 #include "nsCycleCollectionParticipant.h" 20 21 struct JSContext; 22 struct JSStructuredCloneReader; 23 struct JSStructuredCloneWriter; 24 25 class nsIGlobalObject; 26 27 namespace mozilla { 28 29 class ErrorResult; 30 31 namespace gfx { 32 class DataSourceSurface; 33 class DrawTarget; 34 class SourceSurface; 35 } // namespace gfx 36 37 namespace layers { 38 class Image; 39 } 40 41 namespace dom { 42 class OffscreenCanvas; 43 44 class ArrayBufferViewOrArrayBuffer; 45 class CanvasRenderingContext2D; 46 class CreateImageBitmapFromBlob; 47 class CreateImageBitmapFromBlobTask; 48 class CreateImageBitmapFromBlobWorkerTask; 49 class ImageBitmapShutdownObserver; 50 class File; 51 class HTMLCanvasElement; 52 class HTMLImageElement; 53 class HTMLVideoElement; 54 class ImageData; 55 class ImageUtils; 56 class Promise; 57 class PostMessageEvent; // For StructuredClone between windows. 58 class SVGImageElement; 59 class VideoFrame; 60 class SendShutdownToWorkerThread; 61 62 struct ImageBitmapCloneData final { 63 RefPtr<gfx::DataSourceSurface> mSurface; 64 gfx::IntRect mPictureRect; 65 gfxAlphaType mAlphaType; 66 bool mWriteOnly; 67 }; 68 69 /* 70 * ImageBitmap is an opaque handler to several kinds of image-like objects from 71 * HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, ImageData to 72 * CanvasRenderingContext2D and Image Blob. 73 * 74 * An ImageBitmap could be painted to a canvas element. 75 * 76 * Generally, an ImageBitmap only keeps a reference to its source object's 77 * buffer, but if the source object is an ImageData, an Blob or a 78 * HTMLCanvasElement with WebGL rendering context, the ImageBitmap copy the 79 * source object's buffer. 80 */ 81 class ImageBitmap final : public nsISupports, public nsWrapperCache { 82 public: 83 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 84 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ImageBitmap) 85 86 nsCOMPtr<nsIGlobalObject> GetParentObject() const { return mParent; } 87 88 virtual JSObject* WrapObject(JSContext* aCx, 89 JS::Handle<JSObject*> aGivenProto) override; 90 91 uint32_t Width() const { return mPictureRect.Width(); } 92 93 uint32_t Height() const { return mPictureRect.Height(); } 94 95 void Close(); 96 97 SurfaceFromElementResult SurfaceFrom(uint32_t aSurfaceFlags); 98 99 /* 100 * The PrepareForDrawTarget() might return null if the mPictureRect does not 101 * intersect with the size of mData. 102 */ 103 already_AddRefed<gfx::SourceSurface> PrepareForDrawTarget( 104 gfx::DrawTarget* aTarget); 105 106 /* 107 * Transfer ownership of buffer to caller. So this function call 108 * Close() implicitly. 109 */ 110 already_AddRefed<layers::Image> TransferAsImage(); 111 112 // This method returns null if the image has been already closed. 113 UniquePtr<ImageBitmapCloneData> ToCloneData() const; 114 115 static already_AddRefed<ImageBitmap> CreateFromSourceSurface( 116 nsIGlobalObject* aGlobal, gfx::SourceSurface* aSource, ErrorResult& aRv); 117 118 static already_AddRefed<ImageBitmap> CreateFromCloneData( 119 nsIGlobalObject* aGlobal, ImageBitmapCloneData* aData); 120 121 static already_AddRefed<ImageBitmap> CreateFromOffscreenCanvas( 122 nsIGlobalObject* aGlobal, OffscreenCanvas& aOffscreenCanvas, 123 ErrorResult& aRv); 124 125 static already_AddRefed<Promise> Create(nsIGlobalObject* aGlobal, 126 const ImageBitmapSource& aSrc, 127 const Maybe<gfx::IntRect>& aCropRect, 128 const ImageBitmapOptions& aOptions, 129 ErrorResult& aRv); 130 131 static JSObject* ReadStructuredClone( 132 JSContext* aCx, JSStructuredCloneReader* aReader, 133 nsIGlobalObject* aParent, 134 const nsTArray<RefPtr<gfx::DataSourceSurface>>& aClonedSurfaces, 135 uint32_t aIndex); 136 137 static void WriteStructuredClone( 138 JSStructuredCloneWriter* aWriter, 139 nsTArray<RefPtr<gfx::DataSourceSurface>>& aClonedSurfaces, 140 ImageBitmap* aImageBitmap, ErrorResult& aRv); 141 142 friend CreateImageBitmapFromBlob; 143 friend CreateImageBitmapFromBlobTask; 144 friend CreateImageBitmapFromBlobWorkerTask; 145 friend ImageBitmapShutdownObserver; 146 147 size_t GetAllocatedSize() const; 148 149 void OnShutdown(); 150 151 bool IsWriteOnly() const { return mWriteOnly; } 152 bool IsClosed() const { return !mData; }; 153 154 protected: 155 /* 156 * The default value of aIsPremultipliedAlpha is TRUE because that the 157 * data stored in HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, 158 * CanvasRenderingContext2D are alpha-premultiplied in default. 159 * 160 * Actually, if one HTMLCanvasElement's rendering context is WebGLContext, it 161 * is possible to get un-premultipliedAlpha data out. But, we do not do it in 162 * the CreateInternal(from HTMLCanvasElement) method. 163 * 164 * It is also possible to decode an image which is encoded with alpha channel 165 * to be non-premultipliedAlpha. This could be applied in 166 * 1) the CreateInternal(from HTMLImageElement) method (which might trigger 167 * re-decoding if the original decoded data is alpha-premultiplied) and 168 * 2) while decoding a blob. But we do not do it in both code path too. 169 * 170 * ImageData's underlying data is triggered as non-premultipliedAlpha, so set 171 * the aIsPremultipliedAlpha to be false in the 172 * CreateInternal(from ImageData) method. 173 */ 174 ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData, 175 bool aAllocatedImageData, bool aWriteOnly, 176 gfxAlphaType aAlphaType = gfxAlphaType::Premult); 177 178 virtual ~ImageBitmap(); 179 180 void SetPictureRect(const gfx::IntRect& aRect, ErrorResult& aRv); 181 182 void RemoveAssociatedMemory(); 183 184 static already_AddRefed<ImageBitmap> CreateImageBitmapInternal( 185 nsIGlobalObject* aGlobal, gfx::SourceSurface* aSurface, 186 const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions, 187 const bool aWriteOnly, const bool aAllocatedImageData, 188 const bool aMustCopy, const gfxAlphaType aAlphaType, ErrorResult& aRv); 189 190 static already_AddRefed<ImageBitmap> CreateInternal( 191 nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl, 192 const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions, 193 ErrorResult& aRv); 194 195 static already_AddRefed<ImageBitmap> CreateInternal( 196 nsIGlobalObject* aGlobal, SVGImageElement& aImageEl, 197 const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions, 198 ErrorResult& aRv); 199 200 static already_AddRefed<ImageBitmap> CreateInternal( 201 nsIGlobalObject* aGlobal, HTMLVideoElement& aVideoEl, 202 const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions, 203 ErrorResult& aRv); 204 205 static already_AddRefed<ImageBitmap> CreateInternal( 206 nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvasEl, 207 const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions, 208 ErrorResult& aRv); 209 210 static already_AddRefed<ImageBitmap> CreateInternal( 211 nsIGlobalObject* aGlobal, OffscreenCanvas& aOffscreenCanvas, 212 const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions, 213 ErrorResult& aRv); 214 215 static already_AddRefed<ImageBitmap> CreateInternal( 216 nsIGlobalObject* aGlobal, ImageData& aImageData, 217 const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions, 218 ErrorResult& aRv); 219 220 static already_AddRefed<ImageBitmap> CreateInternal( 221 nsIGlobalObject* aGlobal, CanvasRenderingContext2D& aCanvasCtx, 222 const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions, 223 ErrorResult& aRv); 224 225 static already_AddRefed<ImageBitmap> CreateInternal( 226 nsIGlobalObject* aGlobal, ImageBitmap& aImageBitmap, 227 const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions, 228 ErrorResult& aRv); 229 230 static already_AddRefed<ImageBitmap> CreateInternal( 231 nsIGlobalObject* aGlobal, VideoFrame& aVideoFrame, 232 const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions, 233 ErrorResult& aRv); 234 235 nsCOMPtr<nsIGlobalObject> mParent; 236 237 /* 238 * The mData is the data buffer of an ImageBitmap, so the mData must not be 239 * null. 240 * 241 * The mSurface is a cache for drawing the ImageBitmap onto a 242 * HTMLCanvasElement. The mSurface is null while the ImageBitmap is created 243 * and then will be initialized while the PrepareForDrawTarget() method is 244 * called first time. 245 * 246 * The mSurface might just be a reference to the same data buffer of the mData 247 * if the are of mPictureRect is just the same as the mData's size. Or, it is 248 * a independent data buffer which is copied and cropped form the mData's data 249 * buffer. 250 */ 251 RefPtr<layers::Image> mData; 252 RefPtr<gfx::SourceSurface> mSurface; 253 254 /* 255 * The mPictureRect is the size of the source image in default, however, if 256 * users specify the cropping area while creating an ImageBitmap, then this 257 * mPictureRect is the cropping area. 258 * 259 * Note that if the CreateInternal() copies and crops data from the source 260 * image, then this mPictureRect is just the size of the final mData. 261 * 262 * The mPictureRect will be used at PrepareForDrawTarget() while user is going 263 * to draw this ImageBitmap into a HTMLCanvasElement. 264 */ 265 gfx::IntRect mPictureRect; 266 267 gfxAlphaType mAlphaType; 268 269 RefPtr<SendShutdownToWorkerThread> mShutdownRunnable; 270 271 /* 272 * Whether this object allocated allocated and owns the image data. 273 */ 274 bool mAllocatedImageData; 275 276 /* 277 * Write-Only flag is set to true if this image has been generated from a 278 * cross-origin source. This is the opposite of what is called 'origin-clean' 279 * in the spec. 280 */ 281 bool mWriteOnly; 282 }; 283 284 size_t BindingJSObjectMallocBytes(ImageBitmap* aBitmap); 285 286 } // namespace dom 287 } // namespace mozilla 288 289 #endif // mozilla_dom_ImageBitmap_h