00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
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
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
00290 if (!gfi->img && !gfi->image_data && gfi->compressed) {
00291 Gif_UncompressImage(gfi);
00292 release_uncompressed = 1;
00293 }
00294
00295
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
00302
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
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
00334 if (ximage->bits_per_pixel % 8 == 0) {
00335
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
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
00387 if (gfi->transparent >= 0 && gfi->transparent < 256)
00388 pixels[ gfi->transparent ] = saved_transparent;
00389
00390
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;
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
00471 if (!gfi) return None;
00472
00473
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
00480 if (!gfi->img && !gfi->image_data && gfi->compressed) {
00481 Gif_UncompressImage(gfi);
00482 release_uncompressed = 1;
00483 }
00484
00485
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
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
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;
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
00570 pixmap = XCreatePixmap(gfx->display, gfx->drawable,
00571 gfs->screen_width, gfs->screen_height, gfx->depth);
00572 if (!pixmap) goto error_exit;
00573
00574
00575 if (last == None
00576 || (last_gfi && last_gfi->disposal == GIF_DISPOSAL_BACKGROUND)) {
00577
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
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
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
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
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
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