summaryrefslogtreecommitdiff
path: root/src/Graphics/Fountainhead.hs
blob: f96568072374cf4ddf9c3843b5d012e7cadddb36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
{- This Source Code Form is subject to the terms of the Mozilla Public License,
   v. 2.0. If a copy of the MPL was not distributed with this file, You can
   obtain one at https://mozilla.org/MPL/2.0/. -}

module Graphics.Fountainhead
    ( parseFontDirectoryFromFile
    ) where

import qualified Codec.Compression.Zlib as Zlib
import Data.ByteString (ByteString)
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Lazy as ByteString.Lazy
import Data.Void (Void)
import Graphics.Fountainhead.Parser (ParseErrorBundle, fontDirectoryP)
import Graphics.Fountainhead.TrueType (FontDirectory(..))
import qualified Text.Megaparsec as Megaparsec
import Text.Megaparsec (PosState(..), State(..))
import System.IO (IOMode(..), SeekMode(..), hFileSize, hSeek, withBinaryFile)

parseFontDirectoryFromFile :: String
    -> IO (State ByteString Void, Either ParseErrorBundle FontDirectory)
parseFontDirectoryFromFile fontFile =
    withBinaryFile fontFile ReadMode withFontHandle
  where
    withFontHandle fontHandle = doParsing
        <$> readFontContents fontHandle
    doParsing ttfContents =
        let initialState = Megaparsec.State
                { stateInput = ttfContents
                , stateOffset = 0
                , statePosState = Megaparsec.PosState
                    { pstateInput = ttfContents
                    , pstateOffset = 0
                    , pstateSourcePos = Megaparsec.initialPos fontFile
                    , pstateTabWidth = Megaparsec.defaultTabWidth
                    , pstateLinePrefix = ""
                    }
                , stateParseErrors = []
                }
         in Megaparsec.runParser' fontDirectoryP initialState 
    readFontContents fontHandle = do
        firstBytes <- ByteString.unpack <$> ByteString.hGet fontHandle 2
        hSeek fontHandle AbsoluteSeek 0
        fileSize <- fromIntegral <$> hFileSize fontHandle
        case firstBytes of
            0x78 : [secondByte]
                | secondByte `elem` [0x01, 0x9c, 0x5e, 0xda] ->
                    ByteString.Lazy.toStrict . Zlib.decompress
                        <$> ByteString.Lazy.hGet fontHandle fileSize
            _ -> ByteString.hGetContents fontHandle