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_RETURN, "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_RETURN,"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_RETURN, "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_RETURN,"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);
652 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;
660 zoom_factor = dst_width / src_width;
662 /* no adjustment needed when scaling up (some pixels may be left blank) */
665 /* copy source pixmap to temporary image */
666 if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
667 AllPlanes, ZPixmap)) == NULL)
668 Error(ERR_EXIT, "ZoomPixmap(): XGetImage() failed");
670 bits_per_pixel = src_ximage->bits_per_pixel;
671 bytes_per_pixel = (bits_per_pixel + 7) / 8;
673 if ((dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap,
674 0, NULL, dst_width, dst_height,
675 8, dst_width * bytes_per_pixel)) == NULL)
676 Error(ERR_EXIT, "ZoomPixmap(): XCreateImage() failed");
679 checked_malloc(dst_width * dst_height * bytes_per_pixel);
680 dst_ximage->byte_order = src_ximage->byte_order;
682 src_ptr = (byte *)src_ximage->data;
683 dst_ptr = (byte *)dst_ximage->data;
687 col_skip = (zoom_factor - 1) * bytes_per_pixel;
688 row_skip = col_skip * src_width;
690 /* scale image down by scaling factor 'zoom_factor' */
691 for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip)
692 for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip)
693 for (i = 0; i < bytes_per_pixel; i++)
694 *dst_ptr++ = *src_ptr++;
698 row_skip = src_width * bytes_per_pixel;
700 /* scale image up by scaling factor 'zoom_factor' */
701 for (y = 0; y < src_height; y++)
703 for (yy = 0; yy < zoom_factor; yy++)
708 for (x = 0; x < src_width; x++)
710 for (xx = 0; xx < zoom_factor; xx++)
711 for (i = 0; i < bytes_per_pixel; i++)
712 *dst_ptr++ = *(src_ptr + i);
714 src_ptr += bytes_per_pixel;
720 /* copy scaled image to destination pixmap */
721 XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0,
722 dst_width, dst_height);
724 /* free temporary images */
725 X11DestroyImage(src_ximage);
726 X11DestroyImage(dst_ximage);
729 void freeXImage(Image *image, XImageInfo *ximageinfo)
731 if (ximageinfo->index != NULL && ximageinfo->no > 0)
732 XFreeColors(ximageinfo->display, ximageinfo->cmap, ximageinfo->index,
734 /* this ^^^^^^^^^^^^^^ is wrong, because the used color cells
735 * are somewhere between 0 and MAX_COLORS; there are indeed 'ximageinfo->no'
736 * used color cells, but they are not at array position 0 - 'ximageinfo->no'
742 int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
743 Pixmap *pixmap, Pixmap *pixmap_mask)
746 XImageInfo *ximageinfo;
752 debug_print_timestamp(2, NULL); /* initialize timestamp function */
755 /* read the graphic file in PCX format to image structure */
756 if ((image = Read_PCX_to_Image(filename)) == NULL)
760 printf("%s:\n", filename);
761 debug_print_timestamp(2, " READING PCX FILE TO IMAGE: ");
764 screen = DefaultScreen(display);
765 visual = DefaultVisual(display, screen);
766 depth = DefaultDepth(display, screen);
768 /* convert image structure to X11 Pixmap */
769 if (!(ximageinfo = Image_to_Pixmap(display, screen, visual,
770 window, gc, depth, image)))
774 return PCX_OtherError;
777 /* if a private colormap has been created, install it */
778 if (ximageinfo->cmap != DefaultColormap(display, screen))
779 XSetWindowColormap(display, window, ximageinfo->cmap);
782 debug_print_timestamp(2, " CONVERTING IMAGE TO PIXMAP:");
785 /* create clip mask for the image */
786 ximageinfo->pixmap_mask = Image_to_Mask(image, display, window);
789 debug_print_timestamp(2, " CONVERTING IMAGE TO MASK: ");
792 *pixmap = ximageinfo->pixmap;
793 *pixmap_mask = ximageinfo->pixmap_mask;
795 /* free generic image and ximageinfo after native Pixmap has been created */
802 #endif /* PLATFORM_UNIX */
803 #endif /* TARGET_X11 */
806 /* ========================================================================= */
807 /* PLATFORM INDEPENDENT IMAGE FUNCTIONS */
808 /* ========================================================================= */
812 char *source_filename;
817 int original_width; /* original image file width */
818 int original_height; /* original image file height */
820 boolean contains_small_images; /* set after adding small images */
821 boolean scaled_up; /* set after scaling up */
823 typedef struct ImageInfo ImageInfo;
825 static struct ArtworkListInfo *image_info = NULL;
827 static void *Load_PCX(char *filename)
832 printf("::: loading PCX file '%s'\n", filename);
835 img_info = checked_calloc(sizeof(ImageInfo));
837 if ((img_info->bitmap = LoadImage(filename)) == NULL)
839 Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s",
840 filename, GetError());
845 img_info->source_filename = getStringCopy(filename);
847 img_info->original_width = img_info->bitmap->width;
848 img_info->original_height = img_info->bitmap->height;
850 img_info->contains_small_images = FALSE;
851 img_info->scaled_up = FALSE;
856 static void FreeImage(void *ptr)
858 ImageInfo *image = (ImageInfo *)ptr;
864 FreeBitmap(image->bitmap);
866 if (image->source_filename)
867 free(image->source_filename);
872 int getImageListSize()
874 return (image_info->num_file_list_entries +
875 image_info->num_dynamic_file_list_entries);
878 struct FileInfo *getImageListEntryFromImageID(int pos)
880 int num_list_entries = image_info->num_file_list_entries;
881 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
883 return (pos < num_list_entries ? &image_info->file_list[list_pos] :
884 &image_info->dynamic_file_list[list_pos]);
887 static ImageInfo *getImageInfoEntryFromImageID(int pos)
889 int num_list_entries = image_info->num_file_list_entries;
890 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
891 ImageInfo **img_info =
892 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
893 image_info->dynamic_artwork_list);
895 return img_info[list_pos];
898 Bitmap *getBitmapFromImageID(int pos)
900 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
902 return (img_info != NULL ? img_info->bitmap : NULL);
905 int getOriginalImageWidthFromImageID(int pos)
907 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
909 return (img_info != NULL ? img_info->original_width : 0);
912 int getOriginalImageHeightFromImageID(int pos)
914 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
916 return (img_info != NULL ? img_info->original_height : 0);
919 char *getTokenFromImageID(int graphic)
921 struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
923 return (file_list != NULL ? file_list->token : NULL);
926 int getImageIDFromToken(char *token)
928 struct FileInfo *file_list = image_info->file_list;
929 int num_list_entries = image_info->num_file_list_entries;
932 for (i = 0; i < num_list_entries; i++)
933 if (strEqual(file_list[i].token, token))
939 char *getImageConfigFilename()
941 return getCustomArtworkConfigFilename(image_info->type);
944 int getImageListPropertyMappingSize()
946 return image_info->num_property_mapping_entries;
949 struct PropertyMapping *getImageListPropertyMapping()
951 return image_info->property_mapping;
954 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
955 struct ConfigTypeInfo *config_suffix_list,
956 char **base_prefixes, char **ext1_suffixes,
957 char **ext2_suffixes, char **ext3_suffixes,
958 char **ignore_tokens)
962 image_info = checked_calloc(sizeof(struct ArtworkListInfo));
963 image_info->type = ARTWORK_TYPE_GRAPHICS;
965 /* ---------- initialize file list and suffix lists ---------- */
967 image_info->num_file_list_entries = num_file_list_entries;
968 image_info->num_dynamic_file_list_entries = 0;
970 image_info->file_list =
971 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
972 num_file_list_entries);
973 image_info->dynamic_file_list = NULL;
975 image_info->num_suffix_list_entries = 0;
976 for (i = 0; config_suffix_list[i].token != NULL; i++)
977 image_info->num_suffix_list_entries++;
979 image_info->suffix_list = config_suffix_list;
981 /* ---------- initialize base prefix and suffixes lists ---------- */
983 image_info->num_base_prefixes = 0;
984 for (i = 0; base_prefixes[i] != NULL; i++)
985 image_info->num_base_prefixes++;
987 image_info->num_ext1_suffixes = 0;
988 for (i = 0; ext1_suffixes[i] != NULL; i++)
989 image_info->num_ext1_suffixes++;
991 image_info->num_ext2_suffixes = 0;
992 for (i = 0; ext2_suffixes[i] != NULL; i++)
993 image_info->num_ext2_suffixes++;
995 image_info->num_ext3_suffixes = 0;
996 for (i = 0; ext3_suffixes[i] != NULL; i++)
997 image_info->num_ext3_suffixes++;
999 image_info->num_ignore_tokens = 0;
1000 for (i = 0; ignore_tokens[i] != NULL; i++)
1001 image_info->num_ignore_tokens++;
1003 image_info->base_prefixes = base_prefixes;
1004 image_info->ext1_suffixes = ext1_suffixes;
1005 image_info->ext2_suffixes = ext2_suffixes;
1006 image_info->ext3_suffixes = ext3_suffixes;
1007 image_info->ignore_tokens = ignore_tokens;
1009 image_info->num_property_mapping_entries = 0;
1011 image_info->property_mapping = NULL;
1013 /* ---------- initialize artwork reference and content lists ---------- */
1015 image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *);
1017 image_info->artwork_list =
1018 checked_calloc(num_file_list_entries * sizeof(ImageInfo *));
1019 image_info->dynamic_artwork_list = NULL;
1021 image_info->content_list = NULL;
1023 /* ---------- initialize artwork loading/freeing functions ---------- */
1025 image_info->load_artwork = Load_PCX;
1026 image_info->free_artwork = FreeImage;
1029 void ReloadCustomImages()
1032 printf("::: reloading images '%s' ...\n", artwork.gfx_current_identifier);
1035 LoadArtworkConfig(image_info);
1036 ReloadCustomArtworkList(image_info);
1039 void CreateImageWithSmallImages(int pos, int zoom_factor)
1041 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
1043 if (img_info == NULL || img_info->contains_small_images)
1046 CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor);
1048 img_info->contains_small_images = TRUE;
1049 img_info->scaled_up = TRUE;
1052 void ScaleImage(int pos, int zoom_factor)
1054 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
1056 if (img_info == NULL || img_info->scaled_up)
1059 if (zoom_factor != 1)
1060 ScaleBitmap(img_info->bitmap, zoom_factor);
1062 img_info->scaled_up = TRUE;
1065 void FreeAllImages()
1067 FreeCustomArtworkLists(image_info);