o Added color support
[s-roff.git] / src / xditview / font.c
blob8b4114af620fb6946dd1fc713d5d9d0a11a6069e
1 /*
2 * font.c
4 * map dvi fonts to X fonts
5 */
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"
16 static void DisposeFontSizes();
17 void DestroyFontMap();
19 /* XFontName.c */
20 extern Bool XParseFontName();
21 extern Bool XFormatFontName();
23 static char *
24 savestr (s)
25 char *s;
27 char *n;
29 if (!s)
30 return 0;
31 n = XtMalloc (strlen (s) + 1);
32 if (n)
33 strcpy (n, s);
34 return n;
37 static DviFontList *
38 LookupFontByPosition (dw, position)
39 DviWidget dw;
40 int position;
42 DviFontList *f;
44 for (f = dw->dvi.fonts; f; f = f->next)
45 if (f->dvi_number == position)
46 break;
47 return f;
50 int
51 MaxFontPosition (dw)
52 DviWidget dw;
54 DviFontList *f;
55 int n = -1;
57 for (f = dw->dvi.fonts; f; f = f->next)
58 if (f->dvi_number > n)
59 n = f->dvi_number;
60 return n;
63 static DviFontSizeList *
64 LookupFontSizeBySize (dw, f, size)
65 DviWidget dw;
66 DviFontList *f;
67 int size;
69 DviFontSizeList *fs, *best = 0, *smallest = 0;
70 int bestsize = 0;
71 XFontName fontName;
72 unsigned int fontNameAttributes;
73 char fontNameString[2048];
74 int decipointsize;
76 if (f->scalable) {
77 decipointsize = (10*size)/dw->dvi.sizescale;
78 for (best = f->sizes; best; best = best->next)
79 if (best->size == decipointsize)
80 return best;
81 best = (DviFontSizeList *) XtMalloc(sizeof *best);
82 best->next = f->sizes;
83 best->size = decipointsize;
84 f->sizes = best;
85 XParseFontName (f->x_name, &fontName, &fontNameAttributes);
86 fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth);
87 fontNameAttributes |= FontNameResolutionX;
88 fontNameAttributes |= FontNameResolutionY;
89 fontNameAttributes |= FontNamePointSize;
90 fontName.ResolutionX = dw->dvi.display_resolution;
91 fontName.ResolutionY = dw->dvi.display_resolution;
92 fontName.PointSize = decipointsize;
93 XFormatFontName (&fontName, fontNameAttributes, fontNameString);
94 best->x_name = savestr (fontNameString);
95 best->doesnt_exist = 0;
96 best->font = 0;
97 return best;
99 for (fs = f->sizes; fs; fs=fs->next) {
100 if (dw->dvi.sizescale*fs->size <= 10*size
101 && fs->size >= bestsize) {
102 best = fs;
103 bestsize = fs->size;
105 if (smallest == 0 || fs->size < smallest->size)
106 smallest = fs;
108 return best ? best : smallest;
111 static char *
112 SkipFontNameElement (n)
113 char *n;
115 while (*n != '-')
116 if (!*++n)
117 return 0;
118 return n+1;
121 # define SizePosition 8
122 # define EncodingPosition 13
124 static int
125 ConvertFontNameToSize (n)
126 char *n;
128 int i, size;
130 for (i = 0; i < SizePosition; i++) {
131 n = SkipFontNameElement (n);
132 if (!n)
133 return -1;
135 size = atoi (n);
136 return size;
139 static char *
140 ConvertFontNameToEncoding (n)
141 char *n;
143 int i;
144 for (i = 0; i < EncodingPosition; i++) {
145 n = SkipFontNameElement (n);
146 if (!n)
147 return 0;
149 return n;
152 DviFontSizeList *
153 InstallFontSizes (dw, x_name, scalablep)
154 DviWidget dw;
155 char *x_name;
156 Boolean *scalablep;
158 char fontNameString[2048];
159 char **fonts;
160 int i, count;
161 int size;
162 DviFontSizeList *sizes, *new;
163 XFontName fontName;
164 unsigned int fontNameAttributes;
166 *scalablep = FALSE;
167 if (!XParseFontName (x_name, &fontName, &fontNameAttributes))
168 return 0;
169 fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize
170 |FontNameAverageWidth);
171 fontNameAttributes |= FontNameResolutionX;
172 fontNameAttributes |= FontNameResolutionY;
173 fontName.ResolutionX = dw->dvi.display_resolution;
174 fontName.ResolutionY = dw->dvi.display_resolution;
175 XFormatFontName (&fontName, fontNameAttributes, fontNameString);
176 fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count);
177 sizes = 0;
178 for (i = 0; i < count; i++) {
179 size = ConvertFontNameToSize (fonts[i]);
180 if (size == 0) {
181 DisposeFontSizes (dw, sizes);
182 sizes = 0;
183 *scalablep = TRUE;
184 break;
186 if (size != -1) {
187 new = (DviFontSizeList *) XtMalloc (sizeof *new);
188 new->next = sizes;
189 new->size = size;
190 new->x_name = savestr (fonts[i]);
191 new->doesnt_exist = 0;
192 new->font = 0;
193 sizes = new;
196 XFreeFontNames (fonts);
197 return sizes;
200 static void
201 DisposeFontSizes (dw, fs)
202 DviWidget dw;
203 DviFontSizeList *fs;
205 DviFontSizeList *next;
207 for (; fs; fs=next) {
208 next = fs->next;
209 if (fs->x_name)
210 XtFree (fs->x_name);
211 if (fs->font && fs->font != dw->dvi.default_font) {
212 XUnloadFont (XtDisplay (dw), fs->font->fid);
213 XFree ((char *)fs->font);
215 XtFree ((char *) fs);
219 static DviFontList *
220 InstallFont (dw, position, dvi_name, x_name)
221 DviWidget dw;
222 int position;
223 char *dvi_name;
224 char *x_name;
226 DviFontList *f;
227 char *encoding;
229 if ((f = LookupFontByPosition (dw, position)) != NULL) {
231 * ignore gratuitous font loading
233 if (!strcmp (f->dvi_name, dvi_name) &&
234 !strcmp (f->x_name, x_name))
235 return f;
237 DisposeFontSizes (dw, f->sizes);
238 if (f->dvi_name)
239 XtFree (f->dvi_name);
240 if (f->x_name)
241 XtFree (f->x_name);
242 f->device_font = 0;
243 } else {
244 f = (DviFontList *) XtMalloc (sizeof (*f));
245 f->next = dw->dvi.fonts;
246 dw->dvi.fonts = f;
248 f->initialized = FALSE;
249 f->dvi_name = savestr (dvi_name);
250 f->device_font = device_find_font (dw->dvi.device, dvi_name);
251 f->x_name = savestr (x_name);
252 f->dvi_number = position;
253 f->sizes = 0;
254 f->scalable = FALSE;
255 if (f->x_name) {
256 encoding = ConvertFontNameToEncoding (f->x_name);
257 f->char_map = DviFindMap (encoding);
258 } else
259 f->char_map = 0;
261 * force requery of fonts
263 dw->dvi.font = 0;
264 dw->dvi.font_number = -1;
265 dw->dvi.cache.font = 0;
266 dw->dvi.cache.font_number = -1;
267 dw->dvi.device_font = 0;
268 dw->dvi.device_font_number = -1;
269 return f;
272 void
273 ForgetFonts (dw)
274 DviWidget dw;
276 DviFontList *f = dw->dvi.fonts;
278 while (f) {
279 DviFontList *tem = f;
281 if (f->sizes)
282 DisposeFontSizes (dw, f->sizes);
283 if (f->dvi_name)
284 XtFree (f->dvi_name);
285 if (f->x_name)
286 XtFree (f->x_name);
287 f = f->next;
288 XtFree ((char *) tem);
292 * force requery of fonts
294 dw->dvi.font = 0;
295 dw->dvi.font_number = -1;
296 dw->dvi.cache.font = 0;
297 dw->dvi.cache.font_number = -1;
298 dw->dvi.device_font = 0;
299 dw->dvi.device_font_number = -1;
300 dw->dvi.fonts = 0;
304 static char *
305 MapDviNameToXName (dw, dvi_name)
306 DviWidget dw;
307 char *dvi_name;
309 DviFontMap *fm;
311 for (fm = dw->dvi.font_map; fm; fm=fm->next)
312 if (!strcmp (fm->dvi_name, dvi_name))
313 return fm->x_name;
314 return 0;
317 #if 0
318 static char *
319 MapXNameToDviName (dw, x_name)
320 DviWidget dw;
321 char *x_name;
323 DviFontMap *fm;
325 for (fm = dw->dvi.font_map; fm; fm=fm->next)
326 if (!strcmp (fm->x_name, x_name))
327 return fm->dvi_name;
328 return 0;
330 #endif
332 void
333 ParseFontMap (dw)
334 DviWidget dw;
336 char dvi_name[1024];
337 char x_name[2048];
338 char *m, *s;
339 DviFontMap *fm, *new;
341 if (dw->dvi.font_map)
342 DestroyFontMap (dw->dvi.font_map);
343 fm = 0;
344 m = dw->dvi.font_map_string;
345 while (*m) {
346 s = m;
347 while (*m && !isspace (*m))
348 ++m;
349 strncpy (dvi_name, s, m-s);
350 dvi_name[m-s] = '\0';
351 while (isspace (*m))
352 ++m;
353 s = m;
354 while (*m && *m != '\n')
355 ++m;
356 strncpy (x_name, s, m-s);
357 x_name[m-s] = '\0';
358 new = (DviFontMap *) XtMalloc (sizeof *new);
359 new->x_name = savestr (x_name);
360 new->dvi_name = savestr (dvi_name);
361 new->next = fm;
362 fm = new;
363 ++m;
365 dw->dvi.font_map = fm;
368 void
369 DestroyFontMap (font_map)
370 DviFontMap *font_map;
372 DviFontMap *next;
374 for (; font_map; font_map = next) {
375 next = font_map->next;
376 if (font_map->x_name)
377 XtFree (font_map->x_name);
378 if (font_map->dvi_name)
379 XtFree (font_map->dvi_name);
380 XtFree ((char *) font_map);
384 /* ARGSUSED */
386 void
387 SetFontPosition (dw, position, dvi_name, extra)
388 DviWidget dw;
389 int position;
390 char *dvi_name;
391 char *extra; /* unused */
393 char *x_name;
395 x_name = MapDviNameToXName (dw, dvi_name);
396 if (x_name)
397 (void) InstallFont (dw, position, dvi_name, x_name);
400 XFontStruct *
401 QueryFont (dw, position, size)
402 DviWidget dw;
403 int position;
404 int size;
406 DviFontList *f;
407 DviFontSizeList *fs;
409 f = LookupFontByPosition (dw, position);
410 if (!f)
411 return dw->dvi.default_font;
412 if (!f->initialized) {
413 f->sizes = InstallFontSizes (dw, f->x_name, &f->scalable);
414 f->initialized = TRUE;
416 fs = LookupFontSizeBySize (dw, f, size);
417 if (!fs)
418 return dw->dvi.default_font;
419 if (!fs->font) {
420 if (fs->x_name)
421 fs->font = XLoadQueryFont (XtDisplay (dw), fs->x_name);
422 if (!fs->font)
423 fs->font = dw->dvi.default_font;
425 return fs->font;
428 DeviceFont *
429 QueryDeviceFont (dw, position)
430 DviWidget dw;
431 int position;
433 DviFontList *f;
435 f = LookupFontByPosition (dw, position);
436 if (!f)
437 return 0;
438 return f->device_font;
441 DviCharNameMap *
442 QueryFontMap (dw, position)
443 DviWidget dw;
444 int position;
446 DviFontList *f;
448 f = LookupFontByPosition (dw, position);
449 if (f)
450 return f->char_map;
451 else
452 return 0;
455 #if 0
456 LoadFont (dw, position, size)
457 DviWidget dw;
458 int position;
459 int size;
461 XFontStruct *font;
463 font = QueryFont (dw, position, size);
464 dw->dvi.font_number = position;
465 dw->dvi.font_size = size;
466 dw->dvi.font = font;
467 XSetFont (XtDisplay (dw), dw->dvi.normal_GC, font->fid);
468 return;
470 #endif
473 Local Variables:
474 c-indent-level: 8
475 c-continued-statement-offset: 8
476 c-brace-offset: -8
477 c-argdecl-indent: 8
478 c-label-offset: -8
479 c-tab-always-indent: nil
480 End: