commit 17730aac5a7ece78e2f8b54e6986e6e16977038d Author: Bertrand Benjamin Date: Mon Jul 25 16:25:38 2022 +0200 Feat: Initialise le depot pour l'année 2022-2023 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0d49fea --- /dev/null +++ b/Makefile @@ -0,0 +1,37 @@ +CLEUSB=Cle8G + +COMMON_EXCLUDE=--exclude "__pycache__" --exclude "venv/" --exclude ".git" --exclude ".gitignore" --exclude ".*" --exclude "**/*.ppm" + +VENV="enseignements" + +install: + git config core.hooksPath ./tools/git/hooks/ + python -m venv ~/.venv/$(VENV) + ( \ + . ~/.venv/$(VENV)/bin/activate;\ + pip install -r requirements.txt;\ + ) + +update: + ( \ + . ~/.venv/$(VENV)/bin/activate;\ + pip install --ignore-installed -r requirements.txt + ) + +clean: + git clean -idx -e venv/ -e video/ + +sequence: + sh ./tools/scripts/new_sequence.sh + +eval: + sh ./tools/scripts/new_eval.sh + +rsync_cleUSB: clean + rsync -rtv -u --del --exclude "venv" ./ $(COMMON_EXCLUDE) /run/media/lafrite/$(CLEUSB)/Enseignements + rsync -rtv -u $(COMMON_EXCLUDE) ../Divers/ /run/media/lafrite/$(CLEUSB)/Divers + rsync -rtv -u $(COMMON_EXCLUDE) ../Notes/ /run/media/lafrite/$(CLEUSB)/Notes + rsync -rtv -u $(COMMON_EXCLUDE) ../Productions\ Eleves/ /run/media/lafrite/$(CLEUSB)/Productions + + +.PHONY: diff --git a/config.sh b/config.sh new file mode 100755 index 0000000..f0c8401 --- /dev/null +++ b/config.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +export ROOT=`pwd` + +export TEXINPUTS=".:${ROOT}/tools/style//::" + +# activate virtual env +source ~/.venv/enseignements/bin/activate + +goroot(){ + cd $ROOT +} + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d7b08cb --- /dev/null +++ b/requirements.txt @@ -0,0 +1,17 @@ +docutils==0.18.1 +gitdb==4.0.9 +GitPython==3.1.24 +greenlet==1.1.2 +invoke==1.6.0 +jedi==0.18.1 +Jinja2==2.11.2 +MarkupSafe==1.1.1 +msgpack==1.0.0 +mypytex==0.4 +parso==0.8.3 +prompt-toolkit==3.0.24 +pynvim==0.4.3 +restructuredtext-lint==1.3.2 +smmap==3.0.4 +Unidecode==1.3.2 +wcwidth==0.2.5 diff --git a/tools/examples/chapter/1B_premier_bilan.tex b/tools/examples/chapter/1B_premier_bilan.tex new file mode 100644 index 0000000..d93be71 --- /dev/null +++ b/tools/examples/chapter/1B_premier_bilan.tex @@ -0,0 +1,71 @@ +\documentclass[a4paper,12pt]{article} +\usepackage{myXsim} + +\title{Étude de la fonction logarithme} +\tribe{Terminale TESL} +\date{Mai 2020} + +\begin{document} + +\maketitle + +\section{Représentation graphique} + +La \textbf{fonction logarithme} notée $\ln$ est définie sur $\R^{+*}=\intOO{0}{+\infty}$ par $\ln :x \mapsto ln(x)$. + + \begin{minipage}{0.5\textwidth} + \begin{itemize} + \item Elle est continue et dérivable sur $\R^{+*}$ + \item Elle est négative sur $\intOO{0}{1}$ + \item Elle est positive sur $\intOO{1}{+\infty}$ + \item $\ln(1) = 0$ et $\ln(e) = 1$ + \end{itemize} + \begin{tikzpicture} + \tkzTabInit[lgt=2,espcl=5]{$x$/1,$f(x)$/2}% + {$0$, $+\infty$}% + \tkzTabVar{D-/$-\infty$, +/$+\infty$}% + \end{tikzpicture} + \end{minipage} + \hfill + \begin{minipage}{0.4\textwidth} + \begin{tikzpicture}[yscale=0.8, xscale=1] + \tkzInit[xmin=0,xmax=6,xstep=1, + ymin=-3,ymax=3,ystep=1] + \tkzGrid + \tkzAxeXY[up space=0.5,right space=.5] + \tkzFct[domain = 0.01:6, line width=1pt]{log(x)} + \tkzText[draw,fill = brown!20](5,-2.5){$f(x)=\ln(x)$} + \end{tikzpicture} + \end{minipage} + +\section{Dérivée de $\ln$} + +\subsection*{Propriété} + +La dérivée de la fonction logarithme est la fonction inverse +\[ + \forall x \in \intOO{0}{+\infty} \qquad \ln'(x) = \frac{1}{x} +\] + +On en déduit, pour tout $x > 0$: +\begin{itemize} + \item $\ln'(x) = \dfrac{1}{x}$ et $\dfrac{1}{x} > 0$ alors la fonction logarithme est \dotfill + \item $\ln''(x) = \makebox[2cm]{\dotfill}$ et $\makebox[2cm]{\dotfill}$ alors la fonction logarithme est \dotfill +\end{itemize} + +\subsection*{Exemples de calculs} + +Calcul de la dérivée de $f(x) = 2x + 1 - 4\ln(x)$ +\afaire{} + +Calcul de la dérivée de $f(x) = (2x+1)\ln(x)$ +\afaire{} + +Calcul de la dérivée de $f(x) = \dfrac{2x+1}{\ln(x)}$ +\afaire{} + + + + + +\end{document} diff --git a/tools/examples/chapter/1E_premiers_exercices.pdf b/tools/examples/chapter/1E_premiers_exercices.pdf new file mode 100644 index 0000000..e60c95c Binary files /dev/null and b/tools/examples/chapter/1E_premiers_exercices.pdf differ diff --git a/tools/examples/chapter/1E_premiers_exercices.tex b/tools/examples/chapter/1E_premiers_exercices.tex new file mode 100644 index 0000000..5711a99 --- /dev/null +++ b/tools/examples/chapter/1E_premiers_exercices.tex @@ -0,0 +1,21 @@ +\documentclass[a4paper,10pt]{article} +\usepackage{myXsim} + +\title{Lorem lorem} +\tribe{Lorem} +\date{Mai 2020} + +\pagestyle{empty} +\geometry{left=10mm,right=10mm, top=10mm} + +\DeclareExerciseCollection{banque} +\xsimsetup{ + step=1, +} + +\begin{document} + +\input{exercises.tex} +\printcollection{banque} + +\end{document} diff --git a/tools/examples/chapter/cours.tex b/tools/examples/chapter/cours.tex new file mode 100644 index 0000000..0f8d088 --- /dev/null +++ b/tools/examples/chapter/cours.tex @@ -0,0 +1,12 @@ +\collectexercises{banque} +\begin{exercise}[subtitle={lorem - cours}, step={1}, topics={lorem}] + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +\end{exercise} + +\begin{exercise}[subtitle={lorem lorem - cours}, step={2}, topics={lorem}] + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +\end{exercise} + +\collectexercisesstop{banque} diff --git a/tools/examples/chapter/exercises.tex b/tools/examples/chapter/exercises.tex new file mode 100644 index 0000000..baa4a96 --- /dev/null +++ b/tools/examples/chapter/exercises.tex @@ -0,0 +1,33 @@ +\collectexercises{banque} +\begin{exercise}[subtitle={lorem}, step={1}, topics={Logarithme}, origin={Inspiré de 23p201}] + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +\end{exercise} + +\begin{solution} + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +\end{solution} + +\begin{exercise}[subtitle={lorem lorem}, step={1}, topics={Logarithme}, origin={Création}] + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +\end{exercise} + +\begin{solution} + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +\end{solution} + +\begin{exercise}[subtitle={lorem lorem lorem}, step={2}, topics={Logarithme}, origin={BAC ES 2017 AN sept EX3}] + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +\end{exercise} + +\begin{solution} + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +\end{solution} + +\collectexercisesstop{banque} diff --git a/tools/examples/presentation.pdf b/tools/examples/presentation.pdf new file mode 100644 index 0000000..b74d46d Binary files /dev/null and b/tools/examples/presentation.pdf differ diff --git a/tools/examples/presentation.tex b/tools/examples/presentation.tex new file mode 100755 index 0000000..39c70af --- /dev/null +++ b/tools/examples/presentation.tex @@ -0,0 +1,49 @@ +\documentclass[14pt]{classPres} + +\author{} +\title{} +\date{} + +\begin{document} +\begin{frame}{Questions flashs} + \begin{center} + \vfill + Terminale ES-L + \vfill + 30 secondes par calcul + \vfill + \tiny \jobname + \end{center} +\end{frame} + +\begin{frame}{Calcul 1} + Un ordinateur coûte 400\euro. On a une remise de 5\%. \\ + Combien va-t-il nous coûter? +\end{frame} + +\begin{frame}{Calcul 2} + Sur une totale de recette de \np{2400}\euro, 40\% ont été réalisée par des paiement en espèce. \\ + Quelle est le montant des paiements réalisé en espèce? +\end{frame} + +\begin{frame}{Calcul 3} + \[ + 4x + 5 = 25 + \] +\end{frame} + +\begin{frame}{Calcul 4} + \[ + f(x) = 3x^2 + 4x - 10 + \] + Calculer $f(3)$ +\end{frame} + +\begin{frame}{Fin} + \begin{center} + On retourne son papier. + \end{center} +\end{frame} + + +\end{document} diff --git a/tools/examples/shortcuts_settings.pdf b/tools/examples/shortcuts_settings.pdf new file mode 100644 index 0000000..1e1785f Binary files /dev/null and b/tools/examples/shortcuts_settings.pdf differ diff --git a/tools/examples/shortcuts_settings.tex b/tools/examples/shortcuts_settings.tex new file mode 100644 index 0000000..72df6e8 --- /dev/null +++ b/tools/examples/shortcuts_settings.tex @@ -0,0 +1,260 @@ +\documentclass[a4paper,10pt]{article} +\usepackage{myXsim} +\usepackage{qrcode} + +\title{TITRE} +\tribe{TRIBU} +\date{DATE} + +\begin{document} + +\maketitle + +\section{Raccourcis}% + +\begin{itemize} + \item \verb+\ds+ $\ds \frac{1}{2}$ + + \item \verb+\N+ $\N$ + \item \verb+\Z+ $\Z$ + \item \verb+\Q+ $\Q$ + \item \verb+\R+ $\R$ + \item \verb+\C+ $\C$ + + \item \verb+\intOO+ $\intOO{\#1}{\#2}$ + \item \verb+\intFO+ $\intOO{\#1}{\#2}$ + \item \verb+\intOF+ $\intOO{\#1}{\#2}$ + \item \verb+\intFF+ $\intOO{\#1}{\#2}$ + + \item \verb+\vect+ $\vect{\#1}$ + \item \verb+\norme+ $\norme{\#1}$ + \item \verb+\scal+ $\scal{\#1}{\#2}$ + \item \verb+\vectCoord+ $\vectCoord{\#1}{\#2}$ + + \item \verb+\e+ $\e$ + % \item \verb+\i+ $\i$ + + \item \verb+\coefBino+ $\coefBino{\#1}{\#2}$ + + \item \verb+\equiv+ $\equiv$ + + \item \verb+\calc+ $\calc{\#1}$ +\end{itemize} + +\section{Compétences} +\begin{itemize} + + \item \verb+\Cher+ \Cher + \item \verb+\Mod+ \Mod + \item \verb+\Rep+ \Rep + \item \verb+\Rai+ \Rai + \item \verb+\Cal+ \Cal + \item \verb+\Com+ \Com + \item \verb+\Con+ \Con + + \item \verb+\RepLevel+ \RepLevel{.}\RepLevel{0}\RepLevel{1}\RepLevel{2}\RepLevel{3} + + \item \verb+\SignalBar+ \SignalBar{2} + \item \verb+\Assesment+ \Assesment{3} + \item \verb+\competencesStatement+ \competencesStatement +\end{itemize} + +\section{tikzpicture} +\begin{verbatim} + \begin{tikzpicture}[scale=1] + ... + \end{tikzpicture} +\end{verbatim} +\begin{itemize} + \item \verb+\cercleTrigo+ + \begin{tikzpicture}[scale=1] + \cercleTrigo + \end{tikzpicture} + \item \verb+\cercleTrigoNoOIJ+ + \begin{tikzpicture}[scale=1] + \cercleTrigoNoOIJ + \end{tikzpicture} + \item \verb+\repere+ + \begin{tikzpicture}[scale=1] + \repere{-2}{2}{-2}{2} + \end{tikzpicture} + \item \verb+\repereNoGrid+ + \begin{tikzpicture}[scale=1] + \repereNoGrid{-2}{2}{-2}{2} + \end{tikzpicture} + \item \verb+\boxplot+ + \begin{tikzpicture}[scale=1] + \boxplot{2}{0}{1}{2}{3}{4}{5} + \end{tikzpicture} + \item \verb+\boxplotNoNames+ + \begin{tikzpicture}[scale=1] + \boxplotNoNames{2}{0}{1}{2}{3}{4}{5} + \end{tikzpicture} +\end{itemize} + +\section{Mise en avant} +\begin{itemize} + \item \verb+\afaire+ + \afaire{\#1} + \item \verb+\envideo+ + \envideo{\#linktaget}{\#linkname} + \item \verb+\enclasse+ + \enclasse{\#1} + \item \verb+\arediger+ + \arediger{\#1} +\end{itemize} + +\section{Algo} + +\begin{multicols}{2} + \begin{verbatim} +\begin{algorithm}[H] + \SetAlgoLined + \Entree{n} + \Deb{ + $u \leftarrow 3$ \; + \Pour{$i$ de 1 à 3}{ + $u \leftarrow u+2$ \; + } + } + \Sortie{u} +\end{algorithm} + \end{verbatim} + + \columnbreak + + \begin{algorithm}[H] + \SetAlgoLined + \Entree{n} + \Deb{ + $u \leftarrow 3$ \; + \Pour{$i$ de 1 à 3}{ + $u \leftarrow u+2$ \; + } + } + \Sortie{u} + \end{algorithm} +\end{multicols} + +\section{Programmation} +\begin{multicols}{2} + \begin{verbatim} + \begin{lstlisting}[language=Python, basicstyle=\small, frame=] + x = ("Nombre de tirage?") + if x < 200: + print("Le tarif est ", x*0.11) + else: + print("Le tarif est ", x*0.8) + \end{lstlisting} + \end{verbatim} + + \columnbreak + \begin{lstlisting}[language=Python, basicstyle=\small, frame=] + x = ("Nombre de tirage?") + if x < 200: + print("Le tarif est ", x*0.11) + else: + print("Le tarif est ", x*0.8) + \end{lstlisting} +\end{multicols} + +\section{QRcode} + +\verb+\usepackage{qrcode}+ + +\qrcode{phrase à coder} + +\section{Graphique et tableaux} + +\subsection{Grahique} + +\begin{multicols}{2} + \begin{verbatim} +\begin{tikzpicture}[baseline=(current bounding box.south), + xscale=1, yscale=0.5] + \tkzInit[xmin=-5,xmax=5,xstep=1, + ymin=-5,ymax=5,ystep=1] + \tkzGrid + \tkzAxeXY + \tkzFct[domain=-5:5,color=red,very thick]% + { 0.4*x*x - 3 }; +\end{tikzpicture} + + \end{verbatim} + \columnbreak + \begin{tikzpicture}[baseline=(current bounding box.south), + xscale=1, yscale=0.5] + \tkzInit[xmin=-5,xmax=5,xstep=1, + ymin=-5,ymax=5,ystep=1] + \tkzGrid + \tkzAxeXY + \tkzFct[domain=-5:5,color=red,very thick]% + { 0.4*x*x - 3 }; + \end{tikzpicture} + +\end{multicols} + +Quand on change la valeur de \verb+xstep+, il faut replacer \verb+x+ par \verb+\x+. + +\begin{multicols}{2} + \begin{verbatim} +\begin{tikzpicture}[baseline=(current bounding box.south), + xscale=0.5, yscale=0.4] + \tkzInit[xmin=-5,xmax=5,xstep=0.5, + ymin=-5,ymax=5,ystep=1] + \tkzGrid + \tkzAxeXY + \tkzFct[domain=-5:5,color=red,very thick]% + { 0.4*\x*\x - 3 }; +\end{tikzpicture} + \end{verbatim} + \columnbreak + \begin{tikzpicture}[baseline=(current bounding box.south), + xscale=0.5, yscale=0.4] + \tkzInit[xmin=-5,xmax=5,xstep=0.5, + ymin=-5,ymax=5,ystep=1] + \tkzGrid + \tkzAxeXY + \tkzFct[domain=-5:5,color=red,very thick]% + { 0.4*\x*\x - 3 }; + \end{tikzpicture} +\end{multicols} + +\subsection{Tableau de signes et variations} + +\begin{multicols}{2} + \begin{verbatim} +\begin{tikzpicture}[baseline=(current bounding box.south)] + \tkzTabInit[lgt=2,espcl=2] + {$ x $/1,$ f(x) $/2}{-1, 2, 3, 5} + \tkzTabLine{, +, z, +, z, -, d, + , } +\end{tikzpicture} + \end{verbatim} + \columnbreak + \begin{tikzpicture}[baseline=(current bounding box.south)] + \tkzTabInit[lgt=2,espcl=2] + {$ x $/1,$ f(x) $/2}{-1, 2, 3, 5} + \tkzTabLine{, +, z, +, z, -, d, + , } + \end{tikzpicture} +\end{multicols} + +\begin{multicols}{2} + \begin{verbatim} +\begin{tikzpicture}[baseline=(current bounding box.south)] + \tkzTabInit[lgt=2,espcl=2] + {$ x $/1, $ f(x) $/2}{-2, 0, 1 } + \tkzTabVar{ +/3, -/1, +/5} +\end{tikzpicture} + \end{verbatim} + \columnbreak + \begin{tikzpicture}[baseline=(current bounding box.south)] + \tkzTabInit[lgt=2,espcl=2] + {$ x $/1, $ f(x) $/2}{-2, 0, 1 } + \tkzTabVar{ +/3, -/1, +/5} + \end{tikzpicture} +\end{multicols} + + + +\end{document} + diff --git a/tools/examples/tikzpicture.pdf b/tools/examples/tikzpicture.pdf new file mode 100644 index 0000000..488ca19 Binary files /dev/null and b/tools/examples/tikzpicture.pdf differ diff --git a/tools/examples/tikzpicture.tex b/tools/examples/tikzpicture.tex new file mode 100644 index 0000000..551246f --- /dev/null +++ b/tools/examples/tikzpicture.tex @@ -0,0 +1,63 @@ +\documentclass[a4paper,10pt]{article} +\RequirePackage[utf8x]{inputenc} +\RequirePackage[french]{babel} +\RequirePackage[T1]{fontenc} +\usepackage{tikz} +\usepackage{pgfplots} +\pgfplotsset{compat = newest} +\usepgfplotslibrary{external} + + +\RequirePackage{tkz-tab} +\RequirePackage{tkz-fct} + + +\title{Snippets pour tikzpicture} +\date{} +\author{Benjamin Bertrand} + +\begin{document} + +\section{La base} + +\begin{tikzpicture} + % par défaut les unités sont en cm + % un segment + \draw (0, 0) -- (1, 0); + % Coordonnées relatives + \draw (0, 0) -- ++(0, 1); + % Coordonnées polaire (angle: rayon) + \draw (0, 0) -- (45: 1); + % une figure pleine + \fill (2, 2) -- (1, 1) -- (2, 3) -- cycle; + % Un cercle (centre et rayon) + \draw (4, 1) circle (1); + % rectangle + \draw (5, 0) rectangle (6, 6); +\end{tikzpicture} + +\section{Graphiques de fonctions} + + +\begin{tikzpicture} + \begin{axis}[ + axis lines = center, + %grid = both, + xlabel = {$x$}, + xtick distance=1, + ylabel = {$y$}, + ytick distance=1, + legend pos = north west, + legend entries={$f(x)$, $g(x)$} + ] + \addplot[domain=-6:7,samples=40, color=red, very thick]{-0.1*(x+5)*(x-1)*(x-6)}; + \end{axis} +\end{tikzpicture} + + +\begin{tikzpicture} + \begin{axis}[axis x line=bottom,axis y line = left] + \addplot[ybar,fill=blue,draw=blue,bar width=1cm] coordinates { (1,194) (2,213) (3,251)(4,233) (5,194)}; \end{axis} +\end{tikzpicture} + +\end{document} diff --git a/tools/git/hooks/pre-commit b/tools/git/hooks/pre-commit new file mode 100755 index 0000000..6b6c23e --- /dev/null +++ b/tools/git/hooks/pre-commit @@ -0,0 +1,146 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# vim:fenc=utf-8 +# +# Copyright © 2017 lafrite +# +# Distributed under terms of the MIT license. + +""" +Git hook to ensure validity of all rst files +""" + +from git import Repo +from pathlib import Path +import re +import time +import restructuredtext_lint +import sys + +import logging + +formatter = logging.Formatter('%(name)s :: %(levelname)s :: %(message)s') +steam_handler = logging.StreamHandler() +#steam_handler = logging.FileHandler('logging.conf') +steam_handler.setLevel(logging.DEBUG) +steam_handler.setFormatter(formatter) + +# création de l'objet logger qui va nous servir à écrire dans les logs +logger = logging.getLogger("precommit") +# on met le niveau du logger à DEBUG, comme ça il écrit tout +logger.setLevel(logging.WARNING) +logger.addHandler(steam_handler) + +# Files selection + +def get_commited_files(repo): + hdiff = repo.head.commit.diff() + diff = {"A":[], "M":[]} + for f in hdiff.iter_change_type("A"): + diff["A"].append(f.b_path) + for f in hdiff.iter_change_type("M"): + diff["M"].append(f.b_path) + + return diff + +def select_by_extension(files, ext="rst"): + return [i for i in files if i.split(".")[-1] == ext and 'skeleton' not in i] + +# Rst linter + +def rst_lint(filename): + with open(filename, 'r') as f: + errors = restructuredtext_lint.lint(f.read()) + for e in errors: + logger.warning(f"{filename} \n{e.full_message}\n") + return errors + + +# Rst parameters normalize + +def normalize_file(filename, normalizers = {}): + logger.debug(f"Normalizing {filename}") + logger.debug(f"With {normalizers}") + new_file = "" + modified_lines = [] + with open(filename, 'r') as f: + for l in f.readlines(): + new_line = run_normalizers(l, normalizers) + if new_line != l: + modified_lines.append(f"{l}") + logger.warning(f"{filename}\n\t{l}\t{new_line}") + new_file += new_line + + with open(filename, "w") as f: + f.write(new_file) + logger.debug(f"{filename} written") + + return modified_lines + +def run_normalizers(line, normalizers): + for c in normalizers: + obs = re.search(c, line) + if obs: + logger.debug(f"Find for {c}") + return normalizers[c](line) + return line + +# Rst function tools + +def update_date(line): + date = time.strftime("%Y-%m-%d") + logger.debug(f"Update Date to: {date}") + return f":date: {date}\n" + +def update_modified(line): + modified = time.strftime("%Y-%m-%d") + logger.debug(f"Update modified to: {modified}") + return f":modified: {modified}\n" + +def normalize_tags(line): + logger.debug(f"Normaizing tags") + tags = line.split(":")[-1] + tags = [i.strip().capitalize() for i in tags.split(",")] + tags_str = ", ".join(tags) + logger.debug(f"Update tags to: {tags_str}") + return f":tags: {tags_str}\n" + +NORMALIZERS_MODIFIED = { + ":modified:.*": update_modified, + ":tags:.*": normalize_tags, + } + +NORMALIZERS_NEW = { + ":date:.*": update_date, + ":modified:.*": update_modified, + ":tags:.*": normalize_tags, + } + +if __name__ == "__main__": + r = Repo() + diff = get_commited_files(r) + + errors = [] + modified = [] + + # New files + for f in select_by_extension(diff["A"], "rst"): + errors += rst_lint(f) + modified += normalize_file(f, NORMALIZERS_NEW) + r.index.add([f]) + # Modified files + for f in select_by_extension(diff["M"], "rst"): + errors += rst_lint(f) + modified += normalize_file(f, NORMALIZERS_MODIFIED) + r.index.add([f]) + + if len(errors) > 0: + logger.warning("Errors in rst formating, commit aborted") + sys.exit(1) + + + +# ----------------------------- +# Reglages pour 'vim' +# vim:set autoindent expandtab tabstop=4 shiftwidth=4: +# cursor: 16 del diff --git a/tools/scripts/new_eval.sh b/tools/scripts/new_eval.sh new file mode 100644 index 0000000..1f8402f --- /dev/null +++ b/tools/scripts/new_eval.sh @@ -0,0 +1,66 @@ +#!/bin/bash + + +display_result() { + dialog --title "$1" \ + --no-collapse \ + --msgbox "$result" 0 0 +} + +exec 3>&1 +selection=$(dialog \ + --backtitle "Création d'une nouvelle évaluation: Classe" \ + --title "Menu" \ + --clear \ + --cancel-label "Exit" \ + --menu "Choisir un niveau:" 0 0 4 \ + "1" "2nd" \ + "2" "Enseignements Scientifique" \ + "3" "4e" \ + "4" "Technologique" \ + 2>&1 1>&3) +exec 3>&- +case $selection in + 1 ) + tribe="2nd" + ;; + 2 ) + tribe="EnseignementsScientifique" + ;; + 3 ) + tribe="4e" + ;; + 4 ) + tribe="Technologique" + ;; +esac + +exec 3>&1 +date=$(dialog --calendar "Date" 0 0 2>&1 1>&3 | awk -F "/" '{print $3"-"$2"-"$1}') +exec 3>&- + +exec 3>&1 +name=$(dialog \ + --inputbox "Nom de l'évaluation" \ + 0 0 \ + 2>&1 1>&3) +exec 3>&- + +exec 3>&1 +duration=$(dialog \ + --inputbox "Temps pour le travailler" \ + 0 0 \ + 2>&1 1>&3) +exec 3>&- + +mkdir -p $tribe/Evaluations/ +sequence_path=$tribe/Evaluations/DS_${date}/ +mkdir -p $sequence_path + +export name=$name +export date=$date +export tribe=$tribe +export duration=$duration +envsubst < ./tools/skeleton/eval/exercises.tex > $sequence_path/exercises.tex +envsubst < ./tools/skeleton/eval/sujet.tex > $sequence_path/sujet.tex + diff --git a/tools/scripts/new_sequence.sh b/tools/scripts/new_sequence.sh new file mode 100644 index 0000000..6d3239f --- /dev/null +++ b/tools/scripts/new_sequence.sh @@ -0,0 +1,112 @@ +#!/bin/bash + + +display_result() { + dialog --title "$1" \ + --no-collapse \ + --msgbox "$result" 0 0 +} + +exec 3>&1 +date=$(dialog --calendar "Date" 0 0 2>&1 1>&3 | awk -F "/" '{print $3"-"$2"-"$1}') +exec 3>&- + +exec 3>&1 +selection=$(dialog \ + --backtitle "Création d'une nouvelle séquence: Classe" \ + --title "Menu" \ + --clear \ + --cancel-label "Exit" \ + --menu "Choisir un niveau:" 0 0 4 \ + "1" "2nd" \ + "2" "Enseignements Scientifique" \ + "3" "4e" \ + "4" "Technologique" \ + 2>&1 1>&3) +exec 3>&- +case $selection in + 1 ) + tribe="2nd" + ;; + 2 ) + tribe="EnseignementsScientifique" + ;; + 3 ) + tribe="4e" + ;; + 4 ) + tribe="Technologique" + ;; +esac + +exec 3>&1 +cd $tribe +existing_seq=$(ls -d */) +nbr_seq=$(echo $existing_seq | wc -w) +next_seq_number=$(expr $nbr_seq) + +title=$(dialog \ + --inputbox "Séquences trouvée\n${existing_seq/ /\n} \nNom de la nouvelle sequence (n°$next_seq_number)" \ + 0 0 \ + 2>&1 1>&3) +exec 3>&- +cd .. + + +exec 3>&1 +summary=$(dialog \ + --inputbox "Résumé de la séquence" \ + 0 0 \ + 2>&1 1>&3) +exec 3>&- + +## ajouter les tags +exec 3>&1 +tags=$(dialog \ + --inputbox "Liste des tags séparés par une virgule" \ + 0 0 \ + 2>&1 1>&3) +exec 3>&- + +## Plan de travail ou classique +exec 3>&1 +selection=$(dialog \ + --backtitle "Création d'une nouvelle séquence: Type" \ + --title "Menu" \ + --clear \ + --cancel-label "Exit" \ + --menu "Type de séquence:" 0 0 4 \ + "1" "Classique" \ + "2" "Plan de travail" \ + 2>&1 1>&3) +exec 3>&- +case $selection in + 1 ) + sequence_type="classique" + ;; + 2 ) + sequence_type="plan_de_travail" + ;; +esac + + +sequence_path=$tribe/$(printf "%02d" $next_seq_number)_${title// /_}/ +mkdir -p $sequence_path + +export title=$title +export title_under=${title//?/#} +export author='Benjamin Bertrand' +export date=`date --date="$date 00:00" "+%B %Y"` +export tribe=$tribe +export tags=$tags +export summary=$summary +SKELETONPATH=./tools/skeleton/sequence +for i in `ls $SKELETONPATH/common/` +do + envsubst < $SKELETONPATH/common/$i > $sequence_path/$i +done +for i in `ls $SKELETONPATH/$sequence_type` +do + envsubst < $SKELETONPATH/$sequence_type/$i > $sequence_path/$i +done + diff --git a/tools/skeleton/eval/exercises.tex b/tools/skeleton/eval/exercises.tex new file mode 100644 index 0000000..ce8f3c6 --- /dev/null +++ b/tools/skeleton/eval/exercises.tex @@ -0,0 +1,7 @@ +\begin{exercise}[subtitle={<++>}, step={1}, origin={<++>}, topics={ ${title} }, tags={ ${tags} }] + <++> +\end{exercise} + +\begin{solution} + <++> +\end{solution} diff --git a/tools/skeleton/eval/sujet.tex b/tools/skeleton/eval/sujet.tex new file mode 100644 index 0000000..f01b210 --- /dev/null +++ b/tools/skeleton/eval/sujet.tex @@ -0,0 +1,27 @@ +\documentclass[a4paper,12pt]{article} +\usepackage{myXsim} + +% Title Page +\title{ ${name} \hfill ${subname}} +\tribe{${tribe}} +\date{${date}} +\duree{${duration}} + +\DeclareExerciseCollection[step=1]{banque} +\xsimsetup{collect} + + +\begin{document} +\maketitle + +Le barème est donné à titre indicatif, il pourra être modifié. + +\input{exercises.tex} +\printcollection{banque} +\end{document} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "master" +%%% End: + diff --git a/tools/skeleton/sequence/classique/1B.tex b/tools/skeleton/sequence/classique/1B.tex new file mode 100755 index 0000000..2c8fa8c --- /dev/null +++ b/tools/skeleton/sequence/classique/1B.tex @@ -0,0 +1,14 @@ +\documentclass[a4paper,10pt]{article} +\usepackage{myXsim} + +\author{${author}} +\title{${title} - Cours} +\date{${date}} + +\pagestyle{empty} + +\begin{document} + +\maketitle + +\end{document} diff --git a/tools/skeleton/sequence/classique/1E.tex b/tools/skeleton/sequence/classique/1E.tex new file mode 100755 index 0000000..46562ce --- /dev/null +++ b/tools/skeleton/sequence/classique/1E.tex @@ -0,0 +1,17 @@ +\documentclass[a4paper,10pt]{article} +\usepackage{myXsim} + +\author{${author}} +\title{${title} - Exercices} +\date{${date}} + +\DeclareExerciseCollection[step=1]{banque} +\xsimsetup{collect} + + +\begin{document} +\input{exercises.tex} + +\printcollection{banque} + +\end{document} diff --git a/tools/skeleton/sequence/common/exercises.tex b/tools/skeleton/sequence/common/exercises.tex new file mode 100644 index 0000000..ce8f3c6 --- /dev/null +++ b/tools/skeleton/sequence/common/exercises.tex @@ -0,0 +1,7 @@ +\begin{exercise}[subtitle={<++>}, step={1}, origin={<++>}, topics={ ${title} }, tags={ ${tags} }] + <++> +\end{exercise} + +\begin{solution} + <++> +\end{solution} diff --git a/tools/skeleton/sequence/common/index.rst b/tools/skeleton/sequence/common/index.rst new file mode 100644 index 0000000..7226b60 --- /dev/null +++ b/tools/skeleton/sequence/common/index.rst @@ -0,0 +1,12 @@ +${title} +${title_under} + +:date: ${date} +:modified: ${date} +:authors: ${author} +:tags: ${tags} +:category: ${tribe} +:summary: ${summary} + +Étape 1: +======== diff --git a/tools/skeleton/sequence/plan_de_travail/plan_de_travail.tex b/tools/skeleton/sequence/plan_de_travail/plan_de_travail.tex new file mode 100644 index 0000000..dfd6250 --- /dev/null +++ b/tools/skeleton/sequence/plan_de_travail/plan_de_travail.tex @@ -0,0 +1,44 @@ +\documentclass[a4paper,12pt]{article} +\usepackage{myXsim} + +\author{${author}} +\title{${title} - Plan de travail} +\tribe{${tribe}} +\date{${date}} + +\pagestyle{empty} + +\DeclareExerciseCollection{banque} +\xsimsetup{ +} + + +\begin{document} +\maketitle + +% Résumé + +\bigskip + +Savoir-faire de la séquence +\begin{itemize} + \item +\end{itemize} + +\bigskip + +Ordre des étapes à respecter + + +\section{} + +\listsectionexercises + + +\pagebreak + +\input{exercises.tex} +\printcollection{banque} + + +\end{document} diff --git a/tools/skeleton/sequence/plan_de_travail/solutions.tex b/tools/skeleton/sequence/plan_de_travail/solutions.tex new file mode 100644 index 0000000..a02d6b1 --- /dev/null +++ b/tools/skeleton/sequence/plan_de_travail/solutions.tex @@ -0,0 +1,28 @@ +\documentclass[a4paper,10pt]{article} +\usepackage{myXsim} + +\usetikzlibrary{shapes.geometric} + +\author{${author}} +\title{${title} - Solutions} +\tribe{${tribe}} +\date{${date}} + +\DeclareExerciseCollection{banque} +\xsimsetup{ + exercise/print=false, + solution/print=true, +} + +\pagestyle{empty} + + +\begin{document} + +\maketitle + +\input{exercises.tex} +%\printcollection{banque} +%\printsolutions{exercises} + +\end{document} diff --git a/tools/style/base.sty b/tools/style/base.sty new file mode 100755 index 0000000..f5640e8 --- /dev/null +++ b/tools/style/base.sty @@ -0,0 +1,89 @@ +\NeedsTeXFormat{LaTeX2e} + +% extensions +%\RequirePackage[utf8x]{inputenc} +\RequirePackage[french]{babel} +%\usepackage[babel=true,kerning=true]{microtype} +%\RequirePackage{amssymb} +%\RequirePackage{amsmath} +%\RequirePackage{amsfonts} +\PassOptionsToPackage{table,usenames,dvipsnames}{xcolor} +\RequirePackage{hyperref} +%\RequirePackage{subfig} +\RequirePackage{fancybox} +\RequirePackage{graphicx} +\graphicspath{{./}{\string~/.Clipart/}} + +\RequirePackage{textcomp} +\RequirePackage{gensymb} +\RequirePackage{ifthen, calc} +\RequirePackage{tabularx} +\RequirePackage{tasks} + +% Géométrie +\RequirePackage{geometry} +\geometry{left=10mm, + right=10mm, + top=5mm, + bottom=5mm, + includeheadfoot, + headsep=0pt, + footskip=1em, +} + +\setlength{\columnsep}{30pt} % default=10pt +\setlength{\columnseprule}{1pt} % default=0pt (no line) + +% Symbole euro +\RequirePackage{eurosym} + +% Espaces pour écrire les grands nombres +\RequirePackage[np]{numprint} + +% Outils pour les tableaux et les fonctions +\RequirePackage{tkz-tab} +\RequirePackage{tkz-fct} + +% Pour les block scratch +\RequirePackage{scratch3} + +% Plusieurs colonnes +\RequirePackage{multicol} + +% inteligent import (see https://codeyarns.com/2010/05/27/latex-import-subimport-for-document-organization/) +\RequirePackage{import} + +% Lecture des fichiers csv et affichage des csv en table +\RequirePackage{csvsimple} + +% Mes racourcis +\RequirePackage{shortcuts} + +%Polices +\RequirePackage{kpfonts-otf} +\RequirePackage{fontspec} +\setmainfont{KpSans} +\setsansfont{KpSans} +\setmonofont{KpMono} + +% \RequirePackage[nomath]{kpfonts} +% \renewcommand*\familydefault{\sfdefault} +% \RequirePackage[T1]{fontenc} + + +% Les tableaux +\renewcommand{\arraystretch}{1.5} +\newcolumntype{C}[1]{>{\centering\arraybackslash }b{#1}} + +% Figure qui se fondent dans le texte +\RequirePackage{wrapfig} + +% Code formating with listing +\RequirePackage{code} + +% Write algorithm +\usepackage[linesnumbered, boxed, french]{algorithm2e} + +\RequirePackage{enumitem} +\setlist[itemize,1]{label=$\bullet$} + diff --git a/tools/style/classPres.cls b/tools/style/classPres.cls new file mode 100755 index 0000000..e41f7b0 --- /dev/null +++ b/tools/style/classPres.cls @@ -0,0 +1,22 @@ +\NeedsTeXFormat{LaTeX2e} + +\ProvidesClass{classPres} + +% Classe de base - Beamer +%\pdfminorversion=4 +\LoadClassWithOptions{beamer} + +\usetheme{Singapore} +%\usepackage[defaultsans]{droidsans} +%\usepackage[T1]{fontenc} +%\usefonttheme[onlymath]{serif} + +% extensions + +\RequirePackage{colorscheme} +\RequirePackage{base} +\geometry{left=10mm,right=10mm, top=0mm} + + +% Les tableaux +\renewcommand{\arraystretch}{1.5} diff --git a/tools/style/code.sty b/tools/style/code.sty new file mode 100755 index 0000000..503bbc9 --- /dev/null +++ b/tools/style/code.sty @@ -0,0 +1,47 @@ +\NeedsTeXFormat{LaTeX2e} + +\RequirePackage{listings} + +\lstset{literate= + {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1 + {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1 + {à}{{\`a}}1 {è}{{\`e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1 + {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1 + {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1 + {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1 + {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1 + {Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1 + {Ã}{{\~A}}1 {ã}{{\~a}}1 {Õ}{{\~O}}1 {õ}{{\~o}}1 + {œ}{{\oe}}1 {Œ}{{\OE}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1 + {ű}{{\H{u}}}1 {Ű}{{\H{U}}}1 {ő}{{\H{o}}}1 {Ő}{{\H{O}}}1 + {ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1 {å}{{\r a}}1 {Å}{{\r A}}1 + {€}{{\euro}}1 {£}{{\pounds}}1 {«}{{\guillemotleft}}1 + {»}{{\guillemotright}}1 {ñ}{{\~n}}1 {Ñ}{{\~N}}1 {¿}{{?`}}1 +} +\lstset{ + backgroundcolor=\color{white}, % choose the background color; you must add \usepackage{color} or \usepackage{xcolor}; should come as last argument + %basicstyle=\tiny, % the size of the fonts that are used for the code + breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace + breaklines=true, % sets automatic line breaking + captionpos=b, % sets the caption-position to bottom + commentstyle=\color{gray}, % comment style + deletekeywords={...}, % if you want to delete keywords from the given language + escapeinside={\%*}{*)}, % if you want to add LaTeX within your code + extendedchars=true, % lets you use non-ASCII characters; for 8-bits encodings only, does not work with UTF-8 + frame=single, % adds a frame around the coden, + keepspaces=true, % keeps spaces in text, useful for keeping indentation of code (possibly needs columns=flexible) + keywordstyle=\color{green}, % keyword style + language=Python, % the language of the code + morekeywords={*,...}, % if you want to add more keywords to the set + numbers=left, % where to put the line-numbers; possible values are (none, left, right) + % numbersep=5pt, % how far the line-numbers are from the code + numberstyle=\tiny\color{gray}, % the style that is used for the line-numbers + rulecolor=\color{black}, % if not set, the frame-color may be changed on line-breaks within not-black text (e.g. comments (green here)) + showspaces=false, % show spaces everywhere adding particular underscores; it overrides 'showstringspaces' + showstringspaces=false, % underline spaces within strings only + showtabs=false, % show tabs within strings adding particular underscores + %stepnumber=2, % the step between two line-numbers. If it's 1, each line will be numbered + stringstyle=\color{purple}, + tabsize=2, % sets default tabsize to 2 spaces + %title=\tiny\lstname % show the filename of files included with \lstinputlisting; also try caption instead of title +} diff --git a/tools/style/colorscheme.sty b/tools/style/colorscheme.sty new file mode 100755 index 0000000..1951b9a --- /dev/null +++ b/tools/style/colorscheme.sty @@ -0,0 +1,51 @@ +\NeedsTeXFormat{LaTeX2e} + + +% Couleurs, +\RequirePackage{xcolor} +\RequirePackage{colortbl} + +% Couleurs éléments + +% \definecolor{coulpied}{couleur3} +% \definecolor{coulnumexos}{couleur5} +% \definecolor{coulrule}{couleur5} +% \definecolor{coulsection}{couleur1} +% \definecolor{coultable1}{couleur4} +% \definecolor{coultable2}{couleur3} +% \definecolor{coultheo}{couleur4} +% \definecolor{couldef}{couleur3} + +% Solarized theme +\definecolor{base03}{HTML}{002b36} +\definecolor{base02}{HTML}{073642} +\definecolor{base01}{HTML}{586e75} +\definecolor{base00}{HTML}{657b83} +\definecolor{base0}{HTML}{839496} +\definecolor{base1}{HTML}{93a1a1} +\definecolor{base2}{HTML}{eee8d5} +\definecolor{base3}{HTML}{FDF6E3} +\definecolor{yellow}{HTML}{B58900} +\definecolor{orange}{HTML}{cb4b16} +\definecolor{red}{HTML}{DC322F} +\definecolor{magenta}{HTML}{d33682} +\definecolor{violet}{HTML}{6c71c4} +\definecolor{blue}{HTML}{268bd2} +\definecolor{cyan}{HTML}{2aa198} +\definecolor{green}{HTML}{859900} + +% My theme +\colorlet{text}{base03} +\colorlet{footer}{base02} +\colorlet{bgentete}{base2} + +\colorlet{title}{blue} +\colorlet{subtitle}{base02} +\colorlet{line}{base1} +\colorlet{comments}{base01} +\colorlet{exercise}{blue} +\colorlet{note}{red} + + +\colorlet{highlightbg}{base2} +\colorlet{tabular}{base3} diff --git a/tools/style/myXsim.sty b/tools/style/myXsim.sty new file mode 100644 index 0000000..c0931ef --- /dev/null +++ b/tools/style/myXsim.sty @@ -0,0 +1,150 @@ +\NeedsTeXFormat{LaTeX2e} +% extensions + +\RequirePackage{colorscheme} +\RequirePackage{base} +\RequirePackage{myhdr} +\RequirePackage{notbeamer} + +\RequirePackage{xsim} + +\DeclareExerciseTagging{step} +\DeclareExerciseTagging{type} +\DeclareExerciseTagging{tribe} +\DeclareExerciseTagging{difficulty} +\DeclareExerciseTagging{origin} +\DeclareExerciseTagging{mode} + +\DeclareExerciseTranslations{total}{ + French = total, +} + +\DeclareExerciseEnvironmentTemplate{exo}{% + \subsection* + {% + \color{exercise}{\XSIMmixedcase{\GetExerciseName}}\nobreakspace + \GetExerciseProperty{counter}% + \hspace{0.5cm} \GetExercisePropertyT{mode} + {{\PropertyValue}}% + \hspace{0.5cm} \color{line}\hrulefill \hspace{0.5cm} + \color{exercise} + \GetExercisePropertyT{subtitle} + {{\PropertyValue}}% + \GetExercisePropertyT{points} + {{(/\PropertyValue})}% + \noindent + } +}{} + +\xsimsetup{exercise/template=exo} + +\DeclareExerciseEnvironmentTemplate{sol}{% + \subsection* + {% + \color{exercise}\nobreakspace + Exercice \GetExerciseProperty{counter}% + \hspace{0.5cm} \color{line}\hrulefill \hspace{0.5cm} + \color{exercise}{\XSIMmixedcase{\GetExerciseName}} + \hspace{0.5cm} \color{line}\hrulefill \hspace{0.5cm} + \color{exercise} + \GetExercisePropertyT{subtitle} + {{\PropertyValue}}% + \noindent + } +}{} +\xsimsetup{solution/template=sol} + + +\DeclareExerciseTableTemplate{DNB}{% + \XSIMputright\ExerciseTableCode{% + \hline + \XSIMifblankTF{\ExerciseType} + {} + {\XSIMmixedcase{\GetExerciseParameter{exercise-name}}} + & + \XSIMmixedcase{\XSIMtranslate{points}} \\ + \hline + }% + \ForEachUsedExerciseByType{% + \XSIMifeqTF{#1}{\ExerciseTableType{#1}} + {% + \XSIMifblankTF{\ExerciseType} + {% + \XSIMputright\ExerciseTableCode{% + \XSIMmixedcase{\ExerciseParameterGet{#1}{exercise-name} }% + }% + } + {}% + \XSIMputright\ExerciseTableCode + {#3 & \XSIMifblankTF{#5}{\printgoal{0}}{\printgoal{#5}}\\ }% + } + {}% + } + \XSIMputright\ExerciseTableCode{% + \hline + \XSIMmixedcase{\XSIMtranslate{total}} & + \XSIMifblankTF{\ExerciseType} + {\TotalExerciseGoal{points}{}{}} + {\TotalExerciseTypeGoal{\ExerciseType}{points}{}{}} \\ + \hline + }% + \XSIMexpandcode{% + \noexpand\begin{tabular}{|\XSIMifblankTF{\ExerciseType}{l}{c}|c|} + \noexpand\ExerciseTableCode + \noexpand\end{tabular}% + }% +} + +\newcommand\printsectionexercises{% + \ForEachUsedExerciseByType{% + \ifnum\ExercisePropertyGet{##1}{##2}{step}=\value{section} + \printexercise{exercise}{##2} + \fi + }% +} + +\newcommand\listsectionexercises{% + + \begin{itemize}[label={$\square$}] + \ForEachUsedExerciseByType{% + \ifnum\ExercisePropertyGet{##1}{##2}{step}=\value{section}% + \item % + \GetExerciseProperty{mode}% + {{\PropertyValue}}\;% + \XSIMmixedcase{\GetExerciseName}\nobreakspace + \GetExerciseProperty{counter}% + {{\PropertyValue}}% + : % + \GetExerciseProperty{subtitle}% + {{\PropertyValue}}% + \dotfill + %Auto-évaluation + \begin{tikzpicture} + \foreach \k in {0,1,...,4}{ + \draw (\k*0.5, 0) node[draw, star, star points=5, star point ratio=0.5]{}; + } + \end{tikzpicture} + \fi + }% + \end{itemize} +} + +\xsimsetup{ + exercise/within = section, + exercise/the-counter = \arabic{exercise}, +} + +\newcommand\searchMode{\faIcon{search}} +\newcommand\groupMode{\faIcon{users}} +\newcommand\trainMode{\faIcon{tools}} +\newcommand\projectMode{\faIcon{sitemap}} + +\newcommand\legendMode{% + \textbf{Légende:} \hfill + \searchMode: pour découvrir quelque chose + \hfill + \groupMode: à faire en groupe + \hfill + \trainMode: pour s'entrainer +} + diff --git a/tools/style/myhdr.sty b/tools/style/myhdr.sty new file mode 100644 index 0000000..44a31cc --- /dev/null +++ b/tools/style/myhdr.sty @@ -0,0 +1,97 @@ +\NeedsTeXFormat{LaTeX2e} +% extensions + +\RequirePackage{colorscheme} +\RequirePackage{lastpage} + +\RequirePackage{fancyhdr} + +\newcommand{\op@entete}{} +\newcommand{\op@typedoctmp}{} +\newcommand{\op@tribe}{} +\newcommand{\op@duree}{} +\newcommand{\op@sujet}{} +\newcommand{\op@subtitle}{\op@tribe{} -- \@date{}} + +\newcommand{\tribe}[1]{\renewcommand{\op@tribe}{#1}} +\newcommand{\duree}[1]{\renewcommand{\op@duree}{#1}} +\newcommand{\sujet}[1]{\renewcommand{\op@sujet}{Sujet #1}} + +%% Redéfinition de maketitle +\renewcommand{\maketitle}{% + \noindent{\huge \color{title}\bfseries \@title}\par + \noindent{\color{line}\rule{\linewidth}{1ex}}\par + \noindent{\color{subtitle}\bfseries \op@subtitle \hfill \large\op@sujet}\par + %\vspace{2.5\baselineskip} + %\thispagestyle{plain} +} + +%%% Page de garde +\renewcommand{\titlepage}{% + \pagestyle{plain} + \begin{center} + {\Huge \@title} \\ + \vfill + {\Huge \op@tribe} \\ + + \vfill + \fbox{ + \parbox{0.7\textwidth}{\large Épreuve de : + \begin{center} + \Huge MATHÉMATIQUES + \\[1cm] + {\Large \@date} \\[1cm] + \end{center} + \Large Durée de l'épreuve : \op@duree + \\[1cm] + } + } + \vfill + + ~\\[1cm] + \normalsize + Ce sujet comporte \pageref{LastPage}\, pages, numérotées de 1 / \pageref{LastPage}\; à \pageref{LastPage} / \pageref{LastPage}\\ + Dès qu'il vous est remis, assurez-vous qu'il est complet. + ~\\[0.5cm] + + L'utilisation de la calculatrice en mode \textbf{examen} est autorisée. + + \medskip + L'échange de calculatrice entre les élèves est strictement interdit.\\ + L'usage du dictionnaire n'est pas autorisé. \\[1cm] + + %\textbf{10 points} sont réservés à l'orthographe et à la présentation. + + \gradingtable[type=exercise,template=DNB] + + \vfill + \end{center} + \clearpage +} + +% Header et Footer +\pagestyle{fancy} + +%\setlength{\headheight}{10pt} +%\fancyheadoffset{\textwidth} + +\renewcommand{\headrulewidth}{0pt} +\renewcommand{\footrulewidth}{0pt} + +\newcommand{\op@boiteentete}{\makebox[0pt][l]{\hspace*{-3ex}% + \color{bgentete}\rule[-0.8ex]{\textwidth-5ex}{3ex}% + }} +\lhead{\scriptsize\op@boiteentete \@title} +\chead{} +\rhead{\scriptsize\@date} +\lfoot{\scriptsize\op@boiteentete \op@subtitle} +\cfoot{} +\rfoot{\scriptsize\thepage\ / \pageref{LastPage}} +\fancypagestyle{plain}{ % + \fancyhf{} % remove everything + \renewcommand{\headrulewidth}{0pt} % remove lines as well + \renewcommand{\footrulewidth}{0pt} + \lfoot{\scriptsize\op@boiteentete \op@subtitle} + \cfoot{} + \rfoot{\scriptsize\thepage\ / \pageref{LastPage}} +} diff --git a/tools/style/notbeamer.sty b/tools/style/notbeamer.sty new file mode 100755 index 0000000..5485942 --- /dev/null +++ b/tools/style/notbeamer.sty @@ -0,0 +1,82 @@ +\NeedsTeXFormat{LaTeX2e} + + +% Pour gérer les todo +\RequirePackage[french]{todonotes} +\newcounter{afaire} +\newcommand{\afaire}[2][]{% + % initials of the author (optional) + note in the margin + \refstepcounter{afaire}% + {% + %\setstretch{0.7}% spacing + \todo[inline,#1]{% + \textbf{À faire au crayon à papier:}~#2}% +}} +\newcounter{envideo} +\newcommand{\envideo}[3][]{% + % initials of the author (optional) + note in the margin + \refstepcounter{envideo}% + {% + %\setstretch{0.7}% spacing + \todo[inline,backgroundcolor=green,#1]{% + \textbf{Voir la vidéo}~ #3 + + \begin{minipage}{0.2\linewidth} + \qrcode{#2} + \end{minipage} + \begin{minipage}{0.8\linewidth} + \url{#2} + \end{minipage} + + }% +}} +\newcounter{enclasse} +\newcommand{\enclasse}[2][]{% + % initials of the author (optional) + note in the margin + \refstepcounter{enclasse}% + {% + %\setstretch{0.7}% spacing + \todo[inline,backgroundcolor=green,#1]{% + \textbf{Sera complété en classe}~#2}% +}} +\newcounter{arediger} +\newcommand{\arediger}[2][]{% + % initials of the author (optional) + note in the margin + \refstepcounter{afaire}% + {% + %\setstretch{0.7}% spacing + \todo[inline,#1]{% + \textbf{À rédiger et m'envoyer par mail:}~#2}% +}} + + +\usepackage[tikz]{bclogo} +% Environnements théoreme, définition ... +\newenvironment{encadre}[1] +{ + \begin{bclogo}[barre=none, arrondi=0.1, logo=]{#1} + }{ + \end{bclogo} +} + +\newcounter{doc} +\newenvironment{doc}[1] +{\refstepcounter{doc} + \begin{encadre}{Document \thedoc: #1} + }{ + \end{encadre} +} + +\newenvironment{definition}[1][] +{ + \begin{encadre}{Définition: #1} + }{ + \end{encadre} +} + +\newenvironment{propriete}[1][] +{ + \begin{encadre}{Propriété: #1} + }{ + \end{encadre} +} diff --git a/tools/style/qrcode.dtx b/tools/style/qrcode.dtx new file mode 100644 index 0000000..02cf53a --- /dev/null +++ b/tools/style/qrcode.dtx @@ -0,0 +1,3542 @@ +% \iffalse meta-comment +% +% qrcode.ins +% Copyright 2014 by Anders O.F. Hendrickson (anders.hendrickson@snc.edu) +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3 +% of this license or (at your option) any later version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of LaTeX +% version 2005/12/01 or later. +% +% This work has the LPPL maintenance status `maintained'. +% +% The Current Maintainer of this work is Anders O.F. Hendrickson. +% +% This work consists of the files qrcode.dtx and qrcode.ins +% and the derived file qrcode.sty. +% +% \fi +% +% \iffalse +%<*driver> +\ProvidesFile{qrcode.dtx} +% +%\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%\ProvidesPackage{qrcode} +%<*package> + [2015/01/08 v1.51 QR code generation] +% +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{hyperref} +\usepackage[nolinks]{qrcode} +\EnableCrossrefs +\CodelineIndex +\OnlyDescription +\RecordChanges +\begin{document} + \DocInput{qrcode.dtx} + \PrintChanges + %\PrintIndex +\end{document} +% +% \fi +% +% \CheckSum{0} +% +% \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 \~} +% +% +% \changes{v1.0}{2014/09/26}{Initial version} +% \changes{v1.5}{2015/01/08}{Added support for new lines and hyperlinks.} +% \changes{v1.51}{2015/01/14}{Bug fix.} +% +% \GetFileInfo{qrcode.sty} +% +% \DoNotIndex{\newcommand,\newenvironment,\def} +% +% \def\F{F} +% +% \title{The \textsf{qrcode} package: \\ +% \makebox[0pt][r]{\raisebox{-0.3\height}[0pt][0pt]{\qrcode[hyperlink,tight]{http://ctan.org/pkg/qrcode}}\rule{0.75in}{0pt}}Quick Response code \\ +% generation in \LaTeX\thanks{This document +% corresponds to \textsf{qrcode}~\fileversion, dated \filedate.}} +% \author{Anders Hendrickson\\ St.~Norbert College, De~Pere, WI, USA \\ \texttt{anders.hendrickson@snc.edu}} +% \date{January 8, 2015} +% +% \maketitle +% +% +% \section{Introduction} +% +% The proliferation of smartphones and tablets has led to the widespread +% use of Quick Response (QR) codes, which encode numeric, alphanumeric, kanji, +% or binary information into a square matrix of black and white pixels called modules. +% Although QR codes can encode any information up to almost three kilobytes, +% their most common use is as physical hyperlinks: a mobile device scans +% a printed QR code, decodes a URL, and automatically points a browser to that location. +% +% It is natural to want to include QR codes in certain \LaTeX\ documents; +% for example, one may want to direct the reader of a printed page to +% related interactive content online. +% Before now, the only \LaTeX\ package for producing QR codes was the +% immensely flexible {\tt pst-barcode}. As that package relies on +% {\tt pstricks}, however, it can be difficult to integrate with +% a pdf\LaTeX\ workflow,\footnote{% +% The {\tt auto-pst-pdf} or {\tt pstool} packages can make this possible +% by automatically running +% \LaTeX${}\rightarrow \tt dvips \rightarrow ps2pdf \rightarrow pdfcrop$ +% for each barcode generated in {\tt pstricks}, +% so long as the user is able and willing to enable {\tt\string\write18} +% in {\tt pdflatex} and install Perl. +% Judging by questions on {\tt tex.stackexchange.com} and {\tt latexcommunity.org}, +% this is a significant hurdle for some users. +% Moreover, according to {\tt http://tex.stackexchange.com/questions/72876/} +% this workflow may have trouble if the QR code is in a header.} +% and a pdf\LaTeX\ user may not want the extra overhead just to produce a QR code. +% If one wants to avoid {\tt pstricks}, a Lua\TeX\ solution was proposed at +% {\tt http://tex.stackexchange.com/questions/89649/}, +% and a plain\TeX\ solution can be found at +% {\catcode`\~=12\tt http://ktiml.mff.cuni.cz/~maj/QRcode.TeX}, +% but until now no \LaTeX\ package had been available that did not call on outside machinery. +% +% The {\tt qrcode} package, in contrast, implements the QR code algorithm using +% only \TeX\ and \LaTeX\ commands, so it should work with any \LaTeX\ workflow. +% Because it draws the squares constituting a QR code using the \TeX\ primitive +% |\rule|, there is no need to load any graphics package whatsoever. +% For a user who merely wants a QR code, this is the simplest solution. +% +% \section{Usage}\label{sect:usage} +% +% +% \DescribeMacro{\qrcode} +% The package provides just one command, |\qrcode|, with the following syntax: +% \begin{center} +% |\qrcode|\oarg{options}\marg{text to be encoded} +% \end{center} +% For example, |\qrcode[hyperlink,height=0.5in]{http://www.ctan.org}| produces +% \begin{center} +% \qrcode[hyperlink,height=0.5in]{http://www.ctan.org} +% \end{center} +% Although the most common use of QR codes is as URLs, +% the \meta{text to be encoded} can be almost any typed text. +% The few exceptions to this are described in section \ref{sect:specialcharacters}. +% +% \subsection{Package Options} +% +% \DescribeMacro{nolinks} +% When the |hyperref| package is loaded, +% by default |\qrcode| assumes its argument is a URL +% and makes the QR code produced a hyperlink to that URL. +% This default behavior may be changed by invoking the |nolinks| package option. +% For example, most of the QR codes in this document are not in fact URLs, +% so this documentation was typeset with |\usepackage[nolinks]{qrcode}|. +% The |hyperlinks| option is an antonym to |nolinks| and is the default. +% These options have no effect if hyperref is not loaded. +% +% \DescribeMacro{draft} +% \DescribeMacro{final} +% Creating QR codes for short URLs takes relatively little time.\footnote{On +% this author's laptop, even a 60-character URL (version 4, level M) adds +% only about 0.7 seconds of compilation time.} +% Because \TeX\ was designed for typesetting, not for extensive computations, +% however, if many small QR codes or a single large one are required, +% the time spent can be quite noticeable. To save compilation +% time while working on a large document, calling the |draft| option +% causes the package not to compute QR codes, but merely to insert placeholder +% symbols with no data. The |final| option is an antonym to |draft| +% and is the default. +% \begin{quote} +% \begin{tabular}{p{1.25in}p{3.5in}} +% {\qrcode[draft,version=15]{http://www.tug.org}} +% & +% \begin{minipage}{3in} +% \tt +% |\documentclass{article}| \\ +% |\usepackage[draft]{qrcode}| \\ +% |\begin{document}| \\ +% | \qrcode[version=15]{Dummy code}| \\ +% |\end{document}| +% \end{minipage} +% \end{tabular} +% \end{quote} +% The placeholder symbol produced in {\tt draft} mode will have the same size +% and dimensions as the actual QR code. +% +% To conserve processing time, when |\qrcode| computes the binary matrix representing +% a QR code, it saves that binary data as a string of 1's and 0's +% both in a macro and in the {\tt .aux} file. +% Thus if the same QR code is desired later in the document, or upon the next +% run of \LaTeX, the QR symbol can be redrawn immediately from the saved binary data. +% +% \DescribeMacro{forget} +% There may be times when this is not desired; testing of this package is the chief +% example, but one might also have reason to believe that the {\tt .aux} file +% contains bad data. +% Invoking the |forget| package option causes |\qrcode| to calculate +% every QR code anew, even if a QR code for that \meta{text to be encoded}, level, +% and version +% was read from the {\tt .aux} file or was already computed earlier in the document. +% +% \subsection{Options} +% \DescribeMacro{\qrset} +% Several options affect the appearance and encoding of the QR code; +% {\tt qrcode} uses the {\tt xkeyval} package to handle the setting +% and processing of key-value pairs. +% The following options may either be given as optional arguments +% to |\qrcode| or changed within a \TeX-grouping using the +% macro |\qrset|. +% \begin{quote} +% \begin{tabular}{p{6cm}p{2in}} +% \qrcode{ABCD} +% {\qrset{height=1cm}% +% \qrcode{EFGH}} +% \qrcode{IJKL} +% & +% \begin{minipage}{3in} +% |\qrcode{ABCD}| \\ +% |{\qrset{height=1cm}%| \\ +% | \qrcode{EFGH}}| \\ +% |\qrcode{IJKL}| +% \end{minipage} +% \end{tabular} +% \end{quote} +% +% \DescribeMacro{height} +% The |height=|\meta{dimen} key sets the printed height (and width) of the +% QR code. The default value is {\tt 2cm}. +% \begin{quote} +% \begin{tabular}{p{2in}p{2in}} +% \qrcode{ABCD} \qrcode[height=1cm]{ABCD} +% & |\qrcode{ABCD}| |\qrcode[height=1cm]{ABCD}| +% \end{tabular} +% \end{quote} +% +% \DescribeMacro{level} +% The QR code specification (ISO 18004:2006) includes four +% levels of encoding: Low, Medium, Quality, and High, in +% increasing order of error-correction capabaility. +% In general, for a given text a higher error-correction +% level requires more bits of information in the QR code. +% The key |level=|\meta{level specification} +% selects the minimum acceptable level. +% The \meta{level specification} may be |L|, |M|, |Q|, or |H|; +% the default is |M|. +% It may happen that the smallest QR code able to encode +% the specified text at the desired level +% is in fact large enough to provide a higher level of +% error-correction. If so, {\tt qrcode} automatically upgrades to the higher +% error-correction level, and a message is printed in the log file. +% +% \DescribeMacro{version} +% QR codes range in size from $21\times 21$ modules (``version 1'') +% to $177\times 177$ modules (``version 40''), in steps of 4 modules. +% The package automatically selects the smallest version large enough to encode +% the specified text at the desired error-correction level. +% Nevertheless, there might be occasions when a specific version is required; +% for example, perhaps a set of QR codes should have the same dimensions for +% aesthetic reasons, even though some encode shorter texts than others. +% For this reason, the key |version=|\meta{version specification} allows the user +% to specify a minimum version number, from 1 through 40, for the QR code. +% Setting |version=0| means ``as small as possible''; this is the default. +% If the desired version is not large enough to encode the text, the version +% will automatically be increased to accommodate the text, and a message will +% be placed in the log file. +% \begin{quote} +% \begin{tabular}{p{5.2cm}p{3in}} +% \raggedright +% \qrcode{ABCD} +% \qrcode[version=5]{ABCD} +% \medskip \\ +% \qrcode[version=10]{ABCD} +% \qrcode[version=20]{ABCD} +% & +% \begin{minipage}{3in} +% |\qrcode{ABCD}| \\ +% |\qrcode[version=5]{ABCD}| \\ +% |\medskip \\| \\ +% |\qrcode[version=10]{ABCD}| \\ +% |\qrcode[version=20]{ABCD}| +% \end{minipage} +% \end{tabular} +% \end{quote} +% +% +% \DescribeMacro{tight} +% \DescribeMacro{padding} +% The QR specification states that a QR code should be surrounded by white\-space +% of a width equal to that of four modules. In many applications, a document +% author is likely to provide sufficient spacing anyway (e.g., by placing the +% QR code in a {\tt center} environment, header, or |\marginpar|), so by +% default the |qrcode| package adds no spacing. If the option |padding| is +% specified, however, the QR code will automatically be surrounded with 4 modules' +% worth of white\-space. The key |tight| is an antonym of |padding|; the default is |tight|. +% +% \DescribeMacro{link} +% \DescribeMacro{nolink} +% \DescribeMacro{\qrcode*} +% As described above, if the |hyperref| package is loaded, +% then the QR codes produced in a PDF document can be made +% into hyperlinks to their text. The default behavior +% can be controlled with the options |nolinks| and |hyperlinks|, +% but this default can be overridden for individual QR codes by invoking +% the options |link| or |nolink|. +% Moreover, the starred version of the macro, |\qrcode*|, is a shorthand +% equivalent to |\qrcode[nolink]|. +% \begin{quote} +% \begin{tabular}{p{5.2cm}p{3in}} +% \raggedright +% \qrset{link, height=1.5cm} +% \qrcode{http://www.ctan.org} +% \qrcode[nolink]{This is not a URL.} +% \qrcode*{Neither is this.} +% & +% \begin{minipage}{3in} +% |\qrset{link, height=1.5cm}| \\ +% |\qrcode{http://www.ctan.org}| \\ +% |\qrcode[nolink]{This is not a URL.}| \\ +% |\qrcode*{Neither is this.}| +% \end{minipage} +% \end{tabular} +% \end{quote} +% +% \subsection{Special characters}\label{sect:specialcharacters} +% Many URLs can be processed by \TeX\ with no hiccups, +% but not infrequently a URL may contain the symbols |%|, |#|, +% |~|, |_|, and |&|. Moreover, QR codes need not just contain +% URL's, so a user may wish to encode text containing |^|, |$|, or spaces. +% The |qrcode| package offers two ways of coping with these special characters. +% +% First, the |\qrcode| command itself processes its \meta{text to be encoded} +% in a limited verbatim mode. The following characters will be encoded into +% the QR code as typed: +% \begin{center} +% |#| |$| |&| |^| |_| |~| |%| {\tt\char32} +% \end{center} +% and line breaks as well.\footnote{Technically, when the input character +% {\tt\char`\^\char`\^M} (CR, charcode 13) is encountered, +% the character {\tt\char`\^\char`\^J} (LF, charcode 10) is placed into the QR code.} +% Conspicuously absent from this list are |\|, |{|, and |}|. +% This is intentional, so that macros may be used within |\qrcode| +% to generate the \meta{text to be encoded} automatically. +% If these characters are desired, they may be obtained by ``escaping'' them +% with an extra backslash. +% \begin{quote} +% \begin{tabular}{p{2in}p{3in}} +% \qrset{height=1.5cm}% +% \qrcode{We can include #$&^_~%.} +% \def\foo{bar}% +% \qrcode{Set the \foo\ high.} +% \qrcode{We must escape \\emph\{this\}.} +% & \begin{minipage}{3in} +% |\qrset{height=1.5cm}%| \\ +% |\qrcode{We can include #$&^_~%.}| \\ +% |\def\foo{bar}%| \\ +% |\qrcode{Set the \foo\ high.}| \\ +% |\qrcode{We must escape \\emph\{this\}.}| +% \end{minipage} +% \end{tabular} +% \end{quote} +% +% As with all verbatim modes, however, because \TeX\ irrevocably sets catcodes +% when it first encounters characters, this will not work if the |\qrcode| macro +% is contained in another macro. If you call |\qrcode| inside an +% |\fbox| or a |\marginpar|, for example, and if your URL contains one of those +% special characters, you will either encounter error messages or (worse, because +% it is undetectable to the naked eye) have the wrong QR code typeset. +% In this scenario, you can still include any of the characters +% |#$&^_~%|{\tt\char32}|\{}| +% by escaping them with an extra backslash; +% so long as they eventually pass unexpanded to |\qrcode|, +% they will produce the correct QR code. +% A line break may be obtained with |\?|. +% \begin{quote} +% \begin{tabular}{p{1.5cm}p{2in}} +% \fbox{\qrcode[height=1cm]{\#\$\&\^\_\~\?\%\ \\\{\}}} +% & |\fbox{qrcode[height=1cm]{\#\$\&\^\_\~\?\%\ \\\{\}}}| +% \end{tabular} +% \end{quote} +% +% \section{Limitations and Cautions} +% +% \begin{itemize} +% \item The QR specification includes modes for encoding numeric, alphanumeric, +% or Kanji data more efficiently. This package does not (yet) offer +% those options. +% \item The QR specification offers ways to string lengthy data across multiple +% QR codes. This package does not implement that possibility. +% \end{itemize} +% +% \StopEventually{} +% +% \section{Implementation} +% \subsection{Key handling and options} +% \begin{macrocode} +%%PACKAGE LOADING +\RequirePackage{xcolor}% +\RequirePackage{xkeyval}% + +%%INITIAL CODE +\newif\ifqr@draft@mode +\newif\ifqr@forget@mode + +%%DECLARATION OF OPTIONS +\define@boolkey{qr}[qr@]{draft}[true]{\ifqr@draft\qr@draft@modetrue\else\qr@draft@modefalse\fi}% +\define@boolkey{qr}[qr@]{final}[true]{\ifqr@final\qr@draft@modefalse\else\qr@draft@modetrue\fi}% +\define@boolkey{qr}[qr@]{forget}[true]{\ifqr@forget\qr@forget@modetrue\else\qr@forget@modefalse\fi}% +\define@boolkey{qr}[qr@]{hyperlink}[true]{}% %This creates \ifqr@hyperlink. +\define@boolkey{qr}[qr@]{hyperlinks}[true]{\ifqr@hyperlinks\qr@hyperlinktrue\else\qr@hyperlinkfalse\fi}% +\define@boolkey{qr}[qr@]{link}[true]{\ifqr@link\qr@hyperlinktrue\else\qr@hyperlinkfalse\fi}% +\define@boolkey{qr}[qr@]{nolink}[true]{\ifqr@nolink\qr@hyperlinkfalse\else\qr@hyperlinktrue\fi}% %Make nolink an antonym. +\define@boolkey{qr}[qr@]{links}[true]{\ifqr@links\qr@hyperlinktrue\else\qr@hyperlinkfalse\fi}% +\define@boolkey{qr}[qr@]{nolinks}[true]{\ifqr@nolinks\qr@hyperlinkfalse\else\qr@hyperlinktrue\fi}% %Make nolinks an antonym. + +%%EXECUTION OF OPTIONS +\qr@draft@modefalse +\qr@forget@modefalse +\qr@hyperlinktrue + +\ProcessOptionsX + +% \end{macrocode} +% \subsection{Utilities} +% \begin{macrocode} +%COUNTERS +\newcounter{qr@i}% +\newcounter{qr@j}% +\newcount\qr@a +\newcount\qr@b +\newcount\qr@c + +%BASICS +\let\xa=\expandafter + +%This is for messages. +\newlinechar=`\^^J + + +%Tests +\def\qr@relax{\relax}% + +%Manipulating macros +\def\qr@preface@macro#1#2{% + % #1 = macro name + % #2 = text to add to front of macro + \def\qr@tempb{#2}% + \xa\xa\xa\def\xa\xa\xa#1\xa\xa\xa{\xa\qr@tempb #1}% +}% + +\def\qr@g@preface@macro#1#2{% + % #1 = macro to be appended to + % #2 = code to add + \edef\qr@tempb{#2}% + \xa\xa\xa\gdef\xa\xa\xa#1\xa\xa\xa{\xa\qr@tempb#1}% +} + + +\def\qr@getstringlength#1{% + \bgroup + \qr@a=0% + \xdef\qr@thestring{#1}% + \xa\qr@stringlength@recursive\xa(\qr@thestring\relax\relax)% + \xdef\qr@stringlength{\the\qr@a}% + \egroup +}% + +\def\qr@stringlength@recursive(#1#2){% + \def\qr@testi{#1}% + \ifx\qr@testi\qr@relax + %we are done. + \let\qr@next=\relax% + \else + \advance\qr@a by 1% + \def\qr@next{\qr@stringlength@recursive(#2)}% + \fi + \qr@next +}% +% \end{macrocode} +% \subsubsection{For-loop macro} +% We implement a macro |\qr@for| with the syntax +% \begin{center} +% |\qr@for| \meta{control sequence}=\meta{number} to \meta{number} by \meta{number} \marg{loop body} +% \end{center} +% The \meta{control sequence} becomes the loop variable, +% which is a \TeX\ counter. +% For example, |\qr@for \i=1 to 8 by 2 {\fbox{\number\i}}| +% produces {\makeatletter\qr@for \i=1 to 8 by 2 {\fbox{\number\i}}}. +% \begin{macrocode} +%The \qr@for@depth counter measures the depth of our loop. +%The outermost loop has depth zero. +\newcount\qr@for@depth% +\newcount\qr@for@maxdepth% +\qr@for@depth=0% +\qr@for@maxdepth=0% +%These counters are used in the qr@for loop. +\newcount\qr@for@start% +\newcount\qr@for@end% +\newcount\qr@for@step% +%Now a macro to get a new count for every depth as needed. +\def\qr@allocate@new@for@counter{% + \global\advance\qr@for@maxdepth by 1% + \newcount\qr@newforcount% + \xa\global\xa\let\csname qr@for@var@\the\qr@for@maxdepth\endcsname=\qr@newforcount% +}% + +\newif\ifqr@loopshouldrun +%The extra # in the following definition makes sure #4 scoops up everything up to the next opening brace. +%This is needed so the step can include more than one character without being enclosed in braces itself. +\def\qr@for #1=#2to#3by#4#{% + \qr@for@int{#1}{#2}{#3}{#4}% +}% +\long\def\qr@for@int#1#2#3#4#5{% + \bgroup + %Because we're working within a TeX group, + %any values of \qr@for@start, \qr@for@end, and \qr@for@step from an outer loop + %will be restored after the \egroup. + % + %For the \qr@for@var itself, however, we need a different counter, + %because the user's text within the loop might need to access the variable from the outer loop. + \advance\qr@for@depth by 1\relax% This is a local change. + \ifnum\qr@for@depth>\qr@for@maxdepth% + %This is the first time we have gone to this depth of nesting! + %We should only be over by one. + \qr@allocate@new@for@counter% + \fi +% \showthe\qr@for@depth% + \xa\let\xa\qr@for@var\xa=\csname qr@for@var@\the\qr@for@depth\endcsname% + %Now \qr@for@var points to the same register as \qr@for@var@3 or something. + %The next line lets the user-level variable (e.g., \i or \j) point to the same count register. + \let#1=\qr@for@var% + %Now establish the looping parameters. + \edef\qr@for@start@text{#2}% + \edef\qr@for@end@text{#3}% + \edef\qr@for@step@text{#4}% + \def\qr@for@body{\bgroup #5\egroup}% + \xa\qr@for@start\qr@for@start@text\relax% + \xa\qr@for@end \qr@for@end@text\relax% + \xa\qr@for@step \qr@for@step@text\relax% + % + %Next, test whether the loop should run at all. + % * "\qr@for \i = 1 to 0 by 1" should fail. + % * "\qr@for \i = 3 to 5 by -1" should fail. + % * "\qr@for \i = 6 to 2 by 1" should fail. + % * "\qr@for \i = 4 to 4 by -1" should run. + % * "\qr@for \i = 4 to 4 by 1" should run. + % * "\qr@for \i = 5 to 7 by 0" should fail. + %The loop should fail if (step)=0 or if (step) and (end-start) have opposite signs. + %The loop will fail if (step=0) or (step)*(end-start)<0. + % TODO: "\qr@for \i = 5 to 5 by 0" should run (just one iteration). + \qr@loopshouldruntrue + \ifnum\qr@for@step=0\relax + \qr@loopshouldrunfalse + \fi + \qr@a=\qr@for@end% + \advance\qr@a by -\qr@for@start% + \multiply\qr@a by \qr@for@step% + \ifnum\qr@a<0\relax + \qr@loopshouldrunfalse + \fi + \ifqr@loopshouldrun + \qr@for@var=\qr@for@start% + \ifnum\qr@for@step>0\relax + \def\qr@for@recursive{% + \qr@for@body% + \advance\qr@for@var by \qr@for@step% + \ifnum\qr@for@var>\qr@for@end% + \let\qr@for@next=\relax% + \else% + \let\qr@for@next=\qr@for@recursive% + \fi% + \qr@for@next% + }% + \else + \def\qr@for@recursive{% + \qr@for@body% + \advance\qr@for@var by \qr@for@step% + \ifnum\qr@for@var<\qr@for@end% + \let\qr@for@next=\relax% + \else% + \let\qr@for@next=\qr@for@recursive% + \fi% + \qr@for@next% + }% + \fi + \qr@for@recursive% + \fi + \egroup +}% +% \end{macrocode} +% \subsubsection{Base conversions} +% \begin{macrocode} +\def\qr@padatfront#1#2{% + % #1 = macro containing text to pad + % #2 = desired number of characters + % Pads a number with initial zeros. + \qr@getstringlength{#1}% + \qr@a=\qr@stringlength\relax% + \advance\qr@a by 1\relax% + \qr@for \i = \qr@a to #2 by 1\relax% + {\qr@g@preface@macro{#1}{0}}% +} + + +\qr@a=-1\relax% +\def\qr@savehexsymbols(#1#2){% + \advance\qr@a by 1\relax% + \xa\def\csname qr@hexchar@\the\qr@a\endcsname{#1}% + \xa\edef\csname qr@hextodecimal@#1\endcsname{\the\qr@a}% + \ifnum\qr@a=15\relax + %Done. + \let\qr@next=\relax% + \else + \def\qr@next{\qr@savehexsymbols(#2)}% + \fi% + \qr@next% +}% +\qr@savehexsymbols(0123456789abcdef\relax\relax)% + + +\def\qr@decimaltobase#1#2#3{% + % #1 = macro to store result + % #2 = decimal representation of a positive integer + % #3 = new base + \bgroup + \edef\qr@newbase{#3}% + \gdef\qr@base@result{}% + \qr@a=#2\relax% + \qr@decimaltobase@recursive% + \xdef#1{\qr@base@result}% + \egroup +} +\def\qr@decimaltobase@recursive{% + \qr@b=\qr@a% + \divide\qr@b by \qr@newbase\relax + \multiply\qr@b by -\qr@newbase\relax + \advance\qr@b by \qr@a\relax% + \divide\qr@a by \qr@newbase\relax% + \ifnum\qr@b<10\relax + \edef\qr@newdigit{\the\qr@b}% + \else + \edef\qr@newdigit{\csname qr@hexchar@\the\qr@b\endcsname}% + \fi + \edef\qr@argument{{\noexpand\qr@base@result}{\qr@newdigit}}% + \xa\qr@g@preface@macro\qr@argument% + \ifnum\qr@a=0\relax + \relax + \else + \xa\qr@decimaltobase@recursive + \fi +} + +\newcommand\qr@decimaltohex[3][0]{% + % #1 (opt.) = number of hex digits to create + % #2 = macro to store result + % #3 = decimal digits to convert + \qr@decimaltobase{#2}{#3}{16}% + \qr@padatfront{#2}{#1}% +} + + +\newcommand\qr@decimaltobinary[3][0]{% + % #1 (opt.) = number of bits to create + % #2 = macro to store result + % #3 = decimal digits to convert + \qr@decimaltobase{#2}{#3}{2}% + \qr@padatfront{#2}{#1}% +} + +\qr@for \i = 0 to 15 by 1% + {% + \qr@decimaltohex[1]{\qr@hexchar}{\the\i}% + \qr@decimaltobinary[4]{\qr@bits}{\the\i}% + \xa\xdef\csname qr@b2h@\qr@bits\endcsname{\qr@hexchar}% + \xa\xdef\csname qr@h2b@\qr@hexchar\endcsname{\qr@bits}% + }% + + + +\newcommand\qr@binarytohex[3][\relax]{% + % #1 (optional) = # digits desired + % #2 = macro to save to + % #3 = binary string (must be multiple of 4 bits) + \def\qr@test@i{#1}% + \ifx\qr@test@i\qr@relax% + %No argument specified + \def\qr@desireddigits{0}% + \else + \def\qr@desireddigits{#1}% + \fi + \gdef\qr@base@result{}% + \edef\qr@argument{(#3\relax\relax\relax\relax\relax)}% + \xa\qr@binarytohex@int\qr@argument% + \qr@padatfront{\qr@base@result}{\qr@desireddigits}% + \xdef#2{\qr@base@result}% +} +\def\qr@binarytohex@int(#1#2#3#4#5){% + % #1#2#3#4 = 4 bits + % #5 = remainder, including \relax\relax\relax\relax\relax terminator + \def\qr@test@i{#1}% + \ifx\qr@test@i\qr@relax% + %Done. + \def\qr@next{\relax}% + \else% + \xdef\qr@base@result{\qr@base@result\csname qr@b2h@#1#2#3#4\endcsname}% + \def\qr@next{\qr@binarytohex@int(#5)}% + \fi% + \qr@next% +} + +\newcommand\qr@hextobinary[3][\relax]{% + % #1 (optional) = # bits desired + % #2 = macro to save to + % #3 = hexadecimal string + \bgroup + \def\qr@test@i{#1}% + \ifx\qr@test@i\qr@relax% + %No argument specified + \def\qr@desireddigits{0}% + \else + \def\qr@desireddigits{#1}% + \fi + \gdef\qr@base@result{}% + \edef\qr@argument{(#3\relax\relax)}% + \xa\qr@hextobinary@int\qr@argument% + \qr@padatfront{\qr@base@result}{\qr@desireddigits}% + \xdef#2{\qr@base@result}% + \egroup +} +\def\qr@hextobinary@int(#1#2){% + % #1 = hexadecimal character + % #2 = remainder, including \relax\relax terminator + \def\qr@test@@i{#1}% + \ifx\qr@test@@i\qr@relax% + %Done. + \def\qr@next{\relax}% + \else% + \xdef\qr@base@result{\qr@base@result\csname qr@h2b@#1\endcsname}% + \def\qr@next{\qr@hextobinary@int(#2)}% + \fi% + \qr@next% +} + +\def\qr@hextodecimal#1#2{% + \edef\qr@argument{#2}% + \xa\qr@a\xa=\xa\number\xa"\qr@argument\relax% + \edef#1{\the\qr@a}% +} + +\def\qr@hextodecimal#1#2{% + % #1 = macro to store result + % #2 = hexadecimal representation of a positive integer + \bgroup + \qr@a=0\relax% + \edef\qr@argument{(#2\relax)}% + \xa\qr@hextodecimal@recursive\qr@argument% + \xdef#1{\the\qr@a}% + \egroup +} +\def\qr@hextodecimal@recursive(#1#2){% + % #1 = first hex char + % #2 = remainder + \advance \qr@a by \csname qr@hextodecimal@#1\endcsname\relax% + \edef\qr@testii{#2}% + \ifx\qr@testii\qr@relax% + %Done. + \let\qr@next=\relax% + \else + %There's at least one more digit. + \multiply\qr@a by 16\relax + \edef\qr@next{\noexpand\qr@hextodecimal@recursive(#2)}% + \fi% + \qr@next% +} +% \end{macrocode} +% \subsubsection{Catcode setup} +% \begin{macrocode} +%The following catcode trickery creates special characters +%with catcode 12 (other) for use in our verbatim handling. +{\catcode`\ =12\relax\gdef\qr@otherspace{ }}% +{\catcode`\%=12\relax\gdef\qr@otherpercent{%}}% +{\catcode`\#=12\relax\gdef\qr@otherpound{#}}% +{\catcode`\|=0\relax|catcode`|\=12|relax|gdef|qr@otherbackslash{\}}% +{\catcode`\^^J=12\relax\gdef\qr@otherlf{^^J}}% +\bgroup + \catcode`\<=1\relax + \catcode`\>=2\relax + \catcode`\{=12\relax\gdef\qr@otherleftbrace<{>% + \catcode`\}=12\relax\gdef\qr@otherrightbrace<}>% +\egroup% +{\catcode`\&=12\relax\gdef\qr@otherampersand{&}}% +{\catcode`\~=12\relax\gdef\qr@othertilde{~}}% +{\catcode`\^=12\relax\gdef\qr@othercaret{^}}% +{\catcode`\_=12\relax\gdef\qr@otherunderscore{_}}% +{\catcode`\$=12\relax\gdef\qr@otherdollar{$}}% + +%Line feeds require some special handling. \TeX\ reads a line feed in the input +%as |^^M| (carriage return, character code 13), but it should be encoded in a +%QR code as |^^J| (line feed, character code 10). +%To do this, we make |^^M| an active character and a synonym for a |^^J| with catcode 12. +%Note that the macro |\qr@verbatimlinefeeds| must itself be processed with |^^M| active. +{\catcode`\^^M=13\relax\gdef\qr@verbatimlinefeeds{\let^^M=\qr@otherlf}} +\def\qr@verbatimcatcodes{% + \catcode`\#=12\relax + \catcode`\$=12\relax + \catcode`\&=12\relax + \catcode`\^=12\relax + \catcode`\_=12\relax + \catcode`\~=12\relax + \catcode`\%=12\relax + \catcode`\ =12\relax + \catcode`\^^M=13\relax\qr@verbatimlinefeeds}% + +\def\qr@setescapedspecials{% + \let\ =\qr@otherspace% + \let\%=\qr@otherpercent% + \let\#=\qr@otherpound% + \let\&=\qr@otherampersand% + \let\^=\qr@othercaret% + \let\_=\qr@otherunderscore% + \let\~=\qr@othertilde% + \let\$=\qr@otherdollar% + \let\\=\qr@otherbackslash% + \let\{=\qr@otherleftbrace% + \let\}=\qr@otherrightbrace% + \let\?=\qr@otherlf% +}% +% \end{macrocode} +% \subsection{Plotting} +% \begin{macrocode} +\def\qr@creatematrix#1{% + \xa\gdef\csname #1\endcsname##1##2{% + \csname #1@##1@##2\endcsname + }% +}% + + +\def\qr@storetomatrix#1#2#3#4{% + % #1 = matrix name + % #2 = row number + % #3 = column number + % #4 = value of matrix entry + \xa\gdef\csname #1@#2@#3\endcsname{#4}% +}% + +\def\qr@estoretomatrix#1#2#3#4{% + % This version performs exactly one expansion on #4. + % #1 = matrix name + % #2 = row number + % #3 = column number + % #4 = value of matrix + \xa\xa\xa\gdef\xa\xa\csname #1@#2@#3\endcsname\xa{#4}% +}% + +\def\qr@matrixentry#1#2#3{% + % #1 = matrix name + % #2 = row number + % #3 = column number + \csname #1@#2@#3\endcsname% +}% + + + +\def\qr@createsquareblankmatrix#1#2{% + \qr@creatematrix{#1}% + \xa\gdef\csname #1@numrows\endcsname{#2}% + \xa\gdef\csname #1@numcols\endcsname{#2}% + \qr@for \i = 1 to #2 by 1% + {\qr@for \j = 1 to #2 by 1% + {\qr@storetomatrix{#1}{\the\i}{\the\j}{\qr@blank}}}% +}% + +\def\qr@numberofrowsinmatrix#1{% + \csname #1@numrows\endcsname% +}% + +\def\qr@numberofcolsinmatrix#1{% + \csname #1@numcols\endcsname% +}% + +\def\qr@setnumberofrows#1#2{% + \xa\xdef\csname #1@numrows\endcsname{#2}% +}% + +\def\qr@setnumberofcols#1#2{% + \xa\xdef\csname #1@numcols\endcsname{#2}% +}% + +\newlength\qr@desiredheight +\setlength\qr@desiredheight{2cm}% +\newlength\qr@modulesize +\newlength\qr@minipagewidth + +\def\qr@printmatrix#1{% + \def\qr@black{\rule{\qr@modulesize}{\qr@modulesize}}% + \def\qr@white{\rule{\qr@modulesize}{0pt}}% + \def\qr@black@fixed{\rule{\qr@modulesize}{\qr@modulesize}}% + \def\qr@white@fixed{\rule{\qr@modulesize}{0pt}}% + \def\qr@black@format{\rule{\qr@modulesize}{\qr@modulesize}}% + \def\qr@white@format{\rule{\qr@modulesize}{0pt}}% + %Set module size + \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 + \begin{minipage}{\qr@minipagewidth}% + \baselineskip=\qr@modulesize% + \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% %Blank space at top. + \qr@for \i = 1 to \qr@numberofrowsinmatrix{#1} by 1% + {\ifqr@tight\else\rule{4\qr@modulesize}{0pt}\fi% %Blank space at left. + \qr@for \j = 1 to \qr@numberofcolsinmatrix{#1} by 1% + {\qr@matrixentry{#1}{\the\i}{\the\j}}% + \par}% + \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% + \end{minipage}% +}% + +\def\qr@printsavedbinarymatrix#1{% + \edef\qr@binarystring{#1\relax\relax}% + %Set module size + \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 + \begin{minipage}{\qr@minipagewidth}% + \baselineskip=\qr@modulesize% + \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% %Blank space at top. + \qr@for \i = 1 to \qr@size by 1% + {\ifqr@tight\else\rule{4\qr@modulesize}{0pt}\fi% %Blank space at left. + \qr@for \j = 1 to \qr@size by 1% + {\edef\qr@theargument{(\qr@binarystring)}% + \xa\qr@printsavedbinarymatrix@int\qr@theargument + }% + \par}% + \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% + \end{minipage}% +}% + +\def\qr@printsavedbinarymatrix@int(#1#2){% + % #1 = first bit, either 1 or 0. + % #2 = remainder of string, terminating with \relax\relax + % There's no need to check for EOF here, because + % we'll only call this n^2 times. + \ifcase #1\relax + \rule{\qr@modulesize}{0pt}% % 0: white square + \or + \rule{\qr@modulesize}{\qr@modulesize}% % 1: black square + \fi + \xdef\qr@binarystring{#2}% +}% + +\def\qr@createliteralmatrix#1#2#3{% + % #1 = matrix name + % #2 = m, the number of rows and columns in the square matrix + % #3 = a string of m^2 tokens to be written into the matrix + \qr@creatematrix{#1}% + \xa\xdef\csname #1@numrows\endcsname{#2}% + \xa\xdef\csname #1@numcols\endcsname{#2}% + \gdef\qr@literalmatrix@tokens{#3}% + \qr@for \i = 1 to #2 by 1% + {\qr@for \j = 1 to #2 by 1% + {\xa\qr@createliteralmatrix@int\xa(\qr@literalmatrix@tokens)% + \qr@estoretomatrix{#1}{\the\i}{\the\j}{\qr@entrytext}% + }% + }% +} +\def\qr@createliteralmatrix@int(#1#2){% + \def\qr@entrytext{#1}% + \gdef\qr@literalmatrix@tokens{#2}% +} + + +\qr@createliteralmatrix{finderpattern}{8}{% + \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed% + \qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed% +}% + +\qr@createliteralmatrix{alignmentpattern}{5}{% + \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed% + \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed% + \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed% + \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed% + \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed% +}% + + + + +\def\qr@copymatrixentry#1#2#3#4#5#6{% + % Copy the (#2,#3) entry of matrix #1 + % to the (#5,#6) position of matrix #4. + \xa\xa\xa\global% + \xa\xa\xa\let\xa\xa\csname #4@#5@#6\endcsname% + \csname #1@#2@#3\endcsname% +}% + +\def\qr@createduplicatematrix#1#2{% + % #1 = name of copy + % #2 = original matrix to be copied + \qr@creatematrix{#1}% + \qr@for \i = 1 to \qr@numberofrowsinmatrix{#2} by 1% + {\qr@for \j = 1 to \qr@numberofcolsinmatrix{#2} by 1% + {\qr@copymatrixentry{#2}{\the\i}{\the\j}{#1}{\the\i}{\the\j}% + }% + }% + \qr@setnumberofrows{#1}{\qr@numberofrowsinmatrix{#2}}% + \qr@setnumberofcols{#1}{\qr@numberofcolsinmatrix{#2}}% +}% + +\def\qr@placefinderpattern@int#1#2#3#4#5{% + % Work on matrix #1. + % Start in position (#2, #3) -- should be a corner + % #4 indicates horizontal direction (1=right, -1=left) + % #5 indicates vertical direction (1=down, -1=up) + % + % In this code, \sourcei and \sourcej are TeX counts working through the finderpattern matrix, + % and i and j are LaTeX counters indicating positions in the big matrix. + \setcounter{qr@i}{#2}% + \qr@for \sourcei=1 to 8 by 1% + {\setcounter{qr@j}{#3}% + \qr@for \sourcej=1 to 8 by 1% + {\qr@copymatrixentry{finderpattern}{\the\sourcei}{\the\sourcej}% + {#1}{\theqr@i}{\theqr@j}% + \addtocounter{qr@j}{#5}% + }% + \addtocounter{qr@i}{#4}% + }% +}% + +\def\qr@placefinderpatterns#1{% + % #1=matrix name + \qr@placefinderpattern@int{#1}{1}{1}{1}{1}% + \qr@placefinderpattern@int{#1}{\qr@numberofrowsinmatrix{#1}}{1}{-1}{1}% + \qr@placefinderpattern@int{#1}{1}{\qr@numberofcolsinmatrix{#1}}{1}{-1}% +}% + +\def\qr@placetimingpatterns#1{% + %Set \qr@endingcol to n-8. + \qr@a=\qr@size\relax% + \advance\qr@a by -8\relax% + \edef\qr@endingcol{\the\qr@a}% + \qr@for \j = 9 to \qr@endingcol by 1% + {\ifodd\j\relax% + \qr@storetomatrix{#1}{7}{\the\j}{\qr@black@fixed}% + \qr@storetomatrix{#1}{\the\j}{7}{\qr@black@fixed}% + \else% + \qr@storetomatrix{#1}{7}{\the\j}{\qr@white@fixed}% + \qr@storetomatrix{#1}{\the\j}{7}{\qr@white@fixed}% + \fi% + }% +}% + +\def\qr@placealignmentpattern@int#1#2#3{% + % Work on matrix #1. + % Write an alignment pattern into the matrix, centered on (#2,#3). + \qr@a=#2\relax% + \advance\qr@a by -2\relax% + \qr@b=#3\relax% + \advance\qr@b by -2\relax% + \setcounter{qr@i}{\the\qr@a}% + \qr@for \i=1 to 5 by 1% + {\setcounter{qr@j}{\the\qr@b}% + \qr@for \j=1 to 5 by 1% + {\qr@copymatrixentry{alignmentpattern}{\the\i}{\the\j}% + {#1}{\theqr@i}{\theqr@j}% + \stepcounter{qr@j}% + }% + \stepcounter{qr@i}% + }% +}% + +\newif\ifqr@incorner% +\def\qr@placealignmentpatterns#1{% + %There are k^2-3 alignment patterns, + %arranged in a (k x k) grid within the matrix. + %They begin in row 7, column 7, + %except that the ones in the NW, NE, and SW corners + %are omitted because of the finder patterns. + %Recall that + % * \qr@k stores k, + % * \qr@alignment@firstskip stores how far between the 1st and 2nd row/col, & + % * \qr@alignment@generalskip stores how far between each subsequent row/col. + \xa\ifnum\qr@k>0\relax + %There will be at least one alignment pattern. + %N.B. k cannot equal 1. + \xa\ifnum\qr@k=2\relax + % 2*2-3 = exactly 1 alignment pattern. + \qr@a=7\relax + \advance\qr@a by \qr@alignment@firstskip\relax + \xdef\qr@target@ii{\the\qr@a}% + \qr@placealignmentpattern@int{#1}{\qr@target@ii}{\qr@target@ii}% + \else + % k is at least 3, so the following loops should be safe. + \xdef\qr@target@ii{7}% + \qr@for \ii = 1 to \qr@k by 1% + {\ifcase\ii\relax% + \relax% \ii should never equal 0. + \or + \xdef\qr@target@ii{7}% If \ii = 1, we start in row 7. + \or + %If \ii = 2, we add the firstskip. + \qr@a=\qr@target@ii\relax% + \advance\qr@a by \qr@alignment@firstskip\relax% + \xdef\qr@target@ii{\the\qr@a}% + \else + %If \ii>2, we add the generalskip. + \qr@a=\qr@target@ii\relax% + \advance\qr@a by \qr@alignment@generalskip\relax% + \xdef\qr@target@ii{\the\qr@a}% + \fi + \qr@for \jj = 1 to \qr@k by 1% + {\ifcase\jj\relax% + \relax% \jj should never equal 0. + \or + \xdef\qr@target@jj{7}% If \jj=1, we start in row 7. + \or + %If \jj=2, we add the firstskip. + \qr@a=\qr@target@jj\relax% + \advance\qr@a by \qr@alignment@firstskip% + \xdef\qr@target@jj{\the\qr@a}% + \else + %If \jj>2, we add the generalskip. + \qr@a=\qr@target@jj\relax% + \advance\qr@a by \qr@alignment@generalskip% + \xdef\qr@target@jj{\the\qr@a}% + \fi + \qr@incornerfalse% + \ifnum\ii=1\relax + \ifnum\jj=1\relax + \qr@incornertrue + \else + \ifnum\qr@k=\jj\relax + \qr@incornertrue + \fi + \fi + \else + \xa\ifnum\qr@k=\ii\relax + \ifnum\jj=1\relax + \qr@incornertrue + \fi + \fi + \fi + \ifqr@incorner + \relax + \else + \qr@placealignmentpattern@int{#1}{\qr@target@ii}{\qr@target@jj}% + \fi + }% ends \qr@for \jj + }% ends \qr@for \ii + \fi + \fi +}% + +\def\qr@placedummyformatpatterns#1{% + \qr@for \j = 1 to 9 by 1% + {\ifnum\j=7\relax% + \else% + \qr@storetomatrix{#1}{9}{\the\j}{\qr@format@square}% + \qr@storetomatrix{#1}{\the\j}{9}{\qr@format@square}% + \fi% + }% + \setcounter{qr@j}{\qr@size}% + \qr@for \j = 1 to 8 by 1% + {\qr@storetomatrix{#1}{9}{\theqr@j}{\qr@format@square}% + \qr@storetomatrix{#1}{\theqr@j}{9}{\qr@format@square}% + \addtocounter{qr@j}{-1}% + }% + %Now go back and change the \qr@format@square in (n-8,9) to \qr@black@fixed. + \addtocounter{qr@j}{1}% + \qr@storetomatrix{#1}{\theqr@j}{9}{\qr@black@fixed}% +}% + +\def\qr@placedummyversionpatterns#1{% + \xa\ifnum\qr@version>6\relax + %Must include version information. + \global\c@qr@i=\qr@size% + \global\advance\c@qr@i by -10\relax% + \qr@for \i = 1 to 3 by 1% + {\qr@for \j = 1 to 6 by 1% + {\qr@storetomatrix{#1}{\theqr@i}{\the\j}{\qr@format@square}% + \qr@storetomatrix{#1}{\the\j}{\theqr@i}{\qr@format@square}% + }% + \stepcounter{qr@i}% + }% + \fi +}% + +\def\qr@writebit(#1#2)#3{% + % #3 = matrix name + % (qr@i,qr@j) = position to write in (LaTeX counters) + % #1 = bit to be written + % #2 = remaining bits plus '\relax' as an end-of-file marker + \edef\qr@datatowrite{#2}% + \ifnum#1=1 + \qr@storetomatrix{#3}{\theqr@i}{\theqr@j}{\qr@black}% + \else + \qr@storetomatrix{#3}{\theqr@i}{\theqr@j}{\qr@white}% + \fi +}% + +\newif\ifqr@rightcol +\newif\ifqr@goingup + +\def\qr@writedata@hex#1#2{% + % #1 = name of a matrix that has been prepared with finder patterns, timing patterns, etc. + % #2 = a string consisting of bytes to write into the matrix, in two-char hex format. + \setcounter{qr@i}{\qr@numberofrowsinmatrix{#1}}% + \setcounter{qr@j}{\qr@numberofcolsinmatrix{#1}}% + \qr@rightcoltrue% + \qr@goinguptrue% + \edef\qr@argument{{#1}(#2\relax\relax\relax)}% + \xa\qr@writedata@hex@recursive\qr@argument% +}% + +\def\qr@writedata@hex@recursive#1(#2#3#4){% + % #1 = name of a matrix that has been prepared with finder patterns, timing patterns, etc. + % (qr@i,qr@j) = position to write in LaTeX counters + % #2#3#4 contains the hex codes of the bytes to be written, plus \relax\relax\relax + % as an end-of-file marker + \edef\qr@testii{#2}% + \ifx\qr@testii\qr@relax% + % #2 is \relax, so there is nothing more to write. + \relax + \let\qr@next=\relax + \else + % #2 is not \relax, so there is another byte to write. + \qr@hextobinary[8]{\bytetowrite}{#2#3}% + \xdef\qr@datatowrite{\bytetowrite\relax}% %Add terminating "\relax" + \qr@writedata@recursive{#1}% %This function actually writes the 8 bits. + \edef\qr@argument{{#1}(#4)}% + \xa\def\xa\qr@next\xa{\xa\qr@writedata@hex@recursive\qr@argument}% %Call self to write the next bit. + \fi + \qr@next +}% + +\def\qr@writedata#1#2{% + % #1 = name of a matrix that has been prepared with finder patterns, timing patterns, etc. + % #2 = a string consisting of 0's and 1's to write into the matrix. + \setcounter{qr@i}{\qr@numberofrowsinmatrix{#1}}% + \setcounter{qr@j}{\qr@numberofcolsinmatrix{#1}}% + \qr@rightcoltrue + \qr@goinguptrue + \edef\qr@datatowrite{#2\relax}% + \qr@writedata@recursive{#1}% +}% + +\def\qr@@blank{\qr@blank}% + +\def\qr@writedata@recursive#1{% + % #1 = matrix name + % (qr@i,qr@j) = position to write in (LaTeX counters) + % \qr@datatowrite contains the bits to be written, plus '\relax' as an end-of-file marker + \xa\let\xa\squarevalue\csname #1@\theqr@i @\theqr@j\endcsname% + \ifx\squarevalue\qr@@blank + %Square is blank, so write data in it. + \xa\qr@writebit\xa(\qr@datatowrite){#1}% + %The \qr@writebit macro not only writes the first bit of \qr@datatowrite into the matrix, + %but also removes the bit from the 'bitstream' of \qr@datatowrite. + \fi + %Now adjust our position in the matrix. + \ifqr@rightcol + %From the right-hand half of the two-bit column, we always move left. Easy peasy. + \addtocounter{qr@j}{-1}% + \qr@rightcolfalse + \else + %If we're in the left-hand column, things are harder. + \ifqr@goingup + %First, suppose we're going upwards. + \ifnum\c@qr@i>1\relax% + %If we're not in the first row, things are easy. + %We move one to the right and one up. + \addtocounter{qr@j}{1}% + \addtocounter{qr@i}{-1}% + \qr@rightcoltrue + \else + %If we are in the first row, then we move to the left, + %and we are now in the right-hand column on a downward pass. + \addtocounter{qr@j}{-1}% + \qr@goingupfalse + \qr@rightcoltrue + \fi + \else + %Now, suppose we're going downwards. + \xa\ifnum\qr@size>\c@qr@i\relax% + %If we're not yet in the bottom row, things are easy. + %We move one to the right and one down. + \addtocounter{qr@j}{1}% + \addtocounter{qr@i}{1}% + \qr@rightcoltrue + \else + %If we are in the bottom row, then we move to the left, + %and we are now in the right-hand column on an upward pass. + \addtocounter{qr@j}{-1}% + \qr@rightcoltrue + \qr@goinguptrue + \fi + \fi + %One problem: what if we just moved into the 7th column? + %Das ist verboten. + %If we just moved (left) into the 7th column, we should move on into the 6th column. + \ifnum\c@qr@j=7\relax% + \setcounter{qr@j}{6}% + \fi + \fi + %Now check whether there are any more bits to write. + \ifx\qr@datatowrite\qr@relax + % \qr@datatowrite is just `\relax', so we're done. + \let\qr@next=\relax + \relax + \else + % Write some more! + \def\qr@next{\qr@writedata@recursive{#1}}% + \fi + \qr@next +}% + +\def\qr@writeremainderbits#1{% + % #1 = name of a matrix that has been prepared and partly filled. + % (qr@i,qr@j) = position to write in LaTeX counters + \xa\ifnum\qr@numremainderbits>0\relax + \def\qr@datatowrite{}% + \qr@for \i = 1 to \qr@numremainderbits by 1% + {\g@addto@macro{\qr@datatowrite}{0}}% + \g@addto@macro{\qr@datatowrite}{\relax}% terminator + \qr@writedata@recursive{#1}% + \fi +}% + +\newif\ifqr@cellinmask + +\def\qr@setmaskingfunction#1{% + % #1 = 1 decimal digit for the mask. (I see no reason to use the 3-bit binary code.) + % The current position is (\themaski,\themaskj), with indexing starting at 0. + \edef\qr@maskselection{#1}% + \xa\ifcase\qr@maskselection\relax + %Case 0: checkerboard + \def\qr@parsemaskingfunction{% + % Compute mod(\themaski+\themaskj,2)% + \qr@a=\c@maski% + \advance\qr@a by \c@maskj% + \qr@b=\qr@a% + \divide\qr@b by 2% + \multiply\qr@b by 2% + \advance\qr@a by -\qr@b% + \edef\qr@maskfunctionresult{\the\qr@a}% + }% + \or + %Case 1: horizontal stripes + \def\qr@parsemaskingfunction{% + % Compute mod(\themaski,2)% + \ifodd\c@maski\relax% + \def\qr@maskfunctionresult{1}% + \else% + \def\qr@maskfunctionresult{0}% + \fi% + }% + \or + %Case 2: vertical stripes + \def\qr@parsemaskingfunction{% + % Compute mod(\themaskj,3)% + \qr@a=\c@maskj% + \divide\qr@a by 3% + \multiply\qr@a by 3% + \advance\qr@a by -\c@maskj% + \edef\qr@maskfunctionresult{\the\qr@a}% + }% + \or + %Case 3: diagonal stripes + \def\qr@parsemaskingfunction{% + % Compute mod(\themaski+\themaskj,3)% + \qr@a=\c@maski% + \advance\qr@a by \c@maskj% + \qr@b=\qr@a% + \divide\qr@b by 3% + \multiply\qr@b by 3% + \advance\qr@b by -\qr@a% + \edef\qr@maskfunctionresult{\the\qr@b}% + }% + \or + %Case 4: wide checkerboard + \def\qr@parsemaskingfunction{% + % Compute mod(floor(\themaski/2) + floor(\themaskj/3),2) % + \qr@a=\c@maski% + \divide\qr@a by 2% + \qr@b=\c@maskj% + \divide\qr@b by 3% + \advance\qr@a by \qr@b% + \qr@b=\qr@a% + \divide\qr@a by 2% + \multiply\qr@a by 2% + \advance\qr@a by -\qr@b% + \edef\qr@maskfunctionresult{\the\qr@a}% + }% + \or + %Case 5: quilt + \def\qr@parsemaskingfunction{% + % Compute mod(\themaski*\themaskj,2) + mod(\themaski*\themaskj,3) % + \qr@a=\c@maski% + \multiply\qr@a by \c@maskj% + \qr@b=\qr@a% + \qr@c=\qr@a% + \divide\qr@a by 2% + \multiply\qr@a by 2% + \advance\qr@a by -\qr@c% (result will be -mod(i*j,2), which is negative.) + \divide\qr@b by 3% + \multiply\qr@b by 3% + \advance\qr@b by -\qr@c% (result will be -mod(i*j,3), which is negative.) + \advance\qr@a by \qr@b% (result is negative of what's in the spec.) + \edef\qr@maskfunctionresult{\the\qr@a}% + }% + \or + %Case 6: arrows + \def\qr@parsemaskingfunction{% + % Compute mod( mod(\themaski*\themaskj,2) + mod(\themaski*\themaskj,3) , 2 ) % + \qr@a=\c@maski% + \multiply\qr@a by \c@maskj% + \qr@b=\qr@a% + \qr@c=\qr@a% + \multiply\qr@c by 2% % \qr@c equals 2*i*j. + \divide\qr@a by 2% + \multiply\qr@a by 2% + \advance\qr@c by -\qr@a% Now \qr@c equals i*j + mod(i*j,2). + \divide\qr@b by 3% + \multiply\qr@b by 3% + \advance\qr@c by -\qr@b% (Now \qr@c equals mod(i*j,2) + mod(i*j,3). + \qr@a=\qr@c% + \divide\qr@a by 2% + \multiply\qr@a by 2% + \advance\qr@c by-\qr@a% + \edef\qr@maskfunctionresult{\the\qr@c}% + }% + \or + %Case 7: shotgun + \def\qr@parsemaskingfunction{% + % Compute mod( mod(\themaski+\themaskj,2) + mod(\themaski*\themaskj,3) , 2 ) % + \qr@a=\c@maski% + \advance\qr@a by \c@maskj% %So \qr@a = i+j + \qr@b=\c@maski% + \multiply\qr@b by \c@maskj% %So \qr@b = i*j + \qr@c=\qr@a% + \advance\qr@c by \qr@b% So \qr@c = i+j+i*j + \divide\qr@a by 2% + \multiply\qr@a by 2% + \advance\qr@c by -\qr@a% So \qr@c = mod(i+j,2) + i*j + \divide\qr@b by 3% + \multiply\qr@b by 3% + \advance\qr@c by -\qr@b% So \qr@c = mod(i+j,2) + mod(i*j,3) + \qr@a=\qr@c% + \divide\qr@c by 2% + \multiply\qr@c by 2% + \advance\qr@a by -\qr@c% + \edef\qr@maskfunctionresult{\the\qr@a}% + }% + \fi +}% + + +\def\qr@checkifcellisinmask{% + % The current position is (\i,\j), in TeX counts, + % but the LaTeX counters (maski,maskj) should contain + % the current position with indexing starting at 0. + % That is, maski = \i-1 and maskj = \j-1. + % + % \qr@parsemaskingfunction must have been set by a call to \qr@setmaskingfunction + \qr@parsemaskingfunction + \xa\ifnum\qr@maskfunctionresult=0\relax + \qr@cellinmasktrue + \else + \qr@cellinmaskfalse + \fi +}% + +\newcounter{maski}% +\newcounter{maskj}% + +\def\qr@applymask#1#2#3{% + % #1 = name of a matrix that should be filled out completely + % except for the format and/or version information. + % #2 = name of a new matrix to contain the masked version + % #3 = 1 decimal digit naming the mask + \qr@createduplicatematrix{#2}{#1}% + \qr@setmaskingfunction{#3}% + \setcounter{maski}{-1}% + \qr@for \i = 1 to \qr@size by 1% + {\stepcounter{maski}% + \setcounter{maskj}{-1}% + \qr@for \j = 1 to \qr@size by 1% + {\stepcounter{maskj}% + \qr@checkifcellisinmask + \ifqr@cellinmask + \qr@checkifcurrentcellcontainsdata{#2}% + \ifqr@currentcellcontainsdata + \qr@flipcurrentcell{#2}% + \fi + \fi + }% + }% +}% + +\newif\ifqr@currentcellcontainsdata +\qr@currentcellcontainsdatafalse + +\def\qr@@white{\qr@white}% +\def\qr@@black{\qr@black}% + +\def\qr@checkifcurrentcellcontainsdata#1{% + % #1 = name of matrix + \qr@currentcellcontainsdatafalse + \xa\ifx\csname #1@\the\i @\the\j\endcsname\qr@@white + \qr@currentcellcontainsdatatrue + \fi + \xa\ifx\csname #1@\the\i @\the\j\endcsname\qr@@black + \qr@currentcellcontainsdatatrue + \fi +}% + +\def\qr@flipped@black{\qr@black}% +\def\qr@flipped@white{\qr@white}% + +\def\qr@flipcurrentcell#1{% + % #1 = name of matrix + % (\i, \j) = current position, in TeX counts. + % This assumes the cell contains data, either black or white! + \xa\ifx\csname #1@\the\i @\the\j\endcsname\qr@@white + \qr@storetomatrix{#1}{\the\i}{\the\j}{\qr@flipped@black}% + \else + \qr@storetomatrix{#1}{\the\i}{\the\j}{\qr@flipped@white}% + \fi +}% + +\def\qr@chooseandapplybestmask#1{% + % #1 = name of a matrix that should be filled out completely + % except for the format and/or version information. + % This function applies all eight masks in succession, + % calculates their penalties, and remembers the best. + % The number indicating which mask was used is saved in \qr@mask@selected. + \qr@createduplicatematrix{originalmatrix}{#1}% + \message{^^J}% + \gdef\qr@currentbestmask{0}% + \qr@for \i = 1 to 7 by 1% + {\message{^^J}% + \xa\xa\xa\ifnum\xa\qr@penalty\xa<\qr@currentbestpenalty\relax + %We found a better mask. + \xdef\qr@currentbestmask{\the\i}% + \qr@createduplicatematrix{#1}{currentmasked}% + \xdef\qr@currentbestpenalty{\qr@penalty}% + \fi + }% + \xdef\qr@mask@selected{\qr@currentbestmask}% + \message{^^J}% +}% + + +\def\qr@Ni{3}% +\def\qr@Nii{3}% +\def\qr@Niii{40}% +\def\qr@Niv{10}% +\def\qr@fiveones{11111}% +\def\qr@fivezeros{11111}% +\def\qr@twoones{11}% +\def\qr@twozeros{00}% +\def\qr@finderA{00001011101}% +\def\qr@finderB{10111010000}% +\def\qr@finderB@three{1011101000}% +\def\qr@finderB@two{101110100}% +\def\qr@finderB@one{10111010}% +\def\qr@finderB@zero{1011101}% +\newif\ifqr@stringoffive +\def\qr@addpenaltyiii{% + \addtocounter{penaltyiii}{\qr@Niii}% +}% +\newcounter{totalones}% +\newcounter{penaltyi}% +\newcounter{penaltyii}% +\newcounter{penaltyiii}% +\newcounter{penaltyiv}% +\def\qr@evaluatemaskpenalty#1{% + % #1 = name of a matrix that we will test for the penalty + % according to the specs. + \setcounter{penaltyi}{0}% + \setcounter{penaltyii}{0}% + \setcounter{penaltyiii}{0}% + \setcounter{penaltyiv}{0}% + \bgroup%localize the meanings we give to the symbols + \def\qr@black{1}\def\qr@white{0}% + \def\qr@black@fixed{1}\def\qr@white@fixed{0}% + \def\qr@format@square{0}% This is not stated in the specs, but seems + % to be the standard implementation. + \def\qr@blank{0}% These would be any bits at the end. + % + \setcounter{totalones}{0}% + \qr@for \i=1 to \qr@size by 1% + {\def\qr@lastfive{z}% %The z is a dummy, that will be removed before any testing. + \qr@stringoffivefalse + \def\qr@lasttwo@thisrow{z}% %The z is a dummy. + \def\qr@lasttwo@nextrow{z}% %The z is a dummy. + \def\qr@lastnine{z0000}% %The 0000 stands for the white space to the left. The z is a dummy. + \def\qr@ignore@finderB@at{0}% + \qr@for \j=1 to \qr@size by 1% + {\edef\qr@newbit{\qr@matrixentry{#1}{\the\i}{\the\j}}% + % + % LASTFIVE CODE FOR PENALTY 1 + % First, add the new bit to the end. + \xa\g@addto@macro\xa\qr@lastfive\xa{\qr@newbit}% + \ifnum\j<5\relax% + %Not yet on the 5th entry. + %Don't do any testing. + \else + % 5th entry or later. + % Remove the old one, and then test. + \qr@removefirsttoken\qr@lastfive% + \ifx\qr@lastfive\qr@fiveones% + \ifqr@stringoffive% + %This is a continuation of a previous block of five or more 1's. + \stepcounter{penaltyi}% + \else + %This is a new string of five 1's. + \addtocounter{penaltyi}{\qr@Ni}% + \global\qr@stringoffivetrue + \fi + \else + \ifx\qr@lastfive\qr@fivezeros% + \ifqr@stringoffive + %This is a continuation of a previous block of five or more 0's. + \stepcounter{penaltyi}% + \else + %This is a new string of five 0's. + \addtocounter{penaltyi}{\qr@Ni}% + \global\qr@stringoffivetrue + \fi + \else + %This is not a string of five 1's or five 0's. + \global\qr@stringoffivefalse + \fi + \fi + \fi + % + % 2x2 BLOCKS FOR PENALTY 2 + % Every 2x2 block of all 1's counts for \qr@Nii penalty points. + % We do not need to run this test in the last row. + \xa\ifnum\xa\i\xa<\qr@size\relax + \xa\g@addto@macro\xa\qr@lasttwo@thisrow\xa{\qr@newbit}% + %Compute \qr@iplusone + \qr@a=\i\relax% + \advance\qr@a by 1% + \edef\qr@iplusone{\the\qr@a}% + % + \edef\qr@nextrowbit{\qr@matrixentry{#1}{\qr@iplusone}{\the\j}}% + \xa\g@addto@macro\xa\qr@lasttwo@nextrow\xa{\qr@nextrowbit}% + \ifnum\j<2\relax% + %Still in the first column; no check. + \else + %Second column or later. Remove the old bits, and then test. + \qr@removefirsttoken\qr@lasttwo@thisrow + \qr@removefirsttoken\qr@lasttwo@nextrow + \ifx\qr@lasttwo@thisrow\qr@twoones + \ifx\qr@lasttwo@nextrow\qr@twoones + \addtocounter{penaltyii}{\qr@Nii}% + \fi + \else + \ifx\qr@lasttwo@thisrow\qr@twozeros + \ifx\qr@lasttwo@nextrow\qr@twozeros + \addtocounter{penaltyii}{\qr@Nii}% + \fi + \fi + \fi + \fi + \fi + % + % LASTNINE CODE FOR PENALTY 3 + % First, add the new bit to the end. + \xa\g@addto@macro\xa\qr@lastnine\xa{\qr@newbit}% + \ifnum\j<7\relax% + %Not yet on the 7th entry. + %Don't do any testing. + \else + % 7th entry or later. + % Remove the old one, and then test. + \qr@removefirsttoken\qr@lastnine + \xa\ifnum\qr@size=\j\relax% + % Last column. Any of the following should count: + % 1011101 (\qr@finderB@zero) + % 10111010 (\qr@finderB@one) + % 101110100 (\qr@finderB@two) + % 1011101000 (\qr@finderB@three) + % 10111010000 (\qr@finderB) + \ifx\qr@lastnine\qr@finderB + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@three + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@two + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@one + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@zero + \qr@addpenaltyiii + \fi + \fi + \fi + \fi + \fi + \else + \ifx\qr@lastnine\qr@finderA% %Matches 0000 1011101 + \qr@addpenaltyiii + %Also, we record our discovery, so that we can't count this pattern again + %if it shows up four columns later as 1011101 0000. + % + %Set \qr@ignore@finderB@at to \j+4. + \qr@a=\j\relax% + \advance\qr@a by 4% + \xdef\qr@ignore@finderB@at{\the\qr@a}% + \else + \ifx\qr@lastfive\qr@finderB% %Matches 1011101 0000. + \xa\ifnum\qr@ignore@finderB@at=\j\relax + %This pattern was *not* counted already earlier. + \qr@addpenaltyiii + \fi + \fi + \fi + \fi + \fi + % + %COUNT 1's FOR PENALTY 4 + \xa\ifnum\qr@newbit=1\relax% + \stepcounter{totalones}% + \fi + }% end of j-loop + }% end of i-loop + % + %NOW WE ALSO NEED TO RUN DOWN THE COLUMNS TO FINISH CALCULATING PENALTIES 1 AND 3. + \qr@for \j=1 to \qr@size by 1% + {\def\qr@lastfive{z}% %The z is a dummy, that will be removed before any testing. + \qr@stringoffivefalse + \def\qr@lastnine{z0000}% %The 0000 stands for the white space to the left. The z is a dummy. + \def\qr@ignore@finderB@at{0}% + \qr@for \i=1 to \qr@size by 1% + {\edef\qr@newbit{\qr@matrixentry{#1}{\the\i}{\the\j}}% + % + % LASTFIVE CODE FOR PENALTY 1 + % First, add the new bit to the end. + \xa\g@addto@macro\xa\qr@lastfive\xa{\qr@newbit}% + \ifnum\i<5\relax% + %Not yet on the 5th entry. + %Don't do any testing. + \else + % 5th entry or later. + % Remove the old one, and then test. + \qr@removefirsttoken\qr@lastfive% + \ifx\qr@lastfive\qr@fiveones% + \ifqr@stringoffive% + %This is a continuation of a previous block of five or more 1's. + \stepcounter{penaltyi}% + \else + %This is a new string of five 1's. + \addtocounter{penaltyi}{\qr@Ni}% + \global\qr@stringoffivetrue + \fi + \else + \ifx\qr@lastfive\qr@fivezeros% + \ifqr@stringoffive + %This is a continuation of a previous block of five or more 0's. + \stepcounter{penaltyi}% + \else + %This is a new string of five 0's. + \addtocounter{penaltyi}{\qr@Ni}% + \global\qr@stringoffivetrue + \fi + \else + %This is not a string of five 1's or five 0's. + \global\qr@stringoffivefalse + \fi + \fi + \fi + % + % HAPPILY, WE DON'T NEED TO CALCULATE PENALTY 2 AGAIN. + % + % LASTNINE CODE FOR PENALTY 3 + % First, add the new bit to the end. + \xa\g@addto@macro\xa\qr@lastnine\xa{\qr@newbit}% + \ifnum\i<7\relax% + %Not yet on the 7th entry. + %Don't do any testing. + \else + % 7th entry or later. + % Remove the old one, and then test. + \qr@removefirsttoken\qr@lastnine + \xa\ifnum\qr@size=\i\relax% + % Last column. Any of the following should count: + % 1011101 (\qr@finderB@zero) + % 10111010 (\qr@finderB@one) + % 101110100 (\qr@finderB@two) + % 1011101000 (\qr@finderB@three) + % 10111010000 (\qr@finderB) + \ifx\qr@lastnine\qr@finderB + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@three + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@two + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@one + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@zero + \qr@addpenaltyiii + \fi + \fi + \fi + \fi + \fi + \else + \ifx\qr@lastnine\qr@finderA% %Matches 0000 1011101 + \qr@addpenaltyiii + %Also, we record our discovery, so that we can't count this pattern again + %if it shows up four columns later as 1011101 0000. + % + %Set \qr@ignore@finderB@at to \i+4. + \qr@a=\i\relax% + \advance\qr@a by 4% + \xdef\qr@ignore@finderB@at{\the\qr@a}% + \else + \ifx\qr@lastfive\qr@finderB% %Matches 1011101 0000. + \xa\ifnum\qr@ignore@finderB@at=\i\relax + %This pattern was *not* counted already earlier. + \qr@addpenaltyiii + \fi + \fi + \fi + \fi + \fi + % + }% end of i-loop + }% end of j-loop + \egroup% + % + %CALCULATE PENALTY 4 + %According to the spec, penalty #4 is computed as + % floor( |(i/n^2)-0.5|/0.05 ) + % where i is the total number of 1's in the matrix. + % This is equal to abs(20*i-10n^2) div n^2. + % + \qr@a=\c@totalones\relax + \multiply\qr@a by 20\relax + \qr@b=\qr@size\relax + \multiply\qr@b by \qr@size\relax + \qr@c=10\relax + \multiply\qr@c by \qr@b\relax + \advance\qr@a by -\qr@c\relax + \ifnum\qr@a<0\relax + \multiply\qr@a by -1\relax + \fi + \divide\qr@a by \qr@b\relax + \setcounter{penaltyiv}{\the\qr@a}% + % + %CALCULATE TOTAL PENALTY + \qr@a=\thepenaltyi\relax% + \advance\qr@a by \thepenaltyii\relax% + \advance\qr@a by \thepenaltyiii\relax% + \advance\qr@a by \thepenaltyiv\relax% + \edef\qr@penalty{\the\qr@a}% +}% + +\def\qr@removefirsttoken#1{% + %Removes the first token from the macro named in #1. + \edef\qr@argument{(#1)}% + \xa\qr@removefirsttoken@int\qr@argument% + \xdef#1{\qr@removefirsttoken@result}% +}% +\def\qr@removefirsttoken@int(#1#2){% + \def\qr@removefirsttoken@result{#2}% +}% + +\def\qr@writeformatstring#1#2{% + % #1 = matrix name + % #2 = binary string representing the encoded and masked format information + \setcounter{qr@i}{9}% + \setcounter{qr@j}{1}% + \edef\qr@argument{{#1}(#2\relax)}% + \xa\qr@writeformatA@recursive\qr@argument + % + \setcounter{qr@i}{\qr@numberofrowsinmatrix{#1}}% + \setcounter{qr@j}{9}% + \xa\qr@writeformatB@recursive\qr@argument +}% + +\def\qr@writeformatA@recursive#1(#2#3){% + % #1 = matrix name + % #2 = first bit of string + % #3 = rest of bitstream + % (qr@i,qr@j) = current (valid) position to write (in LaTeX counters) + \ifnum#2=1\relax + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@black@format}% + \else + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@white@format}% + \fi + % Now the tricky part--moving \i and \j to their next positions. + \ifnum\c@qr@j<9\relax + %If we're not yet in column 9, move right. + \stepcounter{qr@j}% + \ifnum\c@qr@j=7\relax + %But we skip column 7! + \stepcounter{qr@j}% + \fi + \else + %If we're in column 9, we move up. + \addtocounter{qr@i}{-1}% + \ifnum\c@qr@i=7\relax + %But we skip row 7! + \addtocounter{qr@i}{-1}% + \fi + \fi + %N.B. that at the end of time, this will leave us at invalid position (0,9). + %That makes for an easy test to know when we are done. + \ifnum\c@qr@i<1 + \let\qr@next=\relax + \else + \def\qr@next{\qr@writeformatA@recursive{#1}(#3)}% + \fi + \qr@next +}% + +\def\qr@writeformatB@recursive#1(#2#3){% + % #1 = matrix name + % #2 = first bit of string + % #3 = rest of bitstream + % (qr@i,qr@j) = current (valid) position to write (in LaTeX counters) + \ifnum#2=1\relax + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@black@format}% + \else + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@white@format}% + \fi + % Now the tricky part--moving counters i and j to their next positions. + \qr@a=\qr@size% + \advance\qr@a by -6\relax% + \ifnum\qr@a<\c@qr@i\relax + %If we're not yet in row n-6, move up. + \addtocounter{qr@i}{-1}% + \else + \ifnum\qr@a=\c@qr@i\relax + %If we're actually in row n-6, we jump to position (9,n-7). + \setcounter{qr@i}{9}% + %Set counter j equal to \qr@size-7. + \global\c@qr@j=\qr@size\relax% + \global\advance\c@qr@j by -7\relax% + \else + %Otherwise, we must be in row 9. + %In this case, we move right. + \stepcounter{qr@j}% + \fi + \fi + %N.B. that at the end of time, this will leave us at invalid position (9,n+1). + %That makes for an easy test to know when we are done. + \xa\ifnum\qr@size<\c@qr@j\relax + \let\qr@next=\relax + \else + \def\qr@next{\qr@writeformatB@recursive{#1}(#3)}% + \fi + \qr@next +}% + +\def\qr@writeversionstring#1#2{% + % #1 = matrix name + % #2 = binary string representing the encoded version information + % + % Plot the encoded version string into the matrix. + % This is only done for versions 7 and higher. + \xa\ifnum\qr@version>6\relax + %Move to position (n-8,6). + \setcounter{qr@i}{\qr@size}\relax% + \addtocounter{qr@i}{-8}\relax% + \setcounter{qr@j}{6}% + \edef\qr@argument{{#1}(#2\relax)}% + \xa\qr@writeversion@recursive\qr@argument + \fi +}% + +\def\qr@writeversion@recursive#1(#2#3){% + % #1 = matrix name + % #2 = first bit of string + % #3 = rest of bitstream + % (qr@i,qr@j) = current (valid) position to write (in LaTeX counters) + % + % The version information is stored symmetrically in the matrix + % In two transposed regions, so we can write both at the same time. + % In the comments, we describe what happens in the lower-left region, + % not the upper-right. + % + %Set \qr@topline equal to n-10. + \qr@a=\qr@size\relax% + \advance\qr@a by -10\relax% + \edef\qr@topline{\the\qr@a}% + % + \ifnum#2=1\relax + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@black@format}% + \qr@storetomatrix{#1}{\theqr@j}{\theqr@i}{\qr@black@format}% + \else + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@white@format}% + \qr@storetomatrix{#1}{\theqr@j}{\theqr@i}{\qr@white@format}% + \fi + % Now the tricky part--moving counters i and j to their next positions. + \addtocounter{qr@i}{-1}% + \xa\ifnum\qr@topline>\c@qr@i\relax + %We've overshot the top of the region. + %We need to move left one column and down three. + \addtocounter{qr@j}{-1}% + \addtocounter{qr@i}{3}% + \fi + %N.B. that at the end of time, this will leave us at invalid position (n-8,0). + %That makes for an easy test to know when we are done. + \ifnum\c@qr@j<1\relax + \let\qr@next=\relax + \else + \def\qr@next{\qr@writeversion@recursive{#1}(#3)}% + \fi + \qr@next +}% +% \end{macrocode} +% +% \subsection{Encoding and error correction} +% \begin{macrocode} +\newcounter{qr@hexchars}% + +\def\qr@string@binarytohex#1{% + \qr@binarytohex{\qr@hex@result}{#1}% +}% + +\def\qr@encode@binary#1{% + % #1 = string of ascii characters, to be converted into bitstream + % + % We do this one entirely in hex, rather than binary, because we can. + \edef\qr@plaintext{#1}% + % + %First, the mode indicator. + \def\qr@codetext{4}% %This means `binary' + % + %Next, the character count. + \qr@getstringlength{\qr@plaintext}% + %Set \qr@charactercountlengthinhex to \qr@charactercountbits@byte/4% + \qr@a=\qr@charactercountbits@byte\relax% + \divide \qr@a by 4\relax% + \edef\qr@charactercountlengthinhex{\the\qr@a}% + \qr@decimaltohex[\qr@charactercountlengthinhex]{\qr@charactercount}{\qr@stringlength}% + \xa\g@addto@macro\xa\qr@codetext\xa{\qr@charactercount}% + % + %Now comes the actual data. + \edef\qr@argument{(,\qr@plaintext\relax\relax\relax)}% + \xa\qr@encode@ascii@recursive\qr@argument% + % + %Now the terminator. + \g@addto@macro\qr@codetext{0}% %This is '0000' in binary. + % + %There is no need to pad bits to make a multiple of 8, + %because the data length is already 4 + 8 + 8n + 4. + % + %Now add padding codewords if needed. + \setcounter{qr@hexchars}{0}% + \qr@getstringlength{\qr@codetext}% + \setcounter{qr@hexchars}{\qr@stringlength}% + %Set \qr@numpaddingcodewords equal to \qr@totaldatacodewords - qr@hexchars/2. + \qr@a=-\c@qr@hexchars\relax + \divide\qr@a by 2\relax + \advance\qr@a by \qr@totaldatacodewords\relax + \edef\qr@numpaddingcodewords{\the\qr@a}% + % + \xa\ifnum\qr@numpaddingcodewords<0% + \edef\ds{ERROR: Too much data! Over by \qr@numpaddingcodewords bytes.}\show\ds% + \fi% + \xa\ifnum\qr@numpaddingcodewords>0% + \qr@for \i = 2 to \qr@numpaddingcodewords by 2% + {\g@addto@macro{\qr@codetext}{ec11}}% + \xa\ifodd\qr@numpaddingcodewords\relax% + \g@addto@macro{\qr@codetext}{ec}% + \fi% + \fi% +}% + +\def\qr@encode@ascii@recursive(#1,#2#3){% + % #1 = hex codes translated so far + % #2 = next plaintext character to translate + % #3 = remainder of plaintext + \edef\qr@testii{#2}% + \ifx\qr@testii\qr@relax% + % All done! + \g@addto@macro\qr@codetext{#1}% + \else% + % Another character to translate. + \edef\qr@asciicode{\number`#2}% + \qr@decimaltohex[2]{\qr@newhexcodes}{\qr@asciicode}% + \edef\qr@argument{(#1\qr@newhexcodes,#3)}% + %\show\qr@argument + \xa\qr@encode@ascii@recursive\qr@argument% + \fi% +}% + +\def\qr@splitcodetextintoblocks{% + \setcounter{qr@i}{0}% + \qr@for \j = 1 to \qr@numshortblocks by 1% + {\stepcounter{qr@i}% + \qr@splitoffblock{\qr@codetext}{\theqr@i}{\qr@shortblock@size}% + }% + \xa\ifnum\qr@numlongblocks>0\relax% + \qr@for \j = 1 to \qr@numlongblocks by 1% + {\stepcounter{qr@i}% + \qr@splitoffblock{\qr@codetext}{\theqr@i}{\qr@longblock@size}% + }% + \fi% +}% + +\def\qr@splitoffblock#1#2#3{% + % #1 = current codetext in hexadecimal + % #2 = number to use in csname "\datablock@#2". + % #3 = number of bytes to split off + \message{}% + \xa\gdef\csname datablock@#2\endcsname{}% %This line is important! + \qr@for \i = 1 to #3 by 1% + {\edef\qr@argument{{#2}(#1)}% + \xa\qr@splitoffblock@int\qr@argument% + }% +}% + +\def\qr@splitoffblock@int#1(#2#3#4){% + % #1 = number to use in csname "\datablock@#1". + % #2#3 = next byte to split off + % #4 = remaining text + % + % We add the next byte to "\datablock@#1", + % and we remove it from the codetext. + \xa\xdef\csname datablock@#1\endcsname{\csname datablock@#1\endcsname#2#3}% + \xdef\qr@codetext{#4}% +}% + +\def\qr@createerrorblocks{% + \qr@for \ii = 1 to \qr@numblocks by 1% + {\message{}% + \FX@generate@errorbytes{\csname datablock@\the\ii\endcsname}{\qr@num@eccodewords}% + \xa\xdef\csname errorblock@\the\ii\endcsname{\FX@errorbytes}% + }% +}% + +\def\qr@interleave{% + \setcounter{qr@i}{0}% + \def\qr@interleaved@text{}% + \message{0\relax% + \message{\qr@longblock@size.>}% + \else + \message{.>}% + \fi + \message{}% +}% + +\def\qr@writefromblock#1#2{% + % #1 = either 'datablock' or 'errorblock' + % #2 = block number, in {1,...,\qr@numblocks}% + \edef\qr@argument{(\csname #1@#2\endcsname\relax\relax\relax)}% + \xa\qr@writefromblock@int\qr@argument + \xa\xdef\csname #1@#2\endcsname{\qr@writefromblock@remainder}% +}% + +\def\qr@writefromblock@int(#1#2#3){% + % #1#2 = first byte (in hex) of text, which will be written to \qr@interleaved@text + % #3 = remainder, including \relax\relax\relax terminator. + \g@addto@macro{\qr@interleaved@text}{#1#2}% + \qr@writefromblock@intint(#3)% +}% + +\def\qr@writefromblock@intint(#1\relax\relax\relax){% + \xdef\qr@writefromblock@remainder{#1}% +}% +% \end{macrocode} +% +% \subsection{Encoding format and version information} +% \begin{macrocode} +\let\xa=\expandafter +\makeatletter + +\def\qr@preface@macro#1#2{% + % #1 = macro name + % #2 = text to add to front of macro + \def\qr@tempb{#2}% + \xa\xa\xa\gdef\xa\xa\xa#1\xa\xa\xa{\xa\qr@tempb #1}% +}% + +\newif\ifqr@leadingcoeff +\def\qr@testleadingcoeff(#1#2){% + % Tests whether the leading digit of #1#2 is 1. + \ifnum#1=1\relax + \qr@leadingcoefftrue + \else + \qr@leadingcoefffalse + \fi +}% + +\def\qr@polynomialdivide#1#2{% + \edef\qr@numerator{#1}% + \edef\qr@denominator{#2}% + \qr@divisiondonefalse% + \xa\xa\xa\qr@oneroundofdivision\xa\xa\xa{\xa\qr@numerator\xa}\xa{\qr@denominator}% +}% + +\def\@qr@empty{}% +\def\qr@oneroundofdivision#1#2{% + % #1 = f(x), of degree n + % #2 = g(x), of degree m + % Obtains a new polynomial h(x), congruent to f(x) modulo g(x), + % but of degree at most n-1. + % + % If leading coefficient of f(x) is 1, subtracts off g(x) * x^(n-m). + % If leading coefficient of f(x) is 0, strips off that leading zero. + % + \qr@testleadingcoeff(#1)% + \ifqr@leadingcoeff + \qr@xorbitstrings{#1}{#2}% + \ifqr@xorfailed + %If xor failed, that means our #1 was already the remainder! + \qr@divisiondonetrue + \edef\qr@theremainder{#1}% + \else + %xor succeeded. We need to recurse. + \xa\xa\xa\edef\xa\xa\xa\qr@numerator\xa\xa\xa{\xa\qr@stripleadingzero\xa(\qr@xorresult)}% + \fi + \else + \xa\def\xa\qr@numerator\xa{\qr@stripleadingzero(#1)}% + \ifx\qr@numerator\@qr@empty + \qr@divisiondonetrue + \def\qr@theremainder{0}% + \fi + \fi + \ifqr@divisiondone + \relax + \else + \xa\qr@oneroundofdivision\xa{\qr@numerator}{#2}% + \fi +}% + +\def\qr@stripleadingzero(0#1){#1}%Strips off a leading zero. + +\newif\ifqr@xorfailed% This flag will trigger when #2 is longer than #1. + +\def\qr@xorbitstrings#1#2{% + % #1 = bitstring + % #2 = bitstring no longer than #1 + \qr@xorfailedfalse + \edef\qr@argument{(,#1\relax\relax)(#2\relax\relax)}% + \xa\qr@xorbitstrings@recursive\qr@argument + %\qr@xorbitstrings@recursive(,#1\relax\relax)(#2\relax\relax)% +}% + +\def\qr@xorbitstrings@recursive(#1,#2#3)(#4#5){% + % #1#2#3 is the first bitstring, xor'ed up through #1. + % #4#5 is the remaining portion of the second bitstring. + \def\qr@testii{#2}% + \def\qr@testiv{#4}% + \ifx\qr@testii\qr@relax + % #1 contains the whole string. + % Now if #4 is also \relax, that means the two strings started off with equal lengths. + % If, however, #4 is not \relax, that means the second string was longer than the first, a problem. + \ifx\qr@testiv\qr@relax + %No problem. We are done. + \qr@xorbit@saveresult(#1#2#3)% + \else + %Problem! The second string was longer than the first. + \qr@xorfailedtrue + \def\qr@xorresult{}% + \fi + \else + % There is still a bit to manipulate in #2. + % Check whether #4 contains anything. + \ifx\qr@testiv\qr@relax + % No, #4 is empty. We are done. "#2#3" contains the remainder of the first string, + % which we append untouched and then strip off the two \relax-es. + \qr@xorbit@saveresult(#1#2#3)% + \else + % Yes, #4 still has something to XOR. Do the task. + \ifnum#2=#4\relax + \qr@xorbitstrings@recursive(#1% + 0,#3)(#5)% + \else + \qr@xorbitstrings@recursive(#1% + 1,#3)(#5)% + \fi + \fi + \fi +}% + +\def\qr@xorbit@saveresult(#1\relax\relax){% + %Strips off the extra '\relax'es at the end. + \def\qr@xorresult{#1}% +}% + +\newif\ifqr@divisiondone + +\def\qr@BCHcode#1{% + \edef\qr@formatinfo{#1}% + \def\qr@formatinfopadded{\qr@formatinfo 0000000000}% + \def\qr@divisor{10100110111}% + \qr@divisiondonefalse + \qr@polynomialdivide{\qr@formatinfopadded}{\qr@divisor}% + % + \qr@getstringlength{\qr@theremainder}% + %Run loop from stringlength+1 to 10. + \qr@a=\qr@stringlength\relax% + \advance\qr@a by 1\relax% + \qr@for \i = \qr@a to 10 by 1% + {\qr@preface@macro{\qr@theremainder}{0}% + \xdef\qr@theremainder{\qr@theremainder}% + }% + \edef\qr@BCHresult{\qr@formatinfo\qr@theremainder}% +}% + +\def\qr@formatmask{101010000010010}% + +\def\qr@encodeandmaskformat#1{% + \qr@BCHcode{#1}% + \qr@xorbitstrings{\qr@BCHresult}{\qr@formatmask}% + \edef\qr@format@bitstring{\qr@xorresult}% +}% + +\def\qr@Golaycode#1{% + % #1 = 6-bit version number + \edef\qr@versioninfo{#1}% + \def\qr@versioninfopadded{\qr@versioninfo 000000000000}% %Append 12 zeros. + \def\qr@divisor{1111100100101}% + \qr@divisiondonefalse + \qr@polynomialdivide{\qr@versioninfopadded}{\qr@divisor}% + % + \qr@getstringlength{\qr@theremainder}% + %Run loop from stringlength+1 to 12. + \qr@a=\qr@stringlength\relax% + \advance\qr@a by 1\relax% + \qr@for \i = \qr@a to 12 by 1% + {\qr@preface@macro{\qr@theremainder}{0}% + \xdef\qr@theremainder{\qr@theremainder}% + }% + \edef\qr@Golayresult{\qr@versioninfo\qr@theremainder}% +}% +% \end{macrocode} +% +% \subsection{Error correction} +% The error-correction code is defined over $\F_{256}=GF(256)$, +% the finite field of order $256$. +% The QR specification encodes this field as $\F_2[X]/(X^8+X^4+X^3+X^2+1)$; +% in other words, each field element is an 8-bit binary string representing +% an integer between 0 and 255. +% +% We represent these 8-bit strings as two hexadecimal characters; +% for example, {\tt 5a} represents {\tt 01011010}. +% Because addition is done by xor-ing the bitstrings, +% we can define addition on hexadecimal characters. +% Since there are only $16^2$ possibilities, +% we create a lookup table. +% \begin{macrocode} +\def\F@result{}% + +\def\qr@xorbitstring#1#2#3{% + % #1 = new macro to receive result + % #2, #3 = bitstrings to xor. The second can be shorter than the first. + \def\qr@xor@result{}% + \edef\qr@argument{(#2\relax\relax)(#3\relax\relax)}% + \xa\qr@xorbitstring@recursive\qr@argument% + \edef#1{\qr@xor@result}% +}% +\def\qr@xorbitstring@recursive(#1#2)(#3#4){% + \edef\qr@testi{#1}% + \ifx\qr@testi\qr@relax% + %Done. + \let\qr@next=\relax% + \else + \if#1#3\relax + \g@addto@macro{\qr@xor@result}{0}% + \else + \g@addto@macro{\qr@xor@result}{1}% + \fi + \edef\qr@next{\noexpand\qr@xorbitstring@recursive(#2)(#4)}% + \fi + \qr@next +} + +\def\F@addchar@raw#1#2{% + %Add two hexadecimal digits using bitwise xor + \qr@hextobinary[4]{\qr@summandA}{#1}% + \qr@hextobinary[4]{\qr@summandB}{#2}% + \qr@xorbitstring{\F@result}{\qr@summandA}{\qr@summandB}% + \qr@binarytohex[1]{\F@result}{\F@result}% +}% + +\def\qr@canceltwos#1{% + \edef\qr@argument{(#1\relax\relax)}% + \xa\qr@canceltwos@int\qr@argument% +}% + +\def\qr@canceltwos@int(#1#2){% + \xa\qr@canceltwos@recursion(,#1#2)% +}% + +\def\qr@canceltwos@recursion(#1,#2#3){% + \def\qr@testii{#2}% + \ifx\qr@testii\qr@relax + %Cancelling complete. + \qr@striptworelaxes(#1#2#3)% + %Now \F@result contains the answer. + \else + \relax + \ifnum#2=2\relax + \qr@canceltwos@recursion(#10,#3)% + \else + \qr@canceltwos@recursion(#1#2,#3)% + \fi + \fi +}% + +\def\qr@striptworelaxes(#1\relax\relax){% + \gdef\F@result{#1}% +}% + +\qr@for \i = 0 to 15 by 1% + {\qr@decimaltohex[1]{\qr@tempa}{\the\i}% + \qr@for \j = 0 to 15 by 1% + {\qr@decimaltohex[1]{\qr@tempb}{\the\j}% + \F@addchar@raw\qr@tempa\qr@tempb + \xa\xdef\csname F@addchar@\qr@tempa\qr@tempb\endcsname{\F@result}% + }% + }% + +\def\F@addchar#1#2{% + \xa\def\xa\F@result\xa{\csname F@addchar@#1#2\endcsname}% +}% + +\def\F@addstrings#1#2{% + \edef\qr@argument{(,#1\relax\relax)(#2\relax\relax)}% + \xa\F@addstrings@recursion\qr@argument% +}% + +\def\F@addstrings@recursion(#1,#2#3)(#4#5){% + %Adds two hexadecimal strings, bitwise, from left to right. + %The second string is allowed to be shorter than the first. + \def\qr@testii{#2}% + \def\qr@testiv{#4}% + \ifx\qr@testii\qr@relax + %The entire string has been processed. + \gdef\F@result{#1}% + \else + \ifx\qr@testiv\qr@relax + %The second string is over. + \qr@striptworelaxes(#1#2#3)% + %Now \F@result contains the answer. + \else + %We continue to add. + \F@addchar{#2}{#4}% + \edef\qr@argument{(#1\F@result,#3)(#5)}% + \xa\F@addstrings@recursion\qr@argument% + \fi + \fi +}% +% \end{macrocode} +% Now we handle multiplication. +% Our approach to multiplying $a,b\in\F_{256}$ +% is to take discrete logarithms (with 2 as our base), +% add the logarithms, and then take the antilog. +% We first create a log table. +% \begin{macrocode} +\gdef\F@stripleadingzero(0#1){\edef\F@result{#1}}% + +\setcounter{qr@i}{0}% +\def\qr@poweroftwo{1}% +\qr@for \i = 1 to 254 by 1% + {\stepcounter{qr@i}% + \qr@a=\qr@poweroftwo\relax + \multiply\qr@a by 2\relax + \edef\qr@poweroftwo{\the\qr@a}% + %\show\qr@poweroftwo + \qr@decimaltohex[2]{\qr@poweroftwo@hex}{\qr@poweroftwo}% + \xa\ifnum\qr@poweroftwo>255\relax + %We need to bitwise add the polynomial represented by 100011101, i.e. 0x11d. + \F@addstrings{\qr@poweroftwo@hex}{11d}% %Now it should start with 0. + \xa\F@stripleadingzero\xa(\F@result)% %Now it should be two hex digits. + \edef\qr@poweroftwo@hex{\F@result}% %Save the hex version. + \qr@hextodecimal{\qr@poweroftwo}{\F@result}% + \fi + \xdef\qr@poweroftwo{\qr@poweroftwo}% + \xa\xdef\csname F@twotothe@\theqr@i\endcsname{\qr@poweroftwo@hex}% + \xa\xdef\csname F@logtwo@\qr@poweroftwo@hex\endcsname{\theqr@i}% + }% +\xa\xdef\csname F@twotothe@0\endcsname{01}% +\xa\xdef\csname F@logtwo@01\endcsname{0}% + +\def\F@twotothe#1{% + \xa\xdef\xa\F@result\xa{\csname F@twotothe@#1\endcsname}% +}% +\def\F@logtwo#1{% + \xa\xdef\xa\F@result\xa{\csname F@logtwo@#1\endcsname}% +}% + +\def\qr@zerozero{00}% + +\def\F@multiply#1#2{% + % #1 and #2 are two elements of F_256, + % given as two-character hexadecimal strings. + % Multiply them within F_256, and place the answer in \F@result + \edef\qr@argA{#1}% + \edef\qr@argB{#2}% + \ifx\qr@argA\qr@zerozero + \def\F@result{00}% + \else + \ifx\qr@argB\qr@zerozero + \def\F@result{00}% + \else + \xa\F@logtwo\xa{\qr@argA}% + \edef\qr@logA{\F@result}% + \xa\F@logtwo\xa{\qr@argB}% + \edef\qr@logB{\F@result}% + \xa\qr@a\xa=\qr@logA\relax% \qr@a = \qr@logA + \xa\advance\xa\qr@a\qr@logB\relax% \advance \qr@a by \qr@logB + \ifnum\qr@a>254\relax% + \advance\qr@a by -255\relax% + \fi% + \xa\F@twotothe\xa{\the\qr@a}% + % Now \F@result contains the product, as desired. + \fi + \fi +}% + + +\def\F@multiply#1#2{% + % #1 and #2 are two elements of F_256, + % given as two-character hexadecimal strings. + % Multiply them within F_256, and place the answer in \F@result + \edef\qr@argA{#1}% + \edef\qr@argB{#2}% + \ifx\qr@argA\qr@zerozero + \def\F@result{00}% + \else + \ifx\qr@argB\qr@zerozero + \def\F@result{00}% + \else + \xa\F@logtwo\xa{\qr@argA}% + \edef\qr@logA{\F@result}% + \xa\F@logtwo\xa{\qr@argB}% + \edef\qr@logB{\F@result}% + \xa\qr@a\xa=\qr@logA\relax% \qr@a = \qr@logA + \xa\advance\xa\qr@a\qr@logB\relax% \advance \qr@a by \qr@logB + \ifnum\qr@a>254\relax% + \advance\qr@a by -255\relax% + \fi% + \xa\F@twotothe\xa{\the\qr@a}% + % Now \F@result contains the product, as desired. + \fi + \fi +}% +% \end{macrocode} +% Having developed $\F_{256}$, we now turn to the real task. +% Each byte of data is read as an element of $\F_{256}$, +% and a sequence of bytes corresponds a polynomial in +% $\F_{256}[X]$. +% The Reed-Solomon code takes that codeword $f(X)\in \F_{256}[X]$ +% of degree $k$, divides $f(X)\cdot X^\ell$ by a fixed +% polynomial, +% and keeps the remainder $r(X)$ as the error-correction word. +% We therefore must implement polynomial division over $\F_{256}$. +% \begin{macrocode} +%These polynomials are represented as sequences of coefficients, +%from highest power to lowest, +%with each coefficient represented by two hexadecimal characters. + +\def\FX@getstringlength#1{% + %Count number of two-character coefficients + \setcounter{qr@i}{0}% + \xdef\qr@argument{(#1\relax\relax\relax)}% + \xa\FX@stringlength@recursive\qr@argument% + \xdef\stringresult{\arabic{qr@i}}% +}% + +\def\FX@stringlength@recursive(#1#2#3){% + \def\qr@testi{#1}% + \ifx\qr@testi\qr@relax + %we are done. + \else + \stepcounter{qr@i}% + %\showthe\c@qr@i + \qr@stringlength@recursive(#3)% + \fi +}% + +\newif\ifFX@leadingcoeff@zero +\def\FX@testleadingcoeff(#1#2#3){% + % Tests whether the leading coefficient of the hex-string #1#2#3 is '00'. + \edef\FX@leadingcoefficient{#1#2}% + \FX@leadingcoeff@zerofalse + \ifx\FX@leadingcoefficient\qr@zerozero + \FX@leadingcoeff@zerotrue + \fi +}% + +\newif\ifFX@divisiondone + +\newcounter{qr@divisionsremaining} %Keep track of how many divisions to go! +\def\FX@polynomialdivide#1#2{% + \edef\FX@numerator{#1}% + \edef\FX@denominator{#2}% + \qr@getstringlength\FX@numerator% + \setcounter{qr@divisionsremaining}{\qr@stringlength}% + \qr@getstringlength\FX@denominator% + \addtocounter{qr@divisionsremaining}{-\qr@stringlength}% + \addtocounter{qr@divisionsremaining}{2}% + \divide\c@qr@divisionsremaining by 2\relax% %2 hex chars per number + \FX@divisiondonefalse% + \xa\xa\xa\FX@polynomialdivide@recursive\xa\xa\xa{\xa\FX@numerator\xa}\xa{\FX@denominator}% +}% + +\def\FX@polynomialdivide@recursive#1#2{% + % #1 = f(x), of degree n + % #2 = g(x), of degree m + % Obtains a new polynomial h(x), congruent to f(x) modulo g(x), + % but of degree at most n-1. + % + % If leading coefficient of f(x) is 0, strips off that leading zero. + % If leading coefficient of f(x) is a, subtracts off a * g(x) * x^(n-m). + % N.B. we assume g is monic. + % + \FX@testleadingcoeff(#1)% + \ifFX@leadingcoeff@zero% + %Leading coefficient is zero, so remove it. + \xa\def\xa\FX@numerator\xa{\FX@stripleadingzero(#1)}% + \else% + %Leading coefficient is nonzero, and contained in \FX@leadingcoefficient + \FX@subtractphase{#1}{#2}{\FX@leadingcoefficient}% + \ifFX@subtract@failed% + %If subtraction failed, that means our #1 was already the remainder! + \FX@divisiondonetrue% + \edef\qr@theremainder{#1}% + \else% + %xor succeeded. We need to recurse. + \xa\xa\xa\edef\xa\xa\xa\FX@numerator\xa\xa\xa{\xa\FX@stripleadingzero\xa(\FX@subtraction@result)}% + \fi% + \fi% + \addtocounter{qr@divisionsremaining}{-1}% + \ifnum\c@qr@divisionsremaining=0\relax + %Division is done! + \FX@divisiondonetrue% + \edef\qr@theremainder{\FX@numerator}% + \relax% + \else% + \xa\FX@polynomialdivide@recursive\xa{\FX@numerator}{#2}% + \fi% +}% + +\def\FX@stripleadingzero(00#1){#1}%Strips off a single leading zero of F_256. + +\newif\ifFX@subtract@failed% This flag will trigger when #2 is longer than #1. + +\def\FX@subtractphase#1#2#3{% + % #1 = bitstring + % #2 = bitstring no longer than #1 + % #3 = leading coefficient + \FX@subtract@failedfalse% + \edef\qr@argument{(,#1\relax\relax\relax)(#2\relax\relax\relax)(#3)}% + \xa\FX@subtract@recursive\qr@argument% +}% + +\def\FX@subtract@recursive(#1,#2#3#4)(#5#6#7)(#8){% + % This is a recursive way to compute f(x) - a*g(x)*x^k. + % #1#2#3#4 is the first bitstring, subtracted up through #1. + % Thus #2#3 constitutes the next two-character coefficient. + % #5#6#7 is the remaining portion of the second bitstring. + % Thus #5#6 constitutes the next two-character coefficient + % #8 is the element a of F_256. It should contain two characters. + \def\qr@testii{#2}% + \def\qr@testv{#5}% + \ifx\qr@testii\qr@relax + % #1 contains the whole string. + % Now if #5 is also \relax, that means the two strings started off with equal lengths. + % If, however, #5 is not \relax, that means the second string was longer than the first, a problem. + \ifx\qr@testv\qr@relax + %No problem. We are done. + \FX@subtract@saveresult(#1#2#3#4)% %We keep the #2#3#4 to be sure we have all three relax-es to strip off. + \else + %Problem! The second string was longer than the first. + %This usually indicates the end of the long division process. + \FX@subtract@failedtrue + \def\FX@subtraction@result{}% + \fi + \else + % There is still a coefficient to manipulate in #2#3. + % Check whether #5 contains anything. + \ifx\qr@testv\qr@relax + % No, #5 is empty. We are done. "#2#3#4" contains the remainder of the first string, + % which we append untouched and then strip off the three \relax-es. + \FX@subtract@saveresult(#1#2#3#4)% + \else + % Yes, #5#6 still has something to XOR. Do the task. + \F@multiply{#5#6}{#8}% Multiply by the factor 'a'. + \F@addstrings{#2#3}{\F@result}% Subtract. (We're in characteristic two, so adding works.) + \edef\qr@argument{(#1\F@result,#4)(#7)(#8)}% + \xa\FX@subtract@recursive\qr@argument% + \fi + \fi +}% + +\def\FX@subtract@saveresult(#1\relax\relax\relax){% + %Strips off the three extra '\relax'es at the end. + \def\FX@subtraction@result{#1}% +}% + +\def\FX@creategeneratorpolynomial#1{% + % #1 = n, the number of error codewords desired. + % We need to create \prod_{j=0}^{n-1} (x-2^j). + \edef\FX@generator@degree{#1}% + \def\FX@generatorpolynomial{01}% Initially, set it equal to 1. + \setcounter{qr@i}{0}% + \FX@creategenerator@recursive% + %The result is now stored in \FX@generatorpolynomial +}% + +\def\FX@creategenerator@recursive{% + % \c@qr@i contains the current value of i. + % \FX@generatorpolynomial contains the current polynomial f(x), + % which should be a degree-i polynomial + % equal to \prod_{j=0}^{i-1} (x-2^j). + % (If i=0, then \FX@generatorpolynomial should be 01.) + % This recursion step should multiply the existing polynomial by (x-2^i), + % increment i by 1, and check whether we're done or not. + \edef\qr@summandA{\FX@generatorpolynomial 00}% This is f(x) * x + \edef\qr@summandB{00\FX@generatorpolynomial}% This is f(x), with a 0x^{i+1} in front. + \F@twotothe{\theqr@i}% + \edef\qr@theconstant{\F@result}% + \FX@subtractphase{\qr@summandA}{\qr@summandB}{\qr@theconstant}% + %This calculates \qr@summandA + \qr@theconstant * \qr@summandB + %and stores the result in \FX@subtraction@result + \edef\FX@generatorpolynomial{\FX@subtraction@result}% + \stepcounter{qr@i}% + \xa\ifnum\FX@generator@degree=\c@qr@i\relax% + %We just multiplied by (x-2^{n-1}), so we're done. + \relax% + \else% + %We need to do this again! + \xa% + \FX@creategenerator@recursive% + \fi% +}% + +\def\FX@generate@errorbytes#1#2{% + % #1 = datastream in hex + % #2 = number of error correction bytes requested + \edef\qr@numerrorbytes{#2}% + \xa\FX@creategeneratorpolynomial\xa{\qr@numerrorbytes}% + \edef\FX@numerator{#1}% + \qr@for \i = 1 to \qr@numerrorbytes by 1% + {\g@addto@macro\FX@numerator{00}}% %One error byte means two hex codes. + \FX@polynomialdivide{\FX@numerator}{\FX@generatorpolynomial}% + \edef\FX@errorbytes{\qr@theremainder}% +}% +% \end{macrocode} +% +% \subsection{Version handling} +% \begin{macrocode} +\newif\ifqr@versionmodules + +\def\qr@level@char#1{% + \xa\ifcase#1 + M\or L\or H\or Q\fi}% + +\newif\ifqr@versiongoodenough +\def\qr@choose@best@version#1{% + % \qr@desiredversion = user-requested version + % \qr@desiredlevel = user-requested error-correction level + \edef\qr@plaintext{#1}% + \qr@getstringlength{\qr@plaintext}% + % + %Run double loop over levels and versions, looking for + %the smallest version that can contain our data, + %and then choosing the best error-correcting level at that version, + %subject to the level being at least as good as the user desires. + \global\qr@versiongoodenoughfalse% + \gdef\qr@bestversion{0}% + \gdef\qr@bestlevel{0}% + \ifnum\qr@desiredversion=0\relax + \qr@a=1\relax + \else + \qr@a=\qr@desiredversion\relax + \fi + \qr@for \i=\qr@a to 40 by 1 + {\edef\qr@version{\the\i}% + \global\qr@versiongoodenoughfalse + \qr@for \j=0 to 3 by 1% + {%First, we map {0,1,2,3} to {1,0,4,3}, so that we loop through {M,L,H,Q} + %in order of increasing error-correction capabilities. + \qr@a = \j\relax + \divide \qr@a by 2\relax + \multiply \qr@a by 4\relax + \advance \qr@a by 1\relax + \advance \qr@a by -\j\relax + \edef\qr@level{\the\qr@a}% + \ifnum\qr@desiredlevel=\qr@a\relax + \global\qr@versiongoodenoughtrue + \fi + \ifqr@versiongoodenough + \qr@calculate@capacity{\qr@version}{\qr@level}% + \xa\xa\xa\ifnum\xa\qr@truecapacity\xa<\qr@stringlength\relax + %Too short + \relax + \else + %Long enough! + \xdef\qr@bestversion{\qr@version}% + \xdef\qr@bestlevel{\qr@level}% + \global\i=40% + \fi + \fi + }% + }% + \edef\qr@version{\qr@bestversion}% + \edef\qr@level{\qr@bestlevel}% + \xa\ifnum\qr@desiredversion>0\relax + \ifx\qr@bestversion\qr@desiredversion\relax + %No change from desired version. + \else + %Version was increased + \message{^^J}% + \fi + \fi + \ifx\qr@bestlevel\qr@desiredlevel\relax + %No change in level. + \else + \message{^^J}% + \fi +}% + +\def\qr@calculate@capacity#1#2{% + \edef\qr@version{#1}% + \edef\qr@level{#2}% + %Calculate \qr@size, the number of modules per side. + % The formula is 4\qr@version+17. + \qr@a=\qr@version\relax% + \multiply\qr@a by 4\relax% + \advance\qr@a by 17\relax% + \edef\qr@size{\the\qr@a}% + % + % Calculate \qr@k, which governs the number of alignment patterns. + % The alignment patterns lie in a kxk square, except for 3 that are replaced by finding patterns. + % The formula is 2 + floor( \qr@version / 7 ), except that k=0 for version 1. + \xa\ifnum\qr@version=1\relax% + \def\qr@k{0}% + \else% + \qr@a=\qr@version\relax + \divide \qr@a by 7\relax + \advance\qr@a by 2\relax + \edef\qr@k{\the\qr@a}% + \fi% + % + %Calculate number of function pattern modules. + %This consists of the three 8x8 finder patterns, the two timing strips, and the (k^2-3) 5x5 alignment patterns. + %The formula is 160+2n+25(k^2-3)-10(k-2), unless k=0 in which case we just have 160+2n. + \qr@a=\qr@size\relax + \multiply\qr@a by 2\relax + \advance\qr@a by 160\relax + \xa\ifnum\qr@k=0\relax\else + %\qr@k is nonzero, hence at least 2, so we continue to add 25(k^2-3)-10(k-2). + \qr@b=\qr@k\relax + \multiply\qr@b by \qr@k\relax + \advance\qr@b by -3\relax + \multiply\qr@b by 25\relax + \advance\qr@a by \qr@b\relax + \qr@b=\qr@k\relax + \advance\qr@b by -2\relax + \multiply\qr@b by 10\relax + \advance\qr@a by -\qr@b\relax + \fi + \edef\qr@numfunctionpatternmodules{\the\qr@a}% + % + %Calculate the number of version modules, either 36 or 0. + \xa\ifnum\qr@version>6\relax + \qr@versionmodulestrue + \def\qr@numversionmodules{36}% + \else + \qr@versionmodulesfalse + \def\qr@numversionmodules{0}% + \fi + % + %Now calculate the codeword capacity and remainder bits. + %Take n^2 modules, subtract all those dedicated to finder patterns etc., format information, and version information, + %and what's left is the number of bits we can play with. + %The number of complete bytes is \qr@numdatacodewords; + %the leftover bits are \qr@numremainderbits. + \qr@a=\qr@size\relax + \multiply \qr@a by \qr@size\relax + \advance \qr@a by -\qr@numfunctionpatternmodules\relax + \advance \qr@a by -31\relax% % There are 31 format modules. + \advance \qr@a by -\qr@numversionmodules\relax + \qr@b=\qr@a\relax + \divide \qr@a by 8\relax + \edef\qr@numdatacodewords{\the\qr@a}% + \multiply\qr@a by 8\relax + \advance \qr@b by -\qr@a\relax + \edef\qr@numremainderbits{\the\qr@b}% + % + %The size of the character count indicator also varies by version. + %There are only two options, so hardcoding seems easier than expressing these functionally. + \xa\ifnum\qr@version<10\relax + \def\qr@charactercountbytes@byte{1}% + \def\qr@charactercountbits@byte{8}% + \else + \def\qr@charactercountbytes@byte{2}% + \def\qr@charactercountbits@byte{16}% + \fi + % + %Now we call on the table, from the QR specification, + %of how many blocks to divide the message into, and how many error bytes each block gets. + %This affects the true capacity for data, which we store into \qr@totaldatacodewords. + % The following macro sets \qr@numblocks and \qr@num@eccodewords + % based on Table 9 of the QR specification. + \qr@settableix + \qr@a = -\qr@numblocks\relax + \multiply \qr@a by \qr@num@eccodewords\relax + \advance\qr@a by \qr@numdatacodewords\relax + \edef\qr@totaldatacodewords{\the\qr@a}% + \advance\qr@a by -\qr@charactercountbytes@byte\relax%Subtract character count + \advance\qr@a by -1\relax% Subtract 1 byte for the 4-bit mode indicator and the 4-bit terminator at the end. + \edef\qr@truecapacity{\the\qr@a}% +} + + +\def\qr@setversion#1#2{% + % #1 = version number, an integer between 1 and 40 inclusive. + % #2 = error-correction level, as an integer between 0 and 3 inclusive. + % 0 = 00 = M + % 1 = 01 = L + % 2 = 10 = H + % 3 = 11 = Q + % This macro calculates and sets a variety of global macros and/or counters + % storing version information that is used later in construction the QR code. + % Thus \qr@setversion should be called every time! + % + \edef\qr@version{#1}% + \edef\qr@level{#2}% + % + \qr@calculate@capacity{\qr@version}{\qr@level}% + %The capacity-check code sets the following: + % * \qr@size + % * \qr@k + % * \ifqr@versionmodules + % * \qr@numversionmodules + % * \qr@numdatacodewords + % * \qr@numremainderbits + % * \qr@charactercountbits@byte + % * \qr@charactercountbytes@byte + % * \qr@numblocks (via \qr@settableix) + % * \qr@num@eccodewords (via \qr@settableix) + % * \qr@totaldatacodewords + % + % The alignment patterns' square is 7 modules in from each edge. + % They are spaced "as evenly as possible" with an even number of modules between each row/column, + % unevenness in division being accommodated by making the first such gap smaller. + % The formula seems to be + % general distance = 2*round((n-13)/(k-1)/2+0.25) + % = 2*floor((n-13)/(k-1)/2+0.75) + % = 2*floor( (2*(n-13)/(k-1)+3) / 4 ) + % = (((2*(n-13)) div (k-1) + 3 ) div 4 ) * 2 + % first distance = leftovers + % The 0.25 is to accommodate version 32, which is the only time we round down. + % Otherwise a simple 2*ceiling((n-13)/(k-1)/2) would have sufficed. + % + \qr@a = \qr@size\relax + \advance\qr@a by -13\relax + \multiply\qr@a by 2\relax + \qr@b = \qr@k\relax + \advance \qr@b by -1\relax + \divide\qr@a by \qr@b\relax + \advance\qr@a by 3\relax + \divide\qr@a by 4\relax + \multiply\qr@a by 2\relax + \edef\qr@alignment@generalskip{\the\qr@a}% + % + %Now set \qr@alignment@firstskip to (\qr@size-13)-(\qr@k-2)*\qr@alignment@generalskip % + \qr@a = \qr@k\relax + \advance\qr@a by -2\relax + \multiply\qr@a by -\qr@alignment@generalskip\relax + \advance\qr@a by \qr@size\relax + \advance\qr@a by -13\relax + \edef\qr@alignment@firstskip{\the\qr@a}% + % + % + % + % Our \qr@totaldatacodewords bytes of data are broken up as evenly as possible + % into \qr@numblocks datablocks; some may be one byte longer than others. + % We set \qr@shortblock@size to floor(\qr@totaldatacodewords / \qr@numblocks) + % and \qr@numlongblocks to mod(\qr@totaldatacodewords , \qr@numblocks). + \qr@a=\qr@totaldatacodewords\relax + \divide\qr@a by \qr@numblocks\relax + \edef\qr@shortblock@size{\the\qr@a}% + \multiply\qr@a by -\qr@numblocks\relax + \advance\qr@a by \qr@totaldatacodewords\relax + \edef\qr@numlongblocks{\the\qr@a}% + % + %Set \qr@longblock@size to \qr@shortblock@size+1. + \qr@a=\qr@shortblock@size\relax + \advance\qr@a by 1\relax + \edef\qr@longblock@size{\the\qr@a}% + % + %Set \qr@numshortblocks to \qr@numblocks - \qr@numlongblocks + \qr@b=\qr@numblocks\relax + \advance\qr@b by -\qr@numlongblocks\relax + \edef\qr@numshortblocks{\the\qr@b}% +}% + +\def\qr@settableix@int(#1,#2){% + \edef\qr@numblocks{#1}% + \edef\qr@num@eccodewords{#2}% +}% + +\def\qr@settableix{% +\xa\ifcase\qr@level\relax + %00: Level 'M', medium error correction + \edef\qr@tempdata{(% + \ifcase\qr@version\relax + \relax %There is no version 0. + \or1,10% + \or1,16% + \or1,26% + \or2,18% + \or2,24% + \or4,16% + \or4,18% + \or4,22% + \or5,22% + \or5,26% + \or5,30% + \or8,22% + \or9,22% + \or9,24% + \or10,24% + \or10,28% + \or11,28% + \or13,26% + \or14,26% + \or16,26% + \or17,26% + \or17,28% + \or18,28% + \or20,28% + \or21,28% + \or23,28% + \or25,28% + \or26,28% + \or28,28% + \or29,28% + \or31,28% + \or33,28% + \or35,28% + \or37,28% + \or38,28% + \or40,28% + \or43,28% + \or45,28% + \or47,28% + \or49,28% + \fi)}% +\or + %01: Level 'L', low error correction + \edef\qr@tempdata{% + (\ifcase\qr@version\relax + \relax %There is no version 0. + \or 1,7% + \or 1,10% + \or 1,15% + \or 1,20% + \or 1,26% + \or 2,18% + \or 2,20% + \or 2,24% + \or 2,30% + \or 4,18% + \or 4,20% + \or 4,24% + \or 4,26% + \or 4,30% + \or 6,22% + \or 6,24% + \or 6,28% + \or 6,30% + \or 7,28% + \or 8,28% + \or 8,28% + \or 9,28% + \or 9,30% + \or 10,30% + \or 12,26% + \or 12,28% + \or 12,30% + \or 13,30% + \or 14,30% + \or 15,30% + \or 16,30% + \or 17,30% + \or 18,30% + \or 19,30% + \or 19,30% + \or 20,30% + \or 21,30% + \or 22,30% + \or 24,30% + \or 25,30% + \fi)}% +\or + %10: Level 'H', high error correction + \edef\qr@tempdata{(% + \ifcase\qr@version\relax + \relax %There is no version 0. + \or1,17% + \or1,28% + \or2,22% + \or4,16% + \or4,22% + \or4,28% + \or5,26% + \or6,26% + \or8,24% + \or8,28% + \or11,24% + \or11,28% + \or16,22% + \or16,24% + \or18,24% + \or16,30% + \or19,28% + \or21,28% + \or25,26% + \or25,28% + \or25,30% + \or34,24% + \or30,30% + \or32,30% + \or35,30% + \or37,30% + \or40,30% + \or42,30% + \or45,30% + \or48,30% + \or51,30% + \or54,30% + \or57,30% + \or60,30% + \or63,30% + \or66,30% + \or70,30% + \or74,30% + \or77,30% + \or81,30% + \fi)}% +\or + %11: Level 'Q', quality error correction + \edef\qr@tempdata{(% + \ifcase\qr@version\relax + \relax %There is no version 0. + \or1,13% + \or1,22% + \or2,18% + \or2,26% + \or4,18% + \or4,24% + \or6,18% + \or6,22% + \or8,20% + \or8,24% + \or8,28% + \or10,26% + \or12,24% + \or16,20% + \or12,30% + \or17,24% + \or16,28% + \or18,28% + \or21,26% + \or20,30% + \or23,28% + \or23,30% + \or25,30% + \or27,30% + \or29,30% + \or34,28% + \or34,30% + \or35,30% + \or38,30% + \or40,30% + \or43,30% + \or45,30% + \or48,30% + \or51,30% + \or53,30% + \or56,30% + \or59,30% + \or62,30% + \or65,30% + \or68,30% + \fi)}% +\fi +\xa\qr@settableix@int\qr@tempdata +}% +% \end{macrocode} +% \subsection{More key handling} +% \begin{macrocode} +\define@key{qr}{version}{\edef\qr@desiredversion{#1}}% +\define@key{qr}{level}{\qr@setlevel{#1}}% +\define@key{qr}{height}{\qr@setheight{#1}}% +\define@boolkey{qr}[qr@]{tight}[true]{}% %This creates \ifqr@tight and initializes it to true. +\define@boolkey{qr}[qr@]{padding}[true]{\ifqr@padding\qr@tightfalse\else\qr@tighttrue\fi}% %Define 'padding' as antonym to 'tight' + +\def\@qr@M{M}\def\@qr@z{0}% +\def\@qr@L{L}\def\@qr@i{1}% +\def\@qr@H{H}\def\@qr@ii{2}% +\def\@qr@Q{Q}\def\@qr@iii{3}% +\def\qr@setlevel#1{% + \edef\qr@level@selected{#1}% + \ifx\qr@level@selected\@qr@M + \edef\qr@desiredlevel{0}% + \fi + \ifx\qr@level@selected\@qr@L + \edef\qr@desiredlevel{1}% + \fi + \ifx\qr@level@selected\@qr@H + \edef\qr@desiredlevel{2}% + \fi + \ifx\qr@level@selected\@qr@Q + \edef\qr@desiredlevel{3}% + \fi + \ifx\qr@level@selected\@qr@z + \edef\qr@desiredlevel{0}% + \fi + \ifx\qr@level@selected\@qr@i + \edef\qr@desiredlevel{1}% + \fi + \ifx\qr@level@selected\@qr@ii + \edef\qr@desiredlevel{2}% + \fi + \ifx\qr@level@selected\@qr@iii + \edef\qr@desiredlevel{3}% + \fi +}% + +\def\qr@setheight#1{% + \setlength{\qr@desiredheight}{#1}% +}% + +\newcommand\qrset[1]{% + \setkeys{qr}{#1}% +} + +%SET DEFAULTS +\qrset{version=0, level=0, tight} +% \end{macrocode} +% \subsection{Main user functions} +% At last we are ready to define the main user functions. +% Some care is needed to ensure +% that the \meta{text to be encoded} is read with the appropriate catcodes, +% and that any escaped special characters are converted to the intended +% characters with category code 12 (other). +% \begin{macrocode} +\newif\ifqr@starinvoked% +\def\qrcode{\@ifstar\qrcode@star\qrcode@nostar}% +\def\qrcode@star{\qr@starinvokedtrue\qrcode@i}% +\def\qrcode@nostar{\qr@starinvokedfalse\qrcode@i}% + +\newcommand\qrcode@i[1][]{% + \begingroup% + \ifqr@starinvoked% + \qr@hyperlinkfalse% + \fi% + \setkeys{qr}{#1}% + \bgroup\qr@verbatimcatcodes\qr@setescapedspecials\qrcode@in}% + +\def\qrcode@in#1{\xdef\qr@texttoencode{#1}\egroup\qrcode@int\endgroup}% + +\def\qrcode@hyperwrapper@hyperref{\href{\qr@texttoencode}}% +\def\qrcode@hyperwrapper@nohyperref{\relax}% + +\AtBeginDocument{% + \@ifpackageloaded{hyperref}% + {\global\let\qrcode@hyperwrapper=\qrcode@hyperwrapper@hyperref}% + {\global\let\qrcode@hyperwrapper=\qrcode@hyperwrapper@nohyperref}% +}% + +\def\qrcode@int{% + \message{^^J^^J^^J}% + %First, choose the version and level. + %Recall that \qr@choose@best@version sets \qr@version and \qr@level. + \xa\qr@choose@best@version\xa{\qr@texttoencode}% + \qr@setversion{\qr@version}{\qr@level}% + % + \ifqr@hyperlink% + \let\qrcode@wrapper=\qrcode@hyperwrapper% + \else% + \let\qrcode@wrapper=\relax% + \fi% + % + %Next, check whether we have already encoded this text at this version + %and level. + \qrcode@wrapper{% + \xa\ifx\csname qr@savedbinarymatrix@\qr@texttoencode @\qr@version @\qr@level\endcsname + \relax% + %This text has not yet been encoded. + \qrcode@int@new% + \else + %This text has already been encoded! + \ifqr@forget@mode + %In 'forget' mode, we deliberately recalculate anyway. + \qrcode@int@new% + \else + \qrcode@int@remember% + \fi + \fi% + }% +}% + +\def\qrcode@int@new{% + \qr@createsquareblankmatrix{newqr}{\qr@size}% + \qr@placefinderpatterns{newqr}% + \qr@placetimingpatterns{newqr}% + \qr@placealignmentpatterns{newqr}% + \qr@placedummyformatpatterns{newqr}% + \qr@placedummyversionpatterns{newqr}% + \ifqr@draft@mode + \message{^^J}% + \relax% Draft mode---don't load any data or do any work. Also don't save! + \def\qr@format@square{\qr@black}% + \def\qr@blank{\qr@white}% + \fboxsep=-\fboxrule% + \fbox{\qr@printmatrix{newqr}}% + \else + \message{^^J}% + \xa\qr@encode@binary\xa{\qr@texttoencode}% + \qr@splitcodetextintoblocks + \qr@createerrorblocks + \qr@interleave + \message{^^J}% + \qr@writeremainderbits{newqr}% + \qr@chooseandapplybestmask{newqr}% + \qr@decimaltobinary[2]{\qr@level@binary}{\qr@level}% + \qr@decimaltobinary[3]{\qr@mask@binary}{\qr@mask@selected}% + \edef\qr@formatstring{\qr@level@binary\qr@mask@binary}% + \message{^^J}% + \message{^^J}% + \message{^^J}% + % + %Also save the binary version into the aux file, for use in later runs. + \message{^^J}% + \message{^^J}% + \fi + \message{^^J}% +}% +\def\qrcode@int@remember{% + %This text has already been encoded, + %so we just copy it from the saved binary string. + \message{^^J}% + \xa\qr@printsavedbinarymatrix\xa{\csname qr@savedbinarymatrix@\qr@texttoencode @\qr@version @\qr@level\endcsname}% + % + % Now this still might need to be written to the aux file. + % + \xa\ifx\csname qr@savedflag@\qr@texttoencode @\qr@version @\qr@level\endcsname\@qr@TRUE + %Okay, this has already been written to aux file. + %Do nothing. + \relax% + \else% + %This has NOT been written to the aux file yet. + %We need to do so now. + \xa\qr@writebinarymatrixtoauxfile\xa{\csname qr@savedbinarymatrix@\qr@texttoencode @\qr@version @\qr@level\endcsname}% + \fi% +}% + +\def\qr@matrixtobinary#1{% + \def\qr@binarymatrix@result{}% + \bgroup + \def\qr@black{1}% + \def\qr@white{0}% + \def\qr@blank{0}% + \def\qr@black@fixed{1}% + \def\qr@white@fixed{0}% + \def\qr@black@format{1}% + \def\qr@white@format{0}% + % + \qr@for \i = 1 to \qr@size by 1% + {\qr@for \j = 1 to \qr@size by 1% + {\edef\qr@theentry{\qr@matrixentry{#1}{\the\i}{\the\j}}% + \xa\g@addto@macro\xa\qr@binarymatrix@result\xa{\qr@theentry}% + }% + }% + \egroup% +}% + +\def\qr@sanitize@output#1{% + %Read through ASCII text '#1' and escape backslashes and braces + \def\qr@sanitized@result{}% + \edef\qr@argument{(#1\relax\relax\relax)}% + \xa\qr@sanitize@output@int\qr@argument% +} + +\def\qr@sanitize@output@int(#1#2){% + % #1 = first character + % #2 = rest of output, including terminator + \edef\qr@testi{#1}% + \ifx\qr@testi\qr@relax + % Done. + \let\qr@next=\relax + \else + \ifx\qr@testi\qr@otherrightbrace + \edef\qr@sanitized@result{\qr@sanitized@result\qr@otherbackslash}% + \else\ifx\qr@testi\qr@otherleftbrace + \edef\qr@sanitized@result{\qr@sanitized@result\qr@otherbackslash}% + \else\ifx\qr@testi\qr@otherbackslash + \edef\qr@sanitized@result{\qr@sanitized@result\qr@otherbackslash}% + \fi + \fi + \fi + \edef\qr@sanitized@result{\qr@sanitized@result#1}% + \def\qr@next{\qr@sanitize@output@int(#2)}% + \fi + \qr@next +} + +\def\@qr@TRUE{TRUE}% +\def\qr@writebinarymatrixtoauxfile#1{% + \qr@sanitize@output{\qr@texttoencode}% + \edef\qr@theargument{{\qr@sanitized@result}{\qr@version}{\qr@level}{#1}}% + \xa\write\xa\@auxout\xa{\xa\string\xa\qr@savematrix\qr@theargument}% + % + % Now set a flag, so we don't write this again. + \xa\gdef\csname qr@savedflag@\qr@texttoencode @\qr@version @\qr@level\endcsname{TRUE}% +}% + +\gdef\qr@dummyqrsavedefinition{}% +\begingroup + \catcode`\#=12\relax + \catcode`\<=1\relax + \catcode`\{=12\relax + \catcode`\>=2\relax + \catcode`\}=12\relax + \catcode`\|=0\relax + \catcode`\\=12|relax + |gdef|qr@dummyqrsavedefinition<% + \ifx\qr@savematrix\@undefined% + \def\qr@savematrix{\begingroup\let\do\@makeother\dospecials\catcode`\{=1\catcode`\}=2\relax + \qr@savematrix@int}% + \def\qr@savematrix@int#1#2#3#4{\endgroup}% + \fi% + > +|endgroup + +\edef\qr@argument{(\qr@dummyqrsavedefinition)}% +\xa\write\xa\@auxout\xa{\qr@dummyqrsavedefinition}% + +\def\qr@savematrix{\bgroup\qr@verbatimcatcodes\qr@setescapedspecials\qr@savematrix@int}% + +\def\qr@savematrix@int#1{\xdef\qr@savedmatrix@name{#1}\egroup\qr@savematrix@int@int}% + +\def\qr@savematrix@int@int#1#2#3{% + % \qr@savedmatrix@name = encoded text + % #1 = version + % #2 = level + % #3 = binary text + \def\ds{^^J}\xa\message\xa{\ds}% + {\let\%=\qr@otherpercent + \xa\gdef\csname qr@savedbinarymatrix@\qr@savedmatrix@name @#1@#2\endcsname{#3}% + }% +}% +% \end{macrocode} +% +% \Finale +\endinput diff --git a/tools/style/qrcode.ins b/tools/style/qrcode.ins new file mode 100644 index 0000000..6e5eade --- /dev/null +++ b/tools/style/qrcode.ins @@ -0,0 +1,57 @@ +%% qrcode.ins +%% Copyright 2015 by Anders O.F. Hendrickson +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `maintained'. +%% +%% The Current Maintainer of this work is Anders O.F. Hendrickson. +%% +%% This work consists of the files qrcode.dtx and qrcode.ins +%% and the derived file qrcode.sty. + +\input docstrip.tex +\keepsilent + +\usedir{tex/latex/qrcode} + +\preamble + +This is a generated file. + +Copyright (C) 2015 by Anders Hendrickson + +This work may be distributed and/or modified under the +conditions of the LaTeX Project Public License, either version 1.3 +of this license or (at your option) any later version. +The latest version of this license is in + http://www.latex-project.org/lppl.txt +and version 1.3 or later is part of all distributions of LaTeX +version 2005/12/01 or later. + +\endpreamble + +\generate{\file{qrcode.sty}{\from{qrcode.dtx}{package}}} + +\obeyspaces +\Msg{*************************************************************} +\Msg{* *} +\Msg{* To finish the installation you have to move the following *} +\Msg{* file into a directory searched by TeX: *} +\Msg{* *} +\Msg{* qrcode.sty *} +\Msg{* *} +\Msg{* To produce the documentation run the file qrcode.dtx *} +\Msg{* through LaTeX. *} +\Msg{* *} +\Msg{* Happy TeXing! *} +\Msg{* *} +\Msg{*************************************************************} + +\endbatchfile diff --git a/tools/style/qrcode.sty b/tools/style/qrcode.sty new file mode 100644 index 0000000..6330464 --- /dev/null +++ b/tools/style/qrcode.sty @@ -0,0 +1,3051 @@ +%% +%% This is file `qrcode.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% qrcode.dtx (with options: `package') +%% +%% This is a generated file. +%% +%% Copyright (C) 2015 by Anders Hendrickson +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +\NeedsTeXFormat{LaTeX2e}[1999/12/01] +\ProvidesPackage{qrcode} + [2015/01/08 v1.51 QR code generation] +%%PACKAGE LOADING +\RequirePackage{xcolor}% +\RequirePackage{xkeyval}% + +%%INITIAL CODE +\newif\ifqr@draft@mode +\newif\ifqr@forget@mode + +%%DECLARATION OF OPTIONS +\define@boolkey{qr}[qr@]{draft}[true]{\ifqr@draft\qr@draft@modetrue\else\qr@draft@modefalse\fi}% +\define@boolkey{qr}[qr@]{final}[true]{\ifqr@final\qr@draft@modefalse\else\qr@draft@modetrue\fi}% +\define@boolkey{qr}[qr@]{forget}[true]{\ifqr@forget\qr@forget@modetrue\else\qr@forget@modefalse\fi}% +\define@boolkey{qr}[qr@]{hyperlink}[true]{}% %This creates \ifqr@hyperlink. +\define@boolkey{qr}[qr@]{hyperlinks}[true]{\ifqr@hyperlinks\qr@hyperlinktrue\else\qr@hyperlinkfalse\fi}% +\define@boolkey{qr}[qr@]{link}[true]{\ifqr@link\qr@hyperlinktrue\else\qr@hyperlinkfalse\fi}% +\define@boolkey{qr}[qr@]{nolink}[true]{\ifqr@nolink\qr@hyperlinkfalse\else\qr@hyperlinktrue\fi}% %Make nolink an antonym. +\define@boolkey{qr}[qr@]{links}[true]{\ifqr@links\qr@hyperlinktrue\else\qr@hyperlinkfalse\fi}% +\define@boolkey{qr}[qr@]{nolinks}[true]{\ifqr@nolinks\qr@hyperlinkfalse\else\qr@hyperlinktrue\fi}% %Make nolinks an antonym. + +%%EXECUTION OF OPTIONS +\qr@draft@modefalse +\qr@forget@modefalse +\qr@hyperlinktrue + +\ProcessOptionsX + +\newcounter{qr@i}% +\newcounter{qr@j}% +\newcount\qr@a +\newcount\qr@b +\newcount\qr@c + +\let\xa=\expandafter + +\newlinechar=`\^^J + +\def\qr@relax{\relax}% + +\def\qr@preface@macro#1#2{% + % #1 = macro name + % #2 = text to add to front of macro + \def\qr@tempb{#2}% + \xa\xa\xa\def\xa\xa\xa#1\xa\xa\xa{\xa\qr@tempb #1}% +}% + +\def\qr@g@preface@macro#1#2{% + % #1 = macro to be appended to + % #2 = code to add + \edef\qr@tempb{#2}% + \xa\xa\xa\gdef\xa\xa\xa#1\xa\xa\xa{\xa\qr@tempb#1}% +} + +\def\qr@getstringlength#1{% + \bgroup + \qr@a=0% + \xdef\qr@thestring{#1}% + \xa\qr@stringlength@recursive\xa(\qr@thestring\relax\relax)% + \xdef\qr@stringlength{\the\qr@a}% + \egroup +}% + +\def\qr@stringlength@recursive(#1#2){% + \def\qr@testi{#1}% + \ifx\qr@testi\qr@relax + %we are done. + \let\qr@next=\relax% + \else + \advance\qr@a by 1% + \def\qr@next{\qr@stringlength@recursive(#2)}% + \fi + \qr@next +}% +\newcount\qr@for@depth% +\newcount\qr@for@maxdepth% +\qr@for@depth=0% +\qr@for@maxdepth=0% +\newcount\qr@for@start% +\newcount\qr@for@end% +\newcount\qr@for@step% +\def\qr@allocate@new@for@counter{% + \global\advance\qr@for@maxdepth by 1% + \newcount\qr@newforcount% + \xa\global\xa\let\csname qr@for@var@\the\qr@for@maxdepth\endcsname=\qr@newforcount% +}% + +\newif\ifqr@loopshouldrun +\def\qr@for #1=#2to#3by#4#{% + \qr@for@int{#1}{#2}{#3}{#4}% +}% +\long\def\qr@for@int#1#2#3#4#5{% + \bgroup + %Because we're working within a TeX group, + %any values of \qr@for@start, \qr@for@end, and \qr@for@step from an outer loop + %will be restored after the \egroup. + % + %For the \qr@for@var itself, however, we need a different counter, + %because the user's text within the loop might need to access the variable from the outer loop. + \advance\qr@for@depth by 1\relax% This is a local change. + \ifnum\qr@for@depth>\qr@for@maxdepth% + %This is the first time we have gone to this depth of nesting! + %We should only be over by one. + \qr@allocate@new@for@counter% + \fi + \xa\let\xa\qr@for@var\xa=\csname qr@for@var@\the\qr@for@depth\endcsname% + %Now \qr@for@var points to the same register as \qr@for@var@3 or something. + %The next line lets the user-level variable (e.g., \i or \j) point to the same count register. + \let#1=\qr@for@var% + %Now establish the looping parameters. + \edef\qr@for@start@text{#2}% + \edef\qr@for@end@text{#3}% + \edef\qr@for@step@text{#4}% + \def\qr@for@body{\bgroup #5\egroup}% + \xa\qr@for@start\qr@for@start@text\relax% + \xa\qr@for@end \qr@for@end@text\relax% + \xa\qr@for@step \qr@for@step@text\relax% + % + %Next, test whether the loop should run at all. + % * "\qr@for \i = 1 to 0 by 1" should fail. + % * "\qr@for \i = 3 to 5 by -1" should fail. + % * "\qr@for \i = 6 to 2 by 1" should fail. + % * "\qr@for \i = 4 to 4 by -1" should run. + % * "\qr@for \i = 4 to 4 by 1" should run. + % * "\qr@for \i = 5 to 7 by 0" should fail. + %The loop should fail if (step)=0 or if (step) and (end-start) have opposite signs. + %The loop will fail if (step=0) or (step)*(end-start)<0. + % TODO: "\qr@for \i = 5 to 5 by 0" should run (just one iteration). + \qr@loopshouldruntrue + \ifnum\qr@for@step=0\relax + \qr@loopshouldrunfalse + \fi + \qr@a=\qr@for@end% + \advance\qr@a by -\qr@for@start% + \multiply\qr@a by \qr@for@step% + \ifnum\qr@a<0\relax + \qr@loopshouldrunfalse + \fi + \ifqr@loopshouldrun + \qr@for@var=\qr@for@start% + \ifnum\qr@for@step>0\relax + \def\qr@for@recursive{% + \qr@for@body% + \advance\qr@for@var by \qr@for@step% + \ifnum\qr@for@var>\qr@for@end% + \let\qr@for@next=\relax% + \else% + \let\qr@for@next=\qr@for@recursive% + \fi% + \qr@for@next% + }% + \else + \def\qr@for@recursive{% + \qr@for@body% + \advance\qr@for@var by \qr@for@step% + \ifnum\qr@for@var<\qr@for@end% + \let\qr@for@next=\relax% + \else% + \let\qr@for@next=\qr@for@recursive% + \fi% + \qr@for@next% + }% + \fi + \qr@for@recursive% + \fi + \egroup +}% +\def\qr@padatfront#1#2{% + % #1 = macro containing text to pad + % #2 = desired number of characters + % Pads a number with initial zeros. + \qr@getstringlength{#1}% + \qr@a=\qr@stringlength\relax% + \advance\qr@a by 1\relax% + \qr@for \i = \qr@a to #2 by 1\relax% + {\qr@g@preface@macro{#1}{0}}% +} + +\qr@a=-1\relax% +\def\qr@savehexsymbols(#1#2){% + \advance\qr@a by 1\relax% + \xa\def\csname qr@hexchar@\the\qr@a\endcsname{#1}% + \xa\edef\csname qr@hextodecimal@#1\endcsname{\the\qr@a}% + \ifnum\qr@a=15\relax + %Done. + \let\qr@next=\relax% + \else + \def\qr@next{\qr@savehexsymbols(#2)}% + \fi% + \qr@next% +}% +\qr@savehexsymbols(0123456789abcdef\relax\relax)% + +\def\qr@decimaltobase#1#2#3{% + % #1 = macro to store result + % #2 = decimal representation of a positive integer + % #3 = new base + \bgroup + \edef\qr@newbase{#3}% + \gdef\qr@base@result{}% + \qr@a=#2\relax% + \qr@decimaltobase@recursive% + \xdef#1{\qr@base@result}% + \egroup +} +\def\qr@decimaltobase@recursive{% + \qr@b=\qr@a% + \divide\qr@b by \qr@newbase\relax + \multiply\qr@b by -\qr@newbase\relax + \advance\qr@b by \qr@a\relax% + \divide\qr@a by \qr@newbase\relax% + \ifnum\qr@b<10\relax + \edef\qr@newdigit{\the\qr@b}% + \else + \edef\qr@newdigit{\csname qr@hexchar@\the\qr@b\endcsname}% + \fi + \edef\qr@argument{{\noexpand\qr@base@result}{\qr@newdigit}}% + \xa\qr@g@preface@macro\qr@argument% + \ifnum\qr@a=0\relax + \relax + \else + \xa\qr@decimaltobase@recursive + \fi +} + +\newcommand\qr@decimaltohex[3][0]{% + % #1 (opt.) = number of hex digits to create + % #2 = macro to store result + % #3 = decimal digits to convert + \qr@decimaltobase{#2}{#3}{16}% + \qr@padatfront{#2}{#1}% +} + +\newcommand\qr@decimaltobinary[3][0]{% + % #1 (opt.) = number of bits to create + % #2 = macro to store result + % #3 = decimal digits to convert + \qr@decimaltobase{#2}{#3}{2}% + \qr@padatfront{#2}{#1}% +} + +\qr@for \i = 0 to 15 by 1% + {% + \qr@decimaltohex[1]{\qr@hexchar}{\the\i}% + \qr@decimaltobinary[4]{\qr@bits}{\the\i}% + \xa\xdef\csname qr@b2h@\qr@bits\endcsname{\qr@hexchar}% + \xa\xdef\csname qr@h2b@\qr@hexchar\endcsname{\qr@bits}% + }% + +\newcommand\qr@binarytohex[3][\relax]{% + % #1 (optional) = # digits desired + % #2 = macro to save to + % #3 = binary string (must be multiple of 4 bits) + \def\qr@test@i{#1}% + \ifx\qr@test@i\qr@relax% + %No argument specified + \def\qr@desireddigits{0}% + \else + \def\qr@desireddigits{#1}% + \fi + \gdef\qr@base@result{}% + \edef\qr@argument{(#3\relax\relax\relax\relax\relax)}% + \xa\qr@binarytohex@int\qr@argument% + \qr@padatfront{\qr@base@result}{\qr@desireddigits}% + \xdef#2{\qr@base@result}% +} +\def\qr@binarytohex@int(#1#2#3#4#5){% + % #1#2#3#4 = 4 bits + % #5 = remainder, including \relax\relax\relax\relax\relax terminator + \def\qr@test@i{#1}% + \ifx\qr@test@i\qr@relax% + %Done. + \def\qr@next{\relax}% + \else% + \xdef\qr@base@result{\qr@base@result\csname qr@b2h@#1#2#3#4\endcsname}% + \def\qr@next{\qr@binarytohex@int(#5)}% + \fi% + \qr@next% +} + +\newcommand\qr@hextobinary[3][\relax]{% + % #1 (optional) = # bits desired + % #2 = macro to save to + % #3 = hexadecimal string + \bgroup + \def\qr@test@i{#1}% + \ifx\qr@test@i\qr@relax% + %No argument specified + \def\qr@desireddigits{0}% + \else + \def\qr@desireddigits{#1}% + \fi + \gdef\qr@base@result{}% + \edef\qr@argument{(#3\relax\relax)}% + \xa\qr@hextobinary@int\qr@argument% + \qr@padatfront{\qr@base@result}{\qr@desireddigits}% + \xdef#2{\qr@base@result}% + \egroup +} +\def\qr@hextobinary@int(#1#2){% + % #1 = hexadecimal character + % #2 = remainder, including \relax\relax terminator + \def\qr@test@@i{#1}% + \ifx\qr@test@@i\qr@relax% + %Done. + \def\qr@next{\relax}% + \else% + \xdef\qr@base@result{\qr@base@result\csname qr@h2b@#1\endcsname}% + \def\qr@next{\qr@hextobinary@int(#2)}% + \fi% + \qr@next% +} + +\def\qr@hextodecimal#1#2{% + \edef\qr@argument{#2}% + \xa\qr@a\xa=\xa\number\xa"\qr@argument\relax% + \edef#1{\the\qr@a}% +} + +\def\qr@hextodecimal#1#2{% + % #1 = macro to store result + % #2 = hexadecimal representation of a positive integer + \bgroup + \qr@a=0\relax% + \edef\qr@argument{(#2\relax)}% + \xa\qr@hextodecimal@recursive\qr@argument% + \xdef#1{\the\qr@a}% + \egroup +} +\def\qr@hextodecimal@recursive(#1#2){% + % #1 = first hex char + % #2 = remainder + \advance \qr@a by \csname qr@hextodecimal@#1\endcsname\relax% + \edef\qr@testii{#2}% + \ifx\qr@testii\qr@relax% + %Done. + \let\qr@next=\relax% + \else + %There's at least one more digit. + \multiply\qr@a by 16\relax + \edef\qr@next{\noexpand\qr@hextodecimal@recursive(#2)}% + \fi% + \qr@next% +} +{\catcode`\ =12\relax\gdef\qr@otherspace{ }}% +{\catcode`\%=12\relax\gdef\qr@otherpercent{%}}% +{\catcode`\#=12\relax\gdef\qr@otherpound{#}}% +{\catcode`\|=0\relax|catcode`|\=12|relax|gdef|qr@otherbackslash{\}}% +{\catcode`\^^J=12\relax\gdef\qr@otherlf{^^J}}% +\bgroup + \catcode`\<=1\relax + \catcode`\>=2\relax + \catcode`\{=12\relax\gdef\qr@otherleftbrace<{>% + \catcode`\}=12\relax\gdef\qr@otherrightbrace<}>% +\egroup% +{\catcode`\&=12\relax\gdef\qr@otherampersand{&}}% +{\catcode`\~=12\relax\gdef\qr@othertilde{~}}% +{\catcode`\^=12\relax\gdef\qr@othercaret{^}}% +{\catcode`\_=12\relax\gdef\qr@otherunderscore{_}}% +{\catcode`\$=12\relax\gdef\qr@otherdollar{$}}% + +{\catcode`\^^M=13\relax\gdef\qr@verbatimlinefeeds{\let^^M=\qr@otherlf}} +\def\qr@verbatimcatcodes{% + \catcode`\#=12\relax + \catcode`\$=12\relax + \catcode`\&=12\relax + \catcode`\^=12\relax + \catcode`\_=12\relax + \catcode`\~=12\relax + \catcode`\%=12\relax + \catcode`\ =12\relax + \catcode`\^^M=13\relax\qr@verbatimlinefeeds}% + +\def\qr@setescapedspecials{% + \let\ =\qr@otherspace% + \let\%=\qr@otherpercent% + \let\#=\qr@otherpound% + \let\&=\qr@otherampersand% + \let\^=\qr@othercaret% + \let\_=\qr@otherunderscore% + \let\~=\qr@othertilde% + \let\$=\qr@otherdollar% + \let\\=\qr@otherbackslash% + \let\{=\qr@otherleftbrace% + \let\}=\qr@otherrightbrace% + \let\?=\qr@otherlf% +}% +\def\qr@creatematrix#1{% + \xa\gdef\csname #1\endcsname##1##2{% + \csname #1@##1@##2\endcsname + }% +}% + +\def\qr@storetomatrix#1#2#3#4{% + % #1 = matrix name + % #2 = row number + % #3 = column number + % #4 = value of matrix entry + \xa\gdef\csname #1@#2@#3\endcsname{#4}% +}% + +\def\qr@estoretomatrix#1#2#3#4{% + % This version performs exactly one expansion on #4. + % #1 = matrix name + % #2 = row number + % #3 = column number + % #4 = value of matrix + \xa\xa\xa\gdef\xa\xa\csname #1@#2@#3\endcsname\xa{#4}% +}% + +\def\qr@matrixentry#1#2#3{% + % #1 = matrix name + % #2 = row number + % #3 = column number + \csname #1@#2@#3\endcsname% +}% + +\def\qr@createsquareblankmatrix#1#2{% + \qr@creatematrix{#1}% + \xa\gdef\csname #1@numrows\endcsname{#2}% + \xa\gdef\csname #1@numcols\endcsname{#2}% + \qr@for \i = 1 to #2 by 1% + {\qr@for \j = 1 to #2 by 1% + {\qr@storetomatrix{#1}{\the\i}{\the\j}{\qr@blank}}}% +}% + +\def\qr@numberofrowsinmatrix#1{% + \csname #1@numrows\endcsname% +}% + +\def\qr@numberofcolsinmatrix#1{% + \csname #1@numcols\endcsname% +}% + +\def\qr@setnumberofrows#1#2{% + \xa\xdef\csname #1@numrows\endcsname{#2}% +}% + +\def\qr@setnumberofcols#1#2{% + \xa\xdef\csname #1@numcols\endcsname{#2}% +}% + +\newlength\qr@desiredheight +\setlength\qr@desiredheight{2cm}% +\newlength\qr@modulesize +\newlength\qr@minipagewidth + +\def\qr@printmatrix#1{% + \def\qr@black{\rule{\qr@modulesize}{\qr@modulesize}}% + \def\qr@white{\rule{\qr@modulesize}{0pt}}% + \def\qr@black@fixed{\rule{\qr@modulesize}{\qr@modulesize}}% + \def\qr@white@fixed{\rule{\qr@modulesize}{0pt}}% + \def\qr@black@format{\rule{\qr@modulesize}{\qr@modulesize}}% + \def\qr@white@format{\rule{\qr@modulesize}{0pt}}% + %Set module size + \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 + \begin{minipage}{\qr@minipagewidth}% + \baselineskip=\qr@modulesize% + \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% %Blank space at top. + \qr@for \i = 1 to \qr@numberofrowsinmatrix{#1} by 1% + {\ifqr@tight\else\rule{4\qr@modulesize}{0pt}\fi% %Blank space at left. + \qr@for \j = 1 to \qr@numberofcolsinmatrix{#1} by 1% + {\qr@matrixentry{#1}{\the\i}{\the\j}}% + \par}% + \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% + \end{minipage}% +}% + +\def\qr@printsavedbinarymatrix#1{% + \edef\qr@binarystring{#1\relax\relax}% + %Set module size + \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 + \begin{minipage}{\qr@minipagewidth}% + \baselineskip=\qr@modulesize% + \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% %Blank space at top. + \qr@for \i = 1 to \qr@size by 1% + {\ifqr@tight\else\rule{4\qr@modulesize}{0pt}\fi% %Blank space at left. + \qr@for \j = 1 to \qr@size by 1% + {\edef\qr@theargument{(\qr@binarystring)}% + \xa\qr@printsavedbinarymatrix@int\qr@theargument + }% + \par}% + \ifqr@tight\else\rule{0pt}{4\qr@modulesize}\par\fi% + \end{minipage}% +}% + +\def\qr@printsavedbinarymatrix@int(#1#2){% + % #1 = first bit, either 1 or 0. + % #2 = remainder of string, terminating with \relax\relax + % There's no need to check for EOF here, because + % we'll only call this n^2 times. + \ifcase #1\relax + \rule{\qr@modulesize}{0pt}% % 0: white square + \or + \rule{\qr@modulesize}{\qr@modulesize}% % 1: black square + \fi + \xdef\qr@binarystring{#2}% +}% + +\def\qr@createliteralmatrix#1#2#3{% + % #1 = matrix name + % #2 = m, the number of rows and columns in the square matrix + % #3 = a string of m^2 tokens to be written into the matrix + \qr@creatematrix{#1}% + \xa\xdef\csname #1@numrows\endcsname{#2}% + \xa\xdef\csname #1@numcols\endcsname{#2}% + \gdef\qr@literalmatrix@tokens{#3}% + \qr@for \i = 1 to #2 by 1% + {\qr@for \j = 1 to #2 by 1% + {\xa\qr@createliteralmatrix@int\xa(\qr@literalmatrix@tokens)% + \qr@estoretomatrix{#1}{\the\i}{\the\j}{\qr@entrytext}% + }% + }% +} +\def\qr@createliteralmatrix@int(#1#2){% + \def\qr@entrytext{#1}% + \gdef\qr@literalmatrix@tokens{#2}% +} + +\qr@createliteralmatrix{finderpattern}{8}{% + \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed% + \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@white@fixed% + \qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed% +}% + +\qr@createliteralmatrix{alignmentpattern}{5}{% + \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed% + \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed% + \qr@black@fixed\qr@white@fixed\qr@black@fixed\qr@white@fixed\qr@black@fixed% + \qr@black@fixed\qr@white@fixed\qr@white@fixed\qr@white@fixed\qr@black@fixed% + \qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed\qr@black@fixed% +}% + +\def\qr@copymatrixentry#1#2#3#4#5#6{% + % Copy the (#2,#3) entry of matrix #1 + % to the (#5,#6) position of matrix #4. + \xa\xa\xa\global% + \xa\xa\xa\let\xa\xa\csname #4@#5@#6\endcsname% + \csname #1@#2@#3\endcsname% +}% + +\def\qr@createduplicatematrix#1#2{% + % #1 = name of copy + % #2 = original matrix to be copied + \qr@creatematrix{#1}% + \qr@for \i = 1 to \qr@numberofrowsinmatrix{#2} by 1% + {\qr@for \j = 1 to \qr@numberofcolsinmatrix{#2} by 1% + {\qr@copymatrixentry{#2}{\the\i}{\the\j}{#1}{\the\i}{\the\j}% + }% + }% + \qr@setnumberofrows{#1}{\qr@numberofrowsinmatrix{#2}}% + \qr@setnumberofcols{#1}{\qr@numberofcolsinmatrix{#2}}% +}% + +\def\qr@placefinderpattern@int#1#2#3#4#5{% + % Work on matrix #1. + % Start in position (#2, #3) -- should be a corner + % #4 indicates horizontal direction (1=right, -1=left) + % #5 indicates vertical direction (1=down, -1=up) + % + % In this code, \sourcei and \sourcej are TeX counts working through the finderpattern matrix, + % and i and j are LaTeX counters indicating positions in the big matrix. + \setcounter{qr@i}{#2}% + \qr@for \sourcei=1 to 8 by 1% + {\setcounter{qr@j}{#3}% + \qr@for \sourcej=1 to 8 by 1% + {\qr@copymatrixentry{finderpattern}{\the\sourcei}{\the\sourcej}% + {#1}{\theqr@i}{\theqr@j}% + \addtocounter{qr@j}{#5}% + }% + \addtocounter{qr@i}{#4}% + }% +}% + +\def\qr@placefinderpatterns#1{% + % #1=matrix name + \qr@placefinderpattern@int{#1}{1}{1}{1}{1}% + \qr@placefinderpattern@int{#1}{\qr@numberofrowsinmatrix{#1}}{1}{-1}{1}% + \qr@placefinderpattern@int{#1}{1}{\qr@numberofcolsinmatrix{#1}}{1}{-1}% +}% + +\def\qr@placetimingpatterns#1{% + %Set \qr@endingcol to n-8. + \qr@a=\qr@size\relax% + \advance\qr@a by -8\relax% + \edef\qr@endingcol{\the\qr@a}% + \qr@for \j = 9 to \qr@endingcol by 1% + {\ifodd\j\relax% + \qr@storetomatrix{#1}{7}{\the\j}{\qr@black@fixed}% + \qr@storetomatrix{#1}{\the\j}{7}{\qr@black@fixed}% + \else% + \qr@storetomatrix{#1}{7}{\the\j}{\qr@white@fixed}% + \qr@storetomatrix{#1}{\the\j}{7}{\qr@white@fixed}% + \fi% + }% +}% + +\def\qr@placealignmentpattern@int#1#2#3{% + % Work on matrix #1. + % Write an alignment pattern into the matrix, centered on (#2,#3). + \qr@a=#2\relax% + \advance\qr@a by -2\relax% + \qr@b=#3\relax% + \advance\qr@b by -2\relax% + \setcounter{qr@i}{\the\qr@a}% + \qr@for \i=1 to 5 by 1% + {\setcounter{qr@j}{\the\qr@b}% + \qr@for \j=1 to 5 by 1% + {\qr@copymatrixentry{alignmentpattern}{\the\i}{\the\j}% + {#1}{\theqr@i}{\theqr@j}% + \stepcounter{qr@j}% + }% + \stepcounter{qr@i}% + }% +}% + +\newif\ifqr@incorner% +\def\qr@placealignmentpatterns#1{% + %There are k^2-3 alignment patterns, + %arranged in a (k x k) grid within the matrix. + %They begin in row 7, column 7, + %except that the ones in the NW, NE, and SW corners + %are omitted because of the finder patterns. + %Recall that + % * \qr@k stores k, + % * \qr@alignment@firstskip stores how far between the 1st and 2nd row/col, & + % * \qr@alignment@generalskip stores how far between each subsequent row/col. + \xa\ifnum\qr@k>0\relax + %There will be at least one alignment pattern. + %N.B. k cannot equal 1. + \xa\ifnum\qr@k=2\relax + % 2*2-3 = exactly 1 alignment pattern. + \qr@a=7\relax + \advance\qr@a by \qr@alignment@firstskip\relax + \xdef\qr@target@ii{\the\qr@a}% + \qr@placealignmentpattern@int{#1}{\qr@target@ii}{\qr@target@ii}% + \else + % k is at least 3, so the following loops should be safe. + \xdef\qr@target@ii{7}% + \qr@for \ii = 1 to \qr@k by 1% + {\ifcase\ii\relax% + \relax% \ii should never equal 0. + \or + \xdef\qr@target@ii{7}% If \ii = 1, we start in row 7. + \or + %If \ii = 2, we add the firstskip. + \qr@a=\qr@target@ii\relax% + \advance\qr@a by \qr@alignment@firstskip\relax% + \xdef\qr@target@ii{\the\qr@a}% + \else + %If \ii>2, we add the generalskip. + \qr@a=\qr@target@ii\relax% + \advance\qr@a by \qr@alignment@generalskip\relax% + \xdef\qr@target@ii{\the\qr@a}% + \fi + \qr@for \jj = 1 to \qr@k by 1% + {\ifcase\jj\relax% + \relax% \jj should never equal 0. + \or + \xdef\qr@target@jj{7}% If \jj=1, we start in row 7. + \or + %If \jj=2, we add the firstskip. + \qr@a=\qr@target@jj\relax% + \advance\qr@a by \qr@alignment@firstskip% + \xdef\qr@target@jj{\the\qr@a}% + \else + %If \jj>2, we add the generalskip. + \qr@a=\qr@target@jj\relax% + \advance\qr@a by \qr@alignment@generalskip% + \xdef\qr@target@jj{\the\qr@a}% + \fi + \qr@incornerfalse% + \ifnum\ii=1\relax + \ifnum\jj=1\relax + \qr@incornertrue + \else + \ifnum\qr@k=\jj\relax + \qr@incornertrue + \fi + \fi + \else + \xa\ifnum\qr@k=\ii\relax + \ifnum\jj=1\relax + \qr@incornertrue + \fi + \fi + \fi + \ifqr@incorner + \relax + \else + \qr@placealignmentpattern@int{#1}{\qr@target@ii}{\qr@target@jj}% + \fi + }% ends \qr@for \jj + }% ends \qr@for \ii + \fi + \fi +}% + +\def\qr@placedummyformatpatterns#1{% + \qr@for \j = 1 to 9 by 1% + {\ifnum\j=7\relax% + \else% + \qr@storetomatrix{#1}{9}{\the\j}{\qr@format@square}% + \qr@storetomatrix{#1}{\the\j}{9}{\qr@format@square}% + \fi% + }% + \setcounter{qr@j}{\qr@size}% + \qr@for \j = 1 to 8 by 1% + {\qr@storetomatrix{#1}{9}{\theqr@j}{\qr@format@square}% + \qr@storetomatrix{#1}{\theqr@j}{9}{\qr@format@square}% + \addtocounter{qr@j}{-1}% + }% + %Now go back and change the \qr@format@square in (n-8,9) to \qr@black@fixed. + \addtocounter{qr@j}{1}% + \qr@storetomatrix{#1}{\theqr@j}{9}{\qr@black@fixed}% +}% + +\def\qr@placedummyversionpatterns#1{% + \xa\ifnum\qr@version>6\relax + %Must include version information. + \global\c@qr@i=\qr@size% + \global\advance\c@qr@i by -10\relax% + \qr@for \i = 1 to 3 by 1% + {\qr@for \j = 1 to 6 by 1% + {\qr@storetomatrix{#1}{\theqr@i}{\the\j}{\qr@format@square}% + \qr@storetomatrix{#1}{\the\j}{\theqr@i}{\qr@format@square}% + }% + \stepcounter{qr@i}% + }% + \fi +}% + +\def\qr@writebit(#1#2)#3{% + % #3 = matrix name + % (qr@i,qr@j) = position to write in (LaTeX counters) + % #1 = bit to be written + % #2 = remaining bits plus '\relax' as an end-of-file marker + \edef\qr@datatowrite{#2}% + \ifnum#1=1 + \qr@storetomatrix{#3}{\theqr@i}{\theqr@j}{\qr@black}% + \else + \qr@storetomatrix{#3}{\theqr@i}{\theqr@j}{\qr@white}% + \fi +}% + +\newif\ifqr@rightcol +\newif\ifqr@goingup + +\def\qr@writedata@hex#1#2{% + % #1 = name of a matrix that has been prepared with finder patterns, timing patterns, etc. + % #2 = a string consisting of bytes to write into the matrix, in two-char hex format. + \setcounter{qr@i}{\qr@numberofrowsinmatrix{#1}}% + \setcounter{qr@j}{\qr@numberofcolsinmatrix{#1}}% + \qr@rightcoltrue% + \qr@goinguptrue% + \edef\qr@argument{{#1}(#2\relax\relax\relax)}% + \xa\qr@writedata@hex@recursive\qr@argument% +}% + +\def\qr@writedata@hex@recursive#1(#2#3#4){% + % #1 = name of a matrix that has been prepared with finder patterns, timing patterns, etc. + % (qr@i,qr@j) = position to write in LaTeX counters + % #2#3#4 contains the hex codes of the bytes to be written, plus \relax\relax\relax + % as an end-of-file marker + \edef\qr@testii{#2}% + \ifx\qr@testii\qr@relax% + % #2 is \relax, so there is nothing more to write. + \relax + \let\qr@next=\relax + \else + % #2 is not \relax, so there is another byte to write. + \qr@hextobinary[8]{\bytetowrite}{#2#3}% + \xdef\qr@datatowrite{\bytetowrite\relax}% %Add terminating "\relax" + \qr@writedata@recursive{#1}% %This function actually writes the 8 bits. + \edef\qr@argument{{#1}(#4)}% + \xa\def\xa\qr@next\xa{\xa\qr@writedata@hex@recursive\qr@argument}% %Call self to write the next bit. + \fi + \qr@next +}% + +\def\qr@writedata#1#2{% + % #1 = name of a matrix that has been prepared with finder patterns, timing patterns, etc. + % #2 = a string consisting of 0's and 1's to write into the matrix. + \setcounter{qr@i}{\qr@numberofrowsinmatrix{#1}}% + \setcounter{qr@j}{\qr@numberofcolsinmatrix{#1}}% + \qr@rightcoltrue + \qr@goinguptrue + \edef\qr@datatowrite{#2\relax}% + \qr@writedata@recursive{#1}% +}% + +\def\qr@@blank{\qr@blank}% + +\def\qr@writedata@recursive#1{% + % #1 = matrix name + % (qr@i,qr@j) = position to write in (LaTeX counters) + % \qr@datatowrite contains the bits to be written, plus '\relax' as an end-of-file marker + \xa\let\xa\squarevalue\csname #1@\theqr@i @\theqr@j\endcsname% + \ifx\squarevalue\qr@@blank + %Square is blank, so write data in it. + \xa\qr@writebit\xa(\qr@datatowrite){#1}% + %The \qr@writebit macro not only writes the first bit of \qr@datatowrite into the matrix, + %but also removes the bit from the 'bitstream' of \qr@datatowrite. + \fi + %Now adjust our position in the matrix. + \ifqr@rightcol + %From the right-hand half of the two-bit column, we always move left. Easy peasy. + \addtocounter{qr@j}{-1}% + \qr@rightcolfalse + \else + %If we're in the left-hand column, things are harder. + \ifqr@goingup + %First, suppose we're going upwards. + \ifnum\c@qr@i>1\relax% + %If we're not in the first row, things are easy. + %We move one to the right and one up. + \addtocounter{qr@j}{1}% + \addtocounter{qr@i}{-1}% + \qr@rightcoltrue + \else + %If we are in the first row, then we move to the left, + %and we are now in the right-hand column on a downward pass. + \addtocounter{qr@j}{-1}% + \qr@goingupfalse + \qr@rightcoltrue + \fi + \else + %Now, suppose we're going downwards. + \xa\ifnum\qr@size>\c@qr@i\relax% + %If we're not yet in the bottom row, things are easy. + %We move one to the right and one down. + \addtocounter{qr@j}{1}% + \addtocounter{qr@i}{1}% + \qr@rightcoltrue + \else + %If we are in the bottom row, then we move to the left, + %and we are now in the right-hand column on an upward pass. + \addtocounter{qr@j}{-1}% + \qr@rightcoltrue + \qr@goinguptrue + \fi + \fi + %One problem: what if we just moved into the 7th column? + %Das ist verboten. + %If we just moved (left) into the 7th column, we should move on into the 6th column. + \ifnum\c@qr@j=7\relax% + \setcounter{qr@j}{6}% + \fi + \fi + %Now check whether there are any more bits to write. + \ifx\qr@datatowrite\qr@relax + % \qr@datatowrite is just `\relax', so we're done. + \let\qr@next=\relax + \relax + \else + % Write some more! + \def\qr@next{\qr@writedata@recursive{#1}}% + \fi + \qr@next +}% + +\def\qr@writeremainderbits#1{% + % #1 = name of a matrix that has been prepared and partly filled. + % (qr@i,qr@j) = position to write in LaTeX counters + \xa\ifnum\qr@numremainderbits>0\relax + \def\qr@datatowrite{}% + \qr@for \i = 1 to \qr@numremainderbits by 1% + {\g@addto@macro{\qr@datatowrite}{0}}% + \g@addto@macro{\qr@datatowrite}{\relax}% terminator + \qr@writedata@recursive{#1}% + \fi +}% + +\newif\ifqr@cellinmask + +\def\qr@setmaskingfunction#1{% + % #1 = 1 decimal digit for the mask. (I see no reason to use the 3-bit binary code.) + % The current position is (\themaski,\themaskj), with indexing starting at 0. + \edef\qr@maskselection{#1}% + \xa\ifcase\qr@maskselection\relax + %Case 0: checkerboard + \def\qr@parsemaskingfunction{% + % Compute mod(\themaski+\themaskj,2)% + \qr@a=\c@maski% + \advance\qr@a by \c@maskj% + \qr@b=\qr@a% + \divide\qr@b by 2% + \multiply\qr@b by 2% + \advance\qr@a by -\qr@b% + \edef\qr@maskfunctionresult{\the\qr@a}% + }% + \or + %Case 1: horizontal stripes + \def\qr@parsemaskingfunction{% + % Compute mod(\themaski,2)% + \ifodd\c@maski\relax% + \def\qr@maskfunctionresult{1}% + \else% + \def\qr@maskfunctionresult{0}% + \fi% + }% + \or + %Case 2: vertical stripes + \def\qr@parsemaskingfunction{% + % Compute mod(\themaskj,3)% + \qr@a=\c@maskj% + \divide\qr@a by 3% + \multiply\qr@a by 3% + \advance\qr@a by -\c@maskj% + \edef\qr@maskfunctionresult{\the\qr@a}% + }% + \or + %Case 3: diagonal stripes + \def\qr@parsemaskingfunction{% + % Compute mod(\themaski+\themaskj,3)% + \qr@a=\c@maski% + \advance\qr@a by \c@maskj% + \qr@b=\qr@a% + \divide\qr@b by 3% + \multiply\qr@b by 3% + \advance\qr@b by -\qr@a% + \edef\qr@maskfunctionresult{\the\qr@b}% + }% + \or + %Case 4: wide checkerboard + \def\qr@parsemaskingfunction{% + % Compute mod(floor(\themaski/2) + floor(\themaskj/3),2) % + \qr@a=\c@maski% + \divide\qr@a by 2% + \qr@b=\c@maskj% + \divide\qr@b by 3% + \advance\qr@a by \qr@b% + \qr@b=\qr@a% + \divide\qr@a by 2% + \multiply\qr@a by 2% + \advance\qr@a by -\qr@b% + \edef\qr@maskfunctionresult{\the\qr@a}% + }% + \or + %Case 5: quilt + \def\qr@parsemaskingfunction{% + % Compute mod(\themaski*\themaskj,2) + mod(\themaski*\themaskj,3) % + \qr@a=\c@maski% + \multiply\qr@a by \c@maskj% + \qr@b=\qr@a% + \qr@c=\qr@a% + \divide\qr@a by 2% + \multiply\qr@a by 2% + \advance\qr@a by -\qr@c% (result will be -mod(i*j,2), which is negative.) + \divide\qr@b by 3% + \multiply\qr@b by 3% + \advance\qr@b by -\qr@c% (result will be -mod(i*j,3), which is negative.) + \advance\qr@a by \qr@b% (result is negative of what's in the spec.) + \edef\qr@maskfunctionresult{\the\qr@a}% + }% + \or + %Case 6: arrows + \def\qr@parsemaskingfunction{% + % Compute mod( mod(\themaski*\themaskj,2) + mod(\themaski*\themaskj,3) , 2 ) % + \qr@a=\c@maski% + \multiply\qr@a by \c@maskj% + \qr@b=\qr@a% + \qr@c=\qr@a% + \multiply\qr@c by 2% % \qr@c equals 2*i*j. + \divide\qr@a by 2% + \multiply\qr@a by 2% + \advance\qr@c by -\qr@a% Now \qr@c equals i*j + mod(i*j,2). + \divide\qr@b by 3% + \multiply\qr@b by 3% + \advance\qr@c by -\qr@b% (Now \qr@c equals mod(i*j,2) + mod(i*j,3). + \qr@a=\qr@c% + \divide\qr@a by 2% + \multiply\qr@a by 2% + \advance\qr@c by-\qr@a% + \edef\qr@maskfunctionresult{\the\qr@c}% + }% + \or + %Case 7: shotgun + \def\qr@parsemaskingfunction{% + % Compute mod( mod(\themaski+\themaskj,2) + mod(\themaski*\themaskj,3) , 2 ) % + \qr@a=\c@maski% + \advance\qr@a by \c@maskj% %So \qr@a = i+j + \qr@b=\c@maski% + \multiply\qr@b by \c@maskj% %So \qr@b = i*j + \qr@c=\qr@a% + \advance\qr@c by \qr@b% So \qr@c = i+j+i*j + \divide\qr@a by 2% + \multiply\qr@a by 2% + \advance\qr@c by -\qr@a% So \qr@c = mod(i+j,2) + i*j + \divide\qr@b by 3% + \multiply\qr@b by 3% + \advance\qr@c by -\qr@b% So \qr@c = mod(i+j,2) + mod(i*j,3) + \qr@a=\qr@c% + \divide\qr@c by 2% + \multiply\qr@c by 2% + \advance\qr@a by -\qr@c% + \edef\qr@maskfunctionresult{\the\qr@a}% + }% + \fi +}% + +\def\qr@checkifcellisinmask{% + % The current position is (\i,\j), in TeX counts, + % but the LaTeX counters (maski,maskj) should contain + % the current position with indexing starting at 0. + % That is, maski = \i-1 and maskj = \j-1. + % + % \qr@parsemaskingfunction must have been set by a call to \qr@setmaskingfunction + \qr@parsemaskingfunction + \xa\ifnum\qr@maskfunctionresult=0\relax + \qr@cellinmasktrue + \else + \qr@cellinmaskfalse + \fi +}% + +\newcounter{maski}% +\newcounter{maskj}% + +\def\qr@applymask#1#2#3{% + % #1 = name of a matrix that should be filled out completely + % except for the format and/or version information. + % #2 = name of a new matrix to contain the masked version + % #3 = 1 decimal digit naming the mask + \qr@createduplicatematrix{#2}{#1}% + \qr@setmaskingfunction{#3}% + \setcounter{maski}{-1}% + \qr@for \i = 1 to \qr@size by 1% + {\stepcounter{maski}% + \setcounter{maskj}{-1}% + \qr@for \j = 1 to \qr@size by 1% + {\stepcounter{maskj}% + \qr@checkifcellisinmask + \ifqr@cellinmask + \qr@checkifcurrentcellcontainsdata{#2}% + \ifqr@currentcellcontainsdata + \qr@flipcurrentcell{#2}% + \fi + \fi + }% + }% +}% + +\newif\ifqr@currentcellcontainsdata +\qr@currentcellcontainsdatafalse + +\def\qr@@white{\qr@white}% +\def\qr@@black{\qr@black}% + +\def\qr@checkifcurrentcellcontainsdata#1{% + % #1 = name of matrix + \qr@currentcellcontainsdatafalse + \xa\ifx\csname #1@\the\i @\the\j\endcsname\qr@@white + \qr@currentcellcontainsdatatrue + \fi + \xa\ifx\csname #1@\the\i @\the\j\endcsname\qr@@black + \qr@currentcellcontainsdatatrue + \fi +}% + +\def\qr@flipped@black{\qr@black}% +\def\qr@flipped@white{\qr@white}% + +\def\qr@flipcurrentcell#1{% + % #1 = name of matrix + % (\i, \j) = current position, in TeX counts. + % This assumes the cell contains data, either black or white! + \xa\ifx\csname #1@\the\i @\the\j\endcsname\qr@@white + \qr@storetomatrix{#1}{\the\i}{\the\j}{\qr@flipped@black}% + \else + \qr@storetomatrix{#1}{\the\i}{\the\j}{\qr@flipped@white}% + \fi +}% + +\def\qr@chooseandapplybestmask#1{% + % #1 = name of a matrix that should be filled out completely + % except for the format and/or version information. + % This function applies all eight masks in succession, + % calculates their penalties, and remembers the best. + % The number indicating which mask was used is saved in \qr@mask@selected. + \qr@createduplicatematrix{originalmatrix}{#1}% + \message{^^J}% + \gdef\qr@currentbestmask{0}% + \qr@for \i = 1 to 7 by 1% + {\message{^^J}% + \xa\xa\xa\ifnum\xa\qr@penalty\xa<\qr@currentbestpenalty\relax + %We found a better mask. + \xdef\qr@currentbestmask{\the\i}% + \qr@createduplicatematrix{#1}{currentmasked}% + \xdef\qr@currentbestpenalty{\qr@penalty}% + \fi + }% + \xdef\qr@mask@selected{\qr@currentbestmask}% + \message{^^J}% +}% + +\def\qr@Ni{3}% +\def\qr@Nii{3}% +\def\qr@Niii{40}% +\def\qr@Niv{10}% +\def\qr@fiveones{11111}% +\def\qr@fivezeros{11111}% +\def\qr@twoones{11}% +\def\qr@twozeros{00}% +\def\qr@finderA{00001011101}% +\def\qr@finderB{10111010000}% +\def\qr@finderB@three{1011101000}% +\def\qr@finderB@two{101110100}% +\def\qr@finderB@one{10111010}% +\def\qr@finderB@zero{1011101}% +\newif\ifqr@stringoffive +\def\qr@addpenaltyiii{% + \addtocounter{penaltyiii}{\qr@Niii}% +}% +\newcounter{totalones}% +\newcounter{penaltyi}% +\newcounter{penaltyii}% +\newcounter{penaltyiii}% +\newcounter{penaltyiv}% +\def\qr@evaluatemaskpenalty#1{% + % #1 = name of a matrix that we will test for the penalty + % according to the specs. + \setcounter{penaltyi}{0}% + \setcounter{penaltyii}{0}% + \setcounter{penaltyiii}{0}% + \setcounter{penaltyiv}{0}% + \bgroup%localize the meanings we give to the symbols + \def\qr@black{1}\def\qr@white{0}% + \def\qr@black@fixed{1}\def\qr@white@fixed{0}% + \def\qr@format@square{0}% This is not stated in the specs, but seems + % to be the standard implementation. + \def\qr@blank{0}% These would be any bits at the end. + % + \setcounter{totalones}{0}% + \qr@for \i=1 to \qr@size by 1% + {\def\qr@lastfive{z}% %The z is a dummy, that will be removed before any testing. + \qr@stringoffivefalse + \def\qr@lasttwo@thisrow{z}% %The z is a dummy. + \def\qr@lasttwo@nextrow{z}% %The z is a dummy. + \def\qr@lastnine{z0000}% %The 0000 stands for the white space to the left. The z is a dummy. + \def\qr@ignore@finderB@at{0}% + \qr@for \j=1 to \qr@size by 1% + {\edef\qr@newbit{\qr@matrixentry{#1}{\the\i}{\the\j}}% + % + % LASTFIVE CODE FOR PENALTY 1 + % First, add the new bit to the end. + \xa\g@addto@macro\xa\qr@lastfive\xa{\qr@newbit}% + \ifnum\j<5\relax% + %Not yet on the 5th entry. + %Don't do any testing. + \else + % 5th entry or later. + % Remove the old one, and then test. + \qr@removefirsttoken\qr@lastfive% + \ifx\qr@lastfive\qr@fiveones% + \ifqr@stringoffive% + %This is a continuation of a previous block of five or more 1's. + \stepcounter{penaltyi}% + \else + %This is a new string of five 1's. + \addtocounter{penaltyi}{\qr@Ni}% + \global\qr@stringoffivetrue + \fi + \else + \ifx\qr@lastfive\qr@fivezeros% + \ifqr@stringoffive + %This is a continuation of a previous block of five or more 0's. + \stepcounter{penaltyi}% + \else + %This is a new string of five 0's. + \addtocounter{penaltyi}{\qr@Ni}% + \global\qr@stringoffivetrue + \fi + \else + %This is not a string of five 1's or five 0's. + \global\qr@stringoffivefalse + \fi + \fi + \fi + % + % 2x2 BLOCKS FOR PENALTY 2 + % Every 2x2 block of all 1's counts for \qr@Nii penalty points. + % We do not need to run this test in the last row. + \xa\ifnum\xa\i\xa<\qr@size\relax + \xa\g@addto@macro\xa\qr@lasttwo@thisrow\xa{\qr@newbit}% + %Compute \qr@iplusone + \qr@a=\i\relax% + \advance\qr@a by 1% + \edef\qr@iplusone{\the\qr@a}% + % + \edef\qr@nextrowbit{\qr@matrixentry{#1}{\qr@iplusone}{\the\j}}% + \xa\g@addto@macro\xa\qr@lasttwo@nextrow\xa{\qr@nextrowbit}% + \ifnum\j<2\relax% + %Still in the first column; no check. + \else + %Second column or later. Remove the old bits, and then test. + \qr@removefirsttoken\qr@lasttwo@thisrow + \qr@removefirsttoken\qr@lasttwo@nextrow + \ifx\qr@lasttwo@thisrow\qr@twoones + \ifx\qr@lasttwo@nextrow\qr@twoones + \addtocounter{penaltyii}{\qr@Nii}% + \fi + \else + \ifx\qr@lasttwo@thisrow\qr@twozeros + \ifx\qr@lasttwo@nextrow\qr@twozeros + \addtocounter{penaltyii}{\qr@Nii}% + \fi + \fi + \fi + \fi + \fi + % + % LASTNINE CODE FOR PENALTY 3 + % First, add the new bit to the end. + \xa\g@addto@macro\xa\qr@lastnine\xa{\qr@newbit}% + \ifnum\j<7\relax% + %Not yet on the 7th entry. + %Don't do any testing. + \else + % 7th entry or later. + % Remove the old one, and then test. + \qr@removefirsttoken\qr@lastnine + \xa\ifnum\qr@size=\j\relax% + % Last column. Any of the following should count: + % 1011101 (\qr@finderB@zero) + % 10111010 (\qr@finderB@one) + % 101110100 (\qr@finderB@two) + % 1011101000 (\qr@finderB@three) + % 10111010000 (\qr@finderB) + \ifx\qr@lastnine\qr@finderB + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@three + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@two + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@one + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@zero + \qr@addpenaltyiii + \fi + \fi + \fi + \fi + \fi + \else + \ifx\qr@lastnine\qr@finderA% %Matches 0000 1011101 + \qr@addpenaltyiii + %Also, we record our discovery, so that we can't count this pattern again + %if it shows up four columns later as 1011101 0000. + % + %Set \qr@ignore@finderB@at to \j+4. + \qr@a=\j\relax% + \advance\qr@a by 4% + \xdef\qr@ignore@finderB@at{\the\qr@a}% + \else + \ifx\qr@lastfive\qr@finderB% %Matches 1011101 0000. + \xa\ifnum\qr@ignore@finderB@at=\j\relax + %This pattern was *not* counted already earlier. + \qr@addpenaltyiii + \fi + \fi + \fi + \fi + \fi + % + %COUNT 1's FOR PENALTY 4 + \xa\ifnum\qr@newbit=1\relax% + \stepcounter{totalones}% + \fi + }% end of j-loop + }% end of i-loop + % + %NOW WE ALSO NEED TO RUN DOWN THE COLUMNS TO FINISH CALCULATING PENALTIES 1 AND 3. + \qr@for \j=1 to \qr@size by 1% + {\def\qr@lastfive{z}% %The z is a dummy, that will be removed before any testing. + \qr@stringoffivefalse + \def\qr@lastnine{z0000}% %The 0000 stands for the white space to the left. The z is a dummy. + \def\qr@ignore@finderB@at{0}% + \qr@for \i=1 to \qr@size by 1% + {\edef\qr@newbit{\qr@matrixentry{#1}{\the\i}{\the\j}}% + % + % LASTFIVE CODE FOR PENALTY 1 + % First, add the new bit to the end. + \xa\g@addto@macro\xa\qr@lastfive\xa{\qr@newbit}% + \ifnum\i<5\relax% + %Not yet on the 5th entry. + %Don't do any testing. + \else + % 5th entry or later. + % Remove the old one, and then test. + \qr@removefirsttoken\qr@lastfive% + \ifx\qr@lastfive\qr@fiveones% + \ifqr@stringoffive% + %This is a continuation of a previous block of five or more 1's. + \stepcounter{penaltyi}% + \else + %This is a new string of five 1's. + \addtocounter{penaltyi}{\qr@Ni}% + \global\qr@stringoffivetrue + \fi + \else + \ifx\qr@lastfive\qr@fivezeros% + \ifqr@stringoffive + %This is a continuation of a previous block of five or more 0's. + \stepcounter{penaltyi}% + \else + %This is a new string of five 0's. + \addtocounter{penaltyi}{\qr@Ni}% + \global\qr@stringoffivetrue + \fi + \else + %This is not a string of five 1's or five 0's. + \global\qr@stringoffivefalse + \fi + \fi + \fi + % + % HAPPILY, WE DON'T NEED TO CALCULATE PENALTY 2 AGAIN. + % + % LASTNINE CODE FOR PENALTY 3 + % First, add the new bit to the end. + \xa\g@addto@macro\xa\qr@lastnine\xa{\qr@newbit}% + \ifnum\i<7\relax% + %Not yet on the 7th entry. + %Don't do any testing. + \else + % 7th entry or later. + % Remove the old one, and then test. + \qr@removefirsttoken\qr@lastnine + \xa\ifnum\qr@size=\i\relax% + % Last column. Any of the following should count: + % 1011101 (\qr@finderB@zero) + % 10111010 (\qr@finderB@one) + % 101110100 (\qr@finderB@two) + % 1011101000 (\qr@finderB@three) + % 10111010000 (\qr@finderB) + \ifx\qr@lastnine\qr@finderB + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@three + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@two + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@one + \qr@addpenaltyiii + \else + \qr@removefirsttoken\qr@lastnine + \ifx\qr@lastnine\qr@finderB@zero + \qr@addpenaltyiii + \fi + \fi + \fi + \fi + \fi + \else + \ifx\qr@lastnine\qr@finderA% %Matches 0000 1011101 + \qr@addpenaltyiii + %Also, we record our discovery, so that we can't count this pattern again + %if it shows up four columns later as 1011101 0000. + % + %Set \qr@ignore@finderB@at to \i+4. + \qr@a=\i\relax% + \advance\qr@a by 4% + \xdef\qr@ignore@finderB@at{\the\qr@a}% + \else + \ifx\qr@lastfive\qr@finderB% %Matches 1011101 0000. + \xa\ifnum\qr@ignore@finderB@at=\i\relax + %This pattern was *not* counted already earlier. + \qr@addpenaltyiii + \fi + \fi + \fi + \fi + \fi + % + }% end of i-loop + }% end of j-loop + \egroup% + % + %CALCULATE PENALTY 4 + %According to the spec, penalty #4 is computed as + % floor( |(i/n^2)-0.5|/0.05 ) + % where i is the total number of 1's in the matrix. + % This is equal to abs(20*i-10n^2) div n^2. + % + \qr@a=\c@totalones\relax + \multiply\qr@a by 20\relax + \qr@b=\qr@size\relax + \multiply\qr@b by \qr@size\relax + \qr@c=10\relax + \multiply\qr@c by \qr@b\relax + \advance\qr@a by -\qr@c\relax + \ifnum\qr@a<0\relax + \multiply\qr@a by -1\relax + \fi + \divide\qr@a by \qr@b\relax + \setcounter{penaltyiv}{\the\qr@a}% + % + %CALCULATE TOTAL PENALTY + \qr@a=\thepenaltyi\relax% + \advance\qr@a by \thepenaltyii\relax% + \advance\qr@a by \thepenaltyiii\relax% + \advance\qr@a by \thepenaltyiv\relax% + \edef\qr@penalty{\the\qr@a}% +}% + +\def\qr@removefirsttoken#1{% + %Removes the first token from the macro named in #1. + \edef\qr@argument{(#1)}% + \xa\qr@removefirsttoken@int\qr@argument% + \xdef#1{\qr@removefirsttoken@result}% +}% +\def\qr@removefirsttoken@int(#1#2){% + \def\qr@removefirsttoken@result{#2}% +}% + +\def\qr@writeformatstring#1#2{% + % #1 = matrix name + % #2 = binary string representing the encoded and masked format information + \setcounter{qr@i}{9}% + \setcounter{qr@j}{1}% + \edef\qr@argument{{#1}(#2\relax)}% + \xa\qr@writeformatA@recursive\qr@argument + % + \setcounter{qr@i}{\qr@numberofrowsinmatrix{#1}}% + \setcounter{qr@j}{9}% + \xa\qr@writeformatB@recursive\qr@argument +}% + +\def\qr@writeformatA@recursive#1(#2#3){% + % #1 = matrix name + % #2 = first bit of string + % #3 = rest of bitstream + % (qr@i,qr@j) = current (valid) position to write (in LaTeX counters) + \ifnum#2=1\relax + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@black@format}% + \else + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@white@format}% + \fi + % Now the tricky part--moving \i and \j to their next positions. + \ifnum\c@qr@j<9\relax + %If we're not yet in column 9, move right. + \stepcounter{qr@j}% + \ifnum\c@qr@j=7\relax + %But we skip column 7! + \stepcounter{qr@j}% + \fi + \else + %If we're in column 9, we move up. + \addtocounter{qr@i}{-1}% + \ifnum\c@qr@i=7\relax + %But we skip row 7! + \addtocounter{qr@i}{-1}% + \fi + \fi + %N.B. that at the end of time, this will leave us at invalid position (0,9). + %That makes for an easy test to know when we are done. + \ifnum\c@qr@i<1 + \let\qr@next=\relax + \else + \def\qr@next{\qr@writeformatA@recursive{#1}(#3)}% + \fi + \qr@next +}% + +\def\qr@writeformatB@recursive#1(#2#3){% + % #1 = matrix name + % #2 = first bit of string + % #3 = rest of bitstream + % (qr@i,qr@j) = current (valid) position to write (in LaTeX counters) + \ifnum#2=1\relax + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@black@format}% + \else + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@white@format}% + \fi + % Now the tricky part--moving counters i and j to their next positions. + \qr@a=\qr@size% + \advance\qr@a by -6\relax% + \ifnum\qr@a<\c@qr@i\relax + %If we're not yet in row n-6, move up. + \addtocounter{qr@i}{-1}% + \else + \ifnum\qr@a=\c@qr@i\relax + %If we're actually in row n-6, we jump to position (9,n-7). + \setcounter{qr@i}{9}% + %Set counter j equal to \qr@size-7. + \global\c@qr@j=\qr@size\relax% + \global\advance\c@qr@j by -7\relax% + \else + %Otherwise, we must be in row 9. + %In this case, we move right. + \stepcounter{qr@j}% + \fi + \fi + %N.B. that at the end of time, this will leave us at invalid position (9,n+1). + %That makes for an easy test to know when we are done. + \xa\ifnum\qr@size<\c@qr@j\relax + \let\qr@next=\relax + \else + \def\qr@next{\qr@writeformatB@recursive{#1}(#3)}% + \fi + \qr@next +}% + +\def\qr@writeversionstring#1#2{% + % #1 = matrix name + % #2 = binary string representing the encoded version information + % + % Plot the encoded version string into the matrix. + % This is only done for versions 7 and higher. + \xa\ifnum\qr@version>6\relax + %Move to position (n-8,6). + \setcounter{qr@i}{\qr@size}\relax% + \addtocounter{qr@i}{-8}\relax% + \setcounter{qr@j}{6}% + \edef\qr@argument{{#1}(#2\relax)}% + \xa\qr@writeversion@recursive\qr@argument + \fi +}% + +\def\qr@writeversion@recursive#1(#2#3){% + % #1 = matrix name + % #2 = first bit of string + % #3 = rest of bitstream + % (qr@i,qr@j) = current (valid) position to write (in LaTeX counters) + % + % The version information is stored symmetrically in the matrix + % In two transposed regions, so we can write both at the same time. + % In the comments, we describe what happens in the lower-left region, + % not the upper-right. + % + %Set \qr@topline equal to n-10. + \qr@a=\qr@size\relax% + \advance\qr@a by -10\relax% + \edef\qr@topline{\the\qr@a}% + % + \ifnum#2=1\relax + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@black@format}% + \qr@storetomatrix{#1}{\theqr@j}{\theqr@i}{\qr@black@format}% + \else + \qr@storetomatrix{#1}{\theqr@i}{\theqr@j}{\qr@white@format}% + \qr@storetomatrix{#1}{\theqr@j}{\theqr@i}{\qr@white@format}% + \fi + % Now the tricky part--moving counters i and j to their next positions. + \addtocounter{qr@i}{-1}% + \xa\ifnum\qr@topline>\c@qr@i\relax + %We've overshot the top of the region. + %We need to move left one column and down three. + \addtocounter{qr@j}{-1}% + \addtocounter{qr@i}{3}% + \fi + %N.B. that at the end of time, this will leave us at invalid position (n-8,0). + %That makes for an easy test to know when we are done. + \ifnum\c@qr@j<1\relax + \let\qr@next=\relax + \else + \def\qr@next{\qr@writeversion@recursive{#1}(#3)}% + \fi + \qr@next +}% +\newcounter{qr@hexchars}% + +\def\qr@string@binarytohex#1{% + \qr@binarytohex{\qr@hex@result}{#1}% +}% + +\def\qr@encode@binary#1{% + % #1 = string of ascii characters, to be converted into bitstream + % + % We do this one entirely in hex, rather than binary, because we can. + \edef\qr@plaintext{#1}% + % + %First, the mode indicator. + \def\qr@codetext{4}% %This means `binary' + % + %Next, the character count. + \qr@getstringlength{\qr@plaintext}% + %Set \qr@charactercountlengthinhex to \qr@charactercountbits@byte/4% + \qr@a=\qr@charactercountbits@byte\relax% + \divide \qr@a by 4\relax% + \edef\qr@charactercountlengthinhex{\the\qr@a}% + \qr@decimaltohex[\qr@charactercountlengthinhex]{\qr@charactercount}{\qr@stringlength}% + \xa\g@addto@macro\xa\qr@codetext\xa{\qr@charactercount}% + % + %Now comes the actual data. + \edef\qr@argument{(,\qr@plaintext\relax\relax\relax)}% + \xa\qr@encode@ascii@recursive\qr@argument% + % + %Now the terminator. + \g@addto@macro\qr@codetext{0}% %This is '0000' in binary. + % + %There is no need to pad bits to make a multiple of 8, + %because the data length is already 4 + 8 + 8n + 4. + % + %Now add padding codewords if needed. + \setcounter{qr@hexchars}{0}% + \qr@getstringlength{\qr@codetext}% + \setcounter{qr@hexchars}{\qr@stringlength}% + %Set \qr@numpaddingcodewords equal to \qr@totaldatacodewords - qr@hexchars/2. + \qr@a=-\c@qr@hexchars\relax + \divide\qr@a by 2\relax + \advance\qr@a by \qr@totaldatacodewords\relax + \edef\qr@numpaddingcodewords{\the\qr@a}% + % + \xa\ifnum\qr@numpaddingcodewords<0% + \edef\ds{ERROR: Too much data! Over by \qr@numpaddingcodewords bytes.}\show\ds% + \fi% + \xa\ifnum\qr@numpaddingcodewords>0% + \qr@for \i = 2 to \qr@numpaddingcodewords by 2% + {\g@addto@macro{\qr@codetext}{ec11}}% + \xa\ifodd\qr@numpaddingcodewords\relax% + \g@addto@macro{\qr@codetext}{ec}% + \fi% + \fi% +}% + +\def\qr@encode@ascii@recursive(#1,#2#3){% + % #1 = hex codes translated so far + % #2 = next plaintext character to translate + % #3 = remainder of plaintext + \edef\qr@testii{#2}% + \ifx\qr@testii\qr@relax% + % All done! + \g@addto@macro\qr@codetext{#1}% + \else% + % Another character to translate. + \edef\qr@asciicode{\number`#2}% + \qr@decimaltohex[2]{\qr@newhexcodes}{\qr@asciicode}% + \edef\qr@argument{(#1\qr@newhexcodes,#3)}% + %\show\qr@argument + \xa\qr@encode@ascii@recursive\qr@argument% + \fi% +}% + +\def\qr@splitcodetextintoblocks{% + \setcounter{qr@i}{0}% + \qr@for \j = 1 to \qr@numshortblocks by 1% + {\stepcounter{qr@i}% + \qr@splitoffblock{\qr@codetext}{\theqr@i}{\qr@shortblock@size}% + }% + \xa\ifnum\qr@numlongblocks>0\relax% + \qr@for \j = 1 to \qr@numlongblocks by 1% + {\stepcounter{qr@i}% + \qr@splitoffblock{\qr@codetext}{\theqr@i}{\qr@longblock@size}% + }% + \fi% +}% + +\def\qr@splitoffblock#1#2#3{% + % #1 = current codetext in hexadecimal + % #2 = number to use in csname "\datablock@#2". + % #3 = number of bytes to split off + \message{}% + \xa\gdef\csname datablock@#2\endcsname{}% %This line is important! + \qr@for \i = 1 to #3 by 1% + {\edef\qr@argument{{#2}(#1)}% + \xa\qr@splitoffblock@int\qr@argument% + }% +}% + +\def\qr@splitoffblock@int#1(#2#3#4){% + % #1 = number to use in csname "\datablock@#1". + % #2#3 = next byte to split off + % #4 = remaining text + % + % We add the next byte to "\datablock@#1", + % and we remove it from the codetext. + \xa\xdef\csname datablock@#1\endcsname{\csname datablock@#1\endcsname#2#3}% + \xdef\qr@codetext{#4}% +}% + +\def\qr@createerrorblocks{% + \qr@for \ii = 1 to \qr@numblocks by 1% + {\message{}% + \FX@generate@errorbytes{\csname datablock@\the\ii\endcsname}{\qr@num@eccodewords}% + \xa\xdef\csname errorblock@\the\ii\endcsname{\FX@errorbytes}% + }% +}% + +\def\qr@interleave{% + \setcounter{qr@i}{0}% + \def\qr@interleaved@text{}% + \message{0\relax% + \message{\qr@longblock@size.>}% + \else + \message{.>}% + \fi + \message{}% +}% + +\def\qr@writefromblock#1#2{% + % #1 = either 'datablock' or 'errorblock' + % #2 = block number, in {1,...,\qr@numblocks}% + \edef\qr@argument{(\csname #1@#2\endcsname\relax\relax\relax)}% + \xa\qr@writefromblock@int\qr@argument + \xa\xdef\csname #1@#2\endcsname{\qr@writefromblock@remainder}% +}% + +\def\qr@writefromblock@int(#1#2#3){% + % #1#2 = first byte (in hex) of text, which will be written to \qr@interleaved@text + % #3 = remainder, including \relax\relax\relax terminator. + \g@addto@macro{\qr@interleaved@text}{#1#2}% + \qr@writefromblock@intint(#3)% +}% + +\def\qr@writefromblock@intint(#1\relax\relax\relax){% + \xdef\qr@writefromblock@remainder{#1}% +}% +\let\xa=\expandafter +\makeatletter + +\def\qr@preface@macro#1#2{% + % #1 = macro name + % #2 = text to add to front of macro + \def\qr@tempb{#2}% + \xa\xa\xa\gdef\xa\xa\xa#1\xa\xa\xa{\xa\qr@tempb #1}% +}% + +\newif\ifqr@leadingcoeff +\def\qr@testleadingcoeff(#1#2){% + % Tests whether the leading digit of #1#2 is 1. + \ifnum#1=1\relax + \qr@leadingcoefftrue + \else + \qr@leadingcoefffalse + \fi +}% + +\def\qr@polynomialdivide#1#2{% + \edef\qr@numerator{#1}% + \edef\qr@denominator{#2}% + \qr@divisiondonefalse% + \xa\xa\xa\qr@oneroundofdivision\xa\xa\xa{\xa\qr@numerator\xa}\xa{\qr@denominator}% +}% + +\def\@qr@empty{}% +\def\qr@oneroundofdivision#1#2{% + % #1 = f(x), of degree n + % #2 = g(x), of degree m + % Obtains a new polynomial h(x), congruent to f(x) modulo g(x), + % but of degree at most n-1. + % + % If leading coefficient of f(x) is 1, subtracts off g(x) * x^(n-m). + % If leading coefficient of f(x) is 0, strips off that leading zero. + % + \qr@testleadingcoeff(#1)% + \ifqr@leadingcoeff + \qr@xorbitstrings{#1}{#2}% + \ifqr@xorfailed + %If xor failed, that means our #1 was already the remainder! + \qr@divisiondonetrue + \edef\qr@theremainder{#1}% + \else + %xor succeeded. We need to recurse. + \xa\xa\xa\edef\xa\xa\xa\qr@numerator\xa\xa\xa{\xa\qr@stripleadingzero\xa(\qr@xorresult)}% + \fi + \else + \xa\def\xa\qr@numerator\xa{\qr@stripleadingzero(#1)}% + \ifx\qr@numerator\@qr@empty + \qr@divisiondonetrue + \def\qr@theremainder{0}% + \fi + \fi + \ifqr@divisiondone + \relax + \else + \xa\qr@oneroundofdivision\xa{\qr@numerator}{#2}% + \fi +}% + +\def\qr@stripleadingzero(0#1){#1}%Strips off a leading zero. + +\newif\ifqr@xorfailed% This flag will trigger when #2 is longer than #1. + +\def\qr@xorbitstrings#1#2{% + % #1 = bitstring + % #2 = bitstring no longer than #1 + \qr@xorfailedfalse + \edef\qr@argument{(,#1\relax\relax)(#2\relax\relax)}% + \xa\qr@xorbitstrings@recursive\qr@argument + %\qr@xorbitstrings@recursive(,#1\relax\relax)(#2\relax\relax)% +}% + +\def\qr@xorbitstrings@recursive(#1,#2#3)(#4#5){% + % #1#2#3 is the first bitstring, xor'ed up through #1. + % #4#5 is the remaining portion of the second bitstring. + \def\qr@testii{#2}% + \def\qr@testiv{#4}% + \ifx\qr@testii\qr@relax + % #1 contains the whole string. + % Now if #4 is also \relax, that means the two strings started off with equal lengths. + % If, however, #4 is not \relax, that means the second string was longer than the first, a problem. + \ifx\qr@testiv\qr@relax + %No problem. We are done. + \qr@xorbit@saveresult(#1#2#3)% + \else + %Problem! The second string was longer than the first. + \qr@xorfailedtrue + \def\qr@xorresult{}% + \fi + \else + % There is still a bit to manipulate in #2. + % Check whether #4 contains anything. + \ifx\qr@testiv\qr@relax + % No, #4 is empty. We are done. "#2#3" contains the remainder of the first string, + % which we append untouched and then strip off the two \relax-es. + \qr@xorbit@saveresult(#1#2#3)% + \else + % Yes, #4 still has something to XOR. Do the task. + \ifnum#2=#4\relax + \qr@xorbitstrings@recursive(#1% + 0,#3)(#5)% + \else + \qr@xorbitstrings@recursive(#1% + 1,#3)(#5)% + \fi + \fi + \fi +}% + +\def\qr@xorbit@saveresult(#1\relax\relax){% + %Strips off the extra '\relax'es at the end. + \def\qr@xorresult{#1}% +}% + +\newif\ifqr@divisiondone + +\def\qr@BCHcode#1{% + \edef\qr@formatinfo{#1}% + \def\qr@formatinfopadded{\qr@formatinfo 0000000000}% + \def\qr@divisor{10100110111}% + \qr@divisiondonefalse + \qr@polynomialdivide{\qr@formatinfopadded}{\qr@divisor}% + % + \qr@getstringlength{\qr@theremainder}% + %Run loop from stringlength+1 to 10. + \qr@a=\qr@stringlength\relax% + \advance\qr@a by 1\relax% + \qr@for \i = \qr@a to 10 by 1% + {\qr@preface@macro{\qr@theremainder}{0}% + \xdef\qr@theremainder{\qr@theremainder}% + }% + \edef\qr@BCHresult{\qr@formatinfo\qr@theremainder}% +}% + +\def\qr@formatmask{101010000010010}% + +\def\qr@encodeandmaskformat#1{% + \qr@BCHcode{#1}% + \qr@xorbitstrings{\qr@BCHresult}{\qr@formatmask}% + \edef\qr@format@bitstring{\qr@xorresult}% +}% + +\def\qr@Golaycode#1{% + % #1 = 6-bit version number + \edef\qr@versioninfo{#1}% + \def\qr@versioninfopadded{\qr@versioninfo 000000000000}% %Append 12 zeros. + \def\qr@divisor{1111100100101}% + \qr@divisiondonefalse + \qr@polynomialdivide{\qr@versioninfopadded}{\qr@divisor}% + % + \qr@getstringlength{\qr@theremainder}% + %Run loop from stringlength+1 to 12. + \qr@a=\qr@stringlength\relax% + \advance\qr@a by 1\relax% + \qr@for \i = \qr@a to 12 by 1% + {\qr@preface@macro{\qr@theremainder}{0}% + \xdef\qr@theremainder{\qr@theremainder}% + }% + \edef\qr@Golayresult{\qr@versioninfo\qr@theremainder}% +}% +\def\F@result{}% + +\def\qr@xorbitstring#1#2#3{% + % #1 = new macro to receive result + % #2, #3 = bitstrings to xor. The second can be shorter than the first. + \def\qr@xor@result{}% + \edef\qr@argument{(#2\relax\relax)(#3\relax\relax)}% + \xa\qr@xorbitstring@recursive\qr@argument% + \edef#1{\qr@xor@result}% +}% +\def\qr@xorbitstring@recursive(#1#2)(#3#4){% + \edef\qr@testi{#1}% + \ifx\qr@testi\qr@relax% + %Done. + \let\qr@next=\relax% + \else + \if#1#3\relax + \g@addto@macro{\qr@xor@result}{0}% + \else + \g@addto@macro{\qr@xor@result}{1}% + \fi + \edef\qr@next{\noexpand\qr@xorbitstring@recursive(#2)(#4)}% + \fi + \qr@next +} + +\def\F@addchar@raw#1#2{% + %Add two hexadecimal digits using bitwise xor + \qr@hextobinary[4]{\qr@summandA}{#1}% + \qr@hextobinary[4]{\qr@summandB}{#2}% + \qr@xorbitstring{\F@result}{\qr@summandA}{\qr@summandB}% + \qr@binarytohex[1]{\F@result}{\F@result}% +}% + +\def\qr@canceltwos#1{% + \edef\qr@argument{(#1\relax\relax)}% + \xa\qr@canceltwos@int\qr@argument% +}% + +\def\qr@canceltwos@int(#1#2){% + \xa\qr@canceltwos@recursion(,#1#2)% +}% + +\def\qr@canceltwos@recursion(#1,#2#3){% + \def\qr@testii{#2}% + \ifx\qr@testii\qr@relax + %Cancelling complete. + \qr@striptworelaxes(#1#2#3)% + %Now \F@result contains the answer. + \else + \relax + \ifnum#2=2\relax + \qr@canceltwos@recursion(#10,#3)% + \else + \qr@canceltwos@recursion(#1#2,#3)% + \fi + \fi +}% + +\def\qr@striptworelaxes(#1\relax\relax){% + \gdef\F@result{#1}% +}% + +\qr@for \i = 0 to 15 by 1% + {\qr@decimaltohex[1]{\qr@tempa}{\the\i}% + \qr@for \j = 0 to 15 by 1% + {\qr@decimaltohex[1]{\qr@tempb}{\the\j}% + \F@addchar@raw\qr@tempa\qr@tempb + \xa\xdef\csname F@addchar@\qr@tempa\qr@tempb\endcsname{\F@result}% + }% + }% + +\def\F@addchar#1#2{% + \xa\def\xa\F@result\xa{\csname F@addchar@#1#2\endcsname}% +}% + +\def\F@addstrings#1#2{% + \edef\qr@argument{(,#1\relax\relax)(#2\relax\relax)}% + \xa\F@addstrings@recursion\qr@argument% +}% + +\def\F@addstrings@recursion(#1,#2#3)(#4#5){% + %Adds two hexadecimal strings, bitwise, from left to right. + %The second string is allowed to be shorter than the first. + \def\qr@testii{#2}% + \def\qr@testiv{#4}% + \ifx\qr@testii\qr@relax + %The entire string has been processed. + \gdef\F@result{#1}% + \else + \ifx\qr@testiv\qr@relax + %The second string is over. + \qr@striptworelaxes(#1#2#3)% + %Now \F@result contains the answer. + \else + %We continue to add. + \F@addchar{#2}{#4}% + \edef\qr@argument{(#1\F@result,#3)(#5)}% + \xa\F@addstrings@recursion\qr@argument% + \fi + \fi +}% +\gdef\F@stripleadingzero(0#1){\edef\F@result{#1}}% + +\setcounter{qr@i}{0}% +\def\qr@poweroftwo{1}% +\qr@for \i = 1 to 254 by 1% + {\stepcounter{qr@i}% + \qr@a=\qr@poweroftwo\relax + \multiply\qr@a by 2\relax + \edef\qr@poweroftwo{\the\qr@a}% + %\show\qr@poweroftwo + \qr@decimaltohex[2]{\qr@poweroftwo@hex}{\qr@poweroftwo}% + \xa\ifnum\qr@poweroftwo>255\relax + %We need to bitwise add the polynomial represented by 100011101, i.e. 0x11d. + \F@addstrings{\qr@poweroftwo@hex}{11d}% %Now it should start with 0. + \xa\F@stripleadingzero\xa(\F@result)% %Now it should be two hex digits. + \edef\qr@poweroftwo@hex{\F@result}% %Save the hex version. + \qr@hextodecimal{\qr@poweroftwo}{\F@result}% + \fi + \xdef\qr@poweroftwo{\qr@poweroftwo}% + \xa\xdef\csname F@twotothe@\theqr@i\endcsname{\qr@poweroftwo@hex}% + \xa\xdef\csname F@logtwo@\qr@poweroftwo@hex\endcsname{\theqr@i}% + }% +\xa\xdef\csname F@twotothe@0\endcsname{01}% +\xa\xdef\csname F@logtwo@01\endcsname{0}% + +\def\F@twotothe#1{% + \xa\xdef\xa\F@result\xa{\csname F@twotothe@#1\endcsname}% +}% +\def\F@logtwo#1{% + \xa\xdef\xa\F@result\xa{\csname F@logtwo@#1\endcsname}% +}% + +\def\qr@zerozero{00}% + +\def\F@multiply#1#2{% + % #1 and #2 are two elements of F_256, + % given as two-character hexadecimal strings. + % Multiply them within F_256, and place the answer in \F@result + \edef\qr@argA{#1}% + \edef\qr@argB{#2}% + \ifx\qr@argA\qr@zerozero + \def\F@result{00}% + \else + \ifx\qr@argB\qr@zerozero + \def\F@result{00}% + \else + \xa\F@logtwo\xa{\qr@argA}% + \edef\qr@logA{\F@result}% + \xa\F@logtwo\xa{\qr@argB}% + \edef\qr@logB{\F@result}% + \xa\qr@a\xa=\qr@logA\relax% \qr@a = \qr@logA + \xa\advance\xa\qr@a\qr@logB\relax% \advance \qr@a by \qr@logB + \ifnum\qr@a>254\relax% + \advance\qr@a by -255\relax% + \fi% + \xa\F@twotothe\xa{\the\qr@a}% + % Now \F@result contains the product, as desired. + \fi + \fi +}% + +\def\F@multiply#1#2{% + % #1 and #2 are two elements of F_256, + % given as two-character hexadecimal strings. + % Multiply them within F_256, and place the answer in \F@result + \edef\qr@argA{#1}% + \edef\qr@argB{#2}% + \ifx\qr@argA\qr@zerozero + \def\F@result{00}% + \else + \ifx\qr@argB\qr@zerozero + \def\F@result{00}% + \else + \xa\F@logtwo\xa{\qr@argA}% + \edef\qr@logA{\F@result}% + \xa\F@logtwo\xa{\qr@argB}% + \edef\qr@logB{\F@result}% + \xa\qr@a\xa=\qr@logA\relax% \qr@a = \qr@logA + \xa\advance\xa\qr@a\qr@logB\relax% \advance \qr@a by \qr@logB + \ifnum\qr@a>254\relax% + \advance\qr@a by -255\relax% + \fi% + \xa\F@twotothe\xa{\the\qr@a}% + % Now \F@result contains the product, as desired. + \fi + \fi +}% + +\def\FX@getstringlength#1{% + %Count number of two-character coefficients + \setcounter{qr@i}{0}% + \xdef\qr@argument{(#1\relax\relax\relax)}% + \xa\FX@stringlength@recursive\qr@argument% + \xdef\stringresult{\arabic{qr@i}}% +}% + +\def\FX@stringlength@recursive(#1#2#3){% + \def\qr@testi{#1}% + \ifx\qr@testi\qr@relax + %we are done. + \else + \stepcounter{qr@i}% + %\showthe\c@qr@i + \qr@stringlength@recursive(#3)% + \fi +}% + +\newif\ifFX@leadingcoeff@zero +\def\FX@testleadingcoeff(#1#2#3){% + % Tests whether the leading coefficient of the hex-string #1#2#3 is '00'. + \edef\FX@leadingcoefficient{#1#2}% + \FX@leadingcoeff@zerofalse + \ifx\FX@leadingcoefficient\qr@zerozero + \FX@leadingcoeff@zerotrue + \fi +}% + +\newif\ifFX@divisiondone + +\newcounter{qr@divisionsremaining} %Keep track of how many divisions to go! +\def\FX@polynomialdivide#1#2{% + \edef\FX@numerator{#1}% + \edef\FX@denominator{#2}% + \qr@getstringlength\FX@numerator% + \setcounter{qr@divisionsremaining}{\qr@stringlength}% + \qr@getstringlength\FX@denominator% + \addtocounter{qr@divisionsremaining}{-\qr@stringlength}% + \addtocounter{qr@divisionsremaining}{2}% + \divide\c@qr@divisionsremaining by 2\relax% %2 hex chars per number + \FX@divisiondonefalse% + \xa\xa\xa\FX@polynomialdivide@recursive\xa\xa\xa{\xa\FX@numerator\xa}\xa{\FX@denominator}% +}% + +\def\FX@polynomialdivide@recursive#1#2{% + % #1 = f(x), of degree n + % #2 = g(x), of degree m + % Obtains a new polynomial h(x), congruent to f(x) modulo g(x), + % but of degree at most n-1. + % + % If leading coefficient of f(x) is 0, strips off that leading zero. + % If leading coefficient of f(x) is a, subtracts off a * g(x) * x^(n-m). + % N.B. we assume g is monic. + % + \FX@testleadingcoeff(#1)% + \ifFX@leadingcoeff@zero% + %Leading coefficient is zero, so remove it. + \xa\def\xa\FX@numerator\xa{\FX@stripleadingzero(#1)}% + \else% + %Leading coefficient is nonzero, and contained in \FX@leadingcoefficient + \FX@subtractphase{#1}{#2}{\FX@leadingcoefficient}% + \ifFX@subtract@failed% + %If subtraction failed, that means our #1 was already the remainder! + \FX@divisiondonetrue% + \edef\qr@theremainder{#1}% + \else% + %xor succeeded. We need to recurse. + \xa\xa\xa\edef\xa\xa\xa\FX@numerator\xa\xa\xa{\xa\FX@stripleadingzero\xa(\FX@subtraction@result)}% + \fi% + \fi% + \addtocounter{qr@divisionsremaining}{-1}% + \ifnum\c@qr@divisionsremaining=0\relax + %Division is done! + \FX@divisiondonetrue% + \edef\qr@theremainder{\FX@numerator}% + \relax% + \else% + \xa\FX@polynomialdivide@recursive\xa{\FX@numerator}{#2}% + \fi% +}% + +\def\FX@stripleadingzero(00#1){#1}%Strips off a single leading zero of F_256. + +\newif\ifFX@subtract@failed% This flag will trigger when #2 is longer than #1. + +\def\FX@subtractphase#1#2#3{% + % #1 = bitstring + % #2 = bitstring no longer than #1 + % #3 = leading coefficient + \FX@subtract@failedfalse% + \edef\qr@argument{(,#1\relax\relax\relax)(#2\relax\relax\relax)(#3)}% + \xa\FX@subtract@recursive\qr@argument% +}% + +\def\FX@subtract@recursive(#1,#2#3#4)(#5#6#7)(#8){% + % This is a recursive way to compute f(x) - a*g(x)*x^k. + % #1#2#3#4 is the first bitstring, subtracted up through #1. + % Thus #2#3 constitutes the next two-character coefficient. + % #5#6#7 is the remaining portion of the second bitstring. + % Thus #5#6 constitutes the next two-character coefficient + % #8 is the element a of F_256. It should contain two characters. + \def\qr@testii{#2}% + \def\qr@testv{#5}% + \ifx\qr@testii\qr@relax + % #1 contains the whole string. + % Now if #5 is also \relax, that means the two strings started off with equal lengths. + % If, however, #5 is not \relax, that means the second string was longer than the first, a problem. + \ifx\qr@testv\qr@relax + %No problem. We are done. + \FX@subtract@saveresult(#1#2#3#4)% %We keep the #2#3#4 to be sure we have all three relax-es to strip off. + \else + %Problem! The second string was longer than the first. + %This usually indicates the end of the long division process. + \FX@subtract@failedtrue + \def\FX@subtraction@result{}% + \fi + \else + % There is still a coefficient to manipulate in #2#3. + % Check whether #5 contains anything. + \ifx\qr@testv\qr@relax + % No, #5 is empty. We are done. "#2#3#4" contains the remainder of the first string, + % which we append untouched and then strip off the three \relax-es. + \FX@subtract@saveresult(#1#2#3#4)% + \else + % Yes, #5#6 still has something to XOR. Do the task. + \F@multiply{#5#6}{#8}% Multiply by the factor 'a'. + \F@addstrings{#2#3}{\F@result}% Subtract. (We're in characteristic two, so adding works.) + \edef\qr@argument{(#1\F@result,#4)(#7)(#8)}% + \xa\FX@subtract@recursive\qr@argument% + \fi + \fi +}% + +\def\FX@subtract@saveresult(#1\relax\relax\relax){% + %Strips off the three extra '\relax'es at the end. + \def\FX@subtraction@result{#1}% +}% + +\def\FX@creategeneratorpolynomial#1{% + % #1 = n, the number of error codewords desired. + % We need to create \prod_{j=0}^{n-1} (x-2^j). + \edef\FX@generator@degree{#1}% + \def\FX@generatorpolynomial{01}% Initially, set it equal to 1. + \setcounter{qr@i}{0}% + \FX@creategenerator@recursive% + %The result is now stored in \FX@generatorpolynomial +}% + +\def\FX@creategenerator@recursive{% + % \c@qr@i contains the current value of i. + % \FX@generatorpolynomial contains the current polynomial f(x), + % which should be a degree-i polynomial + % equal to \prod_{j=0}^{i-1} (x-2^j). + % (If i=0, then \FX@generatorpolynomial should be 01.) + % This recursion step should multiply the existing polynomial by (x-2^i), + % increment i by 1, and check whether we're done or not. + \edef\qr@summandA{\FX@generatorpolynomial 00}% This is f(x) * x + \edef\qr@summandB{00\FX@generatorpolynomial}% This is f(x), with a 0x^{i+1} in front. + \F@twotothe{\theqr@i}% + \edef\qr@theconstant{\F@result}% + \FX@subtractphase{\qr@summandA}{\qr@summandB}{\qr@theconstant}% + %This calculates \qr@summandA + \qr@theconstant * \qr@summandB + %and stores the result in \FX@subtraction@result + \edef\FX@generatorpolynomial{\FX@subtraction@result}% + \stepcounter{qr@i}% + \xa\ifnum\FX@generator@degree=\c@qr@i\relax% + %We just multiplied by (x-2^{n-1}), so we're done. + \relax% + \else% + %We need to do this again! + \xa% + \FX@creategenerator@recursive% + \fi% +}% + +\def\FX@generate@errorbytes#1#2{% + % #1 = datastream in hex + % #2 = number of error correction bytes requested + \edef\qr@numerrorbytes{#2}% + \xa\FX@creategeneratorpolynomial\xa{\qr@numerrorbytes}% + \edef\FX@numerator{#1}% + \qr@for \i = 1 to \qr@numerrorbytes by 1% + {\g@addto@macro\FX@numerator{00}}% %One error byte means two hex codes. + \FX@polynomialdivide{\FX@numerator}{\FX@generatorpolynomial}% + \edef\FX@errorbytes{\qr@theremainder}% +}% +\newif\ifqr@versionmodules + +\def\qr@level@char#1{% + \xa\ifcase#1 + M\or L\or H\or Q\fi}% + +\newif\ifqr@versiongoodenough +\def\qr@choose@best@version#1{% + % \qr@desiredversion = user-requested version + % \qr@desiredlevel = user-requested error-correction level + \edef\qr@plaintext{#1}% + \qr@getstringlength{\qr@plaintext}% + % + %Run double loop over levels and versions, looking for + %the smallest version that can contain our data, + %and then choosing the best error-correcting level at that version, + %subject to the level being at least as good as the user desires. + \global\qr@versiongoodenoughfalse% + \gdef\qr@bestversion{0}% + \gdef\qr@bestlevel{0}% + \ifnum\qr@desiredversion=0\relax + \qr@a=1\relax + \else + \qr@a=\qr@desiredversion\relax + \fi + \qr@for \i=\qr@a to 40 by 1 + {\edef\qr@version{\the\i}% + \global\qr@versiongoodenoughfalse + \qr@for \j=0 to 3 by 1% + {%First, we map {0,1,2,3} to {1,0,4,3}, so that we loop through {M,L,H,Q} + %in order of increasing error-correction capabilities. + \qr@a = \j\relax + \divide \qr@a by 2\relax + \multiply \qr@a by 4\relax + \advance \qr@a by 1\relax + \advance \qr@a by -\j\relax + \edef\qr@level{\the\qr@a}% + \ifnum\qr@desiredlevel=\qr@a\relax + \global\qr@versiongoodenoughtrue + \fi + \ifqr@versiongoodenough + \qr@calculate@capacity{\qr@version}{\qr@level}% + \xa\xa\xa\ifnum\xa\qr@truecapacity\xa<\qr@stringlength\relax + %Too short + \relax + \else + %Long enough! + \xdef\qr@bestversion{\qr@version}% + \xdef\qr@bestlevel{\qr@level}% + \global\i=40% + \fi + \fi + }% + }% + \edef\qr@version{\qr@bestversion}% + \edef\qr@level{\qr@bestlevel}% + \xa\ifnum\qr@desiredversion>0\relax + \ifx\qr@bestversion\qr@desiredversion\relax + %No change from desired version. + \else + %Version was increased + \message{^^J}% + \fi + \fi + \ifx\qr@bestlevel\qr@desiredlevel\relax + %No change in level. + \else + \message{^^J}% + \fi +}% + +\def\qr@calculate@capacity#1#2{% + \edef\qr@version{#1}% + \edef\qr@level{#2}% + %Calculate \qr@size, the number of modules per side. + % The formula is 4\qr@version+17. + \qr@a=\qr@version\relax% + \multiply\qr@a by 4\relax% + \advance\qr@a by 17\relax% + \edef\qr@size{\the\qr@a}% + % + % Calculate \qr@k, which governs the number of alignment patterns. + % The alignment patterns lie in a kxk square, except for 3 that are replaced by finding patterns. + % The formula is 2 + floor( \qr@version / 7 ), except that k=0 for version 1. + \xa\ifnum\qr@version=1\relax% + \def\qr@k{0}% + \else% + \qr@a=\qr@version\relax + \divide \qr@a by 7\relax + \advance\qr@a by 2\relax + \edef\qr@k{\the\qr@a}% + \fi% + % + %Calculate number of function pattern modules. + %This consists of the three 8x8 finder patterns, the two timing strips, and the (k^2-3) 5x5 alignment patterns. + %The formula is 160+2n+25(k^2-3)-10(k-2), unless k=0 in which case we just have 160+2n. + \qr@a=\qr@size\relax + \multiply\qr@a by 2\relax + \advance\qr@a by 160\relax + \xa\ifnum\qr@k=0\relax\else + %\qr@k is nonzero, hence at least 2, so we continue to add 25(k^2-3)-10(k-2). + \qr@b=\qr@k\relax + \multiply\qr@b by \qr@k\relax + \advance\qr@b by -3\relax + \multiply\qr@b by 25\relax + \advance\qr@a by \qr@b\relax + \qr@b=\qr@k\relax + \advance\qr@b by -2\relax + \multiply\qr@b by 10\relax + \advance\qr@a by -\qr@b\relax + \fi + \edef\qr@numfunctionpatternmodules{\the\qr@a}% + % + %Calculate the number of version modules, either 36 or 0. + \xa\ifnum\qr@version>6\relax + \qr@versionmodulestrue + \def\qr@numversionmodules{36}% + \else + \qr@versionmodulesfalse + \def\qr@numversionmodules{0}% + \fi + % + %Now calculate the codeword capacity and remainder bits. + %Take n^2 modules, subtract all those dedicated to finder patterns etc., format information, and version information, + %and what's left is the number of bits we can play with. + %The number of complete bytes is \qr@numdatacodewords; + %the leftover bits are \qr@numremainderbits. + \qr@a=\qr@size\relax + \multiply \qr@a by \qr@size\relax + \advance \qr@a by -\qr@numfunctionpatternmodules\relax + \advance \qr@a by -31\relax% % There are 31 format modules. + \advance \qr@a by -\qr@numversionmodules\relax + \qr@b=\qr@a\relax + \divide \qr@a by 8\relax + \edef\qr@numdatacodewords{\the\qr@a}% + \multiply\qr@a by 8\relax + \advance \qr@b by -\qr@a\relax + \edef\qr@numremainderbits{\the\qr@b}% + % + %The size of the character count indicator also varies by version. + %There are only two options, so hardcoding seems easier than expressing these functionally. + \xa\ifnum\qr@version<10\relax + \def\qr@charactercountbytes@byte{1}% + \def\qr@charactercountbits@byte{8}% + \else + \def\qr@charactercountbytes@byte{2}% + \def\qr@charactercountbits@byte{16}% + \fi + % + %Now we call on the table, from the QR specification, + %of how many blocks to divide the message into, and how many error bytes each block gets. + %This affects the true capacity for data, which we store into \qr@totaldatacodewords. + % The following macro sets \qr@numblocks and \qr@num@eccodewords + % based on Table 9 of the QR specification. + \qr@settableix + \qr@a = -\qr@numblocks\relax + \multiply \qr@a by \qr@num@eccodewords\relax + \advance\qr@a by \qr@numdatacodewords\relax + \edef\qr@totaldatacodewords{\the\qr@a}% + \advance\qr@a by -\qr@charactercountbytes@byte\relax%Subtract character count + \advance\qr@a by -1\relax% Subtract 1 byte for the 4-bit mode indicator and the 4-bit terminator at the end. + \edef\qr@truecapacity{\the\qr@a}% +} + +\def\qr@setversion#1#2{% + % #1 = version number, an integer between 1 and 40 inclusive. + % #2 = error-correction level, as an integer between 0 and 3 inclusive. + % 0 = 00 = M + % 1 = 01 = L + % 2 = 10 = H + % 3 = 11 = Q + % This macro calculates and sets a variety of global macros and/or counters + % storing version information that is used later in construction the QR code. + % Thus \qr@setversion should be called every time! + % + \edef\qr@version{#1}% + \edef\qr@level{#2}% + % + \qr@calculate@capacity{\qr@version}{\qr@level}% + %The capacity-check code sets the following: + % * \qr@size + % * \qr@k + % * \ifqr@versionmodules + % * \qr@numversionmodules + % * \qr@numdatacodewords + % * \qr@numremainderbits + % * \qr@charactercountbits@byte + % * \qr@charactercountbytes@byte + % * \qr@numblocks (via \qr@settableix) + % * \qr@num@eccodewords (via \qr@settableix) + % * \qr@totaldatacodewords + % + % The alignment patterns' square is 7 modules in from each edge. + % They are spaced "as evenly as possible" with an even number of modules between each row/column, + % unevenness in division being accommodated by making the first such gap smaller. + % The formula seems to be + % general distance = 2*round((n-13)/(k-1)/2+0.25) + % = 2*floor((n-13)/(k-1)/2+0.75) + % = 2*floor( (2*(n-13)/(k-1)+3) / 4 ) + % = (((2*(n-13)) div (k-1) + 3 ) div 4 ) * 2 + % first distance = leftovers + % The 0.25 is to accommodate version 32, which is the only time we round down. + % Otherwise a simple 2*ceiling((n-13)/(k-1)/2) would have sufficed. + % + \qr@a = \qr@size\relax + \advance\qr@a by -13\relax + \multiply\qr@a by 2\relax + \qr@b = \qr@k\relax + \advance \qr@b by -1\relax + \divide\qr@a by \qr@b\relax + \advance\qr@a by 3\relax + \divide\qr@a by 4\relax + \multiply\qr@a by 2\relax + \edef\qr@alignment@generalskip{\the\qr@a}% + % + %Now set \qr@alignment@firstskip to (\qr@size-13)-(\qr@k-2)*\qr@alignment@generalskip % + \qr@a = \qr@k\relax + \advance\qr@a by -2\relax + \multiply\qr@a by -\qr@alignment@generalskip\relax + \advance\qr@a by \qr@size\relax + \advance\qr@a by -13\relax + \edef\qr@alignment@firstskip{\the\qr@a}% + % + % + % + % Our \qr@totaldatacodewords bytes of data are broken up as evenly as possible + % into \qr@numblocks datablocks; some may be one byte longer than others. + % We set \qr@shortblock@size to floor(\qr@totaldatacodewords / \qr@numblocks) + % and \qr@numlongblocks to mod(\qr@totaldatacodewords , \qr@numblocks). + \qr@a=\qr@totaldatacodewords\relax + \divide\qr@a by \qr@numblocks\relax + \edef\qr@shortblock@size{\the\qr@a}% + \multiply\qr@a by -\qr@numblocks\relax + \advance\qr@a by \qr@totaldatacodewords\relax + \edef\qr@numlongblocks{\the\qr@a}% + % + %Set \qr@longblock@size to \qr@shortblock@size+1. + \qr@a=\qr@shortblock@size\relax + \advance\qr@a by 1\relax + \edef\qr@longblock@size{\the\qr@a}% + % + %Set \qr@numshortblocks to \qr@numblocks - \qr@numlongblocks + \qr@b=\qr@numblocks\relax + \advance\qr@b by -\qr@numlongblocks\relax + \edef\qr@numshortblocks{\the\qr@b}% +}% + +\def\qr@settableix@int(#1,#2){% + \edef\qr@numblocks{#1}% + \edef\qr@num@eccodewords{#2}% +}% + +\def\qr@settableix{% +\xa\ifcase\qr@level\relax + %00: Level 'M', medium error correction + \edef\qr@tempdata{(% + \ifcase\qr@version\relax + \relax %There is no version 0. + \or1,10% + \or1,16% + \or1,26% + \or2,18% + \or2,24% + \or4,16% + \or4,18% + \or4,22% + \or5,22% + \or5,26% + \or5,30% + \or8,22% + \or9,22% + \or9,24% + \or10,24% + \or10,28% + \or11,28% + \or13,26% + \or14,26% + \or16,26% + \or17,26% + \or17,28% + \or18,28% + \or20,28% + \or21,28% + \or23,28% + \or25,28% + \or26,28% + \or28,28% + \or29,28% + \or31,28% + \or33,28% + \or35,28% + \or37,28% + \or38,28% + \or40,28% + \or43,28% + \or45,28% + \or47,28% + \or49,28% + \fi)}% +\or + %01: Level 'L', low error correction + \edef\qr@tempdata{% + (\ifcase\qr@version\relax + \relax %There is no version 0. + \or 1,7% + \or 1,10% + \or 1,15% + \or 1,20% + \or 1,26% + \or 2,18% + \or 2,20% + \or 2,24% + \or 2,30% + \or 4,18% + \or 4,20% + \or 4,24% + \or 4,26% + \or 4,30% + \or 6,22% + \or 6,24% + \or 6,28% + \or 6,30% + \or 7,28% + \or 8,28% + \or 8,28% + \or 9,28% + \or 9,30% + \or 10,30% + \or 12,26% + \or 12,28% + \or 12,30% + \or 13,30% + \or 14,30% + \or 15,30% + \or 16,30% + \or 17,30% + \or 18,30% + \or 19,30% + \or 19,30% + \or 20,30% + \or 21,30% + \or 22,30% + \or 24,30% + \or 25,30% + \fi)}% +\or + %10: Level 'H', high error correction + \edef\qr@tempdata{(% + \ifcase\qr@version\relax + \relax %There is no version 0. + \or1,17% + \or1,28% + \or2,22% + \or4,16% + \or4,22% + \or4,28% + \or5,26% + \or6,26% + \or8,24% + \or8,28% + \or11,24% + \or11,28% + \or16,22% + \or16,24% + \or18,24% + \or16,30% + \or19,28% + \or21,28% + \or25,26% + \or25,28% + \or25,30% + \or34,24% + \or30,30% + \or32,30% + \or35,30% + \or37,30% + \or40,30% + \or42,30% + \or45,30% + \or48,30% + \or51,30% + \or54,30% + \or57,30% + \or60,30% + \or63,30% + \or66,30% + \or70,30% + \or74,30% + \or77,30% + \or81,30% + \fi)}% +\or + %11: Level 'Q', quality error correction + \edef\qr@tempdata{(% + \ifcase\qr@version\relax + \relax %There is no version 0. + \or1,13% + \or1,22% + \or2,18% + \or2,26% + \or4,18% + \or4,24% + \or6,18% + \or6,22% + \or8,20% + \or8,24% + \or8,28% + \or10,26% + \or12,24% + \or16,20% + \or12,30% + \or17,24% + \or16,28% + \or18,28% + \or21,26% + \or20,30% + \or23,28% + \or23,30% + \or25,30% + \or27,30% + \or29,30% + \or34,28% + \or34,30% + \or35,30% + \or38,30% + \or40,30% + \or43,30% + \or45,30% + \or48,30% + \or51,30% + \or53,30% + \or56,30% + \or59,30% + \or62,30% + \or65,30% + \or68,30% + \fi)}% +\fi +\xa\qr@settableix@int\qr@tempdata +}% +\define@key{qr}{version}{\edef\qr@desiredversion{#1}}% +\define@key{qr}{level}{\qr@setlevel{#1}}% +\define@key{qr}{height}{\qr@setheight{#1}}% +\define@boolkey{qr}[qr@]{tight}[true]{}% %This creates \ifqr@tight and initializes it to true. +\define@boolkey{qr}[qr@]{padding}[true]{\ifqr@padding\qr@tightfalse\else\qr@tighttrue\fi}% %Define 'padding' as antonym to 'tight' + +\def\@qr@M{M}\def\@qr@z{0}% +\def\@qr@L{L}\def\@qr@i{1}% +\def\@qr@H{H}\def\@qr@ii{2}% +\def\@qr@Q{Q}\def\@qr@iii{3}% +\def\qr@setlevel#1{% + \edef\qr@level@selected{#1}% + \ifx\qr@level@selected\@qr@M + \edef\qr@desiredlevel{0}% + \fi + \ifx\qr@level@selected\@qr@L + \edef\qr@desiredlevel{1}% + \fi + \ifx\qr@level@selected\@qr@H + \edef\qr@desiredlevel{2}% + \fi + \ifx\qr@level@selected\@qr@Q + \edef\qr@desiredlevel{3}% + \fi + \ifx\qr@level@selected\@qr@z + \edef\qr@desiredlevel{0}% + \fi + \ifx\qr@level@selected\@qr@i + \edef\qr@desiredlevel{1}% + \fi + \ifx\qr@level@selected\@qr@ii + \edef\qr@desiredlevel{2}% + \fi + \ifx\qr@level@selected\@qr@iii + \edef\qr@desiredlevel{3}% + \fi +}% + +\def\qr@setheight#1{% + \setlength{\qr@desiredheight}{#1}% +}% + +\newcommand\qrset[1]{% + \setkeys{qr}{#1}% +} + +\qrset{version=0, level=0, tight} +\newif\ifqr@starinvoked% +\def\qrcode{\@ifstar\qrcode@star\qrcode@nostar}% +\def\qrcode@star{\qr@starinvokedtrue\qrcode@i}% +\def\qrcode@nostar{\qr@starinvokedfalse\qrcode@i}% + +\newcommand\qrcode@i[1][]{% + \begingroup% + \ifqr@starinvoked% + \qr@hyperlinkfalse% + \fi% + \setkeys{qr}{#1}% + \bgroup\qr@verbatimcatcodes\qr@setescapedspecials\qrcode@in}% + +\def\qrcode@in#1{\xdef\qr@texttoencode{#1}\egroup\qrcode@int\endgroup}% + +\def\qrcode@hyperwrapper@hyperref{\href{\qr@texttoencode}}% +\def\qrcode@hyperwrapper@nohyperref{\relax}% + +\AtBeginDocument{% + \@ifpackageloaded{hyperref}% + {\global\let\qrcode@hyperwrapper=\qrcode@hyperwrapper@hyperref}% + {\global\let\qrcode@hyperwrapper=\qrcode@hyperwrapper@nohyperref}% +}% + +\def\qrcode@int{% + \message{^^J^^J^^J}% + %First, choose the version and level. + %Recall that \qr@choose@best@version sets \qr@version and \qr@level. + \xa\qr@choose@best@version\xa{\qr@texttoencode}% + \qr@setversion{\qr@version}{\qr@level}% + % + \ifqr@hyperlink% + \let\qrcode@wrapper=\qrcode@hyperwrapper% + \else% + \let\qrcode@wrapper=\relax% + \fi% + % + %Next, check whether we have already encoded this text at this version + %and level. + \qrcode@wrapper{% + \xa\ifx\csname qr@savedbinarymatrix@\qr@texttoencode @\qr@version @\qr@level\endcsname + \relax% + %This text has not yet been encoded. + \qrcode@int@new% + \else + %This text has already been encoded! + \ifqr@forget@mode + %In 'forget' mode, we deliberately recalculate anyway. + \qrcode@int@new% + \else + \qrcode@int@remember% + \fi + \fi% + }% +}% + +\def\qrcode@int@new{% + \qr@createsquareblankmatrix{newqr}{\qr@size}% + \qr@placefinderpatterns{newqr}% + \qr@placetimingpatterns{newqr}% + \qr@placealignmentpatterns{newqr}% + \qr@placedummyformatpatterns{newqr}% + \qr@placedummyversionpatterns{newqr}% + \ifqr@draft@mode + \message{^^J}% + \relax% Draft mode---don't load any data or do any work. Also don't save! + \def\qr@format@square{\qr@black}% + \def\qr@blank{\qr@white}% + \fboxsep=-\fboxrule% + \fbox{\qr@printmatrix{newqr}}% + \else + \message{^^J}% + \xa\qr@encode@binary\xa{\qr@texttoencode}% + \qr@splitcodetextintoblocks + \qr@createerrorblocks + \qr@interleave + \message{^^J}% + \qr@writeremainderbits{newqr}% + \qr@chooseandapplybestmask{newqr}% + \qr@decimaltobinary[2]{\qr@level@binary}{\qr@level}% + \qr@decimaltobinary[3]{\qr@mask@binary}{\qr@mask@selected}% + \edef\qr@formatstring{\qr@level@binary\qr@mask@binary}% + \message{^^J}% + \message{^^J}% + \message{^^J}% + % + %Also save the binary version into the aux file, for use in later runs. + \message{^^J}% + \message{^^J}% + \fi + \message{^^J}% +}% +\def\qrcode@int@remember{% + %This text has already been encoded, + %so we just copy it from the saved binary string. + \message{^^J}% + \xa\qr@printsavedbinarymatrix\xa{\csname qr@savedbinarymatrix@\qr@texttoencode @\qr@version @\qr@level\endcsname}% + % + % Now this still might need to be written to the aux file. + % + \xa\ifx\csname qr@savedflag@\qr@texttoencode @\qr@version @\qr@level\endcsname\@qr@TRUE + %Okay, this has already been written to aux file. + %Do nothing. + \relax% + \else% + %This has NOT been written to the aux file yet. + %We need to do so now. + \xa\qr@writebinarymatrixtoauxfile\xa{\csname qr@savedbinarymatrix@\qr@texttoencode @\qr@version @\qr@level\endcsname}% + \fi% +}% + +\def\qr@matrixtobinary#1{% + \def\qr@binarymatrix@result{}% + \bgroup + \def\qr@black{1}% + \def\qr@white{0}% + \def\qr@blank{0}% + \def\qr@black@fixed{1}% + \def\qr@white@fixed{0}% + \def\qr@black@format{1}% + \def\qr@white@format{0}% + % + \qr@for \i = 1 to \qr@size by 1% + {\qr@for \j = 1 to \qr@size by 1% + {\edef\qr@theentry{\qr@matrixentry{#1}{\the\i}{\the\j}}% + \xa\g@addto@macro\xa\qr@binarymatrix@result\xa{\qr@theentry}% + }% + }% + \egroup% +}% + +\def\qr@sanitize@output#1{% + %Read through ASCII text '#1' and escape backslashes and braces + \def\qr@sanitized@result{}% + \edef\qr@argument{(#1\relax\relax\relax)}% + \xa\qr@sanitize@output@int\qr@argument% +} + +\def\qr@sanitize@output@int(#1#2){% + % #1 = first character + % #2 = rest of output, including terminator + \edef\qr@testi{#1}% + \ifx\qr@testi\qr@relax + % Done. + \let\qr@next=\relax + \else + \ifx\qr@testi\qr@otherrightbrace + \edef\qr@sanitized@result{\qr@sanitized@result\qr@otherbackslash}% + \else\ifx\qr@testi\qr@otherleftbrace + \edef\qr@sanitized@result{\qr@sanitized@result\qr@otherbackslash}% + \else\ifx\qr@testi\qr@otherbackslash + \edef\qr@sanitized@result{\qr@sanitized@result\qr@otherbackslash}% + \fi + \fi + \fi + \edef\qr@sanitized@result{\qr@sanitized@result#1}% + \def\qr@next{\qr@sanitize@output@int(#2)}% + \fi + \qr@next +} + +\def\@qr@TRUE{TRUE}% +\def\qr@writebinarymatrixtoauxfile#1{% + \qr@sanitize@output{\qr@texttoencode}% + \edef\qr@theargument{{\qr@sanitized@result}{\qr@version}{\qr@level}{#1}}% + \xa\write\xa\@auxout\xa{\xa\string\xa\qr@savematrix\qr@theargument}% + % + % Now set a flag, so we don't write this again. + \xa\gdef\csname qr@savedflag@\qr@texttoencode @\qr@version @\qr@level\endcsname{TRUE}% +}% + +\gdef\qr@dummyqrsavedefinition{}% +\begingroup + \catcode`\#=12\relax + \catcode`\<=1\relax + \catcode`\{=12\relax + \catcode`\>=2\relax + \catcode`\}=12\relax + \catcode`\|=0\relax + \catcode`\\=12|relax + |gdef|qr@dummyqrsavedefinition<% + \ifx\qr@savematrix\@undefined% + \def\qr@savematrix{\begingroup\let\do\@makeother\dospecials\catcode`\{=1\catcode`\}=2\relax + \qr@savematrix@int}% + \def\qr@savematrix@int#1#2#3#4{\endgroup}% + \fi% + > +|endgroup + +\edef\qr@argument{(\qr@dummyqrsavedefinition)}% +\xa\write\xa\@auxout\xa{\qr@dummyqrsavedefinition}% + +\def\qr@savematrix{\bgroup\qr@verbatimcatcodes\qr@setescapedspecials\qr@savematrix@int}% + +\def\qr@savematrix@int#1{\xdef\qr@savedmatrix@name{#1}\egroup\qr@savematrix@int@int}% + +\def\qr@savematrix@int@int#1#2#3{% + % \qr@savedmatrix@name = encoded text + % #1 = version + % #2 = level + % #3 = binary text + \def\ds{^^J}\xa\message\xa{\ds}% + {\let\%=\qr@otherpercent + \xa\gdef\csname qr@savedbinarymatrix@\qr@savedmatrix@name @#1@#2\endcsname{#3}% + }% +}% +\endinput +%% +%% End of file `qrcode.sty'. diff --git a/tools/style/shortcuts.sty b/tools/style/shortcuts.sty new file mode 100755 index 0000000..cf883fd --- /dev/null +++ b/tools/style/shortcuts.sty @@ -0,0 +1,318 @@ +\NeedsTeXFormat{LaTeX2e} + +%%%%%%%%%%%%%%%%% +% Raccourcis % +%%%%%%%%%%%%%%%%% + +% Displaystyle +\newcommand{\ds}{\displaystyle} + +% Ensembles +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +%\newcommand{\D}{\mathbb{D}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\R}{\mathbb{R}} +\newcommand{\C}{\mathbb{C}} + + + +% intervalles ouvert ouvert +\newcommand{\intOO}[2]{\left]{#1}\,{;}\,{#2}\right[} +% intervalles ouvert fermé +\newcommand{\intOF}[2]{\left]{#1}\,{;}\,{#2}\right]} +% intervalles fermé ouvert +\newcommand{\intFO}[2]{\left[{#1}\,{;}\,{#2}\right[} +% intervalles fermé fermé +\newcommand{\intFF}[2]{\left[{#1}\,{;}\,{#2}\right]} + + +%% Vecteurs +% représentation d'un vecteur +\newcommand{\vect}[1]{\overrightarrow{#1}} +% Norme d'un vecteur +\newcommand{\norme}[1]{||\vect{#1}||} +% Produit scalaire +\newcommand{\scal}[2]{\vect{#1} \cdot \vect{#2}} +\newcommand{\vectCoord}[2]{% + {\renewcommand{\arraystretch}{1}% + \left(\begin{array}{c} #1 \\ #2 \end{array} \right)% + }% +} + +% Les complexes +\def\Ouv{$\left(\text{O}~;~\vect{u},~\vect{v}\right)$} +\newcommand{\e}{\mathrm{\,e\,}}% le e de l'exponentielle +%\renewcommand{\i}{\mathrm{\,i\,}}% le i des complexes + +%% Proba +\newcommand{\coefBino}[2]{\vectCoord{#1}{#2}} + +%% Logique +\renewcommand{\equiv}{\Leftrightarrow} + +%% Calculatrice +\usepackage{listings} +\newcommand{\calc}[1]{\Ovalbox{\lstinline|#1|}} +%\newcommand{\calc}[1]{\verb!#1!} + +%% Autres +\newcommand{\TODO}[1]{\textcolor{red}{note(#1)}} + +% Difficulté + +\usepackage{fontawesome5} +\newcommand{\dure}{(\faBolt) } +\newcommand{\superDure}{(\faBioHazard) } + +% Icones +\newcommand{\icon}[2][scale=0.4]{% +\includegraphics[#1]{icons/#2.png}% +} + +% Icones des compétences +\newcommand{\iconScale}{0.3} +\newcommand{\Cher}[1][scale=\iconScale]{% + \icon[#1]{card-pick} +} +\newcommand{\Mod}[1][scale=\iconScale]{% + \icon[#1]{processor} +} +\newcommand{\Rep}[1][scale=\iconScale]{% + \icon[#1]{chart} +} +\newcommand{\Rai}[1][scale=\iconScale]{% + \icon[#1]{brain} + %\icon[#1]{gears} +} +\newcommand{\Cal}[1][scale=\iconScale]{% + \icon[#1]{computing} +} +\newcommand{\Com}[1][scale=\iconScale]{% + \icon[#1]{conversation} +} +\newcommand{\Con}[1][scale=\iconScale]{% + \icon[#1]{book-cover} +} + +% Pour l'évaluation par compétence +\usepackage{tikzsymbols} +\usetikzlibrary{babel, shapes, snakes} + +\RequirePackage{xstring} +\newcommand{\RepLevel}[1]{% + \IfEqCase{#1}{% + {.}{\Xey[2]}% + {0}{\Changey[2]{-1}}% + {1}{\Changey[2][black!20]{0}}% + {2}{\Changey[2][black!40]{1}}% + {3}{\Cooley[2][black!60]}% + }[\PackageError{Rep}{Undefinded type of answer: #1}{}]% +} +\newcommand{\RepT}{\Cooley[2][black!70]} +\newcommand{\RepD}{\Changey[2][black!40]{1}} +\newcommand{\RepU}{\Changey[2][black!10]{0}} +\newcommand{\RepZ}{\Changey[2]{-1}} +\newcommand{\NoRep}{\Xey[2]} + +\newcommand{\EmptySignalBar}{% + \draw (0, 0) rectangle ++(0.8, 1); + \draw (1, 0) rectangle ++(0.8, 2); + \draw (2, 0) rectangle ++(0.8, 3); + \draw (3, 0) rectangle ++(0.8, 4); +} +\newcommand{\filledSignalBar}[1]{% + \IfEqCase{#1}{% + {}{% + } + {e}{% + \EmptySignalBar + } + {3}{% + \EmptySignalBar + \filldraw[fill=green] (0, 0) rectangle ++(0.8, 1); + \filldraw[fill=green] (1, 0) rectangle ++(0.8, 2); + \filldraw[fill=green] (2, 0) rectangle ++(0.8, 3); + \filldraw[fill=green] (3, 0) rectangle ++(0.8, 4); + } + {2}{% + \EmptySignalBar + \filldraw[fill=green] (0, 0) rectangle ++(0.8, 1); + \filldraw[fill=green] (1, 0) rectangle ++(0.8, 2); + \filldraw[fill=green] (2, 0) rectangle ++(0.8, 3); + } + {1}{% + \EmptySignalBar + \filldraw[fill=yellow] (0, 0) rectangle ++(0.8, 1); + \filldraw[fill=yellow] (1, 0) rectangle ++(0.8, 2); + } + {0}{% + \EmptySignalBar + \filldraw[fill=red] (0, 0) rectangle ++(0.8, 1); + } + }[\PackageError{Assesment}{Undefinded type of answer: #1}{}]% +} + +\newcommand{\SignalBar}[1]{% + \begin{tikzpicture}[scale=0.15] + \filledSignalBar{#1} + \end{tikzpicture} +} + +\newcommand{\Assesment}[1]{% + \SignalBar{#1} + \IfEqCase{#1}{% + {3}{% + Très bonne maîtrise% + }% + {2}{% + Maîtrise satisfaisante + }% + {1}{% + Maîtrise fragile% + }% + {0}{% + Maîtrise insufisante% + }% + }[\PackageError{Assesment}{Undefinded type of answer: #1}{}]% +} + +\newcommand{\competencesStatement}{% + \begin{multicols}{3} + \noindent + Nom: \dotfill \\[0.5cm] + Prénom: \dotfill \\ + \vfill\none + \columnbreak + \noindent + \Cher Chercher \hfill \SignalBar{e}\\ + \Mod Modélser \hfill \SignalBar{e}\\ + \Rep Représenter \hfill \SignalBar{e}\\ + \vfill\none + \columnbreak + \noindent + \Rai Raisonner \hfill \SignalBar{e}\\ + \Cal Calculer \hfill \SignalBar{e}\\ + \Com Communiquer \hfill \SignalBar{e}\\ + \end{multicols} +} + + +% ########################## +% Tikz shortcuts +% ########################## + +% Les dessins +\RequirePackage{tikz} + +%% le cercle trigo +\newcommand{\cercleTrigo}% +{% + \draw[->, very thick] (-1.1,0) -- (1.1, 0); + \draw[->, very thick] (0,-1.1) -- (0,1.1); + \draw[very thick] (0,0) circle (1); + \draw (0,0) node[below left] {$O$}; + \draw (1,0) node[below right] {$I$}; + \draw (0,1) node[above left] {$J$}; +} + +\newcommand{\cercleTrigoNoOIJ}% +{% + \draw[->, very thick] (-1.1,0) -- (1.1, 0); + \draw[->, very thick] (0,-1.1) -- (0,1.1); + \draw[very thick] (0,0) circle (1); +} + +%% Le repère orthonormé avec la grille +%%% \repere{xmin}{xmax}{ymin}{ymax} +\newcommand{\repere}[4]% +{% + \draw[very thin, gray] (#1,#3) grid (#2,#4); + \draw[->, very thick] (#1,0) -- (#2,0); + \draw[->, very thick] (0,#3) -- (0,#4); + \draw (0,0) node[below left] {$O$}; + \draw (1, 0) node [below left] {1}; + \draw (0, 1) node [below left] {1}; + } +\newcommand{\repereOIJ}[4]% +{% + \draw[very thin, gray] (#1,#3) grid (#2,#4); + \draw[->, very thick] (#1,0) -- (#2,0); + \draw[->, very thick] (0,#3) -- (0,#4); + \draw (0,0) node[below left] {$O$}; + \draw[->, very thick] (0, 0) -- node [below, midway] {$\vect{i}$} (1, 0); + \draw[->, very thick] (0, 0) -- node [left, midway] {$\vect{j}$} (0, 1); + } +\newcommand{\repereNoGrid}[4]% +{% + \draw[->, very thick] (#1,0) -- (#2,0); + \draw[->, very thick] (0,#3) -- (0,#4); + } + +%% Diagramme boite +%%% \boxplot{Vertical Center}{min}{Q1}{Me}{Q3}{Max} +\newcommand{\boxplot}[6]% +{% + \filldraw[color=highlightbg, draw=text] (#3, {#1 - 0.5}) rectangle (#5, {#1 + 0.5}); + \draw (#2, {#1 - 0.5}) -- (#2, {#1 + 0.5}) node[above] {$Min$}; + \draw (#3, {#1 - 0.5}) -- (#3, {#1 + 0.5}) node[above] {$Q_1$}; + \draw (#4, {#1 - 0.5}) -- (#4, {#1 + 0.5}) node[above] {$Me$}; + \draw (#5, {#1 - 0.5}) -- (#5, {#1 + 0.5}) node[above] {$Q_3$}; + \draw (#6, {#1 - 0.5}) -- (#6, {#1 + 0.5}) node[above] {$Max$}; + + \draw (#2, #1) -- (#3, #1); + \draw (#5, #1) -- (#6, #1); + + %\draw ({(#2 +#3)/2}, #1) node[above] {25\%}; + %\draw ({(#3 +#4)/2}, #1) node[above] {25\%}; + %\draw ({(#4 +#5)/2}, #1) node[above] {25\%}; + %\draw ({(#5 +#6)/2}, #1) node[above] {25\%}; + +} +\newcommand{\boxplotNoNames}[6]% +{% + \filldraw[color=highlightbg, draw=text] (#3, {#1 - 0.5}) rectangle (#5, {#1 + 0.5}); + \draw (#2, {#1 - 0.5}) -- (#2, {#1 + 0.5}); + \draw (#3, {#1 - 0.5}) -- (#3, {#1 + 0.5}); + \draw (#4, {#1 - 0.5}) -- (#4, {#1 + 0.5}); + \draw (#5, {#1 - 0.5}) -- (#5, {#1 + 0.5}); + \draw (#6, {#1 - 0.5}) -- (#6, {#1 + 0.5}); + + \draw (#2, #1) -- (#3, #1); + \draw (#5, #1) -- (#6, #1); +} + +\usetikzlibrary{quotes,arrows.meta} + +\tikzset{ + % drawing parallelepipoid + annotated cuboid/.pic={ + \tikzset{% + every edge quotes/.append style={midway, auto}, + /cuboid/.cd, + #1 + } + \draw [every edge/.append style={pic actions, densely dashed, opacity=.5}, pic actions] + (0,0,0) coordinate (o) -- ++(-\cubescale*\cubex,0,0) coordinate (a) -- ++(0,-\cubescale*\cubey,0) coordinate (b) edge coordinate [pos=1] (g) ++(0,0,-\cubescale*\cubez) -- ++(\cubescale*\cubex,0,0) coordinate (c) -- cycle + (o) -- ++(0,0,-\cubescale*\cubez) coordinate (d) -- ++(0,-\cubescale*\cubey,0) coordinate (e) edge (g) -- (c) -- cycle + (o) -- (a) -- ++(0,0,-\cubescale*\cubez) coordinate (f) edge (g) -- (d) -- cycle; + \path [every edge/.append style={pic actions, |-|}] + (b) +(0,-5pt) coordinate (b1) edge ["\cubex \cubeunits"'] (b1 -| c) + (b) +(-5pt,0) coordinate (b2) edge ["\cubey \cubeunits"] (b2 |- a) + (c) +(3.5pt,-3.5pt) coordinate (c2) edge ["\cubez \cubeunits"'] ([xshift=3.5pt,yshift=-3.5pt]e) + ; + }, + /cuboid/.search also={/tikz}, + /cuboid/.cd, + width/.store in=\cubex, + height/.store in=\cubey, + depth/.store in=\cubez, + units/.store in=\cubeunits, + scale/.store in=\cubescale, + width=10, + height=10, + depth=10, + units=cm, + scale=.1, +} +