rnd-20131212-1-src
[rocksndiamonds.git] / src / libgame / image.c
index 72e9580cc0ce1f09136302a1e157c126f99ac2b2..50dce1d713b0df9c49b12be304610cf013adecdb 100644 (file)
@@ -1,7 +1,7 @@
 /***********************************************************
 * Artsoft Retro-Game Library                               *
 *----------------------------------------------------------*
-* (c) 1994-2002 Artsoft Entertainment                      *
+* (c) 1994-2006 Artsoft Entertainment                      *
 *               Holger Schemel                             *
 *               Detmolder Strasse 189                      *
 *               33604 Bielefeld                            *
@@ -31,13 +31,6 @@ Image *newImage(unsigned int width, unsigned int height, unsigned int depth)
   unsigned int bytes_per_pixel = (depth + 7) / 8;
   int i;
 
-#if 0
-  if (depth > 8)
-    Error(ERR_EXIT, "images with more than 256 colors are not supported");
-
-  depth = 8;
-#endif
-
   image = checked_calloc(sizeof(Image));
   image->data = checked_calloc(width * height * bytes_per_pixel);
   image->width = width;
@@ -71,28 +64,28 @@ void freeImage(Image *image)
    note: the internal format is big endian */
 
 #define memory_to_value(ptr, len) (                                        \
-(len) == 1 ? (unsigned long)(                 *( (byte *)(ptr))         ) : \
-(len) == 2 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr))   ))<< 8)   \
-                         + (                 *(((byte *)(ptr))+1)      ) : \
-(len) == 3 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr))   ))<<16)   \
-                         + (((unsigned long)(*(((byte *)(ptr))+1)))<< 8)   \
-                         + (                 *(((byte *)(ptr))+2)      ) : \
-            (unsigned long)(((unsigned long)(*( (byte *)(ptr))   ))<<24)   \
-                         + (((unsigned long)(*(((byte *)(ptr))+1)))<<16)   \
-                         + (((unsigned long)(*(((byte *)(ptr))+2)))<< 8)   \
-                         + (                 *(((byte *)(ptr))+3)      ) )
+(len) == 1 ? (unsigned int)(                *( (byte *)(ptr))         ) : \
+(len) == 2 ? (unsigned int)(((unsigned int)(*( (byte *)(ptr))   ))<< 8)   \
+                        + (                *(((byte *)(ptr))+1)      ) : \
+(len) == 3 ? (unsigned int)(((unsigned int)(*( (byte *)(ptr))   ))<<16)   \
+                        + (((unsigned int)(*(((byte *)(ptr))+1)))<< 8)   \
+                        + (                *(((byte *)(ptr))+2)      ) : \
+            (unsigned int)(((unsigned int)(*( (byte *)(ptr))   ))<<24)   \
+                        + (((unsigned int)(*(((byte *)(ptr))+1)))<<16)   \
+                        + (((unsigned int)(*(((byte *)(ptr))+2)))<< 8)   \
+                        + (                *(((byte *)(ptr))+3)      ) )
 
 
 #define value_to_memory(value, ptr, len) (                             \
 (len) == 1 ? (*( (byte *)(ptr)   ) = ( value     ) ) :                 \
-(len) == 2 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>> 8),   \
+(len) == 2 ? (*( (byte *)(ptr)   ) = (((unsigned int)(value))>> 8),    \
              *(((byte *)(ptr))+1) = ( value     ) ) :                  \
-(len) == 3 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>16),   \
-             *(((byte *)(ptr))+1) = (((unsigned long)(value))>> 8),    \
+(len) == 3 ? (*( (byte *)(ptr)   ) = (((unsigned int)(value))>>16),    \
+             *(((byte *)(ptr))+1) = (((unsigned int)(value))>> 8),     \
              *(((byte *)(ptr))+2) = ( value     ) ) :                  \
