00001 #ifdef WIN32
00002 #pragma warning(disable : 4786 )
00003 #endif
00004 #include "CSFont.h"
00005 #include "CSXMLHelper.h"
00006
00007 using namespace std;
00008
00009 CSFontLoader CSFontLoader::INSTANCE;
00010 const char *CSFont::CLASS = "CSFont";
00011 CSFonts CSFont::mAllFonts;
00012
00013
00014 CSFont::CSFont(const std::string &filename)
00015 {
00016 static char *functionName="CSFont";
00017 LOG_ENTER
00018 mKey = -1;
00019 mPicture = 0;
00020 mFilename = 0;
00021
00022 mSpaceWidth = 0;
00023 mH = -1;
00024 mId = 0;
00025 CSFontData data;
00026 loadFontData(filename, data);
00027 initialize(data);
00028 addFont(this);
00029 LOG_EXIT
00030 }
00031
00032 void CSFont::initialize(const CSFontData &data)
00033 {
00034 static char *functionName="initialize";
00035 LOG_ENTER
00036
00037
00038 mId = strdup(data.id);
00039 mPicture = CSPictureLoader::INSTANCE.load(data.filename);
00040 mPicture->getRGB(mR,mG,mB);
00041 mFilename = strdup(data.filename);
00042
00043 int x = 0, i = 0;
00044 if (SDL_MUSTLOCK(mPicture->getSurface()))
00045 {
00046 SDL_LockSurface(mPicture->getSurface());
00047 }
00048 while ( x < mPicture->getSurface()->w )
00049 {
00050 if (SDLMain::getPixel(mPicture->getSurface(),x,0) == SDL_MapRGB(mPicture->getSurface()->format,255,0,255))
00051 {
00052 mCharPos[i++]=x;
00053
00054 while ( ( x < mPicture->getSurface()->w-1) && (SDLMain::getPixel(mPicture->getSurface(),x,0) ==SDL_MapRGB(mPicture->getSurface()->format,255,0,255)) )
00055 {
00056 x++;
00057 }
00058 mCharPos[i++]=x;
00059 }
00060 x++;
00061 }
00062 if (SDL_MUSTLOCK(mPicture->getSurface()))
00063 {
00064 SDL_UnlockSurface(mPicture->getSurface());
00065 }
00066 mH = mPicture->getSurface()->h;
00067
00068
00069 mSpaceWidth = mCharPos[('n'-33)*2+1+1] - mCharPos[('n'-33)*2+1];
00070 mMonoSpaced = data.monospaced;
00071 LOG_EXIT
00072 }
00073
00074 CSFont::~CSFont()
00075 {
00076 static char *functionName="~CSFont";
00077 LOG_ENTER
00078 removeFont(this);
00079 if (mFilename)
00080 {
00081 free(mFilename);
00082 mFilename = 0;
00083 }
00084 if (mId)
00085 {
00086 free(mId);
00087 mId = 0;
00088 }
00089
00090
00091 deleteColorFonts();
00092 LOG_EXIT
00093 }
00094
00095 void CSFont::setSolid(bool b)
00096 {
00097 static char *functionName="setSolid";
00098 if (mPicture == 0)
00099 {
00100 return;
00101 }
00102 mPicture->setSolid(b);
00103 }
00104
00105
00106 void CSFont::loadFontData(const std::string &filename, CSFontData &data)
00107 {
00108 static char *functionName="loadFontData";
00109 LOG_ENTER
00110 CSXMLHelper xmlSupport(filename, "FONT");
00111 try
00112 {
00113 if (xmlSupport.getError())
00114 {
00115 LOG_EXIT
00116 throw "error";
00117 }
00118
00119 data.id = strdup(xmlSupport.getString("ID").c_str());
00120 data.filename = strdup(xmlSupport.getString("PICTURE").c_str());
00121 data.monospaced = xmlSupport.getInt("MONO_SPACED");
00122 }
00123 catch(...)
00124 {
00125 LOG_EXIT
00126 SDLMain::shutdown((std::string)"XML error \"" + filename + "\": " + xmlSupport.getErrorMessage().c_str(), 1);
00127 }
00128 LOG_EXIT
00129 }
00130
00131 void CSFont::putString(SDL_Surface *surface, int x, int y, const char *text)
00132 {
00133 static char *functionName="putString";
00134 int ofs;
00135 int i=0;
00136 SDL_Rect srcrect,dstrect;
00137 int sx = x;
00138 int sy = y;
00139 srcrect.y = 1;
00140 dstrect.y = y;
00141 srcrect.h = dstrect.h = mPicture->getSurface()->h-1;
00142 while (text[i]!='\0')
00143 {
00144 dstrect.y = y;
00145
00146 if (text[i] <32)
00147 {
00148 i++;
00149 continue;
00150 }
00151 if (text[i]==' ')
00152 {
00153 dstrect.x = x;
00154 dstrect.w = mSpaceWidth;
00155 x+=dstrect.w;
00156 if (mPicture->isSolid())
00157 {
00158 SDL_FillRect(surface, &dstrect, mPicture->getColorKey());
00159 }
00160 i++;
00161 }
00162 else
00163 {
00164 ofs= (text[i]-33)*2+1;
00165
00166 srcrect.x = mCharPos[ofs];
00167 dstrect.x = x;
00168 srcrect.w = dstrect.w = mCharPos[ofs+1] - mCharPos[ofs];
00169 x+=dstrect.w;
00170
00171 SDL_BlitSurface(mPicture->getSurface(), &srcrect, surface, &dstrect);
00172
00173 i++;
00174 }
00175 }
00176
00177 SDL_Rect mUpdateRegion;
00178 mUpdateRegion.x = sx;
00179 mUpdateRegion.y = sy;
00180 mUpdateRegion.w = dstrect.x + srcrect.w;
00181 mUpdateRegion.h = dstrect.h;
00182 SDLMain::addUpdateRect(mUpdateRegion);
00183 }
00184
00185 int CSFont::getWidth(const char *text)
00186 {
00187 static char *functionName="getWidth";
00188 int ofs=0;
00189 int i=0,x=0;
00190
00191 while (text[i]!='\0')
00192 {
00193 if (text[i]==' ')
00194 {
00195 x+=mSpaceWidth;
00196 i++;
00197 }
00198 else
00199 {
00200 ofs=(text[i]-33)*2+1;
00201 if (ofs < 0) break;
00202 x+=mCharPos[ofs+1]-mCharPos[ofs];
00203 i++;
00204 }
00205 }
00206 return x;
00207 }
00208
00209 void CSFont::xCenteredString(SDL_Surface *surface, int y, const char *text)
00210 {
00211 static char *functionName="xCenteredString";
00212 putString(surface, surface->w/2-getWidth(text)/2, y, text);
00213 }
00214
00215
00216 void CSFont::inputText(SDL_Surface *dest, int x, int y, int w, char *text)
00217 {
00218 static char *functionName="inputText";
00219 LOG_ENTER
00220 SDL_Event event;
00221 int ch=-1,blink=0;
00222 long blinktimer=0;
00223 SDL_Surface *back;
00224 SDL_Rect rect;
00225 int previous;
00226
00227 back = SDL_AllocSurface(dest->flags,
00228 dest->w,
00229 mH,
00230 dest->format->BitsPerPixel,
00231 dest->format->Rmask,
00232 dest->format->Gmask,
00233 dest->format->Bmask, 0);
00234 rect.x=0;
00235 rect.y=y;
00236 rect.w=dest->w;
00237 rect.h=mPicture->getSurface()->h;
00238 SDL_BlitSurface(dest, &rect, back, NULL);
00239 putString(dest,x,y,text);
00240 SDL_UpdateRects(dest, 1, &rect);
00241
00242
00243 previous=SDL_EnableUNICODE(1);
00244 blinktimer=SDL_GetTicks();
00245 SDL_PollEvent(&event);
00246 while (ch!=SDLK_RETURN)
00247 {
00248 if (event.type==SDL_KEYDOWN)
00249 {
00250 ch=event.key.keysym.unicode;
00251 if (((ch>31)||(ch=='\b')) && (ch<128))
00252 {
00253 if ((ch=='\b')&&(strlen(text)>0))
00254 {
00255 text[strlen(text)-1]='\0';
00256 }
00257 else if (ch!='\b')
00258 {
00259 sprintf(text,"%s%c",text,ch);
00260 }
00261 if (getWidth(text)>w)
00262 {
00263 text[strlen(text)-1]='\0';
00264 }
00265 SDL_BlitSurface( back, NULL, dest, &rect);
00266 putString(dest, x, y, text);
00267 SDL_UpdateRects(dest, 1, &rect);
00268 SDL_WaitEvent(&event);
00269 }
00270 }
00271 if (SDL_GetTicks()>blinktimer)
00272 {
00273 blink=1-blink;
00274 blinktimer=SDL_GetTicks()+500;
00275 if (blink)
00276 {
00277 putString(dest, x+getWidth(text), y, "|");
00278 SDL_UpdateRects(dest, 1, &rect);
00279 }
00280 else
00281 {
00282 SDL_BlitSurface( back, NULL, dest, &rect);
00283 putString(dest, x, y, text);
00284 SDL_UpdateRects(dest, 1, &rect);
00285 }
00286 }
00287 SDL_Delay(1);
00288 SDL_PollEvent(&event);
00289 }
00290 text[strlen(text)]='\0';
00291 SDLMain::freeSurface(back);
00292 SDL_EnableUNICODE(previous);
00293 LOG_EXIT
00294 }
00295
00296 void CSFont::putString(SDL_Surface *surface, int x, int y, int color, const char *text, int style)
00297 {
00298 static char *functionName="putString";
00299 bool isNewColor = true;
00300 SDL_Surface *fontPicture = 0;
00301 if (color == mKey)
00302
00303
00304 {
00305 color = color + 0x010101;
00306 }
00307
00308 ColorFontMap::iterator iter = mColorFontMap.find(color);
00309 if (iter != mColorFontMap.end())
00310 {
00311 fontPicture = iter->second;
00312 isNewColor = false;
00313 }
00314 else
00315 {
00316 SDL_Rect rect;
00317 rect.x = 0;
00318 rect.y = 0;
00319 rect.w = mPicture->getSurface()->w;
00320 rect.h = mPicture->getSurface()->h;
00321
00322 int flags = SDLMain::getScreen()->flags;
00323 if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE)
00324 {
00325 flags -= SDL_HWSURFACE;
00326 }
00327 if ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)
00328 {
00329 flags -= SDL_DOUBLEBUF;
00330 }
00331 if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN)
00332 {
00333 flags -= SDL_FULLSCREEN;
00334 }
00335
00336 fontPicture = SDL_CreateRGBSurface(flags,
00337 rect.w,
00338 rect.h,
00339 SDLMain::getScreen()->format->BitsPerPixel,
00340 SDLMain::getScreen()->format->Rmask,
00341 SDLMain::getScreen()->format->Gmask,
00342 SDLMain::getScreen()->format->Bmask,
00343 SDLMain::getScreen()->format->Amask);
00344 if (SDL_BlitSurface(mPicture->getSurface(), &rect, fontPicture, 0) < 0)
00345 {
00346 SDLMain::shutdown((std::string)"Display Format error: " + SDL_GetError(), 1);
00347 }
00348 mKey = SDL_MapRGB(fontPicture->format, mR, mG, mB);
00349 SDL_SetColorKey(fontPicture, SDL_SRCCOLORKEY, mKey);
00350 mColorFontMap.insert(ColorFontMap::value_type(color, fontPicture));
00351 }
00352
00353 if (isNewColor)
00354 {
00355 int newColor = COLOR(fontPicture, color);
00356 int x,y;
00357
00358 if (SDL_MUSTLOCK(fontPicture))
00359 {
00360 SDL_LockSurface(fontPicture);
00361 }
00362 for (y=0;y<fontPicture->h; y++)
00363 {
00364 for (x=0;x<fontPicture->w; x++)
00365 {
00366 int color = SDLMain::getPixel(fontPicture,x,y);
00367
00368 if (color != mKey)
00369 {
00370 SDLMain::setPixel(fontPicture,x,y,newColor);
00371 }
00372 }
00373 }
00374 if (SDL_MUSTLOCK(fontPicture))
00375 {
00376 SDL_UnlockSurface(fontPicture);
00377 }
00378 }
00379
00380 int sx = x;
00381 int sy = y;
00382 SDL_Rect srcrect,dstrect;
00383 int ofs;
00384 int i=0;
00385 if (!((style & FONT_STYLE_ITALIC) == FONT_STYLE_ITALIC))
00386 {
00387 srcrect.y = 1;
00388 srcrect.h = dstrect.h = fontPicture->h-1;
00389 while (text[i]!='\0')
00390 {
00391 dstrect.y = y;
00392
00393 if (text[i] <32)
00394 {
00395 i++;
00396 continue;
00397 }
00398 if (text[i]==' ')
00399 {
00400 dstrect.x = x;
00401 dstrect.w = mSpaceWidth;
00402 if (mPicture->isSolid())
00403 {
00404 SDL_FillRect(surface, &dstrect, mKey);
00405 }
00406 if ((style & FONT_STYLE_UNDERLINE) == FONT_STYLE_UNDERLINE)
00407 {
00408 SDLMain::line(surface, x, y + srcrect.h -1 , x + mSpaceWidth, y + srcrect.h-1, (color<<8)+255);
00409 }
00410 x += mSpaceWidth;
00411 i++;
00412 }
00413 else
00414 {
00415 ofs= (text[i]-33)*2+1;
00416
00417 srcrect.x = mCharPos[ofs];
00418 dstrect.x = x;
00419 srcrect.w = dstrect.w = mCharPos[ofs+1] - mCharPos[ofs];
00420 SDL_Rect copyDest = dstrect;
00421
00422 SDL_BlitSurface(fontPicture, &srcrect, surface, &dstrect);
00423 if ((style & FONT_STYLE_BOLD) == FONT_STYLE_BOLD)
00424 {
00425 copyDest.x += 1;
00426 SDL_BlitSurface(fontPicture, &srcrect, surface, ©Dest);
00427 }
00428 if ((style & FONT_STYLE_UNDERLINE) == FONT_STYLE_UNDERLINE)
00429 {
00430 SDLMain::line(surface, x, y + srcrect.h -1 , x + srcrect.w, y + srcrect.h-1, (color<<8)+255);
00431 }
00432 x+=srcrect.w;
00433 i++;
00434 }
00435
00436 }
00437 }
00438 else
00439 {
00440 srcrect.y = 1;
00441 srcrect.h = dstrect.h = fontPicture->h-1;
00442 while (text[i]!='\0')
00443 {
00444 dstrect.y = y;
00445
00446 if (text[i] <32)
00447 {
00448 i++;
00449 continue;
00450 }
00451 if (text[i]==' ')
00452 {
00453 dstrect.x = x;
00454 dstrect.w = mSpaceWidth;
00455 if (mPicture->isSolid())
00456 {
00457 SDL_FillRect(surface, &dstrect, mKey);
00458 }
00459 if ((style & FONT_STYLE_UNDERLINE) == FONT_STYLE_UNDERLINE)
00460 {
00461 SDLMain::line(surface, x, y + (fontPicture->h-1) -1 , x + mSpaceWidth, y + (fontPicture->h-1) -1, (color<<8)+255);
00462 }
00463 x += mSpaceWidth;
00464 i++;
00465 }
00466 else
00467 {
00468 ofs= (text[i]-33)*2+1;
00469 int many = 6;
00470 int addy = (fontPicture->h-1+(many-1))/many;
00471 srcrect.h = dstrect.h = addy;
00472
00473 for (int ii = 0; ii< many; ii++)
00474 {
00475 srcrect.y = 1 + (ii*addy);
00476 dstrect.y = y + (ii*addy);
00477
00478 srcrect.h = dstrect.h = addy;
00479 srcrect.x = mCharPos[ofs];
00480 dstrect.x = x+((many-1)-ii);
00481 srcrect.w = dstrect.w = mCharPos[ofs+1] - mCharPos[ofs];
00482 SDL_Rect copyDest = dstrect;
00483
00484 SDL_BlitSurface(fontPicture, &srcrect, surface, &dstrect);
00485 if ((style & FONT_STYLE_BOLD) == FONT_STYLE_BOLD)
00486 {
00487 copyDest.x += 1;
00488 SDL_BlitSurface(fontPicture, &srcrect, surface, ©Dest);
00489 }
00490 }
00491 if ((style & FONT_STYLE_UNDERLINE) == FONT_STYLE_UNDERLINE)
00492 {
00493 SDLMain::line(surface, x, y + (fontPicture->h-1) -1 , x + srcrect.w, y + (fontPicture->h-1)-1, (color<<8)+255);
00494 }
00495 i++;
00496 x+=srcrect.w;
00497 }
00498 }
00499 }
00500 SDL_Rect mUpdateRegion;
00501 mUpdateRegion.x = sx;
00502 mUpdateRegion.y = sy;
00503 mUpdateRegion.w = dstrect.x + srcrect.w;
00504 mUpdateRegion.h = dstrect.h;
00505 SDLMain::addUpdateRect(mUpdateRegion);
00506 }
00507
00508 void CSFont::resetSurface()
00509 {
00510 static char *functionName="resetSurface";
00511 LOG_ENTER
00512 deleteColorFonts();
00513 }
00514
00515
00516
00517
00518 void CSFont::addFont(CSFont *font)
00519 {
00520 if (font == 0)
00521 {
00522 return;
00523 }
00524 removeFont(font);
00525 mAllFonts.push_back(font);
00526 }
00527
00528 void CSFont::removeFont(CSFont *font)
00529 {
00530 if (font == 0)
00531 {
00532 return;
00533 }
00534
00535 CSFonts::iterator iter = mAllFonts.begin();
00536 while ( iter != mAllFonts.end())
00537 {
00538 if ((*iter) == font)
00539 {
00540 mAllFonts.erase(iter);
00541 iter = mAllFonts.begin();
00542 }
00543 else
00544 {
00545 iter++;
00546 }
00547 }
00548 }
00549
00550
00551 void CSFont::resetSurfaces()
00552 {
00553 static char *functionName="resetSurfaces";
00554 LOG_ENTER
00555 CSFonts::iterator iter = mAllFonts.begin();
00556 while ( iter != mAllFonts.end())
00557 {
00558 (*iter)->resetSurface();
00559 iter++;
00560 }
00561 LOG_EXIT
00562 }