require "base64"
module IsoDoc
class PresentationXMLConvert < ::IsoDoc::Convert
SVG = { "m" => "http://www.w3.org/2000/svg" }.freeze
def figure(docxml)
docxml.xpath("//m:svg", SVG).each { |f| svg_wrap(f) }
docxml.xpath(ns("//image")).each { |f| svg_extract(f) }
docxml.xpath(ns("//figure")).each { |f| figure1(f) }
docxml.xpath(ns("//svgmap")).each { |s| svgmap_extract(s) }
imageconvert(docxml)
end
def svg_wrap(elem)
return if elem.parent.name == "image"
elem.wrap("")
end
def svgmap_extract(elem)
if f = elem.at(ns("./figure")) then elem.replace(f)
else elem.remove
end
end
def imageconvert(docxml)
docxml.xpath(ns("//image")).each do |f|
eps2svg(f)
svg_emf_double(f)
end
end
def svg_extract(elem)
return unless %r{^data:image/svg\+xml;}.match?(elem["src"])
return if elem.at("./m:svg", SVG)
svg = Base64.strict_decode64(elem["src"]
.sub(%r{^data:image/svg\+xml;(charset=[^;]+;)?base64,}, ""))
x = Nokogiri::XML.fragment(svg.sub(/<\?xml[^>]*>/, ""), &:huge)
elem["src"] = ""
elem.children = x
end
def figure1(elem)
elem["class"] == "pseudocode" || elem["type"] == "pseudocode" and
return sourcecode1(elem)
figure_label?(elem) or return nil
lbl = @xrefs.anchor(elem["id"], :label, false) or return
# no xref, no label: this can be set in xref
prefix_name(elem, block_delim,
l10n("#{figure_label(elem)} #{lbl}"), "name")
end
def figure_label?(elem)
elem.at(ns("./figure")) && !elem.at(ns("./name")) and return false
true
end
def figure_label(elem)
klass = elem["class"] || "figure"
klasslbl = @i18n.get[klass] || klass
lower2cap klasslbl
end
def eps2svg(img)
return unless eps?(img["mimetype"])
img["mimetype"] = "image/svg+xml"
if src = eps_to_svg(img)
img["src"] = src
img.children = ""
end
end
def svg_emf_double(img)
if emf?(img["mimetype"])
img = emf_encode(img)
img.children.first.previous = emf_to_svg(img)
elsif img["mimetype"] == "image/svg+xml"
src = svg_to_emf(img) or return
img.add_child("")
img.elements.last["src"] = src
end
end
def emf_encode(img)
svg_prep(img)
img.children = ""
img["src"] = ""
img
end
def svg_prep(img)
img["mimetype"] = "image/svg+xml"
%r{^data:}.match?(img["src"]) or
img["src"] = Vectory::Emf.from_path(img["src"]).to_uri.content
end
def emf_to_svg(img)
datauri_src = img.at(ns("./emf/@src")).text
Vectory::Emf.from_datauri(datauri_src)
.to_svg
.content
.sub(/<\?[^>]+>/, "")
end
def eps_to_svg(node)
if !node.text.strip.empty? || %r{^data:}.match?(node["src"])
return eps_to_svg_from_node(node)
end
target_path = imgfile_suffix(node["src"], "svg")
return target_path if File.exist?(target_path)
eps_to_svg_from_node(node, target_path)
end
def eps_to_svg_from_node(node, target_path = nil)
svg = Vectory::Eps.from_node(node).to_svg
return svg.write(target_path).path if target_path
svg.write.path
end
def svg_to_emf(node)
@output_formats[:doc] or return
svg_impose_height_attr(node)
if node.elements&.first&.name == "svg" || %r{^data:}.match?(node["src"])
return svg_to_emf_from_node(node)
end
target_path = imgfile_suffix(node["src"], "emf")
return target_path if File.exist?(target_path)
svg_to_emf_from_node(node, target_path)
end
def svg_to_emf_from_node(node, target_path = nil)
emf = Vectory::Svg.from_node(node).to_emf
return emf.write(target_path).to_uri.content if target_path
emf.to_uri.content
end
def svg_impose_height_attr(node)
e = node.elements&.first or return
(e.name == "svg" &&
(!node["height"] || node["height"] == "auto")) or return
node["height"] = e["height"]
node["width"] = e["width"]
end
def imgfile_suffix(uri, suffix)
"#{File.join(File.dirname(uri), File.basename(uri, '.*'))}.#{suffix}"
end
end
end