IMG_xpm.c
changeset 343 5bf0f0d6a74e
parent 339 2e4f9d95a8c8
child 344 d59179e84a3b
equal deleted inserted replaced
341:18ab81286e51 343:5bf0f0d6a74e
    52 #ifdef LOAD_XPM
    52 #ifdef LOAD_XPM
    53 
    53 
    54 /* See if an image is contained in a data source */
    54 /* See if an image is contained in a data source */
    55 int IMG_isXPM(SDL_RWops *src)
    55 int IMG_isXPM(SDL_RWops *src)
    56 {
    56 {
    57 	int start;
    57 	Sint64 start;
    58 	int is_XPM;
    58 	int is_XPM;
    59 	char magic[9];
    59 	char magic[9];
    60 
    60 
    61 	if ( !src )
    61 	if ( !src )
    62 		return 0;
    62 		return 0;
    63 	start = SDL_RWtell(src);
    63 	start = SDL_RWtell(src);
    64 	is_XPM = 0;
    64 	is_XPM = 0;
    65 	if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
    65 	if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
    66 		if ( memcmp(magic, "/* XPM */", sizeof(magic)) == 0 ) {
    66 		if ( SDL_memcmp(magic, "/* XPM */", sizeof(magic)) == 0 ) {
    67 			is_XPM = 1;
    67 			is_XPM = 1;
    68 		}
    68 		}
    69 	}
    69 	}
    70 	SDL_RWseek(src, start, RW_SEEK_SET);
    70 	SDL_RWseek(src, start, RW_SEEK_SET);
    71 	return(is_XPM);
    71 	return(is_XPM);
   104 	int bytes, s;
   104 	int bytes, s;
   105 	struct color_hash *hash;
   105 	struct color_hash *hash;
   106 
   106 
   107 	/* we know how many entries we need, so we can allocate
   107 	/* we know how many entries we need, so we can allocate
   108 	   everything here */
   108 	   everything here */
   109 	hash = malloc(sizeof *hash);
   109 	hash = (struct color_hash *)SDL_malloc(sizeof *hash);
   110 	if(!hash)
   110 	if(!hash)
   111 		return NULL;
   111 		return NULL;
   112 
   112 
   113 	/* use power-of-2 sized hash table for decoding speed */
   113 	/* use power-of-2 sized hash table for decoding speed */
   114 	for(s = STARTING_HASH_SIZE; s < maxnum; s <<= 1)
   114 	for(s = STARTING_HASH_SIZE; s < maxnum; s <<= 1)
   115 		;
   115 		;
   116 	hash->size = s;
   116 	hash->size = s;
   117 	hash->maxnum = maxnum;
   117 	hash->maxnum = maxnum;
   118 	bytes = hash->size * sizeof(struct hash_entry **);
   118 	bytes = hash->size * sizeof(struct hash_entry **);
   119 	hash->entries = NULL;	/* in case malloc fails */
   119 	hash->entries = NULL;	/* in case malloc fails */
   120 	hash->table = malloc(bytes);
   120 	hash->table = (struct hash_entry **)SDL_malloc(bytes);
   121 	if(!hash->table)
   121 	if(!hash->table)
   122 		return NULL;
   122 		return NULL;
   123 	memset(hash->table, 0, bytes);
   123 	memset(hash->table, 0, bytes);
   124 	hash->entries = malloc(maxnum * sizeof(struct hash_entry));
   124 	hash->entries = (struct hash_entry *)SDL_malloc(maxnum * sizeof(struct hash_entry));
   125 	if(!hash->entries) {
   125 	if(!hash->entries) {
   126 		free(hash->table);
   126 		SDL_free(hash->table);
   127 		return NULL;
   127 		return NULL;
   128 	}
   128 	}
   129 	hash->next_free = hash->entries;
   129 	hash->next_free = hash->entries;
   130 	return hash;
   130 	return hash;
   131 }
   131 }
   147 
   147 
   148 static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp)
   148 static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp)
   149 {
   149 {
   150 	struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
   150 	struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
   151 	while(entry) {
   151 	while(entry) {
   152 		if(memcmp(key, entry->key, cpp) == 0)
   152 		if(SDL_memcmp(key, entry->key, cpp) == 0)
   153 			return entry->color;
   153 			return entry->color;
   154 		entry = entry->next;
   154 		entry = entry->next;
   155 	}
   155 	}
   156 	return 0;		/* garbage in - garbage out */
   156 	return 0;		/* garbage in - garbage out */
   157 }
   157 }
   158 
   158 
   159 static void free_colorhash(struct color_hash *hash)
   159 static void free_colorhash(struct color_hash *hash)
   160 {
   160 {
   161 	if(hash && hash->table) {
   161 	if(hash) {
   162 		free(hash->table);
   162 		if(hash->table)
   163 		free(hash->entries);
   163 			SDL_free(hash->table);
   164 		free(hash);
   164 		if(hash->entries)
       
   165 			SDL_free(hash->entries);
       
   166 		SDL_free(hash);
   165 	}
   167 	}
   166 }
   168 }
   167 
   169 
   168 /*
   170 /*
   169  * convert colour spec to RGB (in 0xrrggbb format).
   171  * convert colour spec to RGB (in 0xrrggbb format).
   869 			buf[0] = buf[1] = spec[1];
   871 			buf[0] = buf[1] = spec[1];
   870 			buf[2] = buf[3] = spec[2];
   872 			buf[2] = buf[3] = spec[2];
   871 			buf[4] = buf[5] = spec[3];
   873 			buf[4] = buf[5] = spec[3];
   872 			break;
   874 			break;
   873 		case 7:
   875 		case 7:
   874 			memcpy(buf, spec + 1, 6);
   876 			SDL_memcpy(buf, spec + 1, 6);
   875 			break;
   877 			break;
   876 		case 13:
   878 		case 13:
   877 			buf[0] = spec[1];
   879 			buf[0] = spec[1];
   878 			buf[1] = spec[2];
   880 			buf[1] = spec[2];
   879 			buf[2] = spec[5];
   881 			buf[2] = spec[5];
   926 		} while(c != '"');
   928 		} while(c != '"');
   927 		if(len) {
   929 		if(len) {
   928 			len += 4;	/* "\",\n\0" */
   930 			len += 4;	/* "\",\n\0" */
   929 			if(len > buflen){
   931 			if(len > buflen){
   930 				buflen = len;
   932 				buflen = len;
   931 				linebufnew = realloc(linebuf, buflen);
   933 				linebufnew = (char *)SDL_realloc(linebuf, buflen);
   932 				if(!linebufnew) {
   934 				if(!linebufnew) {
   933 					free(linebuf);
   935 					SDL_free(linebuf);
   934 					error = "Out of memory";
   936 					error = "Out of memory";
   935 					return NULL;
   937 					return NULL;
   936 				}
   938 				}
   937 				linebuf = linebufnew;
   939 				linebuf = linebufnew;
   938 			}
   940 			}
   946 			do {
   948 			do {
   947 				if(n >= buflen - 1) {
   949 				if(n >= buflen - 1) {
   948 					if(buflen == 0)
   950 					if(buflen == 0)
   949 						buflen = 16;
   951 						buflen = 16;
   950 					buflen *= 2;
   952 					buflen *= 2;
   951 					linebufnew = realloc(linebuf, buflen);
   953 					linebufnew = (char *)SDL_realloc(linebuf, buflen);
   952 					if(!linebufnew) {
   954 					if(!linebufnew) {
   953 						free(linebuf);
   955 						SDL_free(linebuf);
   954 						error = "Out of memory";
   956 						error = "Out of memory";
   955 						return NULL;
   957 						return NULL;
   956 					}
   958 					}
   957 					linebuf = linebufnew;
   959 					linebuf = linebufnew;
   958 				}
   960 				}
   968 	}
   970 	}
   969 }
   971 }
   970 
   972 
   971 #define SKIPSPACE(p)				\
   973 #define SKIPSPACE(p)				\
   972 do {						\
   974 do {						\
   973 	while(isspace((unsigned char)*(p)))	\
   975 	while(SDL_isspace((unsigned char)*(p)))	\
   974 	      ++(p);				\
   976 	      ++(p);				\
   975 } while(0)
   977 } while(0)
   976 
   978 
   977 #define SKIPNONSPACE(p)					\
   979 #define SKIPNONSPACE(p)					\
   978 do {							\
   980 do {							\
   979 	while(!isspace((unsigned char)*(p)) && *p)	\
   981 	while(!SDL_isspace((unsigned char)*(p)) && *p)	\
   980 	      ++(p);					\
   982 	      ++(p);					\
   981 } while(0)
   983 } while(0)
   982 
   984 
   983 /* read XPM from either array or RWops */
   985 /* read XPM from either array or RWops */
   984 static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src)
   986 static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src)
   985 {
   987 {
   986 	int start = 0;
   988 	Sint64 start = 0;
   987 	SDL_Surface *image = NULL;
   989 	SDL_Surface *image = NULL;
   988 	int index;
   990 	int index;
   989 	int x, y;
   991 	int x, y;
   990 	int w, h, ncolors, cpp;
   992 	int w, h, ncolors, cpp;
   991 	int indexed;
   993 	int indexed;
  1017 	 *
  1019 	 *
  1018 	 * where the hotspot coords are intended for mouse cursors.
  1020 	 * where the hotspot coords are intended for mouse cursors.
  1019 	 * Right now we don't use the hotspots but it should be handled
  1021 	 * Right now we don't use the hotspots but it should be handled
  1020 	 * one day.
  1022 	 * one day.
  1021 	 */
  1023 	 */
  1022 	if(sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4
  1024 	if(SDL_sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4
  1023 	   || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) {
  1025 	   || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) {
  1024 		error = "Invalid format description";
  1026 		error = "Invalid format description";
  1025 		goto done;
  1027 		goto done;
  1026 	}
  1028 	}
  1027 
  1029 
  1028 	keystrings = malloc(ncolors * cpp);
  1030 	keystrings = (char *)SDL_malloc(ncolors * cpp);
  1029 	if(!keystrings) {
  1031 	if(!keystrings) {
  1030 		error = "Out of memory";
  1032 		error = "Out of memory";
  1031 		goto done;
  1033 		goto done;
  1032 	}
  1034 	}
  1033 	nextkey = keystrings;
  1035 	nextkey = keystrings;
  1083 				continue;      /* skip symbolic colour names */
  1085 				continue;      /* skip symbolic colour names */
  1084 
  1086 
  1085 			if(!color_to_rgb(colname, p - colname, &rgb))
  1087 			if(!color_to_rgb(colname, p - colname, &rgb))
  1086 				continue;
  1088 				continue;
  1087 
  1089 
  1088 			memcpy(nextkey, line, cpp);
  1090 			SDL_memcpy(nextkey, line, cpp);
  1089 			if(indexed) {
  1091 			if(indexed) {
  1090 				SDL_Color *c = im_colors + index;
  1092 				SDL_Color *c = im_colors + index;
  1091 				c->r = (Uint8)(rgb >> 16);
  1093 				c->r = (Uint8)(rgb >> 16);
  1092 				c->g = (Uint8)(rgb >> 8);
  1094 				c->g = (Uint8)(rgb >> 8);
  1093 				c->b = (Uint8)(rgb);
  1095 				c->b = (Uint8)(rgb);
  1102 		}
  1104 		}
  1103 	}
  1105 	}
  1104 
  1106 
  1105 	/* Read the pixels */
  1107 	/* Read the pixels */
  1106 	pixels_len = w * cpp;
  1108 	pixels_len = w * cpp;
  1107 	dst = image->pixels;
  1109 	dst = (Uint8 *)image->pixels;
  1108 	for(y = 0; y < h; y++) {
  1110 	for(y = 0; y < h; y++) {
  1109 		line = get_next_line(xpmlines, src, pixels_len);
  1111 		line = get_next_line(xpmlines, src, pixels_len);
  1110 		if(indexed) {
  1112 		if(indexed) {
  1111 			/* optimization for some common cases */
  1113 			/* optimization for some common cases */
  1112 			if(cpp == 1)
  1114 			if(cpp == 1)
  1135 			SDL_FreeSurface(image);
  1137 			SDL_FreeSurface(image);
  1136 			image = NULL;
  1138 			image = NULL;
  1137 		}
  1139 		}
  1138 		IMG_SetError(error);
  1140 		IMG_SetError(error);
  1139 	}
  1141 	}
  1140 	free(keystrings);
  1142 	if (keystrings)
       
  1143 		SDL_free(keystrings);
  1141 	free_colorhash(colors);
  1144 	free_colorhash(colors);
  1142 	free(linebuf);
  1145 	if (linebuf)
       
  1146 		SDL_free(linebuf);
  1143 	return(image);
  1147 	return(image);
  1144 }
  1148 }
  1145 
  1149 
  1146 /* Load a XPM type image from an RWops datasource */
  1150 /* Load a XPM type image from an RWops datasource */
  1147 SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src)
  1151 SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src)