/* wmDrawer (c) 2002-2004 Valery Febvre <vfebvre@vfebvre.lautre.net>
 *
 * wmDrawer is a dock application (dockapp) which provides a
 * drawer (button bar) to launch applications from.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "types_defs.h"
#include "images.h"

#ifdef USE_GDKPIXBUF
#include <gdk-pixbuf/gdk-pixbuf-xlib.h>
#endif

#ifdef USE_GDKPIXBUF2
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
#endif

#ifdef USE_IMLIB
#include <Imlib.h>
ImlibData *id;
#endif

unsigned int imageLibIsInit = 0;
extern Display *display;
extern drawerConfig config;
extern int nbImagesPaths;

static int initImgLib (void) {
  if (imageLibIsInit == 0) {
#ifdef USE_GDKPIXBUF
    gdk_pixbuf_xlib_init (display, DefaultScreen (display));
    imageLibIsInit = 1;
#endif
#ifdef USE_GDKPIXBUF2
    g_type_init ();
    gdk_pixbuf_xlib_init (display, DefaultScreen (display));
    imageLibIsInit = 1;
#endif
#ifdef USE_IMLIB
    id = Imlib_init (display);
    imageLibIsInit = 1;
#endif
  }
  return imageLibIsInit;
}

static char *loadImageFromFile (char *file) {
#ifdef USE_GDKPIXBUF
  return (char *)gdk_pixbuf_new_from_file (file);
#endif
#ifdef USE_GDKPIXBUF2
  GError *error = NULL;
  return (char *)gdk_pixbuf_new_from_file (file, &error);
#endif
#ifdef USE_IMLIB
  return (char *)Imlib_load_image (id, file);
#endif
}

static char *loadImageFromXpmData (const char **data) {
#ifdef USE_GDKPIXBUF
  return (char *)gdk_pixbuf_new_from_xpm_data (data);
#endif
#ifdef USE_GDKPIXBUF2
  return (char *)gdk_pixbuf_new_from_xpm_data (data);
#endif
#ifdef USE_IMLIB
  return (char *)Imlib_create_image_from_xpm_data(id, (char **)data);
#endif
}

static int getImageWidth (char *img) {
#ifdef USE_GDKPIXBUF
  return gdk_pixbuf_get_width ((GdkPixbuf *)img);
#endif
#ifdef USE_GDKPIXBUF2
  return gdk_pixbuf_get_width ((GdkPixbuf *)img);
#endif
#ifdef USE_IMLIB
  return ((ImlibImage *)img)->rgb_width;
#endif
}

static int getImageHeight (char *img) {
#ifdef USE_GDKPIXBUF
  return gdk_pixbuf_get_height ((GdkPixbuf *)img);
#endif
#ifdef USE_GDKPIXBUF2
  return gdk_pixbuf_get_height ((GdkPixbuf *)img);
#endif
#ifdef USE_IMLIB
  return ((ImlibImage *)img)->rgb_height;
#endif
}

static char *scaleImage (char *img, int w, int h) {
#ifdef USE_GDKPIXBUF
  return (char *)gdk_pixbuf_scale_simple ((GdkPixbuf *)img,
					  w, h, GDK_INTERP_HYPER);
#endif
#ifdef USE_GDKPIXBUF2
  return (char *)gdk_pixbuf_scale_simple ((GdkPixbuf *)img,
					  w, h, GDK_INTERP_HYPER);
#endif
#ifdef USE_IMLIB
  return (char *)Imlib_clone_scaled_image (id, (ImlibImage *)img, w, h);
#endif
}

static void unrefImage (char *img) {
#ifdef USE_GDKPIXBUF
  gdk_pixbuf_unref ((GdkPixbuf *)img);
#endif
#ifdef USE_GDKPIXBUF2
  g_object_unref ((GdkPixbuf *)img);
#endif
#ifdef USE_IMLIB
  Imlib_kill_image (id, (ImlibImage *)img);
#endif
}

static void createPixmapAndMask (char *img, Pixmap *pixmap, Pixmap *mask) {
#ifdef USE_GDKPIXBUF
  gdk_pixbuf_xlib_render_pixmap_and_mask ((GdkPixbuf *)img, pixmap, mask, 128);
#endif
#ifdef USE_GDKPIXBUF2
  gdk_pixbuf_xlib_render_pixmap_and_mask ((GdkPixbuf *)img, pixmap, mask, 128);
#endif
#ifdef USE_IMLIB
  Imlib_render (id, (ImlibImage *)img, ((ImlibImage *)img)->rgb_width,
		((ImlibImage *)img)->rgb_height);
  *pixmap = Imlib_move_image (id, (ImlibImage *)img);
  *mask   = Imlib_move_mask (id, (ImlibImage *)img);
#endif
}

/*
  Create pixmap from image data and resize it to fit (dimW x dimH)
  img        : image data
  imgPix     : pixmap result
  imgMask    : mask result
  w          : pixmap width result
  h          : pixmap height result
  dimW       : max width allows
  dimH       : max height allows
  resizeMask : resize mask
*/
void createAndResizePixmap (char *img, Pixmap *imgPix, Pixmap *imgMask,
			    int *w, int *h, int dimW, int dimH,
			    unsigned long resizeMask) {
  char *imgScaled = NULL;

  *w = getImageWidth (img);
  *h = getImageHeight (img);

  if (resizeMask > 0) {
    /* resize smaller ? */
    if ((*w > dimW || *h > dimH) && ((resizeMask >> (RESIZE_SMALLER-1)) % 2)) {
      if ((float) *w / (float) dimW > (float) *h / (float) dimH) {
	*h = (int) ((*h * dimW) / *w);
	*w = dimW;
      }
      else {
	*w = (int) ((*w * dimH) / *h);
	*h = dimH;
      }
    }
    /* resize greater ? */
    if ((*w < dimW && *h < dimH) && ((resizeMask >> (RESIZE_GREATER-1)) % 2)) {
      if (*w >= *h) {
	*h = (int) ((*h * dimW) / *w);
	*w = dimW;
      }
      else {
	*w = (int) ((*w * dimH) / *h);
	*h = dimH;
      }
    }
    /* ready for resizing */
    imgScaled = scaleImage (img, *w, *h);
    unrefImage (img);
    img = imgScaled;
  }
  createPixmapAndMask (img, imgPix, imgMask);
  unrefImage (img);
}

