Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

pgsurfacecache.cpp

Go to the documentation of this file.
00001 /*
00002     ParaGUI - crossplatform widgetset
00003     Copyright (C) 2000,2001,2002  Alexander Pipelka
00004  
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009  
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014  
00015     You should have received a copy of the GNU Library General Public
00016     License along with this library; if not, write to the Free
00017     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  
00019     Alexander Pipelka
00020     pipelka@teleweb.at
00021  
00022     Last Update:      $Author: mbickel $
00023     Update Date:      $Date: 2007-04-13 16:16:00 $
00024     Source File:      $Source: /home/cvspsrv/cvsroot/games/asc/source/libs/paragui/src/core/pgsurfacecache.cpp,v $
00025     CVS/RCS Revision: $Revision: 1.2 $
00026     Status:           $State: Exp $
00027 */
00028 
00029 #include "paragui.h"
00030 
00031 #include <iostream>
00032 #include <cstring>
00033 #include <string>
00034 #include <cassert>
00035 
00036 #include "pgsurfacecache.h"
00037 #include "pglog.h"
00038 
00039 #ifdef HASH_MAP_INC
00040 #include HASH_MAP_INC
00041 #else
00042 #include <map>
00043 #endif
00044 
00045 #define MY_SURFACEMAP ((pg_surfacemap_t*)my_surfacemap)
00046 #define MY_SURFACEINDEX ((pg_surfacemap_index_t*)my_surfacemap_index)
00047 
00048 #ifdef HASH_MAP_INC
00049 
00050 struct pg_surface_hash {
00051         size_t operator()(std::string s1) const {
00052                 unsigned long hash = 0;
00053                 for(Uint32 i = 0; i < s1.length(); i++) {
00054                         hash = 5*hash + s1[i];
00055                 }
00056                 return hash;
00057         }
00058 };
00059 
00060 // Don't need custom comparision for strings.
00061 typedef STL_MAP<std::string, pg_surface_cache_t*, pg_surface_hash> pg_surfacemap_t;
00062 // Don't need custom hash or comparision functions when the key is a long.
00063 typedef STL_MAP<unsigned long, pg_surface_cache_t* > pg_surfacemap_index_t;
00064 
00065 typedef pg_surfacemap_t::iterator pg_surfacemap_iter_t;
00066 typedef pg_surfacemap_index_t::iterator pg_surfacemap_index_iter_t;
00067 #else
00068 // Don't need custom comparisions for strings.
00069 typedef std::map<std::string, pg_surface_cache_t*> pg_surfacemap_t;
00070 // Don't need a custom comparision function when the key is a long
00071 typedef std::map<unsigned long, pg_surface_cache_t*> pg_surfacemap_index_t;
00072 
00073 typedef pg_surfacemap_t::iterator pg_surfacemap_iter_t;
00074 typedef pg_surfacemap_index_t::iterator pg_surfacemap_index_iter_t;
00075 #endif
00076 
00077 PG_SurfaceCache::PG_SurfaceCache() {
00078         my_surfacemap = (void*)new(pg_surfacemap_t);
00079         my_surfacemap_index = (void*)new(pg_surfacemap_index_t);
00080 }
00081 
00082 PG_SurfaceCache::~PG_SurfaceCache() {
00083         Cleanup();
00084 
00085         delete MY_SURFACEMAP;
00086         delete MY_SURFACEINDEX;
00087 
00088         my_surfacemap = NULL;
00089         my_surfacemap_index = NULL;
00090 }
00091 
00092 void PG_SurfaceCache::Cleanup() {
00093 
00094         if(my_surfacemap == NULL) {
00095                 return;
00096         }
00097 
00098         pg_surfacemap_iter_t i = MY_SURFACEMAP->begin();
00099         while(i != MY_SURFACEMAP->end()) {
00100                 pg_surface_cache_t* t = (*i).second;
00101                 if(t != NULL) {
00102                         SDL_FreeSurface(t->surface);
00103                         delete t;
00104                 }
00105                 MY_SURFACEMAP->erase(i);
00106                 i = MY_SURFACEMAP->begin();
00107         }
00108 
00109         MY_SURFACEMAP->clear();
00110         MY_SURFACEINDEX->clear();
00111 }
00112 
00113 void PG_SurfaceCache::CreateKey(std::string &key, Uint16 w, Uint16 h,
00114                                 PG_Gradient* gradient, SDL_Surface* background,
00115                                 PG_Draw::BkMode bkmode, Uint8 blend) {
00116         char tmpkey[256];
00117         char colorkey[10];
00118         int i=0;
00119 
00120         assert(w != 0 && h != 0);
00121 
00122         sprintf(tmpkey, "%04x%04x%08lx%01i%01i",
00123                 w, h,
00124                 reinterpret_cast<unsigned long>(background),
00125                 bkmode,
00126                 blend);
00127 
00128         if(gradient != NULL) {
00129                 for(i=0; i<4; i++) {
00130                         sprintf(colorkey, "%02x%02x%02x",
00131                                 gradient->colors[i].r,
00132                                 gradient->colors[i].g,
00133                                 gradient->colors[i].b
00134                                );
00135 
00136                         strcat(tmpkey, colorkey);
00137                 }
00138         }
00139 
00140         key = tmpkey;
00141 
00142         /*      int i=0;
00143                 // length needed for key is:
00144                 // 1 byte for gradient/no gradient
00145                 // 3*4 bytes for gradient
00146                 // 2*2 bytes for size
00147                 // 4 bytes for background ptr
00148                 // 1 byte for bkmode
00149                 // 1 byte for blend
00150                 // == 23 bytes
00151                 char *tmpkey;
00152                 tmpkey = new char[24];
00153                 if(gradient) {
00154                         tmpkey[0] = '\1';
00155                         for(i=0; i<4; i++) {
00156                                 tmpkey[1+i*3] = gradient->colors[i].r;
00157                                 tmpkey[2+i*3] = gradient->colors[i].g;
00158                                 tmpkey[3+i*3] = gradient->colors[i].b;
00159                         }
00160                 } else {
00161                         for(i=0; i<13; i++) {
00162                                 tmpkey[i] = '\0';
00163                         }
00164                 }
00165          
00166                 sprintf(tmpkey+13, "%2c%2c%4c%c%c", w, h,
00167                         (unsigned int)background,  bkmode, blend);
00168          
00169                 key = string(tmpkey, 24);*/
00170 }
00171 
00172 pg_surface_cache_t* PG_SurfaceCache::FindByKey(const std::string &key) {
00173         pg_surfacemap_t::iterator i = MY_SURFACEMAP->find(key);
00174         if(i == MY_SURFACEMAP->end()) {
00175                 return NULL;
00176         }
00177         return (*i).second;
00178         //return (*MY_SURFACEMAP)[key];
00179 }
00180 
00181 pg_surface_cache_t* PG_SurfaceCache::FindBySurface(SDL_Surface* surface) {
00182         return (*MY_SURFACEINDEX)[reinterpret_cast<unsigned long>(surface)];
00183 }
00184 
00185 SDL_Surface* PG_SurfaceCache::FindSurface(const std::string &key) {
00186         pg_surfacemap_t::iterator i = MY_SURFACEMAP->find(key);
00187         if(i == MY_SURFACEMAP->end()) {
00188                 return NULL;
00189         }
00190         return (*i).second->surface;
00191         /*pg_surface_cache_t* t = (*MY_SURFACEMAP)[key];
00192 
00193         if(t == NULL) {
00194                 return NULL;
00195         }
00196 
00197         return t->surface;*/
00198 }
00199 
00200 SDL_Surface* PG_SurfaceCache::AddSurface(const std::string &key, SDL_Surface* surface) {
00201         pg_surface_cache_t* t = NULL;
00202 
00203         if(surface == NULL) {
00204                 return NULL;
00205         }
00206 
00207         // check if surface already exists
00208         t = FindByKey(key);
00209 
00210         // handle existing surface
00211         if(t != NULL) {
00212                 PG_LogDBG("Trying to add surface with existing key!");
00213                 // existing surface has a different pointer
00214                 // than new one
00215                 if(t->surface != surface) {
00216                         PG_LogDBG("New and existing surfacepointers are NOT equal !!!");
00217                         // delete new surface (avoid mem-leak)
00218                         SDL_FreeSurface(surface);
00219                 }
00220 
00221                 // increase refcount and return cached surface
00222                 t->refcount++;
00223                 return t->surface;
00224         }
00225 
00226         pg_surface_cache_t* item = new pg_surface_cache_t;
00227         item->refcount = 1;
00228         item->surface = surface;
00229         item->key = key;
00230         (*MY_SURFACEMAP)[key] = item;
00231         (*MY_SURFACEINDEX)[reinterpret_cast<unsigned long>(surface)] = item;
00232 
00233         return surface;
00234 }
00235 
00236 void PG_SurfaceCache::DeleteSurface(SDL_Surface* surface, bool bDeleteIfNotExists) {
00237 
00238         if(!surface) {
00239                 return;
00240         }
00241 
00242         pg_surface_cache_t* t = FindBySurface(surface);
00243 
00244         // free unmanaged surface
00245         if(t == NULL) {
00246                 if(bDeleteIfNotExists) {
00247                         SDL_FreeSurface(surface);
00248                 }
00249                 return;
00250         }
00251 
00252         // dec reference
00253         t->refcount--;
00254 
00255         // no more references ?
00256         if(t->refcount > 0) {
00257                 return;
00258         }
00259 
00260         MY_SURFACEMAP->erase(t->key);
00261         MY_SURFACEINDEX->erase(reinterpret_cast<unsigned long>(surface));
00262 
00263         SDL_FreeSurface(t->surface);
00264         delete t;
00265 }
00266 
00267 void PG_SurfaceCache::IncRef(const std::string &key) {
00268         pg_surface_cache_t* t = FindByKey(key);
00269 
00270         if(t == NULL) {
00271                 return;
00272         }
00273 
00274         t->refcount++;
00275 }
00276 
00277 
00278 /*
00279  * Local Variables:
00280  * c-basic-offset: 8
00281  * End:
00282  */

Generated on Tue Jun 24 01:27:49 2008 for Advanced Strategic Command by  doxygen 1.4.2