1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
7 // https://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 Warn("cannot load image file '%s': LoadImage() failed", filename);
53 img_info->source_filename = getStringCopy(filename);
55 img_info->original_width = img_info->bitmaps[IMG_BITMAP_STANDARD]->width;
56 img_info->original_height = img_info->bitmaps[IMG_BITMAP_STANDARD]->height;
58 img_info->contains_small_images = FALSE;
59 img_info->contains_textures = FALSE;
60 img_info->scaled_up = FALSE;
62 img_info->conf_tile_size = 0; // will be set later
63 img_info->game_tile_size = 0; // will be set later
65 img_info->leveldir = NULL; // will be set later
70 static void FreeImage(void *ptr)
72 ImageInfo *image = (ImageInfo *)ptr;
78 for (i = 0; i < NUM_IMG_BITMAPS; i++)
79 if (image->bitmaps[i])
80 FreeBitmap(image->bitmaps[i]);
82 if (image->source_filename)
83 free(image->source_filename);
88 int getImageListSize(void)
90 return (image_info->num_file_list_entries +
91 image_info->num_dynamic_file_list_entries);
94 struct FileInfo *getImageListEntryFromImageID(int pos)
96 int num_list_entries = image_info->num_file_list_entries;
97 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
99 return (pos < num_list_entries ? &image_info->file_list[list_pos] :
100 &image_info->dynamic_file_list[list_pos]);
103 static ImageInfo *getImageInfoEntryFromImageID(int pos)
105 int num_list_entries = image_info->num_file_list_entries;
106 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
107 ImageInfo **img_info =
108 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
109 image_info->dynamic_artwork_list);
111 return img_info[list_pos];
114 Bitmap **getBitmapsFromImageID(int pos)
116 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
118 return (img_info != NULL ? img_info->bitmaps : NULL);
121 int getOriginalImageWidthFromImageID(int pos)
123 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
125 return (img_info != NULL ? img_info->original_width : 0);
128 int getOriginalImageHeightFromImageID(int pos)
130 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
132 return (img_info != NULL ? img_info->original_height : 0);
135 char *getTokenFromImageID(int graphic)
137 struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
139 return (file_list != NULL ? file_list->token : NULL);
142 char *getFilenameFromImageID(int graphic)
144 struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
146 return (file_list != NULL ? file_list->filename : NULL);
149 int getImageIDFromToken(char *token)
151 struct FileInfo *file_list = image_info->file_list;
152 int num_list_entries = image_info->num_file_list_entries;
155 for (i = 0; i < num_list_entries; i++)
156 if (strEqual(file_list[i].token, token))
162 char *getImageConfigFilename(void)
164 return getCustomArtworkConfigFilename(image_info->type);
167 int getImageListPropertyMappingSize(void)
169 return image_info->num_property_mapping_entries;
172 struct PropertyMapping *getImageListPropertyMapping(void)
174 return image_info->property_mapping;
177 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
178 struct ConfigTypeInfo *config_suffix_list,
179 char **base_prefixes, char **ext1_suffixes,
180 char **ext2_suffixes, char **ext3_suffixes,
181 char **ignore_tokens)
185 image_info = checked_calloc(sizeof(struct ArtworkListInfo));
186 image_info->type = ARTWORK_TYPE_GRAPHICS;
188 // ---------- initialize file list and suffix lists ----------
190 image_info->num_file_list_entries = num_file_list_entries;
191 image_info->num_dynamic_file_list_entries = 0;
193 image_info->file_list =
194 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
195 num_file_list_entries);
196 image_info->dynamic_file_list = NULL;
198 image_info->num_suffix_list_entries = 0;
199 for (i = 0; config_suffix_list[i].token != NULL; i++)
200 image_info->num_suffix_list_entries++;
202 image_info->suffix_list = config_suffix_list;
204 // ---------- initialize base prefix and suffixes lists ----------
206 image_info->num_base_prefixes = 0;
207 for (i = 0; base_prefixes[i] != NULL; i++)
208 image_info->num_base_prefixes++;
210 image_info->num_ext1_suffixes = 0;
211 for (i = 0; ext1_suffixes[i] != NULL; i++)
212 image_info->num_ext1_suffixes++;
214 image_info->num_ext2_suffixes = 0;
215 for (i = 0; ext2_suffixes[i] != NULL; i++)
216 image_info->num_ext2_suffixes++;
218 image_info->num_ext3_suffixes = 0;
219 for (i = 0; ext3_suffixes[i] != NULL; i++)
220 image_info->num_ext3_suffixes++;
222 image_info->num_ignore_tokens = 0;
223 for (i = 0; ignore_tokens[i] != NULL; i++)
224 image_info->num_ignore_tokens++;
226 image_info->base_prefixes = base_prefixes;
227 image_info->ext1_suffixes = ext1_suffixes;
228 image_info->ext2_suffixes = ext2_suffixes;
229 image_info->ext3_suffixes = ext3_suffixes;
230 image_info->ignore_tokens = ignore_tokens;
232 image_info->num_property_mapping_entries = 0;
234 image_info->property_mapping = NULL;
236 // ---------- initialize artwork reference and content lists ----------
238 image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *);
240 image_info->artwork_list =
241 checked_calloc(num_file_list_entries * sizeof(ImageInfo *));
242 image_info->dynamic_artwork_list = NULL;
244 image_info->content_list = NULL;
246 // ---------- initialize artwork loading/freeing functions ----------
248 image_info->load_artwork = Load_Image;
249 image_info->free_artwork = FreeImage;
252 void ReloadCustomImages(void)
254 print_timestamp_init("ReloadCustomImages");
256 LoadArtworkConfig(image_info);
257 print_timestamp_time("LoadArtworkConfig");
259 ReloadCustomArtworkList(image_info);
260 print_timestamp_time("ReloadCustomArtworkList");
262 print_timestamp_done("ReloadCustomImages");
265 static boolean CheckIfImageContainsSmallImages(ImageInfo *img_info,
268 if (!img_info->contains_small_images)
271 // at this point, small images already exist for this image;
272 // now do some checks that may require re-creating small (or in-game) images
276 // check if the configured tile size for an already loaded image has changed
277 // from one level set to another; this should usually not happen, but if a
278 // custom artwork set redefines classic (or default) graphics with wrong tile
279 // size (by mistake or by intention), it will be corrected to its original
280 // tile size here by forcing complete re-creation of all small images again
282 if (!strEqual(img_info->leveldir, leveldir_current->identifier) &&
283 img_info->conf_tile_size != tile_size)
285 int bitmap_nr = GET_BITMAP_ID_FROM_TILESIZE(img_info->conf_tile_size);
288 // free all calculated, resized bitmaps, but keep last configured size
289 for (i = 0; i < NUM_IMG_BITMAPS; i++)
294 if (img_info->bitmaps[i])
296 FreeBitmap(img_info->bitmaps[i]);
298 img_info->bitmaps[i] = NULL;
302 // re-create small bitmaps from last configured size as new default size
303 if (bitmap_nr != IMG_BITMAP_STANDARD)
305 img_info->bitmaps[IMG_BITMAP_STANDARD] = img_info->bitmaps[bitmap_nr];
306 img_info->bitmaps[bitmap_nr] = NULL;
309 img_info->contains_small_images = FALSE;
314 // special case 1 (continued):
316 // if different tile sizes are used in same image file (usually by mistake,
317 // like forgetting option ".tile_size" for one or more graphic definitions),
318 // make sure to use only the first tile size that is processed for this image
319 // (and ignore all subsequent, potentially different tile size definitions
320 // for this image within the current level set by disabling the above check)
322 setString(&img_info->leveldir, leveldir_current->identifier);
326 // graphic config setting "game.tile_size" has changed since last level set;
327 // this may require resizing image to new size required for in-game graphics
329 if (img_info->game_tile_size != gfx.game_tile_size)
331 ReCreateGameTileSizeBitmap(img_info->bitmaps);
333 img_info->game_tile_size = gfx.game_tile_size;
339 void CreateImageWithSmallImages(int pos, int zoom_factor, int tile_size)
341 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
343 if (img_info == NULL)
346 if (CheckIfImageContainsSmallImages(img_info, tile_size))
349 CreateBitmapWithSmallBitmaps(img_info->bitmaps, zoom_factor, tile_size);
351 img_info->contains_small_images = TRUE;
352 img_info->scaled_up = TRUE; // scaling was also done here
354 img_info->conf_tile_size = tile_size;
355 img_info->game_tile_size = gfx.game_tile_size;
357 setString(&img_info->leveldir, leveldir_current->identifier);
360 void CreateImageTextures(int pos)
362 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
364 if (img_info == NULL || img_info->contains_textures)
367 CreateBitmapTextures(img_info->bitmaps);
369 img_info->contains_textures = TRUE;
372 static void FreeImageTextures(int pos)
374 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
376 if (img_info == NULL || !img_info->contains_textures)
379 FreeBitmapTextures(img_info->bitmaps);
381 img_info->contains_textures = FALSE;
384 void FreeAllImageTextures(void)
386 int num_images = getImageListSize();
389 for (i = 0; i < num_images; i++)
390 FreeImageTextures(i);
393 void ScaleImage(int pos, int zoom_factor)
395 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
397 if (img_info == NULL || img_info->scaled_up)
400 if (zoom_factor != 1)
401 ScaleBitmap(img_info->bitmaps, zoom_factor);
403 img_info->scaled_up = TRUE;
406 void FreeAllImages(void)
408 FreeCustomArtworkLists(image_info);