~ubuntu-branches/ubuntu/karmic/python-scipy/karmic

« back to all changes in this revision

Viewing changes to Lib/xplt/src/play/x11/pals.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T. Chen (new)
  • Date: 2005-03-16 02:15:29 UTC
  • Revision ID: james.westby@ubuntu.com-20050316021529-xrjlowsejs0cijig
Tags: upstream-0.3.2
ImportĀ upstreamĀ versionĀ 0.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * pals.c -- $Id: pals.c,v 1.1 2003/03/08 15:26:51 travo Exp $
 
3
 * palette handling for X11
 
4
 *
 
5
 * Copyright (c) 1998.  See accompanying LEGAL file for details.
 
6
 */
 
7
 
 
8
#include "config.h"
 
9
#include "playx.h"
 
10
#include "pstdlib.h"
 
11
 
 
12
static int x_use_shared(p_scr *s, p_col_t color, p_col_t *pixel);
 
13
static void x_lose_shared(p_scr *s, p_col_t *pixels, int n);
 
14
static void x_all_shared(p_scr *s, XColor *map /*[256]*/);
 
15
static p_col_t x_best_shared(p_scr *s, p_col_t color,
 
16
                             XColor *map, int n);
 
17
static void x_cavailable(void *p, p_hashkey key, void *ctx);
 
18
static void x_list_dead(void *p, p_hashkey key, void *ctx);
 
19
static void x_find_dead(void *p, p_hashkey key, void *ctx);
 
20
static void x_mark_shared(void *p);
 
21
 
 
22
void
 
23
p_palette(p_win *w, p_col_t *colors, int n)
 
