/contrib/groff/src/devices/xditview/font.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 442 lines · 369 code · 48 blank · 25 comment · 70 complexity · 7db2c31c994cb54857c181139d00e13a MD5 · raw file

  1. /*
  2. * font.c
  3. *
  4. * map dvi fonts to X fonts
  5. */
  6. #include <X11/Xos.h>
  7. #include <X11/IntrinsicP.h>
  8. #include <X11/StringDefs.h>
  9. #include <stdio.h>
  10. #include <ctype.h>
  11. #include <stdlib.h>
  12. #include "DviP.h"
  13. #include "XFontName.h"
  14. static void DisposeFontSizes(DviWidget, DviFontSizeList *);
  15. void DestroyFontMap(DviFontMap *);
  16. static char *
  17. savestr (const char *s)
  18. {
  19. char *n;
  20. if (!s)
  21. return 0;
  22. n = XtMalloc (strlen (s) + 1);
  23. if (n)
  24. strcpy (n, s);
  25. return n;
  26. }
  27. static DviFontList *
  28. LookupFontByPosition (DviWidget dw, int position)
  29. {
  30. DviFontList *f;
  31. for (f = dw->dvi.fonts; f; f = f->next)
  32. if (f->dvi_number == position)
  33. break;
  34. return f;
  35. }
  36. int
  37. MaxFontPosition (DviWidget dw)
  38. {
  39. DviFontList *f;
  40. int n = -1;
  41. for (f = dw->dvi.fonts; f; f = f->next)
  42. if (f->dvi_number > n)
  43. n = f->dvi_number;
  44. return n;
  45. }
  46. static DviFontSizeList *
  47. LookupFontSizeBySize (DviWidget dw, DviFontList *f, int size)
  48. {
  49. DviFontSizeList *fs, *best = 0, *smallest = 0;
  50. int bestsize = 0;
  51. XFontName fontName;
  52. unsigned int fontNameAttributes;
  53. char fontNameString[2048];
  54. int decipointsize;
  55. if (f->scalable) {
  56. decipointsize = (10*size)/dw->dvi.sizescale;
  57. for (best = f->sizes; best; best = best->next)
  58. if (best->size == decipointsize)
  59. return best;
  60. best = (DviFontSizeList *) XtMalloc(sizeof *best);
  61. best->next = f->sizes;
  62. best->size = decipointsize;
  63. f->sizes = best;
  64. XParseFontName (f->x_name, &fontName, &fontNameAttributes);
  65. fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth);
  66. fontNameAttributes |= FontNameResolutionX;
  67. fontNameAttributes |= FontNameResolutionY;
  68. fontNameAttributes |= FontNamePointSize;
  69. fontName.ResolutionX = dw->dvi.display_resolution;
  70. fontName.ResolutionY = dw->dvi.display_resolution;
  71. fontName.PointSize = decipointsize;
  72. XFormatFontName (&fontName, fontNameAttributes, fontNameString);
  73. best->x_name = savestr (fontNameString);
  74. best->doesnt_exist = 0;
  75. best->font = 0;
  76. return best;
  77. }
  78. for (fs = f->sizes; fs; fs=fs->next) {
  79. if (dw->dvi.sizescale*fs->size <= 10*size
  80. && fs->size >= bestsize) {
  81. best = fs;
  82. bestsize = fs->size;
  83. }
  84. if (smallest == 0 || fs->size < smallest->size)
  85. smallest = fs;
  86. }
  87. return best ? best : smallest;
  88. }
  89. static char *
  90. SkipFontNameElement (char *n)
  91. {
  92. while (*n != '-')
  93. if (!*++n)
  94. return 0;
  95. return n+1;
  96. }
  97. # define SizePosition 8
  98. # define EncodingPosition 13
  99. static int
  100. ConvertFontNameToSize (char *n)
  101. {
  102. int i, size;
  103. for (i = 0; i < SizePosition; i++) {
  104. n = SkipFontNameElement (n);
  105. if (!n)
  106. return -1;
  107. }
  108. size = atoi (n);
  109. return size;
  110. }
  111. static char *
  112. ConvertFontNameToEncoding (char *n)
  113. {
  114. int i;
  115. for (i = 0; i < EncodingPosition; i++) {
  116. n = SkipFontNameElement (n);
  117. if (!n)
  118. return 0;
  119. }
  120. return n;
  121. }
  122. DviFontSizeList *
  123. InstallFontSizes (DviWidget dw, const char *x_name, Boolean *scalablep)
  124. {
  125. char fontNameString[2048];
  126. char **fonts;
  127. int i, count;
  128. int size;
  129. DviFontSizeList *sizes, *new_size;
  130. XFontName fontName;
  131. unsigned int fontNameAttributes;
  132. *scalablep = FALSE;
  133. if (!XParseFontName ((XFontNameString)x_name, &fontName,
  134. &fontNameAttributes))
  135. return 0;
  136. fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize
  137. |FontNameAverageWidth);
  138. fontNameAttributes |= FontNameResolutionX;
  139. fontNameAttributes |= FontNameResolutionY;
  140. fontName.ResolutionX = dw->dvi.display_resolution;
  141. fontName.ResolutionY = dw->dvi.display_resolution;
  142. XFormatFontName (&fontName, fontNameAttributes, fontNameString);
  143. fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count);
  144. sizes = 0;
  145. for (i = 0; i < count; i++) {
  146. size = ConvertFontNameToSize (fonts[i]);
  147. if (size == 0) {
  148. DisposeFontSizes (dw, sizes);
  149. sizes = 0;
  150. *scalablep = TRUE;
  151. break;
  152. }
  153. if (size != -1) {
  154. new_size = (DviFontSizeList *) XtMalloc (sizeof *new_size);
  155. new_size->next = sizes;
  156. new_size->size = size;
  157. new_size->x_name = savestr (fonts[i]);
  158. new_size->doesnt_exist = 0;
  159. new_size->font = 0;
  160. sizes = new_size;
  161. }
  162. }
  163. XFreeFontNames (fonts);
  164. return sizes;
  165. }
  166. static void
  167. DisposeFontSizes (DviWidget dw, DviFontSizeList *fs)
  168. {
  169. DviFontSizeList *next;
  170. for (; fs; fs=next) {
  171. next = fs->next;
  172. if (fs->x_name)
  173. XtFree (fs->x_name);
  174. if (fs->font && fs->font != dw->dvi.default_font) {
  175. XUnloadFont (XtDisplay (dw), fs->font->fid);
  176. XFree ((char *)fs->font);
  177. }
  178. XtFree ((char *) fs);
  179. }
  180. }
  181. static DviFontList *
  182. InstallFont (DviWidget dw, int position,
  183. const char *dvi_name, const char *x_name)
  184. {
  185. DviFontList *f;
  186. char *encoding;
  187. if ((f = LookupFontByPosition (dw, position)) != NULL) {
  188. /*
  189. * ignore gratuitous font loading
  190. */
  191. if (!strcmp (f->dvi_name, dvi_name) &&
  192. !strcmp (f->x_name, x_name))
  193. return f;
  194. DisposeFontSizes (dw, f->sizes);
  195. if (f->dvi_name)
  196. XtFree (f->dvi_name);
  197. if (f->x_name)
  198. XtFree (f->x_name);
  199. f->device_font = 0;
  200. } else {
  201. f = (DviFontList *) XtMalloc (sizeof (*f));
  202. f->next = dw->dvi.fonts;
  203. dw->dvi.fonts = f;
  204. }
  205. f->initialized = FALSE;
  206. f->dvi_name = savestr (dvi_name);
  207. f->device_font = device_find_font (dw->dvi.device, dvi_name);
  208. f->x_name = savestr (x_name);
  209. f->dvi_number = position;
  210. f->sizes = 0;
  211. f->scalable = FALSE;
  212. if (f->x_name) {
  213. encoding = ConvertFontNameToEncoding (f->x_name);
  214. f->char_map = DviFindMap (encoding);
  215. } else
  216. f->char_map = 0;
  217. /*
  218. * force requery of fonts
  219. */
  220. dw->dvi.font = 0;
  221. dw->dvi.font_number = -1;
  222. dw->dvi.cache.font = 0;
  223. dw->dvi.cache.font_number = -1;
  224. dw->dvi.device_font = 0;
  225. dw->dvi.device_font_number = -1;
  226. return f;
  227. }
  228. void
  229. ForgetFonts (DviWidget dw)
  230. {
  231. DviFontList *f = dw->dvi.fonts;
  232. while (f) {
  233. DviFontList *tem = f;
  234. if (f->sizes)
  235. DisposeFontSizes (dw, f->sizes);
  236. if (f->dvi_name)
  237. XtFree (f->dvi_name);
  238. if (f->x_name)
  239. XtFree (f->x_name);
  240. f = f->next;
  241. XtFree ((char *) tem);
  242. }
  243. /*
  244. * force requery of fonts
  245. */
  246. dw->dvi.font = 0;
  247. dw->dvi.font_number = -1;
  248. dw->dvi.cache.font = 0;
  249. dw->dvi.cache.font_number = -1;
  250. dw->dvi.device_font = 0;
  251. dw->dvi.device_font_number = -1;
  252. dw->dvi.fonts = 0;
  253. }
  254. static char *
  255. MapDviNameToXName (DviWidget dw, const char *dvi_name)
  256. {
  257. DviFontMap *fm;
  258. for (fm = dw->dvi.font_map; fm; fm=fm->next)
  259. if (!strcmp (fm->dvi_name, dvi_name))
  260. return fm->x_name;
  261. return 0;
  262. }
  263. #if 0
  264. static char *
  265. MapXNameToDviName (DviWidget dw, const char *x_name)
  266. {
  267. DviFontMap *fm;
  268. for (fm = dw->dvi.font_map; fm; fm=fm->next)
  269. if (!strcmp (fm->x_name, x_name))
  270. return fm->dvi_name;
  271. return 0;
  272. }
  273. #endif
  274. void
  275. ParseFontMap (DviWidget dw)
  276. {
  277. char dvi_name[1024];
  278. char x_name[2048];
  279. char *m, *s;
  280. DviFontMap *fm, *new_map;
  281. if (dw->dvi.font_map)
  282. DestroyFontMap (dw->dvi.font_map);
  283. fm = 0;
  284. m = dw->dvi.font_map_string;
  285. while (*m) {
  286. s = m;
  287. while (*m && !isspace (*m))
  288. ++m;
  289. strncpy (dvi_name, s, m-s);
  290. dvi_name[m-s] = '\0';
  291. while (isspace (*m))
  292. ++m;
  293. s = m;
  294. while (*m && *m != '\n')
  295. ++m;
  296. strncpy (x_name, s, m-s);
  297. x_name[m-s] = '\0';
  298. new_map = (DviFontMap *) XtMalloc (sizeof *new_map);
  299. new_map->x_name = savestr (x_name);
  300. new_map->dvi_name = savestr (dvi_name);
  301. new_map->next = fm;
  302. fm = new_map;
  303. ++m;
  304. }
  305. dw->dvi.font_map = fm;
  306. }
  307. void
  308. DestroyFontMap (DviFontMap *font_map)
  309. {
  310. DviFontMap *next;
  311. for (; font_map; font_map = next) {
  312. next = font_map->next;
  313. if (font_map->x_name)
  314. XtFree (font_map->x_name);
  315. if (font_map->dvi_name)
  316. XtFree (font_map->dvi_name);
  317. XtFree ((char *) font_map);
  318. }
  319. }
  320. /* ARGSUSED */
  321. void
  322. SetFontPosition (DviWidget dw, int position,
  323. const char *dvi_name, const char *extra)
  324. {
  325. char *x_name;
  326. x_name = MapDviNameToXName (dw, dvi_name);
  327. if (x_name)
  328. (void) InstallFont (dw, position, dvi_name, x_name);
  329. extra = extra; /* unused; suppress compiler warning */
  330. }
  331. XFontStruct *
  332. QueryFont (DviWidget dw, int position, int size)
  333. {
  334. DviFontList *f;
  335. DviFontSizeList *fs;
  336. f = LookupFontByPosition (dw, position);
  337. if (!f)
  338. return dw->dvi.default_font;
  339. if (!f->initialized) {
  340. f->sizes = InstallFontSizes (dw, f->x_name, &f->scalable);
  341. f->initialized = TRUE;
  342. }
  343. fs = LookupFontSizeBySize (dw, f, size);
  344. if (!fs)
  345. return dw->dvi.default_font;
  346. if (!fs->font) {
  347. if (fs->x_name)
  348. fs->font = XLoadQueryFont (XtDisplay (dw), fs->x_name);
  349. if (!fs->font)
  350. fs->font = dw->dvi.default_font;
  351. }
  352. return fs->font;
  353. }
  354. DeviceFont *
  355. QueryDeviceFont (DviWidget dw, int position)
  356. {
  357. DviFontList *f;
  358. f = LookupFontByPosition (dw, position);
  359. if (!f)
  360. return 0;
  361. return f->device_font;
  362. }
  363. DviCharNameMap *
  364. QueryFontMap (DviWidget dw, int position)
  365. {
  366. DviFontList *f;
  367. f = LookupFontByPosition (dw, position);
  368. if (f)
  369. return f->char_map;
  370. else
  371. return 0;
  372. }
  373. #if 0
  374. LoadFont (DviWidget dw, int position, int size)
  375. {
  376. XFontStruct *font;
  377. font = QueryFont (dw, position, size);
  378. dw->dvi.font_number = position;
  379. dw->dvi.font_size = size;
  380. dw->dvi.font = font;
  381. XSetFont (XtDisplay (dw), dw->dvi.normal_GC, font->fid);
  382. return;
  383. }
  384. #endif
  385. /*
  386. Local Variables:
  387. c-indent-level: 8
  388. c-continued-statement-offset: 8
  389. c-brace-offset: -8
  390. c-argdecl-indent: 8
  391. c-label-offset: -8
  392. c-tab-always-indent: nil
  393. End:
  394. */