]> git.saurik.com Git - wxWidgets.git/blob - src/gdk_imlib/utils.c
GTK
[wxWidgets.git] / src / gdk_imlib / utils.c
1 #define _GNU_SOURCE
2
3 #include "gdk_imlib.h"
4 #include "gdk_imlib_private.h"
5
6 void
7 gcalc_map_tables(GdkImlibImage * im)
8 {
9 int i;
10 double g, b, c, ii, v;
11
12 if (!im)
13 return;
14
15 g = ((double)im->mod.gamma) / 256;
16 b = ((double)im->mod.brightness) / 256;
17 c = ((double)im->mod.contrast) / 256;
18 if (g < 0.01)
19 g = 0.01;
20
21 for (i = 0; i < 256; i++)
22 {
23 ii = ((double)i) / 256;
24 v = ((ii - 0.5) * c) + 0.5 + (b - 1);
25 if (v > 0)
26 v = pow(((ii - 0.5) * c) + 0.5 + (b - 1), 1 / g) * 256;
27 else
28 v = 0;
29 if (v > 255)
30 v = 255;
31 else if (v < 0)
32 v = 0;
33 im->rmap[i] = (unsigned char)v;
34 im->gmap[i] = (unsigned char)v;
35 im->bmap[i] = (unsigned char)v;
36 }
37 g = ((double)im->rmod.gamma) / 256;
38 b = ((double)im->rmod.brightness) / 256;
39 c = ((double)im->rmod.contrast) / 256;
40 if (g < 0.01)
41 g = 0.01;
42
43 for (i = 0; i < 256; i++)
44 {
45 ii = ((double)im->rmap[i]) / 256;
46 v = ((ii - 0.5) * c) + 0.5 + (b - 1);
47 if (v > 0)
48 v = pow(((ii - 0.5) * c) + 0.5 + (b - 1), 1 / g) * 256;
49 else
50 v = 0;
51 if (v > 255)
52 v = 255;
53 else if (v < 0)
54 v = 0;
55 im->rmap[i] = (unsigned char)v;
56 }
57 g = ((double)im->gmod.gamma) / 256;
58 b = ((double)im->gmod.brightness) / 256;
59 c = ((double)im->gmod.contrast) / 256;
60 if (g < 0.01)
61 g = 0.01;
62
63 for (i = 0; i < 256; i++)
64 {
65 ii = ((double)im->gmap[i]) / 256;
66 v = ((ii - 0.5) * c) + 0.5 + (b - 1);
67 if (v > 0)
68 v = pow(((ii - 0.5) * c) + 0.5 + (b - 1), 1 / g) * 256;
69 else
70 v = 0;
71 if (v > 255)
72 v = 255;
73 else if (v < 0)
74 v = 0;
75 im->gmap[i] = (unsigned char)v;
76 }
77 g = ((double)im->bmod.gamma) / 256;
78 b = ((double)im->bmod.brightness) / 256;
79 c = ((double)im->bmod.contrast) / 256;
80 if (g < 0.01)
81 g = 0.01;
82 for (i = 0; i < 256; i++)
83 {
84 ii = ((double)im->bmap[i]) / 256;
85 v = ((ii - 0.5) * c) + 0.5 + (b - 1);
86 if (v > 0)
87 v = pow(((ii - 0.5) * c) + 0.5 + (b - 1), 1 / g) * 256;
88 else
89 v = 0;
90 if (v > 255)
91 v = 255;
92 else if (v < 0)
93 v = 0;
94 im->bmap[i] = (unsigned char)v;
95 }
96 gdirty_pixmaps(im);
97 }
98
99 gint
100 gdk_imlib_load_file_to_pixmap(char *filename, GdkPixmap ** pmap, GdkBitmap ** mask)
101 {
102 GdkImlibImage *im;
103
104 im = gdk_imlib_load_image(filename);
105 if (!im)
106 {
107 if (pmap)
108 *pmap = NULL;
109 if (mask)
110 *mask = NULL;
111 return 0;
112 }
113 if (!gdk_imlib_render(im, im->rgb_width, im->rgb_height))
114 {
115 gdk_imlib_destroy_image(im);
116 if (pmap)
117 *pmap = NULL;
118 if (mask)
119 *mask = NULL;
120 return 0;
121 }
122 if (pmap)
123 *pmap = gdk_imlib_move_image(im);
124 if (mask)
125 *mask = gdk_imlib_move_mask(im);
126 gdk_imlib_destroy_image(im);
127 return 1;
128 }
129
130 void
131 gdk_imlib_set_image_modifier(GdkImlibImage * im, GdkImlibColorModifier * mod)
132 {
133 if (!im || !mod)
134 return;
135 im->mod.gamma = mod->gamma;
136 im->mod.brightness = mod->brightness;
137 im->mod.contrast = mod->contrast;
138 gcalc_map_tables(im);
139 }
140
141 void
142 gdk_imlib_set_image_red_modifier(GdkImlibImage * im, GdkImlibColorModifier * mod)
143 {
144 if (!im || !mod)
145 return;
146 im->rmod.gamma = mod->gamma;
147 im->rmod.brightness = mod->brightness;
148 im->rmod.contrast = mod->contrast;
149 gcalc_map_tables(im);
150 }
151
152 void
153 gdk_imlib_set_image_green_modifier(GdkImlibImage * im, GdkImlibColorModifier * mod)
154 {
155 if (!im || !mod)
156 return;
157 im->gmod.gamma = mod->gamma;
158 im->gmod.brightness = mod->brightness;
159 im->gmod.contrast = mod->contrast;
160 gcalc_map_tables(im);
161 }
162
163 void
164 gdk_imlib_set_image_blue_modifier(GdkImlibImage * im, GdkImlibColorModifier * mod)
165 {
166 if (!im | !mod)
167 return;
168 im->bmod.gamma = mod->gamma;
169 im->bmod.brightness = mod->brightness;
170 im->bmod.contrast = mod->contrast;
171 gcalc_map_tables(im);
172 }
173
174 void
175 gdk_imlib_get_image_modifier(GdkImlibImage * im, GdkImlibColorModifier * mod)
176 {
177 if (!im || !mod)
178 return;
179 mod->gamma = im->mod.gamma;
180 mod->brightness = im->mod.brightness;
181 mod->contrast = im->mod.contrast;
182 gcalc_map_tables(im);
183 }
184
185 void
186 gdk_imlib_get_image_red_modifier(GdkImlibImage * im, GdkImlibColorModifier * mod)
187 {
188 if (!im || !mod)
189 return;
190 mod->gamma = im->rmod.gamma;
191 mod->brightness = im->rmod.brightness;
192 mod->contrast = im->rmod.contrast;
193 }
194
195 void
196 gdk_imlib_get_image_green_modifier(GdkImlibImage * im, GdkImlibColorModifier * mod)
197 {
198 if (!im || !mod)
199 return;
200 mod->gamma = im->gmod.gamma;
201 mod->brightness = im->gmod.brightness;
202 mod->contrast = im->gmod.contrast;
203 }
204
205 void
206 gdk_imlib_get_image_blue_modifier(GdkImlibImage * im, GdkImlibColorModifier * mod)
207 {
208 if (!im || !mod)
209 return;
210 mod->gamma = im->bmod.gamma;
211 mod->brightness = im->bmod.brightness;
212 mod->contrast = im->bmod.contrast;
213 }
214
215 void
216 gdk_imlib_set_image_red_curve(GdkImlibImage * im, unsigned char *mod)
217 {
218 int i;
219
220 if (!im || !mod)
221 return;
222 for (i = 0; i < 256; i++)
223 im->rmap[i] = mod[i];
224 gdirty_pixmaps(im);
225 im->mod.contrast = 257;
226 }
227
228 void
229 gdk_imlib_set_image_green_curve(GdkImlibImage * im, unsigned char *mod)
230 {
231 int i;
232
233 if (!im || !mod)
234 return;
235 for (i = 0; i < 256; i++)
236 im->gmap[i] = mod[i];
237 gdirty_pixmaps(im);
238 im->mod.contrast = 257;
239 }
240
241 void
242 gdk_imlib_set_image_blue_curve(GdkImlibImage * im, unsigned char *mod)
243 {
244 int i;
245
246 if (!im || !mod)
247 return;
248 for (i = 0; i < 256; i++)
249 im->bmap[i] = mod[i];
250 gdirty_pixmaps(im);
251 im->mod.contrast = 257;
252 }
253
254 void
255 gdk_imlib_get_image_red_curve(GdkImlibImage * im, unsigned char *mod)
256 {
257 int i;
258
259 if ((!im) || (!mod))
260 return;
261 for (i = 0; i < 256; i++)
262 mod[i] = im->rmap[i];
263 }
264
265 void
266 gdk_imlib_get_image_green_curve(GdkImlibImage * im, unsigned char *mod)
267 {
268 int i;
269
270 if (!im || !mod)
271 return;
272 for (i = 0; i < 256; i++)
273 mod[i] = im->gmap[i];
274 }
275
276 void
277 gdk_imlib_get_image_blue_curve(GdkImlibImage * im, unsigned char *mod)
278 {
279 int i;
280
281 if (!im || !mod)
282 return;
283 for (i = 0; i < 256; i++)
284 mod[i] = im->bmap[i];
285 }
286
287 void
288 gdk_imlib_apply_modifiers_to_rgb(GdkImlibImage * im)
289 {
290 int x, y;
291 unsigned char *ptr;
292
293 if (!im)
294 return;
295 ptr = im->rgb_data;
296 for (y = 0; y < im->rgb_height; y++)
297 {
298 for (x = 0; x < im->rgb_width; x++)
299 {
300 *ptr = im->rmap[*ptr];
301 ptr++;
302 *ptr = im->gmap[*ptr];
303 ptr++;
304 *ptr = im->bmap[*ptr];
305 ptr++;
306 }
307 }
308 im->mod.gamma = 256;
309 im->mod.brightness = 256;
310 im->mod.contrast = 256;
311 im->rmod.gamma = 256;
312 im->rmod.brightness = 256;
313 im->rmod.contrast = 256;
314 im->gmod.gamma = 256;
315 im->gmod.brightness = 256;
316 im->gmod.contrast = 256;
317 im->bmod.gamma = 256;
318 im->bmod.brightness = 256;
319 im->bmod.contrast = 256;
320 gcalc_map_tables(im);
321 gdirty_images(im);
322 gdirty_pixmaps(im);
323 }
324
325 void
326 gdk_imlib_crop_image(GdkImlibImage * im, gint x, gint y, gint w, gint h)
327 {
328 unsigned char *data;
329 int xx, yy, w3, w4;
330 unsigned char *ptr1, *ptr2;
331
332 if (!im)
333 return;
334 if (x < 0)
335 {
336 w += x;
337 x = 0;
338 }
339 if (y < 0)
340 {
341 h += y;
342 y = 0;
343 }
344 if (x >= im->rgb_width)
345 return;
346 if (y >= im->rgb_height)
347 return;
348 if (w <= 0)
349 return;
350 if (h <= 0)
351 return;
352 if (x + w > im->rgb_width)
353 w = im->rgb_width - x;
354 if (y + h > im->rgb_height)
355 h = im->rgb_height - y;
356 if (w <= 0)
357 return;
358 if (h <= 0)
359 return;
360
361 w3 = im->rgb_width * 3;
362 w4 = (im->rgb_width - w) * 3;
363 data = malloc(w * h * 3);
364 if (data == NULL)
365 return;
366 ptr1 = im->rgb_data + (y * w3) + (x * 3);
367 ptr2 = data;
368 for (yy = 0; yy < h; yy++)
369 {
370 for (xx = 0; xx < w; xx++)
371 {
372 *ptr2++ = *ptr1++;
373 *ptr2++ = *ptr1++;
374 *ptr2++ = *ptr1++;
375 }
376 ptr1 += w4;
377 }
378 free(im->rgb_data);
379 im->rgb_data = data;
380 if (im->border.left > x)
381 im->border.left = im->border.left - x;
382 else
383 im->border.left = 0;
384 if (im->border.top > y)
385 im->border.top = im->border.top - y;
386 else
387 im->border.top = 0;
388 if (im->rgb_width - im->border.right < x + w)
389 im->border.right = im->border.right - (im->rgb_width - (x + w));
390 else
391 im->border.right = 0;
392 if (im->rgb_height - im->border.bottom < y + h)
393 im->border.bottom = im->border.bottom - (im->rgb_height - (y + h));
394 else
395 im->border.bottom = 0;
396 im->rgb_width = w;
397 im->rgb_height = h;
398 gdirty_images(im);
399 gdirty_pixmaps(im);
400 }
401
402 void
403 gdk_imlib_changed_image(GdkImlibImage * im)
404 {
405 if (!im)
406 return;
407 gdirty_images(im);
408 gdirty_pixmaps(im);
409 }
410
411 void
412 gdk_imlib_apply_image(GdkImlibImage * im, GdkWindow * p)
413 {
414 GdkPixmap *pp, *mm;
415 int w, h;
416
417 if (!im || !p)
418 return;
419 gdk_window_get_size(p, &w, &h);
420 if (w <= 0 || h <= 0)
421 return;
422 gdk_imlib_render(im, w, h);
423 pp = gdk_imlib_move_image(im);
424 mm = gdk_imlib_move_mask(im);
425 gdk_window_set_back_pixmap(p, pp, 0);
426 if (mm)
427 gdk_window_shape_combine_mask(p, mm, 0, 0);
428 gdk_window_clear(p);
429 gdk_imlib_free_pixmap(pp);
430 }
431
432 void
433 gdk_imlib_paste_image(GdkImlibImage * im, GdkWindow * p, gint x, gint y, gint w, gint h)
434 {
435 GdkGC *gc;
436 GdkPixmap *pp, *mm;
437
438 if (!im || !p)
439 return;
440 if ((w <= 0) || (h <= 0))
441 return;
442 gc = gdk_gc_new(p);
443 gdk_imlib_render(im, w, h);
444 pp = gdk_imlib_move_image(im);
445 mm = gdk_imlib_move_mask(im);
446 if (mm)
447 {
448 gdk_gc_set_clip_mask(gc, mm);
449 gdk_gc_set_clip_origin(gc, x, y);
450 }
451 gdk_draw_pixmap(p, gc, pp, 0, 0, x, y, w, h);
452 gdk_imlib_free_pixmap(pp);
453 gdk_gc_destroy(gc);
454 }
455
456 void
457 gdk_imlib_paste_image_border(GdkImlibImage * im, GdkWindow * p, gint x, gint y, gint w, gint h)
458 {
459 GdkGC *gc;
460 GdkPixmap *pp, *mm;
461
462 if (!im)
463 return;
464
465 if (w <= 0 || h <= 0)
466 return;
467 gc = gdk_gc_new(p);
468 gdk_imlib_render(im, w, h);
469 pp = gdk_imlib_move_image(im);
470 mm = gdk_imlib_move_mask(im);
471 if (mm)
472 {
473 gdk_gc_set_clip_mask(gc, mm);
474 gdk_gc_set_clip_origin(gc, x, y);
475 }
476 if ((w <= (im->border.left + im->border.right)) ||
477 (h <= (im->border.top + im->border.bottom)))
478 gdk_draw_pixmap(p, gc, pp, 0, 0, x, y, w, h);
479 else
480 {
481 gdk_draw_pixmap(p, gc, pp, 0, 0, x, y, w, im->border.top);
482 gdk_draw_pixmap(p, gc, pp, 0, h - im->border.bottom,
483 x, y + (h - im->border.bottom),
484 w, im->border.bottom);
485 gdk_draw_pixmap(p, gc, pp, 0, im->border.top,
486 x, y + im->border.top,
487 im->border.left, h - (im->border.top + im->border.bottom));
488 gdk_draw_pixmap(p, gc, pp, w - im->border.right, h - im->border.bottom,
489 x + (w - im->border.right), y + (h - im->border.bottom),
490 im->border.right, h - (im->border.top + im->border.bottom));
491 }
492 gdk_imlib_free_pixmap(pp);
493 gdk_gc_destroy(gc);
494 }
495
496 void
497 gdk_imlib_flip_image_horizontal(GdkImlibImage * im)
498 {
499 unsigned char *ptr1, *ptr2, r, rr;
500 int x, y;
501 int w3;
502
503 if (!im)
504 return;
505 w3 = im->rgb_width * 3;
506 for (y = 0; y < im->rgb_height; y++)
507 {
508 ptr1 = im->rgb_data + (y * w3);
509 ptr2 = im->rgb_data + (y * w3) + w3 - 3;
510 for (x = 0; x < im->rgb_width >> 1; x++)
511 {
512 r = *ptr1;
513 rr = *ptr2;
514 *ptr2++ = r;
515 *ptr1++ = rr;
516
517 r = *ptr1;
518 rr = *ptr2;
519 *ptr2++ = r;
520 *ptr1++ = rr;
521
522 r = *ptr1;
523 rr = *ptr2;
524 *ptr2 = r;
525 *ptr1++ = rr;
526
527 ptr2 -= 5;
528 }
529 }
530 w3 = im->border.left;
531 im->border.left = im->border.right;
532 im->border.right = w3;
533 gdirty_images(im);
534 gdirty_pixmaps(im);
535 }
536
537 void
538 gdk_imlib_flip_image_vertical(GdkImlibImage * im)
539 {
540 unsigned char *ptr1, *ptr2, r, rr;
541 int x, y, yy;
542 int w3;
543
544 if (!im)
545 return;
546
547 w3 = im->rgb_width * 3;
548 for (yy = im->rgb_height - 1, y = 0; y < im->rgb_height >> 1; y++, yy--)
549 {
550 ptr1 = im->rgb_data + (y * w3);
551 ptr2 = im->rgb_data + (yy * w3);
552 for (x = 0; x < im->rgb_width; x++)
553 {
554 r = *ptr1;
555 rr = *ptr2;
556 *ptr2++ = r;
557 *ptr1++ = rr;
558 r = *ptr1;
559 rr = *ptr2;
560 *ptr2++ = r;
561 *ptr1++ = rr;
562 r = *ptr1;
563 rr = *ptr2;
564 *ptr2++ = r;
565 *ptr1++ = rr;
566 }
567 }
568 w3 = im->border.top;
569 im->border.top = im->border.bottom;
570 im->border.bottom = w3;
571 gdirty_images(im);
572 gdirty_pixmaps(im);
573 }
574
575 void
576 gdk_imlib_rotate_image(GdkImlibImage * im, gint d)
577 {
578 unsigned char *data;
579 int x, y, w3, w4;
580 unsigned char *ptr1, *ptr2;
581
582 if (!im)
583 return;
584 w3 = im->rgb_width * 3;
585 w4 = im->rgb_height * 3;
586
587 data = malloc(im->rgb_width * im->rgb_height * 3);
588 if (data == NULL)
589 return;
590
591 for (y = 0; y < im->rgb_height; y++)
592 {
593 ptr1 = im->rgb_data + (y * w3);
594 ptr2 = data + (y * 3);
595 for (x = 0; x < im->rgb_width; x++)
596 {
597 *ptr2++ = *ptr1++;
598 *ptr2++ = *ptr1++;
599 *ptr2 = *ptr1++;
600 ptr2 += w4 - 2;
601 }
602 }
603 free(im->rgb_data);
604 im->rgb_data = data;
605 w3 = im->rgb_width;
606 im->rgb_width = im->rgb_height;
607 im->rgb_height = w3;
608 w3 = im->border.top;
609 im->border.top = im->border.left;
610 im->border.left = w3;
611 w3 = im->border.bottom;
612 im->border.bottom = im->border.right;
613 im->border.right = w3;
614 gdirty_images(im);
615 gdirty_pixmaps(im);
616 }
617
618 GdkImlibImage *
619 gdk_imlib_create_image_from_data(unsigned char *data, unsigned char *alpha, gint w, gint h)
620 {
621 GdkImlibImage *im;
622 char s[128];
623
624 if (!data || w <= 0 || h <= 0)
625 return NULL;
626
627 im = malloc(sizeof(GdkImlibImage));
628 if (!im)
629 return NULL;
630
631 im->rgb_width = w;
632 im->rgb_height = h;
633 im->rgb_data = malloc(im->rgb_width * im->rgb_height * 3);
634 if (!im->rgb_data)
635 {
636 free(im);
637 return NULL;
638 }
639
640 memcpy(im->rgb_data, data, im->rgb_width * im->rgb_height * 3);
641 /* im->alpha_data=alpha; */
642 im->alpha_data = NULL;
643 g_snprintf(s, sizeof(s), "creat_%x_%x", (int)time(NULL), (int)rand());
644 im->filename = malloc(strlen(s) + 1);
645 if (im->filename)
646 strcpy(im->filename, s);
647 im->width = 0;
648 im->height = 0;
649 im->shape_color.r = -1;
650 im->shape_color.g = -1;
651 im->shape_color.b = -1;
652 im->border.left = 0;
653 im->border.right = 0;
654 im->border.top = 0;
655 im->border.bottom = 0;
656 im->pixmap = NULL;
657 im->shape_mask = NULL;
658 im->cache = 1;
659 im->mod.gamma = id->mod.gamma;
660 im->mod.brightness = id->mod.brightness;
661 im->mod.contrast = id->mod.contrast;
662 im->rmod.gamma = id->rmod.gamma;
663 im->rmod.brightness = id->rmod.brightness;
664 im->rmod.contrast = id->rmod.contrast;
665 im->gmod.gamma = id->gmod.gamma;
666 im->gmod.brightness = id->gmod.brightness;
667 im->gmod.contrast = id->gmod.contrast;
668 im->bmod.gamma = id->bmod.gamma;
669 im->bmod.brightness = id->bmod.brightness;
670 im->bmod.contrast = id->bmod.contrast;
671 if (id->cache.on_image)
672 gadd_image(im, im->filename);
673 gcalc_map_tables(im);
674 return im;
675 }
676
677 GdkImlibImage *
678 gdk_imlib_clone_image(GdkImlibImage * im)
679 {
680 GdkImlibImage *im2;
681 char *s;
682
683 if (!im)
684 return NULL;
685 im2 = malloc(sizeof(GdkImlibImage));
686 if (!im2)
687 return NULL;
688 im2->rgb_width = im->rgb_width;
689 im2->rgb_height = im->rgb_height;
690 im2->rgb_data = malloc(im2->rgb_width * im2->rgb_height * 3);
691 if (!im2->rgb_data)
692 {
693 free(im2);
694 return NULL;
695 }
696
697 memcpy(im2->rgb_data, im->rgb_data, im2->rgb_width * im2->rgb_height * 3);
698 if (im->alpha_data)
699 {
700 im2->alpha_data = malloc(im2->rgb_width * im2->rgb_height);
701 if (!im2->alpha_data)
702 {
703 free(im2->rgb_data);
704 free(im2);
705 return NULL;
706 }
707 memcpy(im2->alpha_data, im->alpha_data, im2->rgb_width * im2->rgb_height);
708 }
709 else
710 im2->alpha_data = NULL;
711 s = malloc(strlen(im->filename) + 320);
712 if (s)
713 {
714 g_snprintf(s, sizeof(s), "%s_%x_%x", im->filename, (int)time(NULL), (int)rand());
715 im2->filename = malloc(strlen(s) + 1);
716 if (im2->filename)
717 strcpy(im2->filename, s);
718 free(s);
719 }
720 else
721 im2->filename = NULL;
722 im2->width = 0;
723 im2->height = 0;
724 im2->shape_color.r = im->shape_color.r;
725 im2->shape_color.g = im->shape_color.g;
726 im2->shape_color.b = im->shape_color.b;
727 im2->border.left = im->border.left;
728 im2->border.right = im->border.right;
729 im2->border.top = im->border.top;
730 im2->border.bottom = im->border.bottom;
731 im2->pixmap = NULL;
732 im2->shape_mask = NULL;
733 im2->cache = 1;
734 im2->mod.gamma = im->mod.gamma;
735 im2->mod.brightness = im->mod.brightness;
736 im2->mod.contrast = im->mod.contrast;
737 im2->rmod.gamma = im->rmod.gamma;
738 im2->rmod.brightness = im->rmod.brightness;
739 im2->rmod.contrast = im->rmod.contrast;
740 im2->gmod.gamma = im->gmod.gamma;
741 im2->gmod.brightness = im->gmod.brightness;
742 im2->gmod.contrast = im->gmod.contrast;
743 im2->bmod.gamma = im->bmod.gamma;
744 im2->bmod.brightness = im->bmod.brightness;
745 im2->bmod.contrast = im->bmod.contrast;
746 gcalc_map_tables(im2);
747 if (id->cache.on_image)
748 gadd_image(im2, im2->filename);
749 return im2;
750 }
751
752 GdkImlibImage *
753 gdk_imlib_clone_scaled_image(GdkImlibImage * im, int w, int h)
754 {
755 GdkImlibImage *im2;
756 char *s;
757
758 if (!im || w <= 0 || h <= 0)
759 return NULL;
760
761 im2 = malloc(sizeof(GdkImlibImage));
762 if (!im2)
763 return NULL;
764 im2->rgb_width = w;
765 im2->rgb_height = h;
766 im2->rgb_data = malloc(w * h * 3);
767 if (!im2->rgb_data)
768 {
769 free(im2);
770 return NULL;
771 }
772 {
773 int x, y, *xarray;
774 unsigned char **yarray, *ptr, *ptr2, *ptr22;
775 int l, r, m, pos, inc, w3;
776
777 xarray = malloc(sizeof(int) * w);
778
779 if (!xarray)
780 {
781 fprintf(stderr, "ERROR: Cannot allocate X co-ord buffer\n");
782 free(im2->rgb_data);
783 free(im2);
784 return NULL;
785 }
786 yarray = malloc(sizeof(unsigned char *) * h);
787
788 if (!yarray)
789 {
790 fprintf(stderr, "ERROR: Cannot allocate Y co-ord buffer\n");
791 free(xarray);
792 free(im2->rgb_data);
793 free(im2);
794 return NULL;
795 }
796 ptr22 = im->rgb_data;
797 w3 = im->rgb_width * 3;
798 inc = 0;
799 if (w < im->border.left + im->border.right)
800 {
801 l = w >> 1;
802 r = w - l;
803 m = 0;
804 }
805 else
806 {
807 l = im->border.left;
808 r = im->border.right;
809 m = w - l - r;
810 }
811 if (m > 0)
812 inc = ((im->rgb_width - im->border.left - im->border.right) << 16) / m;
813 pos = 0;
814 if (l)
815 {
816 for (x = 0; x < l; x++)
817 {
818 xarray[x] = (pos >> 16) + (pos >> 16) + (pos >> 16);
819 pos += 0x10000;
820 }
821 }
822 if (m)
823 {
824 for (x = l; x < l + m; x++)
825 {
826 xarray[x] = (pos >> 16) + (pos >> 16) + (pos >> 16);
827 pos += inc;
828 }
829 }
830 pos = (im->rgb_width - r) << 16;
831 for (x = w - r; x < w; x++)
832 {
833 xarray[x] = (pos >> 16) + (pos >> 16) + (pos >> 16);
834 pos += 0x10000;
835 }
836
837 if (h < im->border.top + im->border.bottom)
838 {
839 l = h >> 1;
840 r = h - l;
841 m = 0;
842 }
843 else
844 {
845 l = im->border.top;
846 r = im->border.bottom;
847 m = h - l - r;
848 }
849 if (m > 0)
850 inc = ((im->rgb_height - im->border.top - im->border.bottom) << 16) / m;
851 pos = 0;
852 for (x = 0; x < l; x++)
853 {
854 yarray[x] = ptr22 + ((pos >> 16) * w3);
855 pos += 0x10000;
856 }
857 if (m)
858 {
859 for (x = l; x < l + m; x++)
860 {
861 yarray[x] = ptr22 + ((pos >> 16) * w3);
862 pos += inc;
863 }
864 }
865 pos = (im->rgb_height - r) << 16;
866 for (x = h - r; x < h; x++)
867 {
868 yarray[x] = ptr22 + ((pos >> 16) * w3);
869 pos += 0x10000;
870 }
871
872 ptr = im2->rgb_data;
873 for (y = 0; y < h; y++)
874 {
875 for (x = 0; x < w; x++)
876 {
877 ptr2 = yarray[y] + xarray[x];
878 *ptr++ = (int)*ptr2++;
879 *ptr++ = (int)*ptr2++;
880 *ptr++ = (int)*ptr2;
881 }
882 }
883 }
884 if (im->alpha_data)
885 {
886 im2->alpha_data = NULL;
887 /* yet to be filled in */
888 }
889 else
890 im2->alpha_data = NULL;
891
892 s = malloc(strlen(im->filename) + 320);
893 if (s)
894 {
895 g_snprintf(s, sizeof(s), "%s_%x_%x_%x_%x", im->filename, (int)time(NULL), w, h, (int)rand());
896 im2->filename = malloc(strlen(s) + 1);
897 if (im2->filename)
898 strcpy(im2->filename, s);
899 free(s);
900 }
901 else
902 im2->filename = NULL;
903 im2->width = 0;
904 im2->height = 0;
905 im2->shape_color.r = im->shape_color.r;
906 im2->shape_color.g = im->shape_color.g;
907 im2->shape_color.b = im->shape_color.b;
908 im2->border.left = im->border.left;
909 im2->border.right = im->border.right;
910 im2->border.top = im->border.top;
911 im2->border.bottom = im->border.bottom;
912 im2->pixmap = NULL;
913 im2->shape_mask = NULL;
914 im2->cache = 1;
915 im2->mod.gamma = im->mod.gamma;
916 im2->mod.brightness = im->mod.brightness;
917 im2->mod.contrast = im->mod.contrast;
918 im2->rmod.gamma = im->rmod.gamma;
919 im2->rmod.brightness = im->rmod.brightness;
920 im2->rmod.contrast = im->rmod.contrast;
921 im2->gmod.gamma = im->gmod.gamma;
922 im2->gmod.brightness = im->gmod.brightness;
923 im2->gmod.contrast = im->gmod.contrast;
924 im2->bmod.gamma = im->bmod.gamma;
925 im2->bmod.brightness = im->bmod.brightness;
926 im2->bmod.contrast = im->bmod.contrast;
927 gcalc_map_tables(im2);
928 if (id->cache.on_image)
929 gadd_image(im2, im2->filename);
930 return im2;
931 }
932
933 GdkImlibImage *
934 gdk_imlib_create_image_from_xpm_data(char **data)
935 {
936 GdkImlibImage *im;
937 unsigned char *ptr;
938 int pc, c, i, j, k, ncolors, cpp, comment, transp, quote,
939 context, len, count, done;
940 int w, h;
941 char *line, s[65536], tok[65536], col[65536];
942 XColor xcol;
943 struct _cmap
944 {
945 char str[8];
946 char transp;
947 int r, g, b;
948 }
949 *cmap;
950 int lookup[128][128];
951
952 if (!data)
953 return NULL;
954 im = malloc(sizeof(GdkImlibImage));
955 if (!im)
956 return NULL;
957 count = 0;
958 transp = 0;
959 done = 0;
960
961 c = ' ';
962 comment = 0;
963 quote = 0;
964 context = 0;
965 ptr = NULL;
966
967 while (!done)
968 {
969 line = data[count++];
970 if (context == 0)
971 {
972 /* Header */
973 sscanf(line, "%i %i %i %i", &w, &h, &ncolors, &cpp);
974 if (cpp > 7)
975 {
976 fprintf(stderr, "gdk_imlib ERROR: XPM data with characters per pixel > 7 not supported\n");
977 free(im);
978 return NULL;
979 }
980 if (w > 32767)
981 {
982 fprintf(stderr, "gdk_imlib ERROR: Image width > 32767 pixels for data\n");
983 free(im);
984 return NULL;
985 }
986 if (h > 32767)
987 {
988 fprintf(stderr, "gdk_imlib ERROR: Image height > 32767 pixels for data\n");
989 free(im);
990 return NULL;
991 }
992 cmap = malloc(sizeof(struct _cmap) * ncolors);
993
994 if (!cmap)
995 {
996 free(im);
997 return NULL;
998 }
999 im->rgb_width = w;
1000 im->rgb_height = h;
1001 im->rgb_data = malloc(im->rgb_width * im->rgb_height * 3);
1002 if (!im->rgb_data)
1003 {
1004 free(cmap);
1005 free(im);
1006 return NULL;
1007 }
1008 im->alpha_data = NULL;
1009 g_snprintf(s, sizeof(s), "creat_%x_%x", (int)time(NULL), (int)rand());
1010 im->filename = malloc(strlen(s) + 1);
1011 if (im->filename)
1012 strcpy(im->filename, s);
1013 im->width = 0;
1014 im->height = 0;
1015 im->border.left = 0;
1016 im->border.right = 0;
1017 im->border.top = 0;
1018 im->border.bottom = 0;
1019 im->pixmap = NULL;
1020 im->shape_mask = NULL;
1021 im->cache = 1;
1022 im->mod.gamma = id->mod.gamma;
1023 im->mod.brightness = id->mod.brightness;
1024 im->mod.contrast = id->mod.contrast;
1025 im->rmod.gamma = id->rmod.gamma;
1026 im->rmod.brightness = id->rmod.brightness;
1027 im->rmod.contrast = id->rmod.contrast;
1028 im->gmod.gamma = id->gmod.gamma;
1029 im->gmod.brightness = id->gmod.brightness;
1030 im->gmod.contrast = id->gmod.contrast;
1031 im->bmod.gamma = id->bmod.gamma;
1032 im->bmod.brightness = id->bmod.brightness;
1033 im->bmod.contrast = id->bmod.contrast;
1034 ptr = im->rgb_data;
1035 j = 0;
1036 context++;
1037 }
1038 else if (context == 1)
1039 {
1040 int colptr;
1041
1042 /* Color Table */
1043 if (j < ncolors)
1044 {
1045 tok[0] = 0;
1046 col[0] = 0;
1047 s[0] = 0;
1048 colptr = 0;
1049 len = strlen(line);
1050 strncpy(cmap[j].str, line, cpp);
1051 cmap[j].str[cpp] = 0;
1052 cmap[j].r = -1;
1053 cmap[j].transp = 0;
1054 for (k = cpp; k < len; k++)
1055 {
1056 if (line[k] != ' ')
1057 {
1058 sscanf(&line[k], "%65536s", s);
1059 k += strlen(s);
1060 if ((!strcmp(s, "m")) || (!strcmp(s, "s")) ||
1061 (!strcmp(s, "g4")) || (!strcmp(s, "g")) ||
1062 (!strcmp(s, "c")) || (k >= len))
1063 {
1064 if (k >= len)
1065 {
1066 int ls;
1067
1068 ls = strlen(s);
1069
1070 if (col[0] && colptr < sizeof(col))
1071 {
1072 strcpy(col + colptr, " ");
1073 colptr++;
1074 }
1075 if (colptr + ls <= sizeof(col))
1076 {
1077 strcpy(col + colptr, s);
1078 colptr += ls;
1079 }
1080
1081 }
1082 if (col[0])
1083 {
1084 if (!strcasecmp(col, "none"))
1085 {
1086 transp = 1;
1087 cmap[j].transp = 1;
1088 }
1089 else
1090 {
1091 if ((cmap[j].r < 0) ||
1092 (!strcmp(tok, "c")))
1093 {
1094 XParseColor(id->x.disp,
1095 id->x.root_cmap,
1096 col, &xcol);
1097 cmap[j].r = xcol.red >> 8;
1098 cmap[j].g = xcol.green >> 8;
1099 cmap[j].b = xcol.blue >> 8;
1100 if ((cmap[j].r == 255) &&
1101 (cmap[j].g == 0) &&
1102 (cmap[j].b == 255))
1103 cmap[j].r = 254;
1104 }
1105 }
1106 }
1107 if (strlen(s) < sizeof(tok))
1108 strcpy(tok, s);
1109 col[0] = 0;
1110 }
1111 else
1112 {
1113 int ls;
1114
1115 ls = strlen(s);
1116
1117 if (col[0] && colptr < sizeof(col))
1118 {
1119 strcpy(col + colptr, " ");
1120 colptr++;
1121 }
1122 if (ls + colptr < sizeof(col))
1123 {
1124 strcpy(col + colptr, s);
1125 colptr += ls;
1126 }
1127 }
1128 }
1129 }
1130 }
1131 j++;
1132 if (j >= ncolors)
1133 {
1134 if (cpp == 1)
1135 for (i = 0; i < ncolors; i++)
1136 lookup[cmap[i].str[0]][cmap[i].str[1]] = i;
1137 if (cpp == 2)
1138 for (i = 0; i < ncolors; i++)
1139 lookup[cmap[i].str[0]][cmap[i].str[1]] = i;
1140 context++;
1141 }
1142 }
1143 else
1144 {
1145 /* Image Data */
1146 i = 0;
1147 if (cpp == 0)
1148 {
1149 }
1150 else if (cpp == 1)
1151 {
1152 if (transp)
1153 {
1154 for (i = 0; ((i < 65536) && (line[i])); i++)
1155 {
1156 col[0] = line[i];
1157 if (cmap[lookup[col[0]][0]].transp)
1158 {
1159 *ptr++ = 255;
1160 *ptr++ = 0;
1161 *ptr++ = 255;
1162 }
1163 else
1164 {
1165 *ptr++ = (unsigned char)cmap[lookup[col[0]][0]].r;
1166 *ptr++ = (unsigned char)cmap[lookup[col[0]][0]].g;
1167 *ptr++ = (unsigned char)cmap[lookup[col[0]][0]].b;
1168 }
1169 }
1170 }
1171 else
1172 {
1173 for (i = 0; ((i < 65536) && (line[i])); i++)
1174 {
1175 col[0] = line[i];
1176 *ptr++ = (unsigned char)cmap[lookup[col[0]][0]].r;
1177 *ptr++ = (unsigned char)cmap[lookup[col[0]][0]].g;
1178 *ptr++ = (unsigned char)cmap[lookup[col[0]][0]].b;
1179 }
1180 }
1181 }
1182 else if (cpp == 2)
1183 {
1184 if (transp)
1185 {
1186 for (i = 0; ((i < 65536) && (line[i])); i++)
1187 {
1188 col[0] = line[i++];
1189 col[1] = line[i];
1190 if (cmap[lookup[col[0]][col[1]]].transp)
1191 {
1192 *ptr++ = 255;
1193 *ptr++ = 0;
1194 *ptr++ = 255;
1195 }
1196 else
1197 {
1198 *ptr++ = (unsigned char)cmap[lookup[col[0]][col[1]]].r;
1199 *ptr++ = (unsigned char)cmap[lookup[col[0]][col[1]]].g;
1200 *ptr++ = (unsigned char)cmap[lookup[col[0]][col[1]]].b;
1201 }
1202 }
1203 }
1204 else
1205 {
1206 for (i = 0; ((i < 65536) && (line[i])); i++)
1207 {
1208 col[0] = line[i++];
1209 col[1] = line[i];
1210 *ptr++ = (unsigned char)cmap[lookup[col[0]][col[1]]].r;
1211 *ptr++ = (unsigned char)cmap[lookup[col[0]][col[1]]].g;
1212 *ptr++ = (unsigned char)cmap[lookup[col[0]][col[1]]].b;
1213 }
1214 }
1215 }
1216 else
1217 {
1218 if (transp)
1219 {
1220 for (i = 0; ((i < 65536) && (line[i])); i++)
1221 {
1222 for (j = 0; j < cpp; j++, i++)
1223 {
1224 col[j] = line[i];
1225 }
1226 col[j] = 0;
1227 i--;
1228 for (j = 0; j < ncolors; j++)
1229 {
1230 if (!strcmp(col, cmap[j].str))
1231 {
1232 if (cmap[j].transp)
1233 {
1234 *ptr++ = 255;
1235 *ptr++ = 0;
1236 *ptr++ = 255;
1237 }
1238 else
1239 {
1240 *ptr++ = (unsigned char)cmap[j].r;
1241 *ptr++ = (unsigned char)cmap[j].g;
1242 *ptr++ = (unsigned char)cmap[j].b;
1243 }
1244 j = ncolors;
1245 }
1246 }
1247 }
1248 }
1249 else
1250 {
1251 for (i = 0; ((i < 65536) && (line[i])); i++)
1252 {
1253 for (j = 0; j < cpp; j++, i++)
1254 {
1255 col[j] = line[i];
1256 }
1257 col[j] = 0;
1258 i--;
1259 for (j = 0; j < ncolors; j++)
1260 {
1261 if (!strcmp(col, cmap[j].str))
1262 {
1263 *ptr++ = (unsigned char)cmap[j].r;
1264 *ptr++ = (unsigned char)cmap[j].g;
1265 *ptr++ = (unsigned char)cmap[j].b;
1266 j = ncolors;
1267 }
1268 }
1269 }
1270 }
1271 }
1272 }
1273 if ((ptr) && ((ptr - im->rgb_data) >= w * h * 3))
1274 done = 1;
1275 }
1276 if (!transp)
1277 {
1278 im->shape_color.r = -1;
1279 im->shape_color.g = -1;
1280 im->shape_color.b = -1;
1281 }
1282 else
1283 {
1284 im->shape_color.r = 255;
1285 im->shape_color.g = 0;
1286 im->shape_color.b = 255;
1287 }
1288 if (id->cache.on_image)
1289 gadd_image(im, im->filename);
1290 gcalc_map_tables(im);
1291 free(cmap);
1292 return im;
1293 }
1294
1295 gint
1296 gdk_imlib_data_to_pixmap(char **data, GdkPixmap ** pmap, GdkBitmap ** mask)
1297 {
1298 GdkImlibImage *im;
1299
1300 im = gdk_imlib_create_image_from_xpm_data(data);
1301 if (!im)
1302 {
1303 if (pmap)
1304 *pmap = NULL;
1305 if (mask)
1306 *mask = NULL;
1307 return 0;
1308 }
1309 if (!gdk_imlib_render(im, im->rgb_width, im->rgb_height))
1310 {
1311 gdk_imlib_destroy_image(im);
1312 if (pmap)
1313 *pmap = NULL;
1314 if (mask)
1315 *mask = NULL;
1316 return 0;
1317 }
1318 if (pmap)
1319 *pmap = gdk_imlib_move_image(im);
1320 if (mask)
1321 *mask = gdk_imlib_move_mask(im);
1322 gdk_imlib_kill_image(im);
1323 return 1;
1324 }
1325
1326 #include <signal.h>
1327 #include <sys/wait.h>
1328
1329 /*
1330 * Helper library
1331 */
1332
1333 static int hpid;
1334 void *oldpiper; /* actually sighandler_t but BSD uses sig_t. */
1335
1336 FILE *
1337 open_helper(const char *instring, const char *fn, const char *mode)
1338 {
1339 char buf[256]; /* This is safe since our input strings
1340
1341 *
1342 * * are bounded */
1343 static char *vec[16];
1344 char *p = strdup(instring);
1345 char *pp;
1346 char *ep;
1347 int vn = 0;
1348 int pid;
1349 FILE *fp = NULL;
1350 char *ofil = NULL;
1351 int ofd = -1;
1352
1353 int pfd[2];
1354
1355 if (p == NULL)
1356 return NULL;
1357
1358 if (strncmp(instring, "%Q", 2) == 0)
1359 {
1360 /*
1361 * Generate a quanting pipeline
1362 */
1363 fprintf(stderr, "Not currently supported: install ImageMagic.\n");
1364 return NULL;
1365 }
1366 /*
1367 * Ok split the instring on spaces and translate
1368 * %C %P %F and %s
1369 *
1370 * FIXME: We need to handle a format string that begins
1371 * %Q to indicate an 8bit quant in the pipeline first.
1372 */
1373
1374 pp = p;
1375
1376 while (vn < 15)
1377 {
1378 while (*pp && isspace(*pp))
1379 pp++;
1380 ep = pp;
1381 while (*ep && !isspace(*ep))
1382 ep++;
1383 if (*pp == 0)
1384 break;
1385 /* pp->ep is now the input string block */
1386 if (*ep)
1387 *ep++ = 0;
1388
1389 if (strcmp(pp, "%s") == 0)
1390 vec[vn] = strdup(fn);
1391 else if (strncmp(pp, "%P/", 3) == 0)
1392 {
1393 strcpy(buf, NETPBM_PATH);
1394 strcat(buf, pp + 2);
1395 if ((vec[vn] = strdup(buf)) == NULL)
1396 break;
1397 }
1398 else if (strncmp(pp, "%J", 3) == 0)
1399 {
1400 if ((vec[vn] = strdup(DJPEG_PROG)) == NULL)
1401 break;
1402 }
1403 else if (strncmp(pp, "%H", 3) == 0)
1404 {
1405 if ((vec[vn] = strdup(CJPEG_PROG)) == NULL)
1406 break;
1407 }
1408 else if (strncmp(pp, "%C/", 3) == 0)
1409 {
1410 strcpy(buf, CONVERT_PATH);
1411 strcat(buf, pp + 2);
1412 if ((vec[vn] = strdup(buf)) == NULL)
1413 break;
1414 }
1415 else if (strncmp(pp, ">%s", 3) == 0)
1416 {
1417 ofil = pp;
1418 vn++;
1419 pp = ep;
1420 continue;
1421 }
1422 else
1423 {
1424 if ((vec[vn] = strdup(pp)) == NULL)
1425 break;
1426 }
1427 vn++;
1428 pp = ep;
1429 }
1430
1431 vec[vn] = NULL;
1432
1433 if (pipe(pfd) == -1)
1434 goto oops;
1435
1436 if (*mode == 'r')
1437 {
1438 fp = fdopen(pfd[0], "r");
1439 if (fp == NULL)
1440 goto oops;
1441 }
1442 else if (*mode == 'w')
1443 {
1444 fp = fdopen(pfd[1], "w");
1445 if (fp == NULL)
1446 goto oops;
1447 }
1448 else
1449 goto oops;
1450
1451 if (ofil != NULL)
1452 if ((ofd = open(ofil, O_WRONLY | O_TRUNC | O_CREAT)) == -1)
1453 goto oops;
1454
1455 switch (pid = fork())
1456 {
1457 case -1:
1458 break;
1459 case 0:
1460 signal(SIGPIPE, SIG_DFL);
1461 if (*mode == 'r')
1462 dup2(pfd[1], 1);
1463 if (*mode == 'w')
1464 {
1465 dup2(pfd[0], 0);
1466 if (ofd != -1)
1467 {
1468 dup2(ofd, 1);
1469 close(1);
1470 }
1471 }
1472 close(pfd[0]);
1473 close(pfd[1]);
1474 execv(vec[0], vec);
1475 perror(vec[0]);
1476 /*
1477 * This MUST be _exit or we will hit the SIGPIPE
1478 * handler in ways we dont want. We want our parent
1479 * to flush the inherited file buffers not us.
1480 */
1481 _exit(1);
1482 default:
1483 hpid = pid;
1484
1485 if (ofd != -1)
1486 close(ofd);
1487 if (*mode == 'r')
1488 close(pfd[1]);
1489 else
1490 close(pfd[0]);
1491 }
1492 for (vn = 0; vn < 16; vn++)
1493 if (vec[vn])
1494 free(vec[vn]);
1495 oldpiper = signal(SIGPIPE, SIG_IGN);
1496 return fp;
1497
1498 oops:
1499 if (ofd != -1)
1500 close(ofd);
1501 if (fp)
1502 fclose(fp);
1503 for (vn = 0; vn < 16; vn++)
1504 if (vec[vn])
1505 free(vec[vn]);
1506 return NULL;
1507 }
1508
1509 int
1510 close_helper(FILE * fp)
1511 {
1512 int info;
1513
1514 fclose(fp);
1515 signal(SIGPIPE, oldpiper);
1516 waitpid(hpid, &info, 0);
1517 return WEXITSTATUS(info);
1518 }