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