Safe Haskell | None |
---|
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 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:
- fill :: [Primitive] -> Drawing px ()
- withTexture :: Texture px -> Drawing px () -> Drawing px ()
- withClipping :: (forall innerPixel. Drawing innerPixel ()) -> Drawing px () -> Drawing px ()
- stroke :: Float -> Join -> (Cap, Cap) -> [Primitive] -> Drawing px ()
- dashedStroke :: DashPattern -> Float -> Join -> (Cap, Cap) -> [Primitive] -> Drawing px ()
- printTextAt :: Font -> Int -> Point -> String -> Drawing px ()
- strokeDebug :: (Pixel px, Modulable (PixelBaseComponent px)) => Texture px -> Texture px -> Float -> Join -> (Cap, Cap) -> [Primitive] -> Drawing px ()
- renderDrawing :: forall px. (Pixel px, Pixel (PixelBaseComponent px), Modulable (PixelBaseComponent px), PixelBaseComponent (PixelBaseComponent px) ~ PixelBaseComponent px) => Int -> Int -> px -> Drawing px () -> Image px
- pathToPrimitives :: Path -> [Primitive]
- type Texture px = SamplerRepeat -> Float -> Float -> px
- type Drawing px a = Free (DrawCommand px) a
- class Ord a => Modulable a
- data V2 a = V2 !a !a
- type Point = V2 Float
- type Vector = V2 Float
- data CubicBezier = CubicBezier {
- _cBezierX0 :: !Point
- _cBezierX1 :: !Point
- _cBezierX2 :: !Point
- _cBezierX3 :: !Point
- data Line = Line {}
- data Bezier = Bezier {}
- data Primitive
- = LinePrim !Line
- | BezierPrim !Bezier
- | CubicBezierPrim !CubicBezier
- data Path = Path {}
- data PathCommand
- class Transformable a where
- line :: Point -> Point -> [Primitive]
- rectangle :: Point -> Float -> Float -> [Primitive]
- circle :: Point -> Float -> [Primitive]
- clip :: Point -> Point -> Primitive -> [Primitive]
- bezierFromPath :: [Point] -> [Bezier]
- lineFromPath :: [Point] -> [Line]
- cubicBezierFromPath :: [Point] -> [CubicBezier]
- data Join
- data Cap
- = CapStraight Float
- | CapRound
- data SamplerRepeat
- type DashPattern = [Float]
Rasterization command
fill :: [Primitive] -> Drawing px ()Source
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
withTexture :: Texture px -> Drawing px () -> Drawing px ()Source
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
:: (forall innerPixel. Drawing innerPixel ()) | The clipping path |
-> Drawing px () | The actual geometry to clip |
-> 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 ]
:: Float | Stroke width |
-> Join | Which kind of join will be used |
-> (Cap, Cap) | Start and end capping. |
-> [Primitive] | List of elements to render |
-> 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
:: DashPattern | Dashing pattern to use for stroking |
-> Float | Stroke width |
-> Join | Which kind of join will be used |
-> (Cap, Cap) | Start and end capping. |
-> [Primitive] | List of elements to render |
-> 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)]
:: Font | Drawing font |
-> Int | font Point size |
-> Point | Baseline begining position |
-> String | String to print |
-> 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 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.
strokeDebug :: (Pixel px, Modulable (PixelBaseComponent px)) => Texture px -> Texture px -> Float -> Join -> (Cap, Cap) -> [Primitive] -> Drawing px ()Source
Internal debug function
:: forall px . (Pixel px, Pixel (PixelBaseComponent px), Modulable (PixelBaseComponent px), PixelBaseComponent (PixelBaseComponent px) ~ PixelBaseComponent px) | |
=> Int | Rendering width |
-> Int | Rendering height |
-> px | Background color |
-> Drawing px () | Rendering action |
-> 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.
pathToPrimitives :: Path -> [Primitive]Source
Transform a path description into a list of renderable primitives.
Rasterization types
type Texture px = SamplerRepeat -> Float -> Float -> pxSource
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.
class Ord a => Modulable a Source
Typeclass intented at pixel value modulation. May be throwed out soon.
Geometry description
data V2 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
V2 !a !a |
Monad V2 | |
Functor V2 | |
Typeable1 V2 | |
Applicative V2 | |
Foldable V2 | |
Traversable V2 | |
Generic1 V2 | |
Distributive V2 | |
R2 V2 | |
R1 V2 | |
Core V2 | |
Metric V2 | |
Additive V2 | |
Traversable1 V2 | |
Foldable1 V2 | |
Apply V2 | |
Bind V2 | |
Eq a => Eq (V2 a) | |
Fractional a => Fractional (V2 a) | |
Data a => Data (V2 a) | |
Num a => Num (V2 a) | |
Ord a => Ord (V2 a) | |
Read a => Read (V2 a) | |
Show a => Show (V2 a) | |
Ix a => Ix (V2 a) | |
Generic (V2 a) | |
Storable a => Storable (V2 a) | |
Epsilon a => Epsilon (V2 a) |
data CubicBezier Source
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)]
CubicBezier | |
|
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)]
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)]
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) ]
LinePrim !Line | Primitive used for lines |
BezierPrim !Bezier | Primitive used for quadratic beziers curves |
CubicBezierPrim !CubicBezier | Primitive used for cubic bezier curve |
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) ]
Path | |
|
data PathCommand Source
Actions to create a path
PathLineTo Point | Draw a line from the current point to another point |
PathQuadraticBezierCurveTo Point Point | Draw a quadratic bezier curve from the current point through the control point to the end point. |
PathCubicBezierCurveTo Point Point Point | Draw a cubic bezier curve using 2 control points. |
class Transformable a whereSource
This typeclass is there to help transform the geometry, by applying a transformation on every point of a geometric element.
Helpers
line :: Point -> Point -> [Primitive]Source
Return a simple line ready to be stroked.
stroke 17 JoinRound (CapRound, CapRound) $ line (V2 10 10) (V2 180 170)
Generate a list of primitive representing a rectangle
fill $ rectangle (V2 30 30) 150 100
Generate a list of primitive representing a circle.
fill $ circle (V2 100 100) 75
Geometry Helpers
:: Point | Minimum point (corner upper left) |
-> Point | Maximum point (corner bottom right) |
-> Primitive | Primitive to be clipped |
-> [Primitive] |
Clip the geometry to a rectangle.
bezierFromPath :: [Point] -> [Bezier]Source
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]
lineFromPath :: [Point] -> [Line]Source
Transform a list a point to a list of lines
lineFromPath [a, b, c, d] = [Line a b, Line b c, Line c d]
cubicBezierFromPath :: [Point] -> [CubicBezier]Source
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]
Rasterization control
Describe how to display the join of broken lines while stroking.
Describe how we will finish the stroking that don't loop.
CapStraight Float | Create a straight caping on the stroke. Cap value should be positive and represent the distance from the end of curve to the actual cap
|
CapRound | Create a rounded caping on the stroke. |
data SamplerRepeat Source
Describe the behaviour of samplers and texturers when they are out of the bounds of image and/or gradient.
SamplerPad | Will clamp (ie. repeat the last pixel) when out of bound |
SamplerRepeat | Will loop on it's definition domain |
SamplerReflect | Will loop inverting axises |
type DashPattern = [Float]Source
Dash pattern to use