2

I am trying to create a general macro that prints a particular custom character, based on an answer to a previous question of mine. Here is a minimal (non-)working example:

%!TEX encoding = UTF-8 Unicode
%!TEX TS-program = xelatex

\documentclass{standalone}
\usepackage[xetex]{accsupp}
\usepackage{xkeyval}
\usepackage[xetex]{xcolor}
\usepackage{xxcolor,tikz,pagecolor}
\usetikzlibrary{calc}
\makeatletter
\newcommand{\SS@xX@draw@val}{.}% default: the current text color
\define@key[SS]{xX}{draw}{\renewcommand{\SS@xX@draw@val}{#1}}
\newcommand{\SS@xX@fill@val}{\thepagecolor}% default: the current page color
\define@key[SS]{xX}{fill}{\renewcommand{\SS@xX@fill@val}{#1}}
\newcommand{\SS@xX@thickness@val}{0.125ex}
\define@key[SS]{xX}{thickness}{\renewcommand{\SS@xX@thickness@val}{#1}}
\newcommand{\SS@xX@shift@val}{(0ex,0ex)}
\define@key[SS]{xX}{shift}{\renewcommand{\SS@xX@shift@val}{#1}}
\newcommand{\SS@x@size@val}{0.25ex}
\define@key[SS]{x}{size}{\renewcommand{\SS@x@size@val}{#1}}
\newcommand*\x[1][]{\BeginAccSupp{method=escape,unicode,ActualText={x⃘}}%
\begin{tikzpicture}\setkeys[SS]{xX,x}{#1}
\node[inner sep=0pt,outer sep=0pt] (letter) {x};
\draw[line width=\SS@xX@thickness@val,\SS@xX@draw@val,fill=\SS@xX@fill@val] let \p{shift} = {\SS@xX@shift@val} in ($ (letter.center) + \p{shift} $) circle (\SS@x@size@val);
\end{tikzpicture}%
\EndAccSupp{}\ignorespaces}
\newcommand{\SS@X@size@val}{0.35ex}
\define@key[SS]{X}{size}{\renewcommand{\SS@X@size@val}{#1}}
\newcommand*\X[1][]{\BeginAccSupp{method=escape,unicode,ActualText={X⃘}}%
\begin{tikzpicture}\setkeys[SS]{xX,X}{#1}
\node[inner sep=0pt,outer sep=0pt] (letter) {X};
\draw[line width=\SS@xX@thickness@val,\SS@xX@draw@val,fill=\SS@xX@fill@val] let \p{shift} = {\SS@xX@shift@val} in ($ (letter.center) + \p{shift} $) circle (\SS@X@size@val);
\end{tikzpicture}%
\EndAccSupp{}\ignorespaces}
\makeatother

\begin{document}
\x\X
\end{document}

This currently fails with the error “Package tikz Error: Cannot Parse this coordinate.

From playing around with the tikzpictures, I've determined that the problem is the usage of \SS@xX@shift@val, but I have no idea how to fix it. Is there a way to get it to do what I want? (Everything else works perfectly if \SS@xX@shift@val and its usage is removed.)

EDIT: Added MWE.

  • 4
    Of course it won't compile. You have no \documentclass and you don't load packages you need or finish with \end{document}. A minimal example should either compile or produce the error you want help with. That code will not produce the error you are asking about, hence it is not possible to help you resolve the error without having to guess what is required to produce it. Guessing is a waste of time when you know and can easily remedy our ignorance. Please help us to help you by telling us. – cfr Oct 7 '15 at 1:41
  • @cfr I've changed over to an MWE; is this answerable now? – Ptharien's Flame Oct 7 '15 at 2:18
  • 2
    Wouldn't it be easier to use PGF's keys here? Aren't you passing a single value when setting both the shift and the size? But the shift is supposed to be of the form (thing,thing) and not merely thing, isn't it? Note that defining single letter commands is a Very Bad Idea. – cfr Oct 7 '15 at 2:42
  • 2
    You're misunderstanding how xkeyval works. The empty default of the optional parameter simply fails to execute any of the provided key-setting code, so the defaults remain in place. – Ptharien's Flame Oct 7 '15 at 3:39
  • 1
    Hence the 'Unless...'. – cfr Oct 7 '15 at 15:31
3

It is a combination of two things first the braces around the macro \SS@xX@shift@val is causing TikZ not to expand before parsing the coordinate and also \p{...} does not expand to a literal (x,y) type of syntax but rather redefines \pgf@x,\pgf@y macros. Hence you can fix the code as follows (truncating the irrelevant parts:

let \p{shift} = \SS@xX@shift@val in ($ (letter.center) + (\x{shift},\y{shift}) $) circle (\SS@x@size@val);

But this is still a bit convoluted because TikZ already has a direct shift syntax in the form of

([shift={(xshift,yshift)}]x,y)

The braces are there to hide the parentheses from the parser but since you have it inside the macro you again don't need them. Hence you can skip the calc part and use the following

\documentclass{standalone}
\usepackage{accsupp}
\usepackage{xkeyval}
\usepackage{xcolor}
\usepackage{xxcolor,tikz,pagecolor}
%\usetikzlibrary{calc}
\makeatletter
\newcommand{\SS@xX@draw@val}{.}% default: the current text color
\define@key[SS]{xX}{draw}{\renewcommand{\SS@xX@draw@val}{#1}}
\newcommand{\SS@xX@fill@val}{\thepagecolor}% default: the current page color
\define@key[SS]{xX}{fill}{\renewcommand{\SS@xX@fill@val}{#1}}
\newcommand{\SS@xX@thickness@val}{0.125ex}
\define@key[SS]{xX}{thickness}{\renewcommand{\SS@xX@thickness@val}{#1}}
\newcommand{\SS@xX@shift@val}{(0ex,0ex)}
\define@key[SS]{xX}{shift}{\renewcommand{\SS@xX@shift@val}{#1}}
\newcommand{\SS@x@size@val}{0.25ex}
\define@key[SS]{x}{size}{\renewcommand{\SS@x@size@val}{#1}}
\newcommand*\x[1][]{\BeginAccSupp{method=escape,unicode,ActualText={x⃘}}%
\begin{tikzpicture}\setkeys[SS]{xX,x}{#1}
\node[inner sep=0pt,outer sep=0pt] (letter) {x};
\draw[line width=\SS@xX@thickness@val,\SS@xX@draw@val,fill=\SS@xX@fill@val] ([shift=\SS@xX@shift@val]letter.center) circle (\SS@x@size@val);
\end{tikzpicture}%
\EndAccSupp{}\ignorespaces}
\newcommand{\SS@X@size@val}{0.35ex}
\define@key[SS]{X}{size}{\renewcommand{\SS@X@size@val}{#1}}
\newcommand*\X[1][]{\BeginAccSupp{method=escape,unicode,ActualText={X⃘}}%
\begin{tikzpicture}\setkeys[SS]{xX,X}{#1}
\node[inner sep=0pt,outer sep=0pt] (letter) {X};
\draw[line width=\SS@xX@thickness@val,\SS@xX@draw@val,fill=\SS@xX@fill@val] ([shift=\SS@xX@shift@val]letter.center) circle (\SS@x@size@val);
\end{tikzpicture}%
\EndAccSupp{}\ignorespaces}
\makeatother

\begin{document}
\x\X
\end{document}

enter image description here

Also note that packages, almost all, can discover the engine that is being used so you don't need [xetex] options.

Finally, this is much easier and structured with pgfkeys which you might consider switching to.

  • Thank you! This is exactly the kind of answer I was hoping for. I learned a little bit more about tikz today! :) – Ptharien's Flame Oct 7 '15 at 14:34
  • 1
    @Ptharien'sFlame My pleasure – percusse Oct 7 '15 at 17:16

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.