fixed bug when changing between graphic sets with different tile size
[rocksndiamonds.git] / src / libgame / image.c
1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
5 //                  Holger Schemel
6 //                  info@artsoft.org
7 //                  http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
9 // image.c
10 // ============================================================================
11
12 #include "image.h"
13 #include "misc.h"
14 #include "setup.h"
15
16
17 struct ImageInfo
18 {
19   char *source_filename;
20   int num_references;
21
22   Bitmap *bitmaps[NUM_IMG_BITMAP_POINTERS];
23
24   int original_width;                   /* original image file width */
25   int original_height;                  /* original image file height */
26
27   boolean contains_small_images;        /* set after adding small images */
28   boolean scaled_up;                    /* set after scaling up */
29
30   int game_tile_size;                   /* size of in-game sized bitmap */
31 };
32 typedef struct ImageInfo ImageInfo;
33
34 static struct ArtworkListInfo *image_info = NULL;
35
36 static void *Load_Image(char *filename)
37 {
38   ImageInfo *img_info = checked_calloc(sizeof(ImageInfo));
39
40   if ((img_info->bitmaps[IMG_BITMAP_STANDARD] = LoadImage(filename)) == NULL)
41   {
42     Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s",
43           filename, GetError());
44
45     free(img_info);
46
47     return NULL;
48   }
49
50   img_info->source_filename = getStringCopy(filename);
51
52   img_info->original_width  = img_info->bitmaps[IMG_BITMAP_STANDARD]->width;
53   img_info->original_height = img_info->bitmaps[IMG_BITMAP_STANDARD]->height;
54
55   img_info->contains_small_images = FALSE;
56   img_info->scaled_up = FALSE;
57
58   img_info->game_tile_size = 0;         // will be set later
59
60   return img_info;
61 }
62
63 static void FreeImage(void *ptr)
64 {
65   ImageInfo *image = (ImageInfo *)ptr;
66   int i;
67
68   if (image == NULL)
69     return;
70
71   for (i = 0; i < NUM_IMG_BITMAPS; i++)
72     if (image->bitmaps[i])
73       FreeBitmap(image->bitmaps[i]);
74
75   if (image->source_filename)
76     free(image->source_filename);
77
78   free(image);
79 }
80
81 int getImageListSize()
82 {
83   return (image_info->num_file_list_entries +
84           image_info->num_dynamic_file_list_entries);
85 }
86
87 struct FileInfo *getImageListEntryFromImageID(int pos)
88 {
89   int num_list_entries = image_info->num_file_list_entries;
90   int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
91
92   return (pos < num_list_entries ? &image_info->file_list[list_pos] :
93           &image_info->dynamic_file_list[list_pos]);
94 }
95
96 static ImageInfo *getImageInfoEntryFromImageID(int pos)
97 {
98   int num_list_entries = image_info->num_file_list_entries;
99   int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
100   ImageInfo **img_info =
101     (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
102                    image_info->dynamic_artwork_list);
103
104   return img_info[list_pos];
105 }
106
107 Bitmap **getBitmapsFromImageID(int pos)
108 {
109   ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
110
111   return (img_info != NULL ? img_info->bitmaps : NULL);
112 }
113
114 int getOriginalImageWidthFromImageID(int pos)
115 {
116   ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
117
118   return (img_info != NULL ? img_info->original_width : 0);
119 }
120
121 int getOriginalImageHeightFromImageID(int pos)
122 {
123   ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
124
125   return (img_info != NULL ? img_info->original_height : 0);
126 }
127
128 char *getTokenFromImageID(int graphic)
129 {
130   struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
131
132   return (file_list != NULL ? file_list->token : NULL);
133 }
134
135 int getImageIDFromToken(char *token)
136 {
137   struct FileInfo *file_list = image_info->file_list;
138   int num_list_entries = image_info->num_file_list_entries;
139   int i;
140
141   for (i = 0; i < num_list_entries; i++)
142     if (strEqual(file_list[i].token, token))
143       return i;
144
145   return -1;
146 }
147
148 char *getImageConfigFilename()
149 {
150   return getCustomArtworkConfigFilename(image_info->type);
151 }
152
153 int getImageListPropertyMappingSize()
154 {
155   return image_info->num_property_mapping_entries;
156 }
157
158 struct PropertyMapping *getImageListPropertyMapping()
159 {
160   return image_info->property_mapping;
161 }
162
163 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
164                    struct ConfigTypeInfo *config_suffix_list,
165                    char **base_prefixes, char **ext1_suffixes,
166                    char **ext2_suffixes, char **ext3_suffixes,
167                    char **ignore_tokens)
168 {
169   int i;
170
171   image_info = checked_calloc(sizeof(struct ArtworkListInfo));
172   image_info->type = ARTWORK_TYPE_GRAPHICS;
173
174   /* ---------- initialize file list and suffix lists ---------- */
175
176   image_info->num_file_list_entries = num_file_list_entries;
177   image_info->num_dynamic_file_list_entries = 0;
178
179   image_info->file_list =
180     getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
181                               num_file_list_entries);
182   image_info->dynamic_file_list = NULL;
183
184   image_info->num_suffix_list_entries = 0;
185   for (i = 0; config_suffix_list[i].token != NULL; i++)
186     image_info->num_suffix_list_entries++;
187
188   image_info->suffix_list = config_suffix_list;
189
190   /* ---------- initialize base prefix and suffixes lists ---------- */
191
192   image_info->num_base_prefixes = 0;
193   for (i = 0; base_prefixes[i] != NULL; i++)
194     image_info->num_base_prefixes++;
195
196   image_info->num_ext1_suffixes = 0;
197   for (i = 0; ext1_suffixes[i] != NULL; i++)
198     image_info->num_ext1_suffixes++;
199
200   image_info->num_ext2_suffixes = 0;
201   for (i = 0; ext2_suffixes[i] != NULL; i++)
202     image_info->num_ext2_suffixes++;
203
204   image_info->num_ext3_suffixes = 0;
205   for (i = 0; ext3_suffixes[i] != NULL; i++)
206     image_info->num_ext3_suffixes++;
207
208   image_info->num_ignore_tokens = 0;
209   for (i = 0; ignore_tokens[i] != NULL; i++)
210     image_info->num_ignore_tokens++;
211
212   image_info->base_prefixes = base_prefixes;
213   image_info->ext1_suffixes = ext1_suffixes;
214   image_info->ext2_suffixes = ext2_suffixes;
215   image_info->ext3_suffixes = ext3_suffixes;
216   image_info->ignore_tokens = ignore_tokens;
217
218   image_info->num_property_mapping_entries = 0;
219
220   image_info->property_mapping = NULL;
221
222   /* ---------- initialize artwork reference and content lists ---------- */
223
224   image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *);
225
226   image_info->artwork_list =
227     checked_calloc(num_file_list_entries * sizeof(ImageInfo *));
228   image_info->dynamic_artwork_list = NULL;
229
230   image_info->content_list = NULL;
231
232   /* ---------- initialize artwork loading/freeing functions ---------- */
233
234   image_info->load_artwork = Load_Image;
235   image_info->free_artwork = FreeImage;
236 }
237
238 void ReloadCustomImages()
239 {
240   print_timestamp_init("ReloadCustomImages");
241
242   LoadArtworkConfig(image_info);
243   print_timestamp_time("LoadArtworkConfig");
244
245   ReloadCustomArtworkList(image_info);
246   print_timestamp_time("ReloadCustomArtworkList");
247
248   print_timestamp_done("ReloadCustomImages");
249 }
250
251 void CreateImageWithSmallImages(int pos, int zoom_factor, int tile_size)
252 {
253   ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
254
255   if (img_info == NULL)
256     return;
257
258   if (img_info->contains_small_images)
259   {
260     if (img_info->game_tile_size != gfx.game_tile_size)
261       ReCreateGameTileSizeBitmap(img_info->bitmaps);
262
263     img_info->game_tile_size = gfx.game_tile_size;
264
265     return;
266   }
267
268   CreateBitmapWithSmallBitmaps(img_info->bitmaps, zoom_factor, tile_size);
269
270   img_info->contains_small_images = TRUE;
271   img_info->scaled_up = TRUE;                   // scaling was also done here
272
273   img_info->game_tile_size = gfx.game_tile_size;
274 }
275
276 void ScaleImage(int pos, int zoom_factor)
277 {
278   ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
279
280   if (img_info == NULL || img_info->scaled_up)
281     return;
282
283   if (zoom_factor != 1)
284     ScaleBitmap(img_info->bitmaps, zoom_factor);
285
286   img_info->scaled_up = TRUE;
287 }
288
289 void FreeAllImages()
290 {
291   FreeCustomArtworkLists(image_info);
292 }