]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/groff/src/devices/xditview/font.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / groff / src / devices / xditview / font.c
1 /*
2  * font.c
3  *
4  * map dvi fonts to X fonts
5  */
6
7 #include <X11/Xos.h>
8 #include <X11/IntrinsicP.h>
9 #include <X11/StringDefs.h>
10 #include <stdio.h>
11 #include <ctype.h>
12 #include <stdlib.h>
13 #include "DviP.h"
14 #include "XFontName.h"
15
16 static void DisposeFontSizes(DviWidget, DviFontSizeList *);
17 void DestroyFontMap(DviFontMap *);
18
19 static char *
20 savestr (const char *s)
21 {
22         char    *n;
23
24         if (!s)
25                 return 0;
26         n = XtMalloc (strlen (s) + 1);
27         if (n)
28                 strcpy (n, s);
29         return n;
30 }
31
32 static DviFontList *
33 LookupFontByPosition (DviWidget dw, int position)
34 {
35         DviFontList     *f;
36
37         for (f = dw->dvi.fonts; f; f = f->next)
38                 if (f->dvi_number == position)
39                         break;
40         return f;
41 }
42
43 int
44 MaxFontPosition (DviWidget dw)
45 {
46         DviFontList     *f;
47         int n = -1;
48
49         for (f = dw->dvi.fonts; f; f = f->next)
50                 if (f->dvi_number > n)
51                         n = f->dvi_number;
52         return n;
53 }
54
55 static DviFontSizeList *
56 LookupFontSizeBySize (DviWidget dw, DviFontList *f, int size)
57 {
58         DviFontSizeList *fs, *best = 0, *smallest = 0;
59         int             bestsize = 0;
60         XFontName       fontName;
61         unsigned int    fontNameAttributes;
62         char            fontNameString[2048];
63         int             decipointsize;
64         
65         if (f->scalable) {
66                 decipointsize = (10*size)/dw->dvi.sizescale;
67                 for (best = f->sizes; best; best = best->next)
68                         if (best->size == decipointsize)
69                                 return best;
70                 best = (DviFontSizeList *) XtMalloc(sizeof *best);
71                 best->next = f->sizes;
72                 best->size = decipointsize;
73                 f->sizes = best;
74                 XParseFontName (f->x_name, &fontName, &fontNameAttributes);
75                 fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth);
76                 fontNameAttributes |= FontNameResolutionX;
77                 fontNameAttributes |= FontNameResolutionY;
78                 fontNameAttributes |= FontNamePointSize;
79                 fontName.ResolutionX = dw->dvi.display_resolution;
80                 fontName.ResolutionY = dw->dvi.display_resolution;
81                 fontName.PointSize = decipointsize;
82                 XFormatFontName (&fontName, fontNameAttributes, fontNameString);
83                 best->x_name = savestr (fontNameString);
84                 best->doesnt_exist = 0;
85                 best->font = 0;
86                 return best;
87         }
88         for (fs = f->sizes; fs; fs=fs->next) {
89                 if (dw->dvi.sizescale*fs->size <= 10*size
90                     && fs->size >= bestsize) {
91                         best = fs;
92                         bestsize = fs->size;
93                 }
94                 if (smallest == 0 || fs->size < smallest->size)
95                         smallest = fs;
96         }
97         return best ? best : smallest;
98 }
99
100 static char *
101 SkipFontNameElement (char *n)
102 {
103         while (*n != '-')
104                 if (!*++n)
105                         return 0;
106         return n+1;
107 }
108
109 # define SizePosition           8
110 # define EncodingPosition       13
111
112 static int
113 ConvertFontNameToSize (char *n)
114 {
115         int     i, size;
116
117         for (i = 0; i < SizePosition; i++) {
118                 n = SkipFontNameElement (n);
119                 if (!n)
120                         return -1;
121         }
122         size = atoi (n);
123         return size;
124 }
125
126 static char *
127 ConvertFontNameToEncoding (char *n)
128 {
129         int i;
130         for (i = 0; i < EncodingPosition; i++) {
131                 n = SkipFontNameElement (n);
132                 if (!n)
133                         return 0;
134         }
135         return n;
136 }
137
138 DviFontSizeList *
139 InstallFontSizes (DviWidget dw, const char *x_name, Boolean *scalablep)
140 {
141         char    fontNameString[2048];
142         char    **fonts;
143         int     i, count;
144         int     size;
145         DviFontSizeList *sizes, *new_size;
146         XFontName       fontName;
147         unsigned int    fontNameAttributes;
148
149         *scalablep = FALSE;
150         if (!XParseFontName ((XFontNameString)x_name, &fontName,
151                              &fontNameAttributes))
152                 return 0;
153         fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize
154                                 |FontNameAverageWidth);
155         fontNameAttributes |= FontNameResolutionX;
156         fontNameAttributes |= FontNameResolutionY;
157         fontName.ResolutionX = dw->dvi.display_resolution;
158         fontName.ResolutionY = dw->dvi.display_resolution;
159         XFormatFontName (&fontName, fontNameAttributes, fontNameString);
160         fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count);
161         sizes = 0;
162         for (i = 0; i < count; i++) {
163                 size = ConvertFontNameToSize (fonts[i]);
164                 if (size == 0) {
165                         DisposeFontSizes (dw, sizes);
166                         sizes = 0;
167                         *scalablep = TRUE;
168                         break;
169                 }
170                 if (size != -1) {
171                         new_size = (DviFontSizeList *) XtMalloc (sizeof *new_size);
172                         new_size->next = sizes;
173                         new_size->size = size;
174                         new_size->x_name = savestr (fonts[i]);
175                         new_size->doesnt_exist = 0;
176                         new_size->font = 0;
177                         sizes = new_size;
178                 }
179         }
180         XFreeFontNames (fonts);
181         return sizes;
182 }
183
184 static void
185 DisposeFontSizes (DviWidget dw, DviFontSizeList *fs)
186 {
187         DviFontSizeList *next;
188
189         for (; fs; fs=next) {
190                 next = fs->next;
191                 if (fs->x_name)
192                         XtFree (fs->x_name);
193                 if (fs->font && fs->font != dw->dvi.default_font) {
194                         XUnloadFont (XtDisplay (dw), fs->font->fid);
195                         XFree ((char *)fs->font);
196                 }
197                 XtFree ((char *) fs);
198         }
199 }
200
201 static DviFontList *
202 InstallFont (DviWidget dw, int position,
203              const char *dvi_name, const char *x_name)
204 {
205         DviFontList     *f;
206         char            *encoding;
207
208         if ((f = LookupFontByPosition (dw, position)) != NULL) {
209                 /*
210                  * ignore gratuitous font loading
211                  */
212                 if (!strcmp (f->dvi_name, dvi_name) &&
213                     !strcmp (f->x_name, x_name))
214                         return f;
215
216                 DisposeFontSizes (dw, f->sizes);
217                 if (f->dvi_name)
218                         XtFree (f->dvi_name);
219                 if (f->x_name)
220                         XtFree (f->x_name);
221                 f->device_font = 0;
222         } else {
223                 f = (DviFontList *) XtMalloc (sizeof (*f));
224                 f->next = dw->dvi.fonts;
225                 dw->dvi.fonts = f;
226         }
227         f->initialized = FALSE;
228         f->dvi_name = savestr (dvi_name);
229         f->device_font = device_find_font (dw->dvi.device, dvi_name);
230         f->x_name = savestr (x_name);
231         f->dvi_number = position;
232         f->sizes = 0;
233         f->scalable = FALSE;
234         if (f->x_name) {
235                 encoding = ConvertFontNameToEncoding (f->x_name);
236                 f->char_map = DviFindMap (encoding);
237         } else
238                 f->char_map = 0;
239         /* 
240          * force requery of fonts
241          */
242         dw->dvi.font = 0;
243         dw->dvi.font_number = -1;
244         dw->dvi.cache.font = 0;
245         dw->dvi.cache.font_number = -1;
246         dw->dvi.device_font = 0;
247         dw->dvi.device_font_number = -1;
248         return f;
249 }
250
251 void
252 ForgetFonts (DviWidget dw)
253 {
254         DviFontList *f = dw->dvi.fonts;
255         
256         while (f) {
257                 DviFontList *tem = f;
258
259                 if (f->sizes)
260                         DisposeFontSizes (dw, f->sizes);
261                 if (f->dvi_name)
262                         XtFree (f->dvi_name);
263                 if (f->x_name)
264                         XtFree (f->x_name);
265                 f = f->next;
266                 XtFree ((char *) tem);
267         }
268         
269         /* 
270          * force requery of fonts
271          */
272         dw->dvi.font = 0;
273         dw->dvi.font_number = -1;
274         dw->dvi.cache.font = 0;
275         dw->dvi.cache.font_number = -1;
276         dw->dvi.device_font = 0;
277         dw->dvi.device_font_number = -1;
278         dw->dvi.fonts = 0;
279 }
280
281
282 static char *
283 MapDviNameToXName (DviWidget dw, const char *dvi_name)
284 {
285         DviFontMap      *fm;
286         
287         for (fm = dw->dvi.font_map; fm; fm=fm->next)
288                 if (!strcmp (fm->dvi_name, dvi_name))
289                         return fm->x_name;
290         return 0;
291 }
292
293 #if 0
294 static char *
295 MapXNameToDviName (DviWidget dw, const char *x_name)
296 {
297         DviFontMap      *fm;
298         
299         for (fm = dw->dvi.font_map; fm; fm=fm->next)
300                 if (!strcmp (fm->x_name, x_name))
301                         return fm->dvi_name;
302         return 0;
303 }
304 #endif
305
306 void
307 ParseFontMap (DviWidget dw)
308 {
309         char            dvi_name[1024];
310         char            x_name[2048];
311         char            *m, *s;
312         DviFontMap      *fm, *new_map;
313
314         if (dw->dvi.font_map)
315                 DestroyFontMap (dw->dvi.font_map);
316         fm = 0;
317         m = dw->dvi.font_map_string;
318         while (*m) {
319                 s = m;
320                 while (*m && !isspace (*m))
321                         ++m;
322                 strncpy (dvi_name, s, m-s);
323                 dvi_name[m-s] = '\0';
324                 while (isspace (*m))
325                         ++m;
326                 s = m;
327                 while (*m && *m != '\n')
328                         ++m;
329                 strncpy (x_name, s, m-s);
330                 x_name[m-s] = '\0';
331                 new_map = (DviFontMap *) XtMalloc (sizeof *new_map);
332                 new_map->x_name = savestr (x_name);
333                 new_map->dvi_name = savestr (dvi_name);
334                 new_map->next = fm;
335                 fm = new_map;
336                 ++m;
337         }
338         dw->dvi.font_map = fm;
339 }
340
341 void
342 DestroyFontMap (DviFontMap *font_map)
343 {
344         DviFontMap      *next;
345
346         for (; font_map; font_map = next) {
347                 next = font_map->next;
348                 if (font_map->x_name)
349                         XtFree (font_map->x_name);
350                 if (font_map->dvi_name)
351                         XtFree (font_map->dvi_name);
352                 XtFree ((char *) font_map);
353         }
354 }
355
356 /* ARGSUSED */
357
358 void
359 SetFontPosition (DviWidget dw, int position,
360                  const char *dvi_name, const char *extra)
361 {
362         char    *x_name;
363
364         x_name = MapDviNameToXName (dw, dvi_name);
365         if (x_name)
366                 (void) InstallFont (dw, position, dvi_name, x_name);
367
368         extra = extra;          /* unused; suppress compiler warning */
369 }
370
371 XFontStruct *
372 QueryFont (DviWidget dw, int position, int size)
373 {
374         DviFontList     *f;
375         DviFontSizeList *fs;
376
377         f = LookupFontByPosition (dw, position);
378         if (!f)
379                 return dw->dvi.default_font;
380         if (!f->initialized) {
381                 f->sizes = InstallFontSizes (dw, f->x_name, &f->scalable);
382                 f->initialized = TRUE;
383         }
384         fs = LookupFontSizeBySize (dw, f, size);
385         if (!fs)
386                 return dw->dvi.default_font;
387         if (!fs->font) {
388                 if (fs->x_name)
389                         fs->font = XLoadQueryFont (XtDisplay (dw), fs->x_name);
390                 if (!fs->font)
391                         fs->font = dw->dvi.default_font;
392         }
393         return fs->font;
394 }
395
396 DeviceFont *
397 QueryDeviceFont (DviWidget dw, int position)
398 {
399         DviFontList     *f;
400
401         f = LookupFontByPosition (dw, position);
402         if (!f)
403                 return 0;
404         return f->device_font;
405 }
406
407 DviCharNameMap *
408 QueryFontMap (DviWidget dw, int position)
409 {
410         DviFontList     *f;
411
412         f = LookupFontByPosition (dw, position);
413         if (f)
414             return f->char_map;
415         else
416             return 0;
417 }
418
419 #if 0
420 LoadFont (DviWidget dw, int position, int size)
421 {
422         XFontStruct     *font;
423
424         font = QueryFont (dw, position, size);
425         dw->dvi.font_number = position;
426         dw->dvi.font_size = size;
427         dw->dvi.font = font;
428         XSetFont (XtDisplay (dw), dw->dvi.normal_GC, font->fid);
429         return;
430 }
431 #endif
432
433 /*
434 Local Variables:
435 c-indent-level: 8
436 c-continued-statement-offset: 8
437 c-brace-offset: -8
438 c-argdecl-indent: 8
439 c-label-offset: -8
440 c-tab-always-indent: nil
441 End:
442 */