int createPixmapFromFile (char *file, Pixmap *imgPix, Pixmap *imgMask,
			  int *w, int *h, int dimW, int dimH,
			  unsigned long resizeMask) {
  int i;
  char *img;
  char path[FILENAME_MAX];

  if (initImgLib() == 0) {
    printf ("%s warning: can't init image library.\n", PACKAGE);
    return 0;
  }
  if (file == NULL) {
    printf ("%s warning: a file path is (null)!\n", PACKAGE);
    return 0;
  }

  /* quick test for absolute path */
  img = loadImageFromFile (file);
  if (file[0] != '/' || img == NULL) {
    /* else try all paths */
    for (i=0; i<nbImagesPaths; i++) {
      sprintf(path, "%s/%s", config.imagesPaths[i], file);
      img = loadImageFromFile (path);
      if (img != NULL) break;
    }
  }
  if (img == NULL) {
    printf ("%s warning: can't load image %s\n", PACKAGE, file);
    return 0;
  }

  createAndResizePixmap (img, imgPix, imgMask, w, h, dimW, dimH, resizeMask);
  return 1;
}

void createPixmapFromData (const char **data, Pixmap *imgPix, Pixmap *imgMask,
			   int *w, int *h, int dimW, int dimH,
			   unsigned long resizeMask) {
  char *img;

  initImgLib();
  img = loadImageFromXpmData (data);
  createAndResizePixmap (img, imgPix, imgMask, w, h, dimW, dimH, resizeMask);
}
