{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module Graphics.Text.Font.Choose.Value where
import Linear.Matrix (M22)
import Linear.V2 (V2(..))
import Graphics.Text.Font.Choose.CharSet (CharSet, CharSet'(..))
--import FreeType.Core.Base (FT_Face(..))
import Graphics.Text.Font.Choose.LangSet (LangSet, LangSet'(..))
import Graphics.Text.Font.Choose.Range (Range)
import Data.MessagePack (MessagePack(..), Object(..))
import qualified Data.Text as Txt
-- | A dynamic type system for `Pattern`s.
data Value = ValueVoid
| ValueInt Int
| ValueDouble Double
| ValueString String
| ValueBool Bool
| ValueMatrix (M22 Double)
| ValueCharSet CharSet
-- | ValueFTFace FT_Face -- FIXME: Is it worth going through the trouble to bridge this?
| ValueLangSet LangSet
| ValueRange Range deriving (Eq, Show, Ord)
instance MessagePack Value where
toObject ValueVoid = ObjectNil
toObject (ValueInt x) = ObjectInt x
toObject (ValueDouble x) = ObjectDouble x
toObject (ValueString x) = ObjectStr $ Txt.pack x
toObject (ValueBool x) = ObjectBool x
toObject (ValueMatrix (V2 (V2 xx yx) (V2 xy yy))) = toObject [xx, xy, yx, yy]
toObject (ValueCharSet x) = toObject $ CharSet' x
toObject (ValueLangSet x) = toObject $ LangSet' x
toObject (ValueRange x) = toObject x
fromObject ObjectNil = Just ValueVoid
fromObject (ObjectBool x) = Just $ ValueBool x
fromObject (ObjectInt x) = Just $ ValueInt x
fromObject (ObjectFloat x) = Just $ ValueDouble $ realToFrac x
fromObject (ObjectDouble x) = Just $ ValueDouble x
fromObject (ObjectStr x) = Just $ ValueString $ Txt.unpack x
fromObject (ObjectBin _) = Nothing -- Would use for to transfer font faces via underlying bytes.
fromObject msg
| Just charset <- fromObject msg = Just $ ValueCharSet $ unCharSet charset
| Just langset <- fromObject msg = Just $ ValueLangSet $ unLangSet langset
| Just range <- fromObject msg = Just $ ValueRange range
| Just [xx, xy, yx, yy] <- fromObject msg :: Maybe [Double] =
-- [Double] decoding is overly generous, potentially conflicts with above.
Just $ ValueMatrix $ V2 (V2 xx yx) (V2 xy yy)
| otherwise = Nothing
-- | Coerces compiletime types to runtime types.
class ToValue x where
toValue :: x -> Value
fromValue :: Value -> Maybe x
fromValue' :: Value -> x -- throws Result.Error
fromValue' self | Just ret <- fromValue self = ret
fromValue' _ = error "Type mismatch!" -- TODO: Throw something nicer!
instance ToValue () where
toValue () = ValueVoid
fromValue ValueVoid = Just ()
fromValue _ = Nothing
instance ToValue Int where
toValue = ValueInt
fromValue (ValueInt x) = Just x
fromValue _ = Nothing
instance ToValue Double where
toValue = ValueDouble
fromValue (ValueDouble x) = Just x
fromValue _ = Nothing
instance ToValue String where
toValue = ValueString
fromValue (ValueString x) = Just x
fromValue _ = Nothing
instance ToValue Bool where
toValue = ValueBool
fromValue (ValueBool x) = Just x
fromValue _ = Nothing
instance ToValue (M22 Double) where
toValue = ValueMatrix
fromValue (ValueMatrix x) = Just x
fromValue _ = Nothing
instance ToValue CharSet' where
toValue = ValueCharSet . unCharSet
fromValue (ValueCharSet x) = Just $ CharSet' x
fromValue _ = Nothing
--instance ToValue FT_Face where
-- toValue = ValueFTFace
-- fromValue (ValueFTFace x) = Just x
-- fromValue _ = Nothing
instance ToValue LangSet' where
toValue = ValueLangSet . unLangSet
fromValue (ValueLangSet x) = Just $ LangSet' x
fromValue _ = Nothing
instance ToValue Range where
toValue = ValueRange
fromValue (ValueRange x) = Just x
fromValue _ = Nothing
instance ToValue Value where
toValue = id
fromValue = Just