The Graphics Package: This File Has Version Number v1.0p, Last Revised 2014/10/28
The Graphics Package: This File Has Version Number v1.0p, Last Revised 2014/10/28
D. P. Carlisle S. P. Q. Rahtz
2014/10/28
1 Introduction
This package implements various ‘graphics’ functions. The main features are a)
inclusion of ‘graphics’ files. b) Rotation of sections of the page, c) Scaling of
sections of the page.
The design is split into three ‘levels’.
2 Package Options
Most of the options, such as dvips, textures etc., specify the driver that is to be
used to print the document. You may wish to set up a configuration file so that
this option always takes effect, even if not specified in the document. To do this,
produce a file graphics.cfg containing the line:
∗ This file has version number v1.0p, last revised 2014/10/28.
1
\ExecuteOptions{dvips}
(or whichever other driver you wish.)
Apart from the driver options there are a few other options to control the
behaviour of the package.
draft Do not include graphics files, but instead print a box of the size the graphic
would take up, and the file name. This greatly speeds up previewing on
most systems.
final Turns off the draft option.
debugshow Show a lot of tracing information on the terminal. If you are not me
you probably do not want to use this option.
hiderotate Do not show rotated text. Sometimes useful if your previewer can
not rotate text.
hidescale Do not show scaled text.
hiresbb Look for Bounding Box lines of the form %%HiResBoundingBox instead
of the standard %%BoundingBox. These are used by some applications to get
round the restriction that BoundingBox comments should only have integer
values.
3 Standard Interface
3.1 Graphics Inclusion
\includegraphics *[hllx,llyi][hurx,uryi]{hfilei}
Include a graphics file.
If * is present, then the graphic is ‘clipped’ to the size specified. If * is omitted,
then any part of the graphic that is outside the specified ‘bounding box’ will over-
print the surrounding text.
If the optional arguments are omitted, then the size of the graphic will be de-
termined by reading an external file as described below. If [hurx,uryi] is present,
then it should specify the coordinates of the top right corner of the image, as a
pair of TEX dimensions. If the units are omitted they default to bp. So [1in,1in]
and [72,72] are equivalent. If only one optional argument appears, the lower left
corner of the image is assumed to be at [0,0]. Otherwise [hllx,llyi] may be used
to specify the coordinates of this point.
\graphicspath {hdir-listi}
This optional declaration may be used to specify a list of directories in which to
search for graphics files. The format is as for the LATEX 2ε primitive \input@path,
a list of directories, each in a {} group (even if there is only one in the list). For
2
example: \graphicspath{{eps/}{tiff/}} would cause the system to look in the
subdirectories eps and tiff of the current directory. The default setting of this
path is \input@path that is: graphics files will be found wherever TEX files are
found.
\DeclareGraphicsExtensions {hext-listi}
This specifies the behaviour of the system when the argument to \includegraphics
does not have an extension specified. Here {hext-listi} should be a comma-
separated list of file extensions, each with a leading period (.). A file name is
produced by appending sep and one extension. If a file is found, the system acts
as if that extension had been specified. If not, the next extension in ext-list is
tried.
Each use of \DeclareGraphicsExtensions overwrites all previous definitions.
It is not possible to add an extension to an existing list.
Early versions of this package defined a default argument for this command.
This has been removed.
\DeclareGraphicsRule {hexti}{htypei}{hread-filei}{hcommand i}
Any number of these declarations can be made. They determine how the sys-
tem behaves when a file with extension ext is specified. (The extension may
be specified explicitly or, if the argument to \includegraphics does not have
an extension, it may be a default extension from the ext-list specified with
\DeclareGraphicsExtensions.)
ext is the extension of the file. Any file with this extension will be processed
by this graphics rule. Normally a file with an extension for which no rule has been
declared will generate an error, however you may use * as the extension to define
a default rule. For instance the dvips driver file declares all files to be of type eps
unless a more specific rule is declared.
Since Version v0.6, extensions should be specified including the . that is, .eps
not eps.
type is the ‘type’ of file involved. All files of the same type will be input with
the same internal command (which must be defined in a ‘driver file’). For example
files with extensions ps, eps, ps.gz may all be classed as type eps.
read-file determines the extension of the file that should be read to determine
size information. It may be the same as ext but it may be different, for example
.ps.gz files are not readable easily by TEX, so you may want to put the bounding
box information in a separate file with extension .ps.bb. If read-file is empty, {},
then the system will not try to locate an external file for size info, and the size
must be specified in the arguments of \includegraphics. As a special case * may
be used to denote the same extension as the graphic file. This is mainly of use in
conjunction with using * as the extension, as in that case the particular graphic
extension is not known. For example
\DeclareGraphicsRule{*}{eps}{*}{}
This would declare a default rule, such that all unknown extensions would be
treated as EPS files, and the graphic file would be read for a BoundingBox com-
ment.
3
If the driver file specifies a procedure for reading size files for type, that will be
used, otherwise the procedure for reading eps files will be used. Thus the size of
bitmap files may be specified in a file with a PostScript style %%BoundingBox line,
if no other specific format is available.
command is usually empty, but if non empty it is used in place of the filename
in the \special. Within this argument, #1 may be used to denote the filename.
Thus using the dvips driver, one may use
\DeclareGraphicsRule{.ps.gz}{eps}{.ps.bb}{‘zcat #1}
the final argument causes dvips to use the zcat command to unzip the file before
inserting it into the PostScript output.
3.2 Rotation
\rotatebox {hanglei}{htexti}
Rotate text angle degrees anti-clockwise. Normally the rotation is about the left-
hand end of the baseline of text.
3.3 Scaling
\scalebox {hh-scalei}[hv-scalei]{htexti}
Scale text by the specified amounts. If v-scale is omitted, the vertical scale factor
is the same as the horizontal one.
\resizebox *{hh-lengthi}{hv-lengthi}{htexti}
Scale text so that the width is h-length. If ! is used as either length argument, the
other argument is used to determine a scale factor that is used in both directions.
Normally v-length refers to the height of the box, but in the star form, it refers
to the ‘height + depth’. As normal for LATEX 2ε box length arguments, \height,
\width, \totalheight and \depth may be used to refer to the original size of the
box.
4
this box should not be displayed. (Not all drivers can support this ‘clipping’.)
Normally all these parameters are set by the ‘user interface level’.
\Gread@eps {hfilei}
For each type of graphics file supported, the driver file must define \Ginclude@type
and, optionally \Gread@type. The read command is responsible for obtaining
size information from the file specified in the \DeclareGraphicsRule command.
However the kernel defines a function, \Gread@eps, which can read PostScript files
to find the %%BoundingBox comment. This function will be used for any type for
which a specific function has not been declared. \Gread@eps accepts a generalised
version of the bounding box comment. TEX units may be used (but there must
be no space before the unit). If the unit is omitted bp is assumed. So
%%BoundingBox 0 0 2in 3in
Would be accepted by this function, to produce a 2in wide, by 3in high graphic.
5.2 Rotation
\Grot@box
Rotate the contents of \box0 through \Grot@angle degrees (anti-clockwise). The
user-interface is responsible for setting the macro \Grot@angle, and putting the
appropriate text in \Grot@box.
5.3 Scaling
\Gscale@box {hxscalei}[hyscalei]{htexti}
(The second argument is not optional.) Scale text by the appropriate scale factors.
\Gscale@box@dd {hdimai}{hdimbi}{htexti}
Scale text in both directions by a factor dima/dimb.
\Gscale@box@dddd {hdimai}{hdimbi}{hdimci}{hdimd i}{htexti}
Scale text in horizontally by a factor dima/dimb, and vertically by a factor of
dimc/dimd.
\Gscale@div {hcmd i}{hdimai}{hdimbi}
Define the macro cmd to be the ratio of the lengths dima/dimb.
5
\Gin@llx, \Gin@lly, Macros storing the ‘bounding box’
\Gin@urx, \Gin@ury
\Gin@nat@width Registers storing the natural size.
\Gin@nat@height
\Gin@req@width Registers storing the required size, after
\Gin@req@height scaling.
\Gin@scalex, \Gin@scaley macros with the scale factors. A value of
! means: Scale by the same amount as
the other direction.
\ifGin@clip \newif token, true if the graphic should
be ‘clipped’ to the bounding box.
Optionally the driver may define a command of the form:
\Gread@type
This is responsible for reading an external file to find the bounding box informa-
tion. If such a command is not declared, but a read-file is specified the command
\Gread@eps, which is defined in the Graphics Kernel will be used.
6.3 Rotation
\Grot@start, \Grot@end These macros must be defined to insert the appropriate
\special to rotate the text between them by \Grot@angle degrees. The kernel
function will make sure that the correct TEX spacing is produced, these functions
only need insert the \special.
6.4 Scaling
\Gscale@start, \Gscale@end, as for rotation, but here scale the text by
\Gscale@x and \Gscale@y.
7 Implementation
6
1 h∗packagei
7.1 Initialisation
\Gin@codes First we save the catcodes of some characters, and set them to fixed values whilst
this file is being read.
2\edef\Gin@codes{%
3 \catcode‘\noexpand\^^A\the\catcode‘\^^A\relax
4 \catcode‘\noexpand\"\the\catcode‘\"\relax
5 \catcode‘\noexpand\*\the\catcode‘\*\relax
6 \catcode‘\noexpand\!\the\catcode‘\!\relax
7 \catcode‘\noexpand\:\the\catcode‘\:\relax}
8 \catcode‘\^^A=\catcode‘\%
9 \@makeother\"%
10 \catcode‘\*=11
11 \@makeother\!%
12 \@makeother\:%
\Gread@BBox %%BoundingBox as a macro for testing with \ifx. This may be redefined by the
hiresbb option.
20 \edef\Gread@BBox{\@percentchar\@percentchar BoundingBox}
7.2 Options
\ds@draft
\ds@final 21 \DeclareOption{draft}{\Gin@drafttrue}
22 \DeclareOption{final}{\Gin@draftfalse}
\ds@hiresbb If given this option the package will look for bounding box comments of the form
%%HiResBoundingBox (which typically have real values) instead of the standard
%%BoundingBox (which should have integer values).
24 \DeclareOption{hiresbb}{%
25 \edef\Gread@BBox{\@percentchar\@percentchar HiResBoundingBox}}
7
\ds@demo If given this option the package will disregard the actual graphics file and insert a
black box unless width or height are already specified.
26 \DeclareOption{demo}{%
27 \AtBeginDocument{%
28 \def\Ginclude@graphics#1{%
29 \rule{\@ifundefined{Gin@@ewidth}{150pt}{\Gin@@ewidth}}%
30 {\@ifundefined{Gin@@eheight}{100pt}{\Gin@@eheight}}}}}
\ds@dvips Tomas Rockicki’s PostScript driver (unix, MSDOS, VMS. . . ). The X11 previewer
\ds@xdvi xdvi supports basically the same set of \specials.
32 \DeclareOption{dvips}{\def\Gin@driver{dvips.def}}
33 \DeclareOption{xdvi}{\ExecuteOptions{dvips}}
\ds@emtex Two freely available sets of drivers for MSDOS, OS/2 and Windows.
\ds@dviwin 41 \DeclareOption{emtex}{\def\Gin@driver{emtex.def}}
42 \DeclareOption{dviwin}{\def\Gin@driver{dviwin.def}}
\ds@oztex OzTEX (Macintosh). Since release 3 of OzTEX, merge with dvips back end.
43 \DeclareOption{oztex}{\ExecuteOptions{dvips}}
8
\ds@pctexps PCTEX (MSDOS/Windows) .
\ds@pctexwin 45 \DeclareOption{pctexps}{\def\Gin@driver{pctexps.def}}
\ds@pctexhp 46 \DeclareOption{pctexwin}{\def\Gin@driver{pctexwin.def}}
\ds@pctex32 47 \DeclareOption{pctexhp}{\def\Gin@driver{pctexhp.def}}
48 \DeclareOption{pctex32}{\def\Gin@driver{pctex32.def}}
\ds@truetex Kinch TrueTeX, and its version with extended special support as shipped by Sci-
\ds@tcidvi entific Word.
49 \DeclareOption{truetex}{\def\Gin@driver{truetex.def}}
50 \DeclareOption{tcidvi}{\def\Gin@driver{tcidvi.def}}
\ds@dvi2ps If anyone is using any of these driver options would they let me know. All these
\ds@dvialw are essentially untried and untested as far as I know.
\ds@dvilaser 52 %\DeclareOption{dvi2ps}{\def\Gin@driver{dvi2ps.def}}
\ds@dvitops 53 %\DeclareOption{dvialw}{\def\Gin@driver{dvialw.def}}
\ds@psprint 54 %\DeclareOption{dvilaser}{\def\Gin@driver{dvilaser.def}}
\ds@pubps 55 %\DeclareOption{dvitops}{\def\Gin@driver{dvitops.def}}
\ds@ln 56 %\DeclareOption{psprint}{\def\Gin@driver{psprint.def}}
57 %\DeclareOption{pubps}{\def\Gin@driver{pubps.def}}
58 %\DeclareOption{ln}{\def\Gin@driver{ln.def}}
A local configuration file may define more options. It should also make one
driver option the default, by calling \ExecuteOptions with the appropriate option.
60 \InputIfFileExists{graphics.cfg}{}{}
\ds@hiderotate
61 \DeclareOption{hiderotate}{%
62 \def\Grot@start{\begingroup\setbox\z@\hbox\bgroup}
63 \def\Grot@end{\egroup\endgroup}}
\ds@hidescale
64 \DeclareOption{hidescale}{%
65 \def\Gscale@start{\begingroup\setbox\z@\hbox\bgroup}
66 \def\Gscale@end{\egroup\endgroup}}
After the options are processed, load the appropriate driver file. If a site wants
a default driver (eg textures) it just needs to put \ExecuteOptions{textures}
in a graphics.cfg file.
67 \ProcessOptions
9
Check that a driver has been specified (either as an option, or as a default
option in the configuration file). Then load the ‘def’ file for that option, if it has
not already been loaded by some other package (for instance the color package).
68 \if!\Gin@driver!
69 \PackageError{graphics}
70 {No driver specified}
71 {You should make a default driver option in a file \MessageBreak
72 graphics.cfg\MessageBreak
73 eg: \protect\ExecuteOptions{textures}%
74 }
75 \else
76 \PackageInfo{graphics}{Driver file: \Gin@driver}
77 \@ifundefined{ver@\Gin@driver}{\input{\Gin@driver}}{}
78 \fi
\Gin@llx In fact these four lengths are now stored as macros not as dimen registers, mainly
\Gin@lly so that integer bp lengths may be passed exactly.
\Gin@urx 79 \def\Gin@llx{0}
\Gin@ury 80 \let\Gin@lly\Gin@llx
81 \let\Gin@urx\Gin@llx
82 \let\Gin@ury\Gin@llx
\ifGin@clip This switch is htruei if any graphics outside the specified bounding box (really
viewport) should not be printed.
85 \newif\ifGin@clip
\DeclareGraphicsExtensions Declare a comma separated list of default extensions to be used if the file is
specified with no extension.
86 \newcommand\DeclareGraphicsExtensions[1]{%
87 \edef\Gin@extensions{\zap@space#1 \@empty}}
\includegraphics Top level command for the standard interface, just look for a *.
89 \def\includegraphics{%
90 \@ifstar
10
91 {\Gin@cliptrue\Gin@i}%
92 {\Gin@clipfalse\Gin@i}}
\Gin@i If an optional argument is present, call \Gin@ii to process it, otherwise call
\Ginclude@graphics.
93 \def\Gin@i{%
94 \@ifnextchar[%]
95 \Gin@ii
96 {\Gin@bboxfalse\Ginclude@graphics}}
\Gin@iii Set the coordinates of the llower left corner, and the coordinates of the upper
right corner. The coordinates may be any TEX dimension, defaulting to bp.
101 \def\Gin@iii[#1,#2][#3,#4]#5{%
102 \begingroup
103 \Gin@bboxtrue
104 \Gin@defaultbp\Gin@llx{#1}%
105 \Gin@defaultbp\Gin@lly{#2}%
106 \Gin@defaultbp\Gin@urx{#3}%
107 \Gin@defaultbp\Gin@ury{#4}%
108 \Ginclude@graphics{#5}%
109 \endgroup}
\Gin@defaultbp This macro grabs a length, #2, which may or may not have a unit, and if a
\Gin@def@bp unit is supplied, converts to ‘bp’ and stores the value in #1. If a unit is not
supplied ‘bp’ is assumed, and #2 is directly stored in #1. Note that supplying ‘bp’
is not quite the same as supplying no units, as in the former case a conversion
via ‘pt’ and back to ‘bp’ takes place which can introduce rounding error. The
error is invisibly small but files conforming to Adobe DSC should have integer
Bounding Box Coordinates, and conceivably some drivers might demand integer
values. (Although most seem to accept real values (if they accept bounding box
coordinates at all) in the \special. This is the reason why the mechanism uses
\def and not TEX lengths, as in earlier releases of the package.
110 \def\Gin@defaultbp#1#2{%
111 \afterassignment\Gin@def@bp\dimen@#2bp\relax{#1}{#2}}
112 \def\Gin@def@bp#1\relax#2#3{%
113 \if!#1!%
114 \def#2{#3}%
115 \else
116 \[email protected]\dimen@
117 \edef#2{\strip@pt\dimen@}%
118 \fi}
11
\DeclareGraphicsRule Declare what actions should be taken for a particular file extension.
#1 extension, #2 type, #3 read-file, #4 command,
119 \def\DeclareGraphicsRule#1#2#3#4{%
120 \edef\@tempa{\string *}\def\@tempb{#3}%
121 \expandafter\edef\csname Gin@rule@#1\endcsname##1%
122 {{#2}%
123 {\ifx\@tempa\@tempb\noexpand\Gin@ext\else#3\fi}%
124 {\ifx\indent#4\indent##1\else#4\fi}}}
\graphicspath User level command to set the input path for graphics files. A list of directories,
each in a {} group.
125 \def\graphicspath#1{\def\Ginput@path{#1}}
\Gin@getbase Given a possible extension, #1, check whether the file exists. If it does set
\Gin@base and \Gin@ext to the filename stripped of the extension, and the ex-
tension, respectively.
129 \def\Gin@getbase#1{%
130 \edef\Gin@tempa{%
131 \def\noexpand\@tempa####1#1\space{%
132 \def\noexpand\Gin@base{####1}}}%
133 \IfFileExists{\filename@area\filename@base#1}%
134 {\Gin@tempa
135 \expandafter\@tempa\@filef@und
136 \edef\Gin@ext{#1}}{}}%
\Gin@sepdefault This must match the token used by \filename@parse to delimit the extension.
138 \def\Gin@sepdefault{.}
\Ginclude@graphics The main internal function implementing graphics file inclusion. #1 is the file
name.
139 \def\Ginclude@graphics#1{%
140 \begingroup
141 \let\input@path\Ginput@path
12
142 \filename@parse{#1}%
143 \ifx\filename@ext\relax
144 \@for\Gin@temp:=\Gin@extensions\do{%
145 \ifx\Gin@ext\relax
146 \Gin@getbase\Gin@temp
147 \fi}%
148 \else
149 \Gin@getbase{\Gin@sepdefault\filename@ext}%
If the user supplied an explicit extension, just give a warning if the file does not
exist. (It may be created later.)
150 \ifx\Gin@ext\relax
151 \@warning{File ‘#1’ not found}%
152 \def\Gin@base{\filename@area\filename@base}%
153 \edef\Gin@ext{\Gin@sepdefault\filename@ext}%
154 \fi
155 \fi
If no extension is supplied, it is an error if the file does not exist, as there is no
way for the system to know which extension to supply.
156 \ifx\Gin@ext\relax
157 \@latex@error{File ‘#1’ not found}%
158 {I could not locate the file with any of these extensions:^^J%
159 \Gin@extensions^^J\@ehc}%
160 \else
161 \@ifundefined{Gin@rule@\Gin@ext}%
Handle default rule.
162 {\ifx\Gin@rule@*\@undefined
163 \@latex@error{Unknown graphics extension: \Gin@ext}\@ehc
164 \else
165 \expandafter\Gin@setfile\Gin@rule@*{\Gin@base\Gin@ext}%
166 \fi}%
167 {\expandafter\expandafter\expandafter\Gin@setfile
168 \csname Gin@rule@\Gin@ext\endcsname{\Gin@base\Gin@ext}}%
169 \fi
170 \endgroup}
13
180 #1%
181 \fi
182 \endcsname{\Gin@base#2}%
183 \else
By now the natural size should be known either from arguments or from the file.
If not generate an error. (The graphicx interface relaxes this condition slightly.)
184 \Gin@nosize{#3}%
185 \fi
186 \fi
The following call will modify the ‘natural size’ if the user has supplied a viewport
or trim specification. (Not available in the standard interface.)
187 \Gin@viewport@code
Save the natural size, and then call \Gin@req@sizes which (in the key-val inter-
face) will calculate the required size from the natural size, and any scaling info.
188 \Gin@nat@height\Gin@ury bp%
189 \advance\Gin@nat@height-\Gin@lly bp%
190 \Gin@nat@width\Gin@urx bp%
191 \advance\Gin@nat@width-\Gin@llx bp%
192 \Gin@req@sizes
Call \Ginclude@type to include the figure unless this is not defined, or draft
mode is being used.
193 \expandafter\ifx\csname Ginclude@#1\endcsname\relax
194 \Gin@drafttrue
195 \expandafter\ifx\csname Gread@#1\endcsname\relax
196 \@latex@error{Can not include graphics of type: #1}\@ehc
197 \global\expandafter\let\csname Gread@#1\endcsname\@empty
198 \fi
199 \fi
200 \leavevmode
201 \ifGin@draft
202 \hb@xt@\Gin@req@width{%
203 \vrule\hss
204 \vbox to \Gin@req@height{%
205 \hrule \@width \Gin@req@width
206 \vss
207 \edef\@tempa{#3}%
208 \rlap{ \ttfamily\expandafter\strip@prefix\meaning\@tempa}%
209 \vss
210 \hrule}%
211 \hss\vrule}%
212 \else
Support \listfiles and then set the final box to the required size.
213 \@addtofilelist{#3}%
214 \ProvidesFile{#3}[Graphic file (type #1)]%
215 \setbox\z@\hbox{\csname Ginclude@#1\endcsname{#3}}%
216 \dp\z@\z@
14
217 \ht\z@\Gin@req@height
218 \wd\z@\Gin@req@width
219 \box\z@
220 \fi}
\Gin@req@sizes In the standard interface there is no scaling, so the required size is the same as the
\Gin@scalex natural size. In other interfaces \Gin@req@sizes will be responsible for setting
\Gin@scaley these parameters. Here we can set them globally.
\Gin@req@height 222 \let\Gin@req@sizes\relax
\Gin@req@width 223 \def\Gin@scalex{1}%
224 \let\Gin@scaley\Gin@exclamation
225 \let\Gin@req@height\Gin@nat@height
226 \let\Gin@req@width\Gin@nat@width
\Gin@nosize This command is called in the case that the graphics type specifies no ‘read file’ and
the user supplied no size arguments. In the standard interface can only generate
an error.
228 \def\Gin@nosize#1{%
229 \@latex@error
230 {Cannot determine size of graphic in #1 (no size specified)}%
231 \@ehc}
\Gread@eps Read an EPS file (#1) and search for a line starting with %%BoundingBox and re-
turns the result by setting four dimension registers \Gin@llx, \Gin@lly, \Gin@urx
and \Gin@ury.
233 \def\Gread@eps#1{%
234 \begingroup
Make it reasonably safe to have binary headers in the EPS file before the bounding
box line.
235 \@tempcnta\z@
236 \loop\ifnum\@tempcnta<\@xxxii
237 \catcode\@tempcnta14 %
238 \advance\@tempcnta\@ne
239 \repeat
15
240 \catcode‘\^^?14 %
241 \let\do\@makeother
242 \dospecials
Make sure tab and space are accepted as white space.
243 \catcode‘\ 10 %
244 \catcode‘\^^I10 %
245 \catcode\endlinechar5 %
246 \@makeother\:%
247 \@makeother\-%
The first thing we need to do is to open the information file, if possible.
248 \immediate\openin\@inputcheck#1 %
249 \ifeof\@inputcheck
250 \@latex@error{File ‘#1’ not found}\@ehc
251 \else
Now we’ll scan lines until we find one that starts with %%BoundingBox: We need
to reset the catcodes to read the file, and so this is done in a group.
252 \Gread@true
253 \let\@tempb\Gread@false
254 \loop
255 \read\@inputcheck to\@tempa
256 \ifeof\@inputcheck
257 \Gread@false
258 \else
259 \expandafter\Gread@find@bb\@tempa:.\\%
260 \fi
261 \ifGread@
262 \repeat
263 \immediate\closein\@inputcheck
264 \fi
265 \ifGin@bbox\else
266 \@latex@error
267 {Cannot determine size of graphic in #1 (no BoundingBox)}%
268 \@ehc
269 \gdef\@gtempa{0 0 72 72 }%
270 \fi
271 \endgroup
272 \expandafter\Gread@parse@bb\@gtempa\\}
\Gread@find@bb If a line in the EPS file starts with a %%BoundingBox:, we will examine it more
closely. Note using the ‘extra’ argument #2#3 causes any space after the : to be
gobbled.
273 \long\def\Gread@find@bb#1:#2#3\\{%
274 \def\@tempa{#1}%
275 \ifx\@tempa\Gread@BBox
276 \Gread@test@atend#2#3()\\%
277 \fi}
16
\Gread@test@atend Determine if the stuff following the %%BoundingBox is ‘(atend)’, which will involve
further reading of the file. This is accomplished by making \@tempb into a no-op,
so that finding a %%BoundingBox does not stop the loop.
278 \def\Gread@test@atend#1(#2)#3\\{%
279 \def\@tempa{#2}%
280 \ifx\@tempa\Gread@atend
281 \Gread@true
282 \let\@tempb\relax
283 \else
284 \gdef\@gtempa{#1}%
285 \@tempb
286 \Gin@bboxtrue
287 \fi}
\Gread@parse@bb We have %%BoundingBox and what follows is not ‘(atend)’ so we will parse the
rest of the line as a BB with four elements. PostScript files should never have
units specified in the BoundingBox comment, but we allow arbitrary TEX units in
external files, or in other interfaces.
288 \def\Gread@parse@bb#1 #2 #3 #4 #5\\{%
289 \Gin@defaultbp\Gin@llx{#1}%
290 \Gin@defaultbp\Gin@lly{#2}%
291 \Gin@defaultbp\Gin@urx{#3}%
292 \Gin@defaultbp\Gin@ury{#4}}%
7.5 Rotation
As above, we will re-use some existing local registers.
17
\rotatebox The angle is specified by #1. The box to be rotated is #2. In the standard interface
the centre of rotation is (0, 0). Then finally call \Grot@box to rotate the box.
304 \long\def\rotatebox#1#2{%
305 \leavevmode
306 \Grot@setangle{#1}%
307 \setbox\z@\hbox{{#2}}%
308 \Grot@x\z@
309 \Grot@y\z@
310 \Grot@box}
\Grot@setangle Set the internal macro used by \Grot@box. In the standard interface this is trivial,
but other interfaces may have more interesting definitions. For example:
\def\Grot@setangle#1{%
\dimen@#1\p@
\[email protected]\dimen@
\edef\Grot@angle{\strip@pt\dimen@}}
C B
r
O
S A
D E
18
The ‘extra’ horizontal translation Lx at the end is calculated so that the leftmost
point of the resulting box has x-coordinate 0. This is desirable as TEX boxes must
have the reference point at the left edge of the box.
\Grot@Px Work out new x coordinate of point after rotation. The parameters #2 and #3 are
the original x and y coordinates of the point. The new x coordinate is stored in
#1.
312 \def\Grot@Px#1#2#3{%
313 #1\Grot@cos#2%
314 \advance#1-\Grot@sin#3}
\Grot@Py Work out new y coordinate of point after rotation. The parameters #2 and #3 are
the original x and y coordinates of the point. The new y coordinate is stored in
#1.
315 \def\Grot@Py#1#2#3{%
316 #1\Grot@sin#2%
317 \advance#1\Grot@cos#3}
\Grot@box This is the tricky bit. We can rotate the box, but then need to work out how
much space to leave for it on the page.
We simplify matters by working out first which quadrant we are in, and then
picking just the right values.
318 \def\Grot@box{%
319 \begingroup
We are going to need to know the sine and cosine of the angle; simplest to calculate
these now.
320 \CalculateSin\Grot@angle
321 \CalculateCos\Grot@angle
322 \edef\Grot@sin{\UseSin\Grot@angle}%
323 \edef\Grot@cos{\UseCos\Grot@angle}%
324 ^^A \GDebug{Rotate: angle \Grot@angle, sine is \Grot@sin,
325 ^^A cosine is \Grot@cos}%
Save the four extents of the original box.
326 \Grot@r\wd\z@ \advance\Grot@r-\Grot@x
327 \Grot@l\z@ \advance\Grot@l-\Grot@x
328 \Grot@h\ht\z@ \advance\Grot@h-\Grot@y
329 \Grot@d-\dp\z@ \advance\Grot@d-\Grot@y
Now a straightforward test to see which quadrant we are operating in;
330 \ifdim\Grot@sin\p@>\z@
331 \ifdim\Grot@cos\p@>\z@
First quadrant: Height=By, Right=Ex, Left=Cx, Depth=Dy
332 \Grot@Py\Grot@height \Grot@r\Grot@h%B
333 \Grot@Px\Grot@right \Grot@r\Grot@d%E
334 \Grot@Px\Grot@left \Grot@l\Grot@h%C
335 \Grot@Py\Grot@depth \Grot@l\Grot@d%D
336 \else
19
Second quadrant: Height=Ey, Right=Dx, Left=Bx, Depth=Cy
337 \Grot@Py\Grot@height \Grot@r\Grot@d%E
338 \Grot@Px\Grot@right \Grot@l\Grot@d%D
339 \Grot@Px\Grot@left \Grot@r\Grot@h%B
340 \Grot@Py\Grot@depth \Grot@l\Grot@h%C
341 \fi
342 \else
343 \ifdim\Grot@cos\p@<\z@
Third quadrant: Height=Dy, Right=Cx, Left=Ex, Depth=By
344 \Grot@Py\Grot@height \Grot@l\Grot@d%D
345 \Grot@Px\Grot@right \Grot@l\Grot@h%C
346 \Grot@Px\Grot@left \Grot@r\Grot@d%E
347 \Grot@Py\Grot@depth \Grot@r\Grot@h%B
348 \else
Fourth quadrant: Height=Cy, Right=Bx, Left=Dx, Depth=Ey
349 \Grot@Py\Grot@height \Grot@l\Grot@h%C
350 \Grot@Px\Grot@right \Grot@r\Grot@h%B
351 \Grot@Px\Grot@left \Grot@l\Grot@d%D
352 \Grot@Py\Grot@depth \Grot@r\Grot@d%E
353 \fi
354 \fi
Now we should translate back by (Ox , Oy ), but TEX can not really deal with
boxes that do not have the reference point at the left edge. (Everything with
a −ve x-coordinate would over-print earlier text). So we modify the horizontal
translation so that the reference point as understood by TEX is at the left edge.
This means that the ‘centre of rotation’ is not fixed by \rotatebox, but typically
moves horizontally. We also need to find the image of the original reference point,
S, as that is where the rotation specials must be inserted.
355 \advance\Grot@height\Grot@y
356 \advance\Grot@depth\Grot@y
357 \Grot@Px\dimen@ \Grot@x\Grot@y
358 \Grot@Py\dimen@ii \Grot@x\Grot@y
359 \dimen@-\dimen@ \advance\dimen@-\Grot@left
360 \dimen@ii-\dimen@ii \advance\dimen@ii\Grot@y
361 ^^A \GDebug{Rotate: (l,r,h,d)^^J%
362 ^^A Original \the\Grot@l,\the\Grot@r,\the\Grot@h,\the\Grot@d,^^J%
363 ^^A New..... \the\Grot@left,\the\Grot@right,%
364 ^^A \the\Grot@height,\the\Grot@depth}%
365 \setbox\z@\hbox{%
366 \kern\dimen@
367 \raise\dimen@ii\hbox{\Grot@start\box\z@\Grot@end}}%
368 \ht\z@\Grot@height
369 \dp\z@-\Grot@depth
370 \advance\Grot@right-\Grot@left\wd\z@\Grot@right
371 \leavevmode\box\z@
372 \endgroup}
20
7.7 Stretching and Scaling
\scalebox The top level \scalebox. If the vertical scale factor is omitted it defaults to the
horizontal scale factor, #1.
373 \def\scalebox#1{%
374 \@ifnextchar[{\Gscale@box{#1}}{\Gscale@box{#1}[#1]}}
\resizebox Look for a *, which specifies that a final vertical size refers to ‘height + depth’
not just ‘height’.
394 \def\resizebox{%
395 \leavevmode
396 \@ifstar{\Gscale@@box\totalheight}{\Gscale@@box\height}}
21
409 \toks@{\Gscale@box@dd{#2}\width}%
410 \else
411 \toks@{\Gscale@box@dddd{#2}\width{#3}#1}%
412 \fi
413 \fi
414 \the\toks@}
\Gscale@box@dddd Scale the text #5 horizontally by a factor #1/#2 and vertically by a factor #3/#4.
422 \long\def\Gscale@box@dddd#1#2#3#4#5{%
423 \@begin@tempboxa\hbox{#5}%
424 \setlength\@tempdima{#1}%
425 \setlength\@tempdimb{#2}%
426 \Gscale@div\@tempa\@tempdima\@tempdimb
427 \setlength\@tempdima{#3}%
428 \setlength\@tempdimb{#4}%
429 \Gscale@div\@tempb\@tempdima\@tempdimb
430 \ifGin@iso
431 \ifdim\@tempa\p@>\@tempb\p@
432 \let\@tempa\@tempb
433 \else
434 \let\@tempb\@tempa
435 \fi
436 \fi
437 \Gscale@box\@tempa[\@tempb]{\box\@tempboxa}%
438 \@end@tempboxa}
\ifGin@iso If this flag is true, then specifying two lengths to \resizebox scales the box by
the same factor in either direction, such that neither length exceeds the stated
amount. No user interface to this flag in the standard package, but it is used by
the keepaspectratio key to \includegraphics in the graphicx package.
439 \newif\ifGin@iso
\Gscale@div The macro #1 is set to the ratio of the lengths #2 and #3.
440 \def\Gscale@div#1#2#3{%
441 \setlength\dimen@{#3}%
442 \ifdim\dimen@=\z@
443 \PackageError{graphics}{Division by 0}\@eha
444 \dimen@#2%
445 \fi
446 \edef\@tempd{\the\dimen@}%
22
447 \setlength\dimen@{#2}%
448 \count@65536\relax
449 \ifdim\dimen@<\z@
450 \dimen@-\dimen@
451 \count@-\count@
452 \fi
453 \ifdim\dimen@>\z@
454 \loop
455 \ifdim\dimen@<8192\p@
456 \dimen@\tw@\dimen@
457 \divide\count@\tw@
458 \repeat
459 \dimen@ii\@tempd\relax
460 \divide\dimen@ii\count@
461 \divide\dimen@\dimen@ii
462 \fi
463 \edef#1{\strip@pt\dimen@}}
Restore Catcodes
464 \Gin@codes
465 \let\Gin@codes\relax
466 h/packagei
23