-             (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>24),   \
-             *(((byte *)(ptr))+1) = (((unsigned long)(value))>>16),    \
-             *(((byte *)(ptr))+2) = (((unsigned long)(value))>> 8),    \
+             (*( (byte *)(ptr)   ) = (((unsigned int)(value))>>24),    \
+             *(((byte *)(ptr))+1) = (((unsigned int)(value))>>16),     \
+             *(((byte *)(ptr))+2) = (((unsigned int)(value))>> 8),     \
              *(((byte *)(ptr))+3) = ( value     ) ))
 
 static Pixmap Image_to_Mask(Image *image, Display *display, Window window)
@@ -392,7 +385,7 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
          if (!private_cmap)
          {
            if (options.verbose)
-             Error(ERR_RETURN, "switching to private colormap");
+             Error(ERR_INFO, "switching to private colormap");
 
            /* we just filled up the default colormap -- get a private one
               which contains all already allocated colors */
@@ -493,7 +486,7 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
       break;
   
     default:
-      Error(ERR_RETURN,"DirectColor, TrueColor or PseudoColor display needed");
+      Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed");
       SetError(error, "display class not supported");
 
       return NULL;
@@ -567,7 +560,7 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
        }
 
         default:
-         Error(ERR_RETURN, "RGB or TrueColor image needed");
+         Error(ERR_INFO, "RGB or TrueColor image needed");
          SetError(error, "image type not supported");
 
          return NULL;
@@ -601,7 +594,7 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
     }
 
     default:
-      Error(ERR_RETURN,"DirectColor, TrueColor or PseudoColor display needed");
+      Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed");
       SetError(error, "display class not supported");
 
       return NULL;
@@ -656,7 +649,11 @@ void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap,
 
   if (scale_down)
   {
+#if 1
+    zoom_factor = MIN(src_width / dst_width, src_height / dst_height);
+#else
     zoom_factor = src_width / dst_width;
+#endif
 
     /* adjust source image size to integer multiple of destination size */
     src_width  = dst_width  * zoom_factor;
@@ -664,7 +661,11 @@ void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap,
   }
   else
   {
+#if 1
+    zoom_factor = MIN(dst_width / src_width, dst_height / src_height);
+#else
     zoom_factor = dst_width / src_width;
+#endif
 
     /* no adjustment needed when scaling up (some pixels may be left blank) */
   }
@@ -718,7 +719,7 @@ void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap,
            for (i = 0; i < bytes_per_pixel; i++)
              *dst_ptr++ = *(src_ptr + i);
 
-         src_ptr += i;
+         src_ptr += bytes_per_pixel;
        }
       }
     }
@@ -820,18 +821,27 @@ struct ImageInfo
   int num_references;
 
   Bitmap *bitmap;
-  boolean contains_small_images;
+
+  int original_width;                  /* original image file width */
+  int original_height;                 /* original image file height */
+
+  boolean contains_small_images;       /* set after adding small images */
+  boolean scaled_up;                   /* set after scaling up */
 };
 typedef struct ImageInfo ImageInfo;
 
 static struct ArtworkListInfo *image_info = NULL;
 
+#if 1
+static void *Load_Image(char *filename)
+#else
 static void *Load_PCX(char *filename)
+#endif
 {
   ImageInfo *img_info;
 
 #if 0
-  printf("loading PCX file '%s'\n", filename);
+  printf("::: loading PCX file '%s'\n", filename);
 #endif
 
   img_info = checked_calloc(sizeof(ImageInfo));
@@ -846,7 +856,11 @@ static void *Load_PCX(char *filename)
 
   img_info->source_filename = getStringCopy(filename);
 
+  img_info->original_width  = img_info->bitmap->width;
+  img_info->original_height = img_info->bitmap->height;
+
   img_info->contains_small_images = FALSE;
+  img_info->scaled_up = FALSE;
 
   return img_info;
 }
