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