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 /* for MS-DOS/Allegro, exclude all except newImage() and freeImage() */
28 Image *newImage(unsigned int width, unsigned int height, unsigned int depth)
31 unsigned int bytes_per_pixel = (depth + 7) / 8;
34 image = checked_calloc(sizeof(Image));
35 image->data = checked_calloc(width * height * bytes_per_pixel);
37 image->height = height;
39 image->bytes_per_pixel = bytes_per_pixel;
40 image->bytes_per_row = width * bytes_per_pixel;
43 for (i = 0; i < MAX_COLORS; i++)
44 image->rgb.color_used[i] = FALSE;
46 image->type = (depth < 8 ? IMAGETYPE_BITMAP :
47 depth > 8 ? IMAGETYPE_TRUECOLOR : IMAGETYPE_RGB);
52 void freeImage(Image *image)
58 #if defined(PLATFORM_UNIX)
60 /* extra colors to try allocating in private color maps to minimize flashing */
61 #define NOFLASH_COLORS 256
63 /* architecture independent value <-> memory conversions;
64 note: the internal format is big endian */
66 #define memory_to_value(ptr, len) ( \
67 (len) == 1 ? (unsigned long)( *( (byte *)(ptr)) ) : \
68 (len) == 2 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr)) ))<< 8) \
69 + ( *(((byte *)(ptr))+1) ) : \
70 (len) == 3 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr)) ))<<16) \
71 + (((unsigned long)(*(((byte *)(ptr))+1)))<< 8) \
72 + ( *(((byte *)(ptr))+2) ) : \
73 (unsigned long)(((unsigned long)(*( (byte *)(ptr)) ))<<24) \
74 + (((unsigned long)(*(((byte *)(ptr))+1)))<<16) \
75 + (((unsigned long)(*(((byte *)(ptr))+2)))<< 8) \
76 + ( *(((byte *)(ptr))+3) ) )
79 #define value_to_memory(value, ptr, len) ( \
80 (len) == 1 ? (*( (byte *)(ptr) ) = ( value ) ) : \
81 (len) == 2 ? (*( (byte *)(ptr) ) = (((unsigned long)(value))>> 8), \
82 *(((byte *)(ptr))+1) = ( value ) ) : \
83 (len) == 3 ? (*( (byte *)(ptr) ) = (((unsigned long)(value))>>16), \
84 *(((byte *)(ptr))+1) = (((unsigned long)(value))>> 8), \
85 *(((byte *)(ptr))+2) = ( value ) ) : \
86 (*( (byte *)(ptr) ) = (((unsigned long)(value))>>24), \
87 *(((byte *)(ptr))+1) = (((unsigned long)(value))>>16), \
88 *(((byte *)(ptr))+2) = (((unsigned long)(value))>> 8), \
89 *(((byte *)(ptr))+3) = ( value ) ))
91 static Pixmap Image_to_Mask(Image *image, Display *display, Window window)
93 byte *src_ptr, *dst_ptr, *dst_ptr2;
94 unsigned int bytes_per_row;
100 bytes_per_row = (image->width + 7) / 8;
101 mask_data = checked_calloc(bytes_per_row * image->height);
103 src_ptr = image->data;
106 /* create bitmap data which can be used by 'XCreateBitmapFromData()'
107 * directly to create a pixmap of depth 1 for use as a clip mask for
108 * the corresponding image pixmap
111 for (y = 0; y < image->height; y++)
113 bitmask = 0x01; /* start with leftmost bit in the byte */
114 dst_ptr2 = dst_ptr; /* start with leftmost byte in the row */
116 for (x = 0; x < image->width; x++)
118 for (i = 0; i < image->bytes_per_pixel; i++)
119 if (*src_ptr++) /* source pixel solid? (pixel index != 0) */
120 *dst_ptr2 |= bitmask; /* then write a bit into the image mask */
122 if ((bitmask <<= 1) == 0) /* bit at rightmost byte position reached? */
124 bitmask = 0x01; /* start again with leftmost bit position */
125 dst_ptr2++; /* continue with next byte in image mask */
129 dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */
132 if ((mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data,
133 image->width, image->height))
135 Error(ERR_EXIT, "Image_to_Mask(): XCreateBitmapFromData() failed");
142 Pixmap Pixmap_to_Mask(Pixmap src_pixmap, int src_width, int src_height)
145 byte *src_ptr, *dst_ptr, *dst_ptr2;
148 unsigned int bytes_per_row;
149 unsigned int x, y, i;
154 /* copy source pixmap to temporary image */
155 if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
156 AllPlanes, ZPixmap)) == NULL)
157 Error(ERR_EXIT, "Pixmap_to_Mask(): XGetImage() failed");
159 bits_per_pixel = src_ximage->bits_per_pixel;
160 bytes_per_pixel = (bits_per_pixel + 7) / 8;
162 bytes_per_row = (src_width + 7) / 8;
163 mask_data = checked_calloc(bytes_per_row * src_height);
165 src_ptr = (byte *)src_ximage->data;
168 /* create bitmap data which can be used by 'XCreateBitmapFromData()'
169 * directly to create a pixmap of depth 1 for use as a clip mask for
170 * the corresponding image pixmap
173 for (y = 0; y < src_height; y++)
175 bitmask = 0x01; /* start with leftmost bit in the byte */
176 dst_ptr2 = dst_ptr; /* start with leftmost byte in the row */
178 for (x = 0; x < src_width; x++)
180 for (i = 0; i < bytes_per_pixel; i++)
181 if (*src_ptr++) /* source pixel solid? (pixel index != 0) */
182 *dst_ptr2 |= bitmask; /* then write a bit into the image mask */
184 if ((bitmask <<= 1) == 0) /* bit at rightmost byte position reached? */
186 bitmask = 0x01; /* start again with leftmost bit position */
187 dst_ptr2++; /* continue with next byte in image mask */
191 dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */
194 if ((mask_pixmap = XCreateBitmapFromData(display, window->drawable,
196 src_width, src_height)) == None)
197 Error(ERR_EXIT, "Pixmap_to_Mask(): XCreateBitmapFromData() failed");
204 static int bitsPerPixelAtDepth(Display *display, int screen, int depth)
206 XPixmapFormatValues *pixmap_format;
207 int i, num_pixmap_formats, bits_per_pixel = -1;
209 /* get Pixmap formats supported by the X server */
210 pixmap_format = XListPixmapFormats(display, &num_pixmap_formats);
212 /* find format that matches the given depth */
213 for (i = 0; i < num_pixmap_formats; i++)
214 if (pixmap_format[i].depth == depth)
215 bits_per_pixel = pixmap_format[i].bits_per_pixel;
217 XFree(pixmap_format);
219 if (bits_per_pixel == -1)
220 Error(ERR_EXIT, "cannot find pixmap format for depth %d", depth);
222 return bits_per_pixel;
225 XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
226 Window window, GC gc, int depth, Image *image)
228 static XColor xcolor_private[NOFLASH_COLORS];
229 static int colorcell_used[NOFLASH_COLORS];
230 static Colormap global_cmap = 0;
231 static Pixel *global_cmap_index;
232 static int num_cmap_entries, free_cmap_entries;
233 static boolean private_cmap = FALSE;
234 Pixel *redvalue, *greenvalue, *bluevalue;
235 unsigned int display_bytes_per_pixel, display_bits_per_pixel;
236 unsigned int a, c = 0, x, y;
239 XImageInfo *ximageinfo;
240 byte *src_ptr, *dst_ptr;
241 char *error = "Image_to_Pixmap(): %s";
243 if (image->type == IMAGETYPE_TRUECOLOR && depth == 8)
245 SetError(error, "cannot handle true-color images on 8-bit display");
251 if (visual == DefaultVisual(display, screen))
252 global_cmap = DefaultColormap(display, screen);
255 global_cmap = XCreateColormap(display, RootWindow(display, screen),
261 xcolor.flags = DoRed | DoGreen | DoBlue;
262 redvalue = greenvalue = bluevalue = NULL;
263 ximageinfo = checked_malloc(sizeof(XImageInfo));
264 ximageinfo->display = display;
265 ximageinfo->depth = depth;
267 switch (visual->class)
273 unsigned int redcolors, greencolors, bluecolors;
274 unsigned int redstep, greenstep, bluestep;
275 unsigned int redbottom, greenbottom, bluebottom;
276 unsigned int redtop, greentop, bluetop;
278 redvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
279 greenvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
280 bluevalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
282 ximageinfo->cmap = global_cmap;
284 retry_direct: /* tag we hit if a DirectColor allocation fails on
285 * default colormap */
287 /* calculate number of distinct colors in each band */
289 redcolors = greencolors = bluecolors = 1;
290 for (pixval = 1; pixval; pixval <<= 1)
292 if (pixval & visual->red_mask)
294 if (pixval & visual->green_mask)
296 if (pixval & visual->blue_mask)
300 /* consistency check */
301 if (redcolors > visual->map_entries ||
302 greencolors > visual->map_entries ||
303 bluecolors > visual->map_entries)
304 Error(ERR_WARN, "inconsistency in color information");
306 redstep = 256 / redcolors;
307 greenstep = 256 / greencolors;
308 bluestep = 256 / bluecolors;
309 redbottom = greenbottom = bluebottom = 0;
310 redtop = greentop = bluetop = 0;
312 for (a = 0; a < visual->map_entries; a++)
315 redtop = redbottom + redstep;
316 if (greenbottom < 256)
317 greentop = greenbottom + greenstep;
318 if (bluebottom < 256)
319 bluetop = bluebottom + bluestep;
321 xcolor.red = (redtop - 1) << 8;
322 xcolor.green = (greentop - 1) << 8;
323 xcolor.blue = (bluetop - 1) << 8;
324 if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
326 /* if an allocation fails for a DirectColor default visual then
327 we should create a private colormap and try again. */
329 if ((visual->class == DirectColor) &&
330 (visual == DefaultVisual(display, screen)))
332 global_cmap = XCopyColormapAndFree(display, global_cmap);
333 ximageinfo->cmap = global_cmap;
339 /* something completely unexpected happened */
341 fprintf(stderr, "Image_to_Pixmap: XAllocColor failed on a TrueColor/Directcolor visual\n");
351 /* fill in pixel values for each band at this intensity */
353 while ((redbottom < 256) && (redbottom < redtop))
354 redvalue[redbottom++] = xcolor.pixel & visual->red_mask;
355 while ((greenbottom < 256) && (greenbottom < greentop))
356 greenvalue[greenbottom++] = xcolor.pixel & visual->green_mask;
357 while ((bluebottom < 256) && (bluebottom < bluetop))
358 bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask;
366 ximageinfo->cmap = global_cmap;
368 for (a = 0; a < MAX_COLORS; a++)
375 if (!image->rgb.color_used[a])
378 xcolor.red = *(image->rgb.red + a);
379 xcolor.green = *(image->rgb.green + a);
380 xcolor.blue = *(image->rgb.blue + a);
382 /* look if this color already exists in our colormap */
383 if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
388 Error(ERR_INFO, "switching to private colormap");
390 /* we just filled up the default colormap -- get a private one
391 which contains all already allocated colors */
393 global_cmap = XCopyColormapAndFree(display, global_cmap);
394 ximageinfo->cmap = global_cmap;
397 /* allocate the rest of the color cells read/write */
399 (Pixel *)checked_malloc(sizeof(Pixel) * NOFLASH_COLORS);
400 for (i = 0; i < NOFLASH_COLORS; i++)
401 if (!XAllocColorCells(display, global_cmap, FALSE, NULL, 0,
402 global_cmap_index + i, 1))
404 num_cmap_entries = free_cmap_entries = i;
407 printf("We've got %d free colormap entries.\n", free_cmap_entries);
410 /* to minimize colormap flashing, copy default colors and try
411 to keep them as near as possible to the old values */
413 for (i = 0; i < num_cmap_entries; i++)
415 xcolor2.pixel = *(global_cmap_index + i);
416 XQueryColor(display, DefaultColormap(display, screen), &xcolor2);
417 XStoreColor(display, global_cmap, &xcolor2);
418 xcolor_private[xcolor2.pixel] = xcolor2;
419 colorcell_used[xcolor2.pixel] = FALSE;
422 /* now we have the default colormap private: all colors we
423 successfully allocated so far are read-only, which is okay,
424 because we don't want to change them anymore -- if we need
425 an existing color again, we get it by XAllocColor; all other
426 colors are read/write and we can set them by XStoreColor,
427 but we will try to overwrite those color cells with our new
428 color which are as close as possible to our new color */
431 /* look for an existing default color close the one we want */
438 for (i = num_cmap_entries - 1; i >= 0; i--)
440 xcolor2.pixel = *(global_cmap_index + i);
441 xcolor2 = xcolor_private[xcolor2.pixel];
443 if (colorcell_used[xcolor2.pixel])
446 if ((xcolor.red & mask) == (xcolor2.red & mask) &&
447 (xcolor.green & mask) == (xcolor2.green & mask) &&
448 (xcolor.blue & mask) == (xcolor2.blue & mask))
451 printf("replacing color cell %ld with a close color\n",
462 mask = (mask << 1) & 0xffff;
465 if (!color_found) /* no more free color cells */
467 SetError(error, "cannot allocate enough color cells");
471 xcolor.pixel = xcolor2.pixel;
472 xcolor_private[xcolor.pixel] = xcolor;
473 colorcell_used[xcolor.pixel] = TRUE;
474 XStoreColor(display, ximageinfo->cmap, &xcolor);
478 *(ximageinfo->index + a) = xcolor.pixel;
482 printf("still %d free colormap entries\n", free_cmap_entries);
485 ximageinfo->no = a; /* number of pixels allocated for this image */
489 Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed");
490 SetError(error, "display class not supported");
496 debug_print_timestamp(2, " ALLOCATING IMAGE COLORS: ");
499 /* create XImage from internal image structure and convert it to Pixmap */
501 display_bits_per_pixel = bitsPerPixelAtDepth(display, screen, depth);
502 display_bytes_per_pixel = (display_bits_per_pixel + 7) / 8;
504 ximage = XCreateImage(display, visual, depth, ZPixmap,
505 0, NULL, image->width, image->height,
506 8, image->width * display_bytes_per_pixel);
508 checked_malloc(image->width * image->height * display_bytes_per_pixel);
509 ximage->byte_order = MSBFirst;
511 src_ptr = image->data;
512 dst_ptr = (byte *)ximage->data;
514 switch (visual->class)
525 for (y = 0; y < image->height; y++) /* general case */
527 for (x = 0; x < image->width; x++)
531 redvalue[image->rgb.red[pixval] >> 8] |
532 greenvalue[image->rgb.green[pixval] >> 8] |
533 bluevalue[image->rgb.blue[pixval] >> 8];
534 value_to_memory(pixval, dst_ptr, display_bytes_per_pixel);
535 dst_ptr += display_bytes_per_pixel;
542 case IMAGETYPE_TRUECOLOR:
544 for (y = 0; y < image->height; y++) /* general case */
546 for (x = 0; x < image->width; x++)
548 pixval = memory_to_value(src_ptr, image->bytes_per_pixel);
550 redvalue[TRUECOLOR_RED(pixval)] |
551 greenvalue[TRUECOLOR_GREEN(pixval)] |
552 bluevalue[TRUECOLOR_BLUE(pixval)];
553 value_to_memory(pixval, dst_ptr, display_bytes_per_pixel);
554 src_ptr += image->bytes_per_pixel;
555 dst_ptr += display_bytes_per_pixel;
563 Error(ERR_INFO, "RGB or TrueColor image needed");
564 SetError(error, "image type not supported");
574 if (display_bytes_per_pixel == 1) /* special case */
576 for (y = 0; y < image->height; y++)
577 for (x = 0; x < image->width; x++)
578 *dst_ptr++ = ximageinfo->index[c + *src_ptr++];
580 else /* general case */
582 for (y = 0; y < image->height; y++)
584 for (x = 0; x < image->width; x++)
586 value_to_memory(ximageinfo->index[c + *src_ptr++],
587 dst_ptr, display_bytes_per_pixel);
588 dst_ptr += display_bytes_per_pixel;
597 Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed");
598 SetError(error, "display class not supported");
605 free((byte *)redvalue);
606 free((byte *)greenvalue);
607 free((byte *)bluevalue);
611 debug_print_timestamp(2, " CONVERTING IMAGE TO XIMAGE:");
614 ximageinfo->pixmap = XCreatePixmap(display, window,
615 ximage->width, ximage->height,
618 XPutImage(ximageinfo->display, ximageinfo->pixmap, gc,
619 ximage, 0, 0, 0, 0, ximage->width, ximage->height);
621 X11DestroyImage(ximage);
627 -----------------------------------------------------------------------------
630 Important note: The scaling code currently only supports scaling of the image
631 up or down by a power of 2 -- other scaling factors currently not supported!
632 Also not supported is scaling of pixmap masks (with depth 1); to scale them,
633 better use Pixmap_to_Mask() for now.
634 -----------------------------------------------------------------------------
637 void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap,
638 int src_width, int src_height,
639 int dst_width, int dst_height)
641 XImage *src_ximage, *dst_ximage;
642 byte *src_ptr, *dst_ptr;
646 int row_skip, col_skip;
648 boolean scale_down = (src_width > dst_width);
653 zoom_factor = MIN(src_width / dst_width, src_height / dst_height);
655 zoom_factor = src_width / dst_width;
658 /* adjust source image size to integer multiple of destination size */
659 src_width = dst_width * zoom_factor;
660 src_height = dst_height * zoom_factor;
665 zoom_factor = MIN(dst_width / src_width, dst_height / src_height);
667 zoom_factor = dst_width / src_width;
670 /* no adjustment needed when scaling up (some pixels may be left blank) */
673 /* copy source pixmap to temporary image */
674 if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
675 AllPlanes, ZPixmap)) == NULL)
676 Error(ERR_EXIT, "ZoomPixmap(): XGetImage() failed");
678 bits_per_pixel = src_ximage->bits_per_pixel;
679 bytes_per_pixel = (bits_per_pixel + 7) / 8;
681 if ((dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap,
682 0, NULL, dst_width, dst_height,
683 8, dst_width * bytes_per_pixel)) == NULL)
684 Error(ERR_EXIT, "ZoomPixmap(): XCreateImage() failed");
687 checked_malloc(dst_width * dst_height * bytes_per_pixel);
688 dst_ximage->byte_order = src_ximage->byte_order;
690 src_ptr = (byte *)src_ximage->data;
691 dst_ptr = (byte *)dst_ximage->data;
695 col_skip = (zoom_factor - 1) * bytes_per_pixel;
696 row_skip = col_skip * src_width;
698 /* scale image down by scaling factor 'zoom_factor' */
699 for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip)
700 for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip)
701 for (i = 0; i < bytes_per_pixel; i++)
702 *dst_ptr++ = *src_ptr++;
706 row_skip = src_width * bytes_per_pixel;
708 /* scale image up by scaling factor 'zoom_factor' */
709 for (y = 0; y < src_height; y++)
711 for (yy = 0; yy < zoom_factor; yy++)
716 for (x = 0; x < src_width; x++)
718 for (xx = 0; xx < zoom_factor; xx++)
719 for (i = 0; i < bytes_per_pixel; i++)
720 *dst_ptr++ = *(src_ptr + i);
722 src_ptr += bytes_per_pixel;
728 /* copy scaled image to destination pixmap */
729 XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0,
730 dst_width, dst_height);
732 /* free temporary images */
733 X11DestroyImage(src_ximage);
734 X11DestroyImage(dst_ximage);
737 void freeXImage(Image *image, XImageInfo *ximageinfo)
739 if (ximageinfo->index != NULL && ximageinfo->no > 0)
740 XFreeColors(ximageinfo->display, ximageinfo->cmap, ximageinfo->index,
742 /* this ^^^^^^^^^^^^^^ is wrong, because the used color cells
743 * are somewhere between 0 and MAX_COLORS; there are indeed 'ximageinfo->no'
744 * used color cells, but they are not at array position 0 - 'ximageinfo->no'
750 int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
751 Pixmap *pixmap, Pixmap *pixmap_mask)
754 XImageInfo *ximageinfo;
760 debug_print_timestamp(2, NULL); /* initialize timestamp function */
763 /* read the graphic file in PCX format to image structure */
764 if ((image = Read_PCX_to_Image(filename)) == NULL)
768 printf("%s:\n", filename);
769 debug_print_timestamp(2, " READING PCX FILE TO IMAGE: ");
772 screen = DefaultScreen(display);
773 visual = DefaultVisual(display, screen);
774 depth = DefaultDepth(display, screen);
776 /* convert image structure to X11 Pixmap */
777 if (!(ximageinfo = Image_to_Pixmap(display, screen, visual,
778 window, gc, depth, image)))
782 return PCX_OtherError;
785 /* if a private colormap has been created, install it */
786 if (ximageinfo->cmap != DefaultColormap(display, screen))
787 XSetWindowColormap(display, window, ximageinfo->cmap);
790 debug_print_timestamp(2, " CONVERTING IMAGE TO PIXMAP:");
793 /* create clip mask for the image */
794 ximageinfo->pixmap_mask = Image_to_Mask(image, display, window);
797 debug_print_timestamp(2, " CONVERTING IMAGE TO MASK: ");
800 *pixmap = ximageinfo->pixmap;
801 *pixmap_mask = ximageinfo->pixmap_mask;
803 /* free generic image and ximageinfo after native Pixmap has been created */
810 #endif /* PLATFORM_UNIX */
811 #endif /* TARGET_X11 */
814 /* ========================================================================= */
815 /* PLATFORM INDEPENDENT IMAGE FUNCTIONS */
816 /* ========================================================================= */
820 char *source_filename;
825 int original_width; /* original image file width */
826 int original_height; /* original image file height */
828 boolean contains_small_images; /* set after adding small images */
829 boolean scaled_up; /* set after scaling up */
831 typedef struct ImageInfo ImageInfo;
833 static struct ArtworkListInfo *image_info = NULL;
835 static void *Load_PCX(char *filename)
840 printf("::: loading PCX file '%s'\n", filename);
843 img_info = checked_calloc(sizeof(ImageInfo));
845 if ((img_info->bitmap = LoadImage(filename)) == NULL)
847 Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s",
848 filename, GetError());
853 img_info->source_filename = getStringCopy(filename);
855 img_info->original_width = img_info->bitmap->width;
856 img_info->original_height = img_info->bitmap->height;
858 img_info->contains_small_images = FALSE;
859 img_info->scaled_up = FALSE;
864 static void FreeImage(void *ptr)
866 ImageInfo *image = (ImageInfo *)ptr;
872 FreeBitmap(image->bitmap);
874 if (image->source_filename)
875 free(image->source_filename);
880 int getImageListSize()
882 return (image_info->num_file_list_entries +
883 image_info->num_dynamic_file_list_entries);
886 struct FileInfo *getImageListEntryFromImageID(int pos)
888 int num_list_entries = image_info->num_file_list_entries;
889 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
891 return (pos < num_list_entries ? &image_info->file_list[list_pos] :
892 &image_info->dynamic_file_list[list_pos]);
895 static ImageInfo *getImageInfoEntryFromImageID(int pos)
897 int num_list_entries = image_info->num_file_list_entries;
898 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
899 ImageInfo **img_info =
900 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
901 image_info->dynamic_artwork_list);
903 return img_info[list_pos];
906 Bitmap *getBitmapFromImageID(int pos)
908 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
910 return (img_info != NULL ? img_info->bitmap : NULL);
913 int getOriginalImageWidthFromImageID(int pos)
915 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
917 return (img_info != NULL ? img_info->original_width : 0);
920 int getOriginalImageHeightFromImageID(int pos)
922 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
924 return (img_info != NULL ? img_info->original_height : 0);
927 char *getTokenFromImageID(int graphic)
929 struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
931 return (file_list != NULL ? file_list->token : NULL);
934 int getImageIDFromToken(char *token)
936 struct FileInfo *file_list = image_info->file_list;
937 int num_list_entries = image_info->num_file_list_entries;
940 for (i = 0; i < num_list_entries; i++)
941 if (strEqual(file_list[i].token, token))
947 char *getImageConfigFilename()
949 return getCustomArtworkConfigFilename(image_info->type);
952 int getImageListPropertyMappingSize()
954 return image_info->num_property_mapping_entries;
957 struct PropertyMapping *getImageListPropertyMapping()
959 return image_info->property_mapping;
962 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
963 struct ConfigTypeInfo *config_suffix_list,
964 char **base_prefixes, char **ext1_suffixes,
965 char **ext2_suffixes, char **ext3_suffixes,
966 char **ignore_tokens)
970 image_info = checked_calloc(sizeof(struct ArtworkListInfo));
971 image_info->type = ARTWORK_TYPE_GRAPHICS;
973 /* ---------- initialize file list and suffix lists ---------- */
975 image_info->num_file_list_entries = num_file_list_entries;
976 image_info->num_dynamic_file_list_entries = 0;
978 image_info->file_list =
979 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
980 num_file_list_entries);
981 image_info->dynamic_file_list = NULL;
983 image_info->num_suffix_list_entries = 0;
984 for (i = 0; config_suffix_list[i].token != NULL; i++)
985 image_info->num_suffix_list_entries++;
987 image_info->suffix_list = config_suffix_list;
989 /* ---------- initialize base prefix and suffixes lists ---------- */
991 image_info->num_base_prefixes = 0;
992 for (i = 0; base_prefixes[i] != NULL; i++)
993 image_info->num_base_prefixes++;
995 image_info->num_ext1_suffixes = 0;
996 for (i = 0; ext1_suffixes[i] != NULL; i++)
997 image_info->num_ext1_suffixes++;
999 image_info->num_ext2_suffixes = 0;
1000 for (i = 0; ext2_suffixes[i] != NULL; i++)
1001 image_info->num_ext2_suffixes++;
1003 image_info->num_ext3_suffixes = 0;
1004 for (i = 0; ext3_suffixes[i] != NULL; i++)
1005 image_info->num_ext3_suffixes++;
1007 image_info->num_ignore_tokens = 0;
1008 for (i = 0; ignore_tokens[i] != NULL; i++)
1009 image_info->num_ignore_tokens++;
1011 image_info->base_prefixes = base_prefixes;
1012 image_info->ext1_suffixes = ext1_suffixes;
1013 image_info->ext2_suffixes = ext2_suffixes;
1014 image_info->ext3_suffixes = ext3_suffixes;
1015 image_info->ignore_tokens = ignore_tokens;
1017 image_info->num_property_mapping_entries = 0;
1019 image_info->property_mapping = NULL;
1021 /* ---------- initialize artwork reference and content lists ---------- */
1023 image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *);
1025 image_info->artwork_list =
1026 checked_calloc(num_file_list_entries * sizeof(ImageInfo *));
1027 image_info->dynamic_artwork_list = NULL;
1029 image_info->content_list = NULL;
1031 /* ---------- initialize artwork loading/freeing functions ---------- */
1033 image_info->load_artwork = Load_PCX;
1034 image_info->free_artwork = FreeImage;
1037 void ReloadCustomImages()
1040 printf("::: reloading images '%s' ...\n", artwork.gfx_current_identifier);
1043 LoadArtworkConfig(image_info);
1044 ReloadCustomArtworkList(image_info);
1047 void CreateImageWithSmallImages(int pos, int zoom_factor)
1049 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
1051 if (img_info == NULL || img_info->contains_small_images)
1054 CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor);
1056 img_info->contains_small_images = TRUE;
1057 img_info->scaled_up = TRUE;
1060 void ScaleImage(int pos, int zoom_factor)
1062 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
1064 if (img_info == NULL || img_info->scaled_up)
1067 if (zoom_factor != 1)
1068 ScaleBitmap(img_info->bitmap, zoom_factor);
1070 img_info->scaled_up = TRUE;
1073 void FreeAllImages()
1075 FreeCustomArtworkLists(image_info);