1151497Sru/*
2151497Sru * font.c
3151497Sru *
4151497Sru * map dvi fonts to X fonts
5151497Sru */
6151497Sru
7151497Sru#include <X11/Xos.h>
8151497Sru#include <X11/IntrinsicP.h>
9151497Sru#include <X11/StringDefs.h>
10151497Sru#include <stdio.h>
11151497Sru#include <ctype.h>
12151497Sru#include <stdlib.h>
13151497Sru#include "DviP.h"
14151497Sru#include "XFontName.h"
15151497Sru
16151497Srustatic void DisposeFontSizes(DviWidget, DviFontSizeList *);
17151497Sruvoid DestroyFontMap(DviFontMap *);
18151497Sru
19151497Srustatic char *
20151497Srusavestr (const char *s)
21151497Sru{
22151497Sru	char	*n;
23151497Sru
24151497Sru	if (!s)
25151497Sru		return 0;
26151497Sru	n = XtMalloc (strlen (s) + 1);
27151497Sru	if (n)
28151497Sru		strcpy (n, s);
29151497Sru	return n;
30151497Sru}
31151497Sru
32151497Srustatic DviFontList *
33151497SruLookupFontByPosition (DviWidget dw, int position)
34151497Sru{
35151497Sru	DviFontList	*f;
36151497Sru
37151497Sru	for (f = dw->dvi.fonts; f; f = f->next)
38151497Sru		if (f->dvi_number == position)
39151497Sru			break;
40151497Sru	return f;
41151497Sru}
42151497Sru
43151497Sruint
44151497SruMaxFontPosition (DviWidget dw)
45151497Sru{
46151497Sru	DviFontList	*f;
47151497Sru	int n = -1;
48151497Sru
49151497Sru	for (f = dw->dvi.fonts; f; f = f->next)
50151497Sru		if (f->dvi_number > n)
51151497Sru			n = f->dvi_number;
52151497Sru	return n;
53151497Sru}
54151497Sru
55151497Srustatic DviFontSizeList *
56151497SruLookupFontSizeBySize (DviWidget dw, DviFontList *f, int size)
57151497Sru{
58151497Sru	DviFontSizeList	*fs, *best = 0, *smallest = 0;
59151497Sru	int		bestsize = 0;
60151497Sru	XFontName	fontName;
61151497Sru	unsigned int    fontNameAttributes;
62151497Sru	char	    	fontNameString[2048];
63151497Sru	int		decipointsize;
64151497Sru
65151497Sru	if (f->scalable) {
66151497Sru		decipointsize = (10*size)/dw->dvi.sizescale;
67151497Sru		for (best = f->sizes; best; best = best->next)
68151497Sru			if (best->size == decipointsize)
69151497Sru				return best;
70151497Sru		best = (DviFontSizeList *) XtMalloc(sizeof *best);
71151497Sru		best->next = f->sizes;
72151497Sru		best->size = decipointsize;
73151497Sru		f->sizes = best;
74151497Sru		XParseFontName (f->x_name, &fontName, &fontNameAttributes);
75151497Sru		fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth);
76151497Sru		fontNameAttributes |= FontNameResolutionX;
77151497Sru		fontNameAttributes |= FontNameResolutionY;
78151497Sru		fontNameAttributes |= FontNamePointSize;
79151497Sru		fontName.ResolutionX = dw->dvi.display_resolution;
80151497Sru		fontName.ResolutionY = dw->dvi.display_resolution;
81151497Sru		fontName.PointSize = decipointsize;
82151497Sru		XFormatFontName (&fontName, fontNameAttributes, fontNameString);
83151497Sru		best->x_name = savestr (fontNameString);
84151497Sru		best->doesnt_exist = 0;
85151497Sru		best->font = 0;
86151497Sru		return best;
87151497Sru	}
88151497Sru	for (fs = f->sizes; fs; fs=fs->next) {
89151497Sru		if (dw->dvi.sizescale*fs->size <= 10*size
90151497Sru		    && fs->size >= bestsize) {
91151497Sru			best = fs;
92151497Sru			bestsize = fs->size;
93151497Sru		}
94151497Sru		if (smallest == 0 || fs->size < smallest->size)
95151497Sru			smallest = fs;
96151497Sru	}
97151497Sru	return best ? best : smallest;
98151497Sru}
99151497Sru
100151497Srustatic char *
101151497SruSkipFontNameElement (char *n)
102151497Sru{
103151497Sru	while (*n != '-')
104151497Sru		if (!*++n)
105151497Sru			return 0;
106151497Sru	return n+1;
107151497Sru}
108151497Sru
109151497Sru# define SizePosition		8
110151497Sru# define EncodingPosition	13
111151497Sru
112151497Srustatic int
113151497SruConvertFontNameToSize (char *n)
114151497Sru{
115151497Sru	int	i, size;
116151497Sru
117151497Sru	for (i = 0; i < SizePosition; i++) {
118151497Sru		n = SkipFontNameElement (n);
119151497Sru		if (!n)
120151497Sru			return -1;
121151497Sru	}
122151497Sru	size = atoi (n);
123151497Sru	return size;
124151497Sru}
125151497Sru
126151497Srustatic char *
127151497SruConvertFontNameToEncoding (char *n)
128151497Sru{
129151497Sru        int i;
130151497Sru	for (i = 0; i < EncodingPosition; i++) {
131151497Sru		n = SkipFontNameElement (n);
132151497Sru		if (!n)
133151497Sru			return 0;
134151497Sru	}
135151497Sru	return n;
136151497Sru}
137151497Sru
138151497SruDviFontSizeList *
139151497SruInstallFontSizes (DviWidget dw, const char *x_name, Boolean *scalablep)
140151497Sru{
141151497Sru	char	fontNameString[2048];
142151497Sru	char	**fonts;
143151497Sru	int	i, count;
144151497Sru	int	size;
145151497Sru	DviFontSizeList	*sizes, *new_size;
146151497Sru	XFontName	fontName;
147151497Sru	unsigned int	fontNameAttributes;
148151497Sru
149151497Sru	*scalablep = FALSE;
150151497Sru	if (!XParseFontName ((XFontNameString)x_name, &fontName,
151151497Sru			     &fontNameAttributes))
152151497Sru		return 0;
153151497Sru	fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize
154151497Sru				|FontNameAverageWidth);
155151497Sru	fontNameAttributes |= FontNameResolutionX;
156151497Sru	fontNameAttributes |= FontNameResolutionY;
157151497Sru	fontName.ResolutionX = dw->dvi.display_resolution;
158151497Sru	fontName.ResolutionY = dw->dvi.display_resolution;
159151497Sru	XFormatFontName (&fontName, fontNameAttributes, fontNameString);
160151497Sru	fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count);
161151497Sru	sizes = 0;
162151497Sru	for (i = 0; i < count; i++) {
163151497Sru		size = ConvertFontNameToSize (fonts[i]);
164151497Sru		if (size == 0) {
165151497Sru			DisposeFontSizes (dw, sizes);
166151497Sru			sizes = 0;
167151497Sru			*scalablep = TRUE;
168151497Sru			break;
169151497Sru		}
170151497Sru		if (size != -1) {
171151497Sru			new_size = (DviFontSizeList *) XtMalloc (sizeof *new_size);
172151497Sru			new_size->next = sizes;
173151497Sru			new_size->size = size;
174151497Sru			new_size->x_name = savestr (fonts[i]);
175151497Sru			new_size->doesnt_exist = 0;
176151497Sru			new_size->font = 0;
177151497Sru			sizes = new_size;
178151497Sru		}
179151497Sru	}
180151497Sru	XFreeFontNames (fonts);
181151497Sru	return sizes;
182151497Sru}
183151497Sru
184151497Srustatic void
185151497SruDisposeFontSizes (DviWidget dw, DviFontSizeList *fs)
186151497Sru{
187151497Sru	DviFontSizeList	*next;
188151497Sru
189151497Sru	for (; fs; fs=next) {
190151497Sru		next = fs->next;
191151497Sru		if (fs->x_name)
192151497Sru			XtFree (fs->x_name);
193151497Sru		if (fs->font && fs->font != dw->dvi.default_font) {
194151497Sru			XUnloadFont (XtDisplay (dw), fs->font->fid);
195151497Sru			XFree ((char *)fs->font);
196151497Sru		}
197151497Sru		XtFree ((char *) fs);
198151497Sru	}
199151497Sru}
200151497Sru
201151497Srustatic DviFontList *
202151497SruInstallFont (DviWidget dw, int position,
203151497Sru	     const char *dvi_name, const char *x_name)
204151497Sru{
205151497Sru	DviFontList	*f;
206151497Sru	char		*encoding;
207151497Sru
208151497Sru	if ((f = LookupFontByPosition (dw, position)) != NULL) {
209151497Sru		/*
210151497Sru		 * ignore gratuitous font loading
211151497Sru		 */
212151497Sru		if (!strcmp (f->dvi_name, dvi_name) &&
213151497Sru		    !strcmp (f->x_name, x_name))
214151497Sru			return f;
215151497Sru
216151497Sru		DisposeFontSizes (dw, f->sizes);
217151497Sru		if (f->dvi_name)
218151497Sru			XtFree (f->dvi_name);
219151497Sru		if (f->x_name)
220151497Sru			XtFree (f->x_name);
221151497Sru		f->device_font = 0;
222151497Sru	} else {
223151497Sru		f = (DviFontList *) XtMalloc (sizeof (*f));
224151497Sru		f->next = dw->dvi.fonts;
225151497Sru		dw->dvi.fonts = f;
226151497Sru	}
227151497Sru	f->initialized = FALSE;
228151497Sru	f->dvi_name = savestr (dvi_name);
229151497Sru	f->device_font = device_find_font (dw->dvi.device, dvi_name);
230151497Sru	f->x_name = savestr (x_name);
231151497Sru	f->dvi_number = position;
232151497Sru	f->sizes = 0;
233151497Sru	f->scalable = FALSE;
234151497Sru	if (f->x_name) {
235151497Sru		encoding = ConvertFontNameToEncoding (f->x_name);
236151497Sru		f->char_map = DviFindMap (encoding);
237151497Sru	} else
238151497Sru		f->char_map = 0;
239151497Sru	/*
240151497Sru	 * force requery of fonts
241151497Sru	 */
242151497Sru	dw->dvi.font = 0;
243151497Sru	dw->dvi.font_number = -1;
244151497Sru	dw->dvi.cache.font = 0;
245151497Sru	dw->dvi.cache.font_number = -1;
246151497Sru	dw->dvi.device_font = 0;
247151497Sru	dw->dvi.device_font_number = -1;
248151497Sru	return f;
249151497Sru}
250151497Sru
251151497Sruvoid
252151497SruForgetFonts (DviWidget dw)
253151497Sru{
254151497Sru	DviFontList *f = dw->dvi.fonts;
255151497Sru
256151497Sru	while (f) {
257151497Sru		DviFontList *tem = f;
258151497Sru
259151497Sru		if (f->sizes)
260151497Sru			DisposeFontSizes (dw, f->sizes);
261151497Sru		if (f->dvi_name)
262151497Sru			XtFree (f->dvi_name);
263151497Sru		if (f->x_name)
264151497Sru			XtFree (f->x_name);
265151497Sru		f = f->next;
266151497Sru		XtFree ((char *) tem);
267151497Sru	}
268151497Sru
269151497Sru	/*
270151497Sru	 * force requery of fonts
271151497Sru	 */
272151497Sru	dw->dvi.font = 0;
273151497Sru	dw->dvi.font_number = -1;
274151497Sru	dw->dvi.cache.font = 0;
275151497Sru	dw->dvi.cache.font_number = -1;
276151497Sru	dw->dvi.device_font = 0;
277151497Sru	dw->dvi.device_font_number = -1;
278151497Sru	dw->dvi.fonts = 0;
279151497Sru}
280151497Sru
281151497Sru
282151497Srustatic char *
283151497SruMapDviNameToXName (DviWidget dw, const char *dvi_name)
284151497Sru{
285151497Sru	DviFontMap	*fm;
286151497Sru
287151497Sru	for (fm = dw->dvi.font_map; fm; fm=fm->next)
288151497Sru		if (!strcmp (fm->dvi_name, dvi_name))
289151497Sru			return fm->x_name;
290151497Sru	return 0;
291151497Sru}
292151497Sru
293151497Sru#if 0
294151497Srustatic char *
295151497SruMapXNameToDviName (DviWidget dw, const char *x_name)
296151497Sru{
297151497Sru	DviFontMap	*fm;
298151497Sru
299151497Sru	for (fm = dw->dvi.font_map; fm; fm=fm->next)
300151497Sru		if (!strcmp (fm->x_name, x_name))
301151497Sru			return fm->dvi_name;
302151497Sru	return 0;
303151497Sru}
304151497Sru#endif
305151497Sru
306151497Sruvoid
307151497SruParseFontMap (DviWidget dw)
308151497Sru{
309151497Sru	char		dvi_name[1024];
310151497Sru	char		x_name[2048];
311151497Sru	char		*m, *s;
312151497Sru	DviFontMap	*fm, *new_map;
313151497Sru
314151497Sru	if (dw->dvi.font_map)
315151497Sru		DestroyFontMap (dw->dvi.font_map);
316151497Sru	fm = 0;
317151497Sru	m = dw->dvi.font_map_string;
318151497Sru	while (*m) {
319151497Sru		s = m;
320151497Sru		while (*m && !isspace (*m))
321151497Sru			++m;
322151497Sru		strncpy (dvi_name, s, m-s);
323151497Sru		dvi_name[m-s] = '\0';
324151497Sru		while (isspace (*m))
325151497Sru			++m;
326151497Sru		s = m;
327151497Sru		while (*m && *m != '\n')
328151497Sru			++m;
329151497Sru		strncpy (x_name, s, m-s);
330151497Sru		x_name[m-s] = '\0';
331151497Sru		new_map = (DviFontMap *) XtMalloc (sizeof *new_map);
332151497Sru		new_map->x_name = savestr (x_name);
333151497Sru		new_map->dvi_name = savestr (dvi_name);
334151497Sru		new_map->next = fm;
335151497Sru		fm = new_map;
336151497Sru		++m;
337151497Sru	}
338151497Sru	dw->dvi.font_map = fm;
339151497Sru}
340151497Sru
341151497Sruvoid
342151497SruDestroyFontMap (DviFontMap *font_map)
343151497Sru{
344151497Sru	DviFontMap	*next;
345151497Sru
346151497Sru	for (; font_map; font_map = next) {
347151497Sru		next = font_map->next;
348151497Sru		if (font_map->x_name)
349151497Sru			XtFree (font_map->x_name);
350151497Sru		if (font_map->dvi_name)
351151497Sru			XtFree (font_map->dvi_name);
352151497Sru		XtFree ((char *) font_map);
353151497Sru	}
354151497Sru}
355151497Sru
356151497Sru/* ARGSUSED */
357151497Sru
358151497Sruvoid
359151497SruSetFontPosition (DviWidget dw, int position,
360151497Sru		 const char *dvi_name, const char *extra)
361151497Sru{
362151497Sru	char	*x_name;
363151497Sru
364151497Sru	x_name = MapDviNameToXName (dw, dvi_name);
365151497Sru	if (x_name)
366151497Sru		(void) InstallFont (dw, position, dvi_name, x_name);
367151497Sru
368151497Sru	extra = extra;		/* unused; suppress compiler warning */
369151497Sru}
370151497Sru
371151497SruXFontStruct *
372151497SruQueryFont (DviWidget dw, int position, int size)
373151497Sru{
374151497Sru	DviFontList	*f;
375151497Sru	DviFontSizeList	*fs;
376151497Sru
377151497Sru	f = LookupFontByPosition (dw, position);
378151497Sru	if (!f)
379151497Sru		return dw->dvi.default_font;
380151497Sru	if (!f->initialized) {
381151497Sru		f->sizes = InstallFontSizes (dw, f->x_name, &f->scalable);
382151497Sru		f->initialized = TRUE;
383151497Sru	}
384151497Sru	fs = LookupFontSizeBySize (dw, f, size);
385151497Sru	if (!fs)
386151497Sru		return dw->dvi.default_font;
387151497Sru	if (!fs->font) {
388151497Sru		if (fs->x_name)
389151497Sru			fs->font = XLoadQueryFont (XtDisplay (dw), fs->x_name);
390151497Sru		if (!fs->font)
391151497Sru			fs->font = dw->dvi.default_font;
392151497Sru	}
393151497Sru	return fs->font;
394151497Sru}
395151497Sru
396151497SruDeviceFont *
397151497SruQueryDeviceFont (DviWidget dw, int position)
398151497Sru{
399151497Sru	DviFontList	*f;
400151497Sru
401151497Sru	f = LookupFontByPosition (dw, position);
402151497Sru	if (!f)
403151497Sru		return 0;
404151497Sru	return f->device_font;
405151497Sru}
406151497Sru
407151497SruDviCharNameMap *
408151497SruQueryFontMap (DviWidget dw, int position)
409151497Sru{
410151497Sru	DviFontList	*f;
411151497Sru
412151497Sru	f = LookupFontByPosition (dw, position);
413151497Sru	if (f)
414151497Sru	    return f->char_map;
415151497Sru	else
416151497Sru	    return 0;
417151497Sru}
418151497Sru
419151497Sru#if 0
420151497SruLoadFont (DviWidget dw, int position, int size)
421151497Sru{
422151497Sru	XFontStruct	*font;
423151497Sru
424151497Sru	font = QueryFont (dw, position, size);
425151497Sru	dw->dvi.font_number = position;
426151497Sru	dw->dvi.font_size = size;
427151497Sru	dw->dvi.font = font;
428151497Sru	XSetFont (XtDisplay (dw), dw->dvi.normal_GC, font->fid);
429151497Sru	return;
430151497Sru}
431151497Sru#endif
432151497Sru
433151497Sru/*
434151497SruLocal Variables:
435151497Sruc-indent-level: 8
436151497Sruc-continued-statement-offset: 8
437151497Sruc-brace-offset: -8
438151497Sruc-argdecl-indent: 8
439151497Sruc-label-offset: -8
440151497Sruc-tab-always-indent: nil
441151497SruEnd:
442151497Sru*/
443