12

I want to make the use of quantum mechanical operators explicit in my text using \hat{A} or \widehat{A}. The problem is that depending on the symbol under the accent it looks either misplaced or too small, but see for yourself:

enter image description here

In the first case, using \hat, the accent above the B looks just slightly too much left-aligned. The other cases are just obviously bad. I have generated all examples using the code below.

I found some related questions: Why does \widehat behave differently if I insert \hspace{0pt}? And in particular: How can I manually choose the size of a wide accent? (math mode) I took some code from the latter, but it doesn't help. Also, the accepted answer in the latter does not compile - I think the accent package doesn't work with xelatex.

So, how can I...

  • better center the accents above the characters?
  • have the accents have a similar width?
  • maybe let them be on the same height (look at the first AB - the hat above the B seems a bit lower)?

.

\documentclass{scrartcl}

\usepackage[tbtags]{mathtools}
\usepackage[math-style=ISO,bold-style=ISO]{unicode-math}
\setmainfont[Ligatures={TeX,Common}]{TeX Gyre Pagella}
\setmathfont{TeX Gyre Pagella Math}

\usepackage{calc}
\newcommand{\styletofont}[1]{%
  \ifx\displaystyle#1\let\next\textfont\fi
  \ifx\textstyle#1\let\next\textfont\fi
  \ifx\scriptstyle#1\let\next\scriptfont\fi
  \ifx\scriptscriptstyle#1\let\next\scriptscriptfont\fi}

\newcommand{\innfwhat}[2]{%
  \styletofont{#1}%
  \dimen0 \fontcharic\next1 \skewchar\next1
  \advance\dimen0 -\fontcharic\next1`#2%
  \makebox[0pt][l]{$#1#2$}%
  \makebox[\widthof{$#1#2$}]{$#1\kern.5\dimen0 \widehat{\vphantom{#2}}$}}
\newcommand{\fwhat}{\mathpalette\innfwhat}

\pagestyle{empty}

\begin{document}

\begin{equation*}
  \begin{split}
    &\hat{A}\hat{B} \\
    &\widehat{A}\widehat{B}\\
    &\widehat{\hspace{0pt}A}\widehat{\hspace{0pt}B}\\
    &\fwhat{A}\fwhat{B}
  \end{split}
\end{equation*}

\end{document}
6

The answer is very font dependent, and I can't access your particular font for which the problem arises. But it seems to me that the kind of kerning you seek almost needs to be reset for each letter. If one were prepared to do that once for an oft-used font, here might be a way.

REVISED SOLUTION (SLOWER, BUT HANDLES \scriptsize, \scriptscriptsize):

Lines beginning with %%%% indicate measures you can alter to conform to your particular font. First I create a stacked dot arrangement (\talldot), merely to have something the vertical height of the desired hat, and which will change size with the math style. I also create \hatglyphCONTENT which is a box containing a cropped \hat. I use that box and scale it to the size of \talldot, designating the result \hatglyph. Note that, since \talldot scales with the math style, so will \hatglyph.

The macro \shifthat stacks the scaled hat over the desired letter in the appropriate math style, employing a horizontal shift of the hat that was passed as an argument.

The macro \newhat is where you define the horizontal shift of the hat for each individual glyph, relative to the centered (non-italic) configuration. Rather than specifying that shift in absolute measure, it is given as a multiplier on \glyphwidth which is 1ex, measured at the appropriate math style.

One of the keys to this solution is scalerel package's \ThisStyle{...\SavedStyle...} syntax, which imports (via \SavedStyle) the math style at invocation to places where that math style is otherwise lost, for example inside boxes or as arguments to other macros.

\documentclass{article}
\usepackage{stackengine}
\usepackage{scalerel}
\usepackage{verbatimbox}
\newlength\glyphwidth
\newcommand\talldot{%
\ThisStyle{%
%%%% 1ST ARGUMENT OF \stackengine (GAP BETWEEN STACKED DOTS)
  \stackengine{.0ex}{$\SavedStyle.$}{$\SavedStyle.$}{O}{c}{F}{F}{S}%
}}
\newsavebox\hatglyphCONTENT
\sbox\hatglyphCONTENT{%
%%%% 1ST OPTIONAL ARGUMENT OF \addvbuffer (CROP OFF TOP OF STACKED hat)
%%%% 2ND OPTIONAL ARGUMENT OF \addvbuffer (CROP OFF BOTTOM OF STACKED hat)
  \addvbuffer[-0.05ex -1ex]{%
    \stackengine{-.1ex}{ }%
                {\(\hat{}\)}{O}{c}{F}{F}{L}%
}}
\newcommand\hatglyph{\ThisStyle{\scalerel*{\usebox{\hatglyphCONTENT}}%
                     {\SavedStyle\talldot}}}
\newcommand\shifthat[2]{%
  \ThisStyle{%
%%%% 1ST ARGUMENT OF \stackengine (GAP BETWEEN GLYPH AND \hatglyph)
    \stackengine{0.0ex}{\(\SavedStyle#2\)}%
                {\(\rule{#1}{0ex}\SavedStyle\hatglyph\)}{O}{c}{F}{T}{S}%
  }%
}
\newcommand\newhat[1]{%
  \ThisStyle{\setlength\glyphwidth{\widthof{$\SavedStyle x$}}%
    \if A#1\shifthat{0.5\glyphwidth}{#1}\else
    \if B#1\shifthat{0.2\glyphwidth}{#1}\else
    \if x#1\shifthat{0.1\glyphwidth}{#1}\else
    \shifthat{0.15\glyphwidth}{#1}% THIS IS THE DEFAULT VALUE
    \fi
    \fi
    \fi
  }%
}
\fboxsep=0pt\fboxrule=.25pt
\begin{document}
\centering
{\tiny How hatglyph is being scaled to \verb|\talldot| (stacked dots)\\
at different mathstyles}
\[
x
\scalerel{\fbox{\hatglyph}}{\ThisStyle{\fbox{$\SavedStyle\talldot$}}}
\scriptstyle
\scalerel{\fbox{\hatglyph}}{\ThisStyle{\fbox{$\SavedStyle\talldot$}}}
\scriptscriptstyle
\scalerel{\fbox{\hatglyph}}{\ThisStyle{\fbox{$\SavedStyle\talldot$}}}
\]

\[
\begin{array}{l}
\hat A \hat B \hat x \hat y A_{{\hat x}_{\hat B \hat A \hat x}}\\
\newhat A \newhat B \newhat x \newhat y A_{{\newhat x}_{\newhat B
\newhat A \newhat x}}\\
\end{array}
\]


\end{document}

enter image description here

ORIGINAL SOLUTION (FAST BUT CAN'T HANDLE \scriptsize, \scriptscriptsize):

The macro \newhat does a test on what letter is the argument and uses a horizontal shift on the hat symbol to set the location for that letter. If a letter has not been "rekerned" in this fashion, it defaults to a setting (as shown for the letter "y" in my example. The value of \Sstackgap determines the vertical spacing betwen the top of the letter and the bottom of the hat. The negative value was required, because my hat is actually an elevated had over a null symbol, and I had to bring it down a bit, when stacked over an additional letter.

The MWE shows the normal \hat on the first line, and \newhat on the second. As I said, since I don't have your font, my font doesn't really suffer the problems yours does, so there is not a great difference.

Note: instead of using a "default" shift, as I do in this MWE, you could alternately use \hat{#1} as the default, which would get you back to where you were. Also, I use pts as units of my shift. You might prefer ex's, so as to retain usage when the font is scaled.

\documentclass{article}
\usepackage[oldsyntax]{stackengine}
\def\stacktype{S}\Sstackgap=-4.3pt
\newcommand\shifthat[2]{%
  \stackengine{\Sstackgap}{$#2$}{\(\hspace{#1}\hat{}\)}{O}{l}{F}{T}{S}}
\newcommand\newhat[1]{%
\if A#1\shifthat{5.2pt}{#1}\else
\if B#1\shifthat{4.8pt}{#1}\else
\if x#1\shifthat{3.6pt}{#1}\else
\shifthat{3.4pt}{#1}% THIS IS THE DEFAULT VALUE
\fi
\fi
\fi
}
\begin{document}
\[
\begin{array}{l}
\hat A \hat B \hat x \hat y\\
\newhat A \newhat B \newhat x \newhat y
\end{array}
\]
\end{document}

enter image description here

[EDIT: This MWE uses obsolete stackengine syntax for setting stackgap lengths (e.g., \Sstackgap=1ex), which prevented scalable lengths from scaling under a fontsize change. Version 2 of the package (submitted JUL-11-13) remedies the problem with a small syntax change.]

  • Thanks a lot for your answer. This would indeed be tedious, but the way you wrote it down it's pretty straight forward, which is good. I am going to try this later and then accept this answer (unless there is some genius alternative still in the making :) ). BTW - you should have access to this font if you use the latest TeXlive. At least that's where I got it from. – mSSM Jul 1 '13 at 16:11
  • Thank you for your edit: I have just tried out your solution and noticed immediately that there is a problem when I try to use \newhat with \scriptstyle size (e.g. when in a superscript) --- the character size will go back to \displaystyle. Is there a way to fix \newhat to account for that? At the moment, I have defined \scripthat and I write \scriptstyle in every argument to \shifthat. – mSSM Jul 12 '13 at 13:29
  • @mSSM I'm heading offline for a few days. I'll have a look next week. – Steven B. Segletes Jul 12 '13 at 13:49
  • @mSSM Really, this is my last msg for a few days. But I'm sure it can be fixed, probably using tactics similar to tex.stackexchange.com/questions/100966/…. Feel free to try scalerel in the meantime. – Steven B. Segletes Jul 12 '13 at 14:26
1

Steven's approach seems like the right way to go, and the task of having to tweak it for each letter isn't much of an obstacle, because in practice only a few letters will need hats in a document.

I've had a few issues with his code, which I've hacked around. Since there are quite a lot of changes, I'm posting the result as this separate answer.

\documentclass[a5paper]{article}

\usepackage{scalerel,stackengine}
\stackMath
\usepackage{verbatimbox} % For \addvbuffer
\usepackage{xparse}
\newlength\glyphwidth
\newlength\widthofx
%Use this in a document body for debugging the glyphs:
%\scalebox{10}{
%\setlength{\fboxsep}{0.0pt}
%\setlength{\fboxrule}{0.1pt}
%\fbox{\fbox{$\usebox{\hatglyphCONTENT}$}%
%      \fbox{$\usebox{\checkglyphCONTENT}$}}
%}
\newsavebox\hatglyphCONTENT
\sbox\hatglyphCONTENT{%
%%%% 1ST OPTIONAL ARGUMENT OF \addvbuffer (CROP OFF TOP OF STACKED hat)
%%%% 2ND OPTIONAL ARGUMENT OF \addvbuffer (CROP OFF BOTTOM OF STACKED hat)
    \addvbuffer[-0.05ex -1.3ex]{$\hat{\phantom{.}}$}%
}
%%%% The floating point parameter scales the hatt glyphs everywhere.
\newcommand\hatglyph{\resizebox{0.6\widthofx}{!}{\usebox{\hatglyphCONTENT}}}
\newcommand\shifthat[2]{%
%%%% 1ST ARGUMENT OF \stackengine (GAP BETWEEN GLYPH AND \hatglyph)
    \stackengine{0.2\widthofx}{%
        \SavedStyle#2}{%
        \rule{#1}{0ex}\hatglyph}{O}{c}{F}{T}{S}%
}
\ExplSyntaxOn
\newcommand\relativeGlyphOffset[1]{%
    % The horizontal offset in arbitrary units that scale with math style.
    \str_case:nnF{#1}{%
        {A}{0.18}%
        {B}{0.1}%
        {W}{0.02}%
        {J}{0.18}%
        {\phi}{0.17}%
    }{0.05}% Default
}\ExplSyntaxOff
% \hatt{decoratedLetter}[A] will insert the decoratedLetter with the hat
% above it, horizontally adjusted as if the decoratedLetter was an "A".
% If the trailing optional argument is not provided, then it defaults 
% to the decoratedLetter. This way we could do e.g. \hatt{\hatt{A}}[A].
\NewDocumentCommand{\hatt}{mO{#1}}{%
    \ThisStyle{%
        \setlength\glyphwidth{\widthof{$\SavedStyle{}\longleftarrow$}}%
        \setlength\widthofx{\widthof{$\SavedStyle{}x$}}%
        \shifthat{\relativeGlyphOffset{#2}\glyphwidth}{#1}%
  }%
}


\begin{document}

\[
\begin{array}{ll}
\mbox{With \textbackslash{}hat: } & \hat W \hat A \hat B \hat \phi \hat x \hat y A\hat J _{{\hat x}_{\hat B \hat A \hat x}}\\
\mbox{With \textbackslash{}hatt: } &  \hatt W  \hatt A  \hatt B  \hatt \phi \hatt x \hatt y A\hatt J _{{\hatt x}_{\hatt B
\hatt A \hatt x }}\\
\end{array}
\]


\end{document}

Results

Some of the changes:

  • Speeded up, by using \ThisStyle only once — that's all that's needed. See here for why nesting too many \ThisStyles slows things down. (In fact, nesting any \mathchoice-based solutions in general.)

  • Adding a new letter is done by adding another line to the lookup table. No need to remember to add another \fi after it.

  • For the case where we wish to add several decorations on a letter, there is now a trailing optional argument for specifying how much to offset the decoration, for example: $\hatt{\hatt{A}}[A]$. This way the outer \hatt will know that it's decorating an "A". The optional argument defaults to the first argument when absent.

  • For my purposes the hats are made larger, as in my work they are not just hints, but have important semantics. This is easy to change using a parameter.

  • Now using a \longleftarrow (any wide character would also do) as a basic unit of measure of a math style, rather than the letter x, because this seems to make a single offset work more consistently across math styles. (The underlying issue can be seen by putting a tight \fbox around an x: much larger (relatively) horizontal padding is added around the x in \scriptscriptstyle than in display style.)


Since I also wrote a similar replacement for \check (aka caron symbol), I might as well post the additional code here.

\newsavebox\checkglyphCONTENT
\sbox\checkglyphCONTENT{%
    \raisebox{\ht\hatglyphCONTENT}[\ht\hatglyphCONTENT][0pt]{%
        \scalebox{1}[-1]{\usebox{\hatglyphCONTENT}}%
    }%
}
%%%% The floating point parameter scales the checkk glyphs everywhere.
\newcommand\checkglyph{\resizebox{0.6\widthofx}{!}{\usebox{\checkglyphCONTENT}}}
\newcommand\shiftcheck[2]{%
%%%% 1ST ARGUMENT OF \stackengine (GAP BETWEEN GLYPH AND \checkglyph)
    \stackengine{0.2\widthofx}{%
        \SavedStyle#2}{%
        \rule{#1}{0ex}\checkglyph}{O}{c}{F}{T}{S}%
}
\NewDocumentCommand{\checkk}{mO{#1}}{%
    \ThisStyle{%
        \setlength\glyphwidth{\widthof{$\SavedStyle{}\longleftarrow$}}%
        \setlength\widthofx{\widthof{$\SavedStyle{}x$}}%
        \shiftcheck{\relativeGlyphOffset{#2}\glyphwidth}{#1}%
    }%
}

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.