5

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

2
  • There is any examples at this link: tex.stackexchange.com/questions/43772/… Commented Nov 10, 2017 at 12:15
  • It should be sufficient to add option --exact to the call of dvisvgm in your tex4ht.env. Commented Nov 10, 2017 at 21:13

1 Answer 1

6

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

11
  • 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. Commented Nov 10, 2017 at 20:42
  • @Martin thanks, I missed that option, it works perfectly! Commented Nov 10, 2017 at 23:01
  • @martin what do you think about bounding box issue with TikZ diagrams from this answer: tex.stackexchange.com/a/386775/2891 ? Commented Nov 11, 2017 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... Commented Nov 11, 2017 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. Commented Nov 11, 2017 at 15:32

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.