~ubuntu-branches/debian/stretch/libmatchbox/stretch

« back to all changes in this revision

Viewing changes to .pc/50-implicit-decl/libmb/mbpixbuf.c

  • Committer: Package Import Robot
  • Author(s): gregor herrmann
  • Date: 2013-11-06 17:16:27 UTC
  • Revision ID: package-import@ubuntu.com-20131106171627-w3qnvnhl4eq16kh4
Tags: 1.9-osso8-3.1
* Non-maintainer upload.
* Fix "FTBFS: ld: dump-image.o: undefined reference to symbol
  'XOpenDisplay'":
  Add patches from Ubuntu / Daniel T Chen:
  + Fixed FTBFS:
    - added missing lib to link;
    - added preprocessor directive to fix implicit declaration
      warning that would have caused FTBFS on amd64 buildds.
  (Closes: #713701)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* mbpixbuf.c libmb
 
2
 *
 
3
 * Copyright (C) 2002 Matthew Allum
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
#define _GNU_SOURCE
 
22
 
 
23
#include <strings.h>
 
24
#include "mbpixbuf.h"
 
25
 
 
26
#define BYTE_ORD_24_RGB  0
 
27
#define BYTE_ORD_24_RBG  1
 
28
#define BYTE_ORD_24_BRG  2
 
29
#define BYTE_ORD_24_BGR  3
 
30
#define BYTE_ORD_24_GRB  4
 
31
#define BYTE_ORD_24_GBR  5
 
32
#define BYTE_ORD_32_ARGB 6
 
33
 
 
34
#define alpha_composite(composite, fg, alpha, bg) {               \
 
35
    ush temp;                                                     \
 
36
    if ((alpha) == 0)                                             \
 
37
       (composite) = (bg);                                        \
 
38
    else if ((alpha) == 255)                                      \
 
39
        (composite) = (fg);                                       \
 
40
    else {                                                        \
 
41
        temp = ((ush)(fg)*(ush)(alpha) +                          \
 
42
                (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128);  \
 
43
    (composite) = (ush)((temp + (temp >> 8)) >> 8);             } \
 
44
}
 
45
 
 
46
#ifdef WORDS_BIGENDIAN
 
47
#define  SHORT_FROM_2BYTES(p) ( *(p+1) | (*(p) << 8) )
 
48
#define  2BYTES_FROM_SHORT(p,s)                       \
 
49
     *((p)+1)   = (unsigned char) s;                  \
 
50
     *(p)       = (unsigned char) ((s >> 8) & 0xff);    
 
51
#else
 
52
#define  SHORT_FROM_2BYTES(p) ( *(p) | (*((p)+1) << 8) )
 
53
#define  BYTES_FROM_SHORT(p,s)                       \
 
54
     *(p)   = (unsigned char) s;                      \
 
55
     *((p)+1) = (unsigned char) ((s >> 8) & 0xff);    
 
56
#endif
 
57
 
 
58
#define internal_16bpp_pixel_to_rgb(p,r,g,b)           \
 
59
      {                                                \
 
60
         unsigned short s = SHORT_FROM_2BYTES(p);      \
 
61
         (r) = (( s & 0xf800) >> 8);                   \
 
62
         (g) = (( s & 0x07e0) >> 3);                   \
 
63
         (b) = (( s & 0x001f) << 3);                   \
 
64
      }
 
65
 
 
66
 
 
67
#define internal_rgb_to_16bpp_pixel(r,g,b,p)          \
 
68
     {                                                \
 
69
      unsigned short s = (  (((b) >> 3) & 0x001f) |   \
 
70
                            (((g) << 3) & 0x07e0) |   \
 
71
                            (((r) << 8) & 0xf800) );  \
 
72
      BYTES_FROM_SHORT(p,s)                           \
 
73
     }
 
74
 
 
75
#define internal_16bpp_pixel_next(p) \
 
76
      (p) += 2
 
77
 
 
78
#define IN_REGION(x,y,w,h) ( (x) > -1 && (x) < (w) && (y) > -1 && (y) <(h) ) 
 
79
 
 
80
typedef unsigned short ush;
 
81
 
 
82
#ifdef USE_PNG
 
83
static unsigned char* 
 
84
_load_png_file( const char *file, 
 
85
                int *width, int *height, int *has_alpha );
 
86
#endif
 
87
 
 
88
#ifdef USE_JPG
 
89
static unsigned char* 
 
90
_load_jpg_file( const char *file, 
 
91
                int *width, int *height, int *has_alpha );
 
92
#endif
 
93
 
 
94
static int _mbpb_trapped_error_code = 0;
 
95
static int (*_mbpb_old_error_handler) (Display *d, XErrorEvent *e);
 
96
 
 
97
static int
 
98
_mbpb_error_handler(Display     *display,
 
99
              XErrorEvent *error)
 
100
{
 
101
   _mbpb_trapped_error_code = error->error_code;
 
102
   return 0;
 
103
}
 
104
 
 
105
static void
 
106
_mbpb_trap_errors(void)
 
107
{
 
108
   _mbpb_trapped_error_code = 0;
 
109
   _mbpb_old_error_handler = XSetErrorHandler(_mbpb_error_handler);
 
110
}
 
111
 
 
112
static int
 
113
_mbpb_untrap_errors(void)
 
114
{
 
115
   XSetErrorHandler(_mbpb_old_error_handler);
 
116
   return _mbpb_trapped_error_code;
 
117
}
 
118
 
 
119
static int
 
120
_paletteAlloc(MBPixbuf *pb);
 
121
 
 
122
#ifdef USE_JPG
 
123
 
 
124
struct my_error_mgr {
 
125
  struct jpeg_error_mgr pub;    /* "public" fields */
 
126
 
 
127
  jmp_buf setjmp_buffer;        /* for return to caller */
 
128
};
 
129
 
 
130
typedef struct my_error_mgr * my_error_ptr;
 
131
 
 
132
void
 
133
_jpeg_error_exit (j_common_ptr cinfo)
 
134
{
 
135
  my_error_ptr myerr = (my_error_ptr) cinfo->err;
 
136
  (*cinfo->err->output_message) (cinfo);
 
137
  longjmp(myerr->setjmp_buffer, 1);
 
138
}
 
139
 
 
140
static unsigned char* 
 
141
_load_jpg_file( const char *file, 
 
142
                int *width, int *height, int *has_alpha )
 
143
{
 
144
  struct jpeg_decompress_struct cinfo;
 
145
  struct my_error_mgr jerr;
 
146
  FILE * infile;                /* source file */
 
147
  JSAMPLE *buffer;              /* Output row buffer */
 
148
  int row_stride;               /* physical row width in output buffer */
 
149
 
 
150
  unsigned char *data = NULL;
 
151
 
 
152
  if ((infile = fopen(file, "rb")) == NULL) {
 
153
    if (mb_want_warnings())
 
154
      fprintf(stderr, "mbpixbuf: can't open %s\n", file);
 
155
    return NULL;
 
156
  }
 
157
 
 
158
  cinfo.err = jpeg_std_error(&jerr.pub);
 
159
  jerr.pub.error_exit = _jpeg_error_exit;
 
160
 
 
161
  if (setjmp(jerr.setjmp_buffer)) {
 
162
    jpeg_destroy_decompress(&cinfo);
 
163
    fclose(infile);
 
164
    return NULL;
 
165
  }
 
166
 
 
167
  jpeg_create_decompress(&cinfo);
 
168
  jpeg_stdio_src(&cinfo, infile);
 
169
  jpeg_read_header(&cinfo, TRUE);
 
170
 
 
171
  cinfo.do_fancy_upsampling = FALSE;
 
172
  cinfo.do_block_smoothing  = FALSE;
 
173
  cinfo.out_color_space     = JCS_RGB;
 
174
  cinfo.scale_num           = 1;
 
175
 
 
176
  jpeg_start_decompress(&cinfo);
 
177
 
 
178
  if( cinfo.output_components != 3 ) 
 
179
    {
 
180
      if (mb_want_warnings())
 
181
        fprintf( stderr, "mbpixbuf: jpegs with %d channles not supported\n", 
 
182
                 cinfo.output_components );
 
183
      jpeg_finish_decompress(&cinfo);
 
184
      jpeg_destroy_decompress(&cinfo);
 
185
      return NULL;
 
186
  }
 
187
 
 
188
  *has_alpha = False;
 
189
  *width     = cinfo.output_width;
 
190
  *height    = cinfo.output_height;
 
191
 
 
192
  data = malloc(*width * *height * 3 );
 
193
  row_stride = cinfo.output_width * cinfo.output_components;
 
194
  buffer = malloc( sizeof(JSAMPLE)*row_stride );
 
195
 
 
196
  while (cinfo.output_scanline < cinfo.output_height) {
 
197
    jpeg_read_scanlines(&cinfo, &buffer, 1);
 
198
    memcpy( &data[ ( cinfo.output_scanline - 1 ) * row_stride ], 
 
199
            buffer, row_stride );
 
200
  }
 
201
 
 
202
  jpeg_finish_decompress(&cinfo);
 
203
  jpeg_destroy_decompress(&cinfo);
 
204
  fclose(infile);
 
205
 
 
206
  if (buffer) free(buffer);
 
207
 
 
208
  return data;
 
209
}
 
210
 
 
211
#endif
 
212
 
 
213
#ifdef USE_PNG
 
214
 
 
215
static unsigned char* 
 
216
_load_png_file( const char *file, 
 
217
               int *width, int *height, int *has_alpha ) {
 
218
  FILE *fd;
 
219
  unsigned char *data;
 
220
  unsigned char header[8];
 
221
  int  bit_depth, color_type;
 
222
 
 
223
  png_uint_32  png_width, png_height, i, rowbytes;
 
224
  png_structp png_ptr;
 
225
  png_infop info_ptr;
 
226
  png_bytep *row_pointers;
 
227
 
 
228
  if ((fd = fopen( file, "rb" )) == NULL) return NULL;
 
229
 
 
230
  fread( header, 1, 8, fd );
 
231
  if ( ! png_check_sig( header, 8 ) ) 
 
232
    {
 
233
      fclose(fd);
 
234
      return NULL;
 
235
    }
 
236
 
 
237
  png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 
238
  if ( ! png_ptr ) {
 
239
    fclose(fd);
 
240
    return NULL;
 
241
  }
 
242
 
 
243
  info_ptr = png_create_info_struct(png_ptr);
 
244
  if ( ! info_ptr ) {
 
245
    png_destroy_read_struct( &png_ptr, (png_infopp)NULL, (png_infopp)NULL);
 
246
    fclose(fd);
 
247
    return NULL;
 
248
  }
 
249
 
 
250
#if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 4
 
251
  if ( setjmp( png_jmpbuf ( png_ptr ) ) ) {
 
252
#else
 
253
  if ( setjmp( png_ptr->jmpbuf ) ) {
 
254
#endif
 
255
    png_destroy_read_struct( &png_ptr, &info_ptr, NULL);
 
256
    fclose(fd);
 
257
    return NULL;
 
258
  }
 
259
 
 
260
  png_init_io( png_ptr, fd );
 
261
  png_set_sig_bytes( png_ptr, 8);
 
262
  png_read_info( png_ptr, info_ptr);
 
263
  png_get_IHDR( png_ptr, info_ptr, &png_width, &png_height, &bit_depth, 
 
264
                &color_type, NULL, NULL, NULL);
 
265
  *width = (int) png_width;
 
266
  *height = (int) png_height;
 
267
 
 
268
  if (( color_type == PNG_COLOR_TYPE_PALETTE )||
 
269
      ( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS )))
 
270
    png_set_expand(png_ptr);
 
271
 
 
272
  if (( color_type == PNG_COLOR_TYPE_GRAY )||
 
273
      ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA ))
 
274
    png_set_gray_to_rgb(png_ptr);
 
275
 
 
276
  if ( color_type == PNG_COLOR_TYPE_RGB_ALPHA
 
277
       || color_type == PNG_COLOR_TYPE_GRAY_ALPHA
 
278
       )
 
279
    *has_alpha = 1;
 
280
  else
 
281
    *has_alpha = 0;
 
282
 
 
283
  /* 8 bits */
 
284
  if ( bit_depth == 16 )
 
285
    png_set_strip_16(png_ptr);
 
286
 
 
287
  if (bit_depth < 8)
 
288
    png_set_packing(png_ptr);
 
289
 
 
290
  /* not needed as data will be RGB not RGBA and have_alpha will reflect this
 
291
    png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
 
292
  */
 
293
 
 
294
  png_read_update_info( png_ptr, info_ptr);
 
295
 
 
296
  /* allocate space for data and row pointers */
 
297
  rowbytes = png_get_rowbytes( png_ptr, info_ptr);
 
298
  data = (unsigned char *) malloc( (rowbytes*(*height + 1)));
 
299
  row_pointers = (png_bytep *) malloc( (*height)*sizeof(png_bytep));
 
300
 
 
301
  if (( data == NULL )||( row_pointers == NULL )) {
 
302
    png_destroy_read_struct( &png_ptr, &info_ptr, NULL);
 
303
    free(data);
 
304
    free(row_pointers);
 
305
    return NULL;
 
306
  }
 
307
 
 
308
  for ( i = 0;  i < *height; i++ )
 
309
    row_pointers[i] = data + i*rowbytes;
 
310
 
 
311
  png_read_image( png_ptr, row_pointers );
 
312
  png_read_end( png_ptr, NULL);
 
313
 
 
314
  free(row_pointers);
 
315
  png_destroy_read_struct( &png_ptr, &info_ptr, NULL);
 
316
  fclose(fd);
 
317
 
 
318
  return data;
 
319
}
 
