16

Context

In my document, I attach a tooltip to the middle part of a word. To demonstrate this behavior, try mousing over just the letter V in the word AVA.

Here is the implementation and usage of my \tooltip command.

%% This tooltip command
\newcommand\tooltip[2]{%
    \special{pdf:bann<</Type/Annot /Subtype/Widget /FT/Btn /Ff 65536 /H/N /TU(#2)>>}%
    #1%
    \special{pdf:eann}%
}

%% is used like so
A\tooltip{V}{Tooltip text here.}A

%% which expands like so.
A\special{…}V\special{…}A

The specifics of making the tooltips are not directly relevant the question, but I have included it for context.

Problem

Separating the parts of the word by interspersing \special{}, i.e. A\special{}V\special{}A causes the kerning between parts to no longer apply.¹ (Note: \special is not special — this behavior also occurs in A{V}A and A{}V{}A, unless one uses XeLaTeX or LuaLaTeX.²)

Partial solution

I was able to restore kerning in the latter two parts using the following command, adapted from this answer, which uses \futurelet to do the trick.

\newcommand\kernright[1]{\def\hltext{#1}\futurelet\hlnext\hldokern}
\def\hldokern{%
    \sbox0{\mbox\hltext\mbox\hlnext}\sbox2{\hltext\hlnext}\kern\dimexpr\wd2-\wd0\relax%
}

(Although that question specifically concerns kerning between different styles, the solution still works. Another more generic question has no satisfactory solution.)

Here are three wrapper commands for \tooltip.

\newcommand\tooltipA[2]{#1}
\newcommand\tooltipB[2]{\tooltip{#1}{#2}}
\newcommand\tooltipC[2]{\tooltip{#1}{#2}\kernright{#1}}

Below is a comparison table and the corresponding rendered image.

                        A\tooltipX{V}{}A expands to             AV kerned?   VA kerned?
                        ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾             ‾‾‾‾‾‾‾‾‾‾   ‾‾‾‾‾‾‾‾‾‾
A. Normal kerned text   AVA                                     yes          yes
B. Interrupted text     A\special{}V\special{}A                 no           no
C. Partial solution     A\special{}V\special{}\kernright{V}A    no           yes

examples of kerning across empty groups

However, I have not been able to come up with a way to write a \tooltipD command that would also restore kerning between A and V, as there does not appear to be a command that does the “opposite” of \futurelet.

Question

How do I restore the kerning between A and V?

I would expect to insert an additional \kernleft command somewhere in the body of the \tooltipC command to yield an output equivalent to the top part of the image.

MWE

(Tooltips should work in XeLaTeX.³)

\documentclass[varwidth=true]{standalone}
\newcommand\tooltip[2]{%
\special{pdf:bann<</Type/Annot /Subtype/Widget /FT/Btn /Ff 65536 /H/N /TU(#2)>>}%
#1%
\special{pdf:eann}%
}
\newcommand\kernright[1]{\def\hltext{#1}\futurelet\hlnext\hldokern}
\def\hldokern{%
\sbox0{\mbox\hltext\mbox\hlnext}\sbox2{\hltext\hlnext}\kern\dimexpr\wd2-\wd0\relax%
}

% A-C are from original question; D is adapted from Steven's answer
\newcommand\tooltipA[2]{#1}
\newcommand\tooltipB[2]{\tooltip{#1}{#2}}
\newcommand\tooltipC[2]{\tooltip{#1}{#2}\kernright{#1}}
\newcommand\tooltipD[2]{%
    #1%
    \setbox0=\hbox{#1}\kern-\wd0%
    \tooltip{#1}{#2}%
    \kern-\wd0#1%
}

\begin{document}
\tooltip{Foo}{Bar}

A\tooltipA{V}{Tooltip text}A

A\tooltipB{V}{Tooltip text}A

A\tooltipC{V}{Tooltip text}A

A\tooltipD{V}{Tooltip text}A
\end{document}
  • 1
    which tex engine and driver are those \special targeted for? – David Carlisle Mar 7 '14 at 8:34
  • Is it just kerns that you need or would you want f\special{}fi to use an ffi ligature. (Solutions involving typesetting the original string might be easier if you do ligatures as well as kerns) – David Carlisle Mar 7 '14 at 9:27
  • @DavidCarlisle I have been using XeLaTeX/xdvipdfmx, but ideally a solution should work in all cases. – hftf Mar 7 '14 at 11:39
  • I hadn't thought about ligatures not applying. (In my document, the A's are often punctuation marks.) Ideally ligatures should also still apply, but I'm not seeing how you would get a tooltip to only cover part of an ffi glyph, for example. – hftf Mar 7 '14 at 11:45
  • well because (apart from using lua) the only general way I can see to do this is to typeset the word without the tooltip and then back up and position the tooltip pdfmark over the word while not typesetting anything, so that you just need to estimate the visual extent of the active region. This only works for pdf style anotations where the anotation is separate from the text in the back end, if you have an html style back end where the annotation has to surround the text then you would have to break ligatures – David Carlisle Mar 7 '14 at 11:49
6

Is an overstrike allowed? If so, this restores the kerning. I don't comprehend the tooltip code, but tried to show what I mean in this MWE. The key to restoring the proper kerning is to start the \tooltip macro on #1 and end it on #1.

I have EDITED to insert \relax after the \kerns, per the OP's warning.

I have re-EDITED, based on comments from the OP. Now that I fully understanding that the first argument to \tooltip isn't just a character, but could conceivably be a word or several words, I have revised my strategy as follows: the only kerning/overstrike that occurs is on the first and last letters of the argument. Thus, spaces and explicit hyphens in the middle of the argument can be used for a linebreak. The one case that still has difficulty is hyphenatable words. This method does not hyphenate, but I'm not quite sure why.

Below is a variant (made to compile in PDFLaTeX) on the file provided by the OP in his comments, to test the kerning of the various methods, A-D, when the methods were stressed with an imminent linebreak. The currently proposed solution is method D, which captures the kerns, but cannot auto-hyphenate.

\documentclass{article}
%\usepackage{fontspec}
\usepackage{xcolor}
%\setmainfont{Minion Pro}
%\setmonofont{Consolas}
\usepackage{stringstrings}

\newcommand\tooltip[2]{%
\special{pdf:bann<</Type/Annot /Subtype/Widget /FT/Btn /Ff 65536 /H/N /TU(#2)>>}%
#1%
\special{pdf:eann}%
}
\newcommand\kernright[1]{\def\hltext{#1}\futurelet\hlnext\hldokern}
\def\hldokern{%
\sbox0{\mbox\hltext\mbox\hlnext}\sbox2{\hltext\hlnext}\kern\dimexpr\wd2-\wd0\relax%
}

\newcommand\tooltipA[2]{#1}
\newcommand\tooltipB[2]{\tooltip{#1}{#2}}
\newcommand\tooltipC[2]{\tooltip{#1}{#2}\kernright{#1}}
\newcommand\tooltipD[2]{%
\firstof#1\relax%
\tooltip{#1}{#2}%
\substring[q]{#1}{$}{$}%
\setbox0=\hbox{\thestring}%
\kern-\wd0\relax\thestring%
}

\def\firstof#1#2\relax{#1\setbox0=\hbox{#1}\kern-\wd0\relax}

\begin{document}
\setlength\parindent{0pt}
\newcommand\lotsofxs{\textcolor{gray!20}{xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xx}}
\newcommand\trial[4]{\lotsofxs{} #2\csname tooltip#1\endcsname{#3}{Tooltip text}#4\par}
\newcommand\fourtrials[4]{
{\texttt{#2|#3|#4}\hfill\textbf{#1}}\par\hrule\par
\trial{A}{#2}{#3}{#4}
\trial{B}{#2}{#3}{#4}
\trial{C}{#2}{#3}{#4}
\trial{D}{#2}{#3}{#4}
\bigskip
}

Default behavior: VAVA\tooltipD{V}{text}AVAV\vspace{1em}

%\rule{\textwidth}{2pt}\par
\fourtrials{Unhyphenatable word (only situation with overflow)}{A}{VxxxxxxxxxxV}{A}
\fourtrials{Multiple words}{A}{Vxxxxx xxxxxV}{A}
\fourtrials{Explicit hyphen}{A}{Vxxxxx\-xxxxxV}{A}
\fourtrials{Hyphenatable word}{‘}{Automatically}{.}
\fourtrials{Multiple words}{‘}{Auto matically}{.}

\end{document}

enter image description here


Original solution:

Conversation with the OP in the comments leads to two points that should be made about this solution. One is that this method will break if a space is in the first argument to \tooltip. The reason is that a space has glue, and glue is not of fixed width. Thus, kerning cannot be used to undo a space.

The second point is that the tooltip in the middle of the word will prevent hyphenation for that word. While this doesn't make the method "broken", it does allow that long words that would otherwise hyphenate will not do so, with a tooltip in their middle. Thus, one could experience margin overruns, not because of the method directly, but because indirectly the normal hyphenation is prevented.

\documentclass{article}
%% This tooltip command
\newcommand\tooltip[2]{%
    #1%
    \setbox0=\hbox{#1}\kern-\wd0\relax%
    \special{pdf:bann<</Type/Annot /Subtype/Widget /FT/Btn /Ff 65536 /H/N /TU(#2)>>}%
    \phantom{#1}%
    \special{pdf:eann}%
    \kern-\wd0\relax#1%
}
\parskip 1ex
\begin{document}
\noindent\rule{\textwidth}{2pt}

The tooltipped word is ``crAVAt,'' with the tooltip on the ``V''.

\noindent$\bullet$ \textbf{As it is supposed to work}

ccvcvf adsakljfd kdfklj sdkljsdf kjsdkj ds fdsfdggfds dd dgfd fsf dsf ddd
crA\tooltip{V}{Tooltip text}At 
dfsf  sdf s sd fsdf sdfsd sd ds sd frsdr d sfsd fds

ccvcvf adsakljfd kdfklj sdkljsdf kjsdkj ds fdsfdggfds dd dgfd fsf dsf dd %d
crA\tooltip{V}{Tooltip text}At 
dfsf  sdf s sd fsdf sdfsd sd ds sd frsdr d sfsd fds

\noindent$\bullet$ \textbf{Tooltip prevents hyphenation, which can cause margin overruns}

ccvcvf adsakljfd kdfklj sdkljsdf kjsdkj ds fdsfdggfds dd dgfd fsf ds
crA\tooltip{V}{Tooltip text}Atinated
the prior word is tooltipped.

ccvcvf adsakljfd kdfklj sdkljsdf kjsdkj ds fdsfdggfds dd dgfd fsf ds
crAVAtinated
the prior word is not tooltipped.

\noindent$\bullet$ \textbf{Spaces (glue)  in tooltip's argument 1 can cause non-alignment of kern}

Here are spaces in the first argument iddsfxsxddgfdxffdxxfgsfdsfdd 
crA\tooltip{V V}{Tooltip text}At 
Here the tooltip was on the ``V V'' in the middle of ``crAV VAt.''


\end{document}

enter image description here

  • It defeats the purpose if the actual tooltip is gone!… It might work for me if I take out \phantom. – hftf Mar 7 '14 at 11:53
  • 1
    @hftf I would also add that it would help us help you if you post a complete MWE in your question; let's say, one that produces the desired tooltip, but doesn't capture the proper kerning. It might help us better understand the requirements, we who don't deal with tooltips. – Steven B. Segletes Mar 7 '14 at 11:58
  • 1
    @hftf I placed the \phantom thinking that all that was required was a horizontal space over which the tooltip would be active. Removing it would be OK, but would result in a triple rather than double strike, of the character. – Steven B. Segletes Mar 7 '14 at 12:02
  • 1
    @hftf One other thought. If the tooltip 1st argument includes a space, then this will break my method because a space has glue, which can stretch/compress during typesetting. Also, the other thought is that words that would otherwise hyphenate to break across a line will no longer hyphenate, because the tooltip code in the middle of the word will destroy its search in the dictionary. That could bring on margin overflows indirectly (not because the method is broken, but because a long word can no longer be hyphenated). – Steven B. Segletes Mar 7 '14 at 13:46
  • 1
    Yes, but it is not kerned with A in Computer Modern, I believe. – hftf Mar 7 '14 at 16:46
3
+200

probably I'd just re-add the kerns explictly after measuring the text with and without the adjacent characters being separated by box boundaries.

\documentclass[varwidth=true]{standalone}
\newcommand\tooltip[2]{%
\special{pdf:bann<</Type/Annot /Subtype/Widget /FT/Btn /Ff 65536 /H/N /TU(#2)>>}%
#1%
\special{pdf:eann}%
}


\newcommand\tooltipZ[6]{%
#1%
\kerna{#1}{#2}%
\tooltip{#3}{#4}%
\kerna{#5}{#6}%
#6%
}

\newcommand\kerna[2]{%
\sbox0{#1}\sbox2{#2}\sbox4{#1#2}%
\kern\dimexpr\wd4-\wd0-\wd2\relax}

\begin{document}
\tooltip{Foo}{Bar}

AVA

% #1 pre-char
% #2 first active char
% #3 active text
% #4 tooltip
% #5 last active char
% #6 post-char
\tooltipZ{A}{V}
         {V}{Tooltip text}
         {V}{A}


\end{document}
  • Surely you don't even need to separate out the first and last characters? – hftf Aug 23 '15 at 18:05
  • The obvious disadvantage of this solution is that the user would need to pass the pre-char and post-char as arguments \tooltipZ{foo}...{bar} even though they are not part of the tooltip, instead of foo\tooltipZ...bar. – hftf Aug 23 '15 at 18:11
  • @hftf for comment 1, Oh I guess you are right you could drop arguments 2 and 5 and use the entire argument 3 for each measurement (so would just have 4 arguments). For comment 2 think of it as a different interface rather than a disadvantage. a disadvantage would be a loss of functionality:-) – David Carlisle Aug 23 '15 at 20:40
3

My suggestion is to slight re-design the \tooltip syntax. The first parameter of such macro is the whole word, but the highlighted text is surrounded into second braces pair, for example:

\tooltip{A{V}Atar}{avatar}

If there isn't the second brace pair then the whole text is highlighted:

\tooltip{tipped text}{tip}

This can be implemented simply without overlapping letters:

\def\tooltip#1{\tooltipA#1{}\end}
\def\tooltipA#1#{\def\tmpa{#1}\tooltipB}
\def\tooltipB#1#2\end#3{\ifx\end#1\end
   \tooltipC{}\tmpa{}{#3}\else \tooltipC\tmpa{#1}{#2}{#3}\fi
}
\def\tooltipC#1#2#3#4{% #1=pre-text, #2=tipped text, #3=post-text, #4=tip
   #1\kerncorr{#1}{#2}%
   \special{pdf:bann<</Type/Annot /Subtype/Widget /FT/Btn /Ff 65536 /H/N /TU(#4)>>}%
   #2%
   \special{pdf:eann}%
   \kerncorr{#2}{#3}#3%
}
\def\kerncorr#1#2{\setbox0=\hbox{#1\kern0pt #2}\setbox2=\hbox{#1#2}%
   \kern\wd2 \kern-\wd0
}

The hyphenation can be set directly by \- if needed, for example

\tooltip{A{V}A\-tar}{avatar}
  • yes same measurement as mine I think but better user syntax +1:-) – David Carlisle Aug 26 '15 at 20:51

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.