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*/ 443