1f80a6dcdSmrg/* 2f80a6dcdSmrg * font.c 3f80a6dcdSmrg * 4f80a6dcdSmrg * map dvi fonts to X fonts 5f80a6dcdSmrg */ 600994698Smrg#ifdef HAVE_CONFIG_H 700994698Smrg# include "config.h" 800994698Smrg#endif 9f80a6dcdSmrg 10f80a6dcdSmrg#include <X11/Xos.h> 11f80a6dcdSmrg#include <X11/IntrinsicP.h> 12f80a6dcdSmrg#include <X11/StringDefs.h> 13f80a6dcdSmrg#include <stdio.h> 14f80a6dcdSmrg#include <stdlib.h> 15f80a6dcdSmrg#include <ctype.h> 16f80a6dcdSmrg#include "DviP.h" 17f80a6dcdSmrg#include "XFontName.h" 18f80a6dcdSmrg 19f80a6dcdSmrgstatic char * 2000994698Smrgsavestr(const char *s) 21f80a6dcdSmrg{ 2200994698Smrg size_t len; 2300994698Smrg char * n; 2400994698Smrg 2500994698Smrg if (!s) 2600994698Smrg return NULL; 2700994698Smrg len = strlen(s) + 1; 2800994698Smrg n = XtMalloc (len); 2900994698Smrg if (n) 3000994698Smrg memcpy(n, s, len); 3100994698Smrg return n; 32f80a6dcdSmrg} 33f80a6dcdSmrg 34f80a6dcdSmrgstatic DviFontList * 3500994698SmrgLookupFontByPosition(DviWidget dw, int position) 36f80a6dcdSmrg{ 3700994698Smrg DviFontList *f; 38f80a6dcdSmrg 3900994698Smrg for (f = dw->dvi.fonts; f; f = f->next) { 4000994698Smrg if (f->dvi_number == position) 4100994698Smrg break; 4200994698Smrg } 4300994698Smrg return f; 44f80a6dcdSmrg} 45f80a6dcdSmrg 46f80a6dcdSmrgstatic DviFontSizeList * 4700994698SmrgLookupFontSizeBySize(DviWidget dw, DviFontList *f, int size) 48f80a6dcdSmrg{ 4900994698Smrg DviFontSizeList *best = NULL; 5000994698Smrg 5100994698Smrg if (f->scalable) { 5200994698Smrg char fontNameString[2048]; 5300994698Smrg XFontName fontName; 5400994698Smrg unsigned int fontNameAttributes; 5500994698Smrg 5600994698Smrg for (best = f->sizes; best; best = best->next) { 5700994698Smrg if (best->size == size) 5800994698Smrg return best; 5900994698Smrg } 6000994698Smrg best = (DviFontSizeList *) XtMalloc(sizeof *best); 6100994698Smrg best->next = f->sizes; 6200994698Smrg best->size = size; 6300994698Smrg XParseFontName(f->x_name, &fontName, &fontNameAttributes); 6400994698Smrg fontNameAttributes &= ~(FontNamePixelSize | FontNameAverageWidth); 6500994698Smrg fontNameAttributes |= FontNameResolutionX; 6600994698Smrg fontNameAttributes |= FontNameResolutionY; 6700994698Smrg fontNameAttributes |= FontNamePointSize; 6800994698Smrg fontName.ResolutionX = dw->dvi.screen_resolution; 6900994698Smrg fontName.ResolutionY = dw->dvi.screen_resolution; 7000994698Smrg fontName.PointSize = size * 10 / dw->dvi.size_scale; 7100994698Smrg XFormatFontName(&fontName, fontNameAttributes, fontNameString); 7200994698Smrg best->x_name = savestr(fontNameString); 73f80a6dcdSmrg#ifdef USE_XFT 7400994698Smrg /* 7500994698Smrg * Force a match of a core font for adobe-fontspecific 7600994698Smrg * encodings; we don't have a scalable font in 7700994698Smrg * the right encoding 7800994698Smrg */ 7900994698Smrg best->core = False; 8000994698Smrg if (!strcmp(fontName.CharSetRegistry, "adobe") && 8100994698Smrg !strcmp(fontName.CharSetEncoding, "fontspecific")) { 8200994698Smrg best->core = True; 8300994698Smrg } 84f80a6dcdSmrg#endif 8500994698Smrg best->doesnt_exist = 0; 8600994698Smrg best->font = NULL; 8700994698Smrg f->sizes = best; 88f80a6dcdSmrg } 8900994698Smrg else { 9000994698Smrg int bestdist = 65536; 9100994698Smrg 9200994698Smrg for (DviFontSizeList * fs = f->sizes; fs; fs = fs->next) { 9300994698Smrg int dist = size - fs->size; 9400994698Smrg 9500994698Smrg if (dist < 0) 9600994698Smrg dist = -dist * 16; 9700994698Smrg if (dist < bestdist) { 9800994698Smrg best = fs; 9900994698Smrg bestdist = dist; 10000994698Smrg } 10100994698Smrg } 102f80a6dcdSmrg } 103f80a6dcdSmrg return best; 104f80a6dcdSmrg} 105f80a6dcdSmrg 10600994698Smrgstatic const char * 10700994698SmrgSkipFontNameElement(const char *n) 108f80a6dcdSmrg{ 10900994698Smrg while (*n != '-') { 11000994698Smrg if (!*++n) 11100994698Smrg return NULL; 11200994698Smrg } 11300994698Smrg return n + 1; 114f80a6dcdSmrg} 115f80a6dcdSmrg 11600994698Smrg#define SizePosition 8 11700994698Smrg#define EncodingPosition 13 118f80a6dcdSmrg 119f80a6dcdSmrg#ifndef USE_XFT 120f80a6dcdSmrgstatic int 12100994698SmrgConvertFontNameToSize(const char *n) 122f80a6dcdSmrg{ 12300994698Smrg int i, size; 12400994698Smrg 12500994698Smrg for (i = 0; i < SizePosition; i++) { 12600994698Smrg n = SkipFontNameElement(n); 12700994698Smrg if (!n) 12800994698Smrg return -1; 12900994698Smrg } 13000994698Smrg size = atoi(n); 13100994698Smrg return size / 10; 132f80a6dcdSmrg} 133f80a6dcdSmrg#endif 134f80a6dcdSmrg 13500994698Smrgstatic const char * 13600994698SmrgConvertFontNameToEncoding(const char *n) 137f80a6dcdSmrg{ 13800994698Smrg for (int i = 0; i < EncodingPosition; i++) { 13900994698Smrg n = SkipFontNameElement(n); 14000994698Smrg if (!n) 14100994698Smrg return NULL; 14200994698Smrg } 14300994698Smrg return n; 144f80a6dcdSmrg} 145f80a6dcdSmrg 146f80a6dcdSmrgstatic void 14700994698SmrgDisposeFontSizes(DviWidget dw, DviFontSizeList *fs) 148f80a6dcdSmrg{ 14900994698Smrg DviFontSizeList *next; 15000994698Smrg 15100994698Smrg for (; fs; fs = next) { 15200994698Smrg next = fs->next; 15300994698Smrg if (fs->x_name) 15400994698Smrg XtFree(fs->x_name); 15500994698Smrg if (fs->font) { 156f80a6dcdSmrg#ifdef USE_XFT 15700994698Smrg XftFontClose(XtDisplay(dw), fs->font); 158f80a6dcdSmrg#else 15900994698Smrg XUnloadFont(XtDisplay(dw), fs->font->fid); 16000994698Smrg XFree((char *) fs->font); 161f80a6dcdSmrg#endif 16200994698Smrg } 16300994698Smrg XtFree((char *) fs); 164f80a6dcdSmrg } 165f80a6dcdSmrg} 166f80a6dcdSmrg 167f80a6dcdSmrgvoid 16800994698SmrgResetFonts(DviWidget dw) 169f80a6dcdSmrg{ 17000994698Smrg for (DviFontList *f = dw->dvi.fonts; f; f = f->next) { 17100994698Smrg if (f->initialized) { 17200994698Smrg DisposeFontSizes(dw, f->sizes); 17300994698Smrg f->sizes = NULL; 17400994698Smrg f->initialized = FALSE; 17500994698Smrg f->scalable = FALSE; 17600994698Smrg } 177f80a6dcdSmrg } 178f80a6dcdSmrg /* 179f80a6dcdSmrg * force requery of fonts 180f80a6dcdSmrg */ 18165912f00Smrg dw->dvi.font = NULL; 182f80a6dcdSmrg dw->dvi.font_number = -1; 18365912f00Smrg dw->dvi.cache.font = NULL; 184f80a6dcdSmrg dw->dvi.cache.font_number = -1; 185f80a6dcdSmrg} 186f80a6dcdSmrg 187f80a6dcdSmrgstatic DviFontSizeList * 18800994698SmrgInstallFontSizes(DviWidget dw, const char *x_name, Boolean *scalablep) 189f80a6dcdSmrg{ 190f80a6dcdSmrg#ifndef USE_XFT 19100994698Smrg char fontNameString[2048]; 19200994698Smrg char **fonts; 19300994698Smrg int count; 19400994698Smrg XFontName fontName; 19500994698Smrg unsigned int fontNameAttributes; 196f80a6dcdSmrg#endif 19700994698Smrg DviFontSizeList *sizes = NULL; 198f80a6dcdSmrg 199f80a6dcdSmrg#ifdef USE_XFT 200f80a6dcdSmrg *scalablep = TRUE; 201f80a6dcdSmrg#else 202f80a6dcdSmrg *scalablep = FALSE; 20300994698Smrg if (!XParseFontName(x_name, &fontName, &fontNameAttributes)) 20400994698Smrg return NULL; 20500994698Smrg 20600994698Smrg fontNameAttributes &= ~(FontNamePixelSize | FontNamePointSize); 207f80a6dcdSmrg fontNameAttributes |= FontNameResolutionX; 208f80a6dcdSmrg fontNameAttributes |= FontNameResolutionY; 209f80a6dcdSmrg fontName.ResolutionX = dw->dvi.screen_resolution; 210f80a6dcdSmrg fontName.ResolutionY = dw->dvi.screen_resolution; 21100994698Smrg XFormatFontName(&fontName, fontNameAttributes, fontNameString); 21200994698Smrg fonts = XListFonts(XtDisplay(dw), fontNameString, 10000000, &count); 2138c7c3c7eSmrg for (int i = 0; i < count; i++) { 21400994698Smrg int size = ConvertFontNameToSize(fonts[i]); 21500994698Smrg 21600994698Smrg if (size == 0) { 21700994698Smrg DisposeFontSizes(dw, sizes); 21800994698Smrg *scalablep = TRUE; 21900994698Smrg sizes = NULL; 22000994698Smrg break; 22100994698Smrg } 22200994698Smrg if (size != -1) { 22300994698Smrg DviFontSizeList *new = (DviFontSizeList *) XtMalloc(sizeof *new); 22400994698Smrg 22500994698Smrg new->next = sizes; 22600994698Smrg new->size = size; 22700994698Smrg new->x_name = savestr(fonts[i]); 22800994698Smrg new->doesnt_exist = 0; 22900994698Smrg new->font = NULL; 23000994698Smrg sizes = new; 23100994698Smrg } 232f80a6dcdSmrg } 23300994698Smrg XFreeFontNames(fonts); 234f80a6dcdSmrg#endif 235f80a6dcdSmrg return sizes; 236f80a6dcdSmrg} 237f80a6dcdSmrg 238f80a6dcdSmrgstatic DviFontList * 23900994698SmrgInstallFont(DviWidget dw, int position, const char *dvi_name, 24000994698Smrg const char *x_name) 241f80a6dcdSmrg{ 24200994698Smrg DviFontList *f = LookupFontByPosition(dw, position); 243f80a6dcdSmrg 244f80a6dcdSmrg if (f) { 24500994698Smrg /* 24600994698Smrg * ignore gratuitous font loading 24700994698Smrg */ 24800994698Smrg if (!strcmp(f->dvi_name, dvi_name) && !strcmp(f->x_name, x_name)) 24900994698Smrg return f; 25000994698Smrg 25100994698Smrg DisposeFontSizes(dw, f->sizes); 25200994698Smrg if (f->dvi_name) 25300994698Smrg XtFree(f->dvi_name); 25400994698Smrg if (f->x_name) 25500994698Smrg XtFree(f->x_name); 25600994698Smrg } 25700994698Smrg else { 25800994698Smrg f = (DviFontList *) XtMalloc(sizeof(*f)); 25900994698Smrg f->next = dw->dvi.fonts; 26000994698Smrg dw->dvi.fonts = f; 261f80a6dcdSmrg } 262f80a6dcdSmrg f->initialized = FALSE; 26300994698Smrg f->dvi_name = savestr(dvi_name); 26400994698Smrg f->x_name = savestr(x_name); 265f80a6dcdSmrg f->dvi_number = position; 26665912f00Smrg f->sizes = NULL; 267f80a6dcdSmrg f->scalable = FALSE; 268f80a6dcdSmrg if (f->x_name) { 26900994698Smrg const char *encoding = ConvertFontNameToEncoding(f->x_name); 27000994698Smrg 27100994698Smrg f->char_map = DviFindMap(encoding); 27200994698Smrg } 27300994698Smrg else 27400994698Smrg f->char_map = NULL; 275f80a6dcdSmrg /* 276f80a6dcdSmrg * force requery of fonts 277f80a6dcdSmrg */ 27865912f00Smrg dw->dvi.font = NULL; 279f80a6dcdSmrg dw->dvi.font_number = -1; 28065912f00Smrg dw->dvi.cache.font = NULL; 281f80a6dcdSmrg dw->dvi.cache.font_number = -1; 282f80a6dcdSmrg return f; 283f80a6dcdSmrg} 284f80a6dcdSmrg 285c166fba9Smrgstatic const char * 28600994698SmrgMapDviNameToXName(DviWidget dw, const char *dvi_name) 287f80a6dcdSmrg{ 28800994698Smrg DviFontMap *fm; 28900994698Smrg 29000994698Smrg for (fm = dw->dvi.font_map; fm; fm = fm->next) 29100994698Smrg if (!strcmp(fm->dvi_name, dvi_name)) 29200994698Smrg return fm->x_name; 293f80a6dcdSmrg ++dvi_name; 29400994698Smrg for (fm = dw->dvi.font_map; fm; fm = fm->next) 29500994698Smrg if (!strcmp(fm->dvi_name, "R")) 29600994698Smrg return fm->x_name; 297f80a6dcdSmrg if (dw->dvi.font_map->x_name) 29800994698Smrg return dw->dvi.font_map->x_name; 299f80a6dcdSmrg return "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1"; 300f80a6dcdSmrg} 301f80a6dcdSmrg 302f80a6dcdSmrgvoid 30300994698SmrgParseFontMap(DviWidget dw) 304f80a6dcdSmrg{ 30500994698Smrg char *m; 30600994698Smrg DviFontMap *fm; 307f80a6dcdSmrg 308f80a6dcdSmrg if (dw->dvi.font_map) 30900994698Smrg DestroyFontMap(dw->dvi.font_map); 31065912f00Smrg fm = NULL; 311f80a6dcdSmrg m = dw->dvi.font_map_string; 312f80a6dcdSmrg while (*m) { 31300994698Smrg char dvi_name[1024]; 31400994698Smrg char x_name[2048]; 31500994698Smrg char *s = m; 31600994698Smrg 31700994698Smrg while (*m && !isspace(*m)) 31800994698Smrg ++m; 31900994698Smrg strncpy(dvi_name, s, m - s); 32000994698Smrg dvi_name[m - s] = '\0'; 32100994698Smrg while (isspace(*m)) 32200994698Smrg ++m; 32300994698Smrg s = m; 32400994698Smrg while (*m && *m != '\n') 32500994698Smrg ++m; 32600994698Smrg strncpy(x_name, s, m - s); 32700994698Smrg x_name[m - s] = '\0'; 32800994698Smrg 32900994698Smrg DviFontMap *new = (DviFontMap *) XtMalloc(sizeof *new); 33000994698Smrg new->x_name = savestr(x_name); 33100994698Smrg new->dvi_name = savestr(dvi_name); 33200994698Smrg new->next = fm; 33300994698Smrg fm = new; 33400994698Smrg ++m; 335f80a6dcdSmrg } 336f80a6dcdSmrg dw->dvi.font_map = fm; 337f80a6dcdSmrg} 338f80a6dcdSmrg 339f80a6dcdSmrgvoid 34000994698SmrgDestroyFontMap(DviFontMap *font_map) 341f80a6dcdSmrg{ 34200994698Smrg DviFontMap *next; 343f80a6dcdSmrg 344f80a6dcdSmrg for (; font_map; font_map = next) { 34500994698Smrg next = font_map->next; 34600994698Smrg if (font_map->x_name) 34700994698Smrg XtFree(font_map->x_name); 34800994698Smrg if (font_map->dvi_name) 34900994698Smrg XtFree(font_map->dvi_name); 35000994698Smrg XtFree((char *) font_map); 351f80a6dcdSmrg } 352f80a6dcdSmrg} 353f80a6dcdSmrg 35400994698Smrg /*ARGSUSED*/ void 35500994698SmrgSetFontPosition(DviWidget dw, int position, const char *dvi_name, 35600994698Smrg const char *extra) 357f80a6dcdSmrg{ 35800994698Smrg const char *x_name; 359f80a6dcdSmrg 36000994698Smrg x_name = MapDviNameToXName(dw, dvi_name); 36100994698Smrg (void) InstallFont(dw, position, dvi_name, x_name); 362f80a6dcdSmrg} 363f80a6dcdSmrg 364f80a6dcdSmrg#ifdef USE_XFT 365f80a6dcdSmrgXftFont * 366f80a6dcdSmrg#else 367f80a6dcdSmrgXFontStruct * 368f80a6dcdSmrg#endif 36900994698SmrgQueryFont(DviWidget dw, int position, int size) 370f80a6dcdSmrg{ 37100994698Smrg DviFontList *f; 37200994698Smrg DviFontSizeList *fs; 373f80a6dcdSmrg 37400994698Smrg f = LookupFontByPosition(dw, position); 375f80a6dcdSmrg if (!f) 37600994698Smrg return dw->dvi.default_font; 377f80a6dcdSmrg if (!f->initialized) { 37800994698Smrg f->sizes = InstallFontSizes(dw, f->x_name, &f->scalable); 37900994698Smrg f->initialized = TRUE; 380f80a6dcdSmrg } 38100994698Smrg fs = LookupFontSizeBySize(dw, f, size); 382f80a6dcdSmrg if (!fs) 38300994698Smrg return dw->dvi.default_font; 384f80a6dcdSmrg if (!fs->font) { 38500994698Smrg if (fs->x_name) { 386f80a6dcdSmrg#ifdef USE_XFT 38700994698Smrg XftPattern *pat; 38800994698Smrg XftPattern *match; 38900994698Smrg XftResult result; 39000994698Smrg 39100994698Smrg pat = XftXlfdParse(fs->x_name, False, False); 39200994698Smrg XftPatternAddBool(pat, XFT_CORE, fs->core); 39300994698Smrg match = XftFontMatch(XtDisplay(dw), 39400994698Smrg XScreenNumberOfScreen(dw->core.screen), 39500994698Smrg pat, &result); 39600994698Smrg XftPatternDestroy(pat); 39700994698Smrg if (match) { 39800994698Smrg fs->font = XftFontOpenPattern(XtDisplay(dw), match); 39900994698Smrg if (!fs->font) 40000994698Smrg XftPatternDestroy(match); 40100994698Smrg } 40200994698Smrg else 40300994698Smrg fs->font = 0; 404f80a6dcdSmrg#else 40500994698Smrg fs->font = XLoadQueryFont(XtDisplay(dw), fs->x_name); 406f80a6dcdSmrg#endif 40700994698Smrg } 40800994698Smrg if (!fs->font) 40900994698Smrg fs->font = dw->dvi.default_font; 410f80a6dcdSmrg } 411f80a6dcdSmrg return fs->font; 412f80a6dcdSmrg} 413f80a6dcdSmrg 414f80a6dcdSmrgDviCharNameMap * 41500994698SmrgQueryFontMap(DviWidget dw, int position) 416f80a6dcdSmrg{ 41700994698Smrg DviFontList *f = LookupFontByPosition(dw, position); 418f80a6dcdSmrg 41900994698Smrg if (f) 42000994698Smrg return f->char_map; 42100994698Smrg else 42200994698Smrg return NULL; 423f80a6dcdSmrg} 424f80a6dcdSmrg 425f80a6dcdSmrgunsigned char * 42600994698SmrgDviCharIsLigature(DviCharNameMap *map, const char *name) 427f80a6dcdSmrg{ 4288c7c3c7eSmrg for (int i = 0; i < DVI_MAX_LIGATURES; i++) { 42900994698Smrg if (!map->ligatures[i][0]) 43000994698Smrg break; 43100994698Smrg if (!strcmp(name, map->ligatures[i][0])) 43200994698Smrg return (unsigned char *) map->ligatures[i][1]; 433f80a6dcdSmrg } 43465912f00Smrg return NULL; 435f80a6dcdSmrg} 436