5

I am trying to use \psbarcode to generate a MECARD QR code with CJK characters in the name field.

tex:

\documentclass[12pt]{memoir}
\usepackage{CJKutf8}

\usepackage{pstricks}
\usepackage{pst-barcode}

\begin{document}

%\CJKfamily{goth}

\textbf{\begin{CJK}{UTF8}{min}トレバー・アレクサンダー\end{CJK}}\
\rule{75mm}{1mm}\\
\begin{minipage}[t]{30mm}
    \vspace{-1mm}%
    \begin{pspicture}(30mm,30mm)
        % The MECARD format is used to exchange contact information. More information at:
        % http://www.nttdocomo.co.jp/english/service/imode/make/content/barcode/function/application/addressbook/index.html
        \psbarcode{MECARD:N:トレバー・アレクサンダー;EMAIL:throwaway@mailinator.com;URL:http://www.whatsmyip.org;;}{eclevel=L width=1.181 height=1.181}{qrcode}
    \end{pspicture}
\end{minipage}
\end{document}

The above MECARD section does not work, but the CJK text earlier in the document does. Specifically, the error from pdflatex (called from Gummi) is:

This is pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012/Debian)
...
/home/trevor/Dropbox/.temp2.tex.swp:18: Undefined control sequence.
\GenericError  ...                                
                                                #4  \errhelp \@err@     ...
l.18 ...=L width=1.181 height=1.181 parse}{qrcode}

If you replace the name field with, say, N:Aso Taro; a QR code is properly generated. This related thread has a similar problem, but the asker's problem was within the ASCII set and the answerer suggested using the parse option in the psbarcode line, then specifying each character as an ASCII code value.

Is it possible to enter a UTF-8 code value instead? I tried the hexadecimal N:\x30C8; with parse in the options, but that didn't work either. I am fine with any way I can get CJK text into these fields.

edit: This is definitely accepted by MECARD itself, as seen in the NTTdocomo example here (newlines added for clarity):

MECARD:
N:ドコモ,太郎;
SOUND:ト゛コモタロウ;
TEL:03XXXXXXXX;
TEL:090XXXXXXXX;
EMAIL:docomotaro@△△.□□□.co.jp;
EMAIL:docomo.taro.△△@docomo.ne.jp;
3

Package pst-barcode needs a plain text string. UTF-8 is supported in 8-bit-TeX by active characters that contain code. The code can be anything, for example it chooses the character from the right position of the font that contains it. That additional stuff that is needed, if the string is typeset by TeX disturbs pst-barcode that only translates plain text strings to bar codes. Since your input encoding is already the right encoding (UTF-8), \detokenize can be used to convert the input string to a text string without active characters:

\documentclass[12pt]{memoir}
\usepackage{CJKutf8}

\usepackage{pstricks}
\usepackage{pst-barcode}

\begin{document}

%\CJKfamily{goth}

\textbf{\begin{CJK}{UTF8}{min}トレバー・アレクサンダー\end{CJK}}\\

\rule{75mm}{1mm}\\
\begin{minipage}[t]{30mm}
    \vspace{-1mm}%
    \begin{pspicture}(30mm,30mm)
        % The MECARD format is used to exchange contact information. More information at:
        % http://www.nttdocomo.co.jp/english/service/imode/make/content/barcode/function/application/addressbook/index.html
        \psbarcode{\detokenize{MECARD:N:トレバー・アレクサンダー;EMAIL:throwaway@mailinator.com;URL:http://www.whatsmyip.org;;}}{eclevel=L width=1.181 height=1.181}{qrcode}
    \end{pspicture}
\end{minipage}
\end{document}

Result

BTW, if the string contains ~ (e.g. in the URL), then this is usually also an active character. It gets converted to \protect \unhbox \voidb@x \penalty \@M \ {}. This happens also with XeTeX or LuaTeX. \detokenize{~} or \string~ solves this, because both constructs convert the active character ~ to an unexpandable character.

Fix for bug in pst-barcode.tex

Package pst-barcode puts the expanded string into a postscript string surrounded by parentheses. Thus an unmatched opening or closing parentheses breaks the PostScript code. And inside the parentheses form of a PostScript string, the backslash is an escape character. The following fix uses \pdfescapestring if available (pdfTeX both modes PDF and DVI) and uses package pdfescape otherwise that can also be used with iniTeX without e-TeX extensions. In both cases the string is converted to a valid PostScript string by escaping problematic characters.

\usepackage{pst-barcode}

\makeatletter
\@ifundefined{pdfescapestring}{%
  \usepackage{pdfescape}% LaTeX
  % \input pdfescape.sty\relax % plain TeX
  \newcommand*{\psbarcode@escape}[1]{%
    \EdefEscapeString\psbarcode@string{#1}%
  }%
}{%
  \newcommand*{\psbarcode@escape}[1]{%
    \edef\psbarcode@string{\pdfescapestring{#1}}%
  }%
}
\def\psbarcode@i#1#2#3{%
  \begin@SpecialObj
  \psbarcode@escape{#1}%
  \addto@pscode{
    gsave
    \psk@barcode@rotate\space
    \psk@barcode@scalex\space \psk@barcode@scaley\space
    \psk@barcode@transx\space \psk@barcode@transy\space
    translate scale rotate
    0 0 moveto (\psbarcode@string) (#2) /#3 /uk.co.terryburton.bwipp findresou
    grestore
  }%
  \end@SpecialObj%
  \ignorespaces%
}
\makeatother
  • Hey, I recognize your name from LaTeX compliation messages :) Thank you so much for the extensive answer; I'm still trying to process it all. Your solution definitely works best for me here. One thing I noticed: the QR code you generated up there contains the literal MECARD string and is not interpreted as an address book, but inserting detokenize worked as you described and produced a MECARD QR code. – bright-star May 23 '13 at 20:53
  • 1
    @TrevorAlexander The wrong QR code image comes from a test version, where I had put an unmatched parentheses to test the patch at the end. Fixed now. – Heiko Oberdiek May 23 '13 at 22:23
2

run your document with xelatex and it will work.

enter image description here

  • You're right, it does! But then the top CJK line of regular text does not: `\textbf{\begin{CJK}{UTF8}{min}トレバー・アレクサンダー\end{CJK}}\` – bright-star May 23 '13 at 7:39
  • 1
    with xelatex you do not need the cjk package. you can simply use japanese as usual. – user2478 May 23 '13 at 9:38

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.