From a34b46e1b553623d5dc385fc8e235df808fbadb2 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 3 Feb 2024 11:58:47 +0100 Subject: Add font compression --- lib/Graphics/Fountainhead/TrueType.hs | 1318 +++++++++++++++++++++++++++++++++ 1 file changed, 1318 insertions(+) create mode 100644 lib/Graphics/Fountainhead/TrueType.hs (limited to 'lib/Graphics/Fountainhead/TrueType.hs') diff --git a/lib/Graphics/Fountainhead/TrueType.hs b/lib/Graphics/Fountainhead/TrueType.hs new file mode 100644 index 0000000..0c15081 --- /dev/null +++ b/lib/Graphics/Fountainhead/TrueType.hs @@ -0,0 +1,1318 @@ +{- 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(..) + , GASPRange(..) + , GASPTable(..) + , 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(..) + , RangeGaspBehavior(..) + , 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 flags. + , flags :: Vector OutlineFlag + -- | 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 + } deriving (Eq, Show) + +instance Semigroup GlyphCoordinate + where + lhs <> rhs = + let GlyphCoordinate{ coordinateX = lhX, coordinateY = lhY } = lhs + GlyphCoordinate{ coordinateX = rhX, coordinateY = rhY } = rhs + in GlyphCoordinate{ coordinateX = lhX + rhX, coordinateY = lhY + rhY } + +instance Monoid GlyphCoordinate + where + mempty = GlyphCoordinate 0 0 + +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 + , repeat :: Word8 + , thisXIsSame :: Bool + , thisYIsSame :: Bool + } deriving (Eq, Show) + +newtype GlyfTable = GlyfTable (Vector GlyphDescription) + deriving (Eq, Show) + +-- 'cmap' table + +-- | 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 + +instance Show BFamilyType + where + show AnyFamilyType = "Any" + show NoFitFamilyType = "No Fit" + show TextAndDisplayFamilyType = "Text and Display" + show ScriptFamilyType = "Script" + show DecorativeFamilyType = "Decorative" + show PictorialFamilyType = "Pictorial" + +instance Enum BFamilyType + where + toEnum 0 = AnyFamilyType + toEnum 1 = NoFitFamilyType + toEnum 2 = TextAndDisplayFamilyType + toEnum 3 = ScriptFamilyType + toEnum 4 = DecorativeFamilyType + toEnum 5 = PictorialFamilyType + toEnum _ = error "Unknown family type" + fromEnum AnyFamilyType = 0 + fromEnum NoFitFamilyType = 1 + fromEnum TextAndDisplayFamilyType = 2 + fromEnum ScriptFamilyType = 3 + fromEnum DecorativeFamilyType = 4 + fromEnum PictorialFamilyType = 5 + +data BSerifStyle + = AnySerifStyle + | NoFitSerifStyle + | CoveSerifStyle + | ObtuseCoveSerifStyle + | SquareCoveSerifStyle + | ObtuseSquareCoveSerifStyle + | SquareSerifStyle + | ThinSerifStyle + | BoneSerifStyle + | ExaggeratedSerifStyle + | TriangleSerifStyle + | NormalSansSerifStyle + | ObtuseSansSerifStyle + | PerpSansSerifStyle + | FlaredSerifStyle + | RoundedSerifStyle + deriving Eq + +instance Show BSerifStyle + where + show AnySerifStyle = "Any" + show NoFitSerifStyle = "No Fit" + show CoveSerifStyle = "Cove" + show ObtuseCoveSerifStyle = "Obtuse Cove" + show SquareCoveSerifStyle = "Square Cove" + show ObtuseSquareCoveSerifStyle = "Obtuse Square Cove" + show SquareSerifStyle = "Square" + show ThinSerifStyle = "Thin" + show BoneSerifStyle = "Bone" + show ExaggeratedSerifStyle = "Exaggerated" + show TriangleSerifStyle = "Triangle" + show NormalSansSerifStyle = "Normal Sans" + show ObtuseSansSerifStyle = "Obtuse Sans" + show PerpSansSerifStyle = "Perp Sans" + show FlaredSerifStyle = "Flared" + show RoundedSerifStyle = "Rounded" + +instance Enum BSerifStyle + where + toEnum 0 = AnySerifStyle + toEnum 1 = NoFitSerifStyle + toEnum 2 = CoveSerifStyle + toEnum 3 = ObtuseCoveSerifStyle + toEnum 4 = SquareCoveSerifStyle + toEnum 5 = ObtuseSquareCoveSerifStyle + toEnum 6 = SquareSerifStyle + toEnum 7 = ThinSerifStyle + toEnum 8 = BoneSerifStyle + toEnum 9 = ExaggeratedSerifStyle + toEnum 10 = TriangleSerifStyle + toEnum 11 = NormalSansSerifStyle + toEnum 12 = ObtuseSansSerifStyle + toEnum 13 = PerpSansSerifStyle + toEnum 14 = FlaredSerifStyle + toEnum 15 = RoundedSerifStyle + toEnum _ = error "Unknown serif type" + fromEnum AnySerifStyle = 0 + fromEnum NoFitSerifStyle = 1 + fromEnum CoveSerifStyle = 2 + fromEnum ObtuseCoveSerifStyle = 3 + fromEnum SquareCoveSerifStyle = 4 + fromEnum ObtuseSquareCoveSerifStyle = 5 + fromEnum SquareSerifStyle = 6 + fromEnum ThinSerifStyle = 7 + fromEnum BoneSerifStyle = 8 + fromEnum ExaggeratedSerifStyle = 9 + fromEnum TriangleSerifStyle = 10 + fromEnum NormalSansSerifStyle = 11 + fromEnum ObtuseSansSerifStyle = 12 + fromEnum PerpSansSerifStyle = 13 + fromEnum FlaredSerifStyle = 14 + fromEnum RoundedSerifStyle = 15 + +data BWeight + = AnyWeight + | NoFitWeight + | VeryLightWeight + | LightWeight + | ThinWeight + | BookWeight + | MediumWeight + | DemiWeight + | BoldWeight + | HeavyWeight + | BlackWeight + | NordWeight + deriving Eq + +instance Show BWeight + where + show AnyWeight = "Any" + show NoFitWeight = "No Fit" + show VeryLightWeight = "Very Light" + show LightWeight = "Light" + show ThinWeight = "Thin" + show BookWeight = "Book" + show MediumWeight = "Medium" + show DemiWeight = "Demi" + show BoldWeight = "Bold" + show HeavyWeight = "Heavy" + show BlackWeight = "Black" + show NordWeight = "Nord" + +instance Enum BWeight + where + fromEnum AnyWeight = 0 + fromEnum NoFitWeight = 1 + fromEnum VeryLightWeight = 2 + fromEnum LightWeight = 3 + fromEnum ThinWeight = 4 + fromEnum BookWeight = 5 + fromEnum MediumWeight = 6 + fromEnum DemiWeight = 7 + fromEnum BoldWeight = 8 + fromEnum HeavyWeight = 9 + fromEnum BlackWeight = 10 + fromEnum NordWeight = 11 + toEnum 0 = AnyWeight + toEnum 1 = NoFitWeight + toEnum 2 = VeryLightWeight + toEnum 3 = LightWeight + toEnum 4 = ThinWeight + toEnum 5 = BookWeight + toEnum 6 = MediumWeight + toEnum 7 = DemiWeight + toEnum 8 = BoldWeight + toEnum 9 = HeavyWeight + toEnum 10 = BlackWeight + toEnum 11 = NordWeight + toEnum _ = error "Unknown weight" + +data BProportion + = AnyProportion + | NoFitProportion + | OldStyleProportion + | ModernProportion + | EvenWidthProportion + | ExpandedProportion + | CondensedProportion + | VeryExpandedProportion + | VeryCondensedProportion + | MonospacedProportion + deriving Eq + +instance Show BProportion + where + show AnyProportion = "Any" + show NoFitProportion = "No Fit" + show OldStyleProportion = "Old Style" + show ModernProportion = "Modern" + show EvenWidthProportion = "Even Width" + show ExpandedProportion = "Expanded" + show CondensedProportion = "Condensed" + show VeryExpandedProportion = "Very Expanded" + show VeryCondensedProportion = "Very Condensed" + show MonospacedProportion = "Monospaced" + +instance Enum BProportion + where + fromEnum AnyProportion = 0 + fromEnum NoFitProportion = 1 + fromEnum OldStyleProportion = 2 + fromEnum ModernProportion = 3 + fromEnum EvenWidthProportion = 4 + fromEnum ExpandedProportion = 5 + fromEnum CondensedProportion = 6 + fromEnum VeryExpandedProportion = 7 + fromEnum VeryCondensedProportion = 8 + fromEnum MonospacedProportion = 9 + toEnum 0 = AnyProportion + toEnum 1 = NoFitProportion + toEnum 2 = OldStyleProportion + toEnum 3 = ModernProportion + toEnum 4 = EvenWidthProportion + toEnum 5 = ExpandedProportion + toEnum 6 = CondensedProportion + toEnum 7 = VeryExpandedProportion + toEnum 8 = VeryCondensedProportion + toEnum 9 = MonospacedProportion + toEnum _ = error "Unknown proportion" + +data BContrast + = AnyContrast + | NoFitContrast + | NoneContrast + | VeryLowContrast + | LowContrast + | MediumLowContrast + | MediumContrast + | MediumHighContrast + | HighContrast + | VeryHighContrast + deriving Eq + +instance Show BContrast + where + show AnyContrast = "Any" + show NoFitContrast = "No Fit" + show NoneContrast = "None" + show VeryLowContrast = "Very Low" + show LowContrast = "Low" + show MediumLowContrast = "Medium Low" + show MediumContrast = "Medium" + show MediumHighContrast = "Medium High" + show HighContrast = "High" + show VeryHighContrast = "Very High" + +instance Enum BContrast + where + fromEnum AnyContrast = 0 + fromEnum NoFitContrast = 1 + fromEnum NoneContrast = 2 + fromEnum VeryLowContrast = 3 + fromEnum LowContrast = 4 + fromEnum MediumLowContrast = 5 + fromEnum MediumContrast = 6 + fromEnum MediumHighContrast = 7 + fromEnum HighContrast = 8 + fromEnum VeryHighContrast = 9 + toEnum 0 = AnyContrast + toEnum 1 = NoFitContrast + toEnum 2 = NoneContrast + toEnum 3 = VeryLowContrast + toEnum 4 = LowContrast + toEnum 5 = MediumLowContrast + toEnum 6 = MediumContrast + toEnum 7 = MediumHighContrast + toEnum 8 = HighContrast + toEnum 9 = VeryHighContrast + toEnum _ = error "Unknown contrast" + +data BStrokeVariation + = AnyStrokeVariation + | NoFitStrokeVariation + | GradualDiagonalStrokeVariation + | GradualTransitionalStrokeVariation + | GradualVerticalStrokeVariation + | GradualHorizontalStrokeVariation + | RapidVerticalStrokeVariation + | RapidHorizontalStrokeVariation + | InstantVerticalStrokeVariation + deriving Eq + +instance Show BStrokeVariation + where + show AnyStrokeVariation = "Any" + show NoFitStrokeVariation = "No Fit" + show GradualDiagonalStrokeVariation = "Gradual/Diagonal" + show GradualTransitionalStrokeVariation = "Gradual/Transitional" + show GradualVerticalStrokeVariation = "Gradual/Vertical" + show GradualHorizontalStrokeVariation = "Gradual/Horizontal" + show RapidVerticalStrokeVariation = "Rapid/Vertical" + show RapidHorizontalStrokeVariation = "Rapid/Horizontal" + show InstantVerticalStrokeVariation = "Instant/Vertical" + +instance Enum BStrokeVariation + where + fromEnum AnyStrokeVariation = 0 + fromEnum NoFitStrokeVariation = 1 + fromEnum GradualDiagonalStrokeVariation = 2 + fromEnum GradualTransitionalStrokeVariation = 3 + fromEnum GradualVerticalStrokeVariation = 4 + fromEnum GradualHorizontalStrokeVariation = 5 + fromEnum RapidVerticalStrokeVariation = 6 + fromEnum RapidHorizontalStrokeVariation = 7 + fromEnum InstantVerticalStrokeVariation = 8 + toEnum 0 = AnyStrokeVariation + toEnum 1 = NoFitStrokeVariation + toEnum 2 = GradualDiagonalStrokeVariation + toEnum 3 = GradualTransitionalStrokeVariation + toEnum 4 = GradualVerticalStrokeVariation + toEnum 5 = GradualHorizontalStrokeVariation + toEnum 6 = RapidVerticalStrokeVariation + toEnum 7 = RapidHorizontalStrokeVariation + toEnum 8 = InstantVerticalStrokeVariation + toEnum _ = error "Unknown stroke variation" + +data BArmStyle + = AnyArmStyle + | NoFitArmStyle + | StraightArmsHorizontalArmStyle + | StraightArmsWedgeArmStyle + | StraightArmsVerticalArmStyle + | StraightArmsSingleSerifArmStyle + | StraightArmsDoubleSerifArmStyle + | NonStraightArmsHorizontalArmStyle + | NonStraightArmsWedgeArmStyle + | NonStraightArmsVerticalArmStyle + | NonStraightArmsSingleSerifArmStyle + | NonStraightArmsDoubleSerifArmStyle + deriving Eq + +instance Show BArmStyle + where + show AnyArmStyle = "Any" + show NoFitArmStyle = "No Fit" + show StraightArmsHorizontalArmStyle = "Straight Arms/Horizontal" + show StraightArmsWedgeArmStyle = "Straight Arms/Wedge" + show StraightArmsVerticalArmStyle = "Straight Arms/Vertical" + show StraightArmsSingleSerifArmStyle = "Straight Arms/Single Serif" + show StraightArmsDoubleSerifArmStyle = "Straight Arms/Double Serif" + show NonStraightArmsHorizontalArmStyle = "Non-Straight Arms/Horizontal" + show NonStraightArmsWedgeArmStyle = "Non-Straight Arms/Wedge" + show NonStraightArmsVerticalArmStyle = "Non-Straight Arms/Vertical" + show NonStraightArmsSingleSerifArmStyle = "Non-Straight Arms/Single Serif" + show NonStraightArmsDoubleSerifArmStyle = "Non-Straight Arms/Double Serif" + +instance Enum BArmStyle + where + fromEnum AnyArmStyle = 0 + fromEnum NoFitArmStyle = 1 + fromEnum StraightArmsHorizontalArmStyle = 2 + fromEnum StraightArmsWedgeArmStyle = 3 + fromEnum StraightArmsVerticalArmStyle = 4 + fromEnum StraightArmsSingleSerifArmStyle = 5 + fromEnum StraightArmsDoubleSerifArmStyle = 6 + fromEnum NonStraightArmsHorizontalArmStyle = 7 + fromEnum NonStraightArmsWedgeArmStyle = 8 + fromEnum NonStraightArmsVerticalArmStyle = 9 + fromEnum NonStraightArmsSingleSerifArmStyle = 10 + fromEnum NonStraightArmsDoubleSerifArmStyle = 11 + toEnum 0 = AnyArmStyle + toEnum 1 = NoFitArmStyle + toEnum 2 = StraightArmsHorizontalArmStyle + toEnum 3 = StraightArmsWedgeArmStyle + toEnum 4 = StraightArmsVerticalArmStyle + toEnum 5 = StraightArmsSingleSerifArmStyle + toEnum 6 = StraightArmsDoubleSerifArmStyle + toEnum 7 = NonStraightArmsHorizontalArmStyle + toEnum 8 = NonStraightArmsWedgeArmStyle + toEnum 9 = NonStraightArmsVerticalArmStyle + toEnum 10 = NonStraightArmsSingleSerifArmStyle + toEnum 11 = NonStraightArmsDoubleSerifArmStyle + toEnum _ = error "Unknown arm style" + +data BLetterform + = AnyLetterform + | NoFitLetterform + | NormalContactLetterform + | NormalWeightedLetterform + | NormalBoxedLetterform + | NormalFlattenedLetterform + | NormalRoundedLetterform + | NormalOffCenterLetterform + | NormalSquareLetterform + | ObliqueContactLetterform + | ObliqueWeightedLetterform + | ObliqueBoxedLetterform + | ObliqueFlattenedLetterform + | ObliqueRoundedLetterform + | ObliqueOffCenterLetterform + | ObliqueSquareLetterform + deriving Eq + +instance Show BLetterform + where + show AnyLetterform = "Any" + show NoFitLetterform = "No Fit" + show NormalContactLetterform = "Normal/Contact" + show NormalWeightedLetterform = "Normal/Weighted" + show NormalBoxedLetterform = "Normal/Boxed" + show NormalFlattenedLetterform = "Normal/Flattened" + show NormalRoundedLetterform = "Normal/Rounded" + show NormalOffCenterLetterform = "Normal/Off Center" + show NormalSquareLetterform = "Normal/Square" + show ObliqueContactLetterform = "Oblique/Contact" + show ObliqueWeightedLetterform = "Oblique/Weighted" + show ObliqueBoxedLetterform = "Oblique/Boxed" + show ObliqueFlattenedLetterform = "Oblique/Flattened" + show ObliqueRoundedLetterform = "Oblique/Rounded" + show ObliqueOffCenterLetterform = "Oblique/Off Center" + show ObliqueSquareLetterform = "Oblique/Square" + +instance Enum BLetterform + where + fromEnum AnyLetterform = 0 + fromEnum NoFitLetterform = 1 + fromEnum NormalContactLetterform = 2 + fromEnum NormalWeightedLetterform = 3 + fromEnum NormalBoxedLetterform = 4 + fromEnum NormalFlattenedLetterform = 5 + fromEnum NormalRoundedLetterform = 6 + fromEnum NormalOffCenterLetterform = 7 + fromEnum NormalSquareLetterform = 8 + fromEnum ObliqueContactLetterform = 9 + fromEnum ObliqueWeightedLetterform = 10 + fromEnum ObliqueBoxedLetterform = 11 + fromEnum ObliqueFlattenedLetterform = 12 + fromEnum ObliqueRoundedLetterform = 13 + fromEnum ObliqueOffCenterLetterform = 14 + fromEnum ObliqueSquareLetterform = 15 + toEnum 0 = AnyLetterform + toEnum 1 = NoFitLetterform + toEnum 2 = NormalContactLetterform + toEnum 3 = NormalWeightedLetterform + toEnum 4 = NormalBoxedLetterform + toEnum 5 = NormalFlattenedLetterform + toEnum 6 = NormalRoundedLetterform + toEnum 7 = NormalOffCenterLetterform + toEnum 8 = NormalSquareLetterform + toEnum 9 = ObliqueContactLetterform + toEnum 10 = ObliqueWeightedLetterform + toEnum 11 = ObliqueBoxedLetterform + toEnum 12 = ObliqueFlattenedLetterform + toEnum 13 = ObliqueRoundedLetterform + toEnum 14 = ObliqueOffCenterLetterform + toEnum 15 = ObliqueSquareLetterform + toEnum _ = error "Unknown letterform" + +data BMidline + = AnyMidline + | NoFitMidline + | StandardTrimmedMidline + | StandardPointedMidline + | StandardSerifedMidline + | HighTrimmedMidline + | HighPointedMidline + | HighSerifedMidline + | ConstantTrimmedMidline + | ConstantPointedMidline + | ConstantSerifedMidline + | LowTrimmedMidline + | LowPointedMidline + | LowSerifedMidline + deriving Eq + +instance Show BMidline + where + show AnyMidline = "Any" + show NoFitMidline = "No Fit" + show StandardTrimmedMidline = "Standard/Trimmed" + show StandardPointedMidline = "Standard/Pointed" + show StandardSerifedMidline = "Standard/Serifed" + show HighTrimmedMidline = "High/Trimmed" + show HighPointedMidline = "High/Pointed" + show HighSerifedMidline = "High/Serifed" + show ConstantTrimmedMidline = "Constant/Trimmed" + show ConstantPointedMidline = "Constant/Pointed" + show ConstantSerifedMidline = "Constant/Serifed" + show LowTrimmedMidline = "Low/Trimmed" + show LowPointedMidline = "Low/Pointed" + show LowSerifedMidline = "Low/Serifed" + +instance Enum BMidline + where + fromEnum AnyMidline = 0 + fromEnum NoFitMidline = 1 + fromEnum StandardTrimmedMidline = 2 + fromEnum StandardPointedMidline = 3 + fromEnum StandardSerifedMidline = 4 + fromEnum HighTrimmedMidline = 5 + fromEnum HighPointedMidline = 6 + fromEnum HighSerifedMidline = 7 + fromEnum ConstantTrimmedMidline = 8 + fromEnum ConstantPointedMidline = 9 + fromEnum ConstantSerifedMidline = 10 + fromEnum LowTrimmedMidline = 11 + fromEnum LowPointedMidline = 12 + fromEnum LowSerifedMidline = 13 + toEnum 0 = AnyMidline + toEnum 1 = NoFitMidline + toEnum 2 = StandardTrimmedMidline + toEnum 3 = StandardPointedMidline + toEnum 4 = StandardSerifedMidline + toEnum 5 = HighTrimmedMidline + toEnum 6 = HighPointedMidline + toEnum 7 = HighSerifedMidline + toEnum 8 = ConstantTrimmedMidline + toEnum 9 = ConstantPointedMidline + toEnum 10 = ConstantSerifedMidline + toEnum 11 = LowTrimmedMidline + toEnum 12 = LowPointedMidline + toEnum 13 = LowSerifedMidline + toEnum _ = error "Unknown midline" + +data BXHeight + = AnyXHeight + | NoFitXHeight + | ConstantSmallXHeight + | ConstantStandardXHeight + | ConstantLargeXHeight + | DuckingSmallXHeight + | DuckingStandardXHeight + | DuckingLargeXHeight + deriving Eq + +instance Show BXHeight + where + show AnyXHeight = "Any" + show NoFitXHeight = "No Fit" + show ConstantSmallXHeight = "Constant/Small" + show ConstantStandardXHeight = "Constant/Standard" + show ConstantLargeXHeight = "Constant/Large" + show DuckingSmallXHeight = "Ducking/Small" + show DuckingStandardXHeight = "Ducking/Standard" + show DuckingLargeXHeight = "Ducking/Large" + +instance Enum BXHeight + where + fromEnum AnyXHeight = 0 + fromEnum NoFitXHeight = 1 + fromEnum ConstantSmallXHeight = 2 + fromEnum ConstantStandardXHeight = 3 + fromEnum ConstantLargeXHeight = 4 + fromEnum DuckingSmallXHeight = 5 + fromEnum DuckingStandardXHeight = 6 + fromEnum DuckingLargeXHeight = 7 + toEnum 0 = AnyXHeight + toEnum 1 = NoFitXHeight + toEnum 2 = ConstantSmallXHeight + toEnum 3 = ConstantStandardXHeight + toEnum 4 = ConstantLargeXHeight + toEnum 5 = DuckingSmallXHeight + toEnum 6 = DuckingStandardXHeight + toEnum 7 = DuckingLargeXHeight + toEnum _ = error "Unknown X height" + +-- * 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) + +-- * 'gasp' table + +-- | Grid-fitting And Scan-conversion Procedure. +data GASPTable = GASPTable + { version :: Word16 -- ^ Version number (set to 0). + , gaspRange :: [GASPRange] -- ^ Sorted by ppem. + } deriving (Eq, Show) + +data GASPRange = GASPRange + { rangeMaxPPEM :: Word16 -- ^ Upper limit of range, in PPEM. + , rangeGaspBehavior :: Word16 -- ^ Flags describing desired rasterizer behavior. + } deriving (Eq, Show) + +data RangeGaspBehavior + = KGASPGridFit -- ^ Use gridfitting. + | KGASPDoGray -- ^ Use grayscale rendering. + deriving (Eq, Show) + +instance Enum RangeGaspBehavior + where + toEnum 1 = KGASPGridFit + toEnum 2 = KGASPDoGray + toEnum _ = error "Unknown range GASP behavior" + fromEnum KGASPGridFit = 1 + fromEnum KGASPDoGray = 2 -- cgit v1.2.3