3

TL/DR

I understand this is a perverse question, but—is it possible, in fontspec/XeLaTeX|LuaLaTeX, to separately scale uppercase and lowercase letters of a monospace typewriter font to achieve the effect of having

  • lowercase letters scaled to "MatchLowercase", and
  • uppercase letters to "MatchUppercase",

so that the cap-to-x-height ratio matches the main font.

I understand that this would destroy kerning calculations in a normal font, but for monospace, it seems reasonably straightforward to horizontally stack non-overlapping boxes. (Though I suspect this may create eye-soreness for initial-case words where simple stacking will create extra space between the uppercase first letter and the lowercase tail: W·ord.)

Bonus for suggesting a monospace typewriter font that harmonises with EB Garamond.

Longform

I'm using XeLaTeX at the moment, but I have a lot of branches so the document compiles with LuaLaTeX as well. I'm using fontspec.

I'm writing a document with lots of code and I'm using EB Garamond for the body (and Garamond-Math.otf for math). I've had a heck of a time finding a monospace/typewriter font that looks good with garamond.

I've settled on IBM Plex Mono:

\setmonofont{IBMPlexMono}%
  [
  , Path = {…}
  , UprightFont = *-Regular.otf
  , ItalicFont = *-Italic.otf
  , BoldFont = *-Bold.otf
  , BoldItalicFont = *-BoldItalic.otf
  , Scale=MatchLowercase
  ]

though I welcome recommendations, especially those that have fairly broad unicode support for UTF in comments.

Given the fixed choice of IBM Plex Mono, my problem is that the cap-to-x-height ratio between EB Garamond and Plex are so different that it looks a little strange with inline code when I scale by MatchLowercase.

4
  • 1
    Try Drafting Mono (indestructibletype.com/Drafting).
    – Thérèse
    Commented Jul 15, 2023 at 16:16
  • 2
    Sorry, but this is perverse. 😉 The font designer carefully chose the proportion between uppercase and lowercase letters. If the monospaced font doesn’t suit your taste it probably means that the font combination isn’t really good.
    – egreg
    Commented Jul 15, 2023 at 16:34
  • @egreg Agreed :) I have an inner designer somewhere in my heart and therefore understand my request is a recipe for abuse. But I need to see what it looks like. I just can't find a good tt for combination with EB Garamond. I've wanted to write a formidable mathematical document in Garamond since my MSc thesis.
    – Timtro
    Commented Jul 15, 2023 at 17:09
  • @Thérèse That's a lovely font, and I'm glad to have added it to my catalogue. You're right in that it's flesh is a better match with EB Garamond than Plex, but unfortunately the cap-to-x-height ratio is still a mismatch and it lacks box-drawing characters. But overall I prefer it to Plex as a pair with EB Garamond.
    – Timtro
    Commented Jul 16, 2023 at 17:25

3 Answers 3

2

It's indeed a perverse question, I'm afraid.

The font designer decided about the proportion between capital and lowercase letter and you're trying to ruin their artwork.

Anyway, it's possible to do it with kernel commands.

\documentclass{article}
\usepackage{fontspec}

\setmainfont{TeX Gyre Pagella}

\setmonofont{IBMPlexMono}[
  Extension=.otf,
  UprightFont = *-Regular,
  ItalicFont = *-Italic,
  BoldFont = *-Bold,
  BoldItalicFont = *-BoldItalic,
  Scale=MatchLowercase,
]
\newfontfamily{\UCMONO}{IBMPlexMono}[
  Extension=.otf,
  UprightFont = *-Regular,
  ItalicFont = *-Italic,
  BoldFont = *-Bold,
  BoldItalicFont = *-BoldItalic,
  Scale=MatchUppercase,
]

\ExplSyntaxOn
\NewDocumentCommand{\atexttt}{m}
 {
  \texttt { \text_map_function:nN { #1 } \__timtro_uclc:n }
 }

\cs_new_protected:Nn \__timtro_uclc:n
 {
  \str_if_eq:eeTF { #1 } { \text_lowercase:n { #1 } }
   { #1 } { {\UCMONO#1} }
 }
\ExplSyntaxOff

\begin{document}

Sm \atexttt{Sm} \texttt{Sm}

\end{document}

enter image description here

Comment: the picture clearly show how bad your idea is. 😊 Look at the uppercase “S” and you'll see that the stroke thickness is visibly different from the “m”. You also lose the “monospacedness”, because capital letters will be wider than lowercase.

For long verbatim-like parts don't use this. And don't use it at all. 🙃

2
  • Thanks so much, @egreg. While I had predicted the loss of monospacing, I forgot to consider too that it would distort the weight. I perhaps could have lived with the former until I figured out a way to adjust kerning, the latter is a dealbreaker. Just so you don't feel you wasted your time: I was intensely curious about how this effect could be achieved, regardless of wheather or not it was a good idea. You scratched my mind-itch :)
    – Timtro
    Commented Jul 16, 2023 at 15:06
  • NB: When I tried this, it blew the memory caps. (But I did use it to replace \texttt in the whole 200 page document.)
    – Timtro
    Commented Jul 16, 2023 at 18:23
1

I wrote some code similar to this back in 2018, which scales uppercase and lowercase separately to fake small caps.

For this purpose, you could simplify it considerably. You don’t want to capitalize the scaled lowercase letters, and you might or might not want to scale them horizontally as I did. The code to automatically determine the x-height would change to instead use the x-height of the main font.

However, you should first look for a sans-serif monospace font with a more similar x-height.

1

Perhaps something like this might be of some limited use?

Adapting from my answer at Fake small caps with XeTeX/fontspec?, I control the vertical scale of upper and lower-case letters in \fauxtt with \Cscale and \Vscale. The horizontal scale of the tt letters is adjusted, if desired, via \Hscale.

In the MWE, the first line of output is unadjusted tt. In the 2nd line of output is \fauxtt.

\documentclass{article}
\usepackage{fontspec,graphicx,xcolor}
\usepackage{graphicx}
\makeatletter
\makeatother
\newcommand\fauxtt[1]{\fauxtthelper#1 \relax\relax}
\def\fauxtthelper#1 #2\relax{%
  \fauxtthelphelp#1\relax\relax%
  \if\relax#2\relax\else\ \fauxtthelper#2\relax\fi%
}
\def\fauxtthelphelp#1#2\relax{%
  \ifnum`#1=\lccode`#1\relax\scalebox{\Hscale}[\Vscale]{\ttfamily#1}\else%
    \scalebox{\Hscale}[\Cscale]{\ttfamily#1}\fi%
  \ifx\relax#2\relax\else\fauxtthelphelp#2\relax\fi}
\begin{document}
\fontspec{Palatino Linotype}
\def\Hscale{1.00}\def\Vscale{1.05}\def\Cscale{1.13}%

\noindent\rlap{\color{red}\rule[4.5pt]{2in}{.1pt}}%
\rlap{\color{red}\rule{2in}{.1pt}}%
\rlap{\color{red}\rule[7pt]{2in}{.1pt}}%
Sm
\texttt{Sm}

\noindent\rlap{\color{red}\rule[4.5pt]{2in}{.1pt}}%
\rlap{\color{red}\rule{2in}{.1pt}}%
\rlap{\color{red}\rule[7pt]{2in}{.1pt}}%
Sm
\fauxtt{Sm}
\end{document}

enter image description here

1
  • Thank you so much for this. It's taken me a little time to understand what you're doing here, but it's clever :) +1up for using recursion (twice). I learned a lot from this answer: it's been 20 years since I've sat with my TeXbook and written something this low-level.
    – Timtro
    Commented Jul 16, 2023 at 16:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .