packages feed

comic 0 → 0.0.1

raw patch · 5 files changed

+331/−31 lines, 5 filesdep +deepseqdep +hashabledep +hashable-orphansdep ~aesondep ~basedep ~textPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: deepseq, hashable, hashable-orphans, lens, sorted-list, time, uuid

Dependency ranges changed: aeson, base, text

API changes (from Hackage documentation)

- Data.Comic: instance Data.Aeson.Types.FromJSON.FromJSON Data.Comic.Position
- Data.Comic: instance Data.Aeson.Types.ToJSON.ToJSON Data.Comic.Position
- Data.Comic: instance GHC.Classes.Eq Data.Comic.Font
- Data.Comic: instance GHC.Classes.Eq Data.Comic.Position
- Data.Comic: instance GHC.Classes.Ord Data.Comic.Font
- Data.Comic: instance GHC.Classes.Ord Data.Comic.Position
- Data.Comic: instance GHC.Show.Show Data.Comic.Font
- Data.Comic: instance GHC.Show.Show Data.Comic.Position
+ Data.Comic: [_pX] :: Position -> {-# UNPACK #-} !Int
+ Data.Comic: [_pY] :: Position -> {-# UNPACK #-} !Int
+ Data.Comic.Flip: Box :: {-# UNPACK #-} !RelPosition -> {-# UNPACK #-} !RelPosition -> Box
+ Data.Comic.Flip: FSBackground :: {-# UNPACK #-} !OnScreen -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !ImageName -> FrameSplice
+ Data.Comic.Flip: FSText :: {-# UNPACK #-} !OnScreen -> {-# UNPACK #-} !Box -> {-# UNPACK #-} !Text -> {-# UNPACK #-} !Font -> !TextType -> !TextLayout -> FrameSplice
+ Data.Comic.Flip: Font :: {-# UNPACK #-} !FontName -> {-# UNPACK #-} !FontSize -> {-# UNPACK #-} !RGBA -> Font
+ Data.Comic.Flip: HACenter :: HAlignment
+ Data.Comic.Flip: HALeft :: HAlignment
+ Data.Comic.Flip: HARight :: HAlignment
+ Data.Comic.Flip: OnScreen :: {-# UNPACK #-} !StartTime -> {-# UNPACK #-} !EndTime -> OnScreen
+ Data.Comic.Flip: RPos :: {-# UNPACK #-} !Float -> {-# UNPACK #-} !Float -> RelPosition
+ Data.Comic.Flip: ScheduledSegment :: {-# UNPACK #-} !Segment -> {-# UNPACK #-} !UUID -> !DiffTime -> ScheduledSegment
+ Data.Comic.Flip: Segment :: !DiffTime -> SortedList FrameSplice -> Segment
+ Data.Comic.Flip: TextLayout :: !HAlignment -> !VAlignment -> !Bool -> TextLayout
+ Data.Comic.Flip: TxtBreaking :: TextType
+ Data.Comic.Flip: TxtScroll :: TextType
+ Data.Comic.Flip: TxtSpeech :: TextType
+ Data.Comic.Flip: TxtStatic :: TextType
+ Data.Comic.Flip: VABottom :: VAlignment
+ Data.Comic.Flip: VACenter :: VAlignment
+ Data.Comic.Flip: VATop :: VAlignment
+ Data.Comic.Flip: [_bBr] :: Box -> {-# UNPACK #-} !RelPosition
+ Data.Comic.Flip: [_bTl] :: Box -> {-# UNPACK #-} !RelPosition
+ Data.Comic.Flip: [_fsBackground] :: FrameSplice -> {-# UNPACK #-} !ImageName
+ Data.Comic.Flip: [_fsDepth] :: FrameSplice -> {-# UNPACK #-} !Int
+ Data.Comic.Flip: [_fsFont] :: FrameSplice -> {-# UNPACK #-} !Font
+ Data.Comic.Flip: [_fsTextLayout] :: FrameSplice -> !TextLayout
+ Data.Comic.Flip: [_fsTxtType] :: FrameSplice -> !TextType
+ Data.Comic.Flip: [_fsTxt] :: FrameSplice -> {-# UNPACK #-} !Text
+ Data.Comic.Flip: [_fsWhen] :: FrameSplice -> {-# UNPACK #-} !OnScreen
+ Data.Comic.Flip: [_fsWhere] :: FrameSplice -> {-# UNPACK #-} !Box
+ Data.Comic.Flip: [_osEnd] :: OnScreen -> {-# UNPACK #-} !EndTime
+ Data.Comic.Flip: [_osStart] :: OnScreen -> {-# UNPACK #-} !StartTime
+ Data.Comic.Flip: [_rX] :: RelPosition -> {-# UNPACK #-} !Float
+ Data.Comic.Flip: [_rY] :: RelPosition -> {-# UNPACK #-} !Float
+ Data.Comic.Flip: [_sDuration] :: Segment -> !DiffTime
+ Data.Comic.Flip: [_sSplice] :: Segment -> SortedList FrameSplice
+ Data.Comic.Flip: [_ssPlayTill] :: ScheduledSegment -> !DiffTime
+ Data.Comic.Flip: [_ssSegID] :: ScheduledSegment -> {-# UNPACK #-} !UUID
+ Data.Comic.Flip: [_ssSegment] :: ScheduledSegment -> {-# UNPACK #-} !Segment
+ Data.Comic.Flip: [_tlHorizontal] :: TextLayout -> !HAlignment
+ Data.Comic.Flip: [_tlShrink] :: TextLayout -> !Bool
+ Data.Comic.Flip: [_tlVertical] :: TextLayout -> !VAlignment
+ Data.Comic.Flip: blackRGBA :: RGBA
+ Data.Comic.Flip: data Box
+ Data.Comic.Flip: data Font
+ Data.Comic.Flip: data FrameSplice
+ Data.Comic.Flip: data HAlignment
+ Data.Comic.Flip: data OnScreen
+ Data.Comic.Flip: data RelPosition
+ Data.Comic.Flip: data ScheduledSegment
+ Data.Comic.Flip: data Segment
+ Data.Comic.Flip: data TextLayout
+ Data.Comic.Flip: data TextType
+ Data.Comic.Flip: data VAlignment
+ Data.Comic.Flip: fsBackground :: Traversal' FrameSplice ImageName
+ Data.Comic.Flip: fsDepth :: Traversal' FrameSplice Int
+ Data.Comic.Flip: fsFont :: Traversal' FrameSplice Font
+ Data.Comic.Flip: fsTextLayout :: Traversal' FrameSplice TextLayout
+ Data.Comic.Flip: fsTxt :: Traversal' FrameSplice Text
+ Data.Comic.Flip: fsTxtType :: Traversal' FrameSplice TextType
+ Data.Comic.Flip: fsWhen :: Lens' FrameSplice OnScreen
+ Data.Comic.Flip: fsWhere :: Traversal' FrameSplice Box
+ Data.Comic.Flip: instance Control.DeepSeq.NFData Data.Comic.Flip.Box
+ Data.Comic.Flip: instance Control.DeepSeq.NFData Data.Comic.Flip.FrameSplice
+ Data.Comic.Flip: instance Control.DeepSeq.NFData Data.Comic.Flip.HAlignment
+ Data.Comic.Flip: instance Control.DeepSeq.NFData Data.Comic.Flip.OnScreen
+ Data.Comic.Flip: instance Control.DeepSeq.NFData Data.Comic.Flip.ScheduledSegment
+ Data.Comic.Flip: instance Control.DeepSeq.NFData Data.Comic.Flip.Segment
+ Data.Comic.Flip: instance Control.DeepSeq.NFData Data.Comic.Flip.TextLayout
+ Data.Comic.Flip: instance Control.DeepSeq.NFData Data.Comic.Flip.TextType
+ Data.Comic.Flip: instance Control.DeepSeq.NFData Data.Comic.Flip.VAlignment
+ Data.Comic.Flip: instance Data.Aeson.Types.FromJSON.FromJSON Data.Comic.Flip.FrameSplice
+ Data.Comic.Flip: instance Data.Aeson.Types.FromJSON.FromJSON Data.Comic.Flip.HAlignment
+ Data.Comic.Flip: instance Data.Aeson.Types.FromJSON.FromJSON Data.Comic.Flip.ScheduledSegment
+ Data.Comic.Flip: instance Data.Aeson.Types.FromJSON.FromJSON Data.Comic.Flip.Segment
+ Data.Comic.Flip: instance Data.Aeson.Types.FromJSON.FromJSON Data.Comic.Flip.TextType
+ Data.Comic.Flip: instance Data.Aeson.Types.FromJSON.FromJSON Data.Comic.Flip.VAlignment
+ Data.Comic.Flip: instance Data.Aeson.Types.ToJSON.ToJSON Data.Comic.Flip.FrameSplice
+ Data.Comic.Flip: instance Data.Aeson.Types.ToJSON.ToJSON Data.Comic.Flip.HAlignment
+ Data.Comic.Flip: instance Data.Aeson.Types.ToJSON.ToJSON Data.Comic.Flip.ScheduledSegment
+ Data.Comic.Flip: instance Data.Aeson.Types.ToJSON.ToJSON Data.Comic.Flip.Segment
+ Data.Comic.Flip: instance Data.Aeson.Types.ToJSON.ToJSON Data.Comic.Flip.TextType
+ Data.Comic.Flip: instance Data.Aeson.Types.ToJSON.ToJSON Data.Comic.Flip.VAlignment
+ Data.Comic.Flip: instance Data.Hashable.Class.Hashable Data.Comic.Flip.Box
+ Data.Comic.Flip: instance Data.Hashable.Class.Hashable Data.Comic.Flip.FrameSplice
+ Data.Comic.Flip: instance Data.Hashable.Class.Hashable Data.Comic.Flip.HAlignment
+ Data.Comic.Flip: instance Data.Hashable.Class.Hashable Data.Comic.Flip.OnScreen
+ Data.Comic.Flip: instance Data.Hashable.Class.Hashable Data.Comic.Flip.Segment
+ Data.Comic.Flip: instance Data.Hashable.Class.Hashable Data.Comic.Flip.TextLayout
+ Data.Comic.Flip: instance Data.Hashable.Class.Hashable Data.Comic.Flip.TextType
+ Data.Comic.Flip: instance Data.Hashable.Class.Hashable Data.Comic.Flip.VAlignment
+ Data.Comic.Flip: instance GHC.Base.Monoid Data.Comic.Flip.Segment
+ Data.Comic.Flip: instance GHC.Base.Semigroup Data.Comic.Flip.Segment
+ Data.Comic.Flip: instance GHC.Classes.Eq Data.Comic.Flip.Box
+ Data.Comic.Flip: instance GHC.Classes.Eq Data.Comic.Flip.FrameSplice
+ Data.Comic.Flip: instance GHC.Classes.Eq Data.Comic.Flip.HAlignment
+ Data.Comic.Flip: instance GHC.Classes.Eq Data.Comic.Flip.OnScreen
+ Data.Comic.Flip: instance GHC.Classes.Eq Data.Comic.Flip.ScheduledSegment
+ Data.Comic.Flip: instance GHC.Classes.Eq Data.Comic.Flip.Segment
+ Data.Comic.Flip: instance GHC.Classes.Eq Data.Comic.Flip.TextLayout
+ Data.Comic.Flip: instance GHC.Classes.Eq Data.Comic.Flip.TextType
+ Data.Comic.Flip: instance GHC.Classes.Eq Data.Comic.Flip.VAlignment
+ Data.Comic.Flip: instance GHC.Classes.Ord Data.Comic.Flip.Box
+ Data.Comic.Flip: instance GHC.Classes.Ord Data.Comic.Flip.FrameSplice
+ Data.Comic.Flip: instance GHC.Classes.Ord Data.Comic.Flip.HAlignment
+ Data.Comic.Flip: instance GHC.Classes.Ord Data.Comic.Flip.OnScreen
+ Data.Comic.Flip: instance GHC.Classes.Ord Data.Comic.Flip.ScheduledSegment
+ Data.Comic.Flip: instance GHC.Classes.Ord Data.Comic.Flip.Segment
+ Data.Comic.Flip: instance GHC.Classes.Ord Data.Comic.Flip.TextLayout
+ Data.Comic.Flip: instance GHC.Classes.Ord Data.Comic.Flip.TextType
+ Data.Comic.Flip: instance GHC.Classes.Ord Data.Comic.Flip.VAlignment
+ Data.Comic.Flip: instance GHC.Enum.Enum Data.Comic.Flip.HAlignment
+ Data.Comic.Flip: instance GHC.Enum.Enum Data.Comic.Flip.TextType
+ Data.Comic.Flip: instance GHC.Enum.Enum Data.Comic.Flip.VAlignment
+ Data.Comic.Flip: instance GHC.Generics.Generic Data.Comic.Flip.Box
+ Data.Comic.Flip: instance GHC.Generics.Generic Data.Comic.Flip.FrameSplice
+ Data.Comic.Flip: instance GHC.Generics.Generic Data.Comic.Flip.HAlignment
+ Data.Comic.Flip: instance GHC.Generics.Generic Data.Comic.Flip.OnScreen
+ Data.Comic.Flip: instance GHC.Generics.Generic Data.Comic.Flip.ScheduledSegment
+ Data.Comic.Flip: instance GHC.Generics.Generic Data.Comic.Flip.Segment
+ Data.Comic.Flip: instance GHC.Generics.Generic Data.Comic.Flip.TextLayout
+ Data.Comic.Flip: instance GHC.Generics.Generic Data.Comic.Flip.TextType
+ Data.Comic.Flip: instance GHC.Generics.Generic Data.Comic.Flip.VAlignment
+ Data.Comic.Flip: instance GHC.Read.Read Data.Comic.Flip.Box
+ Data.Comic.Flip: instance GHC.Read.Read Data.Comic.Flip.FrameSplice
+ Data.Comic.Flip: instance GHC.Read.Read Data.Comic.Flip.HAlignment
+ Data.Comic.Flip: instance GHC.Read.Read Data.Comic.Flip.OnScreen
+ Data.Comic.Flip: instance GHC.Read.Read Data.Comic.Flip.TextLayout
+ Data.Comic.Flip: instance GHC.Read.Read Data.Comic.Flip.TextType
+ Data.Comic.Flip: instance GHC.Read.Read Data.Comic.Flip.VAlignment
+ Data.Comic.Flip: instance GHC.Show.Show Data.Comic.Flip.Box
+ Data.Comic.Flip: instance GHC.Show.Show Data.Comic.Flip.FrameSplice
+ Data.Comic.Flip: instance GHC.Show.Show Data.Comic.Flip.HAlignment
+ Data.Comic.Flip: instance GHC.Show.Show Data.Comic.Flip.OnScreen
+ Data.Comic.Flip: instance GHC.Show.Show Data.Comic.Flip.ScheduledSegment
+ Data.Comic.Flip: instance GHC.Show.Show Data.Comic.Flip.Segment
+ Data.Comic.Flip: instance GHC.Show.Show Data.Comic.Flip.TextLayout
+ Data.Comic.Flip: instance GHC.Show.Show Data.Comic.Flip.TextType
+ Data.Comic.Flip: instance GHC.Show.Show Data.Comic.Flip.VAlignment
+ Data.Comic.Flip: osEnd :: Lens' OnScreen EndTime
+ Data.Comic.Flip: osStart :: Lens' OnScreen StartTime
+ Data.Comic.Flip: sDuration :: Lens' Segment DiffTime
+ Data.Comic.Flip: sSplice :: Lens' Segment (SortedList FrameSplice)
+ Data.Comic.Flip: tlHorizontal :: Lens' TextLayout HAlignment
+ Data.Comic.Flip: tlShrink :: Lens' TextLayout Bool
+ Data.Comic.Flip: tlVertical :: Lens' TextLayout VAlignment
+ Data.Comic.Flip: whiteRGBA :: RGBA
+ Data.Comic.Types: Font :: {-# UNPACK #-} !FontName -> {-# UNPACK #-} !FontSize -> {-# UNPACK #-} !RGBA -> Font
+ Data.Comic.Types: Pos :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Position
+ Data.Comic.Types: RPos :: {-# UNPACK #-} !Float -> {-# UNPACK #-} !Float -> RelPosition
+ Data.Comic.Types: [_pX] :: Position -> {-# UNPACK #-} !Int
+ Data.Comic.Types: [_pY] :: Position -> {-# UNPACK #-} !Int
+ Data.Comic.Types: [_rX] :: RelPosition -> {-# UNPACK #-} !Float
+ Data.Comic.Types: [_rY] :: RelPosition -> {-# UNPACK #-} !Float
+ Data.Comic.Types: blackRGBA :: RGBA
+ Data.Comic.Types: data Font
+ Data.Comic.Types: data Position
+ Data.Comic.Types: data RelPosition
+ Data.Comic.Types: instance Control.DeepSeq.NFData Data.Comic.Types.Font
+ Data.Comic.Types: instance Control.DeepSeq.NFData Data.Comic.Types.Position
+ Data.Comic.Types: instance Control.DeepSeq.NFData Data.Comic.Types.RelPosition
+ Data.Comic.Types: instance Data.Aeson.Types.FromJSON.FromJSON Data.Comic.Types.Position
+ Data.Comic.Types: instance Data.Aeson.Types.FromJSON.FromJSON Data.Comic.Types.RelPosition
+ Data.Comic.Types: instance Data.Aeson.Types.ToJSON.ToJSON Data.Comic.Types.Position
+ Data.Comic.Types: instance Data.Aeson.Types.ToJSON.ToJSON Data.Comic.Types.RelPosition
+ Data.Comic.Types: instance Data.Hashable.Class.Hashable Data.Comic.Types.Font
+ Data.Comic.Types: instance Data.Hashable.Class.Hashable Data.Comic.Types.Position
+ Data.Comic.Types: instance Data.Hashable.Class.Hashable Data.Comic.Types.RelPosition
+ Data.Comic.Types: instance GHC.Classes.Eq Data.Comic.Types.Font
+ Data.Comic.Types: instance GHC.Classes.Eq Data.Comic.Types.Position
+ Data.Comic.Types: instance GHC.Classes.Eq Data.Comic.Types.RelPosition
+ Data.Comic.Types: instance GHC.Classes.Ord Data.Comic.Types.Font
+ Data.Comic.Types: instance GHC.Classes.Ord Data.Comic.Types.Position
+ Data.Comic.Types: instance GHC.Classes.Ord Data.Comic.Types.RelPosition
+ Data.Comic.Types: instance GHC.Generics.Generic Data.Comic.Types.Font
+ Data.Comic.Types: instance GHC.Generics.Generic Data.Comic.Types.Position
+ Data.Comic.Types: instance GHC.Generics.Generic Data.Comic.Types.RelPosition
+ Data.Comic.Types: instance GHC.Read.Read Data.Comic.Types.Font
+ Data.Comic.Types: instance GHC.Read.Read Data.Comic.Types.Position
+ Data.Comic.Types: instance GHC.Read.Read Data.Comic.Types.RelPosition
+ Data.Comic.Types: instance GHC.Show.Show Data.Comic.Types.Font
+ Data.Comic.Types: instance GHC.Show.Show Data.Comic.Types.Position
+ Data.Comic.Types: instance GHC.Show.Show Data.Comic.Types.RelPosition
+ Data.Comic.Types: type FontName = Text
+ Data.Comic.Types: type FontSize = Int
+ Data.Comic.Types: type HintSize = Int
+ Data.Comic.Types: type ImageName = Text
+ Data.Comic.Types: type RGBA = (Word8, Word8, Word8, Word8)
+ Data.Comic.Types: whiteRGBA :: RGBA
- Data.Comic: Font :: FontName -> FontSize -> RGBA -> Font
+ Data.Comic: Font :: {-# UNPACK #-} !FontName -> {-# UNPACK #-} !FontSize -> {-# UNPACK #-} !RGBA -> Font
- Data.Comic: Pos :: Int -> Int -> Position
+ Data.Comic: Pos :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Position
- Data.Comic: type RGBA = (Float, Float, Float, Float)
+ Data.Comic: type RGBA = (Word8, Word8, Word8, Word8)

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ # Revision history for comic -## 0  -- YYYY-mm-dd+## 0  -- 2019-04-30++* Added Semigroup instance for Segment to satisfy new 'base' requirements.++## 0  -- 2017-03-23  * First version. Released on an unsuspecting world.
comic.cabal view
@@ -1,7 +1,6 @@ name:                comic-version:             0+version:             0.0.1 synopsis:            A format for describing comics.--- description:          homepage:            https://oss.xkcd.com/ license:             BSD3 license-file:        LICENSE@@ -16,13 +15,22 @@ source-repository head   type: git   location: https://code.xkrd.net/xkcd/comic.git-                     + library   hs-source-dirs:      src   default-language:    Haskell2010   exposed-modules:           Data.Comic+        , Data.Comic.Types+        , Data.Comic.Flip   build-depends:-        base >=4.9 && <4.11+        base >=4.9 && <4.13       , text >= 1.2 && < 1.3-      , aeson >= 1.1 && < 1.2+      , aeson == 1.4.*+      , time >= 1.6 && < 1.10+      , sorted-list >= 0.2 && < 0.3+      , hashable >= 1.2 && < 1.3+      , hashable-orphans == 0+      , uuid > 1.3 && < 1.4+      , deepseq >= 1.4 && < 1.5+      , lens > 4.15 && < 4.18
src/Data/Comic.hs view
@@ -12,30 +12,7 @@ import qualified Data.Aeson as JS import qualified Data.Aeson.Types as JS import Data.Aeson (ToJSON(..), FromJSON(..), (.:))--type ImageName = Text-type FontName = Text-type FontSize = Int-type HintSize = Int-type RGBA = (Float, Float, Float, Float)--blackRGBA :: RGBA-blackRGBA = (0, 0, 0, 1)--data Font =-    Font FontName FontSize RGBA-  deriving (Show, Eq, Ord)--data Position =-    Pos Int Int-  deriving (Show, Eq, Ord)--instance ToJSON Position where-  toJSON (Pos x y) = JS.object [("x", toJSON x), ("y", toJSON y)]--instance FromJSON Position where-  parseJSON (JS.Object v) = Pos <$> v .: "x" <*> v .: "y"-  parseJSON _ = mzero+import Data.Comic.Types  data Hint =     ZoneHint {@@ -90,7 +67,7 @@             , ("txt", toJSON t) ]  json2text :: JS.Value -> JS.Parser ((Position, Position), Font, Text)-json2text (JS.Object v1) = +json2text (JS.Object v1) =         (\tl br fn fs c t -> ((tl, br), Font fn fs c, t)) <$>           v1 .: "tl" <*> v1 .: "br" <*>           v1 .: "font" <*> v1 .: "size" <*> v1 .: "color" <*>
+ src/Data/Comic/Flip.hs view
@@ -0,0 +1,247 @@+{-# LANGUAGE OverloadedStrings, DeriveGeneric, DeriveAnyClass, TemplateHaskell #-}+module Data.Comic.Flip (+   Segment(..), ScheduledSegment(..)+ , FrameSplice(..), TextType(..)+ , OnScreen(..), Box(..)+ , RelPosition(..), Font(..), blackRGBA, whiteRGBA+ , TextLayout(..), HAlignment(..), VAlignment(..)+ , osStart, osEnd+ , fsWhen, fsDepth, fsBackground, fsFont, fsTxt, fsTxtType, fsTextLayout, fsWhere+ , tlHorizontal, tlVertical, tlShrink+ , sDuration, sSplice+ ) where++import Control.Applicative+import Control.DeepSeq+import Control.Lens+import Control.Monad+import qualified Data.Aeson as JS+import Data.Aeson (ToJSON(..), FromJSON(..), (.:))+import Data.Comic.Types+import Data.Foldable+import Data.Hashable (Hashable(hashWithSalt))+import Data.Hashable.Orphans ()+import Data.SortedList hiding (map)+import qualified Data.SortedList as Sorted+import Data.Text (Text)+import Data.Time+import Data.UUID (UUID)+import GHC.Generics (Generic)++type StartTime = Float+type EndTime = Float++data OnScreen =+    OnScreen+    { _osStart :: {-# UNPACK #-} !StartTime+    , _osEnd :: {-# UNPACK #-} !EndTime+    }+  deriving (Read, Show, Eq, Ord, Generic, NFData)++makeLenses ''OnScreen++instance Hashable OnScreen where+  hashWithSalt s (OnScreen strt end) = hashWithSalt s (strt, end)++data Box =+    Box+    { _bTl :: {-# UNPACK #-} !RelPosition+    , _bBr :: {-# UNPACK #-} !RelPosition+    }+  deriving (Read, Show, Eq, Ord, Generic, NFData)++instance Hashable Box where+  hashWithSalt s (Box tl br) = hashWithSalt s (tl, br)++data HAlignment =+    HALeft+  | HACenter+  | HARight+  deriving (Read, Show, Eq, Ord, Generic, NFData, Enum, Hashable)++instance ToJSON HAlignment where+  toJSON HALeft = JS.String "left"+  toJSON HACenter = JS.String "center"+  toJSON HARight = JS.String "right"++instance FromJSON HAlignment where+  parseJSON (JS.String "left") = pure HALeft+  parseJSON (JS.String "center") = pure HACenter+  parseJSON (JS.String "right") = pure HARight+  parseJSON _ = mzero++data VAlignment =+    VATop+  | VACenter+  | VABottom+  deriving (Read, Show, Eq, Ord, Generic, NFData, Enum, Hashable)++instance ToJSON VAlignment where+  toJSON VATop = JS.String "top"+  toJSON VACenter = JS.String "center"+  toJSON VABottom = JS.String "bottom"++instance FromJSON VAlignment where+  parseJSON (JS.String "top") = pure VATop+  parseJSON (JS.String "center") = pure VACenter+  parseJSON (JS.String "bottom") = pure VABottom+  parseJSON _ = mzero++data TextLayout =+    TextLayout+    { _tlHorizontal :: !HAlignment+    , _tlVertical :: !VAlignment+    , _tlShrink :: !Bool+    }+  deriving (Read, Show, Eq, Ord, Generic, NFData, Hashable)++makeLenses ''TextLayout++data TextType =+    TxtStatic+  | TxtScroll+  | TxtSpeech+  | TxtBreaking+  deriving (Read, Show, Eq, Ord, Generic, NFData, Enum, Hashable)++instance ToJSON TextType where+    toJSON TxtStatic = JS.String "static"+    toJSON TxtScroll = JS.String "scroll"+    toJSON TxtSpeech = JS.String "speech"+    toJSON TxtBreaking = JS.String "breaking"++instance FromJSON TextType where+    parseJSON (JS.String "static") = return TxtStatic+    parseJSON (JS.String "scroll") = return TxtScroll+    parseJSON (JS.String "speech") = return TxtSpeech+    parseJSON (JS.String "breaking") = return TxtBreaking+    parseJSON _ = mzero++data FrameSplice =+    FSBackground+    { _fsWhen :: {-# UNPACK #-} !OnScreen+    , _fsDepth :: {-# UNPACK #-} !Int+    , _fsBackground :: {-# UNPACK #-} !ImageName+    }+  | FSText+    { _fsWhen :: {-# UNPACK #-} !OnScreen+    , _fsWhere :: {-# UNPACK #-} !Box+    , _fsTxt :: {-# UNPACK #-} !Text+    , _fsFont :: {-# UNPACK #-} !Font+    , _fsTxtType :: !TextType+    , _fsTextLayout :: !TextLayout+    }+   deriving (Read, Show, Eq, Ord, Generic, NFData)++makeLenses ''FrameSplice++instance Hashable FrameSplice where+  hashWithSalt s (FSBackground o d i) = hashWithSalt s (o, d, i)+  hashWithSalt s (FSText o w t f tt a) =+    hashWithSalt s (o, w, t, f, tt, a)++instance ToJSON FrameSplice where+    toJSON (FSBackground (OnScreen strt end) d img) =+      JS.object $+        [ ("start", toJSON strt), ("end", toJSON end)+        , ("depth", toJSON d)+        , ("panel", toJSON img)+        ]+    toJSON (FSText (OnScreen strt end) (Box tl br) txt (Font fn fs c) tt (TextLayout h v s)) =+      JS.object $+        [ ("start", toJSON strt), ("end", toJSON end)+        , ("tl", toJSON tl), ("br", toJSON br)+        , ("font", toJSON fn), ("size", toJSON fs), ("color", toJSON c)+        , ("txt", toJSON txt)+        , ("txt_type", toJSON tt)+        , ("align", toJSON h), ("valign", toJSON v), ("shrink_fit", toJSON s)+        ]++instance FromJSON FrameSplice where+    parseJSON (JS.Object v) =+          (FSBackground <$> (OnScreen <$> v .: "start" <*> v .: "end")+                        <*> v .: "depth"+                        <*> v .: "panel")+      <|> (FSText <$> (OnScreen <$> v .: "start" <*> v .: "end")+                  <*> (Box <$> v .: "tl" <*> v .: "br")+                  <*> v .: "txt"+                  <*> (Font <$>  v .: "font" <*> v .: "size" <*> v .: "color")+                  <*> v .: "txt_type"+                  <*> (TextLayout <$> v .: "align" <*> v .: "valign" <*> v .: "shrink_fit"))+    parseJSON _ = mzero++data Segment =+    Segment+    { _sDuration :: !DiffTime+      -- ^ This is how long, ideally, the segment would air for.+    , _sSplice :: SortedList FrameSplice+      -- ^ The actual stage directions for playing the content.+      --   Times are [0, 1] of the Duration.+      --   We keep sorting for a stable Ord instance.+    }+  deriving (Show, Eq, Ord, Generic, NFData)++makeLenses ''Segment++instance Semigroup Segment where+  (<>) a b = mconcat [a, b]++instance Monoid Segment where+  mempty = Segment 0 mempty+  mappend a b = mconcat [a, b]+  mconcat os =+    let totTime = fromRational . toRational  . foldl (\a s -> a + _sDuration s) 0 $ os+     in Segment (fromRational . toRational $ totTime)+                (snd . foldl (\(c, fs) s ->+                   let sdur = fromRational . toRational $ s ^. sDuration+                       timePrev = c+sdur+                       segPercent = sdur / totTime+                    in (timePrev+                       ,fs `mappend` (Sorted.map (\f ->+                          -- We rescale the [0-1] time range into the percent that this+                          -- Segment forms of the overal, and shift it into position.+                          ((f & fsWhen.osStart %~ (\st -> (st*sdur+c)/totTime))+                              & fsWhen.osEnd %~ (\se -> (se*sdur+c)/totTime))) (_sSplice $ s))+                        )) (0, mempty) $ os)++instance Hashable Segment where+  hashWithSalt s (Segment dur spl) =+    hashWithSalt s (dur, spl)++instance ToJSON Segment where+    toJSON (Segment dur splcs) =+      JS.object $+        [ ("duration", toJSON (realToFrac dur::Float))+        , ("splices", toJSON . toList $ splcs)+        ]++instance FromJSON Segment where+    parseJSON (JS.Object v) =+      Segment <$> ((realToFrac::Float -> DiffTime) <$> v .: "duration")+              <*> (toSortedList <$> v .: "splices")+    parseJSON _ = mzero++data ScheduledSegment =+    ScheduledSegment+    { _ssSegment :: {-# UNPACK #-} !Segment+    , _ssSegID :: {-# UNPACK #-} !UUID+    , _ssPlayTill :: !DiffTime+      -- ^ This is how long in the future this segment should end,+      --   from the time it is transmited to the client.+    }+  deriving (Show, Eq, Ord, Generic, NFData)++instance ToJSON ScheduledSegment where+    toJSON (ScheduledSegment seg segid till) =+      JS.object+        [ ("till", toJSON (realToFrac till::Float))+        , ("id", toJSON segid)+        , ("segment", toJSON seg)+        ]++instance FromJSON ScheduledSegment where+    parseJSON (JS.Object v) =+        ScheduledSegment <$> v .: "segment"+                         <*> v .: "id"+                         <*> ((realToFrac::Float -> DiffTime) <$> v .: "till")+    parseJSON _ = mzero
+ src/Data/Comic/Types.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE OverloadedStrings, DeriveGeneric, DeriveAnyClass #-}+module Data.Comic.Types (+   ImageName+ , Font(..), FontName, FontSize, HintSize+ , RGBA, blackRGBA, whiteRGBA+ , Position (..), RelPosition (..)+ ) where++import Control.DeepSeq+import Control.Monad+import qualified Data.Aeson as JS+import Data.Aeson (ToJSON(..), FromJSON(..), (.:))+import Data.Hashable (Hashable(hashWithSalt))+import Data.Text (Text)+import Data.Word+import GHC.Generics (Generic)++type ImageName = Text+type FontName = Text+type FontSize = Int+type HintSize = Int+type RGBA = (Word8, Word8, Word8, Word8)++blackRGBA :: RGBA+blackRGBA = (0, 0, 0, 255)++whiteRGBA :: RGBA+whiteRGBA = (255, 255, 255, 255)++data Font =+    Font {-# UNPACK #-} !FontName {-# UNPACK #-} !FontSize {-# UNPACK #-} !RGBA+  deriving (Read, Show, Eq, Ord, Generic, NFData)++instance Hashable Font where+  hashWithSalt s (Font fn fs rgba) =+    hashWithSalt s (fn, fs, rgba)++data Position =+    Pos { _pX :: {-# UNPACK #-} !Int, _pY :: {-# UNPACK #-} !Int }+  deriving (Read, Show, Eq, Ord, Generic, NFData)++instance Hashable Position where+  hashWithSalt s (Pos x y) = hashWithSalt s (x, y)++instance ToJSON Position where+  toJSON (Pos x y) = JS.object [("x", toJSON x), ("y", toJSON y)]++instance FromJSON Position where+  parseJSON (JS.Object v) = Pos <$> v .: "x" <*> v .: "y"+  parseJSON _ = mzero++data RelPosition =+    RPos { _rX :: {-# UNPACK #-} !Float, _rY :: {-# UNPACK #-} !Float }+  deriving (Read, Show, Eq, Ord, Generic, NFData)++instance Hashable RelPosition where+  hashWithSalt s (RPos x y) = hashWithSalt s (x, y)++instance ToJSON RelPosition where+  toJSON (RPos x y) = JS.object [("x", toJSON x), ("y", toJSON y)]++instance FromJSON RelPosition where+  parseJSON (JS.Object v) = RPos <$> v .: "x" <*> v .: "y"+  parseJSON _ = mzero