/*
 * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2013 Google Inc. 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 INC. AND ITS CONTRIBUTORS ``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 INC. OR ITS 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 "platform/graphics/GraphicsContext.h"

#include "platform/geometry/FloatRect.h"
#include "platform/geometry/FloatRoundedRect.h"
#include "platform/geometry/IntRect.h"
#include "platform/graphics/ColorSpace.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/Path.h"
#include "platform/graphics/paint/PaintController.h"
#include "platform/tracing/TraceEvent.h"
#include "platform/weborigin/KURL.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkAnnotation.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/effects/SkLumaColorFilter.h"
#include "third_party/skia/include/effects/SkPictureImageFilter.h"
#include "third_party/skia/include/pathops/SkPathOps.h"
#include "third_party/skia/include/utils/SkNullCanvas.h"
#include "wtf/Assertions.h"
#include "wtf/MathExtras.h"
#include <memory>

namespace blink {

GraphicsContext::GraphicsContext(PaintController& paintController,
                                 DisabledMode disableContextOrPainting,
                                 SkMetaData* metaData)
    : m_canvas(nullptr),
      m_paintController(paintController),
      m_paintStateStack(),
      m_paintStateIndex(0),
#if DCHECK_IS_ON()
      m_layerCount(0),
      m_disableDestructionChecks(false),
      m_inDrawingRecorder(false),
#endif
      m_disabledState(disableContextOrPainting),
      m_deviceScaleFactor(1.0f),
      m_printing(false),
      m_hasMetaData(!!metaData) {
  if (metaData)
    m_metaData = *metaData;

  // FIXME: Do some tests to determine how many states are typically used, and
  // allocate several here.
  m_paintStateStack.append(GraphicsContextState::create());
  m_paintState = m_paintStateStack.back().get();

  if (contextDisabled()) {
    DEFINE_STATIC_LOCAL(SkCanvas*, nullCanvas, (SkCreateNullCanvas()));
    m_canvas = nullCanvas;
  }
}

GraphicsContext::~GraphicsContext() {
#if DCHECK_IS_ON()
  if (!m_disableDestructionChecks) {
    ASSERT(!m_paintStateIndex);
    ASSERT(!m_paintState->saveCount());
    ASSERT(!m_layerCount);
    ASSERT(!saveCount());
  }
#endif
}

void GraphicsContext::save() {
  if (contextDisabled())
    return;

  m_paintState->incrementSaveCount();

  ASSERT(m_canvas);
  m_canvas->save();
}

void GraphicsContext::restore() {
  if (contextDisabled())
    return;

  if (!m_paintStateIndex && !m_paintState->saveCount()) {
    DLOG(ERROR) << "ERROR void GraphicsContext::restore() stack is empty";
    return;
  }

  if (m_paintState->saveCount()) {
    m_paintState->decrementSaveCount();
  } else {
    m_paintStateIndex--;
    m_paintState = m_paintStateStack[m_paintStateIndex].get();
  }

  ASSERT(m_canvas);
  m_canvas->restore();
}

#if ENABLE(ASSERT)
unsigned GraphicsContext::saveCount() const {
  // Each m_paintStateStack entry implies an additional save op
  // (on top of its own saveCount), except for the first frame.
  unsigned count = m_paintStateIndex;
  ASSERT(m_paintStateStack.size() > m_paintStateIndex);
  for (unsigned i = 0; i <= m_paintStateIndex; ++i)
    count += m_paintStateStack[i]->saveCount();

  return count;
}
#endif

void GraphicsContext::saveLayer(const SkRect* bounds, const SkPaint* paint) {
  if (contextDisabled())
    return;

  ASSERT(m_canvas);

  m_canvas->saveLayer(bounds, paint);
}

void GraphicsContext::restoreLayer() {
  if (contextDisabled())
    return;

  ASSERT(m_canvas);

  m_canvas->restore();
}

#if DCHECK_IS_ON()
void GraphicsContext::setInDrawingRecorder(bool val) {
  // Nested drawing recorers are not allowed.
  ASSERT(!val || !m_inDrawingRecorder);
  m_inDrawingRecorder = val;
}
#endif

void GraphicsContext::setShadow(
    const FloatSize& offset,
    float blur,
    const Color& color,
    DrawLooperBuilder::ShadowTransformMode shadowTransformMode,
    DrawLooperBuilder::ShadowAlphaMode shadowAlphaMode,
    ShadowMode shadowMode) {
  if (contextDisabled())
    return;

  DrawLooperBuilder drawLooperBuilder;
  if (!color.alpha()) {
    // When shadow-only but there is no shadow, we use an empty draw looper
    // to disable rendering of the source primitive.  When not shadow-only, we
    // clear the looper.
    setDrawLooper(shadowMode != DrawShadowOnly
                      ? nullptr
                      : drawLooperBuilder.detachDrawLooper());
    return;
  }

  drawLooperBuilder.addShadow(offset, blur, color, shadowTransformMode,
                              shadowAlphaMode);
  if (shadowMode == DrawShadowAndForeground) {
    drawLooperBuilder.addUnmodifiedContent();
  }
  setDrawLooper(drawLooperBuilder.detachDrawLooper());
}

void GraphicsContext::setDrawLooper(sk_sp<SkDrawLooper> drawLooper) {
  if (contextDisabled())
    return;

  mutableState()->setDrawLooper(std::move(drawLooper));
}

SkColorFilter* GraphicsContext::getColorFilter() const {
  return immutableState()->getColorFilter();
}

void GraphicsContext::setColorFilter(ColorFilter colorFilter) {
  GraphicsContextState* stateToSet = mutableState();

  // We only support one active color filter at the moment. If (when) this
  // becomes a problem, we should switch to using color filter chains (Skia work
  // in progress).
  DCHECK(!stateToSet->getColorFilter());
  stateToSet->setColorFilter(WebCoreColorFilterToSkiaColorFilter(colorFilter));
}

void GraphicsContext::concat(const SkMatrix& matrix) {
  if (contextDisabled())
    return;

  ASSERT(m_canvas);

  m_canvas->concat(matrix);
}

void GraphicsContext::beginLayer(float opacity,
                                 SkBlendMode xfermode,
                                 const FloatRect* bounds,
                                 ColorFilter colorFilter,
                                 sk_sp<SkImageFilter> imageFilter) {
  if (contextDisabled())
    return;

  SkPaint layerPaint;
  layerPaint.setAlpha(static_cast<unsigned char>(opacity * 255));
  layerPaint.setBlendMode(static_cast<SkBlendMode>(xfermode));
  layerPaint.setColorFilter(WebCoreColorFilterToSkiaColorFilter(colorFilter));
  layerPaint.setImageFilter(std::move(imageFilter));

  if (bounds) {
    SkRect skBounds = *bounds;
    saveLayer(&skBounds, &layerPaint);
  } else {
    saveLayer(nullptr, &layerPaint);
  }

#if DCHECK_IS_ON()
  ++m_layerCount;
#endif
}

void GraphicsContext::endLayer() {
  if (contextDisabled())
    return;

  restoreLayer();

  ASSERT(m_layerCount-- > 0);
}

void GraphicsContext::beginRecording(const FloatRect& bounds) {
  if (contextDisabled())
    return;

  m_canvas = m_pictureRecorder.beginRecording(bounds, nullptr);
  if (m_hasMetaData)
    skia::GetMetaData(*m_canvas) = m_metaData;
}

namespace {

sk_sp<SkPicture> createEmptyPicture() {
  SkPictureRecorder recorder;
  recorder.beginRecording(SkRect::MakeEmpty(), nullptr);
  return recorder.finishRecordingAsPicture();
}

}  // anonymous namespace

sk_sp<SkPicture> GraphicsContext::endRecording() {
  if (contextDisabled()) {
    // Clients expect endRecording() to always return a non-null picture.
    // Cache an empty SKP to minimize overhead when disabled.
    DEFINE_STATIC_LOCAL(sk_sp<SkPicture>, emptyPicture, (createEmptyPicture()));
    return emptyPicture;
  }

  sk_sp<SkPicture> picture = m_pictureRecorder.finishRecordingAsPicture();
  m_canvas = nullptr;
  ASSERT(picture);
  return picture;
}

void GraphicsContext::drawPicture(const SkPicture* picture) {
  if (contextDisabled() || !picture || picture->cullRect().isEmpty())
    return;

  ASSERT(m_canvas);
  m_canvas->drawPicture(picture);
}

void GraphicsContext::compositePicture(sk_sp<SkPicture> picture,
                                       const FloatRect& dest,
                                       const FloatRect& src,
                                       SkBlendMode op) {
  if (contextDisabled() || !picture)
    return;
  ASSERT(m_canvas);

  SkPaint picturePaint;
  picturePaint.setBlendMode(static_cast<SkBlendMode>(op));
  m_canvas->save();
  SkRect sourceBounds = src;
  SkRect skBounds = dest;
  SkMatrix pictureTransform;
  pictureTransform.setRectToRect(sourceBounds, skBounds,
                                 SkMatrix::kFill_ScaleToFit);
  m_canvas->concat(pictureTransform);
  picturePaint.setImageFilter(SkPictureImageFilter::MakeForLocalSpace(
      std::move(picture), sourceBounds,
      static_cast<SkFilterQuality>(imageInterpolationQuality())));
  m_canvas->saveLayer(&sourceBounds, &picturePaint);
  m_canvas->restore();
  m_canvas->restore();
}

void GraphicsContext::drawFocusRingPath(const SkPath& path,
                                        const Color& color,
                                        float width) {
  drawPlatformFocusRing(path, m_canvas, color.rgb(), width);
}

void GraphicsContext::drawFocusRingRect(const SkRect& rect,
                                        const Color& color,
                                        float width) {
  drawPlatformFocusRing(rect, m_canvas, color.rgb(), width);
}

void GraphicsContext::drawFocusRing(const Path& focusRingPath,
                                    float width,
                                    int offset,
                                    const Color& color) {
  // FIXME: Implement support for offset.
  if (contextDisabled())
    return;

  drawFocusRingPath(focusRingPath.getSkPath(), color, width);
}

void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects,
                                    float width,
                                    int offset,
                                    const Color& color) {
  if (contextDisabled())
    return;

  unsigned rectCount = rects.size();
  if (!rectCount)
    return;

  SkRegion focusRingRegion;
  offset = focusRingOffset(offset);
  for (unsigned i = 0; i < rectCount; i++) {
    SkIRect r = rects[i];
    if (r.isEmpty())
      continue;
    r.inset(-offset, -offset);
    focusRingRegion.op(r, SkRegion::kUnion_Op);
  }

  if (focusRingRegion.isEmpty())
    return;

  if (focusRingRegion.isRect()) {
    drawFocusRingRect(SkRect::Make(focusRingRegion.getBounds()), color, width);
  } else {
    SkPath path;
    if (focusRingRegion.getBoundaryPath(&path))
      drawFocusRingPath(path, color, width);
  }
}

static inline FloatRect areaCastingShadowInHole(const FloatRect& holeRect,
                                                float shadowBlur,
                                                float shadowSpread,
                                                const FloatSize& shadowOffset) {
  FloatRect bounds(holeRect);

  bounds.inflate(shadowBlur);

  if (shadowSpread < 0)
    bounds.inflate(-shadowSpread);

  FloatRect offsetBounds = bounds;
  offsetBounds.move(-shadowOffset);
  return unionRect(bounds, offsetBounds);
}

void GraphicsContext::drawInnerShadow(const FloatRoundedRect& rect,
                                      const Color& shadowColor,
                                      const FloatSize& shadowOffset,
                                      float shadowBlur,
                                      float shadowSpread,
                                      Edges clippedEdges) {
  if (contextDisabled())
    return;

  FloatRect holeRect(rect.rect());
  holeRect.inflate(-shadowSpread);

  if (holeRect.isEmpty()) {
    fillRoundedRect(rect, shadowColor);
    return;
  }

  if (clippedEdges & LeftEdge) {
    holeRect.move(-std::max(shadowOffset.width(), 0.0f) - shadowBlur, 0);
    holeRect.setWidth(holeRect.width() + std::max(shadowOffset.width(), 0.0f) +
                      shadowBlur);
  }
  if (clippedEdges & TopEdge) {
    holeRect.move(0, -std::max(shadowOffset.height(), 0.0f) - shadowBlur);
    holeRect.setHeight(holeRect.height() +
                       std::max(shadowOffset.height(), 0.0f) + shadowBlur);
  }
  if (clippedEdges & RightEdge)
    holeRect.setWidth(holeRect.width() - std::min(shadowOffset.width(), 0.0f) +
                      shadowBlur);
  if (clippedEdges & BottomEdge)
    holeRect.setHeight(holeRect.height() -
                       std::min(shadowOffset.height(), 0.0f) + shadowBlur);

  Color fillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(),
                  255);

  FloatRect outerRect = areaCastingShadowInHole(rect.rect(), shadowBlur,
                                                shadowSpread, shadowOffset);
  FloatRoundedRect roundedHole(holeRect, rect.getRadii());

  GraphicsContextStateSaver stateSaver(*this);
  if (rect.isRounded()) {
    clipRoundedRect(rect);
    if (shadowSpread < 0)
      roundedHole.expandRadii(-shadowSpread);
    else
      roundedHole.shrinkRadii(shadowSpread);
  } else {
    clip(rect.rect());
  }

  DrawLooperBuilder drawLooperBuilder;
  drawLooperBuilder.addShadow(FloatSize(shadowOffset), shadowBlur, shadowColor,
                              DrawLooperBuilder::ShadowRespectsTransforms,
                              DrawLooperBuilder::ShadowIgnoresAlpha);
  setDrawLooper(drawLooperBuilder.detachDrawLooper());
  fillRectWithRoundedHole(outerRect, roundedHole, fillColor);
}

void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  StrokeStyle penStyle = getStrokeStyle();
  if (penStyle == NoStroke)
    return;

  FloatPoint p1 = point1;
  FloatPoint p2 = point2;
  bool isVerticalLine = (p1.x() == p2.x());
  int width = roundf(strokeThickness());

  // We know these are vertical or horizontal lines, so the length will just
  // be the sum of the displacement component vectors give or take 1 -
  // probably worth the speed up of no square root, which also won't be exact.
  FloatSize disp = p2 - p1;
  int length = SkScalarRoundToInt(disp.width() + disp.height());
  SkPaint paint(immutableState()->strokePaint(length));

  if (getStrokeStyle() == DottedStroke || getStrokeStyle() == DashedStroke) {
    // Do a rect fill of our endpoints.  This ensures we always have the
    // appearance of being a border.  We then draw the actual dotted/dashed
    // line.
    SkRect r1, r2;
    r1.set(p1.x(), p1.y(), p1.x() + width, p1.y() + width);
    r2.set(p2.x(), p2.y(), p2.x() + width, p2.y() + width);

    if (isVerticalLine) {
      r1.offset(-width / 2, 0);
      r2.offset(-width / 2, -width);
    } else {
      r1.offset(0, -width / 2);
      r2.offset(-width, -width / 2);
    }
    SkPaint fillPaint;
    fillPaint.setColor(paint.getColor());
    drawRect(r1, fillPaint);
    drawRect(r2, fillPaint);
  }

  adjustLineToPixelBoundaries(p1, p2, width, penStyle);
  m_canvas->drawLine(p1.x(), p1.y(), p2.x(), p2.y(), paint);
}

void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt,
                                                float width,
                                                DocumentMarkerLineStyle style) {
  if (contextDisabled())
    return;

  // Use 2x resources for a device scale factor of 1.5 or above.
  int deviceScaleFactor = m_deviceScaleFactor > 1.5f ? 2 : 1;

  // Create the pattern we'll use to draw the underline.
  int index = style == DocumentMarkerGrammarLineStyle ? 1 : 0;
  static SkBitmap* misspellBitmap1x[2] = {0, 0};
  static SkBitmap* misspellBitmap2x[2] = {0, 0};
  SkBitmap** misspellBitmap =
      deviceScaleFactor == 2 ? misspellBitmap2x : misspellBitmap1x;
  if (!misspellBitmap[index]) {
#if OS(MACOSX)
    // Match the artwork used by the Mac.
    const int rowPixels = 4 * deviceScaleFactor;
    const int colPixels = 3 * deviceScaleFactor;
    SkBitmap bitmap;
    if (!bitmap.tryAllocN32Pixels(rowPixels, colPixels))
      return;

    bitmap.eraseARGB(0, 0, 0, 0);
    const uint32_t transparentColor = 0x00000000;

    if (deviceScaleFactor == 1) {
      const uint32_t colors[2][6] = {{0x2a2a0600, 0x57571000, 0xa8a81b00,
                                      0xbfbf1f00, 0x70701200, 0xe0e02400},
                                     {0x2a0f0f0f, 0x571e1e1e, 0xa83d3d3d,
                                      0xbf454545, 0x70282828, 0xe0515151}};

      // Pattern: a b a   a b a
      //          c d c   c d c
      //          e f e   e f e
      for (int x = 0; x < colPixels; ++x) {
        uint32_t* row = bitmap.getAddr32(0, x);
        row[0] = colors[index][x * 2];
        row[1] = colors[index][x * 2 + 1];
        row[2] = colors[index][x * 2];
        row[3] = transparentColor;
      }
    } else if (deviceScaleFactor == 2) {
      const uint32_t colors[2][18] = {
          {0x0a090101, 0x33320806, 0x55540f0a, 0x37360906, 0x6e6c120c,
           0x6e6c120c, 0x7674140d, 0x8d8b1810, 0x8d8b1810, 0x96941a11,
           0xb3b01f15, 0xb3b01f15, 0x6d6b130c, 0xd9d62619, 0xd9d62619,
           0x19180402, 0x7c7a150e, 0xcecb2418},
          {0x0a020202, 0x33141414, 0x55232323, 0x37161616, 0x6e2e2e2e,
           0x6e2e2e2e, 0x76313131, 0x8d3a3a3a, 0x8d3a3a3a, 0x963e3e3e,
           0xb34b4b4b, 0xb34b4b4b, 0x6d2d2d2d, 0xd95b5b5b, 0xd95b5b5b,
           0x19090909, 0x7c343434, 0xce575757}};

      // Pattern: a b c c b a
      //          d e f f e d
      //          g h j j h g
      //          k l m m l k
      //          n o p p o n
      //          q r s s r q
      for (int x = 0; x < colPixels; ++x) {
        uint32_t* row = bitmap.getAddr32(0, x);
        row[0] = colors[index][x * 3];
        row[1] = colors[index][x * 3 + 1];
        row[2] = colors[index][x * 3 + 2];
        row[3] = colors[index][x * 3 + 2];
        row[4] = colors[index][x * 3 + 1];
        row[5] = colors[index][x * 3];
        row[6] = transparentColor;
        row[7] = transparentColor;
      }
    } else
      ASSERT_NOT_REACHED();

    misspellBitmap[index] = new SkBitmap(bitmap);
#else
    // We use a 2-pixel-high misspelling indicator because that seems to be
    // what WebKit is designed for, and how much room there is in a typical
    // page for it.
    const int rowPixels =
        32 * deviceScaleFactor;  // Must be multiple of 4 for pattern below.
    const int colPixels = 2 * deviceScaleFactor;
    SkBitmap bitmap;
    if (!bitmap.tryAllocN32Pixels(rowPixels, colPixels))
      return;

    bitmap.eraseARGB(0, 0, 0, 0);
    if (deviceScaleFactor == 1)
      draw1xMarker(&bitmap, index);
    else if (deviceScaleFactor == 2)
      draw2xMarker(&bitmap, index);
    else
      ASSERT_NOT_REACHED();

    misspellBitmap[index] = new SkBitmap(bitmap);
#endif
  }

#if OS(MACOSX)
  SkScalar originX = WebCoreFloatToSkScalar(pt.x()) * deviceScaleFactor;
  SkScalar originY = WebCoreFloatToSkScalar(pt.y()) * deviceScaleFactor;

  // Make sure to draw only complete dots.
  int rowPixels = misspellBitmap[index]->width();
  float widthMod = fmodf(width * deviceScaleFactor, rowPixels);
  if (rowPixels - widthMod > deviceScaleFactor)
    width -= widthMod / deviceScaleFactor;
#else
  SkScalar originX = WebCoreFloatToSkScalar(pt.x());

  // Offset it vertically by 1 so that there's some space under the text.
  SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1;
  originX *= deviceScaleFactor;
  originY *= deviceScaleFactor;
#endif

  SkMatrix localMatrix;
  localMatrix.setTranslate(originX, originY);

  SkPaint paint;
  paint.setShader(SkShader::MakeBitmapShader(
      *misspellBitmap[index], SkShader::kRepeat_TileMode,
      SkShader::kRepeat_TileMode, &localMatrix));

  SkRect rect;
  rect.set(originX, originY,
           originX + WebCoreFloatToSkScalar(width) * deviceScaleFactor,
           originY + SkIntToScalar(misspellBitmap[index]->height()));

  if (deviceScaleFactor == 2) {
    save();
    scale(0.5, 0.5);
  }
  drawRect(rect, paint);
  if (deviceScaleFactor == 2)
    restore();
}

void GraphicsContext::drawLineForText(const FloatPoint& pt, float width) {
  if (contextDisabled())
    return;

  if (width <= 0)
    return;

  SkPaint paint;
  switch (getStrokeStyle()) {
    case NoStroke:
    case SolidStroke:
    case DoubleStroke: {
      int thickness = SkMax32(static_cast<int>(strokeThickness()), 1);
      SkRect r;
      r.fLeft = WebCoreFloatToSkScalar(pt.x());
      // Avoid anti-aliasing lines. Currently, these are always horizontal.
      // Round to nearest pixel to match text and other content.
      r.fTop = WebCoreFloatToSkScalar(floorf(pt.y() + 0.5f));
      r.fRight = r.fLeft + WebCoreFloatToSkScalar(width);
      r.fBottom = r.fTop + SkIntToScalar(thickness);
      paint = immutableState()->fillPaint();
      // Text lines are drawn using the stroke color.
      paint.setColor(strokeColor().rgb());
      drawRect(r, paint);
      return;
    }
    case DottedStroke:
    case DashedStroke: {
      int y = floorf(pt.y() + std::max<float>(strokeThickness() / 2.0f, 0.5f));
      drawLine(IntPoint(pt.x(), y), IntPoint(pt.x() + width, y));
      return;
    }
    case WavyStroke:
    default:
      break;
  }

  ASSERT_NOT_REACHED();
}

// Draws a filled rectangle with a stroked border.
void GraphicsContext::drawRect(const IntRect& rect) {
  if (contextDisabled())
    return;

  ASSERT(!rect.isEmpty());
  if (rect.isEmpty())
    return;

  SkRect skRect = rect;
  if (immutableState()->fillColor().alpha())
    drawRect(skRect, immutableState()->fillPaint());

  if (immutableState()->getStrokeData().style() != NoStroke &&
      immutableState()->strokeColor().alpha()) {
    // Stroke a width: 1 inset border
    SkPaint paint(immutableState()->fillPaint());
    paint.setColor(strokeColor().rgb());
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(1);

    skRect.inset(0.5f, 0.5f);
    drawRect(skRect, paint);
  }
}

void GraphicsContext::drawText(const Font& font,
                               const TextRunPaintInfo& runInfo,
                               const FloatPoint& point,
                               const SkPaint& paint) {
  if (contextDisabled())
    return;

  if (font.drawText(m_canvas, runInfo, point, m_deviceScaleFactor, paint))
    m_paintController.setTextPainted();
}

template <typename DrawTextFunc>
void GraphicsContext::drawTextPasses(const DrawTextFunc& drawText) {
  TextDrawingModeFlags modeFlags = textDrawingMode();

  if (modeFlags & TextModeFill) {
    drawText(immutableState()->fillPaint());
  }

  if ((modeFlags & TextModeStroke) && getStrokeStyle() != NoStroke &&
      strokeThickness() > 0) {
    SkPaint paintForStroking(immutableState()->strokePaint());
    if (modeFlags & TextModeFill) {
      paintForStroking.setLooper(
          0);  // shadow was already applied during fill pass
    }
    drawText(paintForStroking);
  }
}

void GraphicsContext::drawText(const Font& font,
                               const TextRunPaintInfo& runInfo,
                               const FloatPoint& point) {
  if (contextDisabled())
    return;

  drawTextPasses([&font, &runInfo, &point, this](const SkPaint& paint) {
    if (font.drawText(m_canvas, runInfo, point, m_deviceScaleFactor, paint))
      m_paintController.setTextPainted();
  });
}

void GraphicsContext::drawEmphasisMarks(const Font& font,
                                        const TextRunPaintInfo& runInfo,
                                        const AtomicString& mark,
                                        const FloatPoint& point) {
  if (contextDisabled())
    return;

  drawTextPasses([&font, &runInfo, &mark, &point, this](const SkPaint& paint) {
    font.drawEmphasisMarks(m_canvas, runInfo, mark, point, m_deviceScaleFactor,
                           paint);
  });
}

void GraphicsContext::drawBidiText(
    const Font& font,
    const TextRunPaintInfo& runInfo,
    const FloatPoint& point,
    Font::CustomFontNotReadyAction customFontNotReadyAction) {
  if (contextDisabled())
    return;

  drawTextPasses([&font, &runInfo, &point, customFontNotReadyAction,
                  this](const SkPaint& paint) {
    if (font.drawBidiText(m_canvas, runInfo, point, customFontNotReadyAction,
                          m_deviceScaleFactor, paint))
      m_paintController.setTextPainted();
  });
}

void GraphicsContext::drawHighlightForText(const Font& font,
                                           const TextRun& run,
                                           const FloatPoint& point,
                                           int h,
                                           const Color& backgroundColor,
                                           int from,
                                           int to) {
  if (contextDisabled())
    return;

  fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor);
}

void GraphicsContext::drawImage(
    Image* image,
    const FloatRect& dest,
    const FloatRect* srcPtr,
    SkBlendMode op,
    RespectImageOrientationEnum shouldRespectImageOrientation) {
  if (contextDisabled() || !image)
    return;

  const FloatRect src = srcPtr ? *srcPtr : image->rect();

  SkPaint imagePaint = immutableState()->fillPaint();
  imagePaint.setBlendMode(static_cast<SkBlendMode>(op));
  imagePaint.setColor(SK_ColorBLACK);
  imagePaint.setFilterQuality(computeFilterQuality(image, dest, src));
  imagePaint.setAntiAlias(shouldAntialias());
  image->draw(m_canvas, imagePaint, dest, src, shouldRespectImageOrientation,
              Image::ClampImageToSourceRect);
  m_paintController.setImagePainted();
}

void GraphicsContext::drawImageRRect(
    Image* image,
    const FloatRoundedRect& dest,
    const FloatRect& srcRect,
    SkBlendMode op,
    RespectImageOrientationEnum respectOrientation) {
  if (contextDisabled() || !image)
    return;

  if (!dest.isRounded()) {
    drawImage(image, dest.rect(), &srcRect, op, respectOrientation);
    return;
  }

  DCHECK(dest.isRenderable());

  const FloatRect visibleSrc = intersection(srcRect, image->rect());
  if (dest.isEmpty() || visibleSrc.isEmpty())
    return;

  SkPaint imagePaint = immutableState()->fillPaint();
  imagePaint.setBlendMode(static_cast<SkBlendMode>(op));
  imagePaint.setColor(SK_ColorBLACK);
  imagePaint.setFilterQuality(
      computeFilterQuality(image, dest.rect(), srcRect));
  imagePaint.setAntiAlias(shouldAntialias());

  bool useShader = (visibleSrc == srcRect) &&
                   (respectOrientation == DoNotRespectImageOrientation);
  if (useShader) {
    const SkMatrix localMatrix = SkMatrix::MakeRectToRect(
        visibleSrc, dest.rect(), SkMatrix::kFill_ScaleToFit);
    useShader = image->applyShader(imagePaint, localMatrix);
  }

  if (useShader) {
    // Shader-based fast path.
    m_canvas->drawRRect(dest, imagePaint);
  } else {
    // Clip-based fallback.
    SkAutoCanvasRestore autoRestore(m_canvas, true);
    m_canvas->clipRRect(dest, SkRegion::kIntersect_Op,
                        imagePaint.isAntiAlias());
    image->draw(m_canvas, imagePaint, dest.rect(), srcRect, respectOrientation,
                Image::ClampImageToSourceRect);
  }

  m_paintController.setImagePainted();
}

SkFilterQuality GraphicsContext::computeFilterQuality(
    Image* image,
    const FloatRect& dest,
    const FloatRect& src) const {
  InterpolationQuality resampling;
  if (printing()) {
    resampling = InterpolationNone;
  } else if (image->currentFrameIsLazyDecoded()) {
    resampling = InterpolationHigh;
  } else {
    resampling = computeInterpolationQuality(
        SkScalarToFloat(src.width()), SkScalarToFloat(src.height()),
        SkScalarToFloat(dest.width()), SkScalarToFloat(dest.height()),
        image->currentFrameIsComplete());

    if (resampling == InterpolationNone) {
      // FIXME: This is to not break tests (it results in the filter bitmap flag
      // being set to true). We need to decide if we respect InterpolationNone
      // being returned from computeInterpolationQuality.
      resampling = InterpolationLow;
    }
  }
  return static_cast<SkFilterQuality>(
      limitInterpolationQuality(*this, resampling));
}

void GraphicsContext::drawTiledImage(Image* image,
                                     const FloatRect& destRect,
                                     const FloatPoint& srcPoint,
                                     const FloatSize& tileSize,
                                     SkBlendMode op,
                                     const FloatSize& repeatSpacing) {
  if (contextDisabled() || !image)
    return;
  image->drawTiled(*this, destRect, srcPoint, tileSize, op, repeatSpacing);
  m_paintController.setImagePainted();
}

void GraphicsContext::drawTiledImage(Image* image,
                                     const FloatRect& dest,
                                     const FloatRect& srcRect,
                                     const FloatSize& tileScaleFactor,
                                     Image::TileRule hRule,
                                     Image::TileRule vRule,
                                     SkBlendMode op) {
  if (contextDisabled() || !image)
    return;

  if (hRule == Image::StretchTile && vRule == Image::StretchTile) {
    // Just do a scale.
    drawImage(image, dest, &srcRect, op);
    return;
  }

  image->drawTiled(*this, dest, srcRect, tileScaleFactor, hRule, vRule, op);
  m_paintController.setImagePainted();
}

void GraphicsContext::drawOval(const SkRect& oval, const SkPaint& paint) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  m_canvas->drawOval(oval, paint);
}

void GraphicsContext::drawPath(const SkPath& path, const SkPaint& paint) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  m_canvas->drawPath(path, paint);
}

void GraphicsContext::drawRect(const SkRect& rect, const SkPaint& paint) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  m_canvas->drawRect(rect, paint);
}

void GraphicsContext::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  m_canvas->drawRRect(rrect, paint);
}

void GraphicsContext::fillPath(const Path& pathToFill) {
  if (contextDisabled() || pathToFill.isEmpty())
    return;

  drawPath(pathToFill.getSkPath(), immutableState()->fillPaint());
}

void GraphicsContext::fillRect(const FloatRect& rect) {
  if (contextDisabled())
    return;

  drawRect(rect, immutableState()->fillPaint());
}

void GraphicsContext::fillRect(const FloatRect& rect,
                               const Color& color,
                               SkBlendMode xferMode) {
  if (contextDisabled())
    return;

  SkPaint paint = immutableState()->fillPaint();
  paint.setColor(color.rgb());
  paint.setBlendMode(xferMode);

  drawRect(rect, paint);
}

void GraphicsContext::fillRoundedRect(const FloatRoundedRect& rrect,
                                      const Color& color) {
  if (contextDisabled())
    return;

  if (!rrect.isRounded() || !rrect.isRenderable()) {
    fillRect(rrect.rect(), color);
    return;
  }

  if (color == fillColor()) {
    drawRRect(rrect, immutableState()->fillPaint());
    return;
  }

  SkPaint paint = immutableState()->fillPaint();
  paint.setColor(color.rgb());

  drawRRect(rrect, paint);
}

namespace {

bool isSimpleDRRect(const FloatRoundedRect& outer,
                    const FloatRoundedRect& inner) {
  // A DRRect is "simple" (i.e. can be drawn as a rrect stroke) if
  //   1) all sides have the same width
  const FloatSize strokeSize =
      inner.rect().minXMinYCorner() - outer.rect().minXMinYCorner();
  if (!WebCoreFloatNearlyEqual(strokeSize.aspectRatio(), 1) ||
      !WebCoreFloatNearlyEqual(strokeSize.width(),
                               outer.rect().maxX() - inner.rect().maxX()) ||
      !WebCoreFloatNearlyEqual(strokeSize.height(),
                               outer.rect().maxY() - inner.rect().maxY()))
    return false;

  // and
  //   2) the inner radii are not constrained
  const FloatRoundedRect::Radii& oRadii = outer.getRadii();
  const FloatRoundedRect::Radii& iRadii = inner.getRadii();
  if (!WebCoreFloatNearlyEqual(oRadii.topLeft().width() - strokeSize.width(),
                               iRadii.topLeft().width()) ||
      !WebCoreFloatNearlyEqual(oRadii.topLeft().height() - strokeSize.height(),
                               iRadii.topLeft().height()) ||
      !WebCoreFloatNearlyEqual(oRadii.topRight().width() - strokeSize.width(),
                               iRadii.topRight().width()) ||
      !WebCoreFloatNearlyEqual(oRadii.topRight().height() - strokeSize.height(),
                               iRadii.topRight().height()) ||
      !WebCoreFloatNearlyEqual(
          oRadii.bottomRight().width() - strokeSize.width(),
          iRadii.bottomRight().width()) ||
      !WebCoreFloatNearlyEqual(
          oRadii.bottomRight().height() - strokeSize.height(),
          iRadii.bottomRight().height()) ||
      !WebCoreFloatNearlyEqual(oRadii.bottomLeft().width() - strokeSize.width(),
                               iRadii.bottomLeft().width()) ||
      !WebCoreFloatNearlyEqual(
          oRadii.bottomLeft().height() - strokeSize.height(),
          iRadii.bottomLeft().height()))
    return false;

  // We also ignore DRRects with a very thick relative stroke (shapes which are
  // mostly filled by the stroke): Skia's stroke outline can diverge
  // significantly from the outer/inner contours in some edge cases, so we fall
  // back to drawDRRect() instead.
  const float kMaxStrokeToSizeRatio = 0.75f;
  if (2 * strokeSize.width() / outer.rect().width() > kMaxStrokeToSizeRatio ||
      2 * strokeSize.height() / outer.rect().height() > kMaxStrokeToSizeRatio)
    return false;

  return true;
}

}  // anonymous namespace

void GraphicsContext::fillDRRect(const FloatRoundedRect& outer,
                                 const FloatRoundedRect& inner,
                                 const Color& color) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  if (!isSimpleDRRect(outer, inner)) {
    if (color == fillColor()) {
      m_canvas->drawDRRect(outer, inner, immutableState()->fillPaint());
    } else {
      SkPaint paint(immutableState()->fillPaint());
      paint.setColor(color.rgb());
      m_canvas->drawDRRect(outer, inner, paint);
    }

    return;
  }

  // We can draw this as a stroked rrect.
  float strokeWidth = inner.rect().x() - outer.rect().x();
  SkRRect strokeRRect = outer;
  strokeRRect.inset(strokeWidth / 2, strokeWidth / 2);

  SkPaint strokePaint(immutableState()->fillPaint());
  strokePaint.setColor(color.rgb());
  strokePaint.setStyle(SkPaint::kStroke_Style);
  strokePaint.setStrokeWidth(strokeWidth);

  m_canvas->drawRRect(strokeRRect, strokePaint);
}

void GraphicsContext::fillEllipse(const FloatRect& ellipse) {
  if (contextDisabled())
    return;

  drawOval(ellipse, immutableState()->fillPaint());
}

void GraphicsContext::strokePath(const Path& pathToStroke) {
  if (contextDisabled() || pathToStroke.isEmpty())
    return;

  drawPath(pathToStroke.getSkPath(), immutableState()->strokePaint());
}

void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) {
  if (contextDisabled())
    return;

  SkPaint paint(immutableState()->strokePaint());
  paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth));
  // Reset the dash effect to account for the width
  immutableState()->getStrokeData().setupPaintDashPathEffect(&paint, 0);
  // strokerect has special rules for CSS when the rect is degenerate:
  // if width==0 && height==0, do nothing
  // if width==0 || height==0, then just draw line for the other dimension
  SkRect r(rect);
  bool validW = r.width() > 0;
  bool validH = r.height() > 0;
  if (validW && validH) {
    drawRect(r, paint);
  } else if (validW || validH) {
    // we are expected to respect the lineJoin, so we can't just call
    // drawLine -- we have to create a path that doubles back on itself.
    SkPath path;
    path.moveTo(r.fLeft, r.fTop);
    path.lineTo(r.fRight, r.fBottom);
    path.close();
    drawPath(path, paint);
  }
}

void GraphicsContext::strokeEllipse(const FloatRect& ellipse) {
  if (contextDisabled())
    return;

  drawOval(ellipse, immutableState()->strokePaint());
}

void GraphicsContext::clipRoundedRect(const FloatRoundedRect& rrect,
                                      SkRegion::Op regionOp,
                                      AntiAliasingMode shouldAntialias) {
  if (contextDisabled())
    return;

  if (!rrect.isRounded()) {
    clipRect(rrect.rect(), shouldAntialias, regionOp);
    return;
  }

  clipRRect(rrect, shouldAntialias, regionOp);
}

void GraphicsContext::clipOut(const Path& pathToClip) {
  if (contextDisabled())
    return;

  // Use const_cast and temporarily toggle the inverse fill type instead of
  // copying the path.
  SkPath& path = const_cast<SkPath&>(pathToClip.getSkPath());
  path.toggleInverseFillType();
  clipPath(path, AntiAliased);
  path.toggleInverseFillType();
}

void GraphicsContext::clipOutRoundedRect(const FloatRoundedRect& rect) {
  if (contextDisabled())
    return;

  clipRoundedRect(rect, SkRegion::kDifference_Op);
}

void GraphicsContext::clipRect(const SkRect& rect,
                               AntiAliasingMode aa,
                               SkRegion::Op op) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  m_canvas->clipRect(rect, op, aa == AntiAliased);
}

void GraphicsContext::clipPath(const SkPath& path,
                               AntiAliasingMode aa,
                               SkRegion::Op op) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  m_canvas->clipPath(path, op, aa == AntiAliased);
}

void GraphicsContext::clipRRect(const SkRRect& rect,
                                AntiAliasingMode aa,
                                SkRegion::Op op) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  m_canvas->clipRRect(rect, op, aa == AntiAliased);
}

void GraphicsContext::rotate(float angleInRadians) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  m_canvas->rotate(
      WebCoreFloatToSkScalar(angleInRadians * (180.0f / 3.14159265f)));
}

void GraphicsContext::translate(float x, float y) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  if (!x && !y)
    return;

  m_canvas->translate(WebCoreFloatToSkScalar(x), WebCoreFloatToSkScalar(y));
}

void GraphicsContext::scale(float x, float y) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  m_canvas->scale(WebCoreFloatToSkScalar(x), WebCoreFloatToSkScalar(y));
}

void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  sk_sp<SkData> url(SkData::MakeWithCString(link.getString().utf8().data()));
  SkAnnotateRectWithURL(m_canvas, destRect, url.get());
}

void GraphicsContext::setURLFragmentForRect(const String& destName,
                                            const IntRect& rect) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  sk_sp<SkData> skDestName(SkData::MakeWithCString(destName.utf8().data()));
  SkAnnotateLinkToDestination(m_canvas, rect, skDestName.get());
}

void GraphicsContext::setURLDestinationLocation(const String& name,
                                                const IntPoint& location) {
  if (contextDisabled())
    return;
  ASSERT(m_canvas);

  sk_sp<SkData> skName(SkData::MakeWithCString(name.utf8().data()));
  SkAnnotateNamedDestination(
      m_canvas, SkPoint::Make(location.x(), location.y()), skName.get());
}

void GraphicsContext::concatCTM(const AffineTransform& affine) {
  concat(affineTransformToSkMatrix(affine));
}

void GraphicsContext::fillRectWithRoundedHole(
    const FloatRect& rect,
    const FloatRoundedRect& roundedHoleRect,
    const Color& color) {
  if (contextDisabled())
    return;

  SkPaint paint(immutableState()->fillPaint());
  paint.setColor(color.rgb());
  m_canvas->drawDRRect(SkRRect::MakeRect(rect), roundedHoleRect, paint);
}

void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1,
                                                  FloatPoint& p2,
                                                  float strokeWidth,
                                                  StrokeStyle penStyle) {
  // For odd widths, we add in 0.5 to the appropriate x/y so that the float
  // arithmetic works out.  For example, with a border width of 3, WebKit will
  // pass us (y1+y2)/2, e.g., (50+53)/2 = 103/2 = 51 when we want 51.5.  It is
  // always true that an even width gave us a perfect position, but an odd width
  // gave us a position that is off by exactly 0.5.
  if (penStyle == DottedStroke || penStyle == DashedStroke) {
    if (p1.x() == p2.x()) {
      p1.setY(p1.y() + strokeWidth);
      p2.setY(p2.y() - strokeWidth);
    } else {
      p1.setX(p1.x() + strokeWidth);
      p2.setX(p2.x() - strokeWidth);
    }
  }

  if (static_cast<int>(strokeWidth) % 2) {  // odd
    if (p1.x() == p2.x()) {
      // We're a vertical line.  Adjust our x.
      p1.setX(p1.x() + 0.5f);
      p2.setX(p2.x() + 0.5f);
    } else {
      // We're a horizontal line. Adjust our y.
      p1.setY(p1.y() + 0.5f);
      p2.setY(p2.y() + 0.5f);
    }
  }
}

sk_sp<SkColorFilter> GraphicsContext::WebCoreColorFilterToSkiaColorFilter(
    ColorFilter colorFilter) {
  switch (colorFilter) {
    case ColorFilterLuminanceToAlpha:
      return SkLumaColorFilter::Make();
    case ColorFilterLinearRGBToSRGB:
      return ColorSpaceUtilities::createColorSpaceFilter(ColorSpaceLinearRGB,
                                                         ColorSpaceDeviceRGB);
    case ColorFilterSRGBToLinearRGB:
      return ColorSpaceUtilities::createColorSpaceFilter(ColorSpaceDeviceRGB,
                                                         ColorSpaceLinearRGB);
    case ColorFilterNone:
      break;
    default:
      ASSERT_NOT_REACHED();
      break;
  }

  return nullptr;
}

#if !OS(MACOSX)
void GraphicsContext::draw2xMarker(SkBitmap* bitmap, int index) {
  const SkPMColor lineColor = lineColors(index);
  const SkPMColor antiColor1 = antiColors1(index);
  const SkPMColor antiColor2 = antiColors2(index);

  uint32_t* row1 = bitmap->getAddr32(0, 0);
  uint32_t* row2 = bitmap->getAddr32(0, 1);
  uint32_t* row3 = bitmap->getAddr32(0, 2);
  uint32_t* row4 = bitmap->getAddr32(0, 3);

  // Pattern: X0o   o0X0o   o0
  //          XX0o o0XXX0o o0X
  //           o0XXX0o o0XXX0o
  //            o0X0o   o0X0o
  const SkPMColor row1Color[] = {lineColor, antiColor1, antiColor2, 0,
                                 0,         0,          antiColor2, antiColor1};
  const SkPMColor row2Color[] = {lineColor, lineColor,  antiColor1, antiColor2,
                                 0,         antiColor2, antiColor1, lineColor};
  const SkPMColor row3Color[] = {0,         antiColor2, antiColor1, lineColor,
                                 lineColor, lineColor,  antiColor1, antiColor2};
  const SkPMColor row4Color[] = {0,         0,          antiColor2, antiColor1,
                                 lineColor, antiColor1, antiColor2, 0};

  for (int x = 0; x < bitmap->width() + 8; x += 8) {
    int count = std::min(bitmap->width() - x, 8);
    if (count > 0) {
      memcpy(row1 + x, row1Color, count * sizeof(SkPMColor));
      memcpy(row2 + x, row2Color, count * sizeof(SkPMColor));
      memcpy(row3 + x, row3Color, count * sizeof(SkPMColor));
      memcpy(row4 + x, row4Color, count * sizeof(SkPMColor));
    }
  }
}

void GraphicsContext::draw1xMarker(SkBitmap* bitmap, int index) {
  const uint32_t lineColor = lineColors(index);
  const uint32_t antiColor = antiColors2(index);

  // Pattern: X o   o X o   o X
  //            o X o   o X o
  uint32_t* row1 = bitmap->getAddr32(0, 0);
  uint32_t* row2 = bitmap->getAddr32(0, 1);
  for (int x = 0; x < bitmap->width(); x++) {
    switch (x % 4) {
      case 0:
        row1[x] = lineColor;
        break;
      case 1:
        row1[x] = antiColor;
        row2[x] = antiColor;
        break;
      case 2:
        row2[x] = lineColor;
        break;
      case 3:
        row1[x] = antiColor;
        row2[x] = antiColor;
        break;
    }
  }
}

SkPMColor GraphicsContext::lineColors(int index) {
  static const SkPMColor colors[] = {
      SkPreMultiplyARGB(0xFF, 0xFF, 0x00, 0x00),  // Opaque red.
      SkPreMultiplyARGB(0xFF, 0xC0, 0xC0, 0xC0)   // Opaque gray.
  };

  return colors[index];
}

SkPMColor GraphicsContext::antiColors1(int index) {
  static const SkPMColor colors[] = {
      SkPreMultiplyARGB(0xB0, 0xFF, 0x00, 0x00),  // Semitransparent red.
      SkPreMultiplyARGB(0xB0, 0xC0, 0xC0, 0xC0)   // Semitransparent gray.
  };

  return colors[index];
}

SkPMColor GraphicsContext::antiColors2(int index) {
  static const SkPMColor colors[] = {
      SkPreMultiplyARGB(0x60, 0xFF, 0x00, 0x00),  // More transparent red
      SkPreMultiplyARGB(0x60, 0xC0, 0xC0, 0xC0)   // More transparent gray
  };

  return colors[index];
}
#endif

}  // namespace blink
