2

I'm trying to draw text in different shapes using a custom font.

With the help of Steven, I was able to get most of the text shapes I needed working well. See the question here

Everything works well, except when using custom fonts. I'm using the fontspec package with XeLaTeX for custom fonts. Below is what I'm using to generate the final output:

\documentclass[11pt]{article}

\usepackage{ifthen,trimclip,calc,fp,graphicx}
\usepackage[active, tightpage]{preview}
\usepackage[usenames,dvipsnames,svgnames,table]{xcolor}
\usepackage{fontspec}
\usepackage[document]{ragged2e}

\setlength\PreviewBorder{0.2pt}%

\title{bidPress}
\author{bidPress}
\date{September 2016}

\setmainfont[ExternalLocation=/path/to/fonts/]{"HelveticaLTStd-Roman.ttf"}

\newsavebox\mytext
\newcounter{mycount}
\newlength\clipsize

\newcommand\parabtext[5][0]{%
  \edef\neck{#3}% percent to depress the amplitude
  \def\cuts{#4}% Number of cuts
  \savebox{\mytext}{\kern.2pt#5\kern.2pt}% TEXT
  \FPeval{\myprod}{1/cuts}%
  \clipsize=\myprod\wd\mytext\relax%
  \setcounter{mycount}{0}%
  \whiledo{\value{mycount}<\cuts}{%
    \stepcounter{mycount}%
    \edef\NA{\themycount}%
    \edef\NB{\the\numexpr\cuts-\themycount\relax}%
    \FPeval{\myprod}{(\NA-.5)*(\NB+.5)*4/\cuts/\cuts}%
    \ifnum0#1=0\relax%
      \FPeval{\myprod}{1 - \neck*(\myprod)}%
    \else%
      \FPeval{\myprod}{1 - \neck*(1-\myprod)}%
    \fi%
    \clipbox{%
      \value{mycount}\clipsize-\clipsize\relax{} %
      -1pt %
      \wd\mytext-\value{mycount}\clipsize\relax{} %
      -1pt%
    }{\raisebox{#2\dimexpr\ht\mytext-\myprod\ht\mytext}{%
        \scalebox{1}[\myprod]{\usebox{\mytext}}}}%
  }%
}


\makeatletter
\ifdefined\XeTeXversion
  \def\@cliptoboxdim#1{%
    \setbox #1=\hbox{%
      \Gin@defaultbp\WIDTH{\wd #1}%
      \Gin@defaultbp \DEPTH {\dp #1}%
      \@tempdima \ht #1%
      \advance\@tempdima\dp#1%
      \Gin@defaultbp \TOTALHEIGHT {\@tempdima }%
      \special{pdf:literal q}% 
      \special{pdf:literal 0 -\DEPTH \space \WIDTH \space \TOTALHEIGHT \space re W n }%
      \rlap{\copy #1}%
      \special {pdf:literal Q}%
      \hskip\wd#1%
    }%
  }
\fi
\makeatother


\begin{document}
\begin{preview}
\begin{center}

\special{pdf:bcolor [0.0 0.0 0.0] }

\parabtext{0}{.7}{100}{\large TEST TEST TEST}

\end{center}
\end{preview}
\end{document}

This works well when I don't use a custom font, i.e. removing the \setmainfont line.

With a custom font the left side of the fonts are chopped off. Below is an example with Helvetica:

Example with Helvetica

Helvetica isn't so bad, but it gets worse with some other fonts like Chewy

Example with Chewy

Paul Gaborit
  • 70,770
  • 10
  • 176
  • 283

1 Answers1

1

Here, I try to lay out the issues at work. For my MWE, I only perform 10 vertical slices across the argument, since seeing the actual slices helps, I think, visualize the issue here.

The argument text is set in the \mytext savebox. By definition, the box is only as wide as the space allocated for the glyphs. Often (some fonts more than others), glyphs extend past the horizontal edges of their allocated boxes. In this case, the overhanging part of the glyph gets truncated.

The first line of my MWE shows this, where I have artificially made the kern buffer 1pt less than the actual width of the argument.

In my original answer from the other question, I added a small .2pt space buffer before and after the argument (\savebox{\mytext}{\kern.2pt#5\kern.2pt}), to try to avoid this truncation. For some fonts, the OP has found, that buffer is not enough. So, in my comments above, I proposed creating a length, here called \bufferzone that the user can set in a font-dependent way to add that space buffer. But there are two complications of this:

  1. The text gets shifted to the right by \bufferzone and has a \bufferzone dead space following it (this is shown in the 2nd and 3rd lines of output in my MWE, where \bufferzone has been set to 5pt and 50pt, respectively); and

  2. The buffer zone is also subject to slicing and dicing, and so thre resolution of the remaining slices are decreased as some slices are wasted on empty space.

The correction for item 1 above is to undo the bufferzone, before and after the slicing process, which I do with \bufferzonecorrection in my MWE. This is done for lines 4 and 5 of the output of my MWE. After one becomes convinced on the rightness of this approach, I recommend just replacing \bufferzonecorrection in my MWE with -\bufferzone.

Item 2 above is not fixable, but its effect can be minimized by selecting \bufferzone to the proper value for the selected font. As such, lines 4 and 5 of the ouput are not "optimized", since several slices are wasted on empty (but non-visible) space, and the result is significantly different from the line 1 output.

\documentclass[11pt]{article}

\usepackage{ifthen,trimclip,calc,fp,graphicx}
\usepackage[active, tightpage]{preview}
\usepackage[usenames,dvipsnames,svgnames,table]{xcolor}
%\usepackage{fontspec}
%\usepackage[document]{ragged2e}

\setlength\PreviewBorder{0.2pt}%

%\title{bidPress}
%\author{bidPress}
%\date{September 2016}

%\setmainfont[ExternalLocation=/path/to/fonts/]{"HelveticaLTStd-Roman.ttf"}

\newsavebox\mytext
\newcounter{mycount}
\newlength\clipsize
\newlength\bufferzone
\newlength\bufferzonecorrection
\bufferzone=.2pt\relax

\newcommand\parabtext[5][0]{%
  \edef\neck{#3}% percent to depress the amplitude
  \def\cuts{#4}% Number of cuts
  \savebox{\mytext}{\kern\bufferzone#5\kern\bufferzone}% TEXT
  \FPeval{\myprod}{1/cuts}%
  \clipsize=\myprod\wd\mytext\relax%
  \setcounter{mycount}{0}%
  \hspace{\bufferzonecorrection}% STEVEN SUGGESTS SETTING TO -\bufferzone
  \whiledo{\value{mycount}<\cuts}{%
    \stepcounter{mycount}%
    \edef\NA{\themycount}%
    \edef\NB{\the\numexpr\cuts-\themycount\relax}%
    \FPeval{\myprod}{(\NA-.5)*(\NB+.5)*4/\cuts/\cuts}%
    \ifnum0#1=0\relax%
      \FPeval{\myprod}{1 - \neck*(\myprod)}%
    \else%
      \FPeval{\myprod}{1 - \neck*(1-\myprod)}%
    \fi%
    \clipbox{%
      \value{mycount}\clipsize-\clipsize\relax{} %
      -1pt %
      \wd\mytext-\value{mycount}\clipsize\relax{} %
      -1pt%
    }{\raisebox{#2\dimexpr\ht\mytext-\myprod\ht\mytext}{%
        \scalebox{1}[\myprod]{\usebox{\mytext}}}}%
  }%
  \hspace{\bufferzonecorrection}% STEVEN SUGGESTS SETTING TO -\bufferzone
}


\makeatletter
\ifdefined\XeTeXversion
  \def\@cliptoboxdim#1{%
    \setbox #1=\hbox{%
      \Gin@defaultbp\WIDTH{\wd #1}%
      \Gin@defaultbp \DEPTH {\dp #1}%
      \@tempdima \ht #1%
      \advance\@tempdima\dp#1%
      \Gin@defaultbp \TOTALHEIGHT {\@tempdima }%
      \special{pdf:literal q}% 
      \special{pdf:literal 0 -\DEPTH \space \WIDTH \space \TOTALHEIGHT \space re W n }%
      \rlap{\copy #1}%
      \special {pdf:literal Q}%
      \hskip\wd#1%
    }%
  }
\fi
\makeatother
\begin{document}
\begin{preview}
\bufferzone=-1pt\relax%
\parabtext{0}{.7}{10}{\large TEST TEST TEST}\rule{5pt}{5pt}

\bufferzone=5pt\relax%
\parabtext{0}{.7}{10}{\large TEST TEST TEST}\rule{5pt}{5pt}

\bufferzone=50pt\relax%
\parabtext{0}{.7}{10}{\large TEST TEST TEST}\rule{5pt}{5pt}

\bufferzone=5pt\relax%
\bufferzonecorrection=-\bufferzone\relax
\parabtext{0}{.7}{10}{\large TEST TEST TEST}\rule{5pt}{5pt}

\bufferzone=50pt\relax%
\bufferzonecorrection=-\bufferzone\relax
\parabtext{0}{.7}{10}{\large TEST TEST TEST}\rule{5pt}{5pt}
\end{preview}
\end{document}

enter image description here