{-# LANGUAGE BangPatterns #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE DisambiguateRecordFields #-} module Verify.Graphics.Vty.Image ( module Verify.Graphics.Vty.Image , module Graphics.Vty.Image ) where import Verify.Graphics.Vty.Attributes import Graphics.Vty.Image import Graphics.Vty.Image.Internal import Verify data UnitImage = UnitImage Char Image instance Arbitrary UnitImage where arbitrary = do SingleColumnChar c <- arbitrary a <- arbitrary return $ UnitImage c (char a c) instance Show UnitImage where show (UnitImage c _) = "UnitImage " ++ show c data DefaultImage = DefaultImage Image instance Show DefaultImage where show (DefaultImage i) = "DefaultImage (" ++ show i ++ ") " ++ show (imageWidth i, imageHeight i) instance Arbitrary DefaultImage where arbitrary = do i <- return $ char defAttr 'X' return $ DefaultImage i data SingleRowSingleAttrImage = SingleRowSingleAttrImage { expectedAttr :: Attr , expectedColumns :: Int , rowImage :: Image } instance Show SingleRowSingleAttrImage where show (SingleRowSingleAttrImage attr columns image) = "SingleRowSingleAttrImage (" ++ show attr ++ ") " ++ show columns ++ " ( " ++ show image ++ " )" newtype WidthResize = WidthResize (Image -> (Image, Int)) instance Arbitrary WidthResize where arbitrary = do WidthResize f <- arbitrary w <- choose (1,64) oneof $ map (return . WidthResize) [ \i -> (i, imageWidth i) , \i -> (resizeWidth w $ fst $ f i, w) , \i -> let i' = fst $ f i in (cropLeft w i', min (imageWidth i') w) , \i -> let i' = fst $ f i in (cropRight w i', min (imageWidth i') w) ] newtype HeightResize = HeightResize (Image -> (Image, Int)) instance Arbitrary HeightResize where arbitrary = do HeightResize f <- arbitrary h <- choose (1,64) oneof $ map (return . HeightResize) [ \i -> (i, imageHeight i) , \i -> (resizeHeight h $ fst $ f i, h) , \i -> let i' = fst $ f i in (cropTop h i', min (imageHeight i') h) , \i -> let i' = fst $ f i in (cropBottom h i', min (imageHeight i') h) ] newtype ImageResize = ImageResize (Image -> (Image, (Int, Int))) instance Arbitrary ImageResize where arbitrary = oneof [ return $! ImageResize $! \i -> (i, (imageWidth i, imageHeight i)) , return $! ImageResize $! \i -> (i, (imageWidth i, imageHeight i)) , return $! ImageResize $! \i -> (i, (imageWidth i, imageHeight i)) , return $! ImageResize $! \i -> (i, (imageWidth i, imageHeight i)) , return $! ImageResize $! \i -> (i, (imageWidth i, imageHeight i)) , return $! ImageResize $! \i -> (i, (imageWidth i, imageHeight i)) , do ImageResize f <- arbitrary WidthResize g <- arbitrary return $! ImageResize $! \i -> let (i0, (_, outHeight)) = f i gI = g i0 in (fst gI, (snd gI, outHeight)) , do ImageResize f <- arbitrary HeightResize g <- arbitrary return $! ImageResize $! \i -> let (i0, (outWidth, _)) = f i gI = g i0 in (fst gI, (outWidth, snd gI)) ] instance Arbitrary SingleRowSingleAttrImage where arbitrary = do -- The text must contain at least one character. Otherwise the -- image simplifies to the IdImage which has a height of 0. If -- this is to represent a single row then the height must be 1 singleColumnRowText <- Verify.resize 16 (listOf1 arbitrary) a <- arbitrary let outImage = horizCat $ [char a c | SingleColumnChar c <- singleColumnRowText] outWidth = length singleColumnRowText return $ SingleRowSingleAttrImage a outWidth outImage data SingleRowTwoAttrImage = SingleRowTwoAttrImage { part0 :: SingleRowSingleAttrImage , part1 :: SingleRowSingleAttrImage , joinImage :: Image } deriving Show instance Arbitrary SingleRowTwoAttrImage where arbitrary = do p0 <- arbitrary p1 <- arbitrary return $ SingleRowTwoAttrImage p0 p1 (rowImage p0 <|> rowImage p1) data SingleAttrSingleSpanStack = SingleAttrSingleSpanStack { stackImage :: Image , stackSourceImages :: [SingleRowSingleAttrImage] , stackWidth :: Int , stackHeight :: Int } deriving Show instance Arbitrary SingleAttrSingleSpanStack where arbitrary = do imageList <- Verify.resize 16 (listOf1 arbitrary) return $ mkSingleAttrSingleSpanStack imageList shrink s = do imageList <- shrink $ stackSourceImages s if null imageList then [] else return $ mkSingleAttrSingleSpanStack imageList mkSingleAttrSingleSpanStack imageList = let image = vertCat [ i | SingleRowSingleAttrImage { rowImage = i } <- imageList ] in SingleAttrSingleSpanStack image imageList (maximum $ map expectedColumns imageList) (toEnum $ length imageList) instance Arbitrary Image where arbitrary = oneof [ return EmptyImage , do SingleAttrSingleSpanStack {stackImage} <- Verify.resize 8 arbitrary ImageResize f <- Verify.resize 2 arbitrary return $! fst $! f stackImage , do SingleAttrSingleSpanStack {stackImage} <- Verify.resize 8 arbitrary ImageResize f <- Verify.resize 2 arbitrary return $! fst $! f stackImage , do i0 <- arbitrary i1 <- arbitrary let i = i0 <|> i1 ImageResize f <- Verify.resize 2 arbitrary return $! fst $! f i , do i0 <- arbitrary i1 <- arbitrary let i = i0 <-> i1 ImageResize f <- Verify.resize 2 arbitrary return $! fst $! f i ] {- shrink i@(HorizJoin {partLeft, partRight}) = do let !i_alt = backgroundFill (imageWidth i) (imageHeight i) !partLeft' <- shrink partLeft !partRight' <- shrink partRight [i_alt, partLeft' <|> partRight'] shrink i@(VertJoin {partTop, partBottom}) = do let !i_alt = backgroundFill (imageWidth i) (imageHeight i) !partTop' <- shrink partTop !partBottom' <- shrink partBottom [i_alt, partTop' <-> partBottom'] shrink i@(CropRight {croppedImage, outputWidth}) = do let !i_alt = backgroundFill (imageWidth i) (imageHeight i) [i_alt, croppedImage] shrink i@(CropLeft {croppedImage, leftSkip, outputWidth}) = do let !i_alt = backgroundFill (imageWidth i) (imageHeight i) [i_alt, croppedImage] shrink i@(CropBottom {croppedImage, outputHeight}) = do let !i_alt = backgroundFill (imageWidth i) (imageHeight i) [i_alt, croppedImage] shrink i@(CropTop {croppedImage, topSkip, outputHeight}) = do let !i_alt = backgroundFill (imageWidth i) (imageHeight i) [i_alt, croppedImage] shrink i = [emptyImage, backgroundFill (imageWidth i) (imageHeight i)] -} data CropOperation = CropFromLeft | CropFromRight | CropFromTop | CropFromBottom deriving (Eq, Show) instance Arbitrary CropOperation where arbitrary = oneof $ map return [CropFromLeft, CropFromRight, CropFromTop, CropFromBottom] data Translation = Translation Image (Int, Int) Image deriving (Eq, Show) instance Arbitrary Translation where arbitrary = do i <- arbitrary x <- arbitrary `suchThat` (> 0) y <- arbitrary `suchThat` (> 0) let i' = translate x y i return $ Translation i (x,y) i'