packages feed

opentype 0.0.1 → 0.1.0

raw patch · 13 files changed

+1981/−119 lines, 13 filesdep +microlensdep +microlens-thdep +mtlPVP ok

version bump matches the API change (PVP)

Dependencies added: microlens, microlens-th, mtl, unordered-containers

API changes (from Hackage documentation)

- Opentype.Fileformat: data CmapTable
- Opentype.Fileformat: data GlyfTable
- Opentype.Fileformat: glyfTable :: OpentypeFont -> Maybe GlyfTable
- Opentype.Fileformat: maxpTable :: OpentypeFont -> Maybe MaxpTable
+ Opentype.Fileformat: [getCmaps] :: CmapTable -> [CMap]
+ Opentype.Fileformat: [glyphName] :: Glyph a -> String
+ Opentype.Fileformat: [glyphVector] :: GlyfTable -> (Vector (Glyph Int))
+ Opentype.Fileformat: [nameRecords] :: NameTable -> [NameRecord]
+ Opentype.Fileformat: _cmapTable :: Lens' OpentypeFont CmapTable
+ Opentype.Fileformat: _glyfTable :: Traversal' OpentypeFont GlyfTable
+ Opentype.Fileformat: _glyphComponents :: Traversal' StandardGlyph [GlyphComponent Int]
+ Opentype.Fileformat: _glyphContours :: Traversal' StandardGlyph [[CurvePoint]]
+ Opentype.Fileformat: _glyphInstructions :: Traversal' StandardGlyph Instructions
+ Opentype.Fileformat: _headTable :: Lens' OpentypeFont HeadTable
+ Opentype.Fileformat: _hheaTable :: Lens' OpentypeFont HheaTable
+ Opentype.Fileformat: _kernPairs :: Lens' KernTable [KernPair]
+ Opentype.Fileformat: _kernTable :: Traversal' OpentypeFont KernTable
+ Opentype.Fileformat: _maxpTable :: Traversal' OpentypeFont MaxpTable
+ Opentype.Fileformat: _nameTable :: Lens' OpentypeFont NameTable
+ Opentype.Fileformat: _os2Table :: Traversal' OpentypeFont OS2Table
+ Opentype.Fileformat: _otherTables :: Lens' OpentypeFont GenericTables
+ Opentype.Fileformat: _outlineTables :: Lens' OpentypeFont OutlineTables
+ Opentype.Fileformat: _postTable :: Lens' OpentypeFont PostTable
+ Opentype.Fileformat: emptyCmapTable :: CmapTable
+ Opentype.Fileformat: emptyGlyfTable :: GlyfTable
+ Opentype.Fileformat: emptyMaxpTable :: MaxpTable
+ Opentype.Fileformat: getScaledContours :: OpentypeFont -> StandardGlyph -> [[CurvePoint]]
+ Opentype.Fileformat: newtype CmapTable
+ Opentype.Fileformat: newtype GlyfTable
+ Opentype.Fileformat: type StandardGlyph = Glyph Int
+ Opentype.Fileformat: type WordMap a = Map Word32 a
+ Opentype.Fileformat.FontInfo: Bold :: Weight
+ Opentype.Fileformat.FontInfo: Condensed :: Width
+ Opentype.Fileformat.FontInfo: EditEmbed :: EmbedLicence
+ Opentype.Fileformat.FontInfo: Expanded :: Width
+ Opentype.Fileformat.FontInfo: ExtraBold :: Weight
+ Opentype.Fileformat.FontInfo: ExtraCondensed :: Width
+ Opentype.Fileformat.FontInfo: ExtraExpanded :: Width
+ Opentype.Fileformat.FontInfo: ExtraLight :: Weight
+ Opentype.Fileformat.FontInfo: FontInfo :: String -> Int -> FWord -> FWord -> FWord -> Weight -> Width -> Slant -> Maybe Bool -> Maybe Int -> Maybe Double -> Maybe FWord -> Maybe (FWord, FWord) -> Maybe (FWord, FWord) -> Maybe (FWord, FWord) -> Maybe (FWord, FWord) -> [EmbedLicence] -> Maybe FWord -> Maybe FWord -> Maybe (Int, Int) -> Maybe (Char, Char, Char, Char) -> Maybe (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Maybe (Word32, Word32, Word32, Word32) -> Maybe (Word32, Word32) -> Maybe FWord -> Maybe FWord -> Maybe Int -> Maybe Int -> Maybe FWord -> Maybe FWord -> String -> [Decoration] -> String -> String -> String -> String -> String -> String -> String -> String -> String -> String -> String -> String -> String -> String -> UTCTime -> Maybe UTCTime -> FontInfo
+ Opentype.Fileformat.FontInfo: Heavy :: Weight
+ Opentype.Fileformat.FontInfo: Italic :: Slant
+ Opentype.Fileformat.FontInfo: Light :: Weight
+ Opentype.Fileformat.FontInfo: MediumWeight :: Weight
+ Opentype.Fileformat.FontInfo: MediumWidth :: Width
+ Opentype.Fileformat.FontInfo: Negative :: Decoration
+ Opentype.Fileformat.FontInfo: NoSlant :: Slant
+ Opentype.Fileformat.FontInfo: NoSubsetEmbed :: EmbedLicence
+ Opentype.Fileformat.FontInfo: NormalWeight :: Weight
+ Opentype.Fileformat.FontInfo: Oblique :: Slant
+ Opentype.Fileformat.FontInfo: OnlyBitmapEmbed :: EmbedLicence
+ Opentype.Fileformat.FontInfo: Outlined :: Decoration
+ Opentype.Fileformat.FontInfo: PrintPreview :: EmbedLicence
+ Opentype.Fileformat.FontInfo: RestrictedEmbedding :: EmbedLicence
+ Opentype.Fileformat.FontInfo: SemiBold :: Weight
+ Opentype.Fileformat.FontInfo: SemiCondensed :: Width
+ Opentype.Fileformat.FontInfo: SemiExpanded :: Width
+ Opentype.Fileformat.FontInfo: Shadow :: Decoration
+ Opentype.Fileformat.FontInfo: StrikeOut :: Decoration
+ Opentype.Fileformat.FontInfo: Thin :: Weight
+ Opentype.Fileformat.FontInfo: UltraCondensed :: Width
+ Opentype.Fileformat.FontInfo: UltraExpanded :: Width
+ Opentype.Fileformat.FontInfo: Underscore :: Decoration
+ Opentype.Fileformat.FontInfo: [fontCapHeight] :: FontInfo -> Maybe FWord
+ Opentype.Fileformat.FontInfo: [fontCaretOffset] :: FontInfo -> Maybe FWord
+ Opentype.Fileformat.FontInfo: [fontCodepageRanges] :: FontInfo -> Maybe (Word32, Word32)
+ Opentype.Fileformat.FontInfo: [fontCopyright] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontCreated] :: FontInfo -> UTCTime
+ Opentype.Fileformat.FontInfo: [fontDarkPalette] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontDecoration] :: FontInfo -> [Decoration]
+ Opentype.Fileformat.FontInfo: [fontDescription] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontDesignerUrl] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontDesigner] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontEmBase] :: FontInfo -> FWord
+ Opentype.Fileformat.FontInfo: [fontEmbeddingLicence] :: FontInfo -> [EmbedLicence]
+ Opentype.Fileformat.FontInfo: [fontFamilyClass] :: FontInfo -> Maybe (Int, Int)
+ Opentype.Fileformat.FontInfo: [fontFamily] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontID] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontItalicAngle] :: FontInfo -> Maybe Double
+ Opentype.Fileformat.FontInfo: [fontLicenceUrl] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontLicence] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontLightPalette] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontLineGap] :: FontInfo -> FWord
+ Opentype.Fileformat.FontInfo: [fontLowerOpticalPointSize] :: FontInfo -> Maybe Int
+ Opentype.Fileformat.FontInfo: [fontLowestRecPPEM] :: FontInfo -> Maybe Int
+ Opentype.Fileformat.FontInfo: [fontManufacturer] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontModified] :: FontInfo -> Maybe UTCTime
+ Opentype.Fileformat.FontInfo: [fontMonospaced] :: FontInfo -> Maybe Bool
+ Opentype.Fileformat.FontInfo: [fontPanose] :: FontInfo -> Maybe (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)
+ Opentype.Fileformat.FontInfo: [fontPsName] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontSampleText] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontSlant] :: FontInfo -> Slant
+ Opentype.Fileformat.FontInfo: [fontStrikeoutPosition] :: FontInfo -> Maybe FWord
+ Opentype.Fileformat.FontInfo: [fontStrikoutSize] :: FontInfo -> Maybe FWord
+ Opentype.Fileformat.FontInfo: [fontSubFamilyExtra] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontSubScriptOffset] :: FontInfo -> Maybe (FWord, FWord)
+ Opentype.Fileformat.FontInfo: [fontSubScriptSize] :: FontInfo -> Maybe (FWord, FWord)
+ Opentype.Fileformat.FontInfo: [fontSuperScriptOffset] :: FontInfo -> Maybe (FWord, FWord)
+ Opentype.Fileformat.FontInfo: [fontSuperScriptSize] :: FontInfo -> Maybe (FWord, FWord)
+ Opentype.Fileformat.FontInfo: [fontTrademark] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontUnderlinePosition] :: FontInfo -> Maybe FWord
+ Opentype.Fileformat.FontInfo: [fontUnderlineThickness] :: FontInfo -> Maybe FWord
+ Opentype.Fileformat.FontInfo: [fontUnicodeRanges] :: FontInfo -> Maybe (Word32, Word32, Word32, Word32)
+ Opentype.Fileformat.FontInfo: [fontUnitsPerEm] :: FontInfo -> FWord
+ Opentype.Fileformat.FontInfo: [fontUpperOpticalPointSize] :: FontInfo -> Maybe Int
+ Opentype.Fileformat.FontInfo: [fontVendorID] :: FontInfo -> Maybe (Char, Char, Char, Char)
+ Opentype.Fileformat.FontInfo: [fontVendorUrl] :: FontInfo -> String
+ Opentype.Fileformat.FontInfo: [fontVersion] :: FontInfo -> Int
+ Opentype.Fileformat.FontInfo: [fontWeight] :: FontInfo -> Weight
+ Opentype.Fileformat.FontInfo: [fontWidth] :: FontInfo -> Width
+ Opentype.Fileformat.FontInfo: [fontXHeight] :: FontInfo -> Maybe FWord
+ Opentype.Fileformat.FontInfo: data Decoration
+ Opentype.Fileformat.FontInfo: data EmbedLicence
+ Opentype.Fileformat.FontInfo: data FontInfo
+ Opentype.Fileformat.FontInfo: data Slant
+ Opentype.Fileformat.FontInfo: data Weight
+ Opentype.Fileformat.FontInfo: data Width
+ Opentype.Fileformat.FontInfo: infoToTables :: FontInfo -> (HeadTable, HheaTable, NameTable, PostTable, OS2Table)
+ Opentype.Fileformat.FontInfo: instance GHC.Classes.Eq Opentype.Fileformat.FontInfo.Decoration
+ Opentype.Fileformat.FontInfo: instance GHC.Classes.Eq Opentype.Fileformat.FontInfo.Slant
+ Opentype.Fileformat.FontInfo: instance GHC.Classes.Eq Opentype.Fileformat.FontInfo.Weight
+ Opentype.Fileformat.FontInfo: instance GHC.Classes.Eq Opentype.Fileformat.FontInfo.Width
+ Opentype.Fileformat.FontInfo: instance GHC.Classes.Ord Opentype.Fileformat.FontInfo.Weight
+ Opentype.Fileformat.FontInfo: instance GHC.Classes.Ord Opentype.Fileformat.FontInfo.Width
+ Opentype.Fileformat.FontInfo: instance GHC.Show.Show Opentype.Fileformat.FontInfo.Slant
+ Opentype.Fileformat.FontInfo: instance GHC.Show.Show Opentype.Fileformat.FontInfo.Weight
+ Opentype.Fileformat.FontInfo: instance GHC.Show.Show Opentype.Fileformat.FontInfo.Width
+ Opentype.Fileformat.Unicode: codepointName :: CodePoint -> String
+ Opentype.Fileformat.Unicode: hasDescriptiveName :: CodePoint -> Bool
+ Opentype.Fileformat.Unicode: makeUnicodeTables :: UnicodeGlyphMap -> UnicodeKernPairs -> PostTable -> (CmapTable, GlyfTable, PostTable, KernTable)
+ Opentype.Fileformat.Unicode: nameToCodepoint :: String -> Maybe CodePoint
+ Opentype.Fileformat.Unicode: postscriptIndex :: String -> Maybe Int
+ Opentype.Fileformat.Unicode: postscriptName :: Int -> Maybe String
+ Opentype.Fileformat.Unicode: postscriptNames :: Vector String
+ Opentype.Fileformat.Unicode: type CodePoint = Int
+ Opentype.Fileformat.Unicode: type UnicodeGlyphMap = HashMap String (Glyph String)
+ Opentype.Fileformat.Unicode: type UnicodeKernPairs = [(String, String, FWord)]
- Opentype.Fileformat: CompositeGlyph :: [GlyphComponent] -> GlyphOutlines
+ Opentype.Fileformat: CompositeGlyph :: [GlyphComponent a] -> GlyphOutlines a
- Opentype.Fileformat: GlyfTable :: (Vector Glyph) -> GlyfTable
+ Opentype.Fileformat: GlyfTable :: (Vector (Glyph Int)) -> GlyfTable
- Opentype.Fileformat: Glyph :: Word16 -> Int16 -> FWord -> FWord -> FWord -> FWord -> GlyphOutlines -> Glyph
+ Opentype.Fileformat: Glyph :: String -> Word16 -> Int16 -> FWord -> FWord -> FWord -> FWord -> GlyphOutlines a -> Glyph a
- Opentype.Fileformat: GlyphComponent :: Int -> Maybe Instructions -> ShortFrac -> ShortFrac -> ShortFrac -> ShortFrac -> Int -> Int -> Bool -> Bool -> Bool -> Bool -> Bool -> GlyphComponent
+ Opentype.Fileformat: GlyphComponent :: a -> Maybe Instructions -> ShortFrac -> ShortFrac -> ShortFrac -> ShortFrac -> Int -> Int -> Bool -> Bool -> Bool -> Bool -> Maybe Bool -> GlyphComponent a
- Opentype.Fileformat: GlyphContours :: [[CurvePoint]] -> Instructions -> GlyphOutlines
+ Opentype.Fileformat: GlyphContours :: [[CurvePoint]] -> Instructions -> GlyphOutlines a
- Opentype.Fileformat: [advanceWidth] :: Glyph -> Word16
+ Opentype.Fileformat: [advanceWidth] :: Glyph a -> Word16
- Opentype.Fileformat: [componentID] :: GlyphComponent -> Int
+ Opentype.Fileformat: [componentID] :: GlyphComponent a -> a
- Opentype.Fileformat: [componentInstructions] :: GlyphComponent -> Maybe Instructions
+ Opentype.Fileformat: [componentInstructions] :: GlyphComponent a -> Maybe Instructions
- Opentype.Fileformat: [componentXX] :: GlyphComponent -> ShortFrac
+ Opentype.Fileformat: [componentXX] :: GlyphComponent a -> ShortFrac
- Opentype.Fileformat: [componentXY] :: GlyphComponent -> ShortFrac
+ Opentype.Fileformat: [componentXY] :: GlyphComponent a -> ShortFrac
- Opentype.Fileformat: [componentX] :: GlyphComponent -> Int
+ Opentype.Fileformat: [componentX] :: GlyphComponent a -> Int
- Opentype.Fileformat: [componentYX] :: GlyphComponent -> ShortFrac
+ Opentype.Fileformat: [componentYX] :: GlyphComponent a -> ShortFrac
- Opentype.Fileformat: [componentYY] :: GlyphComponent -> ShortFrac
+ Opentype.Fileformat: [componentYY] :: GlyphComponent a -> ShortFrac
- Opentype.Fileformat: [componentY] :: GlyphComponent -> Int
+ Opentype.Fileformat: [componentY] :: GlyphComponent a -> Int
- Opentype.Fileformat: [glyphOutlines] :: Glyph -> GlyphOutlines
+ Opentype.Fileformat: [glyphOutlines] :: Glyph a -> GlyphOutlines a
- Opentype.Fileformat: [glyphXmax] :: Glyph -> FWord
+ Opentype.Fileformat: [glyphXmax] :: Glyph a -> FWord
- Opentype.Fileformat: [glyphXmin] :: Glyph -> FWord
+ Opentype.Fileformat: [glyphXmin] :: Glyph a -> FWord
- Opentype.Fileformat: [glyphYmax] :: Glyph -> FWord
+ Opentype.Fileformat: [glyphYmax] :: Glyph a -> FWord
- Opentype.Fileformat: [glyphYmin] :: Glyph -> FWord
+ Opentype.Fileformat: [glyphYmin] :: Glyph a -> FWord
- Opentype.Fileformat: [leftSideBearing] :: Glyph -> Int16
+ Opentype.Fileformat: [leftSideBearing] :: Glyph a -> Int16
- Opentype.Fileformat: [matchPoints] :: GlyphComponent -> Bool
+ Opentype.Fileformat: [matchPoints] :: GlyphComponent a -> Bool
- Opentype.Fileformat: [overlapCompound] :: GlyphComponent -> Bool
+ Opentype.Fileformat: [overlapCompound] :: GlyphComponent a -> Bool
- Opentype.Fileformat: [roundXYtoGrid] :: GlyphComponent -> Bool
+ Opentype.Fileformat: [roundXYtoGrid] :: GlyphComponent a -> Bool
- Opentype.Fileformat: [scaledComponentOffset] :: GlyphComponent -> Bool
+ Opentype.Fileformat: [scaledComponentOffset] :: GlyphComponent a -> Maybe Bool
- Opentype.Fileformat: [useMyMetrics] :: GlyphComponent -> Bool
+ Opentype.Fileformat: [useMyMetrics] :: GlyphComponent a -> Bool
- Opentype.Fileformat: data Glyph
+ Opentype.Fileformat: data Glyph a
- Opentype.Fileformat: data GlyphComponent
+ Opentype.Fileformat: data GlyphComponent a
- Opentype.Fileformat: data GlyphOutlines
+ Opentype.Fileformat: data GlyphOutlines a

