00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #include <sstream>
00060
00061 #include "guichan/exception.hpp"
00062 #include "guichan/imagefont.hpp"
00063 #include "guichan/image.hpp"
00064
00065 namespace gcn
00066 {
00067 ImageFont::ImageFont(const std::string& filename, const std::string& glyphs)
00068 {
00069 if (Image::_getImageLoader() == NULL)
00070 {
00071 throw GCN_EXCEPTION("I have no ImageLoader!");
00072 }
00073
00074 ImageLoader* imageLoader = Image::_getImageLoader();
00075 mFilename = filename;
00076 Image::_getImageLoader()->prepare(filename);
00077 Color separator = Image::_getImageLoader()->getPixel(0, 0);
00078
00079 int i = 0;
00080 for (i=0; separator == imageLoader->getPixel(i, 0)
00081 && i < imageLoader->getWidth(); ++i)
00082 {
00083 }
00084
00085 if (i >= imageLoader->getWidth())
00086 {
00087 throw GCN_EXCEPTION("Corrupt image.");
00088 }
00089
00090 int j = 0;
00091 for (j = 0; j < imageLoader->getHeight(); ++j)
00092 {
00093 if (separator == imageLoader->getPixel(i, j))
00094 {
00095 break;
00096 }
00097 }
00098
00099 mHeight = j;
00100 int x = 0, y = 0;
00101 unsigned char k;
00102
00103 for (i=0; i < (int)glyphs.size(); ++i)
00104 {
00105 k = glyphs.at(i);
00106 addGlyph(k, x, y, separator);
00107 }
00108
00109 int w = imageLoader->getWidth();
00110 int h = imageLoader->getHeight();
00111 void* data = imageLoader->finalize();
00112
00113 mImage = new Image(data, w, h);
00114 mRowSpacing = 0;
00115 mGlyphSpacing = 0;
00116 }
00117
00118 ImageFont::ImageFont(const std::string& filename, unsigned char glyphsFrom, unsigned char glyphsTo)
00119 {
00120 if (Image::_getImageLoader() == NULL)
00121 {
00122 throw GCN_EXCEPTION("I have no ImageLoader!");
00123 }
00124
00125 ImageLoader* imageLoader = Image::_getImageLoader();
00126 mFilename = filename;
00127 Image::_getImageLoader()->prepare(filename);
00128 Color separator = Image::_getImageLoader()->getPixel(0, 0);
00129
00130 int i = 0;
00131 for (i=0; separator == imageLoader->getPixel(i, 0)
00132 && i < imageLoader->getWidth(); ++i)
00133 {
00134 }
00135
00136 if (i >= imageLoader->getWidth())
00137 {
00138 throw GCN_EXCEPTION("Corrupt image.");
00139 }
00140
00141 int j = 0;
00142 for (j = 0; j < imageLoader->getHeight(); ++j)
00143 {
00144 if (separator == imageLoader->getPixel(i, j))
00145 {
00146 break;
00147 }
00148 }
00149
00150 mHeight = j;
00151 int x = 0, y = 0;
00152 unsigned char k;
00153
00154 for (i=glyphsFrom; i<glyphsTo+1; i++)
00155 {
00156 addGlyph(i, x, y, separator);
00157 }
00158
00159 int w = imageLoader->getWidth();
00160 int h = imageLoader->getHeight();
00161 void* data = imageLoader->finalize();
00162
00163 mImage = new Image(data, w, h);
00164 mRowSpacing = 0;
00165 mGlyphSpacing = 0;
00166 }
00167
00168 ImageFont::~ImageFont()
00169 {
00170 Image::_getImageLoader()->free(mImage);
00171 delete mImage;
00172 }
00173
00174 int ImageFont::getWidth(unsigned char glyph) const
00175 {
00176 if (mGlyph[glyph].width == 0)
00177 {
00178 return mGlyph[(int)(' ')].width + mGlyphSpacing;
00179 }
00180
00181 return mGlyph[glyph].width + mGlyphSpacing;
00182 }
00183
00184 int ImageFont::getHeight() const
00185 {
00186 return mHeight + mRowSpacing;
00187 }
00188
00189 int ImageFont::drawGlyph(Graphics* graphics, unsigned char glyph, int x, int y)
00190 {
00191
00192 int yoffset = getRowSpacing() >> 1;
00193
00194 if (mGlyph[glyph].width == 0)
00195 {
00196 graphics->drawRectangle(Rectangle(x, y + 1 + yoffset, mGlyph[(int)(' ')].width - 1,
00197 mGlyph[(int)(' ')].height - 2));
00198
00199 return mGlyph[(int)(' ')].width + mGlyphSpacing;
00200 }
00201
00202 graphics->drawImage(mImage, mGlyph[glyph].x, mGlyph[glyph].y, x,
00203 y + yoffset, mGlyph[glyph].width, mGlyph[glyph].height);
00204
00205 return mGlyph[glyph].width + mGlyphSpacing;
00206 }
00207
00208 void ImageFont::drawString(Graphics* graphics, const std::string& text, int x, int y)
00209 {
00210 unsigned int i;
00211
00212 for (i = 0; i< text.size(); ++i)
00213 {
00214 drawGlyph(graphics, text.at(i), x, y);
00215 x += getWidth(text.at(i));
00216 }
00217 }
00218
00219 void ImageFont::setRowSpacing(int spacing)
00220 {
00221 mRowSpacing = spacing;
00222 }
00223
00224 int ImageFont::getRowSpacing()
00225 {
00226 return mRowSpacing;
00227 }
00228
00229 void ImageFont::setGlyphSpacing(int spacing)
00230 {
00231 mGlyphSpacing = spacing;
00232 }
00233
00234 int ImageFont::getGlyphSpacing()
00235 {
00236 return mGlyphSpacing;
00237 }
00238
00239 void ImageFont::addGlyph(unsigned char c, int &x,
00240 int &y, const Color& separator)
00241 {
00242 ImageLoader* il = Image::_getImageLoader();
00243
00244 Color color;
00245 do
00246 {
00247 ++x;
00248
00249 if (x >= il->getWidth())
00250 {
00251 y += mHeight + 1;
00252 x = 0;
00253
00254 if (y >= il->getHeight())
00255 {
00256 std::string str;
00257 std::ostringstream os(str);
00258 os << "Image ";
00259 os << mFilename;
00260 os << " with font is corrupt near character '";
00261 os << c;
00262 os << "'";
00263 throw GCN_EXCEPTION(os.str());
00264 }
00265 }
00266
00267 color = il->getPixel(x, y);
00268
00269 } while (color == separator);
00270
00271 int w = 0;
00272
00273 do
00274 {
00275 ++w;
00276
00277 if (x+w >= il->getWidth())
00278 {
00279 std::string str;
00280 std::ostringstream os(str);
00281 os << "Image ";
00282 os << mFilename;
00283 os << " with font is corrupt near character '";
00284 os << c;
00285 os << "'";
00286 throw GCN_EXCEPTION(os.str());
00287 }
00288
00289 color = il->getPixel(x + w, y);
00290
00291 } while (color != separator);
00292
00293 mGlyph[c] = Rectangle(x, y, w, mHeight);
00294
00295 x += w;
00296 }
00297
00298 int ImageFont::getWidth(const std::string& text) const
00299 {
00300 unsigned int i;
00301 int size = 0;
00302
00303 for (i = 0; i < text.size(); ++i)
00304 {
00305 size += getWidth(text.at(i));
00306 }
00307
00308 return size;
00309 }
00310
00311 int ImageFont::getStringIndexAt(const std::string& text, int x)
00312 {
00313 unsigned int i;
00314 int size = 0;
00315
00316 for (i = 0; i < text.size(); ++i)
00317 {
00318 size += getWidth(text.at(i));
00319
00320 if (size > x)
00321 {
00322 return i;
00323 }
00324 }
00325
00326 return text.size();
00327 }
00328 }