Mercurial > sdl-ios-xcode
annotate src/video/SDL_pixels.c @ 934:af585d6efec8
Date: Thu, 17 Jun 2004 11:38:51 -0700 (PDT)
From: Eric Wing <ewing2121@yahoo.com>
Subject: New OS X patch (was Re: [SDL] Bug with inverted mouse coordinates in
I have a new patch for OS X I would like to submit.
First, it appears no further action has been taken on
my fix from Apple on the OpenGL windowed mode mouse
inversion problem. The fix would reunify the code, and
no longer require case checking for which version of
the OS you are running. This is probably a good fix
because the behavior with the old code could change
again with future versions of the OS, so those fixes
are included in this new patch.
But in addition, when I was at Apple, I asked them
about the ability to distinguish between the modifier
keys on the left and right sides of the keyboard (e.g.
Left Shift, Right Shift, Left/Right Alt, L/R Cmd, L/R
Ctrl). They told me that starting with Panther, the OS
began supporting this feature. This has always been a
source of annoyance for me when bringing a program
that comes from Windows or Linux to OS X when the
keybindings happened to need distinguishable left-side
and right-side keys. So the rest of the patch I am
submitting contains new code to support this feature
on Panther (and presumably later versions of the OS).
So after removing the OS version checks for the mouse
inversion problem, I reused the OS version checks to
activate the Left/Right detection of modifier keys. If
you are running Panther (or above), the new code will
attempt to distinguish between sides. For the older
OS's, the code path reverts to the original code.
I've tested with Panther on a G4 Cube, G5 dual
processor, and Powerbook Rev C. The Cube and G5
keyboards demonstrated the ability to distinguish
between sides. The Powerbook seems to only have
left-side keys, but the patch was still able to handle
it by producing the same results as before the patch.
I also wanted to test a non-Apple keyboard.
Unfortunately, I don't have any PC USB keyboards.
However, I was able to borrow a Sun Microsystems USB
keyboard, so I tried that out on the G5, and I got the
correct behavior for left and right sides. I'm
expecting that if it worked with a Sun keyboard, most
other keyboards should work with no problems.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 20 Aug 2004 22:35:23 +0000 |
parents | 333db1d87876 |
children | 3bf4103b2b89 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
695
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
50
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* General (mostly internal) pixel/color manipulation routines for SDL */ | |
29 | |
30 #include <stdio.h> | |
31 #include <stdlib.h> | |
32 #include <string.h> | |
33 | |
34 #include "SDL_error.h" | |
35 #include "SDL_endian.h" | |
36 #include "SDL_video.h" | |
37 #include "SDL_sysvideo.h" | |
38 #include "SDL_blit.h" | |
39 #include "SDL_pixels_c.h" | |
40 #include "SDL_RLEaccel_c.h" | |
41 | |
42 /* Helper functions */ | |
43 /* | |
44 * Allocate a pixel format structure and fill it according to the given info. | |
45 */ | |
46 SDL_PixelFormat *SDL_AllocFormat(int bpp, | |
47 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) | |
48 { | |
49 SDL_PixelFormat *format; | |
50 Uint32 mask; | |
51 | |
52 /* Allocate an empty pixel format structure */ | |
53 format = malloc(sizeof(*format)); | |
54 if ( format == NULL ) { | |
55 SDL_OutOfMemory(); | |
56 return(NULL); | |
57 } | |
58 memset(format, 0, sizeof(*format)); | |
59 format->alpha = SDL_ALPHA_OPAQUE; | |
60 | |
61 /* Set up the format */ | |
62 format->BitsPerPixel = bpp; | |
63 format->BytesPerPixel = (bpp+7)/8; | |
64 switch (bpp) { | |
65 case 1: | |
66 /* Create the 2 color black-white palette */ | |
67 format->palette = (SDL_Palette *)malloc( | |
68 sizeof(SDL_Palette)); | |
69 if ( format->palette == NULL ) { | |
70 SDL_FreeFormat(format); | |
71 SDL_OutOfMemory(); | |
72 return(NULL); | |
73 } | |
74 (format->palette)->ncolors = 2; | |
75 (format->palette)->colors = (SDL_Color *)malloc( | |
76 (format->palette)->ncolors*sizeof(SDL_Color)); | |
77 if ( (format->palette)->colors == NULL ) { | |
78 SDL_FreeFormat(format); | |
79 SDL_OutOfMemory(); | |
80 return(NULL); | |
81 } | |
82 format->palette->colors[0].r = 0xFF; | |
83 format->palette->colors[0].g = 0xFF; | |
84 format->palette->colors[0].b = 0xFF; | |
85 format->palette->colors[1].r = 0x00; | |
86 format->palette->colors[1].g = 0x00; | |
87 format->palette->colors[1].b = 0x00; | |
88 format->Rloss = 8; | |
89 format->Gloss = 8; | |
90 format->Bloss = 8; | |
91 format->Aloss = 8; | |
92 format->Rshift = 0; | |
93 format->Gshift = 0; | |
94 format->Bshift = 0; | |
95 format->Ashift = 0; | |
96 format->Rmask = 0; | |
97 format->Gmask = 0; | |
98 format->Bmask = 0; | |
99 format->Amask = 0; | |
100 break; | |
101 | |
102 case 4: | |
103 /* Create the 16 color VGA palette */ | |
104 format->palette = (SDL_Palette *)malloc( | |
105 sizeof(SDL_Palette)); | |
106 if ( format->palette == NULL ) { | |
107 SDL_FreeFormat(format); | |
108 SDL_OutOfMemory(); | |
109 return(NULL); | |
110 } | |
111 (format->palette)->ncolors = 16; | |
112 (format->palette)->colors = (SDL_Color *)malloc( | |
113 (format->palette)->ncolors*sizeof(SDL_Color)); | |
114 if ( (format->palette)->colors == NULL ) { | |
115 SDL_FreeFormat(format); | |
116 SDL_OutOfMemory(); | |
117 return(NULL); | |
118 } | |
119 /* Punt for now, will this ever be used? */ | |
120 memset((format->palette)->colors, 0, | |
121 (format->palette)->ncolors*sizeof(SDL_Color)); | |
122 | |
123 /* Palettized formats have no mask info */ | |
124 format->Rloss = 8; | |
125 format->Gloss = 8; | |
126 format->Bloss = 8; | |
127 format->Aloss = 8; | |
128 format->Rshift = 0; | |
129 format->Gshift = 0; | |
130 format->Bshift = 0; | |
131 format->Ashift = 0; | |
132 format->Rmask = 0; | |
133 format->Gmask = 0; | |
134 format->Bmask = 0; | |
135 format->Amask = 0; | |
136 break; | |
137 | |
138 case 8: | |
139 /* Create an empty 256 color palette */ | |
140 format->palette = (SDL_Palette *)malloc( | |
141 sizeof(SDL_Palette)); | |
142 if ( format->palette == NULL ) { | |
143 SDL_FreeFormat(format); | |
144 SDL_OutOfMemory(); | |
145 return(NULL); | |
146 } | |
147 (format->palette)->ncolors = 256; | |
148 (format->palette)->colors = (SDL_Color *)malloc( | |
149 (format->palette)->ncolors*sizeof(SDL_Color)); | |
150 if ( (format->palette)->colors == NULL ) { | |
151 SDL_FreeFormat(format); | |
152 SDL_OutOfMemory(); | |
153 return(NULL); | |
154 } | |
155 memset((format->palette)->colors, 0, | |
156 (format->palette)->ncolors*sizeof(SDL_Color)); | |
157 | |
158 /* Palettized formats have no mask info */ | |
159 format->Rloss = 8; | |
160 format->Gloss = 8; | |
161 format->Bloss = 8; | |
162 format->Aloss = 8; | |
163 format->Rshift = 0; | |
164 format->Gshift = 0; | |
165 format->Bshift = 0; | |
166 format->Ashift = 0; | |
167 format->Rmask = 0; | |
168 format->Gmask = 0; | |
169 format->Bmask = 0; | |
170 format->Amask = 0; | |
171 break; | |
172 | |
173 default: | |
174 /* No palette, just packed pixel info */ | |
175 format->palette = NULL; | |
176 format->Rshift = 0; | |
177 format->Rloss = 8; | |
178 if ( Rmask ) { | |
179 for ( mask = Rmask; !(mask&0x01); mask >>= 1 ) | |
180 ++format->Rshift; | |
181 for ( ; (mask&0x01); mask >>= 1 ) | |
182 --format->Rloss; | |
183 } | |
184 format->Gshift = 0; | |
185 format->Gloss = 8; | |
186 if ( Gmask ) { | |
187 for ( mask = Gmask; !(mask&0x01); mask >>= 1 ) | |
188 ++format->Gshift; | |
189 for ( ; (mask&0x01); mask >>= 1 ) | |
190 --format->Gloss; | |
191 } | |
192 format->Bshift = 0; | |
193 format->Bloss = 8; | |
194 if ( Bmask ) { | |
195 for ( mask = Bmask; !(mask&0x01); mask >>= 1 ) | |
196 ++format->Bshift; | |
197 for ( ; (mask&0x01); mask >>= 1 ) | |
198 --format->Bloss; | |
199 } | |
200 format->Ashift = 0; | |
201 format->Aloss = 8; | |
202 if ( Amask ) { | |
203 for ( mask = Amask; !(mask&0x01); mask >>= 1 ) | |
204 ++format->Ashift; | |
205 for ( ; (mask&0x01); mask >>= 1 ) | |
206 --format->Aloss; | |
207 } | |
208 format->Rmask = Rmask; | |
209 format->Gmask = Gmask; | |
210 format->Bmask = Bmask; | |
211 format->Amask = Amask; | |
212 break; | |
213 } | |
214 /* Calculate some standard bitmasks, if necessary | |
215 * Note: This could conflict with an alpha mask, if given. | |
216 */ | |
217 if ( (bpp > 8) && !format->Rmask && !format->Gmask && !format->Bmask ) { | |
218 /* R-G-B */ | |
219 if ( bpp > 24 ) | |
220 bpp = 24; | |
221 format->Rloss = 8-(bpp/3); | |
222 format->Gloss = 8-(bpp/3)-(bpp%3); | |
223 format->Bloss = 8-(bpp/3); | |
224 format->Rshift = ((bpp/3)+(bpp%3))+(bpp/3); | |
225 format->Gshift = (bpp/3); | |
226 format->Bshift = 0; | |
227 format->Rmask = ((0xFF>>format->Rloss)<<format->Rshift); | |
228 format->Gmask = ((0xFF>>format->Gloss)<<format->Gshift); | |
229 format->Bmask = ((0xFF>>format->Bloss)<<format->Bshift); | |
230 } | |
231 return(format); | |
232 } | |
233 SDL_PixelFormat *SDL_ReallocFormat(SDL_Surface *surface, int bpp, | |
234 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) | |
235 { | |
236 if ( surface->format ) { | |
237 SDL_FreeFormat(surface->format); | |
238 SDL_FormatChanged(surface); | |
239 } | |
240 surface->format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); | |
241 return surface->format; | |
242 } | |
243 | |
244 /* | |
245 * Change any previous mappings from/to the new surface format | |
246 */ | |
247 void SDL_FormatChanged(SDL_Surface *surface) | |
248 { | |
845
333db1d87876
Fixed a bug in detecting surface mapping changes
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
249 static int format_version = 0; |
333db1d87876
Fixed a bug in detecting surface mapping changes
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
250 ++format_version; |
333db1d87876
Fixed a bug in detecting surface mapping changes
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
251 if ( format_version < 0 ) { /* It wrapped... */ |
333db1d87876
Fixed a bug in detecting surface mapping changes
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
252 format_version = 1; |
333db1d87876
Fixed a bug in detecting surface mapping changes
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
253 } |
333db1d87876
Fixed a bug in detecting surface mapping changes
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
254 surface->format_version = format_version; |
0 | 255 SDL_InvalidateMap(surface->map); |
256 } | |
257 /* | |
258 * Free a previously allocated format structure | |
259 */ | |
260 void SDL_FreeFormat(SDL_PixelFormat *format) | |
261 { | |
262 if ( format ) { | |
263 if ( format->palette ) { | |
264 if ( format->palette->colors ) { | |
265 free(format->palette->colors); | |
266 } | |
267 free(format->palette); | |
268 } | |
269 free(format); | |
270 } | |
271 } | |
272 /* | |
273 * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors | |
274 */ | |
275 void SDL_DitherColors(SDL_Color *colors, int bpp) | |
276 { | |
277 int i; | |
278 if(bpp != 8) | |
279 return; /* only 8bpp supported right now */ | |
280 | |
281 for(i = 0; i < 256; i++) { | |
282 int r, g, b; | |
283 /* map each bit field to the full [0, 255] interval, | |
284 so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */ | |
285 r = i & 0xe0; | |
286 r |= r >> 3 | r >> 6; | |
287 colors[i].r = r; | |
288 g = (i << 3) & 0xe0; | |
289 g |= g >> 3 | g >> 6; | |
290 colors[i].g = g; | |
291 b = i & 0x3; | |
292 b |= b << 2; | |
293 b |= b << 4; | |
294 colors[i].b = b; | |
295 } | |
296 } | |
297 /* | |
298 * Calculate the pad-aligned scanline width of a surface | |
299 */ | |
300 Uint16 SDL_CalculatePitch(SDL_Surface *surface) | |
301 { | |
302 Uint16 pitch; | |
303 | |
304 /* Surface should be 4-byte aligned for speed */ | |
305 pitch = surface->w*surface->format->BytesPerPixel; | |
306 switch (surface->format->BitsPerPixel) { | |
307 case 1: | |
308 pitch = (pitch+7)/8; | |
309 break; | |
310 case 4: | |
311 pitch = (pitch+1)/2; | |
312 break; | |
313 default: | |
314 break; | |
315 } | |
316 pitch = (pitch + 3) & ~3; /* 4-byte aligning */ | |
317 return(pitch); | |
318 } | |
319 /* | |
320 * Match an RGB value to a particular palette index | |
321 */ | |
322 Uint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b) | |
323 { | |
324 /* Do colorspace distance matching */ | |
325 unsigned int smallest; | |
326 unsigned int distance; | |
327 int rd, gd, bd; | |
328 int i; | |
329 Uint8 pixel=0; | |
330 | |
331 smallest = ~0; | |
332 for ( i=0; i<pal->ncolors; ++i ) { | |
333 rd = pal->colors[i].r - r; | |
334 gd = pal->colors[i].g - g; | |
335 bd = pal->colors[i].b - b; | |
336 distance = (rd*rd)+(gd*gd)+(bd*bd); | |
337 if ( distance < smallest ) { | |
338 pixel = i; | |
339 if ( distance == 0 ) { /* Perfect match! */ | |
340 break; | |
341 } | |
342 smallest = distance; | |
343 } | |
344 } | |
345 return(pixel); | |
346 } | |
347 | |
348 /* Find the opaque pixel value corresponding to an RGB triple */ | |
349 Uint32 SDL_MapRGB(SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b) | |
350 { | |
351 if ( format->palette == NULL ) { | |
352 return (r >> format->Rloss) << format->Rshift | |
353 | (g >> format->Gloss) << format->Gshift | |
354 | (b >> format->Bloss) << format->Bshift | |
355 | format->Amask; | |
356 } else { | |
357 return SDL_FindColor(format->palette, r, g, b); | |
358 } | |
359 } | |
360 | |
361 /* Find the pixel value corresponding to an RGBA quadruple */ | |
362 Uint32 SDL_MapRGBA(SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b, Uint8 a) | |
363 { | |
364 if ( format->palette == NULL ) { | |
365 return (r >> format->Rloss) << format->Rshift | |
366 | (g >> format->Gloss) << format->Gshift | |
367 | (b >> format->Bloss) << format->Bshift | |
368 | ((a >> format->Aloss) << format->Ashift & format->Amask); | |
369 } else { | |
370 return SDL_FindColor(format->palette, r, g, b); | |
371 } | |
372 } | |
373 | |
374 void SDL_GetRGBA(Uint32 pixel, SDL_PixelFormat *fmt, | |
375 Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) | |
376 { | |
377 if ( fmt->palette == NULL ) { | |
378 /* | |
379 * This makes sure that the result is mapped to the | |
380 * interval [0..255], and the maximum value for each | |
381 * component is 255. This is important to make sure | |
382 * that white is indeed reported as (255, 255, 255), | |
383 * and that opaque alpha is 255. | |
384 * This only works for RGB bit fields at least 4 bit | |
385 * wide, which is almost always the case. | |
386 */ | |
628
e561e8752d33
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
387 unsigned v; |
e561e8752d33
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
388 v = (pixel & fmt->Rmask) >> fmt->Rshift; |
688
c0522010bb6d
Date: Tue, 12 Aug 2003 14:26:19 +0200 (MEST)
Sam Lantinga <slouken@libsdl.org>
parents:
628
diff
changeset
|
389 *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1))); |
628
e561e8752d33
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
390 v = (pixel & fmt->Gmask) >> fmt->Gshift; |
688
c0522010bb6d
Date: Tue, 12 Aug 2003 14:26:19 +0200 (MEST)
Sam Lantinga <slouken@libsdl.org>
parents:
628
diff
changeset
|
391 *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1))); |
628
e561e8752d33
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
392 v = (pixel & fmt->Bmask) >> fmt->Bshift; |
688
c0522010bb6d
Date: Tue, 12 Aug 2003 14:26:19 +0200 (MEST)
Sam Lantinga <slouken@libsdl.org>
parents:
628
diff
changeset
|
393 *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1))); |
0 | 394 if(fmt->Amask) { |
628
e561e8752d33
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
395 v = (pixel & fmt->Amask) >> fmt->Ashift; |
688
c0522010bb6d
Date: Tue, 12 Aug 2003 14:26:19 +0200 (MEST)
Sam Lantinga <slouken@libsdl.org>
parents:
628
diff
changeset
|
396 *a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); |
695 | 397 } else { |
0 | 398 *a = SDL_ALPHA_OPAQUE; |
695 | 399 } |
0 | 400 } else { |
401 *r = fmt->palette->colors[pixel].r; | |
402 *g = fmt->palette->colors[pixel].g; | |
403 *b = fmt->palette->colors[pixel].b; | |
404 *a = SDL_ALPHA_OPAQUE; | |
405 } | |
406 } | |
407 | |
408 void SDL_GetRGB(Uint32 pixel, SDL_PixelFormat *fmt, Uint8 *r,Uint8 *g,Uint8 *b) | |
409 { | |
410 if ( fmt->palette == NULL ) { | |
411 /* the note for SDL_GetRGBA above applies here too */ | |
628
e561e8752d33
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
412 unsigned v; |
e561e8752d33
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
413 v = (pixel & fmt->Rmask) >> fmt->Rshift; |
688
c0522010bb6d
Date: Tue, 12 Aug 2003 14:26:19 +0200 (MEST)
Sam Lantinga <slouken@libsdl.org>
parents:
628
diff
changeset
|
414 *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1))); |
628
e561e8752d33
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
415 v = (pixel & fmt->Gmask) >> fmt->Gshift; |
688
c0522010bb6d
Date: Tue, 12 Aug 2003 14:26:19 +0200 (MEST)
Sam Lantinga <slouken@libsdl.org>
parents:
628
diff
changeset
|
416 *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1))); |
628
e561e8752d33
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
417 v = (pixel & fmt->Bmask) >> fmt->Bshift; |
688
c0522010bb6d
Date: Tue, 12 Aug 2003 14:26:19 +0200 (MEST)
Sam Lantinga <slouken@libsdl.org>
parents:
628
diff
changeset
|
418 *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1))); |
0 | 419 } else { |
420 *r = fmt->palette->colors[pixel].r; | |
421 *g = fmt->palette->colors[pixel].g; | |
422 *b = fmt->palette->colors[pixel].b; | |
423 } | |
424 } | |
425 | |
426 /* Apply gamma to a set of colors - this is easy. :) */ | |
427 void SDL_ApplyGamma(Uint16 *gamma, SDL_Color *colors, SDL_Color *output, | |
428 int ncolors) | |
429 { | |
430 int i; | |
431 | |
432 for ( i=0; i<ncolors; ++i ) { | |
433 output[i].r = gamma[0*256 + colors[i].r] >> 8; | |
434 output[i].g = gamma[1*256 + colors[i].g] >> 8; | |
435 output[i].b = gamma[2*256 + colors[i].b] >> 8; | |
436 } | |
437 } | |
438 | |
439 /* Map from Palette to Palette */ | |
440 static Uint8 *Map1to1(SDL_Palette *src, SDL_Palette *dst, int *identical) | |
441 { | |
442 Uint8 *map; | |
443 int i; | |
444 | |
445 if ( identical ) { | |
446 if ( src->ncolors <= dst->ncolors ) { | |
447 /* If an identical palette, no need to map */ | |
448 if ( memcmp(src->colors, dst->colors, src->ncolors* | |
449 sizeof(SDL_Color)) == 0 ) { | |
450 *identical = 1; | |
451 return(NULL); | |
452 } | |
453 } | |
454 *identical = 0; | |
455 } | |
456 map = (Uint8 *)malloc(src->ncolors); | |
457 if ( map == NULL ) { | |
458 SDL_OutOfMemory(); | |
459 return(NULL); | |
460 } | |
461 for ( i=0; i<src->ncolors; ++i ) { | |
462 map[i] = SDL_FindColor(dst, | |
463 src->colors[i].r, src->colors[i].g, src->colors[i].b); | |
464 } | |
465 return(map); | |
466 } | |
467 /* Map from Palette to BitField */ | |
468 static Uint8 *Map1toN(SDL_Palette *src, SDL_PixelFormat *dst) | |
469 { | |
470 Uint8 *map; | |
471 int i; | |
472 int bpp; | |
50 | 473 unsigned alpha; |
0 | 474 |
475 bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel); | |
476 map = (Uint8 *)malloc(src->ncolors*bpp); | |
477 if ( map == NULL ) { | |
478 SDL_OutOfMemory(); | |
479 return(NULL); | |
480 } | |
481 | |
50 | 482 alpha = dst->Amask ? SDL_ALPHA_OPAQUE : 0; |
0 | 483 /* We memory copy to the pixel map so the endianness is preserved */ |
484 for ( i=0; i<src->ncolors; ++i ) { | |
485 ASSEMBLE_RGBA(&map[i*bpp], dst->BytesPerPixel, dst, | |
486 src->colors[i].r, src->colors[i].g, | |
50 | 487 src->colors[i].b, alpha); |
0 | 488 } |
489 return(map); | |
490 } | |
491 /* Map from BitField to Dithered-Palette to Palette */ | |
492 static Uint8 *MapNto1(SDL_PixelFormat *src, SDL_Palette *dst, int *identical) | |
493 { | |
494 /* Generate a 256 color dither palette */ | |
495 SDL_Palette dithered; | |
496 SDL_Color colors[256]; | |
497 | |
498 dithered.ncolors = 256; | |
499 SDL_DitherColors(colors, 8); | |
500 dithered.colors = colors; | |
501 return(Map1to1(&dithered, dst, identical)); | |
502 } | |
503 | |
504 SDL_BlitMap *SDL_AllocBlitMap(void) | |
505 { | |
506 SDL_BlitMap *map; | |
507 | |
508 /* Allocate the empty map */ | |
509 map = (SDL_BlitMap *)malloc(sizeof(*map)); | |
510 if ( map == NULL ) { | |
511 SDL_OutOfMemory(); | |
512 return(NULL); | |
513 } | |
514 memset(map, 0, sizeof(*map)); | |
515 | |
516 /* Allocate the software blit data */ | |
517 map->sw_data = (struct private_swaccel *)malloc(sizeof(*map->sw_data)); | |
518 if ( map->sw_data == NULL ) { | |
519 SDL_FreeBlitMap(map); | |
520 SDL_OutOfMemory(); | |
521 return(NULL); | |
522 } | |
523 memset(map->sw_data, 0, sizeof(*map->sw_data)); | |
524 | |
525 /* It's ready to go */ | |
526 return(map); | |
527 } | |
528 void SDL_InvalidateMap(SDL_BlitMap *map) | |
529 { | |
530 if ( ! map ) { | |
531 return; | |
532 } | |
533 map->dst = NULL; | |
534 map->format_version = (unsigned int)-1; | |
535 if ( map->table ) { | |
536 free(map->table); | |
537 map->table = NULL; | |
538 } | |
539 } | |
540 int SDL_MapSurface (SDL_Surface *src, SDL_Surface *dst) | |
541 { | |
542 SDL_PixelFormat *srcfmt; | |
543 SDL_PixelFormat *dstfmt; | |
544 SDL_BlitMap *map; | |
545 | |
546 /* Clear out any previous mapping */ | |
547 map = src->map; | |
548 if ( (src->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { | |
549 SDL_UnRLESurface(src, 1); | |
550 } | |
551 SDL_InvalidateMap(map); | |
552 | |
553 /* Figure out what kind of mapping we're doing */ | |
554 map->identity = 0; | |
555 srcfmt = src->format; | |
556 dstfmt = dst->format; | |
557 switch (srcfmt->BytesPerPixel) { | |
558 case 1: | |
559 switch (dstfmt->BytesPerPixel) { | |
560 case 1: | |
561 /* Palette --> Palette */ | |
562 /* If both SDL_HWSURFACE, assume have same palette */ | |
563 if ( ((src->flags & SDL_HWSURFACE) == SDL_HWSURFACE) && | |
564 ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) ) { | |
565 map->identity = 1; | |
566 } else { | |
567 map->table = Map1to1(srcfmt->palette, | |
568 dstfmt->palette, &map->identity); | |
569 } | |
570 if ( ! map->identity ) { | |
571 if ( map->table == NULL ) { | |
572 return(-1); | |
573 } | |
574 } | |
575 if (srcfmt->BitsPerPixel!=dstfmt->BitsPerPixel) | |
576 map->identity = 0; | |
577 break; | |
578 | |
579 default: | |
580 /* Palette --> BitField */ | |
581 map->table = Map1toN(srcfmt->palette, dstfmt); | |
582 if ( map->table == NULL ) { | |
583 return(-1); | |
584 } | |
585 break; | |
586 } | |
587 break; | |
588 default: | |
589 switch (dstfmt->BytesPerPixel) { | |
590 case 1: | |
591 /* BitField --> Palette */ | |
592 map->table = MapNto1(srcfmt, | |
593 dstfmt->palette, &map->identity); | |
594 if ( ! map->identity ) { | |
595 if ( map->table == NULL ) { | |
596 return(-1); | |
597 } | |
598 } | |
599 map->identity = 0; /* Don't optimize to copy */ | |
600 break; | |
601 default: | |
602 /* BitField --> BitField */ | |
603 if ( FORMAT_EQUAL(srcfmt, dstfmt) ) | |
604 map->identity = 1; | |
605 break; | |
606 } | |
607 break; | |
608 } | |
609 | |
610 map->dst = dst; | |
611 map->format_version = dst->format_version; | |
612 | |
613 /* Choose your blitters wisely */ | |
614 return(SDL_CalculateBlit(src)); | |
615 } | |
616 void SDL_FreeBlitMap(SDL_BlitMap *map) | |
617 { | |
618 if ( map ) { | |
619 SDL_InvalidateMap(map); | |
620 if ( map->sw_data != NULL ) { | |
621 free(map->sw_data); | |
622 } | |
623 free(map); | |
624 } | |
625 } |