00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
00121
00122
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
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
00173
00174 int x = xmin + width / 2;
00175 x += offset - size.get_x() / 2;
00176
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 }