4

Introduction

Since my real use case is obviously somewhat more complex than the problem presented in the MWE, I'll explain the use case first so that you can judge whether my approach is the correct one. Perhaps an alternative method can be used to get the desired output.

The issue in my case has to do with spacing. More specifically, I'm trying to align two baselines. In brief, the issue is that:

  1. I am required to \vskip between two heights.
  2. When doing so, the box that is typeset progresses downward. In my case this is not desirable: the baseline of the first line of \marginpar's box contents should rest on the baseline which we just \vskipped to. The rest should be typeset downward.

Judging from point 2, my initial (possible) workaround would be to set the height of the marginpar box to contain the height of the first line, and the depth should be any other vertical material (so the depth of the first line + height and depth of subsequent lines). It would then have to ignore the height but not the depth of the box. This seems (to me) needlessly complicated at first thought.

Below, you will find an edited picture of the output of the real case with the dimensions (that I know of) that LaTeX has to offer for alignment of the produced vertical box. I have altered the screenshot of the output slightly, outlining the baselines and the calculated \vskip from the algorithm.

enter image description here

In the next picture, the spacing has been altered manually, to (approximately) get the desired output:

enter image description here

Real use case & specifics

(If you think you won't need to know any background and you already know the answer, skip this bit.)

I'm trying to build an alternative to the normal way marginpars are typeset by using the extended set of the primitive macros provided by the pdf part of pdfLaTeX. Specifically, I'm using \pdfsavepos which saves positions at which \marginpar is issued. The boxes containing the material to be typeset as a marginpar are stored away for later typesetting (which will happen during \output, at the point the footer is constructed). To do so, it appends a macro to \@evenfoot and \@oddfoot. In brief,

  1. Calculates the absolute height of the page which corresponds to the top of the text column.
  2. Extracts the height at which \marginpar is issued (which is appended to the \marginpar command).
  3. Builds (but not typeset) the two boxes produced by \marginpar (one for the left side, one for right).
  4. Calculates the required \vskip to align the first line of the material from the \marginpar argument to align with the line in which \marginpar occurred.

I'm not going into the specifics of the code (you can do so in my other question if you're interested: Reflowing marginpars typeset using pdfsavepos). For now, I'll just skip to the relevant bits, which are mostly about getting the spacing right.

The issue is as follows: \pdfsavepos saves the absolute page height of the baseline on which the command is issued. Consider the below picture: (If you can't read the small print, here is also a link to the StackExchange imgur: http://i.stack.imgur.com/2J1An.png.)

enter image description here

Of course I could simply set a negative \vskip of -8.14\p@ and be done with it. For variable font sizes and different fonts, the issue becomes more complex. The below document shows in console how much I would have to raise the box to get the desired alignment (the \rule is only to show the baseline more clearly):

\documentclass{article}\usepackage{fix-cm}\begin{document}
\count0=0
\loop
\ifnum\count0<20
\advance\count0by1
\typeout{The following amount of overfull vbox corresponds to font size: \the\count0}%
\hfill\rule{\linewidth}{1pt}\rlap{\fontsize{\count0pt}{0pt}\selectfont
\textsuperscript{1}\hskip-\marginparsep\smash{\raise0pt%8.5pt
\vbox to 0pt{\hbox{\fontsize{\count0pt}{0pt}\selectfont
\textsuperscript{1}stuff}}}}%
{\fontsize{\count0pt}{0pt}\selectfont  %\typeout{fontsize\the\count0:\the\fontcharht\font`1}%
}%
\repeat
\end{document}

The above shows that the difference in the top of the \textsuperscript between the line and the \rlapped box is indeed 8.14 point, which will also produce the desired alignment in the main document.

At this point I'm considering an \ifcase construction, which converts font size to required \vskip to get the desired alignment. This is not very general and requires extensive checking of all possible font sizes, and so on. I can think of a more general solution to the issue. Brief correspondence in chat with David Carlisle pointed me towards other solutions: I shouldn't even be aware of these heights, and that my solution was wrong to begin with. (I should be using \vtop.) I've tried replacing any \vboxes with \vtops, but to no avail. I can see \vtop work for other cases, however I don't see how it would work in this setting. Look at this example:

\documentclass{article}\usepackage{fix-cm}
\def\ex{Some long example test. Some short text.}\def\exx{\hbox to .45\linewidth{\ex}}
\begin{document}
\setbox0=\vbox{\exx\exx\exx}
\setbox2=\vtop{\exx\exx\exx}
Sample text \box0 
\vskip20pt
\textsuperscript{1}\box2
\end{document}

Box two still produces the wrong alignment. I'm not sure if that's related to my usage or whether the operation simply doesn't do what I want.

The dimension 8.14pt obviously comes from the height of the \textsuperscript of 1 (which has fontsize 5 I think for \normalsize [right?!]) raised by some amount as calculated in the "TeX book" appendix G. I'd obviously like to generalize this to a arbitrary font size, arbitrary height of the first line, etc.

MWE

Again, the issue is a spacing issue. Consider the following MWE:

\documentclass{article}\usepackage{fix-cm}
\def\ex{Some long example test. Some short text.}
\def\exx{\hbox to .45\linewidth{\ex}}
\def\textone{\textsuperscript{1}}
\def\textonerepeat{\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone\textone}
\begin{document}
\setbox0=\vbox{\exx\exx\hbox to .45\linewidth{\textonerepeat\textonerepeat\textonerepeat}}
\setbox2=\vtop to 0pt{\exx\vskip0pt \exx\exx}
Sample text \box0 %\raise8.14pt
\box2
\end{document}

I get the correct alignment by uncommenting \raise8.14pt:

enter image description here

(In the picture on the right, I've already altered the screenshot to show the baseline, and showed the outline of \box2.)

Is there any operation, dimension, or otherwise, to get the desired alignment (like in the picture on the right)? I'm thinking of something like \topisbaseline\box0 or something. The solution would have to work for arbitrary font size and (most importantly) arbitrary fonts.

  • I'm assuming you don't really want the baseline of your margin text to align with the top of the superscript 1's (which seems to be what your right image shows)? – David Carlisle May 18 '15 at 16:41
  • @DavidCarlisle Imagine vskipping a height from vbox1 to vbox2. Generally, vbox2 progresses downward from the point where we vskipped to. After the operation, the part of the first line that belongs to the "height" of the first line, should now rest on the point where we vskipped to. – 1010011010 May 18 '15 at 17:38
  • that's one way of describing it yes, but surely you don't want the misalignment shown by the final image on the right? don't you want the baseline and superscript number in your margin to align with the baseline and superscript number in the text? – David Carlisle May 18 '15 at 18:12
  • @DavidCarlisle That's precisely the goal.. – 1010011010 May 18 '15 at 18:13
3

The question is far too long to consider really and I don't understand the altered image at all.

In this version of the MWE I have marked in red the baseline of the outer sample text, \box0 and \box2, which are all naturally aligned on that baseline without having to measure the height of box2 (which depends on the fonts used) .

enter image description here

\documentclass{article}\usepackage{fix-cm}
\def\ex{Some long example test. Some short text.}
\def\exx{\hbox to .45\linewidth{\ex}}
\def\textone{\textsuperscript{1}}
\def\textonerepeat{\textone\textone\textone
\textone\textone\textone\textone\textone
\textone\textone\textone}
\begin{document}
\setbox0=\vbox{\exx\exx\hbox to .45\linewidth{%
\textonerepeat\textonerepeat\textonerepeat}}
\setbox2=\vtop{\hbox{\textone\ex}\exx\exx\exx}
Sample text \box0 %\raise8.14pt
\showthe\ht2
\box2
\end{document}

If for some reason you do need the 8.14pt length, you do not need any font-specific calculations it is simply \ht2 (which is why you should not use ... to 0pt when saving box2 as its main effect is to hide this length).

I have added \showthe\ht2 so TeX stops and shows:

> 8.14003pt.
l.13 \showthe\ht2

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.