{-# LINE 2 "./Graphics/Rendering/Cairo/SVG.chs" #-}------------------------------------------------------------------------------- |-- Module : Graphics.Rendering.Cairo.SVG-- Copyright : (c) 2005 Duncan Coutts, Paolo Martini-- License : BSD-style (see cairo/COPYRIGHT)---- Maintainer : gtk2hs-devel@lists.sourceforge.net-- Stability : experimental-- Portability : portable---- The SVG extension to the Cairo 2D graphics library.-------------------------------------------------------------------------------moduleGraphics.Rendering.Cairo.SVG(-- * Convenience API-- | These operations render an SVG image directly in the current 'Render'-- contect. Because they operate in the cairo 'Render' monad they are-- affected by the current transformation matrix. So it is possible, for-- example, to scale or rotate an SVG image.---- In the following example we scale an SVG image to a unit square:---- > let (width, height) = svgGetSize in-- > do scale (1/width) (1/height)-- > svgRender svgsvgRenderFromFile,svgRenderFromHandle,svgRenderFromString,-- * Standard API-- | With this API there are seperate functions for loading the SVG and-- rendering it. This allows us to be more effecient in the case that an SVG-- image is used many times - since it can be loaded just once and rendered-- many times. With the convenience API above the SVG would be parsed and-- processed each time it is drawn.SVG,svgRender,svgGetSize,-- ** Block scoped versions-- | These versions of the SVG loading operations give temporary access-- to the 'SVG' object within the scope of the handler function. These-- operations guarantee that the resources for the SVG object are deallocated-- at the end of the handler block. If this form of resource allocation is-- too restrictive you can use the GC-managed versions below.---- These versions are ofen used in the following style:---- > withSvgFromFile "foo.svg" $ \svg -> do-- > ...-- > svgRender svg-- > ...withSvgFromFile,withSvgFromHandle,withSvgFromString,-- ** GC-managed versions-- | These versions of the SVG loading operations use the standard Haskell-- garbage collector to manage the resources associated with the 'SVG' object.-- As such they are more convenient to use but the GC cannot give-- strong guarantees about when the resources associated with the 'SVG' object-- will be released. In most circumstances this is not a problem, especially-- if the SVG files being used are not very big.svgNewFromFile,svgNewFromHandle,svgNewFromString,)whereimportControl.Monad(when)importForeignimportForeign.CimportControl.Monad.Reader(ask,liftIO)importSystem.IO(Handle,openFile,IOMode(ReadMode),hGetBuf)importSystem.Glib.GError(GError(GError),checkGError)importSystem.Glib.GObject(GObject(..),GObjectClass(..),constructNewGObject,unGObject,objectUnref)importGraphics.Rendering.Cairo.Internal(Render,bracketR)importGraphics.Rendering.Cairo.Types(Cairo(Cairo)){-# LINE 93 "./Graphics/Rendering/Cairo/SVG.chs" #-}----------------------- Types--newtypeSVG=SVG(ForeignPtr(SVG)){-# LINE 99 "./Graphics/Rendering/Cairo/SVG.chs" #-}mkSVG=(SVG,objectUnref)unSVG(SVGobj)=objinstanceGObjectClassSVGwheretoGObject=GObject.castForeignPtr.unSVGunsafeCastGObject=SVG.castForeignPtr.unGObject----------------------- Basic API---- block scoped versionswithSvgFromFile::FilePath->(SVG->Rendera)->RenderawithSvgFromFilefileaction=withSVG$\svg->doliftIO$svgParseFromFilefilesvgactionsvgwithSvgFromHandle::Handle->(SVG->Rendera)->RenderawithSvgFromHandlehndaction=withSVG$\svg->doliftIO$svgParseFromHandlehndsvgactionsvgwithSvgFromString::String->(SVG->Rendera)->RenderawithSvgFromStringstraction=withSVG$\svg->doliftIO$svgParseFromStringstrsvgactionsvgwithSVG::(SVG->Rendera)->RenderawithSVG=bracketR(dog_type_init{-# LINE 135 "./Graphics/Rendering/Cairo/SVG.chs" #-}svgPtr<-rsvg_handle_new{-# LINE 136 "./Graphics/Rendering/Cairo/SVG.chs" #-}svgPtr'<-newForeignPtr_svgPtrreturn(SVGsvgPtr'))(\(SVGfptr)->withForeignPtrfptr$\ptr->g_object_unref(castPtrptr))-- GC managed versionssvgNewFromFile::FilePath->IOSVGsvgNewFromFilefile=dosvg<-svgNewsvgParseFromFilefilesvgreturnsvgsvgNewFromHandle::Handle->IOSVGsvgNewFromHandlehnd=dosvg<-svgNewsvgParseFromHandlehndsvgreturnsvgsvgNewFromString::String->IOSVGsvgNewFromStringstr=dosvg<-svgNewsvgParseFromStringstrsvgreturnsvgsvgNew::IOSVGsvgNew=dog_type_init{-# LINE 164 "./Graphics/Rendering/Cairo/SVG.chs" #-}constructNewGObjectmkSVGrsvg_handle_new{-# LINE 165 "./Graphics/Rendering/Cairo/SVG.chs" #-}-- internal implementationsvgParseFromFile::FilePath->SVG->IO()svgParseFromFilefilesvg=dohnd<-openFilefileReadModesvgParseFromHandlehndsvgsvgParseFromHandle::Handle->SVG->IO()svgParseFromHandlehndsvg=allocaBytes4096$\bufferPtr->doletloop=docount<-hGetBufhndbufferPtr4096when(count>0)(checkStatus$(\(SVGarg1)arg2arg3arg4->withForeignPtrarg1$\argPtr1->rsvg_handle_writeargPtr1arg2arg3arg4){-# LINE 181 "./Graphics/Rendering/Cairo/SVG.chs" #-}svg(castPtrbufferPtr)(fromIntegralcount))when(count==4096)looploopcheckStatus$(\(SVGarg1)arg2->withForeignPtrarg1$\argPtr1->rsvg_handle_closeargPtr1arg2)svgsvgParseFromString::String->SVG->IO()svgParseFromStringstrsvg=doletloop""=return()loopstr=casesplitAt4096strof(chunk,str')->dowithCStringLenchunk$\(chunkPtr,len)->checkStatus$(\(SVGarg1)arg2arg3arg4->withForeignPtrarg1$\argPtr1->rsvg_handle_writeargPtr1arg2arg3arg4){-# LINE 194 "./Graphics/Rendering/Cairo/SVG.chs" #-}svg(castPtrchunkPtr)(fromIntegrallen)loopstr'loopstrcheckStatus$(\(SVGarg1)arg2->withForeignPtrarg1$\argPtr1->rsvg_handle_closeargPtr1arg2)svg-- actually render it-- | render an SVG file---- Returns @False@ if an error was detected.-- On librsvg before 2.22.3, @svgRender@ always returns @True@.svgRender::SVG->RenderBoolsvgRendersvg=docr<-askret<-liftIO$(\(SVGarg1)(Cairoarg2)->withForeignPtrarg1$\argPtr1->rsvg_handle_render_cairoargPtr1arg2)svgcrreturn(ret/=0)-- | Get the width and height of the SVG image.--svgGetSize::SVG->(Int,Int)-- ^ @(width, height)@svgGetSizesvg=unsafePerformIO$allocaBytes24$\dimentionsPtr->do(\(SVGarg1)arg2->withForeignPtrarg1$\argPtr1->rsvg_handle_get_dimensionsargPtr1arg2)svgdimentionsPtrwidth<-(\ptr->do{peekByteOffptr0::IOCInt})dimentionsPtrheight<-(\ptr->do{peekByteOffptr4::IOCInt})dimentionsPtrreturn(fromIntegralwidth,fromIntegralheight)----------------------- Convenience API--svgRenderFromFile::FilePath->RenderBoolsvgRenderFromFilefile=withSvgFromFilefilesvgRendersvgRenderFromHandle::Handle->RenderBoolsvgRenderFromHandlehnd=withSvgFromHandlehndsvgRendersvgRenderFromString::String->RenderBoolsvgRenderFromStringstr=withSvgFromStringstrsvgRender----------------------- Utils--checkStatus::(Ptr(Ptr())->IOCInt)->IO()checkStatusaction=checkGError(\ptr->actionptr>>return())(\(GErrordomaincodemsg)->fail("svg cairo error: "++msg))foreignimportccallsafe"g_type_init"g_type_init::(IO())foreignimportccallunsafe"rsvg_handle_new"rsvg_handle_new::(IO(PtrSVG))foreignimportccallunsafe"g_object_unref"g_object_unref::((Ptr())->(IO()))foreignimportccallunsafe"rsvg_handle_write"rsvg_handle_write::((PtrSVG)->((PtrCUChar)->(CUInt->((Ptr(Ptr()))->(IOCInt)))))foreignimportccallunsafe"rsvg_handle_close"rsvg_handle_close::((PtrSVG)->((Ptr(Ptr()))->(IOCInt)))foreignimportccallunsafe"rsvg_handle_render_cairo"rsvg_handle_render_cairo::((PtrSVG)->((PtrCairo)->(IOCInt)))foreignimportccallunsafe"rsvg_handle_get_dimensions"rsvg_handle_get_dimensions::((PtrSVG)->((Ptr())->(IO())))