Here is a proof of concept using LuaXML for SVG parsing and Flowfram for flow frames.
I've created a package svgflowfram.sty
:
\ProvidesPackage{svgflowfram}
\RequirePackage{flowfram}
\RequirePackage{xparse}
\RequirePackage{luacode}
\begin{luacode*}
local load_frames = require "svgframes"
function print_frame(x,y, width, height)
tex.print(string.format("\\newflowframe{%isp}{%isp}{%isp}{%isp}", width, height, x, y))
end
\end{luacode*}
\NewDocumentCommand\svgframes{o m o}{%
\IfNoValueTF{#1}{\def\svgflowfram@pages{}}{\def\svgflowfram@pages{#1}}
\IfNoValueTF{#3}{\def\svgflowfram@name{}}{\def\svgflowfram@name{#3}}
\directlua{
local frames = load_frames("\luatexluaescapestring{#2}")
for _, frame in ipairs(frames) do
print_frame(frame.x, frame.y, frame.width, frame.height)
end
}
}
\endinput
It provides a command \svgframes
. It can consume three parameters, one is mandatory, others optional. The optional arguments should add support for the page specification used by Flowframe and optional name for the frames. These features are not implemented yet, so you can just use the mandatory argument, which is the SVG file name.
The SVG frame parsing is implemented in the svgframes.lua
library:
local domobj = require "luaxml-domobject"
-- just assume we use milimeters at the moment
local function get_dimen(el, dimen_attr)
return tex.sp(el:get_attribute(dimen_attr) .. "mm")
end
function load_frames(svgfile, name)
local f=io.open(svgfile, "r")
if not f then return nil, "Cannot open file " .. svgfile end
local content = f:read("*all")
f:close()
local dom = domobj.parse(content)
local frames = {}
for _, r in ipairs(dom:query_selector("rect")) do
local x, y, width, height = get_dimen(r, "x"), get_dimen(r, "y"), get_dimen(r, "width"), get_dimen(r, "height")
y = tex.pageheight - (y + height)
frames[#frames+1] = {x=x, y=y, width=width, height=height}
end
return frames
end
return load_frames
It provides function load_frames
which loads the SVG file using LuaXML DOM funnctions, loops over all <rect>
elements. The dimensions are converted to millimeters and then to sp
. The y
dimension needs to be calculated relative to the page height.
It can be used in this way:
\documentclass{article}
\usepackage{svgflowfram}
\usepackage{lipsum}
\usepackage[margin=0pt]{geometry}
\svgframes{frames.svg}
\begin{document}
\lipsum[1-10]
\end{document}
Sample SVG file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg8"
inkscape:version="0.92.4 (unknown)"
sodipodi:docname="frames.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.41"
inkscape:cx="-316.1324"
inkscape:cy="554.28571"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Vrstva 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#ffffff;stroke:#000000;stroke-width:0.27966458;stroke-miterlimit:0.30000001;stroke-dasharray:none;stroke-dashoffset:0"
id="rect815"
width="58.724594"
height="40.655487"
x="17.42378"
y="33.061993" />
<rect
style="fill:#ffffff;stroke:#000000;stroke-width:0.27966458;stroke-miterlimit:0.30000001;stroke-dasharray:none;stroke-dashoffset:0"
id="rect817"
width="82.601608"
height="36.783535"
x="90.990852"
y="91.141266" />
<rect
style="fill:#ffffff;stroke:#000000;stroke-width:0.27966458;stroke-miterlimit:0.30000001;stroke-dasharray:none;stroke-dashoffset:0;image-rendering:auto"
id="rect819"
width="80.020325"
height="41.94614"
x="20.005081"
y="143.4126">
<title
id="title842">logo</title>
</rect>
<rect
style="fill:#ffffff;stroke:#000000;stroke-width:0.27966458;stroke-miterlimit:0.30000001;stroke-dasharray:none;stroke-dashoffset:0"
id="rect821"
width="108.41463"
height="43.236786"
x="70.985771"
y="203.42784" />
</g>
</svg>
Rendered in Inkscape
And the PDF:

One issue is that widths for paragraphs that are split over two frames are wrong. I am not sure how to fix that.
SVG
using LuaXML, it should be quite easy to process all rectangles using the DOM functions. – michal.h21 Dec 3 '19 at 11:48