Ebnf2ps-1.0.8: src/Fonts.hs
--------------------------------------------------------------------------------
-- Copyright 1994 by Peter Thiemann
-- $Log: Fonts.hs,v $
-- Revision 1.1.1.1 1998/12/09 13:34:08 pjt
-- Imported sources
--
-- Revision 1.1 1993/08/31 12:31:32 thiemann
-- Initial revision
--
-- Revision 1.1 1993/08/31 12:31:32 thiemann
-- Initial revision
--
-- $Locker: $
-- Last Modified By: M. Walter
--------------------------------------------------------------------------------
module Fonts (FONT, makeFont, fontDescender, stringWidth, stringHeight, fontName, fontScale, noFont)
where
import Data.Char
import Numeric
data FONT = FONT String Int Int (String -> Int)
instance Eq FONT where
(==) (FONT s1 m1 n1 f1) (FONT s2 m2 n2 f2) = s1 == s2 && m1 == m2 && n1 == n2
noFont = FONT "" 0 0 (const 0)
data Afm = Descender Int
| CharMetric Int Int String Int Int Int Int
-- CharMetric charNo charWX charName llx lly urx ury
-- deriving Text
fontName :: FONT -> String
fontName (FONT name _ _ _) = name
fontScale :: FONT -> Int
fontScale (FONT _ scale _ _) = scale
fontDescender :: FONT -> Int
fontDescender (FONT _ _ theDescender _) = theDescender
stringWidth :: FONT -> String -> Int
stringWidth (FONT _ _ _ theStringWidth) = theStringWidth
stringHeight :: FONT -> String -> Int
stringHeight (FONT _ scale _ _) _ = scale * 100
makeFont :: String -> Int -> String -> FONT
makeFont fontName fontScale fontAfm =
FONT fontName fontScale theDescender
((`div` 10). (* fontScale). getStringWidth parsedAfm)
where
parsedAfm = parseAfmFile (lines fontAfm)
theDescender = getDescender parsedAfm
getStringWidth :: [Afm] -> String -> Int
getStringWidth afms str = sum (map (getCharWidth afms . ord) str)
getCharWidth :: [Afm] -> Int -> Int
getCharWidth (CharMetric charNo charWX charName llx lly urx ury: afms) chNo
| charNo == chNo = charWX
| otherwise = getCharWidth afms chNo
getCharWidth (_:afms) chNo = getCharWidth afms chNo
getCharWidth [] chNo = 0
getDescender :: [Afm] -> Int
getDescender (Descender d: _) = d
getDescender (_:rest) = getDescender rest
getDescender [] = 0
--------------------------------------------------------------------------------
parseAfmFile :: [String] -> [Afm]
parseAfmFile [] = []
parseAfmFile (('D':'e':'s':'c':'e':'n':'d':'e':'r':line):lines) =
Descender descender: parseAfmFile lines
where (descender,_):_ = readSigned readDec (skipWhite line)
parseAfmFile (('E':'n':'d':'C':'h':'a':'r':'M':'e':'t':'r':'i':'c':'s':_):_) = []
parseAfmFile (('C':' ':line):lines) = CharMetric charNo charWX charName llx lly urx ury:
parseAfmFile lines
where (charNo, rest1):_ = readSigned readDec (skipWhite line)
'W':'X':rest2 = skipWhiteOrSemi rest1
(charWX, rest3):_ = readDec (skipWhite rest2)
'N':rest4 = skipWhiteOrSemi rest3
(charName, rest5) = span isAlpha (skipWhite rest4)
'B':rest6 = skipWhiteOrSemi rest5
(llx, rest7):_ = readSigned readDec (skipWhite rest6)
(lly, rest8):_ = readSigned readDec (skipWhite rest7)
(urx, rest9):_ = readSigned readDec (skipWhite rest8)
(ury, _):_ = readSigned readDec (skipWhite rest9)
parseAfmFile (_:lines) = parseAfmFile lines
skipWhite = dropWhile isSpace
skipWhiteOrSemi = dropWhile isSkipChar
isSkipChar c = isSpace c || c == ';'