Kukatz 3D  0.1
Török Attila szakdolgozata
projects/Kukatz 3D/src/string.cpp
00001 /*
00002  * string.cpp - Kukatz 3D
00003  * Copyright (c) 2011 - TÖRÖK Attila (torokati44@gmail.com)
00004  *
00005  * This software is provided 'as-is', without any express or implied
00006  * warranty. In no event will the authors be held liable for any damages
00007  * arising from the use of this software.
00008  *
00009  * Permission is granted to anyone to use this software for any purpose,
00010  * including commercial applications, and to alter it and redistribute it
00011  * freely, subject to the following restrictions:
00012  *
00013  *       1. The origin of this software must not be misrepresented; you must not
00014  *                      claim that you wrote the original software. If you use this software
00015  *                      in a product, an acknowledgment in the product documentation would be
00016  *                      appreciated but is not required.
00017  *
00018  *       2. Altered source versions must be plainly marked as such, and must not be
00019  *                      misrepresented as being the original software.
00020  *
00021  *       3. This notice may not be removed or altered from any source
00022  *                      distribution.
00023  */
00024 
00025 #include "string.hpp"
00026 
00027 #include <iostream>
00028 
00029 #include <SFML/Graphics.hpp>
00030 
00031 #include "resourcemanager.hpp"
00032 #include "font.hpp"
00033 
00034 String::String(const sf::Unicode::Text& t, const std::string& f, float s):
00035         font_id(f), text(t), contains_color_reset(false), color(255, 255, 255, 255),
00036         font_ptr(ResourceManager::instance().fonts[f]), billboard(false), size(s)
00037 {
00038         displaylist = glGenLists(1);
00039         make_list();
00040 }
00041 
00042 String::String(const sf::Unicode::Text& t, const std::string& f):
00043         font_id(f), text(t), contains_color_reset(false), color(255, 255, 255, 255),
00044         font_ptr(ResourceManager::instance().fonts[f]), billboard(false),
00045         size(font_ptr->line_height)
00046 {
00047         displaylist = glGenLists(1);
00048         make_list();
00049 }
00050 
00051 void String::make_list()
00052 {
00053         contains_color_reset = false;
00054         bool first = true;
00055         
00056         sf::Vector2i cursor(0, font_ptr->size);
00057         
00058         Font::glyph_t* prev_glyph_ptr = 0;
00059         Font::glyph_t* glyph_ptr = 0;
00060         
00061         glNewList(displaylist, GL_COMPILE);
00062         glBegin(GL_QUADS);
00063         for (size_t i = 0; i < text.length(); ++i)
00064         {
00065                 prev_glyph_ptr = glyph_ptr;
00066                 glyph_ptr = &(font_ptr->glyphs[text[i]]);
00067                 
00068                 switch (text[i])
00069                 {
00070                         case '\n':
00071                         {
00072                                 cursor.x = 0;
00073                                 cursor.y -= font_ptr->line_height;
00074                         }
00075                         break;
00076                         case '\t':
00077                         {
00078                                 cursor.x /= font_ptr->line_height;
00079                                 cursor.x += 1;
00080                                 cursor.x *= font_ptr->line_height;
00081                         }
00082                         break;
00083                         case 0xC:
00084                         {
00085                                 sf::Uint8 r = text[++i];
00086                                 sf::Uint8 g = text[++i];
00087                                 sf::Uint8 b = text[++i];
00088                                 sf::Uint8 a = text[++i];
00089                                 
00090                                 glColor4ub(r, g, b, a);
00091                         }
00092                         break;
00093                         case 0xE:
00094                         {
00095                                 contains_color_reset = true;
00096                                 glColor4ub(color.r, color.g, color.b, color.a);
00097                         }
00098                         break;
00099                         default:
00100                         {
00101                                 if (i > 0) // kerning
00102                                 {
00103                                         for (sf::Uint32 j = 0; j < prev_glyph_ptr->kernings.size(); ++j)
00104                                         {
00105                                                 if (prev_glyph_ptr->kernings[j].first == i)
00106                                                 {
00107                                                         cursor.x -= prev_glyph_ptr->kernings[j].second;
00108                                                         break;
00109                                                 }
00110                                         }
00111                                 }
00112                                 
00113                                 sf::Vector2i fontmap_size(font_ptr->texture_ptr->get_width(),
00114                                         font_ptr->texture_ptr->get_height());
00115                                 
00116                                 int vx;
00117                                 int vy;
00118                                 
00119                                 // BOTTOM LEFT
00120                                 glTexCoord2f((float)glyph_ptr->x / (float)fontmap_size.x,
00121                                         (float)(glyph_ptr->y + glyph_ptr->h) / (float)fontmap_size.y);
00122                                 
00123                                 vx = cursor.x + glyph_ptr->xo;
00124                                 vy = cursor.y - glyph_ptr->h - glyph_ptr->yo;
00125                                 
00126                                 glVertex2i(vx, vy);
00127                                 
00128                                 if (first)
00129                                 {
00130                                         bottom_left.x = vx;
00131                                         bottom_left.y = vy;
00132                                 }
00133                                 else
00134                                 {
00135                                         if (vx < bottom_left.x)
00136                                         {
00137                                                 bottom_left.x = vx;
00138                                         }
00139                                         if (vy < bottom_left.y)
00140                                         {
00141                                                 bottom_left.y = vy;
00142                                         }
00143                                 }
00144                                 
00145                                 // BOTTOM RIGHT
00146                                 glTexCoord2f((float)(glyph_ptr->x + glyph_ptr->w) / (float)fontmap_size.x,
00147                                         (float)(glyph_ptr->y + glyph_ptr->h) / (float)fontmap_size.y);
00148                                 glVertex2i(cursor.x + glyph_ptr->w + glyph_ptr->xo, cursor.y - glyph_ptr->h - glyph_ptr->yo);
00149                                 
00150                                 // TOP RIGHT
00151                                 glTexCoord2f((float)(glyph_ptr->x + glyph_ptr->w) / (float)fontmap_size.x,
00152                                         (float)(glyph_ptr->y) / (float)fontmap_size.y);
00153                                 
00154                                 vx = cursor.x + glyph_ptr->w + glyph_ptr->xo;
00155                                 vy = cursor.y - glyph_ptr->yo;
00156                                 
00157                                 glVertex2i(vx, vy);
00158                                 
00159                                 if (first)
00160                                 {
00161                                         top_right.x = vx;
00162                                         top_right.y = vy;
00163                                 }
00164                                 else
00165                                 {
00166                                         if (vx > top_right.x)
00167                                         {
00168                                                 top_right.x = vx;
00169                                         }
00170                                         if (vy > top_right.y)
00171                                         {
00172                                                 top_right.y = vy;
00173                                         }
00174                                 }
00175                                 
00176                                 // TOP LEFT
00177                                 glTexCoord2f((float)glyph_ptr->x / (float)fontmap_size.x,
00178                                         (float)(glyph_ptr->y) / (float)fontmap_size.y);
00179                                 glVertex2i(cursor.x + glyph_ptr->xo, cursor.y - glyph_ptr->yo);
00180                                 
00181                                 cursor.x += glyph_ptr->xa;
00182                                 
00183                                 first = false;
00184                         }
00185                         break;
00186                 }
00187         }
00188         glEnd();
00189         glEndList();
00190 }
00191 
00192 float String::get_width()
00193 {
00194         return (float)(top_right.x - bottom_left.x) * (float)size / (float)font_ptr->line_height;
00195 }
00196 
00197 float String::get_height()
00198 {
00199         return (float)(top_right.y - bottom_left.y) * (float)size / (float)font_ptr->line_height;
00200 }
00201 
00202 unsigned int String::num_lines()
00203 {
00204         unsigned int ret = 1;
00205         for (size_t i = 0; i < text.size(); ++i)
00206         {
00207                 if (text[i] == '\n')
00208                 {
00209                         ++ret;
00210                 }
00211         }
00212         return ret;
00213 }
00214 
00215 void String::render()
00216 {
00217         ResourceManager::instance().use_program(0);
00218         
00219         font_ptr->texture_ptr->bind();
00220         
00221         glDisable(GL_DEPTH_TEST);
00222         
00223         glPushMatrix();
00224         float scale = (float)size / (float)(font_ptr->line_height);
00225         
00226         if (billboard)
00227         {
00228                 float modelview[16];
00229                 
00230                 glGetFloatv(GL_MODELVIEW_MATRIX, modelview);
00231                 
00232                 for (unsigned int i = 0; i < 3; i++)
00233                 {
00234                         for ( unsigned int j = 0; j < 3; j++)
00235                         {
00236                                 modelview[i * 4 + j] = ((i == j)?(scale / 200.f):0.0f);
00237                         }
00238                 }
00239                 
00240                 glLoadMatrixf(modelview);
00241                 glTranslatef(-get_width() / 2.0f, -get_height() / 2.0f, 0);
00242         }
00243         else
00244         {
00245                 glScalef(scale, scale, 1.0f);
00246         }
00247         glTranslatef(0, (num_lines() - 1) * font_ptr->line_height, 0);
00248         glColor4ub(color.r, color.g, color.b, color.a);
00249         
00250         glCallList(displaylist);
00251         glColor4ub(255, 255, 255, 255);
00252         
00253         glPopMatrix();
00254         glEnable(GL_DEPTH_TEST);
00255 }
00256 
00257 void String::set_text(const sf::Unicode::Text& t)
00258 {
00259         if (text.compare(t) != 0)
00260         {
00261                 text = t;
00262                 make_list();
00263         }
00264 }
00265 
00266 sf::Unicode::Text String::get_text()
00267 {
00268         return text;
00269 }
00270 
00271 void String::set_color(const sf::Color& c)
00272 {
00273         color = c;
00274         
00275         if (contains_color_reset)
00276         {
00277                 make_list();
00278         }
00279 }
00280 
00281 void String::set_color(sf::Uint8 r, sf::Uint8 g, sf::Uint8 b, sf::Uint8 a)
00282 {
00283         color.r = r;
00284         color.g = g;
00285         color.b = b;
00286         color.a = a;
00287         
00288         if (contains_color_reset)
00289         {
00290                 make_list();
00291         }
00292 }
00293 
00294 String::~String()
00295 {
00296         glDeleteLists(displaylist, 1);
00297 }
 Összes Osztályok