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

CSPicture.cpp

Go to the documentation of this file.
00001 #ifdef WIN32
00002 #pragma warning(disable : 4786 )
00003 #endif
00004 
00005 #include "CSPicture.h"
00006 #include "CSBitmap.h"
00007 #include "CSXMLHelper.h"
00008 
00009 using namespace std;
00010 const char *CSPicture::CLASS = "CSPicture";
00011 CSPictures CSPicture::mAllPictures;
00012 
00013 CSPictureLoader CSPictureLoader::INSTANCE;
00014 CSPictureDirectLoader CSPictureDirectLoader::INSTANCE;
00015 
00016 // constructor using "*.xml" file
00017 CSPicture::CSPicture(const std::string &filename, bool isDirectLoad)
00018 {
00019     static char *functionName="CSPicture";
00020     mLoadName = filename;
00021     mFactor = 0;
00022     mScaledPicture = 0; 
00023     mRLEUse = RLE_PERHAPS;
00024     mAlpha = -1;
00025     mId = 0;
00026     mR = 0;
00027     mG = 0;
00028     mB = 0;
00029     mPicture = 0;
00030     mScaledWidth = 0;
00031     mScaledHeight = 0;
00032     mStartPixelsX = 0;
00033     mStartPixelsY = 0;
00034     mProjection = 0;
00035     mPixelProjectionCount = 0;
00036     mRLEAccelleration = 0;
00037     mIsCreatedAsScaled = false;
00038     mColorKey = -1;
00039     mIsSolid = false;
00040     CSPictureData data;
00041     mIsDirectLoad = isDirectLoad;
00042     if (!isDirectLoad)
00043     {
00044         loadPictureData(filename, data);
00045     }
00046     initialize(data, isDirectLoad);
00047     addPicture(this);
00048 }
00049 
00050 /** if pictures are to large - they get garbled during
00051   * conversion if in SDL_HWSURFACE (Windows) (FONT)
00052   * so I guessed 1000 pixel - and do them if encountered as NOT! Hardware
00053   * this is guess only - and I don't know WHY
00054   * it happens - bad work around!!!
00055   */
00056 SDL_Surface *CSPicture::convertToCurrentScreen(CSBitmap *image, SDL_Rect rect)
00057 {
00058     static char *functionName="convertToCurrentScreen";
00059     SDL_Surface *picture = 0;
00060     int flags = SDLMain::getScreen()->flags;
00061     if (image->picture->w > 1000)
00062     {
00063         if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE)
00064         {
00065             flags -= SDL_HWSURFACE;
00066         }
00067     }
00068     
00069     // at least under windows this is needed!
00070     // direct Draw gives a surface locked error otherwise!
00071     if (mAlpha >=0)
00072     {
00073         if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE)
00074         {
00075             flags -= SDL_HWSURFACE;
00076         }
00077     }
00078     picture = SDL_CreateRGBSurface(flags, 
00079                                rect.w, 
00080                                rect.h, 
00081                                SDLMain::getScreen()->format->BitsPerPixel, 
00082                                SDLMain::getScreen()->format->Rmask, 
00083                                SDLMain::getScreen()->format->Gmask, 
00084                                SDLMain::getScreen()->format->Bmask, 
00085                                SDLMain::getScreen()->format->Amask);
00086 
00087     if (picture == 0)
00088     {
00089         SDLMain::shutdown((std::string)"Create Surface Error error: " + SDL_GetError(), 1);
00090     }
00091     LOG_DEBUG_PRINT("image->picture->w: ", image->picture->w)
00092     LOG_DEBUG_PRINT("image->picture->h: ", (long) image->picture->h)
00093     LOG_DEBUG_PRINT("rect.x: ", (long) rect.x)
00094     LOG_DEBUG_PRINT("rect.y: ", (long) rect.y)
00095     LOG_DEBUG_PRINT("rect.w: ", (long) rect.w)
00096     LOG_DEBUG_PRINT("rect.h: ", (long) rect.h)
00097     LOG_DEBUG_PRINT("picture->w: ", (long) picture->w)
00098     LOG_DEBUG_PRINT("picture->h: ", (long) picture->h) 
00099     LOG_DEBUG_PRINT("image->picture->format->BytesPerPixel: ", (long) image->picture->format->BytesPerPixel) 
00100     LOG_DEBUG_PRINT("picture->format->BytesPerPixel: ", (long) picture->format->BytesPerPixel) 
00101 
00102     LOG_DEBUG_PRINT("picture: ", (long) picture) 
00103     LOG_DEBUG_PRINT("image->picture: ", (long) image->picture) 
00104     LOG_DEBUG_PRINT("image->picture->format_version: ", (long) image->picture->format_version) 
00105     LOG_DEBUG_PRINT("picture->format_version: ", (long) picture->format_version) 
00106 
00107     // oversight in SDL, a "picture" that was just deleted, can be reused with
00108     // exactly the same address and different BytesPerPixel (FullscreenToggle)
00109     // -> than there is a segmentation fault!
00110     // we circumvent that by forcing a mapping!
00111     // with this error SDL_MapSurface() is not called and thus we have a wrong 
00112     // Blit1to... function set internally
00113     /* this doesn't work
00114     if (SDL_MapSurface(image->picture, picture) == -1)
00115     {
00116         SDLMain::shutdown((std::string)"Mapping error: " + SDL_GetError(), 1);
00117     }
00118     */
00119 
00120     // here the "working" "work arround"...
00121     static long helperSingleton = 0;
00122     picture->format_version+=helperSingleton++;// = rand()*1292;
00123 
00124     if (SDL_BlitSurface(image->picture, &rect, picture, 0) < 0)
00125     {
00126         SDLMain::shutdown((std::string)"Display Format error: " + SDL_GetError(), 1);
00127     }
00128     
00129     mR = image->r;
00130     mG = image->g;
00131     mB = image->b;
00132     if ((image->r>=0) && (image->g>=0) && (image->b>=0))
00133     {
00134         if (!(SDLMain::getScreen()->flags & SDL_HWSURFACE))
00135         {
00136             int key;
00137             key = SDL_MapRGB(picture->format, image->r, image->g, image->b);
00138             SDL_SetColorKey(picture, SDL_SRCCOLORKEY | mRLEAccelleration, key); // new
00139         }
00140     }
00141 
00142     // hardware Surface do later
00143     if ((image->r>=0) && (image->g>=0) && (image->b>=0))
00144     {
00145         if (SDLMain::getScreen()->flags & SDL_HWSURFACE)
00146         {
00147             int key;
00148             key = SDL_MapRGB(picture->format, image->r, image->g, image->b);
00149             SDL_SetColorKey(picture, SDL_SRCCOLORKEY | mRLEAccelleration , key); // new
00150         }
00151     }
00152     mColorKey = picture->format->colorkey;
00153     if (mAlpha >=0) SDL_SetAlpha(picture, mRLEAccelleration | SDL_SRCALPHA, mAlpha);
00154 
00155     bool mIsDoublebuffer = (picture->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF;
00156     bool mIsHardware = (picture->flags & SDL_HWSURFACE) == SDL_HWSURFACE;
00157     bool mIsFullscreen = (picture->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN;
00158     return picture;
00159 }
00160 
00161 void CSPicture::initialize(const CSPictureData &data, bool isDirectLoad)
00162 {
00163     static char *functionName="initialize";
00164     // picture muss geladen werden
00165     // Load the BMP file into a surface 
00166     if (isDirectLoad)
00167     {
00168         mId = 0;
00169         CSBitmap *image = CSBitmapDirectLoader::INSTANCE.load(mLoadName);
00170         mUpdateRegion.x = mPictureRegion.x = 0;
00171         mUpdateRegion.y = mPictureRegion.y = 0;
00172         mUpdateRegion.h = mPictureRegion.h = image->picture->h;
00173         mUpdateRegion.w = mPictureRegion.w = image->picture->w;
00174 
00175         buildPixelProjection(image, mUpdateRegion);
00176         mAlpha = -1;
00177         mPicture = convertToCurrentScreen(image, mPictureRegion);
00178         mRLEUse = false;
00179 
00180         mPixelPictureRegion = mPictureRegion;
00181         mPixelPictureRegion.x = 0;
00182         mPixelPictureRegion.y = 0;
00183         buildOptimizeData();
00184         checkRLEAccelleration();
00185     }
00186     else
00187     {
00188         mId = strdup(data.id);
00189         mFileName = strdup(data.filename);
00190 
00191         // if pictures are to large - they get garbled during
00192         // conversion if in FULLSCREEN (Windows)
00193         CSBitmap *image = CSBitmapLoader::INSTANCE.load(data.filename);
00194         if (data.position.x + data.position.y + data.position.w + data.position.h == 0)
00195         {
00196             mUpdateRegion.x = mPictureRegion.x = data.position.x;
00197             mUpdateRegion.y = mPictureRegion.y = data.position.y;
00198             mUpdateRegion.h = mPictureRegion.h = image->picture->h;
00199             mUpdateRegion.w = mPictureRegion.w = image->picture->w;
00200         }
00201         else
00202         {
00203             mUpdateRegion.x = mPictureRegion.x = data.position.x;
00204             mUpdateRegion.y = mPictureRegion.y = data.position.y;
00205             mUpdateRegion.h = mPictureRegion.h = data.position.h;
00206             mUpdateRegion.w = mPictureRegion.w = data.position.w;
00207         }
00208 
00209         buildPixelProjection(image, mUpdateRegion);
00210         mAlpha = data.alpha;
00211         mPicture = convertToCurrentScreen(image, mPictureRegion);
00212         mRLEUse = data.rleUse;
00213 
00214         mPixelPictureRegion = mPictureRegion;
00215         mPixelPictureRegion.x = 0;
00216         mPixelPictureRegion.y = 0;
00217         buildOptimizeData();
00218         checkRLEAccelleration();
00219     }
00220 }
00221 
00222 CSPicture::CSPicture(const CSPicture &picture)
00223 {
00224     static char *functionName="CSPicture";
00225     LOG_ENTER 
00226     mFactor = 0;
00227     mScaledWidth = 0;
00228     mScaledHeight = 0;
00229     mScaledPicture = 0;
00230     mPicture = 0;
00231     mProjection = 0;
00232     mUpdateRegion = picture.mUpdateRegion;
00233     mPictureRegion = picture.mPictureRegion;
00234     mRLEUse = picture.mRLEUse;
00235     mAlpha = picture.mAlpha;
00236     mIsCreatedAsScaled = picture.mIsCreatedAsScaled;
00237     mLoadName = picture.mLoadName;
00238     mIsDirectLoad = picture.mIsDirectLoad;
00239 
00240     mPixelPictureRegion = picture.mPixelPictureRegion;
00241     mStartPixelsX = picture.mStartPixelsX;
00242     mStartPixelsY = picture.mStartPixelsY;
00243     
00244     mPixelProjectionCount = picture.mPixelProjectionCount;
00245     mRLEAccelleration = picture.mRLEAccelleration;
00246     if (picture.mId)
00247     {
00248         mId = strdup(picture.mId);
00249     }
00250     else
00251     {
00252         mId = 0;
00253     }
00254     mFileName = strdup(picture.mFileName);
00255     mIsSolid = picture.mIsSolid;
00256     mColorKey = picture.mColorKey;
00257     mR = picture.mR;
00258     mG = picture.mG;
00259     mB = picture.mB;
00260     mFactor = picture.mFactor;
00261     
00262     if (mIsDirectLoad)
00263     {
00264         mPicture = convertToCurrentScreen(CSBitmapDirectLoader::INSTANCE.load(mLoadName), mPictureRegion);
00265     }
00266     else
00267     {
00268         mPicture = convertToCurrentScreen(CSBitmapLoader::INSTANCE.load(mFileName), mPictureRegion);
00269     }
00270     if (mIsSolid)
00271     {
00272         SDL_SetColorKey(mPicture, mRLEAccelleration, mColorKey+11);
00273         SDL_Surface *h = mPicture;
00274         mPicture = SDL_DisplayFormat(h);
00275         SDLMain::freeSurface(h);
00276     }
00277     else
00278     {
00279         SDL_Surface *h = mPicture;
00280         // software surface needs befor
00281         if (!(SDLMain::getScreen()->flags & SDL_HWSURFACE))
00282         {
00283             SDL_SetColorKey(mPicture, SDL_SRCCOLORKEY| mRLEAccelleration, mColorKey);
00284         }
00285         mPicture = SDL_DisplayFormat(h);
00286 
00287         // hardware surface needs after
00288         if (SDLMain::getScreen()->flags & SDL_HWSURFACE)
00289         {
00290             SDL_SetColorKey(mPicture, SDL_SRCCOLORKEY| mRLEAccelleration, mColorKey);
00291         }
00292         buildOptimizeData();
00293         SDLMain::freeSurface(h);
00294     }
00295 
00296     int x,y;
00297     if (picture.mProjection != 0)
00298     {
00299         mProjection = (unsigned char **) new void *[mUpdateRegion.h];
00300         for (y = 0; y<mUpdateRegion.h; y++)
00301         {
00302             mProjection[y] = (unsigned char *) new unsigned char[mUpdateRegion.w];
00303         }   
00304         for (y = 0; y<mUpdateRegion.h; y++)
00305         {
00306             for (x = 0; x<mUpdateRegion.w; x++)
00307             {
00308                 mProjection[y][x] = picture.mProjection[y][x];
00309             }
00310         }
00311     }
00312     addPicture(this);
00313     LOG_EXIT
00314 }
00315 
00316 CSPicture::~CSPicture()
00317 {
00318     static char *functionName="~CSPicture";
00319     LOG_ENTER 
00320     removePicture(this);
00321     if (mId)
00322     {
00323         free(mId);
00324         mId = 0;
00325     }
00326     if (mFileName)
00327     {
00328         free(mFileName);
00329         mFileName = 0;
00330     }
00331     if (mProjection != 0)
00332     {
00333         for (int y = 0; y<mPictureRegion.h; y++)
00334         {
00335             delete[] mProjection[y];
00336         }   
00337         delete[] mProjection;
00338         mProjection = 0;
00339     }
00340     if (mScaledPicture != 0)
00341     {
00342         if (SDLMain::isInitialized())
00343         {       
00344             SDLMain::freeSurface(mScaledPicture);
00345         }
00346         mScaledPicture = 0;
00347     }
00348     LOG_EXIT
00349 }
00350 
00351 void CSPicture::setSolid(bool b)
00352 {
00353     static char *functionName="setSolid";
00354     if (b == mIsSolid)
00355     {
00356         return;
00357     }
00358 
00359     SDL_Surface *h = mPicture;
00360     mIsSolid = b;
00361     if (mIsSolid)
00362     {
00363         SDL_SetColorKey(mPicture, mRLEAccelleration, mColorKey+11);
00364         mPicture = SDL_DisplayFormat(h);
00365         mPixelPictureRegion = mPictureRegion;
00366         mPixelPictureRegion.x = 0;
00367         mPixelPictureRegion.y = 0;
00368         mStartPixelsX = 0;
00369         mStartPixelsY = 0;
00370         mUpdateRegion.h = mPictureRegion.h;
00371         mUpdateRegion.w = mPictureRegion.w;
00372     }
00373     else
00374     {
00375         // software surface needs befor
00376         if (!(SDLMain::getScreen()->flags & SDL_HWSURFACE))
00377         {
00378             SDL_SetColorKey(mPicture, SDL_SRCCOLORKEY| mRLEAccelleration, mColorKey);
00379         }
00380         mPicture = SDL_DisplayFormat(h);
00381 
00382         // hardware surface needs after
00383         if (SDLMain::getScreen()->flags & SDL_HWSURFACE)
00384         {
00385             SDL_SetColorKey(mPicture, SDL_SRCCOLORKEY| mRLEAccelleration, mColorKey);
00386         }
00387         buildOptimizeData();
00388     }
00389     SDLMain::freeSurface(h);
00390 }
00391 
00392 void CSPicture::setAlpha(int alpha)
00393 {
00394     static char *functionName="setAlpha";
00395     LOG_ENTER 
00396     if (alpha < 0)
00397     {
00398         mAlpha = -1;
00399         SDL_SetAlpha(mPicture, mRLEAccelleration, 0);
00400         LOG_EXIT
00401         return;
00402     }
00403     mAlpha = alpha;
00404     SDL_SetAlpha(mPicture, mRLEAccelleration | SDL_SRCALPHA, alpha);
00405     LOG_EXIT
00406 }
00407 
00408 void CSPicture::display(SDL_Surface *destination, int x, int y)
00409 {
00410     static char *functionName="display";
00411     if ((!mIsSolid) && (mPixelProjectionCount == 0))
00412     {
00413         return;
00414     }
00415 
00416     mUpdateRegion.x = mStartPixelsX + x;
00417     mUpdateRegion.y = mStartPixelsY + y;
00418 
00419     if (SDL_BlitSurface(mPicture, &mPixelPictureRegion, destination, &mUpdateRegion)< 0)
00420     {
00421         SDLMain::shutdown((std::string)"BlitSurface error: " + SDL_GetError(), 1);
00422     }
00423 }
00424 
00425 void CSPicture::display(int x, int y)
00426 {
00427     static char *functionName="display";
00428     if ((!mIsSolid) && (mPixelProjectionCount == 0))
00429     {
00430         return;
00431     }
00432 
00433     mUpdateRegion.x = mStartPixelsX + x;
00434     mUpdateRegion.y = mStartPixelsY + y;
00435     /* Blit onto the screen surface */
00436     if (SDL_BlitSurface(mPicture, &mPixelPictureRegion, SDLMain::getScreen(), &mUpdateRegion)< 0)
00437     {
00438         SDLMain::shutdown((std::string)"BlitSurface error: " + SDL_GetError(), 1);
00439     }
00440     
00441     SDLMain::addUpdateRect(mUpdateRegion);
00442 }
00443 
00444 void CSPicture::display(CSDisplayParams *displayParams)
00445 {
00446     static char *functionName="display";
00447     if ((!mIsSolid) && (mPixelProjectionCount == 0))
00448     {
00449         return;
00450     }
00451 
00452     // optimize - perhaps have some part of below as
00453     // constants - uses less indirections...
00454     mUpdateRegion.x = mStartPixelsX + displayParams->mXDisplayStart + displayParams->mXPos - displayParams->mXWorldStart;
00455     mUpdateRegion.y = mStartPixelsY + displayParams->mYDisplayStart + displayParams->mYPos - displayParams->mYWorldStart;
00456 
00457     /* Blit onto the screen surface */
00458     if (SDL_BlitSurface(mPicture, &mPixelPictureRegion, SDLMain::getScreen(), &mUpdateRegion)< 0)
00459     {
00460         SDLMain::shutdown((std::string)"BlitSurface error: " + SDL_GetError(), 1);
00461     }
00462     
00463     SDLMain::addUpdateRect(mUpdateRegion);
00464 }
00465 
00466 void CSPicture::resetSurface()
00467 {
00468     static char *functionName="resetSurface";
00469     LOG_ENTER 
00470     SDLMain::freeSurface(mPicture);
00471 
00472     if (mIsCreatedAsScaled)
00473     {
00474         SDL_Surface *picture = 0;
00475         if (mIsDirectLoad)
00476         {
00477             picture = convertToCurrentScreen(CSBitmapDirectLoader::INSTANCE.load(mLoadName), mPictureRegion);
00478         }
00479         else
00480         {
00481             picture = convertToCurrentScreen(CSBitmapLoader::INSTANCE.load(mFileName), mPictureRegion);
00482         }
00483         if (picture == 0)
00484         {
00485             SDLMain::shutdown((std::string)"ConvertError: " + SDL_GetError(), 13);
00486         }
00487         mPicture = SDLMain::getInstance()->scale(picture, mFactor);
00488         if (mPicture == 0)
00489         {
00490             SDLMain::shutdown((std::string)"ScaleError: " + SDL_GetError(), 12);
00491         }
00492         SDLMain::freeSurface(picture);
00493 
00494         if (mIsSolid)
00495         {
00496             SDL_SetColorKey(mPicture, mRLEAccelleration, mColorKey+11);
00497             SDL_Surface *h = mPicture;
00498             mPicture = SDL_DisplayFormat(h);
00499             if (mPicture == 0)
00500             {
00501                 SDLMain::shutdown((std::string)"Format Error: " + SDL_GetError(), 14);
00502             }
00503             SDLMain::freeSurface(h);
00504         }
00505         else
00506         {
00507             SDL_Surface *h = mPicture;
00508             // software surface needs befor
00509             if (!(SDLMain::getScreen()->flags & SDL_HWSURFACE))
00510             {
00511                 SDL_SetColorKey(mPicture, SDL_SRCCOLORKEY| mRLEAccelleration, mColorKey);
00512             }
00513             mPicture = SDL_DisplayFormat(h);
00514 
00515             // hardware surface needs after
00516             if (SDLMain::getScreen()->flags & SDL_HWSURFACE)
00517             {
00518                 SDL_SetColorKey(mPicture, SDL_SRCCOLORKEY| mRLEAccelleration, mColorKey);
00519             }
00520             SDLMain::freeSurface(h);
00521         }
00522     }
00523     else
00524     {
00525         // the image is not loaded from disk!
00526         // the loader "buffers" the image - therefor "loading"
00527         // here is ok!
00528         if (mIsDirectLoad)
00529         {
00530             mPicture = convertToCurrentScreen(CSBitmapDirectLoader::INSTANCE.load(mLoadName), mPictureRegion);
00531         }
00532         else
00533         {
00534             mPicture = convertToCurrentScreen(CSBitmapLoader::INSTANCE.load(mFileName), mPictureRegion);
00535         }
00536         if (mPicture == 0)
00537         {
00538             SDLMain::shutdown((std::string)"ConvertError: " + SDL_GetError(), 16);
00539         }
00540         if (mIsSolid)
00541         {
00542             SDL_SetColorKey(mPicture, mRLEAccelleration, mColorKey+11);
00543             SDL_Surface *h = mPicture;
00544             mPicture = SDL_DisplayFormat(h);
00545             if (mPicture == 0)
00546             {
00547                 SDLMain::shutdown((std::string)"Format Error: " + SDL_GetError(), 15);
00548             }
00549             SDLMain::freeSurface(h);
00550         }
00551         else
00552         {
00553             SDL_Surface *h = mPicture;
00554             // software surface needs befor
00555             if (!(SDLMain::getScreen()->flags & SDL_HWSURFACE))
00556             {
00557                 SDL_SetColorKey(mPicture, SDL_SRCCOLORKEY| mRLEAccelleration, mColorKey);
00558             }
00559             mPicture = SDL_DisplayFormat(h);
00560 
00561             // hardware surface needs after
00562             if (SDLMain::getScreen()->flags & SDL_HWSURFACE)
00563             {
00564                 SDL_SetColorKey(mPicture, SDL_SRCCOLORKEY| mRLEAccelleration, mColorKey);
00565             }
00566             SDLMain::freeSurface(h);
00567         }
00568         mFactor = 0;
00569     }
00570     if (mScaledPicture != 0)
00571     {
00572         SDLMain::freeSurface(mScaledPicture);
00573         mScaledPicture = 0;
00574     }
00575     setAlpha(mAlpha);
00576     LOG_EXIT
00577 }
00578 
00579 // static stuff to enable converting picture to and from fullscreen
00580 // all pictures ever loaded from disc are remembered in the Vector "mAllPictures"
00581 void CSPicture::addPicture(CSPicture *picture)
00582 {
00583     if (picture == 0)
00584     {
00585         return;
00586     }
00587     removePicture(picture);
00588     mAllPictures.push_back(picture);
00589 }
00590 
00591 void CSPicture::removePicture(CSPicture *picture)
00592 {
00593     if (picture == 0)
00594     {
00595         return;
00596     }
00597 
00598     CSPictures::iterator iter = mAllPictures.begin();
00599     while ( iter != mAllPictures.end())
00600     {
00601         if ((*iter) == picture)
00602         {
00603             mAllPictures.erase(iter);
00604             iter = mAllPictures.begin();    // restart to be absolutly save!
00605         }
00606         else
00607         {
00608             iter++;
00609         }
00610     }
00611 }
00612 
00613 // resets all surfaces
00614 // loaded via the CSPictureLoader (all!)
00615 void CSPicture::resetSurfaces()
00616 {
00617     static char *functionName="resetSurfaces";
00618     LOG_ENTER 
00619     CSPictures::iterator iter = mAllPictures.begin();
00620     while ( iter != mAllPictures.end())
00621     {
00622         (*iter)->resetSurface();
00623         iter++;
00624     }
00625     LOG_EXIT
00626 }
00627 
00628 // a pixel projection
00629 // has a one for every non transparent pixel
00630 // and a zero for every transparent pixel
00631 // one "pixel" in the projection i an 8-bit value
00632 // one could use a real bitmap - one bit for each pixel
00633 // than one could AND the pixels and be still a bit faster
00634 // but for now - it seems to be sufficient
00635 void CSPicture::buildPixelProjection(CSBitmap *image, const SDL_Rect &position)
00636 {
00637     static char *functionName="buildPixelProjection";
00638     // position data is not available for ALL pictures - must test this
00639     if ( (position.x == 0) &&
00640          (position.y == 0) &&
00641          (position.h == 0) &&
00642          (position.w == 0) 
00643        )
00644     {
00645         // fonts...
00646         // but perhaps we should than use the size of the picture?
00647         // well do that some other time - as this is
00648         // not needed yet
00649         return;
00650     }
00651     
00652     // count all non zero pixels
00653     mPixelProjectionCount = 0;
00654     
00655     // get transparent pixels-value
00656     int key = SDL_MapRGB(image->picture->format, image->r, image->g, image->b);
00657     int x,y;
00658 
00659     // if an old projection should already exist?
00660     // delete it
00661     if (mProjection != 0)
00662     {
00663         for (y = 0; y<mPictureRegion.h; y++)
00664         {
00665             delete[] mProjection[y];
00666         }   
00667         delete[] mProjection;
00668         mProjection = 0;
00669     }
00670 
00671     // build a two dimensional array of chars - (zero or one)
00672     mProjection = (unsigned char **) new void *[position.h];
00673     for (y = 0; y<position.h; y++)
00674     {
00675         mProjection[y] = 0;
00676     }   
00677     for (y = 0; y<position.h; y++)
00678     {
00679         mProjection[y] = (unsigned char *) new unsigned char[position.w];
00680     }   
00681     
00682     if (SDL_MUSTLOCK(image->picture)) 
00683     {
00684         SDL_LockSurface(image->picture);
00685     }
00686     for (y = 0; y<position.h; y++)
00687     {
00688         for (x = 0; x<position.w; x++)
00689         {
00690             Uint32 p = SDLMain::getPixel(image->picture, x+position.x, y+position.y);
00691 
00692             if (key == p)
00693             {
00694                 mProjection[y][x] = 0;
00695             }
00696             else
00697             {
00698                 mProjection[y][x] = 1;
00699                 mPixelProjectionCount++;
00700             }
00701 
00702         }
00703     }
00704 
00705     if (SDL_MUSTLOCK(image->picture)) 
00706     {
00707         SDL_UnlockSurface(image->picture);
00708     }
00709 }
00710     
00711 void CSPicture::checkRLEAccelleration()
00712 {
00713     static char *functionName="checkRLEAccelleration";
00714     if  (mRLEUse == RLE_YES)
00715     {
00716         mRLEAccelleration = SDL_RLEACCEL;
00717         return;
00718     }
00719 
00720     if  (mRLEUse == RLE_NO)
00721     {
00722         return;
00723     }
00724 
00725     // this should be a little bit more sophisticated 
00726     // - can't be bothered right now!
00727     if (mPixelProjectionCount <((mUpdateRegion.h*mUpdateRegion.w)/4))
00728     {
00729 
00730         // is faster completely without RLE?
00731         mRLEAccelleration = SDL_RLEACCEL;
00732     }
00733 }
00734 
00735 void CSPicture::loadPictureData(const std::string &filename, CSPictureData &data)
00736 {
00737     static char *functionName="loadPictureData";
00738     LOG_ENTER 
00739     CSXMLHelper xmlSupport(filename, "PICTURE");
00740     try
00741     {
00742         if (xmlSupport.getError())
00743         {
00744             LOG_EXIT
00745             throw "error";
00746         }
00747 
00748         data.id = strdup(xmlSupport.getString("ID").c_str());
00749         int hasPositionData = xmlSupport.getInt("count(/PICTURE/X)");
00750         if (hasPositionData == 1)
00751         {
00752             data.position.x = xmlSupport.getInt("X");
00753             data.position.y = xmlSupport.getInt("Y");
00754             data.position.w = xmlSupport.getInt("WIDTH");
00755             data.position.h = xmlSupport.getInt("HEIGHT");
00756         }
00757         else
00758         {
00759             data.position.x = 0;
00760             data.position.y = 0;
00761             data.position.w = 0;
00762             data.position.h = 0;
00763         }
00764 
00765         int hasRLEData = xmlSupport.getInt("count(/PICTURE/RLE_USE)");
00766         if (hasRLEData == 1)
00767         {
00768             data.rleUse = xmlSupport.getInt("RLE_USE");
00769         }
00770         int hasAlpha = xmlSupport.getInt("count(/PICTURE/ALPHA)");
00771         if (hasAlpha == 1)
00772         {
00773             data.alpha = xmlSupport.getInt("ALPHA");
00774         }
00775         data.filename = strdup(xmlSupport.getString("BITMAP").c_str());
00776     }
00777     catch(...)
00778     {
00779         LOG_EXIT
00780         SDLMain::shutdown((std::string)"XML error \"" + filename + "\": " + xmlSupport.getErrorMessage().c_str(), 1);
00781     }
00782     LOG_EXIT
00783 }
00784 
00785 // e.g. if a picture is surrounded by transparent pixels
00786 // the surrounding is "removed" and the start x,y is
00787 // set to the "inner" of the surrounding...
00788 void CSPicture::buildOptimizeData()
00789 {
00790     static char *functionName="buildOptimizeData";
00791     if (mProjection == 0)
00792     {
00793         return;
00794     }
00795 
00796     int x,y;
00797     unsigned int startPixelsX = 0;
00798     unsigned int startPixelsY = 0;
00799     unsigned int endPixelsX = mPictureRegion.w;
00800     unsigned int endPixelsY = mPictureRegion.h;
00801 
00802     for (y = 0; y<mPictureRegion.h; y++)
00803     {
00804         bool hasY = false;
00805         for (x = 0; x<mPictureRegion.w; x++)
00806         {
00807             if (mProjection[y][x] == 1)
00808             {
00809                 hasY = true;
00810                 break;
00811             }
00812         }
00813         if (hasY)
00814         {
00815             break;
00816         }
00817         startPixelsY++;
00818     }
00819 
00820     for (x = 0; x<mPictureRegion.w; x++)
00821     {
00822         bool hasX = false;
00823         for (y = 0; y<mPictureRegion.h; y++)
00824         {
00825             if (mProjection[y][x] == 1)
00826             {
00827                 hasX = true;
00828                 break;
00829             }
00830         }
00831         if (hasX)
00832         {
00833             break;
00834         }
00835         startPixelsX++;
00836     }
00837 
00838     for (y = mPictureRegion.h-1; y>=startPixelsY; y--)
00839     {
00840         bool hasY = false;
00841         for (x = 0; x<mPictureRegion.w; x++)
00842         {
00843             if (mProjection[y][x] == 1)
00844             {
00845                 hasY = true;
00846                 break;
00847             }
00848         }
00849         if (hasY)
00850         {
00851             break;
00852         }
00853         endPixelsY = y;
00854     }
00855 
00856     for (x = mPictureRegion.w-1; x>=startPixelsX; x--)
00857     {
00858         bool hasX = false;
00859         for (y = 0; y<mPictureRegion.h; y++)
00860         {
00861             if (mProjection[y][x] == 1)
00862             {
00863                 hasX = true;
00864                 break;
00865             }
00866         }
00867         if (hasX)
00868         {
00869             break;
00870         }
00871         endPixelsX = x;
00872     }
00873 
00874     mStartPixelsX = startPixelsX;
00875     mStartPixelsY = startPixelsY;
00876     mPixelPictureRegion.x += startPixelsX;
00877     mPixelPictureRegion.y += startPixelsY;
00878     mPixelPictureRegion.w = endPixelsX - startPixelsX;
00879     mPixelPictureRegion.h = endPixelsY - startPixelsY;
00880     mUpdateRegion.w = endPixelsX - startPixelsX;
00881     mUpdateRegion.h = endPixelsY - startPixelsY;
00882 }
00883 
00884 /** This function scales the current picture "deeply", each following reference, even to
00885   * the buffered Bitmap will produce a scaled version of the picture.
00886   * Only way to get rid of scaling is unload from the Loader!
00887   *
00888   */
00889 void CSPicture::scale(int width, int divideX, int height, int divideY)
00890 {
00891     static char *functionName="scale";
00892     if (mIsDirectLoad)
00893     {
00894         CSBitmapDirectLoader::INSTANCE.scale((char *) mLoadName.c_str(), width, divideX*mUpdateRegion.w, height, divideY*mUpdateRegion.h);
00895     }
00896     else
00897     {
00898         CSBitmapLoader::INSTANCE.scale(mFileName, width, divideX*mUpdateRegion.w, height, divideY*mUpdateRegion.h);
00899     }
00900 
00901     if (mProjection != 0)
00902     {
00903         for (int y = 0; y<mPictureRegion.h; y++)
00904         {
00905             delete[] mProjection[y];
00906         }   
00907         delete[] mProjection;
00908         mProjection = 0;
00909     }
00910 
00911     mUpdateRegion.x = mPictureRegion.x = SDLMain::getInstance()->scaleX(width, divideX*mUpdateRegion.w, mUpdateRegion.x);
00912     mUpdateRegion.y = mPictureRegion.y = SDLMain::getInstance()->scaleY(height, divideY*mUpdateRegion.h, mUpdateRegion.y);
00913     mUpdateRegion.w = mPictureRegion.w = SDLMain::getInstance()->scaleX(width, divideX*mUpdateRegion.w, mUpdateRegion.w);
00914     mUpdateRegion.h = mPictureRegion.h = SDLMain::getInstance()->scaleY(height, divideY*mUpdateRegion.h, mUpdateRegion.h);
00915 
00916     resetSurface();
00917 
00918     CSBitmap *image = 0;
00919     if (mIsDirectLoad)
00920     {
00921         image = CSBitmapDirectLoader::INSTANCE.load(mLoadName);
00922     }
00923     else
00924     {
00925         image = CSBitmapLoader::INSTANCE.load(mFileName);
00926     }
00927     buildPixelProjection(image, mUpdateRegion);
00928     mPixelPictureRegion = mPictureRegion;
00929     mPixelPictureRegion.x = 0;
00930     mPixelPictureRegion.y = 0;
00931     buildOptimizeData();
00932     checkRLEAccelleration();
00933 }
00934 
00935 void CSPicture::getRGB(int &r, int &b, int &g)
00936 {
00937     static char *functionName="getRGB";
00938     r = mR;
00939     g = mG;
00940     b = mB;
00941 }
00942 
00943 /** Get a scaled version of this CSPicture.
00944   *
00945   */
00946 /** This function scales the current picture with a factor. The scaled result is
00947   * a part of this picture! Both the scaled and unscaled picture can be got with functions.
00948   * The scaled picture is "buffered" by CSPicture and can be got "fast!" again and again
00949   */
00950 SDL_Surface *CSPicture::getScaledPicture(double factor)
00951 {
00952     static char *functionName="getScaledPicture";
00953     if ((mFactor == factor) && (mScaledPicture != 0))
00954     {
00955         return mScaledPicture;
00956     }
00957     mFactor = factor;
00958     if (mScaledPicture != 0)
00959     {
00960         SDLMain::freeSurface(mScaledPicture);
00961         mScaledPicture = 0;
00962     }
00963     
00964     mScaledPicture = SDLMain::getInstance()->scale(mPicture, factor);
00965     if (!isSolid())
00966     {
00967         int key;
00968         key = SDL_MapRGB(mScaledPicture->format, mR, mG, mB);
00969         SDL_SetColorKey(mScaledPicture, SDL_SRCCOLORKEY, key);
00970     }
00971     return mScaledPicture;
00972 }
00973 //! Get a scaled version of this CSPicture.
00974 /** This function scales the current picture with a factor. The scaled result is
00975   * a part of this picture! Both the scaled and unscaled picture can be got with functions.
00976   * The scaled picture is "buffered" by CSPicture and can be got "fast!" again and again
00977   * \return CSPicture -> should not be freed
00978   */
00979 // scale to a given height and width
00980 
00981 SDL_Surface *CSPicture::getScaledPicture(int w, int h)
00982 {
00983     static char *functionName="getScaledPicture";
00984     
00985     if ((mScaledWidth == h) && (mScaledHeight == h) && (mScaledPicture != 0))
00986     {
00987         return mScaledPicture;
00988     }
00989     mScaledWidth = w;
00990     mScaledHeight = h;
00991     if (mScaledPicture != 0)
00992     {
00993         SDLMain::freeSurface(mScaledPicture);
00994         mScaledPicture = 0;
00995     }
00996     
00997     mScaledPicture = SDLMain::getInstance()->scale(mPicture, w,h);
00998     if (!isSolid())
00999     {
01000         int key;
01001         key = SDL_MapRGB(mScaledPicture->format, mR, mG, mB);
01002         SDL_SetColorKey(mScaledPicture, SDL_SRCCOLORKEY, key);
01003     }
01004     return mScaledPicture;
01005 }
01006 
01007 bool CSPicture::isTransparent(int x, int y)
01008 {
01009     static char *functionName="isTransparent";
01010     LOG_ENTER 
01011     if (SDL_MUSTLOCK(mPicture)) 
01012     {
01013         SDL_LockSurface(mPicture);
01014     }
01015     bool val = mColorKey == SDLMain::getPixel(mPicture, x, y);
01016     if (SDL_MUSTLOCK(mPicture)) 
01017     {
01018         SDL_UnlockSurface(mPicture);
01019     }
01020     LOG_EXIT
01021     return val;
01022 }
01023 
01024 /** This function duplicates the current picture, that is builds a new pciture,
01025   * which is scaled to the factor given!
01026   *
01027   */
01028 CSPicture* CSPicture::createScaledPicture(CSPicture* picture, double factor)
01029 {
01030     CSPicture *newPicture = new CSPicture(*picture);
01031     newPicture->mIsCreatedAsScaled = true;
01032     newPicture->mFactor = factor;
01033     newPicture->resetSurface();
01034     
01035     newPicture->mUpdateRegion.x = newPicture->mUpdateRegion.x * newPicture->mFactor;
01036     newPicture->mUpdateRegion.y = newPicture->mUpdateRegion.y * newPicture->mFactor;
01037     newPicture->mUpdateRegion.w = newPicture->mUpdateRegion.w * newPicture->mFactor;
01038     newPicture->mUpdateRegion.h = newPicture->mUpdateRegion.h * newPicture->mFactor;
01039     newPicture->mPixelPictureRegion = newPicture->mUpdateRegion;
01040     newPicture->mPixelPictureRegion.x = 0;
01041     newPicture->mPixelPictureRegion.y = 0;
01042 
01043 
01044     // following is not done yet for copied scaled pictures
01045 //  CSBitmap *image = CSBitmapLoader::INSTANCE.load(mFileName);
01046 //  buildPixelProjection(image, mUpdateRegion);
01047     newPicture->buildOptimizeData();
01048     newPicture->checkRLEAccelleration();
01049     
01050     return newPicture;
01051 }

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