From 3160ceab080fca8fef0cf2cf196b46284d15c19f Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sun, 4 Feb 2024 11:07:15 +0100 Subject: [PATCH] Create a Metrics module --- CHANGELOG.md | 8 +++++- README.md | 39 ++++++++++++++++++++++++++++ README.txt | 6 ----- fountainhead.cabal | 7 ++--- lib/Graphics/Fountainhead/Dumper.hs | 6 ++--- lib/Graphics/Fountainhead/Metrics.hs | 29 +++++++++++++++++++++ lib/Graphics/Fountainhead/Type.hs | 5 ++++ {app => src}/Main.hs | 30 ++++++++++----------- 8 files changed, 101 insertions(+), 29 deletions(-) create mode 100644 README.md delete mode 100644 README.txt create mode 100644 lib/Graphics/Fountainhead/Metrics.hs rename {app => src}/Main.hs (59%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b28f69..982d553 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ -# Revision history for fountainhead +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on +[Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to +[Haskell Package Versioning Policy](https://pvp.haskell.org/). ## Unreleased diff --git a/README.md b/README.md new file mode 100644 index 0000000..006cc49 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# TrueType font parser. + +Fountainhead is a TrueType and OpenType font parser. Its main +purpose is to extract information from the fonts to help to +embed these fonts into PDF documents. It also supports dumping +font information to the screen. + +There is also an executable to dump fonts. + +## Installation + +Add the library as dependency to your project. +Alternatively build and run the executable with: + +```sh +cabal build +``` + +The binary can be executed with: + +```sh +cabal run fountainhead -- +``` + +or installed locally and executed just as: + +```sh +fountainhead +``` + +See + +```sh +fountainhead --help +``` + +for help. + +## Usage diff --git a/README.txt b/README.txt deleted file mode 100644 index a69c401..0000000 --- a/README.txt +++ /dev/null @@ -1,6 +0,0 @@ -# TrueType font parser. - -An experiment to create a TrueType and OpenType font parser and encoder -that can be used to embed fonts in PDF. - -This project is currently only a draft. diff --git a/fountainhead.cabal b/fountainhead.cabal index c213d27..7af36e5 100644 --- a/fountainhead.cabal +++ b/fountainhead.cabal @@ -17,7 +17,7 @@ category: Graphics extra-source-files: CHANGELOG.md - README.txt + README.md common dependencies build-depends: @@ -25,7 +25,7 @@ common dependencies bytestring ^>= 0.11.0, text ^>= 2.0, zlib ^>= 0.6.3 - default-language: Haskell2010 + default-language: GHC2021 library import: dependencies @@ -33,6 +33,7 @@ library Graphics.Fountainhead Graphics.Fountainhead.Compression Graphics.Fountainhead.Dumper + Graphics.Fountainhead.Metrics Graphics.Fountainhead.Parser Graphics.Fountainhead.Type Graphics.Fountainhead.TrueType @@ -62,5 +63,5 @@ executable fountainhead vector, transformers, time - hs-source-dirs: app + hs-source-dirs: src ghc-options: -Wall diff --git a/lib/Graphics/Fountainhead/Dumper.hs b/lib/Graphics/Fountainhead/Dumper.hs index bbb17c2..c3ba277 100644 --- a/lib/Graphics/Fountainhead/Dumper.hs +++ b/lib/Graphics/Fountainhead/Dumper.hs @@ -114,6 +114,7 @@ import Graphics.Fountainhead.Type ( Fixed32(..) , succIntegral , ttfEpoch + , newlineBuilder , fixed2Double ) import Data.Foldable (Foldable(..), find) @@ -160,9 +161,6 @@ justifyNumber count = Text.Builder.fromLazyText . Text.Builder.toLazyText . Text.Builder.decimal -newlineBuilder :: Text.Builder.Builder -newlineBuilder = Text.Builder.singleton '\n' - dumpCaption :: String -> Text.Builder.Builder dumpCaption headline = Text.Builder.fromString headline <> newlineBuilder @@ -288,7 +286,7 @@ longDateTime localTime = Text.Builder.fromLazyText dumpCVTable :: CVTable -> Text.Builder.Builder dumpCVTable (CVTable cvTable) = dumpCaption "'cvt ' Table - Control Value Table" <> "Size = " <> Text.Builder.decimal (tableSize * 2) - <> " bytes, " <> Text.Builder.decimal tableSize <> " entries\n" + <> " bytes, " <> Text.Builder.decimal tableSize <> " entries" <> newlineBuilder <> foldMap (uncurry go) (zip [0..] cvTable) where tableSize = Prelude.length cvTable diff --git a/lib/Graphics/Fountainhead/Metrics.hs b/lib/Graphics/Fountainhead/Metrics.hs new file mode 100644 index 0000000..bb50b93 --- /dev/null +++ b/lib/Graphics/Fountainhead/Metrics.hs @@ -0,0 +1,29 @@ +{- 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/. -} + +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} + +module Graphics.Fountainhead.Metrics + ( FontMetrics(..) + , afmFontMetrics + ) where + +import qualified Data.Text.Lazy.Builder as Text.Builder +import Data.Version (Version(..), showVersion) +import Graphics.Fountainhead.Type (newlineBuilder) + +newtype FontMetrics = FontMetrics + { version :: Version + } deriving (Eq, Show) + +afmKeyString :: Text.Builder.Builder -> String -> Text.Builder.Builder +afmKeyString key value = key <> Text.Builder.singleton '\t' + <> Text.Builder.fromString value <> newlineBuilder + +afmFontMetrics :: FontMetrics -> Text.Builder.Builder +afmFontMetrics FontMetrics{..} + = afmKeyString "StartFontMetrics" (showVersion version) + <> afmKeyString "Comment" "Generated by Fountainhead" + <> "EndFontMetrics" <> newlineBuilder diff --git a/lib/Graphics/Fountainhead/Type.hs b/lib/Graphics/Fountainhead/Type.hs index e809d9c..beaf6e4 100644 --- a/lib/Graphics/Fountainhead/Type.hs +++ b/lib/Graphics/Fountainhead/Type.hs @@ -9,10 +9,12 @@ module Graphics.Fountainhead.Type , FWord , UFWord , fixed2Double + , newlineBuilder , succIntegral , ttfEpoch ) where +import qualified Data.Text.Lazy.Builder as Text.Builder import Data.Bits ((.>>.), (.&.)) import Data.Int (Int16) import Data.Word (Word16, Word32) @@ -39,3 +41,6 @@ fixed2Double (F2Dot14 fixed) = let mantissa = realToFrac (fixed .>>. 14) fraction = realToFrac (fixed .&. 0x3fff) / 16384.0 in mantissa + fraction + +newlineBuilder :: Text.Builder.Builder +newlineBuilder = Text.Builder.singleton '\n' diff --git a/app/Main.hs b/src/Main.hs similarity index 59% rename from app/Main.hs rename to src/Main.hs index b79acaa..a87bf85 100644 --- a/app/Main.hs +++ b/src/Main.hs @@ -10,9 +10,11 @@ import GHC.IO.Exception (ExitCode(..)) import Options.Applicative ( Parser , ParserInfo(..) + , (<**>) , argument , command , execParser + , helper , info , fullDesc , metavar @@ -22,32 +24,30 @@ import Options.Applicative ) data Operation - = Dump FilePath - | Afm FilePath + = Dump + | Afm deriving (Eq, Show) -dump :: Parser Operation -dump = Dump - <$> argument str (metavar "FONTFILE") +data Options = Options Operation FilePath + deriving (Eq, Show) -afm :: Parser Operation -afm = Afm - <$> argument str (metavar "FONTFILE") - -operationOptions :: ParserInfo Operation -operationOptions = info commands fullDesc +operationOptions :: ParserInfo Options +operationOptions = info (options <**> helper) fullDesc where + options = Options + <$> commands + <*> argument str (metavar "FONTFILE") commands = subparser - $ command "dump" (info dump (progDesc "Dumping the contents of a TrueType Font file")) - <> command "afm" (info afm (progDesc "Generating Adobe Font Metrics files for TrueType fonts")) + $ command "dump" (info (pure Dump) (progDesc "Dumping the contents of a TrueType Font file.")) + <> command "afm" (info (pure Afm) (progDesc "Generating Adobe Font Metrics files for TrueType fonts.")) main :: IO () main = execParser operationOptions >>= handleArguments where - handleArguments (Dump fontFile) + handleArguments (Options Dump fontFile) = putStrLn ("Dumping File:" <> fontFile <> "\n\n") >> dumpFontFile fontFile >>= either print (Text.Lazy.putStrLn . Text.Builder.toLazyText) - handleArguments (Afm _) + handleArguments (Options Afm _) = putStrLn "The program expects exactly one argument, the font file path." >> exitWith (ExitFailure 2)