packages feed

reanimate-svg 0.8.2.0 → 0.9.0.0

raw patch · 7 files changed

+215/−52 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Graphics.SvgTree.Memo: memo :: (Typeable a, Show a) => (a -> Tree) -> a -> Tree
+ Graphics.SvgTree.Memo: preRender :: Tree -> Tree
+ Graphics.SvgTree.Printer: ppDocument :: Document -> String
+ Graphics.SvgTree.Printer: ppTree :: Tree -> String
+ Graphics.SvgTree.Types: [_preRendered] :: DrawAttributes -> !Maybe String
+ Graphics.SvgTree.Types: instance Graphics.SvgTree.Types.HasGroup (Graphics.SvgTree.Types.Definitions a) a
+ Graphics.SvgTree.Types: instance Graphics.SvgTree.Types.HasGroup (Graphics.SvgTree.Types.Symbol a) a
+ Graphics.SvgTree.Types: preRendered :: HasDrawAttributes c_apcL => Lens' c_apcL (Maybe String)
- Graphics.SvgTree.PathParser: serializeCommand :: PathCommand -> String
+ Graphics.SvgTree.PathParser: serializeCommand :: PathCommand -> ShowS
- Graphics.SvgTree.PathParser: serializeCommands :: [PathCommand] -> String
+ Graphics.SvgTree.PathParser: serializeCommands :: [PathCommand] -> ShowS
- Graphics.SvgTree.PathParser: serializeGradientCommand :: GradientPathCommand -> String
+ Graphics.SvgTree.PathParser: serializeGradientCommand :: GradientPathCommand -> ShowS
- Graphics.SvgTree.PathParser: serializePoints :: [RPoint] -> String
+ Graphics.SvgTree.PathParser: serializePoints :: [RPoint] -> ShowS
- Graphics.SvgTree.Types: DrawAttributes :: !Last Number -> !Last Texture -> !Maybe Float -> !Last Cap -> !Last LineJoin -> !Last Double -> !Last Texture -> !Maybe Float -> !Maybe Float -> !Maybe [Transformation] -> !Last FillRule -> !Last ElementRef -> !Last ElementRef -> !Last FillRule -> ![Text] -> !Maybe String -> !Last Number -> !Last [Number] -> !Last Number -> !Last [String] -> !Last FontStyle -> !Last TextAnchor -> !Last ElementRef -> !Last ElementRef -> !Last ElementRef -> !Last ElementRef -> DrawAttributes
+ Graphics.SvgTree.Types: DrawAttributes :: !Last Number -> !Last Texture -> !Maybe Float -> !Last Cap -> !Last LineJoin -> !Last Double -> !Last Texture -> !Maybe Float -> !Maybe Float -> !Maybe [Transformation] -> !Last FillRule -> !Last ElementRef -> !Last ElementRef -> !Last FillRule -> ![Text] -> !Maybe String -> !Last Number -> !Last [Number] -> !Last Number -> !Last [String] -> !Last FontStyle -> !Last TextAnchor -> !Last ElementRef -> !Last ElementRef -> !Last ElementRef -> !Last ElementRef -> !Maybe String -> DrawAttributes
- Graphics.SvgTree.Types: attrClass :: HasDrawAttributes c_apco => Lens' c_apco [Text]
+ Graphics.SvgTree.Types: attrClass :: HasDrawAttributes c_apcL => Lens' c_apcL [Text]
- Graphics.SvgTree.Types: attrId :: HasDrawAttributes c_apco => Lens' c_apco (Maybe String)
+ Graphics.SvgTree.Types: attrId :: HasDrawAttributes c_apcL => Lens' c_apcL (Maybe String)
- Graphics.SvgTree.Types: class HasColorMatrix c_ayea
+ Graphics.SvgTree.Types: class HasColorMatrix c_aymy
- Graphics.SvgTree.Types: class HasComposite c_ay4T
+ Graphics.SvgTree.Types: class HasComposite c_aydh
- Graphics.SvgTree.Types: class HasDocument c_axba
+ Graphics.SvgTree.Types: class HasDocument c_axjl
- Graphics.SvgTree.Types: class HasDrawAttributes c_apco
+ Graphics.SvgTree.Types: class HasDrawAttributes c_apcL
- Graphics.SvgTree.Types: class HasGaussianBlur c_ayjn
+ Graphics.SvgTree.Types: class HasGaussianBlur c_ayrL
- Graphics.SvgTree.Types: class HasTextPath c_axTe
+ Graphics.SvgTree.Types: class HasTextPath c_ay1r
- Graphics.SvgTree.Types: clipPathRef :: HasDrawAttributes c_apco => Lens' c_apco (Last ElementRef)
+ Graphics.SvgTree.Types: clipPathRef :: HasDrawAttributes c_apcL => Lens' c_apcL (Last ElementRef)
- Graphics.SvgTree.Types: clipRule :: HasDrawAttributes c_apco => Lens' c_apco (Last FillRule)
+ Graphics.SvgTree.Types: clipRule :: HasDrawAttributes c_apcL => Lens' c_apcL (Last FillRule)
- Graphics.SvgTree.Types: colorMatrix :: HasColorMatrix c_ayea => Lens' c_ayea ColorMatrix
+ Graphics.SvgTree.Types: colorMatrix :: HasColorMatrix c_aymy => Lens' c_aymy ColorMatrix
- Graphics.SvgTree.Types: colorMatrixDrawAttributes :: HasColorMatrix c_ayea => Lens' c_ayea DrawAttributes
+ Graphics.SvgTree.Types: colorMatrixDrawAttributes :: HasColorMatrix c_aymy => Lens' c_aymy DrawAttributes
- Graphics.SvgTree.Types: colorMatrixFilterAttr :: HasColorMatrix c_ayea => Lens' c_ayea FilterAttributes
+ Graphics.SvgTree.Types: colorMatrixFilterAttr :: HasColorMatrix c_aymy => Lens' c_aymy FilterAttributes
- Graphics.SvgTree.Types: colorMatrixIn :: HasColorMatrix c_ayea => Lens' c_ayea (Last FilterSource)
+ Graphics.SvgTree.Types: colorMatrixIn :: HasColorMatrix c_aymy => Lens' c_aymy (Last FilterSource)
- Graphics.SvgTree.Types: colorMatrixType :: HasColorMatrix c_ayea => Lens' c_ayea ColorMatrixType
+ Graphics.SvgTree.Types: colorMatrixType :: HasColorMatrix c_aymy => Lens' c_aymy ColorMatrixType
- Graphics.SvgTree.Types: colorMatrixValues :: HasColorMatrix c_ayea => Lens' c_ayea String
+ Graphics.SvgTree.Types: colorMatrixValues :: HasColorMatrix c_aymy => Lens' c_aymy String
- Graphics.SvgTree.Types: composite :: HasComposite c_ay4T => Lens' c_ay4T Composite
+ Graphics.SvgTree.Types: composite :: HasComposite c_aydh => Lens' c_aydh Composite
- Graphics.SvgTree.Types: compositeDrawAttributes :: HasComposite c_ay4T => Lens' c_ay4T DrawAttributes
+ Graphics.SvgTree.Types: compositeDrawAttributes :: HasComposite c_aydh => Lens' c_aydh DrawAttributes
- Graphics.SvgTree.Types: compositeFilterAttr :: HasComposite c_ay4T => Lens' c_ay4T FilterAttributes
+ Graphics.SvgTree.Types: compositeFilterAttr :: HasComposite c_aydh => Lens' c_aydh FilterAttributes
- Graphics.SvgTree.Types: compositeIn :: HasComposite c_ay4T => Lens' c_ay4T (Last FilterSource)
+ Graphics.SvgTree.Types: compositeIn :: HasComposite c_aydh => Lens' c_aydh (Last FilterSource)
- Graphics.SvgTree.Types: compositeIn2 :: HasComposite c_ay4T => Lens' c_ay4T (Last FilterSource)
+ Graphics.SvgTree.Types: compositeIn2 :: HasComposite c_aydh => Lens' c_aydh (Last FilterSource)
- Graphics.SvgTree.Types: compositeK1 :: HasComposite c_ay4T => Lens' c_ay4T Number
+ Graphics.SvgTree.Types: compositeK1 :: HasComposite c_aydh => Lens' c_aydh Number
- Graphics.SvgTree.Types: compositeK2 :: HasComposite c_ay4T => Lens' c_ay4T Number
+ Graphics.SvgTree.Types: compositeK2 :: HasComposite c_aydh => Lens' c_aydh Number
- Graphics.SvgTree.Types: compositeK3 :: HasComposite c_ay4T => Lens' c_ay4T Number
+ Graphics.SvgTree.Types: compositeK3 :: HasComposite c_aydh => Lens' c_aydh Number
- Graphics.SvgTree.Types: compositeK4 :: HasComposite c_ay4T => Lens' c_ay4T Number
+ Graphics.SvgTree.Types: compositeK4 :: HasComposite c_aydh => Lens' c_aydh Number
- Graphics.SvgTree.Types: compositeOperator :: HasComposite c_ay4T => Lens' c_ay4T CompositeOperator
+ Graphics.SvgTree.Types: compositeOperator :: HasComposite c_aydh => Lens' c_aydh CompositeOperator
- Graphics.SvgTree.Types: definitions :: HasDocument c_axba => Lens' c_axba (Map String Tree)
+ Graphics.SvgTree.Types: definitions :: HasDocument c_axjl => Lens' c_axjl (Map String Tree)
- Graphics.SvgTree.Types: description :: HasDocument c_axba => Lens' c_axba String
+ Graphics.SvgTree.Types: description :: HasDocument c_axjl => Lens' c_axjl String
- Graphics.SvgTree.Types: document :: HasDocument c_axba => Lens' c_axba Document
+ Graphics.SvgTree.Types: document :: HasDocument c_axjl => Lens' c_axjl Document
- Graphics.SvgTree.Types: documentLocation :: HasDocument c_axba => Lens' c_axba FilePath
+ Graphics.SvgTree.Types: documentLocation :: HasDocument c_axjl => Lens' c_axjl FilePath
- Graphics.SvgTree.Types: drawAttributes :: HasDrawAttributes c_apco => Lens' c_apco DrawAttributes
+ Graphics.SvgTree.Types: drawAttributes :: HasDrawAttributes c_apcL => Lens' c_apcL DrawAttributes
- Graphics.SvgTree.Types: elements :: HasDocument c_axba => Lens' c_axba [Tree]
+ Graphics.SvgTree.Types: elements :: HasDocument c_axjl => Lens' c_axjl [Tree]
- Graphics.SvgTree.Types: fillColor :: HasDrawAttributes c_apco => Lens' c_apco (Last Texture)
+ Graphics.SvgTree.Types: fillColor :: HasDrawAttributes c_apcL => Lens' c_apcL (Last Texture)
- Graphics.SvgTree.Types: fillOpacity :: HasDrawAttributes c_apco => Lens' c_apco (Maybe Float)
+ Graphics.SvgTree.Types: fillOpacity :: HasDrawAttributes c_apcL => Lens' c_apcL (Maybe Float)
- Graphics.SvgTree.Types: fillRule :: HasDrawAttributes c_apco => Lens' c_apco (Last FillRule)
+ Graphics.SvgTree.Types: fillRule :: HasDrawAttributes c_apcL => Lens' c_apcL (Last FillRule)
- Graphics.SvgTree.Types: filterRef :: HasDrawAttributes c_apco => Lens' c_apco (Last ElementRef)
+ Graphics.SvgTree.Types: filterRef :: HasDrawAttributes c_apcL => Lens' c_apcL (Last ElementRef)
- Graphics.SvgTree.Types: fontFamily :: HasDrawAttributes c_apco => Lens' c_apco (Last [String])
+ Graphics.SvgTree.Types: fontFamily :: HasDrawAttributes c_apcL => Lens' c_apcL (Last [String])
- Graphics.SvgTree.Types: fontSize :: HasDrawAttributes c_apco => Lens' c_apco (Last Number)
+ Graphics.SvgTree.Types: fontSize :: HasDrawAttributes c_apcL => Lens' c_apcL (Last Number)
- Graphics.SvgTree.Types: fontStyle :: HasDrawAttributes c_apco => Lens' c_apco (Last FontStyle)
+ Graphics.SvgTree.Types: fontStyle :: HasDrawAttributes c_apcL => Lens' c_apcL (Last FontStyle)
- Graphics.SvgTree.Types: gaussianBlur :: HasGaussianBlur c_ayjn => Lens' c_ayjn GaussianBlur
+ Graphics.SvgTree.Types: gaussianBlur :: HasGaussianBlur c_ayrL => Lens' c_ayrL GaussianBlur
- Graphics.SvgTree.Types: gaussianBlurDrawAttributes :: HasGaussianBlur c_ayjn => Lens' c_ayjn DrawAttributes
+ Graphics.SvgTree.Types: gaussianBlurDrawAttributes :: HasGaussianBlur c_ayrL => Lens' c_ayrL DrawAttributes
- Graphics.SvgTree.Types: gaussianBlurEdgeMode :: HasGaussianBlur c_ayjn => Lens' c_ayjn EdgeMode
+ Graphics.SvgTree.Types: gaussianBlurEdgeMode :: HasGaussianBlur c_ayrL => Lens' c_ayrL EdgeMode
- Graphics.SvgTree.Types: gaussianBlurFilterAttr :: HasGaussianBlur c_ayjn => Lens' c_ayjn FilterAttributes
+ Graphics.SvgTree.Types: gaussianBlurFilterAttr :: HasGaussianBlur c_ayrL => Lens' c_ayrL FilterAttributes
- Graphics.SvgTree.Types: gaussianBlurIn :: HasGaussianBlur c_ayjn => Lens' c_ayjn (Last FilterSource)
+ Graphics.SvgTree.Types: gaussianBlurIn :: HasGaussianBlur c_ayrL => Lens' c_ayrL (Last FilterSource)
- Graphics.SvgTree.Types: gaussianBlurStdDeviationX :: HasGaussianBlur c_ayjn => Lens' c_ayjn Number
+ Graphics.SvgTree.Types: gaussianBlurStdDeviationX :: HasGaussianBlur c_ayrL => Lens' c_ayrL Number
- Graphics.SvgTree.Types: gaussianBlurStdDeviationY :: HasGaussianBlur c_ayjn => Lens' c_ayjn (Last Number)
+ Graphics.SvgTree.Types: gaussianBlurStdDeviationY :: HasGaussianBlur c_ayrL => Lens' c_ayrL (Last Number)
- Graphics.SvgTree.Types: groupOpacity :: HasDrawAttributes c_apco => Lens' c_apco (Maybe Float)
+ Graphics.SvgTree.Types: groupOpacity :: HasDrawAttributes c_apcL => Lens' c_apcL (Maybe Float)
- Graphics.SvgTree.Types: height :: HasDocument c_axba => Lens' c_axba (Maybe Number)
+ Graphics.SvgTree.Types: height :: HasDocument c_axjl => Lens' c_axjl (Maybe Number)
- Graphics.SvgTree.Types: markerEnd :: HasDrawAttributes c_apco => Lens' c_apco (Last ElementRef)
+ Graphics.SvgTree.Types: markerEnd :: HasDrawAttributes c_apcL => Lens' c_apcL (Last ElementRef)
- Graphics.SvgTree.Types: markerMid :: HasDrawAttributes c_apco => Lens' c_apco (Last ElementRef)
+ Graphics.SvgTree.Types: markerMid :: HasDrawAttributes c_apcL => Lens' c_apcL (Last ElementRef)
- Graphics.SvgTree.Types: markerStart :: HasDrawAttributes c_apco => Lens' c_apco (Last ElementRef)
+ Graphics.SvgTree.Types: markerStart :: HasDrawAttributes c_apcL => Lens' c_apcL (Last ElementRef)
- Graphics.SvgTree.Types: maskRef :: HasDrawAttributes c_apco => Lens' c_apco (Last ElementRef)
+ Graphics.SvgTree.Types: maskRef :: HasDrawAttributes c_apcL => Lens' c_apcL (Last ElementRef)
- Graphics.SvgTree.Types: strokeColor :: HasDrawAttributes c_apco => Lens' c_apco (Last Texture)
+ Graphics.SvgTree.Types: strokeColor :: HasDrawAttributes c_apcL => Lens' c_apcL (Last Texture)
- Graphics.SvgTree.Types: strokeDashArray :: HasDrawAttributes c_apco => Lens' c_apco (Last [Number])
+ Graphics.SvgTree.Types: strokeDashArray :: HasDrawAttributes c_apcL => Lens' c_apcL (Last [Number])
- Graphics.SvgTree.Types: strokeLineCap :: HasDrawAttributes c_apco => Lens' c_apco (Last Cap)
+ Graphics.SvgTree.Types: strokeLineCap :: HasDrawAttributes c_apcL => Lens' c_apcL (Last Cap)
- Graphics.SvgTree.Types: strokeLineJoin :: HasDrawAttributes c_apco => Lens' c_apco (Last LineJoin)
+ Graphics.SvgTree.Types: strokeLineJoin :: HasDrawAttributes c_apcL => Lens' c_apcL (Last LineJoin)
- Graphics.SvgTree.Types: strokeMiterLimit :: HasDrawAttributes c_apco => Lens' c_apco (Last Double)
+ Graphics.SvgTree.Types: strokeMiterLimit :: HasDrawAttributes c_apcL => Lens' c_apcL (Last Double)
- Graphics.SvgTree.Types: strokeOffset :: HasDrawAttributes c_apco => Lens' c_apco (Last Number)
+ Graphics.SvgTree.Types: strokeOffset :: HasDrawAttributes c_apcL => Lens' c_apcL (Last Number)
- Graphics.SvgTree.Types: strokeOpacity :: HasDrawAttributes c_apco => Lens' c_apco (Maybe Float)
+ Graphics.SvgTree.Types: strokeOpacity :: HasDrawAttributes c_apcL => Lens' c_apcL (Maybe Float)
- Graphics.SvgTree.Types: strokeWidth :: HasDrawAttributes c_apco => Lens' c_apco (Last Number)
+ Graphics.SvgTree.Types: strokeWidth :: HasDrawAttributes c_apcL => Lens' c_apcL (Last Number)
- Graphics.SvgTree.Types: textAnchor :: HasDrawAttributes c_apco => Lens' c_apco (Last TextAnchor)
+ Graphics.SvgTree.Types: textAnchor :: HasDrawAttributes c_apcL => Lens' c_apcL (Last TextAnchor)
- Graphics.SvgTree.Types: textPath :: HasTextPath c_axTe => Lens' c_axTe TextPath
+ Graphics.SvgTree.Types: textPath :: HasTextPath c_ay1r => Lens' c_ay1r TextPath
- Graphics.SvgTree.Types: textPathMethod :: HasTextPath c_axTe => Lens' c_axTe TextPathMethod
+ Graphics.SvgTree.Types: textPathMethod :: HasTextPath c_ay1r => Lens' c_ay1r TextPathMethod
- Graphics.SvgTree.Types: textPathName :: HasTextPath c_axTe => Lens' c_axTe String
+ Graphics.SvgTree.Types: textPathName :: HasTextPath c_ay1r => Lens' c_ay1r String
- Graphics.SvgTree.Types: textPathSpacing :: HasTextPath c_axTe => Lens' c_axTe TextPathSpacing
+ Graphics.SvgTree.Types: textPathSpacing :: HasTextPath c_ay1r => Lens' c_ay1r TextPathSpacing
- Graphics.SvgTree.Types: textPathStartOffset :: HasTextPath c_axTe => Lens' c_axTe Number
+ Graphics.SvgTree.Types: textPathStartOffset :: HasTextPath c_ay1r => Lens' c_ay1r Number
- Graphics.SvgTree.Types: transform :: HasDrawAttributes c_apco => Lens' c_apco (Maybe [Transformation])
+ Graphics.SvgTree.Types: transform :: HasDrawAttributes c_apcL => Lens' c_apcL (Maybe [Transformation])
- Graphics.SvgTree.Types: viewBox :: HasDocument c_axba => Lens' c_axba (Maybe (Double, Double, Double, Double))
+ Graphics.SvgTree.Types: viewBox :: HasDocument c_axjl => Lens' c_axjl (Maybe (Double, Double, Double, Double))
- Graphics.SvgTree.Types: width :: HasDocument c_axba => Lens' c_axba (Maybe Number)
+ Graphics.SvgTree.Types: width :: HasDocument c_axjl => Lens' c_axjl (Maybe Number)

Files

changelog.md view
@@ -1,5 +1,10 @@ -*-change-log-*- +v0.9.0.0 April 2019++ * Performance optimizations.+ * Memo module and render cache.+ v0.8.2.0 March 2019   * Export parser and serializer.
reanimate-svg.cabal view
@@ -1,5 +1,5 @@ name:                reanimate-svg-version:             0.8.2.0+version:             0.9.0.0 synopsis:            SVG file loader and serializer description:   reanimate-svg provides types representing a SVG document,@@ -34,6 +34,8 @@                  , Graphics.SvgTree.Types                  , Graphics.SvgTree.PathParser                  , Graphics.SvgTree.NamedColors+                 , Graphics.SvgTree.Memo+                 , Graphics.SvgTree.Printer    other-modules: Graphics.SvgTree.XmlParser                , Graphics.SvgTree.CssParser
+ src/Graphics/SvgTree/Memo.hs view
@@ -0,0 +1,83 @@+module Graphics.SvgTree.Memo+  ( memo+  , preRender+  ) where++import           Control.Lens+import           Data.IORef+import           Data.Map                 (Map)+import qualified Data.Map                 as Map+import           Data.Maybe+import           Data.Typeable+import           Graphics.SvgTree.Printer+import           Graphics.SvgTree.Types   (Tree, preRendered)+import           System.IO.Unsafe++{-# NOINLINE intCache #-}+intCache :: IORef (Map Int Tree)+intCache = unsafePerformIO (newIORef Map.empty)++{-# NOINLINE doubleCache #-}+doubleCache :: IORef (Map Double Tree)+doubleCache = unsafePerformIO (newIORef Map.empty)++{-# NOINLINE anyCache #-}+anyCache :: IORef (Map (TypeRep,String) Tree)+anyCache = unsafePerformIO (newIORef Map.empty)++memo :: (Typeable a, Show a) => (a -> Tree) -> (a -> Tree)+memo fn =+  case listToMaybe (catMaybes caches) of+    Just ret -> ret+    Nothing  -> memoAny fn+  where+    caches = [try intCache, try doubleCache]+    try cache = cast . memoUsing cache =<< cast fn++memoUsing :: Ord a => IORef (Map a Tree) -> (a -> Tree) -> (a -> Tree)+memoUsing cache fn a = unsafePerformIO $+  atomicModifyIORef cache $ \m ->+    let newVal = preRender $ fn a+        notFound =+          (Map.insert a newVal m, newVal) in+    case Map.lookup a m of+      Nothing -> notFound+      Just t  -> (m, t)++memoAny :: (Typeable a, Show a) => (a -> Tree) -> (a -> Tree)+memoAny fn a = unsafePerformIO $+  atomicModifyIORef anyCache $ \m ->+    let newVal = preRender $ fn a+        notFound =+          (Map.insert (typeOf a, show a) newVal m, newVal) in+    case Map.lookup (typeOf a, show a) m of+      Nothing -> notFound+      Just t  -> (m, t)++preRender :: Tree -> Tree+preRender t = t & preRendered .~ Just (ppTree t)++-- {-# INLINE memo #-}+-- memo :: (a -> b) -> (a -> b)+-- memo fn = unsafePerformIO $ do+--   ref <- newIORef Map.empty+--   return $ \a -> unsafePerformIO $ do+--     stableA <- makeStableName a+--     let key = hashStableName stableA+--     atomicModifyIORef ref $ \m ->+--       case Map.lookup key m of+--         -- Just (s,b) | s == stableA ->+--         --   (m, b)+--         _Nothing -> let !b = fn a in+--           (Map.insert key (stableA, b) m, b)+-- memo fn = unsafePerformIO $ do+--   ht <- HT.new :: IO (HT.BasicHashTable (StableName Any) Any)+--   return $ \a -> unsafePerformIO $ do+--     stableA <- makeStableName $ unsafeCoerce a+--     mbB <- HT.lookup ht stableA+--     case mbB of+--       Just b -> return (unsafeCoerce b)+--       Nothing -> do+--         let !b = fn a+--         HT.insert ht stableA (unsafeCoerce b)+--         return b
src/Graphics/SvgTree/PathParser.hs view
@@ -25,6 +25,9 @@                                              string) import           Data.Scientific            (toRealFloat) +import Numeric+import Text.Show+import Data.List import qualified Data.Text                  as T import           Graphics.SvgTree.Types import           Linear                     hiding (angle, point)@@ -101,58 +104,68 @@                                    <*> (fmap (/= 0) numComma)                                    <*> point -serializePoint :: RPoint -> String-serializePoint (V2 x y) = printf "%g,%g" x y+unwordsS :: [ShowS] -> ShowS+unwordsS = foldr (.) id . intersperse (showChar ' ') -serializePoints :: [RPoint] -> String-serializePoints = unwords . fmap serializePoint+serializePoint :: RPoint -> ShowS+serializePoint (V2 x y) = showFFloat Nothing x . showChar ',' . showFFloat Nothing y -serializeCoords :: [Coord] -> String-serializeCoords = unwords . fmap (printf "%g")+serializePoints :: [RPoint] -> ShowS+serializePoints = unwordsS . map serializePoint -serializePointPair :: (RPoint, RPoint) -> String-serializePointPair (a, b) = serializePoint a ++ " " ++ serializePoint b+serializeCoords :: [Coord] -> ShowS+serializeCoords = unwordsS . fmap (showFFloat Nothing) -serializePointPairs :: [(RPoint, RPoint)] -> String-serializePointPairs = unwords . fmap serializePointPair+serializePointPair :: (RPoint, RPoint) -> ShowS+serializePointPair (a, b) = serializePoint a . showChar ' ' . serializePoint b -serializePointTriplet :: (RPoint, RPoint, RPoint) -> String+serializePointPairs :: [(RPoint, RPoint)] -> ShowS+serializePointPairs = unwordsS . fmap serializePointPair++serializePointTriplet :: (RPoint, RPoint, RPoint) -> ShowS serializePointTriplet (a, b, c) =-    serializePoint a ++ " " ++ serializePoint b ++ " " ++ serializePoint c+    serializePoint a . showChar ' ' . serializePoint b . showChar ' ' . serializePoint c -serializePointTriplets :: [(RPoint, RPoint, RPoint)] -> String-serializePointTriplets = unwords . fmap serializePointTriplet+serializePointTriplets :: [(RPoint, RPoint, RPoint)] -> ShowS+serializePointTriplets = unwordsS . fmap serializePointTriplet -serializeCommands :: [PathCommand] -> String-serializeCommands = unwords . fmap serializeCommand+serializeCommands :: [PathCommand] -> ShowS+serializeCommands = unwordsS . fmap serializeCommand -serializeCommand :: PathCommand -> String+serializeCommand :: PathCommand -> ShowS serializeCommand p = case p of-  MoveTo OriginAbsolute points -> "M" ++ serializePoints points-  MoveTo OriginRelative points -> "m" ++ serializePoints points-  LineTo OriginAbsolute points -> "L" ++ serializePoints points-  LineTo OriginRelative points -> "l" ++ serializePoints points+  MoveTo OriginAbsolute points -> showChar 'M' . serializePoints points+  MoveTo OriginRelative points -> showChar 'm' . serializePoints points+  LineTo OriginAbsolute points -> showChar 'L' . serializePoints points+  LineTo OriginRelative points -> showChar 'l' . serializePoints points -  HorizontalTo OriginAbsolute coords -> "H" ++ serializeCoords coords-  HorizontalTo OriginRelative coords -> "h" ++ serializeCoords coords-  VerticalTo OriginAbsolute coords -> "V" ++ serializeCoords coords-  VerticalTo OriginRelative coords -> "v" ++ serializeCoords coords+  HorizontalTo OriginRelative coords -> showChar 'h' . serializeCoords coords+  HorizontalTo OriginAbsolute coords -> showChar 'H' . serializeCoords coords+  VerticalTo OriginAbsolute coords   -> showChar 'V' . serializeCoords coords+  VerticalTo OriginRelative coords   -> showChar 'v' . serializeCoords coords -  CurveTo OriginAbsolute triplets -> "C" ++ serializePointTriplets triplets-  CurveTo OriginRelative triplets -> "c" ++ serializePointTriplets triplets-  SmoothCurveTo OriginAbsolute pointPairs -> "S" ++ serializePointPairs pointPairs-  SmoothCurveTo OriginRelative pointPairs -> "s" ++ serializePointPairs pointPairs-  QuadraticBezier OriginAbsolute pointPairs -> "Q" ++ serializePointPairs pointPairs-  QuadraticBezier OriginRelative pointPairs -> "q" ++ serializePointPairs pointPairs-  SmoothQuadraticBezierCurveTo OriginAbsolute points -> "T" ++ serializePoints points-  SmoothQuadraticBezierCurveTo OriginRelative points -> "t" ++ serializePoints points-  EllipticalArc OriginAbsolute args -> "A" ++ serializeArgs args-  EllipticalArc OriginRelative args -> "a" ++ serializeArgs args-  EndPath -> "Z"+  CurveTo OriginAbsolute triplets -> showChar 'C' . serializePointTriplets triplets+  CurveTo OriginRelative triplets -> showChar 'c' . serializePointTriplets triplets+  SmoothCurveTo OriginAbsolute pointPairs -> showChar 'S' . serializePointPairs pointPairs+  SmoothCurveTo OriginRelative pointPairs -> showChar 's' . serializePointPairs pointPairs+  QuadraticBezier OriginAbsolute pointPairs -> showChar 'Q' . serializePointPairs pointPairs+  QuadraticBezier OriginRelative pointPairs -> showChar 'q' . serializePointPairs pointPairs+  SmoothQuadraticBezierCurveTo OriginAbsolute points -> showChar 'T' . serializePoints points+  SmoothQuadraticBezierCurveTo OriginRelative points -> showChar 't' . serializePoints points+  EllipticalArc OriginAbsolute args -> showChar 'A' . serializeArgs args+  EllipticalArc OriginRelative args -> showChar 'a' . serializeArgs args+  EndPath -> showChar 'Z'   where     serializeArg (a, b, c, d, e, V2 x y) =-        printf "%g %g %g %d %d %g,%g" a b c (fromEnum d) (fromEnum e) x y-    serializeArgs = unwords . fmap serializeArg+        showFFloat Nothing a . showChar ' ' .+        showFFloat Nothing b . showChar ' ' .+        showFFloat Nothing c . showChar ' ' .+        shows (fromEnum d) . showChar ' ' .+        shows (fromEnum e) . showChar ' ' .+        showFFloat Nothing x . showChar ',' .+        showFFloat Nothing y+        -- printf "%g %g %g %d %d %g,%g" a b c (fromEnum d) (fromEnum e) x y+    serializeArgs = unwordsS . fmap serializeArg   @@ -242,15 +255,15 @@                  <*> (point <* commaWsp)                  <*> mayPoint -serializeGradientCommand :: GradientPathCommand -> String+serializeGradientCommand :: GradientPathCommand -> ShowS serializeGradientCommand p = case p of-  GLine OriginAbsolute points -> "L" ++ smp points-  GLine OriginRelative points -> "l" ++ smp points-  GClose                      -> "Z"+  GLine OriginAbsolute points -> showChar 'L' . smp points+  GLine OriginRelative points -> showChar 'l' . smp points+  GClose                      -> showChar 'Z' -  GCurve OriginAbsolute a b c -> "C" ++ sp a ++ sp b ++ smp c-  GCurve OriginRelative a b c -> "c" ++ sp a ++ sp b ++ smp c+  GCurve OriginAbsolute a b c -> showChar 'C' . sp a . sp b . smp c+  GCurve OriginRelative a b c -> showChar 'c' . sp a . sp b . smp c   where     sp = serializePoint-    smp Nothing   = ""+    smp Nothing   = id     smp (Just pp) = serializePoint pp
+ src/Graphics/SvgTree/Printer.hs view
@@ -0,0 +1,50 @@+module Graphics.SvgTree.Printer+  ( ppTree+  , ppDocument+  ) where++import           Control.Lens+import           Data.Char+import           Data.List+import           Graphics.SvgTree.Types     (DrawAttributes, Tree (..),+                                             groupChildren,+                                             preRendered, Document(..))+import           Graphics.SvgTree.XmlParser+import           Text.XML.Light++ppDocument :: Document -> String+ppDocument doc =+  ppElementS_ (_elements doc) (xmlOfDocument doc) ""++ppTree :: Tree -> String+ppTree t = ppTreeS t ""++ppTreeS :: Tree -> ShowS+ppTreeS tree =+  case tree ^. preRendered of+    Nothing ->+      case xmlOfTree tree of+        Just x  -> ppElementS_ (treeChildren tree) x+        Nothing -> id+    Just s -> showString s++treeChildren :: Tree -> [Tree]+treeChildren (GroupTree g)      = g^.groupChildren+treeChildren (SymbolTree g)     = g^.groupChildren+treeChildren (DefinitionTree g) = g^.groupChildren+treeChildren _                  = []++ppElementS_         :: [Tree] -> Element -> ShowS+ppElementS_ children e xs = tagStart name (elAttribs e) $+  case children of+    [] | "?" `isPrefixOf` qName name -> showString " ?>" xs+       | True  -> showString " />" xs+    _ -> showChar '>' (foldr ppTreeS (tagEnd name xs) children)+  where name = elName e++--------------------------------------------------------------------------------+tagStart           :: QName -> [Attr] -> ShowS+tagStart qn as rs   = '<':showQName qn ++ as_str ++ rs+ where as_str       = if null as then "" else ' ' : unwords (map showAttr as)+       showAttr           :: Attr -> String+       showAttr (Attr qn v) = showQName qn ++ '=' : '"' : v ++ "\""
src/Graphics/SvgTree/Types.hs view
@@ -564,6 +564,7 @@       -- Correspond to the `marker-end` attribute.     , _markerEnd        :: !(Last ElementRef)     , _filterRef        :: !(Last ElementRef)+    , _preRendered      :: !(Maybe String)     }     deriving (Eq, Show) @@ -889,6 +890,9 @@     Symbol { _groupOfSymbol :: Group a }   deriving (Eq, Show) +instance HasGroup (Symbol a) a where+  group = groupOfSymbol+ -- makeLenses ''Symbol -- | Lenses associated with the Symbol type. groupOfSymbol :: Lens (Symbol s) (Symbol t) (Group s) (Group t)@@ -907,6 +911,9 @@     Definitions { _groupOfDefinitions :: Group a }   deriving (Eq, Show) +instance HasGroup (Definitions a) a where+  group = groupOfDefinitions+ -- makeLenses ''Definitions -- | Lenses associated with the Definitions type. groupOfDefinitions :: Lens (Definitions s) (Definitions t) (Group s) (Group t)@@ -2031,12 +2038,12 @@   ClipPathTree e       -> e ^. drawAttributes  setDrawAttrOfTree :: Tree -> DrawAttributes -> Tree-setDrawAttrOfTree v attr = case v of+setDrawAttrOfTree v attr' = case v of   None                 -> None   UseTree e m          -> UseTree (e & drawAttributes .~ attr) m   GroupTree e          -> GroupTree $ e & drawAttributes .~ attr   SymbolTree e         -> SymbolTree $ e & drawAttributes .~ attr-  DefinitionTree e     -> DefinitionTree e & drawAttributes .~ attr+  DefinitionTree e     -> DefinitionTree $ e & drawAttributes .~ attr   FilterTree e         -> FilterTree $ e & drawAttributes .~ attr   PathTree e           -> PathTree $ e & drawAttributes .~ attr   CircleTree e         -> CircleTree $ e & drawAttributes .~ attr@@ -2054,7 +2061,8 @@   MarkerTree e         -> MarkerTree $ e & drawAttributes .~ attr   MaskTree e           -> MaskTree $ e & drawAttributes .~ attr   ClipPathTree e       -> ClipPathTree $ e & drawAttributes .~ attr-+  where+    attr = attr'{_preRendered = Nothing}  instance HasDrawAttributes Tree where   drawAttributes = lens drawAttrOfTree setDrawAttrOfTree@@ -2599,6 +2607,7 @@         , _markerMid = (mappend `on` _markerMid) a b         , _markerEnd = (mappend `on` _markerEnd) a b         , _filterRef = (mappend `on` _filterRef) a b+        , _preRendered = Nothing         }       where         opacityMappend Nothing Nothing    = Nothing@@ -2636,6 +2645,7 @@         , _markerMid        = Last Nothing         , _markerEnd        = Last Nothing         , _filterRef        = Last Nothing+        , _preRendered      = Nothing         }  instance WithDefaultSvg DrawAttributes where
src/Graphics/SvgTree/XmlParser.hs view
@@ -99,15 +99,15 @@  instance ParseableAttribute [PathCommand] where   aparse = parse pathParser-  aserialize = Just . serializeCommands+  aserialize v = Just $ serializeCommands v ""  instance ParseableAttribute GradientPathCommand where   aparse = parse gradientCommand-  aserialize = Just . serializeGradientCommand+  aserialize v = Just $ serializeGradientCommand v ""  instance ParseableAttribute [RPoint] where   aparse = parse pointData-  aserialize = Just . serializePoints+  aserialize v = Just $ serializePoints v ""  instance ParseableAttribute Double where   aparse = parseMayStartDot num