% The bar codes used by supermarkets
\message{<Product Barcodes by Paul Taylor and Shane Voss, 4 June 1994>}
% Paul Taylor <pt@doc.ic.ac.uk> Dept of Computing, Imperial College, London
% with the help of Shane Voss <shane@glg.ed.ac.uk> Geology, U of Edinburgh
% Authoritative version: ftp theory.doc.ic.ac.uk /tex/contrib/Taylor/tex/

% We cracked this code by examining a dozen or so household items.
% The following description does not purport to conform to any patent
% or official standard for bar codes.
% In fact we do not know what the standard is.

% COPYRIGHT Paul Taylor & Shane Voss 1994
% You may copy this file as you please,
% on condition that you do not alter it or charge a fee for it.

% NO WARRANTY
% This description and software is supplied "as is" without any warranty,
% express or implied, including but not limited to merchantability or
% fitness for any purpose.  In particular no claim is made that any
% output it produces will be readable by bar code reading equipment
% or conforms to any standard.  No liability will be accepted by the
% authors, their employers or any third party through which you have
% obtained this file for damages, however caused. You must keep several
% backup copies of your files in a place which cannot be overwritten
% by this software and check all output before sending it to a publisher
% or expensive printer.

% LICENSE
% This software may NOT be used for any commercial or military purpose.
% In particular you may not use it to sell or buy, or to attempt to
% sell or buy any item. (These conditions are intended to prevent you
% from making a profit from it or using it for fraud.) It MAY be used
% for academic or personal purposes, subject to the exclusions above.

% HOW TO USE THE MACROS

% set the size of the barcode block, anticipating a 300dpi printer
\def\BarcodeHeight{12mm}
\def\BarcodeWidth {24mm}  
\newdimen\PixelSize\PixelSize=1in \divide\PixelSize by 300
% (The width will be rounded to ensure that the unit stripe width is
% a whole number of pixels - otherwise it cannot be read accurately.
% The width of the 12digit code will be a multiple of approx 8mm.)

\def\BarcodeDigitFont{\rm} % font command for printing the digits

% Print the eight, twelve and thirteen digit versions of the code:
% \ProductBarcodeVIII  12345678
% \ProductBarcodeXII   123456789012
% \ProductBarcodeXIII 0123456789012
% If you use non-digits or give the wrong number of them,
% the macros will get in a mess - the input is not checked.

% HOW THE BARCODE WORKS

% First, you must forget that the stripes are black and white: what is
% significant is their *width*, which may be 1, 2, 3 or 4 units.
% In particular each digit consists of four stripes of total width 7,
% white-black-white-black on the left and the opposite on the right.

% As a whole, the bar code consists of a start pattern 111 (ie black,
% white and black stripes of unit width), four or six digits, the middle
% pattern 11111, another four or six digits and an end pattern 111.
% The total width is 3+(4x7)+5+(4x7)+3=67 or 3+(6x7)+5+(6x7)+3=95 units.

% The digits are coded as four stripes of the following widths:
%   0=3211  1=2221  2=2122  3=1411  4=1132
%   5=1231  6=1114  7=1312  8=1213  9=3112
% notice that the first and third stripes total an even width,
% the second and fourth odd.  This means that we can recognise
% these patterns in their reverse form, and also that they are reversed.
% This is significant, because the bar code may be presented upside down
% to the reader, which may then recognise the fact and correct for it.

% The more modern 6+6 digit version of the code may be used to encode
% a further digit.  The patterns of stripes may be reversed for some of
% the digits on the left, but not the right. Writing 0 for the standard
% and 1 for the reversed form, the extra digit is encoded as follows:
%   0=000111  1=001011  2=001101  3=001110  4=010011
%   5=011001  6=011100  7=010101  8=010110  9=011010
% (We guessed the coding of 0, 1, 2 and 6 without seeing any items
% which carry these digits.  The most common seem to be 9 for books and
% magazines, and 5 for food and household items; maybe 0126 are unused.)
% The extra digit is printed to the left of the body of the barcode.

% EXAMPLE  ISBN 0-521-24665-2
% The last digit is a checksum, which is computed differently for barcodes.
% The ISBN is prefixed with 978 to turn it into a general product barcode.

% 111 1312 3121 1123 1231 2212 2221 11111 2122 1132 1114 1114 1231 2221 111
%     7    8    0    5    2    1          2    4    6    6    5    1
% 9 = 0    1    1    0    1    0

% This expands to * * *** **   *  * *  *** **   *  ** **  **  * * * etc.
% try doing \ProductBarcodeXIII 9780521246651

\makeatletter

%  \barp@lf@ 4  produces the left forward code for the digit 4 etc

\def\barp@lf#1#2#3#4#5{% left forward
  \barp@white#1\barp@black#2\barp@white#3\barp@black#4\barp@digit#5}%
\def\barp@lr#1#2#3#4#5{% left reverse
  \barp@white#4\barp@black#3\barp@white#2\barp@black#1\barp@digit#5}%
