1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
20 /* ========================================================================= */
21 /* PLATFORM SPECIFIC IMAGE FUNCTIONS */
22 /* ========================================================================= */
24 #if defined(TARGET_X11)
26 Image *newImage(unsigned int width, unsigned int height, unsigned int depth)
29 unsigned int bytes_per_pixel = (depth + 7) / 8;
32 image = checked_calloc(sizeof(Image));
33 image->data = checked_calloc(width * height * bytes_per_pixel);
35 image->height = height;
37 image->bytes_per_pixel = bytes_per_pixel;
38 image->bytes_per_row = width * bytes_per_pixel;
41 for (i = 0; i < MAX_COLORS; i++)
42 image->rgb.color_used[i] = FALSE;
44 image->type = (depth < 8 ? IMAGETYPE_BITMAP :
45 depth > 8 ? IMAGETYPE_TRUECOLOR : IMAGETYPE_RGB);
50 void freeImage(Image *image)
56 /* extra colors to try allocating in private color maps to minimize flashing */
57 #define NOFLASH_COLORS 256
59 /* architecture independent value <-> memory conversions;
60 note: the internal format is big endian */
62 #define memory_to_value(ptr, len) ( \
63 (len) == 1 ? (unsigned int)( *( (byte *)(ptr)) ) : \
64 (len) == 2 ? (unsigned int)(((unsigned int)(*( (byte *)(ptr)) ))<< 8) \
65 + ( *(((byte *)(ptr))+1) ) : \
66 (len) == 3 ? (unsigned int)(((unsigned int)(*( (byte *)(ptr)) ))<<16) \
67 + (((unsigned int)(*(((byte *)(ptr))+1)))<< 8) \
68 + ( *(((byte *)(ptr))+2) ) : \
69 (unsigned int)(((unsigned int)(*( (byte *)(ptr)) ))<<24) \
70 + (((unsigned int)(*(((byte *)(ptr))+1)))<<16) \
71 + (((unsigned int)(*(((byte *)(ptr))+2)))<< 8) \
72 + ( *(((byte *)(ptr))+3) ) )
75 #define value_to_memory(value, ptr, len) ( \
76 (len) == 1 ? (*( (byte *)(ptr) ) = ( value ) ) : \
77 (len) == 2 ? (*( (byte *)(ptr) ) = (((unsigned int)(value))>> 8), \
78 *(((byte *)(ptr))+1) = ( value ) ) : \
79 (len) == 3 ? (*( (byte *)(ptr) ) = (((unsigned int)(value))>>16), \
80 *(((byte *)(ptr))+1) = (((unsigned int)(value))>> 8), \
81 *(((byte *)(ptr))+2) = ( value ) ) : \
82 (*( (byte *)(ptr) ) = (((unsigned int)(value))>>24), \
83 *(((byte *)(ptr))+1) = (((unsigned int)(value))>>16), \
84 *(((byte *)(ptr))+2) = (((unsigned int)(value))>> 8), \
85 *(((byte *)(ptr))+3) = ( value ) ))
87 static Pixmap Image_to_Mask(Image *image, Display *display, Window window)
89 byte *src_ptr, *dst_ptr, *dst_ptr2;
90 unsigned int bytes_per_row;
96 bytes_per_row = (image->width + 7) / 8;
97 mask_data = checked_calloc(bytes_per_row * image->height);
99 src_ptr = image->data;
102 /* create bitmap data which can be used by 'XCreateBitmapFromData()'
103 * directly to create a pixmap of depth 1 for use as a clip mask for
104 * the corresponding image pixmap
107 for (y = 0; y < image->height; y++)
109 bitmask = 0x01; /* start with leftmost bit in the byte */
110 dst_ptr2 = dst_ptr; /* start with leftmost byte in the row */
112 for (x = 0; x < image->width; x++)
114 for (i = 0; i < image->bytes_per_pixel; i++)
115 if (*src_ptr++) /* source pixel solid? (pixel index != 0) */
116 *dst_ptr2 |= bitmask; /* then write a bit into the image mask */
118 if ((bitmask <<= 1) == 0) /* bit at rightmost byte position reached? */
120 bitmask = 0x01; /* start again with leftmost bit position */
121 dst_ptr2++; /* continue with next byte in image mask */
125 dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */
128 if ((mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data,
129 image->width, image->height))
131 Error(ERR_EXIT, "Image_to_Mask(): XCreateBitmapFromData() failed");
138 Pixmap Pixmap_to_Mask(Pixmap src_pixmap, int src_width, int src_height)
141 byte *src_ptr, *dst_ptr, *dst_ptr2;
144 unsigned int bytes_per_row;
145 unsigned int x, y, i;
150 /* copy source pixmap to temporary image */
151 if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
152 AllPlanes, ZPixmap)) == NULL)
153 Error(ERR_EXIT, "Pixmap_to_Mask(): XGetImage() failed");
155 bits_per_pixel = src_ximage->bits_per_pixel;
156 bytes_per_pixel = (bits_per_pixel + 7) / 8;
158 bytes_per_row = (src_width + 7) / 8;
159 mask_data = checked_calloc(bytes_per_row * src_height);
161 src_ptr = (byte *)src_ximage->data;
164 /* create bitmap data which can be used by 'XCreateBitmapFromData()'
165 * directly to create a pixmap of depth 1 for use as a clip mask for
166 * the corresponding image pixmap
169 for (y = 0; y < src_height; y++)
171 bitmask = 0x01; /* start with leftmost bit in the byte */
172 dst_ptr2 = dst_ptr; /* start with leftmost byte in the row */
174 for (x = 0; x < src_width; x++)
176 for (i = 0; i < bytes_per_pixel; i++)
177 if (*src_ptr++) /* source pixel solid? (pixel index != 0) */
178 *dst_ptr2 |= bitmask; /* then write a bit into the image mask */
180 if ((bitmask <<= 1) == 0) /* bit at rightmost byte position reached? */
182 bitmask = 0x01; /* start again with leftmost bit position */
183 dst_ptr2++; /* continue with next byte in image mask */
187 dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */
190 if ((mask_pixmap = XCreateBitmapFromData(display, window->drawable,
192 src_width, src_height)) == None)
193 Error(ERR_EXIT, "Pixmap_to_Mask(): XCreateBitmapFromData() failed");
200 static int bitsPerPixelAtDepth(Display *display, int screen, int depth)
202 XPixmapFormatValues *pixmap_format;
203 int i, num_pixmap_formats, bits_per_pixel = -1;
205 /* get Pixmap formats supported by the X server */
206 pixmap_format = XListPixmapFormats(display, &num_pixmap_formats);
208 /* find format that matches the given depth */
209 for (i = 0; i < num_pixmap_formats; i++)
210 if (pixmap_format[i].depth == depth)
211 bits_per_pixel = pixmap_format[i].bits_per_pixel;
213 XFree(pixmap_format);
215 if (bits_per_pixel == -1)
216 Error(ERR_EXIT, "cannot find pixmap format for depth %d", depth);
218 return bits_per_pixel;
221 XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
222 Window window, GC gc, int depth, Image *image)
224 static XColor xcolor_private[NOFLASH_COLORS];
225 static int colorcell_used[NOFLASH_COLORS];
226 static Colormap global_cmap = 0;
227 static Pixel *global_cmap_index;
228 static int num_cmap_entries, free_cmap_entries;
229 static boolean private_cmap = FALSE;
230 Pixel *redvalue, *greenvalue, *bluevalue;
231 unsigned int display_bytes_per_pixel, display_bits_per_pixel;
232 unsigned int a, c = 0, x, y;
235 XImageInfo *ximageinfo;
236 byte *src_ptr, *dst_ptr;
237 char *error = "Image_to_Pixmap(): %s";
239 if (image->type == IMAGETYPE_TRUECOLOR && depth == 8)
241 SetError(error, "cannot handle true-color images on 8-bit display");
247 if (visual == DefaultVisual(display, screen))
248 global_cmap = DefaultColormap(display, screen);
251 global_cmap = XCreateColormap(display, RootWindow(display, screen),
257 xcolor.flags = DoRed | DoGreen | DoBlue;
258 redvalue = greenvalue = bluevalue = NULL;
259 ximageinfo = checked_malloc(sizeof(XImageInfo));
260 ximageinfo->display = display;
261 ximageinfo->depth = depth;
263 switch (visual->class)
269 unsigned int redcolors, greencolors, bluecolors;
270 unsigned int redstep, greenstep, bluestep;
271 unsigned int redbottom, greenbottom, bluebottom;
272 unsigned int redtop, greentop, bluetop;
274 redvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
275 greenvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
276 bluevalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
278 ximageinfo->cmap = global_cmap;
280 retry_direct: /* tag we hit if a DirectColor allocation fails on
281 * default colormap */
283 /* calculate number of distinct colors in each band */
285 redcolors = greencolors = bluecolors = 1;
286 for (pixval = 1; pixval; pixval <<= 1)
288 if (pixval & visual->red_mask)
290 if (pixval & visual->green_mask)
292 if (pixval & visual->blue_mask)
296 /* consistency check */
297 if (redcolors > visual->map_entries ||
298 greencolors > visual->map_entries ||
299 bluecolors > visual->map_entries)
300 Error(ERR_WARN, "inconsistency in color information");
302 redstep = 256 / redcolors;
303 greenstep = 256 / greencolors;
304 bluestep = 256 / bluecolors;
305 redbottom = greenbottom = bluebottom = 0;
306 redtop = greentop = bluetop = 0;
308 for (a = 0; a < visual->map_entries; a++)
311 redtop = redbottom + redstep;
312 if (greenbottom < 256)
313 greentop = greenbottom + greenstep;
314 if (bluebottom < 256)
315 bluetop = bluebottom + bluestep;
317 xcolor.red = (redtop - 1) << 8;
318 xcolor.green = (greentop - 1) << 8;
319 xcolor.blue = (bluetop - 1) << 8;
320 if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
322 /* if an allocation fails for a DirectColor default visual then
323 we should create a private colormap and try again. */
325 if ((visual->class == DirectColor) &&
326 (visual == DefaultVisual(display, screen)))
328 global_cmap = XCopyColormapAndFree(display, global_cmap);
329 ximageinfo->cmap = global_cmap;
335 /* something completely unexpected happened */
337 fprintf(stderr, "Image_to_Pixmap: XAllocColor failed on a TrueColor/Directcolor visual\n");
347 /* fill in pixel values for each band at this intensity */
349 while ((redbottom < 256) && (redbottom < redtop))
350 redvalue[redbottom++] = xcolor.pixel & visual->red_mask;
351 while ((greenbottom < 256) && (greenbottom < greentop))
352 greenvalue[greenbottom++] = xcolor.pixel & visual->green_mask;
353 while ((bluebottom < 256) && (bluebottom < bluetop))
354 bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask;
362 ximageinfo->cmap = global_cmap;
364 for (a = 0; a < MAX_COLORS; a++)
371 if (!image->rgb.color_used[a])
374 xcolor.red = *(image->rgb.red + a);
375 xcolor.green = *(image->rgb.green + a);
376 xcolor.blue = *(image->rgb.blue + a);
378 /* look if this color already exists in our colormap */
379 if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
384 Error(ERR_INFO, "switching to private colormap");
386 /* we just filled up the default colormap -- get a private one
387 which contains all already allocated colors */
389 global_cmap = XCopyColormapAndFree(display, global_cmap);
390 ximageinfo->cmap = global_cmap;
393 /* allocate the rest of the color cells read/write */
395 (Pixel *)checked_malloc(sizeof(Pixel) * NOFLASH_COLORS);
396 for (i = 0; i < NOFLASH_COLORS; i++)
397 if (!XAllocColorCells(display, global_cmap, FALSE, NULL, 0,
398 global_cmap_index + i, 1))
400 num_cmap_entries = free_cmap_entries = i;
403 printf("We've got %d free colormap entries.\n", free_cmap_entries);
406 /* to minimize colormap flashing, copy default colors and try
407 to keep them as near as possible to the old values */
409 for (i = 0; i < num_cmap_entries; i++)
411 xcolor2.pixel = *(global_cmap_index + i);
412 XQueryColor(display, DefaultColormap(display, screen), &xcolor2);
413 XStoreColor(display, global_cmap, &xcolor2);
414 xcolor_private[xcolor2.pixel] = xcolor2;
415 colorcell_used[xcolor2.pixel] = FALSE;
418 /* now we have the default colormap private: all colors we
419 successfully allocated so far are read-only, which is okay,
420 because we don't want to change them anymore -- if we need
421 an existing color again, we get it by XAllocColor; all other
422 colors are read/write and we can set them by XStoreColor,
423 but we will try to overwrite those color cells with our new
424 color which are as close as possible to our new color */
427 /* look for an existing default color close the one we want */
434 for (i = num_cmap_entries - 1; i >= 0; i--)
436 xcolor2.pixel = *(global_cmap_index + i);
437 xcolor2 = xcolor_private[xcolor2.pixel];
439 if (colorcell_used[xcolor2.pixel])
442 if ((xcolor.red & mask) == (xcolor2.red & mask) &&
443 (xcolor.green & mask) == (xcolor2.green & mask) &&
444 (xcolor.blue & mask) == (xcolor2.blue & mask))
447 printf("replacing color cell %ld with a close color\n",
458 mask = (mask << 1) & 0xffff;
461 if (!color_found) /* no more free color cells */
463 SetError(error, "cannot allocate enough color cells");
467 xcolor.pixel = xcolor2.pixel;
468 xcolor_private[xcolor.pixel] = xcolor;
469 colorcell_used[xcolor.pixel] = TRUE;
470 XStoreColor(display, ximageinfo->cmap, &xcolor);
474 *(ximageinfo->index + a) = xcolor.pixel;
478 printf("still %d free colormap entries\n", free_cmap_entries);
481 ximageinfo->no = a; /* number of pixels allocated for this image */
485 Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed");
486 SetError(error, "display class not supported");
492 debug_print_timestamp(2, " ALLOCATING IMAGE COLORS: ");
495 /* create XImage from internal image structure and convert it to Pixmap */
497 display_bits_per_pixel = bitsPerPixelAtDepth(display, screen, depth);
498 display_bytes_per_pixel = (display_bits_per_pixel + 7) / 8;
500 ximage = XCreateImage(display, visual, depth, ZPixmap,
501 0, NULL, image->width, image->height,
502 8, image->width * display_bytes_per_pixel);
504 checked_malloc(image->width * image->height * display_bytes_per_pixel);
505 ximage->byte_order = MSBFirst;
507 src_ptr = image->data;
508 dst_ptr = (byte *)ximage->data;
510 switch (visual->class)
521 for (y = 0; y < image->height; y++) /* general case */
523 for (x = 0; x < image->width; x++)
527 redvalue[image->rgb.red[pixval] >> 8] |
528 greenvalue[image->rgb.green[pixval] >> 8] |
529 bluevalue[image->rgb.blue[pixval] >> 8];
530 value_to_memory(pixval, dst_ptr, display_bytes_per_pixel);
531 dst_ptr += display_bytes_per_pixel;
538 case IMAGETYPE_TRUECOLOR:
540 for (y = 0; y < image->height; y++) /* general case */
542 for (x = 0; x < image->width; x++)
544 pixval = memory_to_value(src_ptr, image->bytes_per_pixel);
546 redvalue[TRUECOLOR_RED(pixval)] |
547 greenvalue[TRUECOLOR_GREEN(pixval)] |
548 bluevalue[TRUECOLOR_BLUE(pixval)];
549 value_to_memory(pixval, dst_ptr, display_bytes_per_pixel);
550 src_ptr += image->bytes_per_pixel;
551 dst_ptr += display_bytes_per_pixel;
559 Error(ERR_INFO, "RGB or TrueColor image needed");
560 SetError(error, "image type not supported");
570 if (display_bytes_per_pixel == 1) /* special case */
572 for (y = 0; y < image->height; y++)
573 for (x = 0; x < image->width; x++)
574 *dst_ptr++ = ximageinfo->index[c + *src_ptr++];
576 else /* general case */
578 for (y = 0; y < image->height; y++)
580 for (x = 0; x < image->width; x++)
582 value_to_memory(ximageinfo->index[c + *src_ptr++],
583 dst_ptr, display_bytes_per_pixel);
584 dst_ptr += display_bytes_per_pixel;
593 Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed");
594 SetError(error, "display class not supported");
601 free((byte *)redvalue);
602 free((byte *)greenvalue);
603 free((byte *)bluevalue);
607 debug_print_timestamp(2, " CONVERTING IMAGE TO XIMAGE:");
610 ximageinfo->pixmap = XCreatePixmap(display, window,
611 ximage->width, ximage->height,
614 XPutImage(ximageinfo->display, ximageinfo->pixmap, gc,
615 ximage, 0, 0, 0, 0, ximage->width, ximage->height);
617 X11DestroyImage(ximage);
623 -----------------------------------------------------------------------------
626 Important note: The scaling code currently only supports scaling of the image
627 up or down by a power of 2 -- other scaling factors currently not supported!
628 Also not supported is scaling of pixmap masks (with depth 1); to scale them,
629 better use Pixmap_to_Mask() for now.
630 -----------------------------------------------------------------------------
633 void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap,
634 int src_width, int src_height,
635 int dst_width, int dst_height)
637 XImage *src_ximage, *dst_ximage;
638 byte *src_ptr, *dst_ptr;
642 int row_skip, col_skip;
644 boolean scale_down = (src_width > dst_width);
649 zoom_factor = MIN(src_width / dst_width, src_height / dst_height);
651 zoom_factor = src_width / dst_width;
654 /* adjust source image size to integer multiple of destination size */
655 src_width = dst_width * zoom_factor;
656 src_height = dst_height * zoom_factor;
661 zoom_factor = MIN(dst_width / src_width, dst_height / src_height);
663 zoom_factor = dst_width / src_width;
666 /* no adjustment needed when scaling up (some pixels may be left blank) */
669 /* copy source pixmap to temporary image */
670 if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
671 AllPlanes, ZPixmap)) == NULL)
672 Error(ERR_EXIT, "ZoomPixmap(): XGetImage() failed");
674 bits_per_pixel = src_ximage->bits_per_pixel;
675 bytes_per_pixel = (bits_per_pixel + 7) / 8;
677 if ((dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap,
678 0, NULL, dst_width, dst_height,
679 8, dst_width * bytes_per_pixel)) == NULL)
680 Error(ERR_EXIT, "ZoomPixmap(): XCreateImage() failed");
683 checked_malloc(dst_width * dst_height * bytes_per_pixel);
684 dst_ximage->byte_order = src_ximage->byte_order;
686 src_ptr = (byte *)src_ximage->data;
687 dst_ptr = (byte *)dst_ximage->data;
691 col_skip = (zoom_factor - 1) * bytes_per_pixel;
692 row_skip = col_skip * src_width;
694 /* scale image down by scaling factor 'zoom_factor' */
695 for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip)
696 for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip)
697 for (i = 0; i < bytes_per_pixel; i++)
698 *dst_ptr++ = *src_ptr++;
702 row_skip = src_width * bytes_per_pixel;
704 /* scale image up by scaling factor 'zoom_factor' */
705 for (y = 0; y < src_height; y++)
707 for (yy = 0; yy < zoom_factor; yy++)
712 for (x = 0; x < src_width; x++)
714 for (xx = 0; xx < zoom_factor; xx++)
715 for (i = 0; i < bytes_per_pixel; i++)
716 *dst_ptr++ = *(src_ptr + i);
718 src_ptr += bytes_per_pixel;
724 /* copy scaled image to destination pixmap */
725 XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0,
726 dst_width, dst_height);
728 /* free temporary images */
729 X11DestroyImage(src_ximage);
730 X11DestroyImage(dst_ximage);
733 void freeXImage(Image *image, XImageInfo *ximageinfo)
735 if (ximageinfo->index != NULL && ximageinfo->no > 0)
736 XFreeColors(ximageinfo->display, ximageinfo->cmap, ximageinfo->index,
738 /* this ^^^^^^^^^^^^^^ is wrong, because the used color cells
739 * are somewhere between 0 and MAX_COLORS; there are indeed 'ximageinfo->no'
740 * used color cells, but they are not at array position 0 - 'ximageinfo->no'
746 int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
747 Pixmap *pixmap, Pixmap *pixmap_mask)
750 XImageInfo *ximageinfo;
756 debug_print_timestamp(2, NULL); /* initialize timestamp function */
759 /* read the graphic file in PCX format to image structure */
760 if ((image = Read_PCX_to_Image(filename)) == NULL)
764 printf("%s:\n", filename);
765 debug_print_timestamp(2, " READING PCX FILE TO IMAGE: ");
768 screen = DefaultScreen(display);
769 visual = DefaultVisual(display, screen);
770 depth = DefaultDepth(display, screen);
772 /* convert image structure to X11 Pixmap */
773 if (!(ximageinfo = Image_to_Pixmap(display, screen, visual,
774 window, gc, depth, image)))
778 return PCX_OtherError;
781 /* if a private colormap has been created, install it */
782 if (ximageinfo->cmap != DefaultColormap(display, screen))
783 XSetWindowColormap(display, window, ximageinfo->cmap);
786 debug_print_timestamp(2, " CONVERTING IMAGE TO PIXMAP:");
789 /* create clip mask for the image */
790 ximageinfo->pixmap_mask = Image_to_Mask(image, display, window);
793 debug_print_timestamp(2, " CONVERTING IMAGE TO MASK: ");
796 *pixmap = ximageinfo->pixmap;
797 *pixmap_mask = ximageinfo->pixmap_mask;
799 /* free generic image and ximageinfo after native Pixmap has been created */
806 #endif /* TARGET_X11 */
809 /* ========================================================================= */
810 /* PLATFORM INDEPENDENT IMAGE FUNCTIONS */
811 /* ========================================================================= */
815 char *source_filename;
820 int original_width; /* original image file width */
821 int original_height; /* original image file height */
823 boolean contains_small_images; /* set after adding small images */
824 boolean scaled_up; /* set after scaling up */
826 typedef struct ImageInfo ImageInfo;
828 static struct ArtworkListInfo *image_info = NULL;
831 static void *Load_Image(char *filename)
833 static void *Load_PCX(char *filename)
839 printf("::: loading PCX file '%s'\n", filename);
842 img_info = checked_calloc(sizeof(ImageInfo));
844 if ((img_info->bitmap = LoadImage(filename)) == NULL)
846 Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s",
847 filename, GetError());
852 img_info->source_filename = getStringCopy(filename);
854 img_info->original_width = img_info->bitmap->width;
855 img_info->original_height = img_info->bitmap->height;
857 img_info->contains_small_images = FALSE;
858 img_info->scaled_up = FALSE;
863 static void FreeImage(void *ptr)
865 ImageInfo *image = (ImageInfo *)ptr;
871 FreeBitmap(image->bitmap);
873 if (image->source_filename)
874 free(image->source_filename);
879 int getImageListSize()
881 return (image_info->num_file_list_entries +
882 image_info->num_dynamic_file_list_entries);
885 struct FileInfo *getImageListEntryFromImageID(int pos)
887 int num_list_entries = image_info->num_file_list_entries;
888 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
890 return (pos < num_list_entries ? &image_info->file_list[list_pos] :
891 &image_info->dynamic_file_list[list_pos]);
894 static ImageInfo *getImageInfoEntryFromImageID(int pos)
896 int num_list_entries = image_info->num_file_list_entries;
897 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
898 ImageInfo **img_info =
899 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
900 image_info->dynamic_artwork_list);
902 return img_info[list_pos];
905 Bitmap *getBitmapFromImageID(int pos)
907 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
909 return (img_info != NULL ? img_info->bitmap : NULL);
912 int getOriginalImageWidthFromImageID(int pos)
914 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
916 return (img_info != NULL ? img_info->original_width : 0);
919 int getOriginalImageHeightFromImageID(int pos)
921 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
923 return (img_info != NULL ? img_info->original_height : 0);
926 char *getTokenFromImageID(int graphic)
928 struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
930 return (file_list != NULL ? file_list->token : NULL);
933 int getImageIDFromToken(char *token)
935 struct FileInfo *file_list = image_info->file_list;
936 int num_list_entries = image_info->num_file_list_entries;
939 for (i = 0; i < num_list_entries; i++)
940 if (strEqual(file_list[i].token, token))
946 char *getImageConfigFilename()
948 return getCustomArtworkConfigFilename(image_info->type);
951 int getImageListPropertyMappingSize()
953 return image_info->num_property_mapping_entries;
956 struct PropertyMapping *getImageListPropertyMapping()
958 return image_info->property_mapping;
961 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
962 struct ConfigTypeInfo *config_suffix_list,
963 char **base_prefixes, char **ext1_suffixes,
964 char **ext2_suffixes, char **ext3_suffixes,
965 char **ignore_tokens)
969 image_info = checked_calloc(sizeof(struct ArtworkListInfo));
970 image_info->type = ARTWORK_TYPE_GRAPHICS;
972 /* ---------- initialize file list and suffix lists ---------- */
974 image_info->num_file_list_entries = num_file_list_entries;
975 image_info->num_dynamic_file_list_entries = 0;
977 image_info->file_list =
978 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
979 num_file_list_entries);
980 image_info->dynamic_file_list = NULL;
982 image_info->num_suffix_list_entries = 0;
983 for (i = 0; config_suffix_list[i].token != NULL; i++)
984 image_info->num_suffix_list_entries++;
986 image_info->suffix_list = config_suffix_list;
988 /* ---------- initialize base prefix and suffixes lists ---------- */
990 image_info->num_base_prefixes = 0;
991 for (i = 0; base_prefixes[i] != NULL; i++)
992 image_info->num_base_prefixes++;
994 image_info->num_ext1_suffixes = 0;
995 for (i = 0; ext1_suffixes[i] != NULL; i++)
996 image_info->num_ext1_suffixes++;
998 image_info->num_ext2_suffixes = 0;
999 for (i = 0; ext2_suffixes[i] != NULL; i++)
1000 image_info->num_ext2_suffixes++;
1002 image_info->num_ext3_suffixes = 0;
1003 for (i = 0; ext3_suffixes[i] != NULL; i++)
1004 image_info->num_ext3_suffixes++;
1006 image_info->num_ignore_tokens = 0;
1007 for (i = 0; ignore_tokens[i] != NULL; i++)
1008 image_info->num_ignore_tokens++;
1010 image_info->base_prefixes = base_prefixes;
1011 image_info->ext1_suffixes = ext1_suffixes;
1012 image_info->ext2_suffixes = ext2_suffixes;
1013 image_info->ext3_suffixes = ext3_suffixes;
1014 image_info->ignore_tokens = ignore_tokens;
1016 image_info->num_property_mapping_entries = 0;
1018 image_info->property_mapping = NULL;
1020 /* ---------- initialize artwork reference and content lists ---------- */
1022 image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *);
1024 image_info->artwork_list =
1025 checked_calloc(num_file_list_entries * sizeof(ImageInfo *));
1026 image_info->dynamic_artwork_list = NULL;
1028 image_info->content_list = NULL;
1030 /* ---------- initialize artwork loading/freeing functions ---------- */
1033 image_info->load_artwork = Load_Image;
1035 image_info->load_artwork = Load_PCX;
1037 image_info->free_artwork = FreeImage;
1040 void ReloadCustomImages()
1043 printf("::: reloading images '%s' ...\n", artwork.gfx_current_identifier);
1046 print_timestamp_init("ReloadCustomImages");
1048 LoadArtworkConfig(image_info);
1049 print_timestamp_time("LoadArtworkConfig");
1051 ReloadCustomArtworkList(image_info);
1052 print_timestamp_time("ReloadCustomArtworkList");
1054 print_timestamp_done("ReloadCustomImages");
1057 void CreateImageWithSmallImages(int pos, int zoom_factor)
1059 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
1061 if (img_info == NULL || img_info->contains_small_images)
1064 CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor);
1066 img_info->contains_small_images = TRUE;
1067 img_info->scaled_up = TRUE;
1070 void ScaleImage(int pos, int zoom_factor)
1072 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
1074 if (img_info == NULL || img_info->scaled_up)
1077 if (zoom_factor != 1)
1078 ScaleBitmap(img_info->bitmap, zoom_factor);
1080 img_info->scaled_up = TRUE;
1083 void FreeAllImages()
1085 FreeCustomArtworkLists(image_info);