packages feed

FontyFruity 0.4.1 → 0.5

raw patch · 9 files changed

+129/−56 lines, 9 files

Files

FontyFruity.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                FontyFruity
-version:             0.4.1
+version:             0.5
 synopsis:            A true type file format loader
 description:         
     A haskell Truetype file parser.
@@ -28,10 +28,11 @@ Source-Repository this
     Type:      git
     Location:  https://github.com/Twinside/FontyFruity.git
-    Tag:       v0.4.1
+    Tag:       v0.5
 
 library
   exposed-modules: Graphics.Text.TrueType
+                 , Graphics.Text.TrueType.Internal
   other-modules: Graphics.Text.TrueType.Bytecode    
                , Graphics.Text.TrueType.MaxpTable
                , Graphics.Text.TrueType.Header
changelog view
@@ -1,5 +1,14 @@ -*-change-log-*-
 
+v0.5 January 2015
+ * BREAKING CHANGE: the point size is now Float!
+
+ ---- Non breaking change:
+ * Adding: lower level access to the structure, without
+   guaranteed stability.
+ * Adding: an helper function to retrieve the distance from
+   the top of the string bounding box to the baseline.
+
 v0.4.1 January 2015
  * Fixing: Warnings under GHC 7.1O
 
src/Graphics/Text/TrueType.hs view
@@ -14,6 +14,8 @@     , getGlyphForStrings
     , stringBoundingBox
     , findFontOfFamily
+    , pointInPixelAtDpi
+    , pixelSizeInPointAtDpi
 
       -- * Font cache
     , FontCache
@@ -28,8 +30,9 @@     , FontStyle( .. )
     , RawGlyph( .. )
     , Dpi
-    , PointSize
-    , CompositeScaling ( .. )
+    , PointSize( .. )
+    , CompositeScaling( .. )
+    , BoundingBox( .. )
     ) where
 
 #if !MIN_VERSION_base(4,8,0)
@@ -246,8 +249,34 @@ type Dpi = Int
 
 -- | Font size expressed in points.
-type PointSize = Int
+-- You must convert size expressed in pixels to point using
+-- the DPI information.
+-- See pixelSizeInPointAtDpi
+newtype PointSize = PointSize { getPointSize :: Float }
+    deriving (Eq, Show)
 
+toPixelCoord :: (Integral a) => Font -> PointSize -> Dpi -> a -> Float
+toPixelCoord font pointSize dpi v =
+    (fromIntegral v * getPointSize pointSize * fromIntegral dpi) /
+    (72 * emSize)
+  where
+    emSize = fromIntegral $ unitsPerEm font
+
+toFCoord :: Integral a => Font -> PointSize -> Dpi -> Float -> a
+toFCoord font size dpi v = floor $ v * emSize / pixelSize
+  where
+    emSize = fromIntegral $ unitsPerEm font
+    pixelSize = size `pointInPixelAtDpi` dpi
+
+
+pointInPixelAtDpi :: PointSize -> Dpi -> Float
+pointInPixelAtDpi size dpi =
+    (getPointSize size * fromIntegral dpi) / 72
+
+pixelSizeInPointAtDpi :: Float -> Dpi -> PointSize
+pixelSizeInPointAtDpi pixelSize dpi =
+    PointSize $ (pixelSize / fromIntegral dpi) * 72
+
 glyphOfStrings :: Font -> String -> [(Glyph, HorizontalMetric)]
 glyphOfStrings Font { _fontMap = Just mapping
                     , _fontGlyph = Just glyphes
@@ -263,23 +292,37 @@     fromIntegral $ _fUnitsPerEm hdr
 unitsPerEm  _ = 1
 
+-- | String bounding box. with value for
+-- min/max.
+data BoundingBox = BoundingBox
+  { _xMin :: {-# UNPACK #-} !Float
+  , _yMin :: {-# UNPACK #-} !Float
+  , _xMax :: {-# UNPACK #-} !Float
+  , _yMax :: {-# UNPACK #-} !Float
+    -- | Should be 0 most of the times.
+  , _baselineHeight :: {-# UNPACK #-} !Float
+  }
+  deriving (Eq)
+
 -- | Compute the bounding box of a string displayed with a font at
 -- a given size. The resulting coordinate represent the width and the
 -- height in pixels.
-stringBoundingBox :: Font -> Dpi -> PointSize -> String -> (Float, Float)
+stringBoundingBox :: Font -> Dpi -> PointSize -> String -> BoundingBox
 stringBoundingBox font dpi size str =
-    foldl' go (0, 0) $ glyphOfStrings font str
+    BoundingBox 0 yMini width yMaxi 0
   where
-    emSize = fromIntegral $ unitsPerEm font
+    (width, yMini, yMaxi) =
+        foldl' go (0, 0, 0) $ glyphOfStrings font str
 
-    toPixel v = fromIntegral v * pixelSize / emSize
-      where pixelSize = fromIntegral (size * dpi) / 72
+    toPixel :: Integral a => a -> Float
+    toPixel = toPixelCoord font size dpi
 
-    go (xf, yf) (glyph, metric) = (width', height')
+    go (xf, yMin, yMax) (glyph, metric) = (width', yMin', yMax')
       where
         advance = _hmtxAdvanceWidth metric
         width' = xf + toPixel advance
-        height' = max yf . toPixel . _glfYMax $ _glyphHeader glyph
+        yMin' = max yMin. toPixel . _glfYMin $ _glyphHeader glyph
+        yMax' = max yMax. toPixel . _glfYMax $ _glyphHeader glyph
 
 
 -- | Extract a list of outlines for every char in the string.
@@ -290,27 +333,22 @@                       -> [(Font, PointSize, String)] -- ^ Text to draw
                       -> [[VU.Vector (Float, Float)]] -- ^ List of contours for each char
 getStringCurveAtPoint dpi initPos lst = snd $ mapAccumL go initPos glyphes where
-  glyphes = concat [(font, size, fromIntegral $ unitsPerEm font,)
-                            <$> glyphOfStrings font str | (font, size, str) <- lst]
-
-  toPixel (_, pointSize, emSize, _) v = fromIntegral v * pixelSize / emSize
-    where
-      pixelSize = fromIntegral (pointSize * dpi) / 72
+  glyphes = concat [(font, size,)
+                         <$> glyphOfStrings font str | (font, size, str) <- lst]
 
-  toFCoord (_, pointSize, emSize, _) v = floor $ v * emSize / pixelSize
-    where
-      pixelSize = fromIntegral (pointSize * dpi) / 72
+  toPixel (font, pointSize, _) = toPixelCoord font pointSize dpi
+  toCoord (font, pointSize, _) = toFCoord font pointSize dpi
 
   maximumSize = maximum [ toPixel p . _glfYMax $ _glyphHeader glyph
-                                | p@(_, _, _, (glyph, _)) <- glyphes ]
+                                | p@(_, _, (glyph, _)) <- glyphes ]
 
-  go (xf, yf) p@(font, pointSize, _, (glyph, metric)) = ((toPixel p $ xi + advance, yf), curves)
+  go (xf, yf) p@(font, pointSize, (glyph, metric)) = ((toPixel p $ xi + advance, yf), curves)
     where
-      (xi, yi) = (toFCoord p xf, toFCoord p yf)
+      (xi, yi) = (toCoord p xf, toCoord p yf)
       bearing = fromIntegral $ _hmtxLeftSideBearing metric
       advance = fromIntegral $ _hmtxAdvanceWidth metric
       curves =
-          getGlyphIndexCurvesAtPointSizeAndPos font dpi (toFCoord p maximumSize)
+          getGlyphIndexCurvesAtPointSizeAndPos font dpi (toCoord p maximumSize)
             (pointSize, glyph) (xi + bearing, yi)
 
 -- | This function return the list of all contour for all char with the given
@@ -321,24 +359,18 @@                    -> [[VU.Vector (Float, Float)]]
 getGlyphForStrings dpi lst =  go <$> glyphes where
   glyphes = concat
-    [(font, size, fromIntegral $ unitsPerEm font,)
-                            <$> glyphOfStrings font str | (font, size, str) <- lst]
-
-  toFCoord (_, pointSize, emSize, _) v = floor $ v * emSize / pixelSize :: Int
-    where
-      pixelSize = fromIntegral (pointSize * dpi) / 72
+    [(font, size,) <$> glyphOfStrings font str | (font, size, str) <- lst]
 
-  toPixel pointSize emSize v = fromIntegral v * pixelSize / emSize
-    where
-      pixelSize = fromIntegral (pointSize * dpi) / 72
+  toCoord (font, pointSize, _) = toFCoord font pointSize dpi
 
   maximumSize :: Float
-  maximumSize = maximum [ toPixel pointSize em . _glfYMax $ _glyphHeader glyph
-                                | (_, pointSize, em, (glyph, _)) <- glyphes ]
+  maximumSize =
+     maximum [ toPixelCoord font pointSize dpi . _glfYMax $ _glyphHeader glyph
+                   | (font, pointSize, (glyph, _)) <- glyphes ]
 
-  go p@(font, pointSize, _, (glyph, _metric)) =
+  go p@(font, pointSize, (glyph, _metric)) =
     getGlyphIndexCurvesAtPointSizeAndPos
-        font dpi (toFCoord p maximumSize) (pointSize, glyph) (0, 0)
+        font dpi (toCoord p maximumSize) (pointSize, glyph) (0, 0)
 
 getGlyphIndexCurvesAtPointSizeAndPos :: Font -> Dpi -> Int -> (PointSize, Glyph)
                                      -> (Int, Int)
@@ -352,7 +384,7 @@     go index | index >= V.length allGlyphs = []
              | otherwise = glyphExtract $ allGlyphs V.! index
 
-    pixelSize = fromIntegral (pointSize * dpi) / 72
+    pixelSize = pointSize `pointInPixelAtDpi` dpi
     emSize = fromIntegral $ _fUnitsPerEm hdr
 
     baseYF = toPixelCoordinate (0 :: Int) baseY
src/Graphics/Text/TrueType/FontFolders.hs view
@@ -33,7 +33,7 @@ import Data.Binary.Put( Put
                       , putWord32be
                       , putByteString )
-import qualified Data.Map as M
+import qualified Data.Map.Strict as M
 import System.Environment( lookupEnv )
 import System.FilePath( (</>) )
 {-
@@ -128,13 +128,14 @@ -- version.
 newtype FontCache =
     FontCache (M.Map FontDescriptor FilePath)
+    deriving Show
 
 -- | Font cache with no pre-existing fonts in it.
 emptyFontCache :: FontCache
 emptyFontCache = FontCache M.empty
 
 signature :: B.ByteString
-signature = "FontyFruity__FONTCACHE:0.4"
+signature = "FontyFruity__FONTCACHE:0.5"
 
 putFontCache :: FontCache -> Put
 putFontCache (FontCache cache) = do
@@ -164,7 +165,8 @@   folders <- fontFolders
   found <- build [("", v) | v <- folders]
   return . FontCache
-         $ M.fromList [(d, path) | (Just d, path) <- found]
+         $ M.fromList [(d, path) | (Just d, path) <- found
+                                 , _descriptorFamilyName d /= ""]
   where
     descriptorOf Font { _fontHeader = Just hdr
                       , _fontNames = Just names} =
src/Graphics/Text/TrueType/FontType.hs view
@@ -20,18 +20,20 @@ 
 -- | Type representing a font.
 data Font = Font
-    { _fontOffsetTable       :: !OffsetTable
-    , _fontTables            :: ![(B.ByteString, B.ByteString)]
-    , _fontNames             :: Maybe NameTable
-    , _fontHeader            :: Maybe FontHeader
-    , _fontMaxp              :: Maybe MaxpTable
-    , _fontMap               :: Maybe CharacterMaps
-    , _fontGlyph             :: Maybe (V.Vector Glyph)
-    , _fontLoca              :: Maybe (VU.Vector Word32)
-    , _fontHorizontalHeader  :: Maybe HorizontalHeader
-    , _fontHorizontalMetrics :: Maybe HorizontalMetricsTable
-    }
-    deriving (Show)
+ { -- | Field discribing various offsets/positions of table
+   -- inside the font file. Not available for reading.
+   _fontOffsetTable       :: !OffsetTable
+ , _fontTables            :: ![(B.ByteString, B.ByteString)]
+ , _fontNames             :: Maybe NameTable
+ , _fontHeader            :: Maybe FontHeader
+ , _fontMaxp              :: Maybe MaxpTable
+ , _fontMap               :: Maybe CharacterMaps
+ , _fontGlyph             :: Maybe (V.Vector Glyph)
+ , _fontLoca              :: Maybe (VU.Vector Word32)
+ , _fontHorizontalHeader  :: Maybe HorizontalHeader
+ , _fontHorizontalMetrics :: Maybe HorizontalMetricsTable
+ }
+ deriving (Show)
 
 instance NFData Font where
     rnf font =
src/Graphics/Text/TrueType/Header.hs view
@@ -51,6 +51,7 @@     let bitAt = testBit styleWord
     return $ FontStyle (bitAt 0) (bitAt 1)
 
+-- | Font header
 data FontHeader = FontHeader
     { -- | Table version number	0x00010000 for version 1.0.
       _fHdrVersionNumber    :: !Fixed
@@ -113,6 +114,7 @@             g64 = getWord64be
 
 
+-- | Header flags.
 data HeaderFlags = HeaderFlags
     { -- | Bit 0 - baseline for font at y=0;
       _hfBaselineY0           :: !Bool
src/Graphics/Text/TrueType/HorizontalInfo.hs view
@@ -23,6 +23,7 @@ 
 import Graphics.Text.TrueType.Types
 
+-- | Describe the "hhea" TrueType table.
 data HorizontalHeader = HorizontalHeader
     { -- | Distance from baseline of highest ascender
       _hheaAscent  :: {-# UNPACK #-} !FWord
@@ -86,6 +87,7 @@     startHdr <$> (fromIntegral <$> getWord16be)
              <*> getWord16be
 
+-- | Information of horizontal advance.
 data HorizontalMetric = HorizontalMetric
     { _hmtxAdvanceWidth    :: {-# UNPACK #-} !Word16
     , _hmtxLeftSideBearing :: {-# UNPACK #-} !Int16
@@ -99,6 +101,8 @@     get = HorizontalMetric <$> g16 <*> (fromIntegral <$> g16)
       where g16 = getWord16be
 
+-- | For every glyph (indexed by the glyph index),
+-- provide horizontal information.
 data HorizontalMetricsTable = HorizontalMetricsTable
     { _glyphMetrics :: !(V.Vector HorizontalMetric)
     }
+ src/Graphics/Text/TrueType/Internal.hs view
@@ -0,0 +1,21 @@+-- | This module provide internal access to many structure,
+-- not exported by default. The stability of this module is
+-- absolutely not insured.
+module Graphics.Text.TrueType.Internal
+    ( Font( .. )
+    , FontHeader( .. )
+    , HeaderFlags( .. )
+    , HorizontalHeader( .. )
+    , HorizontalMetric( .. )
+    , HorizontalMetricsTable( .. )
+    , MaxpTable( .. )
+    , FWord( .. )
+    , Fixed( .. )
+    ) where
+
+import Graphics.Text.TrueType.MaxpTable
+import Graphics.Text.TrueType.HorizontalInfo
+import Graphics.Text.TrueType.FontType
+import Graphics.Text.TrueType.Header
+import Graphics.Text.TrueType.Types
+
src/Graphics/Text/TrueType/Types.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE CPP #-}
 module Graphics.Text.TrueType.Types
-    ( Fixed
-    , FWord
+    ( Fixed( .. )
+    , FWord( .. )
     , F26Dot6( .. )
     ) where