src/video/SDL_pixels.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 07 Mar 2011 00:30:05 -0800
changeset 5438 b705640cb34a
parent 5437 ce10653e370c
child 5439 3a778c6c0269
permissions -rw-r--r--
Fixed bitmap order interpretation; SDL defaults to MSB ordering so a bitstream corresponds to a pixel stream.

The bitmap ordering is defined such that the numbering refers to the pixel index from left to right, and the number position refers to the bit position in the byte.

SDL_BITMAPORDER_4321 is the fourth pixel at the high bit and the first pixel at the low bit (LSBFirst)

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