/*!
  \file
  \brief 文字列サーフェス

  \author Satofumi KAMIMURA

  $Id: TextSurface.cpp 1815 2010-05-06 17:34:19Z satofumi $
*/

#include "TextSurface.h"
#include "Font.h"
#include "SDL_GL_Texture.h"

using namespace qrk;


namespace
{
    SDL_GL_Texture* createTextTexture(const Font& font,
                                      const char text[],
                                      bool length_only = false,
                                      int* width = NULL,
                                      int* height = NULL)
    {
        TTF_Font* font_resource = font.resource();
        if (! font_resource) {
            return NULL;
        }

        if (length_only) {
            TTF_SizeUTF8(font_resource, text, width, height);
            return NULL;
        }

        const Color& fore_color = font.foregroundColor();
        SDL_Color fore;
        fore.r = static_cast<unsigned char>(0xff * fore_color.r);
        fore.g = static_cast<unsigned char>(0xff * fore_color.g);
        fore.b = static_cast<unsigned char>(0xff * fore_color.b);

        const Color& back_color = font.backgroundColor();
        SDL_Color back;
        back.r = static_cast<unsigned char>(0xff * back_color.r);
        back.g = static_cast<unsigned char>(0xff * back_color.g);
        back.b = static_cast<unsigned char>(0xff * back_color.b);

        SDL_Surface* surface =
            TTF_RenderUTF8_Shaded(font_resource, text, fore, back);

        return new SDL_GL_Texture(surface, font.transparent());
    }
}


struct TextSurface::pImpl
{
    const Font& font_;
    SDL_GL_Texture* texture_;
    Rect<long> rect_;


    pImpl(const Font& font, const char* text)
        : font_(font), texture_(createTextTexture(font, text))
    {
        if (texture_) {
            rect_ = Rect<long>(0, 0,
                               static_cast<long>(texture_->w),
                               static_cast<long>(texture_->h));
        }
    }


    ~pImpl(void)
    {
        delete texture_;
    }
};


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


TextSurface::~TextSurface(void)
{
}


bool TextSurface::isValid(void) const
{
    return (pimpl->texture_) ? pimpl->texture_->isValid() : false;
}


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


void TextSurface::setAlpha(float alpha)
{
    if (isValid()) {
        pimpl->texture_->setAlpha(alpha);
    }
}


float TextSurface::alpha(void) const
{
    if (! isValid()) {
        return 0.0;
    }
    return pimpl->texture_->alpha();
}


void TextSurface::setRotateAngle(const Angle& angle)
{
    return pimpl->texture_->setRotateAngle(angle);
}


void TextSurface::draw(const Rect<long>* src, const Rect<long>* dest)
{
    if ((! pimpl->texture_) || (! pimpl->texture_->isValid())) {
        return;
    }
    pimpl->texture_->blitTexture(src, dest);
}


// !!!


Rect<long> TextSurface::surfaceSize(Font& font, const char* text)
{
    int width = 0;
    int height = 0;
    createTextTexture(font, text, true, &width, &height);

    return Rect<long>(0, 0, width, height);
}