24
{
 
25
  p_scr *s = w->s;
 
26
  p_col_t r, g, b;
 
27
  int i;
 
28
  if (n>240) n = 240;
 
29
 
 
30
  if (w->parent) w = w->parent;  /* pixmap uses parent palette */
 
31
  s->gc_color = -1;
 
32
 
 
33
  if (s->vclass==TrueColor || s->vclass==DirectColor) {
 
34
    for (i=0 ; i<n ; i++) {
 
35
      r = P_R(colors[i]);
 
36
      g = P_G(colors[i]);
 
37
      b = P_B(colors[i]);
 
38
      w->pixels[i] = (s->pixels[r]&s->rmask) |
 
39
        (s->pixels[g]&s->gmask) | (s->pixels[b]&s->bmask);
 
40
    }
 
41
    w->n_palette = n;
 
42
 
 
43
  } else if (s->vclass!=PseudoColor) {
 
44
    for (i=0 ; i<n ; i++) {
 
45
      r = P_R(colors[i]);
 
46
      g = P_G(colors[i]);
 
47
      b = P_B(colors[i]);
 
48
      w->pixels[i] = s->pixels[(r+g+b)/3];
 
49
    }
 
50
    w->n_palette = n;
 
51
 
 
52
  } else if (w->rgb_pixels) {
 
53
    for (i=0 ; i<n ; i++) {
 
54
      r = P_R(colors[i]);
 
55
      g = P_G(colors[i]);
 
56
      b = P_B(colors[i]);
 
57
      r = (r+32)>>6;
 
58
      g = (g+16)>>5;
 
59
      b = (b+32)>>6;
 
60
      g += b+(b<<3);
 
61
      w->pixels[i] = w->rgb_pixels[r+g+(g<<2)];  /* r + 5*g * 45*b */
 
62
    }
 
63
    w->n_palette = n;
 
64
 
 
65
  } else {
 
66
    XColor c;
 
67
    int p;
 
68
    p_col_t fg_pixel = s->colors[1].pixel;
 
69
    Display *dpy = s->xdpy->dpy;
 
70
    Visual *visual = DefaultVisual(dpy,s->scr_num);
 
71
    int map_size = visual->map_entries;
 
72
    if (map_size>256) map_size = 256;
 
73
 
 
74
    if (w->cmap==None) {
 
75
      /* this window uses default colormap (read-only shared colors) */
 
76
      int n_old = w->n_palette;
 
77
 
 
78
      /* (1) free our use of existing colors */
 
79
      w->n_palette = 0;
 
80
      x_lose_shared(s, w->pixels, n_old);
 
81
      for (i=0 ; i<n_old ; i++) w->pixels[i] = fg_pixel;
 
82
      if (n<=0) return;
 
83
 
 
84
      /* (2) go for it, but prudently ask in bit reversed order */
 
85
      for (i=0 ; i<256 ; i++) {
 
86
        p = p_bit_rev[i];
 
87
        if (p>=n) continue;
 
88
        if (!x_use_shared(s, colors[p], &w->pixels[p])) break;
 
89
        w->n_palette++;
 
90
      }
 
91
 
 
92
      /* (3) fallback if didn't get full request */
 
93
      if (w->n_palette<n) {
 
94
        XColor map[256];
 
95
        int nsh;
 
96
 
 
97
        /* query all colors, reserving a use of all sharable colors */
 
98
        x_all_shared(s, map);
 
99
        for (nsh=0 ; nsh<256 ; nsh++) {
 
100
          if (map[nsh].flags) break;
 
101
          map[nsh].red =   (map[nsh].red  >>8)&0xff;
 
102
          map[nsh].green = (map[nsh].green>>8)&0xff;
 
103
          map[nsh].blue =  (map[nsh].blue >>8)&0xff;
 
104
        }
 
105
 
 
106
        /* take closest sharable pixel to those requested
 
107
         * - allocate extra uses for colors used more than once */
 
108
        for (; i<256 ; i++) {
 
109
          p = p_bit_rev[i];
 
110
          if (p>=n) continue;
 
111
          w->pixels[p] = x_best_shared(s, colors[p], map, nsh);
 
112
          w->n_palette++;
 
113
        }
 
114
 
 
115
        /* release shared colors we didn't ever use */
 
116
        x_lose_shared(s, (p_col_t *)0, 0);
 
117
      }
 
118
 
 
119
    } else {
 
120
      /* this window has a private colormap (read-write private colors) */
 
121
      char used[256];
 
122
 
 
123
      /* private colormaps will flash display when they are installed
 
124
       * take two steps to minimize the annoyance:
 
125
       * (1) be sure to allocate the 16 standard colors
 
126
       *     s->colors[0:15] the same as default cmap on screen
 
127
       *     -- x_color algorithm fails without this,
 
128
       *        done when cmap created
 
129
       * (2) allocate palette colors from top down, since most
 
130
       *     X servers seem to pass out colors from bottom up and
 
131
       *     important permanent apps (window manager) started first
 
132
       *     -- allocate colors at bottom same as in default cmap */
 
133
      for (i=0 ; i<map_size ; i++) used[i] = 0;
 
134
      for (i=0 ; i<16 ; i++)
 
135
        if (s->colors[i].pixel<map_size) used[s->colors[i].pixel] = 1;
 
136
      for (p=map_size-1,i=0 ; p>=0 && i<n ; p--) {
 
137
        if (used[p]) continue;
 
138
        c.pixel = w->pixels[i] = p;
 
139
        c.red = P_R(colors[i]) << 8;
 
140
        c.green = P_G(colors[i]) << 8;
 
141
        c.blue = P_B(colors[i]) << 8;
 
142
        i++;
 
143
        c.flags = DoRed | DoGreen | DoBlue;
 
144
        XStoreColor(dpy, w->cmap, &c);
 
145
      }
 
146
      for (; i<240 ; i++) w->pixels[i] = fg_pixel;
 
147
      if (p>=0) {
 
148
        /* restore as much of the default colormap as possible */
 
149
        Colormap cmap = DefaultColormap(dpy,s->scr_num);
 
150
        XColor map[256];
 
151
        for (i=0 ; i<=p ; i++) map[i].pixel = i;
 
152
        XQueryColors(dpy, cmap, map, p+1);
 
153
        for (i=0 ; i<=p ; i++) {
 
154
          if (used[i]) continue;
 
155
          map[i].flags = DoRed | DoGreen | DoBlue;
 
156
          XStoreColor(dpy, w->cmap, &map[i]);
 
157
        }
 
158
      }
 
159
      w->n_palette = n;
 
160
    }
 
161
  }
 
162
  if (p_signalling) p_abort();
 
163
}
 
