~ubuntu-branches/ubuntu/raring/python-scipy/raring-proposed

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-01-07 14:12:12 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070107141212-mm0ebkh5b37hcpzn
* Remove build dependency on python-numpy-dev.
* python-scipy: Depend on python-numpy instead of python-numpy-dev.
* Package builds on other archs than i386. Closes: #402783.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * fonts.c -- $Id: fonts.c,v 1.1 2003/03/08 15:26:51 travo Exp $
3
 
 * font management for X11
4
 
 *
5
 
 * Copyright (c) 1998.  See accompanying LEGAL file for details.
6
 
 */
7
 
 
8
 
/* see README in this directory for explanatory notes */
9
 
 
10
 
#include "config.h"
11
 
#include "playx.h"
12
 
 
13
 
#include "pstdlib.h"
14
 
 
15
 
#include <stdio.h>
16
 
#include <string.h>
17
 
 
18
 
/* x_parse_fonts is semi-private, used only in connect.c */
19
 
extern void x_parse_fonts(x_display *xdpy);
20
 
 
21
 
static int x_substitute(x_display *xdpy, int *font, int *pixsize);
22
 
static void x_analyze(x_display *xdpy, int fam);
23
 
static void tmp_free(void);
24
 
 
25
 
static int x_closest(int pixsize, int *sizes, int nsizes, int *ndx);
26
 
static int x_lookup(int pixsize, int *sizes, int nsizes);
27
 
static char *x_face(char *name, int *face);
28
 
static int x_insert(int pixsize, int *sizes, char **names, int nsizes);
29
 
 
30
 
void
31
 
x_parse_fonts(x_display *xdpy)
32
 
{
33
 
  x_analyze(xdpy, P_COURIER);
34
 
  x_analyze(xdpy, P_TIMES);
35
 
  x_analyze(xdpy, P_HELVETICA);
36
 
  x_analyze(xdpy, P_SYMBOL);
37
 
  x_analyze(xdpy, P_NEWCENTURY);
38
 
}
39
 
 
40
 
static char **tmp_fonts = 0;
41
 
static void
42
 
tmp_free(void)
43
 
{
44
 
  char **tmp = tmp_fonts;
45
 
  if (tmp) {
46
 
    tmp_fonts = 0;
47
 
    XFreeFontNames(tmp);
48
 
  }
49
 
}
50
 
 
51
 
XFontStruct *
52
 
x_font(x_display *xdpy, int font, int pixsize)
53
 
