Stuff.
2 % Version 1.1, 25 Dec 2009
4 % Copyright 2009 by David Chiang
6 % This program is free software; you can redistribute it and/or modify
7 % it under the terms of the GNU General Public License as published by
8 % the Free Software Foundation; either version 2 of the License, or
9 % (at your option) any later version.
11 % This program is distributed in the hope that it will be useful,
12 % but WITHOUT ANY WARRANTY; without even the implied warranty of
13 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 % GNU General Public License for more details.
16 % You should have received a copy of the GNU General Public License along
17 % with this program; if not, write to the Free Software Foundation, Inc.,
18 % 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 % - the ability to save a subpicture in local variables
22 % - nodes in subpictures are tracked if the subpicture is placed with arbitrary transforms
23 % - new \pgffitsubpicture macro to transform a subpicture (preserving aspect) to fit in a desired box
25 \newdimen\pgf@subpicminx
26 \newdimen\pgf@subpicminy
27 \newdimen\pgf@subpicmaxx
28 \newdimen\pgf@subpicmaxy
30 % Special virtual node for current subpicture's bounding box
31 \expandafter\def\csname pgf@sh@ns@current subpicture\endcsname{rectangle}
32 \expandafter\def\csname pgf@sh@np@current subpicture\endcsname{%
33 \def\southwest{\pgfqpoint{\pgf@subpicminx}{\pgf@subpicminy}}%
34 \def\northeast{\pgfqpoint{\pgf@subpicmaxx}{\pgf@subpicmaxy}}%
36 \expandafter\def\csname pgf@sh@nt@current subpicture\endcsname{{\pgf@pt@aa}{\pgf@pt@ab}{\pgf@pt@ba}{\pgf@pt@bb}{\the\pgf@pt@x}{\the\pgf@pt@y}} % the transformation at invocation time
37 \expandafter\def\csname pgf@sh@pi@current subpicture\endcsname{\pgfpictureid}
39 % Create a pgfpicture inside an hbox for delayed placement
41 \expandafter\global\expandafter\setbox\pgf@hbox=\hbox\bgroup
44 \relax % not sure why. otherwise a curly brace immediately after causes an error
47 \def\endpgfsubpicture{
48 \global\pgf@subpicminx=\pgf@picminx
49 \global\pgf@subpicminy=\pgf@picminy
50 \global\pgf@subpicmaxx=\pgf@picmaxx
51 \global\pgf@subpicmaxy=\pgf@picmaxy
52 \global\edef\subpictureid{\pgfpictureid}%
53 \pgfsetbaseline{\pgf@picminy}%
55 \endpgfinterruptpicture%
59 % Allocate registers for saving a subpicture. #1 is text, not a control sequence.
60 \def\pgfnewsubpicture#1{%
61 \expandafter\newbox\csname pgf@subpic@hbox@#1\endcsname
62 \expandafter\newdimen\csname pgf@subpic@minx@#1\endcsname
63 \expandafter\newdimen\csname pgf@subpic@miny@#1\endcsname
64 \expandafter\newdimen\csname pgf@subpic@maxx@#1\endcsname
65 \expandafter\newdimen\csname pgf@subpic@maxy@#1\endcsname
68 % saved subpictures are local to the current group
69 \def\pgfsavesubpicture#1{%
70 \expandafter\setbox\csname pgf@subpic@hbox@#1\endcsname\box\pgf@hbox
71 \csname pgf@subpic@minx@#1\endcsname\pgf@subpicminx
72 \csname pgf@subpic@miny@#1\endcsname\pgf@subpicminy
73 \csname pgf@subpic@maxx@#1\endcsname\pgf@subpicmaxx
74 \csname pgf@subpic@maxy@#1\endcsname\pgf@subpicmaxy
75 \expandafter\edef\csname pgf@subpic@id@#1\endcsname{\subpictureid}%
78 % place current subpicture into named subpicture
79 \def\pgfmergesubpicture#1{%
81 % place current subpicture
83 % override containing picture
84 \expandafter\xdef\csname pgf@sh@pi@\subpictureid\endcsname{\csname pgf@subpic@id@#1\endcsname}%
86 \pgfrestoresubpicture{#1}
87 \pgflowlevelobj{\pgftransformshift{\pgfqpoint{\the\pgf@subpicminx}{\the\pgf@subpicminy}}}{\pgfqbox\pgf@hbox}
88 \pgfpathrectanglecorners{\pgfqpoint{\the\pgf@subpicminx}{\the\pgf@subpicminy}}{\pgfqpoint{\the\pgf@subpicmaxx}{\the\pgf@subpicmaxy}}%
89 \pgfusepath{use as bounding box}%
92 \expandafter\setbox\csname pgf@subpic@hbox@#1\endcsname\box\pgf@hbox
93 \csname pgf@subpic@minx@#1\endcsname\pgf@subpicminx
94 \csname pgf@subpic@miny@#1\endcsname\pgf@subpicminy
95 \csname pgf@subpic@maxx@#1\endcsname\pgf@subpicmaxx
96 \csname pgf@subpic@maxy@#1\endcsname\pgf@subpicmaxy
97 % but don't save the new picture id, keep the existing one
100 \def\pgfrestoresubpicture#1{%
101 \edef\act{\global\noexpand\setbox\pgf@hbox\noexpand\box\csname pgf@subpic@hbox@#1\endcsname}\act
102 \expandafter\global\expandafter\pgf@subpicminx\csname pgf@subpic@minx@#1\endcsname
103 \expandafter\global\expandafter\pgf@subpicminy\csname pgf@subpic@miny@#1\endcsname
104 \expandafter\global\expandafter\pgf@subpicmaxx\csname pgf@subpic@maxx@#1\endcsname
105 \expandafter\global\expandafter\pgf@subpicmaxy\csname pgf@subpic@maxy@#1\endcsname
106 \xdef\subpictureid{\csname pgf@subpic@id@#1\endcsname}%
109 % Place a previously-created subpicture, lining up its origin with the current origin
110 \def\pgfplacesubpicture{
112 % expand current bounding box to accommodate subpicture
113 \pgfpathrectanglecorners{\pgfqpoint{\the\pgf@subpicminx}{\the\pgf@subpicminy}}{\pgfqpoint{\the\pgf@subpicmaxx}{\the\pgf@subpicmaxy}}%
114 \pgfusepath{use as bounding box}%
116 % make the subpicture a node in the containing picture
117 \expandafter\gdef\csname pgf@sh@ns@\subpictureid\endcsname{rectangle}%
118 \expandafter\xdef\csname pgf@sh@np@\subpictureid\endcsname{%
119 \noexpand\def\noexpand\southwest{\noexpand\pgfqpoint{\the\pgf@subpicminx}{\the\pgf@subpicminy}}%
120 \noexpand\def\noexpand\northeast{\noexpand\pgfqpoint{\the\pgf@subpicmaxx}{\the\pgf@subpicmaxy}}%
122 \pgfgettransform\pgf@temp
123 \expandafter\xdef\csname pgf@sh@nt@\subpictureid\endcsname{\pgf@temp}%
124 \expandafter\xdef\csname pgf@sh@pi@\subpictureid\endcsname{\pgfpictureid}%
126 % align origin of subpicture with origin
127 \pgftransformshift{\pgfqpoint{\the\pgf@subpicminx}{\the\pgf@subpicminy}}%
128 \pgfqboxsynced{\pgf@hbox}%
132 % Hook onto existing macro \pgf@shape@interpictureshift.
133 % This is called whenever we look up an anchor of a node.
134 % This hook recursively checks to see if the node's picture
135 % is a subpicture of another, and if so, adjusts its position accordingly.
137 % This is slow. It makes drawing trees O(n^2) in the depth of the tree.
138 % The alternative is to store, for each picture, a list of the nodes
139 % inside it. But this way doesn't require us to hijack \pgfnode, and
140 % is robust to re-placement of a subpicture. A compromise would be
141 % to store, for each picture, a list of the *subpictures* inside it.
143 \let\orig@pgf@shape@interpictureshift\pgf@shape@interpictureshift
144 \def\unwind@subpic#1{%
145 % is #1 the current picture?
147 \ifx\subpicid\pgfpictureid
150 % does #1 have a parent picture?
151 \expandafter\ifx\csname pgf@sh@pi@#1\endcsname\relax
152 % no, the original node was not inside the current picture
155 % yes, apply transform and move up to parent picture
157 \pgfsettransform{\csname pgf@sh@nt@#1\endcsname}%
158 \pgf@pos@transform{\pgf@x}{\pgf@y}%
162 \unwind@subpic{\csname pgf@sh@pi@#1\endcsname}%
166 \def\pgf@shape@interpictureshift#1{%
167 \edef\fallback{\pgf@x=\the\pgf@x\pgf@y=\the\pgf@y\noexpand\orig@pgf@shape@interpictureshift{#1}}%
168 \unwind@subpic{\csname pgf@sh@pi@#1\endcsname}%
171 % \pgffitsubpicture{sw}{ne}
172 % Make the subpicture fit in the rectangle from sw to ne, preserving its aspect ratio.
173 \def\pgffitsubpicture#1#2{%
175 \pgfpointdiff{\pgfpointanchor{current subpicture}{south west}}{\pgfpointanchor{current subpicture}{north east}}%
176 \pgf@xa=\pgf@x \pgf@ya=\pgf@y
178 \pgf@process{\pgfpointdiff{#1}{#2}}%
179 \pgf@xb=\pgf@x \pgf@yb=\pgf@y
180 \pgfmathparse{min(\pgf@xb/\pgf@xa,\pgf@yb/\pgf@ya)}%
181 \pgfmathparse{min(1,\pgfmathresult)}%
182 \pgftransformscale{\pgfmathresult}%
185 \pgfpointanchor{current subpicture}{center}%
186 \pgf@xa=\pgf@x \pgf@ya=\pgf@y
188 % we scaled transform, so apply reverse scaling to argument
189 \pgfmathparse{1/\pgfmathresult}%
190 \pgf@process{\pgfpointscale{\pgfmathresult}{\pgfpointlineattime{0.5}{#1}{#2}}}%
191 \pgf@xb=\pgf@x \pgf@yb=\pgf@y
192 \pgfpointdiff{\pgfpoint{\pgf@xa}{\pgf@ya}}{\pgfpoint{\pgf@xb}{\pgf@yb}}%
193 \pgftransformshift{\pgfpoint{\pgf@x}{\pgf@y}}%
196 % utility functions -- not currently used
198 \def\pgfnodedelete#1{%
199 \expandafter\global\expandafter\let\csname pgf@sh@ns@#1\endcsname\relax
200 \expandafter\global\expandafter\let\csname pgf@sh@np@#1\endcsname\relax
201 \expandafter\global\expandafter\let\csname pgf@sh@nt@#1\endcsname\relax
202 \expandafter\global\expandafter\let\csname pgf@sh@pi@#1\endcsname\relax
203 \expandafter\global\expandafter\let\csname pgf@sh@ma@#1\endcsname\relax
206 \def\pgfnodeifexists#1#2#3{%
207 \expandafter\ifx\csname pgf@sh@ns@#1\endcsname\relax#3\else#2\fi