1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2002 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;
36 Error(ERR_EXIT, "images with more than 256 colors are not supported");
41 image = checked_calloc(sizeof(Image));
42 image->data = checked_calloc(width * height * bytes_per_pixel);
44 image->height = height;
46 image->bytes_per_pixel = bytes_per_pixel;
47 image->bytes_per_row = width * bytes_per_pixel;
50 for (i = 0; i < MAX_COLORS; i++)
51 image->rgb.color_used[i] = FALSE;
53 image->type = (depth < 8 ? IMAGETYPE_BITMAP :
54 depth > 8 ? IMAGETYPE_TRUECOLOR : IMAGETYPE_RGB);
59 void freeImage(Image *image)
65 #if defined(PLATFORM_UNIX)
67 /* extra colors to try allocating in private color maps to minimize flashing */
68 #define NOFLASH_COLORS 256
70 /* architecture independent value <-> memory conversions;
71 note: the internal format is big endian */
73 #define memory_to_value(ptr, len) ( \
74 (len) == 1 ? (unsigned long)( *( (byte *)(ptr)) ) : \
75 (len) == 2 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr)) ))<< 8) \
76 + ( *(((byte *)(ptr))+1) ) : \
77 (len) == 3 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr)) ))<<16) \
78 + (((unsigned long)(*(((byte *)(ptr))+1)))<< 8) \
79 + ( *(((byte *)(ptr))+2) ) : \
80 (unsigned long)(((unsigned long)(*( (byte *)(ptr)) ))<<24) \
81 + (((unsigned long)(*(((byte *)(ptr))+1)))<<16) \
82 + (((unsigned long)(*(((byte *)(ptr))+2)))<< 8) \
83 + ( *(((byte *)(ptr))+3) ) )
86 #define value_to_memory(value, ptr, len) ( \
87 (len) == 1 ? (*( (byte *)(ptr) ) = ( value ) ) : \
88 (len) == 2 ? (*( (byte *)(ptr) ) = (((unsigned long)(value))>> 8), \
89 *(((byte *)(ptr))+1) = ( value ) ) : \
90 (len) == 3 ? (*( (byte *)(ptr) ) = (((unsigned long)(value))>>16), \
91 *(((byte *)(ptr))+1) = (((unsigned long)(value))>> 8), \
92 *(((byte *)(ptr))+2) = ( value ) ) : \
93 (*( (byte *)(ptr) ) = (((unsigned long)(value))>>24), \
94 *(((byte *)(ptr))+1) = (((unsigned long)(value))>>16), \
95 *(((byte *)(ptr))+2) = (((unsigned long)(value))>> 8), \
96 *(((byte *)(ptr))+3) = ( value ) ))
98 static Pixmap Image_to_Mask(Image *image, Display *display, Window window)
100 byte *src_ptr, *dst_ptr, *dst_ptr2;
101 unsigned int bytes_per_row;
102 unsigned int x, y, i;
107 bytes_per_row = (image->width + 7) / 8;
108 mask_data = checked_calloc(bytes_per_row * image->height);
110 src_ptr = image->data;
113 /* create bitmap data which can be used by 'XCreateBitmapFromData()'
114 * directly to create a pixmap of depth 1 for use as a clip mask for
115 * the corresponding image pixmap
118 for (y = 0; y < image->height; y++)
120 bitmask = 0x01; /* start with leftmost bit in the byte */
121 dst_ptr2 = dst_ptr; /* start with leftmost byte in the row */
123 for (x = 0; x < image->width; x++)
125 for (i = 0; i < image->bytes_per_pixel; i++)
126 if (*src_ptr++) /* source pixel solid? (pixel index != 0) */
127 *dst_ptr2 |= bitmask; /* then write a bit into the image mask */
129 if ((bitmask <<= 1) == 0) /* bit at rightmost byte position reached? */
131 bitmask = 0x01; /* start again with leftmost bit position */
132 dst_ptr2++; /* continue with next byte in image mask */
136 dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */
139 if ((mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data,
140 image->width, image->height))
142 Error(ERR_EXIT, "Image_to_Mask(): XCreateBitmapFromData() failed");
149 Pixmap Pixmap_to_Mask(Pixmap src_pixmap, int src_width, int src_height)
152 byte *src_ptr, *dst_ptr, *dst_ptr2;
155 unsigned int bytes_per_row;
156 unsigned int x, y, i;
161 /* copy source pixmap to temporary image */
162 if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
163 AllPlanes, ZPixmap)) == NULL)
164 Error(ERR_EXIT, "Pixmap_to_Mask(): XGetImage() failed");
166 bits_per_pixel = src_ximage->bits_per_pixel;
167 bytes_per_pixel = (bits_per_pixel + 7) / 8;
169 bytes_per_row = (src_width + 7) / 8;
170 mask_data = checked_calloc(bytes_per_row * src_height);
172 src_ptr = (byte *)src_ximage->data;
175 /* create bitmap data which can be used by 'XCreateBitmapFromData()'
176 * directly to create a pixmap of depth 1 for use as a clip mask for
177 * the corresponding image pixmap
180 for (y = 0; y < src_height; y++)
182 bitmask = 0x01; /* start with leftmost bit in the byte */
183 dst_ptr2 = dst_ptr; /* start with leftmost byte in the row */
185 for (x = 0; x < src_width; x++)
187 for (i = 0; i < bytes_per_pixel; i++)
188 if (*src_ptr++) /* source pixel solid? (pixel index != 0) */
189 *dst_ptr2 |= bitmask; /* then write a bit into the image mask */
191 if ((bitmask <<= 1) == 0) /* bit at rightmost byte position reached? */
193 bitmask = 0x01; /* start again with leftmost bit position */
194 dst_ptr2++; /* continue with next byte in image mask */
198 dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */
201 if ((mask_pixmap = XCreateBitmapFromData(display, window->drawable,
203 src_width, src_height)) == None)
204 Error(ERR_EXIT, "Pixmap_to_Mask(): XCreateBitmapFromData() failed");
211 static int bitsPerPixelAtDepth(Display *display, int screen, int depth)
213 XPixmapFormatValues *pixmap_format;
214 int i, num_pixmap_formats, bits_per_pixel = -1;
216 /* get Pixmap formats supported by the X server */
217 pixmap_format = XListPixmapFormats(display, &num_pixmap_formats);
219 /* find format that matches the given depth */
220 for (i = 0; i < num_pixmap_formats; i++)
221 if (pixmap_format[i].depth == depth)
222 bits_per_pixel = pixmap_format[i].bits_per_pixel;
224 XFree(pixmap_format);
226 if (bits_per_pixel == -1)
227 Error(ERR_EXIT, "cannot find pixmap format for depth %d", depth);
229 return bits_per_pixel;
232 XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
233 Window window, GC gc, int depth, Image *image)
235 static XColor xcolor_private[NOFLASH_COLORS];
236 static int colorcell_used[NOFLASH_COLORS];
237 static Colormap global_cmap = 0;
238 static Pixel *global_cmap_index;
239 static int num_cmap_entries, free_cmap_entries;
240 static boolean private_cmap = FALSE;
241 Pixel *redvalue, *greenvalue, *bluevalue;
242 unsigned int display_bytes_per_pixel, display_bits_per_pixel;
243 unsigned int a, c = 0, x, y;
246 XImageInfo *ximageinfo;
247 byte *src_ptr, *dst_ptr;
248 char *error = "Image_to_Pixmap(): %s";
250 if (image->type == IMAGETYPE_TRUECOLOR && depth == 8)
252 SetError(error, "cannot handle true-color images on 8-bit display");
258 if (visual == DefaultVisual(display, screen))
259 global_cmap = DefaultColormap(display, screen);
262 global_cmap = XCreateColormap(display, RootWindow(display, screen),
268 xcolor.flags = DoRed | DoGreen | DoBlue;
269 redvalue = greenvalue = bluevalue = NULL;
270 ximageinfo = checked_malloc(sizeof(XImageInfo));
271 ximageinfo->display = display;
272 ximageinfo->depth = depth;
274 switch (visual->class)
280 unsigned int redcolors, greencolors, bluecolors;
281 unsigned int redstep, greenstep, bluestep;
282 unsigned int redbottom, greenbottom, bluebottom;
283 unsigned int redtop, greentop, bluetop;
285 redvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
286 greenvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
287 bluevalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
289 ximageinfo->cmap = global_cmap;
291 retry_direct: /* tag we hit if a DirectColor allocation fails on
292 * default colormap */
294 /* calculate number of distinct colors in each band */
296 redcolors = greencolors = bluecolors = 1;
297 for (pixval = 1; pixval; pixval <<= 1)
299 if (pixval & visual->red_mask)
301 if (pixval & visual->green_mask)
303 if (pixval & visual->blue_mask)
307 /* consistency check */
308 if (redcolors > visual->map_entries ||
309 greencolors > visual->map_entries ||
310 bluecolors > visual->map_entries)
311 Error(ERR_WARN, "inconsistency in color information");
313 redstep = 256 / redcolors;
314 greenstep = 256 / greencolors;
315 bluestep = 256 / bluecolors;
316 redbottom = greenbottom = bluebottom = 0;
317 redtop = greentop = bluetop = 0;
319 for (a = 0; a < visual->map_entries; a++)
322 redtop = redbottom + redstep;
323 if (greenbottom < 256)
324 greentop = greenbottom + greenstep;
325 if (bluebottom < 256)
326 bluetop = bluebottom + bluestep;
328 xcolor.red = (redtop - 1) << 8;
329 xcolor.green = (greentop - 1) << 8;
330 xcolor.blue = (bluetop - 1) << 8;
331 if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
333 /* if an allocation fails for a DirectColor default visual then
334 we should create a private colormap and try again. */
336 if ((visual->class == DirectColor) &&
337 (visual == DefaultVisual(display, screen)))
339 global_cmap = XCopyColormapAndFree(display, global_cmap);
340 ximageinfo->cmap = global_cmap;
346 /* something completely unexpected happened */
348 fprintf(stderr, "Image_to_Pixmap: XAllocColor failed on a TrueColor/Directcolor visual\n");
358 /* fill in pixel values for each band at this intensity */
360 while ((redbottom < 256) && (redbottom < redtop))
361 redvalue[redbottom++] = xcolor.pixel & visual->red_mask;
362 while ((greenbottom < 256) && (greenbottom < greentop))
363 greenvalue[greenbottom++] = xcolor.pixel & visual->green_mask;
364 while ((bluebottom < 256) && (bluebottom < bluetop))
365 bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask;
373 ximageinfo->cmap = global_cmap;
375 for (a = 0; a < MAX_COLORS; a++)
382 if (!image->rgb.color_used[a])
385 xcolor.red = *(image->rgb.red + a);
386 xcolor.green = *(image->rgb.green + a);
387 xcolor.blue = *(image->rgb.blue + a);
389 /* look if this color already exists in our colormap */
390 if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
395 Error(ERR_RETURN, "switching to private colormap");
397 /* we just filled up the default colormap -- get a private one
398 which contains all already allocated colors */
400 global_cmap = XCopyColormapAndFree(display, global_cmap);
401 ximageinfo->cmap = global_cmap;
404 /* allocate the rest of the color cells read/write */
406 (Pixel *)checked_malloc(sizeof(Pixel) * NOFLASH_COLORS);
407 for (i = 0; i < NOFLASH_COLORS; i++)
408 if (!XAllocColorCells(display, global_cmap, FALSE, NULL, 0,
409 global_cmap_index + i, 1))
411 num_cmap_entries = free_cmap_entries = i;
414 printf("We've got %d free colormap entries.\n", free_cmap_entries);
417 /* to minimize colormap flashing, copy default colors and try
418 to keep them as near as possible to the old values */
420 for (i = 0; i < num_cmap_entries; i++)
422 xcolor2.pixel = *(global_cmap_index + i);
423 XQueryColor(display, DefaultColormap(display, screen), &xcolor2);
424 XStoreColor(display, global_cmap, &xcolor2);
425 xcolor_private[xcolor2.pixel] = xcolor2;
426 colorcell_used[xcolor2.pixel] = FALSE;
429 /* now we have the default colormap private: all colors we
430 successfully allocated so far are read-only, which is okay,
431 because we don't want to change them anymore -- if we need
432 an existing color again, we get it by XAllocColor; all other
433 colors are read/write and we can set them by XStoreColor,
434 but we will try to overwrite those color cells with our new
435 color which are as close as possible to our new color */
438 /* look for an existing default color close the one we want */
445 for (i = num_cmap_entries - 1; i >= 0; i--)
447 xcolor2.pixel = *(global_cmap_index + i);
448 xcolor2 = xcolor_private[xcolor2.pixel];
450 if (colorcell_used[xcolor2.pixel])
453 if ((xcolor.red & mask) == (xcolor2.red & mask) &&
454 (xcolor.green & mask) == (xcolor2.green & mask) &&
455 (xcolor.blue & mask) == (xcolor2.blue & mask))
458 printf("replacing color cell %ld with a close color\n",
469 mask = (mask << 1) & 0xffff;
472 if (!color_found) /* no more free color cells */
474 SetError(error, "cannot allocate enough color cells");
478 xcolor.pixel = xcolor2.pixel;
479 xcolor_private[xcolor.pixel] = xcolor;
480 colorcell_used[xcolor.pixel] = TRUE;
481 XStoreColor(display, ximageinfo->cmap, &xcolor);
485 *(ximageinfo->index + a) = xcolor.pixel;
489 printf("still %d free colormap entries\n", free_cmap_entries);
492 ximageinfo->no = a; /* number of pixels allocated for this image */
496 Error(ERR_RETURN,"DirectColor, TrueColor or PseudoColor display needed");
497 SetError(error, "display class not supported");
503 debug_print_timestamp(2, " ALLOCATING IMAGE COLORS: ");
506 /* create XImage from internal image structure and convert it to Pixmap */
508 display_bits_per_pixel = bitsPerPixelAtDepth(display, screen, depth);
509 display_bytes_per_pixel = (display_bits_per_pixel + 7) / 8;
511 ximage = XCreateImage(display, visual, depth, ZPixmap,
512 0, NULL, image->width, image->height,
513 8, image->width * display_bytes_per_pixel);
515 checked_malloc(image->width * image->height * display_bytes_per_pixel);
516 ximage->byte_order = MSBFirst;
518 src_ptr = image->data;
519 dst_ptr = (byte *)ximage->data;
521 switch (visual->class)
532 for (y = 0; y < image->height; y++) /* general case */
534 for (x = 0; x < image->width; x++)
538 redvalue[image->rgb.red[pixval] >> 8] |
539 greenvalue[image->rgb.green[pixval] >> 8] |
540 bluevalue[image->rgb.blue[pixval] >> 8];
541 value_to_memory(pixval, dst_ptr, display_bytes_per_pixel);
542 dst_ptr += display_bytes_per_pixel;
549 case IMAGETYPE_TRUECOLOR:
551 for (y = 0; y < image->height; y++) /* general case */
553 for (x = 0; x < image->width; x++)
555 pixval = memory_to_value(src_ptr, image->bytes_per_pixel);
557 redvalue[TRUECOLOR_RED(pixval)] |
558 greenvalue[TRUECOLOR_GREEN(pixval)] |
559 bluevalue[TRUECOLOR_BLUE(pixval)];
560 value_to_memory(pixval, dst_ptr, display_bytes_per_pixel);
561 src_ptr += image->bytes_per_pixel;
562 dst_ptr += display_bytes_per_pixel;
570 Error(ERR_RETURN, "RGB or TrueColor image needed");
571 SetError(error, "image type not supported");
581 if (display_bytes_per_pixel == 1) /* special case */
583 for (y = 0; y < image->height; y++)
584 for (x = 0; x < image->width; x++)
585 *dst_ptr++ = ximageinfo->index[c + *src_ptr++];
587 else /* general case */
589 for (y = 0; y < image->height; y++)
591 for (x = 0; x < image->width; x++)
593 value_to_memory(ximageinfo->index[c + *src_ptr++],
594 dst_ptr, display_bytes_per_pixel);
595 dst_ptr += display_bytes_per_pixel;
604 Error(ERR_RETURN,"DirectColor, TrueColor or PseudoColor display needed");
605 SetError(error, "display class not supported");
612 free((byte *)redvalue);
613 free((byte *)greenvalue);
614 free((byte *)bluevalue);
618 debug_print_timestamp(2, " CONVERTING IMAGE TO XIMAGE:");
621 ximageinfo->pixmap = XCreatePixmap(display, window,
622 ximage->width, ximage->height,
625 XPutImage(ximageinfo->display, ximageinfo->pixmap, gc,
626 ximage, 0, 0, 0, 0, ximage->width, ximage->height);
628 X11DestroyImage(ximage);
634 -----------------------------------------------------------------------------
637 Important note: The scaling code currently only supports scaling of the image
638 up or down by a power of 2 -- other scaling factors currently not supported!
639 -----------------------------------------------------------------------------
642 void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap,
643 int src_width, int src_height,
644 int dst_width, int dst_height)
646 XImage *src_ximage, *dst_ximage;
647 byte *src_ptr, *dst_ptr;
652 boolean scale_down = (src_width > dst_width);
655 int zoom_factor = src_width / dst_width; /* currently very limited! */
657 int row_skip, col_skip;
661 zoom_factor = src_width / dst_width;
663 /* adjust source image size to integer multiple of destination size */
664 src_width = dst_width * zoom_factor;
665 src_height = dst_height * zoom_factor;
669 zoom_factor = dst_width / src_width;
671 /* no adjustment needed when scaling up (some pixels may be left blank) */
674 /* copy source pixmap to temporary image */
675 if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
676 AllPlanes, ZPixmap)) == NULL)
677 Error(ERR_EXIT, "ZoomPixmap(): XGetImage() failed");
679 bits_per_pixel = src_ximage->bits_per_pixel;
680 bytes_per_pixel = (bits_per_pixel + 7) / 8;
682 if ((dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap,
683 0, NULL, dst_width, dst_height,
684 8, dst_width * bytes_per_pixel)) == NULL)
685 Error(ERR_EXIT, "ZoomPixmap(): XCreateImage() failed");
688 checked_malloc(dst_width * dst_height * bytes_per_pixel);
689 dst_ximage->byte_order = src_ximage->byte_order;
691 src_ptr = (byte *)src_ximage->data;
692 dst_ptr = (byte *)dst_ximage->data;
696 col_skip = (zoom_factor - 1) * bytes_per_pixel;
697 row_skip = col_skip * src_width;
699 /* scale image down by scaling factor 'zoom_factor' */
700 for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip)
701 for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip)
702 for (i = 0; i < bytes_per_pixel; i++)
703 *dst_ptr++ = *src_ptr++;
707 row_skip = src_width * bytes_per_pixel;
710 printf("::: %d, %d -> %d, %d [%d / %d]\n[%ld -> %ld (%ld)] [%ld -> %ld (%ld)]\n",
711 src_width, src_height,
712 dst_width, dst_height,
713 zoom_factor, bytes_per_pixel,
715 src_ptr + src_width * src_height * bytes_per_pixel,
716 src_width * src_height * bytes_per_pixel,
718 dst_ptr + dst_width * dst_height * bytes_per_pixel,
719 dst_width * dst_height * bytes_per_pixel);
723 for (i = 0; i < src_width * src_height * bytes_per_pixel;
726 byte x = *(byte *)(src_ptr + i);
728 printf("::: %d ...\n", i);
736 /* scale image up by scaling factor 'zoom_factor' */
737 for (y = 0; y < src_height; y++)
739 for (yy = 0; yy < zoom_factor; yy++)
745 printf("::: [%d -> %ld / %ld]\n", y, src_ptr, dst_ptr);
748 for (x = 0; x < src_width; x++)
750 for (xx = 0; xx < zoom_factor; xx++)
751 for (i = 0; i < bytes_per_pixel; i++)
753 *dst_ptr++ = *(src_ptr + i);
764 /* copy scaled image to destination pixmap */
765 XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0,
766 dst_width, dst_height);
768 /* free temporary images */
769 X11DestroyImage(src_ximage);
770 X11DestroyImage(dst_ximage);
773 void freeXImage(Image *image, XImageInfo *ximageinfo)
775 if (ximageinfo->index != NULL && ximageinfo->no > 0)
776 XFreeColors(ximageinfo->display, ximageinfo->cmap, ximageinfo->index,
778 /* this ^^^^^^^^^^^^^^ is wrong, because the used color cells
779 * are somewhere between 0 and MAX_COLORS; there are indeed 'ximageinfo->no'
780 * used color cells, but they are not at array position 0 - 'ximageinfo->no'
786 int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
787 Pixmap *pixmap, Pixmap *pixmap_mask)
790 XImageInfo *ximageinfo;
796 debug_print_timestamp(2, NULL); /* initialize timestamp function */
799 /* read the graphic file in PCX format to image structure */
800 if ((image = Read_PCX_to_Image(filename)) == NULL)
804 printf("%s:\n", filename);
805 debug_print_timestamp(2, " READING PCX FILE TO IMAGE: ");
808 screen = DefaultScreen(display);
809 visual = DefaultVisual(display, screen);
810 depth = DefaultDepth(display, screen);
812 /* convert image structure to X11 Pixmap */
813 if (!(ximageinfo = Image_to_Pixmap(display, screen, visual,
814 window, gc, depth, image)))
818 return PCX_OtherError;
821 /* if a private colormap has been created, install it */
822 if (ximageinfo->cmap != DefaultColormap(display, screen))
823 XSetWindowColormap(display, window, ximageinfo->cmap);
826 debug_print_timestamp(2, " CONVERTING IMAGE TO PIXMAP:");
829 /* create clip mask for the image */
830 ximageinfo->pixmap_mask = Image_to_Mask(image, display, window);
833 debug_print_timestamp(2, " CONVERTING IMAGE TO MASK: ");
836 *pixmap = ximageinfo->pixmap;
837 *pixmap_mask = ximageinfo->pixmap_mask;
839 /* free generic image and ximageinfo after native Pixmap has been created */
846 #endif /* PLATFORM_UNIX */
847 #endif /* TARGET_X11 */
850 /* ========================================================================= */
851 /* PLATFORM INDEPENDENT IMAGE FUNCTIONS */
852 /* ========================================================================= */
856 char *source_filename;
860 boolean contains_small_images;
862 typedef struct ImageInfo ImageInfo;
864 static struct ArtworkListInfo *image_info = NULL;
866 static void *Load_PCX(char *filename)
871 printf("loading PCX file '%s'\n", filename);
874 img_info = checked_calloc(sizeof(ImageInfo));
876 if ((img_info->bitmap = LoadImage(filename)) == NULL)
878 Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s",
879 filename, GetError());
884 img_info->source_filename = getStringCopy(filename);
886 img_info->contains_small_images = FALSE;
891 static void FreeImage(void *ptr)
893 ImageInfo *image = (ImageInfo *)ptr;
899 FreeBitmap(image->bitmap);
901 if (image->source_filename)
902 free(image->source_filename);
907 int getImageListSize()
909 return (image_info->num_file_list_entries +
910 image_info->num_dynamic_file_list_entries);
913 struct FileInfo *getImageListEntry(int pos)
915 int num_list_entries = image_info->num_file_list_entries;
916 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
918 return (pos < num_list_entries ? &image_info->file_list[list_pos] :
919 &image_info->dynamic_file_list[list_pos]);
922 static ImageInfo *getImageInfoEntryFromImageID(int pos)
924 int num_list_entries = image_info->num_file_list_entries;
925 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
926 ImageInfo **img_info =
927 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
928 image_info->dynamic_artwork_list);
930 return img_info[list_pos];
933 Bitmap *getBitmapFromImageID(int pos)
936 int num_list_entries = image_info->num_file_list_entries;
937 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
938 ImageInfo **img_info =
939 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
940 image_info->dynamic_artwork_list);
942 return (img_info[list_pos] != NULL ? img_info[list_pos]->bitmap : NULL);
944 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
946 return (img_info != NULL ? img_info->bitmap : NULL);
950 char *getTokenFromImageID(int graphic)
953 /* !!! this does not work for dynamic artwork (crash!) !!! */
954 struct FileInfo *file_list = (struct FileInfo *)image_info->file_list;
956 return file_list[graphic].token;
958 struct FileInfo *file_list = getImageListEntry(graphic);
960 return (file_list != NULL ? file_list->token : NULL);
964 int getImageIDFromToken(char *token)
966 struct FileInfo *file_list = image_info->file_list;
967 int num_list_entries = image_info->num_file_list_entries;
970 for (i = 0; i < num_list_entries; i++)
971 if (strcmp(file_list[i].token, token) == 0)
977 char *getImageConfigFilename()
979 return getCustomArtworkConfigFilename(image_info->type);
982 int getImageListPropertyMappingSize()
984 return image_info->num_property_mapping_entries;
987 struct PropertyMapping *getImageListPropertyMapping()
989 return image_info->property_mapping;
992 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
993 struct ConfigTypeInfo *config_suffix_list,
994 char **base_prefixes, char **ext1_suffixes,
995 char **ext2_suffixes, char **ext3_suffixes,
996 char **ignore_tokens)
1000 image_info = checked_calloc(sizeof(struct ArtworkListInfo));
1001 image_info->type = ARTWORK_TYPE_GRAPHICS;
1003 /* ---------- initialize file list and suffix lists ---------- */
1005 image_info->num_file_list_entries = num_file_list_entries;
1006 image_info->num_dynamic_file_list_entries = 0;
1008 image_info->file_list =
1009 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
1010 num_file_list_entries);
1011 image_info->dynamic_file_list = NULL;
1013 image_info->num_suffix_list_entries = 0;
1014 for (i = 0; config_suffix_list[i].token != NULL; i++)
1015 image_info->num_suffix_list_entries++;
1017 image_info->suffix_list = config_suffix_list;
1019 /* ---------- initialize base prefix and suffixes lists ---------- */
1021 image_info->num_base_prefixes = 0;
1022 for (i = 0; base_prefixes[i] != NULL; i++)
1023 image_info->num_base_prefixes++;
1025 image_info->num_ext1_suffixes = 0;
1026 for (i = 0; ext1_suffixes[i] != NULL; i++)
1027 image_info->num_ext1_suffixes++;
1029 image_info->num_ext2_suffixes = 0;
1030 for (i = 0; ext2_suffixes[i] != NULL; i++)
1031 image_info->num_ext2_suffixes++;
1033 image_info->num_ext3_suffixes = 0;
1034 for (i = 0; ext3_suffixes[i] != NULL; i++)
1035 image_info->num_ext3_suffixes++;
1037 image_info->num_ignore_tokens = 0;
1038 for (i = 0; ignore_tokens[i] != NULL; i++)
1039 image_info->num_ignore_tokens++;
1041 image_info->base_prefixes = base_prefixes;
1042 image_info->ext1_suffixes = ext1_suffixes;
1043 image_info->ext2_suffixes = ext2_suffixes;
1044 image_info->ext3_suffixes = ext3_suffixes;
1045 image_info->ignore_tokens = ignore_tokens;
1047 image_info->num_property_mapping_entries = 0;
1049 image_info->property_mapping = NULL;
1051 /* ---------- initialize artwork reference and content lists ---------- */
1053 image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *);
1055 image_info->artwork_list =
1056 checked_calloc(num_file_list_entries * sizeof(ImageInfo *));
1057 image_info->dynamic_artwork_list = NULL;
1059 image_info->content_list = NULL;
1061 /* ---------- initialize artwork loading/freeing functions ---------- */
1063 image_info->load_artwork = Load_PCX;
1064 image_info->free_artwork = FreeImage;
1067 void ReloadCustomImages()
1070 printf("DEBUG: reloading images '%s' ...\n", artwork.gfx_current_identifier);
1073 LoadArtworkConfig(image_info);
1074 ReloadCustomArtworkList(image_info);
1077 void CreateImageWithSmallImages(int pos)
1079 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
1081 if (img_info == NULL || img_info->contains_small_images)
1084 CreateBitmapWithSmallBitmaps(img_info->bitmap);
1086 img_info->contains_small_images = TRUE;
1089 printf("CreateImageWithSmallImages: '%s' done\n", img_info->source_filename);
1093 void FreeAllImages()
1095 FreeCustomArtworkLists(image_info);