/*!
  \file
  \brief 部分透過できる文字列サーフェス

  \author Satofumi KAMIMURA

  $Id: TextFadeSurface.cpp 1814 2010-05-03 07:57:38Z satofumi $
*/

#include "TextFadeSurface.h"
#include "TextSurface.h"
#include "Utf8.h"
#include <vector>

using namespace qrk;
using namespace std;


struct TextFadeSurface::pImpl
{
    enum {
        FadeWidthPixel = 200,
    };

    typedef vector<Surface*> Surfaces;
    Surfaces text_surfaces_;
    Rect<long> rect_;
    float base_alpha_;
    size_t percent_;


    pImpl(const Font& font, const char* text) : base_alpha_(1.0), percent_(100)
    {
        // 文字毎にサーフェスを作る
        Utf8 utf8_text(text);
        size_t n = utf8_text.size();
        for (size_t i = 0; i < n; ++i) {
            string ch = utf8_text.substr(i, 1).toStdString();
            Surface* surface = new TextSurface(font, ch.c_str());
            text_surfaces_.push_back(surface);
            rect_.w += surface->rect().w;
            rect_.h = max(rect_.h, surface->rect().h);
        }
    }


    ~pImpl(void)
    {
        for (Surfaces::iterator it = text_surfaces_.begin();
             it != text_surfaces_.end(); ++it) {
            delete *it;
        }
    }


    void draw(const Rect<long>* src, const Rect<long>* dest)
    {
        Rect<long> sub_dest(*dest);
        for (Surfaces::iterator it = text_surfaces_.begin();
             it != text_surfaces_.end(); ++it) {
            Surface* surface = *it;
            sub_dest.w = surface->rect().w;
            sub_dest.h = surface->rect().h;
            surface->draw(src, &sub_dest);
            sub_dest.x += surface->rect().w;
        }
    }


    void setAlpha(void)
    {
        int moved_width =
            static_cast<int>((rect_.w + FadeWidthPixel) * percent_ / 100.0);
        int first = -FadeWidthPixel + moved_width;
        int last = 0 + moved_width;
        int x = 0;
        for (Surfaces::iterator it = text_surfaces_.begin();
             it != text_surfaces_.end(); ++it) {
            Surface* surface = *it;

            float alpha = 1.0;
            if (x > last) {
                alpha = 0.0;
            } else if (x <= first) {
                alpha = 1.0;
            } else {
                alpha = (last - x) / static_cast<float>(FadeWidthPixel);
            }
            surface->setAlpha(alpha * base_alpha_);
            x += surface->rect().w;
        }
    }
};


TextFadeSurface::TextFadeSurface(const Font& font, const char* text)
    : pimpl(new pImpl(font, text))
{
}


TextFadeSurface::~TextFadeSurface(void)
{
}


bool TextFadeSurface::isValid(void) const
{
    if (pimpl->text_surfaces_.empty()) {
        return false;
    }
    return pimpl->text_surfaces_.front()->isValid();
}


Rect<long> TextFadeSurface::rect(void) const
{
    return pimpl->rect_;
}


void TextFadeSurface::setAlpha(float alpha)
{
    pimpl->base_alpha_ = max(min(alpha, 1.0f), 0.0f);
    pimpl->setAlpha();
}


float TextFadeSurface::alpha(void) const
{
    return pimpl->base_alpha_;
}


void TextFadeSurface::setRotateAngle(const Angle& angle)
{
    (void)angle;

    // !!!
}


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


void TextFadeSurface::setFadePercent(size_t percent)
{
    pimpl->percent_ = min(percent, static_cast<size_t>(100));
    pimpl->setAlpha();
}
