[reportlab-users] Using non-standard fonts on Mac OS X

Robin Becker reportlab-users@reportlab.com
Thu, 27 May 2004 17:08:57 +0100

This is a multi-part message in MIME format.
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Marius Gedminas wrote:

> On Wed, May 26, 2004 at 10:52:17PM +0200, Jerome Alet wrote:
>>Please, could the following explanation be added to ReportLab's
>>documentation ?
>>I think it clarifies things in a lot of minds (mine at the very least).
> Fixing the problem would be even better than documenting it IMHO ;)
> Marius Gedminas

It is certainly in plan. I'm not really certain about T1 fonts, but TTF's have 
reasonably easy family properties.

Platypus requires that we be able to do

font --> family + style so we know from a font which of the b/i bits are set
family + style --> font so we can change the style for a given font

If we cannot find a transition for a particular font we presumably just do an 

The intention is to have a per user cache of information about fonts. My current 
thinking is based on ttflist.py which is just a simple way to keep information 
about ttf /otf fonts without too much effort.

The same can probably be done for T1 if I can get my head around the AFM or PFB 
information. The standard 14 fonts are easy only the font file names seem to alter.

I don't think we intend to have this information updated automatically on the 
fly, so I'll be providing stuff to make the cache as command line utilities.
Robin Becker

Content-Type: text/plain;
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;

#copyright ReportLab Inc. 2000
#see license.txt for license details
#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/lib/fontslist.py?cvsroot=reportlab
#$Header: /rl_home/repository/users/robin/ttflist.py,v 1.1 2004/03/09 18:48:58 robin Exp $
__version__=''' $Id: ttflist.py,v 1.1 2004/03/09 18:48:58 robin Exp $ '''

class TTFList:
    def __init__(self):

    def readInfo(self):
        L = {}
        B = {}
        self._fontInfo = L
        self._badFiles = B

    def _checkBadFiles(self):
        from os.path import isfile
        BF = self._badFiles
        for fn in BF.keys():
            if not isfile(fn):
                del BF[fn]

    def _knownFiles(self):
        L = self._fontInfo
        KF = {}
        for k,v in L.items():
            fn = v[0]
            tm = v[1]
            if KF.has_key(fn):
                otm,N = KF[fn]
                assert otm==tm, "Times differ for same file"
                N += [k]
                KF[fn] = tm,N
                KF[fn] = tm,[k]
        return KF

    def getFontsListFN(self):
        from tempfile import gettempdir
        import os
        return os.path.join(gettempdir(),'ReportLabFontsList.txt')

    def build(self):
        from reportlab.pdfbase.ttfonts import TTFontFile, TTFError
        from reportlab import rl_config
        from os import stat
        from os.path import isfile
        from stat import ST_MTIME
        names = ('name','fullName','uniqueFontID')
        L = self._fontInfo
        KF = self._knownFiles()
        BF = self._badFiles
        from reportlab.lib.utils import _findFiles
        for fn in _findFiles(rl_config.TTFSearchPath,'.ttf'):
                tm = stat(fn)[ST_MTIME]
                if KF.has_key(fn):
                    kf = KF[fn]
                    del KF[fn]
                    if kf[0]==tm: continue
                    for n in kf[1]:
                        del L[n]

                if BF.has_key(fn):
                    if BF[fn]==tm: continue
                    del BF[fn]

                ttff = TTFontFile(fn,validate=1,charInfo=0)
                t = fn, tm, 'ttf', ttff.familyName, ttff.styleName
                print 'File: %s, TTF OK, fullName: "%s" psName: %s' % (fn, ttff.fullName, ttff.name)
                for n in names:
                    n = getattr(ttff,n)
                    if not L.has_key(n): L[n] = t
                del ttff
            except TTFError, x:
                print 'File:',fn,'  !!!!!!!!!!!',x,'!!!!!!!!!!!'
                BF[fn] = tm
        for fn, kf in KF.items():
            if not isfile(fn):
                for n in kf[1]:
                    del L[n]
        f = open(self.getFontsListFN(),'w')
        def _(a,b,L=L):
            x = L[a]
            y = L[b]
            return cmp((x[3],x[4],x[2],a,x[0],x[1]),(y[3],y[4],y[2],b,y[0],y[1]))
        K = L.keys()
        for k in K:
            print >> f, "L[%s]=%s" % (repr(k),repr(L[k]))
        K = BF.keys()
        for k in K:
            print >> f, "B[%s]=%s" % (repr(k),repr(BF[k]))

    def getFamilies(self):
        if not hasattr(self,'_families'):
            F = {}
            for fn, tm, fontType, familyName, styleName in self._fontInfo.values():
                S={styleName: fn}
                    F[familyName] = S
            self._families = F
        return self._families.keys()

    def getStyles(self):
        if not hasattr(self,'_styles'):
            S = {}
            for s in self._families.values():
                for k in s.keys():
                    S[k] = 1
            self._styles = S.keys()
        return self._styles

if __name__=='__main__':
    ttfl = TTFList()
    import sys
    if '--families' in sys.argv:
        print 'Families'
        F = ttfl.getFamilies()
        if F:
            #fn, tm, fontType, familyName, styleName
            for f in F:
                print f
                V = filter(lambda i: i[1][3]==f,ttfl._fontInfo.items())
                for k,v in V:
                    print '        ',', '.join((k,v[4],v[0]))
    if '--styles' in sys.argv:
        print 'Styles'
        F = ttfl.getStyles()
        if F:
            #fn, tm, fontType, familyName, styleName
            for f in F:
                print f
                V = filter(lambda i: i[1][4]==f,ttfl._fontInfo.items())
                for k,v in V:
                    print '        ',', '.join((k,v[3],v[0]))