fountainhead/src/Graphics/Fountainhead/TrueType.hs

867 lines
29 KiB
Haskell

{- 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 DuplicateRecordFields #-}
{-# LANGUAGE RecordWildCards #-}
-- | Types representing a TrueType font.
module Graphics.Fountainhead.TrueType
( BArmStyle(..)
, BContrast(..)
, BFamilyType(..)
, BLetterform(..)
, BMidline(..)
, BProportion(..)
, BSerifStyle(..)
, BStrokeVariation(..)
, BWeight(..)
, BXHeight(..)
, CVTable(..)
, CmapSubtable(..)
, CmapTable(..)
, CmapEncoding(..)
, CmapFormat0Table(..)
, CmapFormat2Subheader(..)
, CmapFormat2Table(..)
, CmapFormat4Table(..)
, CmapFormat6Table(..)
, CmapGroup(..)
, CmapFormat8Table(..)
, CmapFormat10Table(..)
, CmapFormat12Table(..)
, CmapFormat13Table
, CmapFormat14Table(..)
, ComponentGlyphFlags(..)
, ComponentGlyphPartDescription(..)
, CompoundGlyphDefinition(..)
, DeviceRecord(..)
, FpgmTable(..)
, FontDirectionHint(..)
, FontDirectory(..)
, FontStyle(..)
, GlyfTable(..)
, GlyphArgument(..)
, GlyphCoordinate(..)
, GlyphDefinition(..)
, GlyphDescription(..)
, GlyphTransformationOption(..)
, HdmxTable(..)
, HeadTable(..)
, HheaTable(..)
, HmtxTable(..)
, IndexToLocFormat(..)
, LocaTable(..)
, LongHorMetric(..)
, MaxpTable(..)
, NameRecord(..)
, NameTable(..)
, OffsetSubtable(..)
, OpenMaxpTable(..)
, Os2BaseFields(..)
, Os2MicrosoftFields(..)
, Os2Table(..)
, Os2Version1Fields(..)
, Os2Version4Fields(..)
, Os2Version5Fields(..)
, OutlineFlag(..)
, Panose(..)
, PostFormat2Table(..)
, PostHeader(..)
, PostSubtable(..)
, PostTable(..)
, PrepTable(..)
, SimpleGlyphDefinition(..)
, TableDirectory(..)
, TrueMaxpTable(..)
, UVSOffset(..)
, UVSMapping(..)
, UnicodeValueRange(..)
, VariationSelectorMap
, unLocaTable
, nameStringOffset
) where
import Data.ByteString (ByteString)
import Data.Int (Int8, Int16)
import Data.IntMap (IntMap)
import Data.List.NonEmpty (NonEmpty(..))
import Data.Time (LocalTime(..))
import Data.Vector (Vector)
import Data.Word (Word8, Word16, Word32)
import Graphics.Fountainhead.Type (F2Dot14(..), Fixed32(..), FWord, UFWord)
-- * Font directory
data FontDirectory = FontDirectory
{ offsetSubtable :: OffsetSubtable
, tableDirectory :: [TableDirectory]
} deriving (Eq, Show)
data OffsetSubtable = OffsetSubtable
{ scalerType :: Word32
, numTables :: Int
, searchRange :: Word16
, entrySelector :: Word16
, rangeShift :: Word16
} deriving (Eq, Show)
data TableDirectory = TableDirectory
{ tag :: ByteString
, checkSum :: Word32
, offset :: Int
, length :: Int
} deriving (Eq, Show)
-- * Name table
data NameTable = NameTable
{ format :: Word16 -- ^ Format selector. Set to 0.
, nameRecord :: [NameRecord] -- ^ The name records array.
, variable :: [ByteString] -- ^ The character strings of the names.
} deriving (Eq, Show)
data NameRecord = NameRecord
{ platformID :: Word16 -- ^ Platform identifier code.
, platformSpecificID :: Word16 -- ^ Platform-specific encoding identifier.
, languageID :: Word16 -- ^ Language identifier.
, nameID :: Word16 -- ^ Name identifier.
, length :: Int -- ^ Name string length in bytes.
, offset :: Int -- ^ Offset.
} deriving (Eq, Show)
nameStringOffset :: NameTable -> Word16
nameStringOffset NameTable{..} =
let nameRecordSize = 12
precedingFieldsSize = 2 * 3
in nameRecordSize * fromIntegral (Prelude.length nameRecord) + precedingFieldsSize
-- * 'cvt ' table
newtype CVTable = CVTable [Int16]
deriving (Eq, Show)
-- * Maximum profile table
data TrueMaxpTable = TrueMaxpTable
{ version :: Fixed32 -- ^ 0x00010000 (1.0).
, numGlyphs :: Word16 -- ^ The number of glyphs in the font.
, maxPoints :: Word16 -- ^ Points in non-compound glyph.
, maxContours :: Word16 -- ^ Contours in non-compound glyph.
, maxComponentPoints :: Word16 -- ^ Points in compound glyph.
, maxComponentContours :: Word16 -- ^ Contours in compound glyph.
, maxZones :: Word16 -- ^ Set to 2.
, maxTwilightPoints :: Word16 -- ^ Points used in Twilight Zone (Z0).
, maxStorage :: Word16 -- ^ Number of Storage Area locations.
, maxFunctionDefs :: Word16 -- ^ Number of FDEFs.
, maxInstructionDefs :: Word16 -- ^ Number of IDEFs.
, maxStackElements :: Word16 -- ^ Maximum stack depth.
, maxSizeOfInstructions :: Word16 -- ^ Byte count for glyph instructions.
, maxComponentElements :: Word16 -- ^ Number of glyphs referenced at top level.
, maxComponentDepth :: Word16 -- ^ Levels of recursion, set to 0 if font has only simple glyphs.
} deriving (Eq, Show)
data OpenMaxpTable = OpenMaxpTable
{ version :: Fixed32 -- ^ 0x00005000 (0.5).
, numGlyphs :: Word16 -- ^ The number of glyphs in the font.
} deriving (Eq, Show)
data MaxpTable = OpenMaxp OpenMaxpTable | TrueMaxp TrueMaxpTable
deriving (Eq, Show)
-- * Horizontal header table
data HheaTable = HheaTable
{ version :: Fixed32 -- ^ 0x00010000 (1.0).
, ascent :: FWord -- ^ Distance from baseline of highest ascender.
, descent :: FWord -- ^ Distance from baseline of lowest descender.
, lineGap :: FWord -- ^ Typographic line gap.
, advanceWidthMax :: UFWord -- ^ Must be consistent with horizontal metrics.
, minLeftSideBearing :: FWord -- ^ Must be consistent with horizontal metrics.
, minRightSideBearing :: FWord -- ^ Must be consistent with horizontal metrics.
, xMaxExtent :: FWord -- ^ max(lsb + (xMax-xMin)).
, caretSlopeRise :: Int16 -- ^ used to calculate the slope of the caret (rise/run) set to 1 for vertical caret.
, caretSlopeRun :: Int16 -- ^ 0 for vertical.
, caretOffset :: FWord -- ^ Set value to 0 for non-slanted fonts.
, metricDataFormat :: Int16 -- ^ 0 for current format.
, numOfLongHorMetrics :: Word16 -- ^ Number of advance widths in metrics table.
} deriving (Eq, Show)
-- * Font header table
data IndexToLocFormat
= ShortOffsetIndexToLocFormat
| LongOffsetIndexToLocFormat
deriving (Eq, Show)
data HeadTable = HeadTable
{ version :: Fixed32 -- ^ 0x00010000 if (version 1.0).
, fontRevision :: Fixed32 -- ^ Set by font manufacturer.
, checkSumAdjustment :: Word32 -- ^ To compute: set it to 0, calculate the checksum for the 'head' table and put it in the table directory, sum the entire font as a uint32_t, then store 0xB1B0AFBA - sum. (The checksum for the 'head' table will be wrong as a result. That is OK; do not reset it.)
, magicNumber :: Word32 -- ^ Set to 0x5F0F3CF5.
, flags :: Word16
, unitsPerEm :: Word16 -- ^ Range from 64 to 16384.
, created :: LocalTime -- ^ International date.
, modified :: LocalTime -- ^ International date.
, xMin :: Int16 -- ^ For all glyph bounding boxes.
, yMin :: Int16 -- ^ For all glyph bounding boxes.
, xMax :: Int16 -- ^ For all glyph bounding boxes.
, yMax :: Int16 -- ^ For all glyph bounding boxes.
, macStyle :: FontStyle
, lowestRecPPEM :: Word16 -- ^ Smallest readable size in pixels.
, fontDirectionHint :: FontDirectionHint -- ^ 0 Mixed directional glyphs.
, indexToLocFormat :: IndexToLocFormat -- ^ 0 for short offsets, 1 for long.
, glyphDataFormat :: Word16 -- ^ 0 for current format.
} deriving (Eq, Show)
data FontStyle = FontStyle
{ bold :: Bool
, italic :: Bool
, underline :: Bool
, outline :: Bool
, shadow :: Bool
, condensed :: Bool
, extended :: Bool
} deriving (Eq, Show)
data FontDirectionHint
= MixedDirectionalGlyphs -- ^ 0. Mixed directional glyphs.
| StronglyLeftToRightGlyphs -- ^ 1. Only strongly left to right glyphs.
| LeftToRightGlyphsWithNeutrals -- ^ 2. Like 1 but also contains neutrals.
| StronglyRightToLeftGlyphs -- ^ -1. Only strongly right to left glyphs.
| RightToLeftGlyphsWithNeutrals -- ^ -2. Like -1 but also contains neutrals.
deriving (Eq, Show)
data LocaTable
= ShortLocaTable (Vector Word16)
| LongLocaTable (Vector Word32)
deriving (Eq, Show)
unLocaTable :: LocaTable -> Vector Word32
unLocaTable (LongLocaTable values') = values'
unLocaTable (ShortLocaTable values') = (* 2) . fromIntegral <$> values'
-- * Horizontal metrics table
data LongHorMetric = LongHorMetric
{ advanceWidth :: Word16
, leftSideBearing :: Int16
} deriving (Eq, Show)
data HmtxTable = HmtxTable
{ hMetrics :: NonEmpty LongHorMetric
, leftSideBearing :: [Int16]
} deriving (Eq, Show)
-- * Glyph name and PostScript font table
data PostHeader = PostHeader
{ format :: Fixed32 -- ^ Format of this table
, italicAngle :: Fixed32 -- ^ Italic angle in degrees
, underlinePosition :: Int16 -- ^ Underline position
, underlineThickness :: Int16 -- ^ Underline thickness
, isFixedPitch :: Word32 -- ^ Font is monospaced; set to 1 if the font is monospaced and 0 otherwise (N.B., to maintain compatibility with older versions of the TrueType spec, accept any non-zero value as meaning that the font is monospaced)
, minMemType42 :: Word32 -- ^ Minimum memory usage when a TrueType font is downloaded as a Type 42 font
, maxMemType42 :: Word32 -- ^ Maximum memory usage when a TrueType font is downloaded as a Type 42 font
, minMemType1 :: Word32 -- ^ Minimum memory usage when a TrueType font is downloaded as a Type 1 font
, maxMemType1 :: Word32 -- ^ Maximum memory usage when a TrueType font is downloaded as a Type 1 font
} deriving (Eq, Show)
data PostFormat2Table = PostFormat2Table
{ glyphNameIndex :: Vector Word16 -- ^ Ordinal number of this glyph in 'post' string tables. This is not an offset.
, names :: Vector ByteString
} deriving (Eq, Show)
data PostSubtable
= None
| PostFormat2 PostFormat2Table
| PostFormat25 (Vector Int8)
| PostFormat4 (Vector Word16)
deriving (Eq, Show)
data PostTable = PostTable
{ postHeader :: PostHeader
, postSubtable :: PostSubtable
} deriving (Eq, Show)
-- * Font program table
newtype FpgmTable = FpgmTable (Vector Word8)
deriving (Eq, Show)
-- * Prep table
newtype PrepTable = PrepTable (Vector Word8)
deriving (Eq, Show)
-- * Horizontal device metrics table
data HdmxTable = HdmxTable
{ format :: Int16 -- ^ Format version number.
, records :: [DeviceRecord]
} deriving (Eq, Show)
data DeviceRecord = DeviceRecord
{ pixelSize :: Word8 -- ^ Pixel size for following widths.
, maximumWidth :: Word8 -- ^ Maximum width.
, widths :: Vector Word8 -- ^ Widths.
} deriving (Eq, Show)
-- * Glyph outline table
data GlyphDescription = GlyphDescription
{ numberOfContours :: Int
, xMin :: Int16 -- ^ Minimum x for coordinate data.
, yMin :: Int16 -- ^ Minimum y for coordinate data.
, xMax :: Int16 -- ^ Maximum x for coordinate data.
, yMax :: Int16 -- ^ Maximum y for coordinate data.
, definition :: GlyphDefinition
} deriving (Eq, Show)
data GlyphArgument
= GlyphInt16Argument Int16
| GlyphWord16Argument Word16
| GlyphInt8Argument Int8
| GlyphWord8Argument Word8
deriving (Eq, Show)
data GlyphTransformationOption
= GlyphNoScale
| GlyphScale F2Dot14
| GlyphXyScale F2Dot14 F2Dot14
| Glyph2By2Scale F2Dot14 F2Dot14 F2Dot14 F2Dot14
deriving (Eq, Show)
data SimpleGlyphDefinition = SimpleGlyphDefinition
-- | Array of last points of each contour; n is the number of contours;
-- array entries are point indices.
{ endPtsOfContours :: Vector Word16
-- | Array of instructions for this glyph.
, instructions :: Vector Word8
-- | Array of coordinates; the first is relative to (0,0), others are
-- relative to previous point.
, coordinates :: Vector GlyphCoordinate
} deriving (Eq, Show)
data CompoundGlyphDefinition = CompoundGlyphDefinition
{ components :: Vector ComponentGlyphPartDescription
, instructions :: Vector Word8
} deriving (Eq, Show)
data GlyphDefinition
= SimpleGlyph SimpleGlyphDefinition
| CompoundGlyph CompoundGlyphDefinition
deriving (Eq, Show)
data ComponentGlyphFlags = ComponentGlyphFlags
{ roundXyToGrid :: Bool
, weHaveInstructions :: Bool
, useMyMetrics :: Bool
, overlapCompound :: Bool
} deriving (Eq, Show)
data GlyphCoordinate = GlyphCoordinate
{ coordinateX :: Int16
, coordinateY :: Int16
, onCurve :: Bool
} deriving (Eq, Show)
data ComponentGlyphPartDescription = ComponentGlyphPartDescription
{ flags :: ComponentGlyphFlags
, glyphIndex :: Word16
, argument1 :: GlyphArgument
, argument2 :: GlyphArgument
, transformationOption :: GlyphTransformationOption
} deriving (Eq, Show)
-- * Glyph outline table
data OutlineFlag = OutlineFlag
{ onCurve :: Bool
, xShortVector :: Bool
, yShortVector :: Bool
, thisXIsSame :: Bool
, thisYIsSame :: Bool
} deriving (Eq, Show)
newtype GlyfTable = GlyfTable (Vector GlyphDescription)
deriving (Eq, Show)
-- * Character to glyph mapping table
data CmapTable = CmapTable
{ version :: Word16 -- ^ Version number is zero.
-- | Encodings with an offset into subtables map.
, encodings :: [CmapEncoding]
-- ^ The key into the map is the offset in the 'CmapEncoding's.
, subtables :: IntMap CmapSubtable
} deriving (Eq, Show)
data CmapEncoding = CmapEncoding
{ platformID :: Word16 -- ^ Platform identifier
, platformSpecificID :: Word16 -- ^ Platform-specific encoding identifier.
, offset :: Word32 -- ^ Offst of the mapping table.
} deriving (Eq, Show)
data CmapFormat0Table = CmapFormat0Table
{ language :: Word16 -- ^ Language code.
, glyphIndexArray :: Vector Word8 -- ^ An array that maps character codes to glyph index values.
} deriving (Eq, Show)
data CmapFormat2Subheader = CmapFormat2Subheader
{ firstCode :: Word16
, entryCount :: Word16
, idDelta :: Int16
, idRangeOffset :: Word16
} deriving (Eq, Show)
data CmapFormat2Table = CmapFormat2Table
{ language :: Word16 -- ^ Language code.
, subHeaderKeys :: Vector Word16 -- ^ Array that maps high bytes to subHeaders: value is index * 8.
, subHeaders :: Vector CmapFormat2Subheader -- ^ Variable length array of subHeader structures.
, glyphIndexArray :: Vector Word16 -- ^ Variable length array containing subarrays.
} deriving (Eq, Show)
data CmapFormat4Table = CmapFormat4Table
{ language :: Word16 -- ^ Language code.
, searchRange :: Word16 -- ^ 2 * (2**FLOOR(log2(segCount))).
, entrySelector :: Word16 -- ^ log2(searchRange/2).
, rangeShift :: Word16 -- ^ (2 * segCount) - searchRange.
, endCode :: Vector Word16 -- ^ Ending character code for each segment, last = 0xFFFF.
, startCode :: Vector Word16 -- ^ Starting character code for each segment.
, idDelta :: Vector Word16 -- ^ Delta for all character codes in segment.
, idRangeOffset :: Vector Word16 -- ^ Offset in bytes to glyph indexArray, or 0.
, glyphIndexArray :: Vector Word16 -- ^ Glyph index array.
} deriving (Eq, Show)
data CmapFormat6Table = CmapFormat6Table
{ language :: Word16 -- ^ Language code.
, firstCode :: Word16 -- ^ First character code of subrange.
, glyphIndexArray :: Vector Word16 -- ^ Array of glyph index values for character codes in the range
} deriving (Eq, Show)
data CmapGroup = CmapGroup
-- | First character code in this group; note that if this group is for one
-- or more 16-bit character codes (which is determined from the is32 array),
-- this 32-bit value will have the high 16-bits set to zero.
{ startCharCode :: Word32
-- | Last character code in this group; same condition as listed above for
-- the startCharCode.
, endCharCode :: Word32
-- | Glyph index corresponding to the starting character code.
, startGlyphCode :: Word32
} deriving (Eq, Show)
data CmapFormat8Table = CmapFormat8Table
{ language :: Word32 -- ^ Language code.
-- | Tightly packed array of bits (8K bytes total) indicating whether the
-- particular 16-bit (index) value is the start of a 32-bit character code.
, is32 :: [Word8]
-- | Word32 Number of groupings which follow.
, groups :: Vector CmapGroup
} deriving (Eq, Show)
data CmapFormat10Table = CmapFormat10Table
{ language :: Word32 -- ^ Language code.
, startCharCode :: Word32 -- ^ First character code covered.
, numChars :: Word32 -- ^ Number of character codes covered.
, glyphs :: Vector Word16 -- ^ Array of glyph indices for the character codes covered.
} deriving (Eq, Show)
data CmapFormat12Table = CmapFormat12Table
{ language :: Word32 -- ^ Language code.
, groups :: Vector CmapGroup
} deriving (Eq, Show)
type CmapFormat13Table = CmapFormat12Table
newtype CmapFormat14Table = CmapFormat14Table
{ varSelectorRecords :: VariationSelectorMap
} deriving (Eq, Show)
data CmapSubtable
= CmapFormat0 CmapFormat0Table
| CmapFormat2 CmapFormat2Table
| CmapFormat4 CmapFormat4Table
| CmapFormat6 CmapFormat6Table
| CmapFormat8 CmapFormat8Table
| CmapFormat10 CmapFormat10Table
| CmapFormat12 CmapFormat12Table
| CmapFormat13 CmapFormat13Table
| CmapFormat14 CmapFormat14Table
deriving (Eq, Show)
data UVSOffset a b = DefaultUVSOffset Word32 a | NonDefaultUVSOffset Word32 b
deriving (Eq, Show)
data UVSMapping = UVSMapping
{ unicodeValue :: Word32 -- ^ Base Unicode value of the UVS.
, glyphID :: Word16 -- ^ Glyph ID of the UVS.
} deriving (Eq, Show)
data UnicodeValueRange = UnicodeValueRange
{ startUnicodeValue :: Word32 -- ^ First value in this range.
, additionalCount :: Word8 -- ^ Number of additional values in this range.
} deriving (Eq, Show)
-- | Mapping from variation selector record offsets to the record data.
type VariationSelectorMap = IntMap
(NonEmpty (UVSOffset (Vector UnicodeValueRange) (Vector UVSMapping)))
-- * OS/2 table
data Os2Table
= Os2Version0 Os2BaseFields (Maybe Os2MicrosoftFields)
| Os2Version1 Os2BaseFields Os2MicrosoftFields Os2Version1Fields
| Os2Version2 Os2BaseFields Os2MicrosoftFields Os2Version4Fields
| Os2Version3 Os2BaseFields Os2MicrosoftFields Os2Version4Fields
| Os2Version4 Os2BaseFields Os2MicrosoftFields Os2Version4Fields
| Os2Version5 Os2BaseFields Os2MicrosoftFields Os2Version5Fields
deriving (Eq, Show)
data Os2Version1Fields = Os2Version1Fields
{ ulCodePageRange1 :: Word32
, ulCodePageRange2 :: Word32
} deriving (Eq, Show)
data Os2MicrosoftFields = Os2MicrosoftFields
{ sTypoAscender :: Int16
, sTypoDescender :: Int16
, sTypoLineGap :: Int16
, usWinAscent :: Word16
, usWinDescent :: Word16
} deriving (Eq, Show)
data Os2Version4Fields = Os2Version4Fields
{ ulCodePageRange1 :: Word32
, ulCodePageRange2 :: Word32
, sxHeight :: Int16
, sCapHeight :: Int16
, usDefaultChar :: Word16
, usBreakChar :: Word16
, usMaxContext :: Word16
} deriving (Eq, Show)
data Os2Version5Fields = Os2Version5Fields
{ ulCodePageRange1 :: Word32
, ulCodePageRange2 :: Word32
, sxHeight :: Int16
, sCapHeight :: Int16
, usDefaultChar :: Word16
, usBreakChar :: Word16
, usMaxContext :: Word16
, usLowerOpticalPointSize :: Word16
, usUpperOpticalPointSize :: Word16
} deriving (Eq, Show)
data Os2BaseFields = Os2BaseFields
{ version :: Word16 -- ^ Table version number (set to 0).
-- | Average weighted advance width of lower case letters and space.
, xAvgCharWidth :: Int16
-- | Visual weight (degree of blackness or thickness) of stroke in glyphs.
, usWeightClass :: Word16
-- | Relative change from the normal aspect ratio (width to height ratio)
-- as specified by a font designer for the glyphs in the font.
, usWidthClass :: Word16
-- | Characteristics and properties of this font (set undefined bits to
-- zero).
, fsType :: Int16
-- | Recommended horizontal size in pixels for subscripts.
, ySubscriptXSize :: Int16
-- | Recommended vertical size in pixels for subscripts.
, ySubscriptYSize :: Int16
-- | Recommended horizontal offset for subscripts.
, ySubscriptXOffset :: Int16
-- | Recommended vertical offset form the baseline for subscripts.
, ySubscriptYOffset :: Int16
-- | Recommended horizontal size in pixels for superscripts.
, ySuperscriptXSize :: Int16
-- | Recommended vertical size in pixels for superscripts.
, ySuperscriptYSize :: Int16
-- | Recommended horizontal offset for superscripts.
, ySuperscriptXOffset :: Int16
-- | Recommended vertical offset from the baseline for superscripts.
, ySuperscriptYOffset :: Int16
-- | Width of the strikeout stroke.
, yStrikeoutSize :: Int16
-- | Position of the strikeout stroke relative to the baseline.
, yStrikeoutPosition :: Int16
-- ^ Classification of font-family design.
, sFamilyClass :: Int16
-- | 10 byte series of number used to describe the visual characteristics
-- of a given typeface.
, panose :: Panose
-- | Field is split into two bit fields of 96 and 36 bits each. The low 96
-- bits are used to specify the Unicode blocks encompassed by the font file.
-- The high 32 bits are used to specify the character or script sets covered
-- by the font file. Bit assignments are pending. Set to 0.
, ulUnicodeRange :: Vector Word32
-- | Four character identifier for the font vendor.
, achVendID :: Vector Int8
-- | 2-byte bit field containing information concerning the nature of the
-- font patterns.
, fsSelection :: Word16
-- | The minimum Unicode index in this font.
, fsFirstCharIndex :: Word16
-- | The maximum Unicode index in this font.
, fsLastCharIndex :: Word16
} deriving (Eq, Show)
data Panose = Panose
{ bFamilyType :: BFamilyType
, bSerifStyle :: BSerifStyle
, bWeight :: BWeight
, bProportion :: BProportion
, bContrast :: BContrast
, bStrokeVariation :: BStrokeVariation
, bArmStyle :: BArmStyle
, bLetterform :: BLetterform
, bMidline :: BMidline
, bXHeight :: BXHeight
} deriving (Eq, Show)
data BFamilyType
= AnyFamilyType
| NoFitFamilyType
| TextAndDisplayFamilyType
| ScriptFamilyType
| DecorativeFamilyType
| PictorialFamilyType
deriving (Eq, Show)
data BSerifStyle
= AnySerifStyle
| NoFitSerifStyle
| CoveSerifStyle
| ObtuseCoveSerifStyle
| SquareCoveSerifStyle
| ObtuseSquareCoveSerifStyle
| SquareSerifStyle
| ThinSerifStyle
| BoneSerifStyle
| ExaggeratedSerifStyle
| TriangleSerifStyle
| NormalSansSerifStyle
| ObtuseSansSerifStyle
| PerpSansSerifStyle
| FlaredSerifStyle
| RoundedSerifStyle
deriving (Eq, Show)
data BWeight
= AnyWeight
| NoFitWeight
| VeryLightWeight
| LightWeight
| ThinWeight
| BookWeight
| MediumWeight
| DemiWeight
| BoldWeight
| HeavyWeight
| BlackWeight
| NordWeight
deriving (Eq, Show)
data BProportion
= AnyProportion
| NoFitProportion
| OldStyleProportion
| ModernProportion
| EvenWidthProportion
| ExpandedProportion
| CondensedProportion
| VeryExpandedProportion
| VeryCondensedProportion
| MonospacedProportion
deriving (Eq, Show)
data BContrast
= AnyContrast
| NoFitContrast
| NoneContrast
| VeryLowContrast
| LowContrast
| MediumLowContrast
| MediumContrast
| MediumHighContrast
| HighContrast
| VeryHighContrast
deriving (Eq, Show)
data BStrokeVariation
= AnyStrokeVariatoon
| NoFitStrokeVariatoon
| GradualDiagonalStrokeVariatoon
| GradualTransitionalStrokeVariatoon
| GradualVerticalStrokeVariatoon
| GradualHorizontalStrokeVariatoon
| RapidVerticalStrokeVariatoon
| RapidHorizontalStrokeVariatoon
| InstantVerticalStrokeVariatoon
deriving (Eq, Show)
data BArmStyle
= AnyArmStyle
| NoFitArmStyle
| StraightArmsHorizontalArmStyle
| StraightArmsWedgeArmStyle
| StraightArmsVerticalArmStyle
| StraightArmsSingleSerifArmStyle
| StraightArmsDoubleSerifArmStyle
| NonStraightArmsHorizontalArmStyle
| NonStraightArmsWedgeArmStyle
| NonStraightArmsVerticalArmStyle
| NonStraightArmsSingleSerifArmStyle
| NonStraightArmsDoubleSerifArmStyle
deriving (Eq, Show)
data BLetterform
= AnyLetterform
| NoFitLetterform
| NormalContactLetterform
| NormalWeightedLetterform
| NormalBoxedLetterform
| NormalFlattenedLetterform
| NormalRoundedLetterform
| NormalOffCenterLetterform
| NormalSquareLetterform
| ObliqueContactLetterform
| ObliqueWeightedLetterform
| ObliqueBoxedLetterform
| ObliqueFlattenedLetterform
| ObliqueRoundedLetterform
| ObliqueOffCenterLetterform
| ObliqueSquareLetterform
deriving (Eq, Show)
data BMidline
= AnyMidline
| NoFitMidline
| StandardTrimmedMidline
| StandardPointedMidline
| StandardSerifedMidline
| HighTrimmedMidline
| HighPointedMidline
| HighSerifedMidline
| ConstantTrimmedMidline
| ConstantPointedMidline
| ConstantSerifedMidline
| LowTrimmedMidline
| LowPointedMidline
| LowSerifedMidline
deriving (Eq, Show)
data BXHeight
= AnyXHeight
| NoFitXHeight
| ConstantSmallXHeight
| ConstantStandardXHeight
| ConstantLargeXHeight
| DuckingSmallXHeight
| DuckingStandardXHeight
| DuckingLargeXHeight
deriving (Eq, Show)
-- * Kern table
newtype KernHeader = KernHeader
{ version :: Fixed32 -- ^ The version number of the kerning table (0x00010000 for the current version).
} deriving (Eq, Show)
data KernSubtableHeader = KernSubtableHeader
-- | The length of this subtable in bytes, including this header.
{ length :: Word32
-- | Circumstances under which this table is used.
, coverage :: [Coverage]
-- | The tuple index (used for variations fonts). This value specifies which
-- tuple this subtable covers.
, tupleIndex :: Word16
} deriving (Eq, Show)
data Coverage
= KernVertical -- ^ Set if table has vertical kerning values.
| KernCrossStream -- ^ Set if table has cross-stream kerning values.
| KernVariation -- ^ Set if table has variation kerning values.
| KernUnusedBits -- ^ Set to 0.
| KernFormatMask -- ^ Set the format of this subtable (0-3 currently defined).
deriving (Eq, Show)
data KernFormat0Pair = KernFormat0Pair
{ left :: Word16 -- ^ The glyph index for the lefthand glyph in the kerning pair.
, right :: Word16 -- ^ The glyph index for the righthand glyph in the kerning pair.
-- | The kerning value in FUnits for the left and right pair in FUnits.
-- If this value is greater than zero, the glyphs are moved apart.
-- If this value is less than zero, the glyphs are moved together.
, value :: Int16
} deriving (Eq, Show)
data KernFormat0Table = KernFormat0Table
-- | The largest power of two less than or equal to the value of nPairs,
-- multiplied by the size in bytes of an entry in the subtable.
{ searchRange :: Word16
-- | This is calculated as log2 of the largest power of two less than or
-- equal to the value of nPairs. This value indicates how many iterations of
-- the search loop have to be made. For example, in a list of eight items,
-- there would be three iterations of the loop.
, entrySelector :: Word16
-- | The value of nPairs minus the largest power of two less than or equal
-- to nPairs. This is multiplied by the size in bytes of an entry in the
-- table.
, rangeShift :: Word16
, pairs :: [KernFormat0Pair]
} deriving (Eq, Show)
-- | Kern subtable format 1 header.
data StateHeader = StateHeader
{ stateSize :: Word16 -- ^ Number of classes defined for this table.
-- | Offset from the beginning of the state table to the beginning of the
-- class subtable.
, classTableOffset :: Word16
-- | Offset from the beginning of the state table to the beginning of the
-- state array.
, stateArrayOffset :: Word16
-- | Offset from the beginning of the state table to the beginning of the
-- entry subtable.
, entryTableOffset :: Word16
-- | Offset from the beginning of the state table to the beginning of the
-- state table values.
, valueOffset :: Word16
} deriving (Eq, Show)
data StateEntry = StateEntry
{ newState :: Word16
, flags :: Word16
} deriving (Eq, Show)
data KernFormat1Table = KernFormat1Table
{ stateHeader :: StateHeader
, firstGlyph :: Word16
, classArray :: ByteString
, stateArray :: ByteString
, entries :: [StateEntry]
} deriving (Eq, Show)
data SimpleArrayHeader = SimpleArrayHeader
{ rowWidth :: Word16 -- ^ The width, in bytes, of a row in the subtable.
-- | Offset from beginning of this subtable to the left-hand offset table.
, leftOffsetTable :: Word16
-- | Offset from beginning of this subtable to right-hand offset table.
, rightOffsetTable :: Word16
-- | Offset from beginning of this subtable to the start of the kerning
-- array.
, array :: Word16
} deriving (Eq, Show)
data ClassTableHeader = ClassTableHeader
{ firstGlyph -- ^ First glyph in class range.
-- | The offsets array for all of the glyphs in the range.
, offsets :: [Word16]
} deriving (Eq, Show)
data KernFormat2Table = KernFormat2Table
{ simpleArrayHeader :: SimpleArrayHeader
, classTableHeader :: ClassTableHeader
, values :: [Int16]
} deriving (Eq, Show)