\def\barp@rf#1#2#3#4#5{% right forward
  \barp@black#1\barp@white#2\barp@black#3\barp@white#4\barp@digit#5}%
\def\barp@rr#1#2#3#4#5{% right reverse (not used)
  \barp@black#4\barp@white#3\barp@black#2\barp@white#1\barp@digit#5}%
\def\barp@lf@#1{\expandafter\expandafter\expandafter\barp@lf
  \csname barp@#1\endcsname}
\def\barp@lr@#1{\expandafter\expandafter\expandafter\barp@lr
  \csname barp@#1\endcsname}
\def\barp@rf@#1{\expandafter\expandafter\expandafter\barp@rf
  \csname barp@#1\endcsname}
\def\barp@rr@#1{\expandafter\expandafter\expandafter\barp@rr
  \csname barp@#1\endcsname}
\def\barp@timing#1#2#3#4#5{{\divide\dimen0 2
  \barp@white#1\barp@black#2\barp@white#3\barp@black#4\barp@white#5}}

% the bar encoding of the digits  \barp@4

\def\next#1=#2#3#4#5{\expandafter\def\csname barp@#1\endcsname{#2#3#4#5#1}}
\next 0=3211
\next 1=2221
\next 2=2122
\next 3=1411
\next 4=1132
\next 5=1231
\next 6=1114
\next 7=1312
\next 8=1213
\next 9=3112

% the reversal encoding of the digits \barp@l4

\def\do#1#2#3{\expandafter\aftergroup\csname barp@#2#3@\endcsname
   \aftergroup##\aftergroup#1}%

\def\next#1#2=#3#4#5#6#7#8{%
\begingroup
  \aftergroup\def\expandafter\aftergroup\csname barp@#1#2\endcsname
  \aftergroup##\aftergroup1\aftergroup##\aftergroup2%
  \aftergroup##\aftergroup3\aftergroup##\aftergroup4%
  \if.#7\else\aftergroup##\aftergroup5\aftergroup##\aftergroup6\fi
  \aftergroup{%
      \do1#1#3\do2#1#4\do3#1#5\do4#1#6
      \if.#7\else\do5#1#7\do6#1#8\fi
  \aftergroup}%
\endgroup}%

\next l0=fffrrr
\next l1=ffrfrr
\next l2=ffrrfr
\next l3=ffrrrf
\next l4=frffrr
\next l5=frrffr
\next l6=frrrff
\next l7=frfrfr
\next l8=frfrrf
\next l9=frrfrf

% also do left and right six-digit parts with no extra digit

\next l=ffffff  %\barp@l
\next r=ffffff  %\barp@r

% similarly four-digit versions

\next ls=ffff..
\next rs=ffff..

\let\next\undefined \let\do\undefined % we don't need them any more

% the beginning, middle and end of the code
% also sets up the dimensions

\def\barp@begin#1#2{\hbox\bgroup
    % calculate unit width as (\BarcodeWidth)/(#1) rounded to \PixelSize
    \dimen1=\BarcodeWidth\relax
    \divide\dimen1 #1\relax
    \advance\dimen1 .5\PixelSize
    \divide\dimen1 \PixelSize
    \multiply\dimen1 \PixelSize
    % calculate allowance for digit height
    \setbox0\hbox{\BarcodeDigitFont 0}\dimen0 1.2\ht0
    % print the extra digit if any, overlapping left
    \barp@digit{#2}%
    % and the start code
    \barp@timing01110%
  }%
\def\barp@middle{\barp@timing11111}%
\def\barp@end{\barp@timing01110\egroup}

% the user commands:
%  \ProductBarcodeVIII \ProductBarcodeXII \ProductBarcodeXIII
% for the eight, twelve and thirteen digit codes.

\def\ProductBarcodeVIII#1#2#3#4#5#6#7#8{%
\barp@begin{67}{}\barp@ls#1#2#3#4\barp@middle\barp@rs#5#6#7#8\barp@end}%

\def\ProductBarcodeXII{\barp@xii\barp@l{}}

\def\ProductBarcodeXIII#1{\expandafter\barp@xii\csname barp@l#1\endcsname{#1}}%

\def\barp@xii#1#2#3#4#5#6#7#8{\barp@begin{95}{#2}#1#3#4#5#6#7#8\barp@vi}%

\def\barp@vi#1#2#3#4#5#6{\barp@middle\barp@r#1#2#3#4#5#6\barp@end}%

% how to print black and white stripes

\def\barp@black#1{\vrule depth-\dimen0 width#1\dimen1
                         height\BarcodeHeight\relax}%
\def\barp@white#1{\kern#1\dimen1\relax}%
\def\barp@digit#1{\hbox to\z@{\kern-7\dimen1\hss\BarcodeDigitFont#1\hss}}%

% for debugging, print the widths as digit, not stripes
% \def\barp@black#1{{\bf #1}}\def\barp@white#1{{\it #1}}\def\barp@digit#1{}
% also useful for debugging:
% \def\showname#1{\expandafter\show\csname #1\endcsname}
% \tracingcommands1 \tracingmacros1 \tracingonline1

\makeatother