{
54
 
  char nm[128], *name;
55
 
  XFontStruct *f;
56
 
  if (tmp_fonts) tmp_free();
57
 
 
58
 
  if (font>=P_GUI_FONT || font<0 || pixsize<=0 || pixsize>180) {
59
 
    f = xdpy->font;
60
 
 
61
 
  } else {
62
 
    int siz, i, j, pass, *ip, *jp;
63
 
    for (pass=siz=0 ;; pass++) {
64
 
      ip = jp = 0;
65
 
      j = -1;
66
 
      i = xdpy->most_recent;
67
 
      while (i>=0) {
68
 
        if (!xdpy->cached[i].f) {
69
 
          /* handle interrupted unload operation */
70
 
          if (ip) *ip = -1;
71
 
          break;
72
 
        }
73
 
        if (xdpy->cached[i].font==font &&
74
 
            xdpy->cached[i].pixsize==pixsize) {
75
 
          if (ip) {
76
 
            /* CRITICAL section */
77
 
            *ip = xdpy->cached[i].next;
78
 
            xdpy->cached[i].next = xdpy->most_recent;
79
 
            xdpy->most_recent = i;
80
 
          }
81
 
          return xdpy->cached[i].f;
82
 
        }
83
 
        jp = ip;
84
 
        ip = &xdpy->cached[i].next;
85
 
        j = i;
86
 
        i = *ip;
87
 
      }
88
 
      if (pass) break;
89
 
      siz = x_substitute(xdpy, &font, &pixsize);
90
 
      if (font==P_GUI_FONT) return xdpy->font;
91
 
    }
92
 
 
93
 
    /* construct font name */
94
 
    name = xdpy->available[font].names[siz];
95
 
    if (!xdpy->available[font].sizes[siz]) {
96
 
      /* scalable, need to find specific instance */
97
 
      char *pnm = nm;
98
 
      int n = 7;
99
 
      while (n--) while ((*(pnm++)= *(name++))!='-');
100
 
      sprintf(pnm, "%d%n", pixsize, &n);
101
 
      strcpy(pnm+n, name);
102
 
      tmp_fonts = XListFonts(xdpy->dpy, nm, 4, &n);
103
 
      if (n<=0) return xdpy->font;  /* should never happen (X server bug) */
104
 
      strcpy(nm, tmp_fonts[0]);
105
 
      XFreeFontNames(tmp_fonts);
106
 
      tmp_free();
107
 
      name = nm;
108
 
    }
109
 
 
110
 
    /* should be able to load it */
111
 
    f = XLoadQueryFont(xdpy->dpy, name);
112
 
    if (!f) return xdpy->font;      /* should never happen (X server bug) */
113
 
 
114
 
    if (!xdpy->cached[0].f) {
115
 
      /* cache not yet full */
116
 
      for (j=0 ; j<N_FONT_CACHE-1 ; j++)
117
 
        if (xdpy->cached[j+1].f) break;
118
 
    } else {
119
 
      /* cache is full, need to unload one, j is least recent */
120
 
      XFontStruct *fold = xdpy->cached[j].f;
121
 
      xdpy->cached[j].f = 0;
122
 
      if (jp) *jp = -1;   /* jp pointed to j, now least recent */
123
 
      XFreeFont(xdpy->dpy, fold);
124
 
    }
125
 
 
126
 
    xdpy->cached[j].font = font;
127
 
    xdpy->cached[j].pixsize = pixsize;
128
 
    xdpy->cached[j].f = f;
129
 
    xdpy->cached[j].next = xdpy->most_recent;
130
 
    xdpy->most_recent = j;
131
 
  }
132
 
 
133
 
  if (p_signalling) p_abort();
134
 
 
135
 
  return f;
136
 
}
137
 
 
138
 
static int
139
 
x_substitute(x_display *xdpy, int *font, int *pixsize)
140
 
{
141
 
  int fnt = *font;
142
 
  int siz = *pixsize;
143
 
  int face = fnt&(P_BOLD|P_ITALIC);
144
 
 
145
 
  if (!xdpy->available[fnt].nsizes) {
146
 
    fnt ^= face;
147
 
    if (!face || !xdpy->available[fnt].nsizes) {
148
 
      int i;
149
 
      for (i=1 ; i<4 ; i++) if (xdpy->available[fnt|i].nsizes) break;
150
 
      if (i<4) {
151
 
        fnt |= i;
152
 
      } else {
153
 
        if (xdpy->available[P_TIMES|face].nsizes)
154
 
          fnt = P_TIMES|face;
155
 
        else if (xdpy->available[P_NEWCENTURY|face].nsizes)
156
 
          fnt = P_NEWCENTURY|face;
157
 
        else if (xdpy->available[P_HELVETICA|face].nsizes)
158
 
          fnt = P_HELVETICA|face;
159
 
        else if (xdpy->available[P_COURIER|face].nsizes)
160
 
          fnt = P_COURIER|face;
161
 
        else if (face) {
162
 
          if (xdpy->available[P_TIMES].nsizes)
163
 
            fnt = P_TIMES;
164
 
          else if (xdpy->available[P_NEWCENTURY].nsizes)
165
 
            fnt = P_NEWCENTURY;
166
 
          else if (xdpy->available[P_HELVETICA].nsizes)
167
 
            fnt = P_HELVETICA;
168
 
          else if (xdpy->available[P_COURIER].nsizes)
169
 
            fnt = P_COURIER;
170
 
          else
171
 
            fnt = P_GUI_FONT;
172
 
        } else
173
 
          fnt = P_GUI_FONT;
174
 
      }
175
 
    }
176
 
  }
177
 
 
178
 
  if (fnt!=P_GUI_FONT)
179
 
    siz = x_closest(siz, xdpy->available[fnt].sizes,
180
 
                    xdpy->available[fnt].nsizes, &face);
181
 
  else
182
 
    face = -1;
183
 
 
184
 
  *font = fnt;
185
 
  *pixsize = siz;
186
 
 
187
 
  return face;
188
 
}
189
 
 
190
 
