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

  \author Satofumi KAMIMURA

  $Id: TextSurface.cpp 921 2009-05-22 23:19:16Z 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
{
  Font font_;
  SDL_GL_Texture* texture_;
  Rect<long> rect_;


  pImpl(const Font& font, const char* text)
    : font_(font), texture_(createTextTexture(font, text)),
      rect_(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_->isValid();
}


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


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


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


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);
}
