00001
00002
00003
00004
#include "SFontLoader.h"
00005
00006
#include <iostream>
00007
#include <fstream>
00008
00009
using namespace std;
00010
00011
00012 SFontLoader::SFontLoader()
00013 {
00014 fontData_ = 0;
00015 alphaR_ = 0;
00016 alphaG_ = 0;
00017 alphaB_ = 0;
00018 alphaType_ =
GREY_COLOUR;
00019 seperatorR_ = 255;
00020 seperatorG_ = 0;
00021 seperatorB_ = 255;
00022 fontDefinition_ =
"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
00023
for (
int i=0; i<256; i++){
00024 fontGfxTiles[i] = 0;
00025 charWidth_[i] = -1;
00026 }
00027 }
00028
00029 SFontLoader::~SFontLoader()
00030 {
00031 unloadGfx();
00032 }
00033
00034
00035 void SFontLoader::loadFont(
const string &name)
00036 {
00037 unloadGfx();
00038
00039 fontData_ = loadPpm(name, fontDataWidth_, fontDataHeight_);
00040
00041
for (
int i=0; i<256; i++){
00042 fontGfxTiles[i] = 0;
00043 charWidth_[i] = -1;
00044 }
00045
00046
00047
if (fontData_ !=0){
00048 findCellSizes();
00049
00050 numberOfCharsInFont_ = fontDefinition_.size();
00051
00052
unsigned char *fontDataBuffer = fontData_;
00053
00054
while(isSpaceColour(fontDataBuffer)){
00055 fontDataBuffer+=4;
00056 }
00057 findCharWidths(fontDataBuffer);
00058
00059
for (
unsigned int i = 0; i!=fontDefinition_.size(); i++){
00060
unsigned char character = (
unsigned char)fontDefinition_[i];
00061 charWidth_[character] = definitionFontWidths_[i];
00062
00063 fontGfxTiles[character] =
00064 (
unsigned char*)malloc(fontCellWidth_*fontCellHeight_*4);
00065
if (fontGfxTiles[character]==0)
throw
00066 string(
"Failed to reserve memory for font data buffer");
00067
00068 loadCharacter(i, fontDataBuffer, fontGfxTiles[character]);
00069
00070 }
00071 }
00072
else throw string(
"Failed to open font image: ")+name;
00073
00074 }
00075
00076
void SFontLoader::findCharWidths(
unsigned char *result)
00077 {
00078
for (
int i = 0; i != numberOfCharsInFont_; i++){
00079 definitionFontWidths_[i] = 0;
00080
while(!isSpaceColour(result)){
00081 result+=4;
00082 definitionFontWidths_[i]++;
00083 }
00084
while(isSpaceColour(result)){
00085 result+=4;
00086 }
00087 definitionFontWidths_[i]--;
00088
00089 }
00090
00091 }
00092
00093
void SFontLoader::loadCharacter(
unsigned char number,
00094
unsigned char *inputData,
00095
unsigned char *outputData)
00096 {
00097
00098
for (
int i = 0; i != number; i++){
00099
while(!isSpaceColour(inputData)){
00100 inputData+=4;
00101 }
00102
while(isSpaceColour(inputData)){
00103 inputData+=4;
00104 }
00105 }
00106 inputData += fontDataWidth_*4;
00107
00108 memset(outputData, 0, fontCellHeight_*fontCellWidth_*4);
00109
00110
00111
unsigned char *inputBuffer = inputData;
00112
unsigned char *outputBuffer = outputData;
00113
int width = (
int)definitionFontWidths_[number];
00114
00115
for (
int y=0; y != fontDataHeight_-1; y++){
00116
for (
int x=0; x != width; x++){
00117 *outputBuffer = inputBuffer[0];
00118 outputBuffer++;
00119 *outputBuffer = inputBuffer[1];
00120 outputBuffer++;
00121 *outputBuffer = inputBuffer[2];
00122 outputBuffer++;
00123 *outputBuffer = inputBuffer[3];
00124 outputBuffer++;
00125 inputBuffer+=4;
00126 }
00127 inputData += fontDataWidth_*4;
00128 inputBuffer = inputData;
00129 outputBuffer = outputData + fontCellWidth_*4*(y+1);
00130 }
00131 }
00132
00133
void SFontLoader::readNumber(ifstream &file,
int &number)
00134 {
00135
char c[1];
00136
00137 file.read((
char*)c,1);
00138
while ((*c<'0' || *c>
'9') && !file.bad()){
00139 file.read((
char*)c,1);
00140 }
00141 number =0;
00142
while ((*c>=
'0' && *c<=
'9') && !file.bad()){
00143 number = number *10 +*c-
'0';
00144 file.read((
char*)c,1);
00145 }
00146 }
00147
00148
unsigned char *SFontLoader::loadPpm(
const string &fileName,
int &width,
00149
int &height)
00150 {
00151
unsigned char *result=0, *buf;
00152
unsigned char id[5];
00153
int scale=0;
00154
long count;
00155 ifstream infile (fileName.c_str(), ifstream::binary);
00156
if (!infile)
throw string(
"File IO error, could not open ppm file: ")
00157 +fileName;
00158 infile.read((
char*)
id,2);
00159
00160
if (
id[0]==
'P' ||
id[1]==
'6') {
00161 readNumber(infile, width);
00162 readNumber(infile, height);
00163 readNumber(infile, scale);
00164 cout <<
"'"<< width <<
"'"<< height<<
"'"<<scale<<endl;
00165
00166
if (scale==255){
00167 result = (
unsigned char*)malloc(width*height*4);
00168
if (result!=0){
00169 buf=result;
00170
for (count=0; count != width*height; count++){
00171
if (infile.bad())
throw string(
"File IO error");
00172
00173
id[0] =10;
00174
id[1] =10;
00175
id[2] =10;
00176
00177 infile.read((
char*)
id,3);
00178
if(infile.gcount() != 3 || infile.eof())
00179
throw string(
"Read error in PPM file.");
00180 buf[0] =
id[0];
00181 buf[1] =
id[1];
00182 buf[2] =
id[2];
00183
00184
switch (alphaType_){
00185
case NONE:
00186 buf[3] = 255;
00187
break;
00188
case BLACK_MASK:
00189
if (
id[0] == 0 &&
id[1] == 0 &&
id[2] == 0){
00190 buf[3] = 0;
00191 }
00192
else {
00193 buf[3]= 255;
00194 }
00195
break;
00196
case GREY_COLOUR:
00197
unsigned int alpha;
00198 alpha =
id[0] +
id[1] +
id[2];
00199 alpha /= 3;
00200 buf[3] = (
unsigned char)alpha;
00201 }
00202 buf+=4;
00203
00204 }
00205 }
00206
else throw string (
"Out of memory");
00207 }
00208
else {
00209
throw string (
00210
"SFontloader ppm load only supports ppm images with 256 colours per channel"
00211 );
00212 }
00213 }
00214 infile.close();
00215
00216
return result;
00217 }
00218
00219
00220
void SFontLoader::findCellSizes()
00221 {
00222
int largestWidth=0;
00223
int currentWidth=0;
00224
unsigned char *fontData = fontData_+4;
00225
for (
int i=1; i<fontDataWidth_-1; i++){
00226
if (!isSpaceColour(fontData)){
00227 currentWidth++;
00228
if (currentWidth > largestWidth){
00229 largestWidth = currentWidth;
00230 }
00231 }
00232
else currentWidth=0;
00233 fontData+=4;
00234 }
00235
00236 fontCellHeight_ = 1;
00237
while (fontCellHeight_ < fontDataHeight_-1){
00238 fontCellHeight_*=2;
00239 }
00240 fontCellWidth_ = 1;
00241
while (fontCellWidth_ < largestWidth){
00242 fontCellWidth_*=2;
00243 }
00244 }
00245
00246
void SFontLoader::unloadGfx()
00247 {
00248
if (fontData_ != 0){
00249 free (fontData_);
00250 fontData_ = 0;
00251 }
00252
00253
for (
int i=0; i<256; i++){
00254
if (fontGfxTiles[i] != 0){
00255 free (fontGfxTiles[i]);
00256 fontGfxTiles[i] = 0;
00257 }
00258 charWidth_[i] = -1;
00259 }
00260 }
00261
00262 unsigned char *
SFontLoader::getDataForCharacter(
char character)
00263 {
00264
return fontGfxTiles[(
unsigned char) character];
00265 }
00266
00267 int SFontLoader::getCharacterWidth(
char character)
00268 {
00269
return charWidth_[(
unsigned char) character];
00270 }