AaronCameron.net
I can't believe how tired I am.
Not a Member? - Login or Create an Account...MC Offline
Tuesday the 21st of May 2013 @ 08:03pm
Front Page Journal Projects Your Profile About
[]

LibN2L-4 Library Code Reference

Classes
Compounds
Files
Members
Method Index
Full Reference

cSurface.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002 Nova-2 Library (libN2L, or simply n2l) Game development C++ Library
00003 Copyright (C) 2003  Aaron Cameron
00004 
00005 This library is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU Lesser General Public
00007 License as published by the Free Software Foundation; either
00008 version 2.1 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 Lesser General Public License for more details.
00014 
00015 You should have received a copy of the GNU Lesser General Public
00016 License along with this library; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00018 
00019 A copy of the GNU Lesser General Public License has been provided with
00020 this library in the file 'COPYING'.
00021 
00022 Contact information for the author of this library has been provided
00023 with this library in the file 'AUTHOR'.
00024 ************************************************************************/
00025 #include "cSurface.h"
00026 #include "n2l/n2l.h"
00027 
00028 #include "SDL_image.h"
00029 
00030 namespace n2l
00031 {
00032     /* ************************************************************ */
00033     cSurface::cSurface()
00034     {
00035     }
00036 
00037     /* ************************************************************ */
00038     cSurface::cSurface( const cVfsNodeInterface & iFile ) :
00039         cSurfaceCommonImp()
00040     {
00041         load( iFile );
00042     }
00043 
00044 
00045     /* ************************************************************ */
00046     cSurface::cSurface( SDL_Surface * const iSurface )
00047     {
00048         assign(iSurface);
00049     }
00050 
00051 
00052     /* ************************************************************ */
00053     void cSurface::assign( SDL_Surface * const iSurface )
00054     {
00055         // Clear out whatever we're currently holding.
00056         free();
00057         // Take ownership of provided surface
00058         setRawSurface(iSurface,1);
00059         setFormat( *(rawSurface()->format) );
00060         setProperties( *rawSurface() );
00061     }
00062 
00063 
00064     /* ************************************************************ */
00065     void cSurface::create(  const tUint iWidth, const tUint iHeight, 
00066                             const tUbyte iDepth,
00067                             const tUint32 iRMask, const tUint32 iGMask,
00068                             const tUint32 iBMask, const tUint32 iAMask )
00069     {
00070         if (!empty()) free();
00071         SDL_Surface * nSurface = SDL_CreateRGBSurface(  SDL_SWSURFACE,
00072                                                         iWidth, iHeight, iDepth,
00073                                                         iRMask, iGMask,
00074                                                         iBMask, iAMask );
00075         if (0==nSurface)
00076             throw cSDLException(    "cSurface::create",
00077                                     "Failed to create surface" );
00078         
00079         setRawSurface(nSurface,1);
00080         setFormat( *(rawSurface()->format) );
00081         setProperties( *rawSurface() );
00082     }
00083 
00084 
00085     /* ************************************************************ */
00086     void cSurface::literalCopyBlit( const tVector2s & iDestPos,
00087                                     const cSurfaceInterface & iSSurface )
00088     {
00089         // First thing, ensure that the source and destination pixel formats
00090         // are EXACTLY the same, and that the destination buffer is big enough
00091         // for the copy we want to make.  This isn't really necessary since we
00092         // already know what we're getting, but hey, good practice is good practice.
00093         if (format()!=iSSurface.format())
00094             throw cBadDataUseException( "cSurface::literalCopyBlit",
00095                                         "Corner copy on non-identical src->dest pixel formats" );
00096         if (properties().size().x()+iDestPos.x()<iSSurface.properties().size().x() || 
00097             properties().size().y()+iDestPos.y()<iSSurface.properties().size().y())
00098             throw cBadDataUseException( "cSurface::literalCopyBlit",
00099                                         "Corner copy on uncompatible src->dest surface properties" );
00100             
00101 
00102         // Aquire the surface buffers we need
00103         if (!supportsRWBuffer())
00104             throw cUnsupportedMethodException(  "cSurface::literalCopyBlit",
00105                                                 "this requires write buffer access" );
00106         void *dDataPtr = aquireRWBuffer();
00107         const void *sDataPtr = iSSurface.aquireROBuffer();
00108 
00109         // We're doing this as a byte for byte copy into the top left corner of the
00110         // desination surface.  We could use SDL_BlitSurface, but that would try to 
00111         // resolve the alpha channel of the source, rather than just copying, which
00112         // is what we really want.
00113         const tUint HSize = iSSurface.properties().size().y();
00114         const tUint SPitch = iSSurface.properties().pitch();
00115         const tUint DPitch = properties().pitch();
00116         const tUint BytesPP = format().bytesPerPixel();
00117 
00118         // Move the destination data pointer to the starting pos.
00119         // GCC 3.4.2 doesn't like my original casts, so this is a little
00120         // ugly.
00121         tUbyte *pos1 = (tUbyte*)(dDataPtr);
00122         tUbyte *pos2 = (tUbyte*)(sDataPtr);
00123         pos1 += DPitch*iDestPos.y() + iDestPos.x()*BytesPP;
00124         dDataPtr = pos1;
00125         for (tUint h=0; HSize>h; ++h) {
00126             memcpy( dDataPtr, sDataPtr, SPitch );
00127             pos1 += DPitch;
00128             pos2 += SPitch;
00129             sDataPtr = pos2;
00130             dDataPtr = pos1;
00131         }
00132 
00133         // Release the surface data
00134         dDataPtr = 0;
00135         sDataPtr = 0;
00136         releaseRWBuffer();
00137         iSSurface.releaseROBuffer();
00138     }
00139 
00140 
00141     /* ************************************************************ */
00142     void cSurface::load( const cVfsNodeInterface & iFile )
00143     {
00144         // Clear out whatever we're currently holding.
00145         free();
00146         
00147         // Make sure that the node is like a file.
00148         if (!iFile.likeFile())
00149             throw cBadDataUseException( "cSurface::load",
00150                                         "Vfs Node isn\'t like a file" );
00151 
00152         // Let's just try to load it
00153         SDL_Surface * img = IMG_Load_RW( iFile.getRWops(), 1 );
00154         if (0==img)
00155             throw cDriverLayerException("cSurface::load",
00156                                         "Failed to load image from memory",
00157                                         "SDL_Image",
00158                                         SDL_GetError() );
00159         setRawSurface(img,1);
00160         setFormat( *(rawSurface()->format) );
00161         setProperties( *rawSurface() );
00162     }
00163 
00164 
00165     /* ************************************************************ */
00166     void cSurface::supportedFileFormats( tFileFormatList & oFormatList ) const
00167     {
00168         oFormatList.clear();
00169         oFormatList.push_back( VfsFileType_BMP );
00170         oFormatList.push_back( VfsFileType_JPEG );
00171         oFormatList.push_back( VfsFileType_PNG );
00172 //      oFormatList.push_back( VfsFileType_TIFF );
00173 //      oFormatList.push_back( VfsFileType_TGA );
00174         oFormatList.push_back( VfsFileType_PCX );
00175 
00176         //  Disabled for legal reasons
00177         //  And for lack of tested 8 bit support
00178         //  oFormatList.push_back( VfsFileType_GIF );
00179     }
00180 
00181 
00182     /* ************************************************************ */
00183     const bool cSurface::supportsRWBuffer() const
00184     {
00185         return !(properties().flags() & cSurfaceProperties::SurfaceFlag_HardwareSurface);
00186     }
00187 
00188 
00189     /* ************************************************************ */
00190     void * const cSurface::aquireRWBuffer()
00191     {
00192         if (!supportsRWBuffer())
00193             throw cUnsupportedMethodException(
00194                                     "cSurface::aquireRWBuffer",
00195                                     "RW Buffers not supported" );
00196         if (writeLocks() || readLocks()) return 0;
00197         if (empty())
00198             throw cBadDataUseException(
00199                                     "cSurface::aquireRWBuffer",
00200                                     "There\'s no surface here to lock!" );
00201         incWriteLock();
00202 
00203         SDL_Surface * const surfaceImpPtr = rawSurface();
00204 
00205         // Do whatever we have to do to get access to the raw surface
00206         if (SDL_MUSTLOCK(surfaceImpPtr))
00207             if (-1==SDL_LockSurface(surfaceImpPtr))
00208                 throw cSDLException(    "cSurface::aquireRWBuffer",
00209                                         "Couldn\'t lock surface" );
00210 
00211         // That's it.
00212         return surfaceImpPtr->pixels;
00213     }
00214 
00215 
00216     /* ************************************************************ */
00217     void cSurface::releaseRWBuffer() const
00218     {
00219         if (0==writeLocks())
00220             throw cException(   "cSurface::releaseRWBuffer",
00221                                 "Release of a non-existant lock" );
00222         if (empty())
00223             throw cBadDataUseException(
00224                                     "cSurface::releaseRWBuffer",
00225                                     "Surface implementation has gone away"  );
00226 
00227         // Do we do anything other than remove a reference count?
00228         if (writeLocks()>1) {
00229             decWriteLock(); // This can never happen.
00230             return;
00231         }
00232 
00233         // Undo anything we had to emulate to get a raw surface (assuming this
00234         // is the last lock, that is)
00235         SDL_Surface * surfaceImpPtr( rawSurface() );
00236         if (SDL_MUSTLOCK(surfaceImpPtr))
00237             SDL_UnlockSurface(surfaceImpPtr);
00238 
00239         // That's it, move on.
00240         decWriteLock();
00241     }   
00242 
00243 } // namespace
©2013 Aaron Cameron