SLUG mail archive
[Prev][Next][Index][Thread]
Re: What the right way to get ps files into figures?
Date: Fri, 2 Mar 90 21:53:44 EDT
From: "Bruce R. Miller" <MILLER@vax.cam.nist.gov>
Date: Fri, 2 Mar 90 11:12 PST
From: Walt Bunch <BUNCH@alan.kahuna.decnet.lasc-research.lockheed.com>
I saw a reference to a form "\special{psfile=..." in a SLUG message. I
tried it out with some text, e.g.
Here goes... \special{psfile=ps-file.ps} Done.
and the text (in postscript form from the ps-file.ps file) was in a
random place on the page, half of it falling off the page. I tried
including a drawing instead and all I got was a blank page.
Given that I want to take an image from a PS file and scale it into a
LaTeX box in a figure, what's the right way to do it?
I suppose this is a common question. I just sent a message to join the
mailing list.
Thanks in advance,
Walt Bunch
bunch@alan.decnet.lockheed.com
I've never actually tried it with text, but I'ld assume the issues are
similar. My first attempts also came out quite bizzare.
The main problem is locating the picture --- yeah you knew that :)
I'll describe the way I think of it; not necessarily unique or even the
best -- but it works.
Think of the \special command as putting an infinitesimal TeX `box'
at the place it occured. As TeX fiddles around with the boxes, it
moves that one too. This is nice because you can put your \special
inside of a \begin{figure}...\end{figure}, and the box stays with the
figure. This also means that TeX has allocated NO space for the
insertion; you've got to do that yourself with \vspace* &/or \hspace*.
Now, the stuff being inserted is laid `on top of' (in an appropriate
ps sense) whatever else TeX has put onto the page. In particular, the
inserted `page' has its origin (lower-left corner) at the infinitesimal
box.
Anyway, to make it more concrete:
Step 1) Make a postscript file with graphics; Depending on how
you are producing your graphics, generate a postscript file with
eg.
(with-open-stream (stream (hardcopy:make-hardcopy-stream
`(:file #P"destination-pathname" :lgp2)
:title "A Picure!"))
...)
or
(hardcopy:set-default-bitmap-printer `(:file #P"destination-pathname" :lgp2))
or whatever.
You may have to play with graphics:with-room-for-graphics,
graphics:with-graphics-translation ... so that the origin is in the
`right' place. Easy way: print the resulting file. If the graphics is
sitting close to the lower-left corner of the paper -- Got it!
Now, you can insert it into your tex, for example
\begin{figure}[htb]
\vspace*{height-of-picture}
\special{psfile=ps-file.ps hoffset= 17 voffset= -20}
\caption{A figure with beautify graphics}
\end{figure}
Even so, you sometimes have to tune it by adding hoffset=#pts, voffset=#pts,
to the special. hscale=factor & vscale=factor allow you to scale the picture to a
particular size. But TeX wont figure out how to scale it to fill up a
space; its got no idea of what the psfile contains.
As far as inserting text is concerned, Ethnocentrically speaking, one
normally thinks of text flowing from the top to the bottom. In that
case, perhaps one might want to modify the mental model.
This is all correct, but here at the AI lab Jerry Roylance has come up with a
tex macro that will reads the bounding box information in the the header of a
postscript file, and then automatically computes up with the right offsets for
the psfile special so that the lower left of the bounding box appears at the
(tex) point. It also makes a (tex) box the exact size of the bounding box, so
the macro semantically is the same as setting a character of the size of the
bounding box. See the comments in this file for more information:
% -*- Mode: TeX -*-
% Merging PostScript Illustrations
% These TeX macros enable easy insertion of PostScript
% illustrations into documents produced by TeX and LaTeX.
% The illustrations are automatically sized when the
% PostScript file has a
% BoundingBox: llx lly urx ury
% line in it. The units of measurement for lower-left-x (llx),
% lower-left-y (lly), upper-right-x (urx), and
% upper-right-y (ury) are 1/72 of an inch (a PostScript unit).
% Source locations at the MIT AI Laboratory
% Canonical Source
% Trix /homes/glr/tex/psadobe/psadobe.tex
% References
% Adobe Systems, Inc
% PostScript Language Reference Manual
% Addison-Wesley, 1986
% Appendix C, pages 279-286
% DVILASER/PS User Manual
% ArborText, Inc, 1987
% Copyright Gerald Roylance 1987, 1989
% This file may be copied or distributed as long as this
% copyright notice is not removed.
% PostScript is a trademark of Adobe Systems Incorporated.
% Bugs and Fixes
% bulletproof reading the postscript file [GLR, 11/89]
% reads only the headercomments, demands %! and %%
% add ArborText support [GLR, 3/89]
% clear out some junk [GLR, 3/89]
% convert \mag to a float at runtime [Rich, 12/87]
% removed spurious cr's in psadobeextract, -bb, -header [Rich, 11/87]
% make psfile switch to horizontal mode
% now LaTeX \leavevmode isn't needed [GLR, 11/87]
% changed \errmessage to \message for file not found
% in \psadobeheader [Rich, 12/87]
% added \psadobepercent [Rich, 12/87]
% added \xpsadobe and \xpsadobepercent [Rich, 2/22]
% Usage
% To load the macros, use
% \input{psadobe}
% The macros are read from TeX's default input area.
% To insert an illustration, use
% \psadobe{filename.ps}
% The expression is treated exactly like a character.
% You will probably want to center it or use other positioning
% commands. The illustration is also magnified by the \mag
% parameter. If you don't want this magnification, then
% use
% \psadobenomag{filename.ps}
% The filename may present some difficulty because
% both TeX and the dvi converter use the filename.
% You may have to provide a fully qualified filename.
% The illustrations to be inserted with autosizing must use
% the Adobe PostScript File Structuring Conventions (PFSC).
% These macros do automatic sizing of the inserted illustation
% by reading the PFSC header comment of the PostScript file.
% The Lisp Machine program Illustrate produces the correct format.
% Most MacIntosh programs do not provide a tight bounding box.
% In order to insert a PostScript file, the .dvi to PostScript
% converter must implement \special{PSFILE...} or use ArborText's
% \special{ps:...} commands. The MIT AI Lab uses the Unix program
% dvi2ps (available from ???) and a Lisp Machine dvi converter
% (available from the Symbolics LispMachine Users' Group).
% If your converter cannot understand a set of special commands,
% then after loading psadobe turn off the appropriate set of specials:
% \dvitopsfalse
% \ArborTextfalse
% For further information, see MIT AI Laboratory Working Paper 299a.
% Subroutines
\newif\ifdvitops \dvitopstrue % include PSFILE specials
\newif\ifArborText \ArborTexttrue % include ArborText specials
% The fundamental insertion macro. This inserts a PostScript file
% putting the origin at (x,y) and building a TeX box whose
% size is (w,h). Nothing fancy is done. x,y,w,h are TeX dimensions.
% The magnification m is a string that should be something like 1.40.
%
% psfile(x,y,w,h,m,filename)
%
\newbox\psvoid
%
\def\psfile#1#2#3#4#5#6{%
\unhbox\psvoid% switch to horizontal mode (just like a letter would)
\hbox to #3{% make a box w wide
\kern-#1% offset the illustration's x-pos
\vbox to #4{% make a box h tall
\vfil% push the special down to the bottom
\kern#2% offset by the illustration's y-pos
\ifdvitops\special{psfile=#6 hscale=#5 vscale=#5}\fi%
\ifArborText%
\special{ps::[asis,begin]
0 SPB
/PSFileCheckPoint save def
/showpage {} def
/erasepage {} def
/copypage {} def
/letter {} def
/note {} def
/legal {} def
/ledger {} def
/11x17 {} def
/a3 {} def
/a4 {} def
Xpos Ypos translate
#5 dup scale
/xdefaultmatrix matrix currentmatrix def
/defaultmatrix {xdefaultmatrix exch copy} def
/initmatrix {xdefaultmatrix setmatrix} def
/initgraphics
{initmatrix newpath initclip
1 setlinewidth 0 setlinecap 0 setlinejoin
[] 0 setdash 0 setgray 10 setmiterlimit} def
}%
\special{ps: plotfile #6 asis}%
\special{ps::[asis,end]
PSFileCheckPoint restore
0 SPE }%
\fi%
\kern-#2}% unoffset y
\kern#1\hfil% unoffset x and push the special left
}}
% Convert an integer to a floating point string.
% This gross hack works if \mag < 10000
%
\newcount\float \float=\mag \advance\float by 10000
\def\floater#1#2#3#4#5{#2.#3#4#5}
% Parse a PostScript Header
% The header looks like
%
% %!PS-Adobe-1.0
% %%Creator: Illustrate Version 11.0
% %%CreationDate: 6/23/87 17:35:01
% %%Pages: 1
% %%BoundingBox: 466.12912 718.63934 612.0283 792.0283
% %%EndComments
%
% *** Should complain if #2 is (atend)
% Dimensions of the illustration
\newdimen\psadobex
\newdimen\psadobey
\newdimen\psadobew
\newdimen\psadobeh
\newif\ifpsadobeflag
\newread\psadobefile
% set the default values for the bounding box
% either
% \psadobesetdefault{72}{72}{72}{72}{}
% \psadobesetdefault{72}{72}{72}{72}{true}
%
\def\psadobesetdefault#1#2#3#4#5{%
\global\psadobex= #1 #5bp% set the default sizes to 72 points
\global\psadobey= #2 #5bp%
\global\psadobew= #3 #5bp%
\global\psadobeh= #4 #5bp}
% psadobeextract(junk llx lly urx ury true)
% PostScript and TeX share the same comment character, and now TeX must
% look for that comment character in a PostScript file. So turn % into
% regular character. Unfortunately, that gives us trouble with line
% breaks -- we can no longer put % at the end of a line.
% One fix, due to Chuck Rich, just cleverly (and unreadably) puts the
% line breaks where they are ignored.
% Another fix temporarily redefines ~ as a comment character.
\catcode`\%=12
\catcode`\~=14
~ psadobeextract expects to be called with the box size and
~ some trailing garbage left over from reading the line.
~ \psadobeextract %%BoundingBox: llx lly urx ury %%BoundingBox:\heaven{true}
\def\psadobeextract#1 #2 #3 #4 #5%%BoundingBox:\heaven#6{~
\global\psadobex= #2 #6bp~
\global\psadobey= #3 #6bp~
\global\psadobew= #4 #6bp~
\global\advance\psadobew by -\psadobex~
\global\psadobeh= #5 #6bp~
\global\advance\psadobeh by -\psadobey}
\def\psadobebb#1%%BoundingBox:#2\EOL#3{~
\ifx#2\heaven~ if second arg is the token \heaven
\else~ otherwise
\psadobeflagfalse~ stop looking
\psadobeextract#2{#3}~ extract the bounding box
\closein\psadobefile~ and close the file
\fi}
~ psadobeheader takes 2 arguments. The first is either {} or {true};
~ {} means use normal (with magnification) sizes and {true} means
~ use actual sizes (no magnifcation). The second argument is the name
~ of the PostScript file.
~
\def\psadobeheader#1#2{~
\openin\psadobefile=#2~ open the PostScript file
\relax~
\ifeof\psadobefile~ check if the file is there
\message{psadobe did not find PostScript file #2}~
\else~
\begingroup~ save the character definitions
\def\psadobeendcom{%%EndComments}~
\def\psadobefirst ##1%!##2\EOL{~ make sure line starts with %!
\ifx##2\heaven~
\psadobeflagfalse~ set the exit flag
\message{psadobe: file #2 does not start with a %! comment.
Please add PostScript header comments to the file.}~
\else\fi}~
\def\psadoberest ##1%%##2\EOL{~ make sure line starts with %%
\ifx##2\heaven~
\psadobeflagfalse~ set the exit flag
\else\fi}~
\catcode`\^^M=10~ make sure CR is a space (obeylines)
\catcode`\%=12~ turn off % comments (12 = other)
~ ... should turn off other characters
\psadobeflagtrue~ loop until this psadobeflag is false
\read\psadobefile to \line~ read the first line
~ check first line starts with %!
\expandafter\psadobefirst\line %!\heaven\EOL~
\loop~ read each header line
\ifeof\psadobefile~ if end of file
\psadobeflagfalse~ set the exit flag
\message{psadobe hit EOF looking for BoundingBox in #2.
Please put a BoundingBox comment in the header.}~
\else~
\read\psadobefile to \line~ read a line from the ps file
~ check the line starts with %%
\expandafter\psadoberest\line %%\heaven\EOL~
\ifx\line\psadobeendcom~ if the line is %%EndComments
\psadobeflagfalse~ then the header has ended
\else\fi~
\ifpsadobeflag~ if it's a good header comment, test for BBox
\expandafter\psadobebb\line %%BoundingBox:\heaven\EOL{#1}~
\else~ otherwise we didn't find a BBox
\message{psadobe did not find a BoundingBox comment in #2.
Please put one in.}~
\fi~
\fi~
\ifpsadobeflag\repeat~
\endgroup\fi}
\catcode`\%=14
\catcode`\~=13
% Normal comments are back on now.
% Automatic Sizing of a PostScript File
% These are the advertised calls.
% Everything else may change.
% Insert a Postscript file with scaling by \mag
%
\def\psadobe#1{\xpsadobe{#1}{#1}}
% Following auxiliary definition allows a different pathname syntax
% to be used on Tex'ing machine versus dvi->ps machine.
% [Float mag has to be done here because of expansion problems -- CR]
%
\def\xpsadobe#1#2{%
\psadobesetdefault{72}{72}{72}{72}{}% set the default sizes to 72 points
\psadobeheader{}{#1}% parse the header comments
{\float=\mag \advance\float by 10000%
\psfile{\psadobex}{\psadobey}{\psadobew}%
{\psadobeh}{\expandafter\floater\the\float}{#2}}}
% Insert a PostScript file without scaling by \mag
% read header using true dimensions
% insert the file with a magnification of 1
\def\psadobenomag#1{%
\psadobesetdefault{72}{72}{72}{72}{true}% set the default sizes to 72 points
\psadobeheader{true}{#1}% parse the header comments
\psfile{\psadobex}{\psadobey}{\psadobew}{\psadobeh}{1.000}{#1}}
% Insert a PostScript file, scaling by current value of \mag and a given percent
% N.B. The first argument is the *percent* scaling (i.e. 100 is normal size).
%
% psadobepercent( percent, file )
\def\psadobepercent#1#2{\xpsadobepercent{#1}{#2}{#2}}
% Similarly to \xpsadobe
\def\xpsadobepercent#1#2#3{%
\psadobesetdefault{72}{72}{72}{72}{}% set the default sizes to 72 points
\psadobeheader{}{#2}% parse the header comments
\global\divide\psadobex by 100\global\multiply\psadobex by #1%
\global\divide\psadobey by 100\global\multiply\psadobey by #1%
\global\divide\psadobew by 100\global\multiply\psadobew by #1%
\global\divide\psadobeh by 100\global\multiply\psadobeh by #1%
{\float=\mag \multiply\float by #1\divide\float by 100%
\advance\float by 10000%
\psfile{\psadobex}{\psadobey}{\psadobew}%
{\psadobeh}{\expandafter\floater\the\float}{#3}}}
\endinput
Main Index |
Thread Index