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