% \iffalse % File: qrcodetikz.dtx % Copyright (C) 2025 Miguel V. S. Frasson (mvsfrasson@gmail.com) % % This package may be distributed under the terms of the LaTeX % Project Public License, as described in lppl.txt in the base % LaTeX distribution, either version 1.3 or (at your option) % any later version. % %<*driver> \documentclass{ltxdoc} \usepackage{hyperref} \hypersetup{ colorlinks, linkcolor={blue!50!black}, citecolor={black}, urlcolor={black} } \usepackage{doc,amsmath,enumitem,mathabx,array,booktabs,wasysym} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{microtype} \usepackage[nolinks]{qrcodetikz} \usepackage{tikz} \usetikzlibrary{arrows,arrows.meta} \makeatletter \newcommand{\nDescribeMacro}[1]{% \xa\xa\xa\DescribeMacro\xa\csname\xa\@gobble\string#1\endcsname\ignorespaces}% \makeatother \begin{document} \DocInput{qrcodetikz.dtx} \end{document} % % \fi % % \def\exclamacao{!} % \MakeShortVerb\! % \def\vars#1{\textlangle\textit{#1}\textrangle} % \def\markpage#1{\refstepcounter{enumiv}\label{#1}} % % \title{\textbf{qrcodetikz}: prettier \textsc{qr} codes} % \author{Miguel Vinícius Santini Frasson\\ \texttt{mvsfrasson@gmail.com}} % \date{2025--05--28, version 1.0} % % \noindent % \raisebox{-4mm}{% % \qrcode[link,height=1in]{https://ctan.org/pkg/qrcodetikz}}\qquad % \begin{minipage}[c]{0.65\linewidth} % \maketitle % \end{minipage} % % \tableofcontents % % \section{Introduction} % % The package \href{https://ctan.org/pkg/qrcodetikz}{\texttt{qrcodetikz}} % aims to improve the display of QR codes provided by package % \href{https://ctan.org/pkg/qrcode}{\texttt{qrcode}}. % % \begin{center} % \begin{tabular}{l@{\qquad}c@{\qquad}l} % {\qrcodetikzOff\qrcode[height=2cm]{QR codes}} & vs. % & \qrcodetikzOn\qrcode[height=2cm]{QR codes}\\[0.35in] % with \texttt{qrcode} & & % with \texttt{qrcodetikz} % \end{tabular} % \end{center} % % The Quick Response (QR) codes provided by package \texttt{qrcode} % show white borders on each square (from little to very proeminent % depending on pdf viewer). This is because the QR code is printed % square by square, not the connected regions of squares as such, and % pdf screen viewers show these undesired square borders. % % This package overwrites the \texttt{qrcode} printing functions to % fill connected regions of the QR code using Ti\textit{k}Z, allowing % prettier qrcodes on screen visualization, with possibility of % customization. % % \section{Usage} % % To switch the display of QR codes with Ti\textit{k}Z, just load % package \texttt{qrcodetikz} instead of \texttt{qrcode}. The package % options are the same of \texttt{qrcode} package\footnote{All options % are passed to \texttt{qrcode} package.}, that we repeat briefly (for % details, see \texttt{qrcode} documentation): % \begin{description} % \item[nolinks] disable qrcode links if \texttt{hyperref} is loaded. % \item[draft] doesn't compute QR codes, dummy QR codes are % displayed, like % \raisebox{\depth}[0pt]{\qrcode[draft,version=2,height=1.5cm]{ABCD}} % % \item[final] opposite to draft, display complete QR codes. % \item[forget] do not store QR codes into \texttt{.aux} for reusage, % recompute them in every run (mainly for debug purposes). % \end{description} % % You can set other options using % \texttt{\string\qruse\{\textit{\vars{options}}\}}, which can be set % as options to !\qrcode! command. These options are: % \begin{description} % \item[height=\vars{dimension}] sets the height (and width) of the QR % codes. Default is 2~cm;. % \item[level=\vars{L-M-Q-H}] sets the level of error correction; the % levels are set with one letter: \texttt{L} (low), \texttt{M} (medium), % \texttt{Q} (quality) and \texttt{H} (high). Default is \texttt{M}. % \item[version=\vars{1-to-40}] is related to the size if the QR code. % Must be a number between 1 and 40. Default is the lowest version % that encodes text with desired quality. % \item[padding, tight] QR code specification says that a QR code should be % surrounded by some white space (specifically the width of 4 % modules). With \texttt{padding}, this white border is added. With % \texttt{tight}, this white border is omitted, since it is usually % provided by the user. Defult to \texttt{tight}. % \item[link, nolink] Allows/disallows use of clickable links with the % QR code. % \end{description} % % For many more details, like special characters, please refer to the % documentation of \texttt{qrcode} package. % % \subsection{Fill options} % % \DescribeMacro{\qrcodeFillOptions} % The default plain QR codes are fine and recommended. However, with % \texttt{qrcodetikz}, the user can pass fill options !\fill! command % to display the QR codes, like colors, rounded corners, shades, % etc. using % \begin{center} % \texttt{\string\qrcodeFillOptions\{\vars{fill-options}\}} % \end{center} % The settings persist until the next call of !\qrcodeFillOptions! % (for example, a call of !\qrcodeFillOptions{}! erases previous % customizations). As an example:\medskip % % \DeleteShortVerb\|\DeleteShortVerb\!\MakeShortVerb\+ % \noindent % +\begin{center}+\\ % + +\texttt{\textit{\% rounded corners}}\\ % + \qrcodeFillOptions{rounded corners=1pt}+\\ % + \qrcode{QR codes}\qquad+\\ % + +\texttt{\textit{\% shades}}\\ % + \qrcodeFillOptions{left color=gray,right color=black,draw=black,thin}+\\ % + \qrcode{QR codes}\qquad+\\ % + +\texttt{\textit{\% removing customization}}\\ % + \qrcodeFillOptions{}+\\ % + \qrcode{QR codes}+\\ % +\end{center}+\DeleteShortVerb\+\MakeShortVerb\! % % \noindent would print: % % \begin{center} % \qrcodeFillOptions{rounded corners=1pt} % \qrcode{QR codes}\qquad % \qrcodeFillOptions{left color=gray,right color=black,draw=black,thin} % \qrcode{QR codes}\qquad % \qrcodeFillOptions{} % \qrcode{QR codes}\refstepcounter{enumiv}\label{qrcode-bug} % \end{center} % % Notice that last qrcode was printed plain, without customizations. % % In our humble opinion, plain QR codes are prettier. The % implementation made an effort to produce good looking QR codes with % fill option !rounded corners!, filling individual connected % components of the QR code to avoid straight corners. Other % customizations with fill options are left for the convenience of the % user.\medskip % % \DescribeMacro{\qrcodetikzOn}\DescribeMacro{\qrcodetikzOff} % One can turn on and off QRcodes with Ti\textit{k}Z with commands % \texttt{\string\qrcodetikzOn} and \texttt{\string\qrcodetikzOff}. % When turned off, original \texttt{qrcode} functions for printing are % restored. These functions probably will never be used outside this % manual \smiley. % % This package was not intended specifically to display artistic QR % codes. For that you can take a look into % \href{https://ctan.org/pkg/fancyqr}{\texttt{fancyqr}} package. % % For the regular user, the documentation ends here. In the following % pages we give details of the implementation. % % \section{Implementation} % % \subsection{Ideas and conventions} % % Using the \texttt{qrcode} package, that saves computed QR codes into % the \texttt{.aux} file, if one calls !\qrcode{QrCode}!, we get into % the \texttt{.aux} file the line below (as a long line without % linebreaks):\medskip % % \noindent\texttt{\small\string\qr@savematrix\{QrCode\}\{1\}\{2\}\{\relax % 1111111010000011111111000001000100010000011011\\ % 101010000010111011011101000100010111011011101010101010111011000001001010010\\ % 000011111111010101011111110000000011000000000000000011001011010101011011100\\ % 111100110101100000111000100010100100101100010111010111101011001110010010011\\ % 110000000011110110001101111111000001111010101000001010100001111001011101000\\ % 010100000101011101001011110110001011101001001010100111000001000001110011001\\ % 11111100000101000010\}}\medskip % % Counting the 0's and 1's, we get $441=21^2$ “bits”. Dividing the string into % 21 lines of 21 bits, coloring 1's as black boxes and 0's as light boxes % to ease visualization we get:\medskip % % \begin{center} % \scalebox{0.7}{\begin{minipage}[c]{0.606\linewidth} % \footnotesize % \def\1{\colorbox{black}{\textcolor{white}{1}}}\relax % \def\0{\colorbox{white}{\textcolor{black}{0}}}\ttfamily % \1\1\1\1\1\1\1\0\1\0\0\0\0\0\1\1\1\1\1\1\1\\ % \1\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0\0\1\\ % \1\0\1\1\1\0\1\0\1\0\0\0\0\0\1\0\1\1\1\0\1\\ % \1\0\1\1\1\0\1\0\0\0\1\0\0\0\1\0\1\1\1\0\1\\ % \1\0\1\1\1\0\1\0\1\0\1\0\1\0\1\0\1\1\1\0\1\\ % \1\0\0\0\0\0\1\0\0\1\0\1\0\0\1\0\0\0\0\0\1\\ % \1\1\1\1\1\1\1\0\1\0\1\0\1\0\1\1\1\1\1\1\1\\ % \0\0\0\0\0\0\0\0\1\1\0\0\0\0\0\0\0\0\0\0\0\\ % \0\0\0\0\0\1\1\0\0\1\0\1\1\0\1\0\1\0\1\0\1\\ % \1\0\1\1\1\0\0\1\1\1\1\0\0\1\1\0\1\0\1\1\0\\ % \0\0\0\0\1\1\1\0\0\0\1\0\0\0\1\0\1\0\0\1\0\\ % \0\1\0\1\1\0\0\0\1\0\1\1\1\0\1\0\1\1\1\1\0\\ % \1\0\1\1\0\0\1\1\1\0\0\1\0\0\1\0\0\1\1\1\1\\ % \0\0\0\0\0\0\0\0\1\1\1\1\0\1\1\0\0\0\1\1\0\\ % \1\1\1\1\1\1\1\0\0\0\0\0\1\1\1\1\0\1\0\1\0\\ % \1\0\0\0\0\0\1\0\1\0\1\0\0\0\0\1\1\1\1\0\0\\ % \1\0\1\1\1\0\1\0\0\0\0\1\0\1\0\0\0\0\0\1\0\\ % \1\0\1\1\1\0\1\0\0\1\0\1\1\1\1\0\1\1\0\0\0\\ % \1\0\1\1\1\0\1\0\0\1\0\0\1\0\1\0\1\0\0\1\1\\ % \1\0\0\0\0\0\1\0\0\0\0\0\1\1\1\0\0\1\1\0\0\\ % \1\1\1\1\1\1\1\0\0\0\0\0\1\0\1\0\0\0\0\1\0 % \end{minipage}}\qquad % \begin{tabular}{c} % {\qrcodetikzOff\qrcode[height=5cm]{QrCode}}\\[2.7cm] % (printed with \texttt{qrcode}) % \end{tabular} % % \mbox{} % \end{center} % % So one sees that the binary data must be printed in rows from left % to right, from top to bottom. On the right of the picture above it % is the QR code as printed with the \texttt{qrcode} package: it % prints individual black squares for each 1 and equivalent space for % 0. An unpleasant side effect are the visible thin borders of squares % when pdf file is visualized on screen. This package is meant to fix % this, printing regions as a whole with Ti\textit{k}Z. % % We observed that if we make a path connecting all connected borders % of the pixels, and fill this path with the “even-odd % rule”\,\footnote{The SVG defines the even-odd rule by saying: “This % rule determines the ‘insideness’ of a point on the canvas by drawing % a ray from that point to infinity in any direction and counting the % number of path segments from the given shape that the ray % crosses. If this number is odd, the point is inside; if even, the % point is outside.” % (\href{https://en.wikipedia.org/wiki/Even–odd_rule}{\relax % \texttt{https://en.wikipedia.org/wiki/Even–odd\_rule}}).}, it would % beautifully print the QRcode. % % \begin{center} % \begin{tikzpicture}[scale=1.5] % \draw (0,0) rectangle (0.7,0.7) (0.1,0.1) rectangle (0.6,0.6) % (0.2,0.2) rectangle (0.5,0.5); % \draw[>=stealth',->] (1,0.35) -- ++(0.7,0); % \fill[even odd rule,xshift=2.1cm] (0,0) rectangle % (0.7,0.7) (0.1,0.1) rectangle (0.6,0.6) (0.2,0.2) rectangle % (0.5,0.5); % \end{tikzpicture}\medskip % % Fill with even-odd rule. % \end{center} % % This package is the implementation of such idea. We took advantage % of facilities from \LaTeX3 such as loops, sequences (lists), arrays % of integers, property lists, easy integer computations and other % goodies already loaded into the \LaTeX\ kernel in every run in any % recent \TeX\ distribution. The only external packages needed are % \texttt{qrcode} (to compute the qrcode) and \texttt{tikz} (to fill a % path in even-odd rule). % % If any other package wants to take advance of the conversion (binary % data) $\leftrightarrow$ (Ti\textit{k}Z path), for artistic % reasons for instance, could use\\ % ! \QRTZgetTikzPathMaybeSaved!\texttt{\{\vars{binary data}\}\{\vars{cmd to store path}\}}\\ % explained in section~\ref{sec:prop}, that tries to reuse computed % paths or computes it otherwise. The first argument is expanded, so % it can be a command that holds the binary data. % % In QRcode jargon, the size in number of squares of the QR code is % given by its \textit{version}. This size is % $4 \times \text{\vars{qrcode version}} + 17$. The maximum version % os 40, so the maximum size is $4\times40+17 = 177$. We take advance % of integer arrays in \LaTeX3 (module \textsf{l3intarray}) that % provide fast access to any integer in the array and store all % matrices $n\times n$ as linear sequence of $n^2$ integers, in the % order as the binary data. % % As Ti\textit{k}Z uses cartesian coordinates, we decided to use them % as the coordinates of the pixels. We implement the conversion from % $(x,y)$ coordiante, with $x$ and $y$ from $1$ to $n$, to sequence % index from $1$ to $n^2$ so that % \begin{itemize}[itemsep=0pt,parsep=0pt] % \item pixel $(1,n)$ – top left – is in index $1$; % \item pixel $(n,n)$ – top right – is in index $n$; % \item pixel $(n,n)$ – bottom right – is in index $n^2$; % \item pixel $(1,1)$ – bottom left – is in index $(n-1)n + 1$. % \end{itemize} % Doing the math, index is $(n-y)n + x$.\medskip % % We need to put a convention to the coodinates of the corners. We % define that a pixel $(x,y)$ gives its coordinates to the bottom-left % corner. The coordinates of the lines vary from 1 to $n+1$. This % way, the size of the smallest line segment is 1 and the size of a QR % code is a square of size $n$, so the path must be scaled down to fit % the required size of the QR code. % % With these conventions, we can begin implementation according the % following steps: % % \begin{enumerate} % \item We store the binary matrix into a array of integers; we use % intarrays from \LaTeX3 to get fast read/write access. The % interface $(x,y) \leftrightarrow i$ (array index) is explained in % section~\ref{sec:matrix}. At this point, every pixel is stored as % values 0 (for empty) or 1 (for black). % \item We compute the connected components of the QR code using % “find/union” operations, a fast algorithm, explained in % section~\ref{sec:cc}. The content of the pixel will be 0 (for % empty) or a positive integer that labels the connected component, % shared by all pixels in that same connected component. A positive % value will be printed as black. % \item We build a list of all borders of pixels. We have to fix % notation for a border: after some reimplementations\footnote{After % first successful implementation, we realized that \texttt{rounded % corners} fill option produced ugly straight crossings so we % decided to implement connected components and follow the path % always inward in a crossing with multiple ways. A natural choice % as to walk the borders in “positive” sense according to Calculus % rules, that is, interior is always on the left, so inward means % turn left in most cases. After some reasoning, we came up with % the directions 0 to 3, so turn left means add 1 modulus 4 and turn % right means add $-1$ modulus 4.}, we came up with the notation of % border as a comma list $x,y,d,c$ where $(x,y)$ is the origin of % the border, $d$ is a direction number from 0 to 3 (representing % angle $d\cdot 90$°): 0 ($\rightarrow$), 1 ($\uparrow$), 2 % ($\leftarrow$), 3 ($\downarrow$) in such way that the black pixel % is always to the left of the border and $c$ is the number of the % connected component that such pixel belongs to. Following a % border to the next in the same connected component will walk the % border in “positive” direction (counterclockwise), and in a % crossing, turn left (that is, add 1 modulus 4) will always turn % inward. The process of creating the list of borders is described % in section~\ref{sec:borders}. % % \item Now we build the Ti\textit{k}Z path, the main part of the % package. Starting from any border, the next border is either turn % left (inward), go straight or turn right in the same connected % component, trying in this sequence. Every walked border is % removed from the list of borders. In the beginning and at every % turn, output “$(x,y)$-{}-” to the path, where $(x,y)$ is the % origin of the border. When none of these borders is in the list, % we arrive at a dead end and output “cycle” to the path. This % pocess is reeated while the list of borders is not empty. This % algorithm is implemented in section~\ref{sec:path}. % % \item The package \texttt{qrcode} saves the correspondence % “text+version” $\leftrightarrow$ “binary data” into the aux file, % and at beginning of document, this code saves the binary data as a % macro, avoiding most of the computation. For the computed % Ti\textit{k}Z paths we implement this saving/restoring as a % \LaTeX3 prop list, also saving the correspondence “binary data” % $\leftrightarrow$ “path” into the aux file. This is done in % section~\ref{sec:prop}. % % \item In the mood of \texttt{qrcode} package, we save into the aux % file a line that populates the prop list from previous item. This % is done in section~\ref{sec:aux}. % % \item In section \ref{sec:print} we implement functions that are % meant to replace \texttt{qrcode} functions: that package % implements matrices as a series of macros. Fortunately % \texttt{qrcode} has a function to convert its matrices as binary % data. To avoid any change of behavior and get the closest result % from \texttt{qrcode}, we copied most of the computations plainly % from that package, but printing the path with Ti\textit{k}Z % instead of the original display of individual boxes. % % \item Finally, in section \ref{sec:on-off} we save copies of former functions % and implement turning on and off of new printing functions. % \end{enumerate} % % \subsection{Package identification} % % This package uses \LaTeX3 interface, with most recently implemented % functions in \textsf{l3intarray} module from 2018. In % 2020\footnote{See % \url{https://www.latex-project.org/news/latex2e-news/}, entry for % 2020/02/02.}, \LaTeX3 was included into \LaTeXe{}, so we require % \LaTeXe{} version at least as recent as 2020. If you only have % access to ealier versions of \LaTeXe, you can use % !\usepackage{expl3}!, but we still depend on \LaTeX3 % \textit{intarray} module from 2018. % % This package passes all options to \texttt{qrcode} package and loads % it, if not already loaded. % % \begin{macrocode} \NeedsTeXFormat{LaTeX2e}[2020-02-02] \ProvidesPackage{qrcodetikz}[2025-05-28 v1.0 Prettier qrcodes] \DeclareOption*{\PassOptionsToPackage{\CurrentOption}{qrcode}} \ProcessOptions \RequirePackage{qrcode} \RequirePackage{tikz} % \end{macrocode} % % The package uses \LaTeX3 in most of its extension. Only the final % printing functions that will replace \texttt{qrcode} printing % functions don't use \LaTeX3. % \begin{macrocode} \ExplSyntaxOn % \end{macrocode} % % \subsection{Declaration of variables} % % We declare some few variables. Variables of type “token list” % should end with the suffix !_tl!, but we decided to ommit it for % readability. % % \begin{itemize} % \item Integer variable !\l_qrtz_size_int! holds the size of the side % of QR code. % \begin{macrocode} \int_new:N \l_qrtz_size_int % \end{macrocode} % % \item Individual coordinates of $(x,y)$ are stored in % \begin{macrocode} \tl_new:N \l_qrtz_x \tl_new:N \l_qrtz_y % \end{macrocode} % % \item The direction number (0 to 3) is stored in % \begin{macrocode} \tl_new:N \l_qrtz_dir % \end{macrocode} % % \item The number of current connected component is stored in % \begin{macrocode} \tl_new:N \l_qrtz_component % \end{macrocode} % % \item Current path in construction is stored in % \begin{macrocode} \tl_new:N \l_qrtz_path % \end{macrocode} % % \item Borders are stored in % \begin{macrocode} \tl_new:N \l_qrtz_border \tl_new:N \l_qrtz_inner \tl_new:N \l_qrtz_straight \tl_new:N \l_qrtz_outer % \end{macrocode} % % \item \LaTeX3 intarray that stores matrix. Its size is $177^2=31\,329$, % the worst possible case. % \begin{macrocode} \intarray_new:Nn \g_qrtz_labels_intarray {177 * 177} % \end{macrocode} % % \item \LaTeX3 sequence to store the list of borders % \begin{macrocode} \seq_new:N \l_qrtz_border_seq % \end{macrocode} % % \item \LaTeX3 property list that stores saved information (binary-data % $\leftrightarrow$ path correspondence) % \begin{macrocode} \prop_new:N \g_qrtz_paths_prop % \end{macrocode} % % \item Switch for fallback definition of .aux commands % \begin{macrocode} \bool_new:N \g_qrtz_aux_fallback_written_bool \bool_gset_false:N \g_qrtz_aux_fallback_written_bool % \end{macrocode} % % \item Auxiliary switches % \begin{macrocode} \bool_new:N \l_qrtz_continue_straight_bool \bool_new:N \l_qrtz_can_continue_bool % \end{macrocode} % \end{itemize} % % \subsection{Interface for matrix and intarray correspondence } % \label{sec:matrix} % % \nDescribeMacro{\qrtz_index:nn} % Pixel $(x,y)$ corresponds to index $(n-y)n+x$ on the intarray. % Function !\qrtz_index:nn {!\vars{x}!}{!\vars{y}!}! % returns the linear index of a pixel in coordinates $(x,y)$. % Size is stored in !\l_qrtz_size_int!. % \nDescribeMacro{\qrtz_pixel:nn} % Function !\qrtz_pixel:nn {!\vars{x}!}{!\vars{y}!}! returns the value % of the entry, that is, 0 for white pixel, positive (the connected % component number) if black. % \begin{macrocode} \cs_new:Nn \qrtz_index:nn { ( \l_qrtz_size_int - (#2) ) * \l_qrtz_size_int + (#1) } % \cs_new:Nn \qrtz_pixel:nn { \intarray_item:Nn \g_qrtz_labels_intarray { \qrtz_index:nn {#1}{#2} } } % \end{macrocode} % % \subsection{Computation of connected components} % \label{sec:cc} % % We use \textit{union-find algorithm} to compute connected % components. The idea is that every pixel is a node in a graph, and a % pointed connection $A \to B$ means that “$B$ is parent of $A$”. If % $A$ points to itself, it means that $A$ is a “patriarch”. Two nodes % $A$ and $B$ belong to the same family if they share the same patriarch. % % For example, consider the pointed graph % \[ % 1 \to % \begin{array}[b]{c} % 3\\ \downarrow\\2 % \end{array} % \to 4 \righttoleftarrow,\quad % 5 \righttoleftarrow, % \quad 6 \to 7 \to 8 \righttoleftarrow % \] % % The patriarchs are 4, 5 and 8. The families (\textit{i.e.}, % connected components) are $\{1,2,3,4\}$, $\{5\}$ and $\{6,7,8\}$. % % There are two functions: \textit{find} that returns the patriarch of % an element, and \textit{union} that joins two families, making a % former patriarch to point another node in another family (otherwise % we get a cycle), joining the families under one of the patriarchs. % A way to avoid cycles is to make a patriarch to point another patriarch. % % We implement the “pointing” as the result of an array $A[i]=j$, % meaning $i \to j$. % % The graph above is represented by the array: % \begin{center} % \begin{tabular}{@{}c*{8}{c}@{}} % \toprule % $i$ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 \\ \midrule % $A[i]$ & 2 & 4 & 2 & 4 & 5 & 7 & 8 & 8 \\ \bottomrule % \end{tabular} % \end{center} % % \begin{itemize} % \item find($i$): $j\leftarrow i$. while $A[j]\neq j$ do: $j \leftarrow A[j]$. Return $j$. % % \item union($i,j$): $A[\text{find}(i)] \leftarrow \text{find}(j)$. % \end{itemize} % % We initialize the array with $A[i]=i$ if pixel is black or $A[i]=0$ % otherwise, for all $i$ (all black pixels are disconnected). % % \textit{First pass}: Loop through all pixels $x,y$, that correspond to index % $i$. If a pixel $p$ is black: if pixel $q$ to the right of $p$ is % also black, perform union($p,q$); if pixel $q$ below $p$ is % also black, perform union($p,q$). % % At the end of first pass, all connected components are determined. % It remains to clearly label the component of each pixel, doing the % second pass: % % \textit{Second pass}: loop for all indexes $i$: % $A[i] \leftarrow \text{find(i)}$. % % Now each pixel $p$, which has index $i$\footnote{The index of a % pixel $(x,y)$ is given by function \texttt{\string\qrtz\_index:nn % \{\textit{x}\} \{\textit{y}\}}.}, belongs to component $c = A[i]$. % Below we implement that. The array $A$ is the variable % !\g_qrtz_labels_intarray!. % % \nDescribeMacro{\qrtz_find:nnN} % Implementation of find: !\qrtz_find:nnN {!\vars{x}!}{!\vars{y}!} #3!. % Last arg \texttt{\#3} should be an integer var (module \textsf{l3int}) that % will receive the index of the patriarc of $(x,y)$. % \begin{macrocode} \cs_new:Nn \qrtz_find:nnN { \int_set:Nn #3 { \qrtz_index:nn {#1}{#2} } \int_until_do:nNnn {\intarray_item:Nn \g_qrtz_labels_intarray #3} = #3 { \int_set:Nn #3 {\intarray_item:Nn \g_qrtz_labels_intarray #3} } } % \end{macrocode} % % % \nDescribeMacro{\qrtz_union:nnnn} % Implementation of \textit{union} of pixels $(x_0,y_0)$ and $(x_1,y_1)$. % \begin{macrocode} \cs_new:Nn \qrtz_union:nnnn { \qrtz_find:nnN {#1}{#2} \l_tmpa_int \qrtz_find:nnN {#3}{#4} \l_tmpb_int \intarray_gset:Nnn \g_qrtz_labels_intarray \l_tmpb_int \l_tmpa_int } % \end{macrocode} % % \nDescribeMacro{\qrtz_compute_components:n} % A function that performs the two passes of the % algorithm described above. Its argument \texttt{\#1} is the binary % data of the QR code, loaded into the intarray % !\l_qrtz_labels_intarray!: 1 becomes the index $i$, 0 remains 0. % Index will be stored in !\l_tmpa_int! % \begin{macrocode} \cs_new:Nn \qrtz_compute_components:n { \int_zero:N \l_tmpa_int \tl_map_inline:nn {#1} { \int_incr:N \l_tmpa_int \intarray_gset:Nnn \g_qrtz_labels_intarray { \l_tmpa_int } { ##1 * \l_tmpa_int } } % \end{macrocode} % Set matrix size $n$ as $n\leftarrow \sqrt{l}$, % where $l=\text{\textit{length}}$ is stored in !\l_tmpa_int! after % previous loop. % \begin{macrocode} \int_set:Nn \l_qrtz_size_int { \fp_to_int:n { sqrt( \l_tmpa_int ) } } % \end{macrocode} % % \textit{First pass}: Iterate $x$,$y$ from 1 to % !\l_qrtz_size_int! (size of side of % QRcode); % if (it make sense pixel at right of $(x,y)$) \textit{and} % (current pixel is black) \textit{and} (pixel to the right is black) % [“and” computed with !lazy_all!, that is, one false condition stops % evaluation, returns false], do union operation of these pixels. The % analogue conditions for pixel below current pixel. % \begin{macrocode} \int_step_inline:nn { \l_qrtz_size_int } { % i=##1 \int_step_inline:nn { \l_qrtz_size_int } { % j = ####1 \bool_if:nT { \bool_lazy_all_p:n { { \int_compare_p:nNn {##1} < \l_qrtz_size_int } { \int_compare_p:nNn { \qrtz_pixel:nn {##1}{####1} } > 0 } { \int_compare_p:nNn { \qrtz_pixel:nn {1 + ##1}{####1} } > 0 } } } { \qrtz_union:nnnn {##1}{####1} {1 + ##1}{####1} } \bool_if:nT { \bool_lazy_all_p:n { { \int_compare_p:nNn {####1} < \l_qrtz_size_int } { \int_compare_p:nNn { \qrtz_pixel:nn {##1}{####1} } > 0 } { \int_compare_p:nNn { \qrtz_pixel:nn {##1}{1 + ####1} } > 0 } } } { \qrtz_union:nnnn {##1}{####1} {##1}{1 + ####1} } } } % \end{macrocode} % % \textit{Second pass}: if pixel is black, set its value as its % patriarch (find operation). !\l_tmpa_int! holds index of current % pixel, !\l_tmpb_int! holds index of its patriarch. % \begin{macrocode} \int_step_inline:nn { \l_qrtz_size_int } { % i = ##1 \int_step_inline:nn { \l_qrtz_size_int } { % j = ####1 \int_set:Nn \l_tmpa_int { \qrtz_index:nn {##1} {####1} } \int_compare:nNnF {\intarray_item:Nn \g_qrtz_labels_intarray \l_tmpa_int} = 0 { \qrtz_find:nnN {##1} {####1} \l_tmpb_int \intarray_gset:Nnn \g_qrtz_labels_intarray \l_tmpa_int \l_tmpb_int } } } } % \end{macrocode} % % \subsection{Construction of the list of borders} % \label{sec:borders} % % We decided that a border is a comma list $x,y,d,c$ where $(x,y)$ is % the origin of the border, $c$ is the number of the connected % component of the pixel to which this border corresponds and $d$ is % one of the numbers $0$, $1$, $2$ or $3$ meaning the direction % $d\cdot 90\text{°}$, with the convention that the interior (black % pixel) in on the left of the border, so that when one walks by % subsequent borders, the path is walked in positive sense, % \textit{i.e.}, counterclockwise. % \begin{center} % \begin{tikzpicture}[>=stealth'] % \draw (0,0) rectangle (6,6); % \fill[gray!30!white,draw=gray] % (0,2.5) coordinate (r1) rectangle ++(1,1) % (6,2.5) coordinate (r2) rectangle ++(-1,1) % (3,0) coordinate (r3) rectangle ++(1,1) % (3,6) coordinate (r4) rectangle ++(1,-1) % (r1-|r3) coordinate (r5) rectangle ++(1,1) coordinate (r6); % \draw % (r1) ++(0.5,0.5) node {\parbox{1cm}{\centering{\footnotesize pixel}\\$1,y$}} % (r2) ++(-0.5,0.5) node {\parbox{1cm}{\centering{\footnotesize pixel}\\$n,y$}} % (r3) ++(0.5,0.5) node {\parbox{1cm}{\centering{\footnotesize pixel}\\$x,1$}} % (r4) ++(0.5,-0.5) node {\parbox{1cm}{\centering{\footnotesize pixel}\\$x,n$}} % (r5) ++(0.5,0.5) node {\parbox{1cm}{\centering{\footnotesize pixel}\\$x,y$}}; % % \draw[very thick,red,<-] (r1) -- ++(0,1); % \draw[very thick,red,->] (r2) -- ++(0,1); % \draw[very thick,red,->] (r3) -- ++(1,0); % \draw[very thick,red,<-] (r4) -- ++(1,0); % \draw[very thick,red,->] (r5) -- ++(1,0);; % \draw[very thick,red,<-] (r5) -- ++(0,1); % \draw[very thick,red,->] (r6) -- ++(-1,0);; % \draw[very thick,red,<-] (r6) -- ++(0,-1); % % \draw[<-] (r1) ++(-0.1,0.5) -- ++(-0.5,0) node[left] {border 1,$y+1$,3,$c_1$}; % \draw[<-] (r2) ++(0.1,0.5) -- ++(0.5,0) node[right] {border $n+1$,$y$,1,$c_2$}; % \draw[<-] (r3) ++(0.5,-0.1) -- ++(0,-0.5) node[below] {border $x$,1,0,$c_3$}; % \draw[<-] (r4) ++(0.5,0.1) -- ++(0,0.5) node[above] {border $x+1$,$n+1$,2,$c_4$}; % % \draw[<-] (r6) ++(0.1,-0.3) -- ++(2.2,1.3) node[above right] {border $x+1$,$y$,1,$c_5$};% % \draw[<-] (r5) ++(-0.1,0.5) -- ++(-3.2,1.3) node[above left] {border $x$,$y+1$,3,$c_5$};% % \draw[<-] (r5) ++(0.5,-0.1) -- ++(0,-0.5) node[below] {border $x$,$y$,0,$c_5$}; % \draw[<-] (r6) ++(-0.5,0.1) -- ++(0,0.5) node[above] {border $x$,$y+1$,2,$c_5$};% % \fill % (r5) circle[radius=1.5pt] node[below left,xshift=1pt,yshift=1pt] % {\scriptsize$(x,y)$} % (r5-|r6) circle[radius=1.5pt] node[below right,xshift=-1pt,yshift=1pt] % {\scriptsize$(x+1,y)$} % (r5|-r6) circle[radius=1.5pt] node[above left,xshift=1pt,yshift=-1pt] % {\scriptsize$(x,y+1)$} % (r6) circle[radius=1.5pt] node[above right,xshift=-1pt,yshift=-1pt] % {\scriptsize$(x+1,y+1)$} % ; % \end{tikzpicture} % \end{center} % % \nDescribeMacro{\qrtz_build_border_list:n} % We build the list of borders with the function % !\qrtz_build_border_list:n!, whose arg !#1! is the binary data. It % stores the borders in !\l_qrtz_border_seq! variable. Each border is % a comma list \vars{x},\vars{y},\vars{dir},\vars{component}, as % described above. % % Loop for $x,y$ from 1 to $n$. First !\int_step_inline:nn! for $x$, % secont for $y$, so that $x = {}$!##1!, $y = {}$!####1!. % \begin{macrocode} \cs_new:Nn \qrtz_build_border_list:n { % \end{macrocode} % \par % Next macro sets size and matrix from binary. % \begin{macrocode} \qrtz_compute_components:n { #1 } % \seq_clear:N \l_qrtz_border_seq % \int_step_inline:nn { \l_qrtz_size_int } { % x = ##1 \int_step_inline:nn { \l_qrtz_size_int } { % y = ####1 % \end{macrocode} % Connected component number = !\l_qrtz_component!. % \begin{macrocode} \tl_set:Ne \l_qrtz_component { \qrtz_pixel:nn {##1}{####1} } % \end{macrocode} % If pixel$(x,y)$ is black ($\text{component}>0$), check whether % neighbor pixels are white. We use explicitly the feature of % !\bool_lazy_or:nnT! that the second test is done only if first is false. % \begin{macrocode} \int_compare:nNnT { \l_qrtz_component } > 0 { % \end{macrocode} % For left borders: add border $x$,$y+1$,3,\vars{component} % \begin{macrocode} \bool_lazy_or:nnT { \int_compare_p:nNn { ##1 } = 1 } { \int_compare_p:nNn { \qrtz_pixel:nn {##1 - 1}{####1} } = 0 } { \seq_put_left:Ne \l_qrtz_border_seq { ##1, \int_eval:n{ ####1 + 1 }, 3, \l_qrtz_component } } % % \end{macrocode} % For right borders: add border $x+1$,$y$,1,\vars{component} % \begin{macrocode} \bool_lazy_or:nnT { \int_compare_p:nNn { ##1 } = { \l_qrtz_size_int } } { \int_compare_p:nNn { \qrtz_pixel:nn {##1 + 1}{####1} } = 0 } { \seq_put_left:Ne \l_qrtz_border_seq { \int_eval:n{ ##1 + 1 }, ####1, 1, \l_qrtz_component } } % % \end{macrocode} % For top borders: add border $x+1$,$y+1$,2,\vars{component} % \begin{macrocode} \bool_lazy_or:nnT { \int_compare_p:nNn { ####1 } = { \l_qrtz_size_int } } { \int_compare_p:nNn { \qrtz_pixel:nn {##1}{####1+1} } = 0 } { \seq_put_left:Ne \l_qrtz_border_seq {\int_eval:n{##1+1}, \int_eval:n{####1+1}, 2, \l_qrtz_component } } % % \end{macrocode} % For bottom borders: add border $x$,$y$,0,\vars{component} % \begin{macrocode} \bool_lazy_or:nnT { \int_compare_p:nNn { ####1 } = 1 } { \int_compare_p:nNn { \qrtz_pixel:nn {##1}{####1-1} } = 0 } { \seq_put_left:Ne \l_qrtz_border_seq { ##1, ####1, 0, \l_qrtz_component } } } } } } % \end{macrocode} % % \subsection{Computation of the path} % \label{sec:path} % % Now we get to the main task of the package. Basicly, get a border, follow % the path (always removing the “walked” borders) in the same % connected component until get a closed path, output that subpath and % repeat until list of borders is empty. % % The algorithm is the following:\medskip % % \noindent % \textit{path} $\leftarrow$ “\,”\medskip % % \noindent % \makebox[0pt][r]{\framebox{A}\quad}while \textit{border-list}\\ % \mbox{}~~\textit{can-cont} $\leftarrow$ true\\ % \mbox{}~~\textit{go-straight} $\leftarrow$ false \quad\textit{\color{gray!50!black}\% to force first output to path}\\ % \mbox{}~~get \textit{border} in \textit{border-list} \quad\textit{\color{gray!50!black}\% without removing it}\\ % \mbox{}~~set \textit{x},\textit{y},\textit{dir},\textit{component} from \textit{border}\medskip % % \noindent % \makebox[0pt][r]{\framebox{B}\quad}\mbox{}~~while \textit{can-cont}\\ % \mbox{}~~~~remove \textit{border} \quad\textit{\color{gray!50!black}\% got at the beginning or tested in the if's at end of loop} \\ % \mbox{}~~~~if not \textit{go-straight}\quad\textit{\color{gray!50!black}\% at turn, output to path}\\ % \mbox{}~~~~~|~~\textit{path} $\leftarrow$ \textit{path} + “$(x,y)$-{}-”\\ % \mbox{}~~~~end-if\\ % \mbox{}~~~~set \textit{x},\textit{y} as the end point from \textit{border} \quad\textit{\color{gray!50!black}\% walk the border}\medskip % % \noindent % \makebox[0pt][r]{\framebox{C}\quad}\mbox{}~~~~compute \textit{inner},\textit{outer},\textit{straight} borders\\ % \mbox{}~~~~\textit{\color{gray!50!black}\% inner = x,y,dir\emph{+}1,c,\quad straight = x,y,dir,c,\quad outer = x,y,dir–1,c,}\\ % \mbox{}~~~~if \textit{inner} in \textit{border-list}\\ % \mbox{}~~~~|~~\textit{go-straight} $\leftarrow$ false\\ % \mbox{}~~~~|~~\textit{border} $\leftarrow$ \textit{inner}\\ % \mbox{}~~~~else\\ % \mbox{}~~~~|~~if \textit{straight} in \textit{border-list}\\ % \mbox{}~~~~|~~|~~\textit{go-straight} $\leftarrow$ true\\ % \mbox{}~~~~|~~|~~\textit{border} $\leftarrow$ \textit{straight}\\ % \mbox{}~~~~|~~else\\ % \mbox{}~~~~|~~|~~if \textit{outer} in \textit{border-list}\\ % \mbox{}~~~~|~~|~~|~~\textit{go-straight} $\leftarrow$ false\\ % \mbox{}~~~~|~~|~~|~~\textit{border} $\leftarrow$ \textit{outer}\\ % \mbox{}~~~~|~~|~~else\\ % \mbox{}~~~~|~~|~~|~~\textit{can-cont} $\leftarrow$ false\quad\textit{\color{gray!50!black}\% dead end, restart process to new subpath}\\ % \mbox{}~~~~|~~|~~|~~\textit{path} $\leftarrow$ \textit{path} + “cycle”\\ % \mbox{}~~~~|~~|~~end-if\\ % \mbox{}~~~~|~~end-if\\ % \mbox{}~~~~end-if\\ % \mbox{}~~end-while\\ % end-while\bigskip % % \nDescribeMacro{\qrtz_build_tikz_path:nN} % We implement the construction of the path in function % !\qrtz_build_tikz_path:nN!. The args are !#1! = \vars{binary data} % and !#2! = command that will hold the path. % \begin{macrocode} \cs_new:Nn \qrtz_build_tikz_path:nN { \message{.^^J}% } % \end{macrocode} % \medskip % % Geneate variant \texttt{eN} to always expand binary data and make as % non-expl alias of that. % \begin{macrocode} \cs_generate_variant:Nn \qrtz_build_tikz_path:nN { eN } \tl_set_eq:NN \QRTZBinaryToTikzPath \qrtz_build_tikz_path:eN % \end{macrocode} % % \subsection{Save paths in a \LaTeX3 prop list} % \label{sec:prop} % % \DescribeMacro{\QRTZgetTikzPathMaybeSaved} % The macro !\QRTZgetTikzPathMaybeSaved! is the main function to % retrieve the path corresponding to a binary data. If it was already % computed in a previous run (either just compuuted or stored in the % aux file) this path is stored into a \LaTeX3 property list % (\textsf{l3prop} module) and retrieved by this function. It is a % variant of the function below. % \begin{macrocode} \cs_new:Nn \qrtz_get_tikz_path_maybe_saved:nN { \prop_get:NeN \g_qrtz_paths_prop { #1 } { #2 } % \end{macrocode} % \texttt{qrcode} oftion \texttt{forget} is respected. % \begin{macrocode} \use:c {ifqr@forget@mode} \tl_set_eq:NN #2 \q_no_value \fi \quark_if_no_value:NTF #2 { \qrtz_build_tikz_path:nN { #1 }{ #2 } \qrtz_save_write_path_to_aux:ee { #1 }{ #2 } } { \message{^^J}% } } \cs_generate_variant:Nn \qrtz_get_tikz_path_maybe_saved:nN { eN } \tl_set_eq:NN \QRTZgetTikzPathMaybeSaved \qrtz_get_tikz_path_maybe_saved:eN % \end{macrocode} % % \subsection{Saving paths to aux file} % \label{sec:aux} % % \DescribeMacro{\QRTZsavePath} % The macro !\QRTZsavePath! \texttt{\{\vars{binary}\} \{\vars{tikz path}\}} % associates key \vars{binary} to value \vars{tikz path}, for later % use, to avoid recomputation of path and write correspondence to aux % file. It writes a fallback dummy definition of itself, in case this % package is removed. Its definition is actually a variant of the % macro below. % \begin{macrocode} \cs_new:Nn \qrtz_save_write_path_to_aux:nn { \bool_if:NF \g_qrtz_aux_fallback_written_bool { \iow_shipout:cn { @auxout } { \providecommand{\QRTZsavePath}[2]{} } \bool_gset_true:N \g_qrtz_aux_fallback_written_bool } \message{^^J}% \iow_shipout:cn { @auxout } { \QRTZsavePath {#1}{#2} } % \end{macrocode} % Verifying if binary data was already saved; save if necessary. % \begin{macrocode} \prop_get:NnN \g_qrtz_paths_prop { #1 } \l_tmpa_tl \quark_if_no_value:NT \l_tmpa_tl { \message{^^J}% \prop_gput:Nnn \g_qrtz_paths_prop { #1 } { #2 } } } \cs_generate_variant:Nn \qrtz_save_write_path_to_aux:nn { ee } \tl_set_eq:NN \QRTZsavePath \qrtz_save_write_path_to_aux:nn % \end{macrocode} % % \subsection{Printing function for \texttt{qrcode} matrix and binary data} % \label{sec:print} % % \nDescribeMacro{\QRTZprintQRmatrix} !\QRTZprintQRmatrix! is % \texttt{qrcodetikz}'s counterpart of !\qr@printmatrix! from % \texttt{qrcode}, that prints the QR code stored in a \texttt{qrcode} % matrix. In that package, matrices are stored with macros formed by % the matrix name and matrix indexes. Fortunately it has a function % to convert these matrices to binary data, that we print with % !\QRTZprintBinaryString!. % % \begin{macrocode} \cs_new:Nn \qrtz_print_qr_matrix:n { \message{^^J~(} \use:c{qr@matrixtobinary}{#1} % stores into \qr@binarymatrix@result \QRTZprintBinaryString{ \use:c{qr@binarymatrix@result} } \message{~)~} } \tl_set_eq:NN \QRTZprintQRmatrix \qrtz_print_qr_matrix:n % \end{macrocode} % % We will copy lots of chunks of !\qr@printsavedbinarymatrix! from % \texttt{qrcode} package, so we decided to go in \LaTeXe{} mode, but % missing \LaTeX3, specially by the trouble of the chain of % !\expandafter! below. % \begin{macrocode} \ExplSyntaxOff % \end{macrocode} % % \DescribeMacro{\qrcodeFillOptions}\DescribeMacro{\QRTZ@extraFillOpts} % Macro that stores fill options and a macro that sets it. % \begin{macrocode} \newcommand{\QRTZ@extraFillOpts}{} \newcommand{\qrcodeFillOptions}[1]{\gdef\QRTZ@extraFillOpts{#1}} % \end{macrocode} % % \DescribeMacro{\QRTZprintBinaryString} % Function !\QRTZprintBinaryString! is \texttt{qrcodetikz} counterpart % of function !\qr@printsavedbinarymatrix!, the macro of % \texttt{qrcode} that prints the QR code represented by a binary % string. We copy from it the computations and the use of !\parbox!, % to ensure the same behavior of \texttt{qrcode} printing functions. % It supposes context of a call of !\qrcode! command: !\qr@size! holds % size, !\qr@desiredheight!, !\qr@modulesize!, !\qr@minipagewidth! are % \TeX\ lengths and !\ifqr@tight! holds tight option. % \begin{macrocode} \newcommand{\QRTZprintBinaryString}[1]{% \setlength{\qr@modulesize}{\qr@desiredheight}% \divide\qr@modulesize by \qr@size\relax \setlength{\qr@minipagewidth}{\qr@modulesize}% \multiply\qr@minipagewidth by \qr@size\relax \ifqr@tight \else \advance\qr@minipagewidth by 8\qr@modulesize \fi % \end{macrocode} % After computations, we prepair the Ti\textit{k}Z settings: get the % path for the binary data in !#1! \dots % \begin{macrocode} \QRTZgetTikzPathMaybeSaved{#1}{\QRTZtikzPath}% % \end{macrocode} % and compute the scale. !\QRTZtikzPath! holds a path that displays % data on a square of size $n ={}$!\qr@size! cm that has to fit the % length !\qr@desiredheight!. 1 in = 2.54 cm = 72.27 pt, so 1pt = % 0.03514598 cm. Doing the math, we have the scale below. % \begin{macrocode} \pgfmathsetmacro\QRTZtikzScale{0.03514598*\qr@desiredheight/\qr@size}% % \end{macrocode} % We embed fill options in !\QRTZ@extraFillOpts! expanded once % together with scale and even odd rule options. % \begin{macrocode} \expandafter\def\expandafter\QRTZinternalFillOptions\expandafter{\expandafter [\QRTZ@extraFillOpts,scale=\QRTZtikzScale,even odd rule]}% % \end{macrocode} % Using the same !\parbox! as \texttt{qrcode} we fill the path. With % option \texttt{padding}, we enlarge the bounding box by 4 units: as % the path contains data in the rectangle from $(1,1)$ to $(n+1,n+1)$, % we add coordinates $(-3,-3)$ and $(n+5,n+5)$ to path, enlarging the % bounding box inside Ti\textit{k}Z. % \begin{macrocode} \parbox{\qr@minipagewidth}{% \tikz \expandafter\fill\QRTZinternalFillOptions \ifqr@tight\else(-3,-3)(\qr@size+5,\qr@size+5)\fi \QRTZtikzPath ;% }% } % \end{macrocode} % % \subsection{Replacing qrcode printing functions by new functions} % \label{sec:on-off} % % To implement switches to turn on and off the replacements, we save % copies of original functions and define macros that set original % functions accordingly. % \begin{macrocode} \let\qr@printmatrixORIGINAL\qr@printmatrix \let\qr@printsavedbinarymatrixORIGINAL\qr@printsavedbinarymatrix \newcommand{\qrcodetikzOn}{% \let\qr@printmatrix\QRTZprintQRmatrix \let\qr@printsavedbinarymatrix\QRTZprintBinaryString } \newcommand{\qrcodetikzOff}{% \let\qr@printmatrix\qr@printmatrixORIGINAL \let\qr@printsavedbinarymatrix\qr@printsavedbinarymatrixORIGINAL } \qrcodetikzOn % \end{macrocode} % % We silently fix a typo in \texttt{qrcode} (there, % !\def\qr@fivezeros{11111}!), a not-so-serious bug, used only to compute % a penalty). % \begin{macrocode} \def\qr@fivezeros{00000}% % \end{macrocode} % % \Finale % \endinput % %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~}