_fontdata.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #Copyright ReportLab Europe Ltd. 2000-2017
  2. #see license.txt for license details
  3. #history https://hg.reportlab.com/hg-public/reportlab/log/tip/src/reportlab/pdfbase/_fontdata.py
  4. #$Header $
  5. __version__='3.3.0'
  6. __doc__="""Database of font related things
  7. - standardFonts - tuple of the 14 standard string font names
  8. - standardEncodings - tuple of the known standard font names
  9. - encodings - a mapping object from standard encoding names (and minor variants)
  10. to the encoding vectors ie the tuple of string glyph names
  11. - widthsByFontGlyph - fontname x glyphname --> width of glyph
  12. - widthVectorsByFont - fontName -> vector of widths
  13. This module defines a static, large data structure. At the request
  14. of the Jython project, we have split this off into separate modules
  15. as Jython cannot handle more than 64k of bytecode in the 'top level'
  16. code of a Python module.
  17. """
  18. import os, sys
  19. # mapping of name to width vector, starts empty until fonts are added
  20. # e.g. widths['Courier'] = [...600,600,600,...]
  21. widthVectorsByFont = {}
  22. fontsByName = {}
  23. fontsByBaseEnc = {}
  24. # this is a list of the standard 14 font names in Acrobat Reader
  25. standardFonts = (
  26. 'Courier', 'Courier-Bold', 'Courier-Oblique', 'Courier-BoldOblique',
  27. 'Helvetica', 'Helvetica-Bold', 'Helvetica-Oblique', 'Helvetica-BoldOblique',
  28. 'Times-Roman', 'Times-Bold', 'Times-Italic', 'Times-BoldItalic',
  29. 'Symbol','ZapfDingbats')
  30. standardFontAttributes = {
  31. #family, bold, italic defined for basic ones
  32. 'Courier':('Courier',0,0),
  33. 'Courier-Bold':('Courier',1,0),
  34. 'Courier-Oblique':('Courier',0,1),
  35. 'Courier-BoldOblique':('Courier',1,1),
  36. 'Helvetica':('Helvetica',0,0),
  37. 'Helvetica-Bold':('Helvetica',1,0),
  38. 'Helvetica-Oblique':('Helvetica',0,1),
  39. 'Helvetica-BoldOblique':('Helvetica',1,1),
  40. 'Times-Roman':('Times-Roman',0,0),
  41. 'Times-Bold':('Times-Roman',1,0),
  42. 'Times-Italic':('Times-Roman',0,1),
  43. 'Times-BoldItalic':('Times-Roman',1,1),
  44. 'Symbol':('Symbol',0,0),
  45. 'ZapfDingbats':('ZapfDingbats',0,0)
  46. }
  47. #this maps fontnames to the equivalent filename root.
  48. _font2fnrMapWin32 = {
  49. 'symbol': 'sy______',
  50. 'zapfdingbats': 'zd______',
  51. 'helvetica': '_a______',
  52. 'helvetica-bold': '_ab_____',
  53. 'helvetica-boldoblique': '_abi____',
  54. 'helvetica-oblique': '_ai_____',
  55. 'times-bold': '_eb_____',
  56. 'times-bolditalic': '_ebi____',
  57. 'times-italic': '_ei_____',
  58. 'times-roman': '_er_____',
  59. 'courier-bold': 'cob_____',
  60. 'courier-boldoblique': 'cobo____',
  61. 'courier': 'com_____',
  62. 'courier-oblique': 'coo_____',
  63. }
  64. if sys.platform in ('linux2',):
  65. _font2fnrMapLinux2 ={
  66. 'symbol': 'Symbol',
  67. 'zapfdingbats': 'ZapfDingbats',
  68. 'helvetica': 'Arial',
  69. 'helvetica-bold': 'Arial-Bold',
  70. 'helvetica-boldoblique': 'Arial-BoldItalic',
  71. 'helvetica-oblique': 'Arial-Italic',
  72. 'times-bold': 'TimesNewRoman-Bold',
  73. 'times-bolditalic':'TimesNewRoman-BoldItalic',
  74. 'times-italic': 'TimesNewRoman-Italic',
  75. 'times-roman': 'TimesNewRoman',
  76. 'courier-bold': 'Courier-Bold',
  77. 'courier-boldoblique': 'Courier-BoldOblique',
  78. 'courier': 'Courier',
  79. 'courier-oblique': 'Courier-Oblique',
  80. }
  81. _font2fnrMap = _font2fnrMapLinux2
  82. for k, v in _font2fnrMap.items():
  83. if k in _font2fnrMapWin32.keys():
  84. _font2fnrMapWin32[v.lower()] = _font2fnrMapWin32[k]
  85. del k, v
  86. else:
  87. _font2fnrMap = _font2fnrMapWin32
  88. def _findFNR(fontName):
  89. return _font2fnrMap[fontName.lower()]
  90. from reportlab.rl_config import T1SearchPath
  91. from reportlab.lib.utils import rl_isfile
  92. def _searchT1Dirs(n,rl_isfile=rl_isfile,T1SearchPath=T1SearchPath):
  93. assert T1SearchPath!=[], "No Type-1 font search path"
  94. for d in T1SearchPath:
  95. f = os.path.join(d,n)
  96. if rl_isfile(f): return f
  97. return None
  98. del T1SearchPath, rl_isfile
  99. def findT1File(fontName,ext='.pfb'):
  100. if sys.platform in ('linux2',) and ext=='.pfb':
  101. try:
  102. f = _searchT1Dirs(_findFNR(fontName))
  103. if f: return f
  104. except:
  105. pass
  106. try:
  107. f = _searchT1Dirs(_font2fnrMapWin32[fontName.lower()]+ext)
  108. if f: return f
  109. except:
  110. pass
  111. return _searchT1Dirs(_findFNR(fontName)+ext)
  112. # this lists the predefined font encodings - WinAnsi and MacRoman. We have
  113. # not added MacExpert - it's possible, but would complicate life and nobody
  114. # is asking. StandardEncoding means something special.
  115. standardEncodings = ('WinAnsiEncoding','MacRomanEncoding','StandardEncoding','SymbolEncoding','ZapfDingbatsEncoding','PDFDocEncoding', 'MacExpertEncoding')
  116. #this is the global mapping of standard encodings to name vectors
  117. class _Name2StandardEncodingMap(dict):
  118. '''Trivial fake dictionary with some [] magic'''
  119. _XMap = {'winansi':'WinAnsiEncoding','macroman': 'MacRomanEncoding','standard':'StandardEncoding','symbol':'SymbolEncoding', 'zapfdingbats':'ZapfDingbatsEncoding','pdfdoc':'PDFDocEncoding', 'macexpert':'MacExpertEncoding'}
  120. def __setitem__(self,x,v):
  121. y = x.lower()
  122. if y[-8:]=='encoding': y = y[:-8]
  123. y = self._XMap[y]
  124. if y in self: raise IndexError('Encoding %s is already set' % y)
  125. dict.__setitem__(self,y,v)
  126. def __getitem__(self,x):
  127. y = x.lower()
  128. if y[-8:]=='encoding': y = y[:-8]
  129. y = self._XMap[y]
  130. return dict.__getitem__(self,y)
  131. encodings = _Name2StandardEncodingMap()
  132. #due to compiled method size limits in Jython,
  133. #we pull these in from separate modules to keep this module
  134. #well under 64k. We might well be able to ditch many of
  135. #these anyway now we run on Unicode.
  136. from reportlab.pdfbase._fontdata_enc_winansi import WinAnsiEncoding
  137. from reportlab.pdfbase._fontdata_enc_macroman import MacRomanEncoding
  138. from reportlab.pdfbase._fontdata_enc_standard import StandardEncoding
  139. from reportlab.pdfbase._fontdata_enc_symbol import SymbolEncoding
  140. from reportlab.pdfbase._fontdata_enc_zapfdingbats import ZapfDingbatsEncoding
  141. from reportlab.pdfbase._fontdata_enc_pdfdoc import PDFDocEncoding
  142. from reportlab.pdfbase._fontdata_enc_macexpert import MacExpertEncoding
  143. encodings.update({
  144. 'WinAnsiEncoding': WinAnsiEncoding,
  145. 'MacRomanEncoding': MacRomanEncoding,
  146. 'StandardEncoding': StandardEncoding,
  147. 'SymbolEncoding': SymbolEncoding,
  148. 'ZapfDingbatsEncoding': ZapfDingbatsEncoding,
  149. 'PDFDocEncoding': PDFDocEncoding,
  150. 'MacExpertEncoding': MacExpertEncoding,
  151. })
  152. ascent_descent = {
  153. 'Courier': (629, -157),
  154. 'Courier-Bold': (626, -142),
  155. 'Courier-BoldOblique': (626, -142),
  156. 'Courier-Oblique': (629, -157),
  157. 'Helvetica': (718, -207),
  158. 'Helvetica-Bold': (718, -207),
  159. 'Helvetica-BoldOblique': (718, -207),
  160. 'Helvetica-Oblique': (718, -207),
  161. 'Times-Roman': (683, -217),
  162. 'Times-Bold': (676, -205),
  163. 'Times-BoldItalic': (699, -205),
  164. 'Times-Italic': (683, -205),
  165. 'Symbol': (0, 0),
  166. 'ZapfDingbats': (0, 0)
  167. }
  168. # ditto about 64k limit - profusion of external files
  169. import reportlab.pdfbase._fontdata_widths_courier
  170. import reportlab.pdfbase._fontdata_widths_courierbold
  171. import reportlab.pdfbase._fontdata_widths_courieroblique
  172. import reportlab.pdfbase._fontdata_widths_courierboldoblique
  173. import reportlab.pdfbase._fontdata_widths_helvetica
  174. import reportlab.pdfbase._fontdata_widths_helveticabold
  175. import reportlab.pdfbase._fontdata_widths_helveticaoblique
  176. import reportlab.pdfbase._fontdata_widths_helveticaboldoblique
  177. import reportlab.pdfbase._fontdata_widths_timesroman
  178. import reportlab.pdfbase._fontdata_widths_timesbold
  179. import reportlab.pdfbase._fontdata_widths_timesitalic
  180. import reportlab.pdfbase._fontdata_widths_timesbolditalic
  181. import reportlab.pdfbase._fontdata_widths_symbol
  182. import reportlab.pdfbase._fontdata_widths_zapfdingbats
  183. widthsByFontGlyph = {
  184. 'Courier':
  185. reportlab.pdfbase._fontdata_widths_courier.widths,
  186. 'Courier-Bold':
  187. reportlab.pdfbase._fontdata_widths_courierbold.widths,
  188. 'Courier-Oblique':
  189. reportlab.pdfbase._fontdata_widths_courieroblique.widths,
  190. 'Courier-BoldOblique':
  191. reportlab.pdfbase._fontdata_widths_courierboldoblique.widths,
  192. 'Helvetica':
  193. reportlab.pdfbase._fontdata_widths_helvetica.widths,
  194. 'Helvetica-Bold':
  195. reportlab.pdfbase._fontdata_widths_helveticabold.widths,
  196. 'Helvetica-Oblique':
  197. reportlab.pdfbase._fontdata_widths_helveticaoblique.widths,
  198. 'Helvetica-BoldOblique':
  199. reportlab.pdfbase._fontdata_widths_helveticaboldoblique.widths,
  200. 'Times-Roman':
  201. reportlab.pdfbase._fontdata_widths_timesroman.widths,
  202. 'Times-Bold':
  203. reportlab.pdfbase._fontdata_widths_timesbold.widths,
  204. 'Times-Italic':
  205. reportlab.pdfbase._fontdata_widths_timesitalic.widths,
  206. 'Times-BoldItalic':
  207. reportlab.pdfbase._fontdata_widths_timesbolditalic.widths,
  208. 'Symbol':
  209. reportlab.pdfbase._fontdata_widths_symbol.widths,
  210. 'ZapfDingbats':
  211. reportlab.pdfbase._fontdata_widths_zapfdingbats.widths,
  212. }
  213. #preserve the initial values here
  214. def _reset(
  215. initial_dicts=dict(
  216. ascent_descent=ascent_descent.copy(),
  217. fontsByBaseEnc=fontsByBaseEnc.copy(),
  218. fontsByName=fontsByName.copy(),
  219. standardFontAttributes=standardFontAttributes.copy(),
  220. widthVectorsByFont=widthVectorsByFont.copy(),
  221. widthsByFontGlyph=widthsByFontGlyph.copy(),
  222. )
  223. ):
  224. for k,v in initial_dicts.items():
  225. d=globals()[k]
  226. d.clear()
  227. d.update(v)
  228. from reportlab.rl_config import register_reset
  229. register_reset(_reset)
  230. del register_reset