/*
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc.
 * All rights reserved.
 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
 * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved.
 * Copyright (C) 2013 Adobe Systems Incorporated. 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.
 */

#include "modules/canvas2d/CanvasRenderingContext2D.h"

#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/modules/v8/RenderingContext.h"
#include "core/CSSPropertyNames.h"
#include "core/css/StylePropertySet.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/AXObjectCache.h"
#include "core/dom/StyleEngine.h"
#include "core/events/Event.h"
#include "core/events/MouseEvent.h"
#include "core/frame/Settings.h"
#include "core/html/TextMetrics.h"
#include "core/html/canvas/CanvasFontCache.h"
#include "core/layout/HitTestCanvasResult.h"
#include "core/layout/LayoutBox.h"
#include "core/layout/LayoutTheme.h"
#include "modules/canvas2d/CanvasStyle.h"
#include "modules/canvas2d/HitRegion.h"
#include "modules/canvas2d/Path2D.h"
#include "platform/fonts/FontCache.h"
#include "platform/graphics/DrawLooperBuilder.h"
#include "platform/graphics/ExpensiveCanvasHeuristicParameters.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/StrokeData.h"
#include "platform/graphics/skia/SkiaUtils.h"
#include "platform/text/BidiTextRun.h"
#include "public/platform/Platform.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImageFilter.h"
#include "wtf/MathExtras.h"
#include "wtf/text/StringBuilder.h"
#include "wtf/typed_arrays/ArrayBufferContents.h"

namespace blink {

static const char defaultFont[] = "10px sans-serif";
static const char inheritDirectionString[] = "inherit";
static const char rtlDirectionString[] = "rtl";
static const char ltrDirectionString[] = "ltr";
static const double TryRestoreContextInterval = 0.5;
static const unsigned MaxTryRestoreContextAttempts = 4;
static const double cDeviceScaleFactor = 1.0;  // Canvas is device independent

static bool contextLostRestoredEventsEnabled() {
  return RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled();
}

// Drawing methods need to use this instead of SkAutoCanvasRestore in case
// overdraw detection substitutes the recording canvas (to discard overdrawn
// draw calls).
class CanvasRenderingContext2DAutoRestoreSkCanvas {
  STACK_ALLOCATED();

 public:
  explicit CanvasRenderingContext2DAutoRestoreSkCanvas(
      CanvasRenderingContext2D* context)
      : m_context(context), m_saveCount(0) {
    ASSERT(m_context);
    SkCanvas* c = m_context->drawingCanvas();
    if (c) {
      m_saveCount = c->getSaveCount();
    }
  }

  ~CanvasRenderingContext2DAutoRestoreSkCanvas() {
    SkCanvas* c = m_context->drawingCanvas();
    if (c)
      c->restoreToCount(m_saveCount);
    m_context->validateStateStack();
  }

