/*
 * Copyright (c) 2006,2007,2008, 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER 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 "platform/graphics/skia/SkiaUtils.h"

#include "platform/graphics/GraphicsContext.h"
#include "third_party/skia/include/effects/SkCornerPathEffect.h"

namespace blink {

static const struct CompositOpToXfermodeMode {
  CompositeOperator mCompositOp;
  SkXfermode::Mode m_xfermodeMode;
} gMapCompositOpsToXfermodeModes[] = {
    {CompositeClear, SkXfermode::kClear_Mode},
    {CompositeCopy, SkXfermode::kSrc_Mode},
    {CompositeSourceOver, SkXfermode::kSrcOver_Mode},
    {CompositeSourceIn, SkXfermode::kSrcIn_Mode},
    {CompositeSourceOut, SkXfermode::kSrcOut_Mode},
    {CompositeSourceAtop, SkXfermode::kSrcATop_Mode},
    {CompositeDestinationOver, SkXfermode::kDstOver_Mode},
    {CompositeDestinationIn, SkXfermode::kDstIn_Mode},
    {CompositeDestinationOut, SkXfermode::kDstOut_Mode},
    {CompositeDestinationAtop, SkXfermode::kDstATop_Mode},
    {CompositeXOR, SkXfermode::kXor_Mode},
    {CompositePlusLighter, SkXfermode::kPlus_Mode}};

// Keep this array in sync with the WebBlendMode enum in
// public/platform/WebBlendMode.h.
static const SkXfermode::Mode gMapBlendOpsToXfermodeModes[] = {
    SkXfermode::kClear_Mode,       // WebBlendModeNormal
    SkXfermode::kMultiply_Mode,    // WebBlendModeMultiply
    SkXfermode::kScreen_Mode,      // WebBlendModeScreen
    SkXfermode::kOverlay_Mode,     // WebBlendModeOverlay
    SkXfermode::kDarken_Mode,      // WebBlendModeDarken
    SkXfermode::kLighten_Mode,     // WebBlendModeLighten
    SkXfermode::kColorDodge_Mode,  // WebBlendModeColorDodge
    SkXfermode::kColorBurn_Mode,   // WebBlendModeColorBurn
    SkXfermode::kHardLight_Mode,   // WebBlendModeHardLight
    SkXfermode::kSoftLight_Mode,   // WebBlendModeSoftLight
    SkXfermode::kDifference_Mode,  // WebBlendModeDifference
    SkXfermode::kExclusion_Mode,   // WebBlendModeExclusion
    SkXfermode::kHue_Mode,         // WebBlendModeHue
    SkXfermode::kSaturation_Mode,  // WebBlendModeSaturation
    SkXfermode::kColor_Mode,       // WebBlendModeColor
    SkXfermode::kLuminosity_Mode   // WebBlendModeLuminosity
};

SkXfermode::Mode WebCoreCompositeToSkiaComposite(CompositeOperator op,
                                                 WebBlendMode blendMode) {
  ASSERT(op == CompositeSourceOver || blendMode == WebBlendModeNormal);
  if (blendMode != WebBlendModeNormal) {
    if (static_cast<uint8_t>(blendMode) >=
        SK_ARRAY_COUNT(gMapBlendOpsToXfermodeModes)) {
      SkDEBUGF(
          ("GraphicsContext::setPlatformCompositeOperation unknown "
           "WebBlendMode %d\n",
           blendMode));
      return SkXfermode::kSrcOver_Mode;
    }
    return gMapBlendOpsToXfermodeModes[static_cast<uint8_t>(blendMode)];
  }

  const CompositOpToXfermodeMode* table = gMapCompositOpsToXfermodeModes;
  if (static_cast<uint8_t>(op) >=
      SK_ARRAY_COUNT(gMapCompositOpsToXfermodeModes)) {
    SkDEBUGF(
        ("GraphicsContext::setPlatformCompositeOperation unknown "
         "CompositeOperator %d\n",
         op));
    return SkXfermode::kSrcOver_Mode;
  }
  SkASSERT(table[static_cast<uint8_t>(op)].mCompositOp == op);
  return table[static_cast<uint8_t>(op)].m_xfermodeMode;
}

CompositeOperator compositeOperatorFromSkia(SkXfermode::Mode xferMode) {
  switch (xferMode) {
    case SkXfermode::kClear_Mode:
      return CompositeClear;
    case SkXfermode::kSrc_Mode:
      return CompositeCopy;
    case SkXfermode::kSrcOver_Mode:
      return CompositeSourceOver;
    case SkXfermode::kSrcIn_Mode:
      return CompositeSourceIn;
    case SkXfermode::kSrcOut_Mode:
      return CompositeSourceOut;
    case SkXfermode::kSrcATop_Mode:
      return CompositeSourceAtop;
    case SkXfermode::kDstOver_Mode:
      return CompositeDestinationOver;
    case SkXfermode::kDstIn_Mode:
      return CompositeDestinationIn;
    case SkXfermode::kDstOut_Mode:
      return CompositeDestinationOut;
    case SkXfermode::kDstATop_Mode:
      return CompositeDestinationAtop;
    case SkXfermode::kXor_Mode:
      return CompositeXOR;
    case SkXfermode::kPlus_Mode:
      return CompositePlusLighter;
    default:
      break;
  }
  return CompositeSourceOver;
}

WebBlendMode blendModeFromSkia(SkXfermode::Mode xferMode) {
  switch (xferMode) {
    case SkXfermode::kSrcOver_Mode:
      return WebBlendModeNormal;
    case SkXfermode::kMultiply_Mode:
      return WebBlendModeMultiply;
    case SkXfermode::kScreen_Mode:
      return WebBlendModeScreen;
    case SkXfermode::kOverlay_Mode:
      return WebBlendModeOverlay;
    case SkXfermode::kDarken_Mode:
      return WebBlendModeDarken;
    case SkXfermode::kLighten_Mode:
      return WebBlendModeLighten;
    case SkXfermode::kColorDodge_Mode:
      return WebBlendModeColorDodge;
    case SkXfermode::kColorBurn_Mode:
      return WebBlendModeColorBurn;
    case SkXfermode::kHardLight_Mode:
      return WebBlendModeHardLight;
    case SkXfermode::kSoftLight_Mode:
      return WebBlendModeSoftLight;
    case SkXfermode::kDifference_Mode:
      return WebBlendModeDifference;
    case SkXfermode::kExclusion_Mode:
      return WebBlendModeExclusion;
    case SkXfermode::kHue_Mode:
      return WebBlendModeHue;
    case SkXfermode::kSaturation_Mode:
      return WebBlendModeSaturation;
    case SkXfermode::kColor_Mode:
      return WebBlendModeColor;
    case SkXfermode::kLuminosity_Mode:
      return WebBlendModeLuminosity;
    default:
      break;
  }
  return WebBlendModeNormal;
}

SkMatrix affineTransformToSkMatrix(const AffineTransform& source) {
  SkMatrix result;

  result.setScaleX(WebCoreDoubleToSkScalar(source.a()));
  result.setSkewX(WebCoreDoubleToSkScalar(source.c()));
  result.setTranslateX(WebCoreDoubleToSkScalar(source.e()));

  result.setScaleY(WebCoreDoubleToSkScalar(source.d()));
  result.setSkewY(WebCoreDoubleToSkScalar(source.b()));
  result.setTranslateY(WebCoreDoubleToSkScalar(source.f()));

  // FIXME: Set perspective properly.
  result.setPerspX(0);
  result.setPerspY(0);
  result.set(SkMatrix::kMPersp2, SK_Scalar1);

  return result;
}

bool nearlyIntegral(float value) {
  return fabs(value - floorf(value)) < std::numeric_limits<float>::epsilon();
}

InterpolationQuality limitInterpolationQuality(
    const GraphicsContext& context,
    InterpolationQuality resampling) {
  return std::min(resampling, context.imageInterpolationQuality());
}

InterpolationQuality computeInterpolationQuality(float srcWidth,
                                                 float srcHeight,
                                                 float destWidth,
                                                 float destHeight,
                                                 bool isDataComplete) {
  // The percent change below which we will not resample. This usually means
  // an off-by-one error on the web page, and just doing nearest neighbor
  // sampling is usually good enough.
  const float kFractionalChangeThreshold = 0.025f;

  // Images smaller than this in either direction are considered "small" and
  // are not resampled ever (see below).
  const int kSmallImageSizeThreshold = 8;

  // The amount an image can be stretched in a single direction before we
  // say that it is being stretched so much that it must be a line or
  // background that doesn't need resampling.
  const float kLargeStretch = 3.0f;

  // Figure out if we should resample this image. We try to prune out some
  // common cases where resampling won't give us anything, since it is much
  // slower than drawing stretched.
  float diffWidth = fabs(destWidth - srcWidth);
  float diffHeight = fabs(destHeight - srcHeight);
  bool widthNearlyEqual = diffWidth < std::numeric_limits<float>::epsilon();
  bool heightNearlyEqual = diffHeight < std::numeric_limits<float>::epsilon();
  // We don't need to resample if the source and destination are the same.
  if (widthNearlyEqual && heightNearlyEqual)
    return InterpolationNone;

  if (srcWidth <= kSmallImageSizeThreshold ||
      srcHeight <= kSmallImageSizeThreshold ||
      destWidth <= kSmallImageSizeThreshold ||
      destHeight <= kSmallImageSizeThreshold) {
    // Small image detected.

    // Resample in the case where the new size would be non-integral.
    // This can cause noticeable breaks in repeating patterns, except
    // when the source image is only one pixel wide in that dimension.
    if ((!nearlyIntegral(destWidth) &&
         srcWidth > 1 + std::numeric_limits<float>::epsilon()) ||
        (!nearlyIntegral(destHeight) &&
         srcHeight > 1 + std::numeric_limits<float>::epsilon()))
      return InterpolationLow;

    // Otherwise, don't resample small images. These are often used for
    // borders and rules (think 1x1 images used to make lines).
    return InterpolationNone;
  }

  if (srcHeight * kLargeStretch <= destHeight ||
      srcWidth * kLargeStretch <= destWidth) {
    // Large image detected.

    // Don't resample if it is being stretched a lot in only one direction.
    // This is trying to catch cases where somebody has created a border
    // (which might be large) and then is stretching it to fill some part
    // of the page.
    if (widthNearlyEqual || heightNearlyEqual)
      return InterpolationNone;

    // The image is growing a lot and in more than one direction. Resampling
    // is slow and doesn't give us very much when growing a lot.
    return InterpolationLow;
  }

  if ((diffWidth / srcWidth < kFractionalChangeThreshold) &&
      (diffHeight / srcHeight < kFractionalChangeThreshold)) {
    // It is disappointingly common on the web for image sizes to be off by
    // one or two pixels. We don't bother resampling if the size difference
    // is a small fraction of the original size.
    return InterpolationNone;
  }

  // When the image is not yet done loading, use linear. We don't cache the
  // partially resampled images, and as they come in incrementally, it causes
  // us to have to resample the whole thing every time.
  if (!isDataComplete)
    return InterpolationLow;

  // Everything else gets resampled at high quality.
  return InterpolationHigh;
}

int clampedAlphaForBlending(float alpha) {
  if (alpha < 0)
    return 0;
  int roundedAlpha = roundf(alpha * 256);
  if (roundedAlpha > 256)
    roundedAlpha = 256;
  return roundedAlpha;
}

SkColor scaleAlpha(SkColor color, float alpha) {
  return scaleAlpha(color, clampedAlphaForBlending(alpha));
}

SkColor scaleAlpha(SkColor color, int alpha) {
  int a = (SkColorGetA(color) * alpha) >> 8;
  return (color & 0x00FFFFFF) | (a << 24);
}

template <typename PrimitiveType>
void drawFocusRingPrimitive(const PrimitiveType&,
                            SkCanvas*,
                            const SkPaint&,
                            float cornerRadius) {
  ASSERT_NOT_REACHED();  // Missing an explicit specialization?
}

template <>
void drawFocusRingPrimitive<SkRect>(const SkRect& rect,
                                    SkCanvas* canvas,
                                    const SkPaint& paint,
                                    float cornerRadius) {
  SkRRect rrect;
  rrect.setRectXY(rect, SkFloatToScalar(cornerRadius),
                  SkFloatToScalar(cornerRadius));
  canvas->drawRRect(rrect, paint);
}

template <>
void drawFocusRingPrimitive<SkPath>(const SkPath& path,
                                    SkCanvas* canvas,
                                    const SkPaint& paint,
                                    float cornerRadius) {
  SkPaint pathPaint = paint;
  pathPaint.setPathEffect(
      SkCornerPathEffect::Make(SkFloatToScalar(cornerRadius)));
  canvas->drawPath(path, pathPaint);
}

template <typename PrimitiveType>
void drawPlatformFocusRing(const PrimitiveType& primitive,
                           SkCanvas* canvas,
                           SkColor color,
                           int width) {
  SkPaint paint;
  paint.setAntiAlias(true);
  paint.setStyle(SkPaint::kStroke_Style);
  paint.setColor(color);
  paint.setStrokeWidth(GraphicsContext::focusRingWidth(width));

#if OS(MACOSX)
  paint.setAlpha(64);
  const float cornerRadius = (width - 1) * 0.5f;
#else
  const float cornerRadius = 1;
#endif

  drawFocusRingPrimitive(primitive, canvas, paint, cornerRadius);

#if OS(MACOSX)
  // Inner part
  paint.setAlpha(128);
  paint.setStrokeWidth(paint.getStrokeWidth() * 0.5f);
  drawFocusRingPrimitive(primitive, canvas, paint, cornerRadius);
#endif
}

template void PLATFORM_EXPORT drawPlatformFocusRing<SkRect>(const SkRect&,
                                                            SkCanvas*,
                                                            SkColor,
                                                            int width);
template void PLATFORM_EXPORT drawPlatformFocusRing<SkPath>(const SkPath&,
                                                            SkCanvas*,
                                                            SkColor,
                                                            int width);

}  // namespace blink
