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