fonts.py 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #!/bin/env python
  2. #Copyright ReportLab Europe Ltd. 2000-2017
  3. #see license.txt for license details
  4. #history https://hg.reportlab.com/hg-public/reportlab/log/tip/src/reportlab/lib/fonts.py
  5. __version__='3.3.0'
  6. __doc__='''Utilities to associate bold and italic versions of fonts into families
  7. Bold, italic and plain fonts are usually implemented in separate disk files;
  8. but non-trivial apps want <b>this</b> to do the right thing. We therefore
  9. need to keep 'mappings' between the font family name and the right group
  10. of up to 4 implementation fonts to use.
  11. Most font-handling code lives in pdfbase, and this probably should too.
  12. '''
  13. import sys, os
  14. ###############################################################################
  15. # A place to put useful font stuff
  16. ###############################################################################
  17. #
  18. # Font Mappings
  19. # The brute force approach to finding the correct postscript font name;
  20. # much safer than the rule-based ones we tried.
  21. # preprocessor to reduce font face names to the shortest list
  22. # possible. Add any aliases you wish; it keeps looking up
  23. # until it finds no more translations to do. Any input
  24. # will be lowercased before checking.
  25. _family_alias = {
  26. 'serif':'times',
  27. 'sansserif':'helvetica',
  28. 'monospaced':'courier',
  29. 'arial':'helvetica'
  30. }
  31. #maps a piddle font to a postscript one.
  32. _tt2ps_map = {
  33. #face, bold, italic -> ps name
  34. ('times', 0, 0) :'Times-Roman',
  35. ('times', 1, 0) :'Times-Bold',
  36. ('times', 0, 1) :'Times-Italic',
  37. ('times', 1, 1) :'Times-BoldItalic',
  38. ('courier', 0, 0) :'Courier',
  39. ('courier', 1, 0) :'Courier-Bold',
  40. ('courier', 0, 1) :'Courier-Oblique',
  41. ('courier', 1, 1) :'Courier-BoldOblique',
  42. ('helvetica', 0, 0) :'Helvetica',
  43. ('helvetica', 1, 0) :'Helvetica-Bold',
  44. ('helvetica', 0, 1) :'Helvetica-Oblique',
  45. ('helvetica', 1, 1) :'Helvetica-BoldOblique',
  46. # there is only one Symbol font
  47. ('symbol', 0, 0) :'Symbol',
  48. ('symbol', 1, 0) :'Symbol',
  49. ('symbol', 0, 1) :'Symbol',
  50. ('symbol', 1, 1) :'Symbol',
  51. # ditto for dingbats
  52. ('zapfdingbats', 0, 0) :'ZapfDingbats',
  53. ('zapfdingbats', 1, 0) :'ZapfDingbats',
  54. ('zapfdingbats', 0, 1) :'ZapfDingbats',
  55. ('zapfdingbats', 1, 1) :'ZapfDingbats',
  56. }
  57. _ps2tt_map={}
  58. for k in sorted(_tt2ps_map.keys()):
  59. v = _tt2ps_map[k].lower()
  60. if v not in _ps2tt_map:
  61. _ps2tt_map[v] = k
  62. v = k[0].lower()
  63. if v not in _ps2tt_map:
  64. _ps2tt_map[v] = k
  65. def ps2tt(psfn):
  66. 'ps fontname to family name, bold, italic'
  67. psfn = psfn.lower()
  68. if psfn in _ps2tt_map:
  69. return _ps2tt_map[psfn]
  70. raise ValueError("Can't map determine family/bold/italic for %s" % psfn)
  71. def tt2ps(fn,b,i):
  72. 'family name + bold & italic to ps font name'
  73. K = (fn.lower(),b,i)
  74. if K in _tt2ps_map:
  75. return _tt2ps_map[K]
  76. else:
  77. fn, b1, i1 = ps2tt(K[0])
  78. K = fn, b1|b, i1|i
  79. if K in _tt2ps_map:
  80. return _tt2ps_map[K]
  81. raise ValueError("Can't find concrete font for family=%s, bold=%d, italic=%d" % (fn, b, i))
  82. def addMapping(face, bold, italic, psname):
  83. 'allow a custom font to be put in the mapping'
  84. k = face.lower(), bold, italic
  85. _tt2ps_map[k] = psname
  86. _ps2tt_map[psname.lower()] = k