nanovg-0.1.0.0: src/NanoVG/Internal.chs
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RecordWildCards #-}
module NanoVG.Internal
( FileName(..)
, Image(..)
, Font(..)
, Context(..)
, Transformation(..)
, Extent(..)
, Color(..)
, Paint(..)
, Bounds(..)
, GlyphPosition(..)
, GlyphPositionPtr
, TextRow(..)
, TextRowPtr
, CreateFlags(..)
, Solidity(..)
, LineCap(..)
, Align(..)
, Winding(..)
, beginFrame
, cancelFrame
, endFrame
-- * Color utils
, rgb
, rgbf
, rgba
, rgbaf
, lerpRGBA
, transRGBA
, transRGBAf
, hsl
, hsla
-- * State handling
, save
, restore
, reset
-- * Render styles
, strokeColor
, strokePaint
, fillColor
, fillPaint
, miterLimit
, strokeWidth
, lineCap
, lineJoin
, globalAlpha
-- * Transforms
, resetTransform
, transform
, translate
, rotate
, skewX
, skewY
, scale
, currentTransform
, transformIdentity
, transformTranslate
, transformScale
, transformRotate
, transformSkewX
, transformSkewY
, transformMultiply
, transformPremultiply
, transformInverse
, transformPoint
, degToRad
, radToDeg
-- * Images
, createImage
, createImageMem
, createImageRGBA
, updateImage
, imageSize
, deleteImage
-- * Paints
, linearGradient
, boxGradient
, radialGradient
, imagePattern
-- * Scissoring
, scissor
, intersectScissor
, resetScissor
-- * Paths
, beginPath
, moveTo
, lineTo
, bezierTo
, quadTo
, arcTo
, closePath
, pathWinding
, arc
, rect
, roundedRect
, ellipse
, circle
, fill
, stroke
-- * Text
, createFont
, createFontMem
, findFont
, fontSize
, fontBlur
, textLetterSpacing
, textLineHeight
, textAlign
, fontFaceId
, fontFace
, text
, textBox
, textBounds
, textBoxBounds
, textGlyphPositions
, textMetrics
, textBreakLines
-- * GL
, createGL3
, deleteGL3
, createImageFromHandleGL3
, imageHandleGL3
) where
import Data.Bits hiding (rotate)
import Data.ByteString hiding (null)
import qualified Data.Set as S
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.Word
import Foreign.C.String (CString)
import Foreign.C.Types
import Foreign.Marshal.Alloc
import Foreign.Marshal.Utils
import Foreign.Ptr
import Foreign.Storable
import Linear.Matrix
import Linear.V2
import Linear.V3
import Linear.V4
import Prelude hiding (null)
-- For now only the GL3 backend is supported
#define NANOVG_GL3
-- We need to include this to define GLuint
#include "GL/glew.h"
#include "nanovg.h"
#include "nanovg_gl.h"
#include "nanovg_wrapper.h"
-- | Marshal a Haskell string into a NUL terminated C string using temporary storage.
withCString :: T.Text -> (CString -> IO b) -> IO b
withCString t = useAsCString (T.encodeUtf8 t)
-- | Wrapper around 'useAsCStringLen' that uses 'CUChar's
useAsCStringLen' :: ByteString -> ((Ptr CUChar,CInt) -> IO a) -> IO a
useAsCStringLen' bs f = useAsCStringLen bs (\(ptr,len) -> f (castPtr ptr,fromIntegral len))
-- | Wrapper around 'useAsCStringLen'' that discards the length
useAsPtr :: ByteString -> (Ptr CUChar -> IO a) -> IO a
useAsPtr bs f = useAsCStringLen' bs (f . fst)
-- | Marshalling helper for a constant zero
zero :: Num a => (a -> b) -> b
zero f = f 0
-- | Marshalling helper for a constant 'nullPtr'
null :: (Ptr a -> b) -> b
null f = f nullPtr
-- | Newtype to avoid accidental use of strings
newtype FileName = FileName { unwrapFileName :: T.Text }
-- | Newtype to avoid accidental use of ints
newtype Image = Image {imageHandle :: CInt} deriving (Show,Read,Eq,Ord)
-- | Newtype to avoid accidental use of ints
newtype Font = Font {fontHandle :: CInt} deriving (Show,Read,Eq,Ord)
-- | Opaque context that needs to be passed around
{#pointer *NVGcontext as Context newtype#}
-- | Affine matrix
--
-- > [sx kx tx]
-- > [ky sy ty]
-- > [ 0 0 1]
newtype Transformation = Transformation (M23 CFloat) deriving (Show,Read,Eq,Ord)
instance Storable Transformation where
sizeOf _ = sizeOf (0 :: CFloat) * 6
alignment _ = alignment (0 :: CFloat)
peek p =
do let p' = castPtr p :: Ptr CFloat
a <- peek p'
b <- peekElemOff p' 1
c <- peekElemOff p' 2
d <- peekElemOff p' 3
e <- peekElemOff p' 4
f <- peekElemOff p' 5
pure (Transformation
(V2 (V3 a c e)
(V3 b d f)))
poke p (Transformation (V2 (V3 a c e) (V3 b d f))) =
do let p' = castPtr p :: Ptr CFloat
poke p' a
pokeElemOff p' 1 b
pokeElemOff p' 2 c
pokeElemOff p' 3 d
pokeElemOff p' 4 e
pokeElemOff p' 5 f
newtype Extent = Extent (V2 CFloat) deriving (Show,Read,Eq,Ord)
instance Storable Extent where
sizeOf _ = sizeOf (0 :: CFloat) * 2
alignment _ = alignment (0 :: CFloat)
peek p =
do let p' = castPtr p :: Ptr CFloat
a <- peekElemOff p' 0
b <- peekElemOff p' 1
pure (Extent (V2 a b))
poke p (Extent (V2 a b)) =
do let p' = castPtr p :: Ptr CFloat
pokeElemOff p' 0 a
pokeElemOff p' 1 b
-- | rgba
data Color = Color !CFloat !CFloat !CFloat !CFloat deriving (Show,Read,Eq,Ord)
{#pointer *NVGcolor as ColorPtr -> Color#}
instance Storable Color where
sizeOf _ = sizeOf (0 :: CFloat) * 4
alignment _ = alignment (0 :: CFloat)
peek p =
do let p' = castPtr p :: Ptr CFloat
r <- peek p'
g <- peekElemOff p' 1
b <- peekElemOff p' 2
a <- peekElemOff p' 3
pure (Color r g b a)
poke p (Color r g b a) =
do let p' = castPtr p :: Ptr CFloat
poke p' r
pokeElemOff p' 1 g
pokeElemOff p' 2 b
pokeElemOff p' 3 a
data Paint =
Paint {xform :: Transformation
,extent :: Extent
,radius :: !CFloat
,feather :: !CFloat
,innerColor :: !Color
,outerColor :: !Color
,image :: !Image} deriving (Show,Read,Eq,Ord)
{#pointer *NVGpaint as PaintPtr -> Paint#}
instance Storable Paint where
sizeOf _ = 76
alignment _ = 4
peek p =
do xform <- peek (castPtr (p `plusPtr` {#offsetof NVGpaint->xform#}))
extent <- peek (castPtr (p `plusPtr` {#offsetof NVGpaint->extent#}))
radius <- {#get NVGpaint->radius#} p
feather <- {#get NVGpaint->feather#} p
innerColor <- peek (castPtr (p `plusPtr` 40))
outerColor <- peek (castPtr (p `plusPtr` 56))
image <- peek (castPtr (p `plusPtr` 72))
pure (Paint xform extent radius feather innerColor outerColor (Image image))
poke p (Paint{..}) =
do poke (castPtr (p `plusPtr` {#offsetof NVGpaint->xform#})) xform
poke (castPtr (p `plusPtr` {#offsetof NVGpaint->extent#})) extent
{#set NVGpaint->radius#} p radius
{#set NVGpaint->feather#} p feather
poke (castPtr (p `plusPtr` 40)) innerColor
poke (castPtr (p `plusPtr` 56)) outerColor
poke (castPtr (p `plusPtr` 72)) (imageHandle image)
{#enum NVGwinding as Winding
{} with prefix = "NVG_"
deriving (Show,Read,Eq,Ord)#}
{#enum NVGsolidity as Solidity
{underscoreToCase} with prefix = "NVG_"
deriving (Show,Read,Eq,Ord)#}
{#enum NVGlineCap as LineCap
{underscoreToCase} with prefix = "NVG_"
deriving (Show,Read,Eq,Ord)#}
{#enum NVGalign as Align
{underscoreToCase} with prefix = "NVG_"
deriving (Show,Read,Eq,Ord)#}
data GlyphPosition =
GlyphPosition { -- | Pointer of the glyph in the input string.
str :: !(Ptr CChar)
-- | The x-coordinate of the logical glyph position.
, glyphX :: !CFloat
-- | The left bound of the glyph shape.
, glyphPosMinX :: !CFloat
-- | The right bound of the glyph shape.
, glyphPosMaxX :: !CFloat} deriving (Show,Eq,Ord)
{#pointer *NVGglyphPosition as GlyphPositionPtr -> GlyphPosition#}
instance Storable GlyphPosition where
sizeOf _ = 24
alignment _ = {#alignof NVGglyphPosition#}
peek p =
do str <- {#get NVGglyphPosition->str#} p
x <- {#get NVGglyphPosition->x#} p
minx <- {#get NVGglyphPosition->minx#} p
maxx <- {#get NVGglyphPosition->maxx#} p
pure (GlyphPosition str x minx maxx)
poke p (GlyphPosition str x minx maxx) =
do {#set NVGglyphPosition->str#} p str
{#set NVGglyphPosition->x#} p x
{#set NVGglyphPosition->minx#} p minx
{#set NVGglyphPosition->maxx#} p maxx
data TextRow =
TextRow { -- | Pointer to the input text where the row starts.
start :: !(Ptr CChar)
-- | Pointer to the input text where the row ends (one past the last character).
, end :: !(Ptr CChar)
-- | Pointer to the beginning of the next row.
, next :: !(Ptr CChar)
-- | Logical width of the row.
, width :: !CFloat
-- | Actual bounds of the row. Logical with and bounds can differ because of kerning and some parts over extending.
, textRowMinX :: !CFloat
, textRowMaxX :: !CFloat}
deriving (Show,Eq,Ord)
instance Storable TextRow where
sizeOf _ = 40
alignment _ = {#alignof NVGtextRow#}
peek p =
do start <- {#get NVGtextRow->start#} p
end <- {#get NVGtextRow->end#} p
next <- {#get NVGtextRow->next#} p
width <- {#get NVGtextRow->width#} p
minX <- {#get NVGtextRow->minx#} p
maxX <- {#get NVGtextRow->maxx#} p
pure (TextRow start end next width minX maxX)
poke p (TextRow {..}) =
do {#set NVGtextRow->start#} p start
{#set NVGtextRow->end#} p end
{#set NVGtextRow->next#} p next
{#set NVGtextRow->width#} p width
{#set NVGtextRow->minx#} p textRowMinX
{#set NVGtextRow->maxx#} p textRowMaxX
{#pointer *NVGtextRow as TextRowPtr -> TextRow#}
{#enum NVGimageFlags as ImageFlags
{underscoreToCase} with prefix = "NVG_"
deriving (Show,Read,Eq,Ord)#}
-- | Begin drawing a new frame
--
-- Calls to nanovg drawing API should be wrapped in 'beginFrame' & 'endFrame'.
--
-- 'beginFrame' defines the size of the window to render to in relation currently
-- set viewport (i.e. glViewport on GL backends). Device pixel ration allows to
-- control the rendering on Hi-DPI devices.
--
-- For example, GLFW returns two dimension for an opened window: window size and
-- frame buffer size. In that case you would set windowWidth/Height to the window size
-- devicePixelRatio to: frameBufferWidth / windowWidth.
{#fun unsafe nvgBeginFrame as beginFrame
{`Context',`CInt',`CInt',`Float'} -> `()'#}
-- | Cancels drawing the current frame.
{#fun unsafe nvgCancelFrame as cancelFrame
{`Context'} -> `()'#}
-- | Ends drawing flushing remaining render state.
{#fun unsafe nvgEndFrame as endFrame
{`Context'} -> `()'#}
-- | Returns a color value from red, green, blue values. Alpha will be set to 255 (1.0f).
{#fun pure unsafe nvgRGB_ as rgb
{id`CUChar',id`CUChar',id`CUChar',alloca-`Color'peek*} -> `()'#}
-- | Returns a color value from red, green, blue values. Alpha will be set to 1.0f.
{#fun pure unsafe nvgRGBf_ as rgbf
{`CFloat',`CFloat',`CFloat',alloca-`Color'peek*} -> `()'#}
-- | Returns a color value from red, green, blue and alpha values.
{#fun pure unsafe nvgRGBA_ as rgba
{id`CUChar',id`CUChar',id`CUChar',id`CUChar',alloca-`Color'peek*} -> `()'#}
-- | Returns a color value from red, green, blue and alpha values.
{#fun pure unsafe nvgRGBAf_ as rgbaf
{`CFloat',`CFloat',`CFloat',`CFloat',alloca-`Color'peek*} -> `()'#}
-- | Linearly interpolates from color c0 to c1, and returns resulting color value.
{#fun pure unsafe nvgLerpRGBA_ as lerpRGBA
{with*`Color',with*`Color',`CFloat',alloca-`Color'peek*} -> `()'#}
-- | Sets transparency of a color value.
{#fun pure unsafe nvgTransRGBA_ as transRGBA
{with*`Color',id`CUChar',alloca-`Color'peek*} -> `()'#}
-- | Sets transparency of a color value.
{#fun pure unsafe nvgTransRGBAf_ as transRGBAf
{with*`Color',`CFloat',alloca-`Color'peek*} -> `()'#}
-- | Returns color value specified by hue, saturation and lightness.
-- HSL values are all in range [0..1], alpha will be set to 255.
{#fun pure unsafe nvgHSL_ as hsl
{`CFloat',`CFloat',`CFloat',alloca-`Color'peek*} -> `()'#}
-- | Returns color value specified by hue, saturation and lightness and alpha.
-- HSL values are all in range [0..1], alpha in range [0..255]
{#fun pure unsafe nvgHSLA_ as hsla
{`CFloat',`CFloat',`CFloat',id`CUChar',alloca-`Color'peek*} -> `()'#}
-- | Pushes and saves the current render state into a state stack.
-- A matching 'restore' must be used to restore the state.
{#fun unsafe nvgSave as save
{`Context'} -> `()'#}
-- | Pops and restores current render state.
{#fun unsafe nvgRestore as restore
{`Context'} -> `()'#}
-- | Resets current render state to default values. Does not affect the render state stack.
{#fun unsafe nvgReset as reset
{`Context'} -> `()'#}
-- | Sets current stroke style to a solid color.
{#fun unsafe nvgStrokeColor_ as strokeColor
{`Context',with*`Color'} -> `()'#}
-- | Sets current stroke style to a paint, which can be a one of the gradients or a pattern.
{#fun unsafe nvgStrokePaint_ as strokePaint
{`Context',with*`Paint'} -> `()'#}
-- | Sets current fill style to a solid color.
{#fun unsafe nvgFillColor_ as fillColor
{`Context',with*`Color'} -> `()'#}
-- | Sets current fill style to a paint, which can be a one of the gradients or a pattern.
{#fun unsafe nvgFillPaint_ as fillPaint
{`Context',with*`Paint'} -> `()'#}
-- | Sets the miter limit of the stroke style.
-- Miter limit controls when a sharp corner is beveled.
{#fun unsafe nvgMiterLimit as miterLimit
{`Context',`CFloat'} -> `()'#}
-- | Sets the stroke width of the stroke style.
{#fun unsafe nvgStrokeWidth as strokeWidth
{`Context',`CFloat'} -> `()'#}
-- | Sets how the end of the line (cap) is drawn,
-- Can be one of: 'Butt' (default), 'Round', 'Square'.
{#fun unsafe nvgLineCap as lineCap
{`Context',`LineCap'} -> `()'#}
-- | Sets how sharp path corners are drawn.
-- Can be one of 'Miter' (default), 'Round', 'Bevel.
{#fun unsafe nvgLineJoin as lineJoin
{`Context',`LineCap'} -> `()'#}
-- | Sets the transparency applied to all rendered shapes.
-- Already transparent paths will get proportionally more transparent as well.
{#fun unsafe nvgGlobalAlpha as globalAlpha
{`Context',`CFloat'} -> `()'#}
-- | Resets current transform to a identity matrix.
{#fun unsafe nvgResetTransform as resetTransform
{`Context'} -> `()'#}
-- | Premultiplies current coordinate system by specified matrix.
-- The parameters are interpreted as matrix as follows:
--
-- > [a c e]
-- > [b d f]
-- > [0 0 1]
{#fun unsafe nvgTransform as transform
{`Context',`CFloat',`CFloat',`CFloat',`CFloat',`CFloat',`CFloat'} -> `()'#}
-- | Translates current coordinate system.
{#fun unsafe nvgTranslate as translate
{`Context',`CFloat',`CFloat'} -> `()'#}
-- | Rotates current coordinate system. Angle is specified in radians.
{#fun unsafe nvgRotate as rotate
{`Context',`CFloat'} -> `()'#}
-- | Skews the current coordinate system along X axis. Angle is specified in radians.
{#fun unsafe nvgSkewX as skewX
{`Context',`CFloat'} -> `()'#}
-- | Skews the current coordinate system along Y axis. Angle is specified in radians.
{#fun unsafe nvgSkewY as skewY
{`Context',`CFloat'} -> `()'#}
-- | Scales the current coordinate system.
{#fun unsafe nvgScale as scale
{`Context',`CFloat',`CFloat'} -> `()'#}
peekTransformation :: Ptr CFloat -> IO Transformation
peekTransformation = peek . castPtr
allocaTransformation :: (Ptr CFloat -> IO b) -> IO b
allocaTransformation f = alloca (\(p :: Ptr Transformation) -> f (castPtr p))
withTransformation :: Transformation -> (Ptr CFloat -> IO b) -> IO b
withTransformation t f = with t (\p -> f (castPtr p))
-- | Returns the current transformation matrix.
{#fun unsafe nvgCurrentTransform as currentTransform
{`Context',allocaTransformation-`Transformation'peekTransformation*} -> `()'#}
-- | Sets the transform to identity matrix.
{#fun unsafe nvgTransformIdentity as transformIdentity
{allocaTransformation-`Transformation'peekTransformation*} -> `()'#}
-- | Sets the transform to translation matrix matrix.
{#fun unsafe nvgTransformTranslate as transformTranslate
{allocaTransformation-`Transformation'peekTransformation*,`CFloat',`CFloat'} -> `()'#}
-- | Sets the transform to scale matrix.
{#fun unsafe nvgTransformScale as transformScale
{allocaTransformation-`Transformation'peekTransformation*,`CFloat',`CFloat'} -> `()'#}
-- | Sets the transform to rotate matrix. Angle is specified in radians.
{#fun unsafe nvgTransformRotate as transformRotate
{allocaTransformation-`Transformation'peekTransformation*,`CFloat'} -> `()'#}
-- | Sets the transform to skew-x matrix. Angle is specified in radians.
{#fun unsafe nvgTransformSkewX as transformSkewX
{allocaTransformation-`Transformation'peekTransformation*,`CFloat'} -> `()'#}
-- | Sets the transform to skew-y matrix. Angle is specified in radians.
{#fun unsafe nvgTransformSkewY as transformSkewY
{allocaTransformation-`Transformation'peekTransformation*,`CFloat'} -> `()'#}
-- | Sets the transform to the result of multiplication of two transforms, of A = A*B.
{#fun unsafe nvgTransformMultiply as transformMultiply
{withTransformation*`Transformation'peekTransformation*,withTransformation*`Transformation'} -> `()'#}
-- | Sets the transform to the result of multiplication of two transforms, of A = B*A.
{#fun unsafe nvgTransformPremultiply as transformPremultiply
{withTransformation*`Transformation'peekTransformation*,withTransformation*`Transformation'} -> `()'#}
-- | Sets the destination to inverse of specified transform.
-- Returns 1 if the inverse could be calculated, else 0.
{#fun unsafe nvgTransformInverse as transformInverse
{allocaTransformation-`Transformation'peekTransformation*,withTransformation*`Transformation'} -> `()'#}
-- | Transform a point by given transform.
{#fun pure unsafe nvgTransformPoint as transformPoint
{alloca-`CFloat'peek*,alloca-`CFloat'peek*,withTransformation*`Transformation',`CFloat',`CFloat'} -> `()'#}
-- | Converts degrees to radians.
{#fun pure unsafe nvgDegToRad as degToRad
{`CFloat'} -> `CFloat'#}
-- | Converts radians to degrees.
{#fun pure unsafe nvgRadToDeg as radToDeg
{`CFloat'} -> `CFloat'#}
safeImage :: CInt -> Maybe Image
safeImage i
| i < 0 = Nothing
| otherwise = Just (Image i)
-- | Creates image by loading it from the disk from specified file name.
{#fun unsafe nvgCreateImage as createImage
{`Context','withCString.unwrapFileName'*`FileName',`CInt'} -> `Maybe Image'safeImage#}
-- | Creates image by loading it from the specified chunk of memory.
{#fun unsafe nvgCreateImageMem as createImageMem
{`Context',`ImageFlags',useAsCStringLen'*`ByteString'&} -> `Maybe Image'safeImage#}
-- | Creates image from specified image data.
{#fun unsafe nvgCreateImageRGBA as createImageRGBA
{`Context',`CInt',`CInt',`ImageFlags',useAsPtr*`ByteString'} -> `Maybe Image'safeImage#}
-- | Updates image data specified by image handle.
{#fun unsafe nvgUpdateImage as updateImage
{`Context',imageHandle`Image',useAsPtr*`ByteString'} -> `()'#}
-- | Returns the dimensions of a created image.
{#fun unsafe nvgImageSize as imageSize
{`Context',imageHandle`Image',alloca-`CInt'peek*,alloca-`CInt'peek*} -> `()'#}
-- | Deletes created image.
{#fun unsafe nvgDeleteImage as deleteImage
{`Context',imageHandle`Image'} -> `()'#}
-- | Creates and returns a linear gradient. Parameters (sx,sy)-(ex,ey) specify the start and end coordinates
-- of the linear gradient, icol specifies the start color and ocol the end color.
-- The gradient is transformed by the current transform when it is passed to 'fillPaint' or 'strokePaint'.
{#fun unsafe nvgLinearGradient_ as linearGradient
{`Context',`CFloat',`CFloat',`CFloat',`CFloat',with*`Color',with*`Color',alloca-`Paint'peek*} -> `()'#}
-- | Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering
-- drop shadows or highlights for boxes. Parameters (x,y) define the top-left corner of the rectangle,
-- (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry
-- the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient.
-- The gradient is transformed by the current transform when it is passed to 'fillPaint' or 'strokePaint'.
{#fun unsafe nvgBoxGradient_ as boxGradient
{`Context',`CFloat',`CFloat',`CFloat',`CFloat',`CFloat',`CFloat',with*`Color',with*`Color',alloca-`Paint'peek*} -> `()'#}
-- | Creates and returns a radial gradient. Parameters (cx,cy) specify the center, inr and outr specify
-- the inner and outer radius of the gradient, icol specifies the start color and ocol the end color.
-- The gradient is transformed by the current transform when it is passed to 'fillPaint' or 'strokePaint'.
{#fun unsafe nvgRadialGradient_ as radialGradient
{`Context',`CFloat',`CFloat',`CFloat',`CFloat',with*`Color',with*`Color',alloca-`Paint'peek*} -> `()'#}
-- | Creates and returns an image patter. Parameters (ox,oy) specify the left-top location of the image pattern,
-- (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render.
-- The gradient is transformed by the current transform when it is passed to 'fillPaint' or 'strokePaint'.
{#fun unsafe nvgImagePattern_ as imagePattern
{`Context',`CFloat',`CFloat',`CFloat',`CFloat',`CFloat',imageHandle`Image',`CFloat',alloca-`Paint'peek*} -> `()'#}
-- | Sets the current scissor rectangle.
-- The scissor rectangle is transformed by the current transform.
{#fun unsafe nvgScissor as scissor
{`Context',`CFloat',`CFloat',`CFloat',`CFloat'} -> `()'#}
-- | Intersects current scissor rectangle with the specified rectangle.
-- The scissor rectangle is transformed by the current transform.
-- Note: in case the rotation of previous scissor rect differs from
-- the current one, the intersection will be done between the specified
-- rectangle and the previous scissor rectangle transformed in the current
-- transform space. The resulting shape is always rectangle.
{#fun unsafe nvgIntersectScissor as intersectScissor
{`Context',`CFloat',`CFloat',`CFloat',`CFloat'} -> `()'#}
-- | Reset and disables scissoring.
{#fun unsafe nvgResetScissor as resetScissor
{`Context'} -> `()'#}
-- | Clears the current path and sub-paths.
{#fun unsafe nvgBeginPath as beginPath
{`Context'} -> `()'#}
-- | Starts new sub-path with specified point as first point.
{#fun unsafe nvgMoveTo as moveTo
{`Context',`CFloat',`CFloat'} -> `()'#}
-- | Adds line segment from the last point in the path to the specified point.
{#fun unsafe nvgLineTo as lineTo
{`Context',`CFloat',`CFloat'} -> `()'#}
-- | Adds cubic bezier segment from last point in the path via two control points to the specified point.
{#fun unsafe nvgBezierTo as bezierTo
{`Context',`CFloat',`CFloat',`CFloat',`CFloat',`CFloat',`CFloat'} -> `()'#}
-- | Adds quadratic bezier segment from last point in the path via a control point to the specified point
{#fun unsafe nvgQuadTo as quadTo
{`Context',`CFloat',`CFloat',`CFloat',`CFloat'} -> `()'#}
-- | Adds an arc segment at the corner defined by the last path point, and two specified points.
{#fun unsafe nvgArcTo as arcTo
{`Context',`CFloat',`CFloat',`CFloat',`CFloat',`CFloat'} -> `()'#}
-- | Closes current sub-path with a line segment.
{#fun unsafe nvgClosePath as closePath
{`Context'} -> `()'#}
-- | Sets the current sub-path winding, see NVGwinding and NVGsolidity.
{#fun unsafe nvgPathWinding as pathWinding
{`Context', `CInt'} -> `()'#}
-- | Creates new circle arc shaped sub-path. The arc center is at cx,cy, the arc radius is r,
-- and the arc is drawn from angle a0 to a1, and swept in direction dir (NVG_CCW, or NVG_CW).
-- Angles are specified in radians.
{#fun unsafe nvgArc as arc
{`Context',`CFloat',`CFloat', `CFloat', `CFloat', `CFloat', `Winding'} -> `()'#}
-- | Creates new rectangle shaped sub-path.
{#fun unsafe nvgRect as rect
{`Context',`CFloat',`CFloat',`CFloat',`CFloat'} -> `()'#}
-- | Creates new rounded rectangle shaped sub-path.
{#fun unsafe nvgRoundedRect as roundedRect
{`Context',`CFloat',`CFloat',`CFloat',`CFloat',`CFloat'} -> `()'#}
-- | Creates new ellipse shaped sub-path.
{#fun unsafe nvgEllipse as ellipse
{`Context',`CFloat',`CFloat',`CFloat',`CFloat'} -> `()'#}
-- | Creates new circle shaped sub-path.
{#fun unsafe nvgCircle as circle
{`Context',`CFloat',`CFloat',`CFloat'} -> `()'#}
-- | Fills the current path with current fill style.
{#fun unsafe nvgFill as fill
{`Context'} -> `()'#}
-- | Fills the current path with current stroke style.
{#fun unsafe nvgStroke as stroke
{`Context'} -> `()'#}
safeFont :: CInt -> Maybe Font
safeFont i
| i < 0 = Nothing
| otherwise = Just (Font i)
-- | Creates font by loading it from the disk from specified file name.
-- Returns handle to the font.
{#fun unsafe nvgCreateFont as createFont
{`Context',withCString*`T.Text','withCString.unwrapFileName'*`FileName'} -> `Maybe Font'safeFont#}
-- | Creates image by loading it from the specified memory chunk.
-- Returns handle to the font.
{#fun unsafe nvgCreateFontMem as createFontMem
{`Context',withCString*`T.Text',useAsCStringLen'*`ByteString'&,zero-`CInt'} -> `Maybe Font'safeFont#}
-- | Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found.
{#fun unsafe nvgFindFont as findFont
{`Context', withCString*`T.Text'} -> `Maybe Font'safeFont#}
-- | Sets the font size of current text style.
{#fun unsafe nvgFontSize as fontSize
{`Context',`CFloat'} -> `()'#}
-- | Sets the blur of current text style.
{#fun unsafe nvgFontBlur as fontBlur
{`Context',`CFloat'} -> `()'#}
-- | Sets the letter spacing of current text style.
{#fun unsafe nvgTextLetterSpacing as textLetterSpacing
{`Context',`CFloat'} -> `()'#}
-- | Sets the proportional line height of current text style. The line height is specified as multiple of font size.
{#fun unsafe nvgTextLineHeight as textLineHeight
{`Context',`CFloat'} -> `()'#}
-- | Sets the text align of current text style, see NVGalign for options.
{#fun unsafe nvgTextAlign as textAlign
{`Context',bitMask`S.Set Align'} -> `()'#}
-- | Sets the font face based on specified id of current text style.
{#fun unsafe nvgFontFaceId as fontFaceId
{`Context',fontHandle`Font'} -> `()'#}
-- | Sets the font face based on specified name of current text styl
{#fun unsafe nvgFontFace as fontFace
{`Context',withCString*`T.Text'} -> `()'#}
-- | Draws text string at specified location. If end is specified only the sub-string up to the end is drawn.
{#fun unsafe nvgText as text
{`Context',`CFloat',`CFloat',id`Ptr CChar',id`Ptr CChar'} -> `()'#}
-- | Draws multi-line text string at specified location wrapped at the specified width. If end is specified only the sub-string up to the end is drawn.
-- | White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
-- | Words longer than the max width are slit at nearest character (i.e. no hyphenation).
{#fun unsafe nvgTextBox as textBox
{`Context',`CFloat',`CFloat',`CFloat',withCString*`T.Text',null-`Ptr CUChar'} -> `()'#}
newtype Bounds = Bounds (V4 CFloat) deriving (Show,Read,Eq,Ord)
instance Storable Bounds where
sizeOf _ = sizeOf (0 :: CFloat) * 4
alignment _ = alignment (0 :: CFloat)
peek p =
do let p' = castPtr p :: Ptr CFloat
a <- peekElemOff p' 0
b <- peekElemOff p' 1
c <- peekElemOff p' 2
d <- peekElemOff p' 3
pure (Bounds (V4 a b c d))
poke p (Bounds (V4 a b c d)) =
do let p' = castPtr p :: Ptr CFloat
pokeElemOff p' 0 a
pokeElemOff p' 1 b
pokeElemOff p' 2 c
pokeElemOff p' 3 d
peekBounds :: Ptr CFloat -> IO Bounds
peekBounds = peek . castPtr
allocaBounds :: (Ptr CFloat -> IO b) -> IO b
allocaBounds f = alloca (\(p :: Ptr Bounds) -> f (castPtr p))
-- | Measures the specified text string. Parameter bounds should be a pointer to float[4],
-- if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
-- Returns the horizontal advance of the measured text (i.e. where the next character should drawn).
-- Measured values are returned in local coordinate space.
{#fun unsafe nvgTextBounds as textBounds
{`Context',`CFloat',`CFloat',withCString*`T.Text',null-`Ptr CUChar', allocaBounds-`Bounds'peekBounds*} -> `()'#}
-- | Measures the specified multi-text string. Parameter bounds should be a pointer to float[4],
-- if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
-- Measured values are returned in local coordinate space.
{#fun unsafe nvgTextBoxBounds as textBoxBounds
{`Context',`CFloat',`CFloat',`CFloat',withCString*`T.Text',null-`Ptr CUChar',allocaBounds-`Bounds'peekBounds*} -> `()'#}
-- | Calculates the glyph x positions of the specified text. If end is specified only the sub-string will be used.
-- Measured values are returned in local coordinate space.
{#fun unsafe nvgTextGlyphPositions as textGlyphPositions
{`Context',`CFloat',`CFloat',id`Ptr CChar',id`Ptr CChar',`GlyphPositionPtr', `CInt'} -> `CInt'#}
-- | Returns the vertical metrics based on the current text style.
-- Measured values are returned in local coordinate space.
{#fun unsafe nvgTextMetrics as textMetrics
{`Context',alloca-`CFloat'peek*,alloca-`CFloat'peek*,alloca-`CFloat'peek*} -> `()'#}
-- | Breaks the specified text into lines. If end is specified only the sub-string will be used.
-- White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
-- Words longer than the max width are slit at nearest character (i.e. no hyphenation).
{#fun unsafe nvgTextBreakLines as textBreakLines
{`Context',id`Ptr CChar',id`Ptr CChar',`CFloat',`TextRowPtr',`CInt'} -> `CInt'#}
{#enum NVGcreateFlags as CreateFlags
{underscoreToCase} with prefix = "NVG_"
deriving (Show,Read,Eq,Ord)#}
bitMask :: Enum a => S.Set a -> CInt
bitMask = S.fold (.|.) 0 . S.map (fromIntegral . fromEnum)
{#fun unsafe nvgCreateGL3 as createGL3
{bitMask`S.Set CreateFlags'} -> `Context'#}
{#fun unsafe nvgDeleteGL3 as deleteGL3
{`Context'} -> `()'#}
type GLuint = Word32
{#fun unsafe nvglCreateImageFromHandleGL3 as createImageFromHandleGL3
{`Context',fromIntegral`GLuint',`CInt',`CInt',`CreateFlags'} -> `Image'Image#}
{#fun unsafe nvglImageHandleGL3 as imageHandleGL3
{`Context',imageHandle`Image'} -> `GLuint'fromIntegral#}