1

I am trying to replace the glue space with a stretched version of a glyph in Xetex, using Xetexinterchartoks. Below is a sample:

\documentclass[10pt,a4paper]{article}
\usepackage{graphicx}
\newcommand \stretchit{
    \makeatletter   
    \XeTeXinterchartokenstate 1%
    \newXeTeXintercharclass \mycharclassA%
    \newXeTeXintercharclass \mycharclassB%
    \XeTeXcharclass `\A \mycharclassA
    \XeTeXcharclass `\B \mycharclassB   
    \chardef\mylinechar=`= %
    \def\mystretchedchar{%
    \nobreak%
    \leavevmode%
        %MainScenario 
        %\dimen0=\XeTeXglyphbounds2 \the\XeTeXcharglyph\mylinechar%"0640%
        %\dimen1=\XeTeXglyphbounds4 \the\XeTeXcharglyph\mylinechar%"0640
        %\leaders\hrule height \dimen0 depth \dimen1 \hskip 0pt plus 05.em%
        %Alternative Scenario #1 
        \hskip 0pt plus 05.em %
        \dimen0=\lastskip%
        \unskip   
        \typeout{DIMEN2= \the\dimen0***and last skip=\the\lastskip }%
        %Alternative Scenario #2
        \setbox0=\hbox{\leaders\hrule height \dimen0 depth \dimen1 \hskip 0pt plus 05.em} %testing: hfil,   
        \dimen0=\wd0%      
        %The actual drawing
        \typeout{DIMEN2= \the\dimen0***and last skip=\the\lastskip }%
        \resizebox{\dimen0}{\height}{\mylinechar}% this: \clipbox{0pt}{\mylinechar} might clip some strange whitespaces around the glyph
    \makeatother
    }
    \XeTeXinterchartoks \mycharclassA \mycharclassB = {\mystretchedchar}

}
\begin{document}
\stretchit{}
Test test test testABTest test test testTestTesttesttest testTest test test test test test test
\end{document}

But the width of glue is always reported zero, while of course it is not zero in the output. I guess that might be due to the stage that I calculate glue width when it is still zero.

It is possible to fill the space with \hrule with a number of characters (or a line as in the MainScenario) but what I want is the stretched version of a glyph.

PS: Actually what I need to fill in the gap with is a glyph (Kashida) that looks the same as a horizontal line, the MainScenario draw a line as a substitute but then there would be dents in junction of this ruler/line with other glyphs. I noticed that the stretched glyph does not have this problem (probably due to font hinting things). That is why I want to find a solution for stretching the glyph as much as the glue.

Thanks

  • 1
    unrelated but beware % at ends of lines, you have lots of unneeded ones but m} % will add a space as it is not immediately after the } – David Carlisle Mar 3 '17 at 14:57
  • 1
    Your question isn't totally clear but I suspect you want \skip0=\lastskip not \dimen0=\lastskip as if you put a skip into a dimen register you lose the plus and minus components. – David Carlisle Mar 3 '17 at 15:03
  • @DavidCarlisle, not actually. I simply wanted to find out how much the glue was stretched (finally fixed) so can fill in that space (as you did in you answer) with a stretched character. Also, thanks for educating about % – Shahryar Mar 3 '17 at 19:42
2

You need to measure the stretched width after the paragraph has been broken into lines, not at the point the chardef tokens are inserted. This means that you need two runs of latex to make it work.

enter image description here

\documentclass[10pt,a4paper]{article}
\usepackage{graphicx}

\makeatletter   %would do nothing inside `\newcommand`
\newcount\zzcount
% don't do new... allocations inside another macro
    \newXeTeXintercharclass \mycharclassA%
    \newXeTeXintercharclass \mycharclassB%
    \XeTeXcharclass `\A \mycharclassA
    \XeTeXcharclass `\B \mycharclassB   
    \chardef\mylinechar=`= %
    \def\mystretchedchar{%
    \leavevmode
    \global\advance\zzcount\@ne
     \pdfsavepos
     \edef\tmp{\write\@auxout{\gdef\expandafter\string\csname TESTA\romannumeral\zzcount\endcsname{\noexpand\the\pdflastxpos}}}%
     \tmp
     \hspace{0pt plus 5em}%
     \pdfsavepos
     \edef\tmp{\write\@auxout{\gdef\expandafter\string\csname TESTB\romannumeral\zzcount\endcsname{\noexpand\the\pdflastxpos}}}%
     \tmp
     \expandafter\ifx\csname TESTA\romannumeral\zzcount\endcsname\relax\else
     \llap{\resizebox{\dimexpr
\csname TESTA\romannumeral\zzcount\endcsname sp - 
\csname TESTB\romannumeral\zzcount\endcsname sp
\relax}{\height}{\mylinechar}}%
     \fi
    }
    \makeatother

\newcommand \stretchit{%%%%
    \XeTeXinterchartokenstate 1 %%% leave space after 1
    \XeTeXinterchartoks \mycharclassA \mycharclassB = {\mystretchedchar}%%%
}
\begin{document}
\stretchit{}
Test test test testABTest test test testTestTesttesttest testTest test test test test test test

zz Test test test testABTest test test testTestTesttesttest testTest test test test test test test zzzz zzzz 

zzzz Test test test testABTest test test testTestTesttesttest testTest test test test test test test zzzz zzzz zzzz zzzz zzzz zzzz 


\end{document}
  • Many thanks! It works quite nice in left-to-right and one case situation. However, I wonder if you can suggest how I can use it for many cases situation? As you mentioned "new command name for each time", (probably that is why with more than one case it fails with the above solution, TESTA and TESTB become same). But I have no idea how to implement it , regarding that I want to put that between all two adjacent characters in the document (that is how Kashida works in Persian/Arabic/Urdu) Also, the above solution does not work in BiDi in \setRL mode. TESTA becomes zero in aux. Any idea? – Shahryar Mar 3 '17 at 19:38
  • 1
    @Shahryar I extended with a counter that makes a new name each time (look in the aux file to see the names), it should work in a RTL context I think although you may need to do the subtraction in the other order. – David Carlisle Mar 3 '17 at 21:08
  • Fantastic! The behavior in RTL is a little bit strange. In the aux TESTB comes before TESTA! and the first value is zero: \gdef \TESTBi{0} \gdef \TESTAi{24259131}. The output of the first run and subsequent runs is also different. I would try to play with this today. If I come to a solution I would edit my post to reflect it. Otherwise I think I should post a new question because the above one is not related to this problem. Thanks for providing the two solutions and two steps ahead. – Shahryar Mar 4 '17 at 10:40

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.