Joseph Wright
2018-03-04 15:25:55 UTC
Hello all,
I've run into an oddity with dvips: this might well be 'user error' but
I'd appreciate any insight.
What I'm trying to do is set up box transformations inside a 'drawing'
environment. The aim is to avoid using a completely raw special (ps::
<matrix> concat) as that is opaque to the driver and means it looses
hyperlinks and the like. I can get it all working *provided* I don't
have any translation applied.
In the following example, you only get the result I was expecting if you
set \shiftmatrixtrue and \rotateandscalefalse, i.e. do everything in one
matrix operation. If you split the shift of the box out then an 'extra'
displacement pops up. It seems that the transformation (either
rotation/scaling or matrix-based) is applied to the kern which is
*before* the operations. You see the same effect if you add a y-shift
(moving the box up/down), and with a pure scaling (so no rotation at all).
The same general approach works as-expected with (x)dvipdfmx, where
again we have scaling/rotation but no driver-tracked transformation (cf.
pdfTeX), so I don't think I have the kern in the obviously-wrong place.
I suspect I'm missing a save/restore or similar: any ideas?
Joseph
\newif\ifshiftmatrix
\shiftmatrixtrue
\newif\ifrotateandscale
\rotateandscalefalse
\setbox0=\hbox{%
\special{ps::[begin]}% Line up with TeX current point
\special{ps::/ox currentpoint /oy exch def def}% Save the origin
\special{ps::@beginspecial}% Get scale and axis 'into line'
\special{ps::0 0 moveto}% (0cm,0cm)
\special{ps::85.04045 0 lineto}% (3cm,0cm)
\special{ps::28.3468 0 moveto}% (1cm,0cm}
\special{ps::28.3468 56.69363 lineto}% (1cm,2cm)
\special{ps::stroke}%
\special{ps::newpath}%
\hbox to 0pt{%
\ifshiftmatrix\else\kern 1cm \fi
\special{ps::save}%
\ifrotateandscale
% Singular value decomposition of [1 2 1 1]
\special{ps::58.28253 rotate}%
\special{ps::2.61803 -0.38197 scale}%
\special{ps::-31.71747 rotate}%
\else
\ifshiftmatrix
\special{ps::[1 2 1 1 28.3468 0] concat}%
\else
\special{ps::[1 2 1 1 0 0] concat}%
\fi
\fi
% The next three lines get us 'back' to the TeX origin
\special{ps::72 Resolution div 72 VResolution div neg scale}%
\special{ps::magscale {1 DVImag div dup scale} if}%
\special{ps::ox neg oy neg translate}%
\special{ps::[end]}%
\hbox to 0pt{Hello\hss}%
\special{ps::[begin]}%
\special{ps::restore}%
\hss
}%
\special{ps::@endspecial}% Tidy up
\special{ps::[end]}%
}%
\wd0=3cm %
\ht0=2cm %
\box0 %
world
\bye
I've run into an oddity with dvips: this might well be 'user error' but
I'd appreciate any insight.
What I'm trying to do is set up box transformations inside a 'drawing'
environment. The aim is to avoid using a completely raw special (ps::
<matrix> concat) as that is opaque to the driver and means it looses
hyperlinks and the like. I can get it all working *provided* I don't
have any translation applied.
In the following example, you only get the result I was expecting if you
set \shiftmatrixtrue and \rotateandscalefalse, i.e. do everything in one
matrix operation. If you split the shift of the box out then an 'extra'
displacement pops up. It seems that the transformation (either
rotation/scaling or matrix-based) is applied to the kern which is
*before* the operations. You see the same effect if you add a y-shift
(moving the box up/down), and with a pure scaling (so no rotation at all).
The same general approach works as-expected with (x)dvipdfmx, where
again we have scaling/rotation but no driver-tracked transformation (cf.
pdfTeX), so I don't think I have the kern in the obviously-wrong place.
I suspect I'm missing a save/restore or similar: any ideas?
Joseph
\newif\ifshiftmatrix
\shiftmatrixtrue
\newif\ifrotateandscale
\rotateandscalefalse
\setbox0=\hbox{%
\special{ps::[begin]}% Line up with TeX current point
\special{ps::/ox currentpoint /oy exch def def}% Save the origin
\special{ps::@beginspecial}% Get scale and axis 'into line'
\special{ps::0 0 moveto}% (0cm,0cm)
\special{ps::85.04045 0 lineto}% (3cm,0cm)
\special{ps::28.3468 0 moveto}% (1cm,0cm}
\special{ps::28.3468 56.69363 lineto}% (1cm,2cm)
\special{ps::stroke}%
\special{ps::newpath}%
\hbox to 0pt{%
\ifshiftmatrix\else\kern 1cm \fi
\special{ps::save}%
\ifrotateandscale
% Singular value decomposition of [1 2 1 1]
\special{ps::58.28253 rotate}%
\special{ps::2.61803 -0.38197 scale}%
\special{ps::-31.71747 rotate}%
\else
\ifshiftmatrix
\special{ps::[1 2 1 1 28.3468 0] concat}%
\else
\special{ps::[1 2 1 1 0 0] concat}%
\fi
\fi
% The next three lines get us 'back' to the TeX origin
\special{ps::72 Resolution div 72 VResolution div neg scale}%
\special{ps::magscale {1 DVImag div dup scale} if}%
\special{ps::ox neg oy neg translate}%
\special{ps::[end]}%
\hbox to 0pt{Hello\hss}%
\special{ps::[begin]}%
\special{ps::restore}%
\hss
}%
\special{ps::@endspecial}% Tidy up
\special{ps::[end]}%
}%
\wd0=3cm %
\ht0=2cm %
\box0 %
world
\bye