// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/cpp/graphics_2d.h"

#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_graphics_2d.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/instance_handle.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/module_impl.h"
#include "ppapi/cpp/point.h"
#include "ppapi/cpp/rect.h"

namespace pp {

namespace {

template <> const char* interface_name<PPB_Graphics2D_1_0>() {
  return PPB_GRAPHICS_2D_INTERFACE_1_0;
}

template <> const char* interface_name<PPB_Graphics2D_1_1>() {
  return PPB_GRAPHICS_2D_INTERFACE_1_1;
}

}  // namespace

Graphics2D::Graphics2D() : Resource() {
}

Graphics2D::Graphics2D(const Graphics2D& other)
    : Resource(other),
      size_(other.size_) {
}

Graphics2D::Graphics2D(const InstanceHandle& instance,
                       const Size& size,
                       bool is_always_opaque)
    : Resource() {
  if (has_interface<PPB_Graphics2D_1_1>()) {
    PassRefFromConstructor(get_interface<PPB_Graphics2D_1_1>()->Create(
        instance.pp_instance(),
        &size.pp_size(),
        PP_FromBool(is_always_opaque)));
  } else if (has_interface<PPB_Graphics2D_1_0>()) {
    PassRefFromConstructor(get_interface<PPB_Graphics2D_1_0>()->Create(
        instance.pp_instance(),
        &size.pp_size(),
        PP_FromBool(is_always_opaque)));
  } else {
    return;
  }
  if (!is_null()) {
    // Only save the size if allocation succeeded.
    size_ = size;
  }
}

Graphics2D::~Graphics2D() {
}

Graphics2D& Graphics2D::operator=(const Graphics2D& other) {
  Resource::operator=(other);
  size_ = other.size_;
  return *this;
}

void Graphics2D::PaintImageData(const ImageData& image,
                                const Point& top_left) {
  if (has_interface<PPB_Graphics2D_1_1>()) {
    get_interface<PPB_Graphics2D_1_1>()->PaintImageData(pp_resource(),
                                                        image.pp_resource(),
                                                        &top_left.pp_point(),
                                                        NULL);
  } else if (has_interface<PPB_Graphics2D_1_0>()) {
    get_interface<PPB_Graphics2D_1_0>()->PaintImageData(pp_resource(),
                                                        image.pp_resource(),
                                                        &top_left.pp_point(),
                                                        NULL);
  }
}

void Graphics2D::PaintImageData(const ImageData& image,
                                const Point& top_left,
                                const Rect& src_rect) {
  if (has_interface<PPB_Graphics2D_1_1>()) {
    get_interface<PPB_Graphics2D_1_1>()->PaintImageData(pp_resource(),
                                                        image.pp_resource(),
                                                        &top_left.pp_point(),
                                                        &src_rect.pp_rect());
  } else if (has_interface<PPB_Graphics2D_1_0>()) {
    get_interface<PPB_Graphics2D_1_0>()->PaintImageData(pp_resource(),
                                                        image.pp_resource(),
                                                        &top_left.pp_point(),
                                                        &src_rect.pp_rect());
  }
}

void Graphics2D::Scroll(const Rect& clip, const Point& amount) {
  if (has_interface<PPB_Graphics2D_1_1>()) {
    get_interface<PPB_Graphics2D_1_1>()->Scroll(pp_resource(),
                                                &clip.pp_rect(),
                                                &amount.pp_point());
  } else if (has_interface<PPB_Graphics2D_1_0>()) {
    get_interface<PPB_Graphics2D_1_0>()->Scroll(pp_resource(),
                                                &clip.pp_rect(),
                                                &amount.pp_point());
  }
}

void Graphics2D::ReplaceContents(ImageData* image) {
  if (has_interface<PPB_Graphics2D_1_1>()) {
    get_interface<PPB_Graphics2D_1_1>()->ReplaceContents(pp_resource(),
                                                         image->pp_resource());
  } else if (has_interface<PPB_Graphics2D_1_0>()) {
    get_interface<PPB_Graphics2D_1_0>()->ReplaceContents(pp_resource(),
                                                         image->pp_resource());
  } else {
    return;
  }

  // On success, reset the image data. This is to help prevent people
  // from continuing to use the resource which will result in artifacts.
  *image = ImageData();
}

int32_t Graphics2D::Flush(const CompletionCallback& cc) {
  if (has_interface<PPB_Graphics2D_1_1>()) {
    return get_interface<PPB_Graphics2D_1_1>()->Flush(
        pp_resource(), cc.pp_completion_callback());
  } else if (has_interface<PPB_Graphics2D_1_0>()) {
    return get_interface<PPB_Graphics2D_1_0>()->Flush(
        pp_resource(), cc.pp_completion_callback());
  } else {
    return cc.MayForce(PP_ERROR_NOINTERFACE);
  }
}

bool Graphics2D::SetScale(float scale) {
  if (!has_interface<PPB_Graphics2D_1_1>())
    return false;
  return PP_ToBool(get_interface<PPB_Graphics2D_1_1>()->SetScale(pp_resource(),
                                                                 scale));
}

float Graphics2D::GetScale() {
  if (!has_interface<PPB_Graphics2D_1_1>())
    return 1.0f;
  return get_interface<PPB_Graphics2D_1_1>()->GetScale(pp_resource());
}

}  // namespace pp
