/*
 * 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/core/v8/ExceptionStatePlaceholder.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 inherit[] = "inherit";
static const char rtl[] = "rtl";
static const char ltr[] = "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()->antialiasedClips2dCanvasEnabled())
    m_clipAntialiasing = AntiAliased;
  setShouldAntialias(true);
  ThreadState::current()->registerPreFinalizer(this);
  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.first()
            .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);
  }
}

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() : LTR;
    case CanvasRenderingContext2DState::DirectionRTL:
      return RTL;
    case CanvasRenderingContext2DState::DirectionLTR:
      return LTR;
  }
  ASSERT_NOT_REACHED();
  return LTR;
}

String CanvasRenderingContext2D::direction() const {
  if (state().getDirection() == CanvasRenderingContext2DState::DirectionInherit)
    canvas()->document().updateStyleAndLayoutTreeForNode(canvas());
  return toTextDirection(state().getDirection(), canvas()) == RTL ? rtl : ltr;
}

void CanvasRenderingContext2D::setDirection(const String& directionString) {
  CanvasRenderingContext2DState::Direction direction;
  if (directionString == inherit)
    direction = CanvasRenderingContext2DState::DirectionInherit;
  else if (directionString == rtl)
    direction = CanvasRenderingContext2DState::DirectionRTL;
  else if (directionString == ltr)
    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 == RTL;
  bool override =
      computedStyle ? isOverride(computedStyle->unicodeBidi()) : 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
