packages feed

hoodle-core-0.14: src/Hoodle/ModelAction/Pen.hs

{-# LANGUAGE OverloadedStrings #-}

-----------------------------------------------------------------------------
-- |
-- Module      : Hoodle.ModelAction.Pen 
-- Copyright   : (c) 2011-2014 Ian-Woo Kim
--
-- License     : BSD3
-- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
-- Stability   : experimental
-- Portability : GHC
--
-----------------------------------------------------------------------------

module Hoodle.ModelAction.Pen where

import           Control.Lens (view,set,over)
import           Control.Monad (when)
import           Control.Monad.Identity (runIdentity)
import           Data.Foldable
import qualified Data.IntMap as IM
import           Data.Sequence hiding (take, drop)
import           Data.Strict.Tuple hiding (uncurry)
import qualified Graphics.Rendering.Cairo as Cairo
-- from hoodle-platform 
import           Data.Hoodle.BBox
import           Data.Hoodle.Generic
import           Data.Hoodle.Simple
import           Graphics.Hoodle.Render
import           Graphics.Hoodle.Render.Type
-- from this package 
import           Hoodle.ModelAction.Layer
import           Hoodle.ModelAction.Page
import           Hoodle.Type.Canvas
import           Hoodle.Type.Enum
import           Hoodle.Type.PageArrangement
--

data TempRender a = TempRender { tempSurfaceSrc :: Cairo.Surface  
                               , tempSurfaceTgt :: Cairo.Surface 
                               , widthHeight :: (Double,Double)
                               , tempInfo :: a 
                               } 


-- | update the content of temp selection. should not be often updated
updateTempRender :: TempRender a -> Cairo.Render () -> Bool -> IO ()
updateTempRender temprender renderfunc isFullErase = 
  Cairo.renderWith (tempSurfaceSrc temprender) $ do 
    when isFullErase $ do 
      let (cw,ch) = widthHeight temprender
      Cairo.setSourceRGBA 0.5 0.5 0.5 1
      Cairo.rectangle 0 0 cw ch 
      Cairo.fill 
    renderfunc    

-- |
createNewStroke :: PenInfo -> Seq (Double,Double,Double) -> Stroke 
createNewStroke pinfo pdraw = 
  let ptype = view penType pinfo
      pcolor = view (currentTool.penColor) pinfo
      pcolname = convertPenColorToByteString pcolor 
      pwidth = view (currentTool.penWidth) pinfo
      pvwpen = view variableWidthPen pinfo
      ptool = case ptype of 
                  PenWork -> "pen" 
                  HighlighterWork -> "highlighter"
                  _ -> error "error in addPDraw"
      
      newstroke = 
        case pvwpen of 
          False -> Stroke { stroke_tool = ptool 
                          , stroke_color = pcolname 
                          , stroke_width = pwidth
                          , stroke_data = map (\(x,y,_)->x:!:y) . toList $ pdraw } 
          True -> VWStroke { stroke_tool = ptool
                           , stroke_color = pcolname                 
                           , stroke_vwdata = map (\(x,y,z)->(x,y,pwidth*z)) . toList $ pdraw }
  in newstroke 


-- | 
addPDraw :: RenderCache
         -> PenInfo 
         -> RHoodle
         -> PageNum 
         -> Seq (Double,Double,Double) 
         -> IO (RHoodle,BBox) -- ^ new hoodle and bbox in page coordinate
addPDraw cache pinfo hdl (PageNum pgnum) pdraw = do 
    let currpage = getPageFromGHoodleMap pgnum hdl
        currlayer = getCurrentLayer currpage
        dim = view gdimension currpage
        newstroke = createNewStroke pinfo pdraw         
        newstrokebbox = runIdentity (makeBBoxed newstroke)
        bbox = getBBox newstrokebbox
    newlayerbbox <- updateLayerBuf cache dim (Just bbox)
                    . over gitems (++[RItemStroke newstrokebbox]) 
                    $ currlayer
    let newpagebbox = adjustCurrentLayer newlayerbbox currpage 
        newhdlbbox = set gpages (IM.adjust (const newpagebbox) pgnum (view gpages hdl) ) hdl 
    return (newhdlbbox,bbox)