![[]](/images/special/trans.gif)
LibN2L-4 Library Code ReferenceClassesCompounds Files Members Method Index Full Reference cSurface.cppGo 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 |