Added extra Shape features
Getty Ritter
9 years ago
| 1 | 1 | {-# LANGUAGE RecordWildCards #-} |
| 2 | 2 | {-# LANGUAGE BinaryLiterals #-} |
| 3 | {-# LANGUAGE MultiWayIf #-} | |
| 3 | 4 | |
| 4 | 5 | module Graphics.HVIF |
| 5 | 6 | ( |
| 23 | 24 | , PathRef(..) |
| 24 | 25 | , StyleRef(..) |
| 25 | 26 | , ShapeFlags(..) |
| 27 | , Translation(..) | |
| 28 | , LodScale(..) | |
| 26 | 29 | ) where |
| 27 | 30 | |
| 28 | 31 | import Control.Monad (replicateM, when) |
| 118 | 121 | , shapePaths :: Seq PathRef |
| 119 | 122 | , shapeFlags :: ShapeFlags |
| 120 | 123 | , shapeTransform :: Maybe Matrix |
| 124 | , shapeTranslate :: Maybe Translation | |
| 125 | , shapeLodScale :: Maybe LodScale | |
| 126 | , shapeTransList :: Seq Transformer | |
| 121 | 127 | } deriving (Eq, Show) |
| 122 | 128 | |
| 123 | 129 | type Matrix = Seq Float |
| 133 | 139 | , sfTranslation :: Bool |
| 134 | 140 | } deriving (Eq, Show) |
| 135 | 141 | |
| 142 | data Translation = Translation | |
| 143 | { transX :: Float | |
| 144 | , transY :: Float | |
| 145 | } deriving (Eq, Show) | |
| 146 | ||
| 147 | data LodScale = LodScale | |
| 148 | { lsMin :: Float | |
| 149 | , lsMax :: Float | |
| 150 | } deriving (Eq, Show) | |
| 151 | ||
| 152 | data Transformer | |
| 153 | = TransformerAffine Matrix | |
| 154 | | TransformerContour Float Word8 Word8 | |
| 155 | | TransformerPerspective -- Not fully supported, I think? | |
| 156 | | TransformerStroke Float Word8 Word8 Word8 | |
| 157 | deriving (Eq, Show) | |
| 158 | ||
| 136 | 159 | -- Decoding code |
| 137 | 160 | |
| 138 | 161 | getSeveral :: Get a -> Get (Seq a) |
| 144 | 167 | pFile = do |
| 145 | 168 | header <- getByteString 4 |
| 146 | 169 | when (header /= "ncif") $ |
| 147 |
fail "Missing ` |
|
| 170 | fail "Missing `ncif' header" | |
| 148 | 171 | hvifColors <- getSeveral pStyle |
| 149 | 172 | hvifPaths <- getSeveral pPath |
| 150 | 173 | hvifShapes <- getSeveral pShape |
| 161 | 184 | 0x03 -> ColorSolidNoAlpha <$> get <*> get <*> get |
| 162 | 185 | 0x04 -> ColorSolidGray <$> get <*> get |
| 163 | 186 | 0x05 -> ColorSolidGrayNoAlpha <$> get |
| 164 |
_ -> |
|
| 187 | _ -> getWord16be >> fail "invalid" | |
| 165 | 188 | |
| 166 | 189 | pGradient :: Get Gradient |
| 167 | 190 | pGradient = do |
| 278 | 301 | else |
| 279 | 302 | return (fromIntegral b1 - 32.0) |
| 280 | 303 | |
| 304 | ifFlag :: Bool -> Get a -> Get (Maybe a) | |
| 305 | ifFlag True m = Just <$> m | |
| 306 | ifFlag False _ = pure Nothing | |
| 307 | ||
| 281 | 308 | pShape :: Get Shape |
| 282 | 309 | pShape = do |
| 283 | 310 | sType <- getWord8 |
| 286 | 313 | shapeStyle <- StyleRef <$> get |
| 287 | 314 | shapePaths <- getSeveral (PathRef <$> get) |
| 288 | 315 | shapeFlags <- pShapeFlags |
| 289 | shapeTransform <- | |
| 290 | if sfTransform shapeFlags | |
| 291 | then Just <$> pMatrix | |
| 292 | else return Nothing | |
| 316 | shapeTransform <- ifFlag (sfTransform shapeFlags) $ | |
| 317 | pMatrix | |
| 318 | shapeTranslate <- ifFlag (sfTranslation shapeFlags) $ | |
| 319 | Translation <$> pCoord <*> pCoord | |
| 320 | shapeLodScale <- ifFlag (sfLodScale shapeFlags) $ | |
| 321 | pLodScale | |
| 322 | shapeTransList <- getSeveral pTransformer | |
| 293 | 323 | return Shape { .. } |
| 294 | 324 | |
| 295 | 325 | pShapeFlags :: Get ShapeFlags |
| 323 | 353 | then return 0.0 |
| 324 | 354 | else castToFloat val |
| 325 | 355 | |
| 326 | ||
| 327 | 356 | castToFloat :: Word32 -> Get Float |
| 328 | 357 | castToFloat w32 = |
| 329 | 358 | let bs = encode w32 |
| 330 | 359 | in case runGet getFloat32be bs of |
| 331 | 360 | Left err -> fail err |
| 332 | 361 | Right x -> return x |
| 362 | ||
| 363 | pLodScale :: Get LodScale | |
| 364 | pLodScale = do | |
| 365 | minS <- fromIntegral <$> getWord8 | |
| 366 | maxS <- fromIntegral <$> getWord8 | |
| 367 | return LodScale | |
| 368 | { lsMin = minS / 63.75 | |
| 369 | , lsMax = maxS / 63.75 | |
| 370 | } | |
| 371 | ||
| 372 | pTransformer :: Get Transformer | |
| 373 | pTransformer = do | |
| 374 | tType <- getWord8 | |
| 375 | case tType of | |
| 376 | 20 -> TransformerAffine <$> pMatrix | |
| 377 | 21 -> do | |
| 378 | width <- fromIntegral <$> getWord8 | |
| 379 | lineJoin <- getWord8 | |
| 380 | miterLimit <- getWord8 | |
| 381 | return (TransformerContour (width - 128.0) lineJoin miterLimit) | |
| 382 | 22 -> pure TransformerPerspective | |
| 383 | 23 -> do | |
| 384 | width <- fromIntegral <$> getWord8 | |
| 385 | lineOptions <- getWord8 | |
| 386 | miterLimit <- getWord8 | |
| 387 | let lineJoin = lineOptions .&. 15 | |
| 388 | lineCap = lineOptions `shift` 4 | |
| 389 | return (TransformerStroke (width - 128.0) lineJoin lineCap miterLimit) | |
| 390 | _ -> fail ("Unknown transformer type: " ++ show tType) | |