module Diagrams.Backend.WX (
drawDiagram
, withDiagramImage
, renderDiagramToNewImage
, renderDiagramToImage
, ImageSizeException(..)
) where
import Control.Exception
import Control.Monad
import Data.Bifunctor
import Data.Typeable
import Diagrams.Prelude
import Diagrams.Backend.Cairo
import Diagrams.Backend.Cairo.Internal
import Graphics.Rendering.Cairo
import Graphics.UI.WX as W hiding (bracket, when)
import Graphics.UI.WX.Draw
import Graphics.UI.WXCore.Image
import Graphics.UI.WXCore.WxcClassesAL
import Graphics.UI.WXCore.WxcClassTypes
import Foreign
import Foreign.C.Types
drawDiagram :: (Monoid b, Semigroup b)
=> DC a
-> QDiagram Cairo V2 Double b -> W.Point -> SizeSpec V2 Double
-> W.Color -> [Prop (DC a)] -> IO ()
drawDiagram dc diagram point size bgColor props =
withDiagramImage diagram size bgColor $ \image ->
drawImage dc image point props
withDiagramImage :: (Monoid b, Semigroup b)
=> QDiagram Cairo V2 Double b -> SizeSpec V2 Double
-> W.Color -> (Image () -> IO c) -> IO c
withDiagramImage diagram size bgColor =
bracket (renderDiagramToNewImage diagram size bgColor) imageDelete
renderDiagramToNewImage :: (Monoid b, Semigroup b)
=> QDiagram Cairo V2 Double b -> SizeSpec V2 Double
-> W.Color -> IO (Image ())
renderDiagramToNewImage diagram size bgColor = do
let (w, h) = finalSize size diagram
image <- imageCreateSized $ sz w h
renderDiagramToImage' w h diagram bgColor image
return image
renderDiagramToImage :: (Monoid b, Semigroup b)
=> QDiagram Cairo V2 Double b -> SizeSpec V2 Double
-> W.Color -> Image i -> IO ()
renderDiagramToImage diagram size bgColor image = do
let (w, h) = finalSize size diagram
w' <- imageGetWidth image
h' <- imageGetHeight image
when (w' < w || w' < h) $ throw $ ImageSizeException (w, h) (w', h')
renderDiagramToImage' w h diagram bgColor image
renderDiagramToImage' :: (Monoid b, Semigroup b)
=> Int -> Int -> QDiagram Cairo V2 Double b
-> W.Color -> Image i -> IO ()
renderDiagramToImage' w h diagram bgColor image = do
let fmt = FormatARGB32
let stride = formatStrideForWidth fmt w
let size = stride * h
let opt = CairoOptions
{ _cairoSizeSpec = fromIntegral <$> dims2D w h
, _cairoOutputType = RenderOnly
, _cairoBypassAdjust = False
, _cairoFileName = ""
}
(_, r) = renderDia Cairo opt diagram
bracket (callocArray size) free $ \cairoPtr -> do
withImageSurfaceForData cairoPtr fmt w h stride (`renderWith` r)
withImageData image $ \wxPtr -> copyCairoToWxWidgets
(colorRed bgColor) (colorGreen bgColor) (colorBlue bgColor)
(fromIntegral size) cairoPtr (castPtr wxPtr)
finalSize :: (Monoid b, Semigroup b)
=> SizeSpec V2 Double -> QDiagram Cairo V2 Double b -> (Int, Int)
finalSize size = unr2 . fmap ceiling . fst . sizeAdjustment size . boundingBox
data ImageSizeException
= ImageSizeException !(Int, Int) !(Int, Int)
deriving (Show, Typeable)
instance Exception ImageSizeException where
displayException (ImageSizeException needed avail) =
"Can't render diagram with output size "
++ show needed
++ " to image of size "
++ show avail
foreign import ccall "util.c copyCairoToWxWidgets"
copyCairoToWxWidgets :: CFloat -> CFloat -> CFloat
-> CPtrdiff -> Ptr CUChar -> Ptr CUChar
-> IO ()