śĪźłt»      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ”¢£¤„¦§Ø©Ŗ«¬­®Æ°±²³“µ¶·ø¹ŗ  Safe-Inferred»/Represent an equation `a * x^2 + b * x + c = 0`¼%Coefficient for the square part (x^2)½Coefficient the linear part (x)¾Constantæ(Discriminant equation, if the result is:3Below 0, then the formula doesn't have any solution0Equal to 0, then the formula has an unique root.&Above 0, the formula has two solutionsĄOExtract all the roots of the formula ie. where the unknown gives a result of 0 »Į¼½¾æĄĀĆ»Į¼½¾æĄ»Į¼½¾æĄĀĆ Safe-Inferred,Free and sparse inner product/metric spaces.MCompute 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 411gCompute the squared norm. The name quadrance arises from Norman J. Wildberger's rational trigonometry.'Compute the quadrance of the difference:Compute the distance between two vectors in a metric space.Compute the norm of a vector in a metric space)Convert a non-zero vector to unit vector.DProvides a fairly subjective test to see if a quantity is near zero.nearZero (1e-11 :: Double)FalsenearZero (1e-17 :: Double)TruenearZero (1e-5 :: Float)FalsenearZero (1e-7 :: Float)True%Determine if a quantity is near zero. 8A vector is an additive group with additional structure. The zero vector Compute the sum of two vectorsV2 1 2 ^+^ V2 3 4V2 4 6 *Compute the difference between two vectorsV2 4 5 - V2 3 1V2 1 4 )Linearly interpolate between two vectors.A 1-dimensional vectorA 2-dimensional vectorpure 1 :: V2 IntV2 1 1V2 1 2 + V2 3 4V2 4 6V2 1 2 * V2 3 4V2 3 8 sum (V2 1 2)3 Compute the right scalar product V2 3 4 ^* 2V2 6 8*Compute division by a scalar on the right. Normalize a  functor to have unit 4. This function does not change the functor if its  is 0 or 1.Ä Å a Ę 1e-12Ē Å a Ę 1e-6  ČÉŹĖÄĒĢĶĪĻŠ    ČÉŹĖÄĒĢĶĪĻŠ   None !"234=K4Actions to create a path1Draw a cubic bezier curve using 2 control points.aDraw a quadratic bezier curve from the current point through the control point to the end point.3Draw a line from the current point to another point¾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) ] docimages/path_example.png=Origin of the point, equivalent to the first "move" command.Tell if we must close the path.List of commands in the pathÅ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) ] docimages/primitive_mixed.png%Primitive used for cubic bezier curve +Primitive used for quadratic beziers curves!Primitive used for lines":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)] docimages/cubic_bezier.png$.Origin point, the spline will pass through it.%.First control point of the cubic bezier curve.&/Second control point of the cubic bezier curve.'#End point of the cubic bezier curve(>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)] docimages/quadratic_bezier.png*/Origin points, the spline will pass through it.++Control point, the spline won't pass on it.,+End point, the spline will pass through it.--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)] docimages/simple_line.png/ Origin point0 End point1?Typeclass helper gathering all the points of a given geometry.28Fold an accumulator on all the points of the primitive.3}This typeclass is there to help transform the geometry, by applying a transformation on every point of a geometric element.4AApply a transformation function for every point in the element.ŃRepresent a raster lineŅHorizontal positionÓVertical positionŌAlphaÕHeight5kDescribe the behaviour of samplers and texturers when they are out of the bounds of image and/or gradient.6Will loop inverting axises docimages/sampler_reflect.png7%Will loop on it's definition domain docimages/sampler_repeat.png8;Will clamp (ie. repeat the last pixel) when out of bound docimages/sampler_pad.png9yTell how to fill complex shapes when there is self intersections. If the filling mode is not specified, then it's the ; method which is used.<The examples used are produced with the following function: ’ž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) ] ]:’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. docimages/fill_evenodd.png;’>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. docimages/fill_winding.png<ADescribe how to display the join of broken lines while stroking.=VMake a mitter join. Value must be positive or null. Seems to make sense in [0;1] onlyMiter join with 0 : docimages/join_miter.pngMiter join with 5 : docimages/join_miter_5.png>Make a curved join. docimages/join_round.png?<Describe how we will "finish" the stroking that don't loop.@(Create a rounded caping on the stroke. docimages/cap_round.pngA‰Create a straight caping on the stroke. Cap value should be positive and represent the distance from the end of curve to the actual capcap straight with param 0 : docimages/cap_straight.pngcap straight with param 1 : docimages/cap_straight_1.pngBDash pattern to useC7Type alias just to get more meaningful type signaturesDRepresent a pointERepresent a vectorFCTransform a path description into a list of renderable primitives.ÖJust to get faster sortingQ×Ų !"#$%&'()*+,-./01234ŃŁŅÓŌÕ56789:;<=>?@ABCDEŚŪÜFŻŽßąįāćäåęēčéźėģķīļÖ=×Ų !"#$%&'()*+,-./01234ŃŁŅÓŌÕ56789:;<=>?@ABCDEŚŪÜF+×Ų! "#$%&'()*+,-./01234ŃŁŅÓŌÕ58769;:<>=?A@BCDEŚŪÜFŻŽßąįāćäåęēčéźėģķīļÖNoneHMH8Traversal type, matched to the one of the lens package.I"Try to match the Lens' type alias.J8Does it look familiar? yes it's the official Lens type.š+Create a full lens out of setter and getterK"Traverse all the points of a line.LLine origin point.MLine end point.N Quadratic bezier starting point.Obezier control point.Pbezier end point.Q%Traversal of all the bezier's points.RCubic bezier first pointS!Cubic bezier first control point.T"Cubic bezier second control point.UCubic bezier last point.V0Traversal of all the points of the cubic bezier.W1Traverse all the points defined in the primitive.X%Traversal of all the points of a pathY&Traversal of all the points in a path.GHIJšKLMNOPQRSTUVWXYGHIJKLMNOPQRSTUVWXYLMKNOPQRSTUVWXYJIHGGHIJšKLMNOPQRSTUVWXYNone Z2Represent a 3*3 matrix for homogenous coordinates. | A C E | | B D F | | 0 0 1 |^ X translationa Y translationb5Effectively transform a point given a transformation.c^Effectively transform a vector given a transformation. The translation part won't be applied.d>Create a transformation representing a rotation on the plane. Wfill . transform (applyTransformation $ rotate 0.2) $ rectangle (V2 40 40) 120 120 docimages/transform_rotate.pngehCreate a transformation representing a rotation on the plane. The rotation center is given in parameter jfill . transform (applyTransformation $ rotateCenter 0.2 (V2 200 200)) $ rectangle (V2 40 40) 120 120 %docimages/transform_rotate_center.pngf*Perform a scaling of the given primitives. Tfill . transform (applyTransformation $ scale 2 2) $ rectangle (V2 40 40) 40 40 docimages/transform_scale.pngg.Perform a translation of the given primitives. afill . transform (applyTransformation $ translate (V2 100 100)) $ rectangle (V2 40 40) 40 40 !docimages/transform_translate.pngh&Skew transformation along the X axis. Tfill . transform (applyTransformation $ skewX 0.3) $ rectangle (V2 50 50) 80 80 docimages/transform_skewx.pngi%Skew transformation along the Y axis. Tfill . transform (applyTransformation $ skewY 0.3) $ rectangle (V2 50 50) 80 80 docimages/transform_skewy.pngj~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.k&Inverse a transformation (if possible)Z[\]^_`ańbcdRotation angle in radian.eRotation angle in radianRotation centerfghijņkóZ[\]^_`abcdefghijkZ[\]^_`abcgfdehijkZ[\]^_`ańbcdefghijņkó NoneōPairwise boolean and operatorõPairwise boolean or operatorö$Pairwise vector/point equal operator÷2Pairwise vector/point lower than or equal operatorų)Pairwise vector/point lower than operatorł%Component/scalar lower than operator.ś*Pairwise vector/point difference operator.ūLMin function between two vector/points. Work on every component separately.üIMax function between to vector/point. Work on every component separatly.ż5Abs function for every component of the vector/point.ž7Floor function for every component of the vector/point.’6ceil function for every component of the vector/point.LGiven a point, clamp every coordinates between a given minimum and maximum.8Given two points, return a point in the middle of them.fGiven a boolean choice vector, return elements of the first one if true, of the second one otherwise.Calculate a normal vector7Return the second operand if the vector is nearly nullmTell if two points are nearly indistinguishable. If indistinguishable, we can treat them as the same point.simply `not (a  b)`ōõö÷ųłśūüżž’ōõö÷ųłśūüżž’ōõö÷ųłśūüżž’ōõö÷ųłś Nonel+Transform a list a point to a list of lines :lineFromPath [a, b, c, d] = [Line a b, Line b c, Line c d]>Clamp the bezier curve inside a rectangle given in parameter.l     2Point representing the "minimal" point for cliping2Point representing the "maximal" point for clipingThe linel     l      None24Mm4Create 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]7Only work if the quadratic bezier curve is nearly flat>Create a quadratic bezier curve representing a straight line.>Clamp the bezier curve inside a rectangle given in parameter.3Rewrite the bezier curve to avoid degenerate cases.1Move the bezier to a new position with an offset. m2Point representing the "minimal" point for cliping2Point representing the "maximal" point for cliping(The quadratic bezier curve to be clamped m mNone!"24MRepresent the cubic bezier curve as a vector ready for matrix multiplicationn: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]FRepresent a circle of radius 1 centered on 0 of a cubic bezier curve.+Find the coefficient of the extremum pointsDClamp the cubic bezier curve inside a rectangle given in parameter.8Will subdivide the bezier from 0 to coeff and coeff to 1 !n"#$ Tolerance%&'()*+,2Point representing the "minimal" point for cliping2Point representing the "maximal" point for cliping$The cubic bezier curve to be clamped-. n"&+,-. !n"#$%&'()*+,-.Noneo!Clip the geometry to a rectangle. /012345o!Minimum point (corner upper left)#Maximum point (corner bottom right)Primitive to be clipped6789/01234o9/012345o6789None24pœClass used to calculate bounds of various geometrical primitives. The calculated is precise, the bounding should be minimal with respect with drawn curve.q2Given a graphical elements, calculate it's bounds.rœ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.tDCorner upper left of the bounding box of the considered primitives.uECorner lower right of the bounding box of the considered primitives.vExtract the width of the boundswExtract the height of the boundx=Extract the position of the lower left corner of the bounds.pqrstuvwx:;<=>? pqrstuvwx pqrstuvwx:;<=>?None@Create a "rounded" join or capAMPut a cap at the end of a bezier curve, depending on the kind of cap wanted.BDDon't make them completly flat, but suficiently to assume they are.y€Return an approximation of the length of a given path. It's results is not precise but should be enough for rough calculationsz]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) [CubicBezierPrim $ CubicBezier (V2 40 160) (V2 40 40) (V2 160 40) (V2 160 160)] "docimages/strokize_dashed_path.pngCDEF@AGHIJKLMNOPQRSByTUzStarting offset#Dashing pattern to use for stroking Stroke widthWhich kind of join will be usedStart and end capping.List of elements to transformNQRyUzCDEF@AGHIJKLMNOPQRSByTUzNone{bThis 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) [CubicBezierPrim $ CubicBezier (V2 40 160) (V2 40 40) (V2 160 40) (V2 160 160)]  docimages/strokize_path.png { Stroke width  Which kind of join will be used Start and end capping. List of elements to strokize Cyz{C{zy{None&3=K |ITypeclass intented at pixel value modulation. May be throwed out soon. V@Empty value representing total transparency for the given type. W8Full value representing total opacity for a given type. XsGiven a Float in [0; 1], return the coverage in [emptyValue; fullValue] The second value is the inverse coverage YEModulate two elements, staying in the [emptyValue; fullValue] range. Z+Implement a division between two elements. [4Like modulate but also return the inverse coverage. }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. 5All pixel instances of JuicyPixels should be usable. ~sThis constraint ensure that a type is a pixel and we're allowed to modulate it's color components generically. |VWXYZ\ coverage inverse coverage  background  foreground ][}~^_`abcd|VWXYZ\][}~^ab |VWXYZ\][}~^_`abcdNone &3=KM‘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)] 5the first stop value must be zero and the last, one. €Reification of texture type egRight now, we must stick to ST, due to the fact that we can't specialize with parameterized monad :( f¬The intent of shader texture is to provide ease of implementation If possible providing a custom filler will be more efficient, like already done for the solid colors. gjThis function will interpret the texture description, helping prepare and optimize the real calculation h>Use another image as a texture for the filling. Contrary to  imageTexture?, this function perform a bilinear filtering on the texture. iwUse another image as a texture for the filling. This texture use the "nearest" filtering, AKA no filtering at all. jzPerform a multiplication operation between a full color texture and a greyscale one, used for clip-path implementation. *klmnopqrst€uvwxyz{|}~€e‚ƒ„…fg†‡ˆ‰ŠGradient description. Linear gradient start point. Linear gradient end point. hi‹Gradient description Radial gradient center Radial gradient radius ŒGradient description Radial gradient center Radial gradient radius Radial gradient focus point j€uvwxyz{|}~€gklmnopqrst€ ~}|{zyxwvu€e‚ƒ„…fg†‡ˆ‰Šhi‹ŒjNone3M@Set the repeat pattern of the texture (if any). With padding:  VwithTexture (sampledImageTexture textureImage) $ fill $ rectangle (V2 0 0) 200 200  !docimages/sampled_texture_pad.png  With repeat:  …withTexture (withSampler SamplerRepeat $ sampledImageTexture textureImage) $ fill $ rectangle (V2 0 0) 200 200  $docimages/sampled_texture_repeat.png With reflect:  †withTexture (withSampler SamplerReflect $ sampledImageTexture textureImage) $ fill $ rectangle (V2 0 0) 200 200  %docimages/sampled_texture_reflect.png ‚dTransform 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  $docimages/sampled_texture_scaled.png ƒHThe uniform texture is the simplest texture of all: an uniform color. „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  docimages/linear_gradient.png …>Use another image as a texture for the filling. Contrary to  imageTexture?, this function perform a bilinear filtering on the texture. †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  docimages/radial_gradient.png ‡,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  #docimages/radial_gradient_focus.png ˆzPerform a multiplication operation between a full color texture and a greyscale one, used for clip-path implementation. ‚ƒ$The color used for all the texture. „Gradient description. Linear gradient start point. Linear gradient end point. …†Gradient description Radial gradient center Radial gradient radius ‡Gradient description Radial gradient center Radial gradient radius Radial gradient focus point ˆThe full blown texture.  A greyscale modulation texture. The resulting texture. €‚ƒ„…†‡ˆ €ƒ„†‡…ˆ‚‚ƒ„…†‡ˆNone 234=HKM‰-Structure defining how to render a text range‹Font used during the renderingŒSize of the text (in pixels)^Text to draw | Texture to use for drawing, if Nothing, the currently active texture is used.)Monad used to record the drawing actions.DThis function will spit out drawing instructions to help debugging.XThe outputted code looks like Haskell, but there is no guarantee that it is compilable.Ž‘’“”•‰Š‹ŒŽ–—Ž‘’“”•‰Š‹ŒŽ•”“’‘މŠ‹ŒŽ–—None &3=HKM ‘UReify a filling function call, to be able to manipulate them in a simpler fashion. “Primitives to be filled. ”#Texture for the filled primitives. •How to fill the primitives. –!Optional mask used for clipping. —,Monad used to describe the drawing context. ˜HTransform back a low level drawing order to a more high level Drawing ™)Render the drawing orders on the canvas. šStart an image rendering. See ›> for an usage example. This function can work with either ˜ or ST. ›Fill some geometry.  ’jimmediateDrawExample :: 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)  docimages/immediate_fill.png œ<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  docimages/immediate_mask.png ‘’“”•–—˜™šRendering width Rendering height Background color Actual drawing computation ™š›#Color/Texture used for the filling Primitives to fill œ3Color/Texture used for the filling of the geometry Texture used for the mask. Primitives to fill ‘’“”•–—˜™š›œ —‘’“”•–˜šœ›™ ‘’“”•–—˜™š™š›œNoneB iCallback function in charge to transform the DrawOrder given the transformation to place it on the path.›šState of the path walker, just a bunch of primitives with continuity guarantee. The continuity is guaranteed by the Path used to derive this primitives.ž4Simpler alias if monad transformers are not needed.ŸThe walking transformer monad. &Create a path walker from a given path”2Advance by the given amount of pixels on the path.œ)Extract the first point of the primitive.¢QObtain the current position if we are still on the path, if not, return Nothing.@Gives the orientation vector for the current point on the path.£XObtain the current tangeant of the path if we're still on it. Return Nothing otherwise.¤†This function is the workhorse of the placement, it will walk the path and calculate the appropriate transformation for every order.›žŸžŸ  ”œ¢£¤-Function handling the placement of the order.Starting offset)Baseline vertical position in the orders."Path on which to place the orders.Orders to place on a path.žŸ ”¢£¤Ÿž ”¢£¤ ›žŸžŸ  ”œ¢£¤None &234=HKM„;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 docimages/with_texture.png¦9Draw all the sub drawing commands using a transformation.§hThis command allows you to draw primitives on a given curve, for example, you can draw text on a curve: ’Elet path = Path (V2 100 180) False [PathCubicBezierCurveTo (V2 20 20) (V2 170 20) (V2 300 200)] in stroke 3 JoinRound (CapStraight 0, CapStraight 0) $ pathToPrimitives path withTexture (uniformTexture $ PixelRGBA8 0 0 0 255) $ withPathOrientation path 0 $ printTextAt font 24 (V2 0 0) "Text on path" docimages/text_on_path.pngQYou 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) $ pathToPrimitives path withPathOrientation path 0 $ do printTextAt font 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 docimages/geometry_on_path.pngØ›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 docimages/fill_circle.png©[This function let you choose how to fill the primitives in case of self intersection. See 9% documentation for more information.Ŗ)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 ] docimages/with_clipping.png«QWill stroke geometry with a given stroke width. The elements should be connected @stroke 5 JoinRound (CapRound, CapRound) $ circle (V2 100 100) 75 docimages/stroke_circle.png¬¹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!" docimages/text_example.png>You can use any texture, like a gradient while rendering text.­aPrint complex text, using different texture font and point size for different parts of the text. "docimages/text_complex_example.png®«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.Æ=Transform a drawing into a serie of low-level drawing orders.°FWith stroke geometry with a given stroke width, using a dash pattern. cdashedStroke [5, 10, 5] 3 JoinRound (CapRound, CapStraight 0) [line (V2 0 100) (V2 200 100)] docimages/dashed_stroke.png±¦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. odashedStrokeWithOffset 3 [5, 10, 5] 3 JoinRound (CapRound, CapStraight 0) [line (V2 0 100) (V2 200 100)] 'docimages/dashed_stroke_with_offset.png²3Generate a list of primitive representing a circle. fill $ circle (V2 100 100) 75 docimages/fill_circle.png³5Generate a list of primitive representing an ellipse. !fill $ ellipse (V2 100 100) 75 30 docimages/fill_ellipse.png“EGenerate a strokable line out of points list. Just an helper around l. Wstroke 4 JoinRound (CapRound, CapRound) $ polyline [V2 10 10, V2 100 70, V2 190 190] docimages/stroke_polyline.pngµ@Generate a fillable polygon out of points list. Similar to the “ function, but close the path. /fill $ polygon [V2 30 30, V2 100 70, V2 80 170] docimages/fill_polygon.png¶6Generate a list of primitive representing a rectangle #fill $ rectangle (V2 30 30) 150 100 docimages/fill_rect.png·oSimply draw an image into the canvas. Take into account any previous transformation performed on the geometry. #drawImage textureImage 0 (V2 30 30) docimages/image_simple.pngø#Draw an image with the desired size 1drawImageAtSize textureImage 2 (V2 30 30) 128 128 docimages/image_resize.png¹KGenerate a list of primitive representing a rectangle with rounded corner. 0fill $ roundedRectangle (V2 10 10) 150 150 20 10 #docimages/fill_roundedRectangle.pngŗ)Return a simple line ready to be stroked. Kstroke 17 JoinRound (CapRound, CapRound) $ line (V2 10 10) (V2 180 170) docimages/stroke_line.png”¢£¤„„¦§Path directing the orientation.5Basline Y axis position, used to align text properly.The sub drawings.Ø©ŖThe clipping pathThe actual geometry to clip« Stroke widthWhich kind of join will be usedStart and end capping.List of elements to render¬ Drawing fontfont Point size"Drawing starting point (base line)String to print­Starting point of the base line Ranges description to be printed®Rendering widthRendering heightBackground colorRendering actionÆRendering widthRendering heightBackground colorRendering action°#Dashing pattern to use for stroking Stroke widthWhich kind of join will be usedStart and end capping.List of elements to render±Starting offset#Dashing pattern to use for stroking Stroke widthWhich kind of join will be usedStart and end capping.List of elements to render²Circle center in pixelsCircle radius in pixels³“µ¶Corner upper leftWidth in pixelHeight in pixel·Image to be drawn(Border size, drawn with current texture./Position of the corner upper left of the image.øImage to be drawn(Border size, drawn with current texture./Position of the corner upper left of the image.Width of the drawn imageHeight of the drawn image¹Corner upper leftWidth in pixelHeight in pixel.8Radius along the x axis of the rounded corner. In pixel.8Radius along the y axis of the rounded corner. In pixel.ŗb !"#$%&'()*+,-./0123456789:;<=>?@ABDEFlmnopqrstuvwx|}~€‰Š‹ŒŽ„¦§Ø©Ŗ«¬­®Æ°±²³“µ¶·ø¹ŗbØ©„Ŗ¦§«°±¬­‰Š‹ŒŽ~}®F€|DE"#$%&'-./0()*+,! 3412pqrstuvwxŗ¶¹²³“µø·omln<>=?A@58769;:BƐ”¢£¤„„¦§Ø©Ŗ«¬­®Æ°±²³“µ¶·ø¹ŗ¦ !"##$$%&' ( ) * + , , - . / 0 1 2 3 4 4 5 6 7 8 9 9 : ; < = = > ? @ A B C D E D F G H I J K L M N O P Q R S TUVWXYZ[\]^_`abcdefghhijklmnopqrstuvwx y z{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”••–—˜™š›œœžŸ ”¢£¤„¦§Ø©Ŗ«¬­®Æ°±²³“µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄ Å Ę Ē Č É Ź Å Ė ĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻ Ž ß ą į ā ć ä å Ž ę ē č é ź ė ģ ķ ī ļ š ń ņ ó ō õ ö ÷ ų ł ś ūüżž’                                  ! " #$%&'($)*+,-./01234567899:;<=>?@ABCDEFGHIJKLMNOPQRSTUV‡WXYZ[\]^_`abcdefghijklmnopq”rstuuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œŃžŸ ”¢£¤¢„©¦¦§Ø©ŖRasterific-0.4.2Graphics.Rasterific.LinearGraphics.RasterificGraphics.Rasterific.OutlineGraphics.Rasterific.Lenses#Graphics.Rasterific.TransformationsGraphics.Rasterific.TextureGraphics.Rasterific.ImmediateGraphics.Rasterific.PathWalker$Graphics.Rasterific.QuadraticFormulaGraphics.Rasterific.TypesGraphics.Rasterific.OperatorsGraphics.Rasterific.Line#Graphics.Rasterific.QuadraticBezierGraphics.Rasterific.CubicBezierGraphics.Rasterific.Rasterize"Graphics.Rasterific.PlaneBoundable"Graphics.Rasterific.StrokeInternalGraphics.Rasterific.CompositorGraphics.Rasterific.ShadingGraphics.Rasterific.CommandMetricdot quadranceqddistancenormsignormEpsilonnearZeroAdditivezero^+^^-^lerpV1V2^*^/ normalize PathCommandPathCubicBezierCurveToPathQuadraticBezierCurveTo PathLineToPath_pathOriginPoint _pathClose _pathCommand PrimitiveCubicBezierPrim BezierPrimLinePrim CubicBezier _cBezierX0 _cBezierX1 _cBezierX2 _cBezierX3Bezier _bezierX0 _bezierX1 _bezierX2Line_lineX0_lineX1 PointFoldable foldPoints Transformable transform SamplerRepeatSamplerReflect SamplerPad FillMethod FillEvenOdd FillWindingJoin JoinMiter JoinRoundCapCapRound CapStraight DashPattern StrokeWidthPointVectorpathToPrimitives Traversal' TraversalLens'Lens linePointslineX0lineX1bezX0bezX1bezX2 bezierPointscbezX0cbezX1cbezX2cbezX3cubicBezierPointsprimitivePointspathCommandPoints pathPointsTransformation _transformA _transformC _transformE _transformB _transformD _transformFapplyTransformationapplyVectorTransformationrotate rotateCenterscale translateskewXskewY toNewXBaseinverseTransformation lineFromPathbezierFromPathcubicBezierFromPathclipPlaneBoundable planeBounds PlaneBound_planeMinBound_planeMaxBound boundWidth boundHeightboundLowerLeftCornerapproximatePathLengthdashedStrokizestrokize ModulableRenderablePixelModulablePixelGradientTexture withSamplertransformTextureuniformTexturelinearGradientTexturesampledImageTextureradialGradientTextureradialGradientWithFocusTexturemodulateTexture TextRange _textFont _textSize_text _textTextureDrawing dumpDrawing DrawOrder_orderPrimitives _orderTexture_orderFillMethod _orderMask DrawContextorderToDrawing fillOrderrunDrawContextfillWithTexturefillWithTextureAndMask PathDrawer PathWalker PathWalkerTrunPathWalking advanceBycurrentPositioncurrentTangeantdrawOrdersOnPath withTexturewithTransformationwithPathOrientationfillfillWithMethod withClippingstroke printTextAtprintTextRanges renderDrawingdrawOrdersOfDrawing dashedStrokedashedStrokeWithOffsetcircleellipsepolylinepolygon rectangle drawImagedrawImageAtSizeroundedRectanglelineQuadraticFormula_coeffA_coeffB_coeffC discriminant formulaRoots$fApplicativeQuadraticFormula$fFunctorQuadraticFormula$fEpsilonDoublebaseGHC.Numabsghc-prim GHC.Classes<=$fEpsilonFloat $fMetricV2 $fAdditiveV1 $fAdditiveV2 $fEpsilonV2$fApplicativeV1$fApplicativeV2 $fFunctorV1$fNumV2 $fFunctorV2 EdgeSample_sampleX_sampleY _sampleAlpha_sampleH$fStorableEdgeSample ContainerProducercontainerOfFunctioncontainerOfListlistOfContainer$fPointFoldablePathCommand$fTransformablePathCommand$fPointFoldablePath$fTransformablePath$fPointFoldablef$fTransformablef$fPointFoldablePrimitive$fTransformablePrimitive$fPointFoldableCubicBezier$fTransformableCubicBezier$fShowCubicBezier$fPointFoldableBezier$fTransformableBezier $fShowBezier$fPointFoldableLine$fTransformableLine $fShowLine$fPointFoldableV2$fTransformableV2lenstransformCombinetransformationDeterminant$fMonoidTransformation^&&^^||^^==^^<=^^<^^<^/=^vminvmaxvabsvfloorvceil clampPointmidPoint vpartitionnormalifZeroisNearbyisDistingableFrommiddleclipLine lineLength sanitizeLine lineBreakAt flattenLine offsetLine decomposeLinebezierLengthApproximation straightLine clipBeziersanitizeBezier offsetBezierdecomposeBeziers bezierBreakAt splitBezier flattenBezier CachedBeziercubicBezierCircle extremumsclipCubicBeziercubicBezierBreakAt_cachedA_cachedB_cachedC_cachedDcubicBezierLengthApproximationisSufficientlyFlatsplitCubicBezierflattenCubicBezier cacheBeziercachedBezierAtcachedBezierDerivativeextremumPointscubicBezierBoundsoffsetCubicBezierdecomposeCubicBezierssanitizeCubicBezier CoverageSpan _coverageX _coverageY _coverageVal_coverageLengthcombineEdgeSamples decompose xyComparesortEdgeSamples rasterize$fPlaneBoundablePrimitive$fPlaneBoundableCubicBezier$fPlaneBoundableBezier$fPlaneBoundableLine$fPlaneBoundableV2$fMonoidPlaneBound roundJoincaplinearizePrimitives lastPointlastPointAndNormalfirstPointAndNormalreversePrimitive lineFromTo miterJoinjoinPrimitivesoffsetPrimitives offsetAndJoinapproximateLengthsanitizeflattenPrimitivebreakPrimitiveAtflattensplitPrimitiveUntil dropPatternapproximatePrimitivesLengthdashize emptyValue fullValue clampCoveragemodulatemodivcoverageModulate alphaOver alphaCompose Compositordiv255toWord8compositionDestinationcompositionAlpha$fModulableWord8$fModulableFloat solidColorshaderOfTexturetransformTextureToFillersampledImageShader imageShader GradientArrayFillerCoverageFillerTextureSpaceInfo_tsStart_tsDelta _tsCoverage _tsRepeat _tsBaseIndexModulateTexture ShaderTexture RawTextureSampledTextureWithTextureTransform WithSamplerRadialGradientWithFocusTextureRadialGradientTextureLinearGradientTexture SolidTextureShaderFunction dumpTexture shaderFillerprepareInfoNoTransform prepareInfocombineTransform withTransrepeatGradientreflectGradientgradientColorAtgradientColorAtRepeatlinearGradientShaderradialGradientShaderradialGradientWithFocusShader DrawCommandWithPathOrientation WithTransform WithCliping SetTextureTextFill DashedStrokeStrokeFill $fMonoidF$fFunctorDrawCommand GHC.TypesIOmapExecisCoverageDrawable WalkerState firstPointOffirstTangeantOf _walkerPrims RenderContext currentClipcurrentTexturecurrentTransformation