320
 
 
321
#endif
 
322
 
 
323
static unsigned char* 
 
324
_load_xpm_file( MBPixbuf *pb, const char *filename, int *w, int *h, int *has_alpha)
 
325
{                               /* This hell is adapted from imlib ;-) */
 
326
  FILE *file;
 
327
  
 
328
  struct _cmap
 
329
  {
 
330
    unsigned char       str[6];
 
331
    unsigned char       transp;
 
332
    short                 r, g, b;
 
333
  } *cmap = NULL;
 
334
  
 
335
  unsigned char *data = NULL, *ptr = NULL, *end = NULL;
 
336
 
 
337
  int pc, c = ' ', i = 0, j = 0, k = 0, ncolors = 0, cpp = 0, 
 
338
    comment = 0, transp = 0, quote = 0, context = 0,  len, done = 0;
 
339
 
 
340
  char *line, s[257], tok[128], col[256];
 
341
 
 
342
  XColor xcol;
 
343
  int lsz = 256;
 
344
  
 
345
  short lookup[128 - 32][128 - 32];
 
346
  
 
347
  if (!filename) return NULL;
 
348
  
 
349
  if ((file = fopen( filename, "rb" )) == NULL) return NULL;
 
350
  
 
351
  line = malloc(lsz);
 
352
  
 
353
  while (!done)
 
354
    {
 
355
      pc = c;
 
356
      c = fgetc(file);
 
357
      if (c == EOF)
 
358
        break;
 
359
      if (!quote)
 
360
        {
 
361
          if ((pc == '/') && (c == '*'))
 
362
            comment = 1;
 
363
          else if ((pc == '*') && (c == '/') && (comment))
 
364
            comment = 0;
 
365
        }
 
366
      if (!comment)
 
367
        {
 
368
          if ((!quote) && (c == '"'))
 
369
            {
 
370
              quote = 1;
 
371
              i = 0;
 
372
            }
 
373
          else if ((quote) && (c == '"'))
 
374
            {
 
375
              line[i] = 0;
 
376
              quote = 0;
 
377
              if (context == 0)
 
378
                {
 
379
                  /* Header */
 
380
                  sscanf(line, "%i %i %i %i", w, h, &ncolors, &cpp);
 
381
                  if (ncolors > 32766 || cpp > 5 || *w > 32767 || *h > 32767)
 
382
                    {
 
383
                      if (mb_want_warnings())
 
384
                        fprintf(stderr, "xpm file invalid");
 
385
                      fclose(file);
 
386
                      free(line);
 
387
                      fclose(file);
 
388
                      return NULL;
 
389
                    }
 
390
 
 
391
                  cmap = malloc(sizeof(struct _cmap) * ncolors);
 
392
 
 
393
                  if (!cmap)                  
 
394
                    {
 
395
                      free(line);
 
396
                      fclose(file);
 
397
                      return NULL;
 
398
                    }
 
399
 
 
400
                  data = malloc(*w ** h * 4);
 
401
                  if (!data)
 
402
                    {
 
403
                      free(cmap);
 
404
                      free(line);
 
405
                      fclose(file);
 
406
                      return NULL;
 
407
                    }
 
408
 
 
409
                  ptr = data;
 
410
                  end = ptr + (*w ** h * 4);
 
411
                  j = 0;
 
412
                  context++;
 
413
                }
 
414
              else if (context == 1)
 
415
                {
 
416
                  /* Color Table */
 
417
                  if (j < ncolors)
 
418
                    {
 
419
                      int                 slen;
 
420
                      int                 hascolor, iscolor;
 
421
 
 
422
                      iscolor = 0;
 
423
                      hascolor = 0;
 
424
                      tok[0] = 0;
 
425
                      col[0] = 0;
 
426
                      s[0] = 0;
 
427
                      len = strlen(line);
 
428
                      strncpy((char*)cmap[j].str, line, cpp);
 
429
                      cmap[j].str[cpp] = 0;
 
430
                      cmap[j].r = -1;
 
431
                      cmap[j].transp = 0;
 
432
                      for (k = cpp; k < len; k++)
 
433
                        {
 
434
                          if (line[k] != ' ')
 
435
                            {
 
436
                              s[0] = 0;
 
437
                              sscanf(&line[k], "%256s", s);
 
438
                              slen = strlen(s);
 
439
                              k += slen;
 
440
                              if (!strcmp(s, "c"))
 
441
                                iscolor = 1;
 
442
                              if ((!strcmp(s, "m")) || (!strcmp(s, "s")) ||
 
443
                                  (!strcmp(s, "g4")) || (!strcmp(s, "g")) ||
 
444
                                  (!strcmp(s, "c")) || (k >= len))
 
445
                                {
 
446
                                  if (k >= len)
 
447
                                    {
 
448
                                      if (col[0])
 
449
                                        strcat(col, " ");
 
450
                                      if (strlen(col) + strlen(s) < sizeof(col))
 
451
                                        strcat(col, s);
 
452
                                    }
 
453
                                  if (col[0])
 
454
                                    {
 
455
                                      if (!strcasecmp(col, "none"))
 
456
                                        {
 
457
                                          transp = 1;
 
458
                                          cmap[j].transp = 1;
 
459
                                        }
 
460
                                      else
 
461
                                        {
 
462
                                          if ((((cmap[j].r < 0) ||
 
463
                                                (!strcmp(tok, "c"))) &&
 
464
                                               (!hascolor)))
 
465
                                            {
 
466
                                              XParseColor(pb->dpy,
 
467
                                                          DefaultColormap(pb->dpy, 
 
468
                                                                          pb->scr),
 
469
 
 
470
                                                          col, &xcol);
 
471
                                              cmap[j].r = xcol.red >> 8;
 
472
                                              cmap[j].g = xcol.green >> 8;
 
473
                                              cmap[j].b = xcol.blue >> 8;
 
474
                                              if ((cmap[j].r == 255) &&
 
475
                                                  (cmap[j].g == 0) &&
 
476
                                                  (cmap[j].b == 255))
 
477
                                                cmap[j].r = 254;
 
478
                                              if (iscolor)
 
479
                                                hascolor = 1;
 
480
                                            }
 
481
                                        }
 
482
                                    }
 
483
                                  strcpy(tok, s);
 
484
                                  col[0] = 0;
 
485
                                }
 
486
                              else
 
487
                                {
 
488
                                  if (col[0])
 
489
                                    strcat(col, " ");
 
490
                                  strcat(col, s);
 
491
                                }
 
492
                            }
 
493
                        }
 
494
                    }
 
495
                  j++;
 
496
                  if (j >= ncolors)
 
497
                    {
 
498
                      if (cpp == 1)
 
499
                        for (i = 0; i < ncolors; i++)
 
500
                          lookup[(int)cmap[i].str[0] - 32][0] = i;
 
501
                      if (cpp == 2)
 
502
                        for (i = 0; i < ncolors; i++)
 
503
                          lookup[(int)cmap[i].str[0] - 32][(int)cmap[i].str[1] - 32] = i;
 
504
                      context++;
 
505
                    }
 
506
                }
 
507
              else
 
508
                {
 
509
                  /* Image Data */
 
510
                  i = 0;
 
511
                  if (cpp == 1)
 
512
                    {
 
513
                      for (i = 0; 
 
514
                           ((i < 65536) && (ptr < end) && (line[i])); 
 
515
                           i++)
 
516
                        {
 
517
                          col[0] = line[i];
 
518
                          if (transp && 
 
519
                              cmap[lookup[(int)col[0] - 32][0]].transp)
 
520
                            {
 
521
                              *ptr++ = 0; *ptr++ = 0; *ptr++ = 0; *ptr++ = 0;
 
522
                            }
 
523
                          else 
 
524
                            {
 
525
                              int idx = lookup[(int)col[0] - 32][0];
 
526
                              *ptr++ = (unsigned char)cmap[idx].r;
 
527
                              *ptr++ = (unsigned char)cmap[idx].g;
 
528
                              *ptr++ = (unsigned char)cmap[idx].b;
 
529
                              if (transp) *ptr++ = 255; 
 
530
                            }
 
531
                        }
 
532
                    }
 
533
                  else
 
534
                    {
 
535
                      for (i = 0; 
 
536
                           ((i < 65536) && (ptr < end) && (line[i])); 
 
537
                           i++)
 
538
                        {
 
539
                          for (j = 0; j < cpp; j++, i++)
 
540
                            {
 
541
                              col[j] = line[i];
 
542
                            }
 
543
                          col[j] = 0;
 
544
                          i--;
 
545
                          for (j = 0; j < ncolors; j++)
 
546
                            {
 
547
                              if (!strcmp(col, (char*)cmap[j].str))
 
548
                                {
 
549
                                  if (transp && cmap[j].transp)
 
550
                                    {
 
551
                                      *ptr++ = 0;
 
552
                                      *ptr++ = 0;
 
553
                                      *ptr++ = 0;
 
554
                                      *ptr++ = 0;
 
555
                                    }
 
556
                                  else
 
557
                                    {
 
558
                                      *ptr++ = (unsigned char)cmap[j].r;
 
559
                                      *ptr++ = (unsigned char)cmap[j].g;
 
560
                                      *ptr++ = (unsigned char)cmap[j].b;
 
561
                                      if (transp) *ptr++ = 255;
 
562
                                    }
 
563
                                  j = ncolors;
 
564
                                }
 
565
                            }
 
566
                        }
 
567
                    }
 
568
                }
 
569
            }
 
570
        }
 
571
 
 
572
      /* Scan in line from XPM file */
 
573
      if ((!comment) && (quote) && (c != '"'))
 
574
        {
 
575
          if (c < 32)
 
576
            c = 32;
 
577
          else if (c > 127)
 
578
            c = 127;
 
579
          line[i++] = c;
 
580
        }
 
581
      if (i >= lsz)
 
582
        {
 
583
          lsz += 256;
 
584
          line = realloc(line, lsz);
 
585
          if(line == NULL)
 
586
            {
 
587
              free(cmap);
 
588
              fclose(file);
 
589
              return NULL;
 
590
            }
 
591
        }
 
592
 
 
593
      if ((ptr) && ((ptr - data) >= *w ** h * 4))
 
594
        done = 1;
 
595
    }
 
596
 
 
597
  if (transp)
 
598
    *has_alpha = 1;
 
599
  else
 
600
    *has_alpha = 0;
 
601
 
 
602
  free(cmap);
 
603
  free(line);
 
604
 
 
605
  fclose(file);
 
606
  return data;
 
607
}
 
