[tex-k] dvips/rounding problem

Heiko Oberdiek oberdiek@ruf.uni-freiburg.de
Sun, 3 Jun 2001 21:21:06 +0200 (MET DST)


Hello,

the following test file illustrates a problem with dvips:

\documentclass{article}
\pagestyle{empty}
\tabcolsep1.4pt
\begin{document}
\begin{tabular}{|l|}
111\\
000\\
0000\\
\end{tabular}
\end{document}

The right vertical line in the third row is shifted
to the right, so that the right vertical line of the
tabular is not aligned correctly.

I have started a thread in comp.text.tex and people
points me to the options -e, so that I have now
analysed and fixed the problem:

The dvips documentation says about option -e:
> -e num:
> Make sure that each character is placed at most this many
> pixels from its `True' resolution-independent
> position on the page. The default value of this parameter
> is resolution dependent (it is the number of entries in the
> list [100, 200, 300, 400, 500, 600, 800, 1000, 1200, 1600,
> 2000, 2400, 2800, 3200, $\ldots\,$] that are less than or
> equal to the maxdrift resolution in dots per inch).
> Allowing individual characters to `Drift' from their
> correctly rounded positions by a few pixels, while
> regaining the true position at the beginning of each
> new word, improves the spacing of letters in words.

dopage.c says:
/*
 *   The calculations here are crucial to the appearance of the
 *   document. If the motion is small, we round the amount of
 *   relative motion; otherwise, we update the position and
 *   round the new position. Then we check to insure that the
 *   rounded position didn't accumulate an error that was
 *   greater than maxdrift.
 */
/*
 *   Horizontal motion is analogous. We know the exact width
 *   of each character in pixels. Kerning is distinguished
 *   from space between words if it's less than a thinspace
 *   and not more negative than would occur when an accent
 *   is being positioned by backspacing.
 */

The space between the entry '0000' in the last row
is less than thinspace because of the low value of
\tabcolsep. Therefore dvips thinks that there will
be follow another chars for the "word" '0000' and
the following rule is allowed to shift, limited by
the maxdrift value.

This logic can be broken, if '0000' is set in
a box:

\begin{tabular}{|l|}
\mbox{111}\\
\mbox{000}\\
\mbox{0000}\\
\end{tabular}

or by adding space larger than thinspace:

\newcommand{\fix}{\kern10em\special{}\kern-10em}
% \special{} avoids that \kern is optimized away
\begin{tabular}{|l|}
111\fix\\
000\fix\\
0000\fix\\
\end{tabular}

But the problem can also be fixed at the dvips source level:
In the following patch I added a horizontal synchronisation
before the rule, so that the rules start with the correct
rounded position on the page. The effect is a zero maxdrift
value for rules.

%%% cut %%% dopage.diff %%% cut %%%
*** dopage.c.org        Mon May 29 11:52:16 2000
--- dopage.c    Sun Jun  3 04:17:08 2001
***************
*** 226,231 ****
--- 226,232 ----
     error("! synch") ;
  case 132: case 137: /* rules */
   { integer ry, rx , rxx, ryy ;
+    hh = PixRound(h) ; /* HO 2001/06/03: synchronisation added */
     ry = signedquad() ; rx = signedquad() ;
     if (rx>0 && ry>0) {
        if (curpos) {
%%% cut %%% dopage.diff %%% cut %%%

Yours sincerely
  Heiko <oberdiek@uni-freiburg.de>