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 *
savestr(const char * s)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 *
LookupFontByPosition(DviWidget dw,int position)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
MaxFontPosition(DviWidget dw)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 *
LookupFontSizeBySize(DviWidget dw,DviFontList * f,int size)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 *
SkipFontNameElement(char * n)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
ConvertFontNameToSize(char * n)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 *
ConvertFontNameToEncoding(char * n)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 *
InstallFontSizes(DviWidget dw,const char * x_name,Boolean * scalablep)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
DisposeFontSizes(DviWidget dw,DviFontSizeList * fs)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 *
InstallFont(DviWidget dw,int position,const char * dvi_name,const char * x_name)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
ForgetFonts(DviWidget dw)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 *
MapDviNameToXName(DviWidget dw,const char * dvi_name)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
ParseFontMap(DviWidget dw)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
DestroyFontMap(DviFontMap * font_map)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
SetFontPosition(DviWidget dw,int position,const char * dvi_name,const char * extra)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 *
QueryFont(DviWidget dw,int position,int size)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 *
QueryDeviceFont(DviWidget dw,int position)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 *
QueryFontMap(DviWidget dw,int position)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 */
443