OSDN Git Service

add sdl-1.3
[android-x86/external-stagefright-plugins.git] / SDL-1.3 / android-project / jni / SDL / src / video / SDL_pixels.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
4
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22
23 /* General (mostly internal) pixel/color manipulation routines for SDL */
24
25 #include "SDL_endian.h"
26 #include "SDL_video.h"
27 #include "SDL_sysvideo.h"
28 #include "SDL_blit.h"
29 #include "SDL_pixels_c.h"
30 #include "SDL_RLEaccel_c.h"
31
32
33 /* Lookup tables to expand partial bytes to the full 0..255 range */
34
35 static Uint8 lookup_0[] = {
36 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
37 };
38
39 static Uint8 lookup_1[] = {
40 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 255
41 };
42
43 static Uint8 lookup_2[] = {
44 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 255
45 };
46
47 static Uint8 lookup_3[] = {
48 0, 8, 16, 24, 32, 41, 49, 57, 65, 74, 82, 90, 98, 106, 115, 123, 131, 139, 148, 156, 164, 172, 180, 189, 197, 205, 213, 222, 230, 238, 246, 255
49 };
50
51 static Uint8 lookup_4[] = {
52 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
53 };
54
55 static Uint8 lookup_5[] = {
56 0, 36, 72, 109, 145, 182, 218, 255
57 };
58
59 static Uint8 lookup_6[] = {
60 0, 85, 170, 255
61 };
62
63 static Uint8 lookup_7[] = {
64 0, 255
65 };
66
67 static Uint8 lookup_8[] = {
68 255
69 };
70
71 Uint8* SDL_expand_byte[9] = {
72     lookup_0,
73     lookup_1,
74     lookup_2,
75     lookup_3,
76     lookup_4,
77     lookup_5,
78     lookup_6,
79     lookup_7,
80     lookup_8
81 };
82
83 /* Helper functions */
84
85 const char*
86 SDL_GetPixelFormatName(Uint32 format)
87 {
88     switch (format) {
89 #define CASE(X) case X: return #X;
90     CASE(SDL_PIXELFORMAT_INDEX1LSB)
91     CASE(SDL_PIXELFORMAT_INDEX1MSB)
92     CASE(SDL_PIXELFORMAT_INDEX4LSB)
93     CASE(SDL_PIXELFORMAT_INDEX4MSB)
94     CASE(SDL_PIXELFORMAT_INDEX8)
95     CASE(SDL_PIXELFORMAT_RGB332)
96     CASE(SDL_PIXELFORMAT_RGB444)
97     CASE(SDL_PIXELFORMAT_RGB555)
98     CASE(SDL_PIXELFORMAT_BGR555)
99     CASE(SDL_PIXELFORMAT_ARGB4444)
100     CASE(SDL_PIXELFORMAT_RGBA4444)
101     CASE(SDL_PIXELFORMAT_ABGR4444)
102     CASE(SDL_PIXELFORMAT_BGRA4444)
103     CASE(SDL_PIXELFORMAT_ARGB1555)
104     CASE(SDL_PIXELFORMAT_RGBA5551)
105     CASE(SDL_PIXELFORMAT_ABGR1555)
106     CASE(SDL_PIXELFORMAT_BGRA5551)
107     CASE(SDL_PIXELFORMAT_RGB565)
108     CASE(SDL_PIXELFORMAT_BGR565)
109     CASE(SDL_PIXELFORMAT_RGB24)
110     CASE(SDL_PIXELFORMAT_BGR24)
111     CASE(SDL_PIXELFORMAT_RGB888)
112     CASE(SDL_PIXELFORMAT_RGBX8888)
113     CASE(SDL_PIXELFORMAT_BGR888)
114     CASE(SDL_PIXELFORMAT_BGRX8888)
115     CASE(SDL_PIXELFORMAT_ARGB8888)
116     CASE(SDL_PIXELFORMAT_RGBA8888)
117     CASE(SDL_PIXELFORMAT_ABGR8888)
118     CASE(SDL_PIXELFORMAT_BGRA8888)
119     CASE(SDL_PIXELFORMAT_ARGB2101010)
120     CASE(SDL_PIXELFORMAT_YV12)
121     CASE(SDL_PIXELFORMAT_IYUV)
122     CASE(SDL_PIXELFORMAT_YUY2)
123     CASE(SDL_PIXELFORMAT_UYVY)
124     CASE(SDL_PIXELFORMAT_YVYU)
125 #undef CASE
126     default:
127         return "SDL_PIXELFORMAT_UNKNOWN";
128     }
129 }
130
131 SDL_bool
132 SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask,
133                            Uint32 * Gmask, Uint32 * Bmask, Uint32 * Amask)
134 {
135     Uint32 masks[4];
136
137     /* This function doesn't work with FourCC pixel formats */
138     if (SDL_ISPIXELFORMAT_FOURCC(format)) {
139         SDL_SetError("FOURCC pixel formats are not supported");
140         return SDL_FALSE;
141     }
142  
143     /* Initialize the values here */
144     if (SDL_BYTESPERPIXEL(format) <= 2) {
145         *bpp = SDL_BITSPERPIXEL(format);
146     } else {
147         *bpp = SDL_BYTESPERPIXEL(format) * 8;
148     }
149     *Rmask = *Gmask = *Bmask = *Amask = 0;
150
151     if (format == SDL_PIXELFORMAT_RGB24) {
152 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
153         *Rmask = 0x00FF0000;
154         *Gmask = 0x0000FF00;
155         *Bmask = 0x000000FF;
156 #else
157         *Rmask = 0x000000FF;
158         *Gmask = 0x0000FF00;
159         *Bmask = 0x00FF0000;
160 #endif
161         return SDL_TRUE;
162     }
163
164     if (format == SDL_PIXELFORMAT_BGR24) {
165 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
166         *Rmask = 0x000000FF;
167         *Gmask = 0x0000FF00;
168         *Bmask = 0x00FF0000;
169 #else
170         *Rmask = 0x00FF0000;
171         *Gmask = 0x0000FF00;
172         *Bmask = 0x000000FF;
173 #endif
174         return SDL_TRUE;
175     }
176
177     if (SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED8 &&
178         SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED16 &&
179         SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED32) {
180         /* Not a format that uses masks */
181         return SDL_TRUE;
182     }
183
184     switch (SDL_PIXELLAYOUT(format)) {
185     case SDL_PACKEDLAYOUT_332:
186         masks[0] = 0x00000000;
187         masks[1] = 0x000000E0;
188         masks[2] = 0x0000001C;
189         masks[3] = 0x00000003;
190         break;
191     case SDL_PACKEDLAYOUT_4444:
192         masks[0] = 0x0000F000;
193         masks[1] = 0x00000F00;
194         masks[2] = 0x000000F0;
195         masks[3] = 0x0000000F;
196         break;
197     case SDL_PACKEDLAYOUT_1555:
198         masks[0] = 0x00008000;
199         masks[1] = 0x00007C00;
200         masks[2] = 0x000003E0;
201         masks[3] = 0x0000001F;
202         break;
203     case SDL_PACKEDLAYOUT_5551:
204         masks[0] = 0x0000F800;
205         masks[1] = 0x000007C0;
206         masks[2] = 0x0000003E;
207         masks[3] = 0x00000001;
208         break;
209     case SDL_PACKEDLAYOUT_565:
210         masks[0] = 0x00000000;
211         masks[1] = 0x0000F800;
212         masks[2] = 0x000007E0;
213         masks[3] = 0x0000001F;
214         break;
215     case SDL_PACKEDLAYOUT_8888:
216         masks[0] = 0xFF000000;
217         masks[1] = 0x00FF0000;
218         masks[2] = 0x0000FF00;
219         masks[3] = 0x000000FF;
220         break;
221     case SDL_PACKEDLAYOUT_2101010:
222         masks[0] = 0xC0000000;
223         masks[1] = 0x3FF00000;
224         masks[2] = 0x000FFC00;
225         masks[3] = 0x000003FF;
226         break;
227     case SDL_PACKEDLAYOUT_1010102:
228         masks[0] = 0xFFC00000;
229         masks[1] = 0x003FF000;
230         masks[2] = 0x00000FFC;
231         masks[3] = 0x00000003;
232         break;
233     default:
234         SDL_SetError("Unknown pixel format");
235         return SDL_FALSE;
236     }
237
238     switch (SDL_PIXELORDER(format)) {
239     case SDL_PACKEDORDER_XRGB:
240         *Rmask = masks[1];
241         *Gmask = masks[2];
242         *Bmask = masks[3];
243         break;
244     case SDL_PACKEDORDER_RGBX:
245         *Rmask = masks[0];
246         *Gmask = masks[1];
247         *Bmask = masks[2];
248         break;
249     case SDL_PACKEDORDER_ARGB:
250         *Amask = masks[0];
251         *Rmask = masks[1];
252         *Gmask = masks[2];
253         *Bmask = masks[3];
254         break;
255     case SDL_PACKEDORDER_RGBA:
256         *Rmask = masks[0];
257         *Gmask = masks[1];
258         *Bmask = masks[2];
259         *Amask = masks[3];
260         break;
261     case SDL_PACKEDORDER_XBGR:
262         *Bmask = masks[1];
263         *Gmask = masks[2];
264         *Rmask = masks[3];
265         break;
266     case SDL_PACKEDORDER_BGRX:
267         *Bmask = masks[0];
268         *Gmask = masks[1];
269         *Rmask = masks[2];
270         break;
271     case SDL_PACKEDORDER_BGRA:
272         *Bmask = masks[0];
273         *Gmask = masks[1];
274         *Rmask = masks[2];
275         *Amask = masks[3];
276         break;
277     case SDL_PACKEDORDER_ABGR:
278         *Amask = masks[0];
279         *Bmask = masks[1];
280         *Gmask = masks[2];
281         *Rmask = masks[3];
282         break;
283     default:
284         SDL_SetError("Unknown pixel format");
285         return SDL_FALSE;
286     }
287     return SDL_TRUE;
288 }
289
290 Uint32
291 SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
292                            Uint32 Amask)
293 {
294     switch (bpp) {
295     case 1:
296         /* SDL defaults to MSB ordering */
297         return SDL_PIXELFORMAT_INDEX1MSB;
298     case 4:
299         /* SDL defaults to MSB ordering */
300         return SDL_PIXELFORMAT_INDEX4MSB;
301     case 8:
302         if (Rmask == 0) {
303             return SDL_PIXELFORMAT_INDEX8;
304         }
305         if (Rmask == 0xE0 &&
306             Gmask == 0x1C &&
307             Bmask == 0x03 &&
308             Amask == 0x00) {
309             return SDL_PIXELFORMAT_RGB332;
310         }
311         break;
312     case 12:
313         if (Rmask == 0) {
314             return SDL_PIXELFORMAT_RGB444;
315         }
316         if (Rmask == 0x0F00 &&
317             Gmask == 0x00F0 &&
318             Bmask == 0x000F &&
319             Amask == 0x0000) {
320             return SDL_PIXELFORMAT_RGB444;
321         }
322         break;
323     case 15:
324         if (Rmask == 0) {
325             return SDL_PIXELFORMAT_RGB555;
326         }
327         /* Fall through to 16-bit checks */
328     case 16:
329         if (Rmask == 0) {
330             return SDL_PIXELFORMAT_RGB565;
331         }
332         if (Rmask == 0x7C00 &&
333             Gmask == 0x03E0 &&
334             Bmask == 0x001F &&
335             Amask == 0x0000) {
336             return SDL_PIXELFORMAT_RGB555;
337         }
338         if (Rmask == 0x001F &&
339             Gmask == 0x03E0 &&
340             Bmask == 0x7C00 &&
341             Amask == 0x0000) {
342             return SDL_PIXELFORMAT_BGR555;
343         }
344         if (Rmask == 0x0F00 &&
345             Gmask == 0x00F0 &&
346             Bmask == 0x000F &&
347             Amask == 0xF000) {
348             return SDL_PIXELFORMAT_ARGB4444;
349         }
350         if (Rmask == 0xF000 &&
351             Gmask == 0x0F00 &&
352             Bmask == 0x00F0 &&
353             Amask == 0x000F) {
354             return SDL_PIXELFORMAT_RGBA4444;
355         }
356         if (Rmask == 0x000F &&
357             Gmask == 0x00F0 &&
358             Bmask == 0x0F00 &&
359             Amask == 0xF000) {
360             return SDL_PIXELFORMAT_ABGR4444;
361         }
362         if (Rmask == 0x00F0 &&
363             Gmask == 0x0F00 &&
364             Bmask == 0xF000 &&
365             Amask == 0x000F) {
366             return SDL_PIXELFORMAT_BGRA4444;
367         }
368         if (Rmask == 0x7C00 &&
369             Gmask == 0x03E0 &&
370             Bmask == 0x001F &&
371             Amask == 0x8000) {
372             return SDL_PIXELFORMAT_ARGB1555;
373         }
374         if (Rmask == 0xF800 &&
375             Gmask == 0x07C0 &&
376             Bmask == 0x003E &&
377             Amask == 0x0001) {
378             return SDL_PIXELFORMAT_RGBA5551;
379         }
380         if (Rmask == 0x001F &&
381             Gmask == 0x03E0 &&
382             Bmask == 0x7C00 &&
383             Amask == 0x8000) {
384             return SDL_PIXELFORMAT_ABGR1555;
385         }
386         if (Rmask == 0x003E &&
387             Gmask == 0x07C0 &&
388             Bmask == 0xF800 &&
389             Amask == 0x0001) {
390             return SDL_PIXELFORMAT_BGRA5551;
391         }
392         if (Rmask == 0xF800 &&
393             Gmask == 0x07E0 &&
394             Bmask == 0x001F &&
395             Amask == 0x0000) {
396             return SDL_PIXELFORMAT_RGB565;
397         }
398         if (Rmask == 0x001F &&
399             Gmask == 0x07E0 &&
400             Bmask == 0xF800 &&
401             Amask == 0x0000) {
402             return SDL_PIXELFORMAT_BGR565;
403         }
404         break;
405     case 24:
406         switch (Rmask) {
407         case 0:
408         case 0x00FF0000:
409 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
410             return SDL_PIXELFORMAT_RGB24;
411 #else
412             return SDL_PIXELFORMAT_BGR24;
413 #endif
414         case 0x000000FF:
415 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
416             return SDL_PIXELFORMAT_BGR24;
417 #else
418             return SDL_PIXELFORMAT_RGB24;
419 #endif
420         }
421     case 32:
422         if (Rmask == 0) {
423             return SDL_PIXELFORMAT_RGB888;
424         }
425         if (Rmask == 0x00FF0000 &&
426             Gmask == 0x0000FF00 &&
427             Bmask == 0x000000FF &&
428             Amask == 0x00000000) {
429             return SDL_PIXELFORMAT_RGB888;
430         }
431         if (Rmask == 0xFF000000 &&
432             Gmask == 0x00FF0000 &&
433             Bmask == 0x0000FF00 &&
434             Amask == 0x00000000) {
435             return SDL_PIXELFORMAT_RGBX8888;
436         }
437         if (Rmask == 0x000000FF &&
438             Gmask == 0x0000FF00 &&
439             Bmask == 0x00FF0000 &&
440             Amask == 0x00000000) {
441             return SDL_PIXELFORMAT_BGR888;
442         }
443         if (Rmask == 0x0000FF00 &&
444             Gmask == 0x00FF0000 &&
445             Bmask == 0xFF000000 &&
446             Amask == 0x00000000) {
447             return SDL_PIXELFORMAT_BGRX8888;
448         }
449         if (Rmask == 0x00FF0000 &&
450             Gmask == 0x0000FF00 &&
451             Bmask == 0x000000FF &&
452             Amask == 0xFF000000) {
453             return SDL_PIXELFORMAT_ARGB8888;
454         }
455         if (Rmask == 0xFF000000 &&
456             Gmask == 0x00FF0000 &&
457             Bmask == 0x0000FF00 &&
458             Amask == 0x000000FF) {
459             return SDL_PIXELFORMAT_RGBA8888;
460         }
461         if (Rmask == 0x000000FF &&
462             Gmask == 0x0000FF00 &&
463             Bmask == 0x00FF0000 &&
464             Amask == 0xFF000000) {
465             return SDL_PIXELFORMAT_ABGR8888;
466         }
467         if (Rmask == 0x0000FF00 &&
468             Gmask == 0x00FF0000 &&
469             Bmask == 0xFF000000 &&
470             Amask == 0x000000FF) {
471             return SDL_PIXELFORMAT_BGRA8888;
472         }
473         if (Rmask == 0x3FF00000 &&
474             Gmask == 0x000FFC00 &&
475             Bmask == 0x000003FF &&
476             Amask == 0xC0000000) {
477             return SDL_PIXELFORMAT_ARGB2101010;
478         }
479     }
480     return SDL_PIXELFORMAT_UNKNOWN;
481 }
482
483 static SDL_PixelFormat *formats;
484
485 SDL_PixelFormat *
486 SDL_AllocFormat(Uint32 pixel_format)
487 {
488     SDL_PixelFormat *format;
489
490     /* Look it up in our list of previously allocated formats */
491     for (format = formats; format; format = format->next) {
492         if (pixel_format == format->format) {
493             ++format->refcount;
494             return format;
495         }
496     }
497
498     /* Allocate an empty pixel format structure, and initialize it */
499     format = SDL_malloc(sizeof(*format));
500     if (format == NULL) {
501         SDL_OutOfMemory();
502         return NULL;
503     }
504     if (SDL_InitFormat(format, pixel_format) < 0) {
505         SDL_free(format);
506         return NULL;
507     }
508
509     if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
510         /* Cache the RGB formats */
511         format->next = formats;
512         formats = format;
513     }
514     return format;
515 }
516
517 int
518 SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format)
519 {
520     int bpp;
521     Uint32 Rmask, Gmask, Bmask, Amask;
522     Uint32 mask;
523
524     if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
525                                     &Rmask, &Gmask, &Bmask, &Amask)) {
526         return -1;
527     }
528
529     /* Set up the format */
530     SDL_zerop(format);
531     format->format = pixel_format;
532     format->BitsPerPixel = bpp;
533     format->BytesPerPixel = (bpp + 7) / 8;
534
535     format->Rmask = Rmask;
536     format->Rshift = 0;
537     format->Rloss = 8;
538     if (Rmask) {
539         for (mask = Rmask; !(mask & 0x01); mask >>= 1)
540             ++format->Rshift;
541         for (; (mask & 0x01); mask >>= 1)
542             --format->Rloss;
543     }
544
545     format->Gmask = Gmask;
546     format->Gshift = 0;
547     format->Gloss = 8;
548     if (Gmask) {
549         for (mask = Gmask; !(mask & 0x01); mask >>= 1)
550             ++format->Gshift;
551         for (; (mask & 0x01); mask >>= 1)
552             --format->Gloss;
553     }
554
555     format->Bmask = Bmask;
556     format->Bshift = 0;
557     format->Bloss = 8;
558     if (Bmask) {
559         for (mask = Bmask; !(mask & 0x01); mask >>= 1)
560             ++format->Bshift;
561         for (; (mask & 0x01); mask >>= 1)
562             --format->Bloss;
563     }
564
565     format->Amask = Amask;
566     format->Ashift = 0;
567     format->Aloss = 8;
568     if (Amask) {
569         for (mask = Amask; !(mask & 0x01); mask >>= 1)
570             ++format->Ashift;
571         for (; (mask & 0x01); mask >>= 1)
572             --format->Aloss;
573     }
574
575     format->palette = NULL;
576     format->refcount = 1;
577     format->next = NULL;
578
579     return 0;
580 }
581
582 void
583 SDL_FreeFormat(SDL_PixelFormat *format)
584 {
585     SDL_PixelFormat *prev;
586
587     if (!format) {
588         return;
589     }
590     if (--format->refcount > 0) {
591         return;
592     }
593
594     /* Remove this format from our list */
595     if (format == formats) {
596         formats = format->next;
597     } else if (formats) {
598         for (prev = formats; prev->next; prev = prev->next) {
599             if (prev->next == format) {
600                 prev->next = format->next;
601                 break;
602             }
603         }
604     }
605
606     if (format->palette) {
607         SDL_FreePalette(format->palette);
608     }
609     SDL_free(format);
610 }
611
612 SDL_Palette *
613 SDL_AllocPalette(int ncolors)
614 {
615     SDL_Palette *palette;
616
617     palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
618     if (!palette) {
619         SDL_OutOfMemory();
620         return NULL;
621     }
622     palette->colors =
623         (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
624     if (!palette->colors) {
625         SDL_free(palette);
626         return NULL;
627     }
628     palette->ncolors = ncolors;
629     palette->version = 1;
630     palette->refcount = 1;
631
632     SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
633
634     return palette;
635 }
636
637 int
638 SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
639 {
640     if (!format) {
641         SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
642         return -1;
643     }
644
645     if (palette && palette->ncolors != (1 << format->BitsPerPixel)) {
646         SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format");
647         return -1;
648     }
649
650     if (format->palette == palette) {
651         return 0;
652     }
653
654     if (format->palette) {
655         SDL_FreePalette(format->palette);
656     }
657
658     format->palette = palette;
659
660     if (format->palette) {
661         ++format->palette->refcount;
662     }
663
664     return 0;
665 }
666
667 int
668 SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
669                      int firstcolor, int ncolors)
670 {
671     int status = 0;
672
673     /* Verify the parameters */
674     if (!palette) {
675         return -1;
676     }
677     if (ncolors > (palette->ncolors - firstcolor)) {
678         ncolors = (palette->ncolors - firstcolor);
679         status = -1;
680     }
681
682     if (colors != (palette->colors + firstcolor)) {
683         SDL_memcpy(palette->colors + firstcolor, colors,
684                    ncolors * sizeof(*colors));
685     }
686     ++palette->version;
687     if (!palette->version) {
688         palette->version = 1;
689     }
690
691     return status;
692 }
693
694 void
695 SDL_FreePalette(SDL_Palette * palette)
696 {
697     if (!palette) {
698         return;
699     }
700     if (--palette->refcount > 0) {
701         return;
702     }
703     if (palette->colors) {
704         SDL_free(palette->colors);
705     }
706     SDL_free(palette);
707 }
708
709 /*
710  * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
711  */
712 void
713 SDL_DitherColors(SDL_Color * colors, int bpp)
714 {
715     int i;
716     if (bpp != 8)
717         return;                 /* only 8bpp supported right now */
718
719     for (i = 0; i < 256; i++) {
720         int r, g, b;
721         /* map each bit field to the full [0, 255] interval,
722            so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
723         r = i & 0xe0;
724         r |= r >> 3 | r >> 6;
725         colors[i].r = r;
726         g = (i << 3) & 0xe0;
727         g |= g >> 3 | g >> 6;
728         colors[i].g = g;
729         b = i & 0x3;
730         b |= b << 2;
731         b |= b << 4;
732         colors[i].b = b;
733         colors[i].unused = SDL_ALPHA_OPAQUE;
734     }
735 }
736
737 /* 
738  * Calculate the pad-aligned scanline width of a surface
739  */
740 int
741 SDL_CalculatePitch(SDL_Surface * surface)
742 {
743     int pitch;
744
745     /* Surface should be 4-byte aligned for speed */
746     pitch = surface->w * surface->format->BytesPerPixel;
747     switch (surface->format->BitsPerPixel) {
748     case 1:
749         pitch = (pitch + 7) / 8;
750         break;
751     case 4:
752         pitch = (pitch + 1) / 2;
753         break;
754     default:
755         break;
756     }
757     pitch = (pitch + 3) & ~3;   /* 4-byte aligning */
758     return (pitch);
759 }
760
761 /*
762  * Match an RGB value to a particular palette index
763  */
764 Uint8
765 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b)
766 {
767     /* Do colorspace distance matching */
768     unsigned int smallest;
769     unsigned int distance;
770     int rd, gd, bd;
771     int i;
772     Uint8 pixel = 0;
773
774     smallest = ~0;
775     for (i = 0; i < pal->ncolors; ++i) {
776         rd = pal->colors[i].r - r;
777         gd = pal->colors[i].g - g;
778         bd = pal->colors[i].b - b;
779         distance = (rd * rd) + (gd * gd) + (bd * bd);
780         if (distance < smallest) {
781             pixel = i;
782             if (distance == 0) {        /* Perfect match! */
783                 break;
784             }
785             smallest = distance;
786         }
787     }
788     return (pixel);
789 }
790
791 /* Find the opaque pixel value corresponding to an RGB triple */
792 Uint32
793 SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b)
794 {
795     if (format->palette == NULL) {
796         return (r >> format->Rloss) << format->Rshift
797             | (g >> format->Gloss) << format->Gshift
798             | (b >> format->Bloss) << format->Bshift | format->Amask;
799     } else {
800         return SDL_FindColor(format->palette, r, g, b);
801     }
802 }
803
804 /* Find the pixel value corresponding to an RGBA quadruple */
805 Uint32
806 SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b,
807             Uint8 a)
808 {
809     if (format->palette == NULL) {
810         return (r >> format->Rloss) << format->Rshift
811             | (g >> format->Gloss) << format->Gshift
812             | (b >> format->Bloss) << format->Bshift
813             | ((a >> format->Aloss) << format->Ashift & format->Amask);
814     } else {
815         return SDL_FindColor(format->palette, r, g, b);
816     }
817 }
818
819 void
820 SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g,
821            Uint8 * b)
822 {
823     if (format->palette == NULL) {
824         unsigned v;
825         v = (pixel & format->Rmask) >> format->Rshift;
826         *r = SDL_expand_byte[format->Rloss][v];
827         v = (pixel & format->Gmask) >> format->Gshift;
828         *g = SDL_expand_byte[format->Gloss][v];
829         v = (pixel & format->Bmask) >> format->Bshift;
830         *b = SDL_expand_byte[format->Bloss][v];
831     } else {
832         if (pixel < (unsigned)format->palette->ncolors) {
833             *r = format->palette->colors[pixel].r;
834             *g = format->palette->colors[pixel].g;
835             *b = format->palette->colors[pixel].b;
836         } else {
837             *r = *g = *b = 0;
838         }
839     }
840 }
841
842 void
843 SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format,
844             Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
845 {
846     if (format->palette == NULL) {
847         unsigned v;
848         v = (pixel & format->Rmask) >> format->Rshift;
849         *r = SDL_expand_byte[format->Rloss][v];
850         v = (pixel & format->Gmask) >> format->Gshift;
851         *g = SDL_expand_byte[format->Gloss][v];
852         v = (pixel & format->Bmask) >> format->Bshift;
853         *b = SDL_expand_byte[format->Bloss][v];
854         v = (pixel & format->Amask) >> format->Ashift;
855         *a = SDL_expand_byte[format->Aloss][v];
856     } else {
857         if (pixel < (unsigned)format->palette->ncolors) {
858             *r = format->palette->colors[pixel].r;
859             *g = format->palette->colors[pixel].g;
860             *b = format->palette->colors[pixel].b;
861             *a = SDL_ALPHA_OPAQUE;
862         } else {
863             *r = *g = *b = *a = 0;
864         }
865     }
866 }
867
868 /* Map from Palette to Palette */
869 static Uint8 *
870 Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
871 {
872     Uint8 *map;
873     int i;
874
875     if (identical) {
876         if (src->ncolors <= dst->ncolors) {
877             /* If an identical palette, no need to map */
878             if (src == dst
879                 ||
880                 (SDL_memcmp
881                  (src->colors, dst->colors,
882                   src->ncolors * sizeof(SDL_Color)) == 0)) {
883                 *identical = 1;
884                 return (NULL);
885             }
886         }
887         *identical = 0;
888     }
889     map = (Uint8 *) SDL_malloc(src->ncolors);
890     if (map == NULL) {
891         SDL_OutOfMemory();
892         return (NULL);
893     }
894     for (i = 0; i < src->ncolors; ++i) {
895         map[i] = SDL_FindColor(dst,
896                                src->colors[i].r, src->colors[i].g,
897                                src->colors[i].b);
898     }
899     return (map);
900 }
901
902 /* Map from Palette to BitField */
903 static Uint8 *
904 Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
905         SDL_PixelFormat * dst)
906 {
907     Uint8 *map;
908     int i;
909     int bpp;
910     SDL_Palette *pal = src->palette;
911
912     bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
913     map = (Uint8 *) SDL_malloc(pal->ncolors * bpp);
914     if (map == NULL) {
915         SDL_OutOfMemory();
916         return (NULL);
917     }
918
919     /* We memory copy to the pixel map so the endianness is preserved */
920     for (i = 0; i < pal->ncolors; ++i) {
921         Uint8 A = Amod;
922         Uint8 R = (Uint8) ((pal->colors[i].r * Rmod) / 255);
923         Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255);
924         Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255);
925         ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A);
926     }
927     return (map);
928 }
929
930 /* Map from BitField to Dithered-Palette to Palette */
931 static Uint8 *
932 MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical)
933 {
934     /* Generate a 256 color dither palette */
935     SDL_Palette dithered;
936     SDL_Color colors[256];
937     SDL_Palette *pal = dst->palette;
938
939     dithered.ncolors = 256;
940     SDL_DitherColors(colors, 8);
941     dithered.colors = colors;
942     return (Map1to1(&dithered, pal, identical));
943 }
944
945 SDL_BlitMap *
946 SDL_AllocBlitMap(void)
947 {
948     SDL_BlitMap *map;
949
950     /* Allocate the empty map */
951     map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map));
952     if (map == NULL) {
953         SDL_OutOfMemory();
954         return (NULL);
955     }
956     map->info.r = 0xFF;
957     map->info.g = 0xFF;
958     map->info.b = 0xFF;
959     map->info.a = 0xFF;
960
961     /* It's ready to go */
962     return (map);
963 }
964
965 void
966 SDL_InvalidateMap(SDL_BlitMap * map)
967 {
968     if (!map) {
969         return;
970     }
971     map->dst = NULL;
972     map->src_palette_version = 0;
973     map->dst_palette_version = 0;
974     if (map->info.table) {
975         SDL_free(map->info.table);
976         map->info.table = NULL;
977     }
978 }
979
980 int
981 SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
982 {
983     SDL_PixelFormat *srcfmt;
984     SDL_PixelFormat *dstfmt;
985     SDL_BlitMap *map;
986
987     /* Clear out any previous mapping */
988     map = src->map;
989     if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
990         SDL_UnRLESurface(src, 1);
991     }
992     SDL_InvalidateMap(map);
993
994     /* Figure out what kind of mapping we're doing */
995     map->identity = 0;
996     srcfmt = src->format;
997     dstfmt = dst->format;
998     if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) {
999         if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
1000             /* Palette --> Palette */
1001             map->info.table =
1002                 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
1003             if (!map->identity) {
1004                 if (map->info.table == NULL) {
1005                     return (-1);
1006                 }
1007             }
1008             if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
1009                 map->identity = 0;
1010         } else {
1011             /* Palette --> BitField */
1012             map->info.table =
1013                 Map1toN(srcfmt, src->map->info.r, src->map->info.g,
1014                         src->map->info.b, src->map->info.a, dstfmt);
1015             if (map->info.table == NULL) {
1016                 return (-1);
1017             }
1018         }
1019     } else {
1020         if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
1021             /* BitField --> Palette */
1022             map->info.table = MapNto1(srcfmt, dstfmt, &map->identity);
1023             if (!map->identity) {
1024                 if (map->info.table == NULL) {
1025                     return (-1);
1026                 }
1027             }
1028             map->identity = 0;  /* Don't optimize to copy */
1029         } else {
1030             /* BitField --> BitField */
1031             if (srcfmt == dstfmt) {
1032                 map->identity = 1;
1033             }
1034         }
1035     }
1036
1037     map->dst = dst;
1038
1039     if (dstfmt->palette) {
1040         map->dst_palette_version = dstfmt->palette->version;
1041     } else {
1042         map->dst_palette_version = 0;
1043     }
1044
1045     if (srcfmt->palette) {
1046         map->src_palette_version = srcfmt->palette->version;
1047     } else {
1048         map->src_palette_version = 0;
1049     }
1050
1051     /* Choose your blitters wisely */
1052     return (SDL_CalculateBlit(src));
1053 }
1054
1055 void
1056 SDL_FreeBlitMap(SDL_BlitMap * map)
1057 {
1058     if (map) {
1059         SDL_InvalidateMap(map);
1060         SDL_free(map);
1061     }
1062 }
1063
1064 void
1065 SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
1066 {
1067     int i;
1068
1069     /* 0.0 gamma is all black */
1070     if (gamma <= 0.0f) {
1071         for (i = 0; i < 256; ++i) {
1072             ramp[i] = 0;
1073         }
1074         return;
1075     } else if (gamma == 1.0f) {
1076         /* 1.0 gamma is identity */
1077         for (i = 0; i < 256; ++i) {
1078             ramp[i] = (i << 8) | i;
1079         }
1080         return;
1081     } else {
1082         /* Calculate a real gamma ramp */
1083         int value;
1084         gamma = 1.0f / gamma;
1085         for (i = 0; i < 256; ++i) {
1086             value =
1087                 (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
1088             if (value > 65535) {
1089                 value = 65535;
1090             }
1091             ramp[i] = (Uint16) value;
1092         }
1093     }
1094 }
1095
1096 /* vi: set ts=4 sw=4 expandtab: */