1 # -*- encoding: utf-8 -*-
4 # Copyright (C) 2007-2011 Jörg Lehmann <joergl@users.sourceforge.net>
5 # Copyright (C) 2007-2011 André Wobst <wobsta@users.sourceforge.net>
7 # This file is part of PyX (http://pyx.sourceforge.net/).
9 # PyX is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
14 # PyX is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with PyX; if not, write to the Free Software
21 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USAimport re, warnings
24 from pyx
import font
, filelocator
25 from pyx
.font
import t1file
, afmfile
26 from pyx
.dvi
import encfile
28 class UnsupportedFontFormat(Exception):
31 class UnsupportedPSFragment(Exception):
38 tokenpattern
= re
.compile(r
'"(.*?)("\s+|"$|$)|(.*?)(\s+|$)')
40 def __init__(self
, s
):
41 """ construct font mapping from line s of font mapping file """
42 self
.texname
= self
.basepsname
= self
.fontfilename
= None
45 self
.encodingfilename
= None
47 # supported postscript fragments occuring in psfonts.map
48 # XXX extendfont not yet implemented
49 self
.reencodefont
= self
.extendfont
= self
.slant
= None
51 # cache for openend font and encoding
53 self
._encoding
= _marker
57 match
= self
.tokenpattern
.match(s
)
59 if match
.groups()[0] is not None:
60 tokens
.append('"%s"' % match
.groups()[0])
62 tokens
.append(match
.groups()[2])
65 raise RuntimeError("Cannot tokenize string '%s'" % s
)
67 next_token_is_encfile
= False
69 if next_token_is_encfile
:
70 self
.encodingfilename
= token
71 next_token_is_encfile
= False
72 elif token
.startswith("<"):
74 next_token_is_encfile
= True
75 elif token
.startswith("<<"):
76 # XXX: support non-partial download here
77 self
.fontfilename
= token
[2:]
78 elif token
.startswith("<["):
79 self
.encodingfilename
= token
[2:]
80 elif token
.endswith(".pfa") or token
.endswith(".pfb"):
81 self
.fontfilename
= token
[1:]
82 elif token
.endswith(".enc"):
83 self
.encodingfilename
= token
[1:]
84 elif token
.endswith(".ttf"):
85 raise UnsupportedFontFormat("TrueType font")
87 raise RuntimeError("Unknown token '%s'" % token
)
88 elif token
.startswith('"'):
89 pscode
= token
[1:-1].split()
90 # parse standard postscript code fragments
95 raise UnsupportedPSFragment("Unsupported Postscript fragment '%s'" % pscode
)
97 if cmd
== "ReEncodeFont":
98 self
.reencodefont
= arg
99 elif cmd
== "ExtendFont":
100 self
.extendfont
= arg
101 elif cmd
== "SlantFont":
102 self
.slant
= float(arg
)
104 raise UnsupportedPSFragment("Unsupported Postscript fragment '%s %s'" % (arg
, cmd
))
106 if self
.texname
is None:
109 self
.basepsname
= token
110 if self
.basepsname
is None:
111 self
.basepsname
= self
.texname
113 def getfontname(self
):
114 return self
.basepsname
117 if self
._font
is None:
118 if self
.fontfilename
is not None:
119 fontfile
= filelocator
.open(self
.fontfilename
, [filelocator
.format
.type1
], "rb")
120 t1font
= t1file
.from_PF_bytes(fontfile
.read())
122 assert self
.basepsname
== t1font
.name
, "corrupt MAP file"
124 metricfile
= filelocator
.open(os
.path
.splitext(self
.fontfilename
)[0], [filelocator
.format
.afm
])
126 self
._font
= font
.T1font(t1font
, None)
128 self
._font
= font
.T1font(t1font
, afmfile
.AFMfile(metricfile
))
131 metricfile
= filelocator
.open(self
.basepsname
, [filelocator
.format
.afm
])
132 self
._font
= font
.T1builtinfont(self
.basepsname
, afmfile
.AFMfile(metricfile
))
136 def getencoding(self
):
137 if self
._encoding
is _marker
:
138 if self
.encodingfilename
is not None:
139 encodingfile
= filelocator
.open(self
.encodingfilename
, [filelocator
.format
.tex_ps_header
], "rb")
140 ef
= encfile
.ENCfile(encodingfile
.read())
142 assert ef
.name
== "/%s" % self
.reencodefont
143 self
._encoding
= ef
.vector
146 self
._encoding
= None
147 return self
._encoding
150 return ("'%s' is '%s' read from '%s' encoded as '%s'" %
151 (self
.texname
, self
.basepsname
, self
.fontfile
, repr(self
.encodingfile
)))
155 def readfontmap(filenames
):
156 """ read font map from filename (without path) """
158 for filename
in filenames
:
159 mapfile
= filelocator
.open(filename
, [filelocator
.format
.fontmap
, filelocator
.format
.dvips_config
], mode
="rU")
161 for line
in mapfile
.readlines():
164 if not (line
=="" or line
[0] in (" ", "%", "*", ";" , "#")):
167 except (RuntimeError, UnsupportedPSFragment
), e
:
168 warnings
.warn("Ignoring line %i in mapping file '%s': %s" % (lineno
, mappath
, e
))
169 except UnsupportedFontFormat
, e
:
172 fontmap
[fm
.texname
] = fm