-- 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. -- -- Can render vector graphics to an image and export vector data to PDF. @package Rasterific @version 0.7 -- | This module is a reduction of the Linear package from Edward -- Kmett to match just the need of Rasterific. -- -- If the flag embed_linear is disabled, this module is just a -- reexport from the real linear package. module Graphics.Rasterific.Linear -- | A 1-dimensional vector newtype V1 a V1 :: a -> V1 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 -- | A 3-dimensional vector data V3 a V3 :: !a -> !a -> !a -> V3 a -- | A 4-dimensional vector data V4 a V4 :: !a -> !a -> !a -> !a -> V4 a class R1 t _x :: R1 t => Lens' (t a) a class R2 t _y :: R2 t => Lens' (t a) a -- | A vector is an additive group with additional structure. class Functor f => Additive f -- | The zero vector zero :: (Additive f, Num a) => f a -- | Compute the sum of two vectors -- --
-- >>> V2 1 2 ^+^ V2 3 4 -- V2 4 6 --(^+^) :: (Additive f, Num a) => f a -> f a -> f a -- | Compute the difference between two vectors -- --
-- >>> V2 4 5 - V2 3 1 -- V2 1 4 --(^-^) :: (Additive f, Num a) => f a -> f a -> f a -- | Linearly interpolate between two vectors. lerp :: (Additive f, Num a) => a -> f a -> f a -> f a -- | Provides a fairly subjective test to see if a quantity is near zero. -- --
-- >>> nearZero (1e-11 :: Double) -- False ---- --
-- >>> nearZero (1e-17 :: Double) -- True ---- --
-- >>> nearZero (1e-5 :: Float) -- False ---- --
-- >>> nearZero (1e-7 :: Float) -- True --class Num a => Epsilon a -- | Determine if a quantity is near zero. nearZero :: Epsilon a => a -> Bool -- | Free and sparse inner product/metric spaces. class Additive f => Metric f where quadrance v = dot v v qd f g = quadrance (f ^-^ g) distance f g = norm (f ^-^ g) norm v = sqrt (quadrance v) signorm v = fmap (/ m) v where m = norm v -- | Compute the inner product of two vectors or (equivalently) convert a -- vector f a into a covector f a -> a. -- --
-- >>> V2 1 2 `dot` V2 3 4 -- 11 --dot :: (Metric f, Num a) => f a -> f a -> a -- | Compute the squared norm. The name quadrance arises from Norman J. -- Wildberger's rational trigonometry. quadrance :: (Metric f, Num a) => f a -> a -- | Compute the quadrance of the difference qd :: (Metric f, Num a) => f a -> f a -> a -- | Compute the distance between two vectors in a metric space distance :: (Metric f, Floating a) => f a -> f a -> a -- | Compute the norm of a vector in a metric space norm :: (Metric f, Floating a) => f a -> a -- | Convert a non-zero vector to unit vector. signorm :: (Metric f, Floating a) => f a -> f a -- | Compute the right scalar product -- --
-- >>> V2 3 4 ^* 2 -- V2 6 8 --(^*) :: (Functor f, Num a) => f a -> a -> f a infixl 7 ^* -- | Compute division by a scalar on the right. (^/) :: (Functor f, Floating a) => f a -> a -> f a infixl 7 ^/ -- | Normalize a Metric functor to have unit norm. This -- function does not change the functor if its norm is 0 or 1. normalize :: (Floating a, Metric f, Epsilon a) => f a -> f a instance GHC.Num.Num a => GHC.Num.Num (Graphics.Rasterific.Linear.V1 a) instance GHC.Show.Show a => GHC.Show.Show (Graphics.Rasterific.Linear.V1 a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Graphics.Rasterific.Linear.V1 a) instance GHC.Show.Show a => GHC.Show.Show (Graphics.Rasterific.Linear.V4 a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Graphics.Rasterific.Linear.V4 a) instance GHC.Show.Show a => GHC.Show.Show (Graphics.Rasterific.Linear.V3 a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Graphics.Rasterific.Linear.V3 a) instance GHC.Show.Show a => GHC.Show.Show (Graphics.Rasterific.Linear.V2 a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Graphics.Rasterific.Linear.V2 a) instance Graphics.Rasterific.Linear.R1 Graphics.Rasterific.Linear.V1 instance Graphics.Rasterific.Linear.R1 Graphics.Rasterific.Linear.V2 instance Graphics.Rasterific.Linear.R2 Graphics.Rasterific.Linear.V2 instance Graphics.Rasterific.Linear.R1 Graphics.Rasterific.Linear.V3 instance Graphics.Rasterific.Linear.R2 Graphics.Rasterific.Linear.V3 instance Graphics.Rasterific.Linear.R1 Graphics.Rasterific.Linear.V4 instance Graphics.Rasterific.Linear.R2 Graphics.Rasterific.Linear.V4 instance GHC.Base.Functor Graphics.Rasterific.Linear.V1 instance GHC.Base.Functor Graphics.Rasterific.Linear.V2 instance GHC.Base.Functor Graphics.Rasterific.Linear.V3 instance GHC.Base.Functor Graphics.Rasterific.Linear.V4 instance Data.Foldable.Foldable Graphics.Rasterific.Linear.V3 instance Data.Traversable.Traversable Graphics.Rasterific.Linear.V3 instance Data.Foldable.Foldable Graphics.Rasterific.Linear.V2 instance Data.Traversable.Traversable Graphics.Rasterific.Linear.V2 instance Data.Foldable.Foldable Graphics.Rasterific.Linear.V4 instance Data.Traversable.Traversable Graphics.Rasterific.Linear.V4 instance Data.Foldable.Foldable Graphics.Rasterific.Linear.V1 instance Data.Traversable.Traversable Graphics.Rasterific.Linear.V1 instance GHC.Num.Num a => GHC.Num.Num (Graphics.Rasterific.Linear.V2 a) instance GHC.Num.Num a => GHC.Num.Num (Graphics.Rasterific.Linear.V3 a) instance GHC.Num.Num a => GHC.Num.Num (Graphics.Rasterific.Linear.V4 a) instance GHC.Base.Applicative Graphics.Rasterific.Linear.V4 instance GHC.Base.Applicative Graphics.Rasterific.Linear.V3 instance GHC.Base.Applicative Graphics.Rasterific.Linear.V2 instance GHC.Base.Applicative Graphics.Rasterific.Linear.V1 instance Graphics.Rasterific.Linear.Epsilon GHC.Types.Float instance Graphics.Rasterific.Linear.Epsilon GHC.Types.Double instance Graphics.Rasterific.Linear.Epsilon a => Graphics.Rasterific.Linear.Epsilon (Graphics.Rasterific.Linear.V4 a) instance Graphics.Rasterific.Linear.Epsilon a => Graphics.Rasterific.Linear.Epsilon (Graphics.Rasterific.Linear.V3 a) instance Graphics.Rasterific.Linear.Epsilon a => Graphics.Rasterific.Linear.Epsilon (Graphics.Rasterific.Linear.V2 a) instance Graphics.Rasterific.Linear.Epsilon a => Graphics.Rasterific.Linear.Epsilon (Graphics.Rasterific.Linear.V1 a) instance Graphics.Rasterific.Linear.Additive Graphics.Rasterific.Linear.V4 instance Graphics.Rasterific.Linear.Additive Graphics.Rasterific.Linear.V3 instance Graphics.Rasterific.Linear.Additive Graphics.Rasterific.Linear.V2 instance Graphics.Rasterific.Linear.Additive Graphics.Rasterific.Linear.V1 instance Graphics.Rasterific.Linear.Metric Graphics.Rasterific.Linear.V4 instance Graphics.Rasterific.Linear.Metric Graphics.Rasterific.Linear.V3 instance Graphics.Rasterific.Linear.Metric Graphics.Rasterific.Linear.V2 -- | 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 -- | Effectively transform a vector given a transformation. The translation -- part won't be applied. applyVectorTransformation :: Transformation -> Vector -> Vector -- | 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 -- | Skew transformation along the X axis. -- --
-- fill . transform (applyTransformation $ skewX 0.3) -- $ rectangle (V2 50 50) 80 80 ---- skewX :: Float -> Transformation -- | Skew transformation along the Y axis. -- --
-- fill . transform (applyTransformation $ skewY 0.3) -- $ rectangle (V2 50 50) 80 80 ---- skewY :: Float -> Transformation -- | Given a new X-acis vector, create a rotation matrix to get into this -- new base, assuming an Y basis orthonormal to the X one. toNewXBase :: Vector -> Transformation -- | Inverse a transformation (if possible) inverseTransformation :: Transformation -> Maybe Transformation instance GHC.Show.Show Graphics.Rasterific.Transformations.Transformation instance GHC.Classes.Eq Graphics.Rasterific.Transformations.Transformation instance GHC.Base.Monoid Graphics.Rasterific.Transformations.Transformation -- | This module provide lenses compatible with the lens module but -- without the dependency to it. module Graphics.Rasterific.Lenses -- | Line origin point. lineX0 :: Lens' Line Point -- | Line end point. lineX1 :: Lens' Line Point -- | Traverse all the points of a line. linePoints :: Traversal' Line Point -- | Quadratic bezier starting point. bezX0 :: Lens' Bezier Point -- | bezier control point. bezX1 :: Lens' Bezier Point -- | bezier end point. bezX2 :: Lens' Bezier Point -- | Traversal of all the bezier's points. bezierPoints :: Traversal' Bezier Point -- | Cubic bezier first point cbezX0 :: Lens' CubicBezier Point -- | Cubic bezier first control point. cbezX1 :: Lens' CubicBezier Point -- | Cubic bezier second control point. cbezX2 :: Lens' CubicBezier Point -- | Cubic bezier last point. cbezX3 :: Lens' CubicBezier Point -- | Traversal of all the points of the cubic bezier. cubicBezierPoints :: Traversal' CubicBezier Point -- | Traverse all the points defined in the primitive. primitivePoints :: Traversal' Primitive Point -- | Traversal of all the points of a path pathCommandPoints :: Traversal' PathCommand Point -- | Traversal of all the points in a path. pathPoints :: Traversal' Path Point -- | Does it look familiar? yes it's the official Lens type. type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t -- | Try to match the Lens' type alias. type Lens' s a = Lens s s a a -- | Traversal type, matched to the one of the lens package. type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t type Traversal' s a = Traversal s s a a -- | This module provide helper functions to create outline of shapes. module Graphics.Rasterific.Outline -- | Type alias just to get more meaningful type signatures type StrokeWidth = Float -- | This function will create the outline of a given geometry given a -- path. You can then stroke it. -- --
-- stroke 3 (JoinMiter 0) (CapStraight 0, CapStraight 0) $ -- strokize 40 JoinRound (CapRound, CapRound) $ -- CubicBezier (V2 40 160) (V2 40 40) -- (V2 160 40) (V2 160 160) ---- strokize :: Geometry geom => StrokeWidth -> Join -> (Cap, Cap) -> geom -> [Primitive] -- | Create a list of outlines corresponding to all the dashed elements. -- They can be then stroked -- --
-- mapM_ (stroke 3 (JoinMiter 0) (CapStraight 0, CapStraight 0)) $ -- dashedStrokize 0 [10, 5] -- 40 JoinRound (CapStraight 0, CapStraight 0) $ -- CubicBezier (V2 40 160) (V2 40 40) (V2 160 40) (V2 160 160) ---- dashedStrokize :: Geometry geom => Float -> DashPattern -> StrokeWidth -> Join -> (Cap, Cap) -> geom -> [[Primitive]] -- | Return an approximation of the length of a given path. It's results is -- not precise but should be enough for rough calculations approximatePathLength :: Path -> Float -- | Module defining the type of mesh patch grid. module Graphics.Rasterific.MeshPatch -- | Store the two bezier control points of a bezier. data InterBezier InterBezier :: !Point -> !Point -> InterBezier [_inter0] :: InterBezier -> !Point [_inter1] :: InterBezier -> !Point -- | Store the inner points of a tensor patch. data Derivatives Derivatives :: !Point -> !Point -> !Point -> !Point -> Derivatives [_interNorthWest] :: Derivatives -> !Point [_interNorthEast] :: Derivatives -> !Point [_interSouthWest] :: Derivatives -> !Point [_interSouthEast] :: Derivatives -> !Point -- | Define a mesh patch grid, the grid is conceptually a regular grid of -- _meshPatchWidth * _meshPatchHeight patches but with shared edges data MeshPatch px MeshPatch :: !Int -> !Int -> !(Vector Point) -> !(Vector InterBezier) -> !(Vector InterBezier) -> !(Vector px) -> !(Maybe (Vector Derivatives)) -> MeshPatch px -- | Count of horizontal of *patch* [_meshPatchWidth] :: MeshPatch px -> !Int -- | Count of vertical of *patch* [_meshPatchHeight] :: MeshPatch px -> !Int -- | Main points defining the patch, of size (_meshPatchWidth + 1) * -- (_meshPatchHeight + 1) [_meshPrimaryVertices] :: MeshPatch px -> !(Vector Point) -- | For each line, store the points in between each vertex. There is two -- points between each vertex, so _meshPatchWidth * (_meshPatchHeight + -- 1) points [_meshHorizontalSecondary] :: MeshPatch px -> !(Vector InterBezier) -- | For each colun, store the points in between each vertex. Two points -- between each vertex, so _meshPatchHeight * (_meshPatchWidth + 1) [_meshVerticalSecondary] :: MeshPatch px -> !(Vector InterBezier) -- | Colors for each vertex points [_meshColors] :: MeshPatch px -> !(Vector px) -- | Points used to define tensor patch, if not define, the rest of the -- data structure describes a Coon patch. size must be equal to -- `_meshPatchWidth*_meshPatchHeight` [_meshTensorDerivatives] :: MeshPatch px -> !(Maybe (Vector Derivatives)) -- | Store information for cubic interpolation in a patch. newtype CubicCoefficient px CubicCoefficient :: ParametricValues (V4 (Holder px Float)) -> CubicCoefficient px [getCubicCoefficients] :: CubicCoefficient px -> ParametricValues (V4 (Holder px Float)) -- | Prepare a gradient mesh to use cubic color interpolation, see -- renderCubicMesh documentation to see the global use of this function. calculateMeshColorDerivative :: forall px. (InterpolablePixel px) => MeshPatch px -> MeshPatch (Derivative px) -- | Retrieve a mesh primary vertice purely verticeAt :: MeshPatch px -> Int -> Int -> Point -- | Generate a valid gradient with the shape of a simple grid using some -- simple information. You can use thawMesh and freezeMesh -- to mutate it. generateLinearGrid :: Int -> Int -> Point -> V2 Float -> Vector px -> MeshPatch px -- | Generate a meshpatch at the size given by the image and a number of -- cell in a mesh generateImageMesh :: Int -> Int -> Point -> Image px -> MeshPatch (ImageMesh px) -- | Extract a coon patch at a given position. coonPatchAt :: MeshPatch px -> Int -> Int -> CoonPatch (ParametricValues px) -- | Extract a tensor patch at a given position tensorPatchAt :: MeshPatch px -> Int -> Int -> TensorPatch (ParametricValues px) -- | Extract an image patch out of a mesh at a given position. coonImagePatchAt :: MeshPatch (ImageMesh px) -> Int -> Int -> CoonPatch (ImageMesh px) -- | Extract a tensor image patch out of a mesh at a given position. tensorImagePatchAt :: MeshPatch (ImageMesh px) -> Int -> Int -> TensorPatch (ImageMesh px) -- | Extract a coon patch for cubic interpolation at a given position see -- calculateMeshColorDerivative coonPatchAtWithDerivative :: (InterpolablePixel px) => MeshPatch (Derivative px) -> Int -> Int -> CoonPatch (CubicCoefficient px) -- | Extract a tensor patch for cubic interpolation at a given position see -- calculateMeshColorDerivative tensorPatchAtWithDerivative :: (InterpolablePixel px) => MeshPatch (Derivative px) -> Int -> Int -> TensorPatch (CubicCoefficient px) -- | Extract a list of all the coon patches of the mesh. coonPatchesOf :: MeshPatch px -> [CoonPatch (ParametricValues px)] -- | Extract a list of all the tensor patches of the mesh. tensorPatchesOf :: MeshPatch px -> [TensorPatch (ParametricValues px)] -- | Extract all the coon patch of a mesh using an image interpolation. imagePatchesOf :: MeshPatch (ImageMesh px) -> [CoonPatch (ImageMesh px)] -- | Extract all the tensor patch of a mesh using an image interpolation. tensorImagePatchesOf :: MeshPatch (ImageMesh px) -> [TensorPatch (ImageMesh px)] -- | Extract all the coon patch of a mesh using cubic interpolation. cubicCoonPatchesOf :: (InterpolablePixel px) => MeshPatch (Derivative px) -> [CoonPatch (CubicCoefficient px)] -- | Extract all the tensor patch of a mesh using cubic interpolation. cubicTensorPatchesOf :: (InterpolablePixel px) => MeshPatch (Derivative px) -> [TensorPatch (CubicCoefficient px)] -- | Mutable version of a MeshPatch data MutableMesh s px -- | Normal mesh to mutable mesh thawMesh :: PrimMonad m => MeshPatch px -> m (MutableMesh (PrimState m) px) -- | Mutable mesh to freezed mesh. freezeMesh :: PrimMonad m => MutableMesh (PrimState m) px -> m (MeshPatch px) -- | Given an original MeshPatch, provide context to mutate it through -- modification functions. withMesh :: MeshPatch px -> (forall m. (MonadReader (MutableMesh (PrimState m) px) m, PrimMonad m) => m a) -> (a, MeshPatch px) -- | Set the vertice of a mesh at a given coordinate setVertice :: (MonadReader (MutableMesh (PrimState m) px) m, PrimMonad m) => Int -> Int -> Point -> m () -- | Get the position of vertice getVertice :: (MonadReader (MutableMesh (PrimState m) px) m, PrimMonad m) => Int -> Int -> m Point -- | Set the two control bezier points horizontally setHorizPoints :: (MonadReader (MutableMesh (PrimState m) px) m, PrimMonad m) => Int -> Int -> InterBezier -> m () -- | Set the two control bezier points vertically setVertPoints :: (MonadReader (MutableMesh (PrimState m) px) m, PrimMonad m) => Int -> Int -> InterBezier -> m () -- | Set the value associated to a vertex setColor :: (MonadReader (MutableMesh (PrimState m) px) m, PrimMonad m) => Int -> Int -> px -> m () -- | This module implements drawing primitives to draw directly into the -- output texture, without generating an intermediate scene -- representation. -- -- If you need to draw complex scenes or plot an important set of data, -- this is the module you should use. The downside is that you must -- specify everything you need at each draw call, there is no API to help -- you propagate constants. -- -- The "stroking" must be done using the functions of the Outline -- module. module Graphics.Rasterific.Immediate -- | Monad used to describe the drawing context. type DrawContext m px = StateT (MutableImage (PrimState m) px) m -- | Reify a filling function call, to be able to manipulate them in a -- simpler fashion. data DrawOrder px DrawOrder :: ![[Primitive]] -> !(Texture px) -> !FillMethod -> !(Maybe (Texture (PixelBaseComponent px))) -> !(forall s. DrawContext (ST s) px ()) -> DrawOrder px -- | Primitives to be filled. [_orderPrimitives] :: DrawOrder px -> ![[Primitive]] -- | Texture for the filled primitives. [_orderTexture] :: DrawOrder px -> !(Texture px) -- | How to fill the primitives. [_orderFillMethod] :: DrawOrder px -> !FillMethod -- | Optional mask used for clipping. [_orderMask] :: DrawOrder px -> !(Maybe (Texture (PixelBaseComponent px))) -- | Function to perform direct drawing [_orderDirect] :: DrawOrder px -> !(forall s. DrawContext (ST s) px ()) -- | Transform back a low level drawing order to a more high level Drawing orderToDrawing :: DrawOrder px -> Drawing px () -- | Start an image rendering. See fillWithTexture for an usage -- example. This function can work with either IO or ST. runDrawContext :: forall m px. (PrimMonad m, RenderablePixel px) => Int -> Int -> px -> DrawContext m px () -> m (Image px) -- | Fill some geometry using a composition mask for visibility. -- --
-- immediateDrawMaskExample :: Image PixelRGBA8 -- immediateDrawMaskExample = runST $ -- runDrawContext 200 200 (PixelRGBA8 0 0 0 255) $ -- forM_ [1 .. 10] $ \ix -> -- fillWithTextureAndMask FillWinding texture mask $ -- rectangle (V2 10 (ix * 18 - 5)) 180 13 -- where -- texture = uniformTexture $ PixelRGBA8 0 0x86 0xc1 255 -- mask = sampledImageTexture -- $ runST -- $ runDrawContext 200 200 0 -- $ fillWithTexture FillWinding (uniformTexture 255) maskGeometry -- -- maskGeometry = strokize 15 JoinRound (CapRound, CapRound) -- $ circle (V2 100 100) 80 ---- fillWithTextureAndMask :: (PrimMonad m, RenderablePixel px) => FillMethod -> Texture px -> Texture (PixelBaseComponent px) -> [Primitive] -> DrawContext m px () -- | Fill some geometry. -- --
-- immediateDrawExample :: Image PixelRGBA8 -- immediateDrawExample = runST $ -- runDrawContext 200 200 (PixelRGBA8 0 0 0 0) $ -- fillWithTexture FillWinding texture geometry -- where -- circlePrimitives = circle (V2 100 100) 50 -- geometry = strokize 4 JoinRound (CapRound, CapRound) circlePrimitives -- texture = uniformTexture (PixelRGBA8 255 255 255 255) ---- fillWithTexture :: (PrimMonad m, RenderablePixel px) => FillMethod -> Texture px -> [Primitive] -> DrawContext m px () -- | Function identical to fillWithTexture but with anti-aliasing -- (and transparency) disabled. fillWithTextureNoAA :: (PrimMonad m, RenderablePixel px) => FillMethod -> Texture px -> [Primitive] -> DrawContext m px () -- | Render the drawing orders on the canvas. fillOrder :: (PrimMonad m, RenderablePixel px) => DrawOrder px -> DrawContext m px () -- | Helper function transforming text range to draw order. textToDrawOrders :: Dpi -> Texture px -> Point -> [TextRange px] -> [DrawOrder px] transformOrder :: (Point -> Point) -> DrawOrder px -> DrawOrder px instance Graphics.Rasterific.PlaneBoundable.PlaneBoundable (Graphics.Rasterific.Immediate.DrawOrder px) instance Graphics.Rasterific.Types.Transformable (Graphics.Rasterific.Immediate.DrawOrder px) -- | This module help the walking of path of any shape, being able to -- return the current position and the actual orientation. module Graphics.Rasterific.PathWalker -- | The walking transformer monad. data PathWalkerT m a -- | Simpler alias if monad transformers are not needed. type PathWalker a = PathWalkerT Identity a -- | Callback function in charge to transform the DrawOrder given the -- transformation to place it on the path. type PathDrawer m px = Transformation -> PlaneBound -> DrawOrder px -> m () -- | Create a path walker from a given path runPathWalking :: (Monad m) => Path -> PathWalkerT m a -> m a -- | Advance by the given amount of pixels on the path. advanceBy :: Monad m => Float -> PathWalkerT m () -- | Obtain the current position if we are still on the path, if not, -- return Nothing. currentPosition :: (Monad m) => PathWalkerT m (Maybe Point) -- | Obtain the current tangeant of the path if we're still on it. Return -- Nothing otherwise. currentTangeant :: (Monad m) => PathWalkerT m (Maybe Vector) -- | This function is the workhorse of the placement, it will walk the path -- and calculate the appropriate transformation for every order. drawOrdersOnPath :: Monad m => PathDrawer m px -> Float -> Float -> Path -> [DrawOrder px] -> m () instance Control.Monad.Trans.Class.MonadTrans Graphics.Rasterific.PathWalker.PathWalkerT instance GHC.Base.Functor m => GHC.Base.Functor (Graphics.Rasterific.PathWalker.PathWalkerT m) instance GHC.Base.Monad m => GHC.Base.Applicative (Graphics.Rasterific.PathWalker.PathWalkerT m) instance GHC.Base.Monad m => GHC.Base.Monad (Graphics.Rasterific.PathWalker.PathWalkerT m) -- | Module to describe bi-sampleable types module Graphics.Rasterific.BiSampleable -- | Interpolate a 2D point in a given type class BiSampleable sampled px | sampled -> px -- | The interpolation function interpolate :: BiSampleable sampled px => sampled -> Float -> Float -> px bilinearInterpolation :: InterpolablePixel px => ParametricValues px -> Float -> Float -> px instance (Codec.Picture.Types.Pixel px, Graphics.Rasterific.Compositor.Modulable (Codec.Picture.Types.PixelBaseComponent px)) => Graphics.Rasterific.BiSampleable.BiSampleable (Graphics.Rasterific.PatchTypes.ParametricValues px) px instance (Graphics.Rasterific.Compositor.InterpolablePixel px, GHC.Num.Num (Graphics.Rasterific.Compositor.Holder px GHC.Types.Float)) => Graphics.Rasterific.BiSampleable.BiSampleable (Graphics.Rasterific.PatchTypes.CubicCoefficient px) px instance Graphics.Rasterific.BiSampleable.BiSampleable (Graphics.Rasterific.PatchTypes.ImageMesh Codec.Picture.Types.PixelRGBA8) Codec.Picture.Types.PixelRGBA8 -- | Implementation using "An efficient algorithm for subdivising linear -- Coons surfaces" C.Yao and J.Rokne Computer aided design 8 (1991) -- 291-303 module Graphics.Rasterific.Patch -- | Define the boundary and interpolated values of a coon patch. -- --
-- -----> -- North _____----------------+ -- ^ +------------/ / . -- | / / | -- | / / | -- | / / east | -- | west | / | -- | | v -- \ \ . -- \ __-------------+ -- +----------------/ -- South -- <----- --data CoonPatch weight CoonPatch :: !CubicBezier -> !CubicBezier -> !CubicBezier -> !CubicBezier -> !weight -> CoonPatch weight -- | North border, from left to right at top [_north] :: CoonPatch weight -> !CubicBezier -- | East obrder, from top to bottom [_east] :: CoonPatch weight -> !CubicBezier -- | South border from right to left [_south] :: CoonPatch weight -> !CubicBezier -- | West border from bottom to top [_west] :: CoonPatch weight -> !CubicBezier -- | The patch values [_coonValues] :: CoonPatch weight -> !weight -- | Describe a tensor patch data TensorPatch weight TensorPatch :: !CubicBezier -> !CubicBezier -> !CubicBezier -> !CubicBezier -> !weight -> TensorPatch weight [_curve0] :: TensorPatch weight -> !CubicBezier [_curve1] :: TensorPatch weight -> !CubicBezier [_curve2] :: TensorPatch weight -> !CubicBezier [_curve3] :: TensorPatch weight -> !CubicBezier [_tensorValues] :: TensorPatch weight -> !weight -- | Values associated to the corner of a patch -- --
-- North East -- +--------------+ -- |0 1| -- | | -- | | -- | | -- |3 2| -- +--------------+ -- West South --data ParametricValues a ParametricValues :: !a -> !a -> !a -> !a -> ParametricValues a [_northValue] :: ParametricValues a -> !a [_eastValue] :: ParametricValues a -> !a [_southValue] :: ParametricValues a -> !a [_westValue] :: ParametricValues a -> !a -- | How do we want to perform color/image interpolation within the patch. data PatchInterpolation -- | Bilinear interpolation -- --
-- import qualified Data.Vector as V -- let colorCycle = cycle -- [ PixelRGBA8 0 0x86 0xc1 255 -- , PixelRGBA8 0xff 0xf4 0xc1 255 -- , PixelRGBA8 0xFF 0x53 0x73 255 -- , PixelRGBA8 0xff 0xf4 0xc1 255 -- , PixelRGBA8 0 0x86 0xc1 255] -- colors = V.fromListN (4 * 4) colorCycle -- renderMeshPatch PatchBilinear $ generateLinearGrid 3 3 (V2 10 10) (V2 60 60) colors ---- PatchBilinear :: PatchInterpolation -- | Bicubic interpolation -- --
-- import qualified Data.Vector as V -- let colorCycle = cycle -- [ PixelRGBA8 0 0x86 0xc1 255 -- , PixelRGBA8 0xff 0xf4 0xc1 255 -- , PixelRGBA8 0xFF 0x53 0x73 255 -- , PixelRGBA8 0xff 0xf4 0xc1 255 -- , PixelRGBA8 0 0x86 0xc1 255] -- colors = V.fromListN (4 * 4) colorCycle -- renderMeshPatch PatchBicubic $ generateLinearGrid 3 3 (V2 10 10) (V2 60 60) colors ---- PatchBicubic :: PatchInterpolation -- | Type of coordinate interpolation type CoonColorWeight = Float -- | Store the new generated information after subdivision in 4 quadrants. data Subdivided a Subdivided :: !a -> !a -> !a -> !a -> Subdivided a -- | Upper left [_northWest] :: Subdivided a -> !a -- | Upper right [_northEast] :: Subdivided a -> !a -- | Lower left [_southWest] :: Subdivided a -> !a -- | Lower right [_southEast] :: Subdivided a -> !a -- | Used for Coon patch rendering class (Applicative (Holder a), Functor (Holder a), Foldable (Holder a), Additive (Holder a)) => InterpolablePixel a -- | Rasterize a tensor patch using the Fast Forward Diffrence algorithm, -- likely to be faster than the subdivision one. rasterizeTensorPatch :: (PrimMonad m, ModulablePixel px, BiSampleable src px) => TensorPatch src -> DrawContext m px () -- | Rasterize a coon patch using the Fast Forward Diffrence algorithm, -- likely to be faster than the subdivision one. rasterizeCoonPatch :: (PrimMonad m, ModulablePixel px, BiSampleable src px) => CoonPatch src -> DrawContext m px () -- | Render an mesh patch by interpolating accross an image. renderImageMesh :: PrimMonad m => MeshPatch (ImageMesh PixelRGBA8) -> DrawContext m PixelRGBA8 () -- | Render a simple coon mesh, with only color on the vertices. renderCoonMesh :: forall m px. (PrimMonad m, RenderablePixel px, BiSampleable (ParametricValues px) px) => MeshPatch px -> DrawContext m px () -- | Render a coon mesh but using cubic interpolation for the color. renderCoonMeshBicubic :: forall m px. (PrimMonad m, RenderablePixel px, BiSampleable (CubicCoefficient px) px) => MeshPatch px -> DrawContext m px () -- | Render a coon patch using the subdivision algorithm (potentially -- slower and less precise in case of image mesh. renderCoonPatch :: forall m interp px. (PrimMonad m, RenderablePixel px, BiSampleable interp px) => CoonPatch interp -> DrawContext m px () -- | Render a coon patch using the subdivision algorithm (potentially -- slower and less precise in case of image mesh). You can provide a max -- deepness renderCoonPatchAtDeepness :: forall m interp px. (PrimMonad m, RenderablePixel px, BiSampleable interp px) => Int -> CoonPatch interp -> DrawContext m px () renderTensorPatch :: forall m sampled px. (PrimMonad m, RenderablePixel px, BiSampleable sampled px) => TensorPatch sampled -> DrawContext m px () -- | Render a tensor patch using the subdivision algorithm (potentially -- slower and less precise in case of image mesh. renderTensorPatchAtDeepness :: forall m sampled px. (PrimMonad m, RenderablePixel px, BiSampleable sampled px) => Int -> TensorPatch sampled -> DrawContext m px () -- | Used to describe how to debug print a coon/tensort patch. data DebugOption DebugOption :: !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !PixelRGBA8 -> !PixelRGBA8 -> !PixelRGBA8 -> !PixelRGBA8 -> DebugOption [_drawControlMesh] :: DebugOption -> !Bool [_drawBaseVertices] :: DebugOption -> !Bool [_drawControVertices] :: DebugOption -> !Bool [_colorVertices] :: DebugOption -> !Bool [_drawOutline] :: DebugOption -> !Bool [_outlineColor] :: DebugOption -> !PixelRGBA8 [_controlMeshColor] :: DebugOption -> !PixelRGBA8 [_vertexColor] :: DebugOption -> !PixelRGBA8 [_controlColor] :: DebugOption -> !PixelRGBA8 -- | Default options drawing nearly everything. defaultDebug :: DebugOption -- | Draw the 4 bezier spline representing the boundary of a coon patch. drawCoonPatchOutline :: CoonPatch px -> Drawing pxb () -- | Helper function drawing many information about a coon patch. debugDrawCoonPatch :: DebugOption -> CoonPatch (ParametricValues PixelRGBA8) -> Drawing PixelRGBA8 () -- | Helper function drawing many information about a tensor patch. debugDrawTensorPatch :: DebugOption -> TensorPatch (ParametricValues px) -> Drawing PixelRGBA8 () -- | Define the unit square in [0, 1]^2 parametricBase :: UVPatch -- | Split a coon patch into four new quadrants subdividePatch :: CoonPatch UVPatch -> Subdivided (CoonPatch UVPatch) -- | Subdivide a tensor patch into 4 new quadrant. Perform twice the -- horizontal subdivision with a transposition. subdivideTensorPatch :: TensorPatch UVPatch -> Subdivided (TensorPatch UVPatch) -- | Perform an operation like: -- --
-- o--------o--------o--------o -- | | | | -- | | | | -- | | | | -- o--------o--------o--------o -- | | | | -- | | | | -- | | | | -- o--------o--------o--------o -- | | | | -- | | | | -- | | | | -- o--------o--------o--------o -- | | | | -- | | | | -- | | | | -- o--------o--------o--------o -- -- to (more or less) -- -- o----*---o----*----o----*---o -- | | | | | | | -- | | | | | | | -- | | | | | | | -- o----*---o----*----o----*---o -- | | | | | | | -- | | | | | | | -- | | | | | | | -- o----*---o----*----o----*---o -- | | | | | | | -- | | | | | | | -- | | | | | | | -- o----*---o----*----o----*---o -- | | | | | | | -- | | | | | | | -- | | | | | | | -- o----*---o----*----o----*---o -- ------------------------- -- Left Right --horizontalTensorSubdivide :: TensorPatch UVPatch -> (TensorPatch UVPatch, TensorPatch UVPatch) -- | Swap vertical/horizontal orientation of a tensor patch transposePatch :: TensorPatch (ParametricValues a) -> TensorPatch (ParametricValues a) -- | 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 :: Geometry geom => geom -> Drawing px () -- | This function let you choose how to fill the primitives in case of -- self intersection. See FillMethod documentation for more -- information. fillWithMethod :: Geometry geom => FillMethod -> geom -> Drawing px () -- | Render a mesh patch as an object. Warning, there is no antialiasing on -- mesh patch objects! renderMeshPatch :: PatchInterpolation -> MeshPatch 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 :: (Geometry geom) => Float -> Join -> (Cap, Cap) -> geom -> 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 :: Geometry geom => DashPattern -> Float -> Join -> (Cap, Cap) -> geom -> 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 :: Geometry geom => Float -> DashPattern -> Float -> Join -> (Cap, Cap) -> geom -> 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 "test_fonts/DejaVuSans.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 (PointSize 12) (V2 20 40) -- "A simple text test!" ---- -- -- You can use any texture, like a gradient while rendering text. printTextAt :: Font -> PointSize -> Point -> String -> Drawing px () -- | Print complex text, using different texture font and point size for -- different parts of the text. -- --
-- let blackTexture = -- Just . uniformTexture $ PixelRGBA8 0 0 0 255 -- redTexture = -- Just . uniformTexture $ PixelRGBA8 255 0 0 255 -- in -- printTextRanges (V2 20 40) -- [ TextRange font1 (PointSize 12) "A complex " blackTexture -- , TextRange font2 (PointSize 8) "text test" redTexture] ---- printTextRanges :: Point -> [TextRange px] -> 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 () -- | Will render the whole subaction with a given group opacity, after each -- element has been rendered. That means that completly opaque -- overlapping shapes will be rendered transparently, not one after -- another. -- --
-- withTexture (uniformTexture $ PixelRGBA8 0xFF 0x53 0x73 255) $ -- stroke 3 JoinRound (CapRound, CapRound) $ -- line (V2 0 100) (V2 200 100) -- -- withGroupOpacity 128 $ do -- withTexture (uniformTexture $ PixelRGBA8 0 0x86 0xc1 255) . -- fill $ circle (V2 70 100) 60 -- withTexture (uniformTexture $ PixelRGBA8 0xff 0xf4 0xc1 255) . -- fill $ circle (V2 120 100) 60 ---- -- -- To be compared to the item opacity -- --
-- withTexture (uniformTexture $ PixelRGBA8 0xFF 0x53 0x73 255) $ -- stroke 3 JoinRound (CapRound, CapRound) $ -- line (V2 0 100) (V2 200 100) -- withTexture (uniformTexture $ PixelRGBA8 0 0x86 0xc1 128) . -- fill $ circle (V2 70 100) 60 -- withTexture (uniformTexture $ PixelRGBA8 0xff 0xf4 0xc1 128) . -- fill $ circle (V2 120 100) 60 ---- withGroupOpacity :: PixelBaseComponent px -> Drawing px () -> Drawing px () -- | Draw all the sub drawing commands using a transformation. withTransformation :: Transformation -> Drawing px () -> Drawing px () -- | This command allows you to draw primitives on a given curve, for -- example, you can draw text on a curve: -- --
-- let path = Path (V2 100 180) False -- [PathCubicBezierCurveTo (V2 20 20) (V2 170 20) (V2 300 200)] in -- stroke 3 JoinRound (CapStraight 0, CapStraight 0) path -- withTexture (uniformTexture $ PixelRGBA8 0 0 0 255) $ -- withPathOrientation path 0 $ -- printTextAt font (PointSize 24) (V2 0 0) "Text on path" ---- -- -- You can note that the position of the baseline match the size of the -- characters. -- -- You are not limited to text drawing while using this function, you can -- draw arbitrary geometry like in the following example: -- --
-- let path = Path (V2 100 180) False -- [PathCubicBezierCurveTo (V2 20 20) (V2 170 20) (V2 300 200)] -- withTexture (uniformTexture $ PixelRGBA8 0 0 0 255) $ -- stroke 3 JoinRound (CapStraight 0, CapStraight 0) path -- -- withPathOrientation path 0 $ do -- printTextAt font (PointSize 24) (V2 0 0) "TX" -- fill $ rectangle (V2 (-10) (-10)) 30 20 -- fill $ rectangle (V2 45 0) 10 20 -- fill $ rectangle (V2 60 (-10)) 20 20 -- fill $ rectangle (V2 100 (-15)) 20 50 ---- withPathOrientation :: Path -> Float -> Drawing px () -> Drawing px () -- | Structure defining how to render a text range data TextRange px TextRange :: Font -> PointSize -> String -> Maybe (Texture px) -> TextRange px -- | Font used during the rendering [_textFont] :: TextRange px -> Font -- | Size of the text (in pixels) [_textSize] :: TextRange px -> PointSize -- | Text to draw | Texture to use for drawing, if Nothing, the currently -- active texture is used. [_text] :: TextRange px -> String [_textTexture] :: TextRange px -> Maybe (Texture px) -- | Font size expressed in points. You must convert size expressed in -- pixels to point using the DPI information. See pixelSizeInPointAtDpi newtype PointSize :: * PointSize :: Float -> PointSize [getPointSize] :: PointSize -> Float -- | This constraint ensure that a type is a pixel and we're allowed to -- modulate it's color components generically. type ModulablePixel px = (Pixel px, PackeablePixel px, InterpolablePixel px, InterpolablePixel (PixelBaseComponent px), Storable (PackedRepresentation px), Modulable (PixelBaseComponent px)) -- | This constraint tells us that pixel component must also be pixel and -- be the "bottom" of component, we cannot go further than a -- PixelBaseComponent level. -- -- All pixel instances of JuicyPixels should be usable. type RenderablePixel px = (ModulablePixel px, Pixel (PixelBaseComponent px), PackeablePixel (PixelBaseComponent px), Num (PackedRepresentation px), Num (PackedRepresentation (PixelBaseComponent px)), Num (Holder px Float), Num (Holder (PixelBaseComponent px) Float), Storable (PackedRepresentation (PixelBaseComponent px)), PixelBaseComponent (PixelBaseComponent px) ~ (PixelBaseComponent 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. Default DPI is 96 renderDrawing :: forall px. (RenderablePixel px) => Int -> Int -> px -> Drawing px () -> Image 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. renderDrawingAtDpi :: forall px. (RenderablePixel px) => Int -> Int -> Dpi -> px -> Drawing px () -> Image px renderDrawingAtDpiToPDF :: Int -> Int -> Dpi -> Drawing PixelRGBA8 () -> ByteString renderOrdersAtDpiToPdf :: Int -> Int -> Dpi -> [DrawOrder PixelRGBA8] -> ByteString -- | Transform a path description into a list of renderable primitives. pathToPrimitives :: Path -> [Primitive] -- | Reification of texture type data Texture (px :: *) -- | Monad used to record the drawing actions. type Drawing px = F (DrawCommand px) -- | Typeclass intented at pixel value modulation. May be throwed out soon. class (Ord a, Num a) => Modulable a where coverageModulate c a = (clamped, fullValue - clamped) where clamped = modulate a c -- | 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) $ -- 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 [ 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 [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 [ toPrim $ CubicBezier (V2 50 20) (V2 90 60) -- (V2 5 100) (V2 50 140) -- , toPrim $ Line (V2 50 140) (V2 120 80) -- , toPrim $ 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 $ 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 -- | Generalizing constructors of the Primitive type to work -- generically. class Primitivable a toPrim :: Primitivable a => a -> Primitive -- | All the rasterization works on lists of primitives, in order to ease -- the use of the library, the Geometry type class provides conversion -- facility, which help generalising the geometry definition and avoid -- applying Primitive constructor. -- -- Also streamline the Path conversion. class Geometry a where listToPrims = concatMap toPrimitives . toList -- | Convert an element to a list of primitives to be rendered. toPrimitives :: Geometry a => a -> [Primitive] -- | Helper method to avoid overlaping instances. You shouldn't use it -- directly. listToPrims :: (Geometry a, Foldable f) => f a -> [Primitive] -- | This typeclass is there to help transform the geometry, by applying a -- transformation on every point of a geometric element. class Transformable a where transform f = runIdentity . transformM (return . f) -- | Apply a transformation function for every point in the element. transform :: Transformable a => (Point -> Point) -> a -> a -- | Transform but monadic transformM :: (Transformable a, Monad m) => (Point -> m Point) -> a -> m a -- | Typeclass helper gathering all the points of a given geometry. class PointFoldable a -- | Fold an accumulator on all the points of the primitive. foldPoints :: PointFoldable a => (b -> Point -> b) -> b -> a -> b -- | Class used to calculate bounds of various geometrical primitives. The -- calculated is precise, the bounding should be minimal with respect -- with drawn curve. class PlaneBoundable a -- | Given a graphical elements, calculate it's bounds. planeBounds :: PlaneBoundable a => a -> PlaneBound -- | Represent the minimal axis aligned rectangle in which some primitives -- can be drawn. Should fit to bezier curve and not use directly their -- control points. data PlaneBound PlaneBound :: !Point -> !Point -> PlaneBound -- | Corner upper left of the bounding box of the considered primitives. [_planeMinBound] :: PlaneBound -> !Point -- | Corner lower right of the bounding box of the considered primitives. [_planeMaxBound] :: PlaneBound -> !Point -- | Extract the width of the bounds boundWidth :: PlaneBound -> Float -- | Extract the height of the bound boundHeight :: PlaneBound -> Float -- | Extract the position of the lower left corner of the bounds. boundLowerLeftCorner :: PlaneBound -> Point -- | 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 :: 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 :: Image px -> StrokeWidth -> Point -> Drawing px () -- | This function perform an optimisation, it will render a drawing to an -- image interanlly and create a new order to render this image instead -- of the geometry, effectively cuting the geometry generation part. -- -- It can save execution time when drawing complex elements multiple -- times. cacheDrawing :: forall px. (RenderablePixel px) => Int -> Int -> Dpi -> Drawing px () -> Drawing px () -- | Clip the geometry to a rectangle. clip :: Point -> Point -> Primitive -> Container 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] -- | Gives the orientation vector for the start of the primitive. firstTangeantOf :: Primitive -> Vector -- | Gives the orientation vector at the end of the primitive. lastTangeantOf :: Primitive -> Vector -- | Extract the first point of the primitive. firstPointOf :: Primitive -> Point -- | Return the last point of a given primitive. lastPointOf :: Primitive -> Point -- | 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))) -- [ 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 -- | How do we want to perform color/image interpolation within the patch. data PatchInterpolation -- | Bilinear interpolation -- --
-- import qualified Data.Vector as V -- let colorCycle = cycle -- [ PixelRGBA8 0 0x86 0xc1 255 -- , PixelRGBA8 0xff 0xf4 0xc1 255 -- , PixelRGBA8 0xFF 0x53 0x73 255 -- , PixelRGBA8 0xff 0xf4 0xc1 255 -- , PixelRGBA8 0 0x86 0xc1 255] -- colors = V.fromListN (4 * 4) colorCycle -- renderMeshPatch PatchBilinear $ generateLinearGrid 3 3 (V2 10 10) (V2 60 60) colors ---- PatchBilinear :: PatchInterpolation -- | Bicubic interpolation -- --
-- import qualified Data.Vector as V -- let colorCycle = cycle -- [ PixelRGBA8 0 0x86 0xc1 255 -- , PixelRGBA8 0xff 0xf4 0xc1 255 -- , PixelRGBA8 0xFF 0x53 0x73 255 -- , PixelRGBA8 0xff 0xf4 0xc1 255 -- , PixelRGBA8 0 0x86 0xc1 255] -- colors = V.fromListN (4 * 4) colorCycle -- renderMeshPatch PatchBicubic $ generateLinearGrid 3 3 (V2 10 10) (V2 60 60) colors ---- PatchBicubic :: PatchInterpolation -- | Dash pattern to use type DashPattern = [Float] -- | Transform a drawing into a serie of low-level drawing orders. drawOrdersOfDrawing :: forall px. (RenderablePixel px) => Int -> Int -> Dpi -> px -> Drawing px () -> [DrawOrder px] -- | 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, Show (PixelBaseComponent px), PixelBaseComponent (PixelBaseComponent px) ~ (PixelBaseComponent px)) => Drawing px () -> String -- | 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 -- | Reification of texture type data Texture (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 :: 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 gradDef -- (V2 100 100) 75) $ -- fill $ circle (V2 100 100) 100 ---- radialGradientTexture :: 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 gradDef -- (V2 100 100) 75 (V2 70 70) ) $ -- fill $ circle (V2 100 100) 100 ---- radialGradientWithFocusTexture :: Gradient px -> Point -> Float -> Point -> Texture px -- | Use another image as a texture for the filling. Contrary to -- imageTexture, this function perform a bilinear filtering on -- the texture. sampledImageTexture :: Image px -> Texture px -- | Use a drawing as a repeating background pattern. -- --
-- let pattern = -- patternTexture 40 40 96 (PixelRGBA8 0xFF 0x53 0x73 255) . -- withTexture (uniformTexture $ PixelRGBA8 0 0x86 0xc1 255) $ -- fill $ circle (V2 20 20) 13 -- in -- withTexture pattern $ -- fill $ roundedRectangle (V2 20 20) 160 160 20 20 ---- patternTexture :: RenderablePixel px => Int -> Int -> Dpi -> px -> Drawing px () -> Texture px -- | Texture using a mesh patch as definition meshPatchTexture :: PatchInterpolation -> MeshPatch px -> Texture px -- | Perform a multiplication operation between a full color texture and a -- greyscale one, used for clip-path implementation. modulateTexture :: 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