font.c revision 8c7c3c7e
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{ 438c7c3c7eSmrg DviFontSizeList *best = NULL; 44f80a6dcdSmrg 45f80a6dcdSmrg if (f->scalable) 46f80a6dcdSmrg { 478c7c3c7eSmrg char fontNameString[2048]; 488c7c3c7eSmrg XFontName fontName; 498c7c3c7eSmrg unsigned int fontNameAttributes; 508c7c3c7eSmrg 51f80a6dcdSmrg for (best = f->sizes; best; best = best->next) 52f80a6dcdSmrg if (best->size == size) 53f80a6dcdSmrg return best; 54f80a6dcdSmrg best = (DviFontSizeList *) XtMalloc (sizeof *best); 55f80a6dcdSmrg best->next = f->sizes; 56f80a6dcdSmrg best->size = size; 57f80a6dcdSmrg XParseFontName (f->x_name, &fontName, &fontNameAttributes); 58f80a6dcdSmrg fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth); 59f80a6dcdSmrg fontNameAttributes |= FontNameResolutionX; 60f80a6dcdSmrg fontNameAttributes |= FontNameResolutionY; 61f80a6dcdSmrg fontNameAttributes |= FontNamePointSize; 62f80a6dcdSmrg fontName.ResolutionX = dw->dvi.screen_resolution; 63f80a6dcdSmrg fontName.ResolutionY = dw->dvi.screen_resolution; 64f80a6dcdSmrg fontName.PointSize = size * 10 / dw->dvi.size_scale; 65f80a6dcdSmrg XFormatFontName (&fontName, fontNameAttributes, fontNameString); 66f80a6dcdSmrg best->x_name = savestr (fontNameString); 67f80a6dcdSmrg#ifdef USE_XFT 68f80a6dcdSmrg /* 69f80a6dcdSmrg * Force a match of a core font for adobe-fontspecific 708c7c3c7eSmrg * encodings; we don't have a scalable font in 71f80a6dcdSmrg * the right encoding 72f80a6dcdSmrg */ 73f80a6dcdSmrg best->core = False; 74f80a6dcdSmrg if (!strcmp (fontName.CharSetRegistry, "adobe") && 75f80a6dcdSmrg !strcmp (fontName.CharSetEncoding, "fontspecific")) 76f80a6dcdSmrg { 77f80a6dcdSmrg best->core = True; 78f80a6dcdSmrg } 79f80a6dcdSmrg#endif 80f80a6dcdSmrg best->doesnt_exist = 0; 8165912f00Smrg best->font = NULL; 82f80a6dcdSmrg f->sizes = best; 83f80a6dcdSmrg } 84f80a6dcdSmrg else 85f80a6dcdSmrg { 868c7c3c7eSmrg int bestdist = 65536; 878c7c3c7eSmrg 888c7c3c7eSmrg for (DviFontSizeList *fs = f->sizes; fs; fs=fs->next) { 898c7c3c7eSmrg int 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{ 1338c7c3c7eSmrg for (int i = 0; i < EncodingPosition; i++) { 134f80a6dcdSmrg n = SkipFontNameElement (n); 135f80a6dcdSmrg if (!n) 13665912f00Smrg return NULL; 137f80a6dcdSmrg } 138f80a6dcdSmrg return n; 139f80a6dcdSmrg} 140f80a6dcdSmrg 141f80a6dcdSmrgstatic void 142f80a6dcdSmrgDisposeFontSizes (DviWidget dw, DviFontSizeList *fs) 143f80a6dcdSmrg{ 144f80a6dcdSmrg DviFontSizeList *next; 145f80a6dcdSmrg 146f80a6dcdSmrg for (; fs; fs=next) { 147f80a6dcdSmrg next = fs->next; 148f80a6dcdSmrg if (fs->x_name) 149f80a6dcdSmrg XtFree (fs->x_name); 150f80a6dcdSmrg if (fs->font) 151f80a6dcdSmrg { 152f80a6dcdSmrg#ifdef USE_XFT 153f80a6dcdSmrg XftFontClose (XtDisplay (dw), fs->font); 154f80a6dcdSmrg#else 155f80a6dcdSmrg XUnloadFont (XtDisplay (dw), fs->font->fid); 156f80a6dcdSmrg XFree ((char *)fs->font); 157f80a6dcdSmrg#endif 158f80a6dcdSmrg } 159f80a6dcdSmrg XtFree ((char *) fs); 160f80a6dcdSmrg } 161f80a6dcdSmrg} 162f80a6dcdSmrg 163f80a6dcdSmrgvoid 164f80a6dcdSmrgResetFonts (DviWidget dw) 165f80a6dcdSmrg{ 1668c7c3c7eSmrg for (DviFontList *f = dw->dvi.fonts; f; f = f->next) 167f80a6dcdSmrg { 168f80a6dcdSmrg if (f->initialized) 169f80a6dcdSmrg { 170f80a6dcdSmrg DisposeFontSizes (dw, f->sizes); 17165912f00Smrg f->sizes = NULL; 172f80a6dcdSmrg f->initialized = FALSE; 173f80a6dcdSmrg f->scalable = FALSE; 174f80a6dcdSmrg } 175f80a6dcdSmrg } 176f80a6dcdSmrg /* 177f80a6dcdSmrg * force requery of fonts 178f80a6dcdSmrg */ 17965912f00Smrg dw->dvi.font = NULL; 180f80a6dcdSmrg dw->dvi.font_number = -1; 18165912f00Smrg dw->dvi.cache.font = NULL; 182f80a6dcdSmrg dw->dvi.cache.font_number = -1; 183f80a6dcdSmrg} 184f80a6dcdSmrg 185f80a6dcdSmrgstatic DviFontSizeList * 186f80a6dcdSmrgInstallFontSizes (DviWidget dw, char *x_name, Boolean *scalablep) 187f80a6dcdSmrg{ 188f80a6dcdSmrg#ifndef USE_XFT 189f80a6dcdSmrg char fontNameString[2048]; 190f80a6dcdSmrg char **fonts; 1918c7c3c7eSmrg int count; 192f80a6dcdSmrg XFontName fontName; 193f80a6dcdSmrg unsigned int fontNameAttributes; 194f80a6dcdSmrg#endif 195f80a6dcdSmrg DviFontSizeList *sizes; 196f80a6dcdSmrg 19765912f00Smrg sizes = NULL; 198f80a6dcdSmrg#ifdef USE_XFT 199f80a6dcdSmrg *scalablep = TRUE; 200f80a6dcdSmrg#else 201f80a6dcdSmrg *scalablep = FALSE; 202f80a6dcdSmrg if (!XParseFontName (x_name, &fontName, &fontNameAttributes)) 20365912f00Smrg return NULL; 204f80a6dcdSmrg 205f80a6dcdSmrg fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize); 206f80a6dcdSmrg fontNameAttributes |= FontNameResolutionX; 207f80a6dcdSmrg fontNameAttributes |= FontNameResolutionY; 208f80a6dcdSmrg fontName.ResolutionX = dw->dvi.screen_resolution; 209f80a6dcdSmrg fontName.ResolutionY = dw->dvi.screen_resolution; 210f80a6dcdSmrg XFormatFontName (&fontName, fontNameAttributes, fontNameString); 211f80a6dcdSmrg fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count); 2128c7c3c7eSmrg for (int i = 0; i < count; i++) { 2138c7c3c7eSmrg int size = ConvertFontNameToSize (fonts[i]); 2148c7c3c7eSmrg 215f80a6dcdSmrg if (size == 0) 216f80a6dcdSmrg { 217f80a6dcdSmrg DisposeFontSizes (dw, sizes); 218f80a6dcdSmrg *scalablep = TRUE; 21965912f00Smrg sizes = NULL; 220f80a6dcdSmrg break; 221f80a6dcdSmrg } 222f80a6dcdSmrg if (size != -1) { 2238c7c3c7eSmrg DviFontSizeList *new = (DviFontSizeList *) XtMalloc (sizeof *new); 224f80a6dcdSmrg new->next = sizes; 225f80a6dcdSmrg new->size = size; 226f80a6dcdSmrg new->x_name = savestr (fonts[i]); 227f80a6dcdSmrg new->doesnt_exist = 0; 22865912f00Smrg new->font = NULL; 229f80a6dcdSmrg sizes = new; 230f80a6dcdSmrg } 231f80a6dcdSmrg } 232f80a6dcdSmrg XFreeFontNames (fonts); 233f80a6dcdSmrg#endif 234f80a6dcdSmrg return sizes; 235f80a6dcdSmrg} 236f80a6dcdSmrg 237f80a6dcdSmrgstatic DviFontList * 238c166fba9SmrgInstallFont (DviWidget dw, int position, const char *dvi_name, const char *x_name) 239f80a6dcdSmrg{ 240f80a6dcdSmrg DviFontList *f; 241f80a6dcdSmrg 242f80a6dcdSmrg f = LookupFontByPosition (dw, position); 243f80a6dcdSmrg if (f) { 244f80a6dcdSmrg /* 245f80a6dcdSmrg * ignore gratuitous font loading 246f80a6dcdSmrg */ 247f80a6dcdSmrg if (!strcmp (f->dvi_name, dvi_name) && !strcmp (f->x_name, x_name)) 248f80a6dcdSmrg return f; 249f80a6dcdSmrg 250f80a6dcdSmrg DisposeFontSizes (dw, f->sizes); 251f80a6dcdSmrg if (f->dvi_name) 252f80a6dcdSmrg XtFree (f->dvi_name); 253f80a6dcdSmrg if (f->x_name) 254f80a6dcdSmrg XtFree (f->x_name); 255f80a6dcdSmrg } else { 256f80a6dcdSmrg f = (DviFontList *) XtMalloc (sizeof (*f)); 257f80a6dcdSmrg f->next = dw->dvi.fonts; 258f80a6dcdSmrg dw->dvi.fonts = f; 259f80a6dcdSmrg } 260f80a6dcdSmrg f->initialized = FALSE; 261f80a6dcdSmrg f->dvi_name = savestr (dvi_name); 262f80a6dcdSmrg f->x_name = savestr (x_name); 263f80a6dcdSmrg f->dvi_number = position; 26465912f00Smrg f->sizes = NULL; 265f80a6dcdSmrg f->scalable = FALSE; 266f80a6dcdSmrg if (f->x_name) { 2678c7c3c7eSmrg const char *encoding = ConvertFontNameToEncoding (f->x_name); 268f80a6dcdSmrg f->char_map = DviFindMap (encoding); 269f80a6dcdSmrg } else 27065912f00Smrg f->char_map = NULL; 271f80a6dcdSmrg /* 272f80a6dcdSmrg * force requery of fonts 273f80a6dcdSmrg */ 27465912f00Smrg dw->dvi.font = NULL; 275f80a6dcdSmrg dw->dvi.font_number = -1; 27665912f00Smrg dw->dvi.cache.font = NULL; 277f80a6dcdSmrg dw->dvi.cache.font_number = -1; 278f80a6dcdSmrg return f; 279f80a6dcdSmrg} 280f80a6dcdSmrg 281c166fba9Smrgstatic const char * 282c166fba9SmrgMapDviNameToXName (DviWidget dw, const char *dvi_name) 283f80a6dcdSmrg{ 284f80a6dcdSmrg DviFontMap *fm; 285f80a6dcdSmrg 286f80a6dcdSmrg for (fm = dw->dvi.font_map; fm; fm=fm->next) 287f80a6dcdSmrg if (!strcmp (fm->dvi_name, dvi_name)) 288f80a6dcdSmrg return fm->x_name; 289f80a6dcdSmrg ++dvi_name; 290f80a6dcdSmrg for (fm = dw->dvi.font_map; fm; fm=fm->next) 291f80a6dcdSmrg if (!strcmp (fm->dvi_name, "R")) 292f80a6dcdSmrg return fm->x_name; 293f80a6dcdSmrg if (dw->dvi.font_map->x_name) 294f80a6dcdSmrg return dw->dvi.font_map->x_name; 295f80a6dcdSmrg return "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1"; 296f80a6dcdSmrg} 297f80a6dcdSmrg 298f80a6dcdSmrg 299f80a6dcdSmrgvoid 30065912f00SmrgParseFontMap (DviWidget dw) 301f80a6dcdSmrg{ 3028c7c3c7eSmrg char *m; 3038c7c3c7eSmrg DviFontMap *fm; 304f80a6dcdSmrg 305f80a6dcdSmrg if (dw->dvi.font_map) 306f80a6dcdSmrg DestroyFontMap (dw->dvi.font_map); 30765912f00Smrg fm = NULL; 308f80a6dcdSmrg m = dw->dvi.font_map_string; 309f80a6dcdSmrg while (*m) { 3108c7c3c7eSmrg char dvi_name[1024]; 3118c7c3c7eSmrg char x_name[2048]; 3128c7c3c7eSmrg 3138c7c3c7eSmrg char *s = m; 314f80a6dcdSmrg while (*m && !isspace (*m)) 315f80a6dcdSmrg ++m; 316f80a6dcdSmrg strncpy (dvi_name, s, m-s); 317f80a6dcdSmrg dvi_name[m-s] = '\0'; 318f80a6dcdSmrg while (isspace (*m)) 319f80a6dcdSmrg ++m; 320f80a6dcdSmrg s = m; 321f80a6dcdSmrg while (*m && *m != '\n') 322f80a6dcdSmrg ++m; 323f80a6dcdSmrg strncpy (x_name, s, m-s); 324f80a6dcdSmrg x_name[m-s] = '\0'; 3258c7c3c7eSmrg 3268c7c3c7eSmrg DviFontMap *new = (DviFontMap *) XtMalloc (sizeof *new); 327f80a6dcdSmrg new->x_name = savestr (x_name); 328f80a6dcdSmrg new->dvi_name = savestr (dvi_name); 329f80a6dcdSmrg new->next = fm; 330f80a6dcdSmrg fm = new; 331f80a6dcdSmrg ++m; 332f80a6dcdSmrg } 333f80a6dcdSmrg dw->dvi.font_map = fm; 334f80a6dcdSmrg} 335f80a6dcdSmrg 336f80a6dcdSmrgvoid 33765912f00SmrgDestroyFontMap (DviFontMap *font_map) 338f80a6dcdSmrg{ 339f80a6dcdSmrg DviFontMap *next; 340f80a6dcdSmrg 341f80a6dcdSmrg for (; font_map; font_map = next) { 342f80a6dcdSmrg next = font_map->next; 343f80a6dcdSmrg if (font_map->x_name) 344f80a6dcdSmrg XtFree (font_map->x_name); 345f80a6dcdSmrg if (font_map->dvi_name) 346f80a6dcdSmrg XtFree (font_map->dvi_name); 347f80a6dcdSmrg XtFree ((char *) font_map); 348f80a6dcdSmrg } 349f80a6dcdSmrg} 350f80a6dcdSmrg 351f80a6dcdSmrg/*ARGSUSED*/ 352f80a6dcdSmrgvoid 353c166fba9SmrgSetFontPosition (DviWidget dw, int position, const char *dvi_name, const char *extra) 354f80a6dcdSmrg{ 355c166fba9Smrg const char *x_name; 356f80a6dcdSmrg 357f80a6dcdSmrg x_name = MapDviNameToXName (dw, dvi_name); 358f80a6dcdSmrg (void) InstallFont (dw, position, dvi_name, x_name); 359f80a6dcdSmrg} 360f80a6dcdSmrg 361f80a6dcdSmrg#ifdef USE_XFT 362f80a6dcdSmrgXftFont * 363f80a6dcdSmrg#else 364f80a6dcdSmrgXFontStruct * 365f80a6dcdSmrg#endif 36665912f00SmrgQueryFont (DviWidget dw, int position, int size) 367f80a6dcdSmrg{ 368f80a6dcdSmrg DviFontList *f; 369f80a6dcdSmrg DviFontSizeList *fs; 370f80a6dcdSmrg 371f80a6dcdSmrg f = LookupFontByPosition (dw, position); 372f80a6dcdSmrg if (!f) 373f80a6dcdSmrg return dw->dvi.default_font; 374f80a6dcdSmrg if (!f->initialized) { 375f80a6dcdSmrg f->sizes = InstallFontSizes (dw, f->x_name, &f->scalable); 376f80a6dcdSmrg f->initialized = TRUE; 377f80a6dcdSmrg } 378f80a6dcdSmrg fs = LookupFontSizeBySize (dw, f, size); 379f80a6dcdSmrg if (!fs) 380f80a6dcdSmrg return dw->dvi.default_font; 381f80a6dcdSmrg if (!fs->font) { 382f80a6dcdSmrg if (fs->x_name) 383f80a6dcdSmrg { 384f80a6dcdSmrg#ifdef USE_XFT 385f80a6dcdSmrg XftPattern *pat; 386f80a6dcdSmrg XftPattern *match; 387f80a6dcdSmrg XftResult result; 388f80a6dcdSmrg 389f80a6dcdSmrg pat = XftXlfdParse (fs->x_name, False, False); 390f80a6dcdSmrg XftPatternAddBool (pat, XFT_CORE, fs->core); 391f80a6dcdSmrg match = XftFontMatch (XtDisplay (dw), 392f80a6dcdSmrg XScreenNumberOfScreen(dw->core.screen), 393f80a6dcdSmrg pat, &result); 394f80a6dcdSmrg XftPatternDestroy (pat); 395f80a6dcdSmrg if (match) 396f80a6dcdSmrg { 397f80a6dcdSmrg fs->font = XftFontOpenPattern (XtDisplay (dw), 398f80a6dcdSmrg match); 399f80a6dcdSmrg if (!fs->font) 400f80a6dcdSmrg XftPatternDestroy (match); 401f80a6dcdSmrg } 402f80a6dcdSmrg else 403f80a6dcdSmrg fs->font = 0; 404f80a6dcdSmrg#else 405f80a6dcdSmrg fs->font = XLoadQueryFont (XtDisplay (dw), fs->x_name); 406f80a6dcdSmrg#endif 407f80a6dcdSmrg } 408f80a6dcdSmrg if (!fs->font) 409f80a6dcdSmrg fs->font = dw->dvi.default_font; 410f80a6dcdSmrg } 411f80a6dcdSmrg return fs->font; 412f80a6dcdSmrg} 413f80a6dcdSmrg 414f80a6dcdSmrgDviCharNameMap * 41565912f00SmrgQueryFontMap (DviWidget dw, int position) 416f80a6dcdSmrg{ 417f80a6dcdSmrg DviFontList *f; 418f80a6dcdSmrg 419f80a6dcdSmrg f = LookupFontByPosition (dw, position); 420f80a6dcdSmrg if (f) 421f80a6dcdSmrg return f->char_map; 422f80a6dcdSmrg else 42365912f00Smrg return NULL; 424f80a6dcdSmrg} 425f80a6dcdSmrg 426f80a6dcdSmrgunsigned char * 427c166fba9SmrgDviCharIsLigature (DviCharNameMap *map, const char *name) 428f80a6dcdSmrg{ 4298c7c3c7eSmrg for (int i = 0; i < DVI_MAX_LIGATURES; i++) { 430f80a6dcdSmrg if (!map->ligatures[i][0]) 431f80a6dcdSmrg break; 432f80a6dcdSmrg if (!strcmp (name, map->ligatures[i][0])) 433f80a6dcdSmrg return (unsigned char *) map->ligatures[i][1]; 434f80a6dcdSmrg } 43565912f00Smrg return NULL; 436f80a6dcdSmrg} 437