Home | History | Annotate | Line # | Download | only in xditview
      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 *
     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 *
     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
     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 *
     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 *
    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
    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 *
    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 *
    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
    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 *
    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
    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 *
    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
    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
    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
    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 *
    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 *
    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 *
    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