608
 
 
609
static int
 
610
_paletteAlloc(MBPixbuf *pb)
 
611
{
 
612
  XColor              xcl;
 
613
  int                 colnum, i, j;
 
614
  unsigned long       used[256];
 
615
  int                 num_used, is_used;
 
616
 
 
617
  int num_of_cols = 1 << pb->depth;
 
618
  int colors_per_channel = num_of_cols / 3;
 
619
 
 
620
  if (pb->palette) free(pb->palette);
 
621
 
 
622
  pb->palette = malloc(sizeof(MBPixbufColor) * num_of_cols);
 
623
 
 
624
  num_used = 0;
 
625
  colnum = 0;
 
626
 
 
627
  switch(pb->vis->class)
 
628
    {
 
629
    case PseudoColor:
 
630
    case StaticColor:
 
631
      /*
 
632
      for (r = 0, i = 0; r < colors_per_channel; r++)
 
633
        for (g = 0; g < colors_per_channel; g++)
 
634
          for (b = 0; b < colors_per_channel; b++, i++) 
 
635
            {      
 
636
              xcl.red   = (r * 0xffff) / (colors_per_channel - 1);
 
637
              xcl.green = (g * 0xffff) / (colors_per_channel - 1);
 
638
              xcl.blue  = (b * 0xffff) / (colors_per_channel - 1);
 
639
              xcl.flags = DoRed | DoGreen | DoBlue;
 
640
 
 
641
      */
 
642
 
 
643
      for (i = 0; i < num_of_cols; i++)
 
644
        {                       /* RRRGGGBB - TODO check for 4 bit col */
 
645
          int ii = (i * 256)/num_of_cols;
 
646
          xcl.red = (unsigned short)( ( ii & 0xe0 ) << 8 );
 
647
          xcl.green = (unsigned short)(( ii & 0x1c ) << 11 );
 
648
          xcl.blue = (unsigned short)( ( ii & 0x03 ) << 14 );
 
649
          xcl.flags = DoRed | DoGreen | DoBlue;
 
650
          
 
651
          if (!XAllocColor(pb->dpy, pb->root_cmap, &xcl))
 
652
            {
 
653
              if (mb_want_warnings())
 
654
                printf("alloc color failed\n");
 
655
            }
 
656
          is_used = 0;
 
657
          for (j = 0; j < num_used; j++)
 
658
            {
 
659
              if (xcl.pixel == used[j])
 
660
                {
 
661
                  is_used = 1;
 
662
                  j = num_used;
 
663
                }
 
664
            }
 
665
          if (!is_used)
 
666
            {
 
667
              pb->palette[colnum].r = xcl.red >> 8;
 
668
              pb->palette[colnum].g = xcl.green >> 8;
 
669
              pb->palette[colnum].b = xcl.blue >> 8;
 
670
              pb->palette[colnum].pixel = xcl.pixel;
 
671
              used[num_used++] = xcl.pixel;
 
672
              colnum++;
 
673
            }
 
674
          else
 
675
            xcl.pixel = 0;
 
676
        }
 
677
      break;
 
678
    case GrayScale:
 
679
    case StaticGray:
 
680
      for(i = 0; i < num_of_cols; i++)
 
681
        {
 
682
          xcl.red   = (i * 0xffff) / (colors_per_channel - 1);
 
683
          xcl.green = (i * 0xffff) / (colors_per_channel - 1);
 
684
          xcl.blue  = (i * 0xffff) / (colors_per_channel - 1);
 
685
          xcl.flags = DoRed | DoGreen | DoBlue;
 
686
          
 
687
          if (!XAllocColor(pb->dpy, pb->root_cmap, &xcl))
 
688
            {
 
689
              if (mb_want_warnings())
 
690
                fprintf(stderr, "libmb: alloc color failed\n");
 
691
            }
 
692
          is_used = 0;
 
693
          for (j = 0; j < num_used; j++)
 
694
            {
 
695
              if (xcl.pixel == used[j])
 
696
                {
 
697
                  is_used = 1;
 
698
                  j = num_used;
 
699
                }
 
700
            }
 
701
          if (!is_used)
 
702
            {
 
703
              pb->palette[colnum].r = xcl.red >> 8;
 
704
              pb->palette[colnum].g = xcl.green >> 8;
 
705
              pb->palette[colnum].b = xcl.blue >> 8;
 
706
              pb->palette[colnum].pixel = xcl.pixel;
 
707
              used[num_used++] = xcl.pixel;
 
708
              colnum++;
 
709
            }
 
710
          else
 
711
            xcl.pixel = 0;
 
712
        }
 
713
    }
 
714
  return colnum;
 
715
}
 
716
 
 
717
 
 
718
static unsigned long
 
719
mb_pixbuf_get_pixel(MBPixbuf *pb, int r, int g, int b, int a)
 
720
{
 
721
  if (pb->depth > 8)
 
722
    {
 
723
      switch (pb->depth)
 
724
        {
 
725
        case 15:
 
726
          return ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
 
727
        case 16:
 
728
          return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
 
729
        case 24:
 
730
        case 32:
 
731
          switch (pb->byte_order)
 
732
            {
 
733
            case BYTE_ORD_24_RGB:
 
734
              return ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
 
735
            case BYTE_ORD_24_RBG:
 
736
              return ((r & 0xff) << 16) | ((b & 0xff) << 8) | (g & 0xff);
 
737
            case BYTE_ORD_24_BRG:
 
738
              return ((b & 0xff) << 16) | ((r & 0xff) << 8) | (g & 0xff);
 
739
            case BYTE_ORD_24_BGR:
 
740
              return ((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff);
 
741
            case BYTE_ORD_24_GRB:
 
742
              return ((g & 0xff) << 16) | ((r & 0xff) << 8) | (b & 0xff);
 
743
            case BYTE_ORD_24_GBR:
 
744
              return ((g & 0xff) << 16) | ((b & 0xff) << 8) | (r & 0xff);
 
745
            case BYTE_ORD_32_ARGB:
 
746
              return  (a << 24) | (r << 16) | (g << 8) | b;
 
747
            default:
 
748
              return 0;
 
749
            }
 
750
        default:
 
751
          return 0;
 
752
        }
 
753
      return 0;
 
754
    }
 
755
 
 
756
  /* pb->depth <= 8 */
 
757
  switch(pb->vis->class)
 
758
    {
 
759
    case PseudoColor:
 
760
    case StaticColor:
 
761
    {
 
762
      int                 i;
 
763
      int                 dif;
 
764
      int                 dr, dg, db;
 
765
      unsigned long       col = 0;
 
766
      int                 mindif = 0x7fffffff;
 
767
 
 
768
      for (i = 0; i < pb->num_of_cols; i++)
 
769
        {
 
770
          dr = r - pb->palette[i].r;
 
771
          if (dr < 0)
 
772
            dr = -dr;
 
773
          dg = g - pb->palette[i].g;
 
774
          if (dg < 0)
 
775
            dg = -dg;
 
776
          db = b - pb->palette[i].b;
 
777
          if (db < 0)
 
778
            db = -db;
 
779
          dif = dr + dg + db;
 
780
          if (dif < mindif)
 
781
            {
 
782
              mindif = dif;
 
783
              col = i;
 
784
            }
 
785
        }
 
786
      return pb->palette[col].pixel;
 
787
    }
 
788
    case GrayScale:
 
789
    case StaticGray:
 
790
      return (((r * 77) + (g * 151) + (b * 28)) >> (16 - pb->depth));
 
791
#if 0
 
792
      if ((r+g+b) == 765 ) return 0;    /* HACK */
 
793
      return (1 << pb->depth) - ((( ((r * 54) + (g * 183) + (b * 19)) / 256) * 0xffff )/ (1 << pb->depth)); /* TODO should be oxffffffff ?? */
 
794
#endif      
 
795
    default:
 
796
      break;
 
797
    }
 
798
  return 0;
 
799
}
 
800
 
 
801
unsigned long
 
802
mb_pixbuf_lookup_x_pixel(MBPixbuf *pb, int r, int g, int b, int a)
 
803
{
 
804
  return mb_pixbuf_get_pixel(pb, r, g, b, a);
 
805
}
 
806
 
 
807
 
 
808
MBPixbuf *
 
809
mb_pixbuf_new(Display *dpy, int scr)
 
810
{
 
811
  return mb_pixbuf_new_extended(dpy, 
 
812
                                scr, 
 
813
                                DefaultVisual(dpy, scr),
 
814
                                DefaultDepth(dpy, scr));
 
815
}
 
816
 
 
817
 
 
818
void
 
819
mb_pixbuf_destroy(MBPixbuf *pb)
 
820
{
 
821
  /* XXX Probably needs to free more here */
 
822
  XFreeGC(pb->dpy, pb->gc);
 
823
  free(pb);
 
824
}
 
825
 
 
826
MBPixbuf *
 
827
mb_pixbuf_new_extended(Display *dpy, 
 
828
                       int      scr, 
 
829
                       Visual  *vis,
 
830
                       int      depth)
 
831
{
 
832
  XGCValues gcv;
 
833
  unsigned long rmsk, gmsk, bmsk;
 
834
  MBPixbuf *pb = malloc(sizeof(MBPixbuf));  
 
835
 
 
836
  pb->dpy = dpy;
 
837
  pb->scr = scr;
 
838
 
 
839
  pb->root  = RootWindow(dpy, scr);
 
840
  pb->depth = depth;
 
841
  pb->vis   = vis;
 
842
 
 
843
  pb->palette = NULL;
 
844
 
 
845
  rmsk = pb->vis->red_mask;
 
846
  gmsk = pb->vis->green_mask;
 
847
  bmsk = pb->vis->blue_mask;
 
848
 
 
849
  if (depth == 32 && pb->vis->class == TrueColor)
 
850
    pb->byte_order = BYTE_ORD_32_ARGB;
 
851
  else if ((rmsk > gmsk) && (gmsk > bmsk))
 
852
    pb->byte_order = BYTE_ORD_24_RGB;
 
853
  else if ((rmsk > bmsk) && (bmsk > gmsk))
 
854
    pb->byte_order = BYTE_ORD_24_RBG;
 
855
  else if ((bmsk > rmsk) && (rmsk > gmsk))
 
856
    pb->byte_order = BYTE_ORD_24_BRG;
 
857
  else if ((bmsk > gmsk) && (gmsk > rmsk))
 
858
    pb->byte_order = BYTE_ORD_24_BGR;
 
859
  else if ((gmsk > rmsk) && (rmsk > bmsk))
 
860
    pb->byte_order = BYTE_ORD_24_GRB;
 
861
  else if ((gmsk > bmsk) && (bmsk > rmsk))
 
862
    pb->byte_order = BYTE_ORD_24_GBR;
 
863
  else
 
864
    pb->byte_order = 0;
 
865
 
 
866
  pb->internal_bytespp = 3;
 
867
 
 
868
  if ((pb->depth < 24 && !getenv("MBPIXBUF_FORCE_32BPP_INTERNAL"))
 
869
      || getenv("MBPIXBUF_FORCE_16BPP_INTERNAL"))
 
870
    pb->internal_bytespp = 2;
 
871
 
 
872
  if ((pb->depth <= 8))
 
873
    {
 
874
      XWindowAttributes   xwa;
 
875
      if (XGetWindowAttributes(dpy, pb->root, &xwa))
 
876
        {
 
877
          if (xwa.colormap)
 
878
            pb->root_cmap = xwa.colormap;
 
879
          else
 
880
            pb->root_cmap = DefaultColormap(dpy, scr);
 
881
 
 
882
        }
 
883
      else
 
884
        pb->root_cmap = DefaultColormap(dpy, scr);
 
885
      pb->num_of_cols = _paletteAlloc(pb);
 
886
    }
 
887
 
 
888
  /* TODO: No exposes ? */
 
889
  gcv.foreground = BlackPixel(dpy, scr);
 
890
  gcv.background = WhitePixel(dpy, scr);
 
891
 
 
892
  pb->gc = XCreateGC( dpy, pb->root, GCForeground | GCBackground, &gcv);
 
893
 
 
894
  if (!XShmQueryExtension(pb->dpy) || getenv("MBPIXBUF_NO_SHM")) 
 
895
    {
 
896
      fprintf(stderr, "mbpixbuf: no shared memory extension\n");
 
897
      pb->have_shm = False;
 
898
    } 
 
899
  else                          /* Really check we have shm */
 
900
    {                           /* Urg, not nicer way todo this ? */
 
901
      XShmSegmentInfo shminfo; 
 
902
 
 
903
      pb->have_shm = True;
 
904
 
 
905
      shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777);
 
906
      shminfo.shmaddr=shmat(shminfo.shmid,0,0);
 
907
      shminfo.readOnly=True;
 
908
 
 
909
      _mbpb_trap_errors();
 
910
      
 
911
      XShmAttach(pb->dpy, &shminfo);
 
912
      XSync(pb->dpy, False);
 
913
 
 
914
      if (_mbpb_untrap_errors())
 
915
        {
 
916
          fprintf(stderr, "mbpixbuf: unable to use XShm. DISPLAY remote?\n");
 
917
          pb->have_shm = False;
 
918
        }
 
919
      else XShmDetach(pb->dpy, &shminfo);
 
920
 
 
921
      shmdt(shminfo.shmaddr);
 
922
      shmctl(shminfo.shmid, IPC_RMID, 0);
 
923
    }
 
924
  return pb;
 
925
}
 
