146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL - Simple DirectMedia Layer 346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Copyright (C) 1997-2006 Sam Lantinga 446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is free software; you can redistribute it and/or 646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner modify it under the terms of the GNU Lesser General Public 746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License as published by the Free Software Foundation; either 846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner version 2.1 of the License, or (at your option) any later version. 946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is distributed in the hope that it will be useful, 1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner but WITHOUT ANY WARRANTY; without even the implied warranty of 1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Lesser General Public License for more details. 1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner You should have received a copy of the GNU Lesser General Public 1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License along with this library; if not, write to the Free Software 1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sam Lantinga 2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner slouken@libsdl.org 2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/ 2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h" 2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* General (mostly internal) pixel/color manipulation routines for SDL */ 2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_endian.h" 2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_video.h" 2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_sysvideo.h" 2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_blit.h" 3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_pixels_c.h" 3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_RLEaccel_c.h" 3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Helper functions */ 3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Allocate a pixel format structure and fill it according to the given info. 3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 3746be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerSDL_PixelFormat *SDL_AllocFormat(int bpp, 3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) 3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_PixelFormat *format; 4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 mask; 4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Allocate an empty pixel format structure */ 4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format = SDL_malloc(sizeof(*format)); 4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( format == NULL ) { 4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_OutOfMemory(); 4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(NULL); 4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset(format, 0, sizeof(*format)); 5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->alpha = SDL_ALPHA_OPAQUE; 5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Set up the format */ 5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->BitsPerPixel = bpp; 5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->BytesPerPixel = (bpp+7)/8; 5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( Rmask || Bmask || Gmask ) { /* Packed pixels with custom mask */ 5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette = NULL; 5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Rshift = 0; 5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Rloss = 8; 5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( Rmask ) { 6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( mask = Rmask; !(mask&0x01); mask >>= 1 ) 6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ++format->Rshift; 6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( ; (mask&0x01); mask >>= 1 ) 6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner --format->Rloss; 6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Gshift = 0; 6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Gloss = 8; 6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( Gmask ) { 6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( mask = Gmask; !(mask&0x01); mask >>= 1 ) 6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ++format->Gshift; 7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( ; (mask&0x01); mask >>= 1 ) 7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner --format->Gloss; 7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Bshift = 0; 7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Bloss = 8; 7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( Bmask ) { 7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( mask = Bmask; !(mask&0x01); mask >>= 1 ) 7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ++format->Bshift; 7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( ; (mask&0x01); mask >>= 1 ) 7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner --format->Bloss; 8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Ashift = 0; 8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Aloss = 8; 8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( Amask ) { 8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( mask = Amask; !(mask&0x01); mask >>= 1 ) 8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ++format->Ashift; 8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( ; (mask&0x01); mask >>= 1 ) 8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner --format->Aloss; 8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Rmask = Rmask; 9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Gmask = Gmask; 9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Bmask = Bmask; 9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Amask = Amask; 9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else if ( bpp > 8 ) { /* Packed pixels with standard mask */ 9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* R-G-B */ 9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( bpp > 24 ) 9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bpp = 24; 9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Rloss = 8-(bpp/3); 9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Gloss = 8-(bpp/3)-(bpp%3); 9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Bloss = 8-(bpp/3); 10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Rshift = ((bpp/3)+(bpp%3))+(bpp/3); 10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Gshift = (bpp/3); 10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Bshift = 0; 10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Rmask = ((0xFF>>format->Rloss)<<format->Rshift); 10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Gmask = ((0xFF>>format->Gloss)<<format->Gshift); 10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Bmask = ((0xFF>>format->Bloss)<<format->Bshift); 10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Palettized formats have no mask info */ 10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Rloss = 8; 10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Gloss = 8; 11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Bloss = 8; 11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Aloss = 8; 11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Rshift = 0; 11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Gshift = 0; 11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Bshift = 0; 11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Ashift = 0; 11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Rmask = 0; 11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Gmask = 0; 11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Bmask = 0; 11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->Amask = 0; 12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( bpp <= 8 ) { /* Palettized mode */ 12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int ncolors = 1<<bpp; 12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_PALETTE 12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr,"bpp=%d ncolors=%d\n",bpp,ncolors); 12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette = (SDL_Palette *)SDL_malloc(sizeof(SDL_Palette)); 12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( format->palette == NULL ) { 12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_FreeFormat(format); 12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_OutOfMemory(); 13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(NULL); 13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (format->palette)->ncolors = ncolors; 13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (format->palette)->colors = (SDL_Color *)SDL_malloc( 13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (format->palette)->ncolors*sizeof(SDL_Color)); 13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (format->palette)->colors == NULL ) { 13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_FreeFormat(format); 13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_OutOfMemory(); 13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(NULL); 13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( Rmask || Bmask || Gmask ) { 14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* create palette according to masks */ 14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int Rm=0,Gm=0,Bm=0; 14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int Rw=0,Gw=0,Bw=0; 14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef ENABLE_PALETTE_ALPHA 14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int Am=0,Aw=0; 14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if(Rmask) 14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Rw=8-format->Rloss; 15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for(i=format->Rloss;i>0;i-=Rw) 15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Rm|=1<<i; 15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_PALETTE 15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr,"Rw=%d Rm=0x%02X\n",Rw,Rm); 15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if(Gmask) 15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Gw=8-format->Gloss; 16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for(i=format->Gloss;i>0;i-=Gw) 16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Gm|=1<<i; 16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_PALETTE 16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr,"Gw=%d Gm=0x%02X\n",Gw,Gm); 16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if(Bmask) 16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Bw=8-format->Bloss; 16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for(i=format->Bloss;i>0;i-=Bw) 17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Bm|=1<<i; 17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_PALETTE 17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr,"Bw=%d Bm=0x%02X\n",Bw,Bm); 17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef ENABLE_PALETTE_ALPHA 17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if(Amask) 17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Aw=8-format->Aloss; 17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for(i=format->Aloss;i>0;i-=Aw) 18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Am|=1<<i; 18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner# ifdef DEBUG_PALETTE 18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr,"Aw=%d Am=0x%02X\n",Aw,Am); 18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner# endif 18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for(i=0; i < ncolors; ++i) { 18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int r,g,b; 18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner r=(i&Rmask)>>format->Rshift; 18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner r=(r<<format->Rloss)|((r*Rm)>>Rw); 19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette->colors[i].r=r; 19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner g=(i&Gmask)>>format->Gshift; 19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner g=(g<<format->Gloss)|((g*Gm)>>Gw); 19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette->colors[i].g=g; 19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner b=(i&Bmask)>>format->Bshift; 19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner b=(b<<format->Bloss)|((b*Bm)>>Bw); 19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette->colors[i].b=b; 19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef ENABLE_PALETTE_ALPHA 20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner a=(i&Amask)>>format->Ashift; 20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner a=(a<<format->Aloss)|((a*Am)>>Aw); 20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette->colors[i].unused=a; 20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else 20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette->colors[i].unused=0; 20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else if ( ncolors == 2 ) { 20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Create a black and white bitmap palette */ 21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette->colors[0].r = 0xFF; 21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette->colors[0].g = 0xFF; 21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette->colors[0].b = 0xFF; 21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette->colors[1].r = 0x00; 21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette->colors[1].g = 0x00; 21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format->palette->colors[1].b = 0x00; 21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Create an empty palette */ 21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset((format->palette)->colors, 0, 21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (format->palette)->ncolors*sizeof(SDL_Color)); 22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(format); 22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 22446be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerSDL_PixelFormat *SDL_ReallocFormat(SDL_Surface *surface, int bpp, 22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) 22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface->format ) { 22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_FreeFormat(surface->format); 22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_FormatChanged(surface); 23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); 23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return surface->format; 23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Change any previous mappings from/to the new surface format 23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_FormatChanged(SDL_Surface *surface) 23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner static int format_version = 0; 24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ++format_version; 24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( format_version < 0 ) { /* It wrapped... */ 24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format_version = 1; 24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface->format_version = format_version; 24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_InvalidateMap(surface->map); 24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Free a previously allocated format structure 25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_FreeFormat(SDL_PixelFormat *format) 25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( format ) { 25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( format->palette ) { 25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( format->palette->colors ) { 25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(format->palette->colors); 25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(format->palette); 25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(format); 26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors 26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_DitherColors(SDL_Color *colors, int bpp) 26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if(bpp != 8) 27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return; /* only 8bpp supported right now */ 27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for(i = 0; i < 256; i++) { 27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int r, g, b; 27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* map each bit field to the full [0, 255] interval, 27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */ 27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner r = i & 0xe0; 27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner r |= r >> 3 | r >> 6; 27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner colors[i].r = r; 27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner g = (i << 3) & 0xe0; 28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner g |= g >> 3 | g >> 6; 28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner colors[i].g = g; 28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner b = i & 0x3; 28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner b |= b << 2; 28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner b |= b << 4; 28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner colors[i].b = b; 28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Calculate the pad-aligned scanline width of a surface 29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 29146be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUint16 SDL_CalculatePitch(SDL_Surface *surface) 29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint16 pitch; 29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Surface should be 4-byte aligned for speed */ 29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pitch = surface->w*surface->format->BytesPerPixel; 29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (surface->format->BitsPerPixel) { 29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 1: 29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pitch = (pitch+7)/8; 30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 4: 30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pitch = (pitch+1)/2; 30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pitch = (pitch + 3) & ~3; /* 4-byte aligning */ 30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(pitch); 30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Match an RGB value to a particular palette index 31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 31346be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b) 31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Do colorspace distance matching */ 31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner unsigned int smallest; 31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner unsigned int distance; 31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int rd, gd, bd; 31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 pixel=0; 32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner smallest = ~0; 32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i=0; i<pal->ncolors; ++i ) { 32446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner rd = pal->colors[i].r - r; 32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner gd = pal->colors[i].g - g; 32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bd = pal->colors[i].b - b; 32746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner distance = (rd*rd)+(gd*gd)+(bd*bd); 32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( distance < smallest ) { 32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pixel = i; 33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( distance == 0 ) { /* Perfect match! */ 33146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 33246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 33346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner smallest = distance; 33446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 33546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 33646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(pixel); 33746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 33846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 33946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Find the opaque pixel value corresponding to an RGB triple */ 34046be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUint32 SDL_MapRGB 34146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner(const SDL_PixelFormat * const format, 34246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner const Uint8 r, const Uint8 g, const Uint8 b) 34346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 34446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( format->palette == NULL ) { 34546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return (r >> format->Rloss) << format->Rshift 34646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner | (g >> format->Gloss) << format->Gshift 34746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner | (b >> format->Bloss) << format->Bshift 34846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner | format->Amask; 34946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 35046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return SDL_FindColor(format->palette, r, g, b); 35146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 35246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 35346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 35446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Find the pixel value corresponding to an RGBA quadruple */ 35546be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUint32 SDL_MapRGBA 35646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner(const SDL_PixelFormat * const format, 35746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a) 35846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 35946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( format->palette == NULL ) { 36046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return (r >> format->Rloss) << format->Rshift 36146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner | (g >> format->Gloss) << format->Gshift 36246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner | (b >> format->Bloss) << format->Bshift 36346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner | ((a >> format->Aloss) << format->Ashift & format->Amask); 36446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 36546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return SDL_FindColor(format->palette, r, g, b); 36646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 36746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 36846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 36946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_GetRGBA(Uint32 pixel, SDL_PixelFormat *fmt, 37046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) 37146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 37246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( fmt->palette == NULL ) { 37346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* 37446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * This makes sure that the result is mapped to the 37546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * interval [0..255], and the maximum value for each 37646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * component is 255. This is important to make sure 37746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * that white is indeed reported as (255, 255, 255), 37846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * and that opaque alpha is 255. 37946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * This only works for RGB bit fields at least 4 bit 38046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * wide, which is almost always the case. 38146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 38246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner unsigned v; 38346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner v = (pixel & fmt->Rmask) >> fmt->Rshift; 38446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1))); 38546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner v = (pixel & fmt->Gmask) >> fmt->Gshift; 38646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1))); 38746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner v = (pixel & fmt->Bmask) >> fmt->Bshift; 38846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1))); 38946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if(fmt->Amask) { 39046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner v = (pixel & fmt->Amask) >> fmt->Ashift; 39146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); 39246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 39346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *a = SDL_ALPHA_OPAQUE; 39446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 39546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 39646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *r = fmt->palette->colors[pixel].r; 39746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *g = fmt->palette->colors[pixel].g; 39846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *b = fmt->palette->colors[pixel].b; 39946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *a = SDL_ALPHA_OPAQUE; 40046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 40146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 40246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 40346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_GetRGB(Uint32 pixel, SDL_PixelFormat *fmt, Uint8 *r,Uint8 *g,Uint8 *b) 40446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 40546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( fmt->palette == NULL ) { 40646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* the note for SDL_GetRGBA above applies here too */ 40746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner unsigned v; 40846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner v = (pixel & fmt->Rmask) >> fmt->Rshift; 40946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1))); 41046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner v = (pixel & fmt->Gmask) >> fmt->Gshift; 41146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1))); 41246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner v = (pixel & fmt->Bmask) >> fmt->Bshift; 41346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1))); 41446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 41546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *r = fmt->palette->colors[pixel].r; 41646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *g = fmt->palette->colors[pixel].g; 41746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *b = fmt->palette->colors[pixel].b; 41846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 41946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 42046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 42146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Apply gamma to a set of colors - this is easy. :) */ 42246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_ApplyGamma(Uint16 *gamma, SDL_Color *colors, SDL_Color *output, 42346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int ncolors) 42446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 42546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 42646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 42746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i=0; i<ncolors; ++i ) { 42846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner output[i].r = gamma[0*256 + colors[i].r] >> 8; 42946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner output[i].g = gamma[1*256 + colors[i].g] >> 8; 43046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner output[i].b = gamma[2*256 + colors[i].b] >> 8; 43146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 43246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 43346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 43446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Map from Palette to Palette */ 43546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint8 *Map1to1(SDL_Palette *src, SDL_Palette *dst, int *identical) 43646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 43746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 *map; 43846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 43946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 44046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( identical ) { 44146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( src->ncolors <= dst->ncolors ) { 44246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* If an identical palette, no need to map */ 44346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_memcmp(src->colors, dst->colors, src->ncolors* 44446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner sizeof(SDL_Color)) == 0 ) { 44546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *identical = 1; 44646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(NULL); 44746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 44846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 44946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *identical = 0; 45046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 45146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map = (Uint8 *)SDL_malloc(src->ncolors); 45246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( map == NULL ) { 45346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_OutOfMemory(); 45446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(NULL); 45546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 45646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i=0; i<src->ncolors; ++i ) { 45746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map[i] = SDL_FindColor(dst, 45846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner src->colors[i].r, src->colors[i].g, src->colors[i].b); 45946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 46046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(map); 46146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 46246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Map from Palette to BitField */ 46346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint8 *Map1toN(SDL_PixelFormat *src, SDL_PixelFormat *dst) 46446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 46546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 *map; 46646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 46746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int bpp; 46846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner unsigned alpha; 46946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Palette *pal = src->palette; 47046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 47146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel); 47246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map = (Uint8 *)SDL_malloc(pal->ncolors*bpp); 47346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( map == NULL ) { 47446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_OutOfMemory(); 47546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(NULL); 47646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 47746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 47846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner alpha = dst->Amask ? src->alpha : 0; 47946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* We memory copy to the pixel map so the endianness is preserved */ 48046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i=0; i<pal->ncolors; ++i ) { 48146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ASSEMBLE_RGBA(&map[i*bpp], dst->BytesPerPixel, dst, 48246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pal->colors[i].r, pal->colors[i].g, 48346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pal->colors[i].b, alpha); 48446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 48546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(map); 48646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 48746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Map from BitField to Dithered-Palette to Palette */ 48846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint8 *MapNto1(SDL_PixelFormat *src, SDL_PixelFormat *dst, int *identical) 48946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 49046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Generate a 256 color dither palette */ 49146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Palette dithered; 49246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Color colors[256]; 49346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Palette *pal = dst->palette; 49446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 49546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* SDL_DitherColors does not initialize the 'unused' component of colors, 49646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner but Map1to1 compares it against pal, so we should initialize it. */ 49746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset(colors, 0, sizeof(colors)); 49846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 49946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dithered.ncolors = 256; 50046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_DitherColors(colors, 8); 50146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dithered.colors = colors; 50246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(Map1to1(&dithered, pal, identical)); 50346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 50446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 50546be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerSDL_BlitMap *SDL_AllocBlitMap(void) 50646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 50746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_BlitMap *map; 50846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 50946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Allocate the empty map */ 51046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map = (SDL_BlitMap *)SDL_malloc(sizeof(*map)); 51146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( map == NULL ) { 51246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_OutOfMemory(); 51346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(NULL); 51446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 51546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset(map, 0, sizeof(*map)); 51646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 51746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Allocate the software blit data */ 51846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->sw_data = (struct private_swaccel *)SDL_malloc(sizeof(*map->sw_data)); 51946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( map->sw_data == NULL ) { 52046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_FreeBlitMap(map); 52146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_OutOfMemory(); 52246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(NULL); 52346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 52446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset(map->sw_data, 0, sizeof(*map->sw_data)); 52546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 52646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* It's ready to go */ 52746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(map); 52846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 52946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_InvalidateMap(SDL_BlitMap *map) 53046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 53146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ! map ) { 53246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return; 53346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 53446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->dst = NULL; 53546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->format_version = (unsigned int)-1; 53646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( map->table ) { 53746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(map->table); 53846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->table = NULL; 53946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 54046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 54146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_MapSurface (SDL_Surface *src, SDL_Surface *dst) 54246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 54346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_PixelFormat *srcfmt; 54446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_PixelFormat *dstfmt; 54546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_BlitMap *map; 54646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 54746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Clear out any previous mapping */ 54846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map = src->map; 54946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (src->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { 55046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_UnRLESurface(src, 1); 55146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 55246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_InvalidateMap(map); 55346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 55446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Figure out what kind of mapping we're doing */ 55546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->identity = 0; 55646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner srcfmt = src->format; 55746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dstfmt = dst->format; 55846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (srcfmt->BytesPerPixel) { 55946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 1: 56046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (dstfmt->BytesPerPixel) { 56146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 1: 56246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Palette --> Palette */ 56346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* If both SDL_HWSURFACE, assume have same palette */ 56446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ((src->flags & SDL_HWSURFACE) == SDL_HWSURFACE) && 56546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) ) { 56646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->identity = 1; 56746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 56846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->table = Map1to1(srcfmt->palette, 56946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dstfmt->palette, &map->identity); 57046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 57146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ! map->identity ) { 57246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( map->table == NULL ) { 57346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(-1); 57446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 57546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 57646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (srcfmt->BitsPerPixel!=dstfmt->BitsPerPixel) 57746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->identity = 0; 57846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 57946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 58046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 58146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Palette --> BitField */ 58246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->table = Map1toN(srcfmt, dstfmt); 58346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( map->table == NULL ) { 58446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(-1); 58546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 58646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 58746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 58846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 58946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 59046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (dstfmt->BytesPerPixel) { 59146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 1: 59246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* BitField --> Palette */ 59346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->table = MapNto1(srcfmt, dstfmt, &map->identity); 59446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ! map->identity ) { 59546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( map->table == NULL ) { 59646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(-1); 59746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 59846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 59946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->identity = 0; /* Don't optimize to copy */ 60046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 60146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 60246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* BitField --> BitField */ 60346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( FORMAT_EQUAL(srcfmt, dstfmt) ) 60446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->identity = 1; 60546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 60646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 60746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 60846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 60946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 61046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->dst = dst; 61146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner map->format_version = dst->format_version; 61246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 61346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Choose your blitters wisely */ 61446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(SDL_CalculateBlit(src)); 61546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 61646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_FreeBlitMap(SDL_BlitMap *map) 61746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 61846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( map ) { 61946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_InvalidateMap(map); 62046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( map->sw_data != NULL ) { 62146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(map->sw_data); 62246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 62346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(map); 62446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 62546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 626