 private:
  Member<CanvasRenderingContext2D> m_context;
  int m_saveCount;
};

CanvasRenderingContext2D::CanvasRenderingContext2D(
    HTMLCanvasElement* canvas,
    const CanvasContextCreationAttributes& attrs,
    Document& document)
    : CanvasRenderingContext(canvas, nullptr, attrs),
      m_contextLostMode(NotLostContext),
      m_contextRestorable(true),
      m_tryRestoreContextAttemptCount(0),
      m_dispatchContextLostEventTimer(
          this,
          &CanvasRenderingContext2D::dispatchContextLostEvent),
      m_dispatchContextRestoredEventTimer(
          this,
          &CanvasRenderingContext2D::dispatchContextRestoredEvent),
      m_tryRestoreContextEventTimer(
          this,
          &CanvasRenderingContext2D::tryRestoreContextEvent),
      m_pruneLocalFontCacheScheduled(false) {
  if (document.settings() &&
      document.settings()->getAntialiasedClips2dCanvasEnabled())
    m_clipAntialiasing = AntiAliased;
  setShouldAntialias(true);
  validateStateStack();
}

void CanvasRenderingContext2D::setCanvasGetContextResult(
    RenderingContext& result) {
  result.setCanvasRenderingContext2D(this);
}

CanvasRenderingContext2D::~CanvasRenderingContext2D() {}

void CanvasRenderingContext2D::dispose() {
  if (m_pruneLocalFontCacheScheduled)
    Platform::current()->currentThread()->removeTaskObserver(this);
}

void CanvasRenderingContext2D::validateStateStack() const {
#if DCHECK_IS_ON()
  if (SkCanvas* skCanvas = canvas()->existingDrawingCanvas()) {
    // The canvas should always have an initial save frame, to support
    // resetting the top level matrix and clip.
    DCHECK_GT(skCanvas->getSaveCount(), 1);

    if (m_contextLostMode == NotLostContext) {
      DCHECK_EQ(static_cast<size_t>(skCanvas->getSaveCount()),
                m_stateStack.size() + 1);
    }
  }
#endif
  CHECK(m_stateStack.front()
            .get());  // Temporary for investigating crbug.com/648510
}

bool CanvasRenderingContext2D::isAccelerated() const {
  if (!canvas()->hasImageBuffer())
    return false;
  return canvas()->buffer()->isAccelerated();
}

void CanvasRenderingContext2D::stop() {
  if (!isContextLost()) {
    // Never attempt to restore the context because the page is being torn down.
    loseContext(SyntheticLostContext);
  }
}

bool CanvasRenderingContext2D::isContextLost() const {
  return m_contextLostMode != NotLostContext;
}

void CanvasRenderingContext2D::loseContext(LostContextMode lostMode) {
  if (m_contextLostMode != NotLostContext)
    return;
  m_contextLostMode = lostMode;
  if (m_contextLostMode == SyntheticLostContext && canvas()) {
    canvas()->discardImageBuffer();
  }
  m_dispatchContextLostEventTimer.startOneShot(0, BLINK_FROM_HERE);
}

void CanvasRenderingContext2D::didSetSurfaceSize() {
  if (!m_contextRestorable)
    return;
  // This code path is for restoring from an eviction
  // Restoring from surface failure is handled internally
  ASSERT(m_contextLostMode != NotLostContext && !canvas()->hasImageBuffer());

  if (canvas()->buffer()) {
    if (contextLostRestoredEventsEnabled()) {
      m_dispatchContextRestoredEventTimer.startOneShot(0, BLINK_FROM_HERE);
    } else {
      // legacy synchronous context restoration.
      reset();
      m_contextLostMode = NotLostContext;
    }
  }
}

DEFINE_TRACE(CanvasRenderingContext2D) {
  visitor->trace(m_hitRegionManager);
  visitor->trace(m_filterOperations);
  CanvasRenderingContext::trace(visitor);
  BaseRenderingContext2D::trace(visitor);
  SVGResourceClient::trace(visitor);
}

void CanvasRenderingContext2D::dispatchContextLostEvent(TimerBase*) {
  if (canvas() && contextLostRestoredEventsEnabled()) {
    Event* event = Event::createCancelable(EventTypeNames::contextlost);
    canvas()->dispatchEvent(event);
    if (event->defaultPrevented()) {
      m_contextRestorable = false;
    }
  }

  // If RealLostContext, it means the context was not lost due to surface
  // failure but rather due to a an eviction, which means image buffer exists.
  if (m_contextRestorable && m_contextLostMode == RealLostContext) {
    m_tryRestoreContextAttemptCount = 0;
    m_tryRestoreContextEventTimer.startRepeating(TryRestoreContextInterval,
                                                 BLINK_FROM_HERE);
  }
}

void CanvasRenderingContext2D::tryRestoreContextEvent(TimerBase* timer) {
  if (m_contextLostMode == NotLostContext) {
    // Canvas was already restored (possibly thanks to a resize), so stop
    // trying.
    m_tryRestoreContextEventTimer.stop();
    return;
  }

  DCHECK(m_contextLostMode == RealLostContext);
  if (canvas()->hasImageBuffer() && canvas()->buffer()->restoreSurface()) {
    m_tryRestoreContextEventTimer.stop();
    dispatchContextRestoredEvent(nullptr);
  }

  if (++m_tryRestoreContextAttemptCount > MaxTryRestoreContextAttempts) {
    // final attempt: allocate a brand new image buffer instead of restoring
    canvas()->discardImageBuffer();
    m_tryRestoreContextEventTimer.stop();
    if (canvas()->buffer())
      dispatchContextRestoredEvent(nullptr);
  }
}

void CanvasRenderingContext2D::dispatchContextRestoredEvent(TimerBase*) {
  if (m_contextLostMode == NotLostContext)
    return;
  reset();
  m_contextLostMode = NotLostContext;
  if (contextLostRestoredEventsEnabled()) {
    Event* event(Event::create(EventTypeNames::contextrestored));
    canvas()->dispatchEvent(event);
  }
}

ColorBehavior CanvasRenderingContext2D::drawImageColorBehavior() const {
  return CanvasRenderingContext::colorBehaviorForMediaDrawnToCanvas();
}

void CanvasRenderingContext2D::reset() {
  // This is a multiple inherritance bootstrap
  BaseRenderingContext2D::reset();
}

void CanvasRenderingContext2D::restoreCanvasMatrixClipStack(SkCanvas* c) const {
  restoreMatrixClipStack(c);
}

bool CanvasRenderingContext2D::shouldAntialias() const {
  return state().shouldAntialias();
}

void CanvasRenderingContext2D::setShouldAntialias(bool doAA) {
  modifiableState().setShouldAntialias(doAA);
}

void CanvasRenderingContext2D::scrollPathIntoView() {
  scrollPathIntoViewInternal(m_path);
}

void CanvasRenderingContext2D::scrollPathIntoView(Path2D* path2d) {
  scrollPathIntoViewInternal(path2d->path());
}

void CanvasRenderingContext2D::scrollPathIntoViewInternal(const Path& path) {
  if (!state().isTransformInvertible() || path.isEmpty())
    return;

  canvas()->document().updateStyleAndLayoutIgnorePendingStylesheets();

  LayoutObject* renderer = canvas()->layoutObject();
  LayoutBox* layoutBox = canvas()->layoutBox();
  if (!renderer || !layoutBox)
    return;

  // Apply transformation and get the bounding rect
  Path transformedPath = path;
  transformedPath.transform(state().transform());
  FloatRect boundingRect = transformedPath.boundingRect();

  // Offset by the canvas rect
  LayoutRect pathRect(boundingRect);
  IntRect canvasRect = layoutBox->absoluteContentBox();
  pathRect.moveBy(canvasRect.location());

  renderer->scrollRectToVisible(pathRect, ScrollAlignment::alignCenterAlways,
                                ScrollAlignment::alignTopAlways);

  // TODO: should implement "inform the user" that the caret and/or
  // selection the specified rectangle of the canvas. See
  // http://crbug.com/357987
}

void CanvasRenderingContext2D::clearRect(double x,
                                         double y,
                                         double width,
                                         double height) {
  BaseRenderingContext2D::clearRect(x, y, width, height);

  if (m_hitRegionManager) {
    FloatRect rect(x, y, width, height);
    m_hitRegionManager->removeHitRegionsInRect(rect, state().transform());
  }
}

void CanvasRenderingContext2D::didDraw(const SkIRect& dirtyRect) {
  if (dirtyRect.isEmpty())
    return;

  if (ExpensiveCanvasHeuristicParameters::BlurredShadowsAreExpensive &&
      state().shouldDrawShadows() && state().shadowBlur() > 0) {
    ImageBuffer* buffer = canvas()->buffer();
    if (buffer)
      buffer->setHasExpensiveOp();
  }

  canvas()->didDraw(SkRect::Make(dirtyRect));
}

bool CanvasRenderingContext2D::stateHasFilter() {
  return state().hasFilter(canvas(), canvas()->size(), this);
}

sk_sp<SkImageFilter> CanvasRenderingContext2D::stateGetFilter() {
  return state().getFilter(canvas(), canvas()->size(), this);
}

void CanvasRenderingContext2D::snapshotStateForFilter() {
  // The style resolution required for fonts is not available in frame-less
  // documents.
  if (!canvas()->document().frame())
    return;

  modifiableState().setFontForFilter(accessFont());
}

SkCanvas* CanvasRenderingContext2D::drawingCanvas() const {
  if (isContextLost())
    return nullptr;
  return canvas()->drawingCanvas();
}

SkCanvas* CanvasRenderingContext2D::existingDrawingCanvas() const {
  return canvas()->existingDrawingCanvas();
}

void CanvasRenderingContext2D::disableDeferral(DisableDeferralReason reason) {
  canvas()->disableDeferral(reason);
}

AffineTransform CanvasRenderingContext2D::baseTransform() const {
  return canvas()->baseTransform();
}

String CanvasRenderingContext2D::font() const {
  if (!state().hasRealizedFont())
    return defaultFont;

  canvas()->document().canvasFontCache()->willUseCurrentFont();
  StringBuilder serializedFont;
  const FontDescription& fontDescription = state().font().getFontDescription();

  if (fontDescription.style() == FontStyleItalic)
    serializedFont.append("italic ");
  if (fontDescription.weight() == FontWeightBold)
    serializedFont.append("bold ");
  if (fontDescription.variantCaps() == FontDescription::SmallCaps)
    serializedFont.append("small-caps ");

  serializedFont.appendNumber(fontDescription.computedPixelSize());
  serializedFont.append("px");

  const FontFamily& firstFontFamily = fontDescription.family();
  for (const FontFamily* fontFamily = &firstFontFamily; fontFamily;
       fontFamily = fontFamily->next()) {
    if (fontFamily != &firstFontFamily)
      serializedFont.append(',');

    // FIXME: We should append family directly to serializedFont rather than
    // building a temporary string.
    String family = fontFamily->family();
    if (family.startsWith("-webkit-"))
      family = family.substring(8);
    if (family.contains(' '))
      family = "\"" + family + "\"";

    serializedFont.append(' ');
    serializedFont.append(family);
  }

  return serializedFont.toString();
}

void CanvasRenderingContext2D::setFont(const String& newFont) {
  // The style resolution required for fonts is not available in frame-less
  // documents.
  if (!canvas()->document().frame())
    return;

  canvas()->document().updateStyleAndLayoutTreeForNode(canvas());

  // The following early exit is dependent on the cache not being empty
  // because an empty cache may indicate that a style change has occured
  // which would require that the font be re-resolved. This check has to
  // come after the layout tree update to flush pending style changes.
  if (newFont == state().unparsedFont() && state().hasRealizedFont() &&
      m_fontsResolvedUsingCurrentStyle.size() > 0)
    return;

  CanvasFontCache* canvasFontCache = canvas()->document().canvasFontCache();

  // Map the <canvas> font into the text style. If the font uses keywords like
  // larger/smaller, these will work relative to the canvas.
  RefPtr<ComputedStyle> fontStyle;
  const ComputedStyle* computedStyle = canvas()->ensureComputedStyle();
  if (computedStyle) {
    HashMap<String, Font>::iterator i =
        m_fontsResolvedUsingCurrentStyle.find(newFont);
    if (i != m_fontsResolvedUsingCurrentStyle.end()) {
      ASSERT(m_fontLRUList.contains(newFont));
      m_fontLRUList.remove(newFont);
      m_fontLRUList.add(newFont);
      modifiableState().setFont(
          i->value, canvas()->document().styleEngine().fontSelector());
    } else {
      MutableStylePropertySet* parsedStyle =
          canvasFontCache->parseFont(newFont);
      if (!parsedStyle)
        return;
      fontStyle = ComputedStyle::create();
      FontDescription elementFontDescription(
          computedStyle->getFontDescription());
      // Reset the computed size to avoid inheriting the zoom factor from the
      // <canvas> element.
      elementFontDescription.setComputedSize(
          elementFontDescription.specifiedSize());
      fontStyle->setFontDescription(elementFontDescription);
      fontStyle->font().update(fontStyle->font().getFontSelector());
      canvas()->document().ensureStyleResolver().computeFont(fontStyle.get(),
                                                             *parsedStyle);
      m_fontsResolvedUsingCurrentStyle.add(newFont, fontStyle->font());
      ASSERT(!m_fontLRUList.contains(newFont));
      m_fontLRUList.add(newFont);
      pruneLocalFontCache(canvasFontCache->hardMaxFonts());  // hard limit
      schedulePruneLocalFontCacheIfNeeded();                 // soft limit
      modifiableState().setFont(
          fontStyle->font(), canvas()->document().styleEngine().fontSelector());
    }
  } else {
    Font resolvedFont;
    if (!canvasFontCache->getFontUsingDefaultStyle(newFont, resolvedFont))
      return;
    modifiableState().setFont(
        resolvedFont, canvas()->document().styleEngine().fontSelector());
  }

  // The parse succeeded.
  String newFontSafeCopy(newFont);  // Create a string copy since newFont can be
                                    // deleted inside realizeSaves.
  modifiableState().setUnparsedFont(newFontSafeCopy);
}

void CanvasRenderingContext2D::schedulePruneLocalFontCacheIfNeeded() {
  if (m_pruneLocalFontCacheScheduled)
    return;
  m_pruneLocalFontCacheScheduled = true;
  Platform::current()->currentThread()->addTaskObserver(this);
}

void CanvasRenderingContext2D::didProcessTask() {
  Platform::current()->currentThread()->removeTaskObserver(this);

  // This should be the only place where canvas() needs to be checked for
  // nullness because the circular refence with HTMLCanvasElement mean the
  // canvas and the context keep each other alive as long as the pair is
  // referenced the task observer is the only persisten refernce to this object
  // that is not traced, so didProcessTask() may be call at a time when the
  // canvas has been garbage collected but not the context.
  if (!canvas())
    return;

  // The rendering surface needs to be prepared now because it will be too late
  // to create a layer once we are in the paint invalidation phase.
  canvas()->prepareSurfaceForPaintingIfNeeded();

  pruneLocalFontCache(canvas()->document().canvasFontCache()->maxFonts());
  m_pruneLocalFontCacheScheduled = false;
}

void CanvasRenderingContext2D::pruneLocalFontCache(size_t targetSize) {
  if (targetSize == 0) {
    // Short cut: LRU does not matter when evicting everything
    m_fontLRUList.clear();
    m_fontsResolvedUsingCurrentStyle.clear();
    return;
  }
  while (m_fontLRUList.size() > targetSize) {
    m_fontsResolvedUsingCurrentStyle.remove(m_fontLRUList.first());
    m_fontLRUList.removeFirst();
  }
}

void CanvasRenderingContext2D::styleDidChange(const ComputedStyle* oldStyle,
                                              const ComputedStyle& newStyle) {
  if (oldStyle && oldStyle->font() == newStyle.font())
    return;
  pruneLocalFontCache(0);
}

TreeScope* CanvasRenderingContext2D::treeScope() {
  return &canvas()->treeScope();
}

void CanvasRenderingContext2D::clearFilterReferences() {
  m_filterOperations.removeClient(this);
  m_filterOperations.clear();
}

void CanvasRenderingContext2D::updateFilterReferences(
    const FilterOperations& filters) {
  clearFilterReferences();
  filters.addClient(this);
  m_filterOperations = filters;
}

void CanvasRenderingContext2D::resourceContentChanged() {
  resourceElementChanged();
}

void CanvasRenderingContext2D::resourceElementChanged() {
  clearFilterReferences();
  state().clearResolvedFilter();
}

bool CanvasRenderingContext2D::originClean() const {
  return canvas()->originClean();
}

void CanvasRenderingContext2D::setOriginTainted() {
  return canvas()->setOriginTainted();
}

int CanvasRenderingContext2D::width() const {
  return canvas()->width();
}

int CanvasRenderingContext2D::height() const {
  return canvas()->height();
}

bool CanvasRenderingContext2D::hasImageBuffer() const {
  return canvas()->hasImageBuffer();
}

ImageBuffer* CanvasRenderingContext2D::imageBuffer() const {
  return canvas()->buffer();
}

PassRefPtr<Image> blink::CanvasRenderingContext2D::getImage(
    AccelerationHint hint,
    SnapshotReason reason) const {
  if (!hasImageBuffer())
    return nullptr;
  return canvas()->buffer()->newImageSnapshot(hint, reason);
}

bool CanvasRenderingContext2D::parseColorOrCurrentColor(
    Color& color,
    const String& colorString) const {
  return ::blink::parseColorOrCurrentColor(color, colorString, canvas());
}

HitTestCanvasResult* CanvasRenderingContext2D::getControlAndIdIfHitRegionExists(
    const LayoutPoint& location) {
  if (hitRegionsCount() <= 0)
    return HitTestCanvasResult::create(String(), nullptr);

  LayoutBox* box = canvas()->layoutBox();
  FloatPoint localPos =
      box->absoluteToLocal(FloatPoint(location), UseTransforms);
  if (box->hasBorderOrPadding())
    localPos.move(-box->contentBoxOffset());
  localPos.scale(canvas()->width() / box->contentWidth(),
                 canvas()->height() / box->contentHeight());

  HitRegion* hitRegion = hitRegionAtPoint(localPos);
  if (hitRegion) {
    Element* control = hitRegion->control();
    if (control && canvas()->isSupportedInteractiveCanvasFallback(*control))
      return HitTestCanvasResult::create(hitRegion->id(), hitRegion->control());
    return HitTestCanvasResult::create(hitRegion->id(), nullptr);
  }
  return HitTestCanvasResult::create(String(), nullptr);
}

String CanvasRenderingContext2D::getIdFromControl(const Element* element) {
  if (hitRegionsCount() <= 0)
    return String();

  if (HitRegion* hitRegion = m_hitRegionManager->getHitRegionByControl(element))
    return hitRegion->id();
  return String();
}

String CanvasRenderingContext2D::textAlign() const {
  return textAlignName(state().getTextAlign());
}

void CanvasRenderingContext2D::setTextAlign(const String& s) {
  TextAlign align;
  if (!parseTextAlign(s, align))
    return;
  if (state().getTextAlign() == align)
    return;
  modifiableState().setTextAlign(align);
}

String CanvasRenderingContext2D::textBaseline() const {
  return textBaselineName(state().getTextBaseline());
}

void CanvasRenderingContext2D::setTextBaseline(const String& s) {
  TextBaseline baseline;
  if (!parseTextBaseline(s, baseline))
    return;
  if (state().getTextBaseline() == baseline)
    return;
  modifiableState().setTextBaseline(baseline);
}

static inline TextDirection toTextDirection(
    CanvasRenderingContext2DState::Direction direction,
    HTMLCanvasElement* canvas,
    const ComputedStyle** computedStyle = 0) {
  const ComputedStyle* style =
      (computedStyle ||
       direction == CanvasRenderingContext2DState::DirectionInherit)
          ? canvas->ensureComputedStyle()
          : nullptr;
  if (computedStyle)
    *computedStyle = style;
  switch (direction) {
    case CanvasRenderingContext2DState::DirectionInherit:
      return style ? style->direction() : TextDirection::kLtr;
    case CanvasRenderingContext2DState::DirectionRTL:
      return TextDirection::kRtl;
    case CanvasRenderingContext2DState::DirectionLTR:
      return TextDirection::kLtr;
  }
  ASSERT_NOT_REACHED();
  return TextDirection::kLtr;
}

String CanvasRenderingContext2D::direction() const {
  if (state().getDirection() == CanvasRenderingContext2DState::DirectionInherit)
    canvas()->document().updateStyleAndLayoutTreeForNode(canvas());
  return toTextDirection(state().getDirection(), canvas()) ==
                 TextDirection::kRtl
             ? rtlDirectionString
             : ltrDirectionString;
}

void CanvasRenderingContext2D::setDirection(const String& directionString) {
  CanvasRenderingContext2DState::Direction direction;
  if (directionString == inheritDirectionString)
    direction = CanvasRenderingContext2DState::DirectionInherit;
  else if (directionString == rtlDirectionString)
    direction = CanvasRenderingContext2DState::DirectionRTL;
  else if (directionString == ltrDirectionString)
    direction = CanvasRenderingContext2DState::DirectionLTR;
  else
    return;

  if (state().getDirection() == direction)
    return;

  modifiableState().setDirection(direction);
}

void CanvasRenderingContext2D::fillText(const String& text,
                                        double x,
                                        double y) {
  trackDrawCall(FillText);
  drawTextInternal(text, x, y, CanvasRenderingContext2DState::FillPaintType);
}

void CanvasRenderingContext2D::fillText(const String& text,
                                        double x,
                                        double y,
                                        double maxWidth) {
  trackDrawCall(FillText);
  drawTextInternal(text, x, y, CanvasRenderingContext2DState::FillPaintType,
                   &maxWidth);
}

void CanvasRenderingContext2D::strokeText(const String& text,
                                          double x,
                                          double y) {
  trackDrawCall(StrokeText);
  drawTextInternal(text, x, y, CanvasRenderingContext2DState::StrokePaintType);
}

void CanvasRenderingContext2D::strokeText(const String& text,
                                          double x,
                                          double y,
                                          double maxWidth) {
  trackDrawCall(StrokeText);
  drawTextInternal(text, x, y, CanvasRenderingContext2DState::StrokePaintType,
                   &maxWidth);
}

TextMetrics* CanvasRenderingContext2D::measureText(const String& text) {
  TextMetrics* metrics = TextMetrics::create();

  // The style resolution required for fonts is not available in frame-less
  // documents.
  if (!canvas()->document().frame())
    return metrics;

  canvas()->document().updateStyleAndLayoutTreeForNode(canvas());
  const Font& font = accessFont();
  const SimpleFontData* fontData = font.primaryFont();
  DCHECK(fontData);
  if (!fontData)
    return metrics;

  TextDirection direction;
  if (state().getDirection() == CanvasRenderingContext2DState::DirectionInherit)
    direction = determineDirectionality(text);
  else
    direction = toTextDirection(state().getDirection(), canvas());
  TextRun textRun(text, 0, 0, TextRun::AllowTrailingExpansion |
                                  TextRun::ForbidLeadingExpansion,
                  direction, false);
  textRun.setNormalizeSpace(true);
  FloatRect textBounds = font.selectionRectForText(
      textRun, FloatPoint(), font.getFontDescription().computedSize(), 0, -1,
      true);

  // x direction
  metrics->setWidth(font.width(textRun));
  metrics->setActualBoundingBoxLeft(-textBounds.x());
  metrics->setActualBoundingBoxRight(textBounds.maxX());

  // y direction
  const FontMetrics& fontMetrics = fontData->getFontMetrics();
  const float ascent = fontMetrics.floatAscent();
  const float descent = fontMetrics.floatDescent();
  const float baselineY = getFontBaseline(fontMetrics);

  metrics->setFontBoundingBoxAscent(ascent - baselineY);
  metrics->setFontBoundingBoxDescent(descent + baselineY);
  metrics->setActualBoundingBoxAscent(-textBounds.y() - baselineY);
  metrics->setActualBoundingBoxDescent(textBounds.maxY() + baselineY);

  // Note : top/bottom and ascend/descend are currently the same, so there's no
  // difference between the EM box's top and bottom and the font's ascend and
  // descend
  metrics->setEmHeightAscent(0);
  metrics->setEmHeightDescent(0);

  metrics->setHangingBaseline(0.8f * ascent - baselineY);
  metrics->setAlphabeticBaseline(-baselineY);
  metrics->setIdeographicBaseline(-descent - baselineY);
  return metrics;
}

void CanvasRenderingContext2D::drawTextInternal(
    const String& text,
    double x,
    double y,
    CanvasRenderingContext2DState::PaintType paintType,
    double* maxWidth) {
  // The style resolution required for fonts is not available in frame-less
  // documents.
  if (!canvas()->document().frame())
    return;

  // accessFont needs the style to be up to date, but updating style can cause
  // script to run, (e.g. due to autofocus) which can free the canvas (set size
  // to 0, for example), so update style before grabbing the drawingCanvas.
  canvas()->document().updateStyleAndLayoutTreeForNode(canvas());

  SkCanvas* c = drawingCanvas();
  if (!c)
    return;

  if (!std::isfinite(x) || !std::isfinite(y))
    return;
  if (maxWidth && (!std::isfinite(*maxWidth) || *maxWidth <= 0))
    return;

  // Currently, SkPictureImageFilter does not support subpixel text
  // anti-aliasing, which is expected when !creationAttributes().alpha(), so we
  // need to fall out of display list mode when drawing text to an opaque
  // canvas. crbug.com/583809
  if (!creationAttributes().alpha() && !isAccelerated())
    canvas()->disableDeferral(
        DisableDeferralReasonSubPixelTextAntiAliasingSupport);

  const Font& font = accessFont();
  font.getFontDescription().setSubpixelAscentDescent(true);
  const SimpleFontData* fontData = font.primaryFont();
  DCHECK(fontData);
  if (!fontData)
    return;
  const FontMetrics& fontMetrics = fontData->getFontMetrics();

  // FIXME: Need to turn off font smoothing.

  const ComputedStyle* computedStyle = 0;
  TextDirection direction =
      toTextDirection(state().getDirection(), canvas(), &computedStyle);
  bool isRTL = direction == TextDirection::kRtl;
  bool override =
      computedStyle ? isOverride(computedStyle->getUnicodeBidi()) : false;

  TextRun textRun(text, 0, 0, TextRun::AllowTrailingExpansion, direction,
                  override);
  textRun.setNormalizeSpace(true);
  // Draw the item text at the correct point.
  FloatPoint location(x, y + getFontBaseline(fontMetrics));
  double fontWidth = font.width(textRun);

  bool useMaxWidth = (maxWidth && *maxWidth < fontWidth);
  double width = useMaxWidth ? *maxWidth : fontWidth;

  TextAlign align = state().getTextAlign();
  if (align == StartTextAlign)
    align = isRTL ? RightTextAlign : LeftTextAlign;
  else if (align == EndTextAlign)
    align = isRTL ? LeftTextAlign : RightTextAlign;

  switch (align) {
    case CenterTextAlign:
      location.setX(location.x() - width / 2);
      break;
    case RightTextAlign:
      location.setX(location.x() - width);
      break;
    default:
      break;
  }

  // The slop built in to this mask rect matches the heuristic used in
  // FontCGWin.cpp for GDI text.
  TextRunPaintInfo textRunPaintInfo(textRun);
  textRunPaintInfo.bounds =
      FloatRect(location.x() - fontMetrics.height() / 2,
                location.y() - fontMetrics.ascent() - fontMetrics.lineGap(),
                width + fontMetrics.height(), fontMetrics.lineSpacing());
  if (paintType == CanvasRenderingContext2DState::StrokePaintType)
    inflateStrokeRect(textRunPaintInfo.bounds);

  CanvasRenderingContext2DAutoRestoreSkCanvas stateRestorer(this);
  if (useMaxWidth) {
    drawingCanvas()->save();
    drawingCanvas()->translate(location.x(), location.y());
    // We draw when fontWidth is 0 so compositing operations (eg, a "copy" op)
    // still work.
    drawingCanvas()->scale((fontWidth > 0 ? (width / fontWidth) : 0), 1);
    location = FloatPoint();
  }

  draw(
      [&font, this, &textRunPaintInfo, &location](
          SkCanvas* c, const SkPaint* paint)  // draw lambda
      {
        font.drawBidiText(c, textRunPaintInfo, location,
                          Font::UseFallbackIfFontNotReady, cDeviceScaleFactor,
                          *paint);
      },
      [](const SkIRect& rect)  // overdraw test lambda
      { return false; },
      textRunPaintInfo.bounds, paintType);
}

const Font& CanvasRenderingContext2D::accessFont() {
  if (!state().hasRealizedFont())
    setFont(state().unparsedFont());
  canvas()->document().canvasFontCache()->willUseCurrentFont();
  return state().font();
}

float CanvasRenderingContext2D::getFontBaseline(
    const FontMetrics& fontMetrics) const {
  // If the font is so tiny that the lroundf operations result in two
  // different types of text baselines to return the same baseline, use
  // floating point metrics (crbug.com/338908).
  // If you changed the heuristic here, for consistency please also change it
  // in SimpleFontData::platformInit().
  bool useFloatAscentDescent =
      fontMetrics.ascent() < 3 || fontMetrics.height() < 2;
  switch (state().getTextBaseline()) {
    case TopTextBaseline:
      return useFloatAscentDescent ? fontMetrics.floatAscent()
                                   : fontMetrics.ascent();
    case HangingTextBaseline:
      // According to
      // http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling
      // "FOP (Formatting Objects Processor) puts the hanging baseline at 80% of
      // the ascender height"
      return useFloatAscentDescent ? (fontMetrics.floatAscent() * 4.0) / 5.0
                                   : (fontMetrics.ascent() * 4) / 5;
    case BottomTextBaseline:
    case IdeographicTextBaseline:
      return useFloatAscentDescent ? -fontMetrics.floatDescent()
                                   : -fontMetrics.descent();
    case MiddleTextBaseline:
      return useFloatAscentDescent
                 ? -fontMetrics.floatDescent() + fontMetrics.floatHeight() / 2.0
                 : -fontMetrics.descent() + fontMetrics.height() / 2;
    case AlphabeticTextBaseline:
    default:
      // Do nothing.
      break;
  }
  return 0;
}

void CanvasRenderingContext2D::setIsHidden(bool hidden) {
  if (canvas()->hasImageBuffer())
    canvas()->buffer()->setIsHidden(hidden);
  if (hidden) {
    pruneLocalFontCache(0);
  }
}

bool CanvasRenderingContext2D::isTransformInvertible() const {
  return state().isTransformInvertible();
}

WebLayer* CanvasRenderingContext2D::platformLayer() const {
  return canvas()->buffer() ? canvas()->buffer()->platformLayer() : 0;
}

void CanvasRenderingContext2D::getContextAttributes(
    Canvas2DContextAttributes& attrs) const {
  attrs.setAlpha(creationAttributes().alpha());
  attrs.setColorSpace(colorSpaceAsString());
}

void CanvasRenderingContext2D::drawFocusIfNeeded(Element* element) {
  drawFocusIfNeededInternal(m_path, element);
}

void CanvasRenderingContext2D::drawFocusIfNeeded(Path2D* path2d,
                                                 Element* element) {
  drawFocusIfNeededInternal(path2d->path(), element);
}

void CanvasRenderingContext2D::drawFocusIfNeededInternal(const Path& path,
                                                         Element* element) {
  if (!focusRingCallIsValid(path, element))
    return;

  // Note: we need to check document->focusedElement() rather than just calling
  // element->focused(), because element->focused() isn't updated until after
  // focus events fire.
  if (element->document().focusedElement() == element) {
    scrollPathIntoViewInternal(path);
    drawFocusRing(path);
  }

  // Update its accessible bounds whether it's focused or not.
  updateElementAccessibility(path, element);
}

bool CanvasRenderingContext2D::focusRingCallIsValid(const Path& path,
                                                    Element* element) {
  ASSERT(element);
  if (!state().isTransformInvertible())
    return false;
  if (path.isEmpty())
    return false;
  if (!element->isDescendantOf(canvas()))
    return false;

  return true;
}

void CanvasRenderingContext2D::drawFocusRing(const Path& path) {
  m_usageCounters.numDrawFocusCalls++;
  if (!drawingCanvas())
    return;

  SkColor color = LayoutTheme::theme().focusRingColor().rgb();
  const int focusRingWidth = 5;

  drawPlatformFocusRing(path.getSkPath(), drawingCanvas(), color,
                        focusRingWidth);

  // We need to add focusRingWidth to dirtyRect.
  StrokeData strokeData;
  strokeData.setThickness(focusRingWidth);

  SkIRect dirtyRect;
  if (!computeDirtyRect(path.strokeBoundingRect(strokeData), &dirtyRect))
    return;

  didDraw(dirtyRect);
}

void CanvasRenderingContext2D::updateElementAccessibility(const Path& path,
                                                          Element* element) {
  element->document().updateStyleAndLayoutIgnorePendingStylesheets();
  AXObjectCache* axObjectCache = element->document().existingAXObjectCache();
  LayoutBoxModelObject* lbmo = canvas()->layoutBoxModelObject();
  LayoutObject* renderer = canvas()->layoutObject();
  if (!axObjectCache || !lbmo || !renderer)
    return;

  // Get the transformed path.
  Path transformedPath = path;
  transformedPath.transform(state().transform());

  // Add border and padding to the bounding rect.
  LayoutRect elementRect = enclosingLayoutRect(transformedPath.boundingRect());
  elementRect.move(lbmo->borderLeft() + lbmo->paddingLeft(),
                   lbmo->borderTop() + lbmo->paddingTop());

  // Update the accessible object.
  axObjectCache->setCanvasObjectBounds(canvas(), element, elementRect);
}

void CanvasRenderingContext2D::addHitRegion(const HitRegionOptions& options,
                                            ExceptionState& exceptionState) {
  if (options.id().isEmpty() && !options.control()) {
    exceptionState.throwDOMException(NotSupportedError,
                                     "Both id and control are null.");
    return;
  }

  if (options.control() &&
      !canvas()->isSupportedInteractiveCanvasFallback(*options.control())) {
    exceptionState.throwDOMException(NotSupportedError,
                                     "The control is neither null nor a "
                                     "supported interactive canvas fallback "
                                     "element.");
    return;
  }

  Path hitRegionPath = options.hasPath() ? options.path()->path() : m_path;

  SkCanvas* c = drawingCanvas();

  if (hitRegionPath.isEmpty() || !c || !state().isTransformInvertible() ||
      !c->getClipDeviceBounds(0)) {
    exceptionState.throwDOMException(NotSupportedError,
                                     "The specified path has no pixels.");
    return;
  }

  hitRegionPath.transform(state().transform());

  if (state().hasClip()) {
    hitRegionPath.intersectPath(state().getCurrentClipPath());
    if (hitRegionPath.isEmpty())
      exceptionState.throwDOMException(NotSupportedError,
                                       "The specified path has no pixels.");
  }

  if (!m_hitRegionManager)
    m_hitRegionManager = HitRegionManager::create();

  // Remove previous region (with id or control)
  m_hitRegionManager->removeHitRegionById(options.id());
  m_hitRegionManager->removeHitRegionByControl(options.control());

  HitRegion* hitRegion = HitRegion::create(hitRegionPath, options);
  Element* element = hitRegion->control();
  if (element && element->isDescendantOf(canvas()))
    updateElementAccessibility(hitRegion->path(), hitRegion->control());
  m_hitRegionManager->addHitRegion(hitRegion);
}

void CanvasRenderingContext2D::removeHitRegion(const String& id) {
  if (m_hitRegionManager)
    m_hitRegionManager->removeHitRegionById(id);
}

void CanvasRenderingContext2D::clearHitRegions() {
  if (m_hitRegionManager)
    m_hitRegionManager->removeAllHitRegions();
}

HitRegion* CanvasRenderingContext2D::hitRegionAtPoint(const FloatPoint& point) {
  if (m_hitRegionManager)
    return m_hitRegionManager->getHitRegionAtPoint(point);

  return nullptr;
}

unsigned CanvasRenderingContext2D::hitRegionsCount() const {
  if (m_hitRegionManager)
    return m_hitRegionManager->getHitRegionsCount();

  return 0;
}

bool CanvasRenderingContext2D::isAccelerationOptimalForCanvasContent() const {
  // Heuristic to determine if the GPU accelerated rendering pipeline is optimal
  // for performance based on past usage. It has a bias towards suggesting that
  // the accelerated pipeline is optimal.

  float acceleratedCost = estimateRenderingCost(
      ExpensiveCanvasHeuristicParameters::AcceleratedModeIndex);

  float recordingCost = estimateRenderingCost(
      ExpensiveCanvasHeuristicParameters::RecordingModeIndex);

  float costDifference = acceleratedCost - recordingCost;
  float percentCostReduction = costDifference / acceleratedCost * 100.0;
  float costDifferencePerFrame =
      costDifference / m_usageCounters.numFramesSinceReset;

  if (percentCostReduction >=
          ExpensiveCanvasHeuristicParameters::
              MinPercentageImprovementToSuggestDisableAcceleration &&
      costDifferencePerFrame >=
          ExpensiveCanvasHeuristicParameters::
              MinCostPerFrameImprovementToSuggestDisableAcceleration) {
    return false;
  }
  return true;
}

void CanvasRenderingContext2D::resetUsageTracking() {
  UsageCounters newCounters;
  m_usageCounters = newCounters;
}

}  // namespace blink