926
 
 
927
MBPixbufImage *
 
928
mb_pixbuf_img_new(MBPixbuf *pb, int w, int h)
 
929
{
 
930
  MBPixbufImage *img;
 
931
 
 
932
  img = malloc(sizeof(MBPixbufImage));
 
933
  img->width = w;
 
934
  img->height = h;
 
935
 
 
936
  img->rgba = malloc(sizeof(unsigned char)*((w*h*(pb->internal_bytespp+1))));
 
937
  memset(img->rgba, 0, sizeof(unsigned char)*((w*h*(pb->internal_bytespp+1))));
 
938
 
 
939
  img->ximg = NULL;
 
940
  img->has_alpha = 1;
 
941
  img->internal_bytespp = pb->internal_bytespp;
 
942
 
 
943
  return img;
 
944
}
 
945
 
 
946
MBPixbufImage *
 
947
mb_pixbuf_img_rgba_new(MBPixbuf *pb, int w, int h)
 
948
{
 
949
  return mb_pixbuf_img_new(pb, w, h);
 
950
}
 
951
 
 
952
 
 
953
MBPixbufImage *
 
954
mb_pixbuf_img_rgb_new(MBPixbuf *pixbuf, int width, int height)
 
955
{
 
956
 
 
957
 MBPixbufImage *img;
 
958
 
 
959
 img = malloc(sizeof(MBPixbufImage));
 
960
 img->width = width;
 
961
 img->height = height;
 
962
 
 
963
 img->rgba 
 
964
   = malloc(sizeof(unsigned char)*((width*height*pixbuf->internal_bytespp)));
 
965
 memset(img->rgba, 0, 
 
966
        sizeof(unsigned char)*((width*height*pixbuf->internal_bytespp)));
 
967
  
 
968
 img->ximg = NULL;
 
969
 img->has_alpha = 0;
 
970
 img->internal_bytespp = pixbuf->internal_bytespp;
 
971
 
 
972
 return img;
 
973
 
 
974
}
 
975
 
 
976
/* ARGB Data */
 
977
 
 
978
MBPixbufImage *
 
979
mb_pixbuf_img_new_from_int_data(MBPixbuf            *pixbuf, 
 
980
                                const int           *data,
 
981
                                int                  width,
 
982
                                int                  height)
 
983
{
 
984
  MBPixbufImage *img;
 
985
  int            i=0,x,y;
 
986
 
 
987
  img = mb_pixbuf_img_rgba_new(pixbuf, width, height);
 
988
 
 
989
  if (pixbuf->internal_bytespp == 3)
 
990
    {
 
991
      unsigned char *p = img->rgba;
 
992
      
 
993
      for (y=0; y<height; y++)
 
994
        for (x=0; x<width; x++)
 
995
          {
 
996
            *p++ = (data[i] >> 16) & 0xff;
 
997
            *p++ = (data[i] >> 8) & 0xff;
 
998
            *p++ = data[i] & 0xff;
 
999
            *p++ = data[i] >> 24;
 
1000
            i++;
 
1001
          }
 
1002
    }
 
1003
  else
 
1004
    {
 
1005
      unsigned char *p = img->rgba, r,g,b,a;
 
1006
      
 
1007
      for (y=0; y<height; y++)
 
1008
        for (x=0; x<width; x++)
 
1009
          {
 
1010
            r = ((data[i] >> 16) & 0xff);
 
1011
            g = ((data[i] >> 8) & 0xff);
 
1012
            b = (data[i] & 0xff);
 
1013
            a = (data[i] >> 24);
 
1014
 
 
1015
            internal_rgb_to_16bpp_pixel(r,g,b,p);
 
1016
            internal_16bpp_pixel_next(p);
 
1017
            *p++ = a;
 
1018
            
 
1019
            i++;
 
1020
          }
 
1021
    }
 
1022
  
 
1023
  return img;
 
1024
}
 
1025
 
 
1026
MBPixbufImage *
 
1027
mb_pixbuf_img_new_from_data(MBPixbuf            *pixbuf, 
 
1028
                            const unsigned char *data,
 
1029
                            int                  width,
 
1030
                            int                  height,
 
1031
                            Bool                 has_alpha)
 
1032
{
 
1033
  MBPixbufImage *img;
 
1034
 
 
1035
  if (has_alpha)
 
1036
    img = mb_pixbuf_img_rgba_new(pixbuf, width, height);
 
1037
  else
 
1038
    img = mb_pixbuf_img_rgb_new(pixbuf, width, height);
 
1039
 
 
1040
  if (pixbuf->internal_bytespp == 3)
 
1041
    {
 
1042
      memcpy(img->rgba, data, width*height*(3+has_alpha));
 
1043
    }
 
1044
  else
 
1045
    {
 
1046
      /* Data is expected as 24/32 RGBA. but internally were 
 
1047
       * 16/24 so we need to scale the data down.
 
1048
      */
 
1049
      int x,y;
 
1050
      unsigned char r,g,b, *p16 = img->rgba;
 
1051
      const unsigned char *p24 = data;
 
1052
 
 
1053
      for (x=0; x<img->width; x++)
 
1054
        for (y=0; y<img->height; y++)
 
1055
      {
 
1056
        r = *p24++; g = *p24++; b = *p24++;
 
1057
        internal_rgb_to_16bpp_pixel(r,g,b,p16);
 
1058
        internal_16bpp_pixel_next(p16);
 
1059
 
 
1060
        if (has_alpha)
 
1061
          *p16++ = *p24++;
 
1062
      }
 
1063
    }
 
1064
 
 
1065
  return img;
 
1066
}
 
1067
 
 
1068
MBPixbufImage *
 
1069
mb_pixbuf_img_new_from_drawable (MBPixbuf *pb, 
 
1070
                                 Drawable  drw, 
 
1071
                                 Drawable  msk,
 
1072
                                 int       sx, 
 
1073
                                 int       sy, 
 
1074
                                 int       sw, 
 
1075
                                 int       sh  )
 
1076
{
 
1077
  return mb_pixbuf_img_new_from_x_drawable(pb, drw, msk, sx, sy, sw, sh, 0);
 
1078
}
 
1079
 
 
1080
MBPixbufImage *
 
1081
mb_pixbuf_img_new_from_x_drawable (MBPixbuf *pb, 
 
1082
                                   Drawable  drw, 
 
1083
                                   Drawable  msk,
 
1084
                                   int       sx, 
 
1085
                                   int       sy, 
 
1086
                                   int       sw, 
 
1087
                                   int       sh,
 
1088
                                   Bool      want_alpha)
 
