I wrote a small package to use PDF OCGs (optional content groups, aka
layers) from LaTeX.
Below you can see where I'm standing. I can create OCGs just fine (as
long as they don't include a \newpage, but that's not unexpected).
However, the generated PDF is not 100% clean. Ghostscript says:
**** File did not complete the page properly and may be damaged.
Acroread (8.1.1) still displays the file after a warning. This must be
some stupid oversight since I have an example with OCGs that is Ok.
The difference is that I moved the code to generate the PDF stuff from
the source file to a package. I hope that one of you can point out the
error.
If there is interest, I would like to make this package available.
Since this is my first package I could use a little help preparing the
package for distribution.
Michael
ocg.sty:
%% Copyright (C) 2007 by Michael Ritzert <michael...@gmail.com>
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{ocg}[2007/10/14]
\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}
}{%
\pdfliteral{/OC /OC\@ocg@curnum\space EMC}%
%\unskip%
%\endgroup%
}
Example usage:
\documentclass{article}
\usepackage{ocg}
\begin{document}
\begin{ocg}{Top Layer}{1}{1}
layer 1
\end{ocg}
\begin{ocg}{Bottom Layer}{2}{0}
layer 2
% \newpage % doesn't work yet!
still layer 2
\end{ocg}
\newpage
\begin{ocg}{Markers}{3}{1}
layer 3
\end{ocg}
\begin{ocg}{Top Layer}{1}{1}
layer 1 again
\end{ocg}
\end{document}
Never mind. I found out how to deflate the FlateDecode and it was
obvious...
Remove the /OC /OC\@ocg@curnum\space from the pdfliteral for the EMC
marker and the PDF is fine.
> \newenvironment{ocg}[3]{%
> \@ocg@newocg{#1}{#2}{#3}%
> \gdef\@ocg@curnum{#2}%
> \pdfliteral{/OC /OC\@ocg@curnum\space BDC}%
> \message{/OC\@ocg@curnum}}{%
>
> \pdfliteral{/OC /OC\@ocg@curnum\space EMC}%
Change this to just
\pdfliteral{EMC}%
Michael
What sort of help? Are you planning to convert to a DTX, or create
separate documentation, for example.
Joseph Wright
Scott Pakin's dtxtut is the canonical reference:
<http://www.ctan.org/tex-archive/info/dtxtut/>
I wrote a companion "gallery" that demonstrates some nice features:
<http://www.ctan.org/tex-archive/info/dtxgallery/>
Cheers,
Will
Hello,
I found this OCG package and I think it's a great tool. Congratulations.
Why don't you put it on the CTAN Michael ?