1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
7 // http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
10 // ============================================================================
19 char *source_filename;
22 Bitmap *bitmaps[NUM_IMG_BITMAP_POINTERS];
24 int original_width; /* original image file width */
25 int original_height; /* original image file height */
27 boolean contains_small_images; /* set after adding small images */
28 boolean contains_textures; /* set after adding GPU textures */
29 boolean scaled_up; /* set after scaling up */
31 int conf_tile_size; /* tile size as defined in config */
32 int game_tile_size; /* tile size as resized for game */
34 char *leveldir; /* level set when image was loaded */
36 typedef struct ImageInfo ImageInfo;
38 static struct ArtworkListInfo *image_info = NULL;
40 static void *Load_Image(char *filename)
42 ImageInfo *img_info = checked_calloc(sizeof(ImageInfo));
44 if ((img_info->bitmaps[IMG_BITMAP_STANDARD] = LoadImage(filename)) == NULL)
46 Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s",
47 filename, GetError());
54 img_info->source_filename = getStringCopy(filename);
56 img_info->original_width = img_info->bitmaps[IMG_BITMAP_STANDARD]->width;
57 img_info->original_height = img_info->bitmaps[IMG_BITMAP_STANDARD]->height;
59 img_info->contains_small_images = FALSE;
60 img_info->contains_textures = FALSE;
61 img_info->scaled_up = FALSE;
63 img_info->conf_tile_size = 0; // will be set later
64 img_info->game_tile_size = 0; // will be set later
66 img_info->leveldir = NULL; // will be set later
71 static void FreeImage(void *ptr)
73 ImageInfo *image = (ImageInfo *)ptr;
79 for (i = 0; i < NUM_IMG_BITMAPS; i++)
80 if (image->bitmaps[i])
81 FreeBitmap(image->bitmaps[i]);
83 if (image->source_filename)
84 free(image->source_filename);
89 int getImageListSize()
91 return (image_info->num_file_list_entries +
92 image_info->num_dynamic_file_list_entries);
95 struct FileInfo *getImageListEntryFromImageID(int pos)
97 int num_list_entries = image_info->num_file_list_entries;
98 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
100 return (pos < num_list_entries ? &image_info->file_list[list_pos] :
101 &image_info->dynamic_file_list[list_pos]);
104 static ImageInfo *getImageInfoEntryFromImageID(int pos)
106 int num_list_entries = image_info->num_file_list_entries;
107 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
108 ImageInfo **img_info =
109 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
110 image_info->dynamic_artwork_list);
112 return img_info[list_pos];
115 Bitmap **getBitmapsFromImageID(int pos)
117 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
119 return (img_info != NULL ? img_info->bitmaps : NULL);
122 int getOriginalImageWidthFromImageID(int pos)
124 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
126 return (img_info != NULL ? img_info->original_width : 0);
129 int getOriginalImageHeightFromImageID(int pos)
131 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
133 return (img_info != NULL ? img_info->original_height : 0);
136 char *getTokenFromImageID(int graphic)
138 struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
140 return (file_list != NULL ? file_list->token : NULL);
143 int getImageIDFromToken(char *token)
145 struct FileInfo *file_list = image_info->file_list;
146 int num_list_entries = image_info->num_file_list_entries;
149 for (i = 0; i < num_list_entries; i++)
150 if (strEqual(file_list[i].token, token))
156 char *getImageConfigFilename()
158 return getCustomArtworkConfigFilename(image_info->type);
161 int getImageListPropertyMappingSize()
163 return image_info->num_property_mapping_entries;
166 struct PropertyMapping *getImageListPropertyMapping()
168 return image_info->property_mapping;
171 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
172 struct ConfigTypeInfo *config_suffix_list,
173 char **base_prefixes, char **ext1_suffixes,
174 char **ext2_suffixes, char **ext3_suffixes,
175 char **ignore_tokens)
179 image_info = checked_calloc(sizeof(struct ArtworkListInfo));
180 image_info->type = ARTWORK_TYPE_GRAPHICS;
182 /* ---------- initialize file list and suffix lists ---------- */
184 image_info->num_file_list_entries = num_file_list_entries;
185 image_info->num_dynamic_file_list_entries = 0;
187 image_info->file_list =
188 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
189 num_file_list_entries);
190 image_info->dynamic_file_list = NULL;
192 image_info->num_suffix_list_entries = 0;
193 for (i = 0; config_suffix_list[i].token != NULL; i++)
194 image_info->num_suffix_list_entries++;
196 image_info->suffix_list = config_suffix_list;
198 /* ---------- initialize base prefix and suffixes lists ---------- */
200 image_info->num_base_prefixes = 0;
201 for (i = 0; base_prefixes[i] != NULL; i++)
202 image_info->num_base_prefixes++;
204 image_info->num_ext1_suffixes = 0;
205 for (i = 0; ext1_suffixes[i] != NULL; i++)
206 image_info->num_ext1_suffixes++;
208 image_info->num_ext2_suffixes = 0;
209 for (i = 0; ext2_suffixes[i] != NULL; i++)
210 image_info->num_ext2_suffixes++;
212 image_info->num_ext3_suffixes = 0;
213 for (i = 0; ext3_suffixes[i] != NULL; i++)
214 image_info->num_ext3_suffixes++;
216 image_info->num_ignore_tokens = 0;
217 for (i = 0; ignore_tokens[i] != NULL; i++)
218 image_info->num_ignore_tokens++;
220 image_info->base_prefixes = base_prefixes;
221 image_info->ext1_suffixes = ext1_suffixes;
222 image_info->ext2_suffixes = ext2_suffixes;
223 image_info->ext3_suffixes = ext3_suffixes;
224 image_info->ignore_tokens = ignore_tokens;
226 image_info->num_property_mapping_entries = 0;
228 image_info->property_mapping = NULL;
230 /* ---------- initialize artwork reference and content lists ---------- */
232 image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *);
234 image_info->artwork_list =
235 checked_calloc(num_file_list_entries * sizeof(ImageInfo *));
236 image_info->dynamic_artwork_list = NULL;
238 image_info->content_list = NULL;
240 /* ---------- initialize artwork loading/freeing functions ---------- */
242 image_info->load_artwork = Load_Image;
243 image_info->free_artwork = FreeImage;
246 void ReloadCustomImages()
248 print_timestamp_init("ReloadCustomImages");
250 LoadArtworkConfig(image_info);
251 print_timestamp_time("LoadArtworkConfig");
253 ReloadCustomArtworkList(image_info);
254 print_timestamp_time("ReloadCustomArtworkList");
256 print_timestamp_done("ReloadCustomImages");
259 static boolean CheckIfImageContainsSmallImages(ImageInfo *img_info,
262 if (!img_info->contains_small_images)
265 // at this point, small images already exist for this image;
266 // now do some checks that may require re-creating small (or in-game) images
270 // check if the configured tile size for an already loaded image has changed
271 // from one level set to another; this should usually not happen, but if a
272 // custom artwork set redefines classic (or default) graphics with wrong tile
273 // size (by mistake or by intention), it will be corrected to its original
274 // tile size here by forcing complete re-creation of all small images again
276 if (!strEqual(img_info->leveldir, leveldir_current->identifier) &&
277 img_info->conf_tile_size != tile_size)
279 int bitmap_nr = GET_BITMAP_ID_FROM_TILESIZE(img_info->conf_tile_size);
282 // free all calculated, resized bitmaps, but keep last configured size
283 for (i = 0; i < NUM_IMG_BITMAPS; i++)
288 if (img_info->bitmaps[i])
290 FreeBitmap(img_info->bitmaps[i]);
292 img_info->bitmaps[i] = NULL;
296 // re-create small bitmaps from last configured size as new default size
297 if (bitmap_nr != IMG_BITMAP_STANDARD)
299 img_info->bitmaps[IMG_BITMAP_STANDARD] = img_info->bitmaps[bitmap_nr];
300 img_info->bitmaps[bitmap_nr] = NULL;
303 img_info->contains_small_images = FALSE;
308 // special case 1 (continued):
310 // if different tile sizes are used in same image file (usually by mistake,
311 // like forgetting option ".tile_size" for one or more graphic definitions),
312 // make sure to use only the first tile size that is processed for this image
313 // (and ignore all subsequent, potentially different tile size definitions
314 // for this image within the current level set by disabling the above check)
316 setString(&img_info->leveldir, leveldir_current->identifier);
320 // graphic config setting "game.tile_size" has changed since last level set;
321 // this may require resizing image to new size required for in-game graphics
323 if (img_info->game_tile_size != gfx.game_tile_size)
325 ReCreateGameTileSizeBitmap(img_info->bitmaps);
327 img_info->game_tile_size = gfx.game_tile_size;
333 void CreateImageWithSmallImages(int pos, int zoom_factor, int tile_size)
335 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
337 if (img_info == NULL)
340 if (CheckIfImageContainsSmallImages(img_info, tile_size))
343 CreateBitmapWithSmallBitmaps(img_info->bitmaps, zoom_factor, tile_size);
345 img_info->contains_small_images = TRUE;
346 img_info->scaled_up = TRUE; // scaling was also done here
348 img_info->conf_tile_size = tile_size;
349 img_info->game_tile_size = gfx.game_tile_size;
351 setString(&img_info->leveldir, leveldir_current->identifier);
354 void CreateImageTextures(int pos)
356 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
358 if (img_info == NULL || img_info->contains_textures)
361 CreateBitmapTextures(img_info->bitmaps);
363 img_info->contains_textures = TRUE;
366 void ScaleImage(int pos, int zoom_factor)
368 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
370 if (img_info == NULL || img_info->scaled_up)
373 if (zoom_factor != 1)
374 ScaleBitmap(img_info->bitmaps, zoom_factor);
376 img_info->scaled_up = TRUE;
381 FreeCustomArtworkLists(image_info);