/*
191
 
 -foundry-family-wgt-slant-wid--pixels-pts-hres-vres-spacing-avgwid-char-set
192
 
 */
193
 
 
194
 
static char *pattern[5] = {
195
 
  "-*-courier-*-*-normal--*-*-*-*-m-*-iso8859-1",
196
 
  "-*-times-*-*-normal--*-*-*-*-p-*-iso8859-1",
197
 
  "-*-helvetica-*-*-normal--*-*-*-*-p-*-iso8859-1",
198
 
  "-*-symbol-*-*-normal--*-*-*-*-p-*-*-*",
199
 
  "-*-new century schoolbook-*-*-normal--*-*-*-*-p-*-iso8859-1" };
200
 
 
201
 
static void
202
 
x_analyze(x_display *xdpy, int fam)
203
 
{
204
 
  int i, j, n, face, pixsize, nsizes;
205
 
  char *name;
206
 
  if (tmp_fonts) tmp_free();
207
 
  tmp_fonts = XListFonts(xdpy->dpy, pattern[((unsigned int)fam)>>2], 1024, &n);
208
 
 
209
 
  for (i=0 ; i<n ; i++) {
210
 
    name = x_face(tmp_fonts[i], &face);
211
 
    if (!name) continue;
212
 
 
213
 
    /* extract pixels field */
214
 
    pixsize = 0;
215
 
    if (name[0]!='*') while (name[0] && name[0]>='0' && name[0]<='9')
216
 
      pixsize = 10*pixsize + *(name++) - '0';
217
 
    else
218
 
      name++;
219
 
    if (name[0]!='-') continue;
220
 
 
221
 
    /* protect against superlong font names */
222
 
    if (!pixsize && strlen(tmp_fonts[i])>120) continue;
223
 
 
224
 
    face += fam;
225
 
 
226
 
    nsizes = xdpy->available[face].nsizes;
227
 
    if (x_lookup(pixsize, xdpy->available[face].sizes, nsizes)) continue;
228
 
    if (nsizes%12==0) {
229
 
      int *sizes = xdpy->available[face].sizes;
230
 
      char **names = xdpy->available[face].names;
231
 
      xdpy->available[face].sizes = p_realloc(sizes, sizeof(int)*(nsizes+12));
232
 
      if (!xdpy->available[face].sizes) {
233
 
        xdpy->available[face].sizes = sizes;
234
 
        return;
235
 
      }
236
 
      xdpy->available[face].names = p_realloc(names,sizeof(char*)*(nsizes+13));
237
 
      if (!xdpy->available[face].names) {
238
 
        xdpy->available[face].names = names;
239
 
        return;
240
 
      }
241
 
    }
242
 
    j = x_insert(pixsize, xdpy->available[face].sizes,
243
 
                 xdpy->available[face].names, nsizes);
244
 
    xdpy->available[face].nsizes++;
245
 
    if (pixsize) {
246
 
      xdpy->available[face].names[j] = p_strcpy(tmp_fonts[i]);
247
 
    } else {
248
 
      /* scalable font needs wildcard name */
249
 
      char nm[128], *pnm = nm;
250
 
      int n = 7;
251
 
      name = tmp_fonts[i];
252
 
      while (n--) while ((*(pnm++)= *(name++))!='-');
253
 
      /* skip over pixels, points fields */
254
 
      *(pnm++)= '*';   *(pnm++)= '-';  *(pnm++)= '*';   *(pnm++)= '-';
255
 
      for (n=2 ; n-- ;) while (name[0] && *(name++)!='-');
256
 
      /* copy hres, vres, spacing fields */
257
 
      for (n=3 ; n-- ;) while (name[0] && (*(pnm++)= *(name++))!='-');
258
 
      /* skip over average width field */
259
 
      *(pnm++)= '*';   *(pnm++)= '-';
260
 
      while (name[0] && *(name++)!='-');
261
 
      /* copy remainder (character set fields) */
262
 
      while ((*(pnm++)= *(name++)));
263
 
      xdpy->available[face].names[j] = p_strcpy(nm);
264
 
    }
265
 
  }
266
 
 
267
 
  tmp_free();
268
 
}
269
 
 
270
 
