/*
 * Copyright (C) 2004, 2006, 2009, 2010 Apple Inc. All rights reserved.
 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_HTML_CANVAS_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_HTML_CANVAS_ELEMENT_H_

#include <memory>

#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_blob_callback.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h"
#include "third_party/blink/renderer/core/html/canvas/image_encode_options.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_host.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types_3d.h"
#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h"
#include "third_party/blink/renderer/platform/graphics/surface_layer_bridge.h"
#include "third_party/blink/renderer/platform/heap/handle.h"

#define CanvasDefaultInterpolationQuality kInterpolationLow

namespace cc {
class Layer;
}

namespace blink {

class Canvas2DLayerBridge;
class CanvasContextCreationAttributesCore;
class CanvasDrawListener;
class CanvasRenderingContext;
class CanvasRenderingContextFactory;
class GraphicsContext;
class HitTestCanvasResult;
class HTMLCanvasElement;
class Image;
class ImageBitmapOptions;
class IntSize;

class
    CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContext;
typedef CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContext
    RenderingContext;

class CORE_EXPORT HTMLCanvasElement final
    : public HTMLElement,
      public ContextLifecycleObserver,
      public PageVisibilityObserver,
      public CanvasImageSource,
      public CanvasRenderingContextHost,
      public WebSurfaceLayerBridgeObserver,
      public ImageBitmapSource,
      public OffscreenCanvasPlaceholder {
  DEFINE_WRAPPERTYPEINFO();
  USING_GARBAGE_COLLECTED_MIXIN(HTMLCanvasElement);
  USING_PRE_FINALIZER(HTMLCanvasElement, Dispose);

 public:
  using Node::GetExecutionContext;

  DECLARE_NODE_FACTORY(HTMLCanvasElement);
  ~HTMLCanvasElement() override;

  // Attributes and functions exposed to script
  unsigned width() const { return Size().Width(); }
  unsigned height() const { return Size().Height(); }

  const IntSize& Size() const override { return size_; }

  void setWidth(unsigned, ExceptionState&);
  void setHeight(unsigned, ExceptionState&);

  void SetSize(const IntSize& new_size);

  // Called by Document::getCSSCanvasContext as well as above getContext().
  CanvasRenderingContext* GetCanvasRenderingContext(
      const String&,
      const CanvasContextCreationAttributesCore&);

  String toDataURL(const String& mime_type,
                   const ScriptValue& quality_argument,
                   ExceptionState&) const;
  String toDataURL(const String& mime_type,
                   ExceptionState& exception_state) const {
    return toDataURL(mime_type, ScriptValue(), exception_state);
  }

  void toBlob(V8BlobCallback*,
              const String& mime_type,
              const ScriptValue& quality_argument,
              ExceptionState&);
  void toBlob(V8BlobCallback* callback,
              const String& mime_type,
              ExceptionState& exception_state) {
    return toBlob(callback, mime_type, ScriptValue(), exception_state);
  }

  // Used for canvas capture.
  void AddListener(CanvasDrawListener*);
  void RemoveListener(CanvasDrawListener*);

  // Used for rendering
  void DidDraw(const FloatRect&) override;
  void DidDraw() override;

  void Paint(GraphicsContext&, const LayoutRect&);

  void DisableDeferral(DisableDeferralReason);

  CanvasRenderingContext* RenderingContext() const override {
    return context_.Get();
  }

  scoped_refptr<Image> CopiedImage(SourceDrawingBuffer, AccelerationHint);
  void ClearCopiedImage();

  bool OriginClean() const override;
  void SetOriginTainted() override { origin_clean_ = false; }

  bool IsAnimated2d() const;

  Canvas2DLayerBridge* GetCanvas2DLayerBridge() {
    return canvas2d_bridge_.get();
  }
  Canvas2DLayerBridge* GetOrCreateCanvas2DLayerBridge();

  void DiscardResourceProvider() override;

  FontSelector* GetFontSelector() override;

  bool ShouldBeDirectComposited() const;

  const AtomicString ImageSourceURL() const override;

  InsertionNotificationRequest InsertedInto(ContainerNode*) override;

  bool IsDirty() { return !dirty_rect_.IsEmpty(); }

  void DoDeferredPaintInvalidation();

  void FinalizeFrame() override;

  // ContextLifecycleObserver and PageVisibilityObserver implementation
  void ContextDestroyed(ExecutionContext*) override;

  // PageVisibilityObserver implementation
  void PageVisibilityChanged() override;

  // CanvasImageSource implementation
  scoped_refptr<Image> GetSourceImageForCanvas(SourceImageStatus*,
                                               AccelerationHint,
                                               const FloatSize&) override;
  bool WouldTaintOrigin(const SecurityOrigin*) const override;
  FloatSize ElementSize(const FloatSize&) const override;
  bool IsCanvasElement() const override { return true; }
  bool IsOpaque() const override;
  bool IsAccelerated() const override;

  // SurfaceLayerBridgeObserver implementation
  void OnWebLayerUpdated() override;
  void RegisterContentsLayer(cc::Layer*) override;
  void UnregisterContentsLayer(cc::Layer*) override;

  // CanvasResourceHost implementation
  void NotifyGpuContextLost() override;
  void SetNeedsCompositingUpdate() override;
  void UpdateMemoryUsage() override;

  void DisableAcceleration(std::unique_ptr<Canvas2DLayerBridge>
                               unaccelerated_bridge_used_for_testing = nullptr);

  // ImageBitmapSource implementation
  IntSize BitmapSourceSize() const override;
  ScriptPromise CreateImageBitmap(ScriptState*,
                                  EventTarget&,
                                  base::Optional<IntRect> crop_rect,
                                  const ImageBitmapOptions&) override;

  // OffscreenCanvasPlaceholder implementation.
  void SetPlaceholderFrame(scoped_refptr<CanvasResource>,
                           base::WeakPtr<OffscreenCanvasFrameDispatcher>,
                           scoped_refptr<base::SingleThreadTaskRunner>,
                           unsigned resource_id) override;
  void Trace(blink::Visitor*) override;

  void SetCanvas2DLayerBridgeForTesting(std::unique_ptr<Canvas2DLayerBridge>,
                                        const IntSize&);

  static void RegisterRenderingContextFactory(
      std::unique_ptr<CanvasRenderingContextFactory>);

  void StyleDidChange(const ComputedStyle* old_style,
                      const ComputedStyle& new_style);

  void NotifyListenersCanvasChanged();

  // For Canvas HitRegions
  bool IsSupportedInteractiveCanvasFallback(const Element&);
  HitTestCanvasResult* GetControlAndIdIfHitRegionExists(const LayoutPoint&);
  String GetIdFromControl(const Element*);

  // For OffscreenCanvas that controls this html canvas element
  ::blink::SurfaceLayerBridge* SurfaceLayerBridge() const {
    return surface_layer_bridge_.get();
  }
  void CreateLayer();

  void DetachContext() override { context_ = nullptr; }

  void WillDrawImageTo2DContext(CanvasImageSource*);

  ExecutionContext* GetTopExecutionContext() const override {
    return GetDocument().GetExecutionContext();
  }

  const KURL& GetExecutionContextUrl() const override {
    return GetDocument().TopDocument().Url();
  }

  DispatchEventResult HostDispatchEvent(Event* event) override {
    return DispatchEvent(event);
  }

  bool IsWebGL1Enabled() const override;
  bool IsWebGL2Enabled() const override;
  bool IsWebGLBlocked() const override;
  void SetContextCreationWasBlocked() override {
    context_creation_was_blocked_ = true;
  }

  // Memory Management
  static intptr_t GetGlobalGPUMemoryUsage() { return global_gpu_memory_usage_; }
  static unsigned GetGlobalAcceleratedContextCount() {
    return global_accelerated_context_count_;
  }
  intptr_t GetGPUMemoryUsage() { return gpu_memory_usage_; }
  void DidInvokeGPUReadbackInCurrentFrame() {
    gpu_readback_invoked_in_current_frame_ = true;
  }

  bool NeedsUnbufferedInputEvents() const { return needs_unbuffered_input_; }

  void SetNeedsUnbufferedInputEvents(bool value) {
    needs_unbuffered_input_ = value;
  }

  bool LowLatencyEnabled() const { return !!frame_dispatcher_; }

 protected:
  void DidMoveToNewDocument(Document& old_document) override;

 private:
  explicit HTMLCanvasElement(Document&);
  void Dispose();

  using ContextFactoryVector =
      Vector<std::unique_ptr<CanvasRenderingContextFactory>>;
  static ContextFactoryVector& RenderingContextFactories();
  static CanvasRenderingContextFactory* GetRenderingContextFactory(int);

  enum AccelerationCriteria {
    kNormalAccelerationCriteria,
    kIgnoreResourceLimitCriteria,
  };
  bool ShouldAccelerate(AccelerationCriteria) const;

  void ParseAttribute(const AttributeModificationParams&) override;
  LayoutObject* CreateLayoutObject(const ComputedStyle&) override;
  bool AreAuthorShadowsAllowed() const override { return false; }

  void Reset();

  std::unique_ptr<Canvas2DLayerBridge> CreateAccelerated2dBuffer(
      int* msaa_sample_count);
  std::unique_ptr<Canvas2DLayerBridge> CreateUnaccelerated2dBuffer();
  void SetCanvas2DLayerBridgeInternal(std::unique_ptr<Canvas2DLayerBridge>);

  void SetSurfaceSize(const IntSize&);

  bool PaintsIntoCanvasBuffer() const;

  scoped_refptr<StaticBitmapImage> ToStaticBitmapImage(SourceDrawingBuffer,
                                                       AccelerationHint) const;

  String ToDataURLInternal(const String& mime_type,
                           const double& quality,
                           SourceDrawingBuffer) const;

  // Returns true if the canvas' context type is inherited from
  // ImageBitmapRenderingContextBase.
  bool HasImageBitmapContext() const;

  HeapHashSet<WeakMember<CanvasDrawListener>> listeners_;

  IntSize size_;

  TraceWrapperMember<CanvasRenderingContext> context_;
  // Used only for WebGL currently.
  bool context_creation_was_blocked_;

  bool ignore_reset_;
  FloatRect dirty_rect_;

  bool origin_clean_;
  bool needs_unbuffered_input_ = false;

  // It prevents repeated attempts in allocating resources after the first
  // attempt failed.
  bool HasResourceProvider() {
    return canvas2d_bridge_ || !!CanvasResourceHost::ResourceProvider();
  }

  // Canvas2DLayerBridge is used when canvas has 2d rendering context
  std::unique_ptr<Canvas2DLayerBridge> canvas2d_bridge_;
  void ReplaceExisting2dLayerBridge(std::unique_ptr<Canvas2DLayerBridge>);

  // FIXME: This is temporary for platforms that have to copy the image buffer
  // to render (and for CSSCanvasValue).
  mutable scoped_refptr<Image> copied_image_;

  // Used for OffscreenCanvas that controls this HTML canvas element
  // and for low latency mode.
  std::unique_ptr<::blink::SurfaceLayerBridge> surface_layer_bridge_;

  // Used for low latency mode.
  // TODO: rename to CanvasFrameDispatcher.
  std::unique_ptr<OffscreenCanvasFrameDispatcher> frame_dispatcher_;

  bool did_notify_listeners_for_current_frame_ = false;

  // GPU Memory Management
  static intptr_t global_gpu_memory_usage_;
  static unsigned global_accelerated_context_count_;
  mutable intptr_t gpu_memory_usage_;
  mutable intptr_t externally_allocated_memory_;

  mutable bool gpu_readback_invoked_in_current_frame_;
  int gpu_readback_successive_frames_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_HTML_CANVAS_ELEMENT_H_
