Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

CSFont.cpp

Go to the documentation of this file.
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 //! constructor using "*.pic" file
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     // picture muss geladen werden
00037     // Load the BMP file into a surface 
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     // width of a space is like - 'n'
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     // picture is singleton - not freed
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;  // with resetting of y, the y pos of the string is not altered if 
00145                         // partial printing is done out of bounds (clipped)
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;     // has position and size
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 // untested
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     // start input
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);  //restore the previous state
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)  // cheating here - but I cant' be bothered to make it
00302                         // exact - transaparent color should allways be different
00303                         // from the font color!!!
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;  // with resetting of y, the y pos of the string is not altered if 
00392                             // partial printing is done out of bounds (clipped)
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, &copyDest); 
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 // FONT_STYLE_ITALIC
00439     {
00440         srcrect.y = 1;
00441         srcrect.h = dstrect.h = fontPicture->h-1;
00442         while (text[i]!='\0') 
00443         {
00444             dstrect.y = y;  // with resetting of y, the y pos of the string is not altered if 
00445                             // partial printing is done out of bounds (clipped)
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, &copyDest); 
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;     // has position and size
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 // static stuff to enable converting fonts to and from fullscreen
00516 // all fonts ever loaded from disc are remembered in the Vector "mAllFonts"
00517 // (only neccessary for "color" putString())
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();   // restart to be absolutly save!
00542         }
00543         else
00544         {
00545             iter++;
00546         }
00547     }
00548 }
00549 
00550 // resets all surfaces
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 }

Generated on Wed Jul 14 00:43:29 2004 for CSLib by doxygen 1.3.6