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