#include <SDL3_image/SDL_image.h>
#ifdef LOAD_XPM
bool IMG_isXPM(SDL_IOStream *src)
{
Sint64 start;
bool is_XPM;
char magic[9];
if (!src) {
return false;
}
start = SDL_TellIO(src);
is_XPM = false;
if (SDL_ReadIO(src, magic, sizeof(magic)) == sizeof(magic) ) {
if ( SDL_memcmp(magic, "/* XPM */", sizeof(magic)) == 0 ) {
is_XPM = true;
}
}
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
return is_XPM;
}
#define STARTING_HASH_SIZE 256
struct hash_entry {
char *key;
Uint32 color;
struct hash_entry *next;
};
struct color_hash {
struct hash_entry **table;
struct hash_entry *entries;
struct hash_entry *next_free;
int size;
int maxnum;
};
static int hash_key(const char *key, int cpp, int size)
{
int hash;
hash = 0;
while ( cpp-- > 0 ) {
hash = hash * 33 + *key++;
}
return hash & (size - 1);
}
static struct color_hash *create_colorhash(int maxnum)
{
int bytes, s;
struct color_hash *hash;
hash = (struct color_hash *)SDL_calloc(1, sizeof(*hash));
if (!hash)
return NULL;
for (s = STARTING_HASH_SIZE; s < maxnum; s <<= 1)
;
hash->size = s;
hash->maxnum = maxnum;
bytes = hash->size * sizeof(struct hash_entry **);
if ((bytes / sizeof(struct hash_entry **)) != (Uint32)hash->size) {
SDL_SetError("memory allocation overflow");
SDL_free(hash);
return NULL;
}
hash->table = (struct hash_entry **)SDL_calloc(1, bytes);
if (!hash->table) {
SDL_free(hash);
return NULL;
}
bytes = maxnum * sizeof(struct hash_entry);
if ((bytes / sizeof(struct hash_entry)) != (Uint32)maxnum) {
SDL_SetError("memory allocation overflow");
SDL_free(hash->table);
SDL_free(hash);
return NULL;
}
hash->entries = (struct hash_entry *)SDL_calloc(1, bytes);
if (!hash->entries) {
SDL_free(hash->table);
SDL_free(hash);
return NULL;
}
hash->next_free = hash->entries;
return hash;
}
static int add_colorhash(struct color_hash *hash,
char *key, int cpp, Uint32 color)
{
int index = hash_key(key, cpp, hash->size);
struct hash_entry *e = hash->next_free++;
e->color = color;
e->key = key;
e->next = hash->table[index];
hash->table[index] = e;
return 1;
}
#define QUICK_COLORHASH(hash, key) ((hash)->table[*(Uint8 *)(key)]->color)
static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp)
{
struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
while (entry) {
if (SDL_memcmp(key, entry->key, cpp) == 0)
return entry->color;
entry = entry->next;
}
return 0;
}
static void free_colorhash(struct color_hash *hash)
{
if (hash) {
if (hash->table)
SDL_free(hash->table);
if (hash->entries)
SDL_free(hash->entries);
SDL_free(hash);
}
}
static int color_to_argb(char *spec, int speclen, Uint32 *argb)
{
static struct { char *name; Uint32 argb; } known[] = {
{ "none", 0x00000000 },
{ "black", 0xff000000 },
{ "white", 0xffFFFFFF },
{ "red", 0xffFF0000 },
{ "green", 0xff00FF00 },
{ "blue", 0xff0000FF },
#ifndef DISABLE_EXTENDED_XPM_COLORS
{ "aliceblue", 0xfff0f8ff },
{ "antiquewhite", 0xfffaebd7 },
{ "antiquewhite1", 0xffffefdb },
{ "antiquewhite2", 0xffeedfcc },
{ "antiquewhite3", 0xffcdc0b0 },
{ "antiquewhite4", 0xff8b8378 },
{ "aqua", 0xff00ffff },
{ "aquamarine", 0xff7fffd4 },
{ "aquamarine1", 0xff7fffd4 },
{ "aquamarine2", 0xff76eec6 },
{ "aquamarine3", 0xff66cdaa },
{ "aquamarine4", 0xff458b74 },
{ "azure", 0xfff0ffff },
{ "azure1", 0xfff0ffff },
{ "azure2", 0xffe0eeee },
{ "azure3", 0xffc1cdcd },
{ "azure4", 0xff838b8b },
{ "beige", 0xfff5f5dc },
{ "bisque", 0xffffe4c4 },
{ "bisque1", 0xffffe4c4 },
{ "bisque2", 0xffeed5b7 },
{ "bisque3", 0xffcdb79e },
{ "bisque4", 0xff8b7d6b },
{ "black", 0xff000000 },
{ "blanchedalmond", 0xffffebcd },
{ "blue", 0xff0000ff },
{ "blue1", 0xff0000ff },
{ "blue2", 0xff0000ee },
{ "blue3", 0xff0000cd },
{ "blue4", 0xff00008B },
{ "blueviolet", 0xff8a2be2 },
{ "brown", 0xffA52A2A },
{ "brown1", 0xffFF4040 },
{ "brown2", 0xffEE3B3B },
{ "brown3", 0xffCD3333 },
{ "brown4", 0xff8B2323 },
{ "burlywood", 0xffDEB887 },
{ "burlywood1", 0xffFFD39B },
{ "burlywood2", 0xffEEC591 },
{ "burlywood3", 0xffCDAA7D },
{ "burlywood4", 0xff8B7355 },
{ "cadetblue", 0xff5F9EA0 },
{ "cadetblue", 0xff5f9ea0 },
{ "cadetblue1", 0xff98f5ff },
{ "cadetblue2", 0xff8ee5ee },
{ "cadetblue3", 0xff7ac5cd },
{ "cadetblue4", 0xff53868b },
{ "chartreuse", 0xff7FFF00 },
{ "chartreuse1", 0xff7FFF00 },
{ "chartreuse2", 0xff76EE00 },
{ "chartreuse3", 0xff66CD00 },
{ "chartreuse4", 0xff458B00 },
{ "chocolate", 0xffD2691E },
{ "chocolate1", 0xffFF7F24 },
{ "chocolate2", 0xffEE7621 },
{ "chocolate3", 0xffCD661D },
{ "chocolate4", 0xff8B4513 },
{ "coral", 0xffFF7F50 },
{ "coral1", 0xffFF7256 },
{ "coral2", 0xffEE6A50 },
{ "coral3", 0xffCD5B45 },
{ "coral4", 0xff8B3E2F },
{ "cornflowerblue", 0xff6495ed },
{ "cornsilk", 0xffFFF8DC },
{ "cornsilk1", 0xffFFF8DC },
{ "cornsilk2", 0xffEEE8CD },
{ "cornsilk3", 0xffCDC8B1 },
{ "cornsilk4", 0xff8B8878 },
{ "crimson", 0xffDC143C },
{ "cyan", 0xff00FFFF },
{ "cyan1", 0xff00FFFF },
{ "cyan2", 0xff00EEEE },
{ "cyan3", 0xff00CDCD },
{ "cyan4", 0xff008B8B },
{ "darkblue", 0xff00008b },
{ "darkcyan", 0xff008b8b },
{ "darkgoldenrod", 0xffb8860b },
{ "darkgoldenrod1", 0xffffb90f },
{ "darkgoldenrod2", 0xffeead0e },
{ "darkgoldenrod3", 0xffcd950c },
{ "darkgoldenrod4", 0xff8b6508 },
{ "darkgray", 0xffa9a9a9 },
{ "darkgreen", 0xff006400 },
{ "darkgrey", 0xffa9a9a9 },
{ "darkkhaki", 0xffbdb76b },
{ "darkmagenta", 0xff8b008b },
{ "darkolivegreen", 0xff556b2f },
{ "darkolivegreen1", 0xffcaff70 },
{ "darkolivegreen2", 0xffbcee68 },
{ "darkolivegreen3", 0xffa2cd5a },
{ "darkolivegreen4", 0xff6e8b3d },
{ "darkorange", 0xffff8c00 },
{ "darkorange1", 0xffff7f00 },
{ "darkorange2", 0xffee7600 },
{ "darkorange3", 0xffcd6600 },
{ "darkorange4", 0xff8b4500 },
{ "darkorchid", 0xff9932cc },
{ "darkorchid1", 0xffbf3eff },
{ "darkorchid2", 0xffb23aee },
{ "darkorchid3", 0xff9a32cd },
{ "darkorchid4", 0xff68228b },
{ "darkred", 0xff8b0000 },
{ "darksalmon", 0xffe9967a },
{ "darkseagreen", 0xff8fbc8f },
{ "darkseagreen1", 0xffc1ffc1 },
{ "darkseagreen2", 0xffb4eeb4 },
{ "darkseagreen3", 0xff9bcd9b },
{ "darkseagreen4", 0xff698b69 },
{ "darkslateblue", 0xff483d8b },
{ "darkslategray", 0xff2f4f4f },
{ "darkslategray1", 0xff97ffff },
{ "darkslategray2", 0xff8deeee },
{ "darkslategray3", 0xff79cdcd },
{ "darkslategray4", 0xff528b8b },
{ "darkslategrey", 0xff2f4f4f },
{ "darkturquoise", 0xff00ced1 },
{ "darkviolet", 0xff9400D3 },
{ "darkviolet", 0xff9400d3 },
{ "deeppink", 0xffff1493 },
{ "deeppink1", 0xffff1493 },
{ "deeppink2", 0xffee1289 },
{ "deeppink3", 0xffcd1076 },
{ "deeppink4", 0xff8b0a50 },
{ "deepskyblue", 0xff00bfff },
{ "deepskyblue1", 0xff00bfff },
{ "deepskyblue2", 0xff00b2ee },
{ "deepskyblue3", 0xff009acd },
{ "deepskyblue4", 0xff00688b },
{ "dimgray", 0xff696969 },
{ "dimgrey", 0xff696969 },
{ "dodgerblue", 0xff1e90ff },
{ "dodgerblue1", 0xff1e90ff },
{ "dodgerblue2", 0xff1c86ee },
{ "dodgerblue3", 0xff1874cd },
{ "dodgerblue4", 0xff104e8b },
{ "firebrick", 0xffB22222 },
{ "firebrick1", 0xffFF3030 },
{ "firebrick2", 0xffEE2C2C },
{ "firebrick3", 0xffCD2626 },
{ "firebrick4", 0xff8B1A1A },
{ "floralwhite", 0xfffffaf0 },
{ "forestgreen", 0xff228b22 },
{ "fractal", 0xff808080 },
{ "fuchsia", 0xffFF00FF },
{ "gainsboro", 0xffDCDCDC },
{ "ghostwhite", 0xfff8f8ff },
{ "gold", 0xffFFD700 },
{ "gold1", 0xffFFD700 },
{ "gold2", 0xffEEC900 },
{ "gold3", 0xffCDAD00 },
{ "gold4", 0xff8B7500 },
{ "goldenrod", 0xffDAA520 },
{ "goldenrod1", 0xffFFC125 },
{ "goldenrod2", 0xffEEB422 },
{ "goldenrod3", 0xffCD9B1D },
{ "goldenrod4", 0xff8B6914 },
{ "gray", 0xff7E7E7E },
{ "gray", 0xffBEBEBE },
{ "gray0", 0xff000000 },
{ "gray1", 0xff030303 },
{ "gray10", 0xff1A1A1A },
{ "gray100", 0xffFFFFFF },
{ "gray11", 0xff1C1C1C },
{ "gray12", 0xff1F1F1F },
{ "gray13", 0xff212121 },
{ "gray14", 0xff242424 },
{ "gray15", 0xff262626 },
{ "gray16", 0xff292929 },
{ "gray17", 0xff2B2B2B },
{ "gray18", 0xff2E2E2E },
{ "gray19", 0xff303030 },
{ "gray2", 0xff050505 },
{ "gray20", 0xff333333 },
{ "gray21", 0xff363636 },
{ "gray22", 0xff383838 },
{ "gray23", 0xff3B3B3B },
{ "gray24", 0xff3D3D3D },
{ "gray25", 0xff404040 },
{ "gray26", 0xff424242 },
{ "gray27", 0xff454545 },
{ "gray28", 0xff474747 },
{ "gray29", 0xff4A4A4A },
{ "gray3", 0xff080808 },
{ "gray30", 0xff4D4D4D },
{ "gray31", 0xff4F4F4F },
{ "gray32", 0xff525252 },
{ "gray33", 0xff545454 },
{ "gray34", 0xff575757 },
{ "gray35", 0xff595959 },
{ "gray36", 0xff5C5C5C },
{ "gray37", 0xff5E5E5E },
{ "gray38", 0xff616161 },
{ "gray39", 0xff636363 },
{ "gray4", 0xff0A0A0A },
{ "gray40", 0xff666666 },
{ "gray41", 0xff696969 },
{ "gray42", 0xff6B6B6B },
{ "gray43", 0xff6E6E6E },
{ "gray44", 0xff707070 },
{ "gray45", 0xff737373 },
{ "gray46", 0xff757575 },
{ "gray47", 0xff787878 },
{ "gray48", 0xff7A7A7A },
{ "gray49", 0xff7D7D7D },
{ "gray5", 0xff0D0D0D },
{ "gray50", 0xff7F7F7F },
{ "gray51", 0xff828282 },
{ "gray52", 0xff858585 },
{ "gray53", 0xff878787 },
{ "gray54", 0xff8A8A8A },
{ "gray55", 0xff8C8C8C },
{ "gray56", 0xff8F8F8F },
{ "gray57", 0xff919191 },
{ "gray58", 0xff949494 },
{ "gray59", 0xff969696 },
{ "gray6", 0xff0F0F0F },
{ "gray60", 0xff999999 },
{ "gray61", 0xff9C9C9C },
{ "gray62", 0xff9E9E9E },
{ "gray63", 0xffA1A1A1 },
{ "gray64", 0xffA3A3A3 },
{ "gray65", 0xffA6A6A6 },
{ "gray66", 0xffA8A8A8 },
{ "gray67", 0xffABABAB },
{ "gray68", 0xffADADAD },
{ "gray69", 0xffB0B0B0 },
{ "gray7", 0xff121212 },
{ "gray70", 0xffB3B3B3 },
{ "gray71", 0xffB5B5B5 },
{ "gray72", 0xffB8B8B8 },
{ "gray73", 0xffBABABA },
{ "gray74", 0xffBDBDBD },
{ "gray75", 0xffBFBFBF },
{ "gray76", 0xffC2C2C2 },
{ "gray77", 0xffC4C4C4 },
{ "gray78", 0xffC7C7C7 },
{ "gray79", 0xffC9C9C9 },
{ "gray8", 0xff141414 },
{ "gray80", 0xffCCCCCC },
{ "gray81", 0xffCFCFCF },
{ "gray82", 0xffD1D1D1 },
{ "gray83", 0xffD4D4D4 },
{ "gray84", 0xffD6D6D6 },
{ "gray85", 0xffD9D9D9 },
{ "gray86", 0xffDBDBDB },
{ "gray87", 0xffDEDEDE },
{ "gray88", 0xffE0E0E0 },
{ "gray89", 0xffE3E3E3 },
{ "gray9", 0xff171717 },
{ "gray90", 0xffE5E5E5 },
{ "gray91", 0xffE8E8E8 },
{ "gray92", 0xffEBEBEB },
{ "gray93", 0xffEDEDED },
{ "gray94", 0xffF0F0F0 },
{ "gray95", 0xffF2F2F2 },
{ "gray96", 0xffF5F5F5 },
{ "gray97", 0xffF7F7F7 },
{ "gray98", 0xffFAFAFA },
{ "gray99", 0xffFCFCFC },
{ "green", 0xff008000 },
{ "green", 0xff00FF00 },
{ "green1", 0xff00FF00 },
{ "green2", 0xff00EE00 },
{ "green3", 0xff00CD00 },
{ "green4", 0xff008B00 },
{ "greenyellow", 0xffadff2f },
{ "grey", 0xffBEBEBE },
{ "grey0", 0xff000000 },
{ "grey1", 0xff030303 },
{ "grey10", 0xff1A1A1A },
{ "grey100", 0xffFFFFFF },
{ "grey11", 0xff1C1C1C },
{ "grey12", 0xff1F1F1F },
{ "grey13", 0xff212121 },
{ "grey14", 0xff242424 },
{ "grey15", 0xff262626 },
{ "grey16", 0xff292929 },
{ "grey17", 0xff2B2B2B },
{ "grey18", 0xff2E2E2E },
{ "grey19", 0xff303030 },
{ "grey2", 0xff050505 },
{ "grey20", 0xff333333 },
{ "grey21", 0xff363636 },
{ "grey22", 0xff383838 },
{ "grey23", 0xff3B3B3B },
{ "grey24", 0xff3D3D3D },
{ "grey25", 0xff404040 },
{ "grey26", 0xff424242 },
{ "grey27", 0xff454545 },
{ "grey28", 0xff474747 },
{ "grey29", 0xff4A4A4A },
{ "grey3", 0xff080808 },
{ "grey30", 0xff4D4D4D },
{ "grey31", 0xff4F4F4F },
{ "grey32", 0xff525252 },
{ "grey33", 0xff545454 },
{ "grey34", 0xff575757 },
{ "grey35", 0xff595959 },
{ "grey36", 0xff5C5C5C },
{ "grey37", 0xff5E5E5E },
{ "grey38", 0xff616161 },
{ "grey39", 0xff636363 },
{ "grey4", 0xff0A0A0A },
{ "grey40", 0xff666666 },
{ "grey41", 0xff696969 },
{ "grey42", 0xff6B6B6B },
{ "grey43", 0xff6E6E6E },
{ "grey44", 0xff707070 },
{ "grey45", 0xff737373 },
{ "grey46", 0xff757575 },
{ "grey47", 0xff787878 },
{ "grey48", 0xff7A7A7A },
{ "grey49", 0xff7D7D7D },
{ "grey5", 0xff0D0D0D },
{ "grey50", 0xff7F7F7F },
{ "grey51", 0xff828282 },
{ "grey52", 0xff858585 },
{ "grey53", 0xff878787 },
{ "grey54", 0xff8A8A8A },
{ "grey55", 0xff8C8C8C },
{ "grey56", 0xff8F8F8F },
{ "grey57", 0xff919191 },
{ "grey58", 0xff949494 },
{ "grey59", 0xff969696 },
{ "grey6", 0xff0F0F0F },
{ "grey60", 0xff999999 },
{ "grey61", 0xff9C9C9C },
{ "grey62", 0xff9E9E9E },
{ "grey63", 0xffA1A1A1 },
{ "grey64", 0xffA3A3A3 },
{ "grey65", 0xffA6A6A6 },
{ "grey66", 0xffA8A8A8 },
{ "grey67", 0xffABABAB },
{ "grey68", 0xffADADAD },
{ "grey69", 0xffB0B0B0 },
{ "grey7", 0xff121212 },
{ "grey70", 0xffB3B3B3 },
{ "grey71", 0xffB5B5B5 },
{ "grey72", 0xffB8B8B8 },
{ "grey73", 0xffBABABA },
{ "grey74", 0xffBDBDBD },
{ "grey75", 0xffBFBFBF },
{ "grey76", 0xffC2C2C2 },
{ "grey77", 0xffC4C4C4 },
{ "grey78", 0xffC7C7C7 },
{ "grey79", 0xffC9C9C9 },
{ "grey8", 0xff141414 },
{ "grey80", 0xffCCCCCC },
{ "grey81", 0xffCFCFCF },
{ "grey82", 0xffD1D1D1 },
{ "grey83", 0xffD4D4D4 },
{ "grey84", 0xffD6D6D6 },
{ "grey85", 0xffD9D9D9 },
{ "grey86", 0xffDBDBDB },
{ "grey87", 0xffDEDEDE },
{ "grey88", 0xffE0E0E0 },
{ "grey89", 0xffE3E3E3 },
{ "grey9", 0xff171717 },
{ "grey90", 0xffE5E5E5 },
{ "grey91", 0xffE8E8E8 },
{ "grey92", 0xffEBEBEB },
{ "grey93", 0xffEDEDED },
{ "grey94", 0xffF0F0F0 },
{ "grey95", 0xffF2F2F2 },
{ "grey96", 0xffF5F5F5 },
{ "grey97", 0xffF7F7F7 },
{ "grey98", 0xffFAFAFA },
{ "grey99", 0xffFCFCFC },
{ "honeydew", 0xffF0FFF0 },
{ "honeydew1", 0xffF0FFF0 },
{ "honeydew2", 0xffE0EEE0 },
{ "honeydew3", 0xffC1CDC1 },
{ "honeydew4", 0xff838B83 },
{ "hotpink", 0xffff69b4 },
{ "hotpink1", 0xffff6eb4 },
{ "hotpink2", 0xffee6aa7 },
{ "hotpink3", 0xffcd6090 },
{ "hotpink4", 0xff8b3a62 },
{ "indianred", 0xffcd5c5c },
{ "indianred1", 0xffff6a6a },
{ "indianred2", 0xffee6363 },
{ "indianred3", 0xffcd5555 },
{ "indianred4", 0xff8b3a3a },
{ "indigo", 0xff4B0082 },
{ "ivory", 0xffFFFFF0 },
{ "ivory1", 0xffFFFFF0 },
{ "ivory2", 0xffEEEEE0 },
{ "ivory3", 0xffCDCDC1 },
{ "ivory4", 0xff8B8B83 },
{ "khaki", 0xffF0E68C },
{ "khaki1", 0xffFFF68F },
{ "khaki2", 0xffEEE685 },
{ "khaki3", 0xffCDC673 },
{ "khaki4", 0xff8B864E },
{ "lavender", 0xffE6E6FA },
{ "lavenderblush", 0xfffff0f5 },
{ "lavenderblush1", 0xfffff0f5 },
{ "lavenderblush2", 0xffeee0e5 },
{ "lavenderblush3", 0xffcdc1c5 },
{ "lavenderblush4", 0xff8b8386 },
{ "lawngreen", 0xff7cfc00 },
{ "lemonchiffon", 0xfffffacd },
{ "lemonchiffon1", 0xfffffacd },
{ "lemonchiffon2", 0xffeee9bf },
{ "lemonchiffon3", 0xffcdc9a5 },
{ "lemonchiffon4", 0xff8b8970 },
{ "lightblue", 0xffadd8e6 },
{ "lightblue1", 0xffbfefff },
{ "lightblue2", 0xffb2dfee },
{ "lightblue3", 0xff9ac0cd },
{ "lightblue4", 0xff68838b },
{ "lightcoral", 0xfff08080 },
{ "lightcyan", 0xffe0ffff },
{ "lightcyan1", 0xffe0ffff },
{ "lightcyan2", 0xffd1eeee },
{ "lightcyan3", 0xffb4cdcd },
{ "lightcyan4", 0xff7a8b8b },
{ "lightgoldenrod", 0xffeedd82 },
{ "lightgoldenrod1", 0xffffec8b },
{ "lightgoldenrod2", 0xffeedc82 },
{ "lightgoldenrod3", 0xffcdbe70 },
{ "lightgoldenrod4", 0xff8b814c },
{ "lightgoldenrodyellow", 0xfffafad2 },
{ "lightgray", 0xffd3d3d3 },
{ "lightgreen", 0xff90ee90 },
{ "lightgrey", 0xffd3d3d3 },
{ "lightpink", 0xffffb6c1 },
{ "lightpink1", 0xffffaeb9 },
{ "lightpink2", 0xffeea2ad },
{ "lightpink3", 0xffcd8c95 },
{ "lightpink4", 0xff8b5f65 },
{ "lightsalmon", 0xffffa07a },
{ "lightsalmon1", 0xffffa07a },
{ "lightsalmon2", 0xffee9572 },
{ "lightsalmon3", 0xffcd8162 },
{ "lightsalmon4", 0xff8b5742 },
{ "lightseagreen", 0xff20b2aa },
{ "lightskyblue", 0xff87cefa },
{ "lightskyblue1", 0xffb0e2ff },
{ "lightskyblue2", 0xffa4d3ee },
{ "lightskyblue3", 0xff8db6cd },
{ "lightskyblue4", 0xff607b8b },
{ "lightslateblue", 0xff8470ff },
{ "lightslategray", 0xff778899 },
{ "lightslategrey", 0xff778899 },
{ "lightsteelblue", 0xffb0c4de },
{ "lightsteelblue1", 0xffcae1ff },
{ "lightsteelblue2", 0xffbcd2ee },
{ "lightsteelblue3", 0xffa2b5cd },
{ "lightsteelblue4", 0xff6e7b8b },
{ "lightyellow", 0xffffffe0 },
{ "lightyellow1", 0xffffffe0 },
{ "lightyellow2", 0xffeeeed1 },
{ "lightyellow3", 0xffcdcdb4 },
{ "lightyellow4", 0xff8b8b7a },
{ "lime", 0xff00FF00 },
{ "limegreen", 0xff32cd32 },
{ "linen", 0xffFAF0E6 },
{ "magenta", 0xffFF00FF },
{ "magenta1", 0xffFF00FF },
{ "magenta2", 0xffEE00EE },
{ "magenta3", 0xffCD00CD },
{ "magenta4", 0xff8B008B },
{ "maroon", 0xff800000 },
{ "maroon", 0xffB03060 },
{ "maroon1", 0xffFF34B3 },
{ "maroon2", 0xffEE30A7 },
{ "maroon3", 0xffCD2990 },
{ "maroon4", 0xff8B1C62 },
{ "mediumaquamarine", 0xff66cdaa },
{ "mediumblue", 0xff0000cd },
{ "mediumforestgreen", 0xff32814b },
{ "mediumgoldenrod", 0xffd1c166 },
{ "mediumorchid", 0xffba55d3 },
{ "mediumorchid1", 0xffe066ff },
{ "mediumorchid2", 0xffd15fee },
{ "mediumorchid3", 0xffb452cd },
{ "mediumorchid4", 0xff7a378b },
{ "mediumpurple", 0xff9370db },
{ "mediumpurple1", 0xffab82ff },
{ "mediumpurple2", 0xff9f79ee },
{ "mediumpurple3", 0xff8968cd },
{ "mediumpurple4", 0xff5d478b },
{ "mediumseagreen", 0xff3cb371 },
{ "mediumslateblue", 0xff7b68ee },
{ "mediumspringgreen", 0xff00fa9a },
{ "mediumturquoise", 0xff48d1cc },
{ "mediumvioletred", 0xffc71585 },
{ "midnightblue", 0xff191970 },
{ "mintcream", 0xfff5fffa },
{ "mistyrose", 0xffffe4e1 },
{ "mistyrose1", 0xffffe4e1 },
{ "mistyrose2", 0xffeed5d2 },
{ "mistyrose3", 0xffcdb7b5 },
{ "mistyrose4", 0xff8b7d7b },
{ "moccasin", 0xffFFE4B5 },
{ "navajowhite", 0xffffdead },
{ "navajowhite1", 0xffffdead },
{ "navajowhite2", 0xffeecfa1 },
{ "navajowhite3", 0xffcdb38b },
{ "navajowhite4", 0xff8b795e },
{ "navy", 0xff000080 },
{ "navyblue", 0xff000080 },
{ "none", 0xff0000FF },
{ "oldlace", 0xfffdf5e6 },
{ "olive", 0xff808000 },
{ "olivedrab", 0xff6b8e23 },
{ "olivedrab1", 0xffc0ff3e },
{ "olivedrab2", 0xffb3ee3a },
{ "olivedrab3", 0xff9acd32 },
{ "olivedrab4", 0xff698b22 },
{ "opaque", 0xff000000 },
{ "orange", 0xffFFA500 },
{ "orange1", 0xffFFA500 },
{ "orange2", 0xffEE9A00 },
{ "orange3", 0xffCD8500 },
{ "orange4", 0xff8B5A00 },
{ "orangered", 0xffff4500 },
{ "orangered1", 0xffff4500 },
{ "orangered2", 0xffee4000 },
{ "orangered3", 0xffcd3700 },
{ "orangered4", 0xff8b2500 },
{ "orchid", 0xffDA70D6 },
{ "orchid1", 0xffFF83FA },
{ "orchid2", 0xffEE7AE9 },
{ "orchid3", 0xffCD69C9 },
{ "orchid4", 0xff8B4789 },
{ "palegoldenrod", 0xffeee8aa },
{ "palegreen", 0xff98fb98 },
{ "palegreen1", 0xff9aff9a },
{ "palegreen2", 0xff90ee90 },
{ "palegreen3", 0xff7ccd7c },
{ "palegreen4", 0xff548b54 },
{ "paleturquoise", 0xffafeeee },
{ "paleturquoise1", 0xffbbffff },
{ "paleturquoise2", 0xffaeeeee },
{ "paleturquoise3", 0xff96cdcd },
{ "paleturquoise4", 0xff668b8b },
{ "palevioletred", 0xffdb7093 },
{ "palevioletred1", 0xffff82ab },
{ "palevioletred2", 0xffee799f },
{ "palevioletred3", 0xffcd6889 },
{ "palevioletred4", 0xff8b475d },
{ "papayawhip", 0xffffefd5 },
{ "peachpuff", 0xffffdab9 },
{ "peachpuff1", 0xffffdab9 },
{ "peachpuff2", 0xffeecbad },
{ "peachpuff3", 0xffcdaf95 },
{ "peachpuff4", 0xff8b7765 },
{ "peru", 0xffCD853F },
{ "pink", 0xffFFC0CB },
{ "pink1", 0xffFFB5C5 },
{ "pink2", 0xffEEA9B8 },
{ "pink3", 0xffCD919E },
{ "pink4", 0xff8B636C },
{ "plum", 0xffDDA0DD },
{ "plum1", 0xffFFBBFF },
{ "plum2", 0xffEEAEEE },
{ "plum3", 0xffCD96CD },
{ "plum4", 0xff8B668B },
{ "powderblue", 0xffb0e0e6 },
{ "purple", 0xff800080 },
{ "purple", 0xffA020F0 },
{ "purple1", 0xff9B30FF },
{ "purple2", 0xff912CEE },
{ "purple3", 0xff7D26CD },
{ "purple4", 0xff551A8B },
{ "red", 0xffFF0000 },
{ "red1", 0xffFF0000 },
{ "red2", 0xffEE0000 },
{ "red3", 0xffCD0000 },
{ "red4", 0xff8B0000 },
{ "rosybrown", 0xffbc8f8f },
{ "rosybrown1", 0xffffc1c1 },
{ "rosybrown2", 0xffeeb4b4 },
{ "rosybrown3", 0xffcd9b9b },
{ "rosybrown4", 0xff8b6969 },
{ "royalblue", 0xff4169e1 },
{ "royalblue1", 0xff4876ff },
{ "royalblue2", 0xff436eee },
{ "royalblue3", 0xff3a5fcd },
{ "royalblue4", 0xff27408b },
{ "saddlebrown", 0xff8b4513 },
{ "salmon", 0xffFA8072 },
{ "salmon1", 0xffFF8C69 },
{ "salmon2", 0xffEE8262 },
{ "salmon3", 0xffCD7054 },
{ "salmon4", 0xff8B4C39 },
{ "sandybrown", 0xfff4a460 },
{ "seagreen", 0xff2e8b57 },
{ "seagreen1", 0xff54ff9f },
{ "seagreen2", 0xff4eee94 },
{ "seagreen3", 0xff43cd80 },
{ "seagreen4", 0xff2e8b57 },
{ "seashell", 0xffFFF5EE },
{ "seashell1", 0xffFFF5EE },
{ "seashell2", 0xffEEE5DE },
{ "seashell3", 0xffCDC5BF },
{ "seashell4", 0xff8B8682 },
{ "sienna", 0xffA0522D },
{ "sienna1", 0xffFF8247 },
{ "sienna2", 0xffEE7942 },
{ "sienna3", 0xffCD6839 },
{ "sienna4", 0xff8B4726 },
{ "silver", 0xffC0C0C0 },
{ "skyblue", 0xff87ceeb },
{ "skyblue1", 0xff87ceff },
{ "skyblue2", 0xff7ec0ee },
{ "skyblue3", 0xff6ca6cd },
{ "skyblue4", 0xff4a708b },
{ "slateblue", 0xff6a5acd },
{ "slateblue1", 0xff836fff },
{ "slateblue2", 0xff7a67ee },
{ "slateblue3", 0xff6959cd },
{ "slateblue4", 0xff473c8b },
{ "slategray", 0xff708090 },
{ "slategray1", 0xffc6e2ff },
{ "slategray2", 0xffb9d3ee },
{ "slategray3", 0xff9fb6cd },
{ "slategray4", 0xff6c7b8b },
{ "slategrey", 0xff708090 },
{ "snow", 0xffFFFAFA },
{ "snow1", 0xffFFFAFA },
{ "snow2", 0xffEEE9E9 },
{ "snow3", 0xffCDC9C9 },
{ "snow4", 0xff8B8989 },
{ "springgreen", 0xff00ff7f },
{ "springgreen1", 0xff00ff7f },
{ "springgreen2", 0xff00ee76 },
{ "springgreen3", 0xff00cd66 },
{ "springgreen4", 0xff008b45 },
{ "steelblue", 0xff4682b4 },
{ "steelblue1", 0xff63b8ff },
{ "steelblue2", 0xff5cacee },
{ "steelblue3", 0xff4f94cd },
{ "steelblue4", 0xff36648b },
{ "tan", 0xffD2B48C },
{ "tan1", 0xffFFA54F },
{ "tan2", 0xffEE9A49 },
{ "tan3", 0xffCD853F },
{ "tan4", 0xff8B5A2B },
{ "teal", 0xff008080 },
{ "thistle", 0xffD8BFD8 },
{ "thistle1", 0xffFFE1FF },
{ "thistle2", 0xffEED2EE },
{ "thistle3", 0xffCDB5CD },
{ "thistle4", 0xff8B7B8B },
{ "tomato", 0xffFF6347 },
{ "tomato1", 0xffFF6347 },
{ "tomato2", 0xffEE5C42 },
{ "tomato3", 0xffCD4F39 },
{ "tomato4", 0xff8B3626 },
{ "transparent", 0xff0000FF },
{ "turquoise", 0xff40E0D0 },
{ "turquoise1", 0xff00F5FF },
{ "turquoise2", 0xff00E5EE },
{ "turquoise3", 0xff00C5CD },
{ "turquoise4", 0xff00868B },
{ "violet", 0xffEE82EE },
{ "violetred", 0xffd02090 },
{ "violetred1", 0xffff3e96 },
{ "violetred2", 0xffee3a8c },
{ "violetred3", 0xffcd3278 },
{ "violetred4", 0xff8b2252 },
{ "wheat", 0xffF5DEB3 },
{ "wheat1", 0xffFFE7BA },
{ "wheat2", 0xffEED8AE },
{ "wheat3", 0xffCDBA96 },
{ "wheat4", 0xff8B7E66 },
{ "white", 0xffFFFFFF },
{ "whitesmoke", 0xfff5f5f5 },
{ "yellow", 0xffFFFF00 },
{ "yellow1", 0xffFFFF00 },
{ "yellow2", 0xffEEEE00 },
{ "yellow3", 0xffCDCD00 },
{ "yellow4", 0xff8B8B00 },
{ "yellowgreen", 0xff9acd32 },
#endif
};
if (spec[0] == '#') {
char buf[7];
switch(speclen) {
case 4:
buf[0] = buf[1] = spec[1];
buf[2] = buf[3] = spec[2];
buf[4] = buf[5] = spec[3];
break;
case 7:
SDL_memcpy(buf, spec + 1, 6);
break;
case 13:
buf[0] = spec[1];
buf[1] = spec[2];
buf[2] = spec[5];
buf[3] = spec[6];
buf[4] = spec[9];
buf[5] = spec[10];
break;
}
buf[6] = '\0';
*argb = 0xff000000 | (Uint32)SDL_strtol(buf, NULL, 16);
return 1;
} else {
size_t i;
for (i = 0; i < SDL_arraysize(known); i++) {
if (SDL_strncasecmp(known[i].name, spec, speclen) == 0) {
*argb = known[i].argb;
return 1;
}
}
return 0;
}
}
static char *linebuf;
static size_t buflen;
static char *error;
static char *get_next_line(char ***lines, SDL_IOStream *src, size_t len)
{
char *linebufnew;
if (lines) {
return *(*lines)++;
} else {
char c;
size_t n;
do {
if (SDL_ReadIO(src, &c, 1) != 1) {
error = "Premature end of data";
return NULL;
}
} while (c != '"');
if (len) {
len += 3;
if (len > buflen){
buflen = len;
linebufnew = (char *)SDL_realloc(linebuf, buflen);
if (!linebufnew) {
SDL_free(linebuf);
error = "Out of memory";
return NULL;
}
linebuf = linebufnew;
}
if (SDL_ReadIO(src, linebuf, len) != len) {
error = "Premature end of data";
return NULL;
}
n = len - 1;
} else {
n = 0;
do {
if (n >= buflen) {
if (buflen == 0)
buflen = 16;
buflen *= 2;
linebufnew = (char *)SDL_realloc(linebuf, buflen);
if (!linebufnew) {
SDL_free(linebuf);
error = "Out of memory";
return NULL;
}
linebuf = linebufnew;
}
if (SDL_ReadIO(src, linebuf + n, 1) != 1) {
error = "Premature end of data";
return NULL;
}
} while (linebuf[n++] != '"');
n--;
}
linebuf[n] = '\0';
return linebuf;
}
}
#define SKIPSPACE(p) \
do { \
while (SDL_isspace((unsigned char)*(p))) \
++(p); \
} while (0)
#define SKIPNONSPACE(p) \
do { \
while (!SDL_isspace((unsigned char)*(p)) && *p) \
++(p); \
} while (0)
static SDL_Surface *load_xpm(char **xpm, SDL_IOStream *src, bool force_32bit)
{
Sint64 start = 0;
SDL_Surface *image = NULL;
int index;
int x, y;
int w, h, ncolors, cpp;
int indexed;
Uint8 *dst;
struct color_hash *colors = NULL;
SDL_Color *im_colors = NULL;
char *keystrings = NULL, *nextkey;
char *line;
char ***xpmlines = NULL;
size_t pixels_len;
error = NULL;
linebuf = NULL;
buflen = 0;
if (src)
start = SDL_TellIO(src);
if (xpm)
xpmlines = &xpm;
line = get_next_line(xpmlines, src, 0);
if (!line)
goto done;
if (SDL_sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4
|| w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) {
error = "Invalid format description";
goto done;
}
if ((size_t)((Uint32)ncolors * cpp)/cpp != (Uint32)ncolors) {
error = "Invalid color specification";
goto done;
}
keystrings = (char *)SDL_malloc(ncolors * cpp);
if (!keystrings) {
error = "Out of memory";
goto done;
}
nextkey = keystrings;
if (ncolors <= 256 && !force_32bit) {
indexed = 1;
image = SDL_CreateSurface(w, h, SDL_PIXELFORMAT_INDEX8);
if (image) {
SDL_Palette *palette = SDL_CreateSurfacePalette(image);
if (!palette) {
error = "Couldn't create palette";
goto done;
}
if (ncolors > palette->ncolors) {
ncolors = palette->ncolors;
}
palette->ncolors = ncolors;
im_colors = palette->colors;
}
} else {
indexed = 0;
image = SDL_CreateSurface(w, h, SDL_PIXELFORMAT_ARGB8888);
}
if (!image) {
goto done;
}
colors = create_colorhash(ncolors);
if (!colors) {
error = "Out of memory";
goto done;
}
for (index = 0; index < ncolors; ++index ) {
char *p;
line = get_next_line(xpmlines, src, 0);
if (!line)
goto done;
p = line + cpp + 1;
for (;;) {
char nametype;
char *colname;
Uint32 argb, pixelvalue;
SKIPSPACE(p);
if (!*p) {
error = "colour parse error";
goto done;
}
nametype = *p;
SKIPNONSPACE(p);
SKIPSPACE(p);
colname = p;
SKIPNONSPACE(p);
if (nametype == 's')
continue;
if (!color_to_argb(colname, (int)(p - colname), &argb))
continue;
SDL_memcpy(nextkey, line, cpp);
if (indexed) {
SDL_Color *c = im_colors + index;
c->a = (Uint8)(argb >> 24);
c->r = (Uint8)(argb >> 16);
c->g = (Uint8)(argb >> 8);
c->b = (Uint8)(argb);
pixelvalue = index;
if (argb == 0x00000000) {
SDL_SetSurfaceColorKey(image, true, pixelvalue);
}
} else {
pixelvalue = argb;
}
add_colorhash(colors, nextkey, cpp, pixelvalue);
nextkey += cpp;
break;
}
}
pixels_len = w * cpp;
dst = (Uint8 *)image->pixels;
for (y = 0; y < h; y++) {
line = get_next_line(xpmlines, src, pixels_len);
if (!line)
goto done;
if (indexed) {
if (cpp == 1)
for (x = 0; x < w; x++)
dst[x] = (Uint8)QUICK_COLORHASH(colors,
line + x);
else
for (x = 0; x < w; x++)
dst[x] = (Uint8)get_colorhash(colors,
line + x * cpp,
cpp);
} else {
for (x = 0; x < w; x++)
((Uint32*)dst)[x] = get_colorhash(colors,
line + x * cpp,
cpp);
}
dst += image->pitch;
}
done:
if (error) {
if ( src )
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
if ( image ) {
SDL_DestroySurface(image);
image = NULL;
}
SDL_SetError("%s", error);
}
if (keystrings)
SDL_free(keystrings);
free_colorhash(colors);
if (linebuf)
SDL_free(linebuf);
return image;
}
SDL_Surface *IMG_LoadXPM_IO(SDL_IOStream *src)
{
if ( !src ) {
return NULL;
}
return load_xpm(NULL, src, 0);
}
SDL_Surface *IMG_ReadXPMFromArray(char **xpm)
{
if (!xpm) {
SDL_SetError("array is NULL");
return NULL;
}
return load_xpm(xpm, NULL, false);
}
SDL_Surface *IMG_ReadXPMFromArrayToRGB888(char **xpm)
{
if (!xpm) {
SDL_SetError("array is NULL");
return NULL;
}
return load_xpm(xpm, NULL, true);
}
#else
bool IMG_isXPM(SDL_IOStream *src)
{
return false;
}
SDL_Surface *IMG_LoadXPM_IO(SDL_IOStream *src)
{
SDL_SetError("SDL_image built without XPM support");
return NULL;
}
SDL_Surface *IMG_ReadXPMFromArray(char **xpm)
{
SDL_SetError("SDL_image built without XPM support");
return NULL;
}
SDL_Surface *IMG_ReadXPMFromArrayToRGB888(char **xpm)
{
SDL_SetError("SDL_image built without XPM support");
return NULL;
}
#endif