// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/renderer/rasterizer/blitter/linear_gradient.h"

#include <algorithm>

#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/render_tree/brush.h"
#include "cobalt/renderer/rasterizer/blitter/cobalt_blitter_conversions.h"
#include "cobalt/renderer/rasterizer/blitter/render_state.h"
#include "cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.h"
#include "cobalt/renderer/rasterizer/skia/conversions.h"

#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/effects/SkGradientShader.h"

#if SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)

namespace {

using cobalt::render_tree::ColorRGBA;
using cobalt::render_tree::ColorStopList;
using cobalt::render_tree::LinearGradientBrush;
using cobalt::renderer::rasterizer::blitter::RenderState;
using cobalt::renderer::rasterizer::blitter::SkiaToBlitterPixelFormat;
using cobalt::renderer::rasterizer::blitter::RectFToBlitterRect;
using cobalt::renderer::rasterizer::blitter::LinearGradientCache;
using cobalt::renderer::rasterizer::skia::SkiaColorStops;

int GetPixelOffsetInBytes(const SkImageInfo& image_info,
                          const SbBlitterPixelData& pixel_data) {
  if (image_info.width() == 1)
    return SbBlitterGetPixelDataPitchInBytes(pixel_data);

  SbBlitterPixelDataFormat pixel_format =
      SkiaToBlitterPixelFormat(image_info.colorType());
  return SbBlitterBytesPerPixelForFormat(pixel_format);
}

void ColorStopToPixelData(SbBlitterPixelDataFormat pixel_format,
                          const ColorRGBA& color_stop, uint8_t* pixel_data_out,
                          uint8_t* pixel_data_out_end) {
  DCHECK(pixel_data_out_end >=
         (pixel_data_out + SbBlitterBytesPerPixelForFormat(pixel_format)));
  uint8_t final_b(color_stop.rgb8_b());
  uint8_t final_g(color_stop.rgb8_g());
  uint8_t final_r(color_stop.rgb8_r());
  uint8_t final_a(color_stop.rgb8_a());

  switch (pixel_format) {
    case kSbBlitterPixelDataFormatARGB8:
      pixel_data_out[0] = final_a;
      pixel_data_out[1] = final_r;
      pixel_data_out[2] = final_g;
      pixel_data_out[3] = final_b;
      break;
    case kSbBlitterPixelDataFormatBGRA8:
      pixel_data_out[0] = final_b;
      pixel_data_out[1] = final_g;
      pixel_data_out[2] = final_r;
      pixel_data_out[3] = final_a;
      break;
    case kSbBlitterPixelDataFormatRGBA8:
      pixel_data_out[0] = final_r;
      pixel_data_out[1] = final_g;
      pixel_data_out[2] = final_b;
      pixel_data_out[3] = final_a;
      break;
    default:
      NOTREACHED() << "Unknown or unsupported pixel format." << pixel_format;
      break;
  }
}

// This function uses Skia to render a gradient into the pixel data pointed
// at pixel_data_begin.  This function is intended as a fallback in case when
// RenderSimpleGradient is unable to render the gradient.
void RenderComplexLinearGradient(const LinearGradientBrush& brush,
                                 const ColorStopList& color_stops, int width,
                                 int height, const SkImageInfo& image_info,
                                 uint8_t* pixel_data_begin,
                                 int pitch_in_bytes) {
  SkBitmap bitmap;
  bitmap.installPixels(image_info, pixel_data_begin, pitch_in_bytes);
  SkCanvas canvas(bitmap);
  canvas.clear(SkColorSetARGB(0, 0, 0, 0));

  SkPoint points[2];
  points[0].fX = 0;
  points[0].fY = 0;
  points[1].fX = 0;
  points[1].fY = 0;

  // The -1 offset is easiest to think about in a 2 pixel case:
  // If width = 2, then the ending coordinate should be 1.
  if (brush.IsHorizontal()) {
    if (brush.dest().x() < brush.source().x()) {
      points[0].fX = width - 1;  // Right to Left.
    } else {
      points[1].fX = width - 1;  // Left to Right.
    }
  } else {
    if (brush.dest().y() < brush.source().y()) {
      points[0].fY = height - 1;  // High to Low.
    } else {
      points[1].fY = height - 1;  // Low to High.
    }
  }

  SkiaColorStops skia_color_stops(color_stops);
  sk_sp<SkShader> shader(SkGradientShader::MakeLinear(
      points, skia_color_stops.colors.data(), skia_color_stops.positions.data(),
      skia_color_stops.size(), SkShader::kClamp_TileMode,
      SkGradientShader::kInterpolateColorsInPremul_Flag, NULL));
  SkPaint paint;
  paint.setShader(shader);
  canvas.drawPaint(paint);
}

// This function tries to render a "simple" gradient into the pixel data pointed
// to in the range [pixel_data_begin, pixel_data_end).  Simple gradients here
// are defined as has following properties:
//   1.  Vertical or horizontal gradient.
//   2.  Two color stops only -- one at position 0, and one at position 1.
//
// Having these conditions greatly simplifies the logic, and allows us to avoid
// the overhead of dealing with Skia.
//
// Returns: true if it could successfully render, false if optimal conditions
// are not met.  If false is returned, nothing is written to the pixel data
// buffer.
bool RenderSimpleGradient(const LinearGradientBrush& brush,
                          const ColorStopList& color_stops, int width,
                          int height, SbBlitterPixelDataFormat pixel_format,
                          uint8_t* pixel_data_begin, uint8_t* pixel_data_end,
                          int pixel_offset_in_bytes) {
  if (color_stops.size() != 2) {
    return false;
  }

  const float small_value(1E-6);
  if ((color_stops[0].position < -small_value) ||
      (color_stops[0].position > small_value)) {
    return false;
  }
  if ((color_stops[1].position < 1 - small_value) ||
      (color_stops[1].position > 1 + small_value)) {
    return false;
  }

  const int number_pixels = width * height;

  if ((number_pixels < 2) || (width < 0) || (height < 0)) {
    return false;
  }

  ColorRGBA start_color = color_stops[0].color;
  ColorRGBA end_color = color_stops[1].color;

  // Swap start and end colors if the gradient direction is right to left or
  // down to up.
  if (brush.IsHorizontal()) {
    if (brush.dest().x() < brush.source().x()) {
      std::swap(start_color, end_color);
    }
  } else {
    if (brush.dest().y() < brush.source().y()) {
      std::swap(start_color, end_color);
    }
  }

  ColorRGBA color_step((end_color - start_color) / (number_pixels - 1));
  // We add the color_stop * 0.5f to match pixel positioning in software Skia.
  ColorRGBA current_color(start_color + color_step * 0.5f);
  ColorStopToPixelData(pixel_format, current_color, pixel_data_begin,
                       pixel_data_end);

  uint8_t* second_pixel = pixel_data_begin + pixel_offset_in_bytes;
  uint8_t* last_pixel =
      (pixel_data_begin + (number_pixels - 1) * pixel_offset_in_bytes);
  for (uint8_t* current_pixel = second_pixel; current_pixel != last_pixel;
       current_pixel += pixel_offset_in_bytes) {
    current_color += color_step;
    ColorStopToPixelData(pixel_format, current_color, current_pixel,
                         pixel_data_end);
  }

  ColorStopToPixelData(pixel_format, end_color, last_pixel, pixel_data_end);

  return true;
}

void RenderOptimizedLinearGradient(SbBlitterDevice device,
                                   SbBlitterContext context,
                                   const RenderState& render_state,
                                   cobalt::math::RectF rect,
                                   const LinearGradientBrush& brush,
                                   LinearGradientCache* linear_gradient_cache) {
  DCHECK(linear_gradient_cache);
  if ((rect.width() == 0) && (rect.height() == 0)) return;

  DCHECK(brush.IsVertical() || brush.IsHorizontal());

  SbBlitterSurface surface = kSbBlitterInvalidSurface;
  if (linear_gradient_cache) {
    surface = linear_gradient_cache->Get(brush);
  }

  // The main strategy here is to create a 1D image, and then calculate
  // the gradient values in software.  If the gradient is simple, this can be
  // done with optimized function (RenderSimpleGradient), which avoids calling
  // Skia (and thus is faster).  Otherwise, we call RenderComplexLinearGradient,
  // which uses Skia.

  // Once a gradient is created, a SbBlitterSurface is created and a rectangle
  // is blitted using the blitter API.
  int width = brush.IsHorizontal()
                  ? std::abs(brush.dest().x() - brush.source().x())
                  : 1;
  int height =
      brush.IsVertical() ? std::abs(brush.dest().y() - brush.source().y()) : 1;

  if (SbBlitterIsSurfaceValid(surface) == false) {
    SkImageInfo image_info = SkImageInfo::MakeN32Premul(width, height);

    SbBlitterPixelDataFormat pixel_format =
        SkiaToBlitterPixelFormat(image_info.colorType());

    if (!SbBlitterIsPixelFormatSupportedByPixelData(device, pixel_format)) {
      NOTREACHED() << "Pixel Format is not supported by Pixel Data";
      return;
    }

    SbBlitterPixelData pixel_data =
        SbBlitterCreatePixelData(device, width, height, pixel_format);

    if (SbBlitterIsPixelDataValid(pixel_data)) {
      int bytes_per_pixel = GetPixelOffsetInBytes(image_info, pixel_data);
      int pitch_in_bytes = SbBlitterGetPixelDataPitchInBytes(pixel_data);

      uint8_t* pixel_data_begin =
          static_cast<uint8_t*>(SbBlitterGetPixelDataPointer(pixel_data));
      uint8_t* pixel_data_end = pixel_data_begin + pitch_in_bytes * height;

      const ColorStopList& color_stops(brush.color_stops());

      int pixel_offset_in_bytes =
          (width == 1) ? pitch_in_bytes : bytes_per_pixel;

      // Try rendering without Skia first.
      bool render_successful = RenderSimpleGradient(
          brush, color_stops, width, height, pixel_format, pixel_data_begin,
          pixel_data_end, pixel_offset_in_bytes);
      if (!render_successful) {
        RenderComplexLinearGradient(brush, color_stops, width, height,
                                    image_info, pixel_data_begin,
                                    pitch_in_bytes);
      }

      surface = SbBlitterCreateSurfaceFromPixelData(device, pixel_data);
      linear_gradient_cache->Put(brush, surface);
    }
  }

  if (surface) {
    bool need_blending = false;
    for (ColorStopList::const_iterator it = brush.color_stops().begin();
         it != brush.color_stops().end(); ++it) {
      if (it->color.HasAlpha()) {
        need_blending = true;
        break;
      }
    }

    SbBlitterSetBlending(context, need_blending);
    SbBlitterSetModulateBlitsWithColor(context, false);
    cobalt::math::Rect transformed_rect = cobalt::math::Rect::RoundFromRectF(
        render_state.transform.TransformRect(rect));

    // It may be the case that the linear gradient is larger than the rect.
    SbBlitterRect source_rect;
    if (height == 1) {
      int left = rect.x() - std::min(brush.source().x(), brush.dest().x());
      source_rect = SbBlitterMakeRect(left, 0, rect.width(), 1);
    } else {
      int top = rect.y() - std::min(brush.source().y(), brush.dest().y());
      source_rect = SbBlitterMakeRect(0, top, 1, rect.height());
    }

    SbBlitterRect dest_rect =
        SbBlitterMakeRect(transformed_rect.x(), transformed_rect.y(),
                          transformed_rect.width(), transformed_rect.height());
    SbBlitterBlitRectToRect(context, surface, source_rect, dest_rect);
  }
}

void RenderColoredRect(SbBlitterDevice device, SbBlitterContext context,
                       const RenderState& render_state, const ColorRGBA& color,
                       const cobalt::math::RectF& rect) {
  SbBlitterSetBlending(context, color.a() < 1.0f);
  SbBlitterSetColor(context,
                    SbBlitterColorFromRGBA(color.rgb8_r(), color.rgb8_g(),
                                           color.rgb8_b(), color.rgb8_a()));
  SbBlitterFillRect(
      context, RectFToBlitterRect(render_state.transform.TransformRect(rect)));
}

}  // namespace

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace blitter {

using render_tree::LinearGradientBrush;

bool RenderLinearGradient(SbBlitterDevice device, SbBlitterContext context,
                          const RenderState& render_state,
                          const render_tree::RectNode& rect_node,
                          LinearGradientCache* linear_gradient_cache) {
  DCHECK(rect_node.data().background_brush);
  const LinearGradientBrush* const linear_gradient_brush =
      base::polymorphic_downcast<LinearGradientBrush*>(
          rect_node.data().background_brush.get());
  if (!linear_gradient_brush) return false;

  // Currently, only vertical and horizontal gradients are accelerated.
  math::RectF content_rect = rect_node.data().rect;
  if (linear_gradient_brush->IsVertical()) {
    // Render solid-colored rect(s) to fill any gaps between the content_rect
    // and the gradient.
    float top = linear_gradient_brush->source().y();
    float bottom = linear_gradient_brush->dest().y();
    ColorRGBA top_color = linear_gradient_brush->color_stops().front().color;
    ColorRGBA bottom_color = linear_gradient_brush->color_stops().back().color;
    if (top > bottom) {
      std::swap(top, bottom);
      std::swap(top_color, bottom_color);
    }

    if (top > content_rect.y()) {
      float gap = top - content_rect.y();
      RenderColoredRect(device, context, render_state, top_color,
                        math::RectF(content_rect.x(), content_rect.y(),
                                    content_rect.width(), gap));
      content_rect.set_y(top);
      content_rect.set_height(content_rect.height() - gap);
    }
    if (bottom < content_rect.bottom()) {
      float gap = content_rect.bottom() - bottom;
      RenderColoredRect(
          device, context, render_state, bottom_color,
          math::RectF(content_rect.x(), bottom, content_rect.width(), gap));
      content_rect.set_height(content_rect.height() - gap);
    }
  } else if (linear_gradient_brush->IsHorizontal()) {
    // Render solid-colored rect(s) to fill any gaps between the content_rect
    // and the gradient.
    float left = linear_gradient_brush->source().x();
    float right = linear_gradient_brush->dest().x();
    ColorRGBA left_color = linear_gradient_brush->color_stops().front().color;
    ColorRGBA right_color = linear_gradient_brush->color_stops().back().color;
    if (left > right) {
      std::swap(left, right);
      std::swap(left_color, right_color);
    }

    if (left > content_rect.x()) {
      float gap = left - content_rect.x();
      RenderColoredRect(device, context, render_state, left_color,
                        math::RectF(content_rect.x(), content_rect.y(), gap,
                                    content_rect.height()));
      content_rect.set_x(left);
      content_rect.set_width(content_rect.width() - gap);
    }
    if (right < content_rect.right()) {
      float gap = content_rect.right() - right;
      RenderColoredRect(
          device, context, render_state, right_color,
          math::RectF(right, content_rect.y(), gap, content_rect.height()));
      content_rect.set_width(content_rect.width() - gap);
    }
  } else {
    // Angled gradients are not supported by the optimized path.
    return false;
  }

  RenderOptimizedLinearGradient(device, context, render_state, content_rect,
                                *linear_gradient_brush, linear_gradient_cache);
  return true;
}

}  // namespace blitter
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt

#endif  // SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
