You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
7.6 KiB
204 lines
7.6 KiB
% Copyright 2006 by Till Tantau
|
|
%
|
|
% This file may be distributed and/or modified
|
|
%
|
|
% 1. under the LaTeX Project Public License and/or
|
|
% 2. under the GNU Public License.
|
|
%
|
|
% See the file doc/generic/pgf/licenses/LICENSE for more details.
|
|
|
|
\ProvidesFileRCS{pgfsyssoftpath.code.tex}
|
|
|
|
|
|
% This package provides the pgf system path abstraction layer. This
|
|
% layer is used to construct paths first ``abstractly.'' These
|
|
% abstract paths can still be modified, before they are ``made
|
|
% concrete.''
|
|
%
|
|
% An abstract path consists of a sequence of basic building blocks,
|
|
% each of which is a tuple consisting of two numbers (specifying a
|
|
% coordinate) and a token. Possible tokens are:
|
|
%
|
|
% 1. moveto
|
|
% 2. lineto
|
|
% 3. rectcorner
|
|
% 4. rectsize
|
|
% 5. curvetosupporta
|
|
% 6. curvetosupportb
|
|
% 7. curveto
|
|
% 8. closepath
|
|
% 9. specialround
|
|
%
|
|
% A curveto must always be preceded by a curvetosupporta and a
|
|
% curvetosupportb. A non-empty path must always begin with a
|
|
% moveto. The coordinates of a closepath are non-specified, currently,
|
|
% but they might be set to the coordinate of the path segment start,
|
|
% in the future.
|
|
|
|
|
|
% Access to the current path:
|
|
%
|
|
% Lots of stuff is added to the current path and it can get very long
|
|
% (containing literally tens of thousands of tokens). For such macros,
|
|
% adding things using a simple "g@addtomacro" takes more and more
|
|
% time, resulting in quadratic runtime. To avoid this, ideally, one
|
|
% would collect things in an array and then use a divide and conquer
|
|
% merger. A simple intermediate solution is the following, implemented
|
|
% here: We have the path and two buffers. New tokens are added to the
|
|
% first buffer, which is quite small. When it overflow, its contents
|
|
% is added to the second buffer, which is large. If that buffer
|
|
% overflow, the contents is finally added to the main path (which can
|
|
% have arbitrary length). Whenever the main path is set or read, the
|
|
% buffers are flushed.
|
|
%
|
|
% Because of this buffering, it is imperative that the main path is
|
|
% accessed only via appropriate interface macros.
|
|
|
|
|
|
|
|
% The current path
|
|
\let\pgfsyssoftpath@thepath=\pgfutil@empty
|
|
\let\pgfsyssoftpath@bigbuffer=\pgfutil@empty
|
|
\let\pgfsyssoftpath@smallbuffer=\pgfutil@empty
|
|
\newcount\pgfsyssoftpath@smallbuffer@items
|
|
\newcount\pgfsyssoftpath@bigbuffer@items
|
|
|
|
\def\pgfsyssoftpath@flushbuffers{%
|
|
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\gdef%
|
|
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\pgfsyssoftpath@thepath%
|
|
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{%
|
|
\expandafter\expandafter\expandafter\pgfsyssoftpath@thepath%
|
|
\expandafter\pgfsyssoftpath@bigbuffer\pgfsyssoftpath@smallbuffer}%
|
|
\global\let\pgfsyssoftpath@smallbuffer=\pgfutil@empty
|
|
\global\let\pgfsyssoftpath@bigbuffer=\pgfutil@empty
|
|
\global\pgfsyssoftpath@bigbuffer@items0\relax%
|
|
\global\pgfsyssoftpath@smallbuffer@items0\relax%
|
|
}
|
|
|
|
% Getting and setting the current path
|
|
\def\pgfsyssoftpath@getcurrentpath#1{%
|
|
\pgfsyssoftpath@flushbuffers%
|
|
\let#1=\pgfsyssoftpath@thepath%
|
|
}
|
|
|
|
\def\pgfsyssoftpath@setcurrentpath#1{%
|
|
\global\let\pgfsyssoftpath@thepath=#1%
|
|
\global\let\pgfsyssoftpath@smallbuffer=\pgfutil@empty
|
|
\global\let\pgfsyssoftpath@bigbuffer=\pgfutil@empty
|
|
\global\pgfsyssoftpath@bigbuffer@items0\relax%
|
|
\global\pgfsyssoftpath@smallbuffer@items0\relax%
|
|
}
|
|
|
|
|
|
% Invoking the current path (slightly optimized)
|
|
\def\pgfsyssoftpath@invokecurrentpath{%
|
|
\pgfsyssoftpath@thepath%
|
|
\pgfsyssoftpath@bigbuffer%
|
|
\pgfsyssoftpath@smallbuffer%
|
|
}
|
|
|
|
\def\pgfsyssoftpath@flushcurrentpath{%
|
|
\pgfsyssoftpath@invokecurrentpath%
|
|
\pgfsyssoftpath@setcurrentpath\pgfutil@empty%
|
|
}
|
|
|
|
% Add an item at the end
|
|
\def\pgfsyssoftpath@addtocurrentpath#1{%
|
|
\global\advance\pgfsyssoftpath@smallbuffer@items by1\relax%
|
|
\ifnum\pgfsyssoftpath@smallbuffer@items<40\relax% good number?
|
|
\expandafter\gdef\expandafter\pgfsyssoftpath@smallbuffer\expandafter{\pgfsyssoftpath@smallbuffer#1}%
|
|
\else%
|
|
\pgfsyssoftpath@smalloverflow{#1}%
|
|
\fi%
|
|
}
|
|
\def\pgfsyssoftpath@smalloverflow#1{%
|
|
\global\advance\pgfsyssoftpath@bigbuffer@items by1\relax%
|
|
\ifnum\pgfsyssoftpath@bigbuffer@items<30\relax% good number?
|
|
\expandafter\expandafter\expandafter\gdef%
|
|
\expandafter\expandafter\expandafter\pgfsyssoftpath@bigbuffer%
|
|
\expandafter\expandafter\expandafter{\expandafter\pgfsyssoftpath@bigbuffer\pgfsyssoftpath@smallbuffer#1}%
|
|
\global\let\pgfsyssoftpath@smallbuffer=\pgfutil@empty%
|
|
\global\pgfsyssoftpath@smallbuffer@items0\relax%
|
|
\else%
|
|
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\gdef%
|
|
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\pgfsyssoftpath@thepath%
|
|
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{%
|
|
\expandafter\expandafter\expandafter\pgfsyssoftpath@thepath
|
|
\expandafter\pgfsyssoftpath@bigbuffer\pgfsyssoftpath@smallbuffer#1}%
|
|
\global\let\pgfsyssoftpath@smallbuffer=\pgfutil@empty
|
|
\global\let\pgfsyssoftpath@bigbuffer=\pgfutil@empty
|
|
\global\pgfsyssoftpath@bigbuffer@items0\relax%
|
|
\global\pgfsyssoftpath@smallbuffer@items0\relax%
|
|
\fi%
|
|
}
|
|
|
|
|
|
|
|
\def\pgfsyssoftpath@lastmoveto{{0pt}{0pt}}
|
|
|
|
\newif\ifpgfsyssoftpathmovetorelevant
|
|
\pgfsyssoftpathmovetorelevanttrue
|
|
|
|
% Add a moveto element to the current path
|
|
\def\pgfsyssoftpath@moveto#1#2{%
|
|
\edef\pgfsyssoftpath@coord{{#1}{#2}}%
|
|
\expandafter\pgfsyssoftpath@addtocurrentpath\expandafter{\expandafter\pgfsyssoftpath@movetotoken\pgfsyssoftpath@coord}%
|
|
\ifpgfsyssoftpathmovetorelevant%
|
|
\global\let\pgfsyssoftpath@lastmoveto\pgfsyssoftpath@coord%
|
|
\fi%
|
|
}
|
|
|
|
% Add a lineto element to the current path
|
|
\def\pgfsyssoftpath@lineto#1#2{%
|
|
\edef\pgfsyssoftpath@coord{{#1}{#2}}%
|
|
\expandafter\pgfsyssoftpath@addtocurrentpath\expandafter{\expandafter\pgfsyssoftpath@linetotoken\pgfsyssoftpath@coord}%
|
|
}
|
|
|
|
|
|
% Add curveto elements to the current path
|
|
\def\pgfsyssoftpath@curveto#1#2#3#4#5#6{%
|
|
\edef\pgfsyssoftpath@temp{{%
|
|
\noexpand\pgfsyssoftpath@curvetosupportatoken{#1}{#2}%
|
|
\noexpand\pgfsyssoftpath@curvetosupportbtoken{#3}{#4}%
|
|
\noexpand\pgfsyssoftpath@curvetotoken{#5}{#6}%
|
|
}}%
|
|
\expandafter\pgfsyssoftpath@addtocurrentpath\pgfsyssoftpath@temp%
|
|
}
|
|
|
|
|
|
% Add rectangle elements to the current path
|
|
\def\pgfsyssoftpath@rect#1#2#3#4{%
|
|
\edef\pgfsyssoftpath@temp{{%
|
|
\noexpand\pgfsyssoftpath@rectcornertoken{#1}{#2}%
|
|
\noexpand\pgfsyssoftpath@rectsizetoken{#3}{#4}%
|
|
}}%
|
|
\expandafter\pgfsyssoftpath@addtocurrentpath\pgfsyssoftpath@temp%
|
|
}
|
|
|
|
% Add closepath element to the current path
|
|
\def\pgfsyssoftpath@closepath{%
|
|
\expandafter\pgfsyssoftpath@addtocurrentpath\expandafter{\expandafter\pgfsyssoftpath@closepathtoken\pgfsyssoftpath@lastmoveto}%
|
|
}
|
|
|
|
% Add special element to the current path
|
|
\def\pgfsyssoftpath@specialround#1#2{%
|
|
\edef\pgfsyssoftpath@temp{{#1}{#2}}%
|
|
\expandafter\pgfsyssoftpath@addtocurrentpath\expandafter{\expandafter\pgfsyssoftpath@specialroundtoken\pgfsyssoftpath@temp}%
|
|
}
|
|
|
|
% Marshallers
|
|
\def\pgfsyssoftpath@movetotoken#1#2{\pgfsys@moveto{#1}{#2}}
|
|
\def\pgfsyssoftpath@linetotoken#1#2{\pgfsys@lineto{#1}{#2}}
|
|
\def\pgfsyssoftpath@rectcornertoken#1#2#3#4#5{\pgfsys@rect{#1}{#2}{#4}{#5}} % #3 = \pgfsyssoftpath@rectsizetoken
|
|
\def\pgfsyssoftpath@curvetosupportatoken#1#2#3#4#5#6#7#8{\pgfsys@curveto{#1}{#2}{#4}{#5}{#7}{#8}}
|
|
\def\pgfsyssoftpath@closepathtoken#1#2{\pgfsys@closepath}
|
|
\let\pgfsyssoftpath@specialroundtoken=\pgfutil@gobbletwo
|
|
\def\pgfsyssoftpath@curvetosupportbtoken#1#2{curvetotokenb} % make sure this \ifx-equal only to itself
|
|
\def\pgfsyssoftpath@curvetotoken#1#2{curvetotoken}% make sure this \ifx-equal only to itself
|
|
|
|
|
|
\endinput
|
|
|
|
%%% Local Variables:
|
|
%%% mode: latex
|
|
%%% End:
|
|
|