# Work around for bug in pgf when used with htlatex?

There is a bug in pgf that stops it playing nicely with tikz/pgf. As discovered by michal.h21, the solution is a simple a one line change to pgfsys-tex4ht.def. This bug was reported to the pgf team in 2014, together with a patch, but it remains unfixed as of TeXLive 2017.

Question Is there a way that I can patch the pgf file pgfsys-tex4ht.def from within LaTeX?

It is possible to fix the problem by editing/replacing the system version of pgfsys-tex4ht.def. What I would like, however, is a way of patching this from inside LaTeX because I want to be able to work around this problem in a package. (In an ideal world, the pgf team would just apply Michael's patch, and so fix the problem once and for all, but they just don't seem to be interested in doing this...)

The actual error that occurs is:

! Undefined control sequence.
\pgfsys@svg@newline ->\Hnewline

l.190   \pgfusepathqfill}


and the fix is to replace the line \def\pgfsys@svg@newline{\Hnewline} in pgfsys-tex4ht.def with

\def\pgfsys@svg@newline{^^J} %% corrected


I have tried patching this line in many ways, in latex files, my class file, in cfg files and mk4 files. Sadly, nothing that I have tried fixes the problem. For reasons I don't understand, once the pgfsys-tex4ht.def file has been read it is really hard to convince htlatex to use any other definition of \pgfsys@svg@newline or \Hnewline.

To see the bug in action, compile the following really simple MWE with htlatex:

\documentclass{article}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\draw(0,0)--(10,0);
\end{tikzpicture}

\end{document}


The problem only occurs with htlatex and friends -- the MWE compiles without issue using (pdf)latex.

This situation is quite unfortunate. The pgfsys-tex4ht.def driver is selected automatically by TikZ when the document is compiled with tex4ht. You can create alternative driver, like pgfsys-tex4ht-alt.def:

\input pgfsys-tex4ht.def
\def\pgfsys@svg@newline{^^J}


but the problem is that the alternative driver cannot be defined in the .cfg file, because it is interpreted after the document preamble was executed. You must put it either to the TeX file:

\documentclass{article}
\def\pgfsysdriver{pgfsys-tex4ht-alt.def}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\draw(0,0)--(10,0);
\end{tikzpicture}

\end{document}


Or use one trick in the .mk4 file:

settings.packages = settings.packages ..'\\def\\pgfsysdriver{pgfsys-tex4ht-alt.def}'


You can load additional packages or define custom commands in the settings.packages variables in the mk4 build file.

Edit 2017/11/11:

Another possibility is to use dvisvgm to generate the SVG file. We can use the built-in feature of tex4ht to convert any piece of TeX code inside a \Picture* ... \EndPicture environment to picture and the fact that TikZ has support for dvips commands, which are supported by dvisvgm.

The alternative pgfsys-tex4ht.def:

% Copyright 2006 by Till Tantau
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%

\ProvidesFileRCS $Header: /cvsroot/pgf/pgf/generic/pgf/systemlayer/pgfsys-tex4ht.def,v 1.25 2013/08/06 17:46:08 tantau Exp$

% Driver commands for tex4ht

%
%
%\input pgfsys-dvisvgm.def
\input pgfsys-dvips.def

%
% tex4ht-specific stuff:
%

\newcount\pgf@sys@svg@picnum

% configure the output picture format to svg
\AtBeginDocument{
\Configure{Picture}{.svg}
}

% Make the code inserted by tex4ht configurable

\NewConfigure{tikzpicture}{2}
\Configure{tikzpicture}{%
% \ifvmode\IgnorePar\fi\EndP%\HtmlParOff
\Picture*{}
}{\EndPicture}

\let\orig@pgfsys@begin\pgfsys@beginpicture
\let\orig@pgfsys@end\pgfsys@endpicture
\def\pgfsys@beginpicture{%
\bgroup
\csname a:tikzpicture\endcsname
/pgfsc{}bind def% stroke color is empty by default
/pgffc{}bind def% fill color is empty by default
/pgfstr{stroke}bind def%
/pgffill{fill}bind def%
/pgfeofill{eofill}bind def%
/pgfe{a dup 0 rlineto exch 0 exch rlineto neg 0 rlineto closepath}bind def% rectangle
/pgfw{setlinewidth}bind def% setlinewidth
/pgfs{save pgfpd 72 Resolution div 72 VResolution div neg scale
magscale{1 DVImag div dup scale}if
pgfx neg pgfy neg translate pgffoa .setopacityalpha}bind def% save
/pgfr{pgfsd restore}bind def %restore
userdict begin%
/pgfo{pgfsd /pgfx currentpoint /pgfy exch def def @beginspecial}bind def %open
/pgfc{newpath @endspecial pgfpd}bind def %close
/pgfsd{globaldict /pgfdelta /delta where {pop delta} {0} ifelse put}bind def% save delta
/pgfpd{/delta globaldict /pgfdelta get def}bind def % put delta
/.setopacityalpha where {pop} {/.setopacityalpha{pop}def} ifelse % install .setopacityalpha
/.pgfsetfillopacityalpha{/pgffoa exch def
/pgffill{gsave pgffoa .setopacityalpha fill 1 .setopacityalpha newpath fill grestore newpath}bind def
/pgfeofill{gsave pgffoa .setopacityalpha eofill 1 .setopacityalpha newpath eofill grestore newpath}bind def}bind def
/.pgfsetstrokeopacityalpha{/pgfsoa exch def /pgfstr{gsave pgfsoa .setopacityalpha stroke grestore newpath}bind def}bind def
/pgffoa 1 def
/pgfsoa 1 def
end
}%
\orig@pgfsys@begin%
}%

\def\pgfsys@endpicture{%
% Save the bounding box
%\printdim%
\orig@pgfsys@end%
\csname b:tikzpicture\endcsname%
\egroup
\par% FIXME : was '\Par' but that seems to be undefined!?
}%

\endinput

%%% Local Variables:
%%% mode: latex
%%% End:

• @Andrew I hope that someone can fix the bounding box issue. I wasn't able to correctly resolve that :( – michal.h21 Aug 17 '17 at 12:27
• Thanks MIchal. I have realised that this completely solves my problem: I have added a tikz option to my class file and then I include your pgfsys-tex4ht-alt.def. Perfect! – Andrew Aug 20 '17 at 23:24