1/* $NetBSD$ */ 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 18static void DisposeFontSizes(DviWidget, DviFontSizeList *); 19void DestroyFontMap(DviFontMap *); 20 21static char * 22savestr (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 34static DviFontList * 35LookupFontByPosition (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 45int 46MaxFontPosition (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 57static DviFontSizeList * 58LookupFontSizeBySize (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 102static char * 103SkipFontNameElement (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 114static int 115ConvertFontNameToSize (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 128static char * 129ConvertFontNameToEncoding (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 140DviFontSizeList * 141InstallFontSizes (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 186static void 187DisposeFontSizes (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 203static DviFontList * 204InstallFont (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 253void 254ForgetFonts (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 284static char * 285MapDviNameToXName (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 296static char * 297MapXNameToDviName (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 308void 309ParseFontMap (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 343void 344DestroyFontMap (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 360void 361SetFontPosition (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 373XFontStruct * 374QueryFont (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 398DeviceFont * 399QueryDeviceFont (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 409DviCharNameMap * 410QueryFontMap (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 422LoadFont (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/* 436Local Variables: 437c-indent-level: 8 438c-continued-statement-offset: 8 439c-brace-offset: -8 440c-argdecl-indent: 8 441c-label-offset: -8 442c-tab-always-indent: nil 443End: 444*/ 445