-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A pure haskell drawing engine. -- -- -- Rasterific is a vector drawing library (a rasterizer) implemented in -- pure haskell @package Rasterific @version 0.2 -- | This module provide some helpers in order to perform basic geometric -- transformation on the drawable primitives. -- -- You can combine the transformation is mappend or the -- `(<>)` operator from Data.Monoid . module Graphics.Rasterific.Transformations -- | Represent a 3*3 matrix for homogenous coordinates. -- --
-- | A C E | -- | B D F | -- | 0 0 1 | --data Transformation Transformation :: {-# UNPACK #-} !Float -> {-# UNPACK #-} !Float -> {-# UNPACK #-} !Float -> {-# UNPACK #-} !Float -> {-# UNPACK #-} !Float -> {-# UNPACK #-} !Float -> Transformation _transformA :: Transformation -> {-# UNPACK #-} !Float _transformC :: Transformation -> {-# UNPACK #-} !Float -- | X translation _transformE :: Transformation -> {-# UNPACK #-} !Float _transformB :: Transformation -> {-# UNPACK #-} !Float _transformD :: Transformation -> {-# UNPACK #-} !Float -- | Y translation _transformF :: Transformation -> {-# UNPACK #-} !Float -- | Effectively transform a point given a transformation. applyTransformation :: Transformation -> Point -> Point -- | Perform a translation of the given primitives. -- --
-- fill . transform (applyTransformation $ translate (V2 100 100)) -- $ rectangle (V2 40 40) 40 40 ---- translate :: Vector -> Transformation -- | Perform a scaling of the given primitives. -- --
-- fill . transform (applyTransformation $ scale 2 2) -- $ rectangle (V2 40 40) 40 40 ---- scale :: Float -> Float -> Transformation -- | Create a transformation representing a rotation on the plane. -- --
-- fill . transform (applyTransformation $ rotate 0.2) -- $ rectangle (V2 40 40) 120 120 ---- rotate :: Float -> Transformation -- | Create a transformation representing a rotation on the plane. The -- rotation center is given in parameter -- --
-- fill . transform (applyTransformation $ rotateCenter 0.2 (V2 200 200)) -- $ rectangle (V2 40 40) 120 120 ---- rotateCenter :: Float -> Point -> Transformation -- | Inverse a transformation (if possible) inverseTransformation :: Transformation -> Transformation instance Eq Transformation instance Show Transformation instance Monoid Transformation -- | Module describing the various filling method of the geometric -- primitives. -- -- All points coordinate given in this module are expressed final image -- pixel coordinates. module Graphics.Rasterific.Texture -- | A texture is just a function which given pixel coordinate give back a -- pixel. The float coordinate type allow for transformations to happen -- in the pixel space. type Texture px = SamplerRepeat -> Float -> Float -> px -- | A gradient definition is just a list of stop and pixel values. For -- instance for a simple gradient of black to white, the finition would -- be : -- --
-- [(0, PixelRGBA8 0 0 0 255), (1, PixelRGBA8 255 255 255 255)] ---- -- the first stop value must be zero and the last, one. type Gradient px = [(Float, px)] -- | Set the repeat pattern of the texture (if any). With padding: -- --
-- withTexture (sampledImageTexture textureImage) $ -- fill $ rectangle (V2 0 0) 200 200 ---- -- -- With repeat: -- --
-- withTexture (withSampler SamplerRepeat $ -- sampledImageTexture textureImage) $ -- fill $ rectangle (V2 0 0) 200 200 ---- -- -- With reflect: -- --
-- withTexture (withSampler SamplerReflect $ -- sampledImageTexture textureImage) $ -- fill $ rectangle (V2 0 0) 200 200 ---- withSampler :: SamplerRepeat -> Texture px -> Texture px -- | The uniform texture is the simplest texture of all: an uniform color. uniformTexture :: px -> Texture px -- | Linear gradient texture. -- --
-- let gradDef = [(0, PixelRGBA8 0 0x86 0xc1 255) -- ,(0.5, PixelRGBA8 0xff 0xf4 0xc1 255) -- ,(1, PixelRGBA8 0xFF 0x53 0x73 255)] in -- withTexture (linearGradientTexture SamplerPad gradDef -- (V2 40 40) (V2 130 130)) $ -- fill $ circle (V2 100 100) 100 ---- linearGradientTexture :: (Pixel px, Modulable (PixelBaseComponent px)) => Gradient px -> Point -> Point -> Texture px -- | Radial gradient texture -- --
-- let gradDef = [(0, PixelRGBA8 0 0x86 0xc1 255) -- ,(0.5, PixelRGBA8 0xff 0xf4 0xc1 255) -- ,(1, PixelRGBA8 0xFF 0x53 0x73 255)] in -- withTexture (radialGradientTexture SamplerPad gradDef -- (V2 100 100) 75) $ -- fill $ circle (V2 100 100) 100 ---- radialGradientTexture :: (Pixel px, Modulable (PixelBaseComponent px)) => Gradient px -> Point -> Float -> Texture px -- | Radial gradient texture with a focus point. -- --
-- let gradDef = [(0, PixelRGBA8 0 0x86 0xc1 255) -- ,(0.5, PixelRGBA8 0xff 0xf4 0xc1 255) -- ,(1, PixelRGBA8 0xFF 0x53 0x73 255)] in -- withTexture (radialGradientWithFocusTexture SamplerPad gradDef -- (V2 100 100) 75 (V2 70 70) ) $ -- fill $ circle (V2 100 100) 100 ---- radialGradientWithFocusTexture :: (Pixel px, Modulable (PixelBaseComponent px)) => Gradient px -> Point -> Float -> Point -> Texture px -- | Use another image as a texture for the filling. This texture use the -- nearest filtering, AKA no filtering at all. imageTexture :: Pixel px => Image px -> Texture px -- | Use another image as a texture for the filling. Contrary to -- imageTexture, this function perform a bilinear filtering on the -- texture. sampledImageTexture :: (Pixel px, Modulable (PixelBaseComponent px)) => Image px -> Texture px -- | Perform a multiplication operation between a full color texture and a -- greyscale one, used for clip-path implementation. modulateTexture :: (Pixel px, Modulable (PixelBaseComponent px)) => Texture px -> Texture (PixelBaseComponent px) -> Texture px -- | Transform the coordinates used for texture before applying it, allow -- interesting transformations. -- --
-- withTexture (withSampler SamplerRepeat $ -- transformTexture (rotateCenter 1 (V2 0 0) <> -- scale 0.5 0.25) -- $ sampledImageTexture textureImage) $ -- fill $ rectangle (V2 0 0) 200 200 ---- transformTexture :: Transformation -> Texture px -> Texture px -- | Main module of Rasterific, an Haskell rasterization engine. -- -- Creating an image is rather simple, here is a simple example of a -- drawing and saving it in a PNG file: -- --
-- import Codec.Picture( PixelRGBA8( .. ), writePng ) -- import Graphics.Rasterific -- import Graphics.Rasterific.Texture -- -- main :: IO () -- main = do -- let white = PixelRGBA8 255 255 255 255 -- drawColor = PixelRGBA8 0 0x86 0xc1 255 -- recColor = PixelRGBA8 0xFF 0x53 0x73 255 -- img = renderDrawing 400 200 white $ -- withTexture (uniformTexture drawColor) $ do -- fill $ circle (V2 0 0) 30 -- stroke 4 JoinRound (CapRound, CapRound) $ -- circle (V2 400 200) 40 -- withTexture (uniformTexture recColor) . -- fill $ rectangle (V2 100 100) 200 100 -- -- writePng "yourimage.png" img ---- -- -- The coordinate system is the picture classic one, with the origin in -- the upper left corner; with the y axis growing to the bottom and the x -- axis growing to the right: -- module Graphics.Rasterific -- | Fill some geometry. The geometry should be looping, ie. the -- last point of the last primitive should be equal to the first point of -- the first primitive. -- -- The primitive should be connected. -- --
-- fill $ circle (V2 100 100) 75 ---- fill :: [Primitive] -> Drawing px () -- | This function let you choose how to fill the primitives in case of -- self intersection. See FillMethod documentation for more -- information. fillWithMethod :: FillMethod -> [Primitive] -> Drawing px () -- | Define the texture applyied to all the children draw call. -- --
-- withTexture (uniformTexture $ PixelRGBA8 0 0x86 0xc1 255) $ do -- fill $ circle (V2 50 50) 20 -- fill $ circle (V2 100 100) 20 -- withTexture (uniformTexture $ PixelRGBA8 0xFF 0x53 0x73 255) -- $ circle (V2 150 150) 20 ---- withTexture :: Texture px -> Drawing px () -> Drawing px () -- | Draw some geometry using a clipping path. -- --
-- withClipping (fill $ circle (V2 100 100) 75) $ -- mapM_ (stroke 7 JoinRound (CapRound, CapRound)) -- [line (V2 0 yf) (V2 200 (yf + 10)) -- | y <- [5 :: Int, 17 .. 200] -- , let yf = fromIntegral y ] ---- withClipping :: (forall innerPixel. Drawing innerPixel ()) -> Drawing px () -> Drawing px () -- | Draw all the sub drawing commands using a transformation. withTransformation :: Transformation -> Drawing px () -> Drawing px () -- | Will stroke geometry with a given stroke width. The elements should be -- connected -- --
-- stroke 5 JoinRound (CapRound, CapRound) $ circle (V2 100 100) 75 ---- stroke :: Float -> Join -> (Cap, Cap) -> [Primitive] -> Drawing px () -- | With stroke geometry with a given stroke width, using a dash pattern. -- --
-- dashedStroke [5, 10, 5] 3 JoinRound (CapRound, CapStraight 0) -- [line (V2 0 100) (V2 200 100)] ---- dashedStroke :: DashPattern -> Float -> Join -> (Cap, Cap) -> [Primitive] -> Drawing px () -- | With stroke geometry with a given stroke width, using a dash pattern. -- The offset is there to specify the starting point into the pattern, -- the value can be negative. -- --
-- dashedStrokeWithOffset 3 [5, 10, 5] 3 JoinRound (CapRound, CapStraight 0) -- [line (V2 0 100) (V2 200 100)] ---- dashedStrokeWithOffset :: Float -> DashPattern -> Float -> Join -> (Cap, Cap) -> [Primitive] -> Drawing px () -- | Draw a string at a given position. Text printing imply loading a font, -- there is no default font (yet). Below an example of font rendering -- using a font installed on Microsoft Windows. -- --
-- import Graphics.Text.TrueType( loadFontFile ) -- import Codec.Picture( PixelRGBA8( .. ), writePng ) -- import Graphics.Rasterific -- import Graphics.Rasterific.Texture -- -- main :: IO () -- main = do -- fontErr <- loadFontFile "C:/Windows/Fonts/arial.ttf" -- case fontErr of -- Left err -> putStrLn err -- Right font -> -- writePng "text_example.png" . -- renderDrawing 300 70 (PixelRGBA8 255 255 255 255) -- . withTexture (uniformTexture $ PixelRGBA8 0 0 0 255) $ -- printTextAt font 12 (V2 20 40) "A simple text test!" ---- -- -- You can use any texture, like a gradient while rendering text. printTextAt :: Font -> Int -> Point -> String -> Drawing px () -- | Function to call in order to start the image creation. Tested pixels -- type are PixelRGBA8 and Pixel8, pixel types in other colorspace will -- probably produce weird results. renderDrawing :: (Pixel px, Pixel (PixelBaseComponent px), Modulable (PixelBaseComponent px), PixelBaseComponent (PixelBaseComponent px) ~ (PixelBaseComponent px)) => Int -> Int -> px -> Drawing px () -> Image px -- | Transform a path description into a list of renderable primitives. pathToPrimitives :: Path -> [Primitive] -- | A texture is just a function which given pixel coordinate give back a -- pixel. The float coordinate type allow for transformations to happen -- in the pixel space. type Texture px = SamplerRepeat -> Float -> Float -> px -- | Monad used to record the drawing actions. type Drawing px = Free (DrawCommand px) -- | Typeclass intented at pixel value modulation. May be throwed out soon. class (Ord a, Num a) => Modulable a -- | A 2-dimensional vector -- --
-- >>> pure 1 :: V2 Int -- V2 1 1 ---- --
-- >>> V2 1 2 + V2 3 4 -- V2 4 6 ---- --
-- >>> V2 1 2 * V2 3 4 -- V2 3 8 ---- --
-- >>> sum (V2 1 2) -- 3 --data V2 a :: * -> * V2 :: !a -> !a -> V2 a -- | Represent a point type Point = V2 Float -- | Represent a vector type Vector = V2 Float -- | Describe a cubic bezier spline, described using 4 points. -- --
-- stroke 4 JoinRound (CapRound, CapRound) $ -- [CubicBezierPrim $ CubicBezier (V2 0 10) (V2 205 250) -- (V2 (-10) 250) (V2 160 35)] ---- data CubicBezier CubicBezier :: {-# UNPACK #-} !Point -> {-# UNPACK #-} !Point -> {-# UNPACK #-} !Point -> {-# UNPACK #-} !Point -> CubicBezier -- | Origin point, the spline will pass through it. _cBezierX0 :: CubicBezier -> {-# UNPACK #-} !Point -- | First control point of the cubic bezier curve. _cBezierX1 :: CubicBezier -> {-# UNPACK #-} !Point -- | Second control point of the cubic bezier curve. _cBezierX2 :: CubicBezier -> {-# UNPACK #-} !Point -- | End point of the cubic bezier curve _cBezierX3 :: CubicBezier -> {-# UNPACK #-} !Point -- | Describe a simple 2D line between two points. -- --
-- fill $ LinePrim <$> [ Line (V2 10 10) (V2 190 10) -- , Line (V2 190 10) (V2 95 170) -- , Line (V2 95 170) (V2 10 10)] ---- data Line Line :: {-# UNPACK #-} !Point -> {-# UNPACK #-} !Point -> Line -- | Origin point _lineX0 :: Line -> {-# UNPACK #-} !Point -- | End point _lineX1 :: Line -> {-# UNPACK #-} !Point -- | Describe a quadratic bezier spline, described using 3 points. -- --
-- fill $ BezierPrim <$> [Bezier (V2 10 10) (V2 200 50) (V2 200 100) -- ,Bezier (V2 200 100) (V2 150 200) (V2 120 175) -- ,Bezier (V2 120 175) (V2 30 100) (V2 10 10)] ---- data Bezier Bezier :: {-# UNPACK #-} !Point -> {-# UNPACK #-} !Point -> {-# UNPACK #-} !Point -> Bezier -- | Origin points, the spline will pass through it. _bezierX0 :: Bezier -> {-# UNPACK #-} !Point -- | Control point, the spline won't pass on it. _bezierX1 :: Bezier -> {-# UNPACK #-} !Point -- | End point, the spline will pass through it. _bezierX2 :: Bezier -> {-# UNPACK #-} !Point -- | This datatype gather all the renderable primitives, they are kept -- separated otherwise to allow specialization on some specific -- algorithms. You can mix the different primitives in a single call : -- --
-- fill -- [ CubicBezierPrim $ CubicBezier (V2 50 20) (V2 90 60) -- (V2 5 100) (V2 50 140) -- , LinePrim $ Line (V2 50 140) (V2 120 80) -- , LinePrim $ Line (V2 120 80) (V2 50 20) ] ---- data Primitive -- | Primitive used for lines LinePrim :: !Line -> Primitive -- | Primitive used for quadratic beziers curves BezierPrim :: !Bezier -> Primitive -- | Primitive used for cubic bezier curve CubicBezierPrim :: !CubicBezier -> Primitive -- | Describe a path in a way similar to many graphical packages, using a -- pen position in memory and reusing it for the next move -- For example the example from Primitive could be rewritten: -- --
-- fill . pathToPrimitives $ Path (V2 50 20) True -- [ PathCubicBezierCurveTo (V2 90 60) (V2 5 100) (V2 50 140) -- , PathLineTo (V2 120 80) ] ---- data Path Path :: Point -> Bool -> [PathCommand] -> Path -- | Origin of the point, equivalent to the first move command. _pathOriginPoint :: Path -> Point -- | Tell if we must close the path. _pathClose :: Path -> Bool -- | List of commands in the path _pathCommand :: Path -> [PathCommand] -- | Actions to create a path data PathCommand -- | Draw a line from the current point to another point PathLineTo :: Point -> PathCommand -- | Draw a quadratic bezier curve from the current point through the -- control point to the end point. PathQuadraticBezierCurveTo :: Point -> Point -> PathCommand -- | Draw a cubic bezier curve using 2 control points. PathCubicBezierCurveTo :: Point -> Point -> Point -> PathCommand -- | This typeclass is there to help transform the geometry, by applying a -- transformation on every point of a geometric element. class Transformable a transform :: Transformable a => (Point -> Point) -> a -> a -- | Typeclass helper gathering all the points of a given geometry. class PointFoldable a foldPoints :: PointFoldable a => (b -> Point -> b) -> b -> a -> b -- | Return a simple line ready to be stroked. -- --
-- stroke 17 JoinRound (CapRound, CapRound) $ -- line (V2 10 10) (V2 180 170) ---- line :: Point -> Point -> [Primitive] -- | Generate a list of primitive representing a rectangle -- --
-- fill $ rectangle (V2 30 30) 150 100 ---- rectangle :: Point -> Float -> Float -> [Primitive] -- | Generate a list of primitive representing a rectangle with rounded -- corner. -- --
-- fill $ roundedRectangle (V2 10 10) 150 150 20 10 ---- roundedRectangle :: Point -> Float -> Float -> Float -> Float -> [Primitive] -- | Generate a list of primitive representing a circle. -- --
-- fill $ circle (V2 100 100) 75 ---- circle :: Point -> Float -> [Primitive] -- | Generate a list of primitive representing an ellipse. -- --
-- fill $ ellipse (V2 100 100) 75 30 ---- ellipse :: Point -> Float -> Float -> [Primitive] -- | Generate a strokable line out of points list. Just an helper around -- lineFromPath. -- --
-- stroke 4 JoinRound (CapRound, CapRound) $ -- polyline [V2 10 10, V2 100 70, V2 190 190] ---- polyline :: [Point] -> [Primitive] -- | Generate a fillable polygon out of points list. Similar to the -- polyline function, but close the path. -- --
-- fill $ polygon [V2 30 30, V2 100 70, V2 80 170] ---- polygon :: [Point] -> [Primitive] -- | Draw an image with the desired size -- --
-- drawImageAtSize textureImage 2 (V2 30 30) 128 128 ---- drawImageAtSize :: (Pixel px, Modulable (PixelBaseComponent px)) => Image px -> StrokeWidth -> Point -> Float -> Float -> Drawing px () -- | Simply draw an image into the canvas. Take into account any previous -- transformation performed on the geometry. -- --
-- drawImage textureImage 0 (V2 30 30) ---- drawImage :: (Pixel px, Modulable (PixelBaseComponent px)) => Image px -> StrokeWidth -> Point -> Drawing px () -- | Clip the geometry to a rectangle. clip :: Point -> Point -> Primitive -> [Primitive] -- | Create a list of bezier patch from a list of points, -- --
-- bezierFromPath [a, b, c, d, e] == [Bezier a b c, Bezier c d e] -- bezierFromPath [a, b, c, d, e, f] == [Bezier a b c, Bezier c d e] -- bezierFromPath [a, b, c, d, e, f, g] == -- [Bezier a b c, Bezier c d e, Bezier e f g] --bezierFromPath :: [Point] -> [Bezier] -- | Transform a list a point to a list of lines -- --
-- lineFromPath [a, b, c, d] = [Line a b, Line b c, Line c d] --lineFromPath :: [Point] -> [Line] -- | Create a list of cubic bezier patch from a list of points. -- --
-- cubicBezierFromPath [a, b, c, d, e] = [CubicBezier a b c d] -- cubicBezierFromPath [a, b, c, d, e, f, g] = -- [CubicBezier a b c d, CubicBezier d e f g] --cubicBezierFromPath :: [Point] -> [CubicBezier] -- | Describe how to display the join of broken lines while stroking. data Join -- | Make a curved join. JoinRound :: Join -- | Make a mitter join. Value must be positive or null. Seems to make -- sense in [0;1] only -- --
-- fillingSample :: FillMethod -> Drawing px () -- fillingSample fillMethod = fillWithMethod fillMethod geometry where -- geometry = transform (applyTransformation $ scale 0.35 0.4 -- <> translate (V2 (-80) (-180))) -- $ concatMap pathToPrimitives -- [ Path (V2 484 499) True -- [ PathCubicBezierCurveTo (V2 681 452) (V2 639 312) (V2 541 314) -- , PathCubicBezierCurveTo (V2 327 337) (V2 224 562) (V2 484 499) -- ] -- , Path (V2 136 377) True -- [ PathCubicBezierCurveTo (V2 244 253) (V2 424 420) (V2 357 489) -- , PathCubicBezierCurveTo (V2 302 582) (V2 47 481) (V2 136 377) -- ] -- , Path (V2 340 265) True -- [ PathCubicBezierCurveTo (V2 64 371) (V2 128 748) (V2 343 536) -- , PathCubicBezierCurveTo (V2 668 216) (V2 17 273) (V2 367 575) -- , PathCubicBezierCurveTo (V2 589 727) (V2 615 159) (V2 340 265) -- ] -- ] --data FillMethod -- | Also known as nonzero rule. To determine if a point falls inside the -- curve, you draw an imaginary line through that point. Next you will -- count how many times that line crosses the curve before it reaches -- that point. For every clockwise rotation, you subtract 1 and for every -- counter-clockwise rotation you add 1. -- FillWinding :: FillMethod -- | This rule determines the insideness of a point on the canvas by -- drawing a ray from that point to infinity in any direction and -- counting the number of path segments from the given shape that the ray -- crosses. If this number is odd, the point is inside; if even, the -- point is outside. -- FillEvenOdd :: FillMethod -- | Dash pattern to use type DashPattern = [Float] -- | This function will spit out drawing instructions to help debugging. -- -- The outputted code looks like Haskell, but there is no guarantee that -- it is compilable. dumpDrawing :: Show px => Drawing px () -> String instance Monoid (Drawing px ()) instance Functor (DrawCommand px)