%
% pts_bbox.sty -- open an image and read BoundingBox info
% modified by pts@fazekas.hu at Sun Feb  2 17:07:43 CET 2003
%

\expandafter\ifx\csname ifLaTeX\endcsname\relax\input laemu.sty\relax\fi%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{pts_bbox}[2003/02/02 v0.2 determine BoundingBox]

\def\@@imgread@sPS{PS}%
\def\@@imgread@sEPS{EPS}%
\def\@@imgread@sMetaPost{MetaPost}%

\def\@tempa{}%
\def\@tempb{}%

%** `\@@imgread@stripps FF..\\' set \@tempa to `FF' with `EPS.' and `PS.'
%** stripped from the beginning. FF is a FileFormat such as `TIFF' or
%** `EPS.MPS'.
\def\@@imgread@stripps#1.#2.#3\\{%
  \def\@tempa{#1}%
  \def\@tempb{#2}%
  \ifx\@tempb\@empty\else%
    \ifx\@tempa\@@imgread@sPS \def\@tempa{#2}%
    \else\ifx\@tempa\@@imgread@sEPS \def\@tempa{#2}%
    \else \def\@tempa{#1.#2}\fi\fi%
  \fi%
}%

%%** `\@@imgread@strpqbp#\\' expands to `#' if `#' begins with `?'; else
%%** it expands to `#bp'
%\def\@@imgread@stripqbp#1#2\\{%
%  \if\noexpand#1?%
%    #1#2%
%  \else
%    #1#2bp%
%  \fi
%}%

%** Process output of external command `img_bbox.pl --tex'. Strips EPS.*
%** -> * and PS.* -> *.
%** Example: \graphicPmeta{f2cletter.pdf}{PDF}{3}{-10}{23}{20}
\def\graphicPmeta#1#2#3#4#5#6{%
  %\message{meta{#1}{#2}{#3}{#4}{#5}{#6};}%
  \begingroup%
    \@@imgread@stripps#2..\\% returns \@tempa, ruins \@tempb
    \edef\@tempa{%
      \noexpand\def%
      \expandafter\noexpand\csname @@xb@#1\endcsname%
      %{{\@tempa}{\@@imgread@stripqbp#3\\}{\@@imgread@stripqbp#4\\}%
      %          {\@@imgread@stripqbp#5\\}{\@@imgread@stripqbp#6\\}}%
      {{\@tempa}{#3}{#4}{#5}{#6}}%
    }%
  \expandafter\endgroup\@tempa%
  %\expandafter\edef\csname @@xb@#1\endcsname{{\@tempa}{#3bp}{#4bp}{#5bp}{#6bp}}%
}%

%\graphicPmeta{a}{PS.MPS}{3}{4}{5}{6}\message{<\@@xb@a>}\end

%** Opens the external image file, reads the bounding box information, and
%** calls #1{LLX}{LLY}{URX}{URY}. Failure is indicated by setting any of
%** LLX, LLY, URX or URY to ?.
%** @param #1 a \cs#1#2#3#4 that records the bounding box information
%** @param #2 a filename
\def\@@GetBBox#1#2{%
  % Imp: unset temporary variables (@@gp@xb)
  \edef\@@gp@xb{@@xb@#2}% \ @@xb@foo.eps
  \expandafter\ifx\csname\@@gp@xb\endcsname\relax% no cached value yet
    %\PackageError{pts_img}{BBox read unimplemented}\@ehc%
    \@@imgread@afile\graphicPmeta{#2}%
  \fi%
  \edef\@@gp@xc{\csname\@@gp@xb\endcsname}% full expansion of cached value
  %\message{;\@@gp@xc;}%
  %\expandafter\expandafter\expandafter#1\expandafter\@gobble\@@gp@xc% gobble FileFormat
  \expandafter#1\@@gp@xc% report FileFormat and bbox
}%

\expandafter\ifx\csname @tempcnta\endcsname\relax%
  \newcount\@tempcnta
\fi
%\def\@makeother#1{\catcode`#1=12\relax}
%\chardef\@inputcheck0
% Dat: uses \newread\@inputcheck

\newif\if@@imgread@
%\def\@latex@error{\errmessage{#1}}
%\message{\@@imgread@BBox}%
%*** The DOS EPSF header
\edef\@@imgread@DOSEPSF{%
  % Imp: specify shorter
  \expandafter\@secondoftwo\string\^^c5%
  \expandafter\@secondoftwo\string\^^d0%
  \expandafter\@secondoftwo\string\^^d3%
  \expandafter\@secondoftwo\string\^^c6%
}%
%** A dot, and the first 3 bytes of a JPEG file
\edef\@@imgread@JPEG{%
  % Imp: specify shorter
  .%
  \expandafter\@secondoftwo\string\^^ff%
  \expandafter\@secondoftwo\string\^^d8%
  \expandafter\@secondoftwo\string\^^ff%
}%
\edef\@@imgread@PNG{\expandafter\@secondoftwo\string\^^89PNG}%
\edef\@@imgread@TIFFMM{MM..}% MSB first TIFF header is "MM\0*"
\edef\@@imgread@TIFFII{II*.}% LSB first TIFF header is "II*\0"
\def\@@imgread@atend{atend}
\edef\@@imgread@PDF{\expandafter\@secondoftwo\string\%PDF}
\edef\@@imgread@EPS{\expandafter\@secondoftwo\string\%!PS}
%\def\@@img@sPDF{PDF}%
%\def\@@img@sEPS{EPS}%
%\def\@@img@sQ{?}%

%** \@@imgread@setfour\cs...\\ \def's \cs to be the first four tokens of
%** `...'. `...' must have at least 4 tokens
\long\def\@@imgread@setfour#1#2#3#4#5#6\\{%
  \def#1{#2#3#4#5}%
}%
% vvv also defined in other files
{\catcode`p=12\catcode`t=12\gdef\@@mkb#1pt{#1}}% no p,t in @@mkb

%** Find and process %%BoundingBox ADSC comment in an EPS file, or the first
%** occurence of `/Mediabox [' (at BOL) in a PDF file. The PDF case is not
%** perfect, but cannot be, since TeX is unable to read binary files
%** properly; preprocess the PDF file with pdfboxes.pl to make sure.
%** @param #1 a \cs. calls #1{FileName}{Fileformat}{LLX}{LLY}{URX}{URY}
%** @param #2 filename
\def\@@imgread@afile#1#2{%
  % Dat: EPS with DOS-style binary preview is not supported
  \begingroup
  \@tempcnta0
  % 0  Escape character  (|\| in this manual)
  % 1  Beginning of group  (|{| in this manual)
  % 2  End of group  (|}| in this manual)
  % 3  Math shift  (|$| in this manual)
  % 4  Alignment tab  (|  | in this manual)
  % 5  End of line  (\<return> in this manual)
  % 6  Parameter  (|#| in this manual)
  % 7  Superscript  (|^| in this manual)
  % 8  Subscript  (|_| in this manual)
  % 9  Ignored character  (\<null> in this manual)
  %10  Space  (\] in this manual)
  %11  Letter  (|A|, \dots, |Z| and |a|, \dots, |z|)
  %12  Other character  (none of the above or below)
  %13  Active character  (|~| in this manual)
  %14  Comment character  (|%| in this manual)
  %15  Invalid character  (\<delete> in this manual)
  %
  % (by pts@fazekas.hu at Sun Feb  2 18:27:56 CET 2003)
  % The TeX \read primitive works like this: low-level line separators are
  % "\012", "\015" and "\015\012". \read reads a single line, as ended by
  % a single low-level line-separator. Two extra separators are assumed to be
  % at EOF. Space tokens (10) at the beginning of the line are ignored. A
  % series of empty lines are read as \par + space. The first end-of-line (5)
  % token is converted to a space, and the rest is ignored. The first
  % command (14) character and the rest is ignored.
  %   \ifeof is true between \openin and the first \read iff \open failed.
  %   Thus, we set all unprintable characters to ignored (9). We set both
  % '\012' and '\015' to be comment (14), so no space would be appended at
  % EOLs. Space and tab will be set to space (10). Thus real spaces won't be
  % ignored at the beginning of the lines, and \par will never be read.
  %   It is impossible to read the %!PS header of some DOS EPSF files,
  % because it might be before the first low-level line separator, but
  % ignored because of how we read the EPSF header.
  % 
  \@tempcnta0
  \loop\ifnum\@tempcnta<32 %
    \catcode\@tempcnta9 % ignored
    \advance\@tempcnta\@ne
  \repeat
  \@tempcnta127
  \loop\ifnum\@tempcnta<256%
    \catcode\@tempcnta9 % ignored
    \advance\@tempcnta\@ne
  \repeat
  \catcode`\\12% other
  \catcode`\{12% other
  \catcode`\}12% other
  \catcode`\}12% other
  \catcode`\$12% other
  \catcode`\&12% other
  \catcode`\#12% other
  \catcode`\^12% other
  \catcode`\_12% other
  \catcode`\%12% other
  \catcode`\~12% other
  \catcode`\:12% other
  \catcode`\-12% other
  \catcode32=10% ' ': space, ignored at BOL
  \catcode9=10% '\t': space, ignored at BOL
  \catcode`\]10% ']': space, so we can parse /MediaBox correctly
  \catcode\endlinechar14% '\015': end-of-line
  \catcode10=14%
  \catcode13=14%
  \catcode0=14% important for tiff
  \catcode198=12% last byte of DOS EPSF header
  \catcode211=12% third byte of DOS EPSF header
  \catcode208=12% second byte of DOS EPSF header
  \catcode197=12% first byte of DOS EPSF header
  \catcode137=12% first byte of PNG header
  \catcode255=12% JPEG marker-header
  \catcode216=12% JPEG SOI marker
  %\endlinechar=-1%
  \immediate\openin\@inputcheck#2 %
  \def\@@imgread@fmt{?}%
  \def\@@imgread@bbox{}% not found yet
  \ifeof\@inputcheck
    %\@latex@error%
    \PackageError{bbox}{Image file `#2' not found}\@ehc
  \else
    \read\@inputcheck to\@tempa% first line
    \catcode137=9 % first byte of PNG header
    \catcode255=9 % JPEG marker-header
    \catcode216=9 % JPEG SOI marker
    \expandafter\@@imgread@setfour\expandafter\@tempb\@tempa....\\%
    \expandafter\@@imgread@setfour\expandafter\@tempa\expandafter.\@tempb\\% \@tempb == ABCD -> @tempa = .ABC
    % Now \@tempb contains the first 4 chars, and \@tempa is the first line
    %\message{[\@tempb]}%
    \let\@@imgread@test@end\@@imgread@test@yesend
    \ifx\@tempb\@@imgread@PNG%
      \def\@@imgread@fmt{PNG}%
      \@@imgread@pdftexgetwh{#2}%
    \else\ifx\@tempb\@@imgread@TIFFII%
      \def\@@imgread@fmt{TIFF}%
      \@@imgread@pdftexgetwh{#2}%
    \else\ifx\@tempb\@@imgread@TIFFMM%
      \def\@@imgread@fmt{TIFF}%
      \@@imgread@pdftexgetwh{#2}%
    \else\ifx\@tempb\@@imgread@DOSEPSF%
      % Emit a warning, since these DOS EPSF files cannot be embedded
      % properly by dvips, and even reading the bounding box is quite
      % unstable.
      \PackageWarning{pts_img}{DOS EPSF header in file `#2'\@gobble}%
      \let\@tempb\@@imgread@EPS%
      \let\@@imgread@test@end\@@imgread@test@noend
      \def\@@imgread@fmt{EPS}% or PS
    \else\ifx\@tempb\@@imgread@EPS%
    \else\ifx\@tempb\@@imgread@PDF%
    \else\ifx\@tempa\@@imgread@JPEG% \@tempa
      \def\@@imgread@fmt{JPEG}%
      \@@imgread@pdftexgetwh{#2}%
    %\else% unknown image format
    \fi\fi\fi\fi\fi\fi\fi%
    \ifx\@tempb\@@imgread@EPS%
      \def\@@imgread@fmt{EPS}% or PS
      \edef\@percentchar{\expandafter\@secondoftwo\string\%}% LaTeX has it
      \edef\@@imgread@BBox{\@percentchar\@percentchar BoundingBox}%
      \edef\@@imgread@BBoh{\@percentchar\@percentchar HiResBoundingBox}%
      \edef\@@imgread@BBoe{\@percentchar\@percentchar ExactBoundingBox}%
      \edef\@@imgread@BBoc{\@percentchar\@percentchar Creator}%
      \let\@@imgread@find@bb\@@imgread@find@eps%
      \@@imgread@lines%
    \else\ifx\@tempb\@@imgread@PDF%
      \def\@@imgread@fmt{PDF}%
      \edef\@@imgread@BBox{/MediaBox}% `/MediaBox [' or `/MediaBox['
      \let\@@imgread@find@bb\@@imgread@find@pdf%
      \@@imgread@lines%
    \else% unknown
    \fi\fi%
    %\message{format:\@@imgread@fmt.}%
    \immediate\closein\@inputcheck%
  \fi% \ifeof\@inputcheck
  \edef\@tempa{\noexpand#1{#2}{\@@imgread@fmt}\@tempa}%
  \expandafter\endgroup\@tempa% end the group and call output command
}

%** Use pdfTeX to define \@tempa to be a bounding box of the image.
%** @param #1 filename
\def\@@imgread@pdftexgetwh#1{% !! Imp: use pdfTeX (if present) to get BBox
  \def\@tempa{{?}{?}{?}{?}}% not pdfTeX. Cannot read binary files. Give up.
  \expandafter\ifx\csname pdfoutput\endcsname\relax%
  \else\ifnum0<\pdftexversion%
    % Newer versions of pdfTeX can embed PNG, JPEG and TIFF images directly.
    % Just load the image into a \hbox, and measure its dimensions.
    \begingroup\setbox0=\hbox{%
      \expandafter\ifx\csname pdfximage\endcsname\relax
        \ifnum\pdftexversion<13% older, Debian Slink
          \pdfimage#1\noexpand\noexpand\noexpand\@empty \relax% #1 may start with `width'
        \else
          \pdfimage{#1}%
        \fi
      \else% quite new pdfTeX
        %\immediate\pdfximage would include the image file unnecessarily.
        % Without \immediate, only a single PDF xref entry is occupied per
        % image. This call to \pdfximage doesn't make the bug in
        % pdftex_bug.tex manifest. What a luck.
        \pdfximage{#1}%
        \pdfrefximage\pdflastximage
      \fi
    }%
    % Now \ht0 etc. have the width in bp. We convert it to pt first, and
    % then remove the `pt' unit. The orinal dimension (in bp) was an integer,
    % so we round to the nearest integer to compensate errors of fixed point
    % arithmetic.
    \dp0=-.99626400996264\dp0% *-72/72.27
    \wd0=.99626400996264\wd0%
    \ht0=.99626400996264\ht0%
    \count0=\dp0\advance\count0 32768\divide\count0 65536%
    \count1=\wd0\advance\count1 32768\divide\count1 65536%
    \count2=\ht0\advance\count2 32768\divide\count2 65536%
    %\message{pdfbbox=(0,\the\count0,\the\count1,\the\count2)}%
    \edef\@tempa{\noexpand\def\noexpand\@tempa{{0}{\the\count0}{\the\count1}{\the\count2}}}%
    \expandafter\endgroup\@tempa
  \fi\fi%
}

%** Read the file line-by-line, stop at the first line containing BBox info.
\def\@@imgread@lines{%
  \@@imgread@true
  \let\@tempb\@@imgread@false
  \loop
    %\endlinechar=65 \relax% doesn't work, a space will be appended
    %\catcode13=9 % doesn't work, a space will be appended
    \read\@inputcheck to\@tempa
    \ifeof\@inputcheck
      \@@imgread@false
    \else
      %\message{t(\@tempa)}%
      \expandafter\@@imgread@find@bb\@tempa:[.\\%
    \fi
  \if@@imgread@\repeat
  \ifx\@@imgread@bbox\@empty
    \def\@tempa{{?}{?}{?}{?}}%
  \else% found BBox -- maybe not syntactically correct
    %\message{///\@tempa***}%
    \expandafter\@@imgread@parse@bb\@@imgread@bbox\\%
  \fi%
}
\def\@@imgread@find@eps#1:#2#3\\{%
  \def\@tempa{#1}%
  %\message{find(\@tempa)}%
  \@@imgread@test@end#1.....\\% modifies \@tempa
  \ifx\@tempa\@@imgread@BBox%
    \@@imgread@test@atend#2#3()\\%
  \else\ifx\@tempa\@@imgread@BBoh%
    \@@imgread@test@atend#2#3()\\%
    \ifx\@@imgread@bbox\@empty\else%
      \def\@@imgread@BBox{:}% don't recognise subsequent %%BoundingBox after %%HiResBoundingBox
    \fi%
  \else\ifx\@tempa\@@imgread@BBoe%
    \@@imgread@test@atend#2#3()\\%
    \ifx\@@imgread@bbox\@empty\else%
      \def\@@imgread@BBox{:}% don't recognise subsequent %%BoundingBox after %%HiResBoundingBox
      \def\@@imgread@BBoh{:}% don't recognise subsequent %%HiResBoundingBox after %%ExactBoundingBox
    \fi%
  \else\ifx\@tempa\@@imgread@BBoc%
    \@@imgread@test@creator#2#3\\%
  \fi\fi\fi\fi%
}
%** In normal mode. Runs \@tempb if about to end
%** @param #1..#5 single chararacter tokens
\def\@@imgread@test@yesend#1#2#3#4#5#6\\{%
  %\message{end(#1#2#3#4#5)}%
  \if\noexpand#1\@percentchar%
    \if\noexpand#2\@percentchar%
      \if\noexpand#3E%
        \if\noexpand#4n%
          \if\noexpand#5d%
            \@tempb%
          \fi%
        \fi%
      \fi%
    \else%
      \@tempb%
    \fi%
  \else%
    \@tempb%
  \fi%
}%
%** In MetaPost mode. Runs \@tempb if about to end.
%** The %%HiResBoundingBox comment emitted by ConTeXt is usually after
%** %%EndProlog. So we stop at the first line not beginning with `%'
%** @param #1..#5 single chararacter tokens
\def\@@imgread@test@mpend#1#2#3#4#5#6\\{%
  \if\noexpand#1\@percentchar%
  \else%
    \@tempb%
  \fi%
}%
%** Used as \@@imgread@test@end when reading a DOS EPSF file
\def\@@imgread@test@noend#1\\{}%

\def\@@imgread@find@pdf#1[#2#3\\{%
  \def\@tempa{#1}%
  %\message{find(\@tempa)}%
  \ifx\@tempa\@@imgread@BBox \@@imgread@test@atend#2#3()\\\fi%
}
%** Recognise the ``%%Creator: MetaPost'' ADSC comment. Ruins @tempa
\def\@@imgread@test@creator#1:#2\\{%
  %\message{cr(#1)}%
  \def\@tempa{#1}%
  \ifx\@tempa\@@imgread@sMetaPost%
    \def\@@imgread@fmt{MPS}%
    \let\@@imgread@test@end\@@imgread@test@mpend% find late %%HiresBoundingBox
  \fi%
}%
\def\@@imgread@test@atend#1(#2)#3\\{%
  %\message{atend(#2)}%
  \ifx\@tempb\relax\else% don't allow early ending for (atend)
    \let\@@imgread@test@end\@@imgread@test@yesend
  \fi%
  \def\@tempa{#2}%
  \ifx\@tempa\@@imgread@atend
    \@@imgread@true
    \let\@tempb\relax% read till EOF
  \else
    %\message{gotit(#1)}%
    \def\@@imgread@bbox{#1}%
    % Don't do \@@imgread@false, because better %%BoundingBox may come before %%End
  \fi%
}
%** Sets \@tempa to the BBox info, ruins \dimen[1234]
\def\@@imgread@parse@bb#1 #2 #3 #4:#5\\{%
  \dimen1=#1pt \dimen2=#2pt \dimen3=#3pt \dimen4=#4pt% simplify and pre-round
  % ^^^ important to remove spaces after #4
  \edef\@tempa{{\expandafter\@@mkb\the\dimen1}{\expandafter\@@mkb\the\dimen2}{\expandafter\@@mkb\the\dimen3}{\expandafter\@@mkb\the\dimen4}}%
  %\message{bbox(#1)(#2)(#3)(#4)[\@tempa]}%
}%
