Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

frenderer.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2002 Xavier Trochu
00003 
00004 This software is provided 'as-is', without any express or implied warranty. In no event
00005 will the authors be held liable for any damages arising from the use of this software.
00006 
00007 Permission is granted to anyone to use this software for any purpose, including commercial
00008 applications, and to alter it and redistribute it freely, subject to the following
00009 restrictions:
00010 
00011 1. The origin of this software must not be misrepresented; you must not claim that you
00012    wrote the original software. If you use this software in a product, an acknowledgment
00013    in the product documentation would be appreciated but is not required.
00014 
00015 2. Altered source versions must be plainly marked as such, and must not be misrepresented 
00016    as being the original software.
00017 
00018 3. This notice may not be removed or altered from any source distribution.
00019 */
00020 #include <cstring>
00021 #ifdef DEBUG_FONT_RENDERER
00022 #include <iostream>
00023 #endif
00024 #include "frenderer.h"
00025 #include "rect.h"
00026 
00027 using namespace std;
00028 
00029 font_renderer::font_renderer(bool use_original_colors) throw() : _nb_frames(0), _color(-1), _original(use_original_colors)
00030 {
00031 }
00032 
00033 font_renderer::~font_renderer() throw() {
00034     for(vector<char *>::iterator i = _chars.begin(); i != _chars.end(); i++) {
00035         delete [](*i);
00036     }
00037 }
00038 
00039 void font_renderer::save(int frame) {
00040     _nb_frames++;
00041     _sizes.push_back(make_pair(get_width(), get_height()));
00042     int size = get_width()*get_height();
00043     char * copy = new char[size];
00044     memcpy(copy, data(), size);
00045     _chars.push_back(copy);
00046 }
00047 
00048 int font_renderer::char_width(int v) const throw(exception) {
00049     if(v < 0 || v > _nb_frames) throw(runtime_error("invalid character in font_renderer::char_size"));
00050     return _sizes[v].first;
00051 }
00052 
00053 int font_renderer::char_height(int v) const throw(exception) {
00054     if(v < 0 || v > _nb_frames) throw(runtime_error("invalid character in font_renderer::char_size"));
00055     return _sizes[v].second;
00056 }
00057 
00058 int font_renderer::string_width(const string & str) const throw(exception) {
00059     int ret = 0;
00060     string::const_iterator i = str.begin();
00061     while(i != str.end()) {
00062         ret += char_width(*i++);
00063     }
00064     return ret;
00065 }
00066 
00067 int font_renderer::string_height(const string & str) const throw(exception) {
00068     int ret = 0;
00069     string::const_iterator i = str.begin();
00070     while(i != str.end()) {
00071         ret = max(ret, char_height(*i++));
00072     }
00073     return ret;
00074 }
00075 
00076 int font_renderer::draw_char(char * buffer, const point & size, int x, int y, int chr) const throw(exception) {
00077     int w = _sizes[chr].first;
00078     int h = _sizes[chr].second;
00079     //~ cout << "draw_char(" << chr << ", " << pos << " == " << chsize << endl;
00080     char * src = _chars[chr];
00081     char * dst = buffer + size.get_x()*y+x;
00082     if(_original) {
00083         for(int j = 0; j < h; j++) {
00084             for(int i = 0; i < w; i++) {
00085                 int value = *src++;
00086                 if(value) dst[i] = value;
00087             }
00088             dst += size.get_x();
00089         }
00090     } else {
00091         int color = (_color != -1) ? _color : 1;
00092         for(int j = 0; j < h; j++) {
00093             for(int i = 0; i < w; i++) {
00094                 int value = *src++;
00095                 if(value == 1) {
00096                     //~ cout << pos.get_x()+i << ", " << pos.get_y()+j << endl;
00097                     dst[i] = color;
00098                 } else if(value) {
00099                     dst[i] = 0;
00100                 }
00101             }
00102             dst += size.get_x();
00103         }
00104     }
00105     return w;
00106 }
00107 
00108 namespace {
00109     vector<string> split(const string & str, char sep) {
00110         vector<string> ret;
00111         string::size_type i = 0, j = str.find(sep);
00112         while(i != string::npos) {
00113             ret.push_back(string(str, i, j - i));
00114             if(j != string::npos) {
00115                 i = j+1;
00116                 j = str.find(sep, i);
00117             } else 
00118                 i = j;
00119         }
00120         //~ cout << "split == " << ret.size() << endl;
00121         //~ for(int i = 0; i < ret.size(); i++) {
00122             //~ cout << "split[" << i << "] == " << ret[i] << endl;
00123         //~ }
00124         return ret;
00125     }
00126 }
00127 
00128 void font_renderer::draw_substring(const std::string & str, char * buffer, const point & size, int x, int y) const throw(exception)
00129 {
00130 #ifdef DEBUG_FONT_RENDERER
00131     cout << "font_renderer::draw_substring(" << str << "), x == " << x << ", y == " << y << endl;
00132 #endif
00133     for(string::const_iterator i = str.begin(); i != str.end(); i++)
00134         x += draw_char(buffer, size, x, y, *i);
00135 }
00136 
00137 bool font_renderer::draw_string_absolute(const std::string & str, char * buffer, const point & size, int x, int y) const throw(exception) {
00138     draw_substring(str, buffer, size, x, y);
00139     return true;
00140 }
00141 
00142 bool font_renderer::draw_string_centered(const std::string & str, char * buffer, const point & size, int y, int xmin, int width, int offset) const throw(exception) {
00143     //~ cout << "font_renderer::draw_string(" << str << ") == " << r << endl;
00144     vector<string> words = split(str, ' ');
00145     vector<int> sizes(words.size());
00146     for(int i = 0; i < words.size(); i++)
00147         sizes[i] = string_width(words[i]);
00148     int i = 0, max_width = 0, height = 0;
00149     vector<string> substrings;
00150     vector<int> substr_widths;
00151     vector<int> substr_heights;
00152     int space_width = char_width(' ');
00153     while(i < sizes.size()) {
00154         int substr_width = sizes[i];
00155         string substr = words[i];
00156         int j = i + 1;
00157         while(j < sizes.size() && (substr_width + space_width + sizes[j]) < width) {
00158             substr_width += sizes[j++] + space_width;
00159         }
00160         for(int k = i +1; k < j; k++) {
00161             substr += " ";
00162             substr += words[k];
00163         }
00164         substrings.push_back(substr);
00165         substr_widths.push_back(substr_width);
00166         if(substr_width > max_width)
00167             max_width = substr_width;
00168         i = j;
00169         height += string_height(substr);
00170     }
00171     max_width = (max_width + 1) >> 1;
00172     // we have a box from 0 -> max_width
00173     // we want a box from (xmin + offset) - max_width / 2, (xmin + offset) + max_width / 2
00174     int x = xmin + width / 2;
00175     x += offset - size.get_x() / 2;
00176 //  */ + max_width;
00177     if(x < max_width) x = max_width;
00178     if(x + max_width > size.get_x()) {
00179         x = size.get_x() - max_width;
00180     }
00181     if(y + height > size.get_y()) {
00182         y = size.get_y() - height;
00183     }
00184     for(i = 0; i < substrings.size(); i++) {
00185         int substr_width = substr_widths[i];
00186         draw_substring(substrings[i], buffer, size, x - substr_width / 2, y);
00187         y += string_height(substrings[i]);
00188     }
00189     return true;
00190 }

Generated on Fri Aug 9 22:54:29 2002 for san_player by doxygen1.2.16