{-# LANGUAGE TypeFamilies, TypeOperators, MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- | -- Module : Graphics.Hoodle.Render.Type.Item -- Copyright : (c) 2011-2013 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim -- Stability : experimental -- Portability : GHC -- -- Rendering RItem -- ----------------------------------------------------------------------------- module Graphics.Hoodle.Render.Item where import Control.Applicative import Control.Monad import Control.Monad.Identity import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as C8 -- import qualified Data.ByteString.Lazy as LB import Data.ByteString.Base64 import Graphics.GD.ByteString import Graphics.Rendering.Cairo import qualified Graphics.Rendering.Cairo.SVG as RSVG import System.Directory import System.FilePath -- from hoodle-platform import Data.Hoodle.BBox import Data.Hoodle.Simple import Hoodle.Util.Process -- from this package import Graphics.Hoodle.Render.Type.Item -- | construct renderable item cnstrctRItem :: Item -> IO RItem cnstrctRItem (ItemStroke strk) = return (RItemStroke (runIdentity (makeBBoxed strk))) cnstrctRItem (ItemImage img) = do let imgbbx = runIdentity (makeBBoxed img) src = img_src img embed = getByteStringIfEmbeddedPNG src case embed of Just bstr -> do sfc <- saveTempPNGToCreateSurface bstr return (RItemImage imgbbx (Just sfc)) Nothing -> do let filesrc = C8.unpack (img_src img) filesrcext = takeExtension filesrc imgaction | filesrcext == ".PNG" || filesrcext == ".png" = do b <- doesFileExist filesrc if b then Just <$> imageSurfaceCreateFromPNG filesrc else return Nothing | filesrcext == ".JPG" || filesrcext == ".jpg" = do b <- doesFileExist filesrc if b then Just <$> getJPGandCreateSurface filesrc else return Nothing | otherwise = return Nothing msfc <- imgaction return (RItemImage imgbbx msfc) cnstrctRItem (ItemSVG svg@(SVG _ _ bstr _ _)) = do let str = C8.unpack bstr svgbbx = runIdentity (makeBBoxed svg) rsvg <- RSVG.svgNewFromString str return (RItemSVG svgbbx (Just rsvg)) cnstrctRItem (ItemLink lnk@(Link _ _ _ _ _ bstr _ _)) = do let str = C8.unpack bstr lnkbbx = runIdentity (makeBBoxed lnk) rsvg <- RSVG.svgNewFromString str return (RItemLink lnkbbx (Just rsvg)) cnstrctRItem (ItemLink lnk@(LinkDocID _ _ _ _ _ bstr _ _)) = do let str = C8.unpack bstr lnkbbx = runIdentity (makeBBoxed lnk) rsvg <- RSVG.svgNewFromString str return (RItemLink lnkbbx (Just rsvg)) -- | get embedded png image. If not, just give me nothing. getByteStringIfEmbeddedPNG :: C8.ByteString -> Maybe C8.ByteString getByteStringIfEmbeddedPNG bstr = do guard (C8.length bstr > 22) let (header,dat) = C8.splitAt 22 bstr guard (header == "data:image/png;base64,") either (const Nothing) return (decode dat) -- | read JPG file using GD library and create cairo image surface -- currently, this uses temporary png file (which is potentially dangerous) getJPGandCreateSurface :: FilePath -> IO Surface getJPGandCreateSurface fp = do img <- loadJpegFile fp bstr <- savePngByteString img saveTempPNGToCreateSurface bstr -- | saveTempPNGToCreateSurface :: C8.ByteString -> IO Surface saveTempPNGToCreateSurface bstr = do pipeActionWith (B.writeFile "/dev/stdout" bstr) imageSurfaceCreateFromPNG {- tdir <- getTemporaryDirectory let tfile = tdir "temp.png" imageSurfaceCreateFromPNG tfile -}