ImageBitmap.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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. #ifndef mozilla_dom_ImageBitmap_h
  7. #define mozilla_dom_ImageBitmap_h
  8. #include "mozilla/Attributes.h"
  9. #include "mozilla/dom/ImageBitmapSource.h"
  10. #include "mozilla/dom/TypedArray.h"
  11. #include "mozilla/gfx/Rect.h"
  12. #include "mozilla/Maybe.h"
  13. #include "mozilla/UniquePtr.h"
  14. #include "CanvasRenderingContextHelper.h"
  15. #include "nsCycleCollectionParticipant.h"
  16. #include "nsIGlobalObject.h"
  17. struct JSContext;
  18. struct JSStructuredCloneReader;
  19. struct JSStructuredCloneWriter;
  20. class nsIGlobalObject;
  21. namespace mozilla {
  22. class ErrorResult;
  23. namespace gfx {
  24. class DataSourceSurface;
  25. class DrawTarget;
  26. class SourceSurface;
  27. }
  28. namespace layers {
  29. class Image;
  30. }
  31. namespace dom {
  32. class OffscreenCanvas;
  33. namespace workers {
  34. class WorkerStructuredCloneClosure;
  35. }
  36. class ArrayBufferViewOrArrayBuffer;
  37. class CanvasRenderingContext2D;
  38. struct ChannelPixelLayout;
  39. class CreateImageBitmapFromBlob;
  40. class CreateImageBitmapFromBlobTask;
  41. class CreateImageBitmapFromBlobWorkerTask;
  42. class File;
  43. class HTMLCanvasElement;
  44. class HTMLImageElement;
  45. class HTMLVideoElement;
  46. enum class ImageBitmapFormat : uint32_t;
  47. class ImageData;
  48. class ImageUtils;
  49. template<typename T> class MapDataIntoBufferSource;
  50. class Promise;
  51. class PostMessageEvent; // For StructuredClone between windows.
  52. struct ImageBitmapCloneData final
  53. {
  54. RefPtr<gfx::DataSourceSurface> mSurface;
  55. gfx::IntRect mPictureRect;
  56. bool mIsPremultipliedAlpha;
  57. bool mIsCroppingAreaOutSideOfSourceImage;
  58. bool mWriteOnly;
  59. };
  60. /*
  61. * ImageBitmap is an opaque handler to several kinds of image-like objects from
  62. * HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, ImageData to
  63. * CanvasRenderingContext2D and Image Blob.
  64. *
  65. * An ImageBitmap could be painted to a canvas element.
  66. *
  67. * Generally, an ImageBitmap only keeps a reference to its source object's
  68. * buffer, but if the source object is an ImageData, an Blob or a
  69. * HTMLCanvasElement with WebGL rendering context, the ImageBitmap copy the
  70. * source object's buffer.
  71. */
  72. class ImageBitmap final : public nsISupports,
  73. public nsWrapperCache
  74. {
  75. public:
  76. NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  77. NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ImageBitmap)
  78. nsCOMPtr<nsIGlobalObject> GetParentObject() const { return mParent; }
  79. virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
  80. uint32_t Width() const
  81. {
  82. return mPictureRect.Width();
  83. }
  84. uint32_t Height() const
  85. {
  86. return mPictureRect.Height();
  87. }
  88. void Close();
  89. /*
  90. * The PrepareForDrawTarget() might return null if the mPictureRect does not
  91. * intersect with the size of mData.
  92. */
  93. already_AddRefed<gfx::SourceSurface>
  94. PrepareForDrawTarget(gfx::DrawTarget* aTarget);
  95. /*
  96. * Transfer ownership of buffer to caller. So this function call
  97. * Close() implicitly.
  98. */
  99. already_AddRefed<layers::Image>
  100. TransferAsImage();
  101. UniquePtr<ImageBitmapCloneData>
  102. ToCloneData() const;
  103. static already_AddRefed<ImageBitmap>
  104. CreateFromCloneData(nsIGlobalObject* aGlobal, ImageBitmapCloneData* aData);
  105. static already_AddRefed<ImageBitmap>
  106. CreateFromOffscreenCanvas(nsIGlobalObject* aGlobal,
  107. OffscreenCanvas& aOffscreenCanvas,
  108. ErrorResult& aRv);
  109. static already_AddRefed<Promise>
  110. Create(nsIGlobalObject* aGlobal, const ImageBitmapSource& aSrc,
  111. const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
  112. static already_AddRefed<Promise>
  113. Create(nsIGlobalObject* aGlobal,
  114. const ImageBitmapSource& aBuffer,
  115. int32_t aOffset, int32_t aLength,
  116. mozilla::dom::ImageBitmapFormat aFormat,
  117. const Sequence<mozilla::dom::ChannelPixelLayout>& aLayout,
  118. ErrorResult& aRv);
  119. static JSObject*
  120. ReadStructuredClone(JSContext* aCx,
  121. JSStructuredCloneReader* aReader,
  122. nsIGlobalObject* aParent,
  123. const nsTArray<RefPtr<gfx::DataSourceSurface>>& aClonedSurfaces,
  124. uint32_t aIndex);
  125. static bool
  126. WriteStructuredClone(JSStructuredCloneWriter* aWriter,
  127. nsTArray<RefPtr<gfx::DataSourceSurface>>& aClonedSurfaces,
  128. ImageBitmap* aImageBitmap);
  129. // Mozilla Extensions
  130. static bool ExtensionsEnabled(JSContext* aCx, JSObject* aObj);
  131. friend CreateImageBitmapFromBlob;
  132. friend CreateImageBitmapFromBlobTask;
  133. friend CreateImageBitmapFromBlobWorkerTask;
  134. template<typename T>
  135. friend class MapDataIntoBufferSource;
  136. bool IsWriteOnly() const {
  137. return mWriteOnly;
  138. }
  139. // Mozilla Extensions
  140. ImageBitmapFormat
  141. FindOptimalFormat(const Optional<Sequence<ImageBitmapFormat>>& aPossibleFormats,
  142. ErrorResult& aRv);
  143. int32_t
  144. MappedDataLength(ImageBitmapFormat aFormat, ErrorResult& aRv);
  145. already_AddRefed<Promise>
  146. MapDataInto(JSContext* aCx,
  147. ImageBitmapFormat aFormat,
  148. const ArrayBufferViewOrArrayBuffer& aBuffer,
  149. int32_t aOffset, ErrorResult& aRv);
  150. protected:
  151. /*
  152. * The default value of aIsPremultipliedAlpha is TRUE because that the
  153. * data stored in HTMLImageElement, HTMLVideoElement, HTMLCanvasElement,
  154. * CanvasRenderingContext2D are alpha-premultiplied in default.
  155. *
  156. * Actually, if one HTMLCanvasElement's rendering context is WebGLContext, it
  157. * is possible to get un-premultipliedAlpha data out. But, we do not do it in
  158. * the CreateInternal(from HTMLCanvasElement) method.
  159. *
  160. * It is also possible to decode an image which is encoded with alpha channel
  161. * to be non-premultipliedAlpha. This could be applied in
  162. * 1) the CreateInternal(from HTMLImageElement) method (which might trigger
  163. * re-decoding if the original decoded data is alpha-premultiplied) and
  164. * 2) while decoding a blob. But we do not do it in both code path too.
  165. *
  166. * ImageData's underlying data is triggered as non-premultipliedAlpha, so set
  167. * the aIsPremultipliedAlpha to be false in the
  168. * CreateInternal(from ImageData) method.
  169. */
  170. ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData,
  171. bool aWriteOnly,
  172. bool aIsPremultipliedAlpha = true);
  173. virtual ~ImageBitmap();
  174. void SetPictureRect(const gfx::IntRect& aRect, ErrorResult& aRv);
  175. void SetIsCroppingAreaOutSideOfSourceImage(const gfx::IntSize& aSourceSize,
  176. const Maybe<gfx::IntRect>& aCroppingRect);
  177. static already_AddRefed<ImageBitmap>
  178. CreateInternal(nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl,
  179. const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
  180. static already_AddRefed<ImageBitmap>
  181. CreateInternal(nsIGlobalObject* aGlobal, HTMLVideoElement& aVideoEl,
  182. const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
  183. static already_AddRefed<ImageBitmap>
  184. CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvasEl,
  185. const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
  186. static already_AddRefed<ImageBitmap>
  187. CreateInternal(nsIGlobalObject* aGlobal, ImageData& aImageData,
  188. const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
  189. static already_AddRefed<ImageBitmap>
  190. CreateInternal(nsIGlobalObject* aGlobal, CanvasRenderingContext2D& aCanvasCtx,
  191. const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
  192. static already_AddRefed<ImageBitmap>
  193. CreateInternal(nsIGlobalObject* aGlobal, ImageBitmap& aImageBitmap,
  194. const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
  195. nsCOMPtr<nsIGlobalObject> mParent;
  196. /*
  197. * The mData is the data buffer of an ImageBitmap, so the mData must not be
  198. * null.
  199. *
  200. * The mSurface is a cache for drawing the ImageBitmap onto a
  201. * HTMLCanvasElement. The mSurface is null while the ImageBitmap is created
  202. * and then will be initialized while the PrepareForDrawTarget() method is
  203. * called first time.
  204. *
  205. * The mSurface might just be a reference to the same data buffer of the mData
  206. * if the are of mPictureRect is just the same as the mData's size. Or, it is
  207. * a independent data buffer which is copied and cropped form the mData's data
  208. * buffer.
  209. */
  210. RefPtr<layers::Image> mData;
  211. RefPtr<gfx::SourceSurface> mSurface;
  212. /*
  213. * This is used in the ImageBitmap-Extensions implementation.
  214. * ImageUtils is a wrapper to layers::Image, which add some common methods for
  215. * accessing the layers::Image's data.
  216. */
  217. UniquePtr<ImageUtils> mDataWrapper;
  218. /*
  219. * The mPictureRect is the size of the source image in default, however, if
  220. * users specify the cropping area while creating an ImageBitmap, then this
  221. * mPictureRect is the cropping area.
  222. *
  223. * Note that if the CreateInternal() copies and crops data from the source
  224. * image, then this mPictureRect is just the size of the final mData.
  225. *
  226. * The mPictureRect will be used at PrepareForDrawTarget() while user is going
  227. * to draw this ImageBitmap into a HTMLCanvasElement.
  228. */
  229. gfx::IntRect mPictureRect;
  230. const bool mIsPremultipliedAlpha;
  231. /*
  232. * Set mIsCroppingAreaOutSideOfSourceImage if image bitmap was cropped to the
  233. * source rectangle so that it contains any transparent black pixels (cropping
  234. * area is outside of the source image).
  235. * This is used in mapDataInto() to check if we should reject promise with
  236. * IndexSizeError.
  237. */
  238. bool mIsCroppingAreaOutSideOfSourceImage;
  239. /*
  240. * Write-Only flag is set to true if this image has been generated from a
  241. * cross-origin source. This is the opposite of what is called 'origin-clean'
  242. * in the spec.
  243. */
  244. bool mWriteOnly;
  245. };
  246. } // namespace dom
  247. } // namespace mozilla
  248. #endif // mozilla_dom_ImageBitmap_h