/* * PPOGL - PlanetPenguin Open Game Library * Copyright (C) 2004-2005 Volker Stroebel * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "font.h" #include #include "ftgl/FTGLTextureFont.h" #include "base/glwrappers.h" #include "config.h" namespace ppogl{ Font::Font(const std::string& filename, unsigned int size, const ppogl::Color &color) : RefObject(), mp_font(NULL), m_color(color) { mp_font = new FTGLTextureFont(filename.c_str()); if (mp_font->Error()){ PP_ERROR("Unable to load font: " << filename); }else{ mp_font->FaceSize(size); mp_font->CharMap(ft_encoding_unicode); } } Font::Font(FTFont *font, const ppogl::Color &color) : RefObject(), mp_font(font), m_color(color) { } Font::~Font() { if(mp_font!=NULL){ delete mp_font; } } void Font::draw(const std::string& string, float x, float y) { draw(string, ppogl::Vec2d(x, y)); } void Font::draw(const std::string& string, ppogl::Vec2d position) { const wchar_t* u_string; u_string = Font::utf8ToUnicode(string); gl::PushMatrix(); { gl::Enable(GL_TEXTURE_2D); gl::Color(m_color); gl::Translate(position); mp_font->Render(u_string); gl::Disable(GL_TEXTURE_2D); } gl::PopMatrix(); delete [] u_string; } void Font::draw(const wchar_t *string, float x, float y) { draw(string, ppogl::Vec2d(x, y)); } void Font::draw(const wchar_t *string, ppogl::Vec2d position) { gl::PushMatrix(); { gl::Enable(GL_TEXTURE_2D); gl::Color(m_color); gl::Translate(position); mp_font->Render(string); gl::Disable(GL_TEXTURE_2D); } gl::PopMatrix(); } float Font::ascender() { return mp_font->Ascender(); } float Font::descender() { return mp_font->Descender(); } float Font::advance(const std::string& string) { const wchar_t* u_string; u_string = Font::utf8ToUnicode(string); float adv = mp_font->Advance(u_string); delete [] u_string; return adv; } float Font::advance(const wchar_t* string) { return mp_font->Advance(string); } ppogl::Color& Font::getColor() { return m_color; } FTFont* Font::getFTFont() { return mp_font; } const wchar_t* Font::utf8ToUnicode(const std::string& string) { wchar_t ch; int len = string.length(); wchar_t *u_string = new wchar_t[len+1]; int j=0; for (int i=0; i < len; ++i, ++j ) { ch = (reinterpret_cast(string.c_str()))[i]; if ( ch >= 0xF0 ) { ch = wchar_t(string[i]&0x07) << 18; ch |= wchar_t(string[++i]&0x3F) << 12; ch |= wchar_t(string[++i]&0x3F) << 6; ch |= wchar_t(string[++i]&0x3F); } else if ( ch >= 0xE0 ) { ch = wchar_t(string[i]&0x0F) << 12; ch |= wchar_t(string[++i]&0x3F) << 6; ch |= wchar_t(string[++i]&0x3F); } else if ( ch >= 0xC0 ) { ch = wchar_t(string[i]&0x1F) << 6; ch |= wchar_t(string[++i]&0x3F); } u_string[j] = ch; } u_string[j] = 0; return u_string; } void Font::utf8ToUnicode(wchar_t* buff, const std::string& string) { wchar_t ch; int len = string.length(); int j=0; for (int i=0; i < len; ++i, ++j ) { ch = (reinterpret_cast(string.c_str()))[i]; if ( ch >= 0xF0 ) { ch = wchar_t(string[i]&0x07) << 18; ch |= wchar_t(string[++i]&0x3F) << 12; ch |= wchar_t(string[++i]&0x3F) << 6; ch |= wchar_t(string[++i]&0x3F); } else if ( ch >= 0xE0 ) { ch = wchar_t(string[i]&0x0F) << 12; ch |= wchar_t(string[++i]&0x3F) << 6; ch |= wchar_t(string[++i]&0x3F); } else if ( ch >= 0xC0 ) { ch = wchar_t(string[i]&0x1F) << 6; ch |= wchar_t(string[++i]&0x3F); } buff[j] = ch; } buff[j] = 0; } // FontMgr PPOGL_SINGLETON(FontMgr); FontMgr::FontMgr() { } FontMgr::~FontMgr() { } bool FontMgr::registerFont(const std::string& binding, const std::string& filename, unsigned int size, const ppogl::Color &color) { //todo: check wether the font alrady exists m_bindings[binding] = FontRef(new ppogl::Font(filename, size, color)); return true; } bool FontMgr::bindFont(const std::string& binding, const std::string& fontName) { FontRef font = get(fontName); if(!font) return false; m_bindings[binding] = FontRef(new ppogl::Font(font->getFTFont(), font->getColor())); return true; } bool FontMgr::bindFont(const std::string& binding, const std::string& fontName, const ppogl::Color &color) { FontRef font = get(fontName); if(!font) return false; m_bindings[binding] = FontRef(new ppogl::Font(font->getFTFont(), color)); return true; } void FontMgr::draw(const std::string& binding, const std::string& string, float x, float y) { FontRef font = get(binding); if(font){ font->draw(string, x, y); } } int FontMgr::sqLoad(ppogl::Script *vm) { ppogl::Color color=ppogl::Color::white; std::string binding = vm->getString(1); std::string filename = vm->getString(2); int size = vm->getInt(3); if(vm->getTop()>=4){ vm->pushNull(); int i=0; while(vm->next(4)) { if(i>4) break; double temp = vm->getFloat(); PP_ASSERT(temp>=0.0 && temp<=1.0,"Invalid color value: " << temp); color.values[i]=temp; i++; vm->pop(2); } vm->pop(); } getInstance().registerFont(binding, filename, size, color); return 0; } int FontMgr::sqBind(ppogl::Script *vm) { std::string binding = vm->getString(1); std::string name = vm->getString(2); if(vm->getTop()>=3){ ppogl::Color color=ppogl::Color::white; vm->pushNull(); int i=0; while(vm->next(3)!= 0){ if(i>4) break; double value = vm->getFloat(); PP_ASSERT(value>=0.0 && value<=1.0,"Invalid color value: " << value); vm->pop(2); color.values[i]=value; i++; } vm->pop(); if(!getInstance().bindFont(binding, name, color)){ PP_WARNING("Unable to bind font: " << binding << " -> " << name); } }else{ if(!getInstance().bindFont(binding, name)){ PP_WARNING("Unable to bind font: " << binding << " -> " << name); } } return 0; } } //namepsace ppogl