164
 
 
165
int
 
166
x_rgb_palette(p_win *w)
 
167
{
 
168
  if (w->parent) w = w->parent;
 
169
  if (!w->rgb_pixels) {
 
170
    p_scr *s = w->s;
 
171
    p_col_t *pixels;
 
172
    int i;
 
173
    if (s->vclass!=PseudoColor) return 0;
 
174
 
 
175
    /* would be friendlier to translate preexisting
 
176
     * palette, but nuking it is far simpler */
 
177
    p_palette(w, p_595, 225);
 
178
    x_tmpzap(&s->tmp);
 
179
    pixels = s->tmp = p_malloc(sizeof(p_col_t)*256);
 
180
    if (!pixels) return 0;
 
181
    for (i=0 ; i<256 ; i++) pixels[i] = w->pixels[i];
 
182
    s->tmp = 0;
 
183
    w->rgb_pixels = pixels;
 
184
    p_palette(w, (p_col_t *)0, 0);
 
185
  }
 
186
  return 1;
 
187
}
 
188
 
 
189
/*------------------------------------------------------------------------*/
 
190
 
 
191
struct x_cshared {
 
192
  unsigned long *usepxl;   /* [uses,pixel] for each pixel */
 
193
  unsigned long nextpxl;   /* index into next free usepxl pair */
 
194
  p_hashtab *bypixel;      /* returns usepxl index given pixel value */
 
195
  p_hashtab *bycolor;      /* returns usepxl index given color value */
 
196
  /* note: bypixel hash table is unnecessary if we were guaranteed
 
197
   *    that the pixel values are <256 for PseudoColor displays,
 
198
   *    as I assume in a few places (e.g.- x_all_shared below)
 
199
   *    - nevertheless, it ensures that x_use_shared, x_lose_shared
 
200
   *      and x_nuke_shared work for all possible X servers
 
201
   */
 
202
};
 
203
 
 
204
struct x_deadpix {
 
205
  unsigned long list[256], keys[256];
 
206
  int n, m;
 
207
  x_cshared *shared;
 
208
};
 
209
struct x_c2pix {
 
210
  XColor *map;
 
211
  int n;
 
212
};
 
213
 
 
214
static int
 
215
x_use_shared(p_scr *s, p_col_t color, p_col_t *pixel)
 
216
{
 
217
  x_cshared *shared = s->shared;
 
218
  p_hashkey colkey = P_IHASH(color);
 
219
  unsigned long *usepxl;
 
220
 
 
221
  usepxl = p_hfind(shared->bycolor, colkey);
 
222
 
 
223
  if (!usepxl) {
 
224
    Display *dpy = s->xdpy->dpy;
 
225
    Colormap cmap = DefaultColormap(dpy, s->scr_num);
 
226
    p_hashkey pixkey;
 
227
    XColor c;
 
228
    unsigned long nextpxl = shared->nextpxl;
 
229
    if (nextpxl>=512) return 0;      /* only provide for 256 shared colors */
 
230
    c.red = P_R(color) << 8;
 
231
    c.green = P_G(color) << 8;
 
232
    c.blue = P_B(color) << 8;
 
233
    if (!XAllocColor(dpy, cmap, &c)) return 0; /* default colormap is full */
 
234
    pixkey = P_IHASH(c.pixel);
 
235
    usepxl = p_hfind(shared->bypixel, pixkey);
 
236
    if (usepxl) {                  /* different colors may give same pixel */
 
237
      XFreeColors(dpy, cmap, &c.pixel, 1, 0UL);
 
238
      p_hinsert(shared->bycolor, colkey, usepxl);
 
239
    } else {
 
240
      usepxl = shared->usepxl + nextpxl;
 
241
      shared->nextpxl = usepxl[0];
 
242
      usepxl[0] = 0;     /* this will be first use */
 
243
      usepxl[1] = c.pixel;
 
244
      p_hinsert(shared->bypixel, pixkey, usepxl);
 
245
      p_hinsert(shared->bycolor, colkey, usepxl);
 
246
    }
 
247
  }
 
248
 
 
249
  usepxl[0]++;
 
250
  *pixel = usepxl[1];
 
251
  return 1;
 
252
}
 
