%% This is part of OpTeX project, see http://petr.olsak.net/optex \_codedecl \pdfunidef {PDFunicode strings for outlines <2020-03-12>} % preloaded in format \_edef\_octalprint#1#2{\_noexpand\_directlua{% #1=character-code #2=character if ('#2'>='A' and '#2'<='Z') or ('#2'>='a' and '#2'<='z') then tex.print(string.format('000\_pcent s',"#2")) else local num=#1\_pcent256 tex.print(string.format('\_pcent 03o\_nbb\_pcent03o',(#1-num)/256,num)) end }} \_def\_pdfunidef#1#2{% \_begingroup \_catcode`\\=12 \_let\\=\_bslash \_the\_regoul \_relax % \_regmacro alternatives of logos etc. \_escapechar=-1 \_edef#1{#2\empty}% \_escapechar=`\\ \_ea\_edef \_ea#1\_ea{\_ea\_removeoutmath #1$\_end$}% $x$ -> x \_ea\_edef \_ea#1\_ea{\_ea\_removeoutbraces #1{\_end}}% {x} -> x \_edef#1{\_detokenize\_ea{#1}}% \_replstring#1{ }{{ }}% text text -> text{ }text \_edef\_out{\\376\\377}% \_ea\_pdfunidefB#1^% text -> \_out in octal \_ea \_endgroup \_ea\_def\_ea#1\_ea{\_out} } \_def\_pdfunidefB#1{% \_ifx^#1\_else \_tmpnum=`#1 \_pdfunidefC{\_luaescapestring{#1}}% \_ea\_pdfunidefB \_fi } \_def\_pdfunidefC #1{\_edef\_out{\_out \\\_ea\_octalprint\_ea{\_the\_tmpnum}{#1}}} \_def\_removeoutbraces #1#{#1\_removeoutbracesA} \_def\_removeoutbracesA #1{\_ifx\_end#1\_else #1\_ea\_removeoutbraces\_fi} \_def\_removeoutmath #1$#2${#1\_ifx\_end#2\_else #2\_ea\_removeoutmath\_fi} \_regmacro {}{}{\_let\em=\_empty \_let\rm=\_empty \_let\bf=\_empty \_let\it=\_empty \_let\bi=\_empty \_let\tt=\_empty \_let\/=\_empty \_let~=\_space } \public \pdfunidef ; \_endcode % -------------------------------- There are only two encodings for PDF strings (used in PDFoutlines, PDFinfo etc.). First one is PDFDocEncoding which is one-byte encoding, but most Czech or Slovak characters are missing here. The second encoding is PDFunicode encoding wich is implemented in this file. This encoding is \TeX/-discomfortable, because it looks like \begtt \376\377\000C\000v\000i\001\015\000e\000n\000\355\000\040\000j\000e\000\040 \000z\000\341\000t\001\033\001\176 \endtt This example is real encoding of the string "Cvičení je zátěž". You can see that this is UTF-16 encoding (two bytes per character) with two starting bytes FEFF. Moreover, each byte is encoded by three octal digits preceded by backslash. The only exception is the visible ASCII character encoding: such a character is encoded by its real byte preceded by `\000`. The command \`\pdfunidef``\macro{string}` is implemented here using `\directlua`. The input string is preprocessed: detokenized, converted `\word /` to `\word/` (used in logos) preprocessed spaces using \^`\replstring` and then the \`\_pdfunidefB` is repeated on each character. It calls the `\directlua` chunk to print octal numbers in the macro `\_octalprint`. The \^`\regmacro` is used in order to sed the values of macros `\em`, `\rm`, `\bf`, `\it`, `\bi`, `\tt`, `\/` and `~` to values usable in PDF outlines.