3

I am trying to write a custom command eins such that when you have

\eins{id}{text}

, it outputs the relative box position and depth and height of text in mm (or points) within the printed document together with an identifier that tells me which text element is at that position.

So far I have:

\newcommand\dimtomm[1]{%
    \strip@pt\dimexpr 0.351459804\dimexpr#1\relax\relax %
}

\newcommand{\eins}[2][1]{%
    \zsavepos{#1-ll}
      \newlength{\dd}
      \settodepth{\dd}{#2-ll}
    \write\mywrite{#2: \dimtomm{\zposx{#1-ll}sp}, \dimtomm{\zposy{#1-ll}sp,  \the\dd, } }% 
}

If I specify output file:

\newwrite\mywrite
\openout\mywrite=\jobname.72.280.pos \relax

and I later insert

\eins{title}{\huge \textbf {Big Title} }

It gets me the identifier and the x and y positions (relative) of the text #1 (checked by drawing at printed position on image...) but it does not print the depth

Can it be done? the Answer is yes!

thanks to accepted answer from @gernot. Leaving the original (confusing and confused) question above for context but recording my final implementation bellow for those with the exact same problem: how to get the geometric boundaries of rendered text in a single pdf page.

\makeatletter
\newcommand\dimtomm[1]{%
    \strip@pt\dimexpr 0.351459804\dimexpr#1\relax\relax %
}
\makeatother

\makeatletter
\def\convertto#1#2{\strip@pt\dimexpr #2*65536/\number\dimexpr 1#1}
\makeatother

\newwrite\mywrite
\immediate\openout\mywrite=\jobname.72.280.pos\relax

\newlength{\dd}
\newlength{\ww}
\newlength{\hh}
\newcommand{\eins}[2][1]%
   {\zsavepos{#1-ll}% Store the current position as #1-ll
    {#2}% Output the text provided as mandatory argument
    \settodepth{\dd}{#2}% Measure the depth of the mandatory argument
    \settowidth{\ww}{#2}% Measure the width of the mandatory argument
    \settoheight{\hh}{#2}% Measure the height of the mandatory argument
    \immediate\write\mywrite{#1: \dimtomm{\zposx{#1-ll}sp}, \dimtomm{\zposy{#1-ll}sp},  \convertto{mm}{\the\dd}, \convertto{mm}{\the\hh}, \convertto{mm}{\the\ww} }%
   }

\begin{document}
\eins[title]{\huge \textbf {Huge Title}}
\eins[title]{\Large \textbf {Large Title}}
\end{document}
xor007
  • 133

1 Answers1

4
  • You define \eins to be a command with one optional and one mandatory argument, since you specify \newcommand{\eins}[2][1]. You then use it as \eins{title}, which means that title will be taken as the second, mandatory argument and the default value 1 will be used as first, optional argument. My guess is that you mean

    \eins[title]{\huge \textbf {Big Title}}
    

    Otherwise you measure the depth of title which is zero.

  • In the definition of \eins you define a new length \dd. Move this statement out of the definition of \eins, otherwise you consume a new length each time you invoke \eins.

  • Why to you set \dd to the depth of #2-ll? Shouldn't this be the depth of the mandatory argument, i.e. just of #2? The characters -ll have no depth, so they do not influence the depth, but why do you add them?

  • You start the argument of \write with #2. Do you really intend to write the mandatory argument with all the formatting instructions (which will be expanded and give a mess)? I suppose you rather want to write the label provided as optional argument, which is #1.

  • Do you want to output the mandatory argument or just measure it? At the moment it is not written to the output file. I guess you want to do the first, which means to add #2 to the definition of \eins, maybe best near the place where the position is measured.

  • You have spurious spaces in the definition of \eins, which may appear as extra space in the output. Add percent signs at the end of the lines.

Here is the corrected code (I have removed the conversion of pt to mm).

\documentclass{article}
\usepackage{zref-abspos}
\newwrite\mywrite
\immediate\openout\mywrite=\jobname.72.280.pos\relax
\newlength{\dd}
\newcommand{\eins}[2][1]%
   {\zsavepos{#1-ll}% Store the current position as #1-ll
    {#2}% Output the text provided as mandatory argument
    \settodepth{\dd}{#2}% Measure the depth of the mandatory argument
    \immediate\write\mywrite{#1: \zposx{#1-ll}, \zposy{#1-ll},  \the\dd}% 
   }

\begin{document}
\eins[title]{\huge \textbf {Big Title}}

\eins[title2]{\textbf {Not so big title}}
\end{document}

After running pdflatex, the file \jobname.72.280.pos contains

title: 8799518, 47171296, 4.03276pt
title2: 8799518, 45963106, 1.94444pt
gernot
  • 49,614
  • Thanks a lot for the quick answer! I was confused about the arguments ( I think I still am ). This answer works. But I always get the same depth for all the elements I output. I want to be able to use the command for different elements. – xor007 Apr 17 '17 at 10:56
  • @xor007 You are right, there was a bug: The file commands were delayed until the time when the page was shipped out, and all the write commands output the last value of \dd. I have corrected the code by adding \immediate to the file commands, so they are executed immediately. – gernot Apr 17 '17 at 11:17