Files

Opentype/Fileformat.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TupleSections, TemplateHaskell #-}  -- | This module provides opentype file loading and writing.  An -- attempt was made to have a higher level interface without@@ -6,22 +6,30 @@  module Opentype.Fileformat        (-- * Types-         ShortFrac (..), Fixed, FWord, UFWord, GlyphID,+         ShortFrac (..), Fixed, FWord, UFWord, GlyphID, WordMap,           -- * Main datatype-         OpentypeFont (..), maxpTable, glyfTable, OutlineTables (..), GenericTables,+         OpentypeFont (..), OutlineTables (..), GenericTables,+         -- ** OpentypeFont lenses+         _headTable, _hheaTable, _cmapTable,+         _nameTable, _postTable, _os2Table, _kernTable, _outlineTables, _otherTables,+         _maxpTable, _glyfTable,           -- * IO          readOTFile, writeOTFile,          -- * Head table          HeadTable(..),          -- * Glyf table-         GlyfTable(..), Glyph(..), GlyphOutlines(..),+         GlyfTable(..), Glyph(..), StandardGlyph, GlyphOutlines(..), getScaledContours,+         emptyGlyfTable,          CurvePoint(..), Instructions, GlyphComponent(..),+         -- ** Glyf table lenses+         _glyphContours, _glyphInstructions, _glyphComponents,          -- * CMap table          CmapTable(..), CMap(..), PlatformID(..), MapFormat (..),+         emptyCmapTable,           -- * Hhea table          HheaTable(..),          -- * Maxp table-         MaxpTable(..),+         MaxpTable(..), emptyMaxpTable,          -- * Name table          NameTable(..), NameRecord(..),          -- * Post table@@ -29,7 +37,7 @@          -- * OS/2 table          OS2Table(..),          -- * Kern table-         KernTable(..), KernPair(..)+         KernTable(..), KernPair(..), _kernPairs        ) where import Opentype.Fileformat.Types import Opentype.Fileformat.Head@@ -53,6 +61,10 @@ import qualified Data.ByteString.Lazy as Lazy import qualified Data.ByteString as Strict import Data.ByteString.Unsafe+import Lens.Micro hiding (strict)+import Lens.Micro.TH+import Lens.Micro.Extras+import qualified Data.Vector as V import qualified Data.Map as M  type GenericTables = M.Map String Lazy.ByteString@@ -82,21 +94,21 @@   }   deriving Show + -- | tables for quadratic outlines (truetype or opentype) data OutlineTables =   QuadTables MaxpTable GlyfTable |   CubicTables    deriving Show -maxpTable :: OpentypeFont -> Maybe MaxpTable-maxpTable font = case outlineTables font of-  QuadTables m _ -> Just m-  _ -> Nothing--glyfTable :: OpentypeFont -> Maybe GlyfTable-glyfTable font = case outlineTables font of-  QuadTables _ g -> Just g-  _ -> Nothing+makeLensesFor [("headTable", "_headTable"),+               ("hheaTable", "_hheaTable"),+               ("cmapTable", "_cmapTable"),+               ("nameTable", "_nameTable"),+               ("postTable", "_postTable"),+               ("outlineTables", "_outlineTables"),+               ("otherTables", "_otherTables")]+               ''OpentypeFont  data ScalerType =   -- opentype with cff@@ -110,6 +122,50 @@ type SfntLocs = M.Map Scaler (Word32, Word32) type Scaler = Word32 +_maxpTable :: Traversal' OpentypeFont MaxpTable+_maxpTable f font = case outlineTables font of+  QuadTables m g -> (\m2 -> font { outlineTables = QuadTables m2 g })+                    <$> f m+  _ -> pure font++_glyfTable :: Traversal' OpentypeFont GlyfTable+_glyfTable f font = case outlineTables font of+  QuadTables m g -> (\g2 -> font {outlineTables = QuadTables m g2})+                    <$> f g+  _ -> pure font++_os2Table :: Traversal' OpentypeFont OS2Table+_os2Table f font = case os2Table font of+  Just t -> (\t2 -> font {os2Table = Just t2}) <$> f t+  Nothing -> pure font++_kernTable :: Traversal' OpentypeFont KernTable+_kernTable f font = case kernTable font of+  Just t -> (\t2 -> font {kernTable = Just t2}) <$> f t+  Nothing -> pure font++-- | @getScaledContours scaleOffset glyfTable glyph@: Get the scaled+-- contours for a simple or composite glyph.+getScaledContours :: OpentypeFont -> StandardGlyph -> [[CurvePoint]]+getScaledContours font glyph =+  case preview _glyfTable font of+    Nothing -> []+    Just (GlyfTable vec) ->+      getScaledContours' 10 (appleScaler font) vec glyph++getWindowsMap :: OpentypeFont -> Maybe CMap+getWindowsMap font =+  find (\cm -> cmapPlatform cm == MicrosoftPlatform &&+               cmapEncoding cm `elem` [0, 1]) $+  getCmaps $ cmapTable font+  +getUnicodeChar :: OpentypeFont -> Word32 -> Maybe (Glyph Int)+getUnicodeChar font c = do+  mp <- getWindowsMap font+  gID <- fmap fromIntegral $ M.lookup c $ glyphMap mp+  (V.!? gID) =<< glyphVector <$>+    preview _glyfTable font+ -- | write an opentype font to a file writeOTFile :: OpentypeFont -> FilePath -> IO () writeOTFile font file = @@ -117,16 +173,31 @@     CubicTables ->       error "cubic splines are not yet supported"     QuadTables maxpTbl (GlyfTable glyphs) ->-       let (lengths, glyphBs) = runPutM $ writeGlyphs glyphs+       let (lengths, glyphBs) = runPutM $ writeGlyphs (appleScaler font) glyphs            (format, locaBs) = runPutM $ writeLoca lengths            (longHor, hmtxBs) = runPutM $ writeHmtx glyphs-           head2 = updateHead glyphs $-                   (headTable font) {+           (xmin, ymin, xmax, ymax, _avgWdt) = getMinMax glyphs+           head2 = (headTable font) {                      headVersion = 0x00010000,+                     xMin = xmin,+                     yMin = ymin,+                     xMax = xmax,+                     yMax = ymax,                      fontDirectionHint = 2,                      longLocIndices = format }+           theAscent | ascent (hheaTable font) == 0 = fromIntegral ymax+                     | otherwise = ascent (hheaTable font)+           theDescent | descent (hheaTable font) == 0 = fromIntegral ymin+                      | otherwise = descent (hheaTable font)+           theLineGap = case os2Table font of+             Just os2 -> fromIntegral (unitsPerEm head2) + sTypoLineGap os2 -+                         ascent hhea2 + descent hhea2+             Nothing -> lineGap (hheaTable font)            hhea2 = updateHhea glyphs $-                   (hheaTable font) {numOfLongHorMetrics = fromIntegral longHor}+                   (hheaTable font) {numOfLongHorMetrics = fromIntegral longHor,+                                     ascent = theAscent,+                                     descent= theDescent,+                                     lineGap= theLineGap}            maxp2 = updateMaxp glyphs $                    maxpTbl {maxpVersion = 0x00010000}            headBs = Lazy.toStrict $ runPut $ putHeadTable head2@@ -135,7 +206,28 @@            maxpBs = Lazy.toStrict $ runPut $ putMaxpTable maxp2             nameBs = Lazy.toStrict $ runPut $ putNameTable $ nameTable font            postBs = Lazy.toStrict $ runPut $ putPostTable $ postTable font-           os2Bs  = (Lazy.toStrict . runPut . putOS2Table) <$> os2Table font+           os2Bs  = (Lazy.toStrict . runPut . putOS2Table .+                      (\os2 -> os2 {+                          usWinAscent = fromIntegral theAscent,+                          usWinDescent = fromIntegral $ -theDescent,+                          usFirstCharIndex = fromMaybe 0 $ do+                              mp <- getWindowsMap font+                              Just $ fromIntegral $ fst $ M.findMin $ glyphMap mp,+                          usLastCharIndex = fromMaybe 0xffff $ do+                              mp <- getWindowsMap font+                              let l = fst $ M.findMax $ glyphMap mp+                              if l > 0xffff then Nothing else Just $ fromIntegral l,+                          sxHeight =+                              if sxHeight os2 == 0+                              then fromMaybe 0 $+                                   glyphYmax <$> getUnicodeChar font 0x0078+                              else sxHeight os2,+                          sCapHeight =+                              if sCapHeight os2 == 0+                              then fromMaybe 0 $+                                   glyphYmax <$> getUnicodeChar font 0x0048+                              else sCapHeight os2}))+                    <$> os2Table font            kernBs = (Lazy.toStrict . runPut . putKernTable) <$> kernTable font            scaler | appleScaler font = AppleScaler                    | otherwise = QuadScaler
Opentype/Fileformat/Cmap.hs view
@@ -63,9 +63,12 @@ -- * 5: Johab -- * 10: Unicode UCS-4 -data CmapTable = CmapTable [CMap]+newtype CmapTable = CmapTable {getCmaps :: [CMap]}   deriving Show +emptyCmapTable :: CmapTable+emptyCmapTable = CmapTable []+ data CMap = CMap {   cmapPlatform :: PlatformID,   cmapEncoding :: Word16,@@ -351,7 +354,7 @@       size, segCount, searchRange, entrySelector :: Word16       entrySelector = iLog2 segCount       searchRange = 1 `shift` (fromIntegral $ entrySelector+1)-      segments = getSegments $ M.toList $ glyphMap cmap+      segments = getSegments $ M.toList $ subIntMap 0 0xffff $ glyphMap cmap       (codeSize, layout) = mapAccumL foldLayout (segCount*2) segments       foldLayout offset (RangeSegment start len code) =         (offset-2, Segment4layout (fromIntegral $ start+len-1)
+ Opentype/Fileformat/FontInfo.hs view
@@ -0,0 +1,568 @@+-- | This module implements a somewhat more logical structure+-- containing font information, without the need for an in-depth study+-- of the opentype spec.+module Opentype.Fileformat.FontInfo (FontInfo(..), Weight(..),+                                     Width(..), Slant(..), Decoration(..),+                                     EmbedLicence(..), infoToTables)+where+import Opentype.Fileformat+import Opentype.Fileformat.Types+import Data.Maybe+import Data.Word+import Data.Time+import Data.Char+import Data.Bits+import Data.Binary.Put+import Data.Foldable+import Text.Printf+import Lens.Micro+import Lens.Micro.Extras+import qualified Data.ByteString.Lazy as Lazy+import qualified Data.ByteString as Strict++data Weight = Thin | ExtraLight | Light | NormalWeight | MediumWeight+            | SemiBold | Bold | ExtraBold | Heavy+            deriving (Eq, Ord)++instance Show Weight where+  show Thin = "Thin"+  show ExtraLight = "Extra Light"+  show Light = "Light"+  show NormalWeight = "Regular"+  show MediumWeight = "Medium"+  show SemiBold = "Semibold"+  show Bold = "Bold"+  show ExtraBold = "Extra Bold"+  show Heavy = "Heavy"++data Width = UltraCondensed | ExtraCondensed | Condensed | SemiCondensed+           | MediumWidth | SemiExpanded | Expanded | ExtraExpanded | UltraExpanded+           deriving (Eq, Ord)++instance Show Width where+  show UltraCondensed = "Ultra Condensed"+  show ExtraCondensed = "Extra Condensed"+  show Condensed = "Condensed"+  show SemiCondensed = "Semi Condensed"+  show MediumWidth = "Regular"+  show SemiExpanded = "Semi Expanded"+  show Expanded = "Expanded"+  show ExtraExpanded = "Extra Expanded"+  show UltraExpanded = "Ultra Expanded"+  +data Slant = Italic | Oblique | NoSlant+  deriving Eq++instance Show Slant where+  show Italic = "Italic"+  show Oblique = "Oblique"+  show NoSlant = "Regular"++data Decoration = Underscore | Negative | Outlined | StrikeOut | Shadow+  deriving Eq++data EmbedLicence =+  -- | Fonts must not be modified, embedded or exchanged in any manner+  -- without first obtaining permission of the legal owner.  Caution:+  -- For Restricted License embedding to take effect, it must be the+  -- only level of embedding selected.+  RestrictedEmbedding |+  -- | The font may be embedded, and temporarily loaded on the remote+  -- system. Documents containing Preview & Print fonts must be opened+  -- “read-only;” no edits can be applied to the document.+  PrintPreview |+  -- | The font may be embedded but must only be installed temporarily+  -- on other systems. In contrast to Preview & Print fonts, documents+  -- containing Editable fonts may be opened for reading, editing is+  -- permitted, and changes may be saved.+  EditEmbed |+  -- | When this bit is set, the font may not be subsetted prior to+  -- embedding. Other embedding restrictions also apply.+  NoSubsetEmbed |+  -- | When this bit is set, only bitmaps contained in the font may be+  -- embedded. No outline data may be embedded. If there are no+  -- bitmaps available in the font, then the font is considered+  -- unembeddable and the embedding services will fail. Other+  -- embedding restrictions specified in bits 0-3 and 8 also apply.+  OnlyBitmapEmbed++licenceBit :: EmbedLicence -> Int+licenceBit RestrictedEmbedding = 0x0002+licenceBit PrintPreview = 0x0004+licenceBit EditEmbed = 0x0008+licenceBit NoSubsetEmbed = 0x0100+licenceBit OnlyBitmapEmbed = 0x0200++embeddedBits :: [EmbedLicence] -> Word16+embeddedBits = fromIntegral . sum . map licenceBit++-- |  Currently only english strings are supported.+data FontInfo = FontInfo {+  -- | Font Family name, without subfamily classifiers such as /Bold/, /Italic/, etc...+  fontFamily :: String,+  -- | Font version, multiplied by 1000, for example use 1500 for+  -- version 1.5+  fontVersion :: Int,+  -- | Number of units in an em-square.  Should be a power of 2.+  -- Typical values are 1024 or 2048.+  fontUnitsPerEm :: FWord,+  -- | Distance between the bottom of the em-square and the baseline+  -- in font design units.+  fontEmBase :: FWord,+  -- | Linegap in font design units.  Defined as distance between+  -- baselines - height of em square (`fontUnitsPerEm`).+  fontLineGap :: FWord,+  -- | Weight of the font.  /default/: `NormalWeight`+  fontWeight :: Weight,+  -- | Width of the font.  /default/: `MediumWidth`+  fontWidth :: Width,+  -- | Slant of the font.  /default/: `NoSlant`+  fontSlant :: Slant,+  -- | fixed width font.  /default/: False+  fontMonospaced :: Maybe Bool,+  -- | Smallest readable size in pixels.  /default/: 6+  fontLowestRecPPEM :: Maybe Int,+  -- | talic angle in counter-clockwise degrees from the+  -- vertical. Zero for upright text, negative for text that leans to+  -- the right (forward).  /default/: 0+  fontItalicAngle :: Maybe Double,+  -- | The amount by which a slanted highlight on a glyph needs to be+  -- shifted to produce the best appearance. /default/: 0+  fontCaretOffset :: Maybe FWord,+  -- | The recommended size in font design units for subscripts for+  -- this font. /default/: (fontUnitsPerEM/2, fontUnitsPerEM/2)+  fontSubScriptSize :: Maybe (FWord, FWord),+  -- | The recommended offset in font design units for subscripts for+  -- this font. /default/: (0, -fontUnitsPerEM/4)+  fontSubScriptOffset :: Maybe (FWord, FWord),+  -- | The recommended size in font design units for superscripts for+  -- this font. /default/: (fontUnitsPerEM/2, fontUnitsPerEM/2)+  fontSuperScriptSize :: Maybe (FWord, FWord),+  -- | The recommended offset in font design units for superscripts for+  -- this font. /default/: (cos(90 + italicAngle)*snd superscriptYOffset, (fontUnitsPerEM-fontEmBase)/2)+  fontSuperScriptOffset :: Maybe (FWord, FWord),+  -- | ndicates font embedding licensing rights for the+  -- font. Embeddable fonts may be stored in a document. When a+  -- document with embedded fonts is opened on a system that does not+  -- have the font installed (the remote system), the embedded font+  -- may be loaded for temporary (and in some cases, permanent) use on+  -- that system by an embedding-aware application. Embedding+  -- licensing rights are granted by the vendor of the font.+  -- /default/: []+  fontEmbeddingLicence :: [EmbedLicence],+  -- | Width of the strikeout stroke in font design units.  This field+  -- should normally be the width of the em dash for the current+  -- font. If the size is one, the strikeout line will be the line+  -- represented by the strikeout position field. If the value is two,+  -- the strikeout line will be the line represented by the strikeout+  -- position and the line immediately above the strikeout+  -- position. /default/: fontUnitsPerEm/20 +  fontStrikoutSize :: Maybe FWord,+  -- | The position of the top of the strikeout stroke relative to the+  -- baseline in font design units.  Positive values represent+  -- distances above the baseline, while negative values represent+  -- distances below the baseline. A value of zero falls directly on+  -- the baseline, while a value of one falls one pel above the+  -- baseline. The value of strikeout position should not interfere+  -- with the recognition of standard characters, and therefore should+  -- not line up with crossbars in the+  -- font. /default/. fontUnitsPerEm/5.5+  fontStrikeoutPosition :: Maybe FWord,+  -- | The font class and font subclass are registered values assigned+  -- by IBM to each font family. This parameter is intended for use in+  -- selecting an alternate font when the requested font is not+  -- available. The font class is the most general and the font+  -- subclass is the most specific. The high byte of this field+  -- contains the family class, while the low byte contains the family+  -- subclass. See <https://www.microsoft.com/typography/otspec/ibmfc.htm>+  -- for more information.+  -- /default/: (0,0)+  fontFamilyClass :: Maybe (Int, Int),+  -- | The four character identifier for the vendor of the given type+  -- face. This is not the royalty owner of the original artwork. This+  -- is the company responsible for the marketing and distribution of+  -- the typeface that is being classified. It is reasonable to assume+  -- that there will be 6 vendors of ITC Zapf Dingbats for use on+  -- desktop platforms in the near future (if not already). It is also+  -- likely that the vendors will have other inherent benefits in+  -- their fonts (more kern pairs, unregularized data, hand hinted,+  -- etc.). This identifier will allow for the correct vendor's type+  -- to be used over another, possibly inferior, font file. The Vendor+  -- ID value is not required.+  -- /default/: (' ', ' ', ' ', ' ')+  fontVendorID :: Maybe (Char, Char, Char, Char),+  -- | Panose-1 Classification.  /default/: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0)+  fontPanose :: Maybe (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int),+  -- | Supported Unicode Ranges: See+  -- https://www.microsoft.com/typography/otspec/os2.htm#ur.+  -- /default/ (3, 0, 0, 0)+  fontUnicodeRanges :: Maybe (Word32, Word32, Word32, Word32),+  -- | Supported Codepage Ranges. See+  -- https://www.microsoft.com/typography/otspec/os2.htm#cpr.+  -- /default/: (1, 0)+  fontCodepageRanges :: Maybe (Word32, Word32),+  -- | This metric specifies the distance between the baseline and the+  -- approximate height of non-ascending lowercase letters measured in+  -- FUnits.  /default/ height of glyph at U+0078 (LATIN SMALL LETTER+  -- X)+  fontXHeight :: Maybe FWord,+  -- | This metric specifies the distance between the baseline and the+  -- approximate height of uppercase letters measured in FUnits.+  -- /default/ height of glyph at U+0048 (LATIN CAPITAL LETTER H).+  fontCapHeight :: Maybe FWord,+  -- | This field is used for fonts with multiple optical styles.+  -- +  -- This value is the lower value of the size range for which this+  -- font has been designed. The units for this field are TWIPs+  -- (one-twentieth of a point, or 1440 per inch). The value is+  -- inclusive—meaning that that font was designed to work best at+  -- this point size through, but not including, the point size+  -- indicated by usUpperOpticalPointSize. When used with other+  -- optical fonts that set usLowerOpticalPointSize and+  -- usUpperOpticalPointSize, it would be expected that another font+  -- has this same value as this entry in the usUpperOpticalPointSize+  -- field, unless this font is designed for the lowest size+  -- range. The smallest font in an optical size set should set this+  -- value to 0.When working across multiple optical fonts, there+  -- should be no intentional gaps or overlaps in the+  -- ranges. usLowerOpticalPointSize must be less than+  -- usUpperOpticalPointSize. The maximum valid value is 0xFFFE.+  -- /default/: 0+  fontLowerOpticalPointSize :: Maybe Int,+  -- | fontUpperOptThis field is used for fonts with multiple optical styles.+  --+  -- This value is the upper value of the size range for which this+  -- font has been designed. The units for this field are TWIPs+  -- (one-twentieth of a point, or 1440 per inch). The value is+  -- exclusive—meaning that that font was designed to work best below+  -- this point size down to the usLowerOpticalPointSize+  -- threshold. When used with other optical fonts that set+  -- usLowerOpticalPointSize and usUpperOpticalPointSize, it would be+  -- expected that another font has this same value as this entry in+  -- the usLowerOpticalPointSize field, unless this font is designed+  -- for the highest size range. The largest font in an optical size+  -- set should set this value to 0xFFFF, which is interpreted as+  -- infinity. When working across multiple optical fonts, there+  -- should be no intentional or overlaps left in the+  -- ranges. usUpperOpticalPointSize must be greater than+  -- usLowerOpticalPointSize. The minimum valid value for this field+  -- is 2 (two). The largest possible inclusive point size represented+  -- by this field is 3276.65 points, any higher values would be+  -- represented as infinity.  /default/: 0xffff+  fontUpperOpticalPointSize :: Maybe Int,+  -- | This is the suggested distance of the top of the underline from+  -- the baseline (negative values indicate below baseline).  The+  -- PostScript definition of this FontInfo dictionary key (the y+  -- coordinate of the center of the stroke) is not used for+  -- historical reasons. The value of the PostScript key may be+  -- calculated by subtracting half the underlineThickness from the+  -- value of this field. /default/: /default/ -fontUnitsPerEm/8+  fontUnderlinePosition :: Maybe FWord,+  -- | suggested values for the underline thickness. /default/ fontUnitsPerEm/10+  fontUnderlineThickness :: Maybe FWord,+  -- | This field is used when the font has a subfamily other than+  -- Weight, Width or Slant.  Should not include any width, weight or+  -- slant descriptions. /default/: ""+  fontSubFamilyExtra :: String,+  -- | Set if the font has any of these decorations.  /default/: []+  fontDecoration :: [Decoration],+  -- | Copyright notice.  Default: []+  fontCopyright :: String,+  -- | Unique font identifier+  fontID :: String,+  -- | postscriptName.  /default/: full name with hyphen substituted for spaces.+  fontPsName :: String,+  -- | trademark. /default/: ""+  fontTrademark :: String,+  -- | Manufacturer Name.  /default/: ""+  fontManufacturer :: String,+  -- | name of the designer of the typeface.  /default/: ""+  fontDesigner :: String,+  -- | description of how the font may be legally used, or different+  -- example scenarios for licensed use. This field should be written+  -- in plain language, not legalese.  /default/: ""+  fontLicence :: String,+  -- | description of the typeface. Can contain revision information,+  -- usage recommendations, history, features, etc.+  fontDescription :: String,+  -- | URL where additional licensing information can be found.+  -- /default/ ""+  fontLicenceUrl :: String,+  -- | URL of typeface designer (with protocol, e.g., http://, ftp://).+  fontDesignerUrl :: String,+  -- | URL of font vendor (with protocol, e.g., http://, ftp://). If a+  -- unique serial number is embedded in the URL, it can be used to+  -- register the font.+  fontVendorUrl :: String,+  -- | This can be the font name, or any other text that the designer+  -- thinks is the best sample to display the font in.  /default/: ""+  fontSampleText :: String,+  -- | This ID, if used in the CPAL table’s Palette Labels Array,+  -- specifies that the corresponding color palette in the CPAL table+  -- is appropriate to use with the font when displaying it on a light+  -- background such as white. Name table strings for this ID specify+  -- the user interface strings associated with this+  -- palette. /default/ ""+  fontLightPalette :: String,+  -- | Dark Backgound Palette. This ID, if used in the CPAL table’s+  -- Palette Labels Array, specifies that the corresponding color+  -- palette in the CPAL table is appropriate to use with the font+  -- when displaying it on a dark background such as black. Name table+  -- strings for this ID specify the user interface strings associated+  -- with this palette+  fontDarkPalette :: String,+  -- | font creation time+  fontCreated :: UTCTime,+  -- | font modification time.  /default/: creation time.+  fontModified :: Maybe UTCTime+  }++weightClass :: Weight -> Word16+weightClass Thin = 100+weightClass ExtraLight = 200+weightClass Light = 300+weightClass NormalWeight = 400+weightClass MediumWeight = 500+weightClass SemiBold = 600+weightClass Bold = 700+weightClass ExtraBold = 800+weightClass Heavy = 900++widthClass :: Width -> Word16+widthClass UltraCondensed = 1+widthClass ExtraCondensed = 2+widthClass Condensed = 3+widthClass SemiCondensed = 4+widthClass MediumWidth = 5+widthClass SemiExpanded = 6+widthClass Expanded = 7+widthClass ExtraExpanded = 8+widthClass UltraExpanded = 9++(+++) :: String -> String -> String+s +++ "" = s+s +++ t = s ++ " " ++ t++notRegular :: (Show a, Eq a) => a -> a -> String+notRegular reg sub =+  if reg == sub then "" else show sub++(///) :: Maybe c -> c -> c+(///) = flip fromMaybe++-- | Fill in font information into the font tables+infoToTables :: FontInfo -> (HeadTable, HheaTable, NameTable, PostTable, OS2Table)+infoToTables fi = (headTbl, hheaTbl, nameTbl, postTbl, os2Tbl)+  where+    headTbl = HeadTable {+      headVersion = 0x00010000,+      fontRevision = fromIntegral $ +                     fromIntegral (fontVersion fi) * 0x00010000 `quot`+                     (1000 :: Integer),+      baselineYZero = True,+      sidebearingXZero = True,+      pointsizeDepend = False,+      integerScaling = False,+      alterAdvanceWidth = False,+      verticalFont = False,+      linguisticRenderingLayout = False,+      metamorphosisEffects = False,+      rightToLeftGlyphs = False,+      indicRearrangements = False,+      losslessFontData = False,+      convertedFont = False,+      clearTypeOptimized = False,+      lastResortFont = False,+      unitsPerEm = fromIntegral $ fontUnitsPerEm fi,+      created = fontCreated fi,+      modified = fontModified fi /// fontCreated fi,+      xMin = 0,+      yMin = 0,+      xMax = 0,+      yMax = 0,+      boldStyle = fontWeight fi > NormalWeight,+      italicStyle = fontSlant fi == Italic,+      underlineStyle = Underscore `elem` fontDecoration fi,+      outlineStyle = Outlined `elem` fontDecoration fi,+      shadowStyle = Shadow `elem` fontDecoration fi,+      condensedStyle = fontWidth fi < MediumWidth,+      extendedStyle = fontWidth fi > MediumWidth,+      lowerRecPPEM = (fromIntegral <$> fontLowestRecPPEM fi) /// 6,+      fontDirectionHint = 2,+      longLocIndices = False,+      glyphDataFormat = 0}+    hheaTbl = HheaTable {+      version = 0x00010000,+      ascent = 0,+      descent = 0,+      lineGap = 0,+      advanceWidthMax = 0,+      minLeftSideBearing = 0,+      minRightSideBearing = 0,+      xMaxExtent = 0,+      caretSlopeRise = case fontItalicAngle fi /// 0 of+          0 -> 1+          -90 -> 0+          a -> round $ cos (pi*a/180 + pi/2) * 2048,+      caretSlopeRun = case fontItalicAngle fi /// 0 of+          0 -> 0+          -90 -> 1+          a -> round $ sin (pi*a/180 + pi/2) * 2048,+      caretOffset = fontCaretOffset fi /// 0,+      numOfLongHorMetrics = 0}+    mkNameRecords _ "" = []+    mkNameRecords nid ns = +      [NameRecord MacintoshPlatform 0 0 nid $+       Strict.pack $ map (fromIntegral . (.&.0xff) . ord) ns,+       NameRecord MicrosoftPlatform 1 0x0409 nid $+       Lazy.toStrict $ runPut (traverse_ (putWord16be . fromIntegral . ord) ns)]+    (versionMajor, versionMinor) = fontVersion fi `quotRem` 1000+    fullName = fontFamily fi +++ subFamily+    subFamily = fontSubFamilyExtra fi ++++                notRegular NormalWeight (fontWeight fi) ++++                notRegular MediumWidth (fontWidth fi) ++++                notRegular NoSlant (fontSlant fi)+    wsSubFamily+      | fontWeight fi == NormalWeight && fontSlant fi == NoSlant+      = "Regular"+      | otherwise = weightName +++ notRegular NoSlant (fontSlant fi)+      where+        weightName+          | fontWeight fi < NormalWeight = "Thin"+          | fontWeight fi > NormalWeight = "Bold"+          | otherwise = ""++    nameTbl = NameTable $+        concat [+          mkNameRecords 0 $ fontCopyright fi,+          mkNameRecords 1 $ fontFamily fi +++ fontSubFamilyExtra fi ++++            notRegular MediumWidth (fontWidth fi),+          mkNameRecords 2 wsSubFamily,+          mkNameRecords 3 $ fontID fi,+          mkNameRecords 4 fullName,+          mkNameRecords 5 $ printf "Version %d.%03d" versionMajor versionMinor,+          mkNameRecords 6 $ if null (fontPsName fi)+            then take 63 $ map (\c -> if c == ' ' then '-' else c) fullName+            else fontPsName fi,+          mkNameRecords 7 $ fontTrademark fi,+          mkNameRecords 8 $ fontManufacturer fi,+          mkNameRecords 9 $ fontDesigner fi,+          mkNameRecords 10 $ fontDescription fi,+          mkNameRecords 11 $ fontVendorUrl fi,+          mkNameRecords 12 $ fontDesignerUrl fi,+          mkNameRecords 13 $ fontLicence fi,+          mkNameRecords 14 $ fontLicenceUrl fi,+          mkNameRecords 16 $ fontFamily fi,+          mkNameRecords 17 subFamily,+          mkNameRecords 19 $ fontSampleText fi,+          mkNameRecords 21 $+            if null (fontSubFamilyExtra fi) then ""+            else fontFamily fi +++ fontSubFamilyExtra fi,+          mkNameRecords 22 $+            if null (fontSubFamilyExtra fi) then ""+            else notRegular NormalWeight (fontWeight fi) ++++                 notRegular MediumWidth (fontWidth fi) ++++                 notRegular NoSlant (fontSlant fi),+          mkNameRecords 23 $ fontLightPalette fi,+          mkNameRecords 24 $ fontDarkPalette fi]+    postTbl = PostTable {+      postVersion = PostTable2,+      italicAngle = round $ (fontItalicAngle fi /// 0)+                    * 0x00010000,+      underlinePosition = fontUnderlinePosition fi ///+                          (- fromIntegral (fontUnitsPerEm fi `quot` 8)),+      underlineThickness = fontUnderlineThickness fi ///+                           fromIntegral (fontUnitsPerEm fi `quot` 10),+      isFixedPitch = fromIntegral $ fromEnum $+                     fontMonospaced fi /// False,+      minMemType42 = 0,+      maxMemType42 = 0,+      minMemType1 = 0,+      maxMemType1 = 0,+      glyphNameIndex = [],+      postStrings = []}+    (panose1, panose2, panose3, panose4, panose5,+     panose6, panose7, panose8, panose9, panose10) =+      fontPanose fi /// (0, 0, 0, 0, 0, 0, 0, 0, 0, 0)+    vendorID = case fontVendorID fi of+      Nothing -> 0x20202020+      Just (a, b, c, d) -> fromIntegral $+        ord a `shift` 24 .|. ord b `shift` 16 .|.+        ord c `shift` 8  .|. ord d+    selectionFlags = makeFlag+      [fontSlant fi == Italic,+       Underscore `elem` fontDecoration fi,+       Negative `elem` fontDecoration fi,+       Outlined `elem` fontDecoration fi,+       StrikeOut `elem` fontDecoration fi,+       fontWeight fi > NormalWeight,+       fontWeight fi == NormalWeight &&+       fontWidth fi == MediumWidth &&+       fontSlant fi == NoSlant &&+       null (fontSubFamilyExtra fi),+       True,+       null (fontSubFamilyExtra fi),+       fontSlant fi == Oblique]+    os2Tbl = OS2Table {+      os2version = 5,+      xAvgCharWidth = 0,+      usWeightClass = weightClass $ fontWeight fi,+      usWidthClass = widthClass $ fontWidth fi,+      fsType = embeddedBits $ fontEmbeddingLicence fi,+      ySubscriptXSize = (fst <$> fontSubScriptSize fi) ///+                        (fontUnitsPerEm fi `quot` 2),+      ySubscriptYSize = (snd <$> fontSubScriptSize fi) ///+                        (fontUnitsPerEm fi `quot` 2),+      ySubscriptXOffset = (fst <$> fontSubScriptOffset fi) /// 0,+      ySubscriptYOffset = (snd <$> fontSubScriptOffset fi) ///+                          (- (fontUnitsPerEm fi `quot` 4)),+      ySuperscriptXSize = (fst <$> fontSuperScriptSize fi) ///+                          (fontUnitsPerEm fi `quot` 2),+      ySuperscriptYSize = (snd <$> fontSuperScriptSize fi) ///+                          (fontUnitsPerEm fi `quot` 2),+      ySuperscriptXOffset = (fst <$> fontSuperScriptOffset fi) ///+                            round (realToFrac (ySubscriptYOffset os2Tbl) *+                                   cos (pi/180*((fontItalicAngle fi /// 0) + pi/2))),+      ySuperscriptYOffset = (snd <$> fontSuperScriptOffset fi) ///+                            ((fontUnitsPerEm fi - fontEmBase fi) `quot` 2),+      yStrikeoutSize = fontStrikoutSize fi ///+                       fromIntegral (fontUnitsPerEm fi `quot` 20),+      yStrikeoutPosition = fontStrikeoutPosition fi ///+                           fromIntegral (fontUnitsPerEm fi*10 `quot` 55),+      bFamilyClass = fromIntegral $+                     ((\(x,y) -> (x `shift` 8 .|. y)) <$> fontFamilyClass fi)+                     /// 0,+      bFamilyType = fromIntegral panose1,+      bSerifStyle = fromIntegral panose2,+      bWeight = fromIntegral panose3,+      bProportion = fromIntegral panose4, +      bContrast = fromIntegral panose5,+      bStrokeVariation = fromIntegral panose6,+      bArmStyle = fromIntegral panose7,+      bLetterform = fromIntegral panose8,+      bMidline = fromIntegral panose9,+      bXHeight = fromIntegral panose10,+      ulUnicodeRange1 = (view _1 <$> fontUnicodeRanges fi) /// 3,+      ulUnicodeRange2 = (view _2 <$> fontUnicodeRanges fi) /// 0,+      ulUnicodeRange3 = (view _3 <$> fontUnicodeRanges fi) /// 0,+      ulUnicodeRange4 = (view _4 <$> fontUnicodeRanges fi) /// 0,+      achVendID = vendorID,+      fsSelection = selectionFlags,+      usFirstCharIndex = 0,+      usLastCharIndex = 0,+      sTypoAscender = fontUnitsPerEm fi - fontEmBase fi,+      sTypoDescender = fromIntegral $ - fontEmBase fi,+      sTypoLineGap = fontLineGap fi,+      usWinAscent = 0,+      usWinDescent = 0,+      ulCodePageRange1 = (fst <$> fontCodepageRanges fi) /// 1,+      ulCodePageRange2 = (snd <$> fontCodepageRanges fi) /// 0,+      sxHeight = 0,+      sCapHeight = fontCapHeight fi /// 0,+      usDefaultChar = 0,+      usBreakChar = 0,+      usMaxContext = 1,+      usLowerOpticalPointSize = fromIntegral $+        fontLowerOpticalPointSize fi /// 0,+      usUpperOpticalPointSize = fromIntegral $+        fontUpperOpticalPointSize fi /// 0xffff}
Opentype/Fileformat/Glyph.hs view
@@ -1,23 +1,25 @@-{-# LANGUAGE MultiWayIf, TupleSections #-}+{-# LANGUAGE MultiWayIf, TupleSections, DeriveTraversable #-} module Opentype.Fileformat.Glyph where import Opentype.Fileformat.Types import Opentype.Fileformat.Maxp import Opentype.Fileformat.Hhea import Opentype.Fileformat.Head import qualified Data.Vector as V-import Data.Foldable (traverse_, for_)+import Data.Foldable (traverse_, for_, foldlM) import Control.Monad+import Control.Monad.Cont+import Data.List (foldl')+import Data.Maybe (isJust, fromMaybe) import Data.Function (fix) import qualified Data.ByteString.Lazy as Lazy import qualified Data.ByteString as Strict import Data.Word import Data.Int-import Data.Maybe (isJust) import Data.Bits import Data.Binary import Data.Binary.Put import Data.Binary.Get-+import Lens.Micro  -- | This table contains the data that defines the appearance of -- the glyphs in the font. This includes specification of the points@@ -25,24 +27,57 @@ -- instructions that grid-fit that glyph. The glyf table supports the -- definition of simple glyphs and compound glyphs, that is, glyphs -- that are made up of other glyphs.-data GlyfTable = GlyfTable (V.Vector Glyph)+newtype GlyfTable = GlyfTable {glyphVector :: (V.Vector (Glyph Int))}   deriving Show -data Glyph = Glyph {+type StandardGlyph = Glyph Int++emptyGlyfTable :: GlyfTable+emptyGlyfTable = GlyfTable V.empty++-- | The glyph type is parametrized over the type of glyph reference for compound glyphs.+data Glyph a = Glyph {+  -- | The name of the glyph.  This field isn't used when writing+  -- truetype files.+  glyphName :: String,   advanceWidth :: Word16,   leftSideBearing :: Int16,+  -- | Bounding box: /will be overwritten/   glyphXmin :: FWord,+  -- | Bounding box: /will be overwritten/   glyphYmin :: FWord,+  -- | Bounding box: /will be overwritten/   glyphXmax :: FWord,+  -- | Bounding box: /will be overwritten/   glyphYmax :: FWord,-  glyphOutlines :: GlyphOutlines}-  deriving Show+  glyphOutlines :: GlyphOutlines a}+  deriving (Show, Functor, Foldable, Traversable) -data GlyphOutlines =+data GlyphOutlines a =   GlyphContours [[CurvePoint]] Instructions |-  CompositeGlyph [GlyphComponent]-  deriving Show+  CompositeGlyph [GlyphComponent a]+  deriving (Show, Functor, Foldable, Traversable) +-- | traversal over simple glyph contours+_glyphContours :: Traversal' StandardGlyph [[CurvePoint]]+_glyphContours f glyph = case glyphOutlines glyph of+  GlyphContours pts instrs -> (\pts2 -> glyph {glyphOutlines = GlyphContours pts2 instrs})+                              <$> f pts+  _ -> pure glyph++-- | instructions for simple glyphs+_glyphInstructions :: Traversal' StandardGlyph Instructions+_glyphInstructions f glyph = case glyphOutlines glyph of+  GlyphContours pts instrs -> (\instrs2 -> glyph {glyphOutlines = GlyphContours pts instrs2})+                              <$> f instrs+  _ -> pure glyph++-- | traversal over compound glyph components+_glyphComponents :: Traversal' StandardGlyph [GlyphComponent Int]+_glyphComponents f glyph = case glyphOutlines glyph of+  CompositeGlyph comps -> (\c -> glyph {glyphOutlines = CompositeGlyph c}) <$> f comps+  _ -> pure glyph+ -- | @CurvePoint x y onCurve@: Points used to describe the outline -- using lines and quadratic beziers.  Coordinates are absolute (not -- relative).  If two off-curve points follow each other, an on-curve@@ -53,9 +88,9 @@ -- | TODO: make a proper datatype for instructions. type Instructions = V.Vector Word8 -data GlyphComponent =+data GlyphComponent a =   GlyphComponent {-  componentID :: Int,+  componentID :: a,   componentInstructions :: Maybe Instructions,   -- | transformation matrix for scaling the glyph   componentXX :: ShortFrac,@@ -75,7 +110,7 @@   -- offset is unscaled (microsoft and opentype default) in the   -- rasterizer.   componentY :: Int,-    -- | see previous+  -- | see previous   matchPoints :: Bool,   -- | For the xy values if `matchPoints` is `False`.   roundXYtoGrid :: Bool,@@ -87,16 +122,20 @@   -- affect behaviors in some platforms, however. (See Apple’s   -- specification for details regarding behavior in Apple platforms.)   overlapCompound :: Bool,-  -- | The component offset is scaled by the rasterizer (apple).  Should be-  -- set to `False` (opentype default), unless the font is meant to work-  -- with old apple software.-  scaledComponentOffset :: Bool+  -- | If Just True, The component offset should be scaled by the+  -- rasterizer.  If the value is set to Nothing, it is platform+  -- dependent (False for opentype).  Set this value to "Just False"+  -- for new fonts.+  scaledComponentOffset :: Maybe Bool   }-  deriving Show+  deriving (Show, Functor, Foldable, Traversable) -emptyGlyph :: Glyph-emptyGlyph = Glyph 0 0 0 0 0 0 (GlyphContours [] V.empty)+sum' :: Num a => [a] -> a+sum' = foldl' (+) 0 +emptyGlyph :: StandardGlyph+emptyGlyph = Glyph ".notdef" 0 0 0 0 0 0 (GlyphContours [] V.empty)+ readHmetrics :: Int -> Int -> Get [(Word16, Int16)] readHmetrics 1 m = do   aw <- getWord16be@@ -116,7 +155,7 @@   else (*2).fromIntegral <$> getWord16be   readGlyphTable :: [(Int, Int)] -> [(Word16, Int16)] -> Strict.ByteString-               -> Either String (V.Vector Glyph)+               -> Either String (V.Vector StandardGlyph) readGlyphTable glyphSizes hmetrics glyfBs =   V.fromList <$> zipWithM readGlyph glyphSizes hmetrics   where@@ -129,10 +168,10 @@           Right (_, _, g) -> Right $ g {advanceWidth = aw, leftSideBearing = lsb}  -- return bytestring lengths-writeGlyphs :: V.Vector Glyph -> PutM (V.Vector Int)-writeGlyphs = traverse writeGlyph+writeGlyphs :: Bool -> V.Vector StandardGlyph -> PutM (V.Vector Int)+writeGlyphs scale vec = traverse (writeGlyph . updateBB scale vec) vec -writeGlyph :: Glyph -> PutM Int+writeGlyph :: StandardGlyph -> PutM Int writeGlyph g = do   putLazyByteString bs   replicateM_ pad (putWord8 0)@@ -153,7 +192,7 @@   where     offsets = V.scanl (+) 0 vec     -writeHmtx :: V.Vector Glyph -> PutM Int+writeHmtx :: V.Vector StandardGlyph -> PutM Int writeHmtx gs   | V.null gs = return 0   | otherwise = @@ -173,8 +212,8 @@       tl = findTail (len-2) 0       (dbl, sngl) = V.splitAt (len-tl) gs   -putGlyph :: Glyph -> Put-putGlyph (Glyph _ _ xmin ymin xmax ymax outlines) = do+putGlyph :: StandardGlyph -> Put+putGlyph (Glyph _ _ _ xmin ymin xmax ymax outlines) = do   putInt16be $ case outlines of     GlyphContours pts _ -> fromIntegral $ length pts     _ -> -1@@ -189,7 +228,7 @@       traverse_ (putComponent True) (init comps)       putComponent False $ last comps -getGlyph :: Get Glyph+getGlyph :: Get StandardGlyph getGlyph = do   n <- getInt16be   xmin <- getInt16be@@ -203,7 +242,7 @@       (c, more) <- getComponent       if more then (c:) <$> nextComponent         else return [c]-  return $ Glyph 0 0 xmin ymin xmax ymax outlines+  return $ Glyph "" 0 0 xmin ymin xmax ymax outlines  isShort :: FWord -> Bool isShort n = abs n <= 255@@ -261,7 +300,7 @@     allPts = case concat points of       [] -> []       pts@(p: pts2) -> p: zipWith subCoord pts2 pts-    subCoord (CurvePoint x1 y1 _) (CurvePoint x2 y2 on) =+    subCoord (CurvePoint x2 y2 on) (CurvePoint x1 y1 _) =       CurvePoint (x2-x1) (y2-y1) on     flags = case allPts of       [] -> []@@ -312,10 +351,9 @@     (c, r) = splitAt n l  toOffsets :: (Num a) => [a] -> [a]-toOffsets [] = []-toOffsets (x:xs) = scanl (-) x xs+toOffsets = tail . scanl (+) 0    -getContour :: Int -> Get GlyphOutlines+getContour :: Int -> Get (GlyphOutlines Int) getContour 0 =  return $ GlyphContours [] V.empty getContour nContours = do   lastPts <- replicateM nContours (fromIntegral <$> getWord16be)@@ -332,14 +370,113 @@ isShortInt :: Int -> Bool isShortInt x = x <= 127 && x >= -128 -glyphExtent, glyphRsb :: Glyph -> Int16+glyphExtent, glyphRsb :: StandardGlyph -> Int16 glyphRsb g =   fromIntegral (advanceWidth g) - glyphExtent g    glyphExtent glyf = leftSideBearing glyf + (glyphXmax glyf - glyphXmin glyf) -updateHhea :: V.Vector Glyph -> HheaTable -> HheaTable-updateHhea v h = V.foldl updateHhea1+extendBB :: (FWord, FWord, FWord, FWord)+         -> (FWord, FWord, FWord, FWord)+         -> (FWord, FWord, FWord, FWord) +extendBB (xMin1, yMin1, xMax1, yMax1)+  (xMin2, yMin2, xMax2, yMax2) =+  (min xMin1 xMin2, min yMin1 yMin2,+   max xMax1 xMax2, max yMax1 yMax2)++extendBB2 :: (FWord, FWord, FWord, FWord) -> CurvePoint+          -> (FWord, FWord, FWord, FWord) +extendBB2 (xMin1, yMin1, xMax1, yMax1) (CurvePoint x y _) =+  (min xMin1 x, min yMin1 y, max xMax1 x, max yMax1 y)++minBB :: (FWord, FWord, FWord, FWord)+minBB = (maxBound, maxBound, minBound, minBound)++safeIndex :: Int -> [a] -> Maybe a+safeIndex _ [] = Nothing+safeIndex 0 (x:_) = Just x+safeIndex n (_:l) = safeIndex (n-1) l++onCurve :: CurvePoint -> Bool+onCurve (CurvePoint _ _ on) = on++-- get scaled on-curve points+getScaledContours' :: Int -> Bool -> V.Vector StandardGlyph -> StandardGlyph -> [[CurvePoint]]+getScaledContours' d scale vec glyph+  | d <= 0 = []+  | otherwise =+    case glyphOutlines glyph of+      GlyphContours cp _ -> cp+      CompositeGlyph comps ->+        flip runCont id $ foldlM scalePoints [] comps+    where+      getCompContours :: GlyphComponent Int -> [[CurvePoint]]+      getCompContours comp =+        case vec V.!? componentID comp of+          Nothing -> []+          Just g2 -> getScaledContours' (d-1) scale vec g2+      scalePoints :: [[CurvePoint]] -> GlyphComponent Int -> Cont [[CurvePoint]] [[CurvePoint]]+      scalePoints pts comp+        | matchPoints comp = cont $ \next -> +            let pts2 = getCompContours comp+                (tx, ty) = fromMaybe (0, 0) $ do+                  CurvePoint x1 y1 _ <- safeIndex (componentX comp) $ concat pts+                  CurvePoint x2 y2 _ <- safeIndex (componentY comp) $ concat pts2+                  return (realToFrac $ x1-x2, realToFrac $ y1-y2)+            in if useMyMetrics comp+               then map (map (scalePt tx ty)) pts2+               else next $ pts ++ map (map (scalePt tx ty)) pts2+        | otherwise =  cont $ \next -> +            if useMyMetrics comp+            then map (map (scalePt offsetX offsetY)) (getCompContours comp)+            else next $ pts ++ map (map (scalePt offsetX offsetY)) (getCompContours comp)+            where+              sqr x = x*x+              (offsetX, offsetY) =+                if fromMaybe scale (scaledComponentOffset comp)+                then (realToFrac (componentX comp) *+                      sqrt (sqr (realToFrac (componentXX comp)) ++                            sqr (realToFrac (componentYX comp))),+                      realToFrac (componentY comp) *+                      sqrt (sqr (realToFrac (componentXY comp)) ++                            sqr (realToFrac (componentYY comp))))+                else (realToFrac (componentX comp), realToFrac (componentY comp))+              xx, xy, yx, yy :: Double+              (xx, xy, yx, yy) =+                (realToFrac (componentXX comp),+                 realToFrac (componentXY comp),+                 realToFrac (componentYX comp),+                 realToFrac (componentYY comp))+              scalePt tx ty (CurvePoint x y on) =+                if roundXYtoGrid comp then+                  CurvePoint+                  (round tx + round (realToFrac x * xx + realToFrac y * xy))+                  (round ty + round (realToFrac x * yx + realToFrac y * yy))+                  on+                else+                  CurvePoint+                  (round $ realToFrac x * xx + realToFrac y * xy + tx)+                  (round $ realToFrac x * yx + realToFrac y * yy + ty)+                  on++glyphBB :: Bool -> V.Vector StandardGlyph -> StandardGlyph -> (FWord, FWord, FWord, FWord)+glyphBB scale vec glyph =+  foldl' extendBB2 minBB $+  filter onCurve $ concat $+  getScaledContours' 10 scale vec glyph++updateBB :: Bool -> V.Vector StandardGlyph -> StandardGlyph -> StandardGlyph+updateBB scale vec glyph =+  glyph {glyphXmin = xMin_,+         glyphYmin = yMin_,+         glyphXmax = xMax_,+         glyphYmax = yMax_}+  where+    (xMin_, yMin_, xMax_, yMax_) = glyphBB scale vec glyph+++updateHhea :: V.Vector StandardGlyph -> HheaTable -> HheaTable+updateHhea v h = V.foldl' updateHhea1                  (h {advanceWidthMax     = minBound,                      minLeftSideBearing  = maxBound,                      minRightSideBearing = maxBound,@@ -347,22 +484,21 @@                  v    -updateMinMax :: (FWord, FWord, FWord, FWord)-             -> Glyph -> (FWord, FWord, FWord, FWord)-updateMinMax (xmin, ymin, xmax, ymax) g =+updateMinMax  :: (FWord, FWord, FWord, FWord, Double)+              -> StandardGlyph -> (FWord, FWord, FWord, FWord, Double)+updateMinMax (xmin, ymin, xmax, ymax, totWidth) g =   (min xmin (glyphXmin g),    min ymin (glyphYmin g),    max xmax (glyphXmax g),-   max ymax (glyphYmax g))--updateHead :: V.Vector Glyph -> HeadTable -> HeadTable-updateHead vec headTbl =-  headTbl {xMin = xmin, yMin = ymin,-           xMax = xmax, yMax = ymax}-  where (xmin, ymin, xmax, ymax) =-          V.foldl updateMinMax (maxBound, maxBound, minBound, minBound) vec+   max ymax (glyphYmax g),+   totWidth + realToFrac (glyphXmax g - glyphXmin g)) -updateHhea1 :: HheaTable -> Glyph -> HheaTable+getMinMax :: V.Vector StandardGlyph -> (FWord, FWord, FWord, FWord, FWord)+getMinMax vec =+  over _5 (round . (/ realToFrac (V.length vec))) $+  V.foldl' updateMinMax (maxBound, maxBound, minBound, minBound, 0) vec+  +updateHhea1 :: HheaTable -> StandardGlyph -> HheaTable updateHhea1 hhea g =   hhea {advanceWidthMax     = max (advanceWidthMax hhea)                               (advanceWidth g),@@ -372,8 +508,8 @@                               (glyphRsb g),         xMaxExtent          = max (xMaxExtent hhea)                               (glyphExtent g)}-updateMaxp :: V.Vector Glyph -> MaxpTable -> MaxpTable-updateMaxp vec tbl = V.foldl (updateMaxp1 vec)+updateMaxp :: V.Vector StandardGlyph -> MaxpTable -> MaxpTable+updateMaxp vec tbl = V.foldl' (updateMaxp1 vec)                      (tbl {numGlyphs = 0,                            maxPoints = 0,                            maxContours = 0,@@ -383,7 +519,7 @@                            maxComponentDepth = 0})                      vec -updateMaxp1 :: V.Vector Glyph -> MaxpTable -> Glyph -> MaxpTable+updateMaxp1 :: V.Vector StandardGlyph -> MaxpTable -> StandardGlyph -> MaxpTable updateMaxp1 vec maxp glyf =   maxp {numGlyphs            = numGlyphs maxp + 1,         maxPoints            = max (maxPoints maxp) $@@ -400,7 +536,7 @@                                componentDepth vec glyf}  overComponents :: ([[CurvePoint]] -> Word16) -> ([Word16] ->  Word16)-               -> Int -> Bool -> V.Vector Glyph -> Glyph -> Word16+               -> Int -> Bool -> V.Vector StandardGlyph -> StandardGlyph -> Word16 overComponents f h maxD d v g   | maxD <= 0 = 0   | otherwise =@@ -414,10 +550,10 @@                 Nothing -> 0                 Just g2 -> overComponents f h (maxD-1) False v g2    -glyfPoints, glyfContours, componentRefs, componentDepth, componentPoints, componentContours :: V.Vector Glyph -> Glyph -> Word16+glyfPoints, glyfContours, componentRefs, componentDepth, componentPoints, componentContours :: V.Vector StandardGlyph -> StandardGlyph -> Word16  glyfPoints  =-  overComponents (sum . map (fromIntegral.length)) (const 0) 2 False+  overComponents (sum' . map (fromIntegral.length)) (const 0) 2 False  glyfContours =   overComponents (fromIntegral.length) (const 0) 2 False@@ -426,15 +562,15 @@   overComponents (const 0) (fromIntegral.length) 2 True  componentPoints =-  overComponents (sum . map (fromIntegral . length)) sum 10 True+  overComponents (sum' . map (fromIntegral . length)) sum' 10 True  componentDepth =   overComponents (const 0) ((+1).maximum) 10 True  componentContours =-  overComponents (fromIntegral.length) sum 10 True+  overComponents (fromIntegral.length) sum' 10 True -putComponent :: Bool -> GlyphComponent -> Put+putComponent :: Bool -> GlyphComponent Int -> Put putComponent more c = do   putWord16be flag   putWord16be $ fromIntegral $ componentID c@@ -466,8 +602,8 @@           if matchPoints c           then componentX c > 0xff ||                componentY c > 0xff-          else (not $ isShortInt $ componentX c) ||-               (not $ isShortInt $ componentY c),+          else not (isShortInt $ componentX c) ||+               not (isShortInt $ componentY c),           not $ matchPoints c,           roundXYtoGrid c,           componentXX c /= 1 &&@@ -481,10 +617,10 @@           isJust (componentInstructions c),           useMyMetrics c,           overlapCompound c,-          scaledComponentOffset c,-          not $ scaledComponentOffset c]+          fromMaybe False (scaledComponentOffset c),+          not $ fromMaybe True (scaledComponentOffset c)] -getComponent :: Get (GlyphComponent, Bool)+getComponent :: Get (GlyphComponent Int, Bool) getComponent = do   flag <- getWord16be   gID <- getWord16be@@ -529,6 +665,9 @@   return (     GlyphComponent (fromIntegral gID) instructions tXX tXY tYX tYY       cX cY (not $ byteAt flag 1) (byteAt flag 2)-      (byteAt flag 9) (byteAt flag 10) (byteAt flag 11),+      (byteAt flag 9) (byteAt flag 10)+      (if | (byteAt flag 11) -> Just True+          | (byteAt flag 12) -> Just False+          | otherwise -> Nothing),     byteAt flag 5) -- more components 
Opentype/Fileformat/Head.hs view
@@ -15,7 +15,7 @@ -- most likely to be written and other information about the placement -- of glyphs in the em square. data HeadTable = HeadTable {-  -- | 0x00010000 for version 1.0.  /Will be auto written./+  -- | 0x00010000 for version 1.0.  /Will be overwritten./   headVersion :: Fixed,   -- | set by font manufacturer.   fontRevision :: Fixed,@@ -77,13 +77,13 @@   -- bit 15 zero   unitsPerEm :: Word16,   created :: UTCTime,  modified :: UTCTime,-  -- | /Will be auto written./+  -- | /Will be overwritten./   xMin :: FWord,-  -- | /Will be auto written./+  -- | /Will be overwritten./   yMin :: FWord,-  -- | /Will be auto written./+  -- | /Will be overwritten./   xMax :: FWord,-  -- | /Will be auto written./+  -- | /Will be overwritten./   yMax :: FWord,   -- macStyle   @@ -98,9 +98,9 @@   lowerRecPPEM :: Word16,   -- | deprecated, will be set to 2   fontDirectionHint :: Int16,-  -- | 0 for short offsets, 1 for long.  /Will be auto written./+  -- | 0 for short offsets, 1 for long.  /Will be overwritten./   longLocIndices :: Bool,-  -- | 0 for current format.  /Will be auto written./+  -- | 0 for current format.  /Will be overwritten./   glyphDataFormat :: Int16   }   deriving Show
Opentype/Fileformat/Hhea.hs view
@@ -9,21 +9,21 @@  -- | This table contains information for horizontal layout.  data HheaTable = HheaTable {-  -- | 0x00010000 (1.0), will be auto written.+  -- | 0x00010000 (1.0), will be overwritten.   version :: Fixed,-  -- | Distance from baseline of highest ascender+  -- | Distance from baseline of highest ascender.  /Will be overwritten./   ascent :: FWord,-  -- | Distance from baseline of lowest descender+  -- | Distance from baseline of lowest descender.  /Will be overwritten./   descent :: FWord,-  -- | typographic line gap+  -- | typographic line gap.  Will be overwritten when OS/2 table is present.   lineGap :: FWord,-  -- | /Will be auto written./+  -- | /Will be overwritten./   advanceWidthMax :: UFWord,-  -- | /Will be auto written./+  -- | /Will be overwritten./   minLeftSideBearing :: FWord,-  -- | /Will be auto written./+  -- | /Will be overwritten./   minRightSideBearing :: FWord,-  -- | /Will be auto written./+  -- | /Will be overwritten./   xMaxExtent :: FWord,   -- | used to calculate the slope of the caret (rise/run) set to 1 for vertical caret   caretSlopeRise :: Int16,@@ -31,7 +31,7 @@   caretSlopeRun :: Int16,   -- | set value to 0 for non-slanted fonts   caretOffset :: FWord,-  -- | number of advance widths in metrics table. /Will be auto written./+  -- | number of advance widths in metrics table. /Will be overwritten./   numOfLongHorMetrics :: Word16}   deriving Show 
Opentype/Fileformat/Kern.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE TemplateHaskell #-} module Opentype.Fileformat.Kern where import Opentype.Fileformat.Types@@ -7,6 +8,7 @@ import Data.Bits import Control.Monad import Data.Foldable+import Lens.Micro.TH  -- | @KernPair left right adjustment@: Pair of kerning values.  left -- and right are indices in the glyph table.@@ -14,11 +16,13 @@   deriving Show  data KernTable = KernTable {-  -- | various flags+  -- | various flags, will be overwritten with 1 (default)   coverage :: Word8,   kernPairs :: [KernPair]}   deriving Show +makeLensesFor [("kernPairs", "_kernPairs")] ''KernTable+ getKernTable :: Get KernTable getKernTable = do   version <- getWord16be@@ -40,12 +44,12 @@         KernPair <$> getWord16be <*>  getWord16be <*> getInt16be  putKernTable :: KernTable -> Put-putKernTable (KernTable cov pairs) = do+putKernTable (KernTable _ pairs) = do   putWord16be 0   putWord16be 1   putWord16be 0   putWord16be $ fromIntegral $ 14+6 * length pairs-  putWord16be $ fromIntegral cov+  putWord16be $ fromIntegral 1   putWord16be $ fromIntegral len   putWord16be searchRange   putWord16be entrySelector
Opentype/Fileformat/Maxp.hs view
@@ -43,6 +43,9 @@   maxComponentDepth :: Word16}   deriving Show +emptyMaxpTable :: MaxpTable+emptyMaxpTable = MaxpTable 0x00010000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + putMaxpTable :: MaxpTable -> Put putMaxpTable maxp = do   putWord32be $ maxpVersion maxp
Opentype/Fileformat/Name.hs view
@@ -1,12 +1,15 @@ module Opentype.Fileformat.Name where import Opentype.Fileformat.Types-import Data.List (sort)+import Data.List (sort, foldl')+import Data.Maybe (fromMaybe) import Data.Word import Control.Monad import Data.Binary.Put+import Data.Tuple (swap) import Data.Foldable (for_, traverse_) import Data.Traversable (for)+import qualified Data.HashMap.Strict as HM import qualified Data.ByteString as Strict  -- | This table allows multilingual strings to be associated with the@@ -33,7 +36,7 @@ -- encodingID.  This library doesn't do any conversion.  For more -- information see the opentype specification: -- https://www.microsoft.com/typography/otspec/name.htm-data NameTable = NameTable [NameRecord]+data NameTable = NameTable {nameRecords :: [NameRecord]}   deriving Show  data NameRecord = NameRecord {@@ -59,18 +62,25 @@   putWord16be 0   putWord16be $ fromIntegral len   putWord16be $ fromIntegral $ len * 12 + 6-  for_ (zip offsets records) $ \(offset, r) -> do+  for_ records $ \r -> do     putPf $ namePlatform r     putWord16be $ nameEncoding r     putWord16be $ nameLanguage r     putWord16be $ nameID r     putWord16be $ fromIntegral $ Strict.length $ nameString r-    putWord16be offset-  traverse_ (putByteString.nameString) records+    putWord16be $ fromMaybe 0 $ fromIntegral <$>+      HM.lookup (nameString r) offsets+  traverse_ putByteString $ reverse noDups   where len = length records         records = sort records_-        lengths = map (fromIntegral . Strict.length . nameString) records-        offsets = scanl (+) 0 lengths+        (noDups, offsets) = snd $ foldl'+          (\(offset, (noDups, mp)) r ->+             if HM.member (nameString r) mp+             then (offset, (noDups, mp))+             else (Strict.length (nameString r) + offset, +                    (nameString r:noDups, HM.insert (nameString r) offset mp)))+          (0, ([], HM.empty)) records+          readNameTable :: Strict.ByteString -> Either String NameTable readNameTable bs = do
Opentype/Fileformat/Post.hs view
@@ -35,8 +35,6 @@   -- vertical. Zero for upright text, negative for text that leans to   -- the right (forward).   italicAngle :: Fixed,-  -- | suggested values for the underline thickness.-  underlinePosition :: FWord,   -- | This is the suggested distance of the top of the underline from   -- the baseline (negative values indicate below baseline).   --@@ -45,6 +43,8 @@   -- historical reasons. The value of the PostScript key may be   -- calculated by subtracting half the underlineThickness from the   -- value of this field.+  underlinePosition :: FWord,+  -- | suggested values for the underline thickness.   underlineThickness :: FWord,   -- | Set to 0 if the font is proportionally spaced, non-zero if the   -- font is not proportionally spaced (i.e. monospaced).
+ Opentype/Fileformat/Unicode.hs view
@@ -0,0 +1,111 @@+-- | Utilities for making it easier to create Tables from Unicode+-- data.+module Opentype.Fileformat.Unicode+  (-- * Unicode tables+    UnicodeGlyphMap, UnicodeKernPairs, makeUnicodeTables,+    -- * Postscript Names+    module Opentype.Fileformat.Unicode.PostNames,+  )++where+import Opentype.Fileformat.Unicode.PostNames+import Opentype.Fileformat+import Opentype.Fileformat.FontInfo+import Data.Maybe (fromMaybe, isNothing, mapMaybe)+import qualified Data.Vector as V+import qualified Data.Map as M+import Data.IntSet as IS (empty)+import Data.List (sortBy)+import Data.Either+import Control.Applicative ((<|>))+import qualified Data.HashMap.Strict as HM+import Data.Function++-- | A map from glyphnames to glyphs.  Unicode points are derived+-- using `nameToCodepoint`.  Names without matching codepoint can only+-- be used in composite glyphs.  If the `glyphName` has no matching+-- key in the map, it will be substituted by the empty glyph+type UnicodeGlyphMap = HM.HashMap String (Glyph String)+type UnicodeKernPairs = [(String, String, FWord)]++-- | Create an opentype font from a `UnicodeGlyphMap` and `FontInfo`+-- structure.+makeUnicodeFont :: UnicodeGlyphMap -> UnicodeKernPairs -> FontInfo -> OpentypeFont+makeUnicodeFont uniGlyphs kernPrs info =+  OpentypeFont False headTbl hheaTbl cmapTbl+  nameTbl postTbl (Just os2Tbl) (if null (kernPairs kernTbl) then Nothing else Just kernTbl)+  (QuadTables emptyMaxpTable glyfTbl) M.empty+  where+    (headTbl, hheaTbl, nameTbl, postTbl', os2Tbl) =+      infoToTables info+    (cmapTbl, glyfTbl, postTbl, kernTbl) =+      makeUnicodeTables uniGlyphs kernPrs postTbl'+  ++-- | Given a `UnicodeGlyphMap`, create a `CmapTable`, `GlyfTable` and+-- `KernTable` and update the `PostTable`.+makeUnicodeTables :: UnicodeGlyphMap -> UnicodeKernPairs -> PostTable -> (CmapTable, GlyfTable, PostTable, KernTable)+makeUnicodeTables uniGlyphs kernPrs postTbl =+  (cmapTbl, GlyfTable glyphVector,+   postTbl {postVersion = PostTable2,+            glyphNameIndex = postscriptNameIndex,+            postStrings = postscriptExtraNames},+   KernTable 1 realKernPairs)+  where+    uniqueCodepoints, codepoints :: [(String, (Int, Glyph String))]+    glyphComps :: [(String, Glyph String)]+    uniqueCodepoints =+      filter (\(s, (_, g)) -> glyphName g == s)+      codepoints+    (codepoints, glyphComps) =+      partitionEithers $ map getCodePoint $+      HM.toList uniGlyphs+    nameMap :: HM.HashMap String GlyphID+    nameMap =+      HM.fromList $ flip zip [1..] $+      map fst (sortBy (compare `on` (fst.snd)) uniqueCodepoints)+      ++ map fst glyphComps+    postscriptNameMap :: HM.HashMap String Int+    postscriptNameMap =+      HM.fromList $ zip postscriptExtraNames [258..]+    postscriptExtraNames :: [String]+    postscriptExtraNames =+      filter (isNothing . postscriptIndex) $+      map fst uniqueCodepoints+    postscriptNameIndex :: [Int]+    postscriptNameIndex =+      flip map uniqueCodepoints $ \(n, _) ->+      fromMaybe 0 $+      HM.lookup n postscriptNameMap+      <|> postscriptIndex n+    glyphVector :: V.Vector StandardGlyph+    glyphVector =+      V.fromList $+      map (normalizeGlyph.snd.snd) uniqueCodepoints +++      map (normalizeGlyph.snd) glyphComps+    codepointMap :: WordMap GlyphID+    codepointMap =+      M.fromList $+      flip map codepoints $ \(_, (code, g)) ->+      (fromIntegral code,+       fromMaybe 0 $ HM.lookup (glyphName g) nameMap)+    normalizeGlyph :: Glyph String -> StandardGlyph+    normalizeGlyph =+      fmap (fromIntegral . fromMaybe 0 . (`HM.lookup` nameMap))+    getCodePoint (name, g) =+      case nameToCodepoint name of+        Nothing -> Right (name, g)+        Just cp -> Left (name, (cp, g))+    cmapTbl = CmapTable $ bmpCmap : fullCmap+    bmpCmap = CMap MicrosoftPlatform 1 0 MapFormat4 IS.empty codepointMap+    fullCmap+      | M.null codepointMap ||+        fst (M.findMax codepointMap) <= 0xffff = []+      | otherwise =+        [CMap MicrosoftPlatform 10 0+         MapFormat12 IS.empty codepointMap]+    realKernPairs = flip mapMaybe kernPrs $ \(s1, s2, x) -> do+      c1 <- HM.lookup s1 nameMap+      c2 <- HM.lookup s2 nameMap+      return $ KernPair c1 c2 x+    
+ Opentype/Fileformat/Unicode/PostNames.hs view
@@ -0,0 +1,919 @@+module Opentype.Fileformat.Unicode.PostNames+  (CodePoint, codepointName, hasDescriptiveName, nameToCodepoint,+   postscriptIndex, postscriptName, postscriptNames)+where+import qualified Data.Map.Strict as M+import qualified Data.HashMap.Strict as HM+import Text.Printf+import qualified Data.Set as S+import Opentype.Fileformat+import Data.Tuple (swap)+import Data.Word+import qualified Data.Vector as V+import Data.Char+import Data.Maybe (fromMaybe)+import Data.List (isPrefixOf)++type CodePoint = Int++-- | Standard name for this codepoint.  Will be a descriptive name if+-- one is available, otherwise uni<hex-codepoint>.+codepointName :: CodePoint -> String+codepointName cp =+  case M.lookup cp codeMap of+    Just n -> n+    Nothing+      | cp > 0xffff -> printf "u%06x" cp+      | otherwise -> printf "uni%04x" cp++hasDescriptiveName :: CodePoint -> Bool+hasDescriptiveName cp = M.member cp codeMap++nameToCodepoint :: String -> Maybe CodePoint+nameToCodepoint name+  | prefix == "uni" &&+    nDigits == 4 =+    Just $ foldl (\t d -> t*16 + fromIntegral (digitToInt d))+    0 hexNum+  | prefix == "u" &&+    nDigits >= 4 &&+    nDigits <= 6 =+    Just $ foldl (\t d -> t*16 + fromIntegral (digitToInt d))+    0 hexNum+  | otherwise = HM.lookup prefix nameMap+  where+    (prefix, r) = span isAlpha name+    hexNum = takeWhile isHexDigit r+    nDigits = length hexNum++nameMap :: HM.HashMap String CodePoint+nameMap = HM.fromList $ map swap aglfn++codeMap :: M.Map CodePoint String+codeMap = M.fromList aglfn++-- | index of the string in the list of standard postscript names, if any.+postscriptIndex :: String -> Maybe Int+postscriptIndex n = HM.lookup n postscriptIndexMap++-- | standard postscript name at index, if any.+postscriptName :: Int -> Maybe String+postscriptName i+  | i < 0 || i >= V.length postscriptNames = Nothing+  | otherwise = Just $ postscriptNames V.! i++postscriptIndexMap :: HM.HashMap String Int+postscriptIndexMap =+  HM.fromList $+  zip (V.toList postscriptNames) [1..]+                  +aglfn :: [(CodePoint, String)]+aglfn = [(0x0041,"A"),+         (0x00C6,"AE"),+         (0x01FC,"AEacute"),+         (0x00C1,"Aacute"),+         (0x0102,"Abreve"),+         (0x00C2,"Acircumflex"),+         (0x00C4,"Adieresis"),+         (0x00C0,"Agrave"),+         (0x0391,"Alpha"),+         (0x0386,"Alphatonos"),+         (0x0100,"Amacron"),+         (0x0104,"Aogonek"),+         (0x00C5,"Aring"),+         (0x01FA,"Aringacute"),+         (0x00C3,"Atilde"),+         (0x0042,"B"),+         (0x0392,"Beta"),+         (0x0043,"C"),+         (0x0106,"Cacute"),+         (0x010C,"Ccaron"),+         (0x00C7,"Ccedilla"),+         (0x0108,"Ccircumflex"),+         (0x010A,"Cdotaccent"),+         (0x03A7,"Chi"),+         (0x0044,"D"),+         (0x010E,"Dcaron"),+         (0x0110,"Dcroat"),+         (0x2206,"Delta"),+         (0x0045,"E"),+         (0x00C9,"Eacute"),+         (0x0114,"Ebreve"),+         (0x011A,"Ecaron"),+         (0x00CA,"Ecircumflex"),+         (0x00CB,"Edieresis"),+         (0x0116,"Edotaccent"),+         (0x00C8,"Egrave"),+         (0x0112,"Emacron"),+         (0x014A,"Eng"),+         (0x0118,"Eogonek"),+         (0x0395,"Epsilon"),+         (0x0388,"Epsilontonos"),+         (0x0397,"Eta"),+         (0x0389,"Etatonos"),+         (0x00D0,"Eth"),+         (0x20AC,"Euro"),+         (0x0046,"F"),+         (0x0047,"G"),+         (0x0393,"Gamma"),+         (0x011E,"Gbreve"),+         (0x01E6,"Gcaron"),+         (0x011C,"Gcircumflex"),+         (0x0120,"Gdotaccent"),+         (0x0048,"H"),+         (0x25CF,"H18533"),+         (0x25AA,"H18543"),+         (0x25AB,"H18551"),+         (0x25A1,"H22073"),+         (0x0126,"Hbar"),+         (0x0124,"Hcircumflex"),+         (0x0049,"I"),+         (0x0132,"IJ"),+         (0x00CD,"Iacute"),+         (0x012C,"Ibreve"),+         (0x00CE,"Icircumflex"),+         (0x00CF,"Idieresis"),+         (0x0130,"Idotaccent"),+         (0x2111,"Ifraktur"),+         (0x00CC,"Igrave"),+         (0x012A,"Imacron"),+         (0x012E,"Iogonek"),+         (0x0399,"Iota"),+         (0x03AA,"Iotadieresis"),+         (0x038A,"Iotatonos"),+         (0x0128,"Itilde"),+         (0x004A,"J"),+         (0x0134,"Jcircumflex"),+         (0x004B,"K"),+         (0x039A,"Kappa"),+         (0x004C,"L"),+         (0x0139,"Lacute"),+         (0x039B,"Lambda"),+         (0x013D,"Lcaron"),+         (0x013F,"Ldot"),+         (0x0141,"Lslash"),+         (0x004D,"M"),+         (0x039C,"Mu"),+         (0x004E,"N"),+         (0x0143,"Nacute"),+         (0x0147,"Ncaron"),+         (0x00D1,"Ntilde"),+         (0x039D,"Nu"),+         (0x004F,"O"),+         (0x0152,"OE"),+         (0x00D3,"Oacute"),+         (0x014E,"Obreve"),+         (0x00D4,"Ocircumflex"),+         (0x00D6,"Odieresis"),+         (0x00D2,"Ograve"),+         (0x01A0,"Ohorn"),+         (0x0150,"Ohungarumlaut"),+         (0x014C,"Omacron"),+         (0x2126,"Omega"),+         (0x038F,"Omegatonos"),+         (0x039F,"Omicron"),+         (0x038C,"Omicrontonos"),+         (0x00D8,"Oslash"),+         (0x01FE,"Oslashacute"),+         (0x00D5,"Otilde"),+         (0x0050,"P"),+         (0x03A6,"Phi"),+         (0x03A0,"Pi"),+         (0x03A8,"Psi"),+         (0x0051,"Q"),+         (0x0052,"R"),+         (0x0154,"Racute"),+         (0x0158,"Rcaron"),+         (0x211C,"Rfraktur"),+         (0x03A1,"Rho"),+         (0x0053,"S"),+         (0x250C,"SF010000"),+         (0x2514,"SF020000"),+         (0x2510,"SF030000"),+         (0x2518,"SF040000"),+         (0x253C,"SF050000"),+         (0x252C,"SF060000"),+         (0x2534,"SF070000"),+         (0x251C,"SF080000"),+         (0x2524,"SF090000"),+         (0x2500,"SF100000"),+         (0x2502,"SF110000"),+         (0x2561,"SF190000"),+         (0x2562,"SF200000"),+         (0x2556,"SF210000"),+         (0x2555,"SF220000"),+         (0x2563,"SF230000"),+         (0x2551,"SF240000"),+         (0x2557,"SF250000"),+         (0x255D,"SF260000"),+         (0x255C,"SF270000"),+         (0x255B,"SF280000"),+         (0x255E,"SF360000"),+         (0x255F,"SF370000"),+         (0x255A,"SF380000"),+         (0x2554,"SF390000"),+         (0x2569,"SF400000"),+         (0x2566,"SF410000"),+         (0x2560,"SF420000"),+         (0x2550,"SF430000"),+         (0x256C,"SF440000"),+         (0x2567,"SF450000"),+         (0x2568,"SF460000"),+         (0x2564,"SF470000"),+         (0x2565,"SF480000"),+         (0x2559,"SF490000"),+         (0x2558,"SF500000"),+         (0x2552,"SF510000"),+         (0x2553,"SF520000"),+         (0x256B,"SF530000"),+         (0x256A,"SF540000"),+         (0x015A,"Sacute"),+         (0x0160,"Scaron"),+         (0x015E,"Scedilla"),+         (0x015C,"Scircumflex"),+         (0x03A3,"Sigma"),+         (0x0054,"T"),+         (0x03A4,"Tau"),+         (0x0166,"Tbar"),+         (0x0164,"Tcaron"),+         (0x0398,"Theta"),+         (0x00DE,"Thorn"),+         (0x0055,"U"),+         (0x00DA,"Uacute"),+         (0x016C,"Ubreve"),+         (0x00DB,"Ucircumflex"),+         (0x00DC,"Udieresis"),+         (0x00D9,"Ugrave"),+         (0x01AF,"Uhorn"),+         (0x0170,"Uhungarumlaut"),+         (0x016A,"Umacron"),+         (0x0172,"Uogonek"),+         (0x03A5,"Upsilon"),+         (0x03D2,"Upsilon1"),+         (0x03AB,"Upsilondieresis"),+         (0x038E,"Upsilontonos"),+         (0x016E,"Uring"),+         (0x0168,"Utilde"),+         (0x0056,"V"),+         (0x0057,"W"),+         (0x1E82,"Wacute"),+         (0x0174,"Wcircumflex"),+         (0x1E84,"Wdieresis"),+         (0x1E80,"Wgrave"),+         (0x0058,"X"),+         (0x039E,"Xi"),+         (0x0059,"Y"),+         (0x00DD,"Yacute"),+         (0x0176,"Ycircumflex"),+         (0x0178,"Ydieresis"),+         (0x1EF2,"Ygrave"),+         (0x005A,"Z"),+         (0x0179,"Zacute"),+         (0x017D,"Zcaron"),+         (0x017B,"Zdotaccent"),+         (0x0396,"Zeta"),+         (0x0061,"a"),+         (0x00E1,"aacute"),+         (0x0103,"abreve"),+         (0x00E2,"acircumflex"),+         (0x00B4,"acute"),+         (0x0301,"acutecomb"),+         (0x00E4,"adieresis"),+         (0x00E6,"ae"),+         (0x01FD,"aeacute"),+         (0x00E0,"agrave"),+         (0x2135,"aleph"),+         (0x03B1,"alpha"),+         (0x03AC,"alphatonos"),+         (0x0101,"amacron"),+         (0x0026,"ampersand"),+         (0x2220,"angle"),+         (0x2329,"angleleft"),+         (0x232A,"angleright"),+         (0x0387,"anoteleia"),+         (0x0105,"aogonek"),+         (0x2248,"approxequal"),+         (0x00E5,"aring"),+         (0x01FB,"aringacute"),+         (0x2194,"arrowboth"),+         (0x21D4,"arrowdblboth"),+         (0x21D3,"arrowdbldown"),+         (0x21D0,"arrowdblleft"),+         (0x21D2,"arrowdblright"),+         (0x21D1,"arrowdblup"),+         (0x2193,"arrowdown"),+         (0x2190,"arrowleft"),+         (0x2192,"arrowright"),+         (0x2191,"arrowup"),+         (0x2195,"arrowupdn"),+         (0x21A8,"arrowupdnbse"),+         (0x005E,"asciicircum"),+         (0x007E,"asciitilde"),+         (0x002A,"asterisk"),+         (0x2217,"asteriskmath"),+         (0x0040,"at"),+         (0x00E3,"atilde"),+         (0x0062,"b"),+         (0x005C,"backslash"),+         (0x007C,"bar"),+         (0x03B2,"beta"),+         (0x2588,"block"),+         (0x007B,"braceleft"),+         (0x007D,"braceright"),+         (0x005B,"bracketleft"),+         (0x005D,"bracketright"),+         (0x02D8,"breve"),+         (0x00A6,"brokenbar"),+         (0x2022,"bullet"),+         (0x0063,"c"),+         (0x0107,"cacute"),+         (0x02C7,"caron"),+         (0x21B5,"carriagereturn"),+         (0x010D,"ccaron"),+         (0x00E7,"ccedilla"),+         (0x0109,"ccircumflex"),+         (0x010B,"cdotaccent"),+         (0x00B8,"cedilla"),+         (0x00A2,"cent"),+         (0x03C7,"chi"),+         (0x25CB,"circle"),+         (0x2297,"circlemultiply"),+         (0x2295,"circleplus"),+         (0x02C6,"circumflex"),+         (0x2663,"club"),+         (0x003A,"colon"),+         (0x20A1,"colonmonetary"),+         (0x002C,"comma"),+         (0x2245,"congruent"),+         (0x00A9,"copyright"),+         (0x00A4,"currency"),+         (0x0064,"d"),+         (0x2020,"dagger"),+         (0x2021,"daggerdbl"),+         (0x010F,"dcaron"),+         (0x0111,"dcroat"),+         (0x00B0,"degree"),+         (0x03B4,"delta"),+         (0x2666,"diamond"),+         (0x00A8,"dieresis"),+         (0x0385,"dieresistonos"),+         (0x00F7,"divide"),+         (0x2593,"dkshade"),+         (0x2584,"dnblock"),+         (0x0024,"dollar"),+         (0x20AB,"dong"),+         (0x02D9,"dotaccent"),+         (0x0323,"dotbelowcomb"),+         (0x0131,"dotlessi"),+         (0x22C5,"dotmath"),+         (0x0065,"e"),+         (0x00E9,"eacute"),+         (0x0115,"ebreve"),+         (0x011B,"ecaron"),+         (0x00EA,"ecircumflex"),+         (0x00EB,"edieresis"),+         (0x0117,"edotaccent"),+         (0x00E8,"egrave"),+         (0x0038,"eight"),+         (0x2208,"element"),+         (0x2026,"ellipsis"),+         (0x0113,"emacron"),+         (0x2014,"emdash"),+         (0x2205,"emptyset"),+         (0x2013,"endash"),+         (0x014B,"eng"),+         (0x0119,"eogonek"),+         (0x03B5,"epsilon"),+         (0x03AD,"epsilontonos"),+         (0x003D,"equal"),+         (0x2261,"equivalence"),+         (0x212E,"estimated"),+         (0x03B7,"eta"),+         (0x03AE,"etatonos"),+         (0x00F0,"eth"),+         (0x0021,"exclam"),+         (0x203C,"exclamdbl"),+         (0x00A1,"exclamdown"),+         (0x2203,"existential"),+         (0x0066,"f"),+         (0x2640,"female"),+         (0x2012,"figuredash"),+         (0x25A0,"filledbox"),+         (0x25AC,"filledrect"),+         (0x0035,"five"),+         (0x215D,"fiveeighths"),+         (0x0192,"florin"),+         (0x0034,"four"),+         (0x2044,"fraction"),+         (0x20A3,"franc"),+         (0x0067,"g"),+         (0x03B3,"gamma"),+         (0x011F,"gbreve"),+         (0x01E7,"gcaron"),+         (0x011D,"gcircumflex"),+         (0x0121,"gdotaccent"),+         (0x00DF,"germandbls"),+         (0x2207,"gradient"),+         (0x0060,"grave"),+         (0x0300,"gravecomb"),+         (0x003E,"greater"),+         (0x2265,"greaterequal"),+         (0x00AB,"guillemotleft"),+         (0x00BB,"guillemotright"),+         (0x2039,"guilsinglleft"),+         (0x203A,"guilsinglright"),+         (0x0068,"h"),+         (0x0127,"hbar"),+         (0x0125,"hcircumflex"),+         (0x2665,"heart"),+         (0x0309,"hookabovecomb"),+         (0x2302,"house"),+         (0x02DD,"hungarumlaut"),+         (0x002D,"hyphen"),+         (0x0069,"i"),+         (0x00ED,"iacute"),+         (0x012D,"ibreve"),+         (0x00EE,"icircumflex"),+         (0x00EF,"idieresis"),+         (0x00EC,"igrave"),+         (0x0133,"ij"),+         (0x012B,"imacron"),+         (0x221E,"infinity"),+         (0x222B,"integral"),+         (0x2321,"integralbt"),+         (0x2320,"integraltp"),+         (0x2229,"intersection"),+         (0x25D8,"invbullet"),+         (0x25D9,"invcircle"),+         (0x263B,"invsmileface"),+         (0x012F,"iogonek"),+         (0x03B9,"iota"),+         (0x03CA,"iotadieresis"),+         (0x0390,"iotadieresistonos"),+         (0x03AF,"iotatonos"),+         (0x0129,"itilde"),+         (0x006A,"j"),+         (0x0135,"jcircumflex"),+         (0x006B,"k"),+         (0x03BA,"kappa"),+         (0x0138,"kgreenlandic"),+         (0x006C,"l"),+         (0x013A,"lacute"),+         (0x03BB,"lambda"),+         (0x013E,"lcaron"),+         (0x0140,"ldot"),+         (0x003C,"less"),+         (0x2264,"lessequal"),+         (0x258C,"lfblock"),+         (0x20A4,"lira"),+         (0x2227,"logicaland"),+         (0x00AC,"logicalnot"),+         (0x2228,"logicalor"),+         (0x017F,"longs"),+         (0x25CA,"lozenge"),+         (0x0142,"lslash"),+         (0x2591,"ltshade"),+         (0x006D,"m"),+         (0x00AF,"macron"),+         (0x2642,"male"),+         (0x2212,"minus"),+         (0x2032,"minute"),+         (0x00B5,"mu"),+         (0x00D7,"multiply"),+         (0x266A,"musicalnote"),+         (0x266B,"musicalnotedbl"),+         (0x006E,"n"),+         (0x0144,"nacute"),+         (0x0149,"napostrophe"),+         (0x0148,"ncaron"),+         (0x0039,"nine"),+         (0x2209,"notelement"),+         (0x2260,"notequal"),+         (0x2284,"notsubset"),+         (0x00F1,"ntilde"),+         (0x03BD,"nu"),+         (0x0023,"numbersign"),+         (0x006F,"o"),+         (0x00F3,"oacute"),+         (0x014F,"obreve"),+         (0x00F4,"ocircumflex"),+         (0x00F6,"odieresis"),+         (0x0153,"oe"),+         (0x02DB,"ogonek"),+         (0x00F2,"ograve"),+         (0x01A1,"ohorn"),+         (0x0151,"ohungarumlaut"),+         (0x014D,"omacron"),+         (0x03C9,"omega"),+         (0x03D6,"omega1"),+         (0x03CE,"omegatonos"),+         (0x03BF,"omicron"),+         (0x03CC,"omicrontonos"),+         (0x0031,"one"),+         (0x2024,"onedotenleader"),+         (0x215B,"oneeighth"),+         (0x00BD,"onehalf"),+         (0x00BC,"onequarter"),+         (0x2153,"onethird"),+         (0x25E6,"openbullet"),+         (0x00AA,"ordfeminine"),+         (0x00BA,"ordmasculine"),+         (0x221F,"orthogonal"),+         (0x00F8,"oslash"),+         (0x01FF,"oslashacute"),+         (0x00F5,"otilde"),+         (0x0070,"p"),+         (0x00B6,"paragraph"),+         (0x0028,"parenleft"),+         (0x0029,"parenright"),+         (0x2202,"partialdiff"),+         (0x0025,"percent"),+         (0x002E,"period"),+         (0x00B7,"periodcentered"),+         (0x22A5,"perpendicular"),+         (0x2030,"perthousand"),+         (0x20A7,"peseta"),+         (0x03C6,"phi"),+         (0x03D5,"phi1"),+         (0x03C0,"pi"),+         (0x002B,"plus"),+         (0x00B1,"plusminus"),+         (0x211E,"prescription"),+         (0x220F,"product"),+         (0x2282,"propersubset"),+         (0x2283,"propersuperset"),+         (0x221D,"proportional"),+         (0x03C8,"psi"),+         (0x0071,"q"),+         (0x003F,"question"),+         (0x00BF,"questiondown"),+         (0x0022,"quotedbl"),+         (0x201E,"quotedblbase"),+         (0x201C,"quotedblleft"),+         (0x201D,"quotedblright"),+         (0x2018,"quoteleft"),+         (0x201B,"quotereversed"),+         (0x2019,"quoteright"),+         (0x201A,"quotesinglbase"),+         (0x0027,"quotesingle"),+         (0x0072,"r"),+         (0x0155,"racute"),+         (0x221A,"radical"),+         (0x0159,"rcaron"),+         (0x2286,"reflexsubset"),+         (0x2287,"reflexsuperset"),+         (0x00AE,"registered"),+         (0x2310,"revlogicalnot"),+         (0x03C1,"rho"),+         (0x02DA,"ring"),+         (0x2590,"rtblock"),+         (0x0073,"s"),+         (0x015B,"sacute"),+         (0x0161,"scaron"),+         (0x015F,"scedilla"),+         (0x015D,"scircumflex"),+         (0x2033,"second"),+         (0x00A7,"section"),+         (0x003B,"semicolon"),+         (0x0037,"seven"),+         (0x215E,"seveneighths"),+         (0x2592,"shade"),+         (0x03C3,"sigma"),+         (0x03C2,"sigma1"),+         (0x223C,"similar"),+         (0x0036,"six"),+         (0x002F,"slash"),+         (0x263A,"smileface"),+         (0x0020,"space"),+         (0x2660,"spade"),+         (0x00A3,"sterling"),+         (0x220B,"suchthat"),+         (0x2211,"summation"),+         (0x263C,"sun"),+         (0x0074,"t"),+         (0x03C4,"tau"),+         (0x0167,"tbar"),+         (0x0165,"tcaron"),+         (0x2234,"therefore"),+         (0x03B8,"theta"),+         (0x03D1,"theta1"),+         (0x00FE,"thorn"),+         (0x0033,"three"),+         (0x215C,"threeeighths"),+         (0x00BE,"threequarters"),+         (0x02DC,"tilde"),+         (0x0303,"tildecomb"),+         (0x0384,"tonos"),+         (0x2122,"trademark"),+         (0x25BC,"triagdn"),+         (0x25C4,"triaglf"),+         (0x25BA,"triagrt"),+         (0x25B2,"triagup"),+         (0x0032,"two"),+         (0x2025,"twodotenleader"),+         (0x2154,"twothirds"),+         (0x0075,"u"),+         (0x00FA,"uacute"),+         (0x016D,"ubreve"),+         (0x00FB,"ucircumflex"),+         (0x00FC,"udieresis"),+         (0x00F9,"ugrave"),+         (0x01B0,"uhorn"),+         (0x0171,"uhungarumlaut"),+         (0x016B,"umacron"),+         (0x005F,"underscore"),+         (0x2017,"underscoredbl"),+         (0x222A,"union"),+         (0x2200,"universal"),+         (0x0173,"uogonek"),+         (0x2580,"upblock"),+         (0x03C5,"upsilon"),+         (0x03CB,"upsilondieresis"),+         (0x03B0,"upsilondieresistonos"),+         (0x03CD,"upsilontonos"),+         (0x016F,"uring"),+         (0x0169,"utilde"),+         (0x0076,"v"),+         (0x0077,"w"),+         (0x1E83,"wacute"),+         (0x0175,"wcircumflex"),+         (0x1E85,"wdieresis"),+         (0x2118,"weierstrass"),+         (0x1E81,"wgrave"),+         (0x0078,"x"),+         (0x03BE,"xi"),+         (0x0079,"y"),+         (0x00FD,"yacute"),+         (0x0177,"ycircumflex"),+         (0x00FF,"ydieresis"),+         (0x00A5,"yen"),+         (0x1EF3,"ygrave"),+         (0x007A,"z"),+         (0x017A,"zacute"),+         (0x017E,"zcaron"),+         (0x017C,"zdotaccent"),+         (0x0030,"zero"),+         (0x03B6,"zeta")]++-- | vector of standard postscript names.+postscriptNames :: V.Vector String+postscriptNames =+  V.fromList+  [".notdef",+   ".null",+   "nonmarkingreturn",+   "space",+   "exclam",+   "quotedbl",+   "numbersign",+   "dollar",+   "percent",+   "ampersand",+   "quotesingle",+   "parenleft",+   "parenright",+   "asterisk",+   "plus",+   "comma",+   "hyphen",+   "period",+   "slash",+   "zero",+   "one",+   "two",+   "three",+   "four",+   "five",+   "six",+   "seven",+   "eight",+   "nine",+   "colon",+   "semicolon",+   "less",+   "equal",+   "greater",+   "question",+   "at",+   "A",+   "B",+   "C",+   "D",+   "E",+   "F",+   "G",+   "H",+   "I",+   "J",+   "K",+   "L",+   "M",+   "N",+   "O",+   "P",+   "Q",+   "R",+   "S",+   "T",+   "U",+   "V",+   "W",+   "X",+   "Y",+   "Z",+   "bracketleft",+   "backslash",+   "bracketright",+   "asciicircum",+   "underscore",+   "grave",+   "a",+   "b",+   "c",+   "d",+   "e",+   "f",+   "g",+   "h",+   "i",+   "j",+   "k",+   "l",+   "m",+   "n",+   "o",+   "p",+   "q",+   "r",+   "s",+   "t",+   "u",+   "v",+   "w",+   "x",+   "y",+   "z",+   "braceleft",+   "bar",+   "braceright",+   "asciitilde",+   "Adieresis",+   "Aring",+   "Ccedilla",+   "Eacute",+   "Ntilde",+   "Odieresis",+   "Udieresis",+   "aacute",+   "agrave",+   "acircumflex",+   "adieresis",+   "atilde",+   "aring",+   "ccedilla",+   "eacute",+   "egrave",+   "ecircumflex",+   "edieresis",+   "iacute",+   "igrave",+   "icircumflex",+   "idieresis",+   "ntilde",+   "oacute",+   "ograve",+   "ocircumflex",+   "odieresis",+   "otilde",+   "uacute",+   "ugrave",+   "ucircumflex",+   "udieresis",+   "dagger",+   "degree",+   "cent",+   "sterling",+   "section",+   "bullet",+   "paragraph",+   "germandbls",+   "registered",+   "copyright",+   "trademark",+   "acute",+   "dieresis",+   "notequal",+   "AE",+   "Oslash",+   "infinity",+   "plusminus",+   "lessequal",+   "greaterequal",+   "yen",+   "mu",+   "partialdiff",+   "summation",+   "product",+   "pi",+   "integral",+   "ordfeminine",+   "ordmasculine",+   "Omega",+   "ae",+   "oslash",+   "questiondown",+   "exclamdown",+   "logicalnot",+   "radical",+   "florin",+   "approxequal",+   "Delta",+   "guillemotleft",+   "guillemotright",+   "ellipsis",+   "nonbreakingspace",+   "Agrave",+   "Atilde",+   "Otilde",+   "OE",+   "oe",+   "endash",+   "emdash",+   "quotedblleft",+   "quotedblright",+   "quoteleft",+   "quoteright",+   "divide",+   "lozenge",+   "ydieresis",+   "Ydieresis",+   "fraction",+   "currency",+   "guilsinglleft",+   "guilsinglright",+   "fi",+   "fl",+   "daggerdbl",+   "periodcentered",+   "quotesinglbase",+   "quotedblbase",+   "perthousand",+   "Acircumflex",+   "Ecircumflex",+   "Aacute",+   "Edieresis",+   "Egrave",+   "Iacute",+   "Icircumflex",+   "Idieresis",+   "Igrave",+   "Oacute",+   "Ocircumflex",+   "apple",+   "Ograve",+   "Uacute",+   "Ucircumflex",+   "Ugrave",+   "dotlessi",+   "circumflex",+   "tilde",+   "macron",+   "breve",+   "dotaccent",+   "ring",+   "cedilla",+   "hungarumlaut",+   "ogonek",+   "caron",+   "Lslash",+   "lslash",+   "Scaron",+   "scaron",+   "Zcaron",+   "zcaron",+   "brokenbar",+   "Eth",+   "eth",+   "Yacute",+   "yacute",+   "Thorn",+   "thorn",+   "minus",+   "multiply",+   "onesuperior",+   "twosuperior",+   "threesuperior",+   "onehalf",+   "onequarter",+   "threequarters",+   "franc",+   "Gbreve",+   "gbreve",+   "Idotaccent",+   "Scedilla",+   "scedilla",+   "Cacute",+   "cacute",+   "Ccaron",+   "ccaron",+   "dcroat"]
opentype.cabal view
@@ -1,5 +1,5 @@ name: opentype-version: 0.0.1+version: 0.1.0 cabal-version: >=1.8 build-type: Simple license: BSD3@@ -20,10 +20,22 @@   library   build-depends:-    base >=3 && <5, binary >=0.8.1.0,-    bytestring >0.10.0, containers >=0.5.3, ghc >=7.10.0, time >1.4.0,-    vector >=0.10, pretty-hex >=1.0-  exposed-modules: Opentype.Fileformat+                base >=3 && <5,+                binary >=0.8.1.0,+                bytestring >0.10.0,+                containers >=0.5.3,+                ghc >=7.10.0,+                microlens > 0.4.0.0,+                microlens-th > 0.4.0.0,+                mtl >= 2.2.1,+                pretty-hex >=1.0,+                time >1.4.0,+                unordered-containers >0.2.6.0,+                vector >=0.10+  exposed-modules:+                  Opentype.Fileformat+                  Opentype.Fileformat.Unicode+                  Opentype.Fileformat.FontInfo   exposed: True   buildable: True   other-modules:@@ -37,6 +49,7 @@     Opentype.Fileformat.Post     Opentype.Fileformat.Kern     Opentype.Fileformat.OS2+    Opentype.Fileformat.Unicode.PostNames       ghc-options: -Wall   test-suite test