/*
 * Copyright 2015 Google Inc. 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/skia/cobalt_skia_type_conversions.h"

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace skia {

SkColorType RenderTreeSurfaceFormatToSkia(
    render_tree::PixelFormat render_tree_format) {
  switch (render_tree_format) {
    case render_tree::kPixelFormatRGBA8:
      return kRGBA_8888_SkColorType;
    case render_tree::kPixelFormatBGRA8:
      return kBGRA_8888_SkColorType;
    case render_tree::kPixelFormatY8:
      return kAlpha_8_SkColorType;
    case render_tree::kPixelFormatU8:
      return kAlpha_8_SkColorType;
    case render_tree::kPixelFormatV8:
      return kAlpha_8_SkColorType;
    case render_tree::kPixelFormatUV8:
      return kRGBA_8888_SkColorType;
    default:
      DLOG(FATAL) << "Unknown render tree pixel format!";
      return kUnknown_SkColorType;
  }
}

SkAlphaType RenderTreeAlphaFormatToSkia(
    render_tree::AlphaFormat render_tree_format) {
  switch (render_tree_format) {
    case render_tree::kAlphaFormatPremultiplied:
      return kPremul_SkAlphaType;
    case render_tree::kAlphaFormatUnpremultiplied:
      return kUnpremul_SkAlphaType;
    default: DLOG(FATAL) << "Unknown render tree alpha format!";
  }
  return kUnpremul_SkAlphaType;
}

SkFontStyle CobaltFontStyleToSkFontStyle(render_tree::FontStyle style) {
  SkFontStyle::Slant slant = style.slant == render_tree::FontStyle::kItalicSlant
                                 ? SkFontStyle::kItalic_Slant
                                 : SkFontStyle::kUpright_Slant;

  return SkFontStyle(style.weight, SkFontStyle::kNormal_Width, slant);
}

SkRect CobaltRectFToSkiaRect(const math::RectF& rect) {
  return SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height());
}

SkMatrix CobaltMatrixToSkia(const math::Matrix3F& cobalt_matrix) {
  // Shorten the variable name.
  const math::Matrix3F& cm = cobalt_matrix;

  SkMatrix skia_matrix;
  skia_matrix.setAll(cm.Get(0, 0), cm.Get(0, 1), cm.Get(0, 2), cm.Get(1, 0),
                     cm.Get(1, 1), cm.Get(1, 2), cm.Get(2, 0), cm.Get(2, 1),
                     cm.Get(2, 2));
  return skia_matrix;
}

math::Matrix3F SkiaMatrixToCobalt(const SkMatrix& skia_matrix) {
  return math::Matrix3F::FromValues(
      skia_matrix.get(0), skia_matrix.get(1), skia_matrix.get(2),
      skia_matrix.get(3), skia_matrix.get(4), skia_matrix.get(5),
      skia_matrix.get(6), skia_matrix.get(7), skia_matrix.get(8));
}

}  // namespace skia
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt
