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 +5/−0
- reanimate-svg.cabal +3/−1
- src/Graphics/SvgTree/Memo.hs +83/−0
- src/Graphics/SvgTree/PathParser.hs +58/−45
- src/Graphics/SvgTree/Printer.hs +50/−0
- src/Graphics/SvgTree/Types.hs +13/−3
- src/Graphics/SvgTree/XmlParser.hs +3/−3
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