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 scaled_up; /* set after scaling up */
30 int conf_tile_size; /* tile size as defined in config */
31 int game_tile_size; /* tile size as resized for game */
33 char *leveldir; /* level set when image was loaded */
35 typedef struct ImageInfo ImageInfo;
37 static struct ArtworkListInfo *image_info = NULL;
39 static void *Load_Image(char *filename)
41 ImageInfo *img_info = checked_calloc(sizeof(ImageInfo));
43 if ((img_info->bitmaps[IMG_BITMAP_STANDARD] = LoadImage(filename)) == NULL)
45 Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s",
46 filename, GetError());
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->scaled_up = FALSE;
61 img_info->conf_tile_size = 0; // will be set later
62 img_info->game_tile_size = 0; // will be set later
64 img_info->leveldir = NULL; // will be set later
69 static void FreeImage(void *ptr)
71 ImageInfo *image = (ImageInfo *)ptr;
77 for (i = 0; i < NUM_IMG_BITMAPS; i++)
78 if (image->bitmaps[i])
79 FreeBitmap(image->bitmaps[i]);
81 if (image->source_filename)
82 free(image->source_filename);
87 int getImageListSize()
89 return (image_info->num_file_list_entries +
90 image_info->num_dynamic_file_list_entries);
93 struct FileInfo *getImageListEntryFromImageID(int pos)
95 int num_list_entries = image_info->num_file_list_entries;
96 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
98 return (pos < num_list_entries ? &image_info->file_list[list_pos] :
99 &image_info->dynamic_file_list[list_pos]);
102 static ImageInfo *getImageInfoEntryFromImageID(int pos)
104 int num_list_entries = image_info->num_file_list_entries;
105 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
106 ImageInfo **img_info =
107 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
108 image_info->dynamic_artwork_list);
110 return img_info[list_pos];
113 Bitmap **getBitmapsFromImageID(int pos)
115 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
117 return (img_info != NULL ? img_info->bitmaps : NULL);
120 int getOriginalImageWidthFromImageID(int pos)
122 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
124 return (img_info != NULL ? img_info->original_width : 0);
127 int getOriginalImageHeightFromImageID(int pos)
129 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
131 return (img_info != NULL ? img_info->original_height : 0);
134 char *getTokenFromImageID(int graphic)
136 struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
138 return (file_list != NULL ? file_list->token : NULL);
141 int getImageIDFromToken(char *token)
143 struct FileInfo *file_list = image_info->file_list;
144 int num_list_entries = image_info->num_file_list_entries;
147 for (i = 0; i < num_list_entries; i++)
148 if (strEqual(file_list[i].token, token))
154 char *getImageConfigFilename()
156 return getCustomArtworkConfigFilename(image_info->type);
159 int getImageListPropertyMappingSize()
161 return image_info->num_property_mapping_entries;
164 struct PropertyMapping *getImageListPropertyMapping()
166 return image_info->property_mapping;
169 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
170 struct ConfigTypeInfo *config_suffix_list,
171 char **base_prefixes, char **ext1_suffixes,
172 char **ext2_suffixes, char **ext3_suffixes,
173 char **ignore_tokens)
177 image_info = checked_calloc(sizeof(struct ArtworkListInfo));
178 image_info->type = ARTWORK_TYPE_GRAPHICS;
180 /* ---------- initialize file list and suffix lists ---------- */
182 image_info->num_file_list_entries = num_file_list_entries;
183 image_info->num_dynamic_file_list_entries = 0;
185 image_info->file_list =
186 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
187 num_file_list_entries);
188 image_info->dynamic_file_list = NULL;
190 image_info->num_suffix_list_entries = 0;
191 for (i = 0; config_suffix_list[i].token != NULL; i++)
192 image_info->num_suffix_list_entries++;
194 image_info->suffix_list = config_suffix_list;
196 /* ---------- initialize base prefix and suffixes lists ---------- */
198 image_info->num_base_prefixes = 0;
199 for (i = 0; base_prefixes[i] != NULL; i++)
200 image_info->num_base_prefixes++;
202 image_info->num_ext1_suffixes = 0;
203 for (i = 0; ext1_suffixes[i] != NULL; i++)
204 image_info->num_ext1_suffixes++;
206 image_info->num_ext2_suffixes = 0;
207 for (i = 0; ext2_suffixes[i] != NULL; i++)
208 image_info->num_ext2_suffixes++;
210 image_info->num_ext3_suffixes = 0;
211 for (i = 0; ext3_suffixes[i] != NULL; i++)
212 image_info->num_ext3_suffixes++;
214 image_info->num_ignore_tokens = 0;
215 for (i = 0; ignore_tokens[i] != NULL; i++)
216 image_info->num_ignore_tokens++;
218 image_info->base_prefixes = base_prefixes;
219 image_info->ext1_suffixes = ext1_suffixes;
220 image_info->ext2_suffixes = ext2_suffixes;
221 image_info->ext3_suffixes = ext3_suffixes;
222 image_info->ignore_tokens = ignore_tokens;
224 image_info->num_property_mapping_entries = 0;
226 image_info->property_mapping = NULL;
228 /* ---------- initialize artwork reference and content lists ---------- */
230 image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *);
232 image_info->artwork_list =
233 checked_calloc(num_file_list_entries * sizeof(ImageInfo *));
234 image_info->dynamic_artwork_list = NULL;
236 image_info->content_list = NULL;
238 /* ---------- initialize artwork loading/freeing functions ---------- */
240 image_info->load_artwork = Load_Image;
241 image_info->free_artwork = FreeImage;
244 void ReloadCustomImages()
246 print_timestamp_init("ReloadCustomImages");
248 LoadArtworkConfig(image_info);
249 print_timestamp_time("LoadArtworkConfig");
251 ReloadCustomArtworkList(image_info);
252 print_timestamp_time("ReloadCustomArtworkList");
254 print_timestamp_done("ReloadCustomImages");
257 static boolean CheckIfImageContainsSmallImages(ImageInfo *img_info,
260 if (!img_info->contains_small_images)
263 // at this point, small images already exist for this image;
264 // now do some checks that may require re-creating small (or in-game) images
268 // check if the configured tile size for an already loaded image has changed
269 // from one level set to another; this should usually not happen, but if a
270 // custom artwork set redefines classic (or default) graphics with wrong tile
271 // size (by mistake or by intention), it will be corrected to its original
272 // tile size here by forcing complete re-creation of all small images again
274 if (!strEqual(img_info->leveldir, leveldir_current->identifier) &&
275 img_info->conf_tile_size != tile_size)
277 int bitmap_nr = GET_BITMAP_ID_FROM_TILESIZE(img_info->conf_tile_size);
280 // free all calculated, resized bitmaps, but keep last configured size
281 for (i = 0; i < NUM_IMG_BITMAPS; i++)
286 if (img_info->bitmaps[i])
288 FreeBitmap(img_info->bitmaps[i]);
290 img_info->bitmaps[i] = NULL;
294 // re-create small bitmaps from last configured size as new default size
295 if (bitmap_nr != IMG_BITMAP_STANDARD)
297 img_info->bitmaps[IMG_BITMAP_STANDARD] = img_info->bitmaps[bitmap_nr];
298 img_info->bitmaps[bitmap_nr] = NULL;
301 img_info->contains_small_images = FALSE;
306 // special case 1 (continued):
308 // if different tile sizes are used in same image file (usually by mistake,
309 // like forgetting option ".tile_size" for one or more graphic definitions),
310 // make sure to use only the first tile size that is processed for this image
311 // (and ignore all subsequent, potentially different tile size definitions
312 // for this image within the current level set by disabling the above check)
314 setString(&img_info->leveldir, leveldir_current->identifier);
318 // graphic config setting "game.tile_size" has changed since last level set;
319 // this may require resizing image to new size required for in-game graphics
321 if (img_info->game_tile_size != gfx.game_tile_size)
323 ReCreateGameTileSizeBitmap(img_info->bitmaps);
325 img_info->game_tile_size = gfx.game_tile_size;
331 void CreateImageWithSmallImages(int pos, int zoom_factor, int tile_size)
333 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
335 if (img_info == NULL)
338 if (CheckIfImageContainsSmallImages(img_info, tile_size))
341 CreateBitmapWithSmallBitmaps(img_info->bitmaps, zoom_factor, tile_size);
343 img_info->contains_small_images = TRUE;
344 img_info->scaled_up = TRUE; // scaling was also done here
346 img_info->conf_tile_size = tile_size;
347 img_info->game_tile_size = gfx.game_tile_size;
349 setString(&img_info->leveldir, leveldir_current->identifier);
352 void ScaleImage(int pos, int zoom_factor)
354 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
356 if (img_info == NULL || img_info->scaled_up)
359 if (zoom_factor != 1)
360 ScaleBitmap(img_info->bitmaps, zoom_factor);
362 img_info->scaled_up = TRUE;
367 FreeCustomArtworkLists(image_info);