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