Blame dom/canvas/ImageBitmap.h

Packit f0b94e
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
Packit f0b94e
/* vim:set ts=2 sw=2 sts=2 et cindent: */
Packit f0b94e
/* This Source Code Form is subject to the terms of the Mozilla Public
Packit f0b94e
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit f0b94e
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit f0b94e
Packit f0b94e
#ifndef mozilla_dom_ImageBitmap_h
Packit f0b94e
#define mozilla_dom_ImageBitmap_h
Packit f0b94e
Packit f0b94e
#include "mozilla/Attributes.h"
Packit f0b94e
#include "mozilla/dom/ImageBitmapSource.h"
Packit f0b94e
#include "mozilla/dom/TypedArray.h"
Packit f0b94e
#include "mozilla/gfx/Rect.h"
Packit f0b94e
#include "mozilla/Maybe.h"
Packit f0b94e
#include "mozilla/UniquePtr.h"
Packit f0b94e
#include "gfxTypes.h"  // for gfxAlphaType
Packit f0b94e
#include "nsCycleCollectionParticipant.h"
Packit f0b94e
Packit f0b94e
struct JSContext;
Packit f0b94e
struct JSStructuredCloneReader;
Packit f0b94e
struct JSStructuredCloneWriter;
Packit f0b94e
Packit f0b94e
class nsIGlobalObject;
Packit f0b94e
Packit f0b94e
namespace mozilla {
Packit f0b94e
Packit f0b94e
class ErrorResult;
Packit f0b94e
Packit f0b94e
namespace gfx {
Packit f0b94e
class DataSourceSurface;
Packit f0b94e
class DrawTarget;
Packit f0b94e
class SourceSurface;
Packit f0b94e
}  // namespace gfx
Packit f0b94e
Packit f0b94e
namespace layers {
Packit f0b94e
class Image;
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
namespace dom {
Packit f0b94e
class OffscreenCanvas;
Packit f0b94e
Packit f0b94e
class ArrayBufferViewOrArrayBuffer;
Packit f0b94e
class CanvasRenderingContext2D;
Packit f0b94e
struct ChannelPixelLayout;
Packit f0b94e
class CreateImageBitmapFromBlob;
Packit f0b94e
class CreateImageBitmapFromBlobTask;
Packit f0b94e
class CreateImageBitmapFromBlobWorkerTask;
Packit f0b94e
class File;
Packit f0b94e
class HTMLCanvasElement;
Packit f0b94e
class HTMLImageElement;
Packit f0b94e
class HTMLVideoElement;
Packit f0b94e
enum class ImageBitmapFormat : uint8_t;
Packit f0b94e
class ImageData;
Packit f0b94e
class ImageUtils;
Packit f0b94e
template <typename T>
Packit f0b94e
class MapDataIntoBufferSource;
Packit f0b94e
class Promise;
Packit f0b94e
class PostMessageEvent;  // For StructuredClone between windows.
Packit f0b94e
class ImageBitmapShutdownObserver;
Packit f0b94e
Packit f0b94e
struct ImageBitmapCloneData final {
Packit f0b94e
  RefPtr<gfx::DataSourceSurface> mSurface;
Packit f0b94e
  gfx::IntRect mPictureRect;
Packit f0b94e
  gfxAlphaType mAlphaType;
Packit f0b94e
  bool mIsCroppingAreaOutSideOfSourceImage;
Packit f0b94e
  bool mWriteOnly;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
/*
Packit f0b94e
 * ImageBitmap is an opaque handler to several kinds of image-like objects from
Packit f0b94e
 * HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, ImageData to
Packit f0b94e
 * CanvasRenderingContext2D and Image Blob.
Packit f0b94e
 *
Packit f0b94e
 * An ImageBitmap could be painted to a canvas element.
Packit f0b94e
 *
Packit f0b94e
 * Generally, an ImageBitmap only keeps a reference to its source object's
Packit f0b94e
 * buffer, but if the source object is an ImageData, an Blob or a
Packit f0b94e
 * HTMLCanvasElement with WebGL rendering context, the ImageBitmap copy the
Packit f0b94e
 * source object's buffer.
Packit f0b94e
 */
