src/video/SDL_pixels.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 02 Mar 2013 20:44:16 -0800
changeset 6950 1ddb72193079
parent 6885 700f1b25f77f
child 7023 1d49dc7b5ce9
permissions -rw-r--r--
Added a mouse ID to the mouse events, which set to the special value SDL_TOUCH_MOUSEID for mouse events simulated by touch input.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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     if (map->dst) {
   972         /* Release our reference to the surface - see the note below */
   973         if (--map->dst->refcount <= 0) {
   974             SDL_FreeSurface(map->dst);
   975         }
   976     }
   977     map->dst = NULL;
   978     map->src_palette_version = 0;
   979     map->dst_palette_version = 0;
   980     if (map->info.table) {
   981         SDL_free(map->info.table);
   982         map->info.table = NULL;
   983     }
   984 }
   985 
   986 int
   987 SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
   988 {
   989     SDL_PixelFormat *srcfmt;
   990     SDL_PixelFormat *dstfmt;
   991     SDL_BlitMap *map;
   992 
   993     /* Clear out any previous mapping */
   994     map = src->map;
   995     if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
   996         SDL_UnRLESurface(src, 1);
   997     }
   998     SDL_InvalidateMap(map);
   999 
  1000     /* Figure out what kind of mapping we're doing */
  1001     map->identity = 0;
  1002     srcfmt = src->format;
  1003     dstfmt = dst->format;
  1004     if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) {
  1005         if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
  1006             /* Palette --> Palette */
  1007             map->info.table =
  1008                 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
  1009             if (!map->identity) {
  1010                 if (map->info.table == NULL) {
  1011                     return (-1);
  1012                 }
  1013             }
  1014             if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
  1015                 map->identity = 0;
  1016         } else {
  1017             /* Palette --> BitField */
  1018             map->info.table =
  1019                 Map1toN(srcfmt, src->map->info.r, src->map->info.g,
  1020                         src->map->info.b, src->map->info.a, dstfmt);
  1021             if (map->info.table == NULL) {
  1022                 return (-1);
  1023             }
  1024         }
  1025     } else {
  1026         if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
  1027             /* BitField --> Palette */
  1028             map->info.table = MapNto1(srcfmt, dstfmt, &map->identity);
  1029             if (!map->identity) {
  1030                 if (map->info.table == NULL) {
  1031                     return (-1);
  1032                 }
  1033             }
  1034             map->identity = 0;  /* Don't optimize to copy */
  1035         } else {
  1036             /* BitField --> BitField */
  1037             if (srcfmt == dstfmt) {
  1038                 map->identity = 1;
  1039             }
  1040         }
  1041     }
  1042 
  1043     map->dst = dst;
  1044 
  1045     if (map->dst) {
  1046         /* Keep a reference to this surface so it doesn't get deleted
  1047            while we're still pointing at it.
  1048 
  1049            A better method would be for the destination surface to keep
  1050            track of surfaces that are mapped to it and automatically 
  1051            invalidate them when it is freed, but this will do for now.
  1052         */
  1053         ++map->dst->refcount;
  1054     }
  1055 
  1056     if (dstfmt->palette) {
  1057         map->dst_palette_version = dstfmt->palette->version;
  1058     } else {
  1059         map->dst_palette_version = 0;
  1060     }
  1061 
  1062     if (srcfmt->palette) {
  1063         map->src_palette_version = srcfmt->palette->version;
  1064     } else {
  1065         map->src_palette_version = 0;
  1066     }
  1067 
  1068     /* Choose your blitters wisely */
  1069     return (SDL_CalculateBlit(src));
  1070 }
  1071 
  1072 void
  1073 SDL_FreeBlitMap(SDL_BlitMap * map)
  1074 {
  1075     if (map) {
  1076         SDL_InvalidateMap(map);
  1077         SDL_free(map);
  1078     }
  1079 }
  1080 
  1081 void
  1082 SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
  1083 {
  1084     int i;
  1085 
  1086     /* 0.0 gamma is all black */
  1087     if (gamma <= 0.0f) {
  1088         for (i = 0; i < 256; ++i) {
  1089             ramp[i] = 0;
  1090         }
  1091         return;
  1092     } else if (gamma == 1.0f) {
  1093         /* 1.0 gamma is identity */
  1094         for (i = 0; i < 256; ++i) {
  1095             ramp[i] = (i << 8) | i;
  1096         }
  1097         return;
  1098     } else {
  1099         /* Calculate a real gamma ramp */
  1100         int value;
  1101         gamma = 1.0f / gamma;
  1102         for (i = 0; i < 256; ++i) {
  1103             value =
  1104                 (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
  1105             if (value > 65535) {
  1106                 value = 65535;
  1107             }
  1108             ramp[i] = (Uint16) value;
  1109         }
  1110     }
  1111 }
  1112 
  1113 /* vi: set ts=4 sw=4 expandtab: */