1089
{
 
1090
  int i,x,y,br,bg,bb,mg,mb,mr,lr,lg,lb;
 
1091
  unsigned long xpixel;
 
1092
  unsigned char *p;
 
1093
  MBPixbufImage *img;
 
1094
 
 
1095
  XImage *ximg, *xmskimg = NULL;
 
1096
  int num_of_cols = 1 << pb->depth;
 
1097
 
 
1098
  Window chld;
 
1099
  int          rx;
 
1100
  unsigned int rw, rh, rb, rdepth;
 
1101
 
 
1102
  XShmSegmentInfo shminfo; 
 
1103
 
 
1104
  /* XXX should probably tray an X error here. */
 
1105
  XGetGeometry(pb->dpy, (Window)drw, &chld, &rx, &rx,
 
1106
               (unsigned int *)&rw, (unsigned int *)&rh,
 
1107
               (unsigned int *)&rb, (unsigned int *)&rdepth);
 
1108
 
 
1109
  if (rdepth != pb->depth) return NULL;
 
1110
 
 
1111
  if ( (sx + sw) > rw || (sy + sh) > rh )
 
1112
    {
 
1113
      /* area wanted is bigger than pixmap - should probably trim it down */
 
1114
      return NULL;
 
1115
    }
 
1116
 
 
1117
  XGrabServer(pb->dpy);
 
1118
 
 
1119
  if (1) /* (!pb->have_shm) BROKE */
 
1120
    {
 
1121
      ximg = XGetImage(pb->dpy, drw, sx, sy, sw, sh, -1, ZPixmap);
 
1122
    }
 
1123
  else
 
1124
    {
 
1125
      ximg = XShmCreateImage(pb->dpy, pb->vis, pb->depth, 
 
1126
                              ZPixmap, NULL, &shminfo,
 
1127
                              sw, sh );
 
1128
      XSync(pb->dpy, False);      
 
1129
 
 
1130
      shminfo.shmid=shmget(IPC_PRIVATE,
 
1131
                           ximg->bytes_per_line*ximg->height,
 
1132
                           IPC_CREAT|0777);
 
1133
      shminfo.shmaddr=img->ximg->data=shmat(shminfo.shmid,0,0);
 
1134
      shminfo.readOnly=True;
 
1135
      
 
1136
      XShmAttach(pb->dpy, &shminfo);
 
1137
 
 
1138
      XSync(pb->dpy, False);    
 
1139
  
 
1140
      if (!XShmGetImage(pb->dpy, drw, ximg, sx, sy, -1))
 
1141
        {
 
1142
          return NULL;
 
1143
        }
 
1144
 
 
1145
      XSync(pb->dpy, False);      
 
1146
 
 
1147
    }
 
1148
 
 
1149
  if (msk != None)
 
1150
    xmskimg = XGetImage(pb->dpy, msk, sx, sy, sw, sh, -1, ZPixmap);
 
1151
 
 
1152
  XUngrabServer(pb->dpy);
 
1153
  XFlush(pb->dpy);
 
1154
 
 
1155
  if (ximg == NULL) return NULL;
 
1156
 
 
1157
  if (msk || want_alpha)
 
1158
    img = mb_pixbuf_img_rgba_new(pb, sw, sh);
 
1159
  else
 
1160
    img = mb_pixbuf_img_rgb_new(pb, sw, sh);
 
1161
 
 
1162
  p = img->rgba;
 
1163
 
 
1164
  if (pb->depth > 8)
 
1165
    {
 
1166
      switch (pb->depth) {
 
1167
      case 15:
 
1168
        br = 7;
 
1169
        bg = 2;
 
1170
        bb = 3;
 
1171
        mr = mg = mb = 0xf8;
 
1172
        lr = lg = lb = 0;
 
1173
        break;
 
1174
      case 16:
 
1175
        br = 8;
 
1176
        bg = 3;
 
1177
        lb = 3;
 
1178
        bb = lr = lg = 0;
 
1179
        mr = mb = 0xf8;
 
1180
        mg = 0xfc;
 
1181
        break;
 
1182
      case 24:
 
1183
      case 32:
 
1184
        br = 16;
 
1185
        bg = 8;
 
1186
        bb = 0;
 
1187
        lr = lg = lb = 0;
 
1188
        mr = mg = mb = 0xff;
 
1189
        break;
 
1190
      default:
 
1191
        return NULL;
 
1192
      }
 
1193
 
 
1194
      if (pb->internal_bytespp == 2)
 
1195
        {
 
1196
          for (y = 0; y < sh; y++)
 
1197
            for (x = 0; x < sw; x++)
 
1198
              {
 
1199
                xpixel = XGetPixel(ximg, x, y);
 
1200
                internal_rgb_to_16bpp_pixel((((xpixel >> br) << lr) & mr),
 
1201
                                            (((xpixel >> bg) << lg) & mg),
 
1202
                                            (((xpixel >> bb) << lb) & mb), p);
 
1203
 
 
1204
                internal_16bpp_pixel_next(p);
 
1205
 
 
1206
                if (msk)
 
1207
                  {
 
1208
                    if (xmskimg && XGetPixel(xmskimg, x, y))
 
1209
                      {
 
1210
                        *p++ = 255;
 
1211
                      }
 
1212
                    else *p++ = 0;
 
1213
                  }
 
1214
                else if (want_alpha) p++;
 
1215
              }
 
1216
        }
 
1217
      else
 
1218
        {
 
1219
          for (y = 0; y < sh; y++)
 
1220
            for (x = 0; x < sw; x++)
 
1221
              {
 
1222
                xpixel = XGetPixel(ximg, x, y);
 
1223
                *p++ = (((xpixel >> br) << lr) & mr);      /* r */
 
1224
                *p++ = (((xpixel >> bg) << lg) & mg);      /* g */
 
1225
                *p++ = (((xpixel >> bb) << lb) & mb);      /* b */
 
1226
                if (msk)
 
1227
                  {
 
1228
                    if (xmskimg && XGetPixel(xmskimg, x, y))
 
1229
                      {
 
1230
                        *p++ = 255;
 
1231
                      }
 
1232
                    else *p++ = 0;
 
1233
                  }
 
1234
                else if (want_alpha) p++;
 
1235
              }
 
1236
        }
 
1237
    }
 
1238
  else
 
1239
    {
 
1240
      XColor cols[256];
 
1241
      MBPixbufColor mbcols[256];
 
1242
 
 
1243
      for (i = 0; i < num_of_cols; i++) {
 
1244
        cols[i].pixel = i;
 
1245
        cols[i].flags = DoRed | DoGreen | DoBlue;
 
1246
      }
 
1247
      XQueryColors(pb->dpy, pb->root_cmap, cols, num_of_cols);
 
1248
      for (i = 0; i < num_of_cols; i++) {
 
1249
        mbcols[i].r = cols[i].red >> 8;
 
1250
        mbcols[i].g = cols[i].green >> 8;
 
1251
        mbcols[i].b = cols[i].blue >> 8;
 
1252
        mbcols[i].pixel = cols[i].pixel;
 
1253
      }
 
1254
      for (x = 0; x < sw; x++)
 
1255
        for (y = 0; y < sh; y++)
 
1256
          {
 
1257
            xpixel = XGetPixel(ximg, x, y);
 
1258
            *p++ = mbcols[xpixel & 0xff].r;
 
1259
            *p++ = mbcols[xpixel & 0xff].g;
 
1260
            *p++ = mbcols[xpixel & 0xff].b;
 
1261
            if (msk)
 
1262
              {
 
1263
                if (xmskimg && XGetPixel(xmskimg, x, y))
 
1264
                  {
 
1265
                    *p++ = 255;
 
1266
                  }
 
1267
                else *p++ = 0;
 
1268
              }
 
1269
            else if (want_alpha) p++;                     
 
1270
          }
 
1271
    }
 
1272
 
 
1273
  if (0) /* (pb->have_shm) BROKE */
 
1274
    {
 
1275
      XShmDetach(pb->dpy, &shminfo);
 
1276
      XDestroyImage (ximg);
 
1277
      shmdt(shminfo.shmaddr);
 
1278
      shmctl(shminfo.shmid, IPC_RMID, 0);
 
1279
    }
 
1280
  else XDestroyImage (ximg);
 
1281
 
 
1282
  ximg = NULL;
 
1283
 
 
1284
  return img;
 
1285
}
 
1286
 
 
1287
MBPixbufImage *
 
1288
mb_pixbuf_img_clone(MBPixbuf *pb, MBPixbufImage *img)
 
1289
{
 
1290
  MBPixbufImage *img_new;
 
1291
 
 
1292
  if (img->has_alpha)
 
1293
    img_new = mb_pixbuf_img_rgba_new(pb, img->width, img->height);
 
1294
  else
 
1295
    img_new = mb_pixbuf_img_rgb_new(pb, img->width, img->height);
 
1296
 
 
1297
  memcpy(img_new->rgba, img->rgba, 
 
1298
         sizeof(unsigned char)*((img->width * img->height * (pb->internal_bytespp + img->has_alpha))));
 
1299
  return img_new;
 
1300
}
 
1301
 
 
1302
void
 
1303
mb_pixbuf_img_free(MBPixbuf *pb, MBPixbufImage *img)
 
1304
{
 
1305
  if (img->rgba) free(img->rgba);
 
1306
  free(img);
 
1307
}
 
1308
 
 
1309
static void
 
1310
_mb_convert_24bpp_to_16bpp(MBPixbuf *pb, MBPixbufImage **img)
 
1311
{
 
1312
  MBPixbufImage *img16, *img24 = *img;
 
1313
  int            x,y;
 
1314
  unsigned char  r,g,b, *p16 = NULL, *p24 = NULL;
 
1315
 
 
1316
  if (img24->has_alpha)
 
1317
    img16 = mb_pixbuf_img_rgba_new(pb, img24->width, img24->height);
 
1318
  else
 
1319
    img16 = mb_pixbuf_img_rgb_new(pb, img24->width, img24->height);
 
1320
      
 
1321
  p16 = img16->rgba; p24 = img24->rgba;
 
1322
 
 
1323
  for (x=0; x<img24->width; x++)
 
1324
    for (y=0; y<img24->height; y++)
 
1325
      {
 
1326
        r = *p24++;
 
1327
        g = *p24++;
 
1328
        b = *p24++;
 
1329
 
 
1330
        internal_rgb_to_16bpp_pixel(r,g,b,p16);
 
1331
        internal_16bpp_pixel_next(p16);
 
1332
 
 
1333
        if (img24->has_alpha)
 
1334
          *p16++ = *p24++;
 
1335
      }
 
1336
 
 
1337
  mb_pixbuf_img_free(pb, img24);
 
1338
 
 
1339
  *img = img16;
 
1340
}
 
1341
 
 
1342
MBPixbufImage *
 
1343
mb_pixbuf_img_new_from_file(MBPixbuf *pb, const char *filename)
 
1344
{
 
1345
  MBPixbufImage *img;
 
1346
 
 
1347
  img = malloc(sizeof(MBPixbufImage));
 
1348
 
 
1349
#ifdef USE_PNG
 
1350
  if (!strcasecmp(&filename[strlen(filename)-4], ".png"))
 
1351
    img->rgba = _load_png_file( filename, &img->width, 
 
1352
                                &img->height, &img->has_alpha ); 
 
1353
  else 
 
1354
#endif
 
1355
#ifdef USE_JPG
 
1356
  if (!strcasecmp(&filename[strlen(filename)-4], ".jpg")
 
1357
      || !strcasecmp(&filename[strlen(filename)-5], ".jpeg"))
 
1358
    img->rgba = _load_jpg_file( filename, &img->width, 
 
1359
                                &img->height, &img->has_alpha ); 
 
1360
  else 
 
1361
#endif
 
1362
if (!strcasecmp(&filename[strlen(filename)-4], ".xpm"))
 
1363
    img->rgba = _load_xpm_file( pb, filename, &img->width, 
 
1364
                                &img->height, &img->has_alpha ); 
 
1365
  else img->rgba = NULL;
 
1366
 
 
1367
  if (img->rgba == NULL)
 
1368
    {
 
1369
      /* Load failed */
 
1370
      free(img);
 
1371
      return NULL;
 
1372
    }
 
1373
 
 
1374
  if (pb->internal_bytespp == 2)
 
1375
    {
 
1376
      /* Need to convert the data down, always comes as 24 rgb :/ */
 
1377
      _mb_convert_24bpp_to_16bpp(pb, &img);
 
1378
    }
 
1379
 
 
1380
  img->ximg = NULL;
 
1381
 
 
1382
  return img;
 
1383
}
 
1384
 
 
1385
void
 
1386
mb_pixbuf_img_fill(MBPixbuf *pb, 
 
1387
                   MBPixbufImage *img,
 
1388
                   int r, 
 
1389
                   int g, 
 
1390
                   int b, 
 
1391
                   int a)
 
1392
{
 
1393
  unsigned char *p = img->rgba;
 
1394
  int x,y;
 
1395
 
 
1396
  if (pb->internal_bytespp == 2)
 
1397
    {
 
1398
      for(y=0; y<img->height; y++)
 
1399
        for(x=0; x<img->width; x++)
 
1400
          {
 
1401
            internal_rgb_to_16bpp_pixel(r,g,b,p);
 
1402
            internal_16bpp_pixel_next(p);
 
1403
            if (img->has_alpha) 
 
1404
              { *p = a; *p++; }
 
1405
          }
 
1406
    }
 
1407
  else
 
1408
    {
 
1409
      for(y=0; y<img->height; y++)
 
1410
        for(x=0; x<img->width; x++)
 
1411
          {
 
1412
            *p++ = r;
 
1413
            *p++ = g;
 
1414
            *p++ = b;
 
1415
            if (img->has_alpha) *p++ = a;
 
1416
          }
 
1417
    }
 
1418
}
 
1419
 
 
1420
void
 
1421
mb_pixbuf_img_composite(MBPixbuf *pb, MBPixbufImage *dest,
 
1422
                        MBPixbufImage *src, int dx, int dy)
 