Packit f0b94e
class ImageBitmap final : public nsISupports, public nsWrapperCache {
Packit f0b94e
 public:
Packit f0b94e
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
Packit f0b94e
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ImageBitmap)
Packit f0b94e
Packit f0b94e
  nsCOMPtr<nsIGlobalObject> GetParentObject() const { return mParent; }
Packit f0b94e
Packit f0b94e
  virtual JSObject* WrapObject(JSContext* aCx,
Packit f0b94e
                               JS::Handle<JSObject*> aGivenProto) override;
Packit f0b94e
Packit f0b94e
  uint32_t Width() const { return mPictureRect.Width(); }
Packit f0b94e
Packit f0b94e
  uint32_t Height() const { return mPictureRect.Height(); }
Packit f0b94e
Packit f0b94e
  void Close();
Packit f0b94e
Packit f0b94e
  /*
Packit f0b94e
   * The PrepareForDrawTarget() might return null if the mPictureRect does not
Packit f0b94e
   * intersect with the size of mData.
Packit f0b94e
   */
Packit f0b94e
  already_AddRefed<gfx::SourceSurface> PrepareForDrawTarget(
Packit f0b94e
      gfx::DrawTarget* aTarget);
Packit f0b94e
Packit f0b94e
  /*
Packit f0b94e
   * Transfer ownership of buffer to caller. So this function call
Packit f0b94e
   * Close() implicitly.
Packit f0b94e
   */
Packit f0b94e
  already_AddRefed<layers::Image> TransferAsImage();
Packit f0b94e
Packit f0b94e
  UniquePtr<ImageBitmapCloneData> ToCloneData() const;
Packit f0b94e
Packit f0b94e
  static already_AddRefed<ImageBitmap> CreateFromCloneData(
Packit f0b94e
      nsIGlobalObject* aGlobal, ImageBitmapCloneData* aData);
