font.c revision 65912f00
1/* 2 * font.c 3 * 4 * map dvi fonts to X fonts 5 */ 6/* $XFree86: xc/programs/xditview/font.c,v 1.5 2001/08/27 23:35:12 dawes Exp $ */ 7 8#include <X11/Xos.h> 9#include <X11/IntrinsicP.h> 10#include <X11/StringDefs.h> 11#include <stdio.h> 12#include <stdlib.h> 13#include <ctype.h> 14#include "DviP.h" 15#include "XFontName.h" 16 17static char * 18savestr (char *s) 19{ 20 char *n; 21 22 if (!s) 23 return NULL; 24 n = XtMalloc (strlen (s) + 1); 25 if (n) 26 strcpy (n, s); 27 return n; 28} 29 30static DviFontList * 31LookupFontByPosition (DviWidget dw, int position) 32{ 33 DviFontList *f; 34 35 for (f = dw->dvi.fonts; f; f=f->next) 36 if (f->dvi_number == position) 37 break; 38 return f; 39} 40 41static DviFontSizeList * 42LookupFontSizeBySize (DviWidget dw, DviFontList *f, int size) 43{ 44 DviFontSizeList *fs, *best = NULL; 45 int bestdist; 46 char fontNameString[2048]; 47 XFontName fontName; 48 unsigned int fontNameAttributes; 49 int dist; 50 51 if (f->scalable) 52 { 53 for (best = f->sizes; best; best = best->next) 54 if (best->size == size) 55 return best; 56 best = (DviFontSizeList *) XtMalloc (sizeof *best); 57 best->next = f->sizes; 58 best->size = size; 59 XParseFontName (f->x_name, &fontName, &fontNameAttributes); 60 fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth); 61 fontNameAttributes |= FontNameResolutionX; 62 fontNameAttributes |= FontNameResolutionY; 63 fontNameAttributes |= FontNamePointSize; 64 fontName.ResolutionX = dw->dvi.screen_resolution; 65 fontName.ResolutionY = dw->dvi.screen_resolution; 66 fontName.PointSize = size * 10 / dw->dvi.size_scale; 67 XFormatFontName (&fontName, fontNameAttributes, fontNameString); 68 best->x_name = savestr (fontNameString); 69#ifdef USE_XFT 70 /* 71 * Force a match of a core font for adobe-fontspecific 72 * encodings; we dont have a scalable font in 73 * the right encoding 74 */ 75 best->core = False; 76 if (!strcmp (fontName.CharSetRegistry, "adobe") && 77 !strcmp (fontName.CharSetEncoding, "fontspecific")) 78 { 79 best->core = True; 80 } 81#endif 82 best->doesnt_exist = 0; 83 best->font = NULL; 84 f->sizes = best; 85 } 86 else 87 { 88 bestdist = 65536; 89 for (fs = f->sizes; fs; fs=fs->next) { 90 dist = size - fs->size; 91 if (dist < 0) 92 dist = -dist * 16; 93 if (dist < bestdist) 94 { 95 best = fs; 96 bestdist = dist; 97 } 98 } 99 } 100 return best; 101} 102 103static char * 104SkipFontNameElement (char *n) 105{ 106 while (*n != '-') 107 if (!*++n) 108 return NULL; 109 return n+1; 110} 111 112# define SizePosition 8 113# define EncodingPosition 13 114 115#ifndef USE_XFT 116static int 117ConvertFontNameToSize (char *n) 118{ 119 int i, size; 120 121 for (i = 0; i < SizePosition; i++) { 122 n = SkipFontNameElement (n); 123 if (!n) 124 return -1; 125 } 126 size = atoi (n); 127 return size/10; 128} 129#endif 130 131static char * 132ConvertFontNameToEncoding (char *n) 133{ 134 int i; 135 for (i = 0; i < EncodingPosition; i++) { 136 n = SkipFontNameElement (n); 137 if (!n) 138 return NULL; 139 } 140 return n; 141} 142 143static void 144DisposeFontSizes (DviWidget dw, DviFontSizeList *fs) 145{ 146 DviFontSizeList *next; 147 148 for (; fs; fs=next) { 149 next = fs->next; 150 if (fs->x_name) 151 XtFree (fs->x_name); 152 if (fs->font) 153 { 154#ifdef USE_XFT 155 XftFontClose (XtDisplay (dw), fs->font); 156#else 157 XUnloadFont (XtDisplay (dw), fs->font->fid); 158 XFree ((char *)fs->font); 159#endif 160 } 161 XtFree ((char *) fs); 162 } 163} 164 165void 166ResetFonts (DviWidget dw) 167{ 168 DviFontList *f; 169 170 for (f = dw->dvi.fonts; f; f = f->next) 171 { 172 if (f->initialized) 173 { 174 DisposeFontSizes (dw, f->sizes); 175 f->sizes = NULL; 176 f->initialized = FALSE; 177 f->scalable = FALSE; 178 } 179 } 180 /* 181 * force requery of fonts 182 */ 183 dw->dvi.font = NULL; 184 dw->dvi.font_number = -1; 185 dw->dvi.cache.font = NULL; 186 dw->dvi.cache.font_number = -1; 187} 188 189static DviFontSizeList * 190InstallFontSizes (DviWidget dw, char *x_name, Boolean *scalablep) 191{ 192#ifndef USE_XFT 193 char fontNameString[2048]; 194 char **fonts; 195 int i, count; 196 int size; 197 DviFontSizeList *new; 198 XFontName fontName; 199 unsigned int fontNameAttributes; 200#endif 201 DviFontSizeList *sizes; 202 203 sizes = NULL; 204#ifdef USE_XFT 205 *scalablep = TRUE; 206#else 207 *scalablep = FALSE; 208 if (!XParseFontName (x_name, &fontName, &fontNameAttributes)) 209 return NULL; 210 211 fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize); 212 fontNameAttributes |= FontNameResolutionX; 213 fontNameAttributes |= FontNameResolutionY; 214 fontName.ResolutionX = dw->dvi.screen_resolution; 215 fontName.ResolutionY = dw->dvi.screen_resolution; 216 XFormatFontName (&fontName, fontNameAttributes, fontNameString); 217 fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count); 218 for (i = 0; i < count; i++) { 219 size = ConvertFontNameToSize (fonts[i]); 220 if (size == 0) 221 { 222 DisposeFontSizes (dw, sizes); 223 *scalablep = TRUE; 224 sizes = NULL; 225 break; 226 } 227 if (size != -1) { 228 new = (DviFontSizeList *) XtMalloc (sizeof *new); 229 new->next = sizes; 230 new->size = size; 231 new->x_name = savestr (fonts[i]); 232 new->doesnt_exist = 0; 233 new->font = NULL; 234 sizes = new; 235 } 236 } 237 XFreeFontNames (fonts); 238#endif 239 return sizes; 240} 241 242static DviFontList * 243InstallFont (DviWidget dw, int position, char *dvi_name, char *x_name) 244{ 245 DviFontList *f; 246 char *encoding; 247 248 f = LookupFontByPosition (dw, position); 249 if (f) { 250 /* 251 * ignore gratuitous font loading 252 */ 253 if (!strcmp (f->dvi_name, dvi_name) && !strcmp (f->x_name, x_name)) 254 return f; 255 256 DisposeFontSizes (dw, f->sizes); 257 if (f->dvi_name) 258 XtFree (f->dvi_name); 259 if (f->x_name) 260 XtFree (f->x_name); 261 } else { 262 f = (DviFontList *) XtMalloc (sizeof (*f)); 263 f->next = dw->dvi.fonts; 264 dw->dvi.fonts = f; 265 } 266 f->initialized = FALSE; 267 f->dvi_name = savestr (dvi_name); 268 f->x_name = savestr (x_name); 269 f->dvi_number = position; 270 f->sizes = NULL; 271 f->scalable = FALSE; 272 if (f->x_name) { 273 encoding = ConvertFontNameToEncoding (f->x_name); 274 f->char_map = DviFindMap (encoding); 275 } else 276 f->char_map = NULL; 277 /* 278 * force requery of fonts 279 */ 280 dw->dvi.font = NULL; 281 dw->dvi.font_number = -1; 282 dw->dvi.cache.font = NULL; 283 dw->dvi.cache.font_number = -1; 284 return f; 285} 286 287static char * 288MapDviNameToXName (DviWidget dw, char *dvi_name) 289{ 290 DviFontMap *fm; 291 292 for (fm = dw->dvi.font_map; fm; fm=fm->next) 293 if (!strcmp (fm->dvi_name, dvi_name)) 294 return fm->x_name; 295 ++dvi_name; 296 for (fm = dw->dvi.font_map; fm; fm=fm->next) 297 if (!strcmp (fm->dvi_name, "R")) 298 return fm->x_name; 299 if (dw->dvi.font_map->x_name) 300 return dw->dvi.font_map->x_name; 301 return "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1"; 302} 303 304#ifdef NOTUSED 305static char * 306MapXNameToDviName (DviWidget dw, char *x_name) 307{ 308 DviFontMap *fm; 309 310 for (fm = dw->dvi.font_map; fm; fm=fm->next) 311 if (!strcmp (fm->x_name, x_name)) 312 return fm->dvi_name; 313 return 0; 314} 315#endif 316 317void 318ParseFontMap (DviWidget dw) 319{ 320 char dvi_name[1024]; 321 char x_name[2048]; 322 char *m, *s; 323 DviFontMap *fm, *new; 324 325 if (dw->dvi.font_map) 326 DestroyFontMap (dw->dvi.font_map); 327 fm = NULL; 328 m = dw->dvi.font_map_string; 329 while (*m) { 330 s = m; 331 while (*m && !isspace (*m)) 332 ++m; 333 strncpy (dvi_name, s, m-s); 334 dvi_name[m-s] = '\0'; 335 while (isspace (*m)) 336 ++m; 337 s = m; 338 while (*m && *m != '\n') 339 ++m; 340 strncpy (x_name, s, m-s); 341 x_name[m-s] = '\0'; 342 new = (DviFontMap *) XtMalloc (sizeof *new); 343 new->x_name = savestr (x_name); 344 new->dvi_name = savestr (dvi_name); 345 new->next = fm; 346 fm = new; 347 ++m; 348 } 349 dw->dvi.font_map = fm; 350} 351 352void 353DestroyFontMap (DviFontMap *font_map) 354{ 355 DviFontMap *next; 356 357 for (; font_map; font_map = next) { 358 next = font_map->next; 359 if (font_map->x_name) 360 XtFree (font_map->x_name); 361 if (font_map->dvi_name) 362 XtFree (font_map->dvi_name); 363 XtFree ((char *) font_map); 364 } 365} 366 367/*ARGSUSED*/ 368void 369SetFontPosition (DviWidget dw, int position, char *dvi_name, char *extra) 370{ 371 char *x_name; 372 373 x_name = MapDviNameToXName (dw, dvi_name); 374 (void) InstallFont (dw, position, dvi_name, x_name); 375} 376 377#ifdef USE_XFT 378XftFont * 379#else 380XFontStruct * 381#endif 382QueryFont (DviWidget dw, int position, int size) 383{ 384 DviFontList *f; 385 DviFontSizeList *fs; 386 387 f = LookupFontByPosition (dw, position); 388 if (!f) 389 return dw->dvi.default_font; 390 if (!f->initialized) { 391 f->sizes = InstallFontSizes (dw, f->x_name, &f->scalable); 392 f->initialized = TRUE; 393 } 394 fs = LookupFontSizeBySize (dw, f, size); 395 if (!fs) 396 return dw->dvi.default_font; 397 if (!fs->font) { 398 if (fs->x_name) 399 { 400#ifdef USE_XFT 401 XftPattern *pat; 402 XftPattern *match; 403 XftResult result; 404 405 pat = XftXlfdParse (fs->x_name, False, False); 406 XftPatternAddBool (pat, XFT_CORE, fs->core); 407 match = XftFontMatch (XtDisplay (dw), 408 XScreenNumberOfScreen(dw->core.screen), 409 pat, &result); 410 XftPatternDestroy (pat); 411 if (match) 412 { 413 fs->font = XftFontOpenPattern (XtDisplay (dw), 414 match); 415 if (!fs->font) 416 XftPatternDestroy (match); 417 } 418 else 419 fs->font = 0; 420#else 421 fs->font = XLoadQueryFont (XtDisplay (dw), fs->x_name); 422#endif 423 } 424 if (!fs->font) 425 fs->font = dw->dvi.default_font; 426 } 427 return fs->font; 428} 429 430DviCharNameMap * 431QueryFontMap (DviWidget dw, int position) 432{ 433 DviFontList *f; 434 435 f = LookupFontByPosition (dw, position); 436 if (f) 437 return f->char_map; 438 else 439 return NULL; 440} 441 442unsigned char * 443DviCharIsLigature (DviCharNameMap *map, char *name) 444{ 445 int i; 446 447 for (i = 0; i < DVI_MAX_LIGATURES; i++) { 448 if (!map->ligatures[i][0]) 449 break; 450 if (!strcmp (name, map->ligatures[i][0])) 451 return (unsigned char *) map->ligatures[i][1]; 452 } 453 return NULL; 454} 455 456#if 0 457LoadFont (DviWidget dw, int position, int size) 458{ 459 XFontStruct *font; 460 461 font = QueryFont (dw, position, size); 462 dw->dvi.font_number = position; 463 dw->dvi.font_size = size; 464 dw->dvi.font = font; 465 XSetFont (XtDisplay (dw), dw->dvi.normal_GC, font->fid); 466 return; 467} 468#endif 469