> > It might be a linux shell piping issue, since your are second large > number of file using > destination file I noticed. > > I made sure the input latex file I gave it try_1.tex is not too > large, so not to run into the dvisvgm overflow problem. This file > has only 1,000 pages and may be 5,000 equations.
I've made a new version of dvisvgm-hashes.lua. It compresses consecutive page ranges, so it shouldn't crate such long page lists. Moreover, if GNU Make is available on the system, it makes a Makefile, which calls dvisvgm only on subset of pages (64 by default) and it calls it in parallel (thanks to Reinhard for this idea). It should speed up the compilation in theory, although I am not sure from my tests that it really works in practise. > > When I tried it on a really small file, it worked. _BUT_ and > this is a big _BUT_, some of the math generated looks really > bad but some look like normal SVG. Here is screen shot > > https://www.12000.org/tmp/08182018/image.png > > Looking at the HTML, it seems some math was not really > converted to SVG at all, while other was. I can see it. I am not sure what is the issue, maybe Martin know? The call to dvisvgm is in the form: dvisvgm -v 4 -n --exact -c 1.15,1.15 -p 1-5 filename.idv 2> filename.dlog > > -------------------------------- > <td > class="align-label"> > </td></tr><tr><td > class="align-odd"><span > class="cmex-10x-x-109">∫</span> > <span > class="cmr-10x-x-109">d</span><span > class="cmmi-10x-x-109">y</span></td> > -------------------------- > > What is the above doing in the HTML? Should it not be an image? > You are missing the `pic-align` option I think. Best regards, Michal
local dvireader = require "dvireader" local mkutils = require "mkutils" local filter = require "make4ht-filter" -- mapping between tex4ht image names and hashed image names local output_map = {} local dvisvgm_options = "-n --exact -c 1.15,1.15" local parallel_size = 64 -- local parallel_size = 3 local function make_hashed_name(base, hash) return base .. "-" ..hash..".svg" end -- process output of dvisvgm and find output page numbers and corresponding files local function get_generated_pages(output, pages) local pages = pages or {} local pos = 1 local pos, finish, page = string.find(output, "processing page (%d+)", pos) while(pos) do pos, finish, file = string.find(output, "output written to ([^\n]+)", finish) pages[tonumber(page)] = file pos, finish, page = string.find(output, "processing page (%d+)", finish) end return pages end local function make_ranges(pages) local newpages = {} local start, stop for i=1,#pages do local current = pages[i] local next_el = pages[i+1] or current + 100 -- just select a big number local diff = next_el - current if diff == 1 then if not start then start = current end else local element if start then element = start .. "-" .. current else element = current end newpages[#newpages+1] = element start = nil end end return newpages end local function read_log(dvisvgmlog) local f = io.open(dvisvgmlog, "r") if not f then return nil, "Cannot read dvisvgm log" end local output = f:read("*all") f:close() return output end -- test the existence of GNU Make, which can execute tasks in parallel local function test_make() local make = io.popen("make -v", "r") if not make then return false end local content = make:read("*all") make:close() return content:match("GNU Make") end local function save_file(filename, text) local f = io.open(filename, "w") f:write(text) f:close() end local function make_makefile_command(idvfile, page_sequences) local logs = {} local all = {} -- list of targets in the "all:" makefile target local targets = {} local basename = idvfile:gsub(".idv$", "") local makefilename = basename .. "-images" .. ".mk" -- build make targets for i, ranges in ipairs(page_sequences) do local target = basename .. "-" .. i local logfile = target .. ".dlog" logs[#logs + 1] = logfile all[#all+1] = target local chunk = target .. ":\n\tdvisvgm -v4" .. dvisvgm_options .. " -p " .. ranges .. " " .. idvfile .. " 2> " .. logfile .. "\n" targets[#targets + 1] = chunk end -- construct makefile and save it local makefile = "all: " .. table.concat(all, " ") .. "\n\n" .. table.concat(targets, "\n") save_file(makefilename, makefile) local command = "make -j -f " .. makefilename return command, logs end local function prepare_command(idvfile, pages) local logs = {} if #pages > parallel_size and test_make() then local page_sequences = {} for i=1, #pages, parallel_size do local current_pages = {} for x = i, i+parallel_size -1 do current_pages[#current_pages + 1] = pages[x] end table.insert(page_sequences,table.concat(make_ranges(current_pages), ",")) end return make_makefile_command(idvfile, page_sequences) end -- else local pagesequence = table.concat(make_ranges(pages), ",") -- the stderr from dvisvgm must be redirected and postprocessed local dvisvgmlog = idvfile:gsub("idv$", "dlog") -- local dvisvgm = io.popen("dvisvgm -v4 -n --exact -c 1.15,1.15 -p " .. pagesequence .. " " .. idvfile, "r") local command = "dvisvgm -v4 " .. dvisvgm_options .. " -p " .. pagesequence .. " " .. idvfile .. " 2> " .. dvisvgmlog return command, {dvisvgmlog} -- end end local function execute_dvisvgm(idvfile, pages) if #pages < 1 then return nil, "No pages to convert" end local command, logs = prepare_command(idvfile, pages) print(command) os.execute(command) local generated_pages = {} for _, dvisvgmlog in ipairs(logs) do local output = read_log(dvisvgmlog) generated_pages = get_generated_pages(output, generated_pages) end return generated_pages end local function get_dvi_pages(arg) -- list of pages to convert in this run local to_convert = {} local idv_file = arg.input .. ".idv" -- set extension options local extoptions = mkutils.get_filter_settings "dvisvgm-hashes" or {} dvisvgm_options = arg.options or extoptions.options or dvisvgm_options parallel_size = arg.parallel_size or extoptions.parallel_size or parallel_size local f = io.open(idv_file, "r") if not f then return nil, "Cannot open idv file: " .. idv_file end local content = f:read("*all") f:close() local dvi_pages = dvireader.get_pages(content) -- we must find page numbers and output name sfor the generated images local lg = mkutils.parse_lg(arg.input ..".lg") for _, name in ipairs(lg.images) do local page = tonumber(name.page) local hash = dvi_pages[page] local tex4ht_name = name.output local output_name = make_hashed_name(arg.input, hash) output_map[tex4ht_name] = output_name if not mkutils.file_exists(output_name) then print(output_name) to_convert[#to_convert+1] = page end end local generated_files, msg = execute_dvisvgm(idv_file, to_convert) if not generated_files then return nil, msg end -- rename the generated files to the hashed filenames for page, file in pairs(generated_files) do os.rename(file, make_hashed_name(arg.input, dvi_pages[page])) end end -- this must be used in the .mk4 file as -- Make:dvisvgm_hashes {} Make:add("dvisvgm_hashes", function(arg) get_dvi_pages(arg) end, { parallel_size=parallel_size -- number of pages which should be concetanated before }) -- replace original image names with hashed names local executed = false Make:match(".*", function(arg) if not executed then executed = true local lgfiles = Make.lgfile.files for i, filename in ipairs(lgfiles) do local replace = output_map[filename] if replace then lgfiles[i] = replace end end end end) -- fix src attributes local process = filter { function(str) return str:gsub('src="([^"]+)', function(filename) local newname = output_map[filename] or filename print("newname", newname) return 'src="'.. newname end) end } Make:match("html$", process) -- disable the image processing Make:image(".", function() return "" end)