File: images.c

package info (click to toggle)
wmdrawer 0.10.5-1.1
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd, squeeze, wheezy
  • size: 284 kB
  • ctags: 172
  • sloc: ansic: 1,813; makefile: 96
file content (245 lines) | stat: -rw-r--r-- 6,547 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/* 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);
}