diff --git a/src/Graphics/Fountainhead/Dumper.hs b/src/Graphics/Fountainhead/Dumper.hs index 680c0f7..e7c6156 100644 --- a/src/Graphics/Fountainhead/Dumper.hs +++ b/src/Graphics/Fountainhead/Dumper.hs @@ -18,11 +18,13 @@ module Graphics.Fountainhead.Dumper import Data.ByteString (ByteString) import Data.Int (Int64) +import Data.Word (Word16) import qualified Data.IntMap as IntMap import qualified Data.Text.Encoding as Text import qualified Data.Text.Lazy as Text.Lazy import qualified Data.Text.Lazy.Builder as Text.Builder import qualified Data.Text.Lazy.Builder.Int as Text.Builder +import Data.Vector (Vector) import qualified Data.Vector as Vector import Data.Void import GHC.Records (HasField(..)) @@ -42,6 +44,7 @@ import Graphics.Fountainhead.Parser , cmapTableP ) import Data.Foldable (Foldable(..)) +import Data.Maybe (fromMaybe) type ParseErrorOrDump = Either (Megaparsec.ParseErrorBundle ByteString Void) Text.Builder.Builder @@ -128,6 +131,7 @@ dumpCmap CmapTable{..} (CmapFormat2 _) -> "Format 2" (CmapFormat4 CmapFormat4Table{..}) -> let segCount = Vector.length startCode + dumpSegment' = dumpSegment segCount glyphIndexArray in "Format 4 - Segment mapping to delta values\n\ \ Length: 994\n\ \ Version: 0\n\ @@ -140,14 +144,32 @@ dumpCmap CmapTable{..} <> newlineBuilder <> " rangeShift: " <> Text.Builder.decimal (segCount * 2 - fromIntegral searchRange) <> newlineBuilder - <> fold (Vector.izipWith4 (dumpSegment segCount) startCode endCode idDelta idRangeOffset) + <> fold (Vector.izipWith4 (dumpSegmentSummary segCount) startCode endCode idDelta idRangeOffset) + <> " Number of glyphIndex " + <> Text.Builder.decimal (Vector.length glyphIndexArray) <> newlineBuilder + <> fold (Vector.imap dumpGlyphAtIndex glyphIndexArray) + <> fold (Vector.izipWith4 dumpSegment' startCode endCode idDelta idRangeOffset) (CmapFormat6 _) -> "Format 6" (CmapFormat8 _) -> "Format 8" (CmapFormat10 _) -> "Format 10" (CmapFormat12 _) -> "Format 12" (CmapFormat13 _) -> "Format 13" (CmapFormat14 _) -> "Format 14" - dumpSegment segCount index startCode' endCode' idDelta' idRangeOffset' + dumpSegment :: Int -> Vector Word16 -> Int -> Word16 -> Word16 -> Word16 -> Word16 -> Text.Builder.Builder + dumpSegment segCount glyphIndexArray' segmentIndex startCode' endCode' idDelta' idRangeOffset' = + let charRange = [startCode'..endCode'] + dumpSegmentCharIndex' = + dumpSegmentCharIndex segCount glyphIndexArray' segmentIndex idDelta' idRangeOffset' startCode' + in "Segment " <> Text.Builder.decimal segmentIndex <> ":\n" + <> foldMap dumpSegmentCharIndex' charRange + dumpSegmentCharIndex segCount glyphIndexArray' segmentIndex idDelta' idRangeOffset' startCode' charCode = + let calculateGlyphIndex' = + calculateGlyphIndex charCode segmentIndex segCount glyphIndexArray' idRangeOffset' idDelta' startCode' + in " Char 0x" + <> halfPaddedHexadecimal charCode <> " -> Index " + <> Text.Builder.decimal calculateGlyphIndex' + <> newlineBuilder + dumpSegmentSummary segCount index startCode' endCode' idDelta' idRangeOffset' = " Seg " <> justifyNumber 5 index <> " : St = " <> halfPaddedHexadecimal startCode' <> ", En = " <> halfPaddedHexadecimal endCode' @@ -155,9 +177,23 @@ dumpCmap CmapTable{..} <> ", RO = " <> justifyNumber 6 idRangeOffset' <> ", gId# = " <> dumpGlyphId index segCount idRangeOffset' <> newlineBuilder - dumpGlyphId index segCount idRangeOffset' - | idRangeOffset' == 0 = "N/A" - | otherwise = Text.Builder.decimal $ index - segCount + (fromIntegral idRangeOffset' `div` 2) + dumpGlyphId segmentIndex segCount idRangeOffset' + = maybe "N/A" Text.Builder.decimal + $ calculateGlyphId segmentIndex segCount idRangeOffset' + calculateGlyphIndex :: Word16 -> Int -> Int -> Vector Word16 -> Word16 -> Word16 -> Word16 -> Int + calculateGlyphIndex c segmentIndex segCount glyphIndexArray' idRangeOffset' idDelta' startCode' = + let defaultIndex = fromIntegral $ c + idDelta' + addOffset = fromIntegral + . fromMaybe 0 + . (glyphIndexArray' Vector.!?) + . (+ fromIntegral (c - startCode')) + in maybe defaultIndex addOffset + $ calculateGlyphId segmentIndex segCount idRangeOffset' + calculateGlyphId segmentIndex segCount idRangeOffset' + | idRangeOffset' == 0 = Nothing + | otherwise = Just $ segmentIndex - segCount + (fromIntegral idRangeOffset' `div` 2) + dumpGlyphAtIndex index element = " glyphIdArray[" <> Text.Builder.decimal index <> "] = " + <> Text.Builder.decimal element <> newlineBuilder dumpTables :: Megaparsec.State ByteString Void