4

The tex file with the following code is to be converted into html.

\documentclass{article}
    \usepackage{amsmath,amssymb}
    \begin{document}
    \(\implies\) and \(\iff\) \\
    \(a \implies b\) \(a \iff b\)
    \end{document}

The command

htlatex texfile "xhtml,svg"

is used to convert tex file into html. The symbols \implies and \iff get converted into svg images. The produced svg images are different for these symbols as seen in the attached image. How can this be solved?

enter image description here

5

Edit:

As Martin mentioned in the comments, some glyphs may exceed it's bounding box, which may result in a cropping of theirs parts. It is possible to tell dvisvgm to trace the actual glyph shape using --exact option. I will update tex4ht to use it. In the meantime, you may use a following .mk4 build file:

Make:image("svg$", "dvisvgm -n -p ${page} --exact -c 1.4,1.4 -s ${source} > ${output}")

The result:

enter image description here

Original answer:

It seems that dvisvgm sets wrong dimensions for some images, as it happens for standalone arrows in your example. It seems that height of the first two images is too small, so the image is cropped.

The height of the first image is 3.26027pt, vs 9.6859pt of the third one. It is clear that the height difference isn't as big.

I guess that the best solution would be to fix dvisvgm, but in the meantime, it is possible to use make4ht filters to guess the correct height value. The characters are saved in the SVG file as <path> elements:

<path d='M7.23288 -3.25778C7.65131 -2.89913 8.1594 -2.6401 8.48817 -2.49066C8.12951 -2.33126 7.64134 -2.07223 7.23288 -1.72354H0.9066C0.737235 -1.72354 0.547945 -1.72354 0.547945 -1.52428S0.727273 -1.32503 0.896638 -1.32503H6.78456C6.30635 -0.86675 5.78829 0.00996264 5.78829 0.139477C5.78829 0.249066 5.91781 0.249066 5.97758 0.249066C6.05729 0.249066 6.12702 0.249066 6.16687 0.169365C6.37609 -0.209215 6.65504 -0.737235 7.30262 -1.31507C7.99004 -1.92279 8.65753 -2.19178 9.17559 -2.34122C9.34496 -2.401 9.35492 -2.41096 9.37484 -2.43088C9.39477 -2.44085 9.39477 -2.47073 9.39477 -2.49066S9.39477 -2.53051 9.38481 -2.55044L9.35492 -2.57036C9.33499 -2.58032 9.32503 -2.59029 9.13574 -2.65006C7.79078 -3.04857 6.79452 -3.95517 6.23661 -5.02117C6.12702 -5.22042 6.11706 -5.23039 5.97758 -5.23039C5.91781 -5.23039 5.78829 -5.23039 5.78829 -5.1208C5.78829 -4.99128 6.29639 -4.12453 6.78456 -3.65629H0.896638C0.727273 -3.65629 0.547945 -3.65629 0.547945 -3.45704S0.737235 -3.25778 0.9066 -3.25778H7.23288Z' id='g0-41'/>

Every second number in the path is y coordinate. My naive approach is to process all y coordinates in the svg file, find the maximal value and set the height of the image to this value, if it is bigger than the original value. This approach isn't really robust, because curve sections may be rendered above the maximal coordinate, but I don't know how to solve this issue and I don't want to write proper SVG path parser. So we will hope that this doesn't matter much.

Save the following file as mybuild.mk4:

local filter = require "make4ht-filter"

local max = function(a,b)
  return a > b and a or b
end

local function get_height(svg)
  local height = svg:match("height='([0-9%.]+)pt'")
  return tonumber(height)
end

local function get_max_height(path,max_number)
  local coordinates = {}
  for number in path:gmatch("(%-?[0-9%.]+)") do
    table.insert(coordinates, tonumber(number))
  end
  for i = 2, #coordinates, 2 do
    max_number = max(max_number, coordinates[i])
  end
  return max_number
end

local function update_height(svg, height)
  return svg:gsub("height='.-pt'", "height='"..height .."pt'")
end

-- we need to fix the svg height
local process_svg = filter {function(svg)
  local max_height = 0
  local height = get_height(svg)
  for path in svg:gmatch("path d='([^']+)'") do
    -- find highest height in all paths in the svg file
    max_height = get_max_height(path, max_height)
  end
  -- update the height only if the max_height is larger than height set in the SVG file
  print(max_height, height)
  if max_height > height then
    svg = update_height(svg, max_height)
  end
  return svg
end}

Make:match("svg$", process_svg)

Compile the file using command

make4ht -u -e mybuild.mk4 texfile svg

This is the rendered result:

enter image description here

  • The reason for the incorrect heights is that by default dvisvgm uses the character dimensions from TFM files to compute the bounding box. Since some glyphs may exceed their TFM box, the SVG graphics can be clipped in some cases. To avoid this, call dvisvgm with option --exact. – Martin Nov 10 '17 at 20:42
  • @Martin thanks, I missed that option, it works perfectly! – michal.h21 Nov 10 '17 at 23:01
  • @martin what do you think about bounding box issue with TikZ diagrams from this answer: tex.stackexchange.com/a/386775/2891 ? – michal.h21 Nov 11 '17 at 9:32
  • Would you please create tag for dvisvgm? It would be nice to post question with tag dvisvgm for issues related to dvisvgm... – user61681 Nov 11 '17 at 14:31
  • @michal.h21 as far as I can tell, the dvisvgm driver of TikZ doesn't add the required bbox specials together with the raw SVG fragments in order to update the bounding box accordingly. It might help to use the dvips driver instead, as dvisvgm also understands PostScript specials. I haven't tested that, though. – Martin Nov 11 '17 at 15:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.