1423
{
 
1424
  /* XXX depreictaed, should really now use copy_composite */
 
1425
  int x, y, r, g, b, a;
 
1426
  unsigned char *sp, *dp;
 
1427
  int dbc = 0; 
 
1428
 
 
1429
  if (src->has_alpha == False)
 
1430
    return mb_pixbuf_img_copy(pb, dest, src, 0, 0, 
 
1431
                              src->width, src->height, dx, dy);
 
1432
  sp = src->rgba;
 
1433
  dp = dest->rgba;
 
1434
 
 
1435
  dbc = (pb->internal_bytespp + dest->has_alpha);
 
1436
 
 
1437
  dp += ((dest->width*dbc)*dy) + (dx*dbc);
 
1438
 
 
1439
  if (pb->internal_bytespp == 2)
 
1440
    {
 
1441
      for(y=0; y<src->height; y++)
 
1442
        {
 
1443
          for(x=0; x<src->width; x++)
 
1444
            {
 
1445
              unsigned char dr,dg,db;
 
1446
 
 
1447
              /* TODO, This needs optimising */
 
1448
 
 
1449
              internal_16bpp_pixel_to_rgb(sp,r,g,b);
 
1450
              internal_16bpp_pixel_next(sp);
 
1451
              a = *sp++;
 
1452
                
 
1453
              internal_16bpp_pixel_to_rgb(dp,dr,dg,db);
 
1454
              alpha_composite(dr, r, a, dr);
 
1455
              alpha_composite(dg, g, a, dg);
 
1456
              alpha_composite(db, b, a, db);
 
1457
              internal_rgb_to_16bpp_pixel(dr,dg,db,dp)
 
1458
              internal_16bpp_pixel_next(dp);
 
1459
 
 
1460
              dp += dest->has_alpha;
 
1461
            }
 
1462
          dp += (dest->width-src->width)*dbc;
 
1463
        }
 
1464
 
 
1465
 
 
1466
    }
 
1467
  else
 
1468
    {
 
1469
      for(y=0; y<src->height; y++)
 
1470
        {
 
1471
          for(x=0; x<src->width; x++)
 
1472
            {
 
1473
              r = *sp++;
 
1474
              g = *sp++;
 
1475
              b = *sp++;
 
1476
              a = *sp++;
 
1477
              
 
1478
              alpha_composite(*dp, r, a, *dp);
 
1479
              dp++;
 
1480
              alpha_composite(*dp, g, a, *dp);
 
1481
              dp++;
 
1482
              alpha_composite(*dp, b, a, *dp);
 
1483
              dp++;
 
1484
              dp += dest->has_alpha;
 
1485
            }
 
1486
          dp += (dest->width-src->width)*dbc;
 
1487
        }
 
1488
    }
 
1489
}
 
1490
 
 
1491
void
 
1492
mb_pixbuf_img_copy_composite_with_alpha (MBPixbuf      *pb, 
 
1493
                                         MBPixbufImage *dest,
 
1494
                                         MBPixbufImage *src, 
 
1495
                                         int sx, int sy, 
 
1496
                                         int sw, int sh, 
 
1497
                                         int dx, int dy,
 
1498
                                         int alpha_level )
 
1499
{
 
1500
  int x, y, r, g, b, a;
 
1501
  unsigned char *sp, *dp;
 
1502
  int dbc = 0;   
 
1503
 
 
1504
  if (!src->has_alpha)
 
1505
    return mb_pixbuf_img_copy(pb, dest, src, sx, sy, sw, sh, dx, dy);
 
1506
 
 
1507
  sp = src->rgba;
 
1508
  dp = dest->rgba;
 
1509
 
 
1510
  dbc = (pb->internal_bytespp + dest->has_alpha);
 
1511
 
 
1512
  dp += ((dest->width*dbc)*dy) + (dx*dbc);
 
1513
  sp += ((src->width*(pb->internal_bytespp+1))*sy)  + (sx*(pb->internal_bytespp+1));
 
1514
 
 
1515
  if (pb->internal_bytespp == 2)
 
1516
    {
 
1517
      for(y=0; y<sh; y++)
 
1518
        {
 
1519
          for(x=0; x < sw; x++)
 
1520
            {
 
1521
              unsigned char dr,dg,db;
 
1522
 
 
1523
              /* TODO, This needs optimising */
 
1524
 
 
1525
              internal_16bpp_pixel_to_rgb(sp,r,g,b);
 
1526
              internal_16bpp_pixel_next(sp);
 
1527
              a = *sp; sp++;
 
1528
 
 
1529
              if (alpha_level)
 
1530
                {
 
1531
                  a += alpha_level;
 
1532
                  if (a < 0) a = 0;
 
1533
                  if (a > 255) a = 255;
 
1534
                }
 
1535
                
 
1536
              internal_16bpp_pixel_to_rgb(dp,dr,dg,db);
 
1537
              alpha_composite(dr, r, a, dr);
 
1538
              alpha_composite(dg, g, a, dg);
 
1539
              alpha_composite(db, b, a, db);
 
1540
              internal_rgb_to_16bpp_pixel(dr,dg,db,dp);
 
1541
              internal_16bpp_pixel_next(dp);
 
1542
              
 
1543
              if (dest->has_alpha)
 
1544
                *dp++ =  a;
 
1545
            }
 
1546
          dp += (dest->width-sw)*dbc;
 
1547
          sp += (src->width-sw)*3;
 
1548
        }
 
1549
    }
 
1550
  else
 
1551
    {
 
1552
      for(y=0; y<sh; y++)
 
1553
        {
 
1554
          for(x=0; x < sw; x++)
 
1555
            {
 
1556
              r = *sp++;
 
1557
              g = *sp++;
 
1558
              b = *sp++;
 
1559
              a = *sp++;
 
1560
              
 
1561
              if (alpha_level)
 
1562
                {
 
1563
                  a += alpha_level;
 
1564
                  if (a < 0) a = 0;
 
1565
                  if (a > 255) a = 255;
 
1566
                }
 
1567
              
 
1568
              alpha_composite(*dp, r, a, *dp);
 
1569
              dp++;
 
1570
              alpha_composite(*dp, g, a, *dp);
 
1571
              dp++;
 
1572
              alpha_composite(*dp, b, a, *dp);
 
1573
              dp++;
 
1574
              if (dest->has_alpha) *dp++ = a;
 
1575
            }
 
1576
          dp += (dest->width-sw)*dbc;
 
1577
          sp += (src->width-sw)*4;
 
1578
        }
 
1579
    }
 
1580
}
 
1581
     
 
1582
 
 
1583
void
 
1584
mb_pixbuf_img_copy_composite(MBPixbuf *pb, MBPixbufImage *dest,
 
1585
                             MBPixbufImage *src, int sx, int sy, 
 
1586
                             int sw, int sh, int dx, int dy)
 
1587
{
 
1588
  mb_pixbuf_img_copy_composite_with_alpha(pb, dest,src, sx, sy, sw, sh, dx, dy, 0); 
 
1589
}
 
1590
 
 
1591
 
 
1592
void
 
1593
mb_pixbuf_img_copy(MBPixbuf *pb, MBPixbufImage *dest,
 
1594
                   MBPixbufImage *src, int sx, int sy, int sw, int sh,
 
1595
                   int dx, int dy)
 
1596
{
 
1597
  int x, y, dbc, sbc;
 
1598
  unsigned char *sp, *dp;
 
1599
  
 
1600
  sp = src->rgba;
 
1601
  dp = dest->rgba;
 
1602
  dbc = (pb->internal_bytespp + dest->has_alpha);
 
1603
  sbc = (pb->internal_bytespp + src->has_alpha);
 
1604
 
 
1605
  dp += ((dest->width*dbc)*dy) + (dx*dbc);
 
1606
  sp += ((src->width*sbc)*sy)  + (sx*sbc);
 
1607
 
 
1608
  for(y=0; y<sh; y++)
 
1609
    {
 
1610
      for(x=0; x < sw; x++)
 
1611
        {
 
1612
          *dp++ = *sp++;
 
1613
          *dp++ = *sp++;
 
1614
          if (pb->internal_bytespp > 2)
 
1615
            *dp++ = *sp++;
 
1616
          /* XXX below to optimise */
 
1617
          if (dest->has_alpha && src->has_alpha)
 
1618
            *dp++ = *sp++;
 
1619
          else 
 
1620
            {
 
1621
              if (dest->has_alpha) *dp++ = 0xff;
 
1622
              // dp += dest->has_alpha;
 
1623
              sp += src->has_alpha;
 
1624
            }
 
1625
        }
 
1626
      dp += (dest->width-sw)*dbc;
 
1627
      sp += (src->width-sw)*sbc;
 
1628
    }
 
1629
}
 
1630
 
 
1631
MBPixbufImage *
 
1632
mb_pixbuf_img_scale_down(MBPixbuf *pb, MBPixbufImage *img, 
 
1633
                         int new_width, int new_height)
 
1634
{
 
1635
  MBPixbufImage *img_scaled;
 
1636
  unsigned char *dest, *src, *srcy;
 
1637
  int *xsample, *ysample;
 
1638
  int bytes_per_line, i, x, y,  r, g, b, a, nb_samples, xrange, yrange, rx, ry;
 
1639
 
 
1640
  if ( new_width > img->width || new_height > img->height) 
 
1641
    return NULL;
 
1642
 
 
1643
  if (img->has_alpha)
 
1644
    {
 
1645
      img_scaled = mb_pixbuf_img_rgba_new(pb, new_width, new_height);
 
1646
      bytes_per_line = (img->width * (pb->internal_bytespp+1));
 
1647
    }
 
1648
  else
 
1649
    {
 
1650
      img_scaled = mb_pixbuf_img_rgb_new(pb, new_width, new_height);
 
1651
      bytes_per_line = (img->width * pb->internal_bytespp);
 
1652
    }
 
1653
 
 
1654
  xsample = malloc( (new_width+1) * sizeof(int));
 
1655
  ysample = malloc( (new_height+1) * sizeof(int));
 
1656
 
 
1657
  for ( i = 0; i <= new_width; i++ )
 
1658
    xsample[i] = i*img->width/new_width;
 
1659
  for ( i = 0; i <= new_height; i++ )
 
1660
    ysample[i] = i*img->height/new_height * img->width;
 
1661
 
 
1662
  dest = img_scaled->rgba;
 
1663
 
 
1664
  /* scan output image */
 
1665
  for ( y = 0; y < new_height; y++ ) 
 
1666
    {
 
1667
      yrange = ( ysample[y+1] - ysample[y] )/img->width;
 
1668
      for ( x = 0; x < new_width; x++) 
 
1669
        {
 
1670
          xrange = xsample[x+1] - xsample[x];
 
1671
          srcy = img->rgba + (( ysample[y] + xsample[x] ) 
 
1672
                              * ( (img->has_alpha) ?  (pb->internal_bytespp+1) : pb->internal_bytespp ) );
 
1673
          
 
1674
      /* average R,G,B,A values on sub-rectangle of source image */
 
1675
          nb_samples = xrange * yrange;
 
1676
          if ( nb_samples > 1 ) 
 
1677
            {
 
1678
              r = 0;
 
1679
              g = 0;
 
1680
              b = 0;
 
1681
              a = 0;
 
1682
              for ( ry = 0; ry < yrange; ry++ ) 
 
1683
                {
 
1684
                  src = srcy;
 
1685
                  for ( rx = 0; rx < xrange; rx++ ) 
 
1686
                    {
 
1687
                      /* average R,G,B,A values */
 
1688
                      if (pb->internal_bytespp == 2)
 
1689
                        {
 
1690
                          unsigned char rr,gg,bb;
 
1691
                          internal_16bpp_pixel_to_rgb(src,rr,gg,bb);
 
1692
                          r += rr; g += gg; b += bb;
 
1693
                          internal_16bpp_pixel_next(src);
 
1694
                        }
 
1695
                      else
 
1696
                        {
 
1697
                          r += *src++;
 
1698
                          g += *src++;
 
1699
                          b += *src++;
 
1700
                        }
 
1701
                      if (img->has_alpha) a += *src++;
 
1702
                    }
 
1703
                  srcy += bytes_per_line;
 
1704
                }
 
1705
 
 
1706
              if (pb->internal_bytespp == 2)
 
1707
                {
 
1708
                  unsigned char rr,gg,bb;
 
1709
                  rr = (r/nb_samples);
 
1710
                  gg = (g/nb_samples);
 
1711
                  bb = (b/nb_samples);
 
1712
 
 
1713
                  internal_rgb_to_16bpp_pixel(rr, gg, bb, dest);
 
1714
                  internal_16bpp_pixel_next(dest);
 
1715
                }
 
1716
              else
 
1717
                {
 
1718
                  *dest++ = r/nb_samples;
 
1719
                  *dest++ = g/nb_samples;
 
1720
                  *dest++ = b/nb_samples;
 
1721
                }
 
1722
              if (img_scaled->has_alpha) *dest++ = a/nb_samples; 
 
1723
            }
 
1724
          else 
 
1725
            {
 
1726
              int i;
 
1727
              for (i=0; i<(pb->internal_bytespp + img_scaled->has_alpha); i++)
 
1728
                *dest++ = *srcy++;
 
1729
            }
 
1730
        }
 
1731
    }
 
1732
 
 
1733
  /* cleanup */
 
1734
  free( xsample );
 
1735
  free( ysample );
 
1736
 
 
1737
  return img_scaled;
 
1738
}
 
