Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

gifx.c

Go to the documentation of this file.
00001 /* gifx.c - Functions to turn GIFs in memory into X Pixmaps.
00002    Copyright (C) 1997-9 Eddie Kohler, eddietwo@lcs.mit.edu
00003    This file is part of the GIF library.
00004 
00005    The GIF library is free software*. It is distributed under the GNU General
00006    Public License, version 2 or later; you can copy, distribute, or alter it
00007    at will, as long as this notice is kept intact and this source code is made
00008    available. There is no warranty, express or implied.
00009 
00010    *The LZW compression method used by GIFs is patented. Unisys, the patent
00011    holder, allows the compression algorithm to be used without a license in
00012    software distributed at no cost to the user. */
00013 
00014 #ifdef HAVE_CONFIG_H
00015 # include "config.h"
00016 #endif
00017 #include "gifx.h"
00018 #include <X11/Xutil.h>
00019 #include <assert.h>
00020 #include <string.h>
00021 #ifdef __cplusplus
00022 extern "C" {
00023 #endif
00024 
00025 #define SAFELS(a,b) ((b) < 0 ? (a) >> -(b) : (a) << (b))
00026 
00027 struct Gif_XColormap {
00028   
00029   Gif_XContext *x_context;
00030   Gif_Colormap *colormap;
00031   
00032   int allocated;
00033   int claimed;
00034   u_int16_t npixels;
00035   unsigned long *pixels;
00036   
00037   Gif_XColormap *next;
00038   
00039 };
00040 
00041 static unsigned long crap_pixels[256];
00042 
00043 
00044 static void
00045 load_closest(Gif_XContext *gfx)
00046 {
00047   XColor *color;
00048   u_int16_t ncolor;
00049   u_int16_t ncolormap;
00050   int i;
00051   
00052   if (gfx->closest) return;
00053   
00054   ncolormap = ncolor = gfx->ncolormap;
00055   if (ncolor > 256) ncolor = 256;
00056   color = Gif_NewArray(XColor, ncolor);
00057   
00058   if (ncolormap > 256)
00059     for (i = 0; i < ncolor; i++)
00060       color[i].pixel = (rand() >> 4) % ncolormap;
00061   else
00062     for (i = 0; i < ncolor; i++)
00063       color[i].pixel = i;
00064   XQueryColors(gfx->display, gfx->colormap, color, ncolor);
00065   
00066   gfx->closest = Gif_NewArray(Gif_Color, ncolor);
00067   for (i = 0; i < ncolor; i++) {
00068     Gif_Color *c = &gfx->closest[i];
00069     c->haspixel = 1;
00070     c->red = color[i].red >> 8;
00071     c->green = color[i].green >> 8;
00072     c->blue = color[i].blue >> 8;
00073     c->pixel = color[i].pixel;
00074   }
00075   gfx->nclosest = ncolor;
00076   
00077   Gif_DeleteArray(color);
00078 }
00079 
00080 
00081 static unsigned long
00082 allocate_closest(Gif_XContext *gfx, Gif_Color *c)
00083 {
00084   Gif_Color *closer;
00085   Gif_Color *got = 0;
00086   u_int32_t distance = 0x4000000;
00087   int i;
00088   
00089   load_closest(gfx);
00090   
00091   for (i = 0, closer = gfx->closest; i < gfx->nclosest; i++, closer++) {
00092     int redd = c->red - closer->red;
00093     int greend = c->green - closer->green;
00094     int blued = c->blue - closer->blue;
00095     u_int32_t d = redd * redd + greend * greend + blued * blued;
00096     if (d < distance) {
00097       distance = d;
00098       got = closer;
00099     }
00100   }
00101   
00102   if (!got) return 0;
00103   if (!got->haspixel) {
00104     XColor xcol;
00105     xcol.red = got->red | (got->red << 8);
00106     xcol.green = got->green | (got->green << 8);
00107     xcol.blue = got->blue | (got->blue << 8);
00108     if (XAllocColor(gfx->display, gfx->colormap, &xcol) == 0) {
00109       /* Probably was a read/write color cell. Get rid of it!! */
00110       *got = gfx->closest[gfx->nclosest - 1];
00111       gfx->nclosest--;
00112       return allocate_closest(gfx, c);
00113     }
00114     got->pixel = xcol.pixel;
00115     got->haspixel = 1;
00116   }
00117   
00118   return got->pixel;
00119 }
00120 
00121 
00122 static void
00123 allocate_colors(Gif_XColormap *gfxc)
00124 {
00125   Gif_XContext *gfx = gfxc->x_context;
00126   u_int16_t size = gfxc->colormap->ncol;
00127   Gif_Color *c = gfxc->colormap->col;
00128   unsigned long *pixels = gfxc->pixels;
00129   XColor xcol;
00130   int i;
00131   if (!gfxc->allocated) {
00132     if (size > gfxc->npixels) size = gfxc->npixels;
00133     for (i = 0; i < size; i++, c++) {
00134       xcol.red = c->red | (c->red << 8);
00135       xcol.green = c->green | (c->green << 8);
00136       xcol.blue = c->blue | (c->blue << 8);
00137       if (XAllocColor(gfx->display, gfx->colormap, &xcol))
00138         pixels[i] = xcol.pixel;
00139       else
00140         pixels[i] = allocate_closest(gfx, c);
00141     }
00142     gfxc->allocated = 1;
00143     gfxc->claimed = 0;
00144   }
00145 }
00146 
00147 static void
00148 deallocate_colors(Gif_XColormap *gfxc)
00149 {
00150   Gif_XContext *gfx = gfxc->x_context;
00151   if (gfxc->allocated && !gfxc->claimed) {
00152     XFreeColors(gfx->display, gfx->colormap, gfxc->pixels, gfxc->npixels, 0);
00153     gfxc->allocated = 0;
00154   }
00155 }
00156 
00157 
00158 static Gif_XColormap *
00159 create_x_colormap_extension(Gif_XContext *gfx, Gif_Colormap *gfcm)
00160 {
00161   Gif_XColormap *gfxc;
00162   unsigned long *pixels;
00163   if (!gfcm) return 0;
00164   gfxc = Gif_New(Gif_XColormap);
00165   pixels = gfxc ? Gif_NewArray(unsigned long, 256) : 0;
00166   if (pixels) {
00167     gfxc->x_context = gfx;
00168     gfxc->colormap = gfcm;
00169     gfxc->allocated = 0;
00170     gfxc->npixels = gfcm->ncol;
00171     gfxc->pixels = pixels;
00172     gfxc->next = gfx->xcolormap;
00173     gfx->xcolormap = gfxc;
00174     return gfxc;
00175   } else {
00176     Gif_Delete(gfxc);
00177     Gif_DeleteArray(pixels);
00178     return 0;
00179   }
00180 }
00181 
00182 static Gif_XColormap *
00183 find_x_colormap_extension(Gif_XContext *gfx, Gif_Colormap *gfcm, int create)
00184 {
00185   Gif_XColormap *gfxc = gfx->xcolormap;
00186   if (!gfcm) return 0;
00187   while (gfxc) {
00188     if (gfxc->colormap == gfcm)
00189       return gfxc;
00190     gfxc = gfxc->next;
00191   }
00192   if (create)
00193     return create_x_colormap_extension(gfx, gfcm);
00194   else
00195     return 0;
00196 }
00197 
00198 int
00199 Gif_XAllocateColors(Gif_XContext *gfx, Gif_Colormap *gfcm)
00200 {
00201   Gif_XColormap *gfxc = find_x_colormap_extension(gfx, gfcm, 1);
00202   if (gfxc) {
00203     allocate_colors(gfxc);
00204     return 1;
00205   } else
00206     return 0;
00207 }
00208 
00209 void
00210 Gif_XDeallocateColors(Gif_XContext *gfx, Gif_Colormap *gfcm)
00211 {
00212   Gif_XColormap *gfxc = find_x_colormap_extension(gfx, gfcm, 0);
00213   if (gfxc)
00214     deallocate_colors(gfxc);
00215 }
00216 
00217 
00218 unsigned long *
00219 Gif_XClaimStreamColors(Gif_XContext *gfx, Gif_Stream *gfs, int *np_store)
00220 {
00221   int i;
00222   int npixels = 0;
00223   unsigned long *pixels;
00224   Gif_Colormap *global = gfs->global;
00225   *np_store = 0;
00226   
00227   for (i = 0; i < gfs->nimages; i++) {
00228     Gif_Image *gfi = gfs->images[i];
00229     Gif_Colormap *gfcm = (gfi->local ? gfi->local : global);
00230     Gif_XColormap *gfxc = find_x_colormap_extension(gfx, gfcm, 0);
00231     if (gfxc && gfxc->allocated && gfxc->claimed == 0) {
00232       gfxc->claimed = 2;
00233       npixels += gfxc->npixels;
00234       if (gfcm == global) global = 0;
00235     }
00236   }
00237   
00238   if (!npixels) return 0;
00239   
00240   pixels = Gif_NewArray(unsigned long, npixels);
00241   if (!pixels) return 0;
00242   *np_store = npixels;
00243 
00244   npixels = 0;
00245   global = gfs->global;
00246   for (i = 0; i < gfs->nimages; i++) {
00247     Gif_Image *gfi = gfs->images[i];
00248     Gif_Colormap *gfcm = (gfi->local ? gfi->local : global);
00249     Gif_XColormap *gfxc = find_x_colormap_extension(gfx, gfcm, 0);
00250     if (gfxc && gfxc->allocated && gfxc->claimed == 2) {
00251       memcpy(pixels + npixels, gfxc->pixels, gfxc->npixels);
00252       npixels += gfxc->npixels;
00253       gfxc->claimed = 1;
00254       if (gfcm == global) global = 0;
00255     }
00256   }
00257 
00258   return pixels;
00259 }
00260 
00261 
00262 /* Getting pixmaps */
00263 
00264 #define BYTESIZE 8
00265 
00266 static int
00267 put_sub_image_colormap(Gif_XContext *gfx, Gif_Image *gfi, Gif_Colormap *gfcm,
00268                        int left, int top, int width, int height,
00269                        Pixmap pixmap, int pixmap_x, int pixmap_y)
00270 {
00271   XImage *ximage;
00272   byte *xdata;
00273   
00274   int i, j, k;
00275   int bytes_per_line;
00276   
00277   unsigned long saved_transparent = 0;
00278   int release_uncompressed = 0;
00279   u_int16_t nct;
00280   unsigned long *pixels;
00281   
00282   /* Find the correct image and colormap */
00283   if (!gfi) return 0;
00284   if (!gfx->image_gc)
00285     gfx->image_gc = XCreateGC(gfx->display, pixmap, 0, 0);
00286   if (!gfx->image_gc)
00287     return 0;
00288 
00289   /* Make sure the image is uncompressed */
00290   if (!gfi->img && !gfi->image_data && gfi->compressed) {
00291     Gif_UncompressImage(gfi);
00292     release_uncompressed = 1;
00293   }
00294   
00295   /* Check subimage dimensions */
00296   if (width <= 0 || height <= 0 || left < 0 || top < 0
00297       || left+width <= 0 || top+height <= 0
00298       || left+width > gfi->width || top+height > gfi->height)
00299     return 0;
00300   
00301   /* Allocate colors from the colormap; make sure the transparent color
00302    * has the given pixel value */
00303   if (gfcm) {
00304     Gif_XColormap *gfxc = find_x_colormap_extension(gfx, gfcm, 1);
00305     if (!gfxc) return 0;
00306     allocate_colors(gfxc);
00307     pixels = gfxc->pixels;
00308     nct = gfxc->npixels;
00309   } else {
00310     for (i = 0; i < 256; i++) crap_pixels[i] = gfx->foreground_pixel;
00311     pixels = crap_pixels;
00312     nct = 256;
00313   }
00314   if (gfi->transparent >= 0 && gfi->transparent < 256) {
00315     saved_transparent = pixels[ gfi->transparent ];
00316     pixels[ gfi->transparent ] = gfx->transparent_pixel;
00317   }
00318   
00319   /* Set up the X image */
00320   if (gfx->depth <= 8) i = 8;
00321   else if (gfx->depth <= 16) i = 16;
00322   else i = 32;
00323   ximage =
00324     XCreateImage(gfx->display, gfx->visual, gfx->depth,
00325                  gfx->depth == 1 ? XYBitmap : ZPixmap, 0, NULL,
00326                  width, height, i, 0);
00327   
00328   ximage->bitmap_bit_order = ximage->byte_order = LSBFirst;
00329   bytes_per_line = ximage->bytes_per_line;
00330   xdata = Gif_NewArray(byte, bytes_per_line * height);
00331   ximage->data = (char *)xdata;
00332   
00333   /* The main loop */
00334   if (ximage->bits_per_pixel % 8 == 0) {
00335     /* Optimize for cases where a pixel is exactly one or more bytes */
00336     int bytes_per_pixel = ximage->bits_per_pixel / 8;
00337     
00338     for (j = 0; j < height; j++) {
00339       byte *line = gfi->img[top + j] + left;
00340       byte *writer = xdata + bytes_per_line * j;
00341       for (i = 0; i < width; i++) {
00342         unsigned long pixel;
00343         if (line[i] < nct)
00344           pixel = pixels[line[i]];
00345         else
00346           pixel = pixels[0];
00347         for (k = 0; k < bytes_per_pixel; k++) {
00348           *writer++ = pixel;
00349           pixel >>= 8;
00350         }
00351       }
00352     }
00353     
00354   } else {
00355     /* Other bits-per-pixel */
00356     int bits_per_pixel = ximage->bits_per_pixel;
00357     u_int32_t bits_per_pixel_mask = (1UL << bits_per_pixel) - 1;
00358     
00359     for (j = 0; j < height; j++) {
00360       int imshift = 0;
00361       u_int32_t impixel = 0;
00362       byte *line = gfi->img[top + j] + left;
00363       byte *writer = xdata + bytes_per_line * j;
00364       
00365       for (i = 0; i < width; i++) {
00366         unsigned long pixel;
00367         if (line[i] < nct)
00368           pixel = pixels[line[i]];
00369         else
00370           pixel = pixels[0];
00371         
00372         impixel |= SAFELS(pixel & bits_per_pixel_mask, imshift);
00373         while (imshift + bits_per_pixel >= BYTESIZE) {
00374           *writer++ = impixel;
00375           imshift -= BYTESIZE;
00376           impixel = SAFELS(pixel, imshift);
00377         }
00378         imshift += bits_per_pixel;
00379       }
00380       
00381       if (imshift)
00382         *writer++ = impixel;
00383     }
00384   }
00385   
00386   /* Restore saved transparent pixel value */
00387   if (gfi->transparent >= 0 && gfi->transparent < 256)
00388     pixels[ gfi->transparent ] = saved_transparent;
00389 
00390   /* Put it onto the pixmap */
00391   XPutImage(gfx->display, pixmap, gfx->image_gc, ximage, 0, 0,
00392             pixmap_x, pixmap_y, width, height);
00393   
00394   Gif_DeleteArray(xdata);
00395   ximage->data = 0; /* avoid freeing it again in XDestroyImage */  
00396   XDestroyImage(ximage);
00397 
00398   if (release_uncompressed)
00399     Gif_ReleaseUncompressedImage(gfi);
00400   
00401   return 1;
00402 }
00403 
00404 
00405 Pixmap
00406 Gif_XSubImageColormap(Gif_XContext *gfx, Gif_Image *gfi, Gif_Colormap *gfcm,
00407                       int left, int top, int width, int height)
00408 {
00409   Pixmap pixmap =
00410     XCreatePixmap(gfx->display, gfx->drawable, width, height, gfx->depth);
00411   if (pixmap) {
00412     if (put_sub_image_colormap(gfx, gfi, gfcm, left, top, width, height,
00413                                pixmap, 0, 0))
00414       return pixmap;
00415     else
00416       XFreePixmap(gfx->display, pixmap);
00417   }
00418   return None;
00419 }
00420 
00421 Pixmap
00422 Gif_XImage(Gif_XContext *gfx, Gif_Stream *gfs, Gif_Image *gfi)
00423 {
00424   Gif_Colormap *gfcm;
00425   if (!gfi && gfs->nimages) gfi = gfs->images[0];
00426   if (!gfi) return None;
00427   gfcm = gfi->local;
00428   if (!gfcm) gfcm = gfs->global;
00429   return Gif_XSubImageColormap(gfx, gfi, gfcm,
00430                                0, 0, gfi->width, gfi->height);
00431 }
00432 
00433 Pixmap
00434 Gif_XImageColormap(Gif_XContext *gfx, Gif_Stream *gfs, Gif_Colormap *gfcm,
00435                    Gif_Image *gfi)
00436 {
00437   if (!gfi && gfs->nimages) gfi = gfs->images[0];
00438   if (!gfi) return None;
00439   return Gif_XSubImageColormap(gfx, gfi, gfcm,
00440                                0, 0, gfi->width, gfi->height);
00441 }
00442 
00443 Pixmap
00444 Gif_XSubImage(Gif_XContext *gfx, Gif_Stream *gfs, Gif_Image *gfi,
00445               int left, int top, int width, int height)
00446 {
00447   Gif_Colormap *gfcm;
00448   if (!gfi && gfs->nimages) gfi = gfs->images[0];
00449   if (!gfi) return None;
00450   gfcm = gfi->local;
00451   if (!gfcm) gfcm = gfs->global;
00452   return Gif_XSubImageColormap(gfx, gfi, gfcm,
00453                                left, top, width, height);
00454 }
00455 
00456 
00457 Pixmap
00458 Gif_XSubMask(Gif_XContext *gfx, Gif_Image *gfi,
00459              int left, int top, int width, int height)
00460 {
00461   Pixmap pixmap = None;
00462   XImage *ximage;
00463   byte *xdata;
00464   
00465   int i, j;
00466   int transparent;
00467   int bytes_per_line;
00468   int release_uncompressed = 0;
00469   
00470   /* Find the correct image */
00471   if (!gfi) return None;
00472   
00473   /* Check subimage dimensions */
00474   if (width <= 0 || height <= 0 || left < 0 || top < 0
00475       || left+width <= 0 || top+height <= 0
00476       || left+width > gfi->width || top+height > gfi->height)
00477     return None;
00478   
00479   /* Make sure the image is uncompressed */
00480   if (!gfi->img && !gfi->image_data && gfi->compressed) {
00481     Gif_UncompressImage(gfi);
00482     release_uncompressed = 1;
00483   }
00484   
00485   /* Create the X image */
00486   ximage =
00487     XCreateImage(gfx->display, gfx->visual, 1,
00488                  XYBitmap, 0, NULL,
00489                  width, height,
00490                  8, 0);
00491   
00492   ximage->bitmap_bit_order = ximage->byte_order = LSBFirst;
00493   bytes_per_line = ximage->bytes_per_line;
00494   xdata = Gif_NewArray(byte, bytes_per_line * height);
00495   ximage->data = (char *)xdata;
00496   
00497   transparent = gfi->transparent;
00498   
00499   /* The main loop */
00500   for (j = 0; j < height; j++) {
00501     int imshift = 0;
00502     u_int32_t impixel = 0;
00503     byte *line = gfi->img[top + j] + left;
00504     byte *writer = xdata + bytes_per_line * j;
00505     
00506     for (i = 0; i < width; i++) {
00507       if (line[i] == transparent)
00508         impixel |= 1 << imshift;
00509       
00510       if (++imshift >= BYTESIZE) {
00511         *writer++ = impixel;
00512         imshift = 0;
00513         impixel = 0;
00514       }
00515     }
00516     
00517     if (imshift)
00518       *writer++ = impixel;
00519   }
00520   
00521   /* Create the pixmap */
00522   pixmap =
00523     XCreatePixmap(gfx->display, gfx->drawable, width, height, 1);
00524   if (!gfx->mask_gc)
00525     gfx->mask_gc = XCreateGC(gfx->display, pixmap, 0, 0);
00526   
00527   if (pixmap && gfx->mask_gc)
00528     XPutImage(gfx->display, pixmap, gfx->mask_gc, ximage, 0, 0, 0, 0,
00529               width, height);
00530   
00531   Gif_DeleteArray(xdata);
00532   ximage->data = 0; /* avoid freeing it again in XDestroyImage */  
00533   XDestroyImage(ximage);
00534 
00535   if (release_uncompressed)
00536     Gif_ReleaseUncompressedImage(gfi);
00537   
00538   return pixmap;
00539 }
00540 
00541 
00542 Pixmap
00543 Gif_XMask(Gif_XContext *gfx, Gif_Stream *gfs, Gif_Image *gfi)
00544 {
00545   if (!gfi && gfs->nimages) gfi = gfs->images[0];
00546   if (!gfi) return None;
00547   return Gif_XSubMask(gfx, gfi, 0, 0, gfi->width, gfi->height);
00548 }
00549 
00550 
00551 Pixmap
00552 Gif_XNextImage(Gif_XContext *gfx, Pixmap last_last, Pixmap last,
00553                Gif_Stream *gfs, int n)
00554 {
00555   Pixmap pixmap = None, image = None, mask = None;
00556   Gif_Image *gfi = gfs->images[n];
00557   Gif_Image *last_gfi = (n > 0 ? gfs->images[n-1] : 0);
00558   Gif_Colormap *gfcm = (gfi->local ? gfi->local : gfs->global);
00559   unsigned long bg_pixel;
00560   unsigned long old_transparent = gfx->transparent_pixel;
00561 
00562   if (gfs->screen_width == 0 || gfs->screen_height == 0)
00563     return None;
00564   
00565   if (gfi->width == gfs->screen_width && gfi->height == gfs->screen_height
00566       && gfi->left == 0 && gfi->top == 0 && gfi->transparent < 0)
00567     return Gif_XImage(gfx, gfs, gfi);
00568   
00569   /* create the pixmap */
00570   pixmap = XCreatePixmap(gfx->display, gfx->drawable,
00571                          gfs->screen_width, gfs->screen_height, gfx->depth);
00572   if (!pixmap) goto error_exit;
00573   
00574   /* find background color if necessary */
00575   if (last == None
00576       || (last_gfi && last_gfi->disposal == GIF_DISPOSAL_BACKGROUND)) {
00577     /* find bg_pixel */
00578     if (gfs->global && gfs->background < gfs->global->ncol
00579         && gfs->images[0]->transparent < 0) {
00580       Gif_XColormap *gfxc = find_x_colormap_extension(gfx, gfcm, 1);
00581       if (!gfxc)
00582         return None;
00583       allocate_colors(gfxc);
00584       bg_pixel = gfxc->pixels[gfs->background];
00585     } else
00586       bg_pixel = old_transparent;
00587     /* install it as the foreground color on gfx->image_gc */
00588     if (!gfx->image_gc)
00589       gfx->image_gc = XCreateGC(gfx->display, pixmap, 0, 0);
00590     if (!gfx->image_gc) goto error_exit;
00591     XSetForeground(gfx->display, gfx->image_gc, bg_pixel);
00592     gfx->transparent_pixel = bg_pixel;
00593   }
00594   
00595   /* if there is no `last' then we need special handling */
00596   if (last == None
00597       || (last_gfi && last_gfi->width == gfs->screen_width
00598           && last_gfi->height == gfs->screen_height
00599           && last_gfi->left == 0 && last_gfi->top == 0
00600           && last_gfi->disposal == GIF_DISPOSAL_BACKGROUND)) {
00601     XFillRectangle(gfx->display, pixmap, gfx->image_gc, 0, 0,
00602                    gfs->screen_width, gfs->screen_height);
00603     if (!put_sub_image_colormap(gfx, gfi, gfcm, 0, 0, gfi->width, gfi->height,
00604                                 pixmap, gfi->left, gfi->top))
00605       goto error_exit;
00606     return pixmap;
00607   }
00608   
00609   /* use the disposal to create the intermediate image */
00610   XCopyArea(gfx->display, last, pixmap, gfx->image_gc,
00611             0, 0, gfs->screen_width, gfs->screen_height, 0, 0);
00612   if (last_last != None && last_gfi->disposal == GIF_DISPOSAL_PREVIOUS)
00613     XCopyArea(gfx->display, last_last, pixmap, gfx->image_gc,
00614               last_gfi->left, last_gfi->top, last_gfi->width, last_gfi->height,
00615               last_gfi->left, last_gfi->top);
00616   else if (last_gfi->disposal == GIF_DISPOSAL_BACKGROUND)
00617     XFillRectangle(gfx->display, pixmap, gfx->image_gc,
00618                    last_gfi->left, last_gfi->top,
00619                    last_gfi->width, last_gfi->height);
00620 
00621   /* apply image */
00622   if (gfi->transparent < 0) {
00623     if (!put_sub_image_colormap(gfx, gfi, gfcm, 0, 0, gfi->width, gfi->height,
00624                                 pixmap, gfi->left, gfi->top))
00625       goto error_exit;
00626   } else {
00627     image = Gif_XImage(gfx, gfs, gfi);
00628     mask = Gif_XMask(gfx, gfs, gfi);
00629     if (image == None || mask == None) goto error_exit;
00630     XSetClipMask(gfx->display, gfx->image_gc, mask);
00631     XSetClipOrigin(gfx->display, gfx->image_gc, gfi->left, gfi->top);
00632     XCopyArea(gfx->display, image, pixmap, gfx->image_gc,
00633               0, 0, gfi->width, gfi->height, gfi->left, gfi->top);
00634     XSetClipMask(gfx->display, gfx->image_gc, None);
00635     XFreePixmap(gfx->display, image);
00636     XFreePixmap(gfx->display, mask);
00637   }
00638   
00639   gfx->transparent_pixel = old_transparent;
00640   return pixmap;
00641   
00642  error_exit:
00643   if (pixmap) XFreePixmap(gfx->display, pixmap);
00644   if (image) XFreePixmap(gfx->display, image);
00645   if (mask) XFreePixmap(gfx->display, mask);
00646   gfx->transparent_pixel = old_transparent;
00647   return None;
00648 }
00649 
00650 
00651 /** CREATING AND DESTROYING XCONTEXTS **/
00652 
00653 static void
00654 delete_xcolormap(Gif_XColormap *gfxc)
00655 {
00656   Gif_XContext *gfx = gfxc->x_context;
00657   Gif_XColormap *prev = 0, *trav = gfx->xcolormap;
00658   while (trav != gfxc && trav) {
00659     prev = trav;
00660     trav = trav->next;
00661   }
00662   if (gfx->free_deleted_colormap_pixels)
00663     deallocate_colors(gfxc);
00664   if (prev) prev->next = gfxc->next;
00665   else gfx->xcolormap = gfxc->next;
00666   Gif_DeleteArray(gfxc->pixels);
00667   Gif_Delete(gfxc);
00668 }
00669 
00670 static void
00671 delete_colormap_hook(int dummy, void *colormap_x, void *callback_x)
00672 {
00673   Gif_Colormap *gfcm = (Gif_Colormap *)colormap_x;
00674   Gif_XContext *gfx = (Gif_XContext *)callback_x;
00675   Gif_XColormap *gfxc;
00676   for (gfxc = gfx->xcolormap; gfxc; gfxc = gfxc->next)
00677     if (gfxc->colormap == gfcm) {
00678       delete_xcolormap(gfxc);
00679       return;
00680     }
00681 }
00682 
00683 
00684 Gif_XContext *
00685 Gif_NewXContextFromVisual(Display *display, int screen_number,
00686                           Visual *visual, int depth, Colormap colormap)
00687 {
00688   Gif_XContext *gfx;
00689   
00690   gfx = Gif_New(Gif_XContext);
00691   gfx->display = display;
00692   gfx->screen_number = screen_number;
00693   gfx->drawable = RootWindow(display, screen_number);
00694   
00695   gfx->visual = visual;
00696   gfx->colormap = colormap;
00697   gfx->ncolormap = visual->map_entries;
00698   gfx->depth = depth;
00699   
00700   gfx->closest = 0;
00701   gfx->nclosest = 0;
00702 
00703   gfx->free_deleted_colormap_pixels = 0;
00704   gfx->xcolormap = 0;
00705 
00706   gfx->image_gc = None;
00707   gfx->mask_gc = None;
00708   
00709   gfx->transparent_pixel = 0UL;
00710   gfx->foreground_pixel = 1UL;
00711   gfx->refcount = 0;
00712 
00713   Gif_AddDeletionHook(GIF_T_COLORMAP, delete_colormap_hook, gfx);
00714   return gfx;
00715 }
00716 
00717 
00718 Gif_XContext *
00719 Gif_NewXContext(Display *display, Window window)
00720 {
00721   XWindowAttributes attr;
00722   XGetWindowAttributes(display, window, &attr);
00723   return Gif_NewXContextFromVisual(display, XScreenNumberOfScreen(attr.screen),
00724                                    attr.visual, attr.depth, attr.colormap);
00725 }
00726 
00727 
00728 void
00729 Gif_DeleteXContext(Gif_XContext *gfx)
00730 {
00731   if (!gfx) return;
00732   if (--gfx->refcount > 0) return;
00733   while (gfx->xcolormap)
00734     delete_xcolormap(gfx->xcolormap);
00735   if (gfx->image_gc)
00736     XFreeGC(gfx->display, gfx->image_gc);
00737   if (gfx->mask_gc)
00738     XFreeGC(gfx->display, gfx->mask_gc);
00739   Gif_DeleteArray(gfx->closest);
00740   Gif_Delete(gfx);
00741   Gif_RemoveDeletionHook(GIF_T_COLORMAP, delete_colormap_hook, gfx);
00742 }
00743 
00744 
00745 #ifdef __cplusplus
00746 }
00747 #endif
 

Powered by Plone

This site conforms to the following standards: