text:
module Graphics.Rendering.OpenGL.GL.Evaluators (
   -- * Evaluator-related Types
   Order, maxOrder, Domain, MapDescriptor(..), ControlPoint,

   -- * Defining Evaluator Maps
   -- ** One-dimensional Evaluator Maps
   Map1(..), GLmap1, map1,

   -- ** Two-dimensional Evaluator Maps
   Map2(..), GLmap2, map2,

   -- * Using Evaluator Maps

   -- ** Evaluating an Arbitrary Coordinate Value
   evalCoord1, evalCoord1v, evalCoord2, evalCoord2v,

   -- ** Using Evenly Spaced Coordinate Values

   -- *** Defining a Grid
   mapGrid1, mapGrid2,

   -- *** Evaluating a Whole Mesh
   evalMesh1, evalMesh2,

   -- *** Evaluating a Single Point on a Mesh
   evalPoint1, evalPoint2,

   -- * Normal Generation
   autoNormal
) where

import Control.Monad ( zipWithM_ )
import Data.List ( genericLength )
import Foreign.ForeignPtr ( ForeignPtr, mallocForeignPtrArray, withForeignPtr )
import Foreign.Marshal.Alloc ( alloca )
import Foreign.Marshal.Array ( allocaArray )
import Foreign.Ptr ( Ptr, plusPtr )
import Foreign.Storable ( Storable(peek,poke,sizeOf) )
import Graphics.Rendering.OpenGL.GL.Capability (
   EnableCap(CapAutoNormal,CapMap1Color4,CapMap1Index,CapMap1Normal,
             CapMap1TextureCoord1,CapMap1TextureCoord2,CapMap1TextureCoord3,
             CapMap1TextureCoord4,CapMap1Vertex3,CapMap1Vertex4,CapMap2Color4,
             CapMap2Index,CapMap2Normal,CapMap2TextureCoord1,
             CapMap2TextureCoord2,CapMap2TextureCoord3,CapMap2TextureCoord4,
             CapMap2Vertex3,CapMap2Vertex4),
   makeCapability, makeStateVarMaybe )
import Graphics.Rendering.OpenGL.GL.BasicTypes (
   GLenum, GLint, GLfloat, GLdouble, Capability )
import Graphics.Rendering.OpenGL.GL.PeekPoke ( peek2, peek4 )
import Graphics.Rendering.OpenGL.GL.PolygonMode ( marshalPolygonMode )
import Graphics.Rendering.OpenGL.GL.Polygons ( PolygonMode )
import Graphics.Rendering.OpenGL.GL.QueryUtils (
   GetPName(GetMaxEvalOrder,
            GetMap1GridSegments,GetMap1GridDomain,
            GetMap2GridSegments,GetMap2GridDomain),
   getSizei1, getInteger1, getInteger2, getFloat2, getFloat4, getDouble2,
   getDouble4 )
import Graphics.Rendering.OpenGL.GL.StateVar (
   GettableStateVar, makeGettableStateVar, StateVar, makeStateVar )
import Graphics.Rendering.OpenGL.GL.VertexArrays ( NumComponents, Stride )
import Graphics.Rendering.OpenGL.GL.VertexSpec (
   Vertex3, Vertex4(..), TexCoord1, TexCoord2, TexCoord3, TexCoord4(..),
   Normal3(..), Color4(..), Index1(..) )

--------------------------------------------------------------------------------

#include "HsOpenGLTypes.h"

--------------------------------------------------------------------------------

type Order = GLint

maxOrder :: GettableStateVar Order
maxOrder = makeGettableStateVar (getSizei1 id GetMaxEvalOrder)

--------------------------------------------------------------------------------

class Storable d => Domain d where
   glMap1      :: GLenum -> d -> d -> GLint -> GLint -> Ptr d -> IO ()
   glMap2      :: GLenum -> d -> d -> GLint -> GLint -> d -> d -> GLint -> GLint -> Ptr d -> IO ()
   glGetMapv   :: GLenum -> GLenum -> Ptr d -> IO ()
   evalCoord1  :: d -> IO ()
   evalCoord1v :: Ptr d -> IO ()
   evalCoord2  :: (d, d) -> IO ()
   evalCoord2v :: Ptr d -> IO ()
   glMapGrid1  :: GLint -> d -> d -> IO ()
   glMapGrid2  :: GLint -> d -> d -> GLint -> d -> d -> IO ()
   get2        :: (d -> d -> a) -> GetPName -> IO a
   get4        :: (d -> d -> d -> d -> a) -> GetPName -> IO a

instance Domain GLfloat_ where
   glMap1      = glMap1f
   glMap2      = glMap2f
   glGetMapv   = glGetMapfv
   evalCoord1  = glEvalCoord1f
   evalCoord1v = glEvalCoord1fv
   evalCoord2  = uncurry glEvalCoord2f
   evalCoord2v = glEvalCoord2fv
   glMapGrid1  = glMapGrid1f
   glMapGrid2  = glMapGrid2f
   get2        = getFloat2
   get4        = getFloat4

instance Domain GLdouble_ where
   glMap1      = glMap1d
   glMap2      = glMap2d
   glGetMapv   = glGetMapdv
   evalCoord1  = glEvalCoord1d
   evalCoord1v = glEvalCoord1dv
   evalCoord2  = uncurry glEvalCoord2d
   evalCoord2v = glEvalCoord2dv
   glMapGrid1  = glMapGrid1d
   glMapGrid2  = glMapGrid2d
   get2        = getDouble2
   get4        = getDouble4

--------------------------------------------------------------------------------

data Domain d => MapDescriptor d =
   MapDescriptor (d, d) Stride Order NumComponents
   deriving ( Eq, Ord, Show )

totalComponents1 :: Domain d => MapDescriptor d -> Int
totalComponents1 (MapDescriptor _ stride order numComp) =
   fromIntegral stride * (fromIntegral order - 1) + fromIntegral numComp

totalComponents2 :: Domain d => MapDescriptor d -> MapDescriptor d -> Int
totalComponents2 uDescriptor vDescriptor@(MapDescriptor _ _ _ numComp) =
   totalComponents1 uDescriptor + totalComponents1 vDescriptor - fromIntegral numComp

--------------------------------------------------------------------------------

class ControlPoint c where
   map1Target       :: Domain d => c d -> MapTarget
   map2Target       :: Domain d => c d -> MapTarget
   enableCap1       :: Domain d => c d -> EnableCap
   enableCap2       :: Domain d => c d -> EnableCap
   numComponents    :: Domain d => c d -> Stride
   peekControlPoint :: Domain d => Ptr (c d) -> IO (c d)
   pokeControlPoint :: Domain d => Ptr (c d) -> (c d) -> IO ()

instance ControlPoint Vertex3 where
   map1Target       = const Map1Vertex3
   map2Target       = const Map2Vertex3
   enableCap1       = const CapMap1Vertex3
   enableCap2       = const CapMap2Vertex3
   numComponents    = const 3
   peekControlPoint = peek
   pokeControlPoint = poke

instance ControlPoint Vertex4 where
   map1Target       = const Map1Vertex4
   map2Target       = const Map2Vertex4
   enableCap1       = const CapMap1Vertex4
   enableCap2       = const CapMap2Vertex4
   numComponents    = const 4
   peekControlPoint = peek
   pokeControlPoint = poke

instance ControlPoint Index1 where
   map1Target       = const Map1Index
   map2Target       = const Map2Index
   enableCap1       = const CapMap1Index
   enableCap2       = const CapMap2Index
   numComponents    = const 1
   peekControlPoint = peek
   pokeControlPoint = poke

instance ControlPoint Color4 where
   map1Target       = const Map1Color4
   map2Target       = const Map2Color4
   enableCap1       = const CapMap1Color4
   enableCap2       = const CapMap2Color4
   numComponents    = const 4
   peekControlPoint = peek
   pokeControlPoint = poke

instance ControlPoint Normal3 where
   map1Target       = const Map1Normal
   map2Target       = const Map2Normal
   enableCap1       = const CapMap1Normal
   enableCap2       = const CapMap2Normal
   numComponents    = const 3
   peekControlPoint = peek
   pokeControlPoint = poke

instance ControlPoint TexCoord1 where
   map1Target       = const Map1TextureCoord1
   map2Target       = const Map2TextureCoord1
   enableCap1       = const CapMap1TextureCoord1
   enableCap2       = const CapMap2TextureCoord1
   numComponents    = const 1
   peekControlPoint = peek
   pokeControlPoint = poke

instance ControlPoint TexCoord2 where
   map1Target       = const Map1TextureCoord2
   map2Target       = const Map2TextureCoord2
   enableCap1       = const CapMap1TextureCoord2
   enableCap2       = const CapMap2TextureCoord2
   numComponents    = const 2
   peekControlPoint = peek
   pokeControlPoint = poke

instance ControlPoint TexCoord3 where
   map1Target       = const Map1TextureCoord3
   map2Target       = const Map2TextureCoord3
   enableCap1       = const CapMap1TextureCoord3
   enableCap2       = const CapMap2TextureCoord3
   numComponents    = const 3
   peekControlPoint = peek
   pokeControlPoint = poke

instance ControlPoint TexCoord4 where
   map1Target       = const Map1TextureCoord4
   map2Target       = const Map2TextureCoord4
   enableCap1       = const CapMap1TextureCoord4
   enableCap2       = const CapMap2TextureCoord4
   numComponents    = const 4
   peekControlPoint = peek
   pokeControlPoint = poke

--------------------------------------------------------------------------------

peekControlPoints1 ::
   (ControlPoint c, Domain d) => MapDescriptor d -> Ptr d -> IO [c d]
peekControlPoints1 descriptor ptr =
   mapM peekControlPoint (controlPointPtrs1 descriptor ptr)

peekControlPoints2 ::
      (ControlPoint c, Domain d)
   => MapDescriptor d -> MapDescriptor d -> Ptr d -> IO [[c d]]
peekControlPoints2 uDescriptor vDescriptor ptr =
   mapM (mapM peekControlPoint) (controlPointPtrs2 uDescriptor vDescriptor ptr)

pokeControlPoints1 ::
   (ControlPoint c, Domain d) => MapDescriptor d -> Ptr d -> [c d] -> IO ()
pokeControlPoints1 descriptor ptr =
   zipWithM_ pokeControlPoint (controlPointPtrs1 descriptor ptr)

pokeControlPoints2 ::
      (ControlPoint c, Domain d)
   => MapDescriptor d -> MapDescriptor d -> Ptr d -> [[c d]] -> IO ()
pokeControlPoints2 uDescriptor vDescriptor ptr =
   zipWithM_ (zipWithM_ pokeControlPoint)
             (controlPointPtrs2 uDescriptor vDescriptor ptr)

controlPointPtrs1 :: Domain d => MapDescriptor d -> Ptr d -> [Ptr a]
controlPointPtrs1 (MapDescriptor _ stride order _) ptr =
   [ ptr `plusPtr` (o * s) | o <- [ 0 .. fromIntegral order - 1 ] ]
   where s = sizeOfPtr ptr * fromIntegral stride

controlPointPtrs2 ::
   Domain d => MapDescriptor d -> MapDescriptor d -> Ptr d -> [[Ptr a]]
controlPointPtrs2 uDescriptor vDescriptor ptr =
   [ controlPointPtrs1 vDescriptor p | p <- controlPointPtrs1 uDescriptor ptr ]

sizeOfPtr :: Storable a => Ptr a -> Int
sizeOfPtr = (flip (const sizeOf) :: Storable a => Ptr a -> a -> Int) undefined

--------------------------------------------------------------------------------

data MapTarget =
     Map1Color4
   | Map1Index
   | Map1Normal
   | Map1TextureCoord1
   | Map1TextureCoord2
   | Map1TextureCoord3
   | Map1TextureCoord4
   | Map1Vertex3
   | Map1Vertex4
   | Map2Color4
   | Map2Index
   | Map2Normal
   | Map2TextureCoord1
   | Map2TextureCoord2
   | Map2TextureCoord3
   | Map2TextureCoord4
   | Map2Vertex3
   | Map2Vertex4

marshalMapTarget :: MapTarget -> GLenum
marshalMapTarget x = case x of
   Map1Color4 -> 0xd90
   Map1Index -> 0xd91
   Map1Normal -> 0xd92
   Map1TextureCoord1 -> 0xd93
   Map1TextureCoord2 -> 0xd94
   Map1TextureCoord3 -> 0xd95
   Map1TextureCoord4 -> 0xd96
   Map1Vertex3 -> 0xd97
   Map1Vertex4 -> 0xd98
   Map2Color4 -> 0xdb0
   Map2Index -> 0xdb1
   Map2Normal -> 0xdb2
   Map2TextureCoord1 -> 0xdb3
   Map2TextureCoord2 -> 0xdb4
   Map2TextureCoord3 -> 0xdb5
   Map2TextureCoord4 -> 0xdb6
   Map2Vertex3 -> 0xdb7
   Map2Vertex4 -> 0xdb8

--------------------------------------------------------------------------------

class Map1 m where
   withNewMap1 :: (ControlPoint c, Domain d)
      => MapDescriptor d -> (Ptr d -> IO ()) -> IO (m c d)

   withMap1 :: (ControlPoint c, Domain d)
      => m c d -> (MapDescriptor d -> Ptr d -> IO a) -> IO a

   newMap1 :: (ControlPoint c, Domain d)
      => (d, d) -> [c d] -> IO (m c d)

   getMap1Components :: (ControlPoint c, Domain d)
      => m c d -> IO ((d, d), [c d])

   withNewMap1 descriptor@(MapDescriptor domain _ _ _) act = do
      allocaArray (totalComponents1 descriptor) $ \ptr -> do
         act ptr
         controlPoints <- peekControlPoints1 descriptor ptr
         newMap1 domain controlPoints

   withMap1 m act = do
      (domain, controlPoints) <- getMap1Components m
      let stride = numComponents (head controlPoints)
          order = genericLength controlPoints
          descriptor = MapDescriptor domain stride order (fromIntegral stride)
      allocaArray (totalComponents1 descriptor) $ \ptr -> do
         pokeControlPoints1 descriptor ptr controlPoints
         act descriptor ptr

   newMap1 domain controlPoints = do
      let stride = numComponents (head controlPoints)
          order = genericLength controlPoints
          descriptor = MapDescriptor domain stride order (fromIntegral stride)
      withNewMap1 descriptor $ \ptr ->
         pokeControlPoints1 descriptor ptr controlPoints

   getMap1Components m =
      withMap1 m $ \descriptor@(MapDescriptor domain _ _ _) ptr -> do
         controlPoints <- peekControlPoints1 descriptor ptr
         return (domain, controlPoints)

--------------------------------------------------------------------------------

data (ControlPoint c, Domain d) => GLmap1 c d =
   GLmap1 (MapDescriptor d) (ForeignPtr d)
#ifdef __HADDOCK__
-- Help Haddock a bit, because it doesn't do any instance inference.
instance Eq d => Eq (GLmap1 c d)
instance Ord d => Ord (GLmap1 c d)
instance Show d => Show (GLmap1 c d)
#else
   deriving ( Eq, Ord, Show )
#endif

instance Map1 GLmap1 where
   withNewMap1 descriptor act = do
      fp <- mallocForeignPtrArray (totalComponents1 descriptor)
      withForeignPtr fp act
      return $ GLmap1 descriptor fp

   withMap1 (GLmap1 descriptor fp) act =
      withForeignPtr fp $ act descriptor

--------------------------------------------------------------------------------

map1 :: (Map1 m, ControlPoint c, Domain d) => StateVar (Maybe (m c d))
map1 = makeMap1StateVar enableCap1 getMap1 setMap1

makeMap1StateVar ::
      (c d -> EnableCap) -> (c d -> IO (m c d)) -> (c d -> m c d -> IO ())
   -> StateVar (Maybe (m c d))
makeMap1StateVar getCap getAct setAct =
   makeStateVarMaybe
      (return (getCap undefined))
      (getAct undefined)
      (setAct undefined)

getMap1 :: (Map1 m, ControlPoint c, Domain d) => c d -> IO (m c d)
getMap1 dummyControlPoint = do
   let target = marshalMapTarget (map1Target dummyControlPoint)
       numComp = fromIntegral (numComponents dummyControlPoint)
   domain <- allocaArray 2 $ \ptr -> do
      glGetMapv target (marshalGetMapQuery Domain) ptr
      peek2 (,) ptr
   order <- alloca $ \ptr -> do
      glGetMapiv target (marshalGetMapQuery Order) ptr
      fmap fromIntegral $ peek ptr
   withNewMap1 (MapDescriptor domain (numComponents dummyControlPoint) order numComp) $
      glGetMapv target (marshalGetMapQuery Coeff)

setMap1 :: (Map1 m, ControlPoint c, Domain d) => c d -> m c d -> IO ()
setMap1 dummyControlPoint m =
   withMap1 m $ \(MapDescriptor (u1, u2) stride order _) ->
      glMap1 (marshalMapTarget (map1Target dummyControlPoint)) u1 u2
             (fromIntegral stride) (fromIntegral order)

foreign import CALLCONV unsafe "glMap1f" glMap1f ::
      GLenum
   -> GLfloat -> GLfloat -> GLint -> GLint
   -> Ptr GLfloat -> IO ()

foreign import CALLCONV unsafe "glMap1d" glMap1d ::
      GLenum
   -> GLdouble -> GLdouble -> GLint -> GLint
   -> Ptr GLdouble -> IO ()

--------------------------------------------------------------------------------

class Map2 m where
   withNewMap2 :: (ControlPoint c, Domain d)
      => MapDescriptor d -> MapDescriptor d -> (Ptr d -> IO ()) -> IO (m c d)

   withMap2 :: (ControlPoint c, Domain d)
      => m c d -> (MapDescriptor d -> MapDescriptor d -> Ptr d -> IO a) -> IO a

   newMap2 :: (ControlPoint c, Domain d)
      => (d, d) -> (d, d) -> [[c d]] -> IO (m c d)

   getMap2Components :: (ControlPoint c, Domain d)
      => m c d -> IO ((d, d), (d, d), [[c d]])

   withNewMap2 uDescriptor@(MapDescriptor uDomain _ _ _)
               vDescriptor@(MapDescriptor vDomain _ _ _) act =
      allocaArray (totalComponents2 uDescriptor vDescriptor) $ \ptr -> do
         act ptr
         controlPoints <- peekControlPoints2 uDescriptor vDescriptor ptr
         newMap2 uDomain vDomain controlPoints

   withMap2 m act = do
      (uDomain, vDomain, controlPoints) <- getMap2Components m
      let vStride = numComponents (head (head controlPoints))
          vOrder = genericLength (head controlPoints)
          uStride = vStride * fromIntegral vOrder
          uOrder = genericLength controlPoints
          numComp = fromIntegral vStride
          uDescriptor = MapDescriptor uDomain uStride uOrder numComp
          vDescriptor = MapDescriptor vDomain vStride vOrder numComp
      allocaArray (totalComponents2 uDescriptor vDescriptor) $ \ptr -> do
         pokeControlPoints2 uDescriptor vDescriptor ptr controlPoints
         act uDescriptor vDescriptor ptr

   newMap2 uDomain vDomain controlPoints = do
      let vStride = numComponents (head (head controlPoints))
          vOrder = genericLength (head controlPoints)
          uStride = vStride * fromIntegral vOrder
          uOrder = genericLength controlPoints
          numComp = fromIntegral vStride
          uDescriptor = MapDescriptor uDomain uStride uOrder numComp
          vDescriptor = MapDescriptor vDomain vStride vOrder numComp
      withNewMap2 uDescriptor vDescriptor $ \ptr ->
         pokeControlPoints2 uDescriptor vDescriptor ptr controlPoints

   getMap2Components m =
      withMap2 m $ \uDescriptor@(MapDescriptor uDomain _ _ _)
                    vDescriptor@(MapDescriptor vDomain _ _ _) ptr -> do
         controlPoints <- peekControlPoints2 uDescriptor vDescriptor ptr
         return (uDomain, vDomain, controlPoints)

--------------------------------------------------------------------------------

data (ControlPoint c, Domain d) => GLmap2 c d =
   GLmap2 (MapDescriptor d)  (MapDescriptor d) (ForeignPtr d)
#ifdef __HADDOCK__
-- Help Haddock a bit, because it doesn't do any instance inference.
instance Eq d => Eq (GLmap2 c d)
instance Ord d => Ord (GLmap2 c d)
instance Show d => Show (GLmap2 c d)
#else
   deriving ( Eq, Ord, Show )
#endif

instance Map2 GLmap2 where
   withNewMap2 uDescriptor vDescriptor act = do
      fp <- mallocForeignPtrArray (totalComponents2 uDescriptor vDescriptor)
      withForeignPtr fp act
      return $ GLmap2 uDescriptor vDescriptor fp

   withMap2 (GLmap2 uDescriptor vDescriptor fp) act =
      withForeignPtr fp $ act uDescriptor vDescriptor

--------------------------------------------------------------------------------

map2 :: (Map2 m, ControlPoint c, Domain d) => StateVar (Maybe (m c d))
map2 = makeMap2StateVar enableCap2 getMap2 setMap2

makeMap2StateVar ::
      (c d -> EnableCap) -> (c d -> IO (m c d)) -> (c d -> m c d -> IO ())
   -> StateVar (Maybe (m c d))
makeMap2StateVar getCap getAct setAct =
   makeStateVarMaybe
      (return (getCap undefined))
      (getAct undefined)
      (setAct undefined)

getMap2 :: (Map2 m, ControlPoint c, Domain d) => c d -> IO (m c d)
getMap2 dummyControlPoint = do
   let target = marshalMapTarget (map2Target dummyControlPoint)
   (uDomain, vDomain) <- allocaArray 4 $ \ptr -> do
      glGetMapv target (marshalGetMapQuery Domain) ptr
      peek4 (\u1 u2 v1 v2 -> ((u1, u2), (v1, v2))) ptr
   (uOrder, vOrder) <- allocaArray 2 $ \ptr -> do
      glGetMapiv target (marshalGetMapQuery Order) ptr
      peek2 (,) ptr
   let vStride = numComponents dummyControlPoint
       uStride = vStride * fromIntegral vOrder
   withNewMap2 (MapDescriptor uDomain uStride uOrder (fromIntegral vStride))
               (MapDescriptor vDomain vStride vOrder (fromIntegral vStride)) $
      glGetMapv target (marshalGetMapQuery Coeff)

setMap2 :: (Map2 m, ControlPoint c, Domain d) => c d -> m c d -> IO ()
setMap2 dummyControlPoint m =
   withMap2 m $ \(MapDescriptor (u1, u2) uStride uOrder _)
                 (MapDescriptor (v1, v2) vStride vOrder _) ->
      glMap2 (marshalMapTarget (map2Target dummyControlPoint))
             u1 u2 (fromIntegral uStride) (fromIntegral uOrder)
             v1 v2 (fromIntegral vStride) (fromIntegral vOrder)

foreign import CALLCONV unsafe "glMap2f" glMap2f ::
      GLenum
   -> GLfloat -> GLfloat -> GLint -> GLint
   -> GLfloat -> GLfloat -> GLint -> GLint
   -> Ptr GLfloat -> IO ()

foreign import CALLCONV unsafe "glMap2d" glMap2d ::
      GLenum
   -> GLdouble -> GLdouble -> GLint -> GLint
   -> GLdouble -> GLdouble -> GLint -> GLint
   -> Ptr GLdouble -> IO ()

--------------------------------------------------------------------------------

data GetMapQuery =
     Coeff
   | Order
   | Domain

marshalGetMapQuery :: GetMapQuery -> GLenum
marshalGetMapQuery x = case x of
   Coeff -> 0xa00
   Order -> 0xa01
   Domain -> 0xa02

--------------------------------------------------------------------------------

foreign import CALLCONV unsafe "glGetMapfv" glGetMapfv ::
   GLenum -> GLenum -> Ptr GLfloat -> IO ()

foreign import CALLCONV unsafe "glGetMapdv" glGetMapdv ::
   GLenum -> GLenum -> Ptr GLdouble -> IO ()

foreign import CALLCONV unsafe "glGetMapiv" glGetMapiv ::
   GLenum -> GLenum -> Ptr GLint -> IO ()

--------------------------------------------------------------------------------

foreign import CALLCONV unsafe "glEvalCoord1f" glEvalCoord1f ::
   GLfloat -> IO ()

foreign import CALLCONV unsafe "glEvalCoord1fv" glEvalCoord1fv ::
   Ptr GLfloat -> IO ()

foreign import CALLCONV unsafe "glEvalCoord1d" glEvalCoord1d ::
   GLdouble -> IO ()

foreign import CALLCONV unsafe "glEvalCoord1dv" glEvalCoord1dv ::
   Ptr GLdouble -> IO ()

--------------------------------------------------------------------------------

foreign import CALLCONV unsafe "glEvalCoord2f" glEvalCoord2f ::
   GLfloat -> GLfloat -> IO ()

foreign import CALLCONV unsafe "glEvalCoord2fv" glEvalCoord2fv ::
   Ptr GLfloat -> IO ()

foreign import CALLCONV unsafe "glEvalCoord2d" glEvalCoord2d ::
   GLdouble -> GLdouble -> IO ()

foreign import CALLCONV unsafe "glEvalCoord2dv" glEvalCoord2dv ::
   Ptr GLdouble -> IO ()

--------------------------------------------------------------------------------

mapGrid1 :: Domain d => StateVar (GLint, (d, d))
mapGrid1 =
   makeStateVar
      (do n <- getInteger1 id GetMap1GridSegments
          domain <- get2 (,) GetMap1GridDomain
          return (n, domain))
      (\(n, (u1, u2)) -> glMapGrid1 n u1 u2)

foreign import CALLCONV unsafe "glMapGrid1f" glMapGrid1f ::
   GLint -> GLfloat -> GLfloat -> IO ()

foreign import CALLCONV unsafe "glMapGrid1d" glMapGrid1d ::
   GLint -> GLdouble -> GLdouble -> IO ()

mapGrid2 :: Domain d => StateVar ((GLint, (d, d)), (GLint, (d, d)))
mapGrid2 =
   makeStateVar
      (do (un, vn) <- getInteger2 (,) GetMap2GridSegments
          (u1, u2, v1, v2) <- get4 (,,,) GetMap2GridDomain
          return ((un, (u1, u2)), (vn, (v1, v2))))
      (\((un, (u1, u2)), (vn, (v1, v2))) -> glMapGrid2 un u1 u2 vn v1 v2)

foreign import CALLCONV unsafe "glMapGrid2f" glMapGrid2f ::
   GLint -> GLfloat -> GLfloat -> GLint -> GLfloat -> GLfloat -> IO ()

foreign import CALLCONV unsafe "glMapGrid2d" glMapGrid2d ::
   GLint -> GLdouble -> GLdouble -> GLint -> GLdouble -> GLdouble -> IO ()

--------------------------------------------------------------------------------

evalMesh1 :: PolygonMode -> (GLint, GLint) -> IO ()
evalMesh1 m (p1, p2) = glEvalMesh1 (marshalPolygonMode m) p1 p2

foreign import CALLCONV unsafe "glEvalMesh1" glEvalMesh1 ::
   GLenum -> GLint -> GLint -> IO ()

evalMesh2 :: PolygonMode -> (GLint, GLint) -> (GLint, GLint) -> IO ()
evalMesh2 m (p1, p2) (q1, q2) = glEvalMesh2 (marshalPolygonMode m) p1 p2 q1 q2

foreign import CALLCONV unsafe "glEvalMesh2" glEvalMesh2 ::
   GLenum -> GLint -> GLint -> GLint -> GLint -> IO ()

--------------------------------------------------------------------------------

foreign import CALLCONV unsafe "glEvalPoint1" evalPoint1 ::
   GLint -> IO ()

evalPoint2 :: (GLint, GLint) -> IO ()
evalPoint2 = uncurry glEvalPoint2

foreign import CALLCONV unsafe "glEvalPoint2" glEvalPoint2 ::
   GLint -> GLint -> IO ()

--------------------------------------------------------------------------------

autoNormal :: StateVar Capability
autoNormal = makeCapability CapAutoNormal

redpajama_set_name: RedPajamaGithub


"Jersey Cow" is a sculptural bookend created by the Australian Artist Peter Mortimore. Created using Resin on an Australian Hardwood base, each piece is a hand painted and measures 422 mm x 140 mm x 240 mm. The bookends are available from The Peter Mortimore Gallery, 59 Hickory Street, Dorrigo NSW 2453.
"English Poll Hereford Bull" is a sculptural bookend created by the Australian Artist Peter Mortimore. Created using Resin on an Australian Hardwood base, each piece is a hand painted and measures 422 mm x 140 mm x 240 mm. The bookends are available from The Peter Mortimore Gallery, 59 Hickory Street, Dorrigo NSW 2453.
"Charolais" is a sculptural bookend created by the Australian Artist Peter Mortimore. Created using Resin on an Australian Hardwood base, each piece is a hand painted and measures 422 mm x 140 mm x 240 mm. The bookends are available from The Peter Mortimore Gallery, 59 Hickory Street, Dorrigo NSW 2453.
"Charging Bull" is a sculptural bookend created by the Australian Artist Peter Mortimore. Created using Resin on an Australian Hardwood base, each piece is a hand painted and measures 422 mm x 140 mm x 240 mm. The bookends are available from The Peter Mortimore Gallery, 59 Hickory Street, Dorrigo NSW 2453.
"Brahman Bull" is a sculptural bookend created by Peter A. P. Mortimore. The piece is made with Resin on an Australian Hardwood base, and hand painted. The final piece is 422 mm x 140 mm x 240 mm and available from The Peter Mortimore Gallery, 59 Hickory Street, Dorrigo NSW 2453.
The "Angus Bull" Bookends by Peter A. P. Mortimore is 422 mm x 140 mm x 240 mm and made with Resin on Australian Hardwood. The bookends are available at The Peter Mortimore Gallery, 59 Hickory Street, Dorrigo NSW 2453.


You've likely already come across some of the work of prominent urban filmmaker Rob Whitworth – perhaps you've seen the viral video of Barcelona, or this short film of Istanbul for Turkish Airlines. He's won numerous awards for his innovative use of 4K video and pioneering a new style of filmmaking dubbed 'Flow Motion'. Whitworth has enjoyed widespread critical acclaim for his works and has received over 9 million views on his Vimeo channel alone.
Like this videos? Be sure to subscribe to his Vimeo channel and stay up to date on his latest works!


text:
Middle East & Africa | Let's do this again
A historic day for Malawi's democracy
For only the second time in African history, judges nullify a flawed general election
Feb 6th 2020 | LILONGWE
THERE ARE many ways to rig an election. Voters can be beaten or bribed. Ballot boxes can be stuffed. Computers tallying results can be hacked. But few methods are more rudimentary than that used last year in Malawi's general election. In the southern African country of 18m people the dastardly tool was Tipp-Ex, the correction fluid that has saved many a teenager's error-strewn homework.
Listen to this story.
Enjoy more audio and podcasts on iOS or Android.
Your browser does not support the <audio> element.
On May 27th the Malawi Electoral Commission (MEC) announced a victory for the 79-year-old incumbent president, Peter Mutharika. The MEC said it had received 147 reports of "irregularities", including the use of Tipp-Ex on results sheets, but refused to call for another vote. Opposition candidates petitioned the country's constitutional court, asking judges to nullify the election. Protesters, many of them young Malawians born after the end of dictatorship in 1994, took to the streets to keep up the pressure on the bench.
It worked. On February 3rd the court said there had been "widespread, systematic and grave" flaws in the electoral process. It ordered a re-run of the general election to be held within 150 days. For months millions of Malawians have followed the twists and turns of the case live on radio broadcasts—but few could have hoped for such a decisive verdict.
The judgment is a historic moment for one of the world's poorest countries. Income per person is just $389 a year according to the World Bank, a quarter of the amount in neighbouring Zambia. The flawed democracy that replaced the one-man rule of Hastings Banda has done much to enrich an elite, but little to lift the vast majority out of poverty. The hope is that the court's verdict ushers in a new era in which politicians must govern well rather than cheat to stay in power.
Malawi's case matters beyond its borders. African courts and international election observers have a history of accepting suspicious results. Last year, for example, the constitutional court in the Democratic Republic of Congo affirmed that Félix Tshisekedi had won the presidency fairly despite bucketloads of evidence to the contrary. Regional political organisations have proved similarly short of backbone. The invertebrate Southern African Development Community quickly endorsed Malawi's election, echoing its hurried acceptance of Zimbabwe's iffy count in 2018.
A single verdict will change only so much. But the Malawian judgment follows that of Kenya's Supreme Court, which in 2017 declared void the victory of President Uhuru Kenyatta. "Two African courts have now set tougher standards for elections than international election observers," says Nic Cheeseman, an expert in African politics at the University of Birmingham. In doing so they have made it a little more difficult for politicians to rig elections.
Malawians will hope that the aftermath of their historic court verdict is smoother than it was in Kenya. Raila Odinga, Kenya's main opposition leader, boycotted the re-run, citing yet more irregularities. In Malawi there are obstacles to a clean and peaceful second vote: the MEC will need new leadership, and Mr Mutharika says he will appeal the court's decision.
For now, though, Malawians are proud that the rule of law has prevailed. The verdict shows that though Tipp-Ex may hide the truth, it cannot erase it. ■
This article appeared in the Middle East & Africa section of the print edition under the headline "Let's do this again"
Middle East & Africa February 8th 2020
Félix Tshisekedi has accomplished little in Congo
The legacy of Daniel arap Moi still haunts Kenya
More Africans are marrying spouses of different ethnicities
The Houthi model of government
From the February 8th 2020 edition
More from Middle East & Africa
A white, gay, Zulu-speaking mayor is shaking up South African politics
Chris Pappas is an unlikely but effective trailblazer
Why bicycles are crucial to Congo's cross-border trade
While lorries wait weeks to pay their dues, two-wheelers zip across on the cheap
A populist plan to pay off private debts is another sign of Kuwait's ills
Dysfunctional politics and short-sighted economic policies are holding a rich country back

redpajama_set_name: RedPajamaCommonCrawl


A synthesis of art and technique.
Thanks to its ability to grow, Vicentini manages to gain a leading position among the world leaders in the construction of machines and plants for the ceramic industry: a world where technology and art, knowledge and creativity come together in a perfect synthesis.
Technical quality and commercial capacity, combined with maximum production versatility, make Vicentini the ideal partner for the kitchenware, sanitary ware, tiles, flower vases, artistic and technical ceramics industry.
The confluence in the SETEC group, thanks to the synergies obtainable, gives Vicentini the possibility to improve and expand the range of products and services, as well as their quality. The goal of the Vicentini is the affirmation of the recognized world leadership. The investment of ample resources in the development of the product, in the continuous improvement of the production process and of the technical service, have led Vicentini to be a guarantee of reliability and quality all over the world.
State-of-the-art industrial techniques combined with the ability to produce craftsmanship with precision are the solid bases on which Vicentini has developed the ability to customize the product according to the needs of the most heterogeneous customers.
In order to fully satisfy the requests of the customers, Vicentini is able to offer two services of fundamental importance: the pre-sales consultancy service and the after-sales assistance.
Vicentini devotes the maximum attention to the respect of the norms and the constructive standards.
Each machine that Vicentini builds fully complies with the CE regulations to guarantee the safety of the users.
Moreover, being part of the SETEC group, Vicentini can now also offer a qualified technological assistance and can assist the customer in solving any problem related to raw materials, doughs, glazes, finished products.


General tab requires first & last name, email address, a password and password confirmation. Click Save & Continue.
Account Info tab stores optional information and notes.
Access tab allows a user to be designated an admin and/or a member.
This Person is a Member - check this box to allow the user to see private member information (this may not be enabled on your site).
This Person is an Admin - check this box to allow the user to access Spark. Once checked, you'll be able to select which sections of your site this user can edit.
Member tab - this may not be enabled on your site.


Today the Quran Rainbow is available on Hijabs & Co, an awesome gift for your parents, friends, husband or simply for you.
It' s available in 4 colors : Pink, Cream, Yellow, and Brown.
How much is it? I love the pink one!
oh! It's so petty mashaAllah. Perfect for a gift!
Love it! MashaAllah. Thanks for sharing.
Il est magnifique MashaAllah ! Combien le vends-tu ?
pretty! i think i want one!
I really want it, but i live in germany, you are able to send it to me?
where can i find the pink one?
Salam sister, I know the Qur'an is sold out but I just keep watching the video for the audio, do you know where I can download it?


Foo Guild Gaming Community > Public Forums > Frontpage News > Welcome & Congrats!
View Full Version : Welcome & Congrats!
Congrats to our newest officers:Taurine, xXanderCageXx, and Alifa.
Also, welcome to our newest members: Brokenmind, Ig-twa, Kill, & Abrielle'.
Welcome to the new members! hopefully we will continue to grow as a guild.


Author(s): Ripamonti, G. ; Bertolaccini, M. ; Peritore, R. ; Schippers, S.
Two alternative circuits for very low-supply-voltage bandgap voltage references BGR in a flash memory environment are designed and compared. The circuits allow operation at supply voltages as low as 0.9 V, while requiring as low as 5 /spl mu/A current. Sensitivity to supply voltage variations is reduced by means of suitable feedback circuits. Experimental results confirm that the BGR operates correctly and can be employed in future ultra-low-supply-voltage flash memory devices.
April 1, 2004 - Tsinghua University Press Ltd.
October 1, 2010 - Tsinghua University Press Ltd.


Information and resources for post-secondary institutions that enrol students from Saskatchewan. Find forms, guidelines, policies, instructions, and institutional funding letters.
Information on the legislation enabling Saskatchewan Government to extend degree-granting authority to post-secondary education institutions other than the province's universities. Includes information on how post-secondary institutions can apply for degree-granting authority, the roles of Saskatchewan Higher Education Quality Assurance Board, and more.
Each year, the Ministry of Advanced Education makes available the budget letters for each post-secondary institution. View the budget letters here.
Administrative guidelines and policies pertaining to post-secondary education in Saskatchewan for educational institutions.
There are scholarships, bursaries, and grants available to help students pay for their post-secondary education. Find out about your eligibility and the application process.
If you are thinking of post-secondary schooling or are currently a post-secondary student, students loans from the Governments of Canada and Saskatchewan can provide financial help.
Learn what to do if you are injured while on work placement.
The Ministry of Advanced Education, in collaboration with the Assemblée communautaire fransaskoise, Canadian Parents for French, Collège Mathieu, University of Regina, Saskatchewan Polytechnic, and the University of Saskatchewan have formed a working group to determine a new direction in French-language post-secondary education in Saskatchewan called "Vision 2030".


I arrived at the museum at 17:30 as usual. There was Rob in the entrance foyer, arranging chairs and looking rather hassled. I said hello but he obviously didn't have time so I went upstairs and drew some stuffed birds.
All seemed under control when I came back downstairs so I said hello again. The new sculpture on the plinth: that was his. Congratulations, I said. Wow! When's it being unveiled? Well, now, he said. Stop for a drink.
I picked up a leaflet. The plinth sculpture is called "Under Construction Forever". If you visit http://robertmanners.wordpress.com you'll see it taking shape — under construction. I wonder if he'll keep working on it, now it's installed? I hadn't realised Rob was Robert Manners, artist and curator, and I hadn't seen his work in a while. It's superb.


Fianna Fáil TD for Galway West Éamon Ó Cuív has accused the Agriculture Minister of allowing the fodder crisis to develop into an emergency. He says Minister Creed ignored the situation for months, putting unnecessary pressure on farmers.
Deputy Ó Cuív explained, "This crisis was predicted as far back as last September, and despite warning after warning from ourselves and various farming organisations, the Minister chose to ignore the seriousness of the situation and failed to take any concrete measures to tackle it. Now we have reached almost emergency levels with only a few weeks fodder left in the country. Despite this Minister Creed still maintains "there has been sufficient fodder within the country" up until this week. The reality is that larger co-ops like Dairygold have been aware of the seriousness of the situation and have imported fodder in from other countries – in fact their first delivery is expected tomorrow. This shows just how out of touch the Minister is.
"Unless urgent action is taken this crisis may become unsalvageable. The Minister has a responsibility to farmers and their livestock. Delaying on this is not an option".