static char *
271
 
x_face(char *name, int *face)
272
 
{
273
 
  char *pat = "bold";
274
 
 
275
 
  /* skip to wgt field */
276
 
  int n = 3;
277
 
  while (n--) while (name[0] && *(name++)!='-');
278
 
  *face = 0;
279
 
  if (!name[0]) return 0;
280
 
 
281
 
  /* compare with "bold" -- otherwise assume non-bold */
282
 
  while (name[0] && name[0]==pat[0]) name++, pat++;
283
 
  if (!pat[0] && name[0]=='-') *face |= P_BOLD;
284
 
 
285
 
  /* skip to slant field, compare with "r" -- otherwise assume italic */
286
 
  while (name[0] && *(name++)!='-');
287
 
  if (!name[0] || !name[1]) return 0;
288
 
  if (name[0]!='r' || name[1]!='-') *face |= P_ITALIC;
289
 
 
290
 
  /* skip to pixels field */
291
 
  n = 3;
292
 
  while (n--) while (name[0] &&  *(name++)!='-');
293
 
  return name[0]? name : 0;
294
 
}
295
 
 
296
 
static int
297
 
x_insert(int pixsize, int *sizes, char **names, int nsizes)
298
 
{
299
 
  unsigned int i, j;
300
 
  char *nm;
301
 
  if (!nsizes || sizes[0]>pixsize) {
302
 
    j = 0;
303
 
  } else if (sizes[nsizes-1]<pixsize) {
304
 
    j = nsizes;
305
 
  } else {
306
 
    int k;
307
 
    for (i=0,j=nsizes-1,k=j>>1 ; k!=i ; k=(i+j)>>1) {
308
 
      if (sizes[k]>pixsize) j = k;
309
 
      else i = k;
310
 
    }
311
 
  }
312
 
  names[nsizes+1] = 0; /* see x_disconnect */
313
 
  for (i=nsizes ; i>j ; i--) {
314
 
    sizes[i] = sizes[i-1];
315
 
    nm = names[i-1];
316
 
    names[i-1] = 0;    /* never want two copies of nm in names[] */
317
 
    names[i] = nm;
318
 
  }
319
 
  sizes[j] = pixsize;
320
 
  return j;
321
 
}
322
 
 
323
 
static int
324
 
x_lookup(int pixsize, int *sizes, int nsizes)
325
 
{
326
 
  unsigned int i, j=nsizes-1, k;
327
 
  if (nsizes<=0 || sizes[0]>pixsize || sizes[j]<pixsize) return 0;
328
 
  if (sizes[j]==pixsize) return nsizes;
329
 
  if (!j) return 0;
330
 
  if (sizes[0]==pixsize) return 1;
331
 
  i = 0;
332
 
  for (k=j>>1 ; k!=i ; k=(i+j)>>1) {
333
 
    if (sizes[k]==pixsize) return k+1;
334
 
    if (sizes[k]>pixsize) j = k;
335
 
    else i = k;
336
 
  }
337
 
  return 0;
338
 
}
339
 
 
340
 
static int
341
 
x_closest(int pixsize, int *sizes, int nsizes, int *ndx)
342
 
{
343
 
  unsigned int i, j=nsizes-1, k;
344
 
  if (nsizes<=0 || pixsize<=0) return (*ndx=-1, 0);
345
 
  if (sizes[j]<=pixsize) return (*ndx=j, sizes[j]);
346
 
  else if (sizes[0]>=pixsize) return (*ndx=0, sizes[0]);
347
 
  i = 0;
348
 
  for (k=j>>1 ; k!=i ; k=(i+j)>>1) {
349
 
    if (sizes[k]==pixsize) return (*ndx=k, pixsize);
350
 
    if (sizes[k]>pixsize) j = k;
351
 
    else i = k;
352
 
  }
353
 
  if (pixsize-sizes[i] < sizes[j]-pixsize) return (*ndx=i, sizes[i]);
354
 
  else return (*ndx=j, sizes[j]);
355
 
}