Packit f0b94e
Packit f0b94e
  static already_AddRefed<ImageBitmap> CreateFromOffscreenCanvas(
Packit f0b94e
      nsIGlobalObject* aGlobal, OffscreenCanvas& aOffscreenCanvas,
Packit f0b94e
      ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  static already_AddRefed<Promise> Create(nsIGlobalObject* aGlobal,
Packit f0b94e
                                          const ImageBitmapSource& aSrc,
Packit f0b94e
                                          const Maybe<gfx::IntRect>& aCropRect,
Packit f0b94e
                                          ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  static already_AddRefed<Promise> Create(
Packit f0b94e
      nsIGlobalObject* aGlobal, const ImageBitmapSource& aBuffer,
Packit f0b94e
      int32_t aOffset, int32_t aLength, mozilla::dom::ImageBitmapFormat aFormat,
Packit f0b94e
      const Sequence<mozilla::dom::ChannelPixelLayout>& aLayout,
Packit f0b94e
      ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  static JSObject* ReadStructuredClone(
Packit f0b94e
      JSContext* aCx, JSStructuredCloneReader* aReader,
Packit f0b94e
      nsIGlobalObject* aParent,
Packit f0b94e
      const nsTArray<RefPtr<gfx::DataSourceSurface>>& aClonedSurfaces,
Packit f0b94e
      uint32_t aIndex);
Packit f0b94e
Packit f0b94e
  static bool WriteStructuredClone(
Packit f0b94e
      JSStructuredCloneWriter* aWriter,
Packit f0b94e
      nsTArray<RefPtr<gfx::DataSourceSurface>>& aClonedSurfaces,
Packit f0b94e
      ImageBitmap* aImageBitmap);
Packit f0b94e
Packit f0b94e
  friend CreateImageBitmapFromBlob;
Packit f0b94e
  friend CreateImageBitmapFromBlobTask;
Packit f0b94e
  friend CreateImageBitmapFromBlobWorkerTask;
Packit f0b94e
Packit f0b94e
  template <typename T>
Packit f0b94e
  friend class MapDataIntoBufferSource;
Packit f0b94e
Packit f0b94e
  // Mozilla Extensions
Packit f0b94e
  ImageBitmapFormat FindOptimalFormat(
Packit f0b94e
      const Optional<Sequence<ImageBitmapFormat>>& aPossibleFormats,
Packit f0b94e
      ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  int32_t MappedDataLength(ImageBitmapFormat aFormat, ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  already_AddRefed<Promise> MapDataInto(
Packit f0b94e
      JSContext* aCx, ImageBitmapFormat aFormat,
Packit f0b94e
      const ArrayBufferViewOrArrayBuffer& aBuffer, int32_t aOffset,
Packit f0b94e
      ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  size_t GetAllocatedSize() const;
Packit f0b94e
Packit f0b94e
  void OnShutdown();
Packit f0b94e
Packit f0b94e
  bool IsWriteOnly() const
Packit f0b94e
  {
Packit f0b94e
    return mWriteOnly;
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  /*
Packit f0b94e
   * The default value of aIsPremultipliedAlpha is TRUE because that the
Packit f0b94e
   * data stored in HTMLImageElement, HTMLVideoElement, HTMLCanvasElement,
Packit f0b94e
   * CanvasRenderingContext2D are alpha-premultiplied in default.
Packit f0b94e
   *
Packit f0b94e
   * Actually, if one HTMLCanvasElement's rendering context is WebGLContext, it
Packit f0b94e
   * is possible to get un-premultipliedAlpha data out. But, we do not do it in
Packit f0b94e
   * the CreateInternal(from HTMLCanvasElement) method.
Packit f0b94e
   *
Packit f0b94e
   * It is also possible to decode an image which is encoded with alpha channel
Packit f0b94e
   * to be non-premultipliedAlpha. This could be applied in
Packit f0b94e
   * 1) the CreateInternal(from HTMLImageElement) method (which might trigger
Packit f0b94e
   *    re-decoding if the original decoded data is alpha-premultiplied) and
Packit f0b94e
   * 2) while decoding a blob. But we do not do it in both code path too.
Packit f0b94e
   *
Packit f0b94e
   * ImageData's underlying data is triggered as non-premultipliedAlpha, so set
Packit f0b94e
   * the aIsPremultipliedAlpha to be false in the
Packit f0b94e
   * CreateInternal(from ImageData) method.
Packit f0b94e
   */
Packit f0b94e
  ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData,
Packit f0b94e
              bool aWriteOnly,
Packit f0b94e
              gfxAlphaType aAlphaType = gfxAlphaType::Premult);
Packit f0b94e
Packit f0b94e
  virtual ~ImageBitmap();
Packit f0b94e
Packit f0b94e
  void SetPictureRect(const gfx::IntRect& aRect, ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  void SetIsCroppingAreaOutSideOfSourceImage(
Packit f0b94e
      const gfx::IntSize& aSourceSize,
Packit f0b94e
      const Maybe<gfx::IntRect>& aCroppingRect);
Packit f0b94e
Packit f0b94e
  static already_AddRefed<ImageBitmap> CreateInternal(
Packit f0b94e
      nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl,
Packit f0b94e
      const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  static already_AddRefed<ImageBitmap> CreateInternal(
Packit f0b94e
      nsIGlobalObject* aGlobal, HTMLVideoElement& aVideoEl,
Packit f0b94e
      const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  static already_AddRefed<ImageBitmap> CreateInternal(
Packit f0b94e
      nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvasEl,
Packit f0b94e
      const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  static already_AddRefed<ImageBitmap> CreateInternal(
Packit f0b94e
      nsIGlobalObject* aGlobal, ImageData& aImageData,
Packit f0b94e
      const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  static already_AddRefed<ImageBitmap> CreateInternal(
Packit f0b94e
      nsIGlobalObject* aGlobal, CanvasRenderingContext2D& aCanvasCtx,
Packit f0b94e
      const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  static already_AddRefed<ImageBitmap> CreateInternal(
Packit f0b94e
      nsIGlobalObject* aGlobal, ImageBitmap& aImageBitmap,
Packit f0b94e
      const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv);
Packit f0b94e
Packit f0b94e
  nsCOMPtr<nsIGlobalObject> mParent;
Packit f0b94e
Packit f0b94e
  /*
Packit f0b94e
   * The mData is the data buffer of an ImageBitmap, so the mData must not be
Packit f0b94e
   * null.
Packit f0b94e
   *
Packit f0b94e
   * The mSurface is a cache for drawing the ImageBitmap onto a
Packit f0b94e
   * HTMLCanvasElement. The mSurface is null while the ImageBitmap is created
Packit f0b94e
   * and then will be initialized while the PrepareForDrawTarget() method is
Packit f0b94e
   * called first time.
Packit f0b94e
   *
Packit f0b94e
   * The mSurface might just be a reference to the same data buffer of the mData
Packit f0b94e
   * if the are of mPictureRect is just the same as the mData's size. Or, it is
Packit f0b94e
   * a independent data buffer which is copied and cropped form the mData's data
Packit f0b94e
   * buffer.
Packit f0b94e
   */
Packit f0b94e
  RefPtr<layers::Image> mData;
Packit f0b94e
  RefPtr<gfx::SourceSurface> mSurface;
Packit f0b94e
Packit f0b94e
  /*
Packit f0b94e
   * This is used in the ImageBitmap-Extensions implementation.
Packit f0b94e
   * ImageUtils is a wrapper to layers::Image, which add some common methods for
Packit f0b94e
   * accessing the layers::Image's data.
Packit f0b94e
   */
Packit f0b94e
  UniquePtr<ImageUtils> mDataWrapper;
Packit f0b94e
Packit f0b94e
  /*
Packit f0b94e
   * The mPictureRect is the size of the source image in default, however, if
Packit f0b94e
   * users specify the cropping area while creating an ImageBitmap, then this
Packit f0b94e
   * mPictureRect is the cropping area.
Packit f0b94e
   *
Packit f0b94e
   * Note that if the CreateInternal() copies and crops data from the source
Packit f0b94e
   * image, then this mPictureRect is just the size of the final mData.
Packit f0b94e
   *
Packit f0b94e
   * The mPictureRect will be used at PrepareForDrawTarget() while user is going
Packit f0b94e
   * to draw this ImageBitmap into a HTMLCanvasElement.
Packit f0b94e
   */
Packit f0b94e
  gfx::IntRect mPictureRect;
Packit f0b94e
Packit f0b94e
  const gfxAlphaType mAlphaType;
Packit f0b94e
Packit f0b94e
  RefPtr<ImageBitmapShutdownObserver> mShutdownObserver;
Packit f0b94e
Packit f0b94e
  /*
Packit f0b94e
   * Set mIsCroppingAreaOutSideOfSourceImage if image bitmap was cropped to the
Packit f0b94e
   * source rectangle so that it contains any transparent black pixels (cropping
Packit f0b94e
   * area is outside of the source image).
Packit f0b94e
   * This is used in mapDataInto() to check if we should reject promise with
Packit f0b94e
   * IndexSizeError.
Packit f0b94e
   */
Packit f0b94e
  bool mIsCroppingAreaOutSideOfSourceImage;
Packit f0b94e
Packit f0b94e
  /*
Packit f0b94e
   * Whether this object allocated allocated and owns the image data.
Packit f0b94e
   */
Packit f0b94e
  bool mAllocatedImageData;
Packit f0b94e
Packit f0b94e
  /*
Packit f0b94e
   * Write-Only flag is set to true if this image has been generated from a
Packit f0b94e
   * cross-origin source. This is the opposite of what is called 'origin-clean'
Packit f0b94e
   * in the spec.
Packit f0b94e
   */
Packit f0b94e
  bool mWriteOnly;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
}  // namespace dom
Packit f0b94e
}  // namespace mozilla
Packit f0b94e
Packit f0b94e
#endif  // mozilla_dom_ImageBitmap_h