253
 
 
254
static void
 
255
x_lose_shared(p_scr *s, p_col_t *pixels, int n)
 
256
{
 
257
  x_cshared *shared = s->shared;
 
258
  unsigned long *usepxl;
 
259
  struct x_deadpix deadpix;
 
260
  int i;
 
261
 
 
262
  if (!shared) {
 
263
    shared = p_malloc(sizeof(x_cshared));
 
264
    if (!shared) return;
 
265
    shared->bycolor = p_halloc(256);
 
266
    shared->bypixel = p_halloc(256);
 
267
    shared->usepxl = p_malloc(sizeof(unsigned long)*512);
 
268
    if (!shared->bycolor || !shared->usepxl) return;
 
269
    shared->nextpxl = 0;
 
270
    for (i=0 ; i<512 ; i+=2) shared->usepxl[i] = i+2;
 
271
    s->shared = shared;
 
272
  }
 
273
 
 
274
  while ((n--)>0) {
 
275
    usepxl = p_hfind(shared->bypixel, P_IHASH(pixels[n]));
 
276
    if (usepxl && usepxl[0]) usepxl[0]--;
 
277
  }
 
278
  deadpix.shared = shared;
 
279
  deadpix.n = deadpix.m = 0;
 
280
  p_hiter(shared->bycolor, &x_find_dead, &deadpix);
 
281
  for (i=0 ; i<deadpix.m ; i++)
 
282
    p_hinsert(shared->bycolor, deadpix.keys[i], (void*)0);
 
283
  p_hiter(shared->bypixel, &x_list_dead, &deadpix); /* also unlinks */
 
284
  for (i=0 ; i<deadpix.n ; i++)
 
285
    p_hinsert(shared->bypixel, P_IHASH(deadpix.list[i]), (void*)0);
 
286
  if (deadpix.n) {
 
287
    Display *dpy = s->xdpy->dpy;
 
288
    XFreeColors(dpy, DefaultColormap(dpy,s->scr_num),
 
289
                deadpix.list, deadpix.n, 0UL);
 
290
  }
 
291
}
 
292
 
 
293
static void
 
294
x_all_shared(p_scr *s, XColor *map /*[256]*/)
 
295
{
 
296
  x_cshared *shared = s->shared;
 
297
  if (shared) {
 
298
    int i, n;
 
299
    unsigned long *usepxl;
 
300
    struct x_c2pix available;
 
301
    Display *dpy = s->xdpy->dpy;
 
302
    Colormap cmap = DefaultColormap(dpy,s->scr_num);
 
303
    Visual *visual = DefaultVisual(dpy,s->scr_num);
 
304
    int map_size = visual->map_entries;
 
305
    if (map_size>256) map_size = 256;
 
306
 
 
307
    for (i=n=0 ; i<map_size ; i++)
 
308
      if (!p_hfind(shared->bypixel, P_IHASH(i)))
 
309
        map[n++].pixel = i;
 
310
    if (!n) return;       /* we already own all shared colors */
 
311
 
 
312
    XQueryColors(dpy, cmap, map, n);
 
313
    for (i=0 ; i<n ; i++)
 
314
      if (XAllocColor(dpy, cmap, &map[i])) {
 
315
        /* this color is sharable, record in bypixel table
 
316
         * -includes the standard colors */
 
317
        usepxl = shared->usepxl + shared->nextpxl;
 
318
        shared->nextpxl = usepxl[0];
 
319
        usepxl[0] = 0;     /* we haven't actually used it yet */
 
320
        usepxl[1] = map[i].pixel;
 
321
        p_hinsert(shared->bypixel, P_IHASH(map[i].pixel), usepxl);
 
322
        if (shared->nextpxl>=512) break;
 
323
      }
 
324
    available.map = map;
 
325
    available.n = 0;
 
326
    p_hiter(shared->bypixel, &x_cavailable, &available);
 
327
    XQueryColors(dpy, cmap, map, available.n);
 
328
    for (i=0 ; i<available.n ; i++) map[i].flags = 0;
 
329
    if (i<256) map[i].flags = 1;
 
330
  }
 
331
}
 
