{-# OPTIONS_GHC -fno-warn-missing-signatures #-} {-# LANGUAGE RecordWildCards #-} import Control.Exception import Control.Monad import Data.Binary.Strict.Get import qualified Data.ByteString as B import Data.Monoid import EOT import Font hiding (str) import Options.Applicative hiding (header) import OTF import SVG import System.FilePath import TTF import Utils import WOFF -- platformAppleUnicode = 0 -- platformMacintosh = 1 -- platformISO = 2 platformMicrosoft = 3 -- encodingUndefined = 0 encodingUGL = 1 data Opts = Opts { noEot :: Bool , noWoff :: Bool , noSvg :: Bool , enableSvgKern :: Bool , zopfli :: Bool , svgPlatformId :: UShort , svgEncodingId :: UShort , inputs :: [String]} optsDef :: Parser Opts optsDef = Opts <$> switch (long "no-eot" <> help "Disable eot") <*> switch (long "no-woff" <> help "Disable woff") <*> switch (long "no-svg" <> help "Disable svg") <*> switch (long "svg-enable-kerning" <> help "Enable svg kerning") <*> switch (long "zopfli" <> help "Use Zopfli Compression Algorithm") <*> option auto (long "svg-cmap-platform-id" <> value platformMicrosoft <> help "Svg cmap platform id") <*> option auto (long "svg-cmap-encoding-id" <> value encodingUGL <> help "Svg cmap encoding id") <*> some (argument str (metavar "FONTS")) changeExtension :: FilePath -> FilePath -> FilePath changeExtension ext = flip addExtension ext . dropExtension cmapDescription :: (Integral a) => a -> a -> String cmapDescription 0 0 = "Unicode 1.0 semantics" cmapDescription 0 1 = "Unicode 1.1 semantics" cmapDescription 0 2 = "ISO/IEC 10646 semantics" cmapDescription 0 3 = "Unicode 2.0 and onwards semantics, Unicode BMP only" cmapDescription 0 4 = "Unicode 2.0 and onwards semantics, Unicode full repertoire" cmapDescription 0 5 = "Unicode Variation Sequences" cmapDescription 0 6 = "Unicode full repertoire" cmapDescription 0 _ = "Unicode unknown" cmapDescription 1 0 = "Macintosh Roman 8-bit simple" cmapDescription 1 _ = "Macintosh unknown" cmapDescription 3 0 = "Microsoft Symbol" cmapDescription 3 1 = "Microsoft Unicode BMP (UCS-2)" cmapDescription 3 2 = "Microsoft ShiftJIS" cmapDescription 3 3 = "Microsoft PRC" cmapDescription 3 4 = "Microsoft Big5" cmapDescription 3 5 = "Microsoft Wansung" cmapDescription 3 6 = "Microsoft Johab" cmapDescription 3 7 = "Microsoft Reserved" cmapDescription 3 8 = "Microsoft Reserved" cmapDescription 3 9 = "Microsoft Reserved" cmapDescription 3 10 = "Microsoft Unicode UCS-4" cmapDescription 3 _ = "Microsoft Unknown" cmapDescription _ _ = "Unknown" showCmap :: Cmap -> String showCmap cmap' = formatTable $ header : map pluck (encodingDirectories cmap') where header = ["PlatformId", "EncodingId", "Description"] pluck dir = [show $ cmapPlatformId dir, show $ cmapEncodingId dir, cmapDescription (cmapPlatformId dir) (cmapEncodingId dir)] eotgen :: Font f => f -> B.ByteString -> FilePath -> IO () eotgen font input filename = do putStrLn $ "Generating " ++ target B.writeFile target $ EOT.generate font input where target = changeExtension "eot" filename woffgen :: Font f => f -> B.ByteString -> FilePath -> Opts -> IO () woffgen font input filename Opts{..}= do putStrLn $ "Generating " ++ target B.writeFile target $ WOFF.generate font input zopfli where target = changeExtension "woff" filename svggen :: TTF -> B.ByteString -> FilePath -> Opts -> IO () svggen ttf input filename Opts{..} = do putStrLn $ "Generating " ++ target putStrLn "Available cmaps" putStr $ showCmap $ cmap ttf putStrLn $ "Selecting platformId " ++ show svgPlatformId ++ " encodingId " ++ show svgEncodingId ++ " -- " ++ cmapDescription svgPlatformId svgEncodingId B.writeFile target $ SVG.generate ttf input cmapTable enableSvgKern where target = changeExtension "svg" filename cmapTable = cmapTableFind ttf svgPlatformId svgEncodingId convert :: Opts -> FilePath -> IO () convert opts@Opts{..} filename = do input <- B.readFile filename if takeExtension filename == ".otf" then let otf = fromRight $ runGet (OTF.parse input) input in do unless noEot (eotgen otf input filename) unless noWoff (woffgen otf input filename opts) else let ttf = fromRight $ runGet (TTF.parse input) input in do unless noEot (eotgen ttf input filename) unless noWoff (woffgen ttf input filename opts) unless noSvg (svggen ttf input filename opts) convertFiles :: Opts -> IO () convertFiles opts@Opts{inputs = fonts} = forM_ fonts $ safeConvert opts where safeConvert opts' file = convert opts' file `catch` displayError file displayError :: FilePath -> SomeException -> IO () displayError file e = (putStrLn $ "Failed to convert " ++ file) >> (putStrLn $ show e) webifyVersion = "0.1.7.0" main :: IO () main = do opts <- execParser optsSpec maybe (putStrLn $ "webify " ++ webifyVersion) convertFiles opts where parser = flag' Nothing (long "version" <> help "Display version") <|> (Just <$> optsDef) optsSpec = info (helper <*> parser) mempty