@@ -873,7 +887,7 @@ int getImageListSize()
          image_info->num_dynamic_file_list_entries);
 }
 
-struct FileInfo *getImageListEntry(int pos)
+struct FileInfo *getImageListEntryFromImageID(int pos)
 {
   int num_list_entries = image_info->num_file_list_entries;
   int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
@@ -895,33 +909,30 @@ static ImageInfo *getImageInfoEntryFromImageID(int pos)
 
 Bitmap *getBitmapFromImageID(int pos)
 {
-#if 0
-  int num_list_entries = image_info->num_file_list_entries;
-  int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
-  ImageInfo **img_info =
-    (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
-                  image_info->dynamic_artwork_list);
-
-  return (img_info[list_pos] != NULL ? img_info[list_pos]->bitmap : NULL);
-#else
   ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
 
   return (img_info != NULL ? img_info->bitmap : NULL);
-#endif
 }
 
-char *getTokenFromImageID(int graphic)
+int getOriginalImageWidthFromImageID(int pos)
 {
-#if 0
-  /* !!! this does not work for dynamic artwork (crash!) !!! */
-  struct FileInfo *file_list = (struct FileInfo *)image_info->file_list;
+  ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
 
-  return file_list[graphic].token;
-#else
-  struct FileInfo *file_list = getImageListEntry(graphic);
+  return (img_info != NULL ? img_info->original_width : 0);
+}
+
+int getOriginalImageHeightFromImageID(int pos)
+{
+  ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+  return (img_info != NULL ? img_info->original_height : 0);
+}
+
+char *getTokenFromImageID(int graphic)
+{
+  struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
 
   return (file_list != NULL ? file_list->token : NULL);
-#endif
 }
 
 int getImageIDFromToken(char *token)
@@ -931,7 +942,7 @@ int getImageIDFromToken(char *token)
   int i;
 
   for (i = 0; i < num_list_entries; i++)
-    if (strcmp(file_list[i].token, token) == 0)
+    if (strEqual(file_list[i].token, token))
       return i;
 
   return -1;
@@ -1023,18 +1034,29 @@ void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
 
   /* ---------- initialize artwork loading/freeing functions ---------- */
 
+#if 1
+  image_info->load_artwork = Load_Image;
+#else
   image_info->load_artwork = Load_PCX;
+#endif
   image_info->free_artwork = FreeImage;
 }
 
 void ReloadCustomImages()
 {
 #if 0
-  printf("DEBUG: reloading images '%s' ...\n", artwork.gfx_current_identifier);
+  printf("::: reloading images '%s' ...\n", artwork.gfx_current_identifier);
 #endif
 
+  print_timestamp_init("ReloadCustomImages");
+
   LoadArtworkConfig(image_info);
+  print_timestamp_time("LoadArtworkConfig");
+
   ReloadCustomArtworkList(image_info);
+  print_timestamp_time("ReloadCustomArtworkList");
+
+  print_timestamp_done("ReloadCustomImages");
 }
 
 void CreateImageWithSmallImages(int pos, int zoom_factor)
@@ -1047,16 +1069,20 @@ void CreateImageWithSmallImages(int pos, int zoom_factor)
   CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor);
 
   img_info->contains_small_images = TRUE;
+  img_info->scaled_up = TRUE;
+}
 
-#if 0
-  if (zoom_factor)
-    printf("CreateImageWithSmallImages: '%s' zoomed by factor %d\n",
-          img_info->source_filename, zoom_factor);
-#endif
+void ScaleImage(int pos, int zoom_factor)
+{
+  ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
 
-#if 0
-  printf("CreateImageWithSmallImages: '%s' done\n", img_info->source_filename);
-#endif
+  if (img_info == NULL || img_info->scaled_up)
+    return;
+
+  if (zoom_factor != 1)
+    ScaleBitmap(img_info->bitmap, zoom_factor);
+
+  img_info->scaled_up = TRUE;
 }
 
 void FreeAllImages()