/*!
  \file
  \brief 複数サーフェスの合成

  \author Satofumi KAMIMURA

  $Id: MultiSurface.cpp 897 2009-05-17 20:59:55Z satofumi $
*/

#include "MultiSurface.h"
#include <boost/bind.hpp>
#include <algorithm>
#include <vector>

using namespace qrk;
using namespace boost;
using namespace std;


namespace
{
  typedef vector<Surface*> Surfaces;
  typedef vector<Point<long> > Points;
}


struct MultiSurface::pImpl
{
  Surface& base_surface_;
  Surfaces surfaces_;
  Points offsets_;


  pImpl(Surface& base_surface) : base_surface_(base_surface)
  {
  }


  void draw(const Rect<long>* src, const Rect<long>* dest)
  {
    base_surface_.draw(src, dest);

    // 全て描画
    size_t n = surfaces_.size();
    for (size_t i = 0; i < n; ++i) {
      Point<long>& offset = offsets_[i];
      Surface*& surface = surfaces_[i];
      Rect<long> draw_point = surface->rect();
      draw_point.x = dest->x + offset.x;
      draw_point.y = dest->y + offset.y;

      surface->draw(src, &draw_point);
    }
  }
};


MultiSurface::MultiSurface(Surface& base_surface)
  : pimpl(new pImpl(base_surface))
{
}


MultiSurface::~MultiSurface(void)
{
}


bool MultiSurface::isValid(void) const
{
  return pimpl->base_surface_.isValid();
}


Rect<long> MultiSurface::rect(void) const
{
  return pimpl->base_surface_.rect();
}


void MultiSurface::setAlpha(float alpha)
{
  pimpl->base_surface_.setAlpha(alpha);

  // 登録済みのサーフェスに適用
  for_each(pimpl->surfaces_.begin(), pimpl->surfaces_.end(),
           bind(&Surface::setAlpha, _1, alpha));
}


float MultiSurface::alpha(void) const
{
  return pimpl->base_surface_.alpha();
}


void MultiSurface::draw(const Rect<long>* src, const Rect<long>* dest)
{
  pimpl->draw(src, dest);
}


void MultiSurface::push_front(Surface& surface, const Point<long>& offset)
{
  pimpl->surfaces_.push_back(&surface);
  pimpl->offsets_.push_back(offset);
}