332
 
 
333
static p_col_t
 
334
x_best_shared(p_scr *s, p_col_t color, XColor *map, int n)
 
335
{
 
336
  unsigned long *usepxl;
 
337
  long d1, d0, tmp;
 
338
  int j, k;
 
339
  int r = P_R(color);
 
340
  int g = P_G(color);
 
341
  int b = P_B(color);
 
342
  d0 = 3*256*256;
 
343
  for (k=j=0 ; k<n ; k++) {
 
344
    d1 =  ((tmp = map[k].red   - r), tmp*tmp);
 
345
    d1 += ((tmp = map[k].green - g), tmp*tmp);
 
346
    d1 += ((tmp = map[k].blue  - b), tmp*tmp);
 
347
    if (d1<d0) j = k, d0 = d1;
 
348
  }
 
349
  usepxl = p_hfind(s->shared->bypixel, P_IHASH(map[j].pixel));
 
350
  usepxl[0]++;
 
351
  return usepxl[1];
 
352
}
 
353
 
 
354
void
 
355
x_nuke_shared(p_scr *s)
 
356
{
 
357
  x_cshared *shared = s->shared;
 
358
  if (shared) {
 
359
    unsigned long *usepxl = shared->usepxl;
 
360
    void (*noaction)(void *)= 0;
 
361
    Display *dpy = s->xdpy->dpy;
 
362
    int i, n;
 
363
    s->shared = 0;
 
364
    p_hfree(shared->bypixel, noaction);
 
365
    p_hfree(shared->bycolor, &x_mark_shared);
 
366
    for (i=n=0 ; i<512 ; i+=2)
 
367
      if (usepxl[i]==1) usepxl[n++] = usepxl[i+1];
 
368
    if (n)
 
369
      XFreeColors(dpy, DefaultColormap(dpy,s->scr_num), usepxl, n, 0UL);
 
370
    p_free(usepxl);
 
371
    p_free(shared);
 
372
  }
 
373
  if (p_signalling) p_abort();
 
374
}
 
375
 
 
376
/* ARGSUSED */
 
377
static void
 
378
x_cavailable(void *p, p_hashkey key, void *ctx)
 
379
{
 
380
  unsigned long *usepxl = p;
 
381
  struct x_c2pix *available = ctx;
 
382
  available->map[available->n++].pixel = usepxl[1];
 
383
}
 
384
 
 
385
/* ARGSUSED */
 
386
static void
 
387
x_list_dead(void *p, p_hashkey key, void *ctx)
 
388
{
 
389
  unsigned long *usepxl = p;
 
390
  if (!usepxl[0]) {
 
391
    struct x_deadpix *deadpix = ctx;
 
392
    deadpix->list[deadpix->n++] = usepxl[1];
 
393
    usepxl[0] = deadpix->shared->nextpxl;
 
394
    deadpix->shared->nextpxl = usepxl - deadpix->shared->usepxl;
 
395
  }
 
396
}
 
397
 
 
398
static void
 
399
x_find_dead(void *p, p_hashkey key, void *ctx)
 
400
{
 
401
  unsigned long *usepxl = p;
 
402
  if (!usepxl[0]) {
 
403
    struct x_deadpix *deadpix = ctx;
 
404
    deadpix->keys[deadpix->m++] = key;
 
405
  }
 
406
}
 
407
 
 
408
static void
 
409
x_mark_shared(void *p)
 
410
{
 
411
  unsigned long *usepxl = p;
 
412
  usepxl[0] = 1;  /* 1 cannot be in nextpxl free list (always even) */
 
413
}