PageRenderTime 59ms CodeModel.GetById 2ms app.highlight 52ms RepoModel.GetById 2ms app.codeStats 0ms

/contrib/groff/src/devices/xditview/font.c

https://bitbucket.org/freebsd/freebsd-head/
C | 442 lines | 369 code | 48 blank | 25 comment | 70 complexity | 7db2c31c994cb54857c181139d00e13a MD5 | raw file
  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
 16static void DisposeFontSizes(DviWidget, DviFontSizeList *);
 17void DestroyFontMap(DviFontMap *);
 18
 19static char *
 20savestr (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
 32static DviFontList *
 33LookupFontByPosition (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
 43int
 44MaxFontPosition (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
 55static DviFontSizeList *
 56LookupFontSizeBySize (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
100static char *
101SkipFontNameElement (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
112static int
113ConvertFontNameToSize (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
126static char *
127ConvertFontNameToEncoding (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
138DviFontSizeList *
139InstallFontSizes (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
184static void
185DisposeFontSizes (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
201static DviFontList *
202InstallFont (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
251void
252ForgetFonts (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
282static char *
283MapDviNameToXName (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
294static char *
295MapXNameToDviName (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
306void
307ParseFontMap (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
341void
342DestroyFontMap (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
358void
359SetFontPosition (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
371XFontStruct *
372QueryFont (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
396DeviceFont *
397QueryDeviceFont (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
407DviCharNameMap *
408QueryFontMap (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
420LoadFont (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/*
434Local Variables:
435c-indent-level: 8
436c-continued-statement-offset: 8
437c-brace-offset: -8
438c-argdecl-indent: 8
439c-label-offset: -8
440c-tab-always-indent: nil
441End:
442*/