xref: /netbsd-src/external/gpl2/groff/dist/src/devices/xditview/font.c (revision 89a07cf815a29524268025a1139fac4c5190f765)
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