module NanoVG
( FileName(..)
, Context(..)
, Extent(..)
, Solidity(..)
, LineCap(..)
, beginFrame
, cancelFrame
, endFrame
, Color(..)
, rgb
, rgbf
, rgba
, rgbaf
, lerpRGBA
, transRGBA
, transRGBAf
, hsl
, hsla
, save
, restore
, reset
, strokeColor
, strokePaint
, fillColor
, fillPaint
, miterLimit
, strokeWidth
, lineCap
, lineJoin
, globalAlpha
, Transformation(..)
, resetTransform
, transform
, translate
, rotate
, skewX
, skewY
, scale
, currentTransform
, transformIdentity
, transformTranslate
, transformScale
, transformRotate
, transformSkewX
, transformSkewY
, transformMultiply
, transformPremultiply
, transformInverse
, transformPoint
, degToRad
, radToDeg
, Image(..)
, createImage
, createImageMem
, createImageRGBA
, updateImage
, imageSize
, deleteImage
, Paint(..)
, linearGradient
, boxGradient
, radialGradient
, imagePattern
, scissor
, intersectScissor
, resetScissor
, beginPath
, moveTo
, lineTo
, bezierTo
, quadTo
, arcTo
, closePath
, Winding(..)
, pathWinding
, arc
, rect
, roundedRect
, ellipse
, circle
, fill
, stroke
, Font(..)
, createFont
, createFontMem
, findFont
, fontSize
, fontBlur
, textLetterSpacing
, textLineHeight
, Align(..)
, textAlign
, fontFaceId
, fontFace
, text
, textBox
, Bounds(..)
, textBounds
, textBoxBounds
, GlyphPosition(..)
, GlyphPositionPtr
, textGlyphPositions
, textMetrics
, TextRow(..)
, TextRowPtr
, textBreakLines
, CreateFlags(..)
, createGL3
, deleteGL3
, createImageFromHandleGL3
, imageHandleGL3
, V2(..)
, V3(..)
, V4(..)
, M23
) where
import Data.Functor ((<$>))
import Control.Monad
import qualified Data.Text as T
import Data.Text.Foreign
import qualified Data.Vector as V
import Foreign.C.Types
import Foreign.Marshal.Alloc
import Foreign.Ptr
import Foreign.Storable
import NanoVG.Internal
import NanoVG.Internal.GL3
import qualified NanoVG.Internal.Text as Internal
import NanoVG.Internal.Text hiding (textBreakLines,textGlyphPositions,text)
textBreakLines :: Context -> T.Text -> CFloat -> CInt -> (TextRow -> CInt -> IO ()) -> IO ()
textBreakLines c text' width' chunkSize f =
withCStringLen text' $
\(startPtr,len) ->
allocaBytesAligned (sizeOf (undefined :: TextRow) * fromIntegral chunkSize)
(alignment (undefined :: TextRow)) $
\arrayPtr ->
do let endPtr = startPtr `plusPtr` len
loop line ptr =
do count <-
Internal.textBreakLines c ptr endPtr width' arrayPtr chunkSize
when (count > 0) $
loop (line + count) =<< readChunk line arrayPtr count
loop 0 startPtr
where readChunk
:: CInt -> TextRowPtr -> CInt -> IO (Ptr CChar)
readChunk baseline arrayPtr count =
do forM_ [0 .. (count - 1)] $
\i ->
do textRow <-
peekElemOff arrayPtr
(fromIntegral i)
f textRow (baseline + i)
next <$>
peekElemOff arrayPtr
(fromIntegral (count - 1))
textGlyphPositions :: Context -> CFloat -> CFloat -> Ptr CChar -> Ptr CChar -> CInt -> IO (V.Vector GlyphPosition)
textGlyphPositions c x y startPtr endPtr maxGlyphs =
allocaBytesAligned
(sizeOf (undefined :: GlyphPosition) * fromIntegral maxGlyphs)
(alignment (undefined :: GlyphPosition)) $
\arrayPtr ->
do count <-
Internal.textGlyphPositions c x y startPtr endPtr arrayPtr maxGlyphs
readChunk arrayPtr count
where readChunk
:: GlyphPositionPtr -> CInt -> IO (V.Vector GlyphPosition)
readChunk arrayPtr count =
V.generateM (fromIntegral count) $
\i ->
peekElemOff arrayPtr
(fromIntegral i)
text :: Context -> CFloat -> CFloat -> T.Text -> IO ()
text c x y t = withCStringLen t $ \(ptr,len) -> Internal.text c x y ptr (ptr `plusPtr` len)