mirror of
https://github.com/reanimate/reanimate.git
synced 2026-09-15 10:02:45 +00:00
Process svgs to remove needless view boxes.
This commit is contained in:
parent
72e86dd2ac
commit
816c1d8d7e
3 changed files with 78 additions and 6 deletions
|
|
@ -21,10 +21,11 @@ library
|
||||||
Reanimate.Examples
|
Reanimate.Examples
|
||||||
Reanimate.Combinators
|
Reanimate.Combinators
|
||||||
Reanimate.LaTeX
|
Reanimate.LaTeX
|
||||||
|
Reanimate.Svg
|
||||||
other-modules: Reanimate.Misc
|
other-modules: Reanimate.Misc
|
||||||
build-depends: base >=4.12 && <4.13,
|
build-depends: base >=4.12 && <4.13,
|
||||||
lucid-svg, time, text, unix, lucid, filepath, process, directory,
|
lucid-svg, time, text, unix, lucid, filepath, process, directory,
|
||||||
containers, svg-tree, xml, bytestring
|
containers, svg-tree, xml, bytestring, lens
|
||||||
|
|
||||||
executable reanimate-viewer
|
executable reanimate-viewer
|
||||||
main-is: SvgViewer.hs
|
main-is: SvgViewer.hs
|
||||||
|
|
@ -34,10 +35,11 @@ executable reanimate-viewer
|
||||||
Reanimate.Examples
|
Reanimate.Examples
|
||||||
Reanimate.Combinators
|
Reanimate.Combinators
|
||||||
Reanimate.LaTeX
|
Reanimate.LaTeX
|
||||||
|
Reanimate.Svg
|
||||||
Reanimate.Misc
|
Reanimate.Misc
|
||||||
build-depends: base >=4.12 && <4.13, cairo >=0.13 && <0.14, gtk,
|
build-depends: base >=4.12 && <4.13, cairo >=0.13 && <0.14, gtk,
|
||||||
svgcairo, lucid-svg, time, text, unix, lucid, reanimate,
|
svgcairo, lucid-svg, time, text, unix, lucid, reanimate,
|
||||||
filepath, process, directory, containers, svg-tree, xml,
|
filepath, process, directory, containers, svg-tree, xml,
|
||||||
bytestring
|
bytestring, lens
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,25 @@ import qualified Data.Map as Map
|
||||||
import Lucid (ToHtml (..))
|
import Lucid (ToHtml (..))
|
||||||
import Lucid.Svg (Svg, fill_, font_size_, text_)
|
import Lucid.Svg (Svg, fill_, font_size_, text_)
|
||||||
import Reanimate.Misc
|
import Reanimate.Misc
|
||||||
|
import Reanimate.Svg
|
||||||
import System.FilePath (replaceExtension, takeFileName, (</>))
|
import System.FilePath (replaceExtension, takeFileName, (</>))
|
||||||
import System.IO.Unsafe (unsafePerformIO)
|
import System.IO.Unsafe (unsafePerformIO)
|
||||||
|
|
||||||
import Graphics.Svg (loadSvgFile, parseSvgFile,
|
import Graphics.Svg (loadSvgFile, parseSvgFile,
|
||||||
xmlOfDocument)
|
xmlOfDocument, Tree, elements, defaultSvg, Document)
|
||||||
import Text.XML.Light.Output (ppcElement, prettyConfigPP)
|
import Text.XML.Light.Output (ppcElement, ppcContent, prettyConfigPP)
|
||||||
|
import Text.XML.Light (elContent)
|
||||||
|
import Control.Lens (over, (^.),set, (.~), (&), (%~) )
|
||||||
|
|
||||||
|
-- instance ToHtml Document where
|
||||||
|
-- toHtml = toHtmlRaw
|
||||||
|
-- toHtmlRaw = toHtmlRaw . ppcElement prettyConfigPP . xmlOfDocument
|
||||||
|
|
||||||
|
instance ToHtml Document where
|
||||||
|
toHtml = toHtmlRaw
|
||||||
|
toHtmlRaw doc = toHtmlRaw $ unlines $ map (ppcContent prettyConfigPP) (elContent elt)
|
||||||
|
where
|
||||||
|
elt = xmlOfDocument doc
|
||||||
|
|
||||||
{-# NOINLINE cache #-}
|
{-# NOINLINE cache #-}
|
||||||
cache :: IORef (Map String (Svg ()))
|
cache :: IORef (Map String (Svg ()))
|
||||||
|
|
@ -43,13 +56,13 @@ latexToSVG tex = handle (\(e::SomeException) -> return (failedSvg tex)) $ do
|
||||||
runCmd latex ["-interaction=batchmode", "-halt-on-error", "-output-directory="++tmp_dir, tex_file]
|
runCmd latex ["-interaction=batchmode", "-halt-on-error", "-output-directory="++tmp_dir, tex_file]
|
||||||
runCmd dvisvgm [ dvi_file
|
runCmd dvisvgm [ dvi_file
|
||||||
, "--exact" -- better bboxes.
|
, "--exact" -- better bboxes.
|
||||||
, "--bbox=1,1" -- increase bbox size.
|
-- , "--bbox=1,1" -- increase bbox size.
|
||||||
, "--no-fonts" -- use glyphs instead of fonts.
|
, "--no-fonts" -- use glyphs instead of fonts.
|
||||||
,"--verbosity=0", "-o",svg_file]
|
,"--verbosity=0", "-o",svg_file]
|
||||||
svg_data <- B.readFile svg_file
|
svg_data <- B.readFile svg_file
|
||||||
case parseSvgFile svg_file svg_data of
|
case parseSvgFile svg_file svg_data of
|
||||||
Nothing -> error "Malformed svg"
|
Nothing -> error "Malformed svg"
|
||||||
Just svg -> return $ toHtmlRaw $ ppcElement prettyConfigPP (xmlOfDocument svg)
|
Just svg -> return $ toHtmlRaw $ unbox $ replaceUses svg
|
||||||
|
|
||||||
failedSvg :: String -> Svg ()
|
failedSvg :: String -> Svg ()
|
||||||
failedSvg tex =
|
failedSvg tex =
|
||||||
|
|
|
||||||
57
src/Reanimate/Svg.hs
Normal file
57
src/Reanimate/Svg.hs
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
module Reanimate.Svg where
|
||||||
|
|
||||||
|
import Data.Maybe
|
||||||
|
import qualified Data.Map as Map
|
||||||
|
import Control.Lens (over, (^.),set, (.~), (&), (%~) )
|
||||||
|
import Graphics.Svg
|
||||||
|
|
||||||
|
replaceUses :: Document -> Document
|
||||||
|
replaceUses doc = doc & elements %~ map (mapTree replace)
|
||||||
|
& definitions .~ Map.empty
|
||||||
|
where
|
||||||
|
replace (UseTree _ Just{}) = error "replaceUses: subtree in use?"
|
||||||
|
replace (UseTree use Nothing) =
|
||||||
|
case Map.lookup (use^.useName) idMap of
|
||||||
|
Nothing -> error $ "Unknown id: " ++ (use^.useName)
|
||||||
|
Just tree ->
|
||||||
|
GroupTree $
|
||||||
|
defaultSvg & groupChildren .~ [tree]
|
||||||
|
& drawAttr .~ (defaultSvg & transform .~ Just [baseToTransformation (use^.useBase)])
|
||||||
|
replace x = x
|
||||||
|
baseToTransformation (x,y) =
|
||||||
|
case (toUserUnit defaultDPI x, toUserUnit defaultDPI y) of
|
||||||
|
(Num a, Num b) -> Translate a b
|
||||||
|
_ -> TransformUnknown
|
||||||
|
defaultDPI = 96
|
||||||
|
docTree = GroupTree $ set groupChildren (doc^.elements) defaultSvg
|
||||||
|
idMap = foldTree updMap Map.empty docTree `Map.union`
|
||||||
|
Map.mapMaybe elementToTree (doc^.definitions)
|
||||||
|
updMap m tree =
|
||||||
|
case tree^.drawAttr.attrId of
|
||||||
|
Nothing -> m
|
||||||
|
Just tid -> Map.insert tid tree m
|
||||||
|
elementToTree (ElementGeometry t) = Just t
|
||||||
|
elementToTree _ = Nothing
|
||||||
|
|
||||||
|
docIds :: Document -> [String]
|
||||||
|
docIds doc = Map.keys idMap ++ Map.keys (doc^.definitions)
|
||||||
|
where
|
||||||
|
docTree = GroupTree $ set groupChildren (doc^.elements) defaultSvg
|
||||||
|
idMap = foldTree updMap Map.empty docTree
|
||||||
|
updMap m tree =
|
||||||
|
case tree^.drawAttr.attrId of
|
||||||
|
Nothing -> m
|
||||||
|
Just tid -> Map.insert tid tree m
|
||||||
|
|
||||||
|
|
||||||
|
-- Transform out viewbox. defs and CSS rules are discarded.
|
||||||
|
unbox :: Document -> Document
|
||||||
|
unbox doc@Document{_viewBox = Just (minx, minw, _width, _height)} =
|
||||||
|
doc & viewBox .~ Nothing
|
||||||
|
& width .~ Nothing
|
||||||
|
& height .~ Nothing
|
||||||
|
& elements .~
|
||||||
|
[ GroupTree $ defaultSvg
|
||||||
|
& groupChildren .~ doc^.elements
|
||||||
|
& drawAttr .~ (defaultSvg & transform .~ Just [Translate (-minx) (-minw)]) ]
|
||||||
|
unbox doc = doc
|
||||||
Loading…
Reference in a new issue