1739
 
 
1740
MBPixbufImage *
 
1741
mb_pixbuf_img_scale_up(MBPixbuf *pb, MBPixbufImage *img, 
 
1742
                       int new_width, int new_height)
 
1743
{
 
1744
  MBPixbufImage *img_scaled;
 
1745
  unsigned char *dest, *src;
 
1746
  int x, y, xx, yy, bytes_per_line;
 
1747
 
 
1748
  if ( new_width < img->width || new_height < img->height) 
 
1749
    return NULL;
 
1750
 
 
1751
  if (img->has_alpha)
 
1752
    {
 
1753
      img_scaled = mb_pixbuf_img_rgba_new(pb, new_width, new_height);
 
1754
      bytes_per_line = (img->width * (pb->internal_bytespp+1));
 
1755
    }
 
1756
  else
 
1757
    {
 
1758
      img_scaled = mb_pixbuf_img_rgb_new(pb, new_width, new_height);
 
1759
      bytes_per_line = (img->width * pb->internal_bytespp);
 
1760
    }
 
1761
 
 
1762
 
 
1763
  dest = img_scaled->rgba;
 
1764
  
 
1765
  for (y = 0; y < new_height; y++)
 
1766
    {
 
1767
      yy = (y * img->height) / new_height;
 
1768
      for (x = 0; x < new_width; x++)
 
1769
      {
 
1770
         xx = (x * img->width) / new_width;
 
1771
         src = img->rgba + ((yy * bytes_per_line)) 
 
1772
           + ( (img->has_alpha) ? (xx * (pb->internal_bytespp+1)) : (xx * pb->internal_bytespp) );
 
1773
         *dest++ = *src++;
 
1774
         *dest++ = *src++;
 
1775
         if (pb->internal_bytespp > 2)
 
1776
           *dest++ = *src++;
 
1777
         
 
1778
         if (img->has_alpha)
 
1779
           *dest++ = *src++;
 
1780
      }
 
1781
   }
 
1782
 
 
1783
  return img_scaled;
 
1784
}
 
1785
 
 
1786
MBPixbufImage *
 
1787
mb_pixbuf_img_scale(MBPixbuf *pb, MBPixbufImage *img, 
 
1788
                    int new_width, int new_height)
 
1789
{
 
1790
  if (new_width >= img->width && new_height >= img->height)
 
1791
    return mb_pixbuf_img_scale_up(pb, img, new_width, new_height);
 
1792
 
 
1793
  if (new_width <= img->width && new_height <= img->height)
 
1794
    return mb_pixbuf_img_scale_down(pb, img, new_width, new_height);
 
1795
 
 
1796
  /* TODO: all scale functions should check for a dimention change
 
1797
           being zero and act accordingly - ie faster. 
 
1798
  */
 
1799
  if (new_width >= img->width && new_height <= img->height)
 
1800
    {
 
1801
      MBPixbufImage *tmp=NULL, *tmp2 = NULL;
 
1802
      tmp = mb_pixbuf_img_scale_up(pb, img, new_width, img->height);
 
1803
      
 
1804
      tmp2 = mb_pixbuf_img_scale_down(pb, tmp, new_width, new_height);
 
1805
      mb_pixbuf_img_free(pb, tmp);
 
1806
      return tmp2;
 
1807
    }
 
1808
 
 
1809
  if (new_width <= img->width && new_height >= img->height)
 
1810
    {
 
1811
      MBPixbufImage *tmp, *tmp2;
 
1812
      tmp = mb_pixbuf_img_scale_down(pb, img, new_width, img->height);
 
1813
      
 
1814
      tmp2 = mb_pixbuf_img_scale_up(pb, tmp, new_width, new_height);
 
1815
      mb_pixbuf_img_free(pb, tmp);
 
1816
      return tmp2;
 
1817
    }
 
1818
 
 
1819
  return NULL;
 
1820
}
 
1821
 
 
1822
void
 
1823
mb_pixbuf_img_render_to_drawable(MBPixbuf    *pb,
 
1824
                                 MBPixbufImage *img,
 
1825
                                 Drawable     drw,
 
1826
                                 int drw_x,
 
1827
                                 int drw_y)
 
1828
{
 
1829
  mb_pixbuf_img_render_to_drawable_with_gc(pb, img, drw, drw_x, drw_y, pb->gc);
 
1830
}
 
1831
 
 
1832
 
 
1833
void
 
1834
mb_pixbuf_img_render_to_drawable_with_gc(MBPixbuf    *pb,
 
1835
                                         MBPixbufImage *img,
 
1836
                                         Drawable     drw,
 
1837
                                         int drw_x,
 
1838
                                         int drw_y,
 
1839
                                         GC gc)
 
1840
{
 
1841
      int bitmap_pad;
 
1842
      unsigned char *p;
 
1843
      unsigned long pixel;
 
1844
      int x,y;
 
1845
      int a, r, g, b;
 
1846
 
 
1847
      XShmSegmentInfo shminfo;
 
1848
      Bool shm_success = False;
 
1849
 
 
1850
      if (pb->have_shm)
 
1851
        {
 
1852
          img->ximg = XShmCreateImage(pb->dpy, pb->vis, pb->depth, 
 
1853
                                      ZPixmap, NULL, &shminfo,
 
1854
                                      img->width, img->height );
 
1855
          
 
1856
          shminfo.shmid=shmget(IPC_PRIVATE,
 
1857
                               img->ximg->bytes_per_line*img->ximg->height,
 
1858
                               IPC_CREAT|0777);
 
1859
          shminfo.shmaddr = img->ximg->data = shmat(shminfo.shmid,0,0);
 
1860
 
 
1861
          if (img->ximg->data == (char *)-1)
 
1862
            {
 
1863
              fprintf(stderr, "mbpixbuf: SHM can't attach SHM Segment for Shared XImage, falling back to XImages\n");
 
1864
              XDestroyImage(img->ximg);
 
1865
              shmctl(shminfo.shmid, IPC_RMID, 0);
 
1866
            }
 
1867
          else
 
1868
            {
 
1869
              shminfo.readOnly=True;
 
1870
              XShmAttach(pb->dpy, &shminfo);
 
1871
              shm_success = True;
 
1872
            }
 
1873
        }
 
1874
 
 
1875
      if (!shm_success)
 
1876
        {
 
1877
          bitmap_pad = ( pb->depth > 16 )? 32 : (( pb->depth > 8 )? 16 : 8 );
 
1878
          
 
1879
          img->ximg = XCreateImage( pb->dpy, pb->vis, pb->depth, 
 
1880
                                    ZPixmap, 0, 0,
 
1881
                                    img->width, img->height, bitmap_pad, 0);
 
1882
 
 
1883
          img->ximg->data = malloc( img->ximg->bytes_per_line*img->height );
 
1884
        }
 
1885
 
 
1886
      p = img->rgba;
 
1887
 
 
1888
      if (pb->internal_bytespp == 2)
 
1889
        {
 
1890
          for(y=0; y<img->height; y++)
 
1891
            for(x=0; x<img->width; x++)
 
1892
              {
 
1893
                /* Below is potentially dangerous.  
 
1894
                 */
 
1895
                pixel =  ( *p | (*(p+1) << 8)); 
 
1896
 
 
1897
                p +=  ((img->has_alpha) ?  3 : 2);
 
1898
                
 
1899
                XPutPixel(img->ximg, x, y, pixel);
 
1900
              }
 
1901
        }
 
1902
      else
 
1903
        {
 
1904
          for(y=0; y<img->height; y++)
 
1905
            {
 
1906
              for(x=0; x<img->width; x++)
 
1907
                {
 
1908
                  r = ( *p++ );
 
1909
                  g = ( *p++ );
 
1910
                  b = ( *p++ );
 
1911
                  a = ((img->has_alpha) ?  *p++ : 0xff);
 
1912
                  
 
1913
                  pixel = mb_pixbuf_get_pixel(pb, r, g, b, a);
 
1914
                  XPutPixel(img->ximg, x, y, pixel);
 
1915
                }
 
1916
            }
 
1917
        }
 
1918
 
 
1919
      if (!shm_success)
 
1920
        {
 
1921
          XPutImage( pb->dpy, drw, gc, img->ximg, 0, 0, 
 
1922
                     drw_x, drw_y, img->width, img->height);
 
1923
          XDestroyImage (img->ximg);
 
1924
        }
 
1925
      else
 
1926
        {
 
1927
          XShmPutImage(pb->dpy, drw, gc, img->ximg, 0, 0, 
 
1928
                       drw_x, drw_y, img->width, img->height, False);
 
1929
 
 
1930
          XSync(pb->dpy, False);
 
1931
          XShmDetach(pb->dpy, &shminfo);
 
1932
          XDestroyImage (img->ximg);
 
1933
          shmdt(shminfo.shmaddr);
 
1934
          shmctl(shminfo.shmid, IPC_RMID, 0);
 
1935
        }
 
1936
 
 
1937
      img->ximg = NULL;         /* Safety On */
 
1938
}
 
1939
 
 
1940
void
 
1941
mb_pixbuf_img_render_to_mask(MBPixbuf    *pb,
 
1942
                             MBPixbufImage *img,
 
1943
                             Drawable  mask,
 
1944
                             int drw_x,
 
1945
                             int drw_y)
 
1946
{
 
1947
      unsigned char *p;
 
1948
      int x,y;
 
1949
      GC gc1;
 
1950
      XShmSegmentInfo shminfo; 
 
1951
      Bool shm_success = False;
 
1952
 
 
1953
      if (!img->has_alpha) return;
 
1954
 
 
1955
      gc1 = XCreateGC( pb->dpy, mask, 0, 0 );
 
1956
      XSetForeground(pb->dpy, gc1, WhitePixel( pb->dpy, pb->scr ));
 
1957
 
 
1958
      if (pb->have_shm)
 
1959
        {
 
1960
          img->ximg = XShmCreateImage(pb->dpy, pb->vis, 1, 
 
1961
                                      XYPixmap, NULL, &shminfo,
 
1962
                                      img->width, img->height );
 
1963
 
 
1964
          shminfo.shmid=shmget(IPC_PRIVATE,
 
1965
                               img->ximg->bytes_per_line*img->ximg->height,
 
1966
                               IPC_CREAT|0777);
 
1967
          shminfo.shmaddr=img->ximg->data=shmat(shminfo.shmid,0,0);
 
1968
 
 
1969
          if (img->ximg->data == (char *)-1)
 
1970
            {
 
1971
              if (mb_want_warnings())
 
1972
                fprintf(stderr, "mbpixbuf: SHM can't attach SHM Segment for Shared XImage, falling back to XImages\n");
 
1973
              XDestroyImage(img->ximg);
 
1974
              shmctl(shminfo.shmid, IPC_RMID, 0);
 
1975
            }
 
1976
          else
 
1977
            {
 
1978
              shminfo.readOnly=True;
 
1979
              XShmAttach(pb->dpy, &shminfo);
 
1980
              shm_success = True;
 
1981
            }
 
1982
        }
 
1983
 
 
1984
      if (!shm_success)
 
1985
        {
 
1986
          img->ximg = XCreateImage( pb->dpy, pb->vis, 1, XYPixmap, 
 
1987
                                    0, 0, img->width, img->height, 8, 0);
 
1988
      
 
1989
          img->ximg->data = malloc( img->ximg->bytes_per_line*img->height );
 
1990
        }
 
1991
 
 
1992
      p = img->rgba;
 
1993
 
 
1994
      for(y=0; y<img->height; y++)
 
1995
        for(x=0; x<img->width; x++)
 
1996
            {
 
1997
              p += pb->internal_bytespp; 
 
1998
              XPutPixel(img->ximg, x, y, (*p < 127) ? 0 : 1);
 
1999
              p++;
 
2000
            }
 
2001
 
 
2002
      if (!shm_success)
 
2003
        {
 
2004
          XPutImage( pb->dpy, mask, gc1, img->ximg, 0, 0, 
 
2005
                     drw_x, drw_y, img->width, img->height);
 
2006
          XDestroyImage (img->ximg);
 
2007
        }
 
2008
      else
 
2009
        {
 
2010
          XShmPutImage(pb->dpy, mask, gc1, img->ximg, 0, 0, 
 
2011
                       drw_x, drw_y, img->width, img->height, False);
 
2012
          XSync(pb->dpy, False);
 
2013
          XShmDetach(pb->dpy, &shminfo);
 
2014
          XDestroyImage (img->ximg);
 
2015
          shmdt(shminfo.shmaddr);
 
2016
          shmctl(shminfo.shmid, IPC_RMID, 0);
 
2017
        }
 
2018
 
 
2019
      XFreeGC( pb->dpy, gc1 );
 
2020
      img->ximg = NULL;         /* Safety On */
 
2021
}
 
2022
 
 
2023
unsigned char *
 
2024
mb_pixbuf_img_data (MBPixbuf      *pixbuf,
 
2025
                    MBPixbufImage *image)
 
2026
{
 
2027
  return image->rgba;
 
2028
}
 
2029
 
 
2030
void
 
2031
mb_pixbuf_img_get_pixel (MBPixbuf      *pixbuf,
 
2032
                         MBPixbufImage *img,
 
2033
                         int            x,
 
2034
                         int            y,
 
2035
                         unsigned char *r,
 
2036
                         unsigned char *g,
 
2037
                         unsigned char *b,
 
2038
                         unsigned char *a
 
2039
                         )
 
2040
{
 
2041
  int idx;
 
2042
 
 
2043
  idx = pixbuf->internal_bytespp + img->has_alpha;
 
2044
 
 
2045
  if (pixbuf->internal_bytespp == 2)
 
2046
    {
 
2047
      int offset = ( (y * img->width * idx) + ( x * idx ) );
 
2048
      internal_16bpp_pixel_to_rgb(img->rgba+offset, *r, *g, *b);
 
2049
 
 
2050
      if (img->has_alpha)
 
2051
        *a = *(img->rgba+offset+2);
 
2052
      else
 
2053
        *a = 255;
 
2054
    }
 
2055
  else
 
2056
    {
 
2057
      *r = img->rgba[(((y)*img->width*idx)+((x)*idx))];    
 
2058
      *g = img->rgba[(((y)*img->width*idx)+((x)*idx))+1];    
 
2059
      *b = img->rgba[(((y)*img->width*idx)+((x)*idx))+2]; 
 
2060
      
 
2061
      if (img->has_alpha)
 
2062
        *a = img->rgba[(((y)*img->width*idx)+((x)*idx))+3];
 
2063
      else
 
2064
        *a = 255;
 
2065
    }
 
2066
}
 
2067
 
 
2068
 
 
2069
void
 
2070
mb_pixbuf_img_plot_pixel (MBPixbuf      *pb,
 
2071
                          MBPixbufImage *img,
 
2072
                          int            x,
 
2073
                          int            y,
 
2074
                          unsigned char  r,
 
2075
                          unsigned char  g,
 
2076
                          unsigned char  b)
 
2077
 
2078
  int idx;
 
2079
  if (x >= img->width || y >= img->height) return;
 
2080
 
 
2081
  idx = pb->internal_bytespp + img->has_alpha;
 
2082
 
 
2083
  if (pb->internal_bytespp == 2)
 
2084
    {
 
2085
      int offset = (((y)*img->width*idx)+((x)*idx));
 
2086
      internal_rgb_to_16bpp_pixel(r,g,b, (img->rgba+offset));
 
2087
    }
 
2088
  else
 
2089
    {
 
2090
      img->rgba[(((y)*img->width*idx)+((x)*idx))]   = r;    
 
2091
      img->rgba[(((y)*img->width*idx)+((x)*idx))+1] = g;    
 
2092
      img->rgba[(((y)*img->width*idx)+((x)*idx))+2] = b; 
 
2093
    }
 
2094
}
 
2095
 
 
2096
void
 
2097
mb_pixbuf_img_plot_pixel_with_alpha (MBPixbuf      *pb,
 
2098
                                     MBPixbufImage *img,
 
2099
                                     int            x,
 
2100
                                     int            y,
 
2101
                                     unsigned char  r,
 
2102
                                     unsigned char  g,
 
2103
                                     unsigned char  b,
 
2104
                                     unsigned char  a)
 
2105
 
2106
  int idx = (((y)*img->width*(pb->internal_bytespp+1))+((x)*(pb->internal_bytespp+1)));   
 
2107
 
 
2108
  if (!img->has_alpha)
 
2109
    {
 
2110
      mb_pixbuf_img_plot_pixel (pb, img, x, y, r, g, b );
 
2111
      return;
 
2112
    }
 
2113
    
 
2114
  if (x >= img->width || y >= img->height) return;   
 
2115
 
 
2116
  if (pb->internal_bytespp == 2)
 
2117
    {
 
2118
      unsigned char rr,gg, bb;
 
2119
      internal_16bpp_pixel_to_rgb((img->rgba+idx), rr,gg,bb);
 
2120
 
 
2121
      alpha_composite(rr, (r), (a), rr);    
 
2122
      alpha_composite(gg, (g), (a), gg);    
 
2123
      alpha_composite(bb, (b), (a), bb);    
 
2124
 
 
2125
      internal_rgb_to_16bpp_pixel(rr,gg,bb, (img->rgba+idx));
 
2126
    }
 
2127
  else
 
2128
    {
 
2129
      alpha_composite(img->rgba[idx],   (r), (a), img->rgba[idx]);    
 
2130
      alpha_composite(img->rgba[idx+1], (g), (a), img->rgba[idx+1]);  
 
2131
      alpha_composite(img->rgba[idx+2], (b), (a), img->rgba[idx+2]);  
 
2132
    }
 
2133
}
 
2134
 
 
2135
MBPixbufImage *
 
2136
mb_pixbuf_img_transform (MBPixbuf          *pb,
 
2137
                         MBPixbufImage     *img,
 
2138
                         MBPixbufTransform  transform)
 
2139
{
 
2140
  MBPixbufImage *img_trans;
 
2141
  int            new_width = 0, new_height = 0, new_x = 0, new_y = 0, idx;
 
2142
  int            bytes_per_line, x, y;
 
2143
  int            byte_offset = 0, new_byte_offset = 0;
 
2144
 
 
2145
  switch (transform)
 
2146
    {
 
2147
    case MBPIXBUF_TRANS_ROTATE_90:
 
2148
    case MBPIXBUF_TRANS_ROTATE_270:
 
2149
      new_width = mb_pixbuf_img_get_height(img);
 
2150
      new_height = mb_pixbuf_img_get_width(img);
 
2151
      break;
 
2152
    case MBPIXBUF_TRANS_ROTATE_180:
 
2153
    case MBPIXBUF_TRANS_FLIP_VERT:
 
2154
    case MBPIXBUF_TRANS_FLIP_HORIZ:
 
2155
      new_width = mb_pixbuf_img_get_width(img);
 
2156
      new_height = mb_pixbuf_img_get_height(img);
 
2157
 
 
2158
      break;
 
2159
    }
 
2160
 
 
2161
  if (img->has_alpha)
 
2162
    {
 
2163
      img_trans = mb_pixbuf_img_rgba_new(pb, new_width, new_height);
 
2164
      bytes_per_line = (img->width * (pb->internal_bytespp+1));
 
2165
      idx = pb->internal_bytespp +1 ;
 
2166
    }
 
2167
  else
 
2168
    {
 
2169
      img_trans = mb_pixbuf_img_rgb_new(pb, new_width, new_height);
 
2170
      bytes_per_line = (img->width * pb->internal_bytespp);
 
2171
      idx = pb->internal_bytespp;
 
2172
    }
 
2173
  
 
2174
  for( y = 0; y < img->height; y++ ) 
 
2175
    {
 
2176
      for( x = 0; x < img->width; x++ ) 
 
2177
        {
 
2178
 
 
2179
 
 
2180
          /* XXX This could all be heavily optimised */
 
2181
          switch (transform)
 
2182
            {
 
2183
            case MBPIXBUF_TRANS_ROTATE_180:
 
2184
              new_x = new_width  - 1 - x;
 
2185
              new_y = new_height - 1 - y;
 
2186
              break;
 
2187
            case MBPIXBUF_TRANS_ROTATE_270:
 
2188
              new_x = y;
 
2189
              new_y = img->width - x - 1;
 
2190
              break;
 
2191
            case MBPIXBUF_TRANS_ROTATE_90:
 
2192
              new_x = img->height - y - 1;
 
2193
              new_y = x;
 
2194
              break;
 
2195
            case MBPIXBUF_TRANS_FLIP_VERT:
 
2196
              new_x = x; new_y = img->height - y - 1;
 
2197
              break;
 
2198
            case MBPIXBUF_TRANS_FLIP_HORIZ:
 
2199
              new_y = y; new_x = img->width - x - 1;
 
2200
              break;
 
2201
            }
 
2202
 
 
2203
          byte_offset     = (y * bytes_per_line) + ( x * idx );
 
2204
          new_byte_offset = (new_y * (new_width) * idx) + ( new_x * idx );
 
2205
 
 
2206
          img_trans->rgba[new_byte_offset]   = img->rgba[byte_offset];
 
2207
          img_trans->rgba[new_byte_offset+1] = img->rgba[byte_offset+1];
 
2208
 
 
2209
          if (pb->internal_bytespp > 2)
 
2210
            img_trans->rgba[new_byte_offset+2] = img->rgba[byte_offset+2];
 
2211
 
 
2212
          if (img->has_alpha)
 
2213
            img_trans->rgba[new_byte_offset+pb->internal_bytespp] = img->rgba[byte_offset+pb->internal_bytespp];
 
2214
        }
 
2215
    }
 
2216
 
 
2217
  return img_trans;
 
2218
}