Sorata, our home town for two weeks, perched on a mountainside at 9,000'. Towering behind are Illampu (20,867') and Ancohuma (21,081').
Sorata's central plaza has trees so old nobody knows when they were planted. We went with a Quaker group, primarily to work at the internado, a dormitory for jr. high and high school students from remote villages to live at while they attend the local schools.
Caleb mixes cement for the patio. Luke pokes his head thru a hole he and Caleb pounded in a wall, in preparation to put in a door. And we move a very heavy rock with Eusebio, the internado house parent. We also helped set up six laptops for the students (some of whom had never before used a computer), taught them how to use digital cameras and software, and helped build a shade structure on a rooftop patio.
The internado is a recent project of Bolivian Quaker Education Fund (BQEF). It allows 20 students to attend high school, which would otherwise be infeasible due to the long walk to town. Some of the students are top in their grade. BQEF also provides college scholarships ($50/month) to 35 students. We met some of them and were very impressed. A small donation goes a long way to supporting these very capable young people. Here, counselor Ruben (right) demonstrates a magic trick with the kids.
A typical remote community across the canyon-- a two-hour vehicle ride or a seven-hour walk. Drivers would sometimes handle blind hairpin one-lane corners by minimizing the time spent on them! The walking paths weren't much better, but to the locals (from children to the elderly), a three-hour walk is "muy cerca" (very close). We were able to offer a ride one weekend to three of the kids (ages 14-16), sparing them their usual seven-hour walk to Sorata to go to school.
Much of Bolivia is very traditional, with over 60% of the population indigenous Aymara or Quechua. Women wear bowler hats, large skirts, and invariably are carrying an aguallo, the colorful blanket used to carry children or produce or even car parts. The soccer field in the background is at 14,500'.
Bolivia has the third largest Quaker population of any country. Quaker Bolivia Link is frugal yet very effective organization that does a lot with a little. This llama and alpaca farm was one of their projects, developing an important source of wool, meat, and income for the community.
Many community gatherings (this one for us at the llama farm) include a kind of pot luck meal spread on a blanket. Foods include many different types of potato, including chunya, freeze-dried using an ancient Inca method involving the sun and the freezing nights. This method of storing potatoes remains widespread today.
A street in Sorata. Lonna spent a day with the local traveling medical team-- which turned into two days, a long night, several patients, a trip to the hospital, and some hair-raising driving on mountainside roads.
Luke (16), Bunky (12), and Caleb (19) below Illampu. All the locals told us that the snow fields have greatly receded due to "el cambio de la clima" (climate change).


text:
Research: Wearable payments expected to hit $100bn by 2018
11 April 2016, 16:04 p.m.
Android, Devices, NFC, Payments, Research, Smartwatches
(Image Credit: iStockPhoto/Onfokus)
Many of us are expected to utilise our wearables for payments by 2018, if projections by Juniper Research are correct. The research firm expects contactless payments through wearable devices to reach $95 billion annually by 2018, up from less than $35 billion last year.
Apple's entry into NFC gave the industry a much needed boost, and could well be seen as the tipping point for the technology
The major wearable platforms remain Android Wear and Apple's WatchOS. Google hasn't yet enabled payment support for Android Wear devices, and therefore most devices aren't shipping with the NFC technology used for contactless payments. Apple's wearable has constituted the biggest driver of wearable payments due to its nine million shipped units at the end of 2015, and support for Apple Pay.
Android Pay, Google's payment system, has not induced the same uptake as Apple's due to a slower international rollout and rumoured hesitation from banks to support it. Google has announced it will be launching Android Pay in several new markets – including the UK – in the next few months which should drive its uptake. Not long after we can expect Android Pay to be supported on Android Wear devices, which should further push the use of wearable payments.
The research - Contactless Payments: NFC Handsets, Wearables & Payment Cards 2016-2020 – points towards a "sea change" in the NFC ecosystem where vendors are embedding secure elements within the smartphone in the same approach which Apple takes. Prospects for mobile network operators who have been looking to enter the contactless payments space have dwindled as a result, due to being cut-out the value chain.
According to research co-author Nitin Bhas, "Most operator-led pilots and commercial ventures have now closed down. Apple's entry into NFC gave the industry a much needed boost, and could well be seen as the tipping point for the technology, but at the same time it sounded the death knell for the mobile operator projects."
The whitepaper, 'NFC ~ No Contact Required' is now available to download from the Juniper website together with further details of the full research.
Are your surprised at Juniper's projections for wearable payments? Share your thoughts in the comments.


Bam's Cannoli is a devilishly delectable line of liquids inspired by one of the finest of italian pastries: the deliciously complex cannoli! Featuring savory pastry notes and decadently rich cream paired with an assortment of exciting highlight flavors, Bam's keeps things interesting while retaining the classic sensations of the pastry which inspired them. Original Cannoli may be unrecognizable to a purist, but will certainly appeal to any dessert aficionado's adventurous culinary spirit by combining traditional cannoli flavors with those of key lime and tart fruit cereal. Experience this sweet, savory, and well balanced flavor for yourself by adding a bottle of Bam's Original Cannoli to your cart today!


Tarot 101 Articles and More | Daily Witchery, etc.
I'm currently writing a series of Tarot 101 articles on Pagan Writers Community. It you're interested visit PWC for more information and access to the articles. Currently posted is an article about choosing your own deck and next week will see an article about storage options for Tarot and Oracle decks.
Other than working on these articles, I've been crafting a few other articles for PWC. I'll have an article on the crystal citrine for next week. Hopefully, next week will also see the start of my new Kitchen Witchery column. Still coming up with ideas for that one. Hopefully I'll come up with enough to write every week. We'll see.


text:
Rioters bussed into Croydon to cause mayhem
Rioters bussed into Croydon to cause mayhem, says police chief
Acting Borough Commander Jo Oakley with the Prime Minister in Croydon
Looters were ferried into Croydon by minibus to cause destruction, we can reveal.
In an interview with Acting Borough Commander Jo Oakley, it emerged gangs of rioters were bussed in, reportedly by gang leaders.
The Superintendent defended the tactics of the police but admitted they struggled with the wide geographical scale of the incidents.
She praised the bravery of individual officers who had to deal with a situation she had never seen the like of.
Disorder had already broken out in other boroughs across London and this had stretched the Met's resources, she admitted.
Calls and intelligence took time to come through while the speed at which the situation escalated made things worse.
She said: "It all started happening and escalated very quickly.
"We had a lot of officers in and around the town centre. However there were incidents going on across Croydon.
"The geography caused problems.
"There were so many individual incidents across Croydon. For some of the areas there was no intelligence that was going to happen."
She said areas such as Reeves Corner, where the historic House of Reeves furniture store was burnt to the ground, had nothing to steal but the looters still went there and destroyed things.
Defending the tactics used by police, she said public safety was her top priority and there were shoppers in the town centre when the trouble began.
She said: "The tactics were right for the most part.
"What started it off in no time at all was a mob gang of about 300 throwing anything they got their hand on.
"We would be called to an incident and we would go down there and arrest them and in no time at all a very volatile crowd would come out of the wood work.
"I was really proud of the officers who put themselves in some very difficult positions."
Asked why police did not come and help when buildings were being broken into sometimes yards from the police she said he officers could not break the line.
She said: "They still need to hold a certain line because if they broke that they can get through and cause more trouble."
She revealed she had every officer on the streets of Croydon on Monday night, including CID in uniform and British Transport Police officers as well as every Safer Neighbourhood Team.
And she warned those who had committed the crimes "we will come after you".
She said: "I have some of the best detectives working for me and have an extra team to help with solving these crimes. We are already arresting people."


Anyone up for a little road trip today? And how 'bout we test drive of a new sketchbook along the way?
I love how you textured the page with color and used such a great style of writing on this...and the bunny is just the icing on the cake!