2 SDL_image: An example image loading library for use with SDL
3 Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
23 * XPM (X PixMap) image loader:
25 * Supports the XPMv3 format, EXCEPT:
26 * - hotspot coordinates are ignored
27 * - only colour ('c') colour symbols are used
28 * - rgb.txt is not used (for portability), so only RGB colours
29 * are recognized (#rrggbb etc) - only a few basic colour names are
32 * The result is an 8bpp indexed surface if possible, otherwise 32bpp.
33 * The colourkey is correctly set if transparency is used.
35 * Besides the standard API, also provides
37 * SDL_Surface *IMG_ReadXPMFromArray(char **xpm)
39 * that reads the image data from an XPM file included in the C source.
41 * TODO: include rgb.txt here. The full table (from solaris 2.6) only
42 * requires about 13K in binary form.
50 #include "SDL_image.h"
54 /* See if an image is contained in a data source */
55 int IMG_isXPM(SDL_RWops *src)
63 start = SDL_RWtell(src);
65 if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
66 if ( SDL_memcmp(magic, "/* XPM */", sizeof(magic)) == 0 ) {
70 SDL_RWseek(src, start, RW_SEEK_SET);
74 /* Hash table to look up colors from pixel strings */
75 #define STARTING_HASH_SIZE 256
80 struct hash_entry *next;
84 struct hash_entry **table;
85 struct hash_entry *entries; /* array of all entries */
86 struct hash_entry *next_free;
91 static int hash_key(const char *key, int cpp, int size)
97 hash = hash * 33 + *key++;
99 return hash & (size - 1);
102 static struct color_hash *create_colorhash(int maxnum)
105 struct color_hash *hash;
107 /* we know how many entries we need, so we can allocate
109 hash = (struct color_hash *)SDL_malloc(sizeof *hash);
113 /* use power-of-2 sized hash table for decoding speed */
114 for(s = STARTING_HASH_SIZE; s < maxnum; s <<= 1)
117 hash->maxnum = maxnum;
118 bytes = hash->size * sizeof(struct hash_entry **);
119 hash->entries = NULL; /* in case malloc fails */
120 hash->table = (struct hash_entry **)SDL_malloc(bytes);
125 memset(hash->table, 0, bytes);
126 hash->entries = (struct hash_entry *)SDL_malloc(maxnum * sizeof(struct hash_entry));
128 SDL_free(hash->table);
132 hash->next_free = hash->entries;
136 static int add_colorhash(struct color_hash *hash,
137 char *key, int cpp, Uint32 color)
139 int index = hash_key(key, cpp, hash->size);
140 struct hash_entry *e = hash->next_free++;
143 e->next = hash->table[index];
144 hash->table[index] = e;
148 /* fast lookup that works if cpp == 1 */
149 #define QUICK_COLORHASH(hash, key) ((hash)->table[*(Uint8 *)(key)]->color)
151 static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp)
153 struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
155 if(SDL_memcmp(key, entry->key, cpp) == 0)
159 return 0; /* garbage in - garbage out */
162 static void free_colorhash(struct color_hash *hash)
166 SDL_free(hash->table);
168 SDL_free(hash->entries);
174 * convert colour spec to RGB (in 0xrrggbb format).
175 * return 1 if successful.
177 static int color_to_rgb(char *spec, int speclen, Uint32 *rgb)
179 /* poor man's rgb.txt */
180 static struct { char *name; Uint32 rgb; } known[] = {
181 { "none", 0xFFFFFF },
182 { "black", 0x000000 },
183 { "white", 0xFFFFFF },
185 { "green", 0x00FF00 },
186 { "blue", 0x0000FF },
187 /* This table increases the size of the library by 40K, so it's disabled by default */
188 #ifdef EXTENDED_XPM_COLORS
189 { "aliceblue", 0xf0f8ff },
190 { "antiquewhite", 0xfaebd7 },
191 { "antiquewhite1", 0xffefdb },
192 { "antiquewhite2", 0xeedfcc },
193 { "antiquewhite3", 0xcdc0b0 },
194 { "antiquewhite4", 0x8b8378 },
195 { "aqua", 0x00ffff },
196 { "aquamarine", 0x7fffd4 },
197 { "aquamarine1", 0x7fffd4 },
198 { "aquamarine2", 0x76eec6 },
199 { "aquamarine3", 0x66cdaa },
200 { "aquamarine4", 0x458b74 },
201 { "azure", 0xf0ffff },
202 { "azure1", 0xf0ffff },
203 { "azure2", 0xe0eeee },
204 { "azure3", 0xc1cdcd },
205 { "azure4", 0x838b8b },
206 { "beige", 0xf5f5dc },
207 { "bisque", 0xffe4c4 },
208 { "bisque1", 0xffe4c4 },
209 { "bisque2", 0xeed5b7 },
210 { "bisque3", 0xcdb79e },
211 { "bisque4", 0x8b7d6b },
212 { "black", 0x000000 },
213 { "blanchedalmond", 0xffebcd },
214 { "blue", 0x0000ff },
215 { "blue1", 0x0000ff },
216 { "blue2", 0x0000ee },
217 { "blue3", 0x0000cd },
218 { "blue4", 0x00008B },
219 { "blueviolet", 0x8a2be2 },
220 { "brown", 0xA52A2A },
221 { "brown1", 0xFF4040 },
222 { "brown2", 0xEE3B3B },
223 { "brown3", 0xCD3333 },
224 { "brown4", 0x8B2323 },
225 { "burlywood", 0xDEB887 },
226 { "burlywood1", 0xFFD39B },
227 { "burlywood2", 0xEEC591 },
228 { "burlywood3", 0xCDAA7D },
229 { "burlywood4", 0x8B7355 },
230 { "cadetblue", 0x5F9EA0 },
231 { "cadetblue", 0x5f9ea0 },
232 { "cadetblue1", 0x98f5ff },
233 { "cadetblue2", 0x8ee5ee },
234 { "cadetblue3", 0x7ac5cd },
235 { "cadetblue4", 0x53868b },
236 { "chartreuse", 0x7FFF00 },
237 { "chartreuse1", 0x7FFF00 },
238 { "chartreuse2", 0x76EE00 },
239 { "chartreuse3", 0x66CD00 },
240 { "chartreuse4", 0x458B00 },
241 { "chocolate", 0xD2691E },
242 { "chocolate1", 0xFF7F24 },
243 { "chocolate2", 0xEE7621 },
244 { "chocolate3", 0xCD661D },
245 { "chocolate4", 0x8B4513 },
246 { "coral", 0xFF7F50 },
247 { "coral1", 0xFF7256 },
248 { "coral2", 0xEE6A50 },
249 { "coral3", 0xCD5B45 },
250 { "coral4", 0x8B3E2F },
251 { "cornflowerblue", 0x6495ed },
252 { "cornsilk", 0xFFF8DC },
253 { "cornsilk1", 0xFFF8DC },
254 { "cornsilk2", 0xEEE8CD },
255 { "cornsilk3", 0xCDC8B1 },
256 { "cornsilk4", 0x8B8878 },
257 { "crimson", 0xDC143C },
258 { "cyan", 0x00FFFF },
259 { "cyan1", 0x00FFFF },
260 { "cyan2", 0x00EEEE },
261 { "cyan3", 0x00CDCD },
262 { "cyan4", 0x008B8B },
263 { "darkblue", 0x00008b },
264 { "darkcyan", 0x008b8b },
265 { "darkgoldenrod", 0xb8860b },
266 { "darkgoldenrod1", 0xffb90f },
267 { "darkgoldenrod2", 0xeead0e },
268 { "darkgoldenrod3", 0xcd950c },
269 { "darkgoldenrod4", 0x8b6508 },
270 { "darkgray", 0xa9a9a9 },
271 { "darkgreen", 0x006400 },
272 { "darkgrey", 0xa9a9a9 },
273 { "darkkhaki", 0xbdb76b },
274 { "darkmagenta", 0x8b008b },
275 { "darkolivegreen", 0x556b2f },
276 { "darkolivegreen1", 0xcaff70 },
277 { "darkolivegreen2", 0xbcee68 },
278 { "darkolivegreen3", 0xa2cd5a },
279 { "darkolivegreen4", 0x6e8b3d },
280 { "darkorange", 0xff8c00 },
281 { "darkorange1", 0xff7f00 },
282 { "darkorange2", 0xee7600 },
283 { "darkorange3", 0xcd6600 },
284 { "darkorange4", 0x8b4500 },
285 { "darkorchid", 0x9932cc },
286 { "darkorchid1", 0xbf3eff },
287 { "darkorchid2", 0xb23aee },
288 { "darkorchid3", 0x9a32cd },
289 { "darkorchid4", 0x68228b },
290 { "darkred", 0x8b0000 },
291 { "darksalmon", 0xe9967a },
292 { "darkseagreen", 0x8fbc8f },
293 { "darkseagreen1", 0xc1ffc1 },
294 { "darkseagreen2", 0xb4eeb4 },
295 { "darkseagreen3", 0x9bcd9b },
296 { "darkseagreen4", 0x698b69 },
297 { "darkslateblue", 0x483d8b },
298 { "darkslategray", 0x2f4f4f },
299 { "darkslategray1", 0x97ffff },
300 { "darkslategray2", 0x8deeee },
301 { "darkslategray3", 0x79cdcd },
302 { "darkslategray4", 0x528b8b },
303 { "darkslategrey", 0x2f4f4f },
304 { "darkturquoise", 0x00ced1 },
305 { "darkviolet", 0x9400D3 },
306 { "darkviolet", 0x9400d3 },
307 { "deeppink", 0xff1493 },
308 { "deeppink1", 0xff1493 },
309 { "deeppink2", 0xee1289 },
310 { "deeppink3", 0xcd1076 },
311 { "deeppink4", 0x8b0a50 },
312 { "deepskyblue", 0x00bfff },
313 { "deepskyblue1", 0x00bfff },
314 { "deepskyblue2", 0x00b2ee },
315 { "deepskyblue3", 0x009acd },
316 { "deepskyblue4", 0x00688b },
317 { "dimgray", 0x696969 },
318 { "dimgrey", 0x696969 },
319 { "dodgerblue", 0x1e90ff },
320 { "dodgerblue1", 0x1e90ff },
321 { "dodgerblue2", 0x1c86ee },
322 { "dodgerblue3", 0x1874cd },
323 { "dodgerblue4", 0x104e8b },
324 { "firebrick", 0xB22222 },
325 { "firebrick1", 0xFF3030 },
326 { "firebrick2", 0xEE2C2C },
327 { "firebrick3", 0xCD2626 },
328 { "firebrick4", 0x8B1A1A },
329 { "floralwhite", 0xfffaf0 },
330 { "forestgreen", 0x228b22 },
331 { "fractal", 0x808080 },
332 { "fuchsia", 0xFF00FF },
333 { "gainsboro", 0xDCDCDC },
334 { "ghostwhite", 0xf8f8ff },
335 { "gold", 0xFFD700 },
336 { "gold1", 0xFFD700 },
337 { "gold2", 0xEEC900 },
338 { "gold3", 0xCDAD00 },
339 { "gold4", 0x8B7500 },
340 { "goldenrod", 0xDAA520 },
341 { "goldenrod1", 0xFFC125 },
342 { "goldenrod2", 0xEEB422 },
343 { "goldenrod3", 0xCD9B1D },
344 { "goldenrod4", 0x8B6914 },
345 { "gray", 0x7E7E7E },
346 { "gray", 0xBEBEBE },
347 { "gray0", 0x000000 },
348 { "gray1", 0x030303 },
349 { "gray10", 0x1A1A1A },
350 { "gray100", 0xFFFFFF },
351 { "gray11", 0x1C1C1C },
352 { "gray12", 0x1F1F1F },
353 { "gray13", 0x212121 },
354 { "gray14", 0x242424 },
355 { "gray15", 0x262626 },
356 { "gray16", 0x292929 },
357 { "gray17", 0x2B2B2B },
358 { "gray18", 0x2E2E2E },
359 { "gray19", 0x303030 },
360 { "gray2", 0x050505 },
361 { "gray20", 0x333333 },
362 { "gray21", 0x363636 },
363 { "gray22", 0x383838 },
364 { "gray23", 0x3B3B3B },
365 { "gray24", 0x3D3D3D },
366 { "gray25", 0x404040 },
367 { "gray26", 0x424242 },
368 { "gray27", 0x454545 },
369 { "gray28", 0x474747 },
370 { "gray29", 0x4A4A4A },
371 { "gray3", 0x080808 },
372 { "gray30", 0x4D4D4D },
373 { "gray31", 0x4F4F4F },
374 { "gray32", 0x525252 },
375 { "gray33", 0x545454 },
376 { "gray34", 0x575757 },
377 { "gray35", 0x595959 },
378 { "gray36", 0x5C5C5C },
379 { "gray37", 0x5E5E5E },
380 { "gray38", 0x616161 },
381 { "gray39", 0x636363 },
382 { "gray4", 0x0A0A0A },
383 { "gray40", 0x666666 },
384 { "gray41", 0x696969 },
385 { "gray42", 0x6B6B6B },
386 { "gray43", 0x6E6E6E },
387 { "gray44", 0x707070 },
388 { "gray45", 0x737373 },
389 { "gray46", 0x757575 },
390 { "gray47", 0x787878 },
391 { "gray48", 0x7A7A7A },
392 { "gray49", 0x7D7D7D },
393 { "gray5", 0x0D0D0D },
394 { "gray50", 0x7F7F7F },
395 { "gray51", 0x828282 },
396 { "gray52", 0x858585 },
397 { "gray53", 0x878787 },
398 { "gray54", 0x8A8A8A },
399 { "gray55", 0x8C8C8C },
400 { "gray56", 0x8F8F8F },
401 { "gray57", 0x919191 },
402 { "gray58", 0x949494 },
403 { "gray59", 0x969696 },
404 { "gray6", 0x0F0F0F },
405 { "gray60", 0x999999 },
406 { "gray61", 0x9C9C9C },
407 { "gray62", 0x9E9E9E },
408 { "gray63", 0xA1A1A1 },
409 { "gray64", 0xA3A3A3 },
410 { "gray65", 0xA6A6A6 },
411 { "gray66", 0xA8A8A8 },
412 { "gray67", 0xABABAB },
413 { "gray68", 0xADADAD },
414 { "gray69", 0xB0B0B0 },
415 { "gray7", 0x121212 },
416 { "gray70", 0xB3B3B3 },
417 { "gray71", 0xB5B5B5 },
418 { "gray72", 0xB8B8B8 },
419 { "gray73", 0xBABABA },
420 { "gray74", 0xBDBDBD },
421 { "gray75", 0xBFBFBF },
422 { "gray76", 0xC2C2C2 },
423 { "gray77", 0xC4C4C4 },
424 { "gray78", 0xC7C7C7 },
425 { "gray79", 0xC9C9C9 },
426 { "gray8", 0x141414 },
427 { "gray80", 0xCCCCCC },
428 { "gray81", 0xCFCFCF },
429 { "gray82", 0xD1D1D1 },
430 { "gray83", 0xD4D4D4 },
431 { "gray84", 0xD6D6D6 },
432 { "gray85", 0xD9D9D9 },
433 { "gray86", 0xDBDBDB },
434 { "gray87", 0xDEDEDE },
435 { "gray88", 0xE0E0E0 },
436 { "gray89", 0xE3E3E3 },
437 { "gray9", 0x171717 },
438 { "gray90", 0xE5E5E5 },
439 { "gray91", 0xE8E8E8 },
440 { "gray92", 0xEBEBEB },
441 { "gray93", 0xEDEDED },
442 { "gray94", 0xF0F0F0 },
443 { "gray95", 0xF2F2F2 },
444 { "gray96", 0xF5F5F5 },
445 { "gray97", 0xF7F7F7 },
446 { "gray98", 0xFAFAFA },
447 { "gray99", 0xFCFCFC },
448 { "green", 0x008000 },
449 { "green", 0x00FF00 },
450 { "green1", 0x00FF00 },
451 { "green2", 0x00EE00 },
452 { "green3", 0x00CD00 },
453 { "green4", 0x008B00 },
454 { "greenyellow", 0xadff2f },
455 { "grey", 0xBEBEBE },
456 { "grey0", 0x000000 },
457 { "grey1", 0x030303 },
458 { "grey10", 0x1A1A1A },
459 { "grey100", 0xFFFFFF },
460 { "grey11", 0x1C1C1C },
461 { "grey12", 0x1F1F1F },
462 { "grey13", 0x212121 },
463 { "grey14", 0x242424 },
464 { "grey15", 0x262626 },
465 { "grey16", 0x292929 },
466 { "grey17", 0x2B2B2B },
467 { "grey18", 0x2E2E2E },
468 { "grey19", 0x303030 },
469 { "grey2", 0x050505 },
470 { "grey20", 0x333333 },
471 { "grey21", 0x363636 },
472 { "grey22", 0x383838 },
473 { "grey23", 0x3B3B3B },
474 { "grey24", 0x3D3D3D },
475 { "grey25", 0x404040 },
476 { "grey26", 0x424242 },
477 { "grey27", 0x454545 },
478 { "grey28", 0x474747 },
479 { "grey29", 0x4A4A4A },
480 { "grey3", 0x080808 },
481 { "grey30", 0x4D4D4D },
482 { "grey31", 0x4F4F4F },
483 { "grey32", 0x525252 },
484 { "grey33", 0x545454 },
485 { "grey34", 0x575757 },
486 { "grey35", 0x595959 },
487 { "grey36", 0x5C5C5C },
488 { "grey37", 0x5E5E5E },
489 { "grey38", 0x616161 },
490 { "grey39", 0x636363 },
491 { "grey4", 0x0A0A0A },
492 { "grey40", 0x666666 },
493 { "grey41", 0x696969 },
494 { "grey42", 0x6B6B6B },
495 { "grey43", 0x6E6E6E },
496 { "grey44", 0x707070 },
497 { "grey45", 0x737373 },
498 { "grey46", 0x757575 },
499 { "grey47", 0x787878 },
500 { "grey48", 0x7A7A7A },
501 { "grey49", 0x7D7D7D },
502 { "grey5", 0x0D0D0D },
503 { "grey50", 0x7F7F7F },
504 { "grey51", 0x828282 },
505 { "grey52", 0x858585 },
506 { "grey53", 0x878787 },
507 { "grey54", 0x8A8A8A },
508 { "grey55", 0x8C8C8C },
509 { "grey56", 0x8F8F8F },
510 { "grey57", 0x919191 },
511 { "grey58", 0x949494 },
512 { "grey59", 0x969696 },
513 { "grey6", 0x0F0F0F },
514 { "grey60", 0x999999 },
515 { "grey61", 0x9C9C9C },
516 { "grey62", 0x9E9E9E },
517 { "grey63", 0xA1A1A1 },
518 { "grey64", 0xA3A3A3 },
519 { "grey65", 0xA6A6A6 },
520 { "grey66", 0xA8A8A8 },
521 { "grey67", 0xABABAB },
522 { "grey68", 0xADADAD },
523 { "grey69", 0xB0B0B0 },
524 { "grey7", 0x121212 },
525 { "grey70", 0xB3B3B3 },
526 { "grey71", 0xB5B5B5 },
527 { "grey72", 0xB8B8B8 },
528 { "grey73", 0xBABABA },
529 { "grey74", 0xBDBDBD },
530 { "grey75", 0xBFBFBF },
531 { "grey76", 0xC2C2C2 },
532 { "grey77", 0xC4C4C4 },
533 { "grey78", 0xC7C7C7 },
534 { "grey79", 0xC9C9C9 },
535 { "grey8", 0x141414 },
536 { "grey80", 0xCCCCCC },
537 { "grey81", 0xCFCFCF },
538 { "grey82", 0xD1D1D1 },
539 { "grey83", 0xD4D4D4 },
540 { "grey84", 0xD6D6D6 },
541 { "grey85", 0xD9D9D9 },
542 { "grey86", 0xDBDBDB },
543 { "grey87", 0xDEDEDE },
544 { "grey88", 0xE0E0E0 },
545 { "grey89", 0xE3E3E3 },
546 { "grey9", 0x171717 },
547 { "grey90", 0xE5E5E5 },
548 { "grey91", 0xE8E8E8 },
549 { "grey92", 0xEBEBEB },
550 { "grey93", 0xEDEDED },
551 { "grey94", 0xF0F0F0 },
552 { "grey95", 0xF2F2F2 },
553 { "grey96", 0xF5F5F5 },
554 { "grey97", 0xF7F7F7 },
555 { "grey98", 0xFAFAFA },
556 { "grey99", 0xFCFCFC },
557 { "honeydew", 0xF0FFF0 },
558 { "honeydew1", 0xF0FFF0 },
559 { "honeydew2", 0xE0EEE0 },
560 { "honeydew3", 0xC1CDC1 },
561 { "honeydew4", 0x838B83 },
562 { "hotpink", 0xff69b4 },
563 { "hotpink1", 0xff6eb4 },
564 { "hotpink2", 0xee6aa7 },
565 { "hotpink3", 0xcd6090 },
566 { "hotpink4", 0x8b3a62 },
567 { "indianred", 0xcd5c5c },
568 { "indianred1", 0xff6a6a },
569 { "indianred2", 0xee6363 },
570 { "indianred3", 0xcd5555 },
571 { "indianred4", 0x8b3a3a },
572 { "indigo", 0x4B0082 },
573 { "ivory", 0xFFFFF0 },
574 { "ivory1", 0xFFFFF0 },
575 { "ivory2", 0xEEEEE0 },
576 { "ivory3", 0xCDCDC1 },
577 { "ivory4", 0x8B8B83 },
578 { "khaki", 0xF0E68C },
579 { "khaki1", 0xFFF68F },
580 { "khaki2", 0xEEE685 },
581 { "khaki3", 0xCDC673 },
582 { "khaki4", 0x8B864E },
583 { "lavender", 0xE6E6FA },
584 { "lavenderblush", 0xfff0f5 },
585 { "lavenderblush1", 0xfff0f5 },
586 { "lavenderblush2", 0xeee0e5 },
587 { "lavenderblush3", 0xcdc1c5 },
588 { "lavenderblush4", 0x8b8386 },
589 { "lawngreen", 0x7cfc00 },
590 { "lemonchiffon", 0xfffacd },
591 { "lemonchiffon1", 0xfffacd },
592 { "lemonchiffon2", 0xeee9bf },
593 { "lemonchiffon3", 0xcdc9a5 },
594 { "lemonchiffon4", 0x8b8970 },
595 { "lightblue", 0xadd8e6 },
596 { "lightblue1", 0xbfefff },
597 { "lightblue2", 0xb2dfee },
598 { "lightblue3", 0x9ac0cd },
599 { "lightblue4", 0x68838b },
600 { "lightcoral", 0xf08080 },
601 { "lightcyan", 0xe0ffff },
602 { "lightcyan1", 0xe0ffff },
603 { "lightcyan2", 0xd1eeee },
604 { "lightcyan3", 0xb4cdcd },
605 { "lightcyan4", 0x7a8b8b },
606 { "lightgoldenrod", 0xeedd82 },
607 { "lightgoldenrod1", 0xffec8b },
608 { "lightgoldenrod2", 0xeedc82 },
609 { "lightgoldenrod3", 0xcdbe70 },
610 { "lightgoldenrod4", 0x8b814c },
611 { "lightgoldenrodyellow", 0xfafad2 },
612 { "lightgray", 0xd3d3d3 },
613 { "lightgreen", 0x90ee90 },
614 { "lightgrey", 0xd3d3d3 },
615 { "lightpink", 0xffb6c1 },
616 { "lightpink1", 0xffaeb9 },
617 { "lightpink2", 0xeea2ad },
618 { "lightpink3", 0xcd8c95 },
619 { "lightpink4", 0x8b5f65 },
620 { "lightsalmon", 0xffa07a },
621 { "lightsalmon1", 0xffa07a },
622 { "lightsalmon2", 0xee9572 },
623 { "lightsalmon3", 0xcd8162 },
624 { "lightsalmon4", 0x8b5742 },
625 { "lightseagreen", 0x20b2aa },
626 { "lightskyblue", 0x87cefa },
627 { "lightskyblue1", 0xb0e2ff },
628 { "lightskyblue2", 0xa4d3ee },
629 { "lightskyblue3", 0x8db6cd },
630 { "lightskyblue4", 0x607b8b },
631 { "lightslateblue", 0x8470ff },
632 { "lightslategray", 0x778899 },
633 { "lightslategrey", 0x778899 },
634 { "lightsteelblue", 0xb0c4de },
635 { "lightsteelblue1", 0xcae1ff },
636 { "lightsteelblue2", 0xbcd2ee },
637 { "lightsteelblue3", 0xa2b5cd },
638 { "lightsteelblue4", 0x6e7b8b },
639 { "lightyellow", 0xffffe0 },
640 { "lightyellow1", 0xffffe0 },
641 { "lightyellow2", 0xeeeed1 },
642 { "lightyellow3", 0xcdcdb4 },
643 { "lightyellow4", 0x8b8b7a },
644 { "lime", 0x00FF00 },
645 { "limegreen", 0x32cd32 },
646 { "linen", 0xFAF0E6 },
647 { "magenta", 0xFF00FF },
648 { "magenta1", 0xFF00FF },
649 { "magenta2", 0xEE00EE },
650 { "magenta3", 0xCD00CD },
651 { "magenta4", 0x8B008B },
652 { "maroon", 0x800000 },
653 { "maroon", 0xB03060 },
654 { "maroon1", 0xFF34B3 },
655 { "maroon2", 0xEE30A7 },
656 { "maroon3", 0xCD2990 },
657 { "maroon4", 0x8B1C62 },
658 { "mediumaquamarine", 0x66cdaa },
659 { "mediumblue", 0x0000cd },
660 { "mediumforestgreen", 0x32814b },
661 { "mediumgoldenrod", 0xd1c166 },
662 { "mediumorchid", 0xba55d3 },
663 { "mediumorchid1", 0xe066ff },
664 { "mediumorchid2", 0xd15fee },
665 { "mediumorchid3", 0xb452cd },
666 { "mediumorchid4", 0x7a378b },
667 { "mediumpurple", 0x9370db },
668 { "mediumpurple1", 0xab82ff },
669 { "mediumpurple2", 0x9f79ee },
670 { "mediumpurple3", 0x8968cd },
671 { "mediumpurple4", 0x5d478b },
672 { "mediumseagreen", 0x3cb371 },
673 { "mediumslateblue", 0x7b68ee },
674 { "mediumspringgreen", 0x00fa9a },
675 { "mediumturquoise", 0x48d1cc },
676 { "mediumvioletred", 0xc71585 },
677 { "midnightblue", 0x191970 },
678 { "mintcream", 0xf5fffa },
679 { "mistyrose", 0xffe4e1 },
680 { "mistyrose1", 0xffe4e1 },
681 { "mistyrose2", 0xeed5d2 },
682 { "mistyrose3", 0xcdb7b5 },
683 { "mistyrose4", 0x8b7d7b },
684 { "moccasin", 0xFFE4B5 },
685 { "navajowhite", 0xffdead },
686 { "navajowhite1", 0xffdead },
687 { "navajowhite2", 0xeecfa1 },
688 { "navajowhite3", 0xcdb38b },
689 { "navajowhite4", 0x8b795e },
690 { "navy", 0x000080 },
691 { "navyblue", 0x000080 },
692 { "none", 0x0000FF },
693 { "oldlace", 0xfdf5e6 },
694 { "olive", 0x808000 },
695 { "olivedrab", 0x6b8e23 },
696 { "olivedrab1", 0xc0ff3e },
697 { "olivedrab2", 0xb3ee3a },
698 { "olivedrab3", 0x9acd32 },
699 { "olivedrab4", 0x698b22 },
700 { "opaque", 0x000000 },
701 { "orange", 0xFFA500 },
702 { "orange1", 0xFFA500 },
703 { "orange2", 0xEE9A00 },
704 { "orange3", 0xCD8500 },
705 { "orange4", 0x8B5A00 },
706 { "orangered", 0xff4500 },
707 { "orangered1", 0xff4500 },
708 { "orangered2", 0xee4000 },
709 { "orangered3", 0xcd3700 },
710 { "orangered4", 0x8b2500 },
711 { "orchid", 0xDA70D6 },
712 { "orchid1", 0xFF83FA },
713 { "orchid2", 0xEE7AE9 },
714 { "orchid3", 0xCD69C9 },
715 { "orchid4", 0x8B4789 },
716 { "palegoldenrod", 0xeee8aa },
717 { "palegreen", 0x98fb98 },
718 { "palegreen1", 0x9aff9a },
719 { "palegreen2", 0x90ee90 },
720 { "palegreen3", 0x7ccd7c },
721 { "palegreen4", 0x548b54 },
722 { "paleturquoise", 0xafeeee },
723 { "paleturquoise1", 0xbbffff },
724 { "paleturquoise2", 0xaeeeee },
725 { "paleturquoise3", 0x96cdcd },
726 { "paleturquoise4", 0x668b8b },
727 { "palevioletred", 0xdb7093 },
728 { "palevioletred1", 0xff82ab },
729 { "palevioletred2", 0xee799f },
730 { "palevioletred3", 0xcd6889 },
731 { "palevioletred4", 0x8b475d },
732 { "papayawhip", 0xffefd5 },
733 { "peachpuff", 0xffdab9 },
734 { "peachpuff1", 0xffdab9 },
735 { "peachpuff2", 0xeecbad },
736 { "peachpuff3", 0xcdaf95 },
737 { "peachpuff4", 0x8b7765 },
738 { "peru", 0xCD853F },
739 { "pink", 0xFFC0CB },
740 { "pink1", 0xFFB5C5 },
741 { "pink2", 0xEEA9B8 },
742 { "pink3", 0xCD919E },
743 { "pink4", 0x8B636C },
744 { "plum", 0xDDA0DD },
745 { "plum1", 0xFFBBFF },
746 { "plum2", 0xEEAEEE },
747 { "plum3", 0xCD96CD },
748 { "plum4", 0x8B668B },
749 { "powderblue", 0xb0e0e6 },
750 { "purple", 0x800080 },
751 { "purple", 0xA020F0 },
752 { "purple1", 0x9B30FF },
753 { "purple2", 0x912CEE },
754 { "purple3", 0x7D26CD },
755 { "purple4", 0x551A8B },
757 { "red1", 0xFF0000 },
758 { "red2", 0xEE0000 },
759 { "red3", 0xCD0000 },
760 { "red4", 0x8B0000 },
761 { "rosybrown", 0xbc8f8f },
762 { "rosybrown1", 0xffc1c1 },
763 { "rosybrown2", 0xeeb4b4 },
764 { "rosybrown3", 0xcd9b9b },
765 { "rosybrown4", 0x8b6969 },
766 { "royalblue", 0x4169e1 },
767 { "royalblue1", 0x4876ff },
768 { "royalblue2", 0x436eee },
769 { "royalblue3", 0x3a5fcd },
770 { "royalblue4", 0x27408b },
771 { "saddlebrown", 0x8b4513 },
772 { "salmon", 0xFA8072 },
773 { "salmon1", 0xFF8C69 },
774 { "salmon2", 0xEE8262 },
775 { "salmon3", 0xCD7054 },
776 { "salmon4", 0x8B4C39 },
777 { "sandybrown", 0xf4a460 },
778 { "seagreen", 0x2e8b57 },
779 { "seagreen1", 0x54ff9f },
780 { "seagreen2", 0x4eee94 },
781 { "seagreen3", 0x43cd80 },
782 { "seagreen4", 0x2e8b57 },
783 { "seashell", 0xFFF5EE },
784 { "seashell1", 0xFFF5EE },
785 { "seashell2", 0xEEE5DE },
786 { "seashell3", 0xCDC5BF },
787 { "seashell4", 0x8B8682 },
788 { "sienna", 0xA0522D },
789 { "sienna1", 0xFF8247 },
790 { "sienna2", 0xEE7942 },
791 { "sienna3", 0xCD6839 },
792 { "sienna4", 0x8B4726 },
793 { "silver", 0xC0C0C0 },
794 { "skyblue", 0x87ceeb },
795 { "skyblue1", 0x87ceff },
796 { "skyblue2", 0x7ec0ee },
797 { "skyblue3", 0x6ca6cd },
798 { "skyblue4", 0x4a708b },
799 { "slateblue", 0x6a5acd },
800 { "slateblue1", 0x836fff },
801 { "slateblue2", 0x7a67ee },
802 { "slateblue3", 0x6959cd },
803 { "slateblue4", 0x473c8b },
804 { "slategray", 0x708090 },
805 { "slategray1", 0xc6e2ff },
806 { "slategray2", 0xb9d3ee },
807 { "slategray3", 0x9fb6cd },
808 { "slategray4", 0x6c7b8b },
809 { "slategrey", 0x708090 },
810 { "snow", 0xFFFAFA },
811 { "snow1", 0xFFFAFA },
812 { "snow2", 0xEEE9E9 },
813 { "snow3", 0xCDC9C9 },
814 { "snow4", 0x8B8989 },
815 { "springgreen", 0x00ff7f },
816 { "springgreen1", 0x00ff7f },
817 { "springgreen2", 0x00ee76 },
818 { "springgreen3", 0x00cd66 },
819 { "springgreen4", 0x008b45 },
820 { "steelblue", 0x4682b4 },
821 { "steelblue1", 0x63b8ff },
822 { "steelblue2", 0x5cacee },
823 { "steelblue3", 0x4f94cd },
824 { "steelblue4", 0x36648b },
826 { "tan1", 0xFFA54F },
827 { "tan2", 0xEE9A49 },
828 { "tan3", 0xCD853F },
829 { "tan4", 0x8B5A2B },
830 { "teal", 0x008080 },
831 { "thistle", 0xD8BFD8 },
832 { "thistle1", 0xFFE1FF },
833 { "thistle2", 0xEED2EE },
834 { "thistle3", 0xCDB5CD },
835 { "thistle4", 0x8B7B8B },
836 { "tomato", 0xFF6347 },
837 { "tomato1", 0xFF6347 },
838 { "tomato2", 0xEE5C42 },
839 { "tomato3", 0xCD4F39 },
840 { "tomato4", 0x8B3626 },
841 { "transparent", 0x0000FF },
842 { "turquoise", 0x40E0D0 },
843 { "turquoise1", 0x00F5FF },
844 { "turquoise2", 0x00E5EE },
845 { "turquoise3", 0x00C5CD },
846 { "turquoise4", 0x00868B },
847 { "violet", 0xEE82EE },
848 { "violetred", 0xd02090 },
849 { "violetred1", 0xff3e96 },
850 { "violetred2", 0xee3a8c },
851 { "violetred3", 0xcd3278 },
852 { "violetred4", 0x8b2252 },
853 { "wheat", 0xF5DEB3 },
854 { "wheat1", 0xFFE7BA },
855 { "wheat2", 0xEED8AE },
856 { "wheat3", 0xCDBA96 },
857 { "wheat4", 0x8B7E66 },
858 { "white", 0xFFFFFF },
859 { "whitesmoke", 0xf5f5f5 },
860 { "yellow", 0xFFFF00 },
861 { "yellow1", 0xFFFF00 },
862 { "yellow2", 0xEEEE00 },
863 { "yellow3", 0xCDCD00 },
864 { "yellow4", 0x8B8B00 },
865 { "yellowgreen", 0x9acd32 },
866 #endif /* EXTENDED_XPM_COLORS */
874 buf[0] = buf[1] = spec[1];
875 buf[2] = buf[3] = spec[2];
876 buf[4] = buf[5] = spec[3];
879 SDL_memcpy(buf, spec + 1, 6);
891 *rgb = strtol(buf, NULL, 16);
895 for(i = 0; i < SDL_arraysize(known); i++)
896 if(SDL_strncasecmp(known[i].name, spec, speclen) == 0) {
905 #define MAX(a, b) ((a) > (b) ? (a) : (b))
908 static char *linebuf;
913 * Read next line from the source.
914 * If len > 0, it's assumed to be at least len chars (for efficiency).
915 * Return NULL and set error upon EOF or parse error.
917 static char *get_next_line(char ***lines, SDL_RWops *src, int len)
927 if(SDL_RWread(src, &c, 1, 1) <= 0) {
928 error = "Premature end of data";
933 len += 4; /* "\",\n\0" */
936 linebufnew = (char *)SDL_realloc(linebuf, buflen);
939 error = "Out of memory";
942 linebuf = linebufnew;
944 if(SDL_RWread(src, linebuf, len - 1, 1) <= 0) {
945 error = "Premature end of data";
952 if(n >= buflen - 1) {
956 linebufnew = (char *)SDL_realloc(linebuf, buflen);
959 error = "Out of memory";
962 linebuf = linebufnew;
964 if(SDL_RWread(src, linebuf + n, 1, 1) <= 0) {
965 error = "Premature end of data";
968 } while(linebuf[n++] != '"');
976 #define SKIPSPACE(p) \
978 while(SDL_isspace((unsigned char)*(p))) \
982 #define SKIPNONSPACE(p) \
984 while(!SDL_isspace((unsigned char)*(p)) && *p) \
988 /* read XPM from either array or RWops */
989 static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src)
992 SDL_Surface *image = NULL;
995 int w, h, ncolors, cpp;
998 struct color_hash *colors = NULL;
999 SDL_Color *im_colors = NULL;
1000 char *keystrings = NULL, *nextkey;
1002 char ***xpmlines = NULL;
1010 start = SDL_RWtell(src);
1015 line = get_next_line(xpmlines, src, 0);
1019 * The header string of an XPMv3 image has the format
1021 * <width> <height> <ncolors> <cpp> [ <hotspot_x> <hotspot_y> ]
1023 * where the hotspot coords are intended for mouse cursors.
1024 * Right now we don't use the hotspots but it should be handled
1027 if(SDL_sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4
1028 || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) {
1029 error = "Invalid format description";
1033 keystrings = (char *)SDL_malloc(ncolors * cpp);
1035 error = "Out of memory";
1038 nextkey = keystrings;
1040 /* Create the new surface */
1041 if(ncolors <= 256) {
1043 image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8,
1045 im_colors = image->format->palette->colors;
1046 image->format->palette->ncolors = ncolors;
1049 image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
1050 0xff0000, 0x00ff00, 0x0000ff, 0);
1053 /* Hmm, some SDL error (out of memory?) */
1057 /* Read the colors */
1058 colors = create_colorhash(ncolors);
1060 error = "Out of memory";
1063 for(index = 0; index < ncolors; ++index ) {
1065 line = get_next_line(xpmlines, src, 0);
1071 /* parse a colour definition */
1079 error = "colour parse error";
1088 continue; /* skip symbolic colour names */
1090 if(!color_to_rgb(colname, p - colname, &rgb))
1093 SDL_memcpy(nextkey, line, cpp);
1095 SDL_Color *c = im_colors + index;
1096 c->r = (Uint8)(rgb >> 16);
1097 c->g = (Uint8)(rgb >> 8);
1098 c->b = (Uint8)(rgb);
1102 add_colorhash(colors, nextkey, cpp, pixel);
1104 if(rgb == 0xffffffff)
1105 SDL_SetColorKey(image, SDL_TRUE, pixel);
1110 /* Read the pixels */
1111 pixels_len = w * cpp;
1112 dst = (Uint8 *)image->pixels;
1113 for(y = 0; y < h; y++) {
1114 line = get_next_line(xpmlines, src, pixels_len);
1116 /* optimization for some common cases */
1118 for(x = 0; x < w; x++)
1119 dst[x] = (Uint8)QUICK_COLORHASH(colors,
1122 for(x = 0; x < w; x++)
1123 dst[x] = (Uint8)get_colorhash(colors,
1127 for (x = 0; x < w; x++)
1128 ((Uint32*)dst)[x] = get_colorhash(colors,
1132 dst += image->pitch;
1138 SDL_RWseek(src, start, RW_SEEK_SET);
1140 SDL_FreeSurface(image);
1143 IMG_SetError(error);
1146 SDL_free(keystrings);
1147 free_colorhash(colors);
1153 /* Load a XPM type image from an RWops datasource */
1154 SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src)
1157 /* The error message has been set in SDL_RWFromFile */
1160 return load_xpm(NULL, src);
1163 SDL_Surface *IMG_ReadXPMFromArray(char **xpm)
1165 return load_xpm(xpm, NULL);
1168 #else /* not LOAD_XPM */
1170 /* See if an image is contained in a data source */
1171 int IMG_isXPM(SDL_RWops *src)
1177 /* Load a XPM type image from an SDL datasource */
1178 SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src)
1183 SDL_Surface *IMG_ReadXPMFromArray(char **xpm)
1187 #endif /* not LOAD_XPM */