%% Copyright (C) 2007 by Michael Ritzert <michael.ritz...@gmail.com>
%% Spurious spaces removed by John Bowman [2009/06/01].

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{ocg}[2009/06/01]

\RequirePackage{ifpdf}
\ifpdf
\else
   \PackageWarningNoLine{ocg}{%
      Loading aborted, because pdfTeX is not running in PDF mode%
   }%
   \expandafter\endinput
\fi

\DeclareOption*{}\ProcessOptions*\relax %allow anything as option for the moment

%testing for correct pdfTeX version
%TODO: find out minimum required version!
\ifnum\pdftexversion<120
   \PackageError{ocg}{%
      pdfeTeX, version >= 1.20, required%
   }{%
      Install a newer version!%
   }%
\fi

% Next OCG id -- TODO: autogenerate. but keep possibility to reopen an OCG.
\newcount\@ocg@num\@ocg@num=0

\gdef\@ocg@layersnames{}

% called from the aux file
\def\@ocg@makeknown#1#2#3{% #1: OCG name, #2: OC id, #3: on/off
   \@ifundefined{OCG#2}{%
      \message{OCG#2}
      \expandafter\gdef\csname OCG#2\endcsname{#1}%
      \immediate\pdfobj{<< /Type /OCG /Name (#1) >>}% new ocg
      \xdef\@ocg@curocg{\the\pdflastobj\space 0 R}% reference to id
      \xdef\@ocg@ocgs{\@ocg@ocgs\space\@ocg@curocg}% list of all OCGs in "first defined" order
      \ifnum#3=1 %on
         \xdef\@ocg@ocgson{\@ocg@ocgson\space\@ocg@curocg}% list of all default-on OCGs
      \else%
         \xdef\@ocg@ocgsoff{\@ocg@ocgsoff\space\@ocg@curocg}% list of all default-off OCGs
      \fi%
      \xdef\@ocg@layersnames{%
         \@ocg@layersnames\space/OC#2\space\@ocg@curocg% name-to-id mapping
      }%
   }{%
      \message{OCG#2 reopened}
      % layer reopened
   }
}

\AtBeginDocument{%
   % the auxfile has been read if available. register the OCGs in the page resources.
   \@ocg@addresource
   \let\@ocg@makeknown\@gobble
}

% set page resources to include the layers defined in the aux file
\def\@ocg@addresource{%
   \immediate\pdfobj{<<\@ocg@layersnames\space>>}%
   \xdef\@ocg@namesobj{\the\pdflastobj\space 0 R}%
   % append to pageresources
   \begingroup
   \edef\x{\endgroup
      \pdfpageresources{%
         \the\pdfpageresources
         /Properties \@ocg@namesobj%
      }%
   }%
   \x
}

\newcount\@ocg@@ocgs
\pdfobj reserveobjnum
\@ocg@@ocgs=\pdflastobj

\newcount\@ocg@@layersconfig
\pdfobj reserveobjnum
\@ocg@@layersconfig=\pdflastobj

\pdfcatalog{%
   /OCProperties <<
      /OCGs \the\@ocg@@ocgs\space0 R\space
      /D \the\@ocg@@layersconfig\space0 R\space
   >>%
}
\def\@ocg@ocgs{}
\def\@ocg@ocgson{}
\def\@ocg@ocgsoff{}
\AtEndDocument{%
   \immediate\pdfobj useobjnum \@ocg@@ocgs {%
      [\@ocg@ocgs\space]%
   }%
   \immediate\pdfobj useobjnum \@ocg@@layersconfig {%
      <<
         /Order [\@ocg@ocgs\space]
         /ON    [\@ocg@ocgson\space]
         /OFF   [\@ocg@ocgsoff\space]
      >>%
   }%
}%

% schedule a OCG for creation on the next pdflatex run (via the auxfile)
\def\@ocg@newocg#1#2#3{% #1:name, #2:num, #3:on
    \if@filesw%
      \immediate\write\@auxout{%
        \string\@ocg@makeknown{#1}{#2}{#3}%
      }%
    \fi%
}

% TODO: Are nested OCGs allowed?
\newenvironment{ocg}[3]{%
   \@ocg@newocg{#1}{#2}{#3}%
   \gdef\@ocg@curnum{#2}%
   \pdfliteral{/OC /OC\@ocg@curnum\space BDC}%
   \message{/OC\@ocg@curnum}%
   \ignorespaces
}{%
   \pdfliteral{EMC}%
   %\unskip%
   %\endgroup